netfishing/docs/ARCHITECTURE.md

3.8 KiB

Architecture

Composition

main/main.tscn is the application composition root. It owns long-lived services, the active world, player container, save/settings managers, and the pixelated UI viewport. Services are scene-owned rather than global autoloads, which makes their dependencies visible in the main scene and allows focused tests to instantiate the same composition.

The main script coordinates title, session, world, and UI lifecycle. Domain logic remains in typed resources and services rather than being stored solely in controls.

Domain boundaries

  • fish/ defines species, availability, catches, pools, quality, and selection.
  • fishing/ owns cast/chase state and resolves authoritative fishing surfaces.
  • inventory/, items/, economy/, progression/, and jobs/ own persistent player-facing game state.
  • world/ owns authored map composition and presentation. Water type is a shared typed definition used by water bodies, fish habitat, fishing validation, Logbook classification, and saltwater shoreline presentation.
  • ui/ observes and invokes domain services. It does not define stable item or fish identity.

Resource files (.tres) are authored data. Stable IDs, not display names or node names, connect persistent and networked state to that data.

Networking

NetworkSession owns ENet session lifecycle and peer registration. Dedicated network services validate and replicate bounded domains such as fishing, sales, shops, item use, profiles, jobs, mail, chat, drawings, time, and weather.

DiscoveryClient is an optional directory layer beside NetworkSession. An open host may publish a short-lived room lease, and the shared Join Game page may browse compatible leases before handing the selected address back to the existing direct ENet connection flow. The directory does not carry gameplay traffic or become a gameplay authority. Its base URL comes from network/discovery/base_url, with NETFISHING_DISCOVERY_URL available as a development/deployment override.

The host is authoritative. Clients submit requests or evidence; the host derives trusted context from registered peers, authoritative regions, and server-owned state before mutating inventory, wallet, progression, or shared world state. See decisions/0001-host-authority.md.

Protocol compatibility is defined in network/network_protocol.gd. A visible release version is not a reason to change the protocol number.

Persistence

PlayerDataRoot selects and validates a portable data root. Stores receive paths from that owner rather than inventing unrelated locations. Progression is written by PlayerSaveManager; device settings and social/identity stores have separate formats and lifecycles.

Save migrations are sequential and explicit. Existing catches and ownership are keyed by stable IDs so authored metadata can evolve without rewriting historical records. Current source constants—not documentation—are authoritative for format versions.

Presentation

Gameplay is rendered in 3D with the GL Compatibility renderer. The main UI is presented through a uniformly scaled SubViewport. Shared UI components and palette resources prevent page-specific geometry and style drift.

World presentation systems (time/weather visuals, procedural sky and water, shoreline ribbons, player blob shadows) do not own gameplay collision or network authority. Generated shoreline meshes are deterministic presentation resources baked from explicitly configured static terrain.

Validation

Tests are executable Godot SceneTree scripts. Some are pure content/domain checks, some instantiate the main scene, and multiplayer checks run paired host and client processes on loopback. The repository runner provides isolation and consistent entry points; see TESTING.md.