Document project architecture and asset provenance
This commit is contained in:
parent
930acdb1a6
commit
866cc0fc06
10 changed files with 705 additions and 0 deletions
48
CONTRIBUTING.md
Normal file
48
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Contributing
|
||||
|
||||
NETfishing is currently developed through focused changes on the repository's
|
||||
active development branch. Coordinate scope with the project owner before
|
||||
starting substantial work.
|
||||
|
||||
## Change discipline
|
||||
|
||||
- Keep a change focused; avoid unrelated cleanup.
|
||||
- Inspect the working tree before editing and preserve existing work.
|
||||
- Do not change protocol, save, settings, identity, or portable-data versions
|
||||
as release-label housekeeping.
|
||||
- Treat the host as authoritative for catches, purchases, sales, jobs, mail,
|
||||
and other shared state.
|
||||
- Keep presentation-only systems out of save files and network messages.
|
||||
- Store runtime assets under repository-owned paths; never reference a
|
||||
workstation sync or temporary directory.
|
||||
- Record the source and license of newly imported assets.
|
||||
- Do not commit `.godot/`, test data, logs, captures, or build outputs.
|
||||
|
||||
## Before requesting review
|
||||
|
||||
```sh
|
||||
git diff --check
|
||||
scripts/run_validations.sh quick
|
||||
git status --short
|
||||
```
|
||||
|
||||
Choose additional focused tests from [`docs/TESTING.md`](docs/TESTING.md).
|
||||
Changes involving networking should run the network suite and a real
|
||||
two-process check. Visual changes still require graphical review; headless
|
||||
tests are supporting evidence, not a replacement.
|
||||
|
||||
## Commits
|
||||
|
||||
- Stage audited paths explicitly.
|
||||
- Use a concise imperative subject that describes the outcome.
|
||||
- Do not mix generated build artifacts with source changes.
|
||||
- Do not rewrite published release tags.
|
||||
- Describe behavior, compatibility impact, validation, and asset provenance in
|
||||
the review or release record.
|
||||
|
||||
## Style
|
||||
|
||||
Follow the conventions already present in the surrounding GDScript, scene, and
|
||||
resource files. Prefer typed values, named constants, shared resources, and
|
||||
small domain-specific services. Avoid duplicating protocol definitions or
|
||||
using display strings as persistent identifiers.
|
||||
50
CREDITS.md
Normal file
50
CREDITS.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Credits
|
||||
|
||||
## Project direction
|
||||
|
||||
NETfishing is designed, directed, reviewed, and released by its project
|
||||
creator. A public-facing creator or studio credit has not yet been recorded in
|
||||
this repository.
|
||||
|
||||
## Development assistance
|
||||
|
||||
Development has used automated coding assistance for implementation,
|
||||
investigation, testing, documentation, and review. Design choices, supplied
|
||||
artwork, acceptance decisions, repository operations, and releases remain
|
||||
human-controlled.
|
||||
|
||||
This disclosure is intentionally about process. Commit style, code style, or
|
||||
repository metadata cannot reliably prove whether a particular change was
|
||||
written with or without assistance.
|
||||
|
||||
## Fonts
|
||||
|
||||
- Tuffy: Thatcher Ulrich, Karoly Barta, and Michael Evans. The bundled license
|
||||
dedicates the work to the public domain; see `ui/fonts/Tuffy-LICENSE.txt`.
|
||||
- Seattle Avenue: bundled as `ui/fonts/seattle_avenue.otf`. Author and
|
||||
redistribution terms still need to be recorded before public distribution.
|
||||
|
||||
## Music
|
||||
|
||||
- `audio/music/title/as_in_four_wolves.ogg`: original title/ambient music by
|
||||
the project owner.
|
||||
|
||||
## Sound effects
|
||||
|
||||
- “Spinning reel.wav” by tosha73, used as the source for the fishing fight and
|
||||
manual-reeling loops. Freesound sound 509902, Creative Commons Zero (CC0):
|
||||
https://freesound.org/s/509902/
|
||||
- “Gentle Ocean Waves Loop” by kkenny101, used for the saltwater shoreline
|
||||
ambience. Freesound sound 852826, Creative Commons Zero (CC0):
|
||||
https://freesound.org/s/852826/
|
||||
- “Quick Water Droplet” by qubodup, used for the bobber water-impact sound.
|
||||
Freesound sound 792931, Creative Commons Zero (CC0):
|
||||
https://freesound.org/s/792931/
|
||||
|
||||
## Artwork
|
||||
|
||||
- 2D artwork: Rheannon Eisworth, contributor.
|
||||
- 3D models: original work by the project owner.
|
||||
|
||||
Asset categories and release-record requirements are listed in
|
||||
[`docs/ASSET-PROVENANCE.md`](docs/ASSET-PROVENANCE.md).
|
||||
82
README.md
Normal file
82
README.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# NETfishing
|
||||
|
||||
NETfishing is a multiplayer-first fishing game built with Godot 4.7. The
|
||||
current pre-alpha includes host-authoritative fishing and economy flows,
|
||||
freshwater and saltwater habitats, persistent player data, social features,
|
||||
customization, jobs, and a controller-aware interface.
|
||||
|
||||
The project is under active development. Interfaces, balance, content, and
|
||||
save migrations may continue to change before a stable release.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Godot 4.7.x with the GL Compatibility renderer
|
||||
- Linux, Windows, or an Android development environment supported by Godot
|
||||
- Bash for the repository helper scripts
|
||||
|
||||
Open `project.godot` in Godot, or start the editor from the repository root:
|
||||
|
||||
```sh
|
||||
godot --editor --path .
|
||||
```
|
||||
|
||||
Run the game directly with:
|
||||
|
||||
```sh
|
||||
godot --path .
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
The validation scripts isolate Godot's settings and application-data roots.
|
||||
Run the fast, deterministic suite before submitting a change:
|
||||
|
||||
```sh
|
||||
scripts/run_validations.sh quick
|
||||
```
|
||||
|
||||
Additional suites and individual commands are documented in
|
||||
[`docs/TESTING.md`](docs/TESTING.md).
|
||||
|
||||
## Building
|
||||
|
||||
Export presets are maintained for Linux, Windows, and Android. Repository
|
||||
scripts expect the matching Godot export templates and platform toolchains to
|
||||
already be installed:
|
||||
|
||||
```sh
|
||||
scripts/build_playtest.sh
|
||||
scripts/build_android_debug.sh
|
||||
```
|
||||
|
||||
Build outputs belong under the ignored `builds/` directory. Release builds
|
||||
must follow the project's separate tagged-release checklist; these convenience
|
||||
scripts do not create or publish tags.
|
||||
|
||||
## Project map
|
||||
|
||||
- `main/`: composition root and application orchestration
|
||||
- `world/`: map, environment, water, and world presentation
|
||||
- `player/`, `fishing/`, `fish/`: player and fishing domain
|
||||
- `network/`: transport, identity, and host-authoritative services
|
||||
- `inventory/`, `items/`, `economy/`, `progression/`, `jobs/`: game state
|
||||
- `save/`, `settings/`: versioned persistence
|
||||
- `ui/`: gameplay and menu presentation
|
||||
- `tests/`: focused Godot validation scripts
|
||||
- `scripts/`: build, bake, and validation entry points
|
||||
|
||||
See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) and
|
||||
[`world/README-WORLD-AUTHORING.md`](world/README-WORLD-AUTHORING.md) for more
|
||||
detail.
|
||||
|
||||
## Authorship and assets
|
||||
|
||||
NETfishing is human-directed and uses a mixture of human-authored assets and
|
||||
software-development assistance. The project records this plainly rather than
|
||||
claiming that repository history can prove how each line was produced. See
|
||||
[`CREDITS.md`](CREDITS.md) and
|
||||
[`docs/ASSET-PROVENANCE.md`](docs/ASSET-PROVENANCE.md).
|
||||
|
||||
No project-wide source license has been selected yet. Do not assume permission
|
||||
to redistribute the source or bundled assets beyond rights stated in their
|
||||
individual license records.
|
||||
72
docs/ARCHITECTURE.md
Normal file
72
docs/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# 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.
|
||||
|
||||
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`](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`](TESTING.md).
|
||||
109
docs/ASSET-PROVENANCE.md
Normal file
109
docs/ASSET-PROVENANCE.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# Asset provenance
|
||||
|
||||
This document records where runtime assets came from and what must be verified
|
||||
before redistribution. A Git commit proves when bytes entered this repository;
|
||||
it does not by itself prove authorship or licensing.
|
||||
|
||||
## Intake policy
|
||||
|
||||
For every new external or supplied asset, record:
|
||||
|
||||
- creator or supplying party;
|
||||
- original source location or delivery channel;
|
||||
- source filename and repository destination;
|
||||
- source and destination SHA-256 when copied without modification;
|
||||
- license or explicit permission;
|
||||
- any permitted transformations;
|
||||
- the importing commit or release.
|
||||
|
||||
Runtime resources must use `res://` paths. Workstation Sync folders are intake
|
||||
locations only and must never appear in scenes or resources.
|
||||
|
||||
## Current inventory
|
||||
|
||||
| Asset family | Repository location | Recorded provenance |
|
||||
| --- | --- | --- |
|
||||
| Fish art and portraits | `fish/species/`, `art/exported/fish/` | 2D artwork by contributor Rheannon Eisworth. |
|
||||
| Item icons | `items/icons/` | 2D artwork by contributor Rheannon Eisworth. |
|
||||
| Inventory notepad | `art/ui/ui_notepad.png` | 2D artwork by contributor Rheannon Eisworth; integrated without a runtime external path. |
|
||||
| Environment textures | `art/exported/environment/textures/` | 2D artwork by contributor Rheannon Eisworth. |
|
||||
| UI patterns | `art/patterns/` | 2D artwork by contributor Rheannon Eisworth. |
|
||||
| Character and world models | `art/exported/` | Original 3D models by the project owner. Any embedded 2D artwork is by Rheannon Eisworth. |
|
||||
| Tuffy font | `ui/fonts/Tuffy_Bold.otf` | Public-domain dedication in `ui/fonts/Tuffy-LICENSE.txt`. |
|
||||
| Seattle Avenue font | `ui/fonts/seattle_avenue.otf` | License and attribution not present; resolve before public distribution. |
|
||||
| Title music | `audio/music/title/as_in_four_wolves.ogg` | Original music composed and owned by the project owner. |
|
||||
| Fishing fight loop | `audio/sfx/fishing/fighting.wav` | Edited from “Spinning reel.wav” by Freesound user tosha73, sound 509902, CC0. |
|
||||
| Manual-reeling loop | `audio/sfx/fishing/reeling.wav` | Edited from the same CC0 “Spinning reel.wav” source. |
|
||||
| Saltwater wave ambience | `audio/ambience/waves.wav` | “Gentle Ocean Waves Loop” by Freesound user kkenny101, sound 852826, CC0. |
|
||||
| Bobber water impact | `audio/sfx/fishing/bobber.wav` | “Quick Water Droplet” by Freesound user qubodup, sound 792931, CC0. |
|
||||
|
||||
### Fishing fight loop source record
|
||||
|
||||
- Source page: https://freesound.org/s/509902/
|
||||
- Creator: tosha73
|
||||
- Source title: `Spinning reel.wav`
|
||||
- License: Creative Commons Zero (CC0)
|
||||
- Downloaded source filename: `509902__tosha73__spinning-reel.wav`
|
||||
- Downloaded source SHA-256:
|
||||
`9741afdb1ec9c73f5e039f0e5ac174998cb0a1f737b626531e63919d4d232fad`
|
||||
- Audacity working project: `fighting.aup3`
|
||||
- Audacity project SHA-256:
|
||||
`9928f077ecf48d01416f8d05700707e1b07d0f731846db80e27116f5b82dbbf5`
|
||||
- Runtime edit source/destination SHA-256:
|
||||
`b6f3f2f94bfaf9254ac04dd96b1fd28c15e1011a1db44bb3e70eeaa95de3c212`
|
||||
- Runtime format: 48 kHz, 16-bit, stereo PCM WAV; 2.593479 seconds;
|
||||
configured as a forward loop by the fishing presentation.
|
||||
- Manual-reeling Audacity project: `reeling.aup3`
|
||||
- Manual-reeling Audacity project SHA-256:
|
||||
`20ad52f6bdd16ae6561f06f8355fe309e95023e815053fd5dfbd5a5ce3c1f9f9`
|
||||
- Manual-reeling runtime source/destination SHA-256:
|
||||
`e403d5b7c8af1da4b28599cc0f51de3eda70d9e9296db27852fe7dc95617a29d`
|
||||
- Manual-reeling runtime format: 48 kHz, 16-bit, stereo PCM WAV;
|
||||
2.388083 seconds; configured as a forward loop.
|
||||
- The downloaded source and Audacity projects remain in the project owner's
|
||||
source-work archive; only the finished runtime edits ship in the game.
|
||||
|
||||
### Saltwater wave ambience source record
|
||||
|
||||
- Source page: https://freesound.org/s/852826/
|
||||
- Creator: kkenny101
|
||||
- Source title: `Gentle Ocean Waves Loop`
|
||||
- License: Creative Commons Zero (CC0)
|
||||
- Downloaded source filename:
|
||||
`852826__kkenny101__gentle-ocean-waves-loop.wav`
|
||||
- Downloaded source and runtime source/destination SHA-256:
|
||||
`f93e9890583f072ac52cf197b8b5942397d3d5e889fbdb9112a0776142f50229`
|
||||
- Runtime format: 48 kHz, 24-bit, mono PCM WAV; 21.769917 seconds;
|
||||
configured as a forward loop.
|
||||
- The downloaded source remains in the project owner's source-work archive;
|
||||
only the finished runtime loop ships in the game.
|
||||
|
||||
### Bobber water-impact source record
|
||||
|
||||
- Source page: https://freesound.org/s/792931/
|
||||
- Creator: qubodup
|
||||
- Source title: `Quick Water Droplet`
|
||||
- License: Creative Commons Zero (CC0)
|
||||
- Downloaded source filename: `792931__qubodup__quick-water-droplet.wav`
|
||||
- Downloaded source and runtime source/destination SHA-256:
|
||||
`aef0d16384efed4a7b071c4d80c21597617f882f4e0c1d5295ac194d315eafb7`
|
||||
- Runtime format: 48 kHz, 16-bit, mono PCM WAV; 0.197146 seconds; one-shot.
|
||||
- The downloaded source remains in the project owner's source-work archive;
|
||||
only the finished runtime sound ships in the game.
|
||||
|
||||
## Generated resources
|
||||
|
||||
Godot `.import` sidecars and deterministic shoreline `.tres` meshes are derived
|
||||
repository resources, not original artwork. `.godot/imported/`, editor caches,
|
||||
captures, exports, and temporary test data are not tracked.
|
||||
|
||||
## Release gate
|
||||
|
||||
Before a public binary or source release:
|
||||
|
||||
1. Resolve the Seattle Avenue font license and attribution gap above.
|
||||
2. Record the public owner/studio credit and the contributor's redistribution
|
||||
permission in the chosen project license or release records.
|
||||
3. Confirm the project-wide source/content license selected by the owner.
|
||||
4. Search exported resources for external filesystem paths.
|
||||
5. Preserve required third-party notices with the package.
|
||||
41
docs/BALANCE.md
Normal file
41
docs/BALANCE.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Balance and content notes
|
||||
|
||||
Balance is authored data and should change deliberately. This document records
|
||||
the policy; exact current values remain authoritative in `.tres` resources and
|
||||
typed scripts.
|
||||
|
||||
## Fish
|
||||
|
||||
- Stable fish IDs and catalog numbers must not be changed for display cleanup.
|
||||
- Species availability may constrain water type, time, weather, bait, and other
|
||||
authored context.
|
||||
- Location pools control selection weight; the global catalog remains
|
||||
comprehensive.
|
||||
- Freshwater/saltwater habitat is validated by the host in addition to pool
|
||||
membership.
|
||||
- Value, rarity, quality, and weight ranges should be reviewed together because
|
||||
they affect economy and catch difficulty.
|
||||
|
||||
## Economy and progression
|
||||
|
||||
- Sales and purchases are host-authoritative and must mutate inventory and
|
||||
wallet exactly once.
|
||||
- Reserved assets are rejected atomically; mixed valid/reserved batches must
|
||||
not partially succeed.
|
||||
- Item effects, shop prices, cooler capacity, fishing upgrades, jobs, and
|
||||
experience are separate balance axes. Avoid changing several in an unrelated
|
||||
presentation pass.
|
||||
|
||||
## Recording a balance change
|
||||
|
||||
Include in the change description:
|
||||
|
||||
1. affected stable IDs and resource paths;
|
||||
2. old and new values;
|
||||
3. intended player-facing outcome;
|
||||
4. interactions with quality, availability, and economy;
|
||||
5. deterministic validation performed;
|
||||
6. whether existing saves remain semantically valid.
|
||||
|
||||
Do not bump the save schema or network protocol simply because an authored
|
||||
number changed. Bump a format only when its serialized contract changes.
|
||||
63
docs/TESTING.md
Normal file
63
docs/TESTING.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Testing
|
||||
|
||||
NETfishing validations are Godot `SceneTree` scripts. They use assertions and
|
||||
exit nonzero on failure. Run them with isolated user data so development checks
|
||||
cannot touch real saves, identity, trust, relationships, or settings.
|
||||
|
||||
## Consolidated runner
|
||||
|
||||
```sh
|
||||
scripts/run_validations.sh quick
|
||||
scripts/run_validations.sh full
|
||||
scripts/run_validations.sh host
|
||||
scripts/run_validations.sh network
|
||||
scripts/run_validations.sh all
|
||||
scripts/run_validations.sh --list
|
||||
```
|
||||
|
||||
- `quick` runs deterministic content and domain validations.
|
||||
- `full` adds socket-free scene/runtime checks suitable for headless execution.
|
||||
- `host` runs single-process authoritative-host checks that bind a local UDP
|
||||
port.
|
||||
- `network` runs the loopback host/client validations in pairs.
|
||||
- `all` runs `full`, `host`, and then `network`.
|
||||
|
||||
Set `GODOT_BIN` to select another executable. Set `TEST_TIMEOUT_SECONDS` to
|
||||
change the per-process timeout. The runner creates one temporary XDG root per
|
||||
process and removes it on exit.
|
||||
|
||||
## One focused test
|
||||
|
||||
```sh
|
||||
test_root="$(mktemp -d)"
|
||||
XDG_DATA_HOME="$test_root/data" \
|
||||
XDG_CONFIG_HOME="$test_root/config" \
|
||||
godot --headless --path . --script tests/fish_catalog_content_validation.gd
|
||||
rm -rf -- "$test_root"
|
||||
```
|
||||
|
||||
Do not set `NETFISHING_DATA_DIR` to an arbitrary empty folder: that variable is
|
||||
an explicit portable-data override and must point at a valid NETfishing data
|
||||
root. Isolating XDG paths is sufficient for the validation scripts.
|
||||
|
||||
## Graphical checks
|
||||
|
||||
Headless tests cannot prove visual alignment, actual mouse routing, shader
|
||||
appearance, controller feel, or window-resize behavior. Presentation changes
|
||||
need a real graphical startup with isolated XDG roots and inspection at the
|
||||
canonical 1280×720 layout plus relevant low/high and ultrawide resolutions.
|
||||
|
||||
## Network checks
|
||||
|
||||
Host and paired tests bind loopback UDP ports defined in their scripts. Ensure
|
||||
no old Godot validation process is holding those ports and that the execution
|
||||
environment permits local sockets. The runner starts paired hosts before their
|
||||
clients and requires both processes to exit successfully. Network tests do not
|
||||
contact external servers.
|
||||
|
||||
## Release checks
|
||||
|
||||
A release audit additionally includes clean Git/tag verification, editor import,
|
||||
export-template checks, platform exports, executable smoke tests, archive
|
||||
inspection, and SHA-256 verification. Those checks are intentionally not hidden
|
||||
inside the development runner.
|
||||
27
docs/decisions/0001-host-authority.md
Normal file
27
docs/decisions/0001-host-authority.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# ADR 0001: Host-authoritative shared state
|
||||
|
||||
Status: accepted
|
||||
|
||||
## Context
|
||||
|
||||
NETfishing supports private hosts, open hosts, and joined clients. Catches,
|
||||
currency, owned items, jobs, mail, drawings, profiles, and moderation affect
|
||||
state that cannot safely trust a client's local presentation.
|
||||
|
||||
## Decision
|
||||
|
||||
The host validates requests against registered peers and host-owned context,
|
||||
then performs the authoritative mutation. Clients receive results and replicated
|
||||
presentation state. Client evidence is bounded and reconstructed where
|
||||
possible; it is not treated as authority.
|
||||
|
||||
Private single-player uses the same host path. Presentation-only state does not
|
||||
add RPCs or persistence.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Shared behavior is consistent across private, open-host, and joined-client
|
||||
modes.
|
||||
- Tests must cover local-host and paired host/client paths.
|
||||
- Stable protocol payloads and rejection cleanup require explicit handling.
|
||||
- UI activation cannot be used as proof that a server-side mutation succeeded.
|
||||
27
docs/decisions/0002-authored-data-and-stable-ids.md
Normal file
27
docs/decisions/0002-authored-data-and-stable-ids.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# ADR 0002: Authored resources and stable identifiers
|
||||
|
||||
Status: accepted
|
||||
|
||||
## Context
|
||||
|
||||
Fish, items, pools, availability, shop stock, and other game content evolve
|
||||
independently from saved catches and network messages. Display labels and scene
|
||||
node names are expected to change during development.
|
||||
|
||||
## Decision
|
||||
|
||||
Repository-owned resources are the authoritative authored data. Persistent and
|
||||
networked records refer to stable IDs. Display names, filenames, node names,
|
||||
coordinates, and pool names are not compatibility identifiers.
|
||||
|
||||
Cross-domain concepts such as water type use one typed definition rather than
|
||||
duplicated strings. Comprehensive catalogs remain separate from location-
|
||||
specific selection pools.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Renaming visible UI does not require save migration.
|
||||
- Removing or changing a stable ID requires an explicit compatibility plan.
|
||||
- Content validation checks uniqueness, catalog completeness, pool membership,
|
||||
and typed habitat compatibility.
|
||||
- New authored assets need provenance records as well as resource references.
|
||||
186
scripts/run_validations.sh
Executable file
186
scripts/run_validations.sh
Executable file
|
|
@ -0,0 +1,186 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
readonly PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
|
||||
readonly GODOT_BIN="${GODOT_BIN:-godot}"
|
||||
readonly TEST_TIMEOUT_SECONDS="${TEST_TIMEOUT_SECONDS:-120}"
|
||||
readonly RUN_ROOT="$(mktemp -d -t netfishing-validations.XXXXXX)"
|
||||
|
||||
readonly -a QUICK_TESTS=(
|
||||
"tests/android_readiness_validation.gd"
|
||||
"tests/fish_catalog_content_validation.gd"
|
||||
"tests/fish_quality_validation.gd"
|
||||
"tests/fishing_audio_validation.gd"
|
||||
"tests/fishing_surface_validation.gd"
|
||||
"tests/logbook_validation.gd"
|
||||
"tests/player_experience_validation.gd"
|
||||
"tests/shoreline_ambience_validation.gd"
|
||||
"tests/surface_drawing_validation.gd"
|
||||
"tests/terrain_projection_validation.gd"
|
||||
"tests/world_time_validation.gd"
|
||||
"tests/world_weather_validation.gd"
|
||||
)
|
||||
|
||||
readonly -a RUNTIME_TESTS=(
|
||||
"tests/inventory_notepad_art_validation.gd"
|
||||
"tests/logbook_runtime_validation.gd"
|
||||
"tests/player_experience_ui_validation.gd"
|
||||
"tests/ui_scaling_runtime_validation.gd"
|
||||
)
|
||||
|
||||
readonly -a HOST_TESTS=(
|
||||
"tests/art_tools_validation.gd"
|
||||
"tests/economy_regression_validation.gd"
|
||||
"tests/fish_hotbar_showcase_validation.gd"
|
||||
"tests/fishing_authority_validation.gd"
|
||||
"tests/job_system_validation.gd"
|
||||
"tests/surface_drawing_runtime_validation.gd"
|
||||
)
|
||||
|
||||
readonly -a NETWORK_TESTS=(
|
||||
"tests/economy_regression_validation.gd"
|
||||
"tests/fish_showcase_multiplayer_validation.gd"
|
||||
"tests/fishing_multiplayer_validation.gd"
|
||||
"tests/job_multiplayer_validation.gd"
|
||||
"tests/surface_drawing_multiplayer_validation.gd"
|
||||
"tests/world_time_multiplayer_validation.gd"
|
||||
)
|
||||
|
||||
cleanup() {
|
||||
rm -rf -- "${RUN_ROOT}"
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
usage() {
|
||||
printf 'Usage: %s {quick|full|host|network|all|--list}\n' "$0"
|
||||
}
|
||||
|
||||
prepare_root() {
|
||||
local name="$1"
|
||||
local root="${RUN_ROOT}/${name}"
|
||||
mkdir -p -- "${root}/data" "${root}/config" "${root}/cache"
|
||||
printf '%s\n' "${root}"
|
||||
}
|
||||
|
||||
run_test() {
|
||||
local script="$1"
|
||||
local name="${script#tests/}"
|
||||
name="${name%.gd}"
|
||||
local root
|
||||
root="$(prepare_root "${name}")"
|
||||
printf '\n==> %s\n' "${script}"
|
||||
XDG_DATA_HOME="${root}/data" \
|
||||
XDG_CONFIG_HOME="${root}/config" \
|
||||
XDG_CACHE_HOME="${root}/cache" \
|
||||
timeout "${TEST_TIMEOUT_SECONDS}s" "${GODOT_BIN}" \
|
||||
--headless --path "${PROJECT_ROOT}" --script "${script}"
|
||||
}
|
||||
|
||||
run_network_test() {
|
||||
local script="$1"
|
||||
local name="${script#tests/}"
|
||||
name="${name%.gd}"
|
||||
local host_root client_root host_pid host_status client_status
|
||||
host_root="$(prepare_root "${name}-host")"
|
||||
client_root="$(prepare_root "${name}-client")"
|
||||
printf '\n==> %s (host + client)\n' "${script}"
|
||||
XDG_DATA_HOME="${host_root}/data" \
|
||||
XDG_CONFIG_HOME="${host_root}/config" \
|
||||
XDG_CACHE_HOME="${host_root}/cache" \
|
||||
timeout "${TEST_TIMEOUT_SECONDS}s" "${GODOT_BIN}" \
|
||||
--headless --path "${PROJECT_ROOT}" --script "${script}" -- host \
|
||||
>"${host_root}/output.log" 2>&1 &
|
||||
host_pid=$!
|
||||
sleep 0.75
|
||||
set +e
|
||||
XDG_DATA_HOME="${client_root}/data" \
|
||||
XDG_CONFIG_HOME="${client_root}/config" \
|
||||
XDG_CACHE_HOME="${client_root}/cache" \
|
||||
timeout "${TEST_TIMEOUT_SECONDS}s" "${GODOT_BIN}" \
|
||||
--headless --path "${PROJECT_ROOT}" --script "${script}" -- client \
|
||||
>"${client_root}/output.log" 2>&1
|
||||
client_status=$?
|
||||
wait "${host_pid}"
|
||||
host_status=$?
|
||||
set -e
|
||||
printf '%s\n' '-- host output --'
|
||||
sed -n '1,240p' "${host_root}/output.log"
|
||||
printf '%s\n' '-- client output --'
|
||||
sed -n '1,240p' "${client_root}/output.log"
|
||||
if ((host_status != 0 || client_status != 0)); then
|
||||
printf 'error: host exited %d; client exited %d\n' \
|
||||
"${host_status}" "${client_status}" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_quick() {
|
||||
local test_script
|
||||
for test_script in "${QUICK_TESTS[@]}"; do
|
||||
run_test "${test_script}"
|
||||
done
|
||||
}
|
||||
|
||||
run_full() {
|
||||
local test_script
|
||||
run_quick
|
||||
for test_script in "${RUNTIME_TESTS[@]}"; do
|
||||
run_test "${test_script}"
|
||||
done
|
||||
}
|
||||
|
||||
run_host() {
|
||||
local test_script
|
||||
for test_script in "${HOST_TESTS[@]}"; do
|
||||
run_test "${test_script}"
|
||||
done
|
||||
}
|
||||
|
||||
run_network() {
|
||||
local test_script
|
||||
for test_script in "${NETWORK_TESTS[@]}"; do
|
||||
run_network_test "${test_script}"
|
||||
done
|
||||
}
|
||||
|
||||
list_tests() {
|
||||
printf '%s\n' 'Quick tests:'
|
||||
printf ' %s\n' "${QUICK_TESTS[@]}"
|
||||
printf '%s\n' 'Additional full-suite tests:'
|
||||
printf ' %s\n' "${RUNTIME_TESTS[@]}"
|
||||
printf '%s\n' 'Single-process tests requiring a local UDP bind:'
|
||||
printf ' %s\n' "${HOST_TESTS[@]}"
|
||||
printf '%s\n' 'Paired network tests:'
|
||||
printf ' %s\n' "${NETWORK_TESTS[@]}"
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
quick)
|
||||
run_quick
|
||||
;;
|
||||
full)
|
||||
run_full
|
||||
;;
|
||||
host)
|
||||
run_host
|
||||
;;
|
||||
network)
|
||||
run_network
|
||||
;;
|
||||
all)
|
||||
run_full
|
||||
run_host
|
||||
run_network
|
||||
;;
|
||||
--list)
|
||||
list_tests
|
||||
;;
|
||||
*)
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
printf '\nAll requested validations passed.\n'
|
||||
Loading…
Add table
Add a link
Reference in a new issue