HyCodeYourTale

Networking

Networking

Dokumentace k síťové komunikaci v Hytale.

Obsah

| Soubor | Popis |
|--------|-------|
| PACKETS.md | PacketRegistry, PacketHandler, CachedPacket, GamePacketHandler, SubPacketHandler |
| SYNCHRONIZATION.md | NetworkId, EntityViewer, Visible, ComponentUpdateType, EntityTrackerSystems |

---

Přehled

Hytale používá vlastní síťový protokol pro komunikaci mezi serverem a klientem. Server běží na více vláknech:

Main Thread
├── World Thread (default)
├── World Thread (nether)
├── Scheduler Thread
└── Network Thread <- Zpracování paketů

---

Entity Synchronizace

NetworkId Komponenta

Pro síťovou synchronizaci entity:

// Přidej NetworkId ke každé entitě kterou chceš synchronizovat
holder.addComponent(
NetworkId.getComponentType(),
new NetworkId(store.getExternalData().takeNextNetworkId())
);

ComponentUpdateType

Typy synchronizovaných komponent:

| Typ | Popis |
|-----|-------|
| Transform | Pozice a rotace |
| Model | 3D model |
| PlayerSkin | Skin hráče |
| Item | Item v ruce |
| Block | Block data |
| Equipment | Vybavení |
| EntityStats | Statistiky |
| Nameplate | Jmenovka |
| UIComponents | UI komponenty |
| CombatText | Bojový text |
| MovementStates | Stav pohybu |
| EntityEffects | Efekty |
| DynamicLight | Dynamické světlo |
| Audio | Zvuky |
| ActiveAnimations | Animace |

---

Pakety

EntityUpdates

Pro hromadnou aktualizaci entit:

// Z dekompilovaného kódu:
// Limit: 4,096,000 entit na paket

MapMarker

Pro world map markery:

// Vytvoření markeru
new MapMarker(
id, // Unikátní ID
name, // Zobrazený název
"Icon.png", // Ikona
transformPacket, // Pozice
null // Extra data
);

---

Odesílání Zpráv

Player.sendMessage()

// Odeslání zprávy hráči
player.sendMessage(Message.raw("Hello!"));

// S překladem
player.sendMessage(
Message.translation("server.welcome")
.param("name", player.getName())
);

PlayerRef.sendMessage()

// Přes PlayerRef
playerRef.sendMessage(Message.raw("Message via ref"));

CommandContext.sendMessage()

// V příkazu
context.sendMessage(Message.raw("Command response"));

---

Multi-Server Architektura

Universe

// Získání universe instance
Universe universe = Universe.get();

// Všichni online hráči
Collection players = universe.getPlayers();

// Hráč podle UUID
Player player = universe.getPlayer(uuid);

// Svět podle jména
World world = universe.getWorld("default");

// Cesta k datům
Path universePath = universe.getPath();

World

// Získání světa
World world = player.getWorld();

// Jméno světa
String name = world.getName();

// Konfigurace
WorldConfig config = world.getWorldConfig();

// Entity store
EntityStore entityStore = world.getEntityStore();

// Spuštění na world threadu
world.execute(() -> {
// Bezpečné operace
});

---

Thread Safety v Síťování

Network Thread → World Thread

// Paket přijde na Network threadu
// Pro přístup ke komponentám potřebuješ world.execute()

onPacketReceived(packet -> {
Player player = getPlayerFromPacket(packet);
World world = player.getWorld();

world.execute(() -> {
// Bezpečný přístup ke komponentám
Ref ref = player.getRef();
Store store = ref.getStore();
// ...
});
});

World Thread → Network Thread

// Odesílání paketů je bezpečné z jakéhokoliv vlákna
// Hytale interně zajišťuje thread-safe frontu

player.sendMessage(Message.raw("Safe from any thread"));

---

Tracker System

WorldMapTracker

// Sledování markerů na mapě
tracker.trySendMarker(
chunkViewRadius,
playerChunkX,
playerChunkZ,
position,
yaw,
markerId,
markerName,
dataObject,
markerFactory
);

Entity Tracking

// Entity jsou automaticky trackované podle:
// - Vzdálenosti od hráče
// - Chunk visibility
// - ComponentUpdateType

---

Chunk Networking

ChunkUtil

// Kontrola zda je pozice v chunku
boolean inside = ChunkUtil.isInsideChunk(
chunkX, chunkZ,
MathUtil.floor(position.x),
MathUtil.floor(position.z)
);

Chunk Loading

// Event při načítání chunku
getEventRegistry().registerGlobal(ChunkPreLoadProcessEvent.class, event -> {
WorldChunk chunk = event.getChunk();
BlockChunk blockChunk = chunk.getBlockChunk();

if (blockChunk != null) {
int chunkX = blockChunk.getX();
int chunkZ = blockChunk.getZ();
// ...
}
});

---

Best Practices

1. Minimalizuj Síťový Traffic

// Špatně - posílá se příliš často
for (Player player : allPlayers) {
player.sendMessage(Message.raw("Update!"));
}

// Lépe - batching
Message batchedMessage = buildBatchedMessage(updates);
for (Player player : relevantPlayers) {
player.sendMessage(batchedMessage);
}

2. Validuj Data ze Sítě

// Vždy validuj příchozí data
public void handleClientRequest(Player player, RequestData data) {
// Kontrola oprávnění
if (!canPerformAction(player, data.action)) {
return;
}

// Validace dat
if (!isValidRequest(data)) {
return;
}

// Zpracování
processRequest(player, data);
}

3. Používej Async pro I/O

// Async operace mimo hlavní vlákna
CompletableFuture.runAsync(() -> {
// Network I/O, databáze, soubory
}).thenRun(() -> {
// Callback po dokončení
});

---

Shrnutí

| Komponenta | Účel |
|------------|------|
| NetworkId | Síťová identifikace entity |
| Universe | Globální server state |
| World | Jednotlivý svět |
| WorldMapTracker | Sledování map markerů |
| ChunkUtil | Chunk operace |

| Operace | Thread |
|---------|--------|
| Příjem paketů | Network Thread |
| Přístup ke komponentám | World Thread |
| Odesílání zpráv | Jakýkoliv |
| Odesílání paketů | Jakýkoliv (interně queued) |

Last updated: 20. ledna 2026