Registering packet for more than one protocol version?

Discussion in 'BungeeCord Plugin Development' started by MrAndeos, Sep 9, 2018.

Thread Status:
Not open for further replies.
  1. Hello.
    I am trying to make a plugin, that will allow me to sniff the Player Position packets from client to server, in order to know the player's position from BungeeCord, I've achieved that, but only for one specific protocol version, but I need compatibility from 1.8 all the way up to 1.13.1, how I can like register a packet for more than one protocol version? Here is my register method:
    Code (Java):
    public static void registerPacket(DirectionData data, int protocolVersion, int packetID, Class<? extends Packet> packetClass) {
        try {
            Class<?> protocolMap = Class.forName("net.md_5.bungee.protocol.Protocol$ProtocolMapping");
            Method register = DirectionData.class.getDeclaredMethod("registerPacket", Class.class, Array.newInstance(protocolMap, 0).getClass());
            Method map = Protocol.class.getDeclaredMethod("map", int.class, int.class);
            register.setAccessible(true);
            map.setAccessible(true);
            Object packetMap = Array.newInstance(protocolMap, 1);
            Array.set(packetMap, 0, map.invoke(null, protocolVersion, packetID));
            register.invoke(data, packetClass, packetMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    And how I call this method in onEnable():
    Code (Java):
    // 1.8
    Utils.registerPacket(Protocol.GAME.TO_SERVER, 47, 0x04, PacketPlayerPosition.InPosition.class);
    Utils.registerPacket(Protocol.GAME.TO_SERVER, 47, 0x06, PacketPlayerPosition.InPositionAndLook.class);
    // 1.12.2
    Utils.registerPacket(Protocol.GAME.TO_SERVER, 340, 0x0D, PacketPlayerPosition.InPosition.class);
    Utils.registerPacket(Protocol.GAME.TO_SERVER, 340, 0x0E, PacketPlayerPosition.InPositionAndLook.class);
     
  2. ProxyServer.getInstance().getProtocolVersion()?
     
  3. Nope, this will only return me a protocol version number that the proxy server is running on, in this case, using the latest build of BungeeCord, it will be 401 for 1.13.1. Registering a packet with this protocol version will work, but only for 1.13.1 clients. I need to know how I can register this packet for all 1.8.x (47), 1.9 (107), 1.9.1 (108), 1.9.2 (109), 1.9.3, 1.9.4 (110), 1.10.x (210), 1.11 (315), 1.11.1, 1.11.2 (316), 1.12 (335), 1.12.1 (338), 1.12.2 (340), 1.13 (393) and 1.13.1 (401) protocol versions, since packet fields that i need to sniff (X, Feet Y, Z and Yaw, Pitch when packet is InPlayerPositionAndLook) doesn't change across all these versions, only packet ID changes.
     
  4. Simply add more entries into this array, like I did.
    Now, you obviously need to pass more data to the function, so you could create multiple functions that take multiple args, or make it accept an Integer... vararg.
     
  5. Thanks for reply, but I still can't get it to work, here is the new registerPacket method:
    Code (Java):
    public static void registerPacket(DirectionData data, LinkedHashMap<Integer, Integer> protocolAndPacketID, Class<? extends Packet> packetClass) {
        try {
            Class<?> protocolMap = Class.forName("net.md_5.bungee.protocol.Protocol$ProtocolMapping");
            Method register = DirectionData.class.getDeclaredMethod("registerPacket", Class.class, Array.newInstance(protocolMap, 0).getClass());
            Method map = Protocol.class.getDeclaredMethod("map", int.class, int.class);
            register.setAccessible(true);
            map.setAccessible(true);
            int size = protocolAndPacketID.size();
            Object packetMap = Array.newInstance(protocolMap, size);
            ArrayList<Integer> keys = new ArrayList<Integer>(protocolAndPacketID.keySet());
            for (int i = 0; i < size; i++) {
                int key = keys.get(i);
                int value = protocolAndPacketID.get(key);
                Array.set(packetMap, i, map.invoke(null, key, value));
            }
            register.invoke(data, packetClass, packetMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    And how I call it in onEnable():
    Code (Java):
    LinkedHashMap<Integer, Integer> inPositionMap = new LinkedHashMap<Integer, Integer>();
    inPositionMap.put(47, 0x04);
    inPositionMap.put(340, 0x0D);
    inPositionMap.put(401, 0x10);
    Utils.registerPacket(Protocol.GAME.TO_SERVER, inPositionMap, PacketPlayerPosition.InPosition.class);
    LinkedHashMap<Integer, Integer> inPositionAndLookMap = new LinkedHashMap<Integer, Integer>();
    inPositionAndLookMap.put(47, 0x06);
    inPositionAndLookMap.put(340, 0x0E);
    inPositionAndLookMap.put(401, 0x11);
    Utils.registerPacket(Protocol.GAME.TO_SERVER, inPositionAndLookMap, PacketPlayerPosition.InPositionAndLook.class);
    I can join the server from 1.8.8 client, but it kicks me immediately when I try to join from 1.12.2 or 1.13.1 client with this exception, like it did using the old method, when registering packet for more than one protocol version:
    Code (Java):
    DecoderException : java.lang.IndexOutOfBoundsException: readerIndex(9) + length(8) exceeds writerIndex(12): UnpooledSlicedByteBuf(ridx: 9, widx: 12, cap: 12/12, unwrapped: PooledUnsafeDirectByteBuf(ridx: 14, widx: 34, cap: 34)) @ io.netty.handler.codec.MessageToMessageDecoder:98
     
  6. I guess that the packet is read differently for different versions, and that your read method does not handle it.
    Post the whole stacktrace because we can't read your mind. Also post the read method for the packets.
     
  7. Stack trace:
    Code (Text):
    io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(9) + length(8) exceeds writerIndex(12): UnpooledSlicedByteBuf(ridx: 9, widx: 12, cap: 12/12, unwrapped: PooledUnsafeDirectByteBuf(ridx: 14, widx: 34, cap: 34))
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:98)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:297)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:413)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
        at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
        at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:808)
        at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:408)
        at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:308)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
        at java.lang.Thread.run(Thread.java:748)
    Caused by: java.lang.IndexOutOfBoundsException: readerIndex(9) + length(8) exceeds writerIndex(12): UnpooledSlicedByteBuf(ridx: 9, widx: 12, cap: 12/12, unwrapped: PooledUnsafeDirectByteBuf(ridx: 14, widx: 34, cap: 34))
        at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1405)
        at io.netty.buffer.AbstractByteBuf.readLong(AbstractByteBuf.java:812)
        at io.netty.buffer.AbstractByteBuf.readDouble(AbstractByteBuf.java:838)
        at pl.khc.bungee.packets.packet.client.PacketPlayerPosition$InPosition.read(PacketPlayerPosition.java:61)
        at net.md_5.bungee.protocol.MinecraftDecoder.decode(MinecraftDecoder.java:33)
        at net.md_5.bungee.protocol.MinecraftDecoder.decode(MinecraftDecoder.java:10)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88)
        ... 31 more
    Read method for PacketPlayerPosition.InPosition:
    Code (Java):
    @Override
    public void read(ByteBuf buf, Direction direction, int protocolVersion) {
        this.x = buf.readDouble();
        this.y = buf.readDouble();
        this.z = buf.readDouble();
        super.read(buf, direction, protocolVersion);
    }
    And for InPositionAndLook:
    Code (Java):
    @Override
    public void read(ByteBuf buf, Direction direction, int protocolVersion) {
        this.x = buf.readDouble();
        this.y = buf.readDouble();
        this.z = buf.readDouble();
        this.yaw = buf.readFloat();
        this.pitch = buf.readFloat();
        super.read(buf, direction, protocolVersion);
    }
     
  8. Bump, anyone can help please? I really need to get this to work. :(
     
Thread Status:
Not open for further replies.