支持 Leaf 1.21.11 并内置 TabooLib 依赖
This commit is contained in:
+125
-7
@@ -1,9 +1,7 @@
|
|||||||
import io.izzel.taboolib.gradle.*
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
id("io.izzel.taboolib") version "2.0.11"
|
id("io.izzel.taboolib") version "2.0.2-community-1"
|
||||||
id("org.jetbrains.kotlin.jvm") version "1.7.10"
|
id("org.jetbrains.kotlin.jvm") version "1.7.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,12 +21,27 @@ taboolib {
|
|||||||
bukkitNodes["update-info"] = "支持1.12.2物品附加值"
|
bukkitNodes["update-info"] = "支持1.12.2物品附加值"
|
||||||
}
|
}
|
||||||
env {
|
env {
|
||||||
install(NMS_UTIL, UI)
|
// TabooLib 6.2 split the legacy bundles into versioned modules. The
|
||||||
install(EXPANSION_COMMAND_HELPER, BUKKIT_ALL)
|
// 6.2 platform contains the Bukkit 1.21 compatibility layer.
|
||||||
install(DATABASE, CHAT, CONFIGURATION, LANG, NMS, KETHER)
|
install(
|
||||||
|
"bukkit-ui",
|
||||||
|
"minecraft-command-helper",
|
||||||
|
"bukkit-hook",
|
||||||
|
"bukkit-util",
|
||||||
|
"bukkit-xseries",
|
||||||
|
"platform-bukkit",
|
||||||
|
"platform-bukkit-impl",
|
||||||
|
"database",
|
||||||
|
"minecraft-chat",
|
||||||
|
"basic-configuration",
|
||||||
|
"minecraft-i18n",
|
||||||
|
"minecraft-kether"
|
||||||
|
)
|
||||||
|
|
||||||
|
repoTabooLib = "https://maven.xbaimiao.com/repository/maven-public/"
|
||||||
}
|
}
|
||||||
version {
|
version {
|
||||||
taboolib = "6.1.1-beta17"
|
taboolib = "6.2.0-beta33"
|
||||||
}
|
}
|
||||||
// relocate("kotlin", "libs.kotlin171")
|
// relocate("kotlin", "libs.kotlin171")
|
||||||
relocate("com.xbaimiao.ktor", "com.github.xbaimiao.shoppro.stat")
|
relocate("com.xbaimiao.ktor", "com.github.xbaimiao.shoppro.stat")
|
||||||
@@ -40,6 +53,111 @@ repositories {
|
|||||||
maven("https://r.irepo.space/maven/")
|
maven("https://r.irepo.space/maven/")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val bundledRuntime by configurations.creating
|
||||||
|
|
||||||
|
val taboolibRuntimeModules = listOf(
|
||||||
|
"common",
|
||||||
|
"platform-bukkit",
|
||||||
|
"common-env",
|
||||||
|
"common-util",
|
||||||
|
"common-legacy-api",
|
||||||
|
"common-platform-api",
|
||||||
|
"bukkit-ui",
|
||||||
|
"minecraft-command-helper",
|
||||||
|
"bukkit-hook",
|
||||||
|
"bukkit-util",
|
||||||
|
"bukkit-xseries",
|
||||||
|
"platform-bukkit-impl",
|
||||||
|
"database",
|
||||||
|
"minecraft-chat",
|
||||||
|
"basic-configuration",
|
||||||
|
"minecraft-i18n",
|
||||||
|
"minecraft-kether"
|
||||||
|
)
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// These files are embedded as resources and installed before TabooLib's
|
||||||
|
// primitive loader runs, so a server can start without Maven access.
|
||||||
|
add("bundledRuntime", "me.lucko:jar-relocator:1.7")
|
||||||
|
add("bundledRuntime", "org.ow2.asm:asm:9.6")
|
||||||
|
add("bundledRuntime", "org.ow2.asm:asm-util:9.6")
|
||||||
|
add("bundledRuntime", "org.ow2.asm:asm-commons:9.6")
|
||||||
|
add("bundledRuntime", "org.tabooproject.reflex:reflex:1.1.7")
|
||||||
|
add("bundledRuntime", "org.tabooproject.reflex:analyser:1.1.7")
|
||||||
|
add("bundledRuntime", "org.jetbrains.kotlin:kotlin-stdlib:1.7.10")
|
||||||
|
add("bundledRuntime", "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10")
|
||||||
|
add("bundledRuntime", "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3")
|
||||||
|
taboolibRuntimeModules.forEach { module ->
|
||||||
|
add("bundledRuntime", "io.izzel.taboolib:$module:6.2.0-beta33")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val prepareBundledRuntime by tasks.registering {
|
||||||
|
val output = layout.buildDirectory.dir("generated/bundled-runtime")
|
||||||
|
outputs.dir(output)
|
||||||
|
doLast {
|
||||||
|
val root = output.get().asFile
|
||||||
|
root.deleteRecursively()
|
||||||
|
val resourceRoot = root.resolve("META-INF/taboolib/bundled")
|
||||||
|
val index = linkedMapOf<String, String>()
|
||||||
|
configurations["bundledRuntime"].resolvedConfiguration.resolvedArtifacts.forEach { artifact ->
|
||||||
|
val module = artifact.moduleVersion.id
|
||||||
|
val relative = "${module.group.replace('.', '/')}/${module.name}/${module.version}/${module.name}-${module.version}.jar"
|
||||||
|
val destination = resourceRoot.resolve(relative)
|
||||||
|
destination.parentFile.mkdirs()
|
||||||
|
artifact.file.copyTo(destination, overwrite = true)
|
||||||
|
index[relative] = relative
|
||||||
|
|
||||||
|
// The TabooLib build metadata in this project is generated by the
|
||||||
|
// Kotlin 1.7.10 Gradle plugin, while Reflex 1.1.7 resolves a newer
|
||||||
|
// compatible stdlib transitively. Install the resolved bytes at
|
||||||
|
// the exact paths PrimitiveSettings requests as well.
|
||||||
|
if (module.group == "org.jetbrains.kotlin" &&
|
||||||
|
(module.name == "kotlin-stdlib" || module.name == "kotlin-stdlib-jdk8")) {
|
||||||
|
val requested = "${module.group.replace('.', '/')}/${module.name}/1.7.10/${module.name}-1.7.10.jar"
|
||||||
|
val requestedDestination = resourceRoot.resolve(requested)
|
||||||
|
requestedDestination.parentFile.mkdirs()
|
||||||
|
artifact.file.copyTo(requestedDestination, overwrite = true)
|
||||||
|
index[requested] = requested
|
||||||
|
val requestedPom = requested.removeSuffix(".jar") + ".pom"
|
||||||
|
val requestedPomFile = resourceRoot.resolve(requestedPom)
|
||||||
|
requestedPomFile.parentFile.mkdirs()
|
||||||
|
requestedPomFile.writeText(
|
||||||
|
"<project><modelVersion>4.0.0</modelVersion>" +
|
||||||
|
"<groupId>${module.group}</groupId><artifactId>${module.name}</artifactId>" +
|
||||||
|
"<version>1.7.10</version></project>",
|
||||||
|
Charsets.UTF_8
|
||||||
|
)
|
||||||
|
index[requestedPom] = requestedPom
|
||||||
|
}
|
||||||
|
|
||||||
|
// RuntimeEnvDependency checks POM + SHA-1 files for Kotlin and
|
||||||
|
// coroutine roots. A minimal local POM is sufficient because all
|
||||||
|
// requested root JARs are bundled explicitly.
|
||||||
|
if (module.group == "org.jetbrains.kotlin" || module.group == "org.jetbrains.kotlinx") {
|
||||||
|
val pomRelative = relative.removeSuffix(".jar") + ".pom"
|
||||||
|
val pom = resourceRoot.resolve(pomRelative)
|
||||||
|
pom.parentFile.mkdirs()
|
||||||
|
pom.writeText(
|
||||||
|
"<project><modelVersion>4.0.0</modelVersion>" +
|
||||||
|
"<groupId>${module.group}</groupId><artifactId>${module.name}</artifactId>" +
|
||||||
|
"<version>${module.version}</version></project>",
|
||||||
|
Charsets.UTF_8
|
||||||
|
)
|
||||||
|
index[pomRelative] = pomRelative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val indexFile = root.resolve("META-INF/taboolib/bundled-libraries.properties")
|
||||||
|
indexFile.parentFile.mkdirs()
|
||||||
|
indexFile.writeText(index.entries.joinToString("\n") { (target, resource) -> "$target=$resource" } + "\n", Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.processResources {
|
||||||
|
dependsOn(prepareBundledRuntime)
|
||||||
|
from(prepareBundledRuntime)
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("com.mojang:authlib:3.16.29")
|
compileOnly("com.mojang:authlib:3.16.29")
|
||||||
compileOnly("ink.ptms:nms-all:1.0.0")
|
compileOnly("ink.ptms:nms-all:1.0.0")
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
group=com.github.xbaimiao.shoppro
|
group=com.github.xbaimiao.shoppro
|
||||||
version=1.3.5-SNAPSHOT
|
version=1.3.6-SNAPSHOT
|
||||||
|
|||||||
@@ -1 +1,9 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
maven("https://maven.xbaimiao.com/repository/maven-public/")
|
||||||
|
gradlePluginPortal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rootProject.name = "ShopPro"
|
rootProject.name = "ShopPro"
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package taboolib.common;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs the libraries bundled by the build into TabooLib's normal cache
|
||||||
|
* before PrimitiveLoader starts resolving dependencies.
|
||||||
|
*/
|
||||||
|
public final class BundledLibraryBootstrap {
|
||||||
|
|
||||||
|
private static final String INDEX = "META-INF/taboolib/bundled-libraries.properties";
|
||||||
|
private static final String RESOURCE_PREFIX = "META-INF/taboolib/bundled/";
|
||||||
|
|
||||||
|
private BundledLibraryBootstrap() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void install() {
|
||||||
|
Properties index = new Properties();
|
||||||
|
try (InputStream input = BundledLibraryBootstrap.class.getClassLoader().getResourceAsStream(INDEX)) {
|
||||||
|
if (input == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index.load(input);
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String libraryRoot = "libraries";
|
||||||
|
try (InputStream input = BundledLibraryBootstrap.class.getClassLoader()
|
||||||
|
.getResourceAsStream("META-INF/taboolib/env.properties")) {
|
||||||
|
if (input != null) {
|
||||||
|
Properties env = new Properties();
|
||||||
|
env.load(input);
|
||||||
|
libraryRoot = env.getProperty("file-libs", libraryRoot);
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// The generated defaults already use "libraries".
|
||||||
|
}
|
||||||
|
|
||||||
|
File root = new File(libraryRoot);
|
||||||
|
for (String relativePath : index.stringPropertyNames()) {
|
||||||
|
String resourcePath = index.getProperty(relativePath);
|
||||||
|
if (resourcePath == null || resourcePath.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
File target = new File(root, relativePath.replace('/', File.separatorChar));
|
||||||
|
try {
|
||||||
|
boolean managedArtifact = relativePath.endsWith(".jar") || relativePath.endsWith(".pom");
|
||||||
|
if (!target.isFile() || target.length() == 0L || (managedArtifact && !isSha1Valid(target))) {
|
||||||
|
File parent = target.getParentFile();
|
||||||
|
if (parent != null && !parent.exists() && !parent.mkdirs() && !parent.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try (InputStream input = BundledLibraryBootstrap.class.getClassLoader()
|
||||||
|
.getResourceAsStream(RESOURCE_PREFIX + resourcePath);
|
||||||
|
OutputStream output = Files.newOutputStream(target.toPath())) {
|
||||||
|
if (input == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int read;
|
||||||
|
while ((read = input.read(buffer)) != -1) {
|
||||||
|
output.write(buffer, 0, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (managedArtifact) {
|
||||||
|
writeSha1(target);
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// PrimitiveLoader will report a clear download/load error if a
|
||||||
|
// bundled file cannot be installed.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeSha1(File file) throws IOException {
|
||||||
|
File sha1 = new File(file.getPath() + ".sha1");
|
||||||
|
try {
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
try (InputStream input = Files.newInputStream(file.toPath())) {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int read;
|
||||||
|
while ((read = input.read(buffer)) != -1) {
|
||||||
|
digest.update(buffer, 0, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StringBuilder value = new StringBuilder(40);
|
||||||
|
for (byte part : digest.digest()) {
|
||||||
|
value.append(String.format("%02x", part & 0xff));
|
||||||
|
}
|
||||||
|
Files.write(sha1.toPath(), value.toString().getBytes(java.nio.charset.StandardCharsets.US_ASCII));
|
||||||
|
} catch (java.security.NoSuchAlgorithmException ex) {
|
||||||
|
throw new IOException("SHA-1 is unavailable", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isSha1Valid(File file) {
|
||||||
|
File sha1 = new File(file.getPath() + ".sha1");
|
||||||
|
if (!sha1.isFile() || sha1.length() == 0L) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String expected = new String(Files.readAllBytes(sha1.toPath()), java.nio.charset.StandardCharsets.US_ASCII)
|
||||||
|
.trim().toLowerCase(java.util.Locale.ROOT);
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
try (InputStream input = Files.newInputStream(file.toPath())) {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int read;
|
||||||
|
while ((read = input.read(buffer)) != -1) {
|
||||||
|
digest.update(buffer, 0, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StringBuilder actual = new StringBuilder(40);
|
||||||
|
for (byte part : digest.digest()) {
|
||||||
|
actual.append(String.format("%02x", part & 0xff));
|
||||||
|
}
|
||||||
|
return actual.toString().equals(expected);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package taboolib.common;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static java.lang.System.getProperty;
|
||||||
|
|
||||||
|
/** Runtime settings used by the embedded TabooLib primitive loader. */
|
||||||
|
public class PrimitiveSettings {
|
||||||
|
|
||||||
|
static {
|
||||||
|
// This runs before any PrimitiveLoader dependency check.
|
||||||
|
BundledLibraryBootstrap.install();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String ID = "!taboolib".substring(1);
|
||||||
|
public static final Properties RUNTIME_PROPERTIES = getProperties("env", true);
|
||||||
|
public static final Properties VERSION_PROPERTIES = getProperties("version", false);
|
||||||
|
|
||||||
|
public static final String KOTLIN_VERSION = VERSION_PROPERTIES.getProperty(
|
||||||
|
"!kotlin".substring(1), getProperty("taboolib.kotlin.stdlib", "1.8.22"));
|
||||||
|
public static final String KOTLIN_COROUTINES_VERSION = VERSION_PROPERTIES.getProperty(
|
||||||
|
"!kotlin-coroutines".substring(1), getProperty("taboolib.kotlin.coroutines", "1.7.3"));
|
||||||
|
public static final String TABOOLIB_VERSION = VERSION_PROPERTIES.getProperty(
|
||||||
|
ID, getProperty("taboolib.version", "skip"));
|
||||||
|
public static final boolean SKIP_KOTLIN_RELOCATE = VERSION_PROPERTIES.getProperty(
|
||||||
|
"skip-kotlin-relocate", getProperty("taboolib.skip-relocate.kotlin", "false")).equals("true");
|
||||||
|
public static final boolean SKIP_TABOOLIB_RELOCATE = VERSION_PROPERTIES.getProperty(
|
||||||
|
"skip-taboolib-relocate", getProperty("taboolib.skip-relocate.self", "false")).equals("true");
|
||||||
|
public static final boolean IS_DEV_MODE = TABOOLIB_VERSION.endsWith("-dev")
|
||||||
|
|| getProperty("taboolib.dev", "false").equals("true");
|
||||||
|
public static final boolean IS_DEBUG_MODE = IS_DEV_MODE
|
||||||
|
|| RUNTIME_PROPERTIES.getProperty("debug", getProperty("taboolib.debug", "false")).equals("true");
|
||||||
|
public static final boolean IS_FORCE_DOWNLOAD_IN_DEV_MODE = RUNTIME_PROPERTIES
|
||||||
|
.getProperty("force-download-in-dev", "true").equals("true");
|
||||||
|
public static final String REPO_CENTRAL = RUNTIME_PROPERTIES.getProperty(
|
||||||
|
"repo-central", getProperty("taboolib.repo.central", "https://maven.aliyun.com/repository/central"));
|
||||||
|
public static final String REPO_TABOOLIB = RUNTIME_PROPERTIES.getProperty(
|
||||||
|
"repo-taboolib", getProperty("taboolib.repo.self", "https://maven.xbaimiao.com/repository/maven-public/"));
|
||||||
|
public static final String REPO_REFLEX = RUNTIME_PROPERTIES.getProperty(
|
||||||
|
"repo-reflex", getProperty("taboolib.repo.reflex", REPO_TABOOLIB));
|
||||||
|
public static final String FILE_LIBS = RUNTIME_PROPERTIES.getProperty("file-libs", "libraries");
|
||||||
|
public static final String FILE_ASSETS = RUNTIME_PROPERTIES.getProperty("file-assets", "assets");
|
||||||
|
public static boolean IS_ISOLATED_MODE = RUNTIME_PROPERTIES
|
||||||
|
.getProperty("enable-isolated-classloader", "false").equals("true");
|
||||||
|
public static final String[] INSTALL_MODULES = RUNTIME_PROPERTIES
|
||||||
|
.getProperty("module", getProperty("taboolib.module", "")).split(",");
|
||||||
|
|
||||||
|
public static String formatVersion(String value) {
|
||||||
|
return value.replaceAll("[._-]", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRelocatedKotlinVersion() {
|
||||||
|
return "kotlin" + formatVersion(KOTLIN_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRelocatedKotlinCoroutinesVersion() {
|
||||||
|
return "kotlin" + formatVersion(KOTLIN_VERSION) + "x.coroutines"
|
||||||
|
+ formatVersion(KOTLIN_COROUTINES_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Properties getProperties(String name, boolean allowGlobal) {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
URL url = PrimitiveSettings.class.getClassLoader()
|
||||||
|
.getResource("META-INF/taboolib/" + name + ".properties");
|
||||||
|
if (url != null) {
|
||||||
|
try (InputStreamHolder ignored = new InputStreamHolder(url.openStream())) {
|
||||||
|
properties.load(ignored.input);
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowGlobal) {
|
||||||
|
File globalFile = new File(name + ".properties");
|
||||||
|
if (globalFile.isFile()) {
|
||||||
|
try (FileInputStream input = new FileInputStream(globalFile)) {
|
||||||
|
properties.load(input);
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Small closeable holder to keep the try-with-resources block Java 8 compatible. */
|
||||||
|
private static final class InputStreamHolder implements AutoCloseable {
|
||||||
|
private final java.io.InputStream input;
|
||||||
|
|
||||||
|
private InputStreamHolder(java.io.InputStream input) {
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.github.xbaimiao.shoppro.util
|
|||||||
|
|
||||||
import com.mojang.authlib.GameProfile
|
import com.mojang.authlib.GameProfile
|
||||||
import com.mojang.authlib.properties.Property
|
import com.mojang.authlib.properties.Property
|
||||||
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
import org.bukkit.Color
|
import org.bukkit.Color
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
@@ -18,6 +19,8 @@ import taboolib.library.reflex.Reflex.Companion.setProperty
|
|||||||
import taboolib.library.xseries.XMaterial
|
import taboolib.library.xseries.XMaterial
|
||||||
import taboolib.module.chat.colored
|
import taboolib.module.chat.colored
|
||||||
import taboolib.platform.util.isAir
|
import taboolib.platform.util.isAir
|
||||||
|
import java.net.URL
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@@ -195,6 +198,58 @@ open class ItemBuilder {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bukkit 1.21 stores skull profiles as ResolvableProfile instead of the
|
||||||
|
* authlib GameProfile used by older CraftBukkit versions. Prefer the
|
||||||
|
* public PlayerProfile API when it is available and keep the reflective
|
||||||
|
* field fallback for older servers.
|
||||||
|
*/
|
||||||
|
private fun setSkullTexture(skull: SkullMeta, texture: SkullTexture) {
|
||||||
|
val applied = runCatching {
|
||||||
|
val url = textureUrl(texture.textures) ?: return@runCatching false
|
||||||
|
val createProfile = Bukkit::class.java.methods.firstOrNull {
|
||||||
|
it.name == "createPlayerProfile" &&
|
||||||
|
it.parameterTypes.size == 1 &&
|
||||||
|
it.parameterTypes[0] == UUID::class.java
|
||||||
|
} ?: return@runCatching false
|
||||||
|
val profile = createProfile.invoke(null, texture.uuid ?: UUID.randomUUID())
|
||||||
|
val textures = profile.javaClass.methods.firstOrNull {
|
||||||
|
it.name == "getTextures" && it.parameterTypes.isEmpty()
|
||||||
|
}?.invoke(profile) ?: return@runCatching false
|
||||||
|
val setSkin = textures.javaClass.methods.firstOrNull {
|
||||||
|
it.name == "setSkin" &&
|
||||||
|
it.parameterTypes.size == 1 &&
|
||||||
|
it.parameterTypes[0] == URL::class.java
|
||||||
|
} ?: return@runCatching false
|
||||||
|
setSkin.invoke(textures, URL(url))
|
||||||
|
val setProfile = skull.javaClass.methods.firstOrNull {
|
||||||
|
it.name == "setPlayerProfile" &&
|
||||||
|
it.parameterTypes.size == 1
|
||||||
|
} ?: return@runCatching false
|
||||||
|
setProfile.invoke(skull, profile)
|
||||||
|
true
|
||||||
|
}.getOrDefault(false)
|
||||||
|
|
||||||
|
if (!applied) {
|
||||||
|
runCatching {
|
||||||
|
skull.setProperty("profile", GameProfile(texture.uuid, "test").also {
|
||||||
|
it.properties.put("textures", Property("textures", texture.textures))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun textureUrl(value: String): String? {
|
||||||
|
if (value.startsWith("http://") || value.startsWith("https://")) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
val decoded = runCatching {
|
||||||
|
String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8)
|
||||||
|
}.getOrNull() ?: return null
|
||||||
|
return Regex("\\\"url\\\"\\s*:\\s*\\\"([^\\\"]+)\\\"")
|
||||||
|
.find(decoded)?.groupValues?.get(1)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上色
|
* 上色
|
||||||
*/
|
*/
|
||||||
@@ -255,9 +310,7 @@ open class ItemBuilder {
|
|||||||
itemMeta.owner = skullOwner
|
itemMeta.owner = skullOwner
|
||||||
}
|
}
|
||||||
if (skullTexture != null) {
|
if (skullTexture != null) {
|
||||||
itemMeta.setProperty("profile", GameProfile(skullTexture!!.uuid, "test").also {
|
setSkullTexture(itemMeta, skullTexture!!)
|
||||||
it.properties.put("textures", Property("textures", skullTexture!!.textures))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user