Dieser Commit ist enthalten in:
Ursprung
04b03ce06d
Commit
cbbafd7c09
@ -7,6 +7,7 @@ import org.bukkit.Bukkit;
|
|||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -135,15 +136,16 @@ public final class Reflection {
|
|||||||
return getField(getClass(className), fieldType, index);
|
return getField(getClass(className), fieldType, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common method
|
public static <T> FieldAccessor<T> getField(Class<?> target, Class<T> fieldType, int index, Class<?>... parameters) {
|
||||||
private static <T> FieldAccessor<T> getField(Class<?> target, String name, Class<T> fieldType, int index) {
|
return getField(target, null, fieldType, index, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> FieldAccessor<T> getField(Class<?> target, String name, Class<T> fieldType, int index, Class<?>... parameters) {
|
||||||
for (final Field field : target.getDeclaredFields()) {
|
for (final Field field : target.getDeclaredFields()) {
|
||||||
if ((name == null || field.getName().equals(name)) && fieldType.isAssignableFrom(field.getType()) && index-- <= 0) {
|
if(matching(field, name, fieldType, parameters) && index-- <= 0) {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
|
|
||||||
// A function for retrieving a specific field value
|
|
||||||
return new FieldAccessor<T>() {
|
return new FieldAccessor<T>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T get(Object target) {
|
public T get(Object target) {
|
||||||
@ -179,6 +181,24 @@ public final class Reflection {
|
|||||||
throw new IllegalArgumentException("Cannot find field with type " + fieldType);
|
throw new IllegalArgumentException("Cannot find field with type " + fieldType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T> boolean matching(Field field, String name, Class<T> fieldType, Class<?>... parameters) {
|
||||||
|
if(name != null && !field.getName().equals(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!fieldType.isAssignableFrom(field.getType()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(parameters.length > 0) {
|
||||||
|
Class<?>[] arguments = (Class<?>[]) ((ParameterizedType)field.getType().getGenericSuperclass()).getActualTypeArguments();
|
||||||
|
|
||||||
|
for(int i = 0; i < parameters.length; i++) {
|
||||||
|
if(arguments[i] != parameters[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for the first publicly and privately defined method of the given name and parameter count.
|
* Search for the first publicly and privately defined method of the given name and parameter count.
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.comphenix.tinyprotocol;
|
package com.comphenix.tinyprotocol;
|
||||||
|
|
||||||
import com.comphenix.tinyprotocol.Reflection.FieldAccessor;
|
import com.comphenix.tinyprotocol.Reflection.FieldAccessor;
|
||||||
import com.comphenix.tinyprotocol.Reflection.MethodInvoker;
|
|
||||||
import de.steamwar.core.Core;
|
import de.steamwar.core.Core;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelDuplexHandler;
|
import io.netty.channel.ChannelDuplexHandler;
|
||||||
@ -29,8 +28,20 @@ public class TinyProtocol implements Listener {
|
|||||||
//enforce init
|
//enforce init
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Class<?> craftServer = Reflection.getClass("{obc}.CraftServer");
|
||||||
|
private static final Class<?> dedicatedPlayerList = Reflection.getClass("{nms.server.dedicated}.DedicatedPlayerList");
|
||||||
|
private static final FieldAccessor<?> getPlayerList = Reflection.getField(craftServer, dedicatedPlayerList, 0);
|
||||||
|
private static final Class<?> playerList = Reflection.getClass("{nms.server.players}.PlayerList");
|
||||||
|
private static final Class<?> minecraftServer = Reflection.getClass("{nms.server}.MinecraftServer");
|
||||||
|
private static final FieldAccessor<?> getMinecraftServer = Reflection.getField(playerList, minecraftServer, 0);
|
||||||
|
private static final Class<?> serverConnection = Reflection.getClass("{nms.server.network}.ServerConnection");
|
||||||
|
private static final FieldAccessor<?> getServerConnection = Reflection.getField(minecraftServer, serverConnection, 0);
|
||||||
|
private static final Class<?> networkManager = Reflection.getClass("{nms.network}.NetworkManager");
|
||||||
|
private static final FieldAccessor<List> getConnections = Reflection.getField(serverConnection, List.class, 0, networkManager);
|
||||||
|
|
||||||
private final Plugin plugin;
|
private final Plugin plugin;
|
||||||
private final String handlerName;
|
private final String handlerName;
|
||||||
|
private final List<?> connections;
|
||||||
private boolean closed;
|
private boolean closed;
|
||||||
|
|
||||||
private final Map<Class<?>, List<BiFunction<Player, Object, Object>>> packetFilters = new HashMap<>();
|
private final Map<Class<?>, List<BiFunction<Player, Object, Object>>> packetFilters = new HashMap<>();
|
||||||
@ -38,11 +49,9 @@ public class TinyProtocol implements Listener {
|
|||||||
|
|
||||||
private TinyProtocol(final Plugin plugin) {
|
private TinyProtocol(final Plugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
|
||||||
// Compute handler name
|
|
||||||
this.handlerName = "tiny-" + plugin.getName() + "-" + ++id;
|
this.handlerName = "tiny-" + plugin.getName() + "-" + ++id;
|
||||||
|
this.connections = getConnections.get(getServerConnection.get(getMinecraftServer.get(getPlayerList.get(plugin.getServer()))));
|
||||||
|
|
||||||
// Prepare existing players
|
|
||||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||||
|
|
||||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||||
@ -103,12 +112,8 @@ public class TinyProtocol implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
|
|
||||||
private static final Class<Object> playerConnection = Reflection.getUntypedClass("{nms.server.network}.PlayerConnection");
|
|
||||||
private static final FieldAccessor<Object> getConnection = Reflection.getField("{nms.server.level}.EntityPlayer", playerConnection, 0);
|
|
||||||
private static final Class<Object> networkManager = Reflection.getUntypedClass("{nms.network}.NetworkManager");
|
|
||||||
private static final FieldAccessor<Object> getManager = Reflection.getField(playerConnection, networkManager, 0);
|
|
||||||
private static final FieldAccessor<Channel> getChannel = Reflection.getField(networkManager, Channel.class, 0);
|
private static final FieldAccessor<Channel> getChannel = Reflection.getField(networkManager, Channel.class, 0);
|
||||||
|
private static final FieldAccessor<UUID> getUUID = Reflection.getField(networkManager, UUID.class, 0);
|
||||||
|
|
||||||
private final class PacketInterceptor extends ChannelDuplexHandler {
|
private final class PacketInterceptor extends ChannelDuplexHandler {
|
||||||
private final Player player;
|
private final Player player;
|
||||||
@ -117,9 +122,7 @@ public class TinyProtocol implements Listener {
|
|||||||
private PacketInterceptor(Player player) {
|
private PacketInterceptor(Player player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
Object connection = getConnection.get(getPlayerHandle.invoke(player));
|
channel = getChannel.get(connections.stream().filter(connection -> player.getUniqueId().equals(getUUID.get(connection))).findAny().orElseThrow(() -> new SecurityException("Could not find channel for player " + player.getName())));
|
||||||
Object manager = getManager.get(connection);
|
|
||||||
channel = getChannel.get(manager);
|
|
||||||
|
|
||||||
synchronized (playerInterceptors) {
|
synchronized (playerInterceptors) {
|
||||||
playerInterceptors.put(player, this);
|
playerInterceptors.put(player, this);
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren