### NetMinecraft Client Example Source: https://github.com/raphimc/netminecraft/blob/main/README.md Demonstrates creating a NetMinecraft client, connecting to a server, and sending handshake and request packets. Handles responses and disconnects. ```java NetClient client = new NetClient(new MinecraftChannelInitializer(new Supplier() { @Override public ChannelHandler get() { return new SimpleChannelInboundHandler() { long start; @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { super.handlerAdded(ctx); start = System.currentTimeMillis(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { super.channelActive(ctx); System.out.println("connected"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); System.out.println("disconnected"); } @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { System.out.println("got response in " + (System.currentTimeMillis() - start) + " ms"); channelHandlerContext.close(); } }; } })); ByteBuf handshake = Unpooled.buffer(); PacketTypes.writeVarInt(handshake, 0); // packet id PacketTypes.writeVarInt(handshake, 47); // protocol version PacketTypes.writeString(handshake, "localhost"); // server address handshake.writeShort(25565); // server port PacketTypes.writeVarInt(handshake, 1); // next state ByteBuf request = Unpooled.buffer(); PacketTypes.writeVarInt(request, 0); // packet id client.connect(MinecraftServerAddress.ofResolved("localhost")).syncUninterruptibly(); // blocking connect client.getChannel().writeAndFlush(handshake); client.getChannel().writeAndFlush(request); client.getChannel().closeFuture().syncUninterruptibly(); ``` -------------------------------- ### Setup NetMinecraft Server Source: https://github.com/raphimc/netminecraft/blob/main/README.md Initializes and binds a NetMinecraft server to listen for incoming connections. Handles new connections and disconnections by printing messages to the console. Packet reading logic is a placeholder. ```java NetServer server = new NetServer(new MinecraftChannelInitializer(() -> new SimpleChannelInboundHandler() { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { super.channelActive(ctx); System.out.println("New connection from " + ctx.channel().remoteAddress()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); System.out.println(ctx.channel().remoteAddress() + " closed connection"); } @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { // Read packets here } })); server.bind(new InetSocketAddress("0.0.0.0", 25565), true); ``` -------------------------------- ### Implement AES Encryption for Minecraft Protocol Source: https://context7.com/raphimc/netminecraft/llms.txt Demonstrates setting up AES encryption using the AESEncryption class and enabling it on a Netty channel. Includes manual encryption and decryption examples. Requires a shared secret key. ```java import net.raphimc.netminecraft.netty.crypto.AESEncryption; import net.raphimc.netminecraft.netty.crypto.CryptUtil; import net.raphimc.netminecraft.constants.MCPipeline; import javax.crypto.spec.SecretKeySpec; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; // Generate RSA keypair for encryption handshake (server-side) KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(1024); KeyPair serverKeyPair = keyGen.generateKeyPair(); // During login, client sends encrypted shared secret // Server decrypts and creates AESEncryption byte[] sharedSecretBytes = new byte[16]; // Decrypted from client SecretKeySpec sharedSecret = new SecretKeySpec(sharedSecretBytes, "AES"); try { AESEncryption encryption = new AESEncryption(sharedSecret); // Enable encryption on channel channel.attr(MCPipeline.ENCRYPTION_ATTRIBUTE_KEY).set(encryption); // Manual encryption/decryption (handled automatically by pipeline) byte[] plaintext = "Hello".getBytes(); byte[] ciphertext = new byte[encryption.getEncryptOutputSize(plaintext.length)]; int encryptedLen = encryption.encrypt(plaintext, 0, plaintext.length, ciphertext, 0); byte[] decrypted = new byte[encryption.getDecryptOutputSize(encryptedLen)]; int decryptedLen = encryption.decrypt(ciphertext, 0, encryptedLen, decrypted, 0); } catch (GeneralSecurityException e) { System.err.println("Encryption initialization failed: " + e.getMessage()); } // Utility for decoding RSA public key from bytes byte[] encodedPublicKey = serverKeyPair.getPublic().getEncoded(); var decodedKey = CryptUtil.decodeRsaPublicKey(encodedPublicKey); ``` -------------------------------- ### Setup NetMinecraft Proxy Server Source: https://github.com/raphimc/netminecraft/blob/main/README.md Configures and binds a NetMinecraft proxy server. It establishes a connection to a backend Minecraft server and forwards traffic between the client and the backend. Requires a running Minecraft server at 'localhost'. ```java final NetServer server = new NetServer(new ChannelInitializer() { @Override protected void initChannel(Channel channel) { channel.pipeline().addLast(new SimpleChannelInboundHandler() { private Channel otherChannel; private final NetClient client = new NetClient(new ChannelInitializer() { @Override protected void initChannel(Channel channel) { channel.pipeline().addLast(new SimpleChannelInboundHandler() { @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) { otherChannel.writeAndFlush(byteBuf.retain()); } }); } }); @Override public void channelActive(ChannelHandlerContext ctx) { this.otherChannel = ctx.channel(); this.client.connect(MinecraftServerAddress.ofResolved("localhost")).syncUninterruptibly(); } @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) { this.client.getChannel().writeAndFlush(byteBuf.retain()); } @Override public void channelInactive(ChannelHandlerContext ctx) { this.client.getChannel().close().syncUninterruptibly(); } }); } }); server.bind(new InetSocketAddress("0.0.0.0", 25565)); ``` -------------------------------- ### Create and Bind NetServer Source: https://context7.com/raphimc/netminecraft/llms.txt Instantiate a NetServer to accept Minecraft client connections. Supports non-blocking and blocking bind modes. Requires a MinecraftChannelInitializer. ```java import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import net.raphimc.netminecraft.netty.connection.MinecraftChannelInitializer; import net.raphimc.netminecraft.netty.connection.NetServer; import net.raphimc.netminecraft.packet.PacketTypes; import java.net.InetSocketAddress; // Create a server that accepts Minecraft clients NetServer server = new NetServer(new MinecraftChannelInitializer(() -> new SimpleChannelInboundHandler() { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { super.channelActive(ctx); System.out.println("Client connected: " + ctx.channel().remoteAddress()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); System.out.println("Client disconnected: " + ctx.channel().remoteAddress()); } @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception { // Read packet ID int packetId = PacketTypes.readVarInt(byteBuf); System.out.println("Received packet ID: " + packetId); // Handle handshake packet if (packetId == 0) { int protocolVersion = PacketTypes.readVarInt(byteBuf); String serverAddress = PacketTypes.readString(byteBuf, 255); int serverPort = byteBuf.readUnsignedShort(); int nextState = PacketTypes.readVarInt(byteBuf); System.out.printf("Handshake: version=%d, address=%s, port=%d, state=%d%n", protocolVersion, serverAddress, serverPort, nextState); } } })); // Bind to port 25565 (non-blocking mode) server.bind(new InetSocketAddress("0.0.0.0", 25565), false); System.out.println("Server started on port 25565"); // For blocking mode (waits until server closes): // server.bind(new InetSocketAddress("0.0.0.0", 25565), true); ``` -------------------------------- ### ClientChannelInitializer for NetMinecraft Source: https://github.com/raphimc/netminecraft/blob/main/README.md Extends MinecraftChannelInitializer to set up packet registry for client-side communication. Requires the 'packets' submodule. ```java public class ClientChannelInitializer extends MinecraftChannelInitializer { public ClientChannelInitializer(final Supplier handlerSupplier) { super(handlerSupplier); } @Override protected void initChannel(Channel channel) { super.initChannel(channel); channel.attr(MCPipeline.PACKET_REGISTRY_ATTRIBUTE_KEY).set(new DefaultPacketRegistry(true, protocolVersion)); } } ``` -------------------------------- ### Connect to a Minecraft Server with NetClient Source: https://context7.com/raphimc/netminecraft/llms.txt Establishes a TCP connection to a Minecraft server and sends handshake and status request packets. Requires a custom channel handler to process incoming data. ```java import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import net.raphimc.netminecraft.netty.connection.MinecraftChannelInitializer; import net.raphimc.netminecraft.netty.connection.NetClient; import net.raphimc.netminecraft.packet.PacketTypes; import net.raphimc.netminecraft.util.MinecraftServerAddress; // Create a client with a custom packet handler NetClient client = new NetClient(new MinecraftChannelInitializer(() -> new SimpleChannelInboundHandler() { private long connectionStartTime; @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { super.handlerAdded(ctx); connectionStartTime = System.currentTimeMillis(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { super.channelActive(ctx); System.out.println("Connected to server"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); System.out.println("Disconnected from server"); } @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception { System.out.println("Received response in " + (System.currentTimeMillis() - connectionStartTime) + " ms"); ctx.close(); } })); // Build handshake packet (protocol version 47 = Minecraft 1.8) ByteBuf handshake = Unpooled.buffer(); PacketTypes.writeVarInt(handshake, 0); // Packet ID: Handshake PacketTypes.writeVarInt(handshake, 47); // Protocol version: 1.8 PacketTypes.writeString(handshake, "localhost"); // Server address handshake.writeShort(25565); // Server port PacketTypes.writeVarInt(handshake, 1); // Next state: STATUS // Build status request packet ByteBuf statusRequest = Unpooled.buffer(); PacketTypes.writeVarInt(statusRequest, 0); // Packet ID: Status Request // Connect and send packets client.connect(MinecraftServerAddress.ofResolved("localhost")).syncUninterruptibly(); client.getChannel().writeAndFlush(handshake); client.getChannel().writeAndFlush(statusRequest); client.getChannel().closeFuture().syncUninterruptibly(); ``` -------------------------------- ### Implement a Minecraft Proxy Server Source: https://context7.com/raphimc/netminecraft/llms.txt Uses NetServer and NetClient to establish a bidirectional bridge between a client and a backend server with packet inspection. ```java import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.SimpleChannelInboundHandler; import net.raphimc.netminecraft.netty.connection.NetClient; import net.raphimc.netminecraft.netty.connection.NetServer; import net.raphimc.netminecraft.packet.PacketTypes; import net.raphimc.netminecraft.util.MinecraftServerAddress; import java.net.InetSocketAddress; public class MinecraftProxy { private static final String BACKEND_SERVER = "localhost:25566"; public static void main(String[] args) { NetServer proxyServer = new NetServer(new ChannelInitializer() { @Override protected void initChannel(Channel clientChannel) { clientChannel.pipeline().addLast(new SimpleChannelInboundHandler() { private Channel backendChannel; private final NetClient backendClient = new NetClient(new ChannelInitializer() { @Override protected void initChannel(Channel channel) { channel.pipeline().addLast(new SimpleChannelInboundHandler() { @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) { // Forward server -> client if (backendChannel != null && backendChannel.isActive()) { backendChannel.writeAndFlush(msg.retain()); } } @Override public void channelInactive(ChannelHandlerContext ctx) { if (backendChannel != null) { backendChannel.close(); } } }); } }); @Override public void channelActive(ChannelHandlerContext ctx) { this.backendChannel = ctx.channel(); // Connect to backend server backendClient.connect(MinecraftServerAddress.ofResolved(BACKEND_SERVER)) .addListener(future -> { if (!future.isSuccess()) { ctx.close(); } }); } @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) { // Log packet for inspection int readerIndex = msg.readerIndex(); int packetId = PacketTypes.readVarInt(msg); System.out.println("Client -> Server packet ID: " + packetId); msg.readerIndex(readerIndex); // Forward client -> server if (backendClient.getChannel() != null && backendClient.getChannel().isActive()) { backendClient.getChannel().writeAndFlush(msg.retain()); } } @Override public void channelInactive(ChannelHandlerContext ctx) { if (backendClient.getChannel() != null) { backendClient.getChannel().close(); } } }); } }); System.out.println("Starting proxy on port 25565 -> " + BACKEND_SERVER); proxyServer.bind(new InetSocketAddress("0.0.0.0", 25565), true); } } ``` -------------------------------- ### Configure Netty Pipeline and Channel Attributes Source: https://context7.com/raphimc/netminecraft/llms.txt Manage pipeline handlers and channel attributes for encryption, compression, and performance tuning using MCPipeline. ```java import io.netty.channel.Channel; import net.raphimc.netminecraft.constants.MCPipeline; import net.raphimc.netminecraft.netty.crypto.AESEncryption; import javax.crypto.spec.SecretKeySpec; import java.security.GeneralSecurityException; // Use optimized pipeline for better performance MCPipeline.useOptimizedPipeline(); // Reset to default handlers MCPipeline.useDefaultPipeline(); // Configure channel attributes in a custom ChannelInitializer public class CustomChannelInitializer extends MinecraftChannelInitializer { public CustomChannelInitializer(Supplier handlerSupplier) { super(handlerSupplier); } @Override protected void initChannel(Channel channel) { super.initChannel(channel); // Set flush consolidation threshold (packets per second before consolidation) channel.attr(MCPipeline.FLUSH_CONSOLIDATION_PPS_THRESHOLD_ATTRIBUTE_KEY).set(5000); // Enable compression (threshold in bytes, -1 = disabled) channel.attr(MCPipeline.COMPRESSION_THRESHOLD_ATTRIBUTE_KEY).set(256); // Enable encryption after login sequence try { byte[] sharedSecret = new byte[16]; // From encryption exchange SecretKeySpec secretKey = new SecretKeySpec(sharedSecret, "AES"); AESEncryption encryption = new AESEncryption(secretKey); channel.attr(MCPipeline.ENCRYPTION_ATTRIBUTE_KEY).set(encryption); } catch (GeneralSecurityException e) { e.printStackTrace(); } } } // Handler names for pipeline manipulation String sizerHandler = MCPipeline.SIZER_HANDLER_NAME; // "sizer" String compressionHandler = MCPipeline.COMPRESSION_HANDLER_NAME; // "compression" String encryptionHandler = MCPipeline.ENCRYPTION_HANDLER_NAME; // "encryption" String codecHandler = MCPipeline.PACKET_CODEC_HANDLER_NAME; // "packet-codec" ``` -------------------------------- ### Implement Packet Registry and Handler Source: https://context7.com/raphimc/netminecraft/llms.txt Configures a custom channel initializer to set the packet registry and defines a handler to process typed packets. ```java import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import net.raphimc.netminecraft.constants.ConnectionState; import net.raphimc.netminecraft.constants.MCPipeline; import net.raphimc.netminecraft.netty.connection.MinecraftChannelInitializer; import net.raphimc.netminecraft.packet.Packet; import net.raphimc.netminecraft.packet.impl.handshaking.C2SHandshakingClientIntentionPacket; import net.raphimc.netminecraft.packet.impl.login.C2SLoginHelloPacket; import net.raphimc.netminecraft.packet.impl.login.S2CLoginGameProfilePacket; import net.raphimc.netminecraft.packet.registry.DefaultPacketRegistry; import java.util.function.Supplier; // Custom channel initializer with packet registry public class PacketReadingChannelInitializer extends MinecraftChannelInitializer { private final int protocolVersion; public PacketReadingChannelInitializer(Supplier handlerSupplier, int protocolVersion) { super(handlerSupplier); this.protocolVersion = protocolVersion; } @Override protected void initChannel(Channel channel) { super.initChannel(channel); // true = clientside (receives server packets), false = serverside (receives client packets) channel.attr(MCPipeline.PACKET_REGISTRY_ATTRIBUTE_KEY) .set(new DefaultPacketRegistry(true, protocolVersion)); } } // Handler that receives typed Packet objects public class PacketHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, Packet packet) { // Get the packet registry to change connection state var registry = ctx.channel().attr(MCPipeline.PACKET_REGISTRY_ATTRIBUTE_KEY).get(); if (packet instanceof C2SHandshakingClientIntentionPacket handshake) { System.out.println("Handshake received:"); System.out.println(" Protocol: " + handshake.protocolVersion); System.out.println(" Address: " + handshake.address); System.out.println(" Port: " + handshake.port); System.out.println(" State: " + handshake.intendedState); // Transition to next state switch (handshake.intendedState) { case STATUS -> registry.setConnectionState(ConnectionState.STATUS); case LOGIN -> registry.setConnectionState(ConnectionState.LOGIN); } } else if (packet instanceof C2SLoginHelloPacket loginHello) { System.out.println("Login request from: " + loginHello.name); if (loginHello.uuid != null) { System.out.println(" UUID: " + loginHello.uuid); } } else if (packet instanceof S2CLoginGameProfilePacket gameProfile) { System.out.println("Login success:"); System.out.println(" Name: " + gameProfile.name); System.out.println(" UUID: " + gameProfile.uuid); } } } // Usage with NetServer NetServer server = new NetServer(new PacketReadingChannelInitializer( PacketHandler::new, MCVersion.v1_20_5 )); server.bind(new InetSocketAddress("0.0.0.0", 25565), false); ``` -------------------------------- ### MCVersion Protocol Version Constants Source: https://context7.com/raphimc/netminecraft/llms.txt Use MCVersion constants for protocol handling and version comparison. Access all available versions via MCVersion.ALL_VERSIONS. ```java import net.raphimc.netminecraft.constants.MCVersion; // Use version constants for protocol handling int clientVersion = MCVersion.v1_20_5; System.out.println("Protocol version for 1.20.5: " + clientVersion); // Output: 766 // Version comparison for conditional packet handling if (clientVersion >= MCVersion.v1_19 && clientVersion <= MCVersion.v1_19_4) { // Handle 1.19.x specific packet format System.out.println("Using 1.19.x packet format"); } else if (clientVersion >= MCVersion.v1_20) { // Handle 1.20+ packet format System.out.println("Using 1.20+ packet format"); } // Get all available versions MCVersion.ALL_VERSIONS.forEach((protocolId, versionName) -> { System.out.println(versionName + " = " + protocolId); }); // Output: // v1_7_2 = 4 // v1_8 = 47 // v1_9 = 107 // ... (all versions up to latest) // Common versions reference int v1_8 = MCVersion.v1_8; // 47 int v1_12_2 = MCVersion.v1_12_2; // 340 int v1_16_5 = MCVersion.v1_16_4; // 754 int v1_18_2 = MCVersion.v1_18_2; // 758 int v1_20 = MCVersion.v1_20; // 763 int v1_21 = MCVersion.v1_21; // 767 ``` -------------------------------- ### Custom Packet Implementation Source: https://context7.com/raphimc/netminecraft/llms.txt Implement the Packet interface to create custom packet classes. The read and write methods handle serialization and deserialization. ```java import io.netty.buffer.ByteBuf; import net.raphimc.netminecraft.constants.MCVersion; import net.raphimc.netminecraft.packet.Packet; import net.raphimc.netminecraft.packet.PacketTypes; // Custom packet implementation public class C2SStatusRequestPacket implements Packet { // No fields - this is an empty packet @Override public void read(ByteBuf byteBuf, int protocolVersion) { // Nothing to read } @Override public void write(ByteBuf byteBuf, int protocolVersion) { // Nothing to write } } ``` ```java import io.netty.buffer.ByteBuf; import net.raphimc.netminecraft.constants.MCVersion; import net.raphimc.netminecraft.packet.Packet; import net.raphimc.netminecraft.packet.PacketTypes; // Version-aware packet implementation public class C2SHandshakePacket implements Packet { public int protocolVersion; public String serverAddress; public int serverPort; public int nextState; public C2SHandshakePacket() {} public C2SHandshakePacket(int protocolVersion, String serverAddress, int serverPort, int nextState) { this.protocolVersion = protocolVersion; this.serverAddress = serverAddress; this.serverPort = serverPort; this.nextState = nextState; } @Override public void read(ByteBuf byteBuf, int protocolVersion) { this.protocolVersion = PacketTypes.readVarInt(byteBuf); this.serverAddress = PacketTypes.readString(byteBuf, 255); this.serverPort = byteBuf.readUnsignedShort(); this.nextState = PacketTypes.readVarInt(byteBuf); } @Override public void write(ByteBuf byteBuf, int protocolVersion) { PacketTypes.writeVarInt(byteBuf, this.protocolVersion); PacketTypes.writeString(byteBuf, this.serverAddress); byteBuf.writeShort(this.serverPort); PacketTypes.writeVarInt(byteBuf, this.nextState); } } ``` ```java import io.netty.buffer.ByteBuf; import net.raphimc.netminecraft.constants.MCVersion; import net.raphimc.netminecraft.packet.Packet; import net.raphimc.netminecraft.packet.PacketTypes; import java.util.UUID; // Complex packet with version-specific fields public class C2SLoginHelloPacket implements Packet { public String playerName; public UUID playerUuid; @Override public void read(ByteBuf byteBuf, int protocolVersion) { this.playerName = PacketTypes.readString(byteBuf, 16); if (protocolVersion >= MCVersion.v1_20_2) { this.playerUuid = PacketTypes.readUuid(byteBuf); } else if (protocolVersion >= MCVersion.v1_19_1) { if (byteBuf.readBoolean()) { this.playerUuid = PacketTypes.readUuid(byteBuf); } } } @Override public void write(ByteBuf byteBuf, int protocolVersion) { PacketTypes.writeString(byteBuf, this.playerName); if (protocolVersion >= MCVersion.v1_20_2) { PacketTypes.writeUuid(byteBuf, this.playerUuid); } else if (protocolVersion >= MCVersion.v1_19_1) { byteBuf.writeBoolean(this.playerUuid != null); if (this.playerUuid != null) { PacketTypes.writeUuid(byteBuf, this.playerUuid); } } } } ``` -------------------------------- ### Select and Verify Network Transports with TransportType Source: https://context7.com/raphimc/netminecraft/llms.txt Use TransportType to detect the optimal transport for the current platform or specific address types. Check availability for specific implementations like EPOLL or IO_URING before use. ```java import net.raphimc.netminecraft.util.TransportType; import java.net.InetSocketAddress; // Get the best available transport for the current platform TransportType best = TransportType.getBest(); System.out.println("Best transport: " + best.name()); System.out.println("Available: " + best.isAvailable()); // Linux: EPOLL // macOS/BSD: KQUEUE // Windows/Other: NIO // Get transport based on address type InetSocketAddress inetAddress = new InetSocketAddress("localhost", 25565); TransportType tcpTransport = TransportType.getBest(inetAddress); // Check specific transport availability if (TransportType.EPOLL.isAvailable()) { System.out.println("Epoll is available (Linux)"); } if (TransportType.KQUEUE.isAvailable()) { System.out.println("KQueue is available (macOS/BSD)"); } if (TransportType.IO_URING.isAvailable()) { System.out.println("io_uring is available (Modern Linux)"); } // Get channel classes for custom bootstrap Class clientChannel = best.tcpClientChannelClass(); // e.g., EpollSocketChannel Class serverChannel = best.tcpServerChannelClass(); // e.g., EpollServerSocketChannel // Unix domain socket support (for IPC) if (TransportType.UNIX_EPOLL.isAvailable()) { System.out.println("Unix domain sockets available via Epoll"); } ``` -------------------------------- ### Read and Write Minecraft Protocol Data Types Source: https://context7.com/raphimc/netminecraft/llms.txt Utilize PacketTypes to serialize and deserialize various Minecraft-specific data types like VarInts, strings, and UUIDs into a ByteBuf. ```java import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import net.raphimc.netminecraft.packet.PacketTypes; import java.util.UUID; ByteBuf buffer = Unpooled.buffer(); // Write and read VarInt (variable-length integer, 1-5 bytes) PacketTypes.writeVarInt(buffer, 300); int varIntValue = PacketTypes.readVarInt(buffer); System.out.println("VarInt: " + varIntValue); // Output: 300 // Get VarInt encoded length int length = PacketTypes.getVarIntLength(300); // Returns 2 bytes // Write and read VarLong (variable-length long, 1-10 bytes) buffer.clear(); PacketTypes.writeVarLong(buffer, Long.MAX_VALUE); long varLongValue = PacketTypes.readVarLong(buffer); System.out.println("VarLong: " + varLongValue); // Write and read string (length-prefixed UTF-8) buffer.clear(); PacketTypes.writeString(buffer, "Hello Minecraft!"); String stringValue = PacketTypes.readString(buffer, 256); // max length parameter System.out.println("String: " + stringValue); // Write and read byte array (VarInt length-prefixed) buffer.clear(); byte[] data = new byte[]{0x01, 0x02, 0x03, 0x04}; PacketTypes.writeByteArray(buffer, data); byte[] readData = PacketTypes.readByteArray(buffer); System.out.println("Byte array length: " + readData.length); // Write and read short-prefixed byte array buffer.clear(); PacketTypes.writeShortByteArray(buffer, data); byte[] shortPrefixedData = PacketTypes.readShortByteArray(buffer); // Write and read VarInt array buffer.clear(); PacketTypes.writeVarIntArray(buffer, new int[]{1, 2, 3, 4, 5}); int[] intArray = PacketTypes.readVarIntArray(buffer); // Write and read UUID (128-bit, 16 bytes) buffer.clear(); UUID uuid = UUID.randomUUID(); PacketTypes.writeUuid(buffer, uuid); UUID readUuid = PacketTypes.readUuid(buffer); System.out.println("UUID: " + readUuid); // Read remaining bytes buffer.clear(); buffer.writeBytes(new byte[]{1, 2, 3, 4, 5}); byte[] remaining = PacketTypes.readReadableBytes(buffer); System.out.println("Remaining bytes: " + remaining.length); ``` -------------------------------- ### MinecraftServerAddress Resolution Source: https://context7.com/raphimc/netminecraft/llms.txt Parse Minecraft server addresses, supporting IPv6 and automatic SRV record resolution. Use `ofUnresolved` for direct addresses and `ofResolved` to query SRV records. ```java import net.raphimc.netminecraft.util.MinecraftServerAddress; // Simple address with default port (25565) MinecraftServerAddress address1 = MinecraftServerAddress.ofUnresolved("play.example.com"); System.out.println(address1.getHostString() + ":" + address1.getPort()); // Output: play.example.com:25565 // Address with custom port MinecraftServerAddress address2 = MinecraftServerAddress.ofUnresolved("play.example.com:25566"); System.out.println(address2.getHostString() + ":" + address2.getPort()); // Output: play.example.com:25566 // IPv6 address with port MinecraftServerAddress address3 = MinecraftServerAddress.ofUnresolved("[::1]:25565"); System.out.println(address3.getHostString() + ":" + address3.getPort()); // Output: ::1:25565 // Resolve SRV records automatically (queries _minecraft._tcp.example.com) MinecraftServerAddress resolved = MinecraftServerAddress.ofResolved("example.com"); System.out.println("Resolved to: " + resolved.getHostString() + ":" + resolved.getPort()); // If SRV record exists, returns actual server address; otherwise returns original address // Use with NetClient // NetClient client = new NetClient(new MinecraftChannelInitializer(() -> myHandler)); // client.connect(MinecraftServerAddress.ofResolved("hypixel.net")).syncUninterruptibly(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.