From f53c8c67e22930ef3c2380e6c1d7f12c7bf10d02 Mon Sep 17 00:00:00 2001 From: Matsv Date: Sat, 1 Oct 2016 13:31:14 +0200 Subject: [PATCH] Fix Bukkit config NPE, only change the protocol id if ViaVersion can support it and support unsupported Bungee protocol ids (Not working correctly yet) --- .../us/myles/ViaVersion/ViaVersionPlugin.java | 4 +- .../us/myles/ViaVersion/BungeePlugin.java | 26 ++++++---- .../bungee/handlers/BungeeEncodeHandler.java | 25 ++++++++-- .../bungee/platform/BungeeViaLoader.java | 3 ++ .../providers/BungeeVersionProvider.java | 50 +++++++++++++++++++ .../ViaVersion/api/data/UserConnection.java | 8 +++ .../protocols/base/BaseProtocol.java | 15 ++++-- .../protocols/base/VersionProvider.java | 12 +++++ 8 files changed, 124 insertions(+), 19 deletions(-) create mode 100644 bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java diff --git a/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java index 70603a278..a85fba03a 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -41,8 +41,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform { private List asyncQueuedTasks = new ArrayList<>(); public ViaVersionPlugin() { - // Config magic - conf = new BukkitConfigAPI(); // Command handler commandHandler = new BukkitCommandHandler(); // Init platform @@ -52,6 +50,8 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform { .injector(new BukkitViaInjector()) .loader(new BukkitViaLoader(this)) .build()); + // Config magic + conf = new BukkitConfigAPI(); // For compatibility ViaVersion.setInstance(this); diff --git a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java index 1a95df2a2..2dd9f6470 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java +++ b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java @@ -9,6 +9,7 @@ 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.ViaVersionConfig; @@ -17,6 +18,8 @@ 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; @@ -24,6 +27,7 @@ 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 us.myles.ViaVersion.util.ReflectionUtil; @@ -174,15 +178,19 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { } int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName()); - try { - Object pendingConnection = ReflectionUtil.invoke(e.getPlayer(), "getPendingConnection"); - Object handshake = ReflectionUtil.invoke(pendingConnection, "getHandshake"); - Method setProtocol = handshake.getClass().getDeclaredMethod("setProtocolVersion", int.class); - setProtocol.invoke(handshake, protocolId); - } catch (NoSuchMethodException e1) { - e1.printStackTrace(); - } catch (InvocationTargetException e1) { - e1.printStackTrace(); + List> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId); + + // Check if ViaVersion can support that version + if (protocols != null) { + try { + Object pendingConnection = ReflectionUtil.invoke(e.getPlayer(), "getPendingConnection"); + Object handshake = ReflectionUtil.invoke(pendingConnection, "getHandshake"); + Method setProtocol = handshake.getClass().getDeclaredMethod("setProtocolVersion", int.class); + setProtocol.invoke(handshake, protocolId); + System.out.println("Changed server protocol id " + protocolId + " clientProtocol:" + user.get(ProtocolInfo.class).getProtocolVersion() + " path:" + protocols); + } catch (NoSuchMethodException | InvocationTargetException e1) { + e1.printStackTrace(); + } } } 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 157e196a2..a91f52c17 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 @@ -98,6 +98,8 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { if (player.getServer() != null) { if (player.getServer() != null && !player.getServer().getInfo().getName().equals(storage.getCurrentServer())) { + + System.out.println("Server change " + player.getServer().getInfo().getName()); String serverName = player.getServer().getInfo().getName(); storage.setCurrentServer(serverName); @@ -110,21 +112,34 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { int protocolId = ProtocolDetectorService.getProtocolId(serverName); - Object wrapper = ReflectionUtil.get(player, "ch", Object.class); - wrapper.getClass().getDeclaredMethod("setVersion", int.class).invoke(wrapper, protocolId); - - us.myles.ViaVersion.api.data.UserConnection viaConnection = Via.getManager().getConnection(player.getUniqueId()); + UserConnection viaConnection = Via.getManager().getConnection(player.getUniqueId()); ProtocolInfo info = viaConnection.get(ProtocolInfo.class); // Refresh the pipes List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId); + System.out.println(info.getProtocolVersion() + ">" + protocolId + " " + protocols); ProtocolPipeline pipeline = viaConnection.get(ProtocolInfo.class).getPipeline(); if (protocols != null) { + viaConnection.clearStoredObjects(); pipeline.cleanPipes(); + for (Pair prot : protocols) { pipeline.add(prot.getValue()); } + viaConnection.put(info); + viaConnection.setActive(true); + + // 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 (Pair protocol : protocols) { + protocol.getValue().init(viaConnection); + } + + + Object wrapper = ReflectionUtil.get(player, "ch", Object.class); + wrapper.getClass().getDeclaredMethod("setVersion", int.class).invoke(wrapper, protocolId); + ReflectionUtil.invoke(player, "init"); + } else { + viaConnection.setActive(false); } - ReflectionUtil.invoke(player, "init"); } } } 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 ef552bfa9..fe2a16b32 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,7 +5,9 @@ import us.myles.ViaVersion.BungeePlugin; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.platform.ViaPlatformLoader; import us.myles.ViaVersion.bungee.providers.BungeeMovementTransmitter; +import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider; import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; +import us.myles.ViaVersion.protocols.base.VersionProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; import java.util.concurrent.TimeUnit; @@ -17,6 +19,7 @@ public class BungeeViaLoader implements ViaPlatformLoader { @Override public void load() { Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter()); + Via.getManager().getProviders().use(VersionProvider.class, new BungeeVersionProvider()); plugin.getProxy().getScheduler().schedule(plugin, new ProtocolDetectorService(plugin), 0, 1, TimeUnit.MINUTES); } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java new file mode 100644 index 000000000..699692e31 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java @@ -0,0 +1,50 @@ +package us.myles.ViaVersion.bungee.providers; + +import com.google.common.collect.Lists; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.base.VersionProvider; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.util.List; + +public class BungeeVersionProvider extends VersionProvider { + private static Class ref; + + public BungeeVersionProvider() { + try { + ref = Class.forName("net.md_5.bungee.protocol.ProtocolConstants"); + } catch (Exception e) { + System.out.println("Could not detect the ProtocolConstants class"); + e.printStackTrace(); + } + } + + @Override + public int getServerProtocol(UserConnection user) throws Exception { + if (ref == null) + return super.getServerProtocol(user); + // TODO Have one constant list forever until restart? (Might limit plugins if they change this) + List list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class); + + ProtocolInfo info = user.get(ProtocolInfo.class); + + // Bungee supports it + if (list.contains(info.getProtocolVersion())) + return info.getProtocolVersion(); + + // Older than bungee supports, get the lowest version + if (info.getProtocolVersion() < list.get(0)) { + return list.get(0); + } + + // Loop through all protocols to get the closest protocol id that bungee supports + for (Integer protocol : Lists.reverse(list)) { + if (info.getProtocolVersion() > protocol) + return protocol; + } + + System.out.println("Panic, no protocol id found for " + info.getProtocolVersion()); + return info.getProtocolVersion(); + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java index 9a393af8a..f6cb5d4f8 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java +++ b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java @@ -66,6 +66,14 @@ public class UserConnection { storedObjects.put(object.getClass(), object); } + /** + * Clear all the stored objects + * Used for bungee when switching servers. + */ + public void clearStoredObjects() { + storedObjects.clear(); + } + /** * Send a raw packet to the player * diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java index c95b51fba..f949d6944 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java @@ -11,6 +11,7 @@ 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.platform.providers.ViaProviders; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.protocol.ProtocolPipeline; import us.myles.ViaVersion.api.protocol.ProtocolRegistry; @@ -53,7 +54,9 @@ public class BaseProtocol extends Protocol { if (ProtocolRegistry.SERVER_PROTOCOL == -1) // Set the Server protocol if the detection on startup failed ProtocolRegistry.SERVER_PROTOCOL = protocolVersion; - List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), ProtocolRegistry.SERVER_PROTOCOL); + int protocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); + List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocol); + if (protocols != null) { if (protocolVersion != 9999) { //Fix ServerListPlus @@ -137,13 +140,14 @@ public class BaseProtocol extends Protocol { ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); info.setProtocolVersion(protVer); // Choose the pipe - List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), ProtocolRegistry.SERVER_PROTOCOL); + int protocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); + List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocol); ProtocolPipeline pipeline = wrapper.user().get(ProtocolInfo.class).getPipeline(); if (protocols != null) { for (Pair prot : protocols) { pipeline.add(prot.getValue()); } - wrapper.set(Type.VAR_INT, 0, ProtocolRegistry.SERVER_PROTOCOL); + wrapper.set(Type.VAR_INT, 0, protocol); } // Change state @@ -196,6 +200,11 @@ public class BaseProtocol extends Protocol { // Nothing gets added, ProtocolPipeline handles ProtocolInfo } + @Override + protected void register(ViaProviders providers) { + providers.register(VersionProvider.class, new VersionProvider()); + } + @Override public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception { super.transform(direction, state, packetWrapper); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java new file mode 100644 index 000000000..ec30cf4b1 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.protocols.base; + +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.platform.providers.Provider; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; + +public class VersionProvider implements Provider { + + public int getServerProtocol(UserConnection connection) throws Exception { + return ProtocolRegistry.SERVER_PROTOCOL; + } +}