forked from SteamWar/SteamWar
Remove Reflection from TinyProtocol
This commit is contained in:
@@ -20,11 +20,13 @@
|
|||||||
package com.comphenix.tinyprotocol;
|
package com.comphenix.tinyprotocol;
|
||||||
|
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
import com.mojang.authlib.GameProfile;
|
|
||||||
import de.steamwar.Reflection;
|
import de.steamwar.Reflection;
|
||||||
import de.steamwar.Reflection.Field;
|
|
||||||
import io.netty.channel.*;
|
import io.netty.channel.*;
|
||||||
import org.bukkit.Bukkit;
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.protocol.login.ServerboundHelloPacket;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerConnectionListener;
|
||||||
|
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
@@ -49,27 +51,6 @@ import java.util.logging.Level;
|
|||||||
public abstract class TinyProtocol {
|
public abstract class TinyProtocol {
|
||||||
private static final AtomicInteger ID = new AtomicInteger(0);
|
private static final AtomicInteger ID = new AtomicInteger(0);
|
||||||
|
|
||||||
// Required Minecraft classes
|
|
||||||
private static final Class<?> entityPlayerClass = Reflection.getClass("{nms}.EntityPlayer", "net.minecraft.server.level.EntityPlayer");
|
|
||||||
private static final Class<?> playerConnectionClass = Reflection.getClass("{nms}.PlayerConnection", "net.minecraft.server.network.PlayerConnection");
|
|
||||||
private static final Class<?> networkManagerClass = Reflection.getClass("{nms}.NetworkManager", "net.minecraft.network.NetworkManager");
|
|
||||||
|
|
||||||
// Used in order to lookup a channel
|
|
||||||
private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle");
|
|
||||||
private static final FieldAccessor<?> getConnection = Reflection.getField(entityPlayerClass, null, playerConnectionClass);
|
|
||||||
private static final FieldAccessor<?> getManager = Reflection.getField(playerConnectionClass, null, networkManagerClass);
|
|
||||||
private static final FieldAccessor<Channel> getChannel = Reflection.getField(networkManagerClass, Channel.class, 0);
|
|
||||||
|
|
||||||
// Looking up ServerConnection
|
|
||||||
private static final Class<Object> minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer", "net.minecraft.server.MinecraftServer");
|
|
||||||
private static final Class<Object> serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection", "net.minecraft.server.network.ServerConnection");
|
|
||||||
private static final FieldAccessor<Object> getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0);
|
|
||||||
private static final FieldAccessor<Object> getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0);
|
|
||||||
|
|
||||||
// Packets we have to intercept
|
|
||||||
private static final Class<?> PACKET_LOGIN_IN_START = Reflection.getClass("{nms}.PacketLoginInStart", "net.minecraft.network.protocol.login.PacketLoginInStart");
|
|
||||||
private static final FieldAccessor<GameProfile> getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0);
|
|
||||||
|
|
||||||
// Speedup channel lookup
|
// Speedup channel lookup
|
||||||
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
|
private Map<String, Channel> channelLookup = new MapMaker().weakValues().makeMap();
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
@@ -78,7 +59,7 @@ public abstract class TinyProtocol {
|
|||||||
private Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
|
private Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().<Channel, Boolean>makeMap());
|
||||||
|
|
||||||
// List of network markers
|
// List of network markers
|
||||||
private List<Object> networkManagers;
|
private List<Connection> networkManagers;
|
||||||
|
|
||||||
// Injected channel handlers
|
// Injected channel handlers
|
||||||
private List<Channel> serverChannels = new ArrayList<>();
|
private List<Channel> serverChannels = new ArrayList<>();
|
||||||
@@ -204,34 +185,18 @@ public abstract class TinyProtocol {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void registerChannelHandler() {
|
private void registerChannelHandler() {
|
||||||
Object mcServer = getMinecraftServer.get(Bukkit.getServer());
|
ServerConnectionListener serverConnection = MinecraftServer.getServer().getConnection();
|
||||||
Object serverConnection = getServerConnection.get(mcServer);
|
networkManagers = serverConnection.getConnections();
|
||||||
boolean looking = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Field field = Reflection.getParameterizedField(serverConnectionClass, List.class, networkManagerClass);
|
|
||||||
field.setAccessible(true);
|
|
||||||
|
|
||||||
networkManagers = (List<Object>) field.get(serverConnection);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
plugin.getLogger().info("Encountered an exception checking list fields" + ex);
|
|
||||||
MethodInvoker method = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass);
|
|
||||||
|
|
||||||
networkManagers = (List<Object>) method.invoke(null, serverConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkManagers == null) {
|
|
||||||
throw new IllegalArgumentException("Failed to obtain list of network managers");
|
|
||||||
}
|
|
||||||
// We need to synchronize against this list
|
// We need to synchronize against this list
|
||||||
createServerChannelHandler();
|
createServerChannelHandler();
|
||||||
|
|
||||||
// Find the correct list, or implicitly throw an exception
|
// Find the correct list, or implicitly throw an exception
|
||||||
|
boolean looking = true;
|
||||||
for (int i = 0; looking; i++) {
|
for (int i = 0; looking; i++) {
|
||||||
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
|
List<Object> list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection);
|
||||||
|
|
||||||
for (Object item : list) {
|
for (Object item : list) {
|
||||||
if (!ChannelFuture.class.isInstance(item))
|
if (!(item instanceof ChannelFuture))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Channel future that contains the server connection
|
// Channel future that contains the server connection
|
||||||
@@ -416,10 +381,8 @@ public abstract class TinyProtocol {
|
|||||||
|
|
||||||
// Lookup channel again
|
// Lookup channel again
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
Object connection = getConnection.get(getPlayerHandle.invoke(player));
|
Channel playerChannel = ((CraftPlayer) player).getHandle().connection.connection.channel;
|
||||||
Object manager = getManager.get(connection);
|
channelLookup.put(player.getName(), channel = playerChannel);
|
||||||
|
|
||||||
channelLookup.put(player.getName(), channel = getChannel.get(manager));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
@@ -536,9 +499,8 @@ public abstract class TinyProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleLoginStart(Channel channel, Object packet) {
|
private void handleLoginStart(Channel channel, Object packet) {
|
||||||
if (PACKET_LOGIN_IN_START.isInstance(packet)) {
|
if (packet instanceof ServerboundHelloPacket(String name, UUID packetId)) {
|
||||||
GameProfile profile = getGameProfile.get(packet);
|
channelLookup.put(name, channel);
|
||||||
channelLookup.put(profile.getName(), channel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user