From 257eea5b044bdd0af71c198eb53832927374d963 Mon Sep 17 00:00:00 2001 From: creeper123123321 <7974274+creeper123123321@users.noreply.github.com> Date: Wed, 25 Aug 2021 09:55:43 -0300 Subject: [PATCH] try to fix GoLilyPad servers (#2667) Closes ViaVersion/ViaFabric#21 --- .../protocol1_9to1_8/Protocol1_9To1_8.java | 8 +- .../packets/PlayerPackets.java | 451 ++++++++---------- .../providers/CompressionProvider.java | 153 ++++++ 3 files changed, 360 insertions(+), 252 deletions(-) create mode 100644 common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/providers/CompressionProvider.java diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/Protocol1_9To1_8.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/Protocol1_9To1_8.java index 6d995f3df..644c8a47a 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/Protocol1_9To1_8.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/Protocol1_9To1_8.java @@ -38,12 +38,7 @@ import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.InventoryPac import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.PlayerPackets; import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.SpawnPackets; import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.WorldPackets; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.BossBarProvider; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.CommandBlockProvider; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.EntityIdProvider; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.HandItemProvider; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MainHandProvider; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.*; import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.ClientChunks; import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.CommandBlockStorage; import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.EntityTracker1_9; @@ -141,6 +136,7 @@ public class Protocol1_9To1_8 extends AbstractProtocol { + try { + JsonObject obj = (JsonObject) wrapper.get(Type.COMPONENT, 0); + ChatRewriter.toClient(obj, wrapper.user()); + } catch (Exception e) { + e.printStackTrace(); } }); } @@ -79,13 +77,10 @@ public class PlayerPackets { public void registerMap() { map(Type.VAR_INT); // 0 - Action // We only handle if the title or subtitle is set then just write through. - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - int action = wrapper.get(Type.VAR_INT, 0); - if (action == 0 || action == 1) { - Protocol1_9To1_8.FIX_JSON.write(wrapper, wrapper.read(Type.STRING)); - } + handler(wrapper -> { + int action = wrapper.get(Type.VAR_INT, 0); + if (action == 0 || action == 1) { + Protocol1_9To1_8.FIX_JSON.write(wrapper, wrapper.read(Type.STRING)); } }); // Everything else is handled. @@ -104,11 +99,8 @@ public class PlayerPackets { map(Type.BYTE); // 5 - Player Flags - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) { - wrapper.write(Type.VAR_INT, 0); // 6 - Teleport ID was added - } + handler(wrapper -> { + wrapper.write(Type.VAR_INT, 0); // 6 - Teleport ID was added }); } }); @@ -118,59 +110,56 @@ public class PlayerPackets { public void registerMap() { map(Type.STRING); // 0 - Team Name map(Type.BYTE); // 1 - Mode - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - byte mode = wrapper.get(Type.BYTE, 0); // Mode - if (mode == 0 || mode == 2) { - wrapper.passthrough(Type.STRING); // Display Name - wrapper.passthrough(Type.STRING); // Prefix - wrapper.passthrough(Type.STRING); // Suffix + handler(wrapper -> { + byte mode = wrapper.get(Type.BYTE, 0); // Mode + if (mode == 0 || mode == 2) { + wrapper.passthrough(Type.STRING); // Display Name + wrapper.passthrough(Type.STRING); // Prefix + wrapper.passthrough(Type.STRING); // Suffix - wrapper.passthrough(Type.BYTE); // Friendly Fire + wrapper.passthrough(Type.BYTE); // Friendly Fire - wrapper.passthrough(Type.STRING); // Name tag visibility + wrapper.passthrough(Type.STRING); // Name tag visibility - wrapper.write(Type.STRING, Via.getConfig().isPreventCollision() ? "never" : ""); + wrapper.write(Type.STRING, Via.getConfig().isPreventCollision() ? "never" : ""); - wrapper.passthrough(Type.BYTE); // Colour - } + wrapper.passthrough(Type.BYTE); // Colour + } - if (mode == 0 || mode == 3 || mode == 4) { - String[] players = wrapper.passthrough(Type.STRING_ARRAY); // Players - final EntityTracker1_9 entityTracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - String myName = wrapper.user().getProtocolInfo().getUsername(); - String teamName = wrapper.get(Type.STRING, 0); - for (String player : players) { - if (entityTracker.isAutoTeam() && player.equalsIgnoreCase(myName)) { - if (mode == 4) { - // since removing add to auto team - // Workaround for packet order issue - wrapper.send(Protocol1_9To1_8.class); - wrapper.cancel(); - entityTracker.sendTeamPacket(true, true); - entityTracker.setCurrentTeam("viaversion"); - } else { - // since adding remove from auto team - entityTracker.sendTeamPacket(false, true); - entityTracker.setCurrentTeam(teamName); - } + if (mode == 0 || mode == 3 || mode == 4) { + String[] players = wrapper.passthrough(Type.STRING_ARRAY); // Players + final EntityTracker1_9 entityTracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + String myName = wrapper.user().getProtocolInfo().getUsername(); + String teamName = wrapper.get(Type.STRING, 0); + for (String player : players) { + if (entityTracker.isAutoTeam() && player.equalsIgnoreCase(myName)) { + if (mode == 4) { + // since removing add to auto team + // Workaround for packet order issue + wrapper.send(Protocol1_9To1_8.class); + wrapper.cancel(); + entityTracker.sendTeamPacket(true, true); + entityTracker.setCurrentTeam("viaversion"); + } else { + // since adding remove from auto team + entityTracker.sendTeamPacket(false, true); + entityTracker.setCurrentTeam(teamName); } } } + } - if (mode == 1) { // Remove team - final EntityTracker1_9 entityTracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - String teamName = wrapper.get(Type.STRING, 0); - if (entityTracker.isAutoTeam() - && teamName.equals(entityTracker.getCurrentTeam())) { - // team was removed - // Workaround for packet order issue - wrapper.send(Protocol1_9To1_8.class); - wrapper.cancel(); - entityTracker.sendTeamPacket(true, true); - entityTracker.setCurrentTeam("viaversion"); - } + if (mode == 1) { // Remove team + final EntityTracker1_9 entityTracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + String teamName = wrapper.get(Type.STRING, 0); + if (entityTracker.isAutoTeam() + && teamName.equals(entityTracker.getCurrentTeam())) { + // team was removed + // Workaround for packet order issue + wrapper.send(Protocol1_9To1_8.class); + wrapper.cancel(); + entityTracker.sendTeamPacket(true, true); + entityTracker.setCurrentTeam("viaversion"); } } }); @@ -182,14 +171,11 @@ public class PlayerPackets { public void registerMap() { map(Type.INT); // 0 - Player ID // Parse this info - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - int entityId = wrapper.get(Type.INT, 0); - EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - tracker.addEntity(entityId, Entity1_10Types.EntityType.PLAYER); - tracker.setClientEntityId(entityId); - } + handler(wrapper -> { + int entityId = wrapper.get(Type.INT, 0); + EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + tracker.addEntity(entityId, Entity1_10Types.EntityType.PLAYER); + tracker.setClientEntityId(entityId); }); map(Type.UNSIGNED_BYTE); // 1 - Player Gamemode map(Type.BYTE); // 2 - Player Dimension @@ -198,39 +184,30 @@ public class PlayerPackets { map(Type.STRING); // 5 - Level Type map(Type.BOOLEAN); // 6 - Reduced Debug info - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - tracker.setGameMode(GameMode.getById(wrapper.get(Type.UNSIGNED_BYTE, 0))); //Set player gamemode - } + handler(wrapper -> { + EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + tracker.setGameMode(GameMode.getById(wrapper.get(Type.UNSIGNED_BYTE, 0))); //Set player gamemode }); // Gotta fake their op - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - CommandBlockProvider provider = Via.getManager().getProviders().get(CommandBlockProvider.class); - provider.sendPermission(wrapper.user()); - } - } + handler(wrapper -> { + CommandBlockProvider provider = Via.getManager().getProviders().get(CommandBlockProvider.class); + provider.sendPermission(wrapper.user()); + } ); // Scoreboard will be cleared when join game is received - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - EntityTracker1_9 entityTracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - if (Via.getConfig().isAutoTeam()) { - entityTracker.setAutoTeam(true); - // Workaround for packet order issue - wrapper.send(Protocol1_9To1_8.class); - wrapper.cancel(); - entityTracker.sendTeamPacket(true, true); - entityTracker.setCurrentTeam("viaversion"); - } else { - entityTracker.setAutoTeam(false); - } + handler(wrapper -> { + EntityTracker1_9 entityTracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + if (Via.getConfig().isAutoTeam()) { + entityTracker.setAutoTeam(true); + // Workaround for packet order issue + wrapper.send(Protocol1_9To1_8.class); + wrapper.cancel(); + entityTracker.sendTeamPacket(true, true); + entityTracker.setCurrentTeam("viaversion"); + } else { + entityTracker.setAutoTeam(false); } }); } @@ -243,45 +220,41 @@ public class PlayerPackets { map(Type.VAR_INT); // 1 - Player Count // Due to this being a complex data structure we just use a handler. - handler(new PacketHandler() { + handler(wrapper -> { + int action = wrapper.get(Type.VAR_INT, 0); + int count = wrapper.get(Type.VAR_INT, 1); + for (int i = 0; i < count; i++) { + wrapper.passthrough(Type.UUID); // Player UUID + if (action == 0) { // add player + wrapper.passthrough(Type.STRING); // Player Name - @Override - public void handle(PacketWrapper wrapper) throws Exception { - int action = wrapper.get(Type.VAR_INT, 0); - int count = wrapper.get(Type.VAR_INT, 1); - for (int i = 0; i < count; i++) { - wrapper.passthrough(Type.UUID); // Player UUID - if (action == 0) { // add player - wrapper.passthrough(Type.STRING); // Player Name + int properties = wrapper.passthrough(Type.VAR_INT); - int properties = wrapper.passthrough(Type.VAR_INT); - - // loop through properties - for (int j = 0; j < properties; j++) { - wrapper.passthrough(Type.STRING); // name - wrapper.passthrough(Type.STRING); // value - boolean isSigned = wrapper.passthrough(Type.BOOLEAN); - if (isSigned) { - wrapper.passthrough(Type.STRING); // signature - } + // loop through properties + for (int j = 0; j < properties; j++) { + wrapper.passthrough(Type.STRING); // name + wrapper.passthrough(Type.STRING); // value + boolean isSigned = wrapper.passthrough(Type.BOOLEAN); + if (isSigned) { + wrapper.passthrough(Type.STRING); // signature } - - wrapper.passthrough(Type.VAR_INT); // gamemode - wrapper.passthrough(Type.VAR_INT); // ping - boolean hasDisplayName = wrapper.passthrough(Type.BOOLEAN); - if (hasDisplayName) { - Protocol1_9To1_8.FIX_JSON.write(wrapper, wrapper.read(Type.STRING)); // display name - } - } else if ((action == 1) || (action == 2)) { // update gamemode || update latency - wrapper.passthrough(Type.VAR_INT); - } else if (action == 3) { // update display name - boolean hasDisplayName = wrapper.passthrough(Type.BOOLEAN); - if (hasDisplayName) { - Protocol1_9To1_8.FIX_JSON.write(wrapper, wrapper.read(Type.STRING)); // display name - } - } else if (action == 4) { // remove player - // no fields } + + wrapper.passthrough(Type.VAR_INT); // gamemode + wrapper.passthrough(Type.VAR_INT); // ping + boolean hasDisplayName = wrapper.passthrough(Type.BOOLEAN); + if (hasDisplayName) { + Protocol1_9To1_8.FIX_JSON.write(wrapper, wrapper.read(Type.STRING)); // display name + } + } else if ((action == 1) || (action == 2)) { // update gamemode || update latency + wrapper.passthrough(Type.VAR_INT); + } else if (action == 3) { // update display name + boolean hasDisplayName = wrapper.passthrough(Type.BOOLEAN); + if (hasDisplayName) { + Protocol1_9To1_8.FIX_JSON.write(wrapper, wrapper.read(Type.STRING)); // display name + } + } else if (action == 4) { // remove player + // no fields } } }); @@ -292,38 +265,35 @@ public class PlayerPackets { @Override public void registerMap() { map(Type.STRING); // 0 - Channel Name - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - String name = wrapper.get(Type.STRING, 0); - if (name.equalsIgnoreCase("MC|BOpen")) { - wrapper.read(Type.REMAINING_BYTES); // Not used anymore - wrapper.write(Type.VAR_INT, 0); - } - if (name.equalsIgnoreCase("MC|TrList")) { - wrapper.passthrough(Type.INT); // ID + handler(wrapper -> { + String name = wrapper.get(Type.STRING, 0); + if (name.equalsIgnoreCase("MC|BOpen")) { + wrapper.read(Type.REMAINING_BYTES); // Not used anymore + wrapper.write(Type.VAR_INT, 0); + } + if (name.equalsIgnoreCase("MC|TrList")) { + wrapper.passthrough(Type.INT); // ID - Short size = wrapper.passthrough(Type.UNSIGNED_BYTE); + Short size = wrapper.passthrough(Type.UNSIGNED_BYTE); - for (int i = 0; i < size; ++i) { - Item item1 = wrapper.passthrough(Type.ITEM); - ItemRewriter.toClient(item1); + for (int i = 0; i < size; ++i) { + Item item1 = wrapper.passthrough(Type.ITEM); + ItemRewriter.toClient(item1); - Item item2 = wrapper.passthrough(Type.ITEM); - ItemRewriter.toClient(item2); + Item item2 = wrapper.passthrough(Type.ITEM); + ItemRewriter.toClient(item2); - boolean present = wrapper.passthrough(Type.BOOLEAN); + boolean present = wrapper.passthrough(Type.BOOLEAN); - if (present) { - Item item3 = wrapper.passthrough(Type.ITEM); - ItemRewriter.toClient(item3); - } - - wrapper.passthrough(Type.BOOLEAN); - - wrapper.passthrough(Type.INT); - wrapper.passthrough(Type.INT); + if (present) { + Item item3 = wrapper.passthrough(Type.ITEM); + ItemRewriter.toClient(item3); } + + wrapper.passthrough(Type.BOOLEAN); + + wrapper.passthrough(Type.INT); + wrapper.passthrough(Type.INT); } } }); @@ -334,16 +304,13 @@ public class PlayerPackets { @Override public void registerMap() { map(Type.FLOAT); // 0 - Health - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - float health = wrapper.get(Type.FLOAT, 0); - if (health <= 0) { - // Client unloads chunks on respawn, take note - ClientChunks cc = wrapper.user().get(ClientChunks.class); - cc.getBulkChunks().clear(); - cc.getLoadedChunks().clear(); - } + handler(wrapper -> { + float health = wrapper.get(Type.FLOAT, 0); + if (health <= 0) { + // Client unloads chunks on respawn, take note + ClientChunks cc = wrapper.user().get(ClientChunks.class); + cc.getBulkChunks().clear(); + cc.getLoadedChunks().clear(); } }); } @@ -357,28 +324,22 @@ public class PlayerPackets { map(Type.UNSIGNED_BYTE); // 2 - GameMode map(Type.STRING); // 3 - Level Type - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - // Client unloads chunks on respawn, take note - ClientChunks cc = wrapper.user().get(ClientChunks.class); - cc.getBulkChunks().clear(); - cc.getLoadedChunks().clear(); + handler(wrapper -> { + // Client unloads chunks on respawn, take note + ClientChunks cc = wrapper.user().get(ClientChunks.class); + cc.getBulkChunks().clear(); + cc.getLoadedChunks().clear(); - int gamemode = wrapper.get(Type.UNSIGNED_BYTE, 0); - EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - tracker.setGameMode(GameMode.getById(gamemode)); - } + int gamemode = wrapper.get(Type.UNSIGNED_BYTE, 0); + EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + tracker.setGameMode(GameMode.getById(gamemode)); }); // Fake permissions to get Commandblocks working - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - CommandBlockProvider provider = Via.getManager().getProviders().get(CommandBlockProvider.class); - provider.sendPermission(wrapper.user()); - provider.unloadChunks(wrapper.user()); - } + handler(wrapper -> { + CommandBlockProvider provider = Via.getManager().getProviders().get(CommandBlockProvider.class); + provider.sendPermission(wrapper.user()); + provider.unloadChunks(wrapper.user()); }); } }); @@ -389,21 +350,28 @@ public class PlayerPackets { map(Type.UNSIGNED_BYTE); //0 - Reason map(Type.FLOAT); //1 - Value - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 3) { //Change gamemode - int gamemode = wrapper.get(Type.FLOAT, 0).intValue(); - EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - tracker.setGameMode(GameMode.getById(gamemode)); - } + handler(wrapper -> { + if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 3) { //Change gamemode + int gamemode = wrapper.get(Type.FLOAT, 0).intValue(); + EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + tracker.setGameMode(GameMode.getById(gamemode)); } }); } }); /* Removed packets */ - protocol.cancelClientbound(ClientboundPackets1_8.SET_COMPRESSION); + protocol.registerClientbound(ClientboundPackets1_8.SET_COMPRESSION, null, new PacketRemapper() { + @Override + public void registerMap() { + handler(wrapper -> { + wrapper.cancel(); + CompressionProvider provider = Via.getManager().getProviders().get(CompressionProvider.class); + + provider.handlePlayCompression(wrapper.user(), wrapper.read(Type.VAR_INT)); + }); + } + }); /* Incoming Packets */ @@ -424,21 +392,18 @@ public class PlayerPackets { map(Type.BOOLEAN); // 3 - If Chat Colours on map(Type.UNSIGNED_BYTE); // 4 - Skin Parts - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - int hand = wrapper.read(Type.VAR_INT); + handler(wrapper -> { + int hand = wrapper.read(Type.VAR_INT); - if (Via.getConfig().isLeftHandedHandling()) { - // Add 0x80 if left handed - if (hand == 0) wrapper.set(Type.UNSIGNED_BYTE, 0, - (short) (wrapper.get(Type.UNSIGNED_BYTE, 0).intValue() | 0x80) - ); - } - wrapper.sendToServer(Protocol1_9To1_8.class); - wrapper.cancel(); - Via.getManager().getProviders().get(MainHandProvider.class).setMainHand(wrapper.user(), hand); + if (Via.getConfig().isLeftHandedHandling()) { + // Add 0x80 if left handed + if (hand == 0) wrapper.set(Type.UNSIGNED_BYTE, 0, + (short) (wrapper.get(Type.UNSIGNED_BYTE, 0).intValue() | 0x80) + ); } + wrapper.sendToServer(Protocol1_9To1_8.class); + wrapper.cancel(); + Via.getManager().getProviders().get(MainHandProvider.class).setMainHand(wrapper.user(), hand); }); } }); @@ -458,31 +423,28 @@ public class PlayerPackets { @Override public void registerMap() { map(Type.STRING); // 0 - Channel Name - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - String name = wrapper.get(Type.STRING, 0); - if (name.equalsIgnoreCase("MC|BSign")) { - Item item = wrapper.passthrough(Type.ITEM); - if (item != null) { - item.setIdentifier(387); // Written Book - ItemRewriter.rewriteBookToServer(item); - } - } - if (name.equalsIgnoreCase("MC|AutoCmd")) { - wrapper.set(Type.STRING, 0, "MC|AdvCdm"); - wrapper.write(Type.BYTE, (byte) 0); - wrapper.passthrough(Type.INT); // X - wrapper.passthrough(Type.INT); // Y - wrapper.passthrough(Type.INT); // Z - wrapper.passthrough(Type.STRING); // Command - wrapper.passthrough(Type.BOOLEAN); // Flag - wrapper.clearInputBuffer(); - } - if (name.equalsIgnoreCase("MC|AdvCmd")) { - wrapper.set(Type.STRING, 0, "MC|AdvCdm"); + handler(wrapper -> { + String name = wrapper.get(Type.STRING, 0); + if (name.equalsIgnoreCase("MC|BSign")) { + Item item = wrapper.passthrough(Type.ITEM); + if (item != null) { + item.setIdentifier(387); // Written Book + ItemRewriter.rewriteBookToServer(item); } } + if (name.equalsIgnoreCase("MC|AutoCmd")) { + wrapper.set(Type.STRING, 0, "MC|AdvCdm"); + wrapper.write(Type.BYTE, (byte) 0); + wrapper.passthrough(Type.INT); // X + wrapper.passthrough(Type.INT); // Y + wrapper.passthrough(Type.INT); // Z + wrapper.passthrough(Type.STRING); // Command + wrapper.passthrough(Type.BOOLEAN); // Flag + wrapper.clearInputBuffer(); + } + if (name.equalsIgnoreCase("MC|AdvCmd")) { + wrapper.set(Type.STRING, 0, "MC|AdvCdm"); + } }); } }); @@ -491,19 +453,16 @@ public class PlayerPackets { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Action ID - handler(new PacketHandler() { - @Override - public void handle(PacketWrapper wrapper) throws Exception { - int action = wrapper.get(Type.VAR_INT, 0); - if (action == 2) { - // cancel any blocking >.> - EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); - if (tracker.isBlocking()) { - if (!Via.getConfig().isShowShieldWhenSwordInHand()) { - tracker.setSecondHand(null); - } - tracker.setBlocking(false); + handler(wrapper -> { + int action = wrapper.get(Type.VAR_INT, 0); + if (action == 2) { + // cancel any blocking >.> + EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); + if (tracker.isBlocking()) { + if (!Via.getConfig().isShowShieldWhenSwordInHand()) { + tracker.setSecondHand(null); } + tracker.setBlocking(false); } } }); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/providers/CompressionProvider.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/providers/CompressionProvider.java new file mode 100644 index 000000000..b8f60c9fd --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_9to1_8/providers/CompressionProvider.java @@ -0,0 +1,153 @@ +package com.viaversion.viaversion.protocols.protocol1_9to1_8.providers; + +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.connection.UserConnection; +import com.viaversion.viaversion.api.platform.providers.Provider; +import com.viaversion.viaversion.api.type.Type; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.handler.codec.DecoderException; +import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + +public class CompressionProvider implements Provider { + public void handlePlayCompression(UserConnection user, int threshold) { + if (!user.isClientSide()) throw new IllegalStateException("PLAY state Compression packet is unsupported"); + + ChannelPipeline pipe = user.getChannel().pipeline(); + + if (threshold < 0) { + if (pipe.get("compress") != null) { + pipe.remove("compress"); + pipe.remove("decompress"); + } + } else { + if (pipe.get("compress") == null) { + pipe.addBefore(Via.getManager().getInjector().getEncoderName(), "compress", getEncoder(threshold)); + pipe.addBefore(Via.getManager().getInjector().getDecoderName(), "decompress", getDecoder(threshold)); + } else { + ((CompressionHandler) pipe.get("compress")).setCompressionThreshold(threshold); + ((CompressionHandler) pipe.get("decompress")).setCompressionThreshold(threshold); + } + } + } + + protected CompressionHandler getEncoder(int threshold) { + return new Compressor(threshold); + } + + protected CompressionHandler getDecoder(int threshold) { + return new Decompressor(threshold); + } + + public interface CompressionHandler extends ChannelHandler { + void setCompressionThreshold(int threshold); + } + + private static class Decompressor extends MessageToMessageDecoder implements CompressionHandler { + // https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java + private final Inflater inflater; + private int threshold; + + public Decompressor(int var1) { + this.threshold = var1; + this.inflater = new Inflater(); + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + if (!in.isReadable()) return; + + int outLength = Type.VAR_INT.readPrimitive(in); + if (outLength == 0) { + out.add(in.readBytes(in.readableBytes())); + return; + } + + if (outLength < this.threshold) { + throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold); + } else if (outLength > 2097152) { + throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152); + } + + ByteBuf temp = in; + if (!in.hasArray()) { + temp = ctx.alloc().heapBuffer().writeBytes(in); + } else { + in.retain(); + } + ByteBuf output = ctx.alloc().heapBuffer(outLength, outLength); + try { + this.inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes()); + output.writerIndex(output.writerIndex() + this.inflater.inflate( + output.array(), output.arrayOffset(), outLength)); + out.add(output.retain()); + } finally { + output.release(); + temp.release(); + this.inflater.reset(); + } + } + + @Override + public void setCompressionThreshold(int threshold) { + this.threshold = threshold; + } + } + + private static class Compressor extends MessageToByteEncoder implements CompressionHandler { + // https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java + private final Deflater deflater; + private int threshold; + + public Compressor(int var1) { + this.threshold = var1; + this.deflater = new Deflater(); + } + + protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + int frameLength = in.readableBytes(); + if (frameLength < this.threshold) { + out.writeByte(0); // varint + out.writeBytes(in); + return; + } + + Type.VAR_INT.writePrimitive(out, frameLength); + + ByteBuf temp = in; + if (!in.hasArray()) { + temp = ctx.alloc().heapBuffer().writeBytes(in); + } else { + in.retain(); + } + ByteBuf output = ctx.alloc().heapBuffer(); + try { + this.deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes()); + deflater.finish(); + + while (!deflater.finished()) { + output.ensureWritable(4096); + output.writerIndex(output.writerIndex() + this.deflater.deflate(output.array(), + output.arrayOffset() + output.writerIndex(), output.writableBytes())); + } + out.writeBytes(output); + } finally { + output.release(); + temp.release(); + this.deflater.reset(); + } + } + + @Override + public void setCompressionThreshold(int threshold) { + this.threshold = threshold; + } + } +}