From 4afbe845ff78892d622aed02a110fc8e1dda33d5 Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Mon, 3 Jun 2024 20:56:56 -0500 Subject: [PATCH] Fix attributes, a few enums, and some tests --- build.gradle | 13 +++++++--- .../com/comphenix/protocol/PacketType.java | 1 + .../protocol/reflect/fuzzy/FuzzyMatchers.java | 20 ++++++++++++++ .../protocol/utility/MinecraftReflection.java | 18 ++++++++++--- .../protocol/wrappers/EnumWrappers.java | 3 ++- .../protocol/wrappers/WrappedAttribute.java | 26 ++++++++++++++----- .../protocol/wrappers/WrappedRegistry.java | 4 ++- .../wrappers/codecs/WrappedDataResult.java | 16 +++++++++--- .../utility/MinecraftReflectionTestUtil.java | 2 +- .../wrappers/BukkitConvertersTest.java | 2 +- .../protocol/wrappers/EnumWrappersTest.java | 5 ++-- .../wrappers/WrappedAttributeTest.java | 9 ++++--- 12 files changed, 92 insertions(+), 27 deletions(-) diff --git a/build.gradle b/build.gradle index 06a3f19e0..fb2b35bf2 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } group = 'com.comphenix.protocol' -version = '5.2.1-SNAPSHOT' +version = '5.3.0-SNAPSHOT' description = 'Provides access to the Minecraft protocol' def isSnapshot = version.endsWith('-SNAPSHOT') @@ -34,8 +34,8 @@ repositories { dependencies { implementation 'net.bytebuddy:byte-buddy:1.14.14' - compileOnly 'org.spigotmc:spigot-api:1.20.5-R0.1-SNAPSHOT' - compileOnly 'org.spigotmc:spigot:1.20.5-R0.1-SNAPSHOT' + compileOnly 'org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT' + compileOnly 'org.spigotmc:spigot:1.20.6-R0.1-SNAPSHOT' compileOnly 'io.netty:netty-all:4.0.23.Final' compileOnly 'net.kyori:adventure-text-serializer-gson:4.14.0' compileOnly 'com.googlecode.json-simple:json-simple:1.1.1' @@ -46,7 +46,7 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.6.0' testImplementation 'io.netty:netty-common:4.1.97.Final' testImplementation 'io.netty:netty-transport:4.1.97.Final' - testImplementation 'org.spigotmc:spigot:1.20.5-R0.1-SNAPSHOT' + testImplementation 'org.spigotmc:spigot:1.20.6-R0.1-SNAPSHOT' testImplementation 'net.kyori:adventure-text-serializer-gson:4.14.0' testImplementation 'net.kyori:adventure-text-serializer-plain:4.14.0' } @@ -74,6 +74,11 @@ test { } } +compileTestJava { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + processResources { def includeBuild = isSnapshot && System.getenv('BUILD_NUMBER') def fullVersion = includeBuild diff --git a/src/main/java/com/comphenix/protocol/PacketType.java b/src/main/java/com/comphenix/protocol/PacketType.java index f26d9c6d6..e690dc971 100644 --- a/src/main/java/com/comphenix/protocol/PacketType.java +++ b/src/main/java/com/comphenix/protocol/PacketType.java @@ -731,6 +731,7 @@ public enum Protocol { STATUS("Status", "status"), LOGIN("Login", "login"), CONFIGURATION("Configuration", "configuration"), + TRANSFER("Transfer", "transfer"), // TODO are these the right names? /** * Only for packets removed in Minecraft 1.7.2 diff --git a/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMatchers.java b/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMatchers.java index db8994ce8..7d457f6ab 100644 --- a/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMatchers.java +++ b/src/main/java/com/comphenix/protocol/reflect/fuzzy/FuzzyMatchers.java @@ -29,6 +29,26 @@ public static AbstractFuzzyMatcher> matchArray(AbstractFuzzyMatcher value.isArray() && componentMatcher.isMatch(value.getComponentType(), parent); } + public static AbstractFuzzyMatcher> except(Class clazz) { + return (value, parent) -> !clazz.isAssignableFrom(value); + } + + public static AbstractFuzzyMatcher> assignable(Class clazz) { + return (value, parent) -> clazz.isAssignableFrom(value); + } + + @SafeVarargs + public static AbstractFuzzyMatcher> and(AbstractFuzzyMatcher>... matchers) { + return (value, parent) -> { + for (AbstractFuzzyMatcher> matcher : matchers) { + if (!matcher.isMatch(value, parent)) { + return false; + } + } + return true; + }; + } + /** * Retrieve a fuzzy matcher that will match any class. * diff --git a/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java b/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java index b18282a72..f8a5b0c54 100644 --- a/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java +++ b/src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java @@ -1470,6 +1470,14 @@ public static Class getMinecraftLibraryClass(String className) { .orElseThrow(() -> new RuntimeException("Failed to find class: " + className)); } + public static Optional> getOptionalLibraryClass(String className) { + if (libraryPackage == null) { + libraryPackage = new CachedPackage("", getClassSource()); + } + + return libraryPackage.getPackageClass(className); + } + /** * Set the class object for the specific library class. * @@ -1651,9 +1659,13 @@ public static Class getLibraryClass(String classname) { try { return getMinecraftLibraryClass(classname); } catch (RuntimeException ex) { - Class clazz = getMinecraftLibraryClass("org.bukkit.craftbukkit.libs." + classname); - setMinecraftLibraryClass(classname, clazz); - return clazz; + try { + Class clazz = getMinecraftLibraryClass("org.bukkit.craftbukkit.libs." + classname); + setMinecraftLibraryClass(classname, clazz); + return clazz; + } catch (Exception ignored) { + throw ex; + } } } diff --git a/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java b/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java index e7479739e..889304d74 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java +++ b/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java @@ -358,7 +358,8 @@ public enum ItemSlot { FEET, LEGS, CHEST, - HEAD + HEAD, + BODY } public enum Hand { diff --git a/src/main/java/com/comphenix/protocol/wrappers/WrappedAttribute.java b/src/main/java/com/comphenix/protocol/wrappers/WrappedAttribute.java index 2f57e4f94..6e2d4f71f 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/WrappedAttribute.java +++ b/src/main/java/com/comphenix/protocol/wrappers/WrappedAttribute.java @@ -12,6 +12,11 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.network.protocol.game.PacketPlayOutUpdateAttributes; +import net.minecraft.world.entity.ai.attributes.AttributeBase; +import org.w3c.dom.Attr; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -26,6 +31,8 @@ */ public class WrappedAttribute extends AbstractWrapper { public static boolean KEY_WRAPPED = MinecraftVersion.NETHER_UPDATE.atOrAbove(); + public static boolean IS_STATIC = MinecraftVersion.CAVES_CLIFFS_1.atOrAbove(); + public static boolean IS_IN_HOLDER = MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE.atOrAbove(); // Shared structure modifier private static StructureModifier ATTRIBUTE_MODIFIER; @@ -136,8 +143,13 @@ public static class WrappedAttributeBase { */ public String getAttributeKey() { if (KEY_WRAPPED) { - WrappedAttributeBase base = modifier.withType(ATTRIBUTE_BASE_CLASS, ATTRIBUTE_BASE).read(0); - return base.key.replace("attribute.name.", ""); // TODO not entirely sure why this happens + StructureModifier typedModifier = IS_IN_HOLDER + ? modifier.withParamType(MinecraftReflection.getHolderClass(), + Converters.holder(ATTRIBUTE_BASE, WrappedRegistry.getAttributeRegistry()), + ATTRIBUTE_BASE_CLASS) + : modifier.withType(ATTRIBUTE_BASE_CLASS, ATTRIBUTE_BASE); + WrappedAttributeBase base = typedModifier.read(0); + return base.key.replace("attribute.name.", ""); } else { return (String) modifier.withType(String.class).read(0); } @@ -447,12 +459,10 @@ public WrappedAttribute build() { throw new IllegalStateException("Base value has not been set."); } - boolean isStatic = MinecraftVersion.CAVES_CLIFFS_1.atOrAbove(); - if (ATTRIBUTE_CONSTRUCTOR == null) { FuzzyReflection ref = FuzzyReflection.fromClass(MinecraftReflection.getAttributeSnapshotClass(), true); - FuzzyMethodContract.Builder contract = FuzzyMethodContract.newBuilder().parameterCount(isStatic ? 3 : 4); - if (!isStatic) { + FuzzyMethodContract.Builder contract = FuzzyMethodContract.newBuilder().parameterCount(IS_STATIC ? 3 : 4); + if (!IS_STATIC) { contract.parameterDerivedOf(MinecraftReflection.getPacketClass(), 0); } contract.parameterExactType(double.class).parameterDerivedOf(Collection.class); @@ -471,13 +481,15 @@ public WrappedAttribute build() { if (attributeKey == null) { throw new IllegalArgumentException("Invalid attribute name: " + this.attributeKey); } + + attributeKey = registry.getHolder(attributeKey); } else { attributeKey = this.attributeKey; } try { Object handle; - if (isStatic) { + if (IS_STATIC) { handle = ATTRIBUTE_CONSTRUCTOR.newInstance(attributeKey, baseValue, getUnwrappedModifiers()); } else { handle = ATTRIBUTE_CONSTRUCTOR.newInstance(packet.getHandle(), attributeKey, baseValue, getUnwrappedModifiers()); diff --git a/src/main/java/com/comphenix/protocol/wrappers/WrappedRegistry.java b/src/main/java/com/comphenix/protocol/wrappers/WrappedRegistry.java index f2e39287b..232d02f8a 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/WrappedRegistry.java +++ b/src/main/java/com/comphenix/protocol/wrappers/WrappedRegistry.java @@ -3,6 +3,7 @@ import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.MethodAccessor; +import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftVersion; @@ -15,6 +16,7 @@ import java.lang.reflect.WildcardType; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.Set; public class WrappedRegistry { @@ -87,7 +89,7 @@ public class WrappedRegistry { GET = Accessors.getMethodAccessor(fuzzy.getMethod(FuzzyMethodContract .newBuilder() .parameterCount(1) - .returnDerivedOf(Object.class) + .returnTypeMatches(FuzzyMatchers.and(FuzzyMatchers.assignable(Object.class), FuzzyMatchers.except(Optional.class))) .requireModifier(Modifier.ABSTRACT) .parameterExactType(MinecraftReflection.getMinecraftKeyClass()) .build())); diff --git a/src/main/java/com/comphenix/protocol/wrappers/codecs/WrappedDataResult.java b/src/main/java/com/comphenix/protocol/wrappers/codecs/WrappedDataResult.java index e430df611..2ce2d91cd 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/codecs/WrappedDataResult.java +++ b/src/main/java/com/comphenix/protocol/wrappers/codecs/WrappedDataResult.java @@ -11,10 +11,16 @@ public class WrappedDataResult extends AbstractWrapper { private final static Class HANDLE_TYPE = MinecraftReflection.getLibraryClass("com.mojang.serialization.DataResult"); - private final static Class PARTIAL_DATA_RESULT_CLASS = MinecraftReflection.getLibraryClass("com.mojang.serialization.DataResult$PartialResult"); + private final static Optional> PARTIAL_DATA_RESULT_CLASS = MinecraftReflection.getOptionalLibraryClass("com.mojang.serialization.DataResult$PartialResult"); private final static MethodAccessor ERROR_ACCESSOR = Accessors.getMethodAccessor(HANDLE_TYPE, "error"); private final static MethodAccessor RESULT_ACCESSOR = Accessors.getMethodAccessor(HANDLE_TYPE, "result"); - private final static MethodAccessor PARTIAL_RESULT_MESSAGE_ACCESSOR = Accessors.getMethodAccessor(PARTIAL_DATA_RESULT_CLASS, "message"); + private static MethodAccessor PARTIAL_RESULT_MESSAGE_ACCESSOR; + + static { + if (PARTIAL_DATA_RESULT_CLASS.isPresent()) { + PARTIAL_RESULT_MESSAGE_ACCESSOR = Accessors.getMethodAccessor(PARTIAL_DATA_RESULT_CLASS.get(), "message"); + } + } /** * Construct a new NMS wrapper. @@ -38,13 +44,15 @@ public Optional getErrorMessage() { public Object getOrThrow(Function errorHandler) { Optional err = getErrorMessage(); - if(err.isPresent()) { + if (err.isPresent()) { return errorHandler.apply((String) PARTIAL_RESULT_MESSAGE_ACCESSOR.invoke(err.get())); } + Optional result = getResult(); - if(result.isPresent()) { + if (result.isPresent()) { return result.get(); } + throw new NoSuchElementException(); } } diff --git a/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTestUtil.java b/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTestUtil.java index 0a342c7b6..389fd7d99 100644 --- a/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTestUtil.java +++ b/src/test/java/com/comphenix/protocol/utility/MinecraftReflectionTestUtil.java @@ -2,7 +2,7 @@ public class MinecraftReflectionTestUtil { - public static final String RELEASE_TARGET = "1.20.4"; + public static final String RELEASE_TARGET = "1.20.6"; public static final String PACKAGE_VERSION = "v1_20_R4"; public static final String NMS = "net.minecraft"; public static final String OBC = "org.bukkit.craftbukkit." + PACKAGE_VERSION; diff --git a/src/test/java/com/comphenix/protocol/wrappers/BukkitConvertersTest.java b/src/test/java/com/comphenix/protocol/wrappers/BukkitConvertersTest.java index bb749b34f..7412b2cbd 100644 --- a/src/test/java/com/comphenix/protocol/wrappers/BukkitConvertersTest.java +++ b/src/test/java/com/comphenix/protocol/wrappers/BukkitConvertersTest.java @@ -31,7 +31,7 @@ public static void beforeClass() { @Test public void testItemStacks() { ItemStack item = new ItemStack(Material.DIAMOND_SWORD, 16); - item.addEnchantment(Enchantment.POWER, 4); + item.addEnchantment(Enchantment.SHARPNESS, 4); ItemMeta meta = item.getItemMeta(); meta.setDisplayName(ChatColor.GREEN + "Diamond Sword"); item.setItemMeta(meta); diff --git a/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java b/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java index 50b846043..4f7333959 100644 --- a/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java +++ b/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java @@ -44,8 +44,9 @@ public void validateAllEnumFieldsAreWrapped() { assertNotNull(unwrappedValue); assertEquals(nativeConstant, unwrappedValue); - } catch (Exception exception) { - fail(exception); + } catch (Exception ex) { + fail(ex); + // ex.printStackTrace(); } } } diff --git a/src/test/java/com/comphenix/protocol/wrappers/WrappedAttributeTest.java b/src/test/java/com/comphenix/protocol/wrappers/WrappedAttributeTest.java index 819a31cea..ae2033628 100644 --- a/src/test/java/com/comphenix/protocol/wrappers/WrappedAttributeTest.java +++ b/src/test/java/com/comphenix/protocol/wrappers/WrappedAttributeTest.java @@ -95,9 +95,12 @@ private AttributeSnapshot getAttributeCopy(WrappedAttribute attribute) { modifiers.add((AttributeModifier) wrapper.getHandle()); } - IRegistry registry = BuiltInRegistries.u; - AttributeBase base = registry.a(MinecraftKey.a(attribute.getAttributeKey())); - return new AttributeSnapshot(Holder.a(base), attribute.getBaseValue(), modifiers); + IRegistry registry = BuiltInRegistries.u; + String attributeKey = attribute.getAttributeKey(); + MinecraftKey key = MinecraftKey.a(attributeKey); + AttributeBase base = registry.a(key); + Holder holder = registry.e(base); + return new AttributeSnapshot(holder, attribute.getBaseValue(), modifiers); } private AttributeModifier getModifierCopy(WrappedAttributeModifier modifier) {