Added yet another player hook method.
This method works by injecting into the NetServerHandler object of a player. That way, we can also intercept map chunk packets.
Dieser Commit ist enthalten in:
Ursprung
9e402a3ab4
Commit
e04a78fc04
@ -0,0 +1,115 @@
|
|||||||
|
package com.comphenix.protocol.injector;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.server.Packet;
|
||||||
|
import net.sf.cglib.proxy.Enhancer;
|
||||||
|
import net.sf.cglib.proxy.Factory;
|
||||||
|
import net.sf.cglib.proxy.MethodInterceptor;
|
||||||
|
import net.sf.cglib.proxy.MethodProxy;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a player hook into the NetServerHandler class.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
public class NetworkServerInjector extends PlayerInjector {
|
||||||
|
|
||||||
|
private static Method sendPacket;
|
||||||
|
|
||||||
|
public NetworkServerInjector(Player player, PacketFilterManager manager, Set<Integer> sendingFilters) throws IllegalAccessException {
|
||||||
|
super(player, manager, sendingFilters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initialize() throws IllegalAccessException {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
// Get the send packet method!
|
||||||
|
if (hasInitialized) {
|
||||||
|
if (sendPacket == null)
|
||||||
|
sendPacket = FuzzyReflection.fromObject(serverHandler).getMethodByParameters("sendPacket", Packet.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendServerPacket(Packet packet, boolean filtered) throws InvocationTargetException {
|
||||||
|
Object serverDeleage = filtered ? serverHandlerRef.getValue() : serverHandlerRef.getOldValue();
|
||||||
|
|
||||||
|
if (serverDeleage != null) {
|
||||||
|
try {
|
||||||
|
// Note that invocation target exception is a wrapper for a checked exception
|
||||||
|
sendPacket.invoke(serverDeleage, packet);
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException("Unable to access send packet method.", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unable to load server handler. Cannot send packet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectManager() {
|
||||||
|
if (serverHandlerRef == null)
|
||||||
|
throw new IllegalStateException("Cannot find server handler.");
|
||||||
|
// Don't inject twice
|
||||||
|
if (serverHandlerRef.getValue() instanceof Factory)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Enhancer ex = new Enhancer();
|
||||||
|
ex.setClassLoader(manager.getClassLoader());
|
||||||
|
ex.setSuperclass(serverHandler.getClass());
|
||||||
|
ex.setCallback(new MethodInterceptor() {
|
||||||
|
@Override
|
||||||
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
||||||
|
// The send packet method!
|
||||||
|
if (method.equals(sendPacket)) {
|
||||||
|
Packet packet = (Packet) args[0];
|
||||||
|
|
||||||
|
if (packet != null) {
|
||||||
|
packet = handlePacketRecieved(packet);
|
||||||
|
|
||||||
|
// A NULL packet indicate cancelling
|
||||||
|
if (packet != null)
|
||||||
|
args[0] = packet;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegate to our underlying class
|
||||||
|
try {
|
||||||
|
return method.invoke(serverHandler, args);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inject it now
|
||||||
|
serverHandlerRef.setValue(ex.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanupAll() {
|
||||||
|
if (serverHandlerRef != null)
|
||||||
|
serverHandlerRef.revertValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canInject() {
|
||||||
|
// Probably always
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -61,13 +61,22 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
public enum PlayerInjectHooks {
|
public enum PlayerInjectHooks {
|
||||||
/**
|
/**
|
||||||
* Override the packet queue lists in NetworkHandler.
|
* Override the packet queue lists in NetworkHandler.
|
||||||
|
* <p>
|
||||||
|
* Cannot intercept MapChunk packets.
|
||||||
*/
|
*/
|
||||||
NETWORK_HANDLER_FIELDS,
|
NETWORK_HANDLER_FIELDS,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the network handler object itself.
|
* Override the network handler object itself. Only works in 1.3.
|
||||||
|
* <p>
|
||||||
|
* Cannot intercept MapChunk packets.
|
||||||
*/
|
*/
|
||||||
NETWORK_MANAGER_OBJECT,
|
NETWORK_MANAGER_OBJECT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the server handler object. Versatile, but slow.
|
||||||
|
*/
|
||||||
|
NETWORK_SERVER_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a concurrent set
|
// Create a concurrent set
|
||||||
@ -79,7 +88,7 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
private Map<Player, PlayerInjector> playerInjection = new HashMap<Player, PlayerInjector>();
|
private Map<Player, PlayerInjector> playerInjection = new HashMap<Player, PlayerInjector>();
|
||||||
|
|
||||||
// Player injection type
|
// Player injection type
|
||||||
private PlayerInjectHooks playerHook = PlayerInjectHooks.NETWORK_HANDLER_FIELDS;
|
private PlayerInjectHooks playerHook = PlayerInjectHooks.NETWORK_SERVER_OBJECT;
|
||||||
|
|
||||||
// Packet injection
|
// Packet injection
|
||||||
private PacketInjector packetInjector;
|
private PacketInjector packetInjector;
|
||||||
@ -373,6 +382,8 @@ public final class PacketFilterManager implements ProtocolManager {
|
|||||||
return new NetworkFieldInjector(player, this, sendingFilters);
|
return new NetworkFieldInjector(player, this, sendingFilters);
|
||||||
case NETWORK_MANAGER_OBJECT:
|
case NETWORK_MANAGER_OBJECT:
|
||||||
return new NetworkObjectInjector(player, this, sendingFilters);
|
return new NetworkObjectInjector(player, this, sendingFilters);
|
||||||
|
case NETWORK_SERVER_OBJECT:
|
||||||
|
return new NetworkServerInjector(player, this, sendingFilters);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Cannot construct a player injector.");
|
throw new IllegalArgumentException("Cannot construct a player injector.");
|
||||||
}
|
}
|
||||||
|
@ -56,9 +56,11 @@ abstract class PlayerInjector {
|
|||||||
|
|
||||||
// Reference to the player's network manager
|
// Reference to the player's network manager
|
||||||
protected VolatileField networkManagerRef;
|
protected VolatileField networkManagerRef;
|
||||||
|
protected VolatileField serverHandlerRef;
|
||||||
protected Object networkManager;
|
protected Object networkManager;
|
||||||
|
|
||||||
// Current net handler
|
// Current net handler
|
||||||
|
protected Object serverHandler;
|
||||||
protected Object netHandler;
|
protected Object netHandler;
|
||||||
|
|
||||||
// The packet manager and filters
|
// The packet manager and filters
|
||||||
@ -75,12 +77,18 @@ abstract class PlayerInjector {
|
|||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the notch (NMS) entity player object.
|
||||||
|
* @return Notch player object.
|
||||||
|
*/
|
||||||
|
protected EntityPlayer getEntityPlayer() {
|
||||||
|
CraftPlayer craft = (CraftPlayer) player;
|
||||||
|
return craft.getHandle();
|
||||||
|
}
|
||||||
|
|
||||||
protected void initialize() throws IllegalAccessException {
|
protected void initialize() throws IllegalAccessException {
|
||||||
|
|
||||||
CraftPlayer craft = (CraftPlayer) player;
|
EntityPlayer notchEntity = getEntityPlayer();
|
||||||
EntityPlayer notchEntity = craft.getHandle();
|
|
||||||
|
|
||||||
Object serverHandler = null;
|
|
||||||
|
|
||||||
if (!hasInitialized) {
|
if (!hasInitialized) {
|
||||||
// Do this first, in case we encounter an exception
|
// Do this first, in case we encounter an exception
|
||||||
@ -89,7 +97,8 @@ abstract class PlayerInjector {
|
|||||||
// Retrieve the server handler
|
// Retrieve the server handler
|
||||||
if (serverHandlerField == null)
|
if (serverHandlerField == null)
|
||||||
serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType(".*NetServerHandler");
|
serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType(".*NetServerHandler");
|
||||||
serverHandler = FieldUtils.readField(serverHandlerField, notchEntity);
|
serverHandlerRef = new VolatileField(serverHandlerField, notchEntity);
|
||||||
|
serverHandler = serverHandlerRef.getValue();
|
||||||
|
|
||||||
// Next, get the network manager
|
// Next, get the network manager
|
||||||
if (networkManagerField == null)
|
if (networkManagerField == null)
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren