| package protocolsupport.protocol.pipeline.version; |
| |
| import java.io.IOException; |
| |
| import io.netty.buffer.ByteBuf; |
| import io.netty.channel.Channel; |
| import io.netty.channel.ChannelHandlerContext; |
| import net.minecraft.server.v1_10_R1.EnumProtocol; |
| import net.minecraft.server.v1_10_R1.EnumProtocolDirection; |
| import net.minecraft.server.v1_10_R1.Packet; |
| import net.minecraft.server.v1_10_R1.PacketListener; |
| import protocolsupport.api.ProtocolVersion; |
| import protocolsupport.api.unsafe.Connection; |
| import protocolsupport.protocol.packet.middle.ClientBoundMiddlePacket; |
| import protocolsupport.protocol.packet.middleimpl.PacketData; |
| import protocolsupport.protocol.pipeline.IPacketEncoder; |
| import protocolsupport.protocol.serializer.ChainedProtocolSupportPacketDataSerializer; |
| import protocolsupport.protocol.storage.LocalStorage; |
| import protocolsupport.protocol.storage.SharedStorage; |
| import protocolsupport.protocol.utils.registry.MiddleTransformerRegistry; |
| import protocolsupport.protocol.utils.registry.PacketIdTransformerRegistry; |
| import protocolsupport.protocol.utils.registry.MiddleTransformerRegistry.InitCallBack; |
| import protocolsupport.utils.netty.Allocator; |
| import protocolsupport.utils.netty.ChannelUtils; |
| import protocolsupport.utils.recyclable.RecyclableCollection; |
| |
| public abstract class AbstractPacketEncoder implements IPacketEncoder { |
| |
| protected final Connection connection; |
| protected final SharedStorage sharedstorage; |
| protected final LocalStorage storage = new LocalStorage(); |
| public AbstractPacketEncoder(Connection connection, SharedStorage storage) { |
| this.connection = connection; |
| this.sharedstorage = storage; |
| registry.setCallBack(new InitCallBack<ClientBoundMiddlePacket<RecyclableCollection<PacketData>>>() { |
| @Override |
| public void onInit(ClientBoundMiddlePacket<RecyclableCollection<PacketData>> object) { |
| object.setConnection(AbstractPacketEncoder.this.connection); |
| object.setSharedStorage(AbstractPacketEncoder.this.sharedstorage); |
| object.setLocalStorage(AbstractPacketEncoder.this.storage); |
| } |
| }); |
| varintPacketId = connection.getVersion().isAfterOrEq(ProtocolVersion.MINECRAFT_1_7_5); |
| } |
| |
| protected final MiddleTransformerRegistry<ClientBoundMiddlePacket<RecyclableCollection<PacketData>>> registry = new MiddleTransformerRegistry<>(); |
| protected static final PacketIdTransformerRegistry packetIdRegistry = new PacketIdTransformerRegistry(); |
| |
| private final ChainedProtocolSupportPacketDataSerializer middlebuffer = new ChainedProtocolSupportPacketDataSerializer(); |
| private final boolean varintPacketId; |
| |
| @Override |
| public void encode(ChannelHandlerContext ctx, Packet<PacketListener> packet, ByteBuf output) throws Exception { |
| Channel channel = ctx.channel(); |
| EnumProtocol currentProtocol = channel.attr(ChannelUtils.CURRENT_PROTOCOL_KEY).get(); |
| final Integer packetId = currentProtocol.a(EnumProtocolDirection.CLIENTBOUND, packet); |
| if (packetId == null) { |
| throw new IOException("Can't serialize unregistered packet " + packet.getClass().getName()); |
| } |
| ClientBoundMiddlePacket<RecyclableCollection<PacketData>> packetTransformer = registry.getTransformer(currentProtocol, packetId); |
| packet.b(middlebuffer.prepareNativeSerializer()); |
| packetTransformer.readFromServerData(middlebuffer); |
| packetTransformer.handle(); |
| try (RecyclableCollection<PacketData> data = packetTransformer.toData(connection.getVersion())) { |
| for (PacketData packetdata : data) { |
| ByteBuf senddata = Allocator.allocateBuffer(); |
| int newPacketId = packetIdRegistry.getNewPacketId(currentProtocol, packetdata.getPacketId()); |
| if (varintPacketId) { |
| ChannelUtils.writeVarInt(senddata, newPacketId); |
| } else { |
| senddata.writeByte(newPacketId); |
| } |
| senddata.writeBytes(packetdata); |
| ctx.write(senddata); |
| } |
| ctx.flush(); |
| } |
| } |
| |
| } |