Archiviert
13
0

Attempt to fix a NPE with packet sending

Addresses #88
Dieser Commit ist enthalten in:
Dan Mulloy 2015-06-09 14:19:37 -04:00
Ursprung 423cc320f6
Commit 0d18bd2734
7 geänderte Dateien mit 33 neuen und 22 gelöschten Zeilen

Datei anzeigen

@ -64,6 +64,7 @@ class ChannelInjector extends ByteToMessageDecoder implements Injector {
public static final ReportType REPORT_CANNOT_INTERCEPT_CLIENT_PACKET = new ReportType("Unable to intercept a read client packet."); public static final ReportType REPORT_CANNOT_INTERCEPT_CLIENT_PACKET = new ReportType("Unable to intercept a read client packet.");
public static final ReportType REPORT_CANNOT_EXECUTE_IN_CHANNEL_THREAD = new ReportType("Cannot execute code in channel thread."); public static final ReportType REPORT_CANNOT_EXECUTE_IN_CHANNEL_THREAD = new ReportType("Cannot execute code in channel thread.");
public static final ReportType REPORT_CANNOT_FIND_GET_VERSION = new ReportType("Cannot find getVersion() in NetworkMananger"); public static final ReportType REPORT_CANNOT_FIND_GET_VERSION = new ReportType("Cannot find getVersion() in NetworkMananger");
public static final ReportType REPORT_CANNOT_SEND_PACKET = new ReportType("Unable to send packet %s to %s");
/** /**
* Indicates that a packet has bypassed packet listeners. * Indicates that a packet has bypassed packet listeners.
@ -668,8 +669,9 @@ class ChannelInjector extends ByteToMessageDecoder implements Injector {
} else { } else {
MinecraftMethods.getSendPacketMethod().invoke(getPlayerConnection(), packet); MinecraftMethods.getSendPacketMethod().invoke(getPlayerConnection(), packet);
} }
} catch (Exception e) { } catch (Throwable ex) {
throw new RuntimeException("Unable to send server packet " + packet, e); ProtocolLibrary.getErrorReporter().reportWarning(factory.getPlugin(),
Report.newBuilder(REPORT_CANNOT_SEND_PACKET).messageParam(packet, playerName).error(ex).build());
} }
} }

Datei anzeigen

@ -126,7 +126,7 @@ class NetworkServerInjector extends PlayerInjector {
return; return;
if (!tryInjectManager()) { if (!tryInjectManager()) {
Class<?> serverHandlerClass = MinecraftReflection.getNetServerHandlerClass(); Class<?> serverHandlerClass = MinecraftReflection.getPlayerConnectionClass();
// Try to override the proxied object // Try to override the proxied object
if (proxyServerField != null) { if (proxyServerField != null) {

Datei anzeigen

@ -188,7 +188,7 @@ public abstract class PlayerInjector implements SocketInjector {
// Retrieve the server handler // Retrieve the server handler
if (serverHandlerField == null) { if (serverHandlerField == null) {
serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType( serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType(
"NetServerHandler", MinecraftReflection.getNetServerHandlerClass()); "NetServerHandler", MinecraftReflection.getPlayerConnectionClass());
proxyServerField = getProxyField(notchEntity, serverHandlerField); proxyServerField = getProxyField(notchEntity, serverHandlerField);
} }
@ -402,7 +402,7 @@ public abstract class PlayerInjector implements SocketInjector {
FuzzyReflection reflection = FuzzyReflection.fromObject(currentHandler, true); FuzzyReflection reflection = FuzzyReflection.fromObject(currentHandler, true);
// It might be // It might be
return reflection.getFieldByType("NetServerHandler", MinecraftReflection.getNetServerHandlerClass()); return reflection.getFieldByType("NetServerHandler", MinecraftReflection.getPlayerConnectionClass());
} catch (RuntimeException e) { } catch (RuntimeException e) {
// Damn // Damn
@ -428,7 +428,7 @@ public abstract class PlayerInjector implements SocketInjector {
Class<?> clazz = obj.getClass(); Class<?> clazz = obj.getClass();
return MinecraftReflection.getNetLoginHandlerClass().equals(clazz) || return MinecraftReflection.getNetLoginHandlerClass().equals(clazz) ||
MinecraftReflection.getNetServerHandlerClass().equals(clazz); MinecraftReflection.getPlayerConnectionClass().equals(clazz);
} }
/** /**
@ -601,7 +601,7 @@ public abstract class PlayerInjector implements SocketInjector {
final Object handler = getNetHandler(true); final Object handler = getNetHandler(true);
// Is this a net server class? // Is this a net server class?
if (MinecraftReflection.getNetServerHandlerClass().isAssignableFrom(handler.getClass())) { if (MinecraftReflection.getPlayerConnectionClass().isAssignableFrom(handler.getClass())) {
setUpdatedPlayer( setUpdatedPlayer(
(Player) MinecraftReflection.getBukkitEntity(getEntityPlayer(handler)) (Player) MinecraftReflection.getBukkitEntity(getEntityPlayer(handler))
); );

Datei anzeigen

@ -5,6 +5,7 @@ import org.bukkit.entity.Player;
import com.comphenix.protocol.injector.BukkitUnwrapper; import com.comphenix.protocol.injector.BukkitUnwrapper;
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.google.common.base.Preconditions;
/** /**
* Retrieve the content of well-known fields in Minecraft. * Retrieve the content of well-known fields in Minecraft.
@ -29,7 +30,7 @@ public class MinecraftFields {
if (NETWORK_ACCESSOR == null) { if (NETWORK_ACCESSOR == null) {
Class<?> networkClass = MinecraftReflection.getNetworkManagerClass(); Class<?> networkClass = MinecraftReflection.getNetworkManagerClass();
Class<?> connectionClass = MinecraftReflection.getNetServerHandlerClass(); Class<?> connectionClass = MinecraftReflection.getPlayerConnectionClass();
NETWORK_ACCESSOR = Accessors.getFieldAccessor(connectionClass, networkClass, true); NETWORK_ACCESSOR = Accessors.getFieldAccessor(connectionClass, networkClass, true);
} }
// Retrieve the network manager // Retrieve the network manager
@ -41,7 +42,7 @@ public class MinecraftFields {
} }
/** /**
* Retrieve the player connection (or NetServerHandler) associated with a player. * Retrieve the PlayerConnection (or NetServerHandler) associated with a player.
* @param player - the player. * @param player - the player.
* @return The player connection. * @return The player connection.
*/ */
@ -51,8 +52,10 @@ public class MinecraftFields {
// Retrieve player connection from a native instance // Retrieve player connection from a native instance
private static Object getPlayerConnection(Object nmsPlayer) { private static Object getPlayerConnection(Object nmsPlayer) {
Preconditions.checkNotNull(nmsPlayer, "nmsPlayer cannot be null!");
if (CONNECTION_ACCESSOR == null) { if (CONNECTION_ACCESSOR == null) {
Class<?> connectionClass = MinecraftReflection.getNetServerHandlerClass(); Class<?> connectionClass = MinecraftReflection.getPlayerConnectionClass();
CONNECTION_ACCESSOR = Accessors.getFieldAccessor(nmsPlayer.getClass(), connectionClass, true); CONNECTION_ACCESSOR = Accessors.getFieldAccessor(nmsPlayer.getClass(), connectionClass, true);
} }
return CONNECTION_ACCESSOR.get(nmsPlayer); return CONNECTION_ACCESSOR.get(nmsPlayer);

Datei anzeigen

@ -41,7 +41,7 @@ public class MinecraftMethods {
*/ */
public static Method getSendPacketMethod() { public static Method getSendPacketMethod() {
if (sendPacketMethod == null) { if (sendPacketMethod == null) {
Class<?> serverHandlerClass = MinecraftReflection.getNetServerHandlerClass(); Class<?> serverHandlerClass = MinecraftReflection.getPlayerConnectionClass();
try { try {
sendPacketMethod = FuzzyReflection.fromClass(serverHandlerClass).getMethodByName("sendPacket.*"); sendPacketMethod = FuzzyReflection.fromClass(serverHandlerClass).getMethodByName("sendPacket.*");

Datei anzeigen

@ -463,7 +463,7 @@ public class MinecraftReflection {
* @return TRUE if it is, FALSE otherwise. * @return TRUE if it is, FALSE otherwise.
*/ */
public static boolean isServerHandler(Object obj) { public static boolean isServerHandler(Object obj) {
return obj != null && getNetServerHandlerClass().isAssignableFrom(obj.getClass()); return obj != null && getPlayerConnectionClass().isAssignableFrom(obj.getClass());
} }
/** /**
@ -685,7 +685,7 @@ public class MinecraftReflection {
} }
// Select a method with one Minecraft object parameter // Select a method with one Minecraft object parameter
Method selected = FuzzyReflection.fromClass(getNetServerHandlerClass()). Method selected = FuzzyReflection.fromClass(getPlayerConnectionClass()).
getMethod(FuzzyMethodContract.newBuilder(). getMethod(FuzzyMethodContract.newBuilder().
parameterMatches(paketContract, 0). parameterMatches(paketContract, 0).
parameterCount(1). parameterCount(1).
@ -974,16 +974,16 @@ public class MinecraftReflection {
} }
/** /**
* Retrieve the NetServerHandler class (or PlayerConnection) * Retrieve the PlayerConnection class (or NetServerHandler)
* @return The NetServerHandler class. * @return The PlayerConnection class.
*/ */
public static Class<?> getNetServerHandlerClass() { public static Class<?> getPlayerConnectionClass() {
try { try {
return getMinecraftClass("NetServerHandler", "PlayerConnection"); return getMinecraftClass("PlayerConnection", "NetServerHandler");
} catch (RuntimeException e) { } catch (RuntimeException e) {
try { try {
// Use the player connection field // Use the player connection field
return setMinecraftClass("NetServerHandler", return setMinecraftClass("PlayerConnection",
FuzzyReflection.fromClass(getEntityPlayerClass()). FuzzyReflection.fromClass(getEntityPlayerClass()).
getFieldByType("playerConnection", getNetHandlerClass()).getType() getFieldByType("playerConnection", getNetHandlerClass()).getType()
); );
@ -1012,7 +1012,7 @@ public class MinecraftReflection {
FuzzyFieldContract.newBuilder().typeMatches(playerConnection).build() FuzzyFieldContract.newBuilder().typeMatches(playerConnection).build()
).getType(); ).getType();
return setMinecraftClass("NetServerHandler", fieldType); return setMinecraftClass("PlayerConnection", fieldType);
} }
} }
} }
@ -1025,7 +1025,7 @@ public class MinecraftReflection {
try { try {
return getMinecraftClass("INetworkManager", "NetworkManager"); return getMinecraftClass("INetworkManager", "NetworkManager");
} catch (RuntimeException e) { } catch (RuntimeException e) {
Constructor<?> selected = FuzzyReflection.fromClass(getNetServerHandlerClass()). Constructor<?> selected = FuzzyReflection.fromClass(getPlayerConnectionClass()).
getConstructor(FuzzyMethodContract.newBuilder(). getConstructor(FuzzyMethodContract.newBuilder().
parameterSuperOf(getMinecraftServerClass(), 0). parameterSuperOf(getMinecraftServerClass(), 0).
parameterSuperOf(getEntityPlayerClass(), 2). parameterSuperOf(getEntityPlayerClass(), 2).
@ -1304,7 +1304,7 @@ public class MinecraftReflection {
} else { } else {
serverConnectionContract. serverConnectionContract.
method(FuzzyMethodContract.newBuilder(). method(FuzzyMethodContract.newBuilder().
parameterExactType(getNetServerHandlerClass())); parameterExactType(getPlayerConnectionClass()));
selected = FuzzyReflection.fromClass(getMinecraftServerClass()). selected = FuzzyReflection.fromClass(getMinecraftServerClass()).
getMethod(FuzzyMethodContract.newBuilder(). getMethod(FuzzyMethodContract.newBuilder().
@ -1454,7 +1454,7 @@ public class MinecraftReflection {
field(FuzzyFieldContract.newBuilder(). field(FuzzyFieldContract.newBuilder().
typeDerivedOf(List.class)). typeDerivedOf(List.class)).
method(FuzzyMethodContract.newBuilder(). method(FuzzyMethodContract.newBuilder().
parameterExactType(getNetServerHandlerClass())). parameterExactType(getPlayerConnectionClass())).
build(); build();
Field selected = FuzzyReflection.fromClass(MinecraftReflection.getMinecraftServerClass(), true). Field selected = FuzzyReflection.fromClass(MinecraftReflection.getMinecraftServerClass(), true).

Datei anzeigen

@ -11,6 +11,7 @@ import net.minecraft.server.v1_8_R3.IChatBaseComponent;
import net.minecraft.server.v1_8_R3.IChatBaseComponent.ChatSerializer; import net.minecraft.server.v1_8_R3.IChatBaseComponent.ChatSerializer;
import net.minecraft.server.v1_8_R3.NBTCompressedStreamTools; import net.minecraft.server.v1_8_R3.NBTCompressedStreamTools;
import net.minecraft.server.v1_8_R3.PacketPlayOutUpdateAttributes.AttributeSnapshot; import net.minecraft.server.v1_8_R3.PacketPlayOutUpdateAttributes.AttributeSnapshot;
import net.minecraft.server.v1_8_R3.PlayerConnection;
import net.minecraft.server.v1_8_R3.ServerPing; import net.minecraft.server.v1_8_R3.ServerPing;
import net.minecraft.server.v1_8_R3.ServerPing.ServerData; import net.minecraft.server.v1_8_R3.ServerPing.ServerData;
import net.minecraft.server.v1_8_R3.ServerPing.ServerPingPlayerSample; import net.minecraft.server.v1_8_R3.ServerPing.ServerPingPlayerSample;
@ -94,6 +95,11 @@ public class MinecraftReflectionTest {
assertEquals(ChunkCoordIntPair.class, MinecraftReflection.getChunkCoordIntPair()); assertEquals(ChunkCoordIntPair.class, MinecraftReflection.getChunkCoordIntPair());
} }
@Test
public void testPlayerConnection() {
assertEquals(PlayerConnection.class, MinecraftReflection.getPlayerConnectionClass());
}
@Test @Test
public void testServerPing() { public void testServerPing() {
assertEquals(ServerPing.class, MinecraftReflection.getServerPingClass()); assertEquals(ServerPing.class, MinecraftReflection.getServerPingClass());