From 7494c3f92c1ef1c9d62b2cf79ba2abd31953bff4 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sat, 9 May 2020 22:28:43 +0300 Subject: [PATCH 1/7] dumb server --- build.gradle | 29 +++++++++ src/main/java/mc/server/Main.java | 10 ++- .../java/mc/server/config/NetworkModule.java | 63 +++++++++++++++++++ src/main/java/mc/server/network/Server.java | 6 ++ .../mc/server/network/impl/NettyServer.java | 29 +++++++++ 5 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 src/main/java/mc/server/config/NetworkModule.java create mode 100644 src/main/java/mc/server/network/Server.java create mode 100644 src/main/java/mc/server/network/impl/NettyServer.java diff --git a/build.gradle b/build.gradle index 0205135..e55d1f2 100644 --- a/build.gradle +++ b/build.gradle @@ -13,3 +13,32 @@ repositories { mavenLocal() mavenCentral() } + +ext { + slf4j_version = '1.7.30' + logback_version = '1.2.3' + + library = [ + guice: ['com.google.inject:guice:4.1.0'], + logger: ["ch.qos.logback:logback-core:$logback_version", + "ch.qos.logback:logback-classic:$logback_version"], + lombok: ['org.projectlombok:lombok:1.18.2'], + netty: ['io.netty:netty-all:4.1.22.Final'], + slf4j: ["org.slf4j:slf4j-api:$slf4j_version", + "org.slf4j:jcl-over-slf4j:$slf4j_version"], + ] +} + +dependencies { + /* LOGGER */ + implementation library.slf4j + implementation library.logger + + /* LOMBOK */ + annotationProcessor library.lombok + compileOnly library.lombok + + /* COMPONENTS */ + implementation library.guice + implementation library.netty +} \ No newline at end of file diff --git a/src/main/java/mc/server/Main.java b/src/main/java/mc/server/Main.java index 107397e..1ea7689 100644 --- a/src/main/java/mc/server/Main.java +++ b/src/main/java/mc/server/Main.java @@ -1,8 +1,16 @@ package mc.server; +import com.google.inject.Guice; +import com.google.inject.Injector; +import mc.server.config.NetworkModule; +import mc.server.network.Server; + public class Main { public static void main(String[] args) { - System.out.println("hello?"); + final Injector injector = Guice.createInjector(new NetworkModule()); + + final Server server = injector.getInstance(Server.class); + server.start("127.0.0.1", 25565); } } diff --git a/src/main/java/mc/server/config/NetworkModule.java b/src/main/java/mc/server/config/NetworkModule.java new file mode 100644 index 0000000..f6874f8 --- /dev/null +++ b/src/main/java/mc/server/config/NetworkModule.java @@ -0,0 +1,63 @@ +package mc.server.config; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import com.google.inject.name.Names; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LoggingHandler; +import mc.server.network.Server; +import mc.server.network.impl.NettyServer; + +import java.util.Collections; +import java.util.List; + +public class NetworkModule extends AbstractModule { + + @Override + protected void configure() { + bind(Server.class).to(NettyServer.class).in(Singleton.class); + bind(EventLoopGroup.class).annotatedWith(Names.named("bossGroup")).toInstance(new NioEventLoopGroup(1)); + bind(EventLoopGroup.class).annotatedWith(Names.named("workerGroup")).toInstance(new NioEventLoopGroup()); + } + + @Provides + @Singleton + ServerBootstrap serverBootstrap(@Named("bossGroup") EventLoopGroup bossGroup, + @Named("workerGroup") EventLoopGroup workerGroup, + ChannelInitializer channelChannelInitializer) { + ServerBootstrap bootstrap = new ServerBootstrap(); + + bootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .childHandler(channelChannelInitializer); + + return bootstrap; + } + + @Provides + @Singleton + ChannelInitializer channelChannelInitializer(List channelHandlerList) { + return new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) { + final ChannelPipeline pipeline = socketChannel.pipeline(); + channelHandlerList.forEach(pipeline::addLast); + } + }; + } + + @Provides + @Singleton + List channelHandlerList() { + return Collections.singletonList(new LoggingHandler()); + } +} diff --git a/src/main/java/mc/server/network/Server.java b/src/main/java/mc/server/network/Server.java new file mode 100644 index 0000000..4b08ccc --- /dev/null +++ b/src/main/java/mc/server/network/Server.java @@ -0,0 +1,6 @@ +package mc.server.network; + +public interface Server { + + void start(String host, int port); +} diff --git a/src/main/java/mc/server/network/impl/NettyServer.java b/src/main/java/mc/server/network/impl/NettyServer.java new file mode 100644 index 0000000..2b580ae --- /dev/null +++ b/src/main/java/mc/server/network/impl/NettyServer.java @@ -0,0 +1,29 @@ +package mc.server.network.impl; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import io.netty.bootstrap.ServerBootstrap; +import lombok.extern.slf4j.Slf4j; +import mc.server.network.Server; + + +@Slf4j +public class NettyServer implements Server { + + @Inject + private Provider serverBootstrapProvider; + + @Override + public void start(String host, int port) { + try { + log.info("Network starting: {}:{}", host, port); + serverBootstrapProvider.get() + .bind(host, port) + .sync().channel().closeFuture().sync(); + } catch (InterruptedException e) { + if (log.isTraceEnabled()) { + log.trace("{}: {}", e.getClass().getSimpleName(), e.getMessage(), e); + } + } + } +} From 95b858d47ce451cc92d6bffc355d984491ef77fa Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 10 May 2020 03:40:55 +0300 Subject: [PATCH 2/7] take server info and disconnect --- build.gradle | 1 + settings.gradle | 5 +- .../java/mc/server/config/NetworkModule.java | 54 ++++++++++------ .../network/impl/ChannelInitializer.java | 29 +++++++++ .../server/network/impl/NettyConstants.java | 12 ++++ .../network/impl/codec/PacketDecoder.java | 43 +++++++++++++ .../network/impl/codec/PacketEncoder.java | 24 ++++++++ .../network/impl/codec/PacketSplitter.java | 29 +++++++++ .../impl/handler/AbstractPacketHandler.java | 16 +++++ .../impl/handler/HandshakeHandler.java | 25 ++++++++ .../network/impl/handler/StatusHandler.java | 20 ++++++ .../impl/io/ByteBufNetInputStream.java | 61 +++++++++++++++++++ .../impl/io/ByteBufNetOutputStream.java | 47 ++++++++++++++ 13 files changed, 347 insertions(+), 19 deletions(-) create mode 100644 src/main/java/mc/server/network/impl/ChannelInitializer.java create mode 100644 src/main/java/mc/server/network/impl/NettyConstants.java create mode 100644 src/main/java/mc/server/network/impl/codec/PacketDecoder.java create mode 100644 src/main/java/mc/server/network/impl/codec/PacketEncoder.java create mode 100644 src/main/java/mc/server/network/impl/codec/PacketSplitter.java create mode 100644 src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java create mode 100644 src/main/java/mc/server/network/impl/handler/HandshakeHandler.java create mode 100644 src/main/java/mc/server/network/impl/handler/StatusHandler.java create mode 100644 src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java create mode 100644 src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java diff --git a/build.gradle b/build.gradle index e55d1f2..e540db7 100644 --- a/build.gradle +++ b/build.gradle @@ -41,4 +41,5 @@ dependencies { /* COMPONENTS */ implementation library.guice implementation library.netty + implementation project(':protocol') } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 766e691..f234c19 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,4 @@ -rootProject.name = projectName \ No newline at end of file +rootProject.name = projectName + +include ':protocol' +project(':protocol').projectDir = new File(settingsDir, '../mc-protocol') \ No newline at end of file diff --git a/src/main/java/mc/server/config/NetworkModule.java b/src/main/java/mc/server/config/NetworkModule.java index f6874f8..2fd4a47 100644 --- a/src/main/java/mc/server/config/NetworkModule.java +++ b/src/main/java/mc/server/config/NetworkModule.java @@ -1,24 +1,31 @@ package mc.server.config; import com.google.inject.AbstractModule; +import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.name.Named; import com.google.inject.name.Names; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LoggingHandler; +import mc.protocol.PacketDirection; +import mc.protocol.io.coder.ProtocolDecoder; +import mc.protocol.io.coder.ProtocolEncoder; +import mc.protocol.io.coder.ProtocolSplitter; import mc.server.network.Server; +import mc.server.network.impl.ChannelInitializer; import mc.server.network.impl.NettyServer; +import mc.server.network.impl.codec.PacketDecoder; +import mc.server.network.impl.codec.PacketEncoder; +import mc.server.network.impl.codec.PacketSplitter; +import mc.server.network.impl.handler.HandshakeHandler; -import java.util.Collections; -import java.util.List; +import java.util.HashMap; +import java.util.Map; public class NetworkModule extends AbstractModule { @@ -33,7 +40,7 @@ public class NetworkModule extends AbstractModule { @Singleton ServerBootstrap serverBootstrap(@Named("bossGroup") EventLoopGroup bossGroup, @Named("workerGroup") EventLoopGroup workerGroup, - ChannelInitializer channelChannelInitializer) { + ChannelInitializer channelChannelInitializer) { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) @@ -44,20 +51,31 @@ public class NetworkModule extends AbstractModule { } @Provides - @Singleton - ChannelInitializer channelChannelInitializer(List channelHandlerList) { - return new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel socketChannel) { - final ChannelPipeline pipeline = socketChannel.pipeline(); - channelHandlerList.forEach(pipeline::addLast); - } - }; + PacketSplitter packetSplitter() { + return new PacketSplitter(new ProtocolSplitter()); } @Provides - @Singleton - List channelHandlerList() { - return Collections.singletonList(new LoggingHandler()); + PacketDecoder packetDecoder() { + return new PacketDecoder(new ProtocolDecoder(PacketDirection.SERVER_BOUND)); + } + + @Provides + PacketEncoder packetEncoder() { + return new PacketEncoder(new ProtocolEncoder(PacketDirection.CLIENT_BOUND)); + } + + @Provides + @Named("channelHandlerMap") + Map channelHandlerMap(final Injector injector) { + final Map map = new HashMap<>(); + + map.put("logger", injector.getInstance(LoggingHandler.class)); + map.put("packet_splitter", injector.getInstance(PacketSplitter.class)); + map.put("packet_decoder", injector.getInstance(PacketDecoder.class)); + map.put("packet_encoder", injector.getInstance(PacketEncoder.class)); + map.put("handshake_handler", injector.getInstance(HandshakeHandler.class)); + + return map; } } diff --git a/src/main/java/mc/server/network/impl/ChannelInitializer.java b/src/main/java/mc/server/network/impl/ChannelInitializer.java new file mode 100644 index 0000000..28f1d50 --- /dev/null +++ b/src/main/java/mc/server/network/impl/ChannelInitializer.java @@ -0,0 +1,29 @@ +package mc.server.network.impl; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; + +import java.util.Map; + +@Singleton +public class ChannelInitializer extends io.netty.channel.ChannelInitializer { + + private final Provider> channelHandlerMapProvider; + + @Inject + public ChannelInitializer( + @Named("channelHandlerMap") Provider> channelHandlerMapProvider) { + this.channelHandlerMapProvider = channelHandlerMapProvider; + } + + @Override + protected void initChannel(SocketChannel socketChannel) { + final ChannelPipeline pipeline = socketChannel.pipeline(); + channelHandlerMapProvider.get().forEach(pipeline::addLast); + } +} diff --git a/src/main/java/mc/server/network/impl/NettyConstants.java b/src/main/java/mc/server/network/impl/NettyConstants.java new file mode 100644 index 0000000..17b8a16 --- /dev/null +++ b/src/main/java/mc/server/network/impl/NettyConstants.java @@ -0,0 +1,12 @@ +package mc.server.network.impl; + +import io.netty.util.AttributeKey; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import mc.protocol.State; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class NettyConstants { + + public static final AttributeKey ATTR_STATE = AttributeKey.newInstance("ATTR_STATE"); +} diff --git a/src/main/java/mc/server/network/impl/codec/PacketDecoder.java b/src/main/java/mc/server/network/impl/codec/PacketDecoder.java new file mode 100644 index 0000000..8d383af --- /dev/null +++ b/src/main/java/mc/server/network/impl/codec/PacketDecoder.java @@ -0,0 +1,43 @@ +package mc.server.network.impl.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import lombok.RequiredArgsConstructor; +import mc.protocol.Packet; +import mc.protocol.State; +import mc.protocol.io.coder.ProtocolDecoder; +import mc.server.network.impl.io.ByteBufNetInputStream; + +import java.util.List; +import java.util.Objects; + +import static mc.server.network.impl.NettyConstants.ATTR_STATE; + +@RequiredArgsConstructor +public class PacketDecoder extends ByteToMessageDecoder { + + private final ProtocolDecoder protocolDecoder; + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ctx.channel().attr(ATTR_STATE).set(State.HANDSHAKING); + super.channelActive(ctx); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + ctx.channel().attr(ATTR_STATE).set(null); + super.channelInactive(ctx); + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { + final State state = Objects.requireNonNull(ctx.channel().attr(ATTR_STATE).get()); + + final Packet packet = protocolDecoder.decode(state, new ByteBufNetInputStream(in)); + if (packet != null) { + out.add(packet); + } + } +} diff --git a/src/main/java/mc/server/network/impl/codec/PacketEncoder.java b/src/main/java/mc/server/network/impl/codec/PacketEncoder.java new file mode 100644 index 0000000..3e0fb7d --- /dev/null +++ b/src/main/java/mc/server/network/impl/codec/PacketEncoder.java @@ -0,0 +1,24 @@ +package mc.server.network.impl.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import lombok.RequiredArgsConstructor; +import mc.protocol.Packet; +import mc.protocol.State; +import mc.protocol.io.coder.ProtocolEncoder; +import mc.server.network.impl.io.ByteBufNetOutputStream; + +import static mc.server.network.impl.NettyConstants.ATTR_STATE; + +@RequiredArgsConstructor +public class PacketEncoder extends MessageToByteEncoder { + + private final ProtocolEncoder protocolEncoder; + + @Override + protected void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf out) { + final State state = ctx.channel().attr(ATTR_STATE).get(); + protocolEncoder.encode(state, packet, new ByteBufNetOutputStream(out)); + } +} diff --git a/src/main/java/mc/server/network/impl/codec/PacketSplitter.java b/src/main/java/mc/server/network/impl/codec/PacketSplitter.java new file mode 100644 index 0000000..6589c0a --- /dev/null +++ b/src/main/java/mc/server/network/impl/codec/PacketSplitter.java @@ -0,0 +1,29 @@ +package mc.server.network.impl.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import lombok.RequiredArgsConstructor; +import mc.protocol.io.NetInputStream; +import mc.protocol.io.coder.ProtocolSplitter; +import mc.server.network.impl.io.ByteBufNetInputStream; + +import java.util.List; + +@RequiredArgsConstructor +public class PacketSplitter extends ByteToMessageDecoder { + + private final ProtocolSplitter protocolSplitter; + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { + final NetInputStream netInputStream = protocolSplitter.split(new ByteBufNetInputStream(in)); + + if (netInputStream != null) { + byte[] buff = new byte[netInputStream.readableBytes()]; + netInputStream.readBytes(buff); + out.add(Unpooled.wrappedBuffer(buff)); + } + } +} diff --git a/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java b/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java new file mode 100644 index 0000000..8a4da37 --- /dev/null +++ b/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java @@ -0,0 +1,16 @@ +package mc.server.network.impl.handler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import mc.protocol.Packet; + +public abstract class AbstractPacketHandler

