diff --git a/README.md b/README.md index 4cc85b6a..8bf9d2cf 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ To achieve this it's nearly impossible for a single person or a small team, that - legacy-lands-library - [GitHub](https://github.com/LegacyLands/legacy-lands-library) - *Feel free to open a PR to add your project to here!* +## Prerequisites +- **Java 21** or higher is required for development and compilation. + ## Getting Started If you are interested in creating a project using Fairy framework, please start with [project template](https://github.com/FairyProject/fairy-bukkit-template) and give our [documentation](https://docs.fairyproject.io/) a read!. diff --git a/framework/modules/bukkit/bukkit-nbt/build.gradle.kts b/framework/modules/bukkit/bukkit-nbt/build.gradle.kts index 71cb4af8..e4045838 100644 --- a/framework/modules/bukkit/bukkit-nbt/build.gradle.kts +++ b/framework/modules/bukkit/bukkit-nbt/build.gradle.kts @@ -3,5 +3,5 @@ plugins { } dependencies { - implementation("de.tr7zw:item-nbt-api:2.15.5") + implementation("de.tr7zw:item-nbt-api:2.15.6") } \ No newline at end of file diff --git a/framework/modules/bukkit/bukkit-xseries/build.gradle.kts b/framework/modules/bukkit/bukkit-xseries/build.gradle.kts index 31d6f662..014ddbdf 100644 --- a/framework/modules/bukkit/bukkit-xseries/build.gradle.kts +++ b/framework/modules/bukkit/bukkit-xseries/build.gradle.kts @@ -6,7 +6,7 @@ dependencies { compileOnly("org.spigotmc:spigot-api:1.21.3-R0.1-SNAPSHOT") api("io.fairyproject:core-command") - api("com.github.cryptomorin:XSeries:13.6.0") + api("io.github.almighty-satan:XSeries:13.6.0+26.1") implementation("com.google.code.findbugs:jsr305:3.0.2") } diff --git a/framework/modules/bukkit/bukkit-xseries/src/main/java/com/cryptomorin/xseries/XBlock.java b/framework/modules/bukkit/bukkit-xseries/src/main/java/com/cryptomorin/xseries/XBlock.java index ba81c7a7..98d64ac3 100644 --- a/framework/modules/bukkit/bukkit-xseries/src/main/java/com/cryptomorin/xseries/XBlock.java +++ b/framework/modules/bukkit/bukkit-xseries/src/main/java/com/cryptomorin/xseries/XBlock.java @@ -70,7 +70,7 @@ public final class XBlock { XMaterial.MAGMA_BLOCK, XMaterial.LAVA, XMaterial.CAMPFIRE, XMaterial.FIRE, XMaterial.SOUL_FIRE )); public static final byte CAKE_SLICES = 6; - private static final boolean ISFLAT = XMaterial.supports(13); + private static final boolean ISFLAT = XMaterial.supports(1, 13); private static final Map ITEM_TO_BLOCK = new EnumMap<>(XMaterial.class); static { diff --git a/framework/platforms/bukkit-platform/build.gradle.kts b/framework/platforms/bukkit-platform/build.gradle.kts index d1147d03..7e06ad9b 100644 --- a/framework/platforms/bukkit-platform/build.gradle.kts +++ b/framework/platforms/bukkit-platform/build.gradle.kts @@ -6,7 +6,7 @@ dependencies { api(project(":mc-platform")) api("net.kyori:adventure-platform-bukkit:4.4.1") api("net.kyori:adventure-text-serializer-bungeecord:4.4.1") - api("com.github.retrooper:packetevents-spigot:2.11.1") { + api("com.github.retrooper:packetevents-spigot:2.12.0") { exclude(group = "net.kyori") } compileOnly("io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT") { diff --git a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/mc/BukkitMCGameProfile.java b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/mc/BukkitMCGameProfile.java index 8355de28..1f4e0698 100644 --- a/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/mc/BukkitMCGameProfile.java +++ b/framework/platforms/bukkit-platform/src/main/java/io/fairyproject/bukkit/mc/BukkitMCGameProfile.java @@ -9,10 +9,58 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.util.*; public class BukkitMCGameProfile implements MCGameProfile { + // Reflection cache for authlib API compatibility (old getter-style vs new record-style) + private static final Method GP_GET_NAME; + private static final Method GP_GET_ID; + private static final Method GP_GET_PROPERTIES; + private static final Method PROP_GET_NAME; + private static final Method PROP_GET_VALUE; + private static final Method PROP_GET_SIGNATURE; + private static final Constructor PROP_CONSTRUCTOR; + + static { + GP_GET_NAME = resolveMethod(GameProfile.class, "name", "getName"); + GP_GET_ID = resolveMethod(GameProfile.class, "id", "getId"); + GP_GET_PROPERTIES = resolveMethod(GameProfile.class, "properties", "getProperties"); + PROP_GET_NAME = resolveMethod(com.mojang.authlib.properties.Property.class, "name", "getName"); + PROP_GET_VALUE = resolveMethod(com.mojang.authlib.properties.Property.class, "value", "getValue"); + PROP_GET_SIGNATURE = resolveMethod(com.mojang.authlib.properties.Property.class, "signature", "getSignature"); + PROP_CONSTRUCTOR = resolvePropConstructor(); + } + + private static Method resolveMethod(Class clazz, String... names) { + for (String name : names) { + try { + return clazz.getMethod(name); + } catch (NoSuchMethodException ignored) { + } + } + throw new IllegalStateException("No method found on " + clazz.getName() + " for names: " + Arrays.toString(names)); + } + + private static Constructor resolvePropConstructor() { + try { + return com.mojang.authlib.properties.Property.class.getConstructor(String.class, String.class, String.class); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Cannot find Property constructor", e); + } + } + + @SuppressWarnings("unchecked") + private static T invoke(Method method, Object obj) { + try { + return (T) method.invoke(obj); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + public static final EquivalentConverter CONVERTER = new EquivalentConverter() { @Override public Object getGeneric(MCGameProfile specific) { @@ -46,12 +94,16 @@ public BukkitMCGameProfile(GameProfile gameProfile) { @Override public String getName() { - return this.gameProfile.getName(); + return invoke(GP_GET_NAME, this.gameProfile); } @Override public UUID getUuid() { - return this.gameProfile.getId(); + return invoke(GP_GET_ID, this.gameProfile); + } + + private PropertyMap getPropertyMap() { + return invoke(GP_GET_PROPERTIES, this.gameProfile); } @NotNull @@ -62,15 +114,19 @@ public Set getProperties() { @Override public boolean hasProperty(String property) { - return this.gameProfile.getProperties().containsKey(property); + return getPropertyMap().containsKey(property); } @Override public void setProperty(Property property) { String name = property.getName(); - PropertyMap properties = this.gameProfile.getProperties(); + PropertyMap properties = getPropertyMap(); properties.removeAll(name); - properties.put(name, new com.mojang.authlib.properties.Property(name, property.getValue(), property.getSignature())); + try { + properties.put(name, (com.mojang.authlib.properties.Property) PROP_CONSTRUCTOR.newInstance(name, property.getValue(), property.getSignature())); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } } @Override @@ -80,16 +136,20 @@ public void setProperties(Collection properties) { @Override public void clearProperties() { - this.gameProfile.getProperties().clear(); + getPropertyMap().clear(); } @Override public boolean removeProperty(String property) { - return !this.gameProfile.getProperties().removeAll(property).isEmpty(); + return !getPropertyMap().removeAll(property).isEmpty(); } private static Property toBukkit(com.mojang.authlib.properties.Property property) { - return new Property(property.getName(), property.getValue(), property.getSignature()); + return new Property( + invoke(PROP_GET_NAME, property), + invoke(PROP_GET_VALUE, property), + invoke(PROP_GET_SIGNATURE, property) + ); } private class PropertySet extends AbstractSet { @@ -97,12 +157,12 @@ private class PropertySet extends AbstractSet { @Override @Nonnull public Iterator iterator() { - return new ProfilePropertyIterator(gameProfile.getProperties().values().iterator()); + return new ProfilePropertyIterator(getPropertyMap().values().iterator()); } @Override public int size() { - return gameProfile.getProperties().size(); + return getPropertyMap().size(); } @Override @@ -120,7 +180,7 @@ public boolean addAll(Collection c) { @Override public boolean contains(Object o) { - return o instanceof ProfileProperty && gameProfile.getProperties().containsKey(((ProfileProperty) o).getName()); + return o instanceof ProfileProperty && getPropertyMap().containsKey(((ProfileProperty) o).getName()); } private class ProfilePropertyIterator implements Iterator { diff --git a/framework/platforms/mc-platform/build.gradle.kts b/framework/platforms/mc-platform/build.gradle.kts index ca235779..a6bb9266 100644 --- a/framework/platforms/mc-platform/build.gradle.kts +++ b/framework/platforms/mc-platform/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { api("net.kyori:adventure-text-serializer-gson-legacy-impl:4.25.0") api("net.kyori:adventure-text-serializer-plain:4.25.0") - api("com.github.retrooper:packetevents-api:2.11.1") { + api("com.github.retrooper:packetevents-api:2.12.0") { exclude(group = "net.kyori") } diff --git a/framework/platforms/mc-platform/src/main/java/io/fairyproject/mc/version/MCVersionMappingRegistry.java b/framework/platforms/mc-platform/src/main/java/io/fairyproject/mc/version/MCVersionMappingRegistry.java index f10ace6c..a7472a32 100644 --- a/framework/platforms/mc-platform/src/main/java/io/fairyproject/mc/version/MCVersionMappingRegistry.java +++ b/framework/platforms/mc-platform/src/main/java/io/fairyproject/mc/version/MCVersionMappingRegistry.java @@ -47,7 +47,7 @@ public class MCVersionMappingRegistry { // Hardcoded latest version to validate cache - private static final MCVersion LATEST_VERSION = MCVersion.of(1, 21, 0); + private static final MCVersion LATEST_VERSION = MCVersion.of(26, 1, 0); private final Gson gson = new Gson(); @Getter @@ -143,6 +143,8 @@ protected void loadVersionFromMinecraftData(JsonObject object) { boolean hexColor = major >= 1 && minor >= 16; boolean nmsPrefix = major < 1 || minor < 17; + if (major > 1) + nmsPrefix = false; this.register(new MCVersionMapping(major, minor, patch, nmsPrefix, hexColor, protocolVersion)); } diff --git a/framework/platforms/mc-platform/src/test/java/io/fairyproject/mc/version/MCVersionMappingRegistryTest.java b/framework/platforms/mc-platform/src/test/java/io/fairyproject/mc/version/MCVersionMappingRegistryTest.java index ebeb4a64..f4703c6c 100644 --- a/framework/platforms/mc-platform/src/test/java/io/fairyproject/mc/version/MCVersionMappingRegistryTest.java +++ b/framework/platforms/mc-platform/src/test/java/io/fairyproject/mc/version/MCVersionMappingRegistryTest.java @@ -142,6 +142,7 @@ public void nmsPrefix_shouldNotBeAvailableAbove1_17() { Assertions.assertTrue(registry.findMapping(1, 15, 2).isNmsPrefix()); Assertions.assertTrue(registry.findMapping(1, 16, 0).isNmsPrefix()); Assertions.assertFalse(registry.findMapping(1, 17, 0).isNmsPrefix()); + Assertions.assertFalse(registry.findMapping(26, 1, 0).isNmsPrefix()); } } diff --git a/global.properties b/global.properties index a88e3bff..2e9d12e5 100644 --- a/global.properties +++ b/global.properties @@ -1 +1 @@ -version = 0.8.4b1-SNAPSHOT \ No newline at end of file +version = 0.8.6b1-SNAPSHOT diff --git a/test-plugin/build.gradle.kts b/test-plugin/build.gradle.kts index 1726ed92..e903391d 100644 --- a/test-plugin/build.gradle.kts +++ b/test-plugin/build.gradle.kts @@ -23,8 +23,8 @@ dependencies { } runServer { - version = "1.21.11" - javaVersion.set(JavaVersion.VERSION_21) + version = "26.1" + javaVersion.set(JavaVersion.VERSION_25) } java {