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 index bc3cbf633..6a7e2b14d 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeServerHandler.java @@ -1,11 +1,13 @@ package us.myles.ViaVersion.bungee.handlers; +import com.google.common.base.Joiner; 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 net.md_5.bungee.event.EventPriority; +import net.md_5.bungee.protocol.packet.PluginMessage; import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.boss.BossBar; @@ -13,19 +15,22 @@ 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.protocol.ProtocolVersion; import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; import us.myles.ViaVersion.bungee.storage.BungeeStorage; import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets.InventoryPackets; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.util.List; public class BungeeServerHandler implements Listener { - private static Method getPendingConnection; private static Method getHandshake; + private static Method getRelayMessages; private static Method setProtocol; private static Method getEntityMap = null; private static Method setVersion = null; @@ -34,8 +39,8 @@ public class BungeeServerHandler implements Listener { static { try { - getPendingConnection = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getPendingConnection"); getHandshake = Class.forName("net.md_5.bungee.connection.InitialHandler").getDeclaredMethod("getHandshake"); + getRelayMessages = Class.forName("net.md_5.bungee.connection.InitialHandler").getDeclaredMethod("getRelayMessages"); 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); @@ -62,8 +67,8 @@ public class BungeeServerHandler implements Listener { // Check if ViaVersion can support that version try { - Object pendingConnection = getPendingConnection.invoke(e.getPlayer()); - Object handshake = getHandshake.invoke(pendingConnection); + //Object pendingConnection = getPendingConnection.invoke(e.getPlayer()); + Object handshake = getHandshake.invoke(e.getPlayer().getPendingConnection()); setProtocol.invoke(handshake, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId); } catch (InvocationTargetException | IllegalAccessException e1) { e1.printStackTrace(); @@ -103,6 +108,8 @@ public class BungeeServerHandler implements Listener { int protocolId = ProtocolDetectorService.getProtocolId(serverName); ProtocolInfo info = user.get(ProtocolInfo.class); + int previousServerProtocol = info.getServerProtocolVersion(); + // Refresh the pipes List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId); ProtocolPipeline pipeline = user.get(ProtocolInfo.class).getPipeline(); @@ -121,6 +128,45 @@ public class BungeeServerHandler implements Listener { // Add version-specific base Protocol pipeline.add(ProtocolRegistry.getBaseProtocol(protocolId)); + // Workaround 1.13 server change + Object relayMessages = getRelayMessages.invoke(e.getPlayer().getPendingConnection()); + if (relayMessages instanceof List) { + for (Object message : (List) relayMessages) { + if (message instanceof PluginMessage) { + PluginMessage plMsg = (PluginMessage) message; + String channel = plMsg.getTag(); + if (previousServerProtocol != -1) { + if (previousServerProtocol < ProtocolVersion.v1_13.getId() + && protocolId >= ProtocolVersion.v1_13.getId()) { + channel = InventoryPackets.getNewPluginChannelId(channel); + if (channel.equals("minecraft:register")) { + String[] channels = new String(plMsg.getData(), StandardCharsets.UTF_8).split("\0"); + for (int i = 0; i < channels.length; i++) { + channels[i] = InventoryPackets.getNewPluginChannelId(channels[i]); + } + plMsg.setData(Joiner.on('\0').join(channels).getBytes(StandardCharsets.UTF_8)); + } + } else if (previousServerProtocol >= ProtocolVersion.v1_13.getId() + && protocolId < ProtocolVersion.v1_13.getId()) { + channel = InventoryPackets.getOldPluginChannelId(channel); + if (channel.equals("REGISTER")) { + String[] channels = new String(plMsg.getData(), StandardCharsets.UTF_8).split("\0"); + for (int i = 0; i < channels.length; i++) { + channels[i] = InventoryPackets.getOldPluginChannelId(channels[i]); + } + plMsg.setData(Joiner.on('\0').join(channels).getBytes(StandardCharsets.UTF_8)); + } + } + } + plMsg.setTag(channel); + } else { + Via.getPlatform().getLogger().warning("relayMessages contains a element that isn't a Handshake " + message); + } + } + } else { + Via.getPlatform().getLogger().warning("relayMessages isn't a List! " + relayMessages); + } + user.put(info); user.put(storage); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java index 448d277d9..ede670f54 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java @@ -415,7 +415,8 @@ public class Protocol1_13To1_12_2 extends Protocol { } if (Via.getConfig().is1_13TeamColourFix()) { - colour = getLastColor(prefix); + colour = getLastColor(prefix).ordinal(); + suffix = getLastColor(prefix).toString() + suffix; } wrapper.write(Type.VAR_INT, colour); @@ -844,7 +845,7 @@ public class Protocol1_13To1_12_2 extends Protocol { } // Based on method from https://github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/ChatColor.java - public int getLastColor(String input) { + public ChatColor getLastColor(String input) { int length = input.length(); for (int index = length - 1; index > -1; index--) { @@ -863,12 +864,12 @@ public class Protocol1_13To1_12_2 extends Protocol { case RESET: break; default: - return color.ordinal(); + return color; } } } } - return ChatColor.RESET.ordinal(); + return ChatColor.RESET; } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java index 8ab9f565e..7ddd1688b 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java @@ -596,9 +596,13 @@ public class InventoryPackets { case "wdl:request": return "WDL|REQUEST"; default: - return newId.startsWith("viaversion:legacy/") + return newId.startsWith("viaversion:legacy/") // Our format :) ? new String(BaseEncoding.base32().lowerCase().withPadChar('-').decode( newId.substring(18)), StandardCharsets.UTF_8) + : newId.startsWith("legacy:") + ? newId.substring(7) // Rewrite BungeeCord's format. It will only prevent kicks, plugins will still be broken because of case-sensitivity *plays sad violin* + : newId.startsWith("bungeecord:legacy/") + ? newId.substring(18) : newId; } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/WorldPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/WorldPackets.java index 917e8754e..8b762f8e3 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/WorldPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/WorldPackets.java @@ -26,9 +26,34 @@ import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type; import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; public class WorldPackets { + private static final Set validBiomes = new HashSet<>(); + + static { + // Client will crash if it receives a invalid biome id + for (int i = 0; i < 50; i++) { + validBiomes.add(i); + } + validBiomes.add(127); + for (int i = 129; i <= 134; i++) { + validBiomes.add(i); + } + validBiomes.add(140); + validBiomes.add(149); + validBiomes.add(151); + for (int i = 155; i <= 158; i++) { + validBiomes.add(i); + } + for (int i = 160; i <= 167; i++) { + validBiomes.add(i); + } + } + public static void register(Protocol protocol) { // Outgoing packets @@ -246,9 +271,17 @@ public class WorldPackets { // Rewrite biome id 255 to plains if (chunk.isBiomeData()) { + int latestBiomeWarn = Integer.MIN_VALUE; for (int i = 0; i < 256; i++) { - if (chunk.getBiomeData()[i] == -1) - chunk.getBiomeData()[i] = 1; + int biome = chunk.getBiomeData()[i] & 0xFF; + if (!validBiomes.contains(biome)) { + if (biome != 255 // is it generated naturally? *shrug* + && latestBiomeWarn != biome) { + Via.getPlatform().getLogger().warning("Received invalid biome id " + biome); + latestBiomeWarn = biome; + } + chunk.getBiomeData()[i] = 1; // Plains + } } }