diff --git a/build.gradle.kts b/build.gradle.kts index 54453c2ed..9539df2a0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -499,7 +499,8 @@ val supportedMinecraftVersions = listOf( MinecraftRunTarget("1.21.1", 21), MinecraftRunTarget("1.21.4", 21), MinecraftRunTarget("1.21.8", 21), - MinecraftRunTarget("26.1.2", 25) + MinecraftRunTarget("26.1.2", 25), + MinecraftRunTarget("26.3", 25) ) fun RunServer.configureGuildsRunServer(target: MinecraftRunTarget) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 69e960f2c..ae26ac5a9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ quark = "1.3.0" junit = "5.11.4" mockito = "5.24.0" -minecraft-spigot-api = "26.2-R0.1-SNAPSHOT" +minecraft-spigot-api = "26.3-R0.1-SNAPSHOT" minecraft-spigot-api-legacy = "1.8.8-R0.1-SNAPSHOT" # Newest Spigot API that is still Java 11 loadable. The main source set compiles against the current # API, whose bytecode a Java 11 JVM cannot load, so the tests get this one instead. @@ -22,7 +22,7 @@ taskchain = "3.7.2" worldguardwrapper = "1.1.9-SNAPSHOT" configme = "1.3.0" jsonconfiguration = "1.1" -xseries = "13.7.1" +xseries = "14.0.0" adventure-platform-bukkit = "4.4.1" # 3.1.13 changes GUI constructor compatibility; current GUI classes still extend old constructors. triumph-gui = "3.1.11" @@ -73,4 +73,4 @@ run-paper = { id = "xyz.jpenilla.run-paper", version.ref = "run-paper" } versions = { id = "io.github.ben-manes.versions", version.ref = "versions-plugin" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } -quark = { id = "org.bxteam.quark", version.ref = "quark" } \ No newline at end of file +quark = { id = "org.bxteam.quark", version.ref = "quark" } diff --git a/src/main/java/me/glaremasters/guilds/guild/GuildSkull.java b/src/main/java/me/glaremasters/guilds/guild/GuildSkull.java index 7443a6a75..d9a9aedc7 100644 --- a/src/main/java/me/glaremasters/guilds/guild/GuildSkull.java +++ b/src/main/java/me/glaremasters/guilds/guild/GuildSkull.java @@ -1,8 +1,8 @@ package me.glaremasters.guilds.guild; -import com.cryptomorin.xseries.profiles.builder.XSkull; import com.cryptomorin.xseries.profiles.objects.ProfileInputType; import com.cryptomorin.xseries.profiles.objects.Profileable; +import me.glaremasters.guilds.utils.SkullUtils; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -24,8 +24,8 @@ public class GuildSkull { public GuildSkull(Player player) { final Profileable playerProfile = Profileable.of(player); - itemStack = XSkull.createItem().profile(playerProfile).apply(); - serialized = XSkull.of(itemStack.getItemMeta()).getProfileValue(); + itemStack = SkullUtils.create(playerProfile); + serialized = SkullUtils.profileValue(itemStack, player.getUniqueId().toString()); } /** @@ -57,12 +57,12 @@ public ItemStack createSkull() { final ProfileInputType backupType = ProfileInputType.typeOf("c10591e6909e6a281b371836e462d67a2c78fa0952e910f32b41a26c48c1757c"); final Profileable backupProfile = Profileable.of(backupType, serialized); - return XSkull.createItem().profile(backupProfile).apply(); + return SkullUtils.create(backupProfile); } final Profileable playerProfile = Profileable.of(type, serialized); - return XSkull.createItem().profile(playerProfile).apply(); + return SkullUtils.create(playerProfile); } /** diff --git a/src/main/java/me/glaremasters/guilds/listeners/EntityListener.java b/src/main/java/me/glaremasters/guilds/listeners/EntityListener.java index b056ac669..43f39e2d6 100644 --- a/src/main/java/me/glaremasters/guilds/listeners/EntityListener.java +++ b/src/main/java/me/glaremasters/guilds/listeners/EntityListener.java @@ -2,6 +2,7 @@ import ch.jalu.configme.SettingsManager; import com.cryptomorin.xseries.XPotion; +import com.cryptomorin.xseries.XTag; import me.glaremasters.guilds.challenges.ChallengeHandler; import me.glaremasters.guilds.configuration.sections.GuildSettings; import me.glaremasters.guilds.guild.Guild; @@ -239,7 +240,7 @@ public void onSplash(PotionSplashEvent event) { */ private boolean isHarmfulPotion(final ThrownPotion potion) { for (final PotionEffect effect : potion.getEffects()) { - if (XPotion.DEBUFFS.contains(XPotion.matchXPotion(effect.getType()))) { + if (XTag.DEBUFFS.isTagged(XPotion.of(effect.getType()))) { return true; } } diff --git a/src/main/java/me/glaremasters/guilds/utils/GuiUtils.java b/src/main/java/me/glaremasters/guilds/utils/GuiUtils.java index 93a11db94..b617f2e4c 100644 --- a/src/main/java/me/glaremasters/guilds/utils/GuiUtils.java +++ b/src/main/java/me/glaremasters/guilds/utils/GuiUtils.java @@ -1,7 +1,6 @@ package me.glaremasters.guilds.utils; import com.cryptomorin.xseries.XMaterial; -import com.cryptomorin.xseries.profiles.builder.XSkull; import com.cryptomorin.xseries.profiles.objects.ProfileInputType; import com.cryptomorin.xseries.profiles.objects.Profileable; import me.glaremasters.guilds.guild.GuildMember; @@ -62,7 +61,7 @@ public static ItemStack createSkullItem(final GuildMember member, final String n playerProfile = Profileable.of(backupType, "c10591e6909e6a281b371836e462d67a2c78fa0952e910f32b41a26c48c1757c"); } - final ItemStack itemStack = XSkull.createItem().profile(playerProfile).apply(); + final ItemStack itemStack = SkullUtils.create(playerProfile); final ItemMeta meta = itemStack.getItemMeta(); meta.setDisplayName(StringUtils.color(name)); diff --git a/src/main/java/me/glaremasters/guilds/utils/SkullUtils.java b/src/main/java/me/glaremasters/guilds/utils/SkullUtils.java new file mode 100644 index 000000000..f29344117 --- /dev/null +++ b/src/main/java/me/glaremasters/guilds/utils/SkullUtils.java @@ -0,0 +1,49 @@ +package me.glaremasters.guilds.utils; + +import com.cryptomorin.xseries.XMaterial; +import com.cryptomorin.xseries.profiles.builder.XSkull; +import com.cryptomorin.xseries.profiles.objects.Profileable; +import org.bukkit.inventory.ItemStack; + +/** Cross-version player skull creation with a fallback for XSeries profile reflection failures. */ +public final class SkullUtils { + + private SkullUtils() { + } + + public static ItemStack create(Profileable profile) { + try { + return XSkull.createItem().profile(profile).apply(); + } catch (RuntimeException | LinkageError failure) { + if (!hasLinkageFailure(failure)) { + throw failure; + } + + ItemStack head = XMaterial.PLAYER_HEAD.parseItem(); + if (head == null) { + throw failure; + } + return head; + } + } + + public static String profileValue(ItemStack item, String fallback) { + try { + return XSkull.of(item.getItemMeta()).getProfileValue(); + } catch (RuntimeException | LinkageError failure) { + if (!hasLinkageFailure(failure)) { + throw failure; + } + return fallback; + } + } + + private static boolean hasLinkageFailure(Throwable failure) { + for (Throwable cause = failure; cause != null; cause = cause.getCause()) { + if (cause instanceof LinkageError) { + return true; + } + } + return false; + } +}