Start 1.20.4 update

This commit is contained in:
Dan Mulloy 2023-12-09 15:56:45 -06:00
parent 80a097953f
commit 8ba1dc1284
No known key found for this signature in database
GPG Key ID: 3C5AD5D866D1539A
22 changed files with 206 additions and 99 deletions

View File

@ -34,8 +34,8 @@ repositories {
dependencies { dependencies {
implementation 'net.bytebuddy:byte-buddy:1.14.9' implementation 'net.bytebuddy:byte-buddy:1.14.9'
compileOnly 'org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot-api:1.20.4-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot:1.20.4-R0.1-SNAPSHOT'
compileOnly 'io.netty:netty-all:4.0.23.Final' compileOnly 'io.netty:netty-all:4.0.23.Final'
compileOnly 'net.kyori:adventure-text-serializer-gson:4.13.0' compileOnly 'net.kyori:adventure-text-serializer-gson:4.13.0'
compileOnly 'com.googlecode.json-simple:json-simple:1.1.1' compileOnly 'com.googlecode.json-simple:json-simple:1.1.1'
@ -46,7 +46,7 @@ dependencies {
testImplementation 'org.mockito:mockito-core:5.6.0' testImplementation 'org.mockito:mockito-core:5.6.0'
testImplementation 'io.netty:netty-common:4.1.97.Final' testImplementation 'io.netty:netty-common:4.1.97.Final'
testImplementation 'io.netty:netty-transport:4.1.97.Final' testImplementation 'io.netty:netty-transport:4.1.97.Final'
testImplementation 'org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT' testImplementation 'org.spigotmc:spigot:1.20.4-R0.1-SNAPSHOT'
testImplementation 'net.kyori:adventure-text-serializer-gson:4.13.0' testImplementation 'net.kyori:adventure-text-serializer-gson:4.13.0'
testImplementation 'net.kyori:adventure-text-serializer-plain:4.13.1' testImplementation 'net.kyori:adventure-text-serializer-plain:4.13.1'
} }

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -37,12 +37,12 @@ public class ProtocolLibrary {
/** /**
* The maximum version ProtocolLib has been tested with. * The maximum version ProtocolLib has been tested with.
*/ */
public static final String MAXIMUM_MINECRAFT_VERSION = "1.20.2"; public static final String MAXIMUM_MINECRAFT_VERSION = "1.20.24";
/** /**
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.20.2) was released. * The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.20.4) was released.
*/ */
public static final String MINECRAFT_LAST_RELEASE_DATE = "2023-09-21"; public static final String MINECRAFT_LAST_RELEASE_DATE = "2023-12-07";
/** /**
* Plugins that are currently incompatible with ProtocolLib. * Plugins that are currently incompatible with ProtocolLib.

View File

@ -159,6 +159,37 @@ public class StructureCache {
return TRICKED_DATA_SERIALIZER_BASE.invoke(new ZeroBuffer()); return TRICKED_DATA_SERIALIZER_BASE.invoke(new ZeroBuffer());
} }
static void initTrickDataSerializer() {
// create an empty instance of a nbt tag compound / text compound that we can re-use when needed
Object textCompound = WrappedChatComponent.fromText("").getHandle();
Object compound = Accessors.getConstructorAccessor(MinecraftReflection.getNBTCompoundClass()).invoke();
// base builder which intercepts a few methods
DynamicType.Builder<?> baseBuilder = ByteBuddyFactory.getInstance()
.createSubclass(MinecraftReflection.getPacketDataSerializerClass())
.name(MinecraftMethods.class.getPackage().getName() + ".ProtocolLibTricksNmsDataSerializerBase")
.method(ElementMatchers.takesArguments(MinecraftReflection.getNBTReadLimiterClass())
.and(ElementMatchers.returns(ElementMatchers.isSubTypeOf(MinecraftReflection.getNBTBaseClass()))))
.intercept(FixedValue.value(compound))
.method(ElementMatchers.returns(MinecraftReflection.getIChatBaseComponentClass()))
.intercept(FixedValue.value(textCompound))
.method(ElementMatchers.returns(PublicKey.class).and(ElementMatchers.takesNoArguments()))
.intercept(FixedValue.nullValue());
Class<?> serializerBase = baseBuilder.make()
.load(ByteBuddyFactory.getInstance().getClassLoader(), Default.INJECTION)
.getLoaded();
TRICKED_DATA_SERIALIZER_BASE = Accessors.getConstructorAccessor(serializerBase, ByteBuf.class);
// extended builder which intercepts the read string method as well
Class<?> withStringIntercept = baseBuilder
.name(MinecraftMethods.class.getPackage().getName() + ".ProtocolLibTricksNmsDataSerializerJson")
.method(ElementMatchers.returns(String.class).and(ElementMatchers.takesArguments(int.class)))
.intercept(FixedValue.value("{}"))
.make()
.load(ByteBuddyFactory.getInstance().getClassLoader(), Default.INJECTION)
.getLoaded();
TRICKED_DATA_SERIALIZER_JSON = Accessors.getConstructorAccessor(withStringIntercept, ByteBuf.class);
}
/** /**
* Creates a packet data serializer sub-class if needed to allow the fixed read of a NbtTagCompound because of a * Creates a packet data serializer sub-class if needed to allow the fixed read of a NbtTagCompound because of a
* null check in the MapChunk packet constructor. * null check in the MapChunk packet constructor.
@ -174,43 +205,13 @@ public class StructureCache {
} }
try { try {
// create an empty instance of a nbt tag compound / text compound that we can re-use when needed initTrickDataSerializer();
Object textCompound = WrappedChatComponent.fromText("").getHandle();
Object compound = Accessors.getConstructorAccessor(MinecraftReflection.getNBTCompoundClass()).invoke();
// base builder which intercepts a few methods
DynamicType.Builder<?> baseBuilder = ByteBuddyFactory.getInstance()
.createSubclass(MinecraftReflection.getPacketDataSerializerClass())
.name(MinecraftMethods.class.getPackage().getName() + ".ProtocolLibTricksNmsDataSerializerBase")
.method(ElementMatchers.takesArguments(MinecraftReflection.getNBTReadLimiterClass())
.and(ElementMatchers.returns(ElementMatchers.isSubTypeOf(MinecraftReflection.getNBTBaseClass()))))
.intercept(FixedValue.value(compound))
.method(ElementMatchers.returns(MinecraftReflection.getIChatBaseComponentClass()))
.intercept(FixedValue.value(textCompound))
.method(ElementMatchers.returns(PublicKey.class).and(ElementMatchers.takesNoArguments()))
.intercept(FixedValue.nullValue());
Class<?> serializerBase = baseBuilder.make()
.load(ByteBuddyFactory.getInstance().getClassLoader(), Default.INJECTION)
.getLoaded();
TRICKED_DATA_SERIALIZER_BASE = Accessors.getConstructorAccessor(serializerBase, ByteBuf.class);
// extended builder which intercepts the read string method as well
Class<?> withStringIntercept = baseBuilder
.name(MinecraftMethods.class.getPackage().getName() + ".ProtocolLibTricksNmsDataSerializerJson")
.method(ElementMatchers.returns(String.class).and(ElementMatchers.takesArguments(int.class)))
.intercept(FixedValue.value("{}"))
.make()
.load(ByteBuddyFactory.getInstance().getClassLoader(), Default.INJECTION)
.getLoaded();
TRICKED_DATA_SERIALIZER_JSON = Accessors.getConstructorAccessor(withStringIntercept, ByteBuf.class);
// worked
return true; return true;
} catch (Exception ignored) { } catch (Exception ignored) {
} finally { } finally {
TRICK_TRIED = true; TRICK_TRIED = true;
} }
// didn't work
return false; return false;
} }
} }

View File

@ -41,6 +41,12 @@ public class PacketRegistry {
// Whether or not the registry has been initialized // Whether or not the registry has been initialized
private static volatile boolean INITIALIZED = false; private static volatile boolean INITIALIZED = false;
static void reset() {
synchronized (registryLock) {
INITIALIZED = false;
}
}
/** /**
* Represents a register we are currently building. * Represents a register we are currently building.
* @author Kristian * @author Kristian
@ -314,7 +320,7 @@ public class PacketRegistry {
/** /**
* Initializes the packet registry. * Initializes the packet registry.
*/ */
private static void initialize() { static void initialize() {
if (INITIALIZED) { if (INITIALIZED) {
return; return;
} }

View File

@ -1390,7 +1390,7 @@ public final class MinecraftReflection {
* @param aliases Potential aliases * @param aliases Potential aliases
* @return Optional that may contain the class * @return Optional that may contain the class
*/ */
private static Optional<Class<?>> getOptionalNMS(String className, String... aliases) { public static Optional<Class<?>> getOptionalNMS(String className, String... aliases) {
if (minecraftPackage == null) { if (minecraftPackage == null) {
minecraftPackage = new CachedPackage(getMinecraftPackage(), getClassSource()); minecraftPackage = new CachedPackage(getMinecraftPackage(), getClassSource());
} }

View File

@ -36,6 +36,10 @@ import org.bukkit.Server;
* @author Kristian * @author Kristian
*/ */
public final class MinecraftVersion implements Comparable<MinecraftVersion>, Serializable { public final class MinecraftVersion implements Comparable<MinecraftVersion>, Serializable {
/**
* Version 1.20.4 - the decorated pot update
*/
public static final MinecraftVersion v1_20_4 = new MinecraftVersion("1.20.4");
/** /**
* Version 1.20.2 - the update that added the configuration protocol phase. * Version 1.20.2 - the update that added the configuration protocol phase.
@ -135,7 +139,7 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion>, Ser
/** /**
* The latest release version of minecraft. * The latest release version of minecraft.
*/ */
public static final MinecraftVersion LATEST = CONFIG_PHASE_PROTOCOL_UPDATE; public static final MinecraftVersion LATEST = v1_20_4;
// used when serializing // used when serializing
private static final long serialVersionUID = -8695133558996459770L; private static final long serialVersionUID = -8695133558996459770L;

View File

@ -2,6 +2,7 @@ package com.comphenix.protocol.wrappers;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import java.io.StringReader; import java.io.StringReader;
import java.util.Optional;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
@ -10,7 +11,10 @@ import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
import com.comphenix.protocol.reflect.accessors.MethodAccessor; import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import net.minecraft.network.chat.IChatBaseComponent;
/** /**
* Represents a chat component added in Minecraft 1.7.2 * Represents a chat component added in Minecraft 1.7.2
@ -20,6 +24,8 @@ public class WrappedChatComponent extends AbstractWrapper implements ClonableWra
private static final Class<?> SERIALIZER = MinecraftReflection.getChatSerializerClass(); private static final Class<?> SERIALIZER = MinecraftReflection.getChatSerializerClass();
private static final Class<?> COMPONENT = MinecraftReflection.getIChatBaseComponentClass(); private static final Class<?> COMPONENT = MinecraftReflection.getIChatBaseComponentClass();
private static final Class<?> GSON_CLASS = MinecraftReflection.getMinecraftGsonClass(); private static final Class<?> GSON_CLASS = MinecraftReflection.getMinecraftGsonClass();
private static final Optional<Class<?>> MUTABLE_COMPONENT_CLASS
= MinecraftReflection.getOptionalNMS("network.chat.IChatMutableComponent");
private static Object GSON = null; private static Object GSON = null;
private static MethodAccessor DESERIALIZE = null; private static MethodAccessor DESERIALIZE = null;
@ -38,13 +44,18 @@ public class WrappedChatComponent extends AbstractWrapper implements ClonableWra
GSON = Accessors.getFieldAccessor(fuzzy.getFieldByType("gson", GSON_CLASS)).get(null); GSON = Accessors.getFieldAccessor(fuzzy.getFieldByType("gson", GSON_CLASS)).get(null);
try { if (MinecraftVersion.v1_20_4.atOrAbove()) {
DESERIALIZE = Accessors.getMethodAccessor(FuzzyReflection.fromClass(MinecraftReflection.getChatDeserializer(), true) DESERIALIZE = Accessors.getMethodAccessor(FuzzyReflection.fromClass(SERIALIZER, false)
.getMethodByReturnTypeAndParameters("deserialize", Object.class, new Class<?>[] { GSON_CLASS, String.class, Class.class, boolean.class })); .getMethodByReturnTypeAndParameters("fromJsonLenient", MUTABLE_COMPONENT_CLASS.get(), String.class));
} catch (IllegalArgumentException ex) { } else {
// We'll handle it in the ComponentParser try {
DESERIALIZE = null; DESERIALIZE = Accessors.getMethodAccessor(FuzzyReflection.fromClass(MinecraftReflection.getChatDeserializer(), true)
} .getMethodByReturnTypeAndParameters("deserialize", Object.class, new Class<?>[] { GSON_CLASS, String.class, Class.class, boolean.class }));
} catch (IllegalArgumentException ex) {
// We'll handle it in the ComponentParser
DESERIALIZE = null;
}
}
// Get a component from a standard Minecraft message // Get a component from a standard Minecraft message
CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(MinecraftReflection.getCraftChatMessage(), "fromString", String.class, boolean.class); CONSTRUCT_COMPONENT = Accessors.getMethodAccessor(MinecraftReflection.getCraftChatMessage(), "fromString", String.class, boolean.class);
@ -58,6 +69,10 @@ public class WrappedChatComponent extends AbstractWrapper implements ClonableWra
} }
private static Object deserialize(String json) { private static Object deserialize(String json) {
if (MinecraftVersion.v1_20_4.atOrAbove()) {
return DESERIALIZE.invoke(null, json);
}
// Should be non-null on 1.9 and up // Should be non-null on 1.9 and up
if (DESERIALIZE != null) { if (DESERIALIZE != null) {
return DESERIALIZE.invoke(null, GSON, json, COMPONENT, true); return DESERIALIZE.invoke(null, GSON, json, COMPONENT, true);

View File

@ -7,6 +7,7 @@ import java.util.stream.Collectors;
import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor; import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.utility.MinecraftReflectionTestUtil; import com.comphenix.protocol.utility.MinecraftReflectionTestUtil;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import net.minecraft.SharedConstants; import net.minecraft.SharedConstants;
import net.minecraft.commands.CommandDispatcher; import net.minecraft.commands.CommandDispatcher;
@ -28,16 +29,19 @@ import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.bukkit.*; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_20_R2.CraftLootTable; import org.bukkit.Keyed;
import org.bukkit.craftbukkit.v1_20_R2.CraftRegistry; import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer; import org.bukkit.Server;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemFactory; import org.bukkit.craftbukkit.v1_20_R3.CraftLootTable;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftMagicNumbers; import org.bukkit.craftbukkit.v1_20_R3.CraftRegistry;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey; import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.util.Versioning; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.enchantments.Enchantment; import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemFactory;
import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.v1_20_R3.util.Versioning;
import org.spigotmc.SpigotWorldConfig; import org.spigotmc.SpigotWorldConfig;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@ -102,12 +106,13 @@ public class BukkitInitialization {
resourcePackRepository.c() /* getAvailablePacks() */ .stream().map(ResourcePackLoader::e /* openFull() */).collect(Collectors.toList())); resourcePackRepository.c() /* getAvailablePacks() */ .stream().map(ResourcePackLoader::e /* openFull() */).collect(Collectors.toList()));
LayeredRegistryAccess<RegistryLayer> layeredRegistryAccess = RegistryLayer.a(); // .createRegistryAccess() LayeredRegistryAccess<RegistryLayer> layeredRegistryAccess = RegistryLayer.a(); // .createRegistryAccess()
layeredRegistryAccess = WorldLoader.b(resourceManager, layeredRegistryAccess, RegistryLayer.b /* WORLDGEN */, RegistryDataLoader.a /* WORLDGEN_REGISTRIES */); // .loadAndReplaceLayer() layeredRegistryAccess = WorldLoader.b(resourceManager, layeredRegistryAccess, RegistryLayer.b /* WORLDGEN */, RegistryDataLoader.a /* WORLDGEN_REGISTRIES */); // .loadAndReplaceLayer()
IRegistryCustom.Dimension registryCustom = layeredRegistryAccess.a().c(); // .compositeAccess().freeze() IRegistryCustom.Dimension registryCustom = layeredRegistryAccess.a().d(); // .compositeAccess().freeze()
// IRegistryCustom.Dimension registryCustom = layeredRegistryAccess.a().c(); // .compositeAccess().freeze()
DataPackResources dataPackResources = DataPackResources.a( DataPackResources dataPackResources = DataPackResources.a(
resourceManager, resourceManager,
registryCustom, registryCustom,
FeatureFlags.d.a() /* REGISTRY.allFlags() */, FeatureFlagSet.a() /* REGISTRY.allFlags() */,
CommandDispatcher.ServerType.b /* DEDICATED */, CommandDispatcher.ServerType.b /* DEDICATED */,
0, 0,
MoreExecutors.directExecutor(), MoreExecutors.directExecutor(),
@ -166,7 +171,7 @@ public class BukkitInitialization {
// Init Enchantments // Init Enchantments
Enchantments.A.getClass(); Enchantments.A.getClass();
Enchantment.stopAcceptingRegistrations(); // Enchantment.stopAcceptingRegistrations();
initialized = true; initialized = true;
} }

View File

@ -45,9 +45,9 @@ public class PacketTypeTest {
BukkitInitialization.initializeAll(); BukkitInitialization.initializeAll();
// I'm well aware this is jank, but it does in fact work correctly and give the desired result // I'm well aware this is jank, but it does in fact work correctly and give the desired result
/*PacketType.onDynamicCreate = className -> { /* PacketType.onDynamicCreate = className -> {
throw new RuntimeException("Dynamically generated packet " + className); throw new RuntimeException("Dynamically generated packet " + className);
};*/ }; */
} }
@AfterAll @AfterAll
@ -342,21 +342,22 @@ public class PacketTypeTest {
} }
} }
@Test @Test
public void testPacketCreation() { public void testPacketCreation() {
boolean fail = false; List<PacketType> failed = new ArrayList<>();
for (PacketType type : PacketType.values()) { for (PacketType type : PacketType.values()) {
if (type.isSupported()) { if (!type.isSupported()) {
try { continue;
new PacketContainer(type); }
} catch (Exception ex) {
ex.printStackTrace(); try {
fail = true; new PacketContainer(type);
} } catch (Exception ex) {
} failed.add(type);
} }
assertFalse(fail, "Packet type(s) failed to instantiate"); }
} assertTrue(failed.isEmpty(), "Failed to create: " + failed);
}
@Test @Test
public void testPacketBundleWriting() { public void testPacketBundleWriting() {
@ -365,7 +366,7 @@ public class PacketTypeTest {
List<PacketContainer> bundle = new ArrayList<>(); List<PacketContainer> bundle = new ArrayList<>();
PacketContainer chatMessage = new PacketContainer(PacketType.Play.Server.SYSTEM_CHAT); PacketContainer chatMessage = new PacketContainer(PacketType.Play.Server.SYSTEM_CHAT);
chatMessage.getStrings().write(0, WrappedChatComponent.fromText("Test").getJson()); chatMessage.getChatComponents().write(0, WrappedChatComponent.fromText("Test"));
chatMessage.getBooleans().write(0, false); chatMessage.getBooleans().write(0, false);
bundle.add(chatMessage); bundle.add(chatMessage);
bundlePacket.getPacketBundles().write(0, bundle); bundlePacket.getPacketBundles().write(0, bundle);

View File

@ -58,6 +58,7 @@ import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder; import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.hover.content.Text; import net.md_5.bungee.api.chat.hover.content.Text;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.PacketDataSerializer; import net.minecraft.network.PacketDataSerializer;
import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket;
@ -500,7 +501,8 @@ public class PacketContainerTest {
// are inner classes (which is ultimately pointless because AttributeSnapshots don't access any // are inner classes (which is ultimately pointless because AttributeSnapshots don't access any
// members of the packet itself) // members of the packet itself)
PacketPlayOutUpdateAttributes packet = (PacketPlayOutUpdateAttributes) attribute.getHandle(); PacketPlayOutUpdateAttributes packet = (PacketPlayOutUpdateAttributes) attribute.getHandle();
AttributeBase base = BuiltInRegistries.v.a(MinecraftKey.a("generic.max_health")); IRegistry<AttributeBase> registry = BuiltInRegistries.u;
AttributeBase base = registry.a(MinecraftKey.a("generic.max_health"));
AttributeSnapshot snapshot = new AttributeSnapshot(base, 20.0D, modifiers); AttributeSnapshot snapshot = new AttributeSnapshot(base, 20.0D, modifiers);
attribute.getSpecificModifier(List.class).write(0, Lists.newArrayList(snapshot)); attribute.getSpecificModifier(List.class).write(0, Lists.newArrayList(snapshot));
@ -882,6 +884,7 @@ public class PacketContainerTest {
// Make sure watchable collections can be cloned // Make sure watchable collections can be cloned
if (type == PacketType.Play.Server.ENTITY_METADATA) { if (type == PacketType.Play.Server.ENTITY_METADATA) {
IRegistry<CatVariant> catVariantRegistry = BuiltInRegistries.ak;
constructed.getDataValueCollectionModifier().write(0, Lists.newArrayList( constructed.getDataValueCollectionModifier().write(0, Lists.newArrayList(
new WrappedDataValue(0, Registry.get(Byte.class), (byte) 1), new WrappedDataValue(0, Registry.get(Byte.class), (byte) 1),
new WrappedDataValue(0, Registry.get(Float.class), 5F), new WrappedDataValue(0, Registry.get(Float.class), 5F),
@ -895,7 +898,7 @@ public class PacketContainerTest {
0, 0,
Registry.getItemStackSerializer(false), Registry.getItemStackSerializer(false),
BukkitConverters.getItemStackConverter().getGeneric(new ItemStack(Material.WOODEN_AXE))), BukkitConverters.getItemStackConverter().getGeneric(new ItemStack(Material.WOODEN_AXE))),
new WrappedDataValue(0, Registry.get(CatVariant.class), BuiltInRegistries.aj.e(CatVariant.e)), new WrappedDataValue(0, Registry.get(CatVariant.class), catVariantRegistry.e(CatVariant.e)),
new WrappedDataValue(0, Registry.get(FrogVariant.class), FrogVariant.a) new WrappedDataValue(0, Registry.get(FrogVariant.class), FrogVariant.a)
)); ));
} else if (type == PacketType.Play.Server.CHAT) { } else if (type == PacketType.Play.Server.CHAT) {

View File

@ -12,8 +12,8 @@ import net.minecraft.server.level.PlayerChunkMap;
import net.minecraft.server.level.PlayerChunkMap.EntityTracker; import net.minecraft.server.level.PlayerChunkMap.EntityTracker;
import net.minecraft.server.level.WorldServer; import net.minecraft.server.level.WorldServer;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -35,7 +35,7 @@ public class EntityUtilitiesTest {
when(bukkit.getHandle()).thenReturn(world); when(bukkit.getHandle()).thenReturn(world);
ChunkProviderServer provider = mock(ChunkProviderServer.class); ChunkProviderServer provider = mock(ChunkProviderServer.class);
when(world.k()).thenReturn(provider); when(world.l()).thenReturn(provider);
PlayerChunkMap chunkMap = mock(PlayerChunkMap.class); PlayerChunkMap chunkMap = mock(PlayerChunkMap.class);
Field chunkMapField = FuzzyReflection.fromClass(ChunkProviderServer.class, true) Field chunkMapField = FuzzyReflection.fromClass(ChunkProviderServer.class, true)

View File

@ -0,0 +1,26 @@
package com.comphenix.protocol.injector;
import com.comphenix.protocol.BukkitInitialization;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class StructureCacheTests {
@BeforeAll
public static void beforeAll() {
BukkitInitialization.initializeAll();
}
@Test
public void testInitTrickSerializer() {
try {
StructureCache.initTrickDataSerializer();
} catch (IllegalStateException ex) {
// no exception or an already injected exception means it succeeded
assertTrue(ex.getMessage().contains("Cannot inject already loaded type"));
}
}
}

View File

@ -0,0 +1,41 @@
package com.comphenix.protocol.injector.packet;
import java.util.ArrayList;
import java.util.List;
import com.comphenix.protocol.BukkitInitialization;
import com.comphenix.protocol.PacketType;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class PacketRegistryTests {
@BeforeAll
public static void beforeAll() {
BukkitInitialization.initializeAll();
}
@Test
public void testRegistryInit() {
PacketRegistry.reset();
// completing without exception
PacketRegistry.initialize();
}
@Test
public void testAllPacketsRegistered() {
List<PacketType> missing = new ArrayList<>();
for (PacketType type : PacketType.values()) {
if (type.isDeprecated()) {
continue;
}
if (!PacketRegistry.tryGetPacketClass(type).isPresent()) {
missing.add(type);
}
}
assertTrue(missing.isEmpty(), "Missing packets: " + missing);
}
}

View File

@ -28,7 +28,7 @@ public class AggregateClonerTest {
// @Test // @Test
// Usages of NonNullList were removed in 1.17.1 // Usages of NonNullList were removed in 1.17.1
public void testNonNullList() { /* public void testNonNullList() {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.WINDOW_ITEMS); PacketContainer packet = new PacketContainer(PacketType.Play.Server.WINDOW_ITEMS);
NonNullList<ItemStack> list = NonNullList.a(16, ItemStack.b); NonNullList<ItemStack> list = NonNullList.a(16, ItemStack.b);
@ -41,5 +41,5 @@ public class AggregateClonerTest {
assertEquals(list.size(), list1.size()); assertEquals(list.size(), list1.size());
Assertions.assertArrayEquals(list.toArray(), list1.toArray()); Assertions.assertArrayEquals(list.toArray(), list1.toArray());
} } */
} }

View File

@ -13,7 +13,7 @@ import net.minecraft.world.level.ChunkCoordIntPair;
import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;

View File

@ -2,8 +2,8 @@ package com.comphenix.protocol.utility;
public class MinecraftReflectionTestUtil { public class MinecraftReflectionTestUtil {
public static final String RELEASE_TARGET = "1.20.2"; public static final String RELEASE_TARGET = "1.20.4";
public static final String PACKAGE_VERSION = "v1_20_R2"; public static final String PACKAGE_VERSION = "v1_20_R3";
public static final String NMS = "net.minecraft"; public static final String NMS = "net.minecraft";
public static final String OBC = "org.bukkit.craftbukkit." + PACKAGE_VERSION; public static final String OBC = "org.bukkit.craftbukkit." + PACKAGE_VERSION;

View File

@ -48,7 +48,7 @@ class MinecraftVersionTest {
@Test @Test
void testCurrent() { void testCurrent() {
assertEquals(MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE, MinecraftVersion.getCurrentVersion()); assertEquals(MinecraftVersion.v1_20_4, MinecraftVersion.getCurrentVersion());
} }
@Test @Test

View File

@ -1,5 +1,7 @@
package com.comphenix.protocol.wrappers; package com.comphenix.protocol.wrappers;
import java.util.Optional;
import static com.comphenix.protocol.utility.MinecraftReflection.getMinecraftClass; import static com.comphenix.protocol.utility.MinecraftReflection.getMinecraftClass;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertInstanceOf;
@ -46,7 +48,8 @@ public class AutoWrapperTest {
assertTrue(nms.h()); assertTrue(nms.h());
assertTrue(nms.j()); assertTrue(nms.j());
assertFalse(nms.i()); assertFalse(nms.i());
assertEquals("test", nms.d().a()); assertTrue(nms.d().isPresent());
assertEquals("test", nms.d().get().a());
validateRawText(nms.a(), "Test123"); validateRawText(nms.a(), "Test123");
validateRawText(nms.b(), "Test567"); validateRawText(nms.b(), "Test567");
assertSame(AdvancementFrameType.b, nms.e()); assertSame(AdvancementFrameType.b, nms.e());
@ -61,7 +64,7 @@ public class AutoWrapperTest {
(net.minecraft.world.item.ItemStack)MinecraftReflection.getMinecraftItemStack(new ItemStack(Material.ENDER_EYE)), (net.minecraft.world.item.ItemStack)MinecraftReflection.getMinecraftItemStack(new ItemStack(Material.ENDER_EYE)),
IChatBaseComponent.b("Test123"), IChatBaseComponent.b("Test123"),
IChatBaseComponent.b("Test567"), IChatBaseComponent.b("Test567"),
new net.minecraft.resources.MinecraftKey("minecraft", "test"), Optional.of(new net.minecraft.resources.MinecraftKey("minecraft", "test")),
AdvancementFrameType.b, AdvancementFrameType.b,
true, true,
false, false,

View File

@ -8,6 +8,7 @@ import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.WrappedAttributeModifier.Operation; import com.comphenix.protocol.wrappers.WrappedAttributeModifier.Operation;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.PacketPlayOutUpdateAttributes.AttributeSnapshot; import net.minecraft.network.protocol.game.PacketPlayOutUpdateAttributes.AttributeSnapshot;
import net.minecraft.resources.MinecraftKey; import net.minecraft.resources.MinecraftKey;
@ -93,7 +94,8 @@ public class WrappedAttributeTest {
modifiers.add((AttributeModifier) wrapper.getHandle()); modifiers.add((AttributeModifier) wrapper.getHandle());
} }
AttributeBase base = BuiltInRegistries.v.a(MinecraftKey.a(attribute.getAttributeKey())); IRegistry<AttributeBase> registry = BuiltInRegistries.u;
AttributeBase base = registry.a(MinecraftKey.a(attribute.getAttributeKey()));
return new AttributeSnapshot(base, attribute.getBaseValue(), modifiers); return new AttributeSnapshot(base, attribute.getBaseValue(), modifiers);
} }

View File

@ -19,9 +19,9 @@ import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.GlassPane; import org.bukkit.block.data.type.GlassPane;
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R2.block.impl.CraftStainedGlassPane; import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftStainedGlassPane;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftMagicNumbers; import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -56,7 +56,7 @@ public class WrappedBlockDataTest {
@Test @Test
public void testDataCreation() { public void testDataCreation() {
IBlockData nmsData = CraftMagicNumbers.getBlock(Material.CYAN_STAINED_GLASS_PANE).n(); IBlockData nmsData = CraftMagicNumbers.getBlock(Material.CYAN_STAINED_GLASS_PANE).o();
GlassPane data = (GlassPane) CraftBlockData.fromData(nmsData); GlassPane data = (GlassPane) CraftBlockData.fromData(nmsData);
data.setFace(BlockFace.EAST, true); data.setFace(BlockFace.EAST, true);

View File

@ -19,8 +19,8 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer; import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
import net.minecraft.world.entity.projectile.EntityEgg; import net.minecraft.world.entity.projectile.EntityEgg;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEgg; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEgg;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;