extends SimpleChannelInboundHandler { + + @SuppressWarnings("unchecked") + @Override + protected void channelRead0(ChannelHandlerContext ctx, Packet msg) throws Exception { + channelRead1(ctx, (P) msg); + } + + protected abstract void channelRead1(ChannelHandlerContext ctx, P packet) throws Exception; +} diff --git a/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java b/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java new file mode 100644 index 0000000..b980256 --- /dev/null +++ b/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java @@ -0,0 +1,25 @@ +package mc.server.network.impl.handler; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import io.netty.channel.ChannelHandlerContext; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import mc.protocol.handshake.client.HandshakePacket; + +import static mc.server.network.impl.NettyConstants.ATTR_STATE; + +@Slf4j +@RequiredArgsConstructor(onConstructor = @__({ @Inject })) +public class HandshakeHandler extends AbstractPacketHandler { + + private final Provider statusHandlerProvider; + + @Override + protected void channelRead1(ChannelHandlerContext ctx, HandshakePacket packet) { + log.info("{}", packet); + + ctx.channel().attr(ATTR_STATE).set(packet.getNextState()); + ctx.pipeline().replace("handshake_handler", "status_handler", statusHandlerProvider.get()); + } +} diff --git a/src/main/java/mc/server/network/impl/handler/StatusHandler.java b/src/main/java/mc/server/network/impl/handler/StatusHandler.java new file mode 100644 index 0000000..5fff44b --- /dev/null +++ b/src/main/java/mc/server/network/impl/handler/StatusHandler.java @@ -0,0 +1,20 @@ +package mc.server.network.impl.handler; + +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; +import mc.protocol.status.client.StatusServerRequest; +import mc.protocol.status.server.StatusServerResponse; + +@Slf4j +public class StatusHandler extends AbstractPacketHandler { + + @Override + protected void channelRead1(ChannelHandlerContext ctx, StatusServerRequest packet) { + log.info("{}", packet); + + StatusServerResponse response = new StatusServerResponse(); + response.setInfo("some info server text"); + + ctx.channel().writeAndFlush(response).channel().disconnect(); + } +} diff --git a/src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java b/src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java new file mode 100644 index 0000000..3ba8b98 --- /dev/null +++ b/src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java @@ -0,0 +1,61 @@ +package mc.server.network.impl.io; + +import io.netty.buffer.ByteBuf; +import lombok.RequiredArgsConstructor; +import mc.protocol.io.NetInputStream; + +@RequiredArgsConstructor +public class ByteBufNetInputStream extends NetInputStream { + + private final ByteBuf byteBuf; + + @Override + public void markReadIndex() { + byteBuf.markReaderIndex(); + } + + @Override + public void resetReadIndex() { + byteBuf.resetReaderIndex(); + } + + @Override + public int readableBytes() { + return byteBuf.readableBytes(); + } + + @Override + public byte readByte() { + return byteBuf.readByte(); + } + + @Override + public int readBytes(byte[] buffer, int offset, int lengtn) { + return byteBuf.readBytes(buffer, offset, lengtn).readableBytes(); + } + + @Override + public int readShort() { + return byteBuf.readShort(); + } + + @Override + public int readInt() { + return byteBuf.readInt(); + } + + @Override + public long readLong() { + return byteBuf.readLong(); + } + + @Override + public float readFloat() { + return byteBuf.readFloat(); + } + + @Override + public double readDouble() { + return byteBuf.readDouble(); + } +} diff --git a/src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java b/src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java new file mode 100644 index 0000000..badf014 --- /dev/null +++ b/src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java @@ -0,0 +1,47 @@ +package mc.server.network.impl.io; + +import io.netty.buffer.ByteBuf; +import lombok.RequiredArgsConstructor; +import mc.protocol.io.NetOutputStream; + +@RequiredArgsConstructor +public class ByteBufNetOutputStream extends NetOutputStream { + + private final ByteBuf byteBuf; + + @Override + public void writeByte(int value) { + byteBuf.writeByte(value); + } + + @Override + public void writeBytes(byte[] buffer, int offset, int lengtn) { + byteBuf.writeBytes(buffer, offset, lengtn); + } + + @Override + public void writeShort(int value) { + byteBuf.writeShort(value); + } + + @Override + public void writeInt(int value) { + byteBuf.writeInt(value); + } + + @Override + public void writeLong(long value) { + byteBuf.writeLong(value); + } + + @Override + public void writeFloat(float value) { + byteBuf.writeFloat(value); + } + + @Override + public void writeDouble(double value) { + byteBuf.writeDouble(value); + } +} + From da988b7172cce6f9c8916c9238a65d72158157b6 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 10 May 2020 03:46:42 +0300 Subject: [PATCH 3/7] optimize code --- .../java/mc/server/config/NetworkModule.java | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/main/java/mc/server/config/NetworkModule.java b/src/main/java/mc/server/config/NetworkModule.java index 2fd4a47..19c4b70 100644 --- a/src/main/java/mc/server/config/NetworkModule.java +++ b/src/main/java/mc/server/config/NetworkModule.java @@ -1,7 +1,6 @@ package mc.server.config; import com.google.inject.AbstractModule; -import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Singleton; import com.google.inject.name.Named; @@ -50,31 +49,16 @@ public class NetworkModule extends AbstractModule { return bootstrap; } - @Provides - PacketSplitter packetSplitter() { - return new PacketSplitter(new ProtocolSplitter()); - } - - @Provides - PacketDecoder packetDecoder() { - return new PacketDecoder(new ProtocolDecoder(PacketDirection.SERVER_BOUND)); - } - - @Provides - PacketEncoder packetEncoder() { - return new PacketEncoder(new ProtocolEncoder(PacketDirection.CLIENT_BOUND)); - } - @Provides @Named("channelHandlerMap") - Map channelHandlerMap(final Injector injector) { + Map channelHandlerMap(HandshakeHandler handshakeHandler) { final Map map = new HashMap<>(); - map.put("logger", injector.getInstance(LoggingHandler.class)); - map.put("packet_splitter", injector.getInstance(PacketSplitter.class)); - map.put("packet_decoder", injector.getInstance(PacketDecoder.class)); - map.put("packet_encoder", injector.getInstance(PacketEncoder.class)); - map.put("handshake_handler", injector.getInstance(HandshakeHandler.class)); + map.put("logger", new LoggingHandler()); + map.put("packet_splitter", new PacketSplitter(new ProtocolSplitter())); + map.put("packet_decoder", new PacketDecoder(new ProtocolDecoder(PacketDirection.SERVER_BOUND))); + map.put("packet_encoder", new PacketEncoder(new ProtocolEncoder(PacketDirection.CLIENT_BOUND))); + map.put("handshake_handler", handshakeHandler); return map; } From c903554d7bb81e0faea6a02ed14571ed6aa70fd6 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Wed, 13 May 2020 18:17:54 +0300 Subject: [PATCH 4/7] fix packet handlers --- .../impl/handler/AbstractPacketHandler.java | 7 +++--- .../network/impl/handler/StatusHandler.java | 24 ++++++++++++++++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java b/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java index 8a4da37..09fa7f8 100644 --- a/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java +++ b/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java @@ -4,12 +4,11 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import mc.protocol.Packet; -public abstract class AbstractPacketHandler

extends SimpleChannelInboundHandler { +public abstract class AbstractPacketHandler

extends SimpleChannelInboundHandler

{ - @SuppressWarnings("unchecked") @Override - protected void channelRead0(ChannelHandlerContext ctx, Packet msg) throws Exception { - channelRead1(ctx, (P) msg); + protected void channelRead0(ChannelHandlerContext ctx, P msg) throws Exception { + channelRead1(ctx, msg); } protected abstract void channelRead1(ChannelHandlerContext ctx, P packet) throws Exception; diff --git a/src/main/java/mc/server/network/impl/handler/StatusHandler.java b/src/main/java/mc/server/network/impl/handler/StatusHandler.java index 5fff44b..bfe6751 100644 --- a/src/main/java/mc/server/network/impl/handler/StatusHandler.java +++ b/src/main/java/mc/server/network/impl/handler/StatusHandler.java @@ -1,20 +1,38 @@ package mc.server.network.impl.handler; +import com.google.inject.Inject; import io.netty.channel.ChannelHandlerContext; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import mc.protocol.ProtocolConstant; +import mc.protocol.State; +import mc.protocol.dto.ServerInfo; import mc.protocol.status.client.StatusServerRequest; import mc.protocol.status.server.StatusServerResponse; +import mc.protocol.text.Text; + +import static mc.server.network.impl.NettyConstants.ATTR_STATE; @Slf4j +@RequiredArgsConstructor(onConstructor = @__({ @Inject })) public class StatusHandler extends AbstractPacketHandler { @Override protected void channelRead1(ChannelHandlerContext ctx, StatusServerRequest packet) { log.info("{}", packet); - StatusServerResponse response = new StatusServerResponse(); - response.setInfo("some info server text"); + final ServerInfo.Version version = new ServerInfo.Version(); + version.setName(ProtocolConstant.PROTOCOL_VERSION_VALUE); + version.setProtocol(ProtocolConstant.PROTOCOL_VERSION); - ctx.channel().writeAndFlush(response).channel().disconnect(); + final ServerInfo serverInfo = new ServerInfo(); + serverInfo.setVersion(version); + serverInfo.setDescription(Text.of("MC-SERVER 1.8.8")); + + StatusServerResponse response = new StatusServerResponse(); + response.setServerInfoDto(serverInfo); + + ctx.channel().writeAndFlush(response)/*.channel().disconnect()*/; + ctx.channel().attr(ATTR_STATE).set(State.PLAY); //TODO просто что бы был UnknownPacket } } From 3dfff8c0f2b584d849e603cadfac2731e97fe609 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Wed, 13 May 2020 18:31:57 +0300 Subject: [PATCH 5/7] add PingHandler --- .../network/impl/handler/HandshakeHandler.java | 4 +++- .../mc/server/network/impl/handler/PingHandler.java | 12 ++++++++++++ .../server/network/impl/handler/StatusHandler.java | 6 +----- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 src/main/java/mc/server/network/impl/handler/PingHandler.java diff --git a/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java b/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java index b980256..b055295 100644 --- a/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java +++ b/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java @@ -14,12 +14,14 @@ import static mc.server.network.impl.NettyConstants.ATTR_STATE; public class HandshakeHandler extends AbstractPacketHandler { private final Provider statusHandlerProvider; + private final Provider pingHandlerProvider; @Override protected void channelRead1(ChannelHandlerContext ctx, HandshakePacket packet) { log.info("{}", packet); ctx.channel().attr(ATTR_STATE).set(packet.getNextState()); - ctx.pipeline().replace("handshake_handler", "status_handler", statusHandlerProvider.get()); + ctx.channel().pipeline().replace("handshake_handler", "status_handler", statusHandlerProvider.get()); + ctx.channel().pipeline().addAfter("status_handler", "ping_handler", pingHandlerProvider.get()); } } diff --git a/src/main/java/mc/server/network/impl/handler/PingHandler.java b/src/main/java/mc/server/network/impl/handler/PingHandler.java new file mode 100644 index 0000000..21b9fcd --- /dev/null +++ b/src/main/java/mc/server/network/impl/handler/PingHandler.java @@ -0,0 +1,12 @@ +package mc.server.network.impl.handler; + +import io.netty.channel.ChannelHandlerContext; +import mc.protocol.status.PingPacket; + +public class PingHandler extends AbstractPacketHandler { + + @Override + protected void channelRead1(ChannelHandlerContext ctx, PingPacket packet) { + ctx.writeAndFlush(packet).channel().disconnect(); + } +} diff --git a/src/main/java/mc/server/network/impl/handler/StatusHandler.java b/src/main/java/mc/server/network/impl/handler/StatusHandler.java index bfe6751..b7bb44e 100644 --- a/src/main/java/mc/server/network/impl/handler/StatusHandler.java +++ b/src/main/java/mc/server/network/impl/handler/StatusHandler.java @@ -5,14 +5,11 @@ import io.netty.channel.ChannelHandlerContext; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import mc.protocol.ProtocolConstant; -import mc.protocol.State; import mc.protocol.dto.ServerInfo; import mc.protocol.status.client.StatusServerRequest; import mc.protocol.status.server.StatusServerResponse; import mc.protocol.text.Text; -import static mc.server.network.impl.NettyConstants.ATTR_STATE; - @Slf4j @RequiredArgsConstructor(onConstructor = @__({ @Inject })) public class StatusHandler extends AbstractPacketHandler { @@ -32,7 +29,6 @@ public class StatusHandler extends AbstractPacketHandler { StatusServerResponse response = new StatusServerResponse(); response.setServerInfoDto(serverInfo); - ctx.channel().writeAndFlush(response)/*.channel().disconnect()*/; - ctx.channel().attr(ATTR_STATE).set(State.PLAY); //TODO просто что бы был UnknownPacket + ctx.channel().writeAndFlush(response); } } From a3b5956cdd9c7ecc73a9b103ef109ac2d274b20d Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Fri, 15 May 2020 14:41:08 +0300 Subject: [PATCH 6/7] set favicon server --- build.gradle | 2 ++ .../network/impl/handler/StatusHandler.java | 17 +++++++++++++---- src/main/resources/icon.png | Bin 0 -> 1675 bytes 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/icon.png diff --git a/build.gradle b/build.gradle index e540db7..e5b7eca 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,7 @@ ext { netty: ['io.netty:netty-all:4.1.22.Final'], slf4j: ["org.slf4j:slf4j-api:$slf4j_version", "org.slf4j:jcl-over-slf4j:$slf4j_version"], + commons: ['commons-io:commons-io:2.6'] ] } @@ -41,5 +42,6 @@ dependencies { /* COMPONENTS */ implementation library.guice implementation library.netty + implementation library.commons implementation project(':protocol') } \ No newline at end of file diff --git a/src/main/java/mc/server/network/impl/handler/StatusHandler.java b/src/main/java/mc/server/network/impl/handler/StatusHandler.java index b7bb44e..9289e1b 100644 --- a/src/main/java/mc/server/network/impl/handler/StatusHandler.java +++ b/src/main/java/mc/server/network/impl/handler/StatusHandler.java @@ -1,21 +1,24 @@ package mc.server.network.impl.handler; -import com.google.inject.Inject; import io.netty.channel.ChannelHandlerContext; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import mc.protocol.ProtocolConstant; import mc.protocol.dto.ServerInfo; import mc.protocol.status.client.StatusServerRequest; import mc.protocol.status.server.StatusServerResponse; import mc.protocol.text.Text; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.util.Base64; @Slf4j -@RequiredArgsConstructor(onConstructor = @__({ @Inject })) public class StatusHandler extends AbstractPacketHandler { + private static final String FAVICON_HEADER = "data:image/png;base64,"; + @Override - protected void channelRead1(ChannelHandlerContext ctx, StatusServerRequest packet) { + protected void channelRead1(ChannelHandlerContext ctx, StatusServerRequest packet) throws Exception { log.info("{}", packet); final ServerInfo.Version version = new ServerInfo.Version(); @@ -25,10 +28,16 @@ public class StatusHandler extends AbstractPacketHandler { final ServerInfo serverInfo = new ServerInfo(); serverInfo.setVersion(version); serverInfo.setDescription(Text.of("MC-SERVER 1.8.8")); + serverInfo.setFaviconBase64(getEmbeddedIconBase64()); StatusServerResponse response = new StatusServerResponse(); response.setServerInfoDto(serverInfo); ctx.channel().writeAndFlush(response); } + + private String getEmbeddedIconBase64() throws IOException { + return FAVICON_HEADER + Base64.getEncoder() + .encodeToString(IOUtils.toByteArray(getClass().getResourceAsStream("/icon.png"))); + } } diff --git a/src/main/resources/icon.png b/src/main/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d512fc5472e1d4b4573ba22b5e3e71587dbd4c9f GIT binary patch literal 1675 zcmV;626Xv}P)09zrl&^1WzcGf>6{pC7KKEp~p(7 zm8$R+BqT&YDrzr1B0?|WNG@&Q)Kgp3N=;EK4kUb5;xDLFQ7H?^5{eKeBm_fnt9);4 z_pn}j*IwH*J2STPlPs-g-^_dS+u4~n@6BpcQ&VUHf&eZ8_=ZvbTL2dT7&48Zlvb7b zWGbk@IDkU&w+{BsqbR#>t3NK?x*}u~Fo3erLlWB^vb8%Pv0Z5doP}xJElKUw!>yvO zvoabJC13)kF_$IS!i&pA-4h~>1O)0youCA81SSzd02{oOy^Me#(LSBG!vOFzZzbLl zunv>ycEuMkC(ICQ1s(zlywz-H;Z9ZWW}5U?3LZ=s>>jR;tiWJoJf zw-5CQ_z4`7NgE>svoEgDYHWu5;9OG&Pkzm3mLSdy4dU>?XFOGcl+vm`)fxfZ4n-@F z$z)&{%r1$mpxZKd-HS2Xdx)26p7GAxI{*OLY!-<`0>NNo_e9tA>y*+#dzl*nM@0Kttz#*yDvK`y0*UpH(X>rVM`=}ojZD5?-?68 zq@O*oAGpUcqZTpe|NcS26u0jodJ?uL0i9_bW z_df{fuSbHe>%US;Pg?}Y3}8Ai{Ui;auiD@8`Fxm}eSv&FkFG=6uy3{yxxs?>ov>&iFj2AYnKF#@HDT^oJ?v4^y(6l?EFLn)FF< z&!Nv9|DWEx>pGj;p?VT@gGGXL0-oNyTUFMI4zfaJc6d`jsUOhyZg1&2^>`W|b_B3J z}SADsBhDam=pu7tF21QY! zHr^DC17%nElnM=gpO5)x_XJfV6bgY-dKysd2jm)r!diuRyu3TL6L1uQXYSnKkAz*z zbE|8JMz;b0mX}xHM*(49<594blX76Clq0kgpu}Cvt*)Ub*hj@Jf9O$#f;+9AFM2|wG0Lza89UDD8SgLuKs%Ajn^iH5Dtfd8VR6U1mpl*0q`ZO zlA{L?a2qCqcs#}|8;ixRpvD8Obxh8}8aU1hGM>^mZY^%KS8vW6cX}DiT;b5AY>MG;n+=(kc=NAqF@e7;k1M1aoy@HHNc! z?+Ay(AcXt^&I8_FQe$6%<4{F2NFanD7K;S|oZ+qOH8;2cbC@xmD^^7UAq0ew>qT2U zIc}oK(PKsB=NbvhBq5nhf)H}9sQZ{mTe7mlmth)nu%3_z387HPdg6yPGkzxJV@=uV z@!K$o&;VR@6W}4Cv$NCc^woGgZnZ1*^IVlN!6B3*%|V!lvCacbBzy;81Wour^M8T$ Vqx`lI%8LL1002ovPDHLkV1m=#{XPHy literal 0 HcmV?d00001 From fa3c899120fb29cfffdf2cd8c22a20ce24b48692 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Fri, 15 May 2020 14:44:21 +0300 Subject: [PATCH 7/7] set player info --- .../java/mc/server/network/impl/handler/StatusHandler.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/mc/server/network/impl/handler/StatusHandler.java b/src/main/java/mc/server/network/impl/handler/StatusHandler.java index 9289e1b..9011478 100644 --- a/src/main/java/mc/server/network/impl/handler/StatusHandler.java +++ b/src/main/java/mc/server/network/impl/handler/StatusHandler.java @@ -11,6 +11,7 @@ import org.apache.commons.io.IOUtils; import java.io.IOException; import java.util.Base64; +import java.util.Collections; @Slf4j public class StatusHandler extends AbstractPacketHandler { @@ -25,10 +26,16 @@ public class StatusHandler extends AbstractPacketHandler { version.setName(ProtocolConstant.PROTOCOL_VERSION_VALUE); version.setProtocol(ProtocolConstant.PROTOCOL_VERSION); + final ServerInfo.PlayersInfo playersInfo = new ServerInfo.PlayersInfo(); + playersInfo.setMax(20); + playersInfo.setOnline(0); + playersInfo.setSamplePlayers(Collections.emptyList()); + final ServerInfo serverInfo = new ServerInfo(); serverInfo.setVersion(version); serverInfo.setDescription(Text.of("MC-SERVER 1.8.8")); serverInfo.setFaviconBase64(getEmbeddedIconBase64()); + serverInfo.setPlayersInfo(playersInfo); StatusServerResponse response = new StatusServerResponse(); response.setServerInfoDto(serverInfo);