refactoring: ProtocolDecoder
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
package mc.protocol.codec;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import mc.protocol.NettyAttributes;
|
||||||
|
import mc.protocol.State;
|
||||||
|
import mc.protocol.io.NetByteBuf;
|
||||||
|
import mc.protocol.packets.ClientSidePacket;
|
||||||
|
import mc.protocol.pool.PacketObjectPool;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class ProtocolDecoder extends ByteToMessageDecoder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||||
|
State state = ctx.channel().attr(NettyAttributes.STATE).get();
|
||||||
|
NetByteBuf netByteBuf = new NetByteBuf(in);
|
||||||
|
|
||||||
|
int packetId = netByteBuf.readVarInt();
|
||||||
|
Class<? extends ClientSidePacket> packetClass = state.getClientSidePacketById(packetId);
|
||||||
|
if (packetClass == null) {
|
||||||
|
log.warn("Unknown packet: State {} ; Id 0x{}", state, packetIdAsHexcode(packetId));
|
||||||
|
netByteBuf.skipBytes(netByteBuf.readableBytes());
|
||||||
|
} else {
|
||||||
|
ClientSidePacket packet = PacketObjectPool.getInstance().getPool(packetClass).borrowObject();
|
||||||
|
packet.readSelf(netByteBuf);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("IN: {}:{}", state, packet);
|
||||||
|
}
|
||||||
|
out.add(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String packetIdAsHexcode(int packetId) {
|
||||||
|
String hexPacketId = Integer.toHexString(packetId).toUpperCase();
|
||||||
|
if (hexPacketId.length() == 1) hexPacketId = "0" + hexPacketId;
|
||||||
|
|
||||||
|
return hexPacketId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package mc.protocol.pool;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import mc.protocol.packets.ClientSidePacket;
|
||||||
|
import mc.utils.pool.WideClassObjectPool;
|
||||||
|
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class PacketObjectPool extends WideClassObjectPool<ClientSidePacket> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static final PacketObjectPool instance = new PacketObjectPool();
|
||||||
|
}
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package mc.protocol.io.codec;
|
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import mc.protocol.NettyConnectionContext;
|
|
||||||
import mc.protocol.NetworkAttributes;
|
|
||||||
import mc.protocol.State;
|
|
||||||
import mc.protocol.api.ConnectionContext;
|
|
||||||
import mc.protocol.io.NetByteBuf;
|
|
||||||
import mc.protocol.packets.ClientSidePacket;
|
|
||||||
import mc.protocol.packets.UnknownPacket;
|
|
||||||
import mc.protocol.pool.PacketPool;
|
|
||||||
import org.apache.commons.pool2.ObjectPool;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Slf4j
|
|
||||||
public class ProtocolDecoder extends ByteToMessageDecoder {
|
|
||||||
|
|
||||||
private final boolean readUnknownPackets;
|
|
||||||
private final ObjectPool<NettyConnectionContext> poolNettyConnectionContext;
|
|
||||||
private final PacketPool poolPackets;
|
|
||||||
|
|
||||||
@Setter
|
|
||||||
private Consumer<ConnectionContext> consumerNewConnection;
|
|
||||||
@Setter
|
|
||||||
private Consumer<ConnectionContext> consumerDisconnect;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelActive(@Nonnull ChannelHandlerContext ctx) throws Exception {
|
|
||||||
ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).set(new HashMap<>());
|
|
||||||
|
|
||||||
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
|
||||||
consumerNewConnection.accept(context);
|
|
||||||
|
|
||||||
poolNettyConnectionContext.returnObject(context);
|
|
||||||
super.channelActive(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelInactive(@Nonnull ChannelHandlerContext ctx) throws Exception {
|
|
||||||
NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx);
|
|
||||||
consumerDisconnect.accept(context);
|
|
||||||
|
|
||||||
ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get().clear();
|
|
||||||
ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).set(null);
|
|
||||||
|
|
||||||
poolNettyConnectionContext.returnObject(context);
|
|
||||||
super.channelInactive(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
|
||||||
State state = Objects.requireNonNull(ctx.channel().attr(NetworkAttributes.STATE).get());
|
|
||||||
NetByteBuf netByteBuf = new NetByteBuf(in);
|
|
||||||
|
|
||||||
int packetId = netByteBuf.readVarInt();
|
|
||||||
Class<? extends ClientSidePacket> packetClass = state.getClientSidePacketById(packetId);
|
|
||||||
if (packetClass == null) {
|
|
||||||
log.warn("Unknown packet: State {} ; Id 0x{}", state, packetIdAsHexcode(packetId));
|
|
||||||
|
|
||||||
if (readUnknownPackets) {
|
|
||||||
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 = poolPackets.borrowObject(packetClass);
|
|
||||||
packet.readSelf(netByteBuf);
|
|
||||||
log.debug("IN: {}:{}", state, packet);
|
|
||||||
out.add(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String packetIdAsHexcode(int packetId) {
|
|
||||||
String hexPacketId = Integer.toHexString(packetId).toUpperCase();
|
|
||||||
if (hexPacketId.length() == 1) hexPacketId = "0" + hexPacketId;
|
|
||||||
|
|
||||||
return hexPacketId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package mc.protocol.pool;
|
|
||||||
|
|
||||||
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<P extends ClientSidePacket> extends BasePooledObjectFactory<P> {
|
|
||||||
|
|
||||||
private final Class<P> clazz;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public P create() throws Exception {
|
|
||||||
return clazz.getDeclaredConstructor().newInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PooledObject<P> wrap(P packet) {
|
|
||||||
return new DefaultPooledObject<>(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void passivateObject(PooledObject<P> pooledPacket) {
|
|
||||||
pooledPacket.getObject().passivate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package mc.protocol.pool;
|
|
||||||
|
|
||||||
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<Class<? extends ClientSidePacket>, ObjectPool> mapPoolPackets;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <P extends ClientSidePacket> P borrowObject(Class<P> packetClass) throws Exception {
|
|
||||||
return (P) mapPoolPackets.get(packetClass).borrowObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <P extends ClientSidePacket> void returnObject(P packet) throws Exception {
|
|
||||||
mapPoolPackets.get(packet.getClass()).returnObject(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,17 +8,17 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public class WideClassObjectPool {
|
public abstract class WideClassObjectPool<T extends Passivable> {
|
||||||
|
|
||||||
private final Map<Class, ObjectPool> mapPool = new HashMap<>();
|
private final Map<Class, ObjectPool> mapPool = new HashMap<>();
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public <R extends Passivable> ObjectPool<R> getPool(Class<R> clazz) {
|
public <R extends T> ObjectPool<R> getPool(Class<R> clazz) {
|
||||||
return mapPool.computeIfAbsent(clazz, tClass -> new GenericObjectPool<R>(new WideClassFactory(clazz)));
|
return mapPool.computeIfAbsent(clazz, tClass -> new GenericObjectPool<R>(new WideClassFactory(clazz)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
private static class WideClassFactory<R extends Passivable> extends PassivablePooledObjectFactory<R> {
|
private class WideClassFactory<R extends T> extends PassivablePooledObjectFactory<R> {
|
||||||
|
|
||||||
private final Class<R> clazz;
|
private final Class<R> clazz;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user