Fix some issues with server ping in 1.19.4

This commit is contained in:
Dan Mulloy 2023-03-23 20:23:10 -05:00
parent 05fa147b48
commit 64e1e7de24
No known key found for this signature in database
GPG Key ID: E3B02DE32FB04AC1
6 changed files with 56 additions and 39 deletions

View File

@ -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));

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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<T> implements EquivalentConverter<T> {
}
public T wrap(Object nmsObject) {
Preconditions.checkNotNull(nmsObject);
T instance;
try {
@ -114,6 +117,8 @@ public class AutoWrapper<T> implements EquivalentConverter<T> {
}
public Object unwrap(Object wrapper) {
Preconditions.checkNotNull(wrapper);
// ensures that all accessors are present
computeFieldAccessors();
computeNmsConstructorAccess();
@ -139,14 +144,14 @@ public class AutoWrapper<T> implements EquivalentConverter<T> {
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);
}
}

View File

@ -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();
}

View File

@ -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<Object> players = Optional.of(SAMPLE_WRAPPER.unwrap(playerSample));
Optional<Object> version = Optional.of(DATA_WRAPPER.unwrap(serverData));
Optional<Object> favHandle = Optional.of(FAVICON_WRAPPER.unwrap(favicon));
Optional<Object> playersHandle = Optional.ofNullable(playerSample != null ? SAMPLE_WRAPPER.unwrap(playerSample) : null);
Optional<Object> versionHandle = Optional.ofNullable(serverData != null ? DATA_WRAPPER.unwrap(serverData) : null);
Optional<Object> 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);
}
}