Networking System Overview
Networking System Overview
Section titled “Networking System Overview”The Networking System handles all client-server communication through a packet-based protocol built on Netty. Plugins can send packets, watch packet flow, and filter packets for modification.
Package Location
Section titled “Package Location”- Protocol:
com.hypixel.hytale.protocol - Packets:
com.hypixel.hytale.protocol.packets - Server I/O:
com.hypixel.hytale.server.core.io - Packet Adapters:
com.hypixel.hytale.server.core.io.adapter
Architecture
Section titled “Architecture”flowchart TB
subgraph Network["Networking Architecture"]
Client["Client"]
Transport["Transport<br/>(TCP/QUIC)"]
Handler["PacketHandler"]
subgraph Pipeline["Adapter Pipeline"]
Inbound["Inbound<br/>Adapters"]
Outbound["Outbound<br/>Adapters"]
end
Logic["Game Logic / Plugins"]
end
Client <--> Transport <--> Handler
Handler --> Pipeline
Pipeline --> Logic
Core Classes
Section titled “Core Classes”| Class | Description |
|---|---|
Packet | Base interface for all network packets |
ToClientPacket | Marker interface for server-to-client packets |
ToServerPacket | Marker interface for client-to-server packets |
NetworkChannel | Enum defining packet routing channels |
PacketRegistry | Central registry of packet types |
PacketHandler | Abstract handler for packet processing |
PacketIO | Packet serialization/deserialization |
PacketAdapters | Plugin packet interception system |
Packet Interface
Section titled “Packet Interface”All packets implement the Packet interface:
package com.hypixel.hytale.protocol;
public interface Packet { int getId(); void serialize(@Nonnull ByteBuf buf); int computeSize(); NetworkChannel getChannel();}Packet Direction System
Section titled “Packet Direction System”Network Channel System
Section titled “Network Channel System”Packet Constants
Section titled “Packet Constants”Each packet class defines:
public class ExamplePacket implements Packet { public static final int PACKET_ID = 123; public static final boolean IS_COMPRESSED = false; public static final int MAX_SIZE = 256;
// Fields...
@Override public int getId() { return PACKET_ID; }
@Override public void serialize(@Nonnull ByteBuf buf) { // Write fields to buffer }
public static ExamplePacket deserialize(@Nonnull ByteBuf buf, int offset) { // Read fields from buffer }
@Override public int computeSize() { return MAX_SIZE; }}Packet Categories
Section titled “Packet Categories”The protocol defines ~354 packet types across 18 categories:
| Category | Package | Description |
|---|---|---|
connection | packets.connection | Connect, Disconnect, Ping, Pong |
auth | packets.auth | Authentication tokens and passwords |
player | packets.player | Movement, teleport, inventory actions |
entities | packets.entities | Spawn, despawn, animation, knockback |
world | packets.world | Chunks, blocks, sounds, weather |
interface_ | packets.interface_ | Chat, notifications, UI state |
inventory | packets.inventory | Item drops, stack moves, container ops |
assets | packets.assets | Item/block/particle/effect updates |
interaction | packets.interaction | Mount, interaction triggers |
setup | packets.setup | Initial asset and feature setup |
window | packets.window | Dialog and window management |
camera | packets.camera | Camera shake, fly mode |
buildertools | packets.buildertools | World editing tools |
machinima | packets.machinima | Cinematic scene control |
asseteditor | packets.asseteditor | Asset editor operations |
worldmap | packets.worldmap | Map markers |
serveraccess | packets.serveraccess | Access control |
PacketHandler
Section titled “PacketHandler”PacketHandler is the abstract base class for handling packets:
package com.hypixel.hytale.server.core.io;
public abstract class PacketHandler implements IPacketReceiver { public void write(@Nonnull Packet packet); public void writeNoCache(@Nonnull Packet packet); public void write(@Nonnull Packet... packets); public void write(@Nonnull Packet[] packets, @Nonnull Packet finalPacket); public void writePacket(@Nonnull Packet packet, boolean cache);
public void sendPing(); public void handlePong(@Nonnull Pong packet); public void tickPing(float dt);
public final void registered(@Nullable PacketHandler oldHandler); public final void unregistered(@Nullable PacketHandler newHandler);
public void disconnect(@Nonnull String message);
public abstract void accept(@Nonnull Packet packet);}Handler Types
Section titled “Handler Types”| Handler | Description |
|---|---|
GenericPacketHandler | Generic connection handler |
GenericConnectionPacketHandler | Connection-specific handler |
InitialPacketHandler | Initial connection phase |
GamePacketHandler | In-game player packets |
SubPacketHandler | Custom sub-handlers |
Packet Adapters
Section titled “Packet Adapters”Plugins can intercept packets using the adapter system:
package com.hypixel.hytale.server.core.io.adapter;
public class PacketAdapters { // Watch/filter inbound packets (client → server) public static PacketFilter registerInbound(@Nonnull PacketWatcher watcher); public static PacketFilter registerInbound(@Nonnull PlayerPacketWatcher watcher); public static PacketFilter registerInbound(@Nonnull PlayerPacketFilter filter);
// Watch/filter outbound packets (server → client) public static PacketFilter registerOutbound(@Nonnull PacketWatcher watcher); public static PacketFilter registerOutbound(@Nonnull PlayerPacketWatcher watcher); public static PacketFilter registerOutbound(@Nonnull PlayerPacketFilter filter);
// Deregister adapters public static void deregisterInbound(PacketFilter predicate); public static void deregisterOutbound(PacketFilter predicate);}Adapter Interfaces
Section titled “Adapter Interfaces”// Watch any packet (receives the PacketHandler, not the player)@FunctionalInterfacepublic interface PacketWatcher extends BiConsumer<PacketHandler, Packet> { void accept(PacketHandler handler, Packet packet);}
// Watch player-specific packetspublic interface PlayerPacketWatcher extends BiConsumer<PlayerRef, Packet> { void accept(PlayerRef player, Packet packet);}
// Filter player packets (return true to block, false to allow)public interface PlayerPacketFilter extends BiPredicate<PlayerRef, Packet> { boolean test(PlayerRef player, Packet packet);}
// Low-level filter (operates on PacketHandler directly)public interface PacketFilter extends BiPredicate<PacketHandler, Packet> { boolean test(PacketHandler handler, Packet packet);}Watching Packets
Section titled “Watching Packets”import com.hypixel.hytale.protocol.Packet;import com.hypixel.hytale.protocol.packets.interface_.ChatMessage;import com.hypixel.hytale.server.core.io.adapter.PacketAdapters;import com.hypixel.hytale.server.core.io.adapter.PacketFilter;import com.hypixel.hytale.server.core.io.adapter.PlayerPacketWatcher;import com.hypixel.hytale.server.core.universe.PlayerRef;
public class MyPlugin extends JavaPlugin { private PacketFilter chatWatcher;
@Override protected void setup() { // Watch chat messages chatWatcher = PacketAdapters.registerInbound( (PlayerPacketWatcher) (player, packet) -> { if (packet instanceof ChatMessage chat) { getLogger().info(player.getUsername() + " sent: " + chat.message); } } ); }
@Override protected void shutdown() { // Clean up adapter PacketAdapters.deregisterInbound(chatWatcher); }}Filtering Packets
Section titled “Filtering Packets”import com.hypixel.hytale.protocol.packets.interface_.ChatMessage;import com.hypixel.hytale.server.core.io.adapter.PacketAdapters;import com.hypixel.hytale.server.core.io.adapter.PlayerPacketFilter;
PacketFilter filter = PacketAdapters.registerInbound( (PlayerPacketFilter) (player, packet) -> { if (packet instanceof ChatMessage chat) { if (chat.message.contains("banned_word")) { return true; // true = block/consume the packet } } return false; // false = allow the packet through });Sending Packets
Section titled “Sending Packets”Send packets to players through their packet handler:
import com.hypixel.hytale.protocol.packets.interface_.ChatMessage;import com.hypixel.hytale.server.core.universe.PlayerRef;
public void sendMessage(PlayerRef player, String message) { ChatMessage packet = new ChatMessage(); packet.message = message;
// Send to player player.getPacketHandler().write(packet);}
// Send multiple packetspublic void sendMultiple(PlayerRef player, Packet... packets) { player.getPacketHandler().write(packets);}Wire Protocol
Section titled “Wire Protocol”Packet Frame Format
Section titled “Packet Frame Format”┌─────────────────────────────────────────────┐│ 4 bytes │ 4 bytes │ N bytes ││ Length │ Packet │ Payload ││ (LE) │ ID (LE) │ (compressed/raw) │└─────────────────────────────────────────────┘Compression
Section titled “Compression”- Uses Zstd (Zstandard) compression
- Compression level configurable via
hytale.protocol.compressionLevel - Individual packets opt-in/out via
IS_COMPRESSEDconstant - Max uncompressed payload: 1,677,721,600 bytes
Transport Layer
Section titled “Transport Layer”The networking system supports multiple transports:
package com.hypixel.hytale.server.core.io.transport;
public interface Transport { TransportType getType(); ChannelFuture bind(InetSocketAddress address) throws InterruptedException; void shutdown();}Transport Types
Section titled “Transport Types”| Transport | Class | Description |
|---|---|---|
| TCP | TCPTransport | Standard TCP connections |
| QUIC | QUICTransport | QUIC protocol support |
Ping Monitoring
Section titled “Ping Monitoring”Three ping metrics are tracked per connection:
| Type | Description |
|---|---|
Raw | Raw network latency |
Direct | Direct tick-based ping |
Tick | Game tick synchronized ping |
Metrics include min, max, average, and 99th percentile over 1s, 1m, and 5m windows.
Common Packets
Section titled “Common Packets”Connection
Section titled “Connection”| Packet | Direction | Description |
|---|---|---|
Connect | C→S | Initial connection request |
Disconnect | Both | Connection termination |
Ping | S→C | Latency measurement request |
Pong | C→S | Latency measurement response |
Player
Section titled “Player”| Packet | Direction | Description |
|---|---|---|
PlayerMovement | C→S | Player position/rotation update |
PlayerTeleport | S→C | Server-initiated teleport |
PlayerInventory | S→C | Inventory state sync |
| Packet | Direction | Description |
|---|---|---|
SetChunk | S→C | Chunk data |
ServerSetBlock | S→C | Block change |
SoundEvent | S→C | Sound playback |
Interface
Section titled “Interface”| Packet | Direction | Description |
|---|---|---|
ChatMessage | Both | Chat message |
Notification | S→C | UI notification |
Best Practices
Section titled “Best Practices”- Clean up adapters: Always deregister packet adapters in
shutdown() - Check packet types: Use
instanceofto identify packet types - Minimize filtering: Filters run on every packet; keep them efficient
- Use appropriate transport: TCP for reliability, QUIC for performance
- Respect packet limits: Don’t exceed
MAX_SIZEfor packets
Limitations
Section titled “Limitations”- Cannot create new packet types at runtime
- Packet serialization format is fixed per type
- No direct access to Netty channels
Related
Section titled “Related”- Event System - Server events
- Entity System - Entity packets
- World System - World packets