Compare commits

...
Author SHA1 Message Date
Dan Mulloy 3442d3fb8f Update version to 5.3.0 for release 2024-10-20 17:12:58 -05:00
Pasqual Koschmieder 1e3fa2d36e deps: update bytebuddy and shadow (#3247) 2024-09-24 21:53:32 +02:00
JustRed23 c9ee2f16e2 Fix serializing and deserializing of ItemStack on 1.21 (#3217) 2024-09-23 12:30:34 +00:00
Dan Mulloy 7f615378e4 Compile against 1.21.1 2024-09-22 21:41:32 -05:00
SzczurekYT d636be81e7 Fix ConcurrentModificationException when shutting down async listeners (#3169) 2024-09-23 00:11:17 +00:00
Bjorn Beishline 3cb261f466 Fix ConcurrentModificationException in PacketListenerSet (#3241) 2024-09-23 00:04:12 +00:00
Maurice Eisenblätter 7338183ed6 Fix Github actions & unit tests (#3244)
* chore: update github actions

* test: fix initialization

* test: add missing imports for test initialization
2024-09-22 19:00:57 -05:00
9 changed files with 121 additions and 48 deletions

No files matched your search

+3 -3
View File
@@ -9,10 +9,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
@@ -22,7 +22,7 @@ jobs:
run: ./gradlew build shadowJar --no-daemon
- name: Upload plugin file
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: ProtocolLib
path: build/libs/ProtocolLib.jar
+4 -4
View File
@@ -20,17 +20,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: 'gradle'
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: 'java'
@@ -38,4 +38,4 @@ jobs:
run: ./gradlew build -x test --no-daemon
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
+6 -6
View File
@@ -1,11 +1,11 @@
plugins {
id 'java-library'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'com.gradleup.shadow' version '8.3.2'
}
group = 'com.comphenix.protocol'
version = '5.3.0-SNAPSHOT'
version = '5.3.0'
description = 'Provides access to the Minecraft protocol'
def isSnapshot = version.endsWith('-SNAPSHOT')
@@ -33,9 +33,9 @@ repositories {
}
dependencies {
implementation 'net.bytebuddy:byte-buddy:1.14.14'
compileOnly 'org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot:1.21-R0.1-SNAPSHOT'
implementation 'net.bytebuddy:byte-buddy:1.15.1'
compileOnly 'org.spigotmc:spigot-api:1.21.1-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot:1.21.1-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.21-R0.1-SNAPSHOT'
testImplementation 'org.spigotmc:spigot:1.21.1-R0.1-SNAPSHOT'
testImplementation 'net.kyori:adventure-text-serializer-gson:4.14.0'
testImplementation 'net.kyori:adventure-text-serializer-plain:4.14.0'
}
@@ -17,9 +17,7 @@ package com.comphenix.protocol;
import com.comphenix.protocol.error.BasicErrorReporter;
import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.scheduler.ProtocolScheduler;
import com.comphenix.protocol.utility.MinecraftVersion;
import java.util.List;
import com.google.common.collect.ImmutableList;
import org.apache.commons.lang.Validate;
import org.bukkit.plugin.Plugin;
@@ -37,17 +35,12 @@ public class ProtocolLibrary {
/**
* The maximum version ProtocolLib has been tested with.
*/
public static final String MAXIMUM_MINECRAFT_VERSION = "1.20.4";
public static final String MAXIMUM_MINECRAFT_VERSION = "1.21.1";
/**
* 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-12-07";
/**
* Plugins that are currently incompatible with ProtocolLib.
*/
public static final List<String> INCOMPATIBLE = ImmutableList.of("TagAPI");
public static final String MINECRAFT_LAST_RELEASE_DATE = "2024-08-08";
private static Plugin plugin;
private static ProtocolConfig config;
@@ -17,14 +17,6 @@
package com.comphenix.protocol.async;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.AsynchronousManager;
import com.comphenix.protocol.PacketStream;
import com.comphenix.protocol.PacketType;
@@ -37,8 +29,16 @@ import com.comphenix.protocol.injector.collection.InboundPacketListenerSet;
import com.comphenix.protocol.injector.collection.OutboundPacketListenerSet;
import com.comphenix.protocol.scheduler.ProtocolScheduler;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Represents a filter manager for asynchronous packets.
@@ -284,9 +284,9 @@ public class AsyncFilterManager implements AsynchronousManager {
}
private void unregisterAsyncHandlers(PacketProcessingQueue processingQueue, Plugin plugin) {
// Iterate through every packet listener
for (AsyncListenerHandler listener : processingQueue.values()) {
for (AsyncListenerHandler listener : ImmutableList.copyOf(processingQueue.values())) {
// Remove the listener
if (Objects.equal(listener.getPlugin(), plugin)) {
unregisterAsyncHandler(listener);
@@ -1,5 +1,6 @@
package com.comphenix.protocol.injector.collection;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
@@ -45,7 +46,9 @@ public abstract class PacketListenerSet {
public void addListener(PacketListener packetListener) {
ListeningWhitelist listeningWhitelist = getListeningWhitelist(packetListener);
for (PacketType packetType : listeningWhitelist.getTypes()) {
for (Iterator<PacketType> packet = listeningWhitelist.getTypes().iterator(); packet.hasNext();) {
PacketType packetType = packet.next();
Set<PacketType> supportedPacketTypes = (packetType.getSender() == Sender.SERVER)
? PacketRegistry.getServerPacketTypes()
: PacketRegistry.getClientPacketTypes();
@@ -56,7 +59,7 @@ public abstract class PacketListenerSet {
.build());
// remove unknown packet types
listeningWhitelist.getTypes().remove(packetType);
packet.remove();
}
}
@@ -10,7 +10,9 @@ import java.util.Base64;
import com.comphenix.protocol.injector.netty.NettyByteBufAdapter;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
@@ -31,6 +33,7 @@ public class StreamSerializer {
private static final StreamSerializer DEFAULT = new StreamSerializer();
// Cached methods
private static FieldAccessor STREAM_CODEC;
private static MethodAccessor READ_ITEM_METHOD;
private static MethodAccessor WRITE_ITEM_METHOD;
@@ -235,14 +238,35 @@ public class StreamSerializer {
Object serializer = MinecraftReflection.getPacketDataSerializer(buf);
if (READ_ITEM_METHOD == null) {
READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
.fromClass(serializer.getClass(), false)
.getMethodByReturnTypeAndParameters("readItemStack", MinecraftReflection.getItemStackClass()));
if (MinecraftVersion.v1_21_0.atOrAbove()) {
if (STREAM_CODEC == null) {
STREAM_CODEC = Accessors.getFieldAccessor(FuzzyReflection
.fromClass(MinecraftReflection.getItemStackClass())
.getFieldList(FuzzyFieldContract.newBuilder()
.typeExact(MinecraftReflection.getStreamCodecClass())
.build()).get(1)); //skip OPTIONAL_STREAM_CODEC
}
READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection.fromObject(STREAM_CODEC.get(null), true)
.getMethod(FuzzyMethodContract.newBuilder()
.parameterExactType(MinecraftReflection.getRegistryFriendlyByteBufClass().get())
.returnTypeExact(MinecraftReflection.getItemStackClass())
.build()));
} else {
READ_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
.fromClass(serializer.getClass(), false)
.getMethodByReturnTypeAndParameters("readItemStack", MinecraftReflection.getItemStackClass()));
}
}
try {
// unwrap the item
Object nmsItem = READ_ITEM_METHOD.invoke(serializer);
Object nmsItem;
if (MinecraftVersion.v1_21_0.atOrAbove()) {
nmsItem = READ_ITEM_METHOD.invoke(STREAM_CODEC.get(null), serializer);
} else {
nmsItem = READ_ITEM_METHOD.invoke(serializer);
}
return nmsItem != null ? MinecraftReflection.getBukkitItemStack(nmsItem) : null;
} finally {
ReferenceCountUtil.safeRelease(buf);
@@ -262,11 +286,26 @@ public class StreamSerializer {
* @throws IOException If the operation fails due to reflection problems.
*/
public void serializeItemStack(DataOutputStream output, ItemStack stack) throws IOException {
// TODO this functionality was replaced by the CODEC field in the nms ItemStack
if (WRITE_ITEM_METHOD == null) {
WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true)
.getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass()));
if (MinecraftVersion.v1_21_0.atOrAbove()) {
if (STREAM_CODEC == null) {
STREAM_CODEC = Accessors.getFieldAccessor(FuzzyReflection
.fromClass(MinecraftReflection.getItemStackClass())
.getFieldList(FuzzyFieldContract.newBuilder()
.typeExact(MinecraftReflection.getStreamCodecClass())
.build()).get(1)); //skip OPTIONAL_STREAM_CODEC
}
WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection.fromObject(STREAM_CODEC.get(null), true)
.getMethod(FuzzyMethodContract.newBuilder()
.parameterExactArray(MinecraftReflection.getRegistryFriendlyByteBufClass().get(), MinecraftReflection.getItemStackClass())
.returnTypeExact(void.class)
.build()));
} else {
WRITE_ITEM_METHOD = Accessors.getMethodAccessor(FuzzyReflection
.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true)
.getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass()));
}
}
ByteBuf buf = Unpooled.buffer();
@@ -274,7 +313,12 @@ public class StreamSerializer {
// Get the NMS version of the ItemStack and write it into the buffer
Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack);
WRITE_ITEM_METHOD.invoke(serializer, nmsItem);
if (MinecraftVersion.v1_21_0.atOrAbove()) {
WRITE_ITEM_METHOD.invoke(STREAM_CODEC.get(null), serializer, nmsItem);
} else {
WRITE_ITEM_METHOD.invoke(serializer, nmsItem);
}
// write the serialized content to the stream
output.write(this.getBytesAndRelease(buf));
@@ -1,8 +1,10 @@
package com.comphenix.protocol;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
@@ -41,6 +43,7 @@ import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_21_R1.CraftLootTable;
import org.bukkit.craftbukkit.v1_21_R1.CraftRegistry;
@@ -54,6 +57,7 @@ import org.bukkit.craftbukkit.v1_21_R1.tag.CraftItemTag;
import org.bukkit.craftbukkit.v1_21_R1.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.v1_21_R1.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.v1_21_R1.util.Versioning;
import org.jetbrains.annotations.NotNull;
import org.spigotmc.SpigotWorldConfig;
import static org.mockito.ArgumentMatchers.any;
@@ -118,7 +122,7 @@ public class BukkitInitialization {
resourcePackRepository.c() /* getAvailablePacks() */ .stream().map(ResourcePackLoader::f /* openFull() */).collect(Collectors.toList()));
LayeredRegistryAccess<RegistryLayer> layeredRegistryAccess = RegistryLayer.a(); // .createRegistryAccess()
layeredRegistryAccess = WorldLoader.b(resourceManager, layeredRegistryAccess, RegistryLayer.b /* WORLDGEN */, RegistryDataLoader.a /* WORLDGEN_REGISTRIES */); // .loadAndReplaceLayer()
IRegistryCustom.Dimension registryCustom = layeredRegistryAccess.a().d(); // .compositeAccess().freeze()
IRegistryCustom.Dimension registryCustom = layeredRegistryAccess.a().d(); // .compositeAccess().freeze()
// IRegistryCustom.Dimension registryCustom = layeredRegistryAccess.a().c(); // .compositeAccess().freeze()
DataPackResources dataPackResources = DataPackResources.a(
@@ -162,7 +166,14 @@ public class BukkitInitialization {
});
when(mockedServer.getRegistry(any())).thenAnswer(invocation -> {
Class<Keyed> registryType = invocation.getArgument(0);
return CraftRegistry.createRegistry(registryType, registryCustom);
Object registry = CraftRegistry.createRegistry(registryType, registryCustom);
if (registry == null) {
System.err.println("WARN: Missing registry for " + registryType);
return new DummyRegistry<>();
}
return registry;
});
when(mockedServer.getTag(any(), any(), any())).then(mock -> {
@@ -250,4 +261,28 @@ public class BukkitInitialization {
MinecraftReflectionTestUtil.init();
}
}
class DummyRegistry<T extends Keyed> implements Registry<T> {
@Override
public Iterator<T> iterator() {
return Collections.emptyIterator();
}
@Override
public T get(NamespacedKey key) {
return null;
}
@Override
public T getOrThrow(@NotNull NamespacedKey namespacedKey) {
return null;
}
@Override
public Stream<T> stream() {
List<T> empty = Collections.emptyList();
return empty.stream();
}
}
}
@@ -60,7 +60,6 @@ public class StreamSerializerTest {
}
@Test
@Disabled // TODO -- replaced with registry friendly bytebuf
public void testItems() throws IOException {
StreamSerializer serializer = new StreamSerializer();
ItemStack initial = new ItemStack(Material.STRING);
@@ -72,7 +71,6 @@ public class StreamSerializerTest {
}
@Test
@Disabled // TODO -- replaced with registry friendly bytebuf
public void testItemMeta() throws IOException {
StreamSerializer serializer = new StreamSerializer();
ItemStack initial = new ItemStack(Material.BLUE_WOOL, 2);