diff --git a/src/main/java/com/comphenix/protocol/injector/netty/channel/NettyChannelInjector.java b/src/main/java/com/comphenix/protocol/injector/netty/channel/NettyChannelInjector.java index 19ae3238..67513fe4 100644 --- a/src/main/java/com/comphenix/protocol/injector/netty/channel/NettyChannelInjector.java +++ b/src/main/java/com/comphenix/protocol/injector/netty/channel/NettyChannelInjector.java @@ -209,10 +209,15 @@ public class NettyChannelInjector implements Injector { return false; } + String anchorHandler = "decoder"; + if (MinecraftVersion.FEATURE_PREVIEW_2.atOrAbove()) { + anchorHandler = "unbundler"; + } + // inject our handlers this.wrappedChannel.pipeline().addAfter("encoder", WIRE_PACKET_ENCODER_NAME, WIRE_PACKET_ENCODER); this.wrappedChannel.pipeline().addAfter( - "decoder", + anchorHandler, INTERCEPTOR_NAME, new InboundPacketInterceptor(this, this.channelListener)); diff --git a/src/main/java/com/comphenix/protocol/reflect/accessors/DefaultFieldAccessor.java b/src/main/java/com/comphenix/protocol/reflect/accessors/DefaultFieldAccessor.java index 8314f8ca..5dddb045 100644 --- a/src/main/java/com/comphenix/protocol/reflect/accessors/DefaultFieldAccessor.java +++ b/src/main/java/com/comphenix/protocol/reflect/accessors/DefaultFieldAccessor.java @@ -4,6 +4,8 @@ import java.lang.invoke.MethodHandle; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import com.google.common.base.Preconditions; + final class DefaultFieldAccessor implements FieldAccessor { private final Field field; @@ -13,9 +15,9 @@ final class DefaultFieldAccessor implements FieldAccessor { private final MethodHandle getter; public DefaultFieldAccessor(Field field, MethodHandle setter, MethodHandle getter, boolean staticField) { - this.field = field; - this.setter = setter; - this.getter = getter; + this.field = Preconditions.checkNotNull(field, "field"); + this.setter = Preconditions.checkNotNull(setter, "setter"); + this.getter = Preconditions.checkNotNull(getter, "getter"); this.staticField = staticField; } diff --git a/src/main/java/com/comphenix/protocol/reflect/accessors/MethodHandleHelper.java b/src/main/java/com/comphenix/protocol/reflect/accessors/MethodHandleHelper.java index 9bffe188..00719441 100644 --- a/src/main/java/com/comphenix/protocol/reflect/accessors/MethodHandleHelper.java +++ b/src/main/java/com/comphenix/protocol/reflect/accessors/MethodHandleHelper.java @@ -11,6 +11,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.logging.Level; +import com.google.common.base.Preconditions; + final class MethodHandleHelper { private static final Lookup LOOKUP; @@ -51,29 +53,35 @@ final class MethodHandleHelper { } public static MethodAccessor getMethodAccessor(Method method) { + Preconditions.checkNotNull(method, "method"); + try { MethodHandle unreflected = LOOKUP.unreflect(method); boolean staticMethod = Modifier.isStatic(method.getModifiers()); MethodHandle generified = convertToGeneric(unreflected, staticMethod, false); return new DefaultMethodAccessor(method, generified, staticMethod); - } catch (IllegalAccessException exception) { - throw new IllegalStateException("Unable to access method " + method); + } catch (IllegalAccessException ex) { + throw new IllegalStateException("Unable to access method " + method, ex); } } public static ConstructorAccessor getConstructorAccessor(Constructor constructor) { + Preconditions.checkNotNull(constructor, "constructor"); + try { MethodHandle unreflected = LOOKUP.unreflectConstructor(constructor); MethodHandle generified = convertToGeneric(unreflected, false, true); return new DefaultConstrutorAccessor(constructor, generified); - } catch (IllegalAccessException exception) { - throw new IllegalStateException("Unable to access constructor " + constructor); + } catch (IllegalAccessException ex) { + throw new IllegalStateException("Unable to access constructor " + constructor, ex); } } public static FieldAccessor getFieldAccessor(Field field) { + Preconditions.checkNotNull(field, "field"); + try { boolean staticField = Modifier.isStatic(field.getModifiers()); @@ -97,10 +105,18 @@ final class MethodHandleHelper { setter = setter.asType(VIRTUAL_FIELD_SETTER); } + if (getter == null) { + throw new IllegalStateException("Unable to access field " + field + ". Could not find getter"); + } + + if (setter == null) { + throw new IllegalStateException("Unable to access field " + field + ". Could not find setter"); + } + return new DefaultFieldAccessor(field, setter, getter, staticField); - } catch (IllegalAccessException | NoSuchFieldException exception) { + } catch (IllegalAccessException | NoSuchFieldException ex) { // NoSuchFieldException can never happen, the field always exists - throw new IllegalStateException("Unable to access field " + field, exception); + throw new IllegalStateException("Unable to access field " + field, ex); } } diff --git a/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java b/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java index 647b3b19..fcea2e76 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java +++ b/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java @@ -20,6 +20,7 @@ import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; import com.comphenix.protocol.reflect.accessors.FieldAccessor; import com.google.common.base.Defaults; +import com.google.common.base.Preconditions; import java.lang.reflect.Modifier; import java.util.Arrays; @@ -88,6 +89,8 @@ public class AutoWrapper implements EquivalentConverter { } public T wrap(Object nmsObject) { + Preconditions.checkNotNull(nmsObject); + T instance; try { @@ -114,6 +117,8 @@ public class AutoWrapper implements EquivalentConverter { } public Object unwrap(Object wrapper) { + Preconditions.checkNotNull(wrapper); + // ensures that all accessors are present computeFieldAccessors(); computeNmsConstructorAccess(); @@ -139,14 +144,14 @@ public class AutoWrapper implements EquivalentConverter { nmsAccessors = Arrays .stream(nmsClass.getDeclaredFields()) .filter(field -> !Modifier.isStatic(field.getModifiers())) - .map(field -> Accessors.getFieldAccessor(field)) + .map(Accessors::getFieldAccessor) .toArray(FieldAccessor[]::new); } if (wrapperAccessors == null) { wrapperAccessors = Arrays .stream(wrapperClass.getDeclaredFields()) - .map(field -> Accessors.getFieldAccessor(field)) + .map(Accessors::getFieldAccessor) .toArray(FieldAccessor[]::new); } } diff --git a/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java b/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java index d9398334..1b5d0e30 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java +++ b/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java @@ -68,7 +68,7 @@ public class WrappedServerPing implements ClonableWrapper { this.impl = newImpl(handle); } - private ServerPingImpl newImpl() { + private static ServerPingImpl newImpl() { if (MinecraftVersion.FEATURE_PREVIEW_2.atOrAbove()) { return new ServerPingRecord(); } @@ -76,9 +76,9 @@ public class WrappedServerPing implements ClonableWrapper { return new LegacyServerPing(); } - private ServerPingImpl newImpl(Object handle) { + private static ServerPingImpl newImpl(Object handle) { if (MinecraftVersion.FEATURE_PREVIEW_2.atOrAbove()) { - return new ServerPingRecord(); + return new ServerPingRecord(handle); } return new LegacyServerPing(handle); @@ -87,14 +87,14 @@ public class WrappedServerPing implements ClonableWrapper { /** * Set the player count and player maximum to the default values. */ - protected void resetPlayers() { + private void resetPlayers() { impl.resetPlayers(); } /** * Reset the version string to the default state. */ - protected void resetVersion() { + private void resetVersion() { impl.resetVersion(); } diff --git a/src/main/java/com/comphenix/protocol/wrappers/ping/ServerPingRecord.java b/src/main/java/com/comphenix/protocol/wrappers/ping/ServerPingRecord.java index da15146d..f997fc24 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/ping/ServerPingRecord.java +++ b/src/main/java/com/comphenix/protocol/wrappers/ping/ServerPingRecord.java @@ -26,7 +26,7 @@ public class ServerPingRecord implements ServerPingImpl { private static ConstructorAccessor PING_CTOR; - private static boolean initialized; + private static boolean initialized = false; private static void initialize() { if (initialized) { @@ -42,20 +42,9 @@ public class ServerPingRecord implements ServerPingImpl { PING_CTOR = Accessors.getConstructorAccessor(SERVER_PING.getConstructors()[0]); - DATA_WRAPPER = AutoWrapper - .wrap(ServerData.class, SERVER_DATA_CLASS) - .field(0, Converters.passthrough(String.class)) - .field(1, Converters.passthrough(int.class)); - - SAMPLE_WRAPPER = AutoWrapper - .wrap(PlayerSample.class, PLAYER_SAMPLE_CLASS) - .field(0, Converters.passthrough(int.class)) - .field(1, Converters.passthrough(int.class)) - .field(2, Converters.passthrough(Object.class)); - - FAVICON_WRAPPER = AutoWrapper - .wrap(Favicon.class, MinecraftReflection.getMinecraftClass("network.protocol.status.ServerPing$a")) - .field(0, Converters.passthrough(byte[].class)); + DATA_WRAPPER = AutoWrapper.wrap(ServerData.class, SERVER_DATA_CLASS); + SAMPLE_WRAPPER = AutoWrapper.wrap(PlayerSample.class, PLAYER_SAMPLE_CLASS); + FAVICON_WRAPPER = AutoWrapper.wrap(Favicon.class, MinecraftReflection.getMinecraftClass("network.protocol.status.ServerPing$a")); DEFAULT_DESCRIPTION = WrappedChatComponent.fromLegacyText("A Minecraft Server"); } catch (Exception ex) { @@ -63,18 +52,18 @@ public class ServerPingRecord implements ServerPingImpl { } } - private static class PlayerSample { + public static final class PlayerSample { public int max; public int online; public Object sample; } - private static class ServerData { + public static final class ServerData { public String name; public int protocol; } - private static class Favicon { + public static final class Favicon { public byte[] iconBytes; } @@ -255,10 +244,10 @@ public class ServerPingRecord implements ServerPingImpl { @Override public Object getHandle() { - Optional players = Optional.of(SAMPLE_WRAPPER.unwrap(playerSample)); - Optional version = Optional.of(DATA_WRAPPER.unwrap(serverData)); - Optional favHandle = Optional.of(FAVICON_WRAPPER.unwrap(favicon)); + Optional playersHandle = Optional.ofNullable(playerSample != null ? SAMPLE_WRAPPER.unwrap(playerSample) : null); + Optional versionHandle = Optional.ofNullable(serverData != null ? DATA_WRAPPER.unwrap(serverData) : null); + Optional favHandle = Optional.ofNullable(favicon != null ? FAVICON_WRAPPER.unwrap(favicon) : null); - return PING_CTOR.invoke(description, players, version, favHandle, enforceSafeChat); + return PING_CTOR.invoke(description, playersHandle, versionHandle, favHandle, enforceSafeChat); } }