Skip to content

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.

  • 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
┌─────────────────────────────────────────────────────────────────┐
│ Networking Architecture │
│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ │
│ │ Client │◄──►│ Transport │◄──►│ PacketHandler │ │
│ │ │ │ (TCP/QUIC) │ │ │ │
│ └───────────────┘ └───────────────┘ └────────┬────────┘ │
│ │ │
│ ┌──────────────────────────────┼──────┐ │
│ │ Adapter Pipeline │ │ │
│ │ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │Inbound │ │Outbound │ │ │ │
│ │ │Adapters │ │Adapters │ │ │ │
│ │ └─────────┘ └─────────┘ │ │ │
│ └──────────────────────────────┘ │ │
│ │ │
│ ┌──────────────────────────────▼──────┐ │
│ │ Game Logic / Plugins │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
ClassDescription
PacketInterface for all network packets
PacketRegistryCentral registry of packet types
PacketHandlerAbstract handler for packet processing
PacketIOPacket serialization/deserialization
PacketAdaptersPlugin packet interception system

All packets implement the Packet interface:

package com.hypixel.hytale.protocol;
public interface Packet {
int getId();
void serialize(@Nonnull ByteBuf buf);
int computeSize();
}

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;
}
}

The protocol defines ~354 packet types across 18 categories:

CategoryPackageDescription
connectionpackets.connectionConnect, Disconnect, Ping, Pong
authpackets.authAuthentication tokens and passwords
playerpackets.playerMovement, teleport, inventory actions
entitiespackets.entitiesSpawn, despawn, animation, knockback
worldpackets.worldChunks, blocks, sounds, weather
interface_packets.interface_Chat, notifications, UI state
inventorypackets.inventoryItem drops, stack moves, container ops
assetspackets.assetsItem/block/particle/effect updates
interactionpackets.interactionMount, interaction triggers
setuppackets.setupInitial asset and feature setup
windowpackets.windowDialog and window management
camerapackets.cameraCamera shake, fly mode
buildertoolspackets.buildertoolsWorld editing tools
machinimapackets.machinimaCinematic scene control
asseteditorpackets.asseteditorAsset editor operations
worldmappackets.worldmapMap markers
serveraccesspackets.serveraccessAccess control

PacketHandler is the abstract base class for handling packets:

package com.hypixel.hytale.server.core.io;
public abstract class PacketHandler implements IPacketReceiver {
// Send single packet
public void write(@Nonnull Packet packet);
// Send packet bypassing cache
public void writeNoCache(@Nonnull Packet packet);
// Send multiple packets
public void write(@Nonnull Packet... packets);
// Send packets with final packet
public void write(@Nonnull Packet[] packets, @Nonnull Packet finalPacket);
// Internal write with cache control
public void writePacket(@Nonnull Packet packet, boolean cache);
// Ping management
public void sendPing();
public void handlePong(@Nonnull Pong packet);
public void tickPing(float dt);
// Lifecycle hooks
public void registered(@Nullable PacketHandler oldHandler);
public void unregistered(@Nullable PacketHandler newHandler);
// Abstract: handle incoming packet
public abstract void accept(@Nonnull Packet packet);
}
HandlerDescription
GenericPacketHandlerGeneric connection handler
GenericConnectionPacketHandlerConnection-specific handler
InitialPacketHandlerInitial connection phase
GamePacketHandlerIn-game player packets
SubPacketHandlerCustom sub-handlers

Plugins can intercept packets using the adapter system:

package com.hypixel.hytale.server.core.io.adapter;
public final 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);
}
// Watch any packet
public interface PacketWatcher {
void onPacket(Packet packet);
}
// Watch player-specific packets
public interface PlayerPacketWatcher {
void onPacket(PlayerRef player, Packet packet);
}
// Filter player packets (can modify/block)
public interface PlayerPacketFilter {
boolean filter(PlayerRef player, Packet packet);
}
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.player.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);
}
}
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;
// Block packets containing banned words
PacketFilter filter = PacketAdapters.registerInbound(
(PlayerPacketFilter) (player, packet) -> {
if (packet instanceof ChatMessage chat) {
if (chat.message.contains("banned_word")) {
return false; // Block packet
}
}
return true; // Allow packet
}
);

Send packets to players through their packet handler:

import com.hypixel.hytale.protocol.packets.interface_.ChatMessage;
import com.hypixel.hytale.server.core.player.PlayerRef;
public void sendMessage(PlayerRef player, String message) {
ChatMessage packet = new ChatMessage();
packet.message = message;
// Send to player
player.getPacketHandler().write(packet);
}
// Send multiple packets
public void sendMultiple(PlayerRef player, Packet... packets) {
player.getPacketHandler().write(packets);
}
┌─────────────────────────────────────────────┐
│ 4 bytes │ 4 bytes │ N bytes │
│ Length │ Packet │ Payload │
│ (LE) │ ID (LE) │ (compressed/raw) │
└─────────────────────────────────────────────┘
  • Uses Zstd (Zstandard) compression
  • Compression level configurable via hytale.protocol.compressionLevel
  • Individual packets opt-in/out via IS_COMPRESSED constant
  • Max uncompressed payload: 1,677,721,600 bytes

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();
}
TransportClassDescription
TCPTCPTransportStandard TCP connections
QUICQUICTransportQUIC protocol support

Three ping metrics are tracked per connection:

TypeDescription
RawRaw network latency
DirectDirect tick-based ping
TickGame tick synchronized ping

Metrics include min, max, average, and 99th percentile over 1s, 1m, and 5m windows.

PacketDirectionDescription
ConnectC→SInitial connection request
DisconnectBothConnection termination
PingS→CLatency measurement request
PongC→SLatency measurement response
PacketDirectionDescription
PlayerMovementC→SPlayer position/rotation update
PlayerTeleportS→CServer-initiated teleport
PlayerInventoryS→CInventory state sync
PacketDirectionDescription
SetChunkS→CChunk data
ServerSetBlockS→CBlock change
SoundEventS→CSound playback
PacketDirectionDescription
ChatMessageBothChat message
NotificationS→CUI notification
  1. Clean up adapters: Always deregister packet adapters in shutdown()
  2. Check packet types: Use instanceof to identify packet types
  3. Minimize filtering: Filters run on every packet; keep them efficient
  4. Use appropriate transport: TCP for reliability, QUIC for performance
  5. Respect packet limits: Don’t exceed MAX_SIZE for packets
  • Cannot create new packet types at runtime
  • Packet serialization format is fixed per type
  • No direct access to Netty channels