From b1f076936dfad87d8ed516f0d6be5a08da46e0b1 Mon Sep 17 00:00:00 2001 From: Lennart ten Wolde <0p1q9o2w@hotmail.nl> Date: Thu, 10 Mar 2016 12:38:33 +0100 Subject: [PATCH] Add chunk handler to netty pipeline. FIxes #48 --- .../ViaVersion/handlers/ViaChunkHandler.java | 53 +++++++++++++++++++ .../ViaVersion/handlers/ViaEncodeHandler.java | 32 ----------- .../handlers/ViaVersionInitializer.java | 2 + 3 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 src/main/java/us/myles/ViaVersion/handlers/ViaChunkHandler.java diff --git a/src/main/java/us/myles/ViaVersion/handlers/ViaChunkHandler.java b/src/main/java/us/myles/ViaVersion/handlers/ViaChunkHandler.java new file mode 100644 index 000000000..d3d73964d --- /dev/null +++ b/src/main/java/us/myles/ViaVersion/handlers/ViaChunkHandler.java @@ -0,0 +1,53 @@ +package us.myles.ViaVersion.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; +import us.myles.ViaVersion.ConnectionInfo; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +public class ViaChunkHandler extends MessageToMessageEncoder { + private final ConnectionInfo info; + + public ViaChunkHandler(ConnectionInfo info) { + this.info = info; + } + + @Override + protected void encode(ChannelHandlerContext ctx, Object o, List list) throws Exception { + // Split chunk bulk packet up in to single chunk packets before it reached the encoder. + // This will prevent issues with several plugins and other protocol handlers due to the chunk being sent twice. + // It also sends the chunk in the right order possible resolving some issues with added chunk/block/entity data. + if (!(o instanceof ByteBuf)) { + info.setLastPacket(o); + /* This transformer is more for fixing issues which we find hard at packet level :) */ + if(o.getClass().getName().endsWith("PacketPlayOutMapChunkBulk") && info.isActive()) { + final int[] locX = ReflectionUtil.get(o, "a", int[].class); + final int[] locZ = ReflectionUtil.get(o, "b", int[].class); + final Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World")); + Class mapChunk = ReflectionUtil.nms("PacketPlayOutMapChunk"); + final Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class); + for(int i = 0; i < locX.length; i++) { + int x = locX[i]; + int z = locZ[i]; + // world invoke function + try { + Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z); + Object packet = constructor.newInstance(chunk, true, 65535); + list.add(packet); + } catch(InstantiationException | InvocationTargetException | ClassNotFoundException | IllegalAccessException | NoSuchMethodException e) { + e.printStackTrace(); + } + } + + return; + } + } + + list.add(o); + } +} diff --git a/src/main/java/us/myles/ViaVersion/handlers/ViaEncodeHandler.java b/src/main/java/us/myles/ViaVersion/handlers/ViaEncodeHandler.java index 78b839ba5..c50145bbd 100644 --- a/src/main/java/us/myles/ViaVersion/handlers/ViaEncodeHandler.java +++ b/src/main/java/us/myles/ViaVersion/handlers/ViaEncodeHandler.java @@ -28,38 +28,6 @@ public class ViaEncodeHandler extends MessageToByteEncoder { protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception { // handle the packet type if (!(o instanceof ByteBuf)) { - info.setLastPacket(o); - /* This transformer is more for fixing issues which we find hard at packet level :) */ - if (o.getClass().getName().endsWith("PacketPlayOutMapChunkBulk") && info.isActive()) { - final int[] locX = ReflectionUtil.get(o, "a", int[].class); - final int[] locZ = ReflectionUtil.get(o, "b", int[].class); - - final Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World")); - Class mapChunk = ReflectionUtil.nms("PacketPlayOutMapChunk"); - final Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class); - Runnable chunks = new Runnable() { - - @Override - public void run() { - - for (int i = 0; i < locX.length; i++) { - int x = locX[i]; - int z = locZ[i]; - // world invoke function - try { - Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z); - Object packet = constructor.newInstance(chunk, true, 65535); - ctx.pipeline().writeAndFlush(packet); - } catch (InstantiationException | InvocationTargetException | ClassNotFoundException | IllegalAccessException | NoSuchMethodException e) { - e.printStackTrace(); - } - } - } - }; - chunks.run(); - bytebuf.clear(); - throw new CancelException(); - } // call minecraft encoder PacketUtil.callEncode(this.minecraftEncoder, ctx, o, bytebuf); } diff --git a/src/main/java/us/myles/ViaVersion/handlers/ViaVersionInitializer.java b/src/main/java/us/myles/ViaVersion/handlers/ViaVersionInitializer.java index a2b077a86..a73b67e8d 100644 --- a/src/main/java/us/myles/ViaVersion/handlers/ViaVersionInitializer.java +++ b/src/main/java/us/myles/ViaVersion/handlers/ViaVersionInitializer.java @@ -32,8 +32,10 @@ public class ViaVersionInitializer extends ChannelInitializer { // Add our transformers ViaEncodeHandler encoder = new ViaEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder")); ViaDecodeHandler decoder = new ViaDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder")); + ViaChunkHandler chunkHandler = new ViaChunkHandler(info); socketChannel.pipeline().replace("encoder", "encoder", encoder); socketChannel.pipeline().replace("decoder", "decoder", decoder); + socketChannel.pipeline().addAfter("packet_handler", "viaversion_chunk_handler", chunkHandler); } }