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
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
ClassDescription
PacketBase interface for all network packets
ToClientPacketMarker interface for server-to-client packets
ToServerPacketMarker interface for client-to-server packets
NetworkChannelEnum defining packet routing channels
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();
NetworkChannel getChannel();
}

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 {
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);
}
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 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 (receives the PacketHandler, not the player)
@FunctionalInterface
public interface PacketWatcher extends BiConsumer<PacketHandler, Packet> {
void accept(PacketHandler handler, Packet packet);
}
// Watch player-specific packets
public 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);
}
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);
}
}
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
}
);

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