349 lines
9.2 KiB
Markdown
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
|