Update script to write to vendor/hytale-server
This commit is contained in:
348
docs/07-networking.md
Normal file
348
docs/07-networking.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user