@Override public void rewriteServerbound(ByteBuf packet, int oldId, int newId) { super.rewriteServerbound(packet, oldId, newId); // Special cases int readerIndex = packet.readerIndex(); int packetId = DefinedPacket.readVarInt(packet); int packetIdLength = packet.readerIndex() - readerIndex; if (packetId == 0x18 /* Spectate */) { UUID uuid = DefinedPacket.readUUID(packet); ProxiedPlayer player; if ((player = BungeeCord.getInstance().getPlayer(uuid)) != null) { int previous = packet.writerIndex(); packet.readerIndex(readerIndex); packet.writerIndex(readerIndex + packetIdLength); DefinedPacket.writeUUID( ((UserConnection) player).getPendingConnection().getOfflineId(), packet); packet.writerIndex(previous); } } packet.readerIndex(readerIndex); }
@Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { int size = DefinedPacket.readVarInt(in); if (size == 0) { out.add(in.slice().retain()); in.skipBytes(in.readableBytes()); } else { ByteBuf decompressed = ctx.alloc().directBuffer(); try { zlib.process(in, decompressed); Preconditions.checkState( decompressed.readableBytes() == size, "Decompressed packet size mismatch"); out.add(decompressed); decompressed = null; } finally { if (decompressed != null) { decompressed.release(); } } } }
@Override @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") public void rewriteClientbound(ByteBuf packet, int oldId, int newId) { super.rewriteClientbound(packet, oldId, newId); // Special cases int readerIndex = packet.readerIndex(); int packetId = DefinedPacket.readVarInt(packet); int packetIdLength = packet.readerIndex() - readerIndex; if (packetId == 0x0D /* Collect Item */) { DefinedPacket.readVarInt(packet); rewriteVarInt(packet, oldId, newId, packet.readerIndex()); } else if (packetId == 0x1B /* Attach Entity */) { rewriteInt(packet, oldId, newId, readerIndex + packetIdLength + 4); } else if (packetId == 0x13 /* Destroy Entities */) { int count = DefinedPacket.readVarInt(packet); int[] ids = new int[count]; for (int i = 0; i < count; i++) { ids[i] = DefinedPacket.readVarInt(packet); } packet.readerIndex(readerIndex + packetIdLength); packet.writerIndex(readerIndex + packetIdLength); DefinedPacket.writeVarInt(count, packet); for (int id : ids) { if (id == oldId) { id = newId; } else if (id == newId) { id = oldId; } DefinedPacket.writeVarInt(id, packet); } } else if (packetId == 0x0E /* Spawn Object */) { DefinedPacket.readVarInt(packet); int type = packet.readUnsignedByte(); if (type == 60 || type == 90) { packet.skipBytes(14); int position = packet.readerIndex(); int readId = packet.readInt(); int changedId = -1; if (readId == oldId) { packet.setInt(position, newId); changedId = newId; } else if (readId == newId) { packet.setInt(position, oldId); changedId = oldId; } if (changedId != -1) { if (changedId == 0 && readId != 0) { // Trim off the extra data packet.readerIndex(readerIndex); packet.writerIndex(packet.readableBytes() - 6); } else if (changedId != 0 && readId == 0) { // Add on the extra data packet.readerIndex(readerIndex); packet.capacity(packet.readableBytes() + 6); packet.writerIndex(packet.readableBytes() + 6); } } } } else if (packetId == 0x0C /* Spawn Player */) { DefinedPacket.readVarInt(packet); // Entity ID int idLength = packet.readerIndex() - readerIndex - packetIdLength; UUID uuid = DefinedPacket.readUUID(packet); ProxiedPlayer player; if ((player = BungeeCord.getInstance().getPlayerByOfflineUUID(uuid)) != null) { int previous = packet.writerIndex(); packet.readerIndex(readerIndex); packet.writerIndex(readerIndex + packetIdLength + idLength); DefinedPacket.writeUUID(player.getUniqueId(), packet); packet.writerIndex(previous); } } else if (packetId == 0x42 /* Combat Event */) { int event = packet.readUnsignedByte(); if (event == 1 /* End Combat*/) { DefinedPacket.readVarInt(packet); rewriteInt(packet, oldId, newId, packet.readerIndex()); } else if (event == 2 /* Entity Dead */) { int position = packet.readerIndex(); rewriteVarInt(packet, oldId, newId, packet.readerIndex()); packet.readerIndex(position); DefinedPacket.readVarInt(packet); rewriteInt(packet, oldId, newId, packet.readerIndex()); } } packet.readerIndex(readerIndex); }
@Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { if (protocolVersion < ProtocolConstants.MINECRAFT_SNAPSHOT) { Item item = items[0]; // Only one at a time writeString(item.displayName, buf); // TODO: Server unique only! buf.writeBoolean(action != Action.REMOVE_PLAYER); buf.writeShort(item.ping); } else { DefinedPacket.writeVarInt(action.ordinal(), buf); DefinedPacket.writeVarInt(items.length, buf); for (Item item : items) { DefinedPacket.writeUUID(item.uuid, buf); switch (action) { case ADD_PLAYER: DefinedPacket.writeString(item.username, buf); DefinedPacket.writeVarInt(item.properties.length, buf); for (String[] prop : item.properties) { DefinedPacket.writeString(prop[0], buf); DefinedPacket.writeString(prop[1], buf); if (prop.length >= 3) { buf.writeBoolean(true); DefinedPacket.writeString(prop[2], buf); } else { buf.writeBoolean(false); } } DefinedPacket.writeVarInt(item.gamemode, buf); DefinedPacket.writeVarInt(item.ping, buf); buf.writeBoolean(item.displayName != null); if (item.displayName != null) { DefinedPacket.writeString(item.displayName, buf); } break; case UPDATE_GAMEMODE: DefinedPacket.writeVarInt(item.gamemode, buf); break; case UPDATE_LATENCY: DefinedPacket.writeVarInt(item.ping, buf); break; case UPDATE_DISPLAY_NAME: buf.writeBoolean(item.displayName != null); if (item.displayName != null) { DefinedPacket.writeString(item.displayName, buf); } break; } } } }
@Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { if (protocolVersion < ProtocolConstants.MINECRAFT_SNAPSHOT) { items = new Item[1]; Item item = items[0] = new Item(); item.displayName = item.username = readString(buf); action = !buf.readBoolean() ? Action.REMOVE_PLAYER : Action.ADD_PLAYER; item.ping = buf.readShort(); } else { action = Action.values()[DefinedPacket.readVarInt(buf)]; items = new Item[DefinedPacket.readVarInt(buf)]; for (int i = 0; i < items.length; i++) { Item item = items[i] = new Item(); item.setUuid(DefinedPacket.readUUID(buf)); switch (action) { case ADD_PLAYER: item.username = DefinedPacket.readString(buf); item.properties = new String[DefinedPacket.readVarInt(buf)][]; for (int j = 0; j < item.properties.length; j++) { String name = DefinedPacket.readString(buf); String value = DefinedPacket.readString(buf); if (buf.readBoolean()) { item.properties[j] = new String[] {name, value, DefinedPacket.readString(buf)}; } else { item.properties[j] = new String[] {name, value}; } } item.gamemode = DefinedPacket.readVarInt(buf); item.ping = DefinedPacket.readVarInt(buf); if (buf.readBoolean()) { item.displayName = DefinedPacket.readString(buf); } break; case UPDATE_GAMEMODE: item.gamemode = DefinedPacket.readVarInt(buf); break; case UPDATE_LATENCY: item.ping = DefinedPacket.readVarInt(buf); break; case UPDATE_DISPLAY_NAME: if (buf.readBoolean()) { item.displayName = DefinedPacket.readString(buf); } } } } }