diff --git a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java index 425a158db..0872f8932 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java +++ b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java @@ -1,10 +1,12 @@ package us.myles.ViaVersion; import com.google.gson.JsonObject; +import net.md_5.bungee.UserConnection; 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; @@ -19,6 +21,8 @@ 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.util.GsonUtil; @@ -44,7 +48,7 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { Via.init(ViaManager.builder() .platform(this) .injector(new BungeeViaInjector()) - .loader(new BungeeViaLoader()) + .loader(new BungeeViaLoader(this)) .commandHandler(commandHandler) .build()); @@ -159,4 +163,17 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { Via.getManager().removePortedClient(e.getPlayer().getUniqueId()); } + // Set the handshake version every time someone connects to any server TODO reflection + @EventHandler + public void onServerConnect(ServerConnectEvent e) throws NoSuchFieldException, IllegalAccessException { + us.myles.ViaVersion.api.data.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()); + UserConnection connection = (UserConnection) e.getPlayer(); + connection.getPendingConnection().getHandshake().setProtocolVersion(protocolId); + } + } 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 4b8dc0563..08bea9bda 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,14 +4,24 @@ 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 net.md_5.bungee.netty.ChannelWrapper; 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 us.myles.ViaVersion.util.ReflectionUtil; import java.util.List; @@ -47,6 +57,7 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { } // Increment sent info.incrementSent(); + if (info.isActive()) { // Handle ID int id = Type.VAR_INT.read(bytebuf); @@ -71,6 +82,8 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { bytebuf = BungeePipelineUtil.compress(ctx, bytebuf); } out.add(bytebuf.retain()); + + checkServerChange(); } @Override @@ -79,4 +92,45 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { super.exceptionCaught(ctx, cause); } + // TODO reflection + public void checkServerChange() throws NoSuchFieldException, IllegalAccessException { + 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); + + // TODO HANDLE + if (!ProtocolDetectorService.hasProtocolId(serverName)) { + Via.getPlatform().getLogger().severe("Could not find the protocol id for server " + serverName); + return; + } + + int protocolId = ProtocolDetectorService.getProtocolId(serverName); + net.md_5.bungee.UserConnection connection = (net.md_5.bungee.UserConnection) player; + + ChannelWrapper wrapper = ReflectionUtil.get(connection, "ch", ChannelWrapper.class); + wrapper.setVersion(protocolId); + + us.myles.ViaVersion.api.data.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(); + if (protocols != null) { + pipeline.cleanPipes(); + for (Pair prot : protocols) { + pipeline.add(prot.getValue()); + } + } + connection.init(); + } + } + } + } + } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java index b3a0efe48..d8efb2627 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java @@ -5,9 +5,11 @@ import io.netty.channel.ChannelInitializer; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.platform.ViaInjector; import us.myles.ViaVersion.bungee.handlers.BungeeChannelInitializer; +import us.myles.ViaVersion.util.ReflectionUtil; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.List; public class BungeeViaInjector implements ViaInjector { @Override @@ -42,7 +44,7 @@ public class BungeeViaInjector implements ViaInjector { @Override public int getServerProtocolVersion() throws Exception { - return 47; // TODO Config Option + return (int) ReflectionUtil.getStatic(Class.forName("net.md_5.bungee.protocol.ProtocolConstants"), "SUPPORTED_VERSION_IDS", List.class).get(0); } @Override 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 9e44f86af..ef552bfa9 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 @@ -1,13 +1,23 @@ package us.myles.ViaVersion.bungee.platform; +import lombok.AllArgsConstructor; +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.service.ProtocolDetectorService; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import java.util.concurrent.TimeUnit; + +@AllArgsConstructor public class BungeeViaLoader implements ViaPlatformLoader { + private BungeePlugin plugin; + @Override public void load() { Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter()); + + plugin.getProxy().getScheduler().schedule(plugin, new ProtocolDetectorService(plugin), 0, 1, TimeUnit.MINUTES); } } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java new file mode 100644 index 000000000..d8a27dcf9 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java @@ -0,0 +1,43 @@ +package us.myles.ViaVersion.bungee.service; + +import net.md_5.bungee.api.Callback; +import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.api.config.ServerInfo; +import us.myles.ViaVersion.BungeePlugin; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ProtocolDetectorService implements Runnable { + private static final Map protocolIds = new ConcurrentHashMap<>(); + private BungeePlugin plugin; + + public ProtocolDetectorService(BungeePlugin plugin) { + this.plugin = plugin; + } + + public static Integer getProtocolId(String serverName) { + if (!hasProtocolId(serverName)) + return -1; + return protocolIds.get(serverName); + } + + public static boolean hasProtocolId(String serverName) { + return protocolIds.containsKey(serverName); + } + + @Override + public void run() { + System.out.println("Checking protocol ids"); // TODO remove message after confirming that it works + + for (final Map.Entry lists : plugin.getProxy().getServers().entrySet()) { + lists.getValue().ping(new Callback() { + @Override + public void done(ServerPing serverPing, Throwable throwable) { + if (throwable == null) + protocolIds.put(lists.getKey(), serverPing.getVersion().getProtocol()); + } + }); + } + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/storage/BungeeStorage.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/storage/BungeeStorage.java new file mode 100644 index 000000000..683b8230d --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/storage/BungeeStorage.java @@ -0,0 +1,20 @@ +package us.myles.ViaVersion.bungee.storage; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; + +@Data +@EqualsAndHashCode(callSuper = true) +public class BungeeStorage extends StoredObject { + private ProxiedPlayer player; + private String currentServer; + + public BungeeStorage(UserConnection user, ProxiedPlayer player) { + super(user); + this.player = player; + this.currentServer = ""; + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java index 1525cfee8..f8226a775 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java @@ -162,4 +162,9 @@ public class ProtocolPipeline extends Protocol { public List pipes() { return protocolList; } + + public void cleanPipes() { + pipes().clear(); + registerPackets(); + } }