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/protocol18w32ato1_13/MetadataRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/MetadataRewriter.java index ddddc130e..6cddfca16 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/MetadataRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/MetadataRewriter.java @@ -23,13 +23,13 @@ public class MetadataRewriter { } else if (metadata.getMetaType() == MetaType1_13.BlockID) { // Convert to new block id int data = (int) metadata.getValue(); - metadata.setValue(Protocol18w32aTO1_13.getMapBlockId(data)); + metadata.setValue(Protocol18w32aTO1_13.getNewBlockStateId(data)); } if (type == null) continue; if (type.isOrHasParent(Entity1_13Types.EntityType.MINECART_ABSTRACT) && metadata.getId() == 9) { // New block format int data = (int) metadata.getValue(); - metadata.setValue(Protocol18w32aTO1_13.getMapBlockId(data)); + metadata.setValue(Protocol18w32aTO1_13.getNewBlockStateId(data)); } if(type.is(EntityType.ITEM)){ diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/Protocol18w32aTO1_13.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/Protocol18w32aTO1_13.java index 1c98516a2..c398ce614 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/Protocol18w32aTO1_13.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/Protocol18w32aTO1_13.java @@ -2,6 +2,7 @@ package us.myles.ViaVersion.protocols.protocol18w32ato1_13; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketRemapper; @@ -30,7 +31,7 @@ public class Protocol18w32aTO1_13 extends Protocol { @Override public void handle(PacketWrapper wrapper) throws Exception { String s = wrapper.passthrough(Type.STRING); - if(s.length() > 256){ + if (s.length() > 256) { wrapper.cancel(); } } @@ -48,7 +49,7 @@ public class Protocol18w32aTO1_13 extends Protocol { @Override public void handle(PacketWrapper wrapper) throws Exception { int hand = wrapper.read(Type.VAR_INT); - if(hand == 1){ + if (hand == 1) { wrapper.cancel(); } } @@ -66,7 +67,7 @@ public class Protocol18w32aTO1_13 extends Protocol { @Override public void handle(PacketWrapper wrapper) throws Exception { int action = wrapper.get(Type.VAR_INT, 0); - if(action == 0){ + if (action == 0) { wrapper.passthrough(Type.STRING); wrapper.passthrough(Type.FLOAT); wrapper.passthrough(Type.VAR_INT); @@ -78,6 +79,76 @@ public class Protocol18w32aTO1_13 extends Protocol { }); } }); + + // Advancements + registerOutgoing(State.PLAY, 0x51, 0x51, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.passthrough(Type.BOOLEAN); // Reset/clear + int size = wrapper.passthrough(Type.VAR_INT); // Mapping size + + for (int i = 0; i < size; i++) { + wrapper.passthrough(Type.STRING); // Identifier + + // Parent + if (wrapper.passthrough(Type.BOOLEAN)) + wrapper.passthrough(Type.STRING); + + // Display data + if (wrapper.passthrough(Type.BOOLEAN)) { + wrapper.passthrough(Type.STRING); // Title + wrapper.passthrough(Type.STRING); // Description + Item icon = wrapper.passthrough(Type.FLAT_ITEM); + InventoryPackets.toClient(icon); + wrapper.passthrough(Type.VAR_INT); // Frame type + int flags = wrapper.passthrough(Type.INT); // Flags + if ((flags & 1) != 0) + wrapper.passthrough(Type.STRING); // Background texture + wrapper.passthrough(Type.FLOAT); // X + wrapper.passthrough(Type.FLOAT); // Y + } + + wrapper.passthrough(Type.STRING_ARRAY); // Criteria + + int arrayLength = wrapper.passthrough(Type.VAR_INT); + for (int array = 0; array < arrayLength; array++) { + wrapper.passthrough(Type.STRING_ARRAY); // String array + } + } + } + }); + } + }); + + registerOutgoing(State.PLAY, 0x55, 0x55, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int blockTagsSize = wrapper.read(Type.VAR_INT); // block tags + for (int i = 0; i < blockTagsSize; i++) { + wrapper.passthrough(Type.STRING); + Integer[] blocks = wrapper.passthrough(Type.VAR_INT_ARRAY); + for (int j = 0; j < blocks.length; j++) { + blocks[j] = getNewBlockId(blocks[j]); + } + } + int itemTagsSize = wrapper.read(Type.VAR_INT); // item tags + for (int i = 0; i < itemTagsSize; i++) { + wrapper.passthrough(Type.STRING); + Integer[] items = wrapper.passthrough(Type.VAR_INT_ARRAY); + for (int j = 0; j < items.length; j++) { + items[j] = InventoryPackets.getNewItemId(items[j]); + } + } + } + }); + } + }); } @Override @@ -88,7 +159,7 @@ public class Protocol18w32aTO1_13 extends Protocol { } - public static int getMapBlockId(int blockId) { + public static int getNewBlockStateId(int blockId) { if (blockId > 8573) { blockId += 17; } else if (blockId > 8463) { @@ -101,4 +172,12 @@ public class Protocol18w32aTO1_13 extends Protocol { return blockId; } + + public static int getNewBlockId(final int oldBlockId) { + int blockId = oldBlockId; + if (oldBlockId >= 561) { + blockId += 5; + } + return blockId; + } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/EntityPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/EntityPackets.java index 565eb6395..fc7e839e3 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/EntityPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/EntityPackets.java @@ -43,7 +43,7 @@ public class EntityPackets { if (entType != null) { if (entType.is(Entity1_13Types.EntityType.FALLING_BLOCK)) { int data = wrapper.get(Type.INT, 0); - wrapper.set(Type.INT, 0, Protocol18w32aTO1_13.getMapBlockId(data)); + wrapper.set(Type.INT, 0, Protocol18w32aTO1_13.getNewBlockStateId(data)); } } // Register Type ID diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/InventoryPackets.java index e92ad8bf5..367c8f7d9 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/InventoryPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/InventoryPackets.java @@ -118,15 +118,25 @@ public class InventoryPackets { public static void toClient(Item item) { if (item == null) return; - if(item.getId() >= 443){ - item.setId((short) (item.getId() + 5)); + item.setId((short) getNewItemId(item.getId())); + } + + public static int getNewItemId(int itemId) { + if (itemId >= 443) { + return itemId + 5; } + return itemId; } public static void toServer(Item item) { if (item == null) return; - if(item.getId() >= 448){ - item.setId((short) (item.getId() - 5)); + item.setId((short) getOldItemId(item.getId())); + } + + public static int getOldItemId(int newId) { + if (newId >= 448) { + return newId - 5; } + return newId; } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/WorldPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/WorldPackets.java index 12481f639..041e1e14e 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/WorldPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol18w32ato1_13/packets/WorldPackets.java @@ -26,18 +26,13 @@ public class WorldPackets { ClientWorld clientWorld = wrapper.user().get(ClientWorld.class); Chunk chunk = wrapper.passthrough(new Chunk1_13Type(clientWorld)); - for (int i = 0; i < chunk.getSections().length; i++) { - ChunkSection section = chunk.getSections()[i]; - if (section == null) - continue; - - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - int block = section.getBlock(x, y, z); - - section.setFlatBlock(x, y, z, Protocol18w32aTO1_13.getMapBlockId(block)); - } + for (ChunkSection section : chunk.getSections()) { + if (section != null) { + for (int i = 0; i < section.getPalette().size(); i++) { + section.getPalette().set( + i, + Protocol18w32aTO1_13.getNewBlockStateId(section.getPalette().get(i)) + ); } } } @@ -47,6 +42,23 @@ public class WorldPackets { } }); + // Block Action + protocol.registerOutgoing(State.PLAY, 0x0A, 0x0A, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION); // Location + map(Type.UNSIGNED_BYTE); // Action id + map(Type.UNSIGNED_BYTE); // Action param + map(Type.VAR_INT); // Block id - /!\ NOT BLOCK STATE + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.VAR_INT, 0, Protocol18w32aTO1_13.getNewBlockId(wrapper.get(Type.VAR_INT, 0))); + } + }); + } + }); + // Block Change protocol.registerOutgoing(State.PLAY, 0xB, 0xB, new PacketRemapper() { @Override @@ -58,7 +70,7 @@ public class WorldPackets { public void handle(PacketWrapper wrapper) throws Exception { int id = wrapper.get(Type.VAR_INT, 0); - wrapper.set(Type.VAR_INT, 0, Protocol18w32aTO1_13.getMapBlockId(id)); + wrapper.set(Type.VAR_INT, 0, Protocol18w32aTO1_13.getNewBlockStateId(id)); } }); } @@ -77,7 +89,29 @@ public class WorldPackets { // Convert ids for (BlockChangeRecord record : wrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0)) { int id = record.getBlockId(); - record.setBlockId(Protocol18w32aTO1_13.getMapBlockId(id)); + record.setBlockId(Protocol18w32aTO1_13.getNewBlockStateId(id)); + } + } + }); + } + }); + + // Effect packet + protocol.registerOutgoing(State.PLAY, 0x23, 0x23, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.INT); // Effect Id + map(Type.POSITION); // Location + map(Type.INT); // Data + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int id = wrapper.get(Type.INT, 0); + int data = wrapper.get(Type.INT, 1); + if (id == 1010) { // Play record + wrapper.set(Type.INT, 1, data = InventoryPackets.getNewItemId(data)); + } else if (id == 2001) { // Block break + block break sound + wrapper.set(Type.INT, 1, data = Protocol18w32aTO1_13.getNewBlockStateId(data)); } } }); @@ -140,7 +174,7 @@ public class WorldPackets { int id = wrapper.get(Type.INT, 0); if(id == 3 || id == 20){ int data = wrapper.passthrough(Type.VAR_INT); - wrapper.set(Type.VAR_INT, 0, Protocol18w32aTO1_13.getMapBlockId(data)); + wrapper.set(Type.VAR_INT, 0, Protocol18w32aTO1_13.getNewBlockStateId(data)); } } }); 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 + } } }