diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/LodClient.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/LodClient.java new file mode 100644 index 000000000..d31ce3a87 --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/LodClient.java @@ -0,0 +1,24 @@ +package com.seibel.distanthorizons.common.networking; + +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import net.minecraft.client.Minecraft; + +public class LodClient { + public static final LodClient INSTANCE = new LodClient(); + + private final Minecraft client; + private final NetworkHandler networkHandler; + + private LodClient() { + client = Minecraft.getInstance(); + this.networkHandler = new NetworkHandler(); + } + + public void connect() { + + } + + public void disconnect() { + + } +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/LodServer.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/LodServer.java new file mode 100644 index 000000000..b2b66deae --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/LodServer.java @@ -0,0 +1,59 @@ +package com.seibel.distanthorizons.common.networking; + +import com.seibel.distanthorizons.common.networking.messages.MessageHandler; +import com.seibel.distanthorizons.common.networking.messages.MessageHandlerSide; +import com.seibel.distanthorizons.common.networking.messages.MessageRegistry; +import io.netty.bootstrap.ServerBootstrap; +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.codec.LengthFieldBasedFrameDecoder; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; + +public class LodServer { + // TODO move to config of some sort + static final int PORT = 25049; + + public void start() throws InterruptedException { + EventLoopGroup bossGroup = new NioEventLoopGroup(1); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + try { + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(getInitializer()); + + b.bind(PORT).sync().channel().closeFuture().sync(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + public void stop() { + + } + + private ChannelInitializer getInitializer() { + return new ChannelInitializer<>() { + @Override + public void initChannel(SocketChannel ch) { + ChannelPipeline pipeline = ch.pipeline(); + + var messageRegistry = new MessageRegistry(); + + // Encoding + pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2)); + pipeline.addLast(new MessageDecoder(messageRegistry)); + // TODO packet encoder + + pipeline.addLast(new MessageHandler(MessageHandlerSide.SERVER)); + } + }; + } +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/MessageDecoder.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/MessageDecoder.java new file mode 100644 index 000000000..65c08520f --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/MessageDecoder.java @@ -0,0 +1,21 @@ +package com.seibel.distanthorizons.common.networking; + +import com.seibel.distanthorizons.common.networking.messages.MessageRegistry; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + private MessageRegistry messageRegistry; + + public MessageDecoder(MessageRegistry messageRegistry) { + this.messageRegistry = messageRegistry; + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + out.add(messageRegistry.createMessage(in.readShort()).decode(in)); + } +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/NetworkHandler.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/NetworkHandler.java index ecef2606c..28fc16789 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/networking/NetworkHandler.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/NetworkHandler.java @@ -32,12 +32,8 @@ import net.minecraft.world.entity.player.Player; // TODO: Server sided stuff here public class NetworkHandler { - public static void receivePacketClient(Minecraft client, FriendlyByteBuf buf, Player player) { + public static void receivePacket(FriendlyByteBuf buf) { // This just exists here for testing purposes, it'll be removed in the future System.out.println("Received int " + buf.readInt()); } - - public static void receivePacketServer(FriendlyByteBuf buf, Player player) { - - } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/HelloMessage.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/HelloMessage.java new file mode 100644 index 000000000..471f44642 --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/HelloMessage.java @@ -0,0 +1,5 @@ +package com.seibel.distanthorizons.common.networking.messages; + +public class HelloMessage extends Message { + public int version = 1; +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/Message.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/Message.java new file mode 100644 index 000000000..7257db9b2 --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/Message.java @@ -0,0 +1,23 @@ +package com.seibel.distanthorizons.common.networking.messages; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; + +public abstract class Message { + public Message() { } + + public void encode(ByteBuf out) { + throw new UnsupportedOperationException(); + } + public Message decode(ByteBuf in) { + throw new UnsupportedOperationException(); + } + + protected void handle_Server(ChannelHandlerContext ctx) { + throw new UnsupportedOperationException(); + } + protected void handle_Client(ChannelHandlerContext ctx) { + throw new UnsupportedOperationException(); + } +} + diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageHandler.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageHandler.java new file mode 100644 index 000000000..946d32aba --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageHandler.java @@ -0,0 +1,21 @@ +package com.seibel.distanthorizons.common.networking.messages; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +public class MessageHandler extends SimpleChannelInboundHandler { + private final MessageHandlerSide side; + + public MessageHandler(MessageHandlerSide side) { + this.side = side; + } + + @Override + public void channelRead0(ChannelHandlerContext ctx, Message msg) { + switch (side) { + case CLIENT -> msg.handle_Client(ctx); + case SERVER -> msg.handle_Server(ctx); + default -> throw new IllegalStateException("Invalid handler side"); + } + } +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageHandlerSide.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageHandlerSide.java new file mode 100644 index 000000000..95056390b --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageHandlerSide.java @@ -0,0 +1,6 @@ +package com.seibel.distanthorizons.common.networking.messages; + +public enum MessageHandlerSide { + CLIENT, + SERVER +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageRegistry.java b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageRegistry.java new file mode 100644 index 000000000..8f47e23d3 --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/networking/messages/MessageRegistry.java @@ -0,0 +1,32 @@ +package com.seibel.distanthorizons.common.networking.messages; + +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +public class MessageRegistry { + private final Map> idToConstructor = Map.ofEntries( + // Do NOT remove messages from middle of the list; + // It will break backwards compatibility. + // (Stub indexes out instead) + Map.entry(1, HelloMessage::new) + ); + + private final Map, Integer> classToId = idToConstructor.entrySet().stream() + .collect(Collectors.toMap( + e -> e.getValue().getClass(), + Map.Entry::getKey + )); + + public Message createMessage(int id) throws IllegalArgumentException { + try { + return idToConstructor.get(id).get(); + } catch (NullPointerException e) { + throw new IllegalArgumentException("Invalid message ID"); + } + } + + public int getMessageId(Message message) { + return classToId.get(message.getClass()); + } +}