10 KiB
Networking and Protocol
The Hytale server uses a packet-based networking system for client-server communication. This guide covers the protocol system, packet types, and how to work with networking in your mods.
Overview
The networking layer is built on QUIC protocol and handles:
- Client connections and authentication
- Game state synchronization
- Player input handling
- Entity updates
- World data streaming
- UI communication
Key Components
| Component | Description |
|---|---|
Packet |
Base interface for all packets |
PacketRegistry |
Central packet type registration |
PacketHandler |
Manages client connections and packet processing |
ServerManager |
Server network manager |
Packet Categories
Packets are organized into categories in com.hypixel.hytale.protocol.packets:
| Category | Description |
|---|---|
connection/ |
Connection lifecycle (connect, disconnect, ping) |
auth/ |
Authentication and session management |
player/ |
Player-specific packets (movement, actions) |
entities/ |
Entity creation, updates, removal |
world/ |
World/chunk data streaming |
inventory/ |
Inventory operations |
interaction/ |
Player interactions |
interface_/ |
UI/interface packets |
camera/ |
Camera control |
setup/ |
Initial setup and configuration |
window/ |
Window/container management |
assets/ |
Asset loading and management |
asseteditor/ |
Asset editor tools (dev) |
buildertools/ |
Building tools |
machinima/ |
Machinima/cinematic tools |
serveraccess/ |
Server access control |
worldmap/ |
World map data |
Packet Structure
Packet Interface
All packets implement the Packet interface:
public interface Packet {
// Packets are typically data classes
// with fields for the packet data
}
Example Packet
public class PlayerPositionPacket implements Packet {
private final UUID playerId;
private final Vector3d position;
private final float yaw;
private final float pitch;
public PlayerPositionPacket(UUID playerId, Vector3d position, float yaw, float pitch) {
this.playerId = playerId;
this.position = position;
this.yaw = yaw;
this.pitch = pitch;
}
public UUID getPlayerId() { return playerId; }
public Vector3d getPosition() { return position; }
public float getYaw() { return yaw; }
public float getPitch() { return pitch; }
}
Client Sessions
Managing Clients
// Get the server manager
ServerManager serverManager = ServerManager.get();
// Get handler for a client
PacketHandler handler = serverManager.getHandler(channel);
// Send packet to client
handler.sendPacket(packet);
// Send multiple packets
handler.sendPackets(Arrays.asList(packet1, packet2, packet3));
Client Events
// Player connected
getEventRegistry().register(PlayerConnectEvent.class, event -> {
Player player = event.getPlayer();
// Handle connection
});
// Player disconnected
getEventRegistry().register(PlayerDisconnectEvent.class, event -> {
Player player = event.getPlayer();
// Handle disconnection
});
Sending Packets to Players
Single Player
Player player = getPlayer();
// Send a packet
player.sendPacket(new MyPacket(data));
Multiple Players
// Send to all players
for (Player player : Universe.get().getPlayers()) {
player.sendPacket(packet);
}
// Send to players in a world
World world = Universe.get().getWorld("default");
for (Player player : world.getPlayers()) {
player.sendPacket(packet);
}
// Broadcast to all
Universe.get().broadcast(packet);
Area-Based Broadcasting
// Send to players near a position
Vector3d center = new Vector3d(100, 64, 100);
double radius = 50.0;
for (Player player : Universe.get().getPlayers()) {
if (player.getPosition().distance(center) <= radius) {
player.sendPacket(packet);
}
}
Common Packet Types
Connection Packets
| Packet | Direction | Description |
|---|---|---|
ConnectionRequestPacket |
C->S | Client requests connection |
ConnectionResponsePacket |
S->C | Server accepts/rejects connection |
DisconnectPacket |
Both | Connection termination |
PingPacket |
Both | Latency measurement |
Player Packets
| Packet | Direction | Description |
|---|---|---|
PlayerPositionPacket |
Both | Position update |
PlayerInputPacket |
C->S | Player input (movement, actions) |
PlayerActionPacket |
C->S | Player actions |
Entity Packets
| Packet | Direction | Description |
|---|---|---|
EntitySpawnPacket |
S->C | Entity creation |
EntityUpdatePacket |
S->C | Entity state update |
EntityRemovePacket |
S->C | Entity removal |
EntityMovePacket |
S->C | Entity movement |
World Packets
| Packet | Direction | Description |
|---|---|---|
ChunkDataPacket |
S->C | Chunk data transfer |
BlockChangePacket |
S->C | Block state change |
WorldTimePacket |
S->C | World time sync |
Inventory Packets
| Packet | Direction | Description |
|---|---|---|
InventoryUpdatePacket |
S->C | Inventory contents |
SlotChangePacket |
Both | Single slot update |
ItemPickupPacket |
S->C | Item pickup notification |
Rate Limiting
The server includes built-in rate limiting for packet handling:
// Configuration in HytaleServerConfig
RateLimitConfig {
enabled: boolean // Enable rate limiting
packetsPerSecond: int // Max packets per second
burstCapacity: int // Burst allowance
}
Rate limiting protects against packet spam and potential exploits.
Connection Timeouts
// Configuration in HytaleServerConfig
ConnectionTimeouts {
initialTimeout: Duration // Initial connection timeout
authTimeout: Duration // Authentication timeout
playTimeout: Duration // Gameplay timeout
joinTimeouts: Map<String, Duration> // Per-world join timeouts
}
Custom Packet Handling
Receiving Packets (Server-Side)
To handle incoming packets, use the receiver system:
// Register a packet receiver
getPacketReceiverRegistry().register(MyCustomPacket.class, (player, packet) -> {
// Handle the packet
String data = packet.getData();
processData(player, data);
});
Custom Packet Registration
For advanced mods that need custom packet types:
// Define a custom packet with codec
public class MyCustomPacket implements Packet {
public static final Codec<MyCustomPacket> CODEC = BuilderCodec.of(MyCustomPacket::new)
.with("data", Codec.STRING, p -> p.data)
.build();
private final String data;
public MyCustomPacket(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
UI Communication
Server UI Pages
The server can send UI pages to clients:
// Send a UI page to player
player.showUI(new MyUIPage(data));
// Close UI
player.closeUI();
UI Packets
| Packet | Direction | Description |
|---|---|---|
UIOpenPacket |
S->C | Open a UI screen |
UIClosePacket |
S->C | Close UI |
UIUpdatePacket |
S->C | Update UI data |
UIInteractionPacket |
C->S | UI button/element interaction |
Network Compression
The server supports packet compression for bandwidth optimization:
// In server config
localCompressionEnabled: boolean
When enabled, large packets are compressed before transmission.
Authentication
Auth Flow
- Client sends
ConnectionRequestPacket - Server validates and sends auth challenge
- Client responds with credentials
- Server verifies and sends
ConnectionResponsePacket - If successful, player enters play state
Auth Events
// Handle authentication
getEventRegistry().register(PlayerAuthEvent.class, event -> {
Player player = event.getPlayer();
// Custom auth logic
if (!isAuthorized(player)) {
event.setCancelled(true);
event.setKickMessage("Not authorized!");
}
});
Best Practices
- Minimize packet size - Only send necessary data
- Batch updates - Combine multiple small updates into single packets when possible
- Use appropriate packet types - Don't repurpose packets for unintended uses
- Handle disconnections gracefully - Clean up resources when players disconnect
- Respect rate limits - Don't spam packets to clients
- Validate incoming data - Never trust client data without validation
- Use async for heavy operations - Don't block the network thread
- Consider bandwidth - Players may have limited bandwidth
- Test latency scenarios - Test with simulated network delays
- Secure sensitive operations - Validate permissions server-side
Security Considerations
- Never trust client data - Always validate on the server
- Use server authority - Server is the source of truth for game state
- Validate permissions - Check permissions before processing sensitive packets
- Rate limit custom packets - Prevent abuse of custom packet handlers
- Sanitize inputs - Prevent injection attacks in text data