From b77d6b16e8a46458173542f1b7f936731834b699 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Tue, 4 May 2021 18:49:24 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=20Packet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs.gradle | 3 +- protocol/build.gradle | 1 + .../mc/protocol/PacketInboundHandler.java | 7 ++++- protocol/src/main/java/mc/protocol/State.java | 1 + .../java/mc/protocol/di/ProtocolModule.java | 30 ++++++++++++++++-- .../mc/protocol/io/codec/ProtocolDecoder.java | 11 +++++-- .../mc/protocol/packets/ClientSidePacket.java | 2 ++ .../java/mc/protocol/packets/EmptyPacket.java | 5 +++ .../java/mc/protocol/packets/PingPacket.java | 5 +++ .../mc/protocol/packets/UnknownPacket.java | 16 ++++++++-- .../client/CPlayerPositionAndLookPacket.java | 7 +++++ .../packets/client/ClientSettingsPacket.java | 10 ++++++ .../packets/client/HandshakePacket.java | 8 +++++ .../packets/client/LoginStartPacket.java | 5 +++ .../packets/client/PlayerLookPacket.java | 6 ++++ .../packets/client/PlayerPositionPacket.java | 6 ++++ .../packets/client/PluginMessagePacket.java | 6 ++++ .../packets/client/TeleportConfirmPacket.java | 5 +++ .../java/mc/protocol/utils/PacketFactory.java | 31 +++++++++++++++++++ .../java/mc/protocol/utils/PacketPool.java | 26 ++++++++++++++++ 20 files changed, 180 insertions(+), 11 deletions(-) create mode 100644 protocol/src/main/java/mc/protocol/utils/PacketFactory.java create mode 100644 protocol/src/main/java/mc/protocol/utils/PacketPool.java diff --git a/libs.gradle b/libs.gradle index 691322b..402450a 100644 --- a/libs.gradle +++ b/libs.gradle @@ -19,7 +19,8 @@ ext { yaml : 'org.yaml:snakeyaml:1.28', json : 'com.eclipsesource.minimal-json:minimal-json:0.9.5', ioutils : 'commons-io:commons-io:2.6', - jopt : 'net.sf.jopt-simple:jopt-simple:6.0-alpha-3' + jopt : 'net.sf.jopt-simple:jopt-simple:6.0-alpha-3', + objpool : 'org.apache.commons:commons-pool2:2.9.0' ] libs.logger = [ diff --git a/protocol/build.gradle b/protocol/build.gradle index 03ac861..9bcedb4 100644 --- a/protocol/build.gradle +++ b/protocol/build.gradle @@ -4,6 +4,7 @@ dependencies { api libs.netty api libs.reactor implementation libs.json + implementation libs.objpool testImplementation libs.lang3 } diff --git a/protocol/src/main/java/mc/protocol/PacketInboundHandler.java b/protocol/src/main/java/mc/protocol/PacketInboundHandler.java index a99fb4d..9ae31f1 100644 --- a/protocol/src/main/java/mc/protocol/PacketInboundHandler.java +++ b/protocol/src/main/java/mc/protocol/PacketInboundHandler.java @@ -4,19 +4,24 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import lombok.RequiredArgsConstructor; import mc.protocol.packets.ClientSidePacket; +import mc.protocol.utils.PacketPool; import reactor.core.publisher.Sinks; @RequiredArgsConstructor public class PacketInboundHandler extends SimpleChannelInboundHandler { + private final PacketPool poolPackets; + @SuppressWarnings("rawtypes") @Override - protected void channelRead0(ChannelHandlerContext ctx, ClientSidePacket packet) { + protected void channelRead0(ChannelHandlerContext ctx, ClientSidePacket packet) throws Exception { Sinks.Many packetSinks = ctx.channel().attr(NetworkAttributes.STATE) .get().getPacketSinks(packet.getClass()); if (packetSinks != null) { packetSinks.tryEmitNext(new ChannelContext<>(ctx, packet)); } + + poolPackets.returnObject(packet); } } diff --git a/protocol/src/main/java/mc/protocol/State.java b/protocol/src/main/java/mc/protocol/State.java index 180f4d7..5aba37b 100644 --- a/protocol/src/main/java/mc/protocol/State.java +++ b/protocol/src/main/java/mc/protocol/State.java @@ -80,6 +80,7 @@ public enum State { @Getter private final int id; + @Getter private final Map> clientSidePackets; private final Map, Integer> serverSidePackets; diff --git a/protocol/src/main/java/mc/protocol/di/ProtocolModule.java b/protocol/src/main/java/mc/protocol/di/ProtocolModule.java index 3e8a8df..3fee6b2 100644 --- a/protocol/src/main/java/mc/protocol/di/ProtocolModule.java +++ b/protocol/src/main/java/mc/protocol/di/ProtocolModule.java @@ -13,14 +13,23 @@ import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import mc.protocol.NettyServer; import mc.protocol.PacketInboundHandler; +import mc.protocol.State; import mc.protocol.io.codec.ProtocolDecoder; import mc.protocol.io.codec.ProtocolEncoder; import mc.protocol.io.codec.ProtocolSplitter; +import mc.protocol.packets.ClientSidePacket; +import mc.protocol.packets.UnknownPacket; +import mc.protocol.utils.PacketFactory; +import mc.protocol.utils.PacketPool; +import org.apache.commons.pool2.ObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPool; import javax.annotation.Nonnull; import javax.inject.Provider; import java.util.LinkedHashMap; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; @Module public class ProtocolModule { @@ -55,15 +64,30 @@ public class ProtocolModule { } @Provides - Map provideChannelHandlerMap() { + Map provideChannelHandlerMap(PacketPool packetPool) { Map map = new LinkedHashMap<>(); map.put("packet_splitter", new ProtocolSplitter()); map.put("logger", new LoggingHandler(LogLevel.DEBUG)); - map.put("packet_decoder", new ProtocolDecoder(true)); + map.put("packet_decoder", new ProtocolDecoder(true, packetPool)); map.put("packet_encoder", new ProtocolEncoder()); - map.put("packet_handler", new PacketInboundHandler()); + map.put("packet_handler", new PacketInboundHandler(packetPool)); return map; } + + @Provides + @ServerScope + @SuppressWarnings({ "rawtypes", "unchecked" }) + PacketPool providePacketPool() { + Map, ObjectPool> map = Stream.of(State.values()) + .flatMap(state -> state.getClientSidePackets().values().stream()) + .distinct() + .collect(Collectors.toMap( + packetClass -> packetClass, + packetClass -> new GenericObjectPool(new PacketFactory<>(packetClass)))); + map.put(UnknownPacket.class, new GenericObjectPool(new PacketFactory<>(UnknownPacket.class))); + + return new PacketPool(map); + } } diff --git a/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java b/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java index b7ee9d5..062bd8f 100644 --- a/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java +++ b/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java @@ -10,15 +10,17 @@ import mc.protocol.State; import mc.protocol.io.NetByteBuf; import mc.protocol.packets.ClientSidePacket; import mc.protocol.packets.UnknownPacket; +import mc.protocol.utils.PacketPool; import java.util.List; import java.util.Objects; -@Slf4j @RequiredArgsConstructor +@Slf4j public class ProtocolDecoder extends ByteToMessageDecoder { private final boolean readUnknownPackets; + private final PacketPool poolPackets; @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { @@ -43,14 +45,17 @@ public class ProtocolDecoder extends ByteToMessageDecoder { log.warn("Unknown packet: State {} ; Id 0x{}", state, packetIdAsHexcode(packetId)); if (readUnknownPackets) { - UnknownPacket unknownPacket = new UnknownPacket(state, packetId, netByteBuf.readableBytes()); + UnknownPacket unknownPacket = poolPackets.borrowObject(UnknownPacket.class); + unknownPacket.setState(state); + unknownPacket.setId(packetId); + unknownPacket.setDataSize(netByteBuf.readableBytes()); unknownPacket.readSelf(netByteBuf); out.add(unknownPacket); } else { netByteBuf.skipBytes(netByteBuf.readableBytes()); } } else { - ClientSidePacket packet = packetClass.getDeclaredConstructor().newInstance(); + ClientSidePacket packet = poolPackets.borrowObject(packetClass); packet.readSelf(netByteBuf); log.debug("IN: {}:{}", state, packet); out.add(packet); diff --git a/protocol/src/main/java/mc/protocol/packets/ClientSidePacket.java b/protocol/src/main/java/mc/protocol/packets/ClientSidePacket.java index 6629750..735a823 100644 --- a/protocol/src/main/java/mc/protocol/packets/ClientSidePacket.java +++ b/protocol/src/main/java/mc/protocol/packets/ClientSidePacket.java @@ -8,4 +8,6 @@ import mc.protocol.io.NetByteBuf; public interface ClientSidePacket extends Packet { void readSelf(NetByteBuf netByteBuf); + + void passivate(); } diff --git a/protocol/src/main/java/mc/protocol/packets/EmptyPacket.java b/protocol/src/main/java/mc/protocol/packets/EmptyPacket.java index 60c800f..0e3a740 100644 --- a/protocol/src/main/java/mc/protocol/packets/EmptyPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/EmptyPacket.java @@ -13,4 +13,9 @@ public abstract class EmptyPacket implements ClientSidePacket, ServerSidePacket public void writeSelf(NetByteBuf netByteBuf) { // empty } + + @Override + public void passivate() { + // pass + } } diff --git a/protocol/src/main/java/mc/protocol/packets/PingPacket.java b/protocol/src/main/java/mc/protocol/packets/PingPacket.java index f40b121..3b1ee48 100644 --- a/protocol/src/main/java/mc/protocol/packets/PingPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/PingPacket.java @@ -34,6 +34,11 @@ public class PingPacket implements ClientSidePacket, ServerSidePacket { payload = netByteBuf.readLong(); } + @Override + public void passivate() { + this.payload = null; + } + @Override public void writeSelf(NetByteBuf netByteBuf) { netByteBuf.writeLong(payload); diff --git a/protocol/src/main/java/mc/protocol/packets/UnknownPacket.java b/protocol/src/main/java/mc/protocol/packets/UnknownPacket.java index aef7b74..6722e5f 100644 --- a/protocol/src/main/java/mc/protocol/packets/UnknownPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/UnknownPacket.java @@ -1,17 +1,19 @@ package mc.protocol.packets; import lombok.Data; +import lombok.NoArgsConstructor; import lombok.ToString; import mc.protocol.State; import mc.protocol.io.NetByteBuf; +@NoArgsConstructor @Data @ToString(exclude = "rawData") public class UnknownPacket implements ClientSidePacket { - private final State state; - private final int id; - private final int dataSize; + private State state; + private int id; + private int dataSize; private byte[] rawData; @Override @@ -19,4 +21,12 @@ public class UnknownPacket implements ClientSidePacket { rawData = new byte[dataSize]; netByteBuf.readBytes(rawData); } + + @Override + public void passivate() { + this.state = null; + this.id = 0; + this.dataSize = 0; + this.rawData = null; + } } diff --git a/protocol/src/main/java/mc/protocol/packets/client/CPlayerPositionAndLookPacket.java b/protocol/src/main/java/mc/protocol/packets/client/CPlayerPositionAndLookPacket.java index ed5c002..d7be871 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/CPlayerPositionAndLookPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/CPlayerPositionAndLookPacket.java @@ -51,6 +51,13 @@ public class CPlayerPositionAndLookPacket implements ClientSidePacket { this.onGround = netByteBuf.readBoolean(); } + @Override + public void passivate() { + this.position = null; + this.look = null; + this.onGround = false; + } + public double getYPositionHead() { return this.position.getY() + 1.62f; } diff --git a/protocol/src/main/java/mc/protocol/packets/client/ClientSettingsPacket.java b/protocol/src/main/java/mc/protocol/packets/client/ClientSettingsPacket.java index 680db2c..b78dab3 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/ClientSettingsPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/ClientSettingsPacket.java @@ -64,6 +64,16 @@ public class ClientSettingsPacket implements ClientSidePacket { this.mainHand = MainHand.valueById(netByteBuf.readVarInt()); } + @Override + public void passivate() { + this.locale = null; + this.viewDistance = 0; + this.chatMode = null; + this.chatColors = false; + this.$displayedSkinPartsBitMask = 0; + this.mainHand = null; + } + public boolean isCapeEnabled() { return ($displayedSkinPartsBitMask & 0x01) > 0; } diff --git a/protocol/src/main/java/mc/protocol/packets/client/HandshakePacket.java b/protocol/src/main/java/mc/protocol/packets/client/HandshakePacket.java index ccb86b5..005c6b9 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/HandshakePacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/HandshakePacket.java @@ -47,4 +47,12 @@ public class HandshakePacket implements ClientSidePacket { nextState = State.getById(netByteBuf.readVarInt()); } + @Override + public void passivate() { + this.protocolVersion = 0; + this.host = null; + this.port = 0; + this.nextState = null; + } + } diff --git a/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java b/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java index 77775b6..0462715 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java @@ -34,4 +34,9 @@ public class LoginStartPacket implements ClientSidePacket { this.name = netByteBuf.readString(); } + @Override + public void passivate() { + this.name = null; + } + } diff --git a/protocol/src/main/java/mc/protocol/packets/client/PlayerLookPacket.java b/protocol/src/main/java/mc/protocol/packets/client/PlayerLookPacket.java index 0f6ec16..35568fa 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/PlayerLookPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/PlayerLookPacket.java @@ -39,4 +39,10 @@ public class PlayerLookPacket implements ClientSidePacket { this.onGround = netByteBuf.readBoolean(); } + + @Override + public void passivate() { + this.look = null; + this.onGround = false; + } } diff --git a/protocol/src/main/java/mc/protocol/packets/client/PlayerPositionPacket.java b/protocol/src/main/java/mc/protocol/packets/client/PlayerPositionPacket.java index abbc609..3be5633 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/PlayerPositionPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/PlayerPositionPacket.java @@ -43,6 +43,12 @@ public class PlayerPositionPacket implements ClientSidePacket { this.onGround = netByteBuf.readBoolean(); } + @Override + public void passivate() { + this.position = null; + this.onGround = false; + } + public double getYPositionHead() { return this.position.getY() + 1.62f; } diff --git a/protocol/src/main/java/mc/protocol/packets/client/PluginMessagePacket.java b/protocol/src/main/java/mc/protocol/packets/client/PluginMessagePacket.java index 622bd4e..2ae5ab0 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/PluginMessagePacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/PluginMessagePacket.java @@ -39,4 +39,10 @@ public class PluginMessagePacket implements ClientSidePacket { this.rawData = new byte[netByteBuf.readableBytes()]; netByteBuf.readBytes(this.rawData); } + + @Override + public void passivate() { + this.channelName = null; + this.rawData = null; + } } diff --git a/protocol/src/main/java/mc/protocol/packets/client/TeleportConfirmPacket.java b/protocol/src/main/java/mc/protocol/packets/client/TeleportConfirmPacket.java index eee3df4..fd120e9 100644 --- a/protocol/src/main/java/mc/protocol/packets/client/TeleportConfirmPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/client/TeleportConfirmPacket.java @@ -33,4 +33,9 @@ public class TeleportConfirmPacket implements ClientSidePacket { public void readSelf(NetByteBuf netByteBuf) { this.teleportId = netByteBuf.readVarInt(); } + + @Override + public void passivate() { + this.teleportId = 0; + } } diff --git a/protocol/src/main/java/mc/protocol/utils/PacketFactory.java b/protocol/src/main/java/mc/protocol/utils/PacketFactory.java new file mode 100644 index 0000000..4532257 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/utils/PacketFactory.java @@ -0,0 +1,31 @@ +package mc.protocol.utils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import mc.protocol.packets.ClientSidePacket; +import org.apache.commons.pool2.BasePooledObjectFactory; +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.impl.DefaultPooledObject; + +@Slf4j +@RequiredArgsConstructor +public class PacketFactory

extends BasePooledObjectFactory

{ + + private final Class

clazz; + + @Override + public P create() throws Exception { + log.info("Create {}", clazz); + return clazz.getDeclaredConstructor().newInstance(); + } + + @Override + public PooledObject

wrap(P packet) { + return new DefaultPooledObject<>(packet); + } + + @Override + public void passivateObject(PooledObject

pooledPacket) { + pooledPacket.getObject().passivate(); + } +} diff --git a/protocol/src/main/java/mc/protocol/utils/PacketPool.java b/protocol/src/main/java/mc/protocol/utils/PacketPool.java new file mode 100644 index 0000000..447d7c2 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/utils/PacketPool.java @@ -0,0 +1,26 @@ +package mc.protocol.utils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import mc.protocol.packets.ClientSidePacket; +import org.apache.commons.pool2.ObjectPool; + +import java.util.Map; + +@Slf4j +@RequiredArgsConstructor +public class PacketPool { + + @SuppressWarnings("rawtypes") + private final Map, ObjectPool> mapPoolPackets; + + @SuppressWarnings("unchecked") + public

P borrowObject(Class

packetClass) throws Exception { + return (P) mapPoolPackets.get(packetClass).borrowObject(); + } + + @SuppressWarnings("unchecked") + public

void returnObject(P packet) throws Exception { + mapPoolPackets.get(packet.getClass()).returnObject(packet); + } +}