Files
hytale-server/docs/07-networking.md

349 lines
9.2 KiB
Markdown

# 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:
```java
public interface Packet {
// Packets are typically data classes
// with fields for the packet data
}
```
### Example Packet
```java
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
```java
// 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
```java
// 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
```java
Player player = getPlayer();
// Send a packet
player.sendPacket(new MyPacket(data));
```
### Multiple Players
```java
// 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
```java
// 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:
```java
// 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
```java
// 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:
```java
// 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:
```java
// 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:
```java
// 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:
```java
// In server config
localCompressionEnabled: boolean
```
When enabled, large packets are compressed before transmission.
## Authentication
### Auth Flow
1. Client sends `ConnectionRequestPacket`
2. Server validates and sends auth challenge
3. Client responds with credentials
4. Server verifies and sends `ConnectionResponsePacket`
5. If successful, player enters play state
### Auth Events
```java
// 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
1. **Minimize packet size** - Only send necessary data
2. **Batch updates** - Combine multiple small updates into single packets when possible
3. **Use appropriate packet types** - Don't repurpose packets for unintended uses
4. **Handle disconnections gracefully** - Clean up resources when players disconnect
5. **Respect rate limits** - Don't spam packets to clients
6. **Validate incoming data** - Never trust client data without validation
7. **Use async for heavy operations** - Don't block the network thread
8. **Consider bandwidth** - Players may have limited bandwidth
9. **Test latency scenarios** - Test with simulated network delays
10. **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