refactoring
This commit is contained in:
@@ -1,85 +0,0 @@
|
||||
package mc.protocol;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import mc.protocol.api.ConnectionContext;
|
||||
import mc.protocol.packets.ServerSidePacket;
|
||||
import mc.protocol.pool.Passivable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@EqualsAndHashCode
|
||||
public class NettyConnectionContext implements ConnectionContext, Passivable {
|
||||
|
||||
@Accessors(chain = true)
|
||||
@Setter
|
||||
private ChannelHandlerContext ctx;
|
||||
|
||||
/**
|
||||
* @deprecated костыль
|
||||
*/
|
||||
@Deprecated
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean usedContext;
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
return ctx.channel().attr(NetworkAttributes.STATE).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(State state) {
|
||||
ctx.channel().attr(NetworkAttributes.STATE).set(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated костыль
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public <T> void setCustomProperty(String key, T value) {
|
||||
Map<String, Object> map = ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get();
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated костыль
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> Optional<T> getCustomProperty(String key, Class<T> classResult) {
|
||||
Map<String, Object> map = ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get();
|
||||
return (Optional<T>) Optional.ofNullable(map.getOrDefault(key, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(ServerSidePacket packet) {
|
||||
ctx.write(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendNow(ServerSidePacket packet) {
|
||||
ctx.writeAndFlush(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushSending() {
|
||||
ctx.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
ctx.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivate() {
|
||||
this.ctx = null;
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package mc.protocol;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.api.ConnectionContext;
|
||||
import mc.protocol.api.Server;
|
||||
import mc.protocol.event.EventBus;
|
||||
import mc.protocol.io.codec.ProtocolDecoder;
|
||||
import mc.protocol.io.codec.ProtocolEncoder;
|
||||
import mc.protocol.io.codec.ProtocolSplitter;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Provider;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class NettyServer implements Server {
|
||||
|
||||
private final Provider<ProtocolDecoder> protocolDecoderProvider;
|
||||
private final Provider<PacketInboundHandler> packetInboundHandlerProvider;
|
||||
private final EventBus eventBus;
|
||||
private Consumer<ConnectionContext> consumerNewConnection;
|
||||
private Consumer<ConnectionContext> consumerDisconnect;
|
||||
|
||||
@Override
|
||||
public void bind(String host, int port) {
|
||||
log.info("Network starting: {}:{}", host, port);
|
||||
|
||||
try {
|
||||
createServerBootstrap().bind(host, port).sync().channel().closeFuture().sync();
|
||||
} catch (InterruptedException e) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("{}: {}", e.getClass().getSimpleName(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewConnect(Consumer<ConnectionContext> consumer) {
|
||||
this.consumerNewConnection = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisonnect(Consumer<ConnectionContext> consumer) {
|
||||
this.consumerDisconnect = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("java:S2326") // Сонар, ты бредишь
|
||||
public <P extends ClientSidePacket> void listenPacket(State state, Class<P> packetClass, EventBus.EventHandler<P> eventHandler) {
|
||||
this.eventBus.subscribe(state, packetClass, eventHandler);
|
||||
}
|
||||
|
||||
private ServerBootstrap createServerBootstrap() {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
|
||||
bootstrap.group(new NioEventLoopGroup(1), new NioEventLoopGroup())
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(createChannelChannelInitializer());
|
||||
|
||||
return bootstrap;
|
||||
}
|
||||
|
||||
private ChannelInitializer<SocketChannel> createChannelChannelInitializer() {
|
||||
return new ChannelInitializer<>() {
|
||||
@Override
|
||||
protected void initChannel(@Nonnull SocketChannel socketChannel) {
|
||||
ChannelPipeline pipeline = socketChannel.pipeline();
|
||||
createChannelHandlerMap().forEach(pipeline::addLast);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Map<String, ChannelHandler> createChannelHandlerMap() {
|
||||
Map<String, ChannelHandler> map = new LinkedHashMap<>();
|
||||
|
||||
map.put("packet_splitter", new ProtocolSplitter());
|
||||
map.put("logger", new LoggingHandler(LogLevel.DEBUG));
|
||||
|
||||
ProtocolDecoder protocolDecoder = protocolDecoderProvider.get();
|
||||
protocolDecoder.setConsumerNewConnection(consumerNewConnection);
|
||||
protocolDecoder.setConsumerDisconnect(consumerDisconnect);
|
||||
map.put("packet_decoder", protocolDecoder);
|
||||
|
||||
map.put("packet_encoder", new ProtocolEncoder());
|
||||
map.put("packet_handler", packetInboundHandlerProvider.get());
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package mc.protocol.api;
|
||||
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.packets.ServerSidePacket;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ConnectionContext {
|
||||
|
||||
/**
|
||||
* @deprecated костыль
|
||||
*/
|
||||
@Deprecated
|
||||
void setUsedContext(boolean value);
|
||||
|
||||
/**
|
||||
* @deprecated костыль
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isUsedContext();
|
||||
|
||||
State getState();
|
||||
void setState(State state);
|
||||
|
||||
/**
|
||||
* @deprecated костыль
|
||||
*/
|
||||
@Deprecated
|
||||
<T> void setCustomProperty(String key, T value);
|
||||
|
||||
/**
|
||||
* @deprecated костыль
|
||||
*/
|
||||
@Deprecated
|
||||
<T> Optional<T> getCustomProperty(String key, Class<T> classResult);
|
||||
|
||||
void send(ServerSidePacket packet);
|
||||
void sendNow(ServerSidePacket packet);
|
||||
void flushSending();
|
||||
|
||||
void disconnect();
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package mc.protocol.api;
|
||||
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
import mc.protocol.event.EventBus;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface Server {
|
||||
|
||||
void bind(String host, int port);
|
||||
|
||||
void onNewConnect(Consumer<ConnectionContext> consumer);
|
||||
void onDisonnect(Consumer<ConnectionContext> consumer);
|
||||
|
||||
@SuppressWarnings("java:S2326") // Сонар, ты бредишь
|
||||
<P extends ClientSidePacket> void listenPacket(State state, Class<P> packetClass, EventBus.EventHandler<P> eventHandler);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package mc.protocol.di;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import mc.protocol.NettyConnectionContext;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
import mc.protocol.packets.UnknownPacket;
|
||||
import mc.protocol.pool.NettyConnectionContextFactory;
|
||||
import mc.protocol.pool.PacketFactory;
|
||||
import mc.protocol.pool.PacketPool;
|
||||
import org.apache.commons.pool2.ObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Module
|
||||
public class PoolModule {
|
||||
|
||||
@Provides
|
||||
@ServerScope
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
PacketPool providePacketPool() {
|
||||
Map<Class<? extends ClientSidePacket>, 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);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ServerScope
|
||||
ObjectPool<NettyConnectionContext> providePoolNettyConnectionContext() {
|
||||
return new GenericObjectPool<>(new NettyConnectionContextFactory());
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package mc.protocol.di;
|
||||
|
||||
import dagger.Component;
|
||||
import mc.protocol.api.Server;
|
||||
|
||||
@Component(modules = {
|
||||
ProtocolModule.class,
|
||||
PoolModule.class
|
||||
})
|
||||
@ServerScope
|
||||
public interface ProtocolComponent {
|
||||
|
||||
Server getServer();
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package mc.protocol.di;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.NettyConnectionContext;
|
||||
import mc.protocol.NettyServer;
|
||||
import mc.protocol.PacketInboundHandler;
|
||||
import mc.protocol.api.Server;
|
||||
import mc.protocol.event.EventBus;
|
||||
import mc.protocol.event.SimpleEventBus;
|
||||
import mc.protocol.io.codec.ProtocolDecoder;
|
||||
import mc.protocol.pool.PacketPool;
|
||||
import org.apache.commons.pool2.ObjectPool;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
@Module
|
||||
@RequiredArgsConstructor
|
||||
public class ProtocolModule {
|
||||
|
||||
private final boolean readUnknownPackets;
|
||||
|
||||
@Provides
|
||||
@ServerScope
|
||||
Server provideServer(
|
||||
Provider<ProtocolDecoder> protocolDecoderProvider,
|
||||
Provider<PacketInboundHandler> packetInboundHandlerProvider,
|
||||
EventBus eventBus
|
||||
) {
|
||||
return new NettyServer(protocolDecoderProvider, packetInboundHandlerProvider, eventBus);
|
||||
}
|
||||
|
||||
@Provides
|
||||
ProtocolDecoder provideProtocolDecoder(
|
||||
ObjectPool<NettyConnectionContext> poolNettyConnectionContext,
|
||||
PacketPool poolPackets
|
||||
) {
|
||||
return new ProtocolDecoder(readUnknownPackets, poolNettyConnectionContext, poolPackets);
|
||||
}
|
||||
|
||||
@Provides
|
||||
PacketInboundHandler providePacketInboundHandler(
|
||||
ObjectPool<NettyConnectionContext> poolNettyConnectionContext,
|
||||
PacketPool packetPool,
|
||||
EventBus eventBus
|
||||
) {
|
||||
return new PacketInboundHandler(poolNettyConnectionContext, packetPool, eventBus);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ServerScope
|
||||
EventBus provideEventBus() {
|
||||
return new SimpleEventBus();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package mc.protocol.di;
|
||||
|
||||
import javax.inject.Scope;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Scope
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ServerScope {
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package mc.protocol.event;
|
||||
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.api.ConnectionContext;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
|
||||
public interface EventBus {
|
||||
|
||||
<P extends ClientSidePacket> void subscribe(State state, Class<P> packetClass, EventHandler<P> eventHandler);
|
||||
|
||||
<P extends ClientSidePacket> void emit(State state, ConnectionContext channelContext, P packet);
|
||||
|
||||
@FunctionalInterface
|
||||
interface EventHandler<P extends ClientSidePacket> {
|
||||
void handle(ConnectionContext channelContext, P packet);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package mc.protocol.event;
|
||||
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.api.ConnectionContext;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
import mc.protocol.utils.Table;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class SimpleEventBus implements EventBus {
|
||||
|
||||
private final Table<State, Class<? extends ClientSidePacket>, EventHandler> table = new Table<>();
|
||||
|
||||
@Override
|
||||
public <P extends ClientSidePacket> void subscribe(State state, Class<P> packetClass, EventHandler<P> eventHandler) {
|
||||
table.put(state, packetClass, eventHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <P extends ClientSidePacket> void emit(State state, ConnectionContext channelContext, P packet) {
|
||||
EventHandler eventHandler = table.getColumnAndRow(state, packet.getClass());
|
||||
|
||||
if (eventHandler != null) {
|
||||
eventHandler.handle(channelContext, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
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 State state;
|
||||
private int id;
|
||||
private int dataSize;
|
||||
private byte[] rawData;
|
||||
|
||||
@Override
|
||||
public void readSelf(NetByteBuf netByteBuf) {
|
||||
rawData = new byte[dataSize];
|
||||
netByteBuf.readBytes(rawData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivate() {
|
||||
this.state = null;
|
||||
this.id = 0;
|
||||
this.dataSize = 0;
|
||||
this.rawData = null;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package mc.protocol.pool;
|
||||
|
||||
import mc.protocol.NettyConnectionContext;
|
||||
import org.apache.commons.pool2.BasePooledObjectFactory;
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
|
||||
public class NettyConnectionContextFactory extends BasePooledObjectFactory<NettyConnectionContext> {
|
||||
|
||||
@Override
|
||||
public NettyConnectionContext create() throws Exception {
|
||||
return new NettyConnectionContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledObject<NettyConnectionContext> wrap(NettyConnectionContext context) {
|
||||
return new DefaultPooledObject<>(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivateObject(PooledObject<NettyConnectionContext> pooledObj) {
|
||||
pooledObj.getObject().passivate();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package mc.protocol.world;
|
||||
|
||||
public interface Chunk {
|
||||
|
||||
int getX();
|
||||
int getZ();
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package mc.protocol.world;
|
||||
|
||||
import mc.protocol.model.Location;
|
||||
import mc.protocol.utils.LevelType;
|
||||
|
||||
public interface World {
|
||||
|
||||
LevelType getLevelType();
|
||||
|
||||
Location getSpawn();
|
||||
|
||||
Chunk getChunk(int x, int z);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package mc.protocol.model.text;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class TextTest {
|
||||
|
||||
@Test
|
||||
void contentTest() {
|
||||
Text actual;
|
||||
Text expected;
|
||||
|
||||
actual = Text.builder().append("123").build();
|
||||
expected = new Text(null, null, "123", null);
|
||||
assertEquals(expected, actual);
|
||||
|
||||
actual = Text.builder().append("123").append(Text.of("456")).build();
|
||||
expected = new Text(null, null, "123", List.of(Text.of("456")));
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package mc.protocol.serializer;
|
||||
|
||||
import mc.protocol.model.text.Text;
|
||||
import mc.protocol.model.text.TextColor;
|
||||
import mc.protocol.model.text.TextStyle;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class TextSerializerTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("paramsPlain")
|
||||
void fromPlain(String sample, Text expected) {
|
||||
Text actual = TextSerializer.fromPlain(sample);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<Arguments> paramsPlain() {
|
||||
return Stream.of(
|
||||
Arguments.of("text", Text.of("text")),
|
||||
Arguments.of("&&text", Text.of("&text")),
|
||||
Arguments.of("&ztext", Text.of("text")),
|
||||
Arguments.of("&4red_text", Text.of(TextColor.DARK_RED, "red_text")),
|
||||
Arguments.of("&l&4red_text", Text.of(TextColor.DARK_RED, TextStyle.BOLD, "red_text")),
|
||||
Arguments.of("&4&lred_text", Text.of(TextColor.DARK_RED, TextStyle.BOLD, "red_text")),
|
||||
|
||||
Arguments.of("&4red_text &eyellow_text", Text.builder()
|
||||
.color(TextColor.DARK_RED)
|
||||
.append("red_text ")
|
||||
.append(Text.of(TextColor.YELLOW, "yellow_text"))
|
||||
.build())
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user