refactoring
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
apply from: rootDir.toPath().resolve('logic.gradle').toFile()
|
||||
|
||||
dependencies {
|
||||
implementation project(':utils')
|
||||
api project(':utils')
|
||||
|
||||
implementation libs.netty.transport
|
||||
implementation libs.netty.codec
|
||||
|
||||
@@ -4,7 +4,7 @@ import io.netty.util.AttributeKey;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@UtilityClass
|
||||
public class NettyAttributes {
|
||||
public class ProtocolAttributes {
|
||||
|
||||
public static final AttributeKey<State> STATE = AttributeKey.newInstance("STATE");
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package mc.protocol.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
import mc.protocol.utils.Table;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class PacketProcessor {
|
||||
|
||||
private final Table<State, Class<? extends ClientSidePacket>, Handler> table = new Table<>();
|
||||
|
||||
public <P extends ClientSidePacket> PacketProcessor addHandler(State state, Class<P> packetClass, Handler<P> handler) {
|
||||
table.put(state, packetClass, handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <P extends ClientSidePacket> void process(State state, ChannelHandlerContext ctx, P packet) {
|
||||
Handler handler = table.getColumnAndRow(state, packet.getClass());
|
||||
|
||||
if (handler != null) {
|
||||
handler.handle(ctx, packet);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Handler<P extends ClientSidePacket> {
|
||||
void handle(ChannelHandlerContext ctx, P packet);
|
||||
}
|
||||
}
|
||||
@@ -4,23 +4,25 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.NettyAttributes;
|
||||
import mc.protocol.ProtocolAttributes;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class PacketInboundHandler extends SimpleChannelInboundHandler<ClientSidePacket> {
|
||||
public class ProtocolInboundHandler extends SimpleChannelInboundHandler<ClientSidePacket> {
|
||||
|
||||
private static final String CLIENT_FORCE_DISCONNECTED_IOEXCEPTION_MESSAGE_RU = "Программа на вашем хост-компьютере разорвала установленное подключение";
|
||||
|
||||
private final PacketProcessor packetProcessor;
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, ClientSidePacket packet) {
|
||||
State state = ctx.channel().attr(NettyAttributes.STATE).get();
|
||||
|
||||
//TODO process
|
||||
State state = Objects.requireNonNull(ctx.channel().attr(ProtocolAttributes.STATE).get());
|
||||
packetProcessor.process(state, ctx, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -4,20 +4,26 @@ 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.ProtocolAttributes;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.buffer.NetByteBuf;
|
||||
import mc.protocol.packets.ClientSidePacket;
|
||||
import mc.protocol.pool.PacketObjectPool;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
public class ProtocolDecoder extends ByteToMessageDecoder {
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
ctx.channel().attr(ProtocolAttributes.STATE).set(State.HANDSHAKING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
State state = ctx.channel().attr(NettyAttributes.STATE).get();
|
||||
State state = Objects.requireNonNull(ctx.channel().attr(ProtocolAttributes.STATE).get());
|
||||
NetByteBuf netByteBuf = new NetByteBuf(in);
|
||||
|
||||
int packetId = netByteBuf.readVarInt();
|
||||
|
||||
@@ -5,17 +5,19 @@ import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.NettyAttributes;
|
||||
import mc.protocol.ProtocolAttributes;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.buffer.NetByteBuf;
|
||||
import mc.protocol.packets.ServerSidePacket;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
public class ProtocolEncoder extends MessageToByteEncoder<ServerSidePacket> {
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ServerSidePacket packet, ByteBuf out) {
|
||||
State state = ctx.channel().attr(NettyAttributes.STATE).get();
|
||||
State state = Objects.requireNonNull(ctx.channel().attr(ProtocolAttributes.STATE).get());
|
||||
Integer packetId = state.getServerSidePacketId(packet.getClass());
|
||||
if (packetId == null) {
|
||||
log.error("Unknown send packet: State {} ; Class {}", state, packet.getClass());
|
||||
|
||||
@@ -24,9 +24,13 @@ application {
|
||||
|
||||
dependencies {
|
||||
implementation project(':cli-parser')
|
||||
implementation project(':protocol-new')
|
||||
|
||||
implementation libs.logger.logback
|
||||
implementation libs.hocon
|
||||
|
||||
implementation libs.netty.transport
|
||||
implementation libs.netty.handler
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
|
||||
@@ -8,9 +8,18 @@ import lombok.SneakyThrows;
|
||||
import mc.cliparser.CommandLine;
|
||||
import mc.cliparser.CommandLineParser;
|
||||
import mc.cliparser.Option;
|
||||
import mc.server.di.ConfigComponent;
|
||||
import mc.server.di.ConfigModule;
|
||||
import mc.server.di.DaggerConfigComponent;
|
||||
import mc.protocol.ProtocolAttributes;
|
||||
import mc.protocol.ProtocolConstant;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.handler.PacketProcessor;
|
||||
import mc.protocol.model.ServerInfo;
|
||||
import mc.protocol.model.ServerInfoSerializer;
|
||||
import mc.protocol.model.text.TextSerializer;
|
||||
import mc.protocol.packets.KeepAlivePacket;
|
||||
import mc.protocol.packets.handshaking.client.HandshakePacket;
|
||||
import mc.protocol.packets.status.client.StatusServerRequestPacket;
|
||||
import mc.protocol.packets.status.server.StatusServerResponse;
|
||||
import mc.server.di.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -22,6 +31,7 @@ import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Main {
|
||||
@@ -52,11 +62,11 @@ public class Main {
|
||||
commandLine.has(configOption) ? Paths.get(configOption.value()) : null);
|
||||
ConfigComponent configComponent = DaggerConfigComponent.builder()
|
||||
.configModule(configModule).build();
|
||||
Config config = configComponent.getConfig();
|
||||
//endregion
|
||||
|
||||
Logger log = LoggerFactory.getLogger("LAUNCHER");
|
||||
if (log.isDebugEnabled()) {
|
||||
Config config = configComponent.getConfig();
|
||||
log.debug("Logback config path: {}", logconfigOption.value() == null ? "(default)" : logconfigOption.value());
|
||||
log.debug("Config path: {}", configOption.value() == null ? "(default)" : configOption.value());
|
||||
|
||||
@@ -65,8 +75,18 @@ public class Main {
|
||||
.sorted()
|
||||
.forEach(log::debug);
|
||||
}
|
||||
|
||||
ServerComponent serverComponent = DaggerServerComponent.create();
|
||||
setupPacketProcessor(serverComponent, configComponent);
|
||||
|
||||
Config config = configComponent.getConfig();
|
||||
NettyServer server = serverComponent.getNettyServer();
|
||||
|
||||
log.info("Server starting: {}:{}", config.getString("server.host"), config.getInt("server.port"));
|
||||
server.start(config.getString("server.host"), config.getInt("server.port"));
|
||||
}
|
||||
|
||||
//TODO нужно продумать как этот метод сделать доступным для расширенных версий сервера
|
||||
/**
|
||||
* Перенастраиваем logback с учетом путей.
|
||||
* <p>По-умолчанию, logback пытается искать свои конфиги по заранее зашитым путям.
|
||||
@@ -94,4 +114,37 @@ public class Main {
|
||||
URL url = Objects.requireNonNull(Main.class.getResource("/logback-default.xml"));
|
||||
return Paths.get(url.toURI());
|
||||
}
|
||||
|
||||
private static void setupPacketProcessor(ServerComponent serverComponent, ConfigComponent configComponent) {
|
||||
PacketProcessor packetProcessor = serverComponent.getPacketProcessor();
|
||||
|
||||
packetProcessor.addHandler(State.HANDSHAKING, HandshakePacket.class,
|
||||
(ctx, packet) -> ctx.channel().attr(ProtocolAttributes.STATE).set(packet.getNextState()));
|
||||
|
||||
setupStatusPacketProcessor(packetProcessor, configComponent);
|
||||
}
|
||||
|
||||
private static void setupStatusPacketProcessor(PacketProcessor packetProcessor, ConfigComponent configComponent) {
|
||||
Config config = configComponent.getConfig();
|
||||
|
||||
packetProcessor
|
||||
.addHandler(State.STATUS, KeepAlivePacket.class, (ctx, packet) -> {
|
||||
ctx.writeAndFlush(packet);
|
||||
ctx.close();
|
||||
})
|
||||
.addHandler(State.STATUS, StatusServerRequestPacket.class, (ctx, packet) -> {
|
||||
ServerInfo serverInfo = new ServerInfo();
|
||||
serverInfo.version().name(ProtocolConstant.PROTOCOL_NAME);
|
||||
serverInfo.version().protocol(ProtocolConstant.PROTOCOL_NUMBER);
|
||||
serverInfo.players().max(config.getInt("players.max-online"));
|
||||
serverInfo.players().online(config.getInt("players.fake-online.value"));
|
||||
serverInfo.players().sample(Collections.emptyList());
|
||||
serverInfo.description(TextSerializer.fromPlain(config.getString("motd")));
|
||||
|
||||
StatusServerResponse response = new StatusServerResponse();
|
||||
response.setInfo(ServerInfoSerializer.toStringPlain(serverInfo));
|
||||
|
||||
ctx.writeAndFlush(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
55
server-new/src/main/java/mc/server/NettyServer.java
Normal file
55
server-new/src/main/java/mc/server/NettyServer.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package mc.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
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.handler.PacketProcessor;
|
||||
import mc.protocol.handler.ProtocolInboundHandler;
|
||||
import mc.protocol.handler.codec.ProtocolDecoder;
|
||||
import mc.protocol.handler.codec.ProtocolEncoder;
|
||||
import mc.protocol.handler.codec.ProtocolSplitter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class NettyServer {
|
||||
|
||||
private final PacketProcessor packetProcessor;
|
||||
|
||||
public void start(String host, int port) {
|
||||
try {
|
||||
createServerBootstrap().bind(host, port).sync().channel().closeFuture().sync();
|
||||
} catch (InterruptedException e) {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("{}: {}", e.getClass().getSimpleName(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ServerBootstrap createServerBootstrap() {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
|
||||
bootstrap.group(new NioEventLoopGroup(1), new NioEventLoopGroup())
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(@Nonnull SocketChannel socketChannel) {
|
||||
socketChannel.pipeline()
|
||||
.addLast("packet_splitter", new ProtocolSplitter())
|
||||
.addLast("logger", new LoggingHandler(LogLevel.DEBUG))
|
||||
.addLast("packet_decoder", new ProtocolDecoder())
|
||||
.addLast("packet_encoder", new ProtocolEncoder())
|
||||
.addLast("packet_handler", new ProtocolInboundHandler(packetProcessor));
|
||||
}
|
||||
});
|
||||
|
||||
return bootstrap;
|
||||
}
|
||||
}
|
||||
15
server-new/src/main/java/mc/server/di/ServerComponent.java
Normal file
15
server-new/src/main/java/mc/server/di/ServerComponent.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package mc.server.di;
|
||||
|
||||
import dagger.Component;
|
||||
import mc.protocol.handler.PacketProcessor;
|
||||
import mc.server.NettyServer;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Component(modules = ServerModule.class)
|
||||
@Singleton
|
||||
public interface ServerComponent {
|
||||
|
||||
PacketProcessor getPacketProcessor();
|
||||
NettyServer getNettyServer();
|
||||
}
|
||||
24
server-new/src/main/java/mc/server/di/ServerModule.java
Normal file
24
server-new/src/main/java/mc/server/di/ServerModule.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package mc.server.di;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import mc.protocol.handler.PacketProcessor;
|
||||
import mc.server.NettyServer;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Module
|
||||
public class ServerModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
PacketProcessor providePacketProcessor() {
|
||||
return new PacketProcessor();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
NettyServer provideNettyServer(PacketProcessor packetProcessor) {
|
||||
return new NettyServer(packetProcessor);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user