View on GitHub

FOnline Engine

Flexible cross-platform isometric game engine

Networking

This document explains the reusable engine networking layers: message buffers, debug/hash handling, legacy net commands, client/server connection abstractions, and the ordered UDP transport.

Use it when changing Source/Common/NetBuffer.*, NetCommand.*, NetworkUdp.*, Source/Client/NetworkClient*, Source/Server/NetworkServer*, or network tests.

Ownership model

The engine owns transport abstractions, message framing, ordered UDP behavior, and client/server connection interfaces. An embedding project owns deployment topology, public server addresses, operational policy, and game-specific command usage.

Do not document project-specific hosts, ports, or release infrastructure here.

Source paths inspected

Message buffers

Source/Common/NetBuffer.h defines the shared binary message layer:

Important constants:

NetOutBuffer responsibilities:

NetInBuffer responsibilities:

Property synchronization and entity state transfer should go through these helpers instead of hand-rolled byte layouts.

Hashes and debug hashes

Network buffers can serialize hstring values. NetOutBuffer can be created with debug_hashes, and NetInBuffer resolves hashed strings through a HashResolver.

When changing hash serialization, inspect both generated metadata/hash registration and runtime network consumers. Debug hash behavior is especially important for diagnosing missing hash names across client/server builds.

Net commands

Source/Common/NetCommand.h contains legacy/admin-style command IDs and PackNetCommand():

PackNetCommand() converts command text into an outgoing network buffer using a log callback and hash resolver.

Treat command IDs as wire-level compatibility points. If they change, update server/client handling and tests together.

Client connection abstraction

Source/Client/NetworkClient.h defines NetworkClientConnection.

The public surface is transport-neutral:

Factory methods choose transport implementation:

Concrete files include:

The client runtime should depend on the abstract connection interface where possible; transport-specific behavior belongs in the implementation files.

Server connection abstraction

Source/Server/NetworkServer.h defines two server-side abstractions:

NetworkServerConnection owns callback registration and dispatch:

NetworkServer starts transport-specific servers through factories:

Concrete files include:

Ordered UDP transport

Source/Common/NetworkUdp.h implements an ordered/reliable payload layer over UDP.

Packet types:

UdpTransportOptions controls:

UdpPacketInfo carries parsed packet data:

UdpOrderedChannel owns session state and reliable ordering:

Standalone helpers:

When changing UDP behavior, validate acknowledgement handling, pending-byte limits, resend timing, packet parsing, disconnect handling, and redundant tail packets.

Relationship to entity and property state

Entity/property synchronization uses property metadata to decide what can be sent and network buffers to serialize the data.

Relevant property flags from EntityModel.md:

A network change that affects property replication should be reviewed together with entity/property docs and tests.

Transport selection

The source tree supports several connection families:

Build availability is controlled by compile-time feature toggles and platform dependencies. For build toggles and package workflow, see BuildWorkflow.md and BuildToolsPipeline.md.

Tests to inspect

Relevant tests include:

Change routing

Validation checklist

  1. Run UDP, client, and server network tests relevant to the changed transport.
  2. Validate both connect/accept and disconnect paths.
  3. Validate partial receives and message framing when changing NetInBuffer / NetOutBuffer.
  4. Validate hash resolution/debug-hash behavior across client and server builds.
  5. Validate property synchronization when message layout or property-data serialization changes.
  6. Validate platform-specific transport availability when touching ASIO/WebSocket/socket code.