From c896ed5f63303cb77b6764d633132c02488e58da Mon Sep 17 00:00:00 2001 From: Matsv Date: Wed, 2 Nov 2016 17:17:41 +0100 Subject: [PATCH] Move the Bungee server switch handler to an event instead of inside the encoder, this will also make ViaBackwards work correctly --- .../bukkit/handlers/BukkitEncodeHandler.java | 6 +- .../us/myles/ViaVersion/BungeePlugin.java | 46 ------- .../bungee/commands/BungeeCommand.java | 2 +- .../bungee/handlers/BungeeEncodeHandler.java | 83 ------------ .../bungee/handlers/BungeeServerHandler.java | 126 ++++++++++++++++++ .../bungee/platform/BungeeViaLoader.java | 2 + .../sponge4/Sponge4ArmorListener.java | 2 +- 7 files changed, 134 insertions(+), 133 deletions(-) create mode 100644 bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitEncodeHandler.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitEncodeHandler.java index c148d6b53..2e040983f 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitEncodeHandler.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitEncodeHandler.java @@ -8,7 +8,8 @@ import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.bukkit.util.NMSUtil; import us.myles.ViaVersion.exception.CancelException; -import us.myles.ViaVersion.handlers.*; +import us.myles.ViaVersion.handlers.ChannelHandlerContextWrapper; +import us.myles.ViaVersion.handlers.ViaHandler; import us.myles.ViaVersion.packets.Direction; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.util.PipelineUtil; @@ -23,10 +24,11 @@ public class BukkitEncodeHandler extends MessageToByteEncoder implements ViaHand try { versionField = NMSUtil.nms("PacketEncoder").getDeclaredField("version"); versionField.setAccessible(true); - } catch (Exception e){ + } catch (Exception e) { // Not compat version } } + private final UserConnection info; private final MessageToByteEncoder minecraftEncoder; diff --git a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java index 2b6c22849..7266e76c2 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java +++ b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java @@ -5,32 +5,23 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PlayerDisconnectEvent; -import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.event.EventHandler; -import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.ViaAPI; import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.configuration.ConfigurationProvider; -import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.platform.TaskId; import us.myles.ViaVersion.api.platform.ViaPlatform; -import us.myles.ViaVersion.api.protocol.Protocol; -import us.myles.ViaVersion.api.protocol.ProtocolRegistry; import us.myles.ViaVersion.bungee.commands.BungeeCommand; import us.myles.ViaVersion.bungee.commands.BungeeCommandHandler; import us.myles.ViaVersion.bungee.commands.BungeeCommandSender; import us.myles.ViaVersion.bungee.platform.*; import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; -import us.myles.ViaVersion.bungee.storage.BungeeStorage; import us.myles.ViaVersion.dump.PluginInfo; -import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.util.GsonUtil; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -38,26 +29,10 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; public class BungeePlugin extends Plugin implements ViaPlatform, Listener { - private static Method getPendingConnection; - private static Method getHandshake; - private static Method setProtocol; - private BungeeViaAPI api; private BungeeConfigAPI config; private BungeeCommandHandler commandHandler; - static { - try { - getPendingConnection = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getPendingConnection"); - getHandshake = Class.forName("net.md_5.bungee.connection.InitialHandler").getDeclaredMethod("getHandshake"); - setProtocol = Class.forName("net.md_5.bungee.protocol.packet.Handshake").getDeclaredMethod("setProtocolVersion", int.class); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - @Override public void onLoad() { api = new BungeeViaAPI(); @@ -179,25 +154,4 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { public void onQuit(PlayerDisconnectEvent e) { Via.getManager().removePortedClient(e.getPlayer().getUniqueId()); } - - // Set the handshake version every time someone connects to any server - @EventHandler - public void onServerConnect(ServerConnectEvent e) throws NoSuchFieldException, IllegalAccessException { - UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId()); - if (!user.has(BungeeStorage.class)) { - user.put(new BungeeStorage(user, e.getPlayer())); - } - - int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName()); - List> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId); - - // Check if ViaVersion can support that version - try { - Object pendingConnection = getPendingConnection.invoke(e.getPlayer()); - Object handshake = getHandshake.invoke(pendingConnection); - setProtocol.invoke(handshake, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId); - } catch (InvocationTargetException e1) { - e1.printStackTrace(); - } - } } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommand.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommand.java index bdb4cbd51..900b562c1 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommand.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommand.java @@ -4,7 +4,7 @@ import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.TabExecutor; -public class BungeeCommand extends Command implements TabExecutor{ +public class BungeeCommand extends Command implements TabExecutor { private final BungeeCommandHandler handler; public BungeeCommand(BungeeCommandHandler handler) { diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java index c10d5f562..3d88529c2 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java @@ -4,25 +4,15 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageEncoder; -import net.md_5.bungee.api.connection.ProxiedPlayer; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.Pair; -import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.data.UserConnection; -import us.myles.ViaVersion.api.protocol.Protocol; -import us.myles.ViaVersion.api.protocol.ProtocolPipeline; -import us.myles.ViaVersion.api.protocol.ProtocolRegistry; import us.myles.ViaVersion.api.type.Type; -import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; -import us.myles.ViaVersion.bungee.storage.BungeeStorage; import us.myles.ViaVersion.bungee.util.BungeePipelineUtil; import us.myles.ViaVersion.exception.CancelException; import us.myles.ViaVersion.packets.Direction; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.util.PipelineUtil; -import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.util.List; @ChannelHandler.Sharable @@ -82,8 +72,6 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { bytebuf = BungeePipelineUtil.compress(ctx, bytebuf); } out.add(bytebuf.retain()); - - checkServerChange(); } @Override @@ -91,75 +79,4 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { if (PipelineUtil.containsCause(cause, CancelException.class)) return; super.exceptionCaught(ctx, cause); } - - public void checkServerChange() throws Exception { - if (info.has(BungeeStorage.class)) { - BungeeStorage storage = info.get(BungeeStorage.class); - ProxiedPlayer player = storage.getPlayer(); - - if (player.getServer() != null) { - if (player.getServer() != null && !player.getServer().getInfo().getName().equals(storage.getCurrentServer())) { - String serverName = player.getServer().getInfo().getName(); - - storage.setCurrentServer(serverName); - - int protocolId = ProtocolDetectorService.getProtocolId(serverName); - - UserConnection viaConnection = Via.getManager().getConnection(player.getUniqueId()); - ProtocolInfo info = viaConnection.get(ProtocolInfo.class); - // Refresh the pipes - List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId); - ProtocolPipeline pipeline = viaConnection.get(ProtocolInfo.class).getPipeline(); - viaConnection.clearStoredObjects(); - pipeline.cleanPipes(); - if (protocols == null) { - // TODO Check Bungee Supported Protocols? *shrugs* - protocolId = info.getProtocolVersion(); - } else { - for (Pair prot : protocols) { - pipeline.add(prot.getValue()); - } - } - - viaConnection.put(info); - viaConnection.put(storage); - - viaConnection.setActive(protocols != null); - - // Init all protocols TODO check if this can get moved up to the previous for loop, and doesn't require the pipeline to already exist. - for (Protocol protocol : pipeline.pipes()) { - protocol.init(viaConnection); - } - - Object wrapper = channelWrapper.get(player); - setVersion.invoke(wrapper, protocolId); - - Object entityMap = getEntityMap.invoke(null, protocolId); - entityRewrite.set(player, entityMap); - } - } - } - } - - private static Method getEntityMap = null; - private static Method setVersion = null; - private static Field entityRewrite = null; - private static Field channelWrapper = null; - - static { - try { - getEntityMap = Class.forName("net.md_5.bungee.entitymap.EntityMap").getDeclaredMethod("getEntityMap", int.class); - setVersion = Class.forName("net.md_5.bungee.netty.ChannelWrapper").getDeclaredMethod("setVersion", int.class); - channelWrapper = Class.forName("net.md_5.bungee.UserConnection").getDeclaredField("ch"); - channelWrapper.setAccessible(true); - entityRewrite = Class.forName("net.md_5.bungee.UserConnection").getDeclaredField("entityRewrite"); - entityRewrite.setAccessible(true); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - } } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java new file mode 100644 index 000000000..ef7bbf8d8 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java @@ -0,0 +1,126 @@ +package us.myles.ViaVersion.bungee.handlers; + +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.event.ServerConnectEvent; +import net.md_5.bungee.api.event.ServerConnectedEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.event.EventHandler; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.Protocol; +import us.myles.ViaVersion.api.protocol.ProtocolPipeline; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; +import us.myles.ViaVersion.bungee.storage.BungeeStorage; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; + +public class BungeeServerHandler implements Listener { + private static Method getPendingConnection; + private static Method getHandshake; + private static Method setProtocol; + private static Method getEntityMap = null; + private static Method setVersion = null; + private static Field entityRewrite = null; + private static Field channelWrapper = null; + + static { + try { + getPendingConnection = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getPendingConnection"); + getHandshake = Class.forName("net.md_5.bungee.connection.InitialHandler").getDeclaredMethod("getHandshake"); + setProtocol = Class.forName("net.md_5.bungee.protocol.packet.Handshake").getDeclaredMethod("setProtocolVersion", int.class); + getEntityMap = Class.forName("net.md_5.bungee.entitymap.EntityMap").getDeclaredMethod("getEntityMap", int.class); + setVersion = Class.forName("net.md_5.bungee.netty.ChannelWrapper").getDeclaredMethod("setVersion", int.class); + channelWrapper = Class.forName("net.md_5.bungee.UserConnection").getDeclaredField("ch"); + channelWrapper.setAccessible(true); + entityRewrite = Class.forName("net.md_5.bungee.UserConnection").getDeclaredField("entityRewrite"); + entityRewrite.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Set the handshake version every time someone connects to any server + @EventHandler + public void onServerConnect(ServerConnectEvent e) throws NoSuchFieldException, IllegalAccessException { + UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId()); + if (!user.has(BungeeStorage.class)) { + user.put(new BungeeStorage(user, e.getPlayer())); + } + + int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName()); + List> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId); + + // Check if ViaVersion can support that version + try { + Object pendingConnection = getPendingConnection.invoke(e.getPlayer()); + Object handshake = getHandshake.invoke(pendingConnection); + setProtocol.invoke(handshake, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId); + } catch (InvocationTargetException e1) { + e1.printStackTrace(); + } + } + + @EventHandler + public void onServerConnected(ServerConnectedEvent e) { + try { + checkServerChange(e, Via.getManager().getConnection(e.getPlayer().getUniqueId())); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + + public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception { + if (user.has(BungeeStorage.class)) { + BungeeStorage storage = user.get(BungeeStorage.class); + ProxiedPlayer player = storage.getPlayer(); + + if (e.getServer() != null) { + if (!e.getServer().getInfo().getName().equals(storage.getCurrentServer())) { + String serverName = e.getServer().getInfo().getName(); + + storage.setCurrentServer(serverName); + + int protocolId = ProtocolDetectorService.getProtocolId(serverName); + + UserConnection viaConnection = Via.getManager().getConnection(player.getUniqueId()); + ProtocolInfo info = viaConnection.get(ProtocolInfo.class); + // Refresh the pipes + List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId); + ProtocolPipeline pipeline = viaConnection.get(ProtocolInfo.class).getPipeline(); + viaConnection.clearStoredObjects(); + pipeline.cleanPipes(); + if (protocols == null) { + // TODO Check Bungee Supported Protocols? *shrugs* + protocolId = info.getProtocolVersion(); + } else { + for (Pair prot : protocols) { + pipeline.add(prot.getValue()); + } + } + + viaConnection.put(info); + viaConnection.put(storage); + + viaConnection.setActive(protocols != null); + + // Init all protocols TODO check if this can get moved up to the previous for loop, and doesn't require the pipeline to already exist. + for (Protocol protocol : pipeline.pipes()) { + protocol.init(viaConnection); + } + + Object wrapper = channelWrapper.get(player); + setVersion.invoke(wrapper, protocolId); + + Object entityMap = getEntityMap.invoke(null, protocolId); + entityRewrite.set(player, entityMap); + } + } + } + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java index 9ba4e250e..eb34076cb 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java @@ -5,6 +5,7 @@ import net.md_5.bungee.api.ProxyServer; import us.myles.ViaVersion.BungeePlugin; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.platform.ViaPlatformLoader; +import us.myles.ViaVersion.bungee.handlers.BungeeServerHandler; import us.myles.ViaVersion.bungee.listeners.UpdateListener; import us.myles.ViaVersion.bungee.providers.BungeeMovementTransmitter; import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider; @@ -23,6 +24,7 @@ public class BungeeViaLoader implements ViaPlatformLoader { // Listeners ProxyServer.getInstance().getPluginManager().registerListener(plugin, plugin); ProxyServer.getInstance().getPluginManager().registerListener(plugin, new UpdateListener()); + ProxyServer.getInstance().getPluginManager().registerListener(plugin, new BungeeServerHandler()); // Providers Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter()); diff --git a/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ArmorListener.java b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ArmorListener.java index 5b542bdb4..4e69b7061 100644 --- a/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ArmorListener.java +++ b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ArmorListener.java @@ -22,7 +22,7 @@ import java.lang.reflect.Field; import java.util.Optional; import java.util.UUID; -public class Sponge4ArmorListener extends ViaListener{ +public class Sponge4ArmorListener extends ViaListener { private static Field entityIdField; private static final UUID ARMOR_ATTRIBUTE = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150");