554 lines
21 KiB
Markdown
554 lines
21 KiB
Markdown
# Agrarian Technical Design Document
|
|
|
|
## Purpose
|
|
|
|
This document defines the technical shape of Agrarian at the foundation stage.
|
|
It translates the core design direction into practical architecture decisions,
|
|
runtime boundaries, data contracts, build lanes, and near-term implementation
|
|
rules.
|
|
|
|
Detailed designs for multiplayer/networking, persistence, Earth-scale terrain
|
|
streaming, economy/AGR, and art/code standards are intentionally split into
|
|
their own roadmap documents.
|
|
|
|
## Current Technical Baseline
|
|
|
|
Agrarian is an Unreal Engine 5.7 C++ project with Blueprint assets layered on
|
|
top for early gameplay content and testable prototype objects.
|
|
|
|
Current project direction:
|
|
|
|
- authoritative gameplay state lives on the server;
|
|
- clients receive replicated state for UI and presentation;
|
|
- core gameplay systems are C++ components or actors;
|
|
- content-facing configuration uses Data Assets where possible;
|
|
- MVP terrain starts with one real 1 km x 1 km Ground Zero tile;
|
|
- tile packages can be served from the MVP map tile server;
|
|
- Windows-Builder is the primary Unreal/Visual Studio build VM;
|
|
- Ubuntu-Codex is the source-control and automation workstation;
|
|
- Unraid `DevBox` hosts shared project storage and supporting VMs.
|
|
|
|
## Runtime Architecture
|
|
|
|
### Server Authority
|
|
|
|
The server is authoritative for gameplay outcomes.
|
|
|
|
Server-owned state includes:
|
|
|
|
- player survival values;
|
|
- inventory changes;
|
|
- crafting results;
|
|
- world time;
|
|
- weather state applied to gameplay;
|
|
- resource depletion/harvest results;
|
|
- wildlife state;
|
|
- placed structures;
|
|
- persistence save/load decisions.
|
|
|
|
Clients may request actions, but the server validates and applies results.
|
|
|
|
### Client Responsibilities
|
|
|
|
Clients are responsible for:
|
|
|
|
- player input;
|
|
- camera and local presentation;
|
|
- UI/HUD;
|
|
- local animation;
|
|
- local audio/visual feedback;
|
|
- displaying replicated survival, inventory, weather, and world state;
|
|
- local tile cache storage once streaming matures.
|
|
|
|
Clients should not directly call public weather APIs or mutate authoritative
|
|
world state.
|
|
|
|
### Gameplay System Boundaries
|
|
|
|
Early runtime systems should remain small and explicit:
|
|
|
|
- `AAgrarianGameState`: world time, weather, ambient temperature, replicated
|
|
environment state.
|
|
- `UAgrarianSurvivalComponent`: health, hunger, thirst, stamina, body
|
|
temperature, injury, and survival damage.
|
|
- Inventory component/classes: item stacks, item definitions, resource intake,
|
|
and crafting inputs/outputs.
|
|
- Crafting component/classes: recipes, validation, output creation.
|
|
- Interaction component/classes: player-facing use/gather/build entry points.
|
|
- Resource actors: gatherable wood, stone, fiber, water, wildlife, and future
|
|
natural resources.
|
|
- Buildable actors: campfire, primitive shelter, frames, walls, roof panels,
|
|
and later settlement infrastructure.
|
|
- Persistence layer: save/load contracts for player and world state.
|
|
|
|
Blueprints can compose and expose these systems, but core replicated behavior
|
|
should remain in C++ as much as practical.
|
|
|
|
## Time And Environment
|
|
|
|
The MVP gameplay calendar target is:
|
|
|
|
```text
|
|
4 real hours = 1 in-game day
|
|
```
|
|
|
|
The current C++ default is:
|
|
|
|
```text
|
|
GameHoursPerRealMinute = 0.1
|
|
```
|
|
|
|
That equals 6 in-game minutes per real minute, or 24 in-game hours over 4 real
|
|
hours.
|
|
|
|
Day/night presentation should mimic the represented Earth region's local solar
|
|
and weather context as the system matures. This means the gameplay calendar can
|
|
be compressed while visual lighting, seasonal direction, and weather mapping
|
|
still derive from the represented map tile.
|
|
|
|
Near-term technical work:
|
|
|
|
- add Ground Zero local time-zone metadata; completed for the current C++ game-state default.
|
|
- add sunrise/sunset lookup or approximation by latitude/longitude; completed as a tile-aware NOAA approximation in `AAgrarianGameState`.
|
|
- map real weather snapshots into internal Agrarian weather states;
|
|
- cache weather snapshots server-side;
|
|
- keep deterministic fallback weather when external data is unavailable.
|
|
|
|
The repeatable solar metadata data path is
|
|
`Scripts/generate_tile_solar_metadata.py`. It reads the tile registry and emits
|
|
metadata only for source-backed, generated, validated, packaged, or published
|
|
tiles with explicit time-zone data. Placeholder/unknown tiles are skipped so the
|
|
future Earth-scale registry does not generate or fetch data for theoretical
|
|
tiles that do not exist yet.
|
|
|
|
Calendar conversion helpers live in `AAgrarianGameState` and keep the MVP target
|
|
of `4 real hours = 1 in-game day`. The same game state now exposes replicated
|
|
calendar year/day, absolute-day, season, real-hour conversion, long-task
|
|
progress, and crop-season fit helpers. Crop checks use the active tile's
|
|
growing-zone profile, including frost-free days and a crop safety buffer, so a
|
|
long-maturity crop can be rejected or marked marginal in regions with short
|
|
seasons.
|
|
|
|
The repeatable growing-zone metadata data path is
|
|
`Scripts/generate_tile_growing_zone_metadata.py`. It reads the tile registry and
|
|
emits metadata only for source-backed, generated, validated, packaged, or
|
|
published tiles with explicit growing-zone data. Ground Zero currently uses a
|
|
conservative Pacifica coastal profile; later regional expansion should replace
|
|
or enrich these overrides with authoritative zone, climate, and temperature
|
|
datasets.
|
|
|
|
Temperature is authoritative on `AAgrarianGameState`. The MVP curve uses the
|
|
active tile's sunrise and solar noon to place the daily low near sunrise and the
|
|
daily high after solar noon, then applies weather modifiers for rain, cold wind,
|
|
and storms. Regional daily low/high values provide the deterministic fallback.
|
|
When a server-side weather adapter is available, it should set observed regional
|
|
temperature and blend weight through the game-state hook rather than allowing
|
|
clients to call public weather APIs directly. This keeps real-world temperature
|
|
and weather tied to the represented map tile while preserving a deterministic
|
|
fallback if an external provider is unavailable.
|
|
|
|
Primitive shelters expose a replicated protection volume and
|
|
`WeatherProtection` rating. Server-side survival ticks calculate the best
|
|
overlapping shelter protection for each character, replicate the current
|
|
protection value, reduce ambient weather exposure and cold damage by that
|
|
percentage, and trend the care-history shelter quality field toward the active
|
|
protection level. The dev HUD shows current shelter protection so weather
|
|
pressure can be tuned during MVP tests.
|
|
|
|
Weather exposure zones use `AAgrarianWeatherExposureZone` volumes placed by the
|
|
Ground Zero setup script. They describe local ridge, coastal-wind, and drainage
|
|
cooling effects with an exposure multiplier and temperature offset. Server-side
|
|
survival ticks select the strongest overlapping zone effect, replicate the
|
|
current multiplier and offset, then apply them to ambient body-temperature drift
|
|
and cold damage after shelter protection. This lets future generated tiles add
|
|
biome, slope, elevation, hydrology, and coastal modifiers without changing the
|
|
core survival calculation.
|
|
|
|
The safe Ground Zero spawn is selected by `Scripts/setup_ground_zero_demo_map.py`
|
|
from declared candidate coordinates and a known safe fallback coordinate. The
|
|
setup validates the selected player start against terrain elevation, terrain
|
|
slope, a minimum above-terrain Z offset, freshwater spacing, and resource-cluster
|
|
spacing before saving the map. `Scripts/verify_ground_zero_safe_spawn.py`
|
|
rechecks the placed `AGR_DemoPlayerStart` against the same constraints so future
|
|
map, resource, water, or terrain changes cannot silently move the player below
|
|
sea level, into steep terrain, into water, or into a dense resource cluster.
|
|
|
|
First-pass sky and lighting use `AAgrarianSkyLightingController`. The controller
|
|
owns movable sun, skylight, and exponential-height-fog components and reads the
|
|
replicated `AAgrarianGameState` time, active tile sunrise/sunset, weather state,
|
|
and mapped cloud cover. It adjusts sun pitch, sun intensity/color, sky-light
|
|
intensity, and fog density every tick so the Ground Zero demo visually tracks
|
|
the represented local day/night cycle and current weather without hard-coded
|
|
static light settings. The Ground Zero map setup script places this controller
|
|
and removes the earlier static demo sun/skylight/fog actors.
|
|
|
|
First-pass weather audio uses `AAgrarianWeatherAudioController`. The controller
|
|
owns ambient, rain, wind, and storm audio components with assignable loop sound
|
|
slots. It reads replicated weather state, provider wind speed, provider cloud
|
|
data, and local night/day state, then fades component volumes so rain, wind, and
|
|
storm cues follow the same authoritative weather mapping used by temperature and
|
|
lighting. The current MVP can ship without final sound assets because the
|
|
controller is silent until loops are assigned; placeholder or final audio can be
|
|
added by setting the exposed sound properties on the placed controller or a
|
|
Blueprint child.
|
|
|
|
The first real-weather adapter is `UAgrarianWeatherProviderSubsystem`. It uses
|
|
Open-Meteo forecast requests keyed by tile center latitude/longitude, parses the
|
|
current temperature, daily low/high, precipitation, wind, humidity, cloud cover,
|
|
pressure, provider timestamp, and weather code, then applies the mapped state to
|
|
`AAgrarianGameState` on the server. It is tile-driven rather than Ground-Zero
|
|
hard-coded: `Scripts/generate_tile_weather_manifest.py` emits every
|
|
source-backed, generated, validated, packaged, or published tile with center
|
|
coordinates, while placeholder/unknown tiles are skipped. Future source-backed
|
|
tiles therefore become weather-eligible when their registry entries are added.
|
|
|
|
Ground Zero weather lookup coordinates are explicit in the tile registry. The
|
|
current MVP tile `gz_us_ca_pacifica_utm10n_e544_n4160` uses its tile center,
|
|
latitude `37.5925` and longitude `-122.4995`, as the canonical real-world
|
|
weather lookup point. `Scripts/generate_tile_weather_manifest.py` reads
|
|
`weather_lookup_metadata` when present, falls back to the tile center for
|
|
source-backed tiles, and emits the provider routing used by the weather
|
|
subsystem.
|
|
|
|
Open-Meteo is the first global MVP weather source. The provider contract is
|
|
stored in `Data/Weather/open_meteo_mvp_source.json`, including the forecast
|
|
endpoint, requested current/daily variables, tile lookup rule, and Agrarian
|
|
mapping notes. `Scripts/verify_open_meteo_mvp_source.py` validates the static
|
|
contract and can perform a live Open-Meteo request for every source-backed tile
|
|
in `Data/Tiles/tile_weather_manifest.json`. This keeps the provider global for
|
|
all future real tiles instead of adding one-off Ground Zero weather code.
|
|
|
|
NOAA/NWS is the US-only fallback and enrichment path. The provider contract is
|
|
stored in `Data/Weather/noaa_nws_us_fallback.json`. The weather provider
|
|
subsystem can check whether an active tile center coordinate is inside the
|
|
approximate NWS coverage window, request `api.weather.gov/points/{lat},{lon}`,
|
|
follow `properties.forecastGridData`, and parse gridded temperature,
|
|
precipitation probability, and wind speed as fallback inputs. The NWS path is
|
|
only used for eligible US/NWS-covered tiles; Open-Meteo remains the global
|
|
source for all tiles.
|
|
|
|
Real-weather snapshots are cached server-side in
|
|
`UAgrarianWeatherProviderSubsystem::ServerWeatherSnapshotCache`. Cache keys use
|
|
provider plus tile ID, and the default TTL is 15 minutes. Server requests first
|
|
try to apply a fresh cached snapshot to `AAgrarianGameState`; only cache misses
|
|
call Open-Meteo or NOAA/NWS. Clients never call Open-Meteo or NOAA/NWS directly.
|
|
They receive weather, temperature, source, and state through replicated game
|
|
state fields.
|
|
|
|
Real-weather provider values are mapped into `FAgrarianMappedWeatherInputs`
|
|
before they affect gameplay. The mapped snapshot keeps tile ID, tile center
|
|
coordinate, temperature,
|
|
precipitation, wind, cloud cover, humidity, pressure, visibility, and provider
|
|
weather code available alongside the collapsed Agrarian weather state. Open-Meteo
|
|
fills those fields directly where available; NOAA/NWS fills them from grid data
|
|
where available and derives provisional visibility/weather-state values until a
|
|
deeper provider-specific mapping pass is added.
|
|
|
|
The applied weather state also has a replicated debug snapshot:
|
|
`FAgrarianWeatherDebugSnapshot`. It records the weather source, provider
|
|
timestamp, tile ID, tile center coordinate, provider weather code, input values,
|
|
and final in-game `EAgrarianWeatherType` after mapping. Save files persist both
|
|
the mapped inputs and the applied debug snapshot so weather issues can be traced
|
|
back to a specific provider response and tile without inferring those values from
|
|
separate systems.
|
|
|
|
Deterministic fallback weather keeps the game playable when external providers
|
|
are disabled, unreachable, or return unusable data. The fallback snapshot is
|
|
derived from tile ID and Agrarian day, then mapped through the same
|
|
`FAgrarianMappedWeatherInputs` path as live providers. It produces seasonal
|
|
daily low/high temperatures, current temperature, cloud cover, humidity, wind,
|
|
pressure, precipitation, visibility, and the collapsed Agrarian weather state.
|
|
Fallback snapshots use provider `deterministic-fallback` and are cached
|
|
server-side with the normal weather cache TTL.
|
|
|
|
## Terrain And Tile Delivery
|
|
|
|
### MVP Tile
|
|
|
|
The MVP starts with one real Ground Zero tile:
|
|
|
|
- 1 km x 1 km tile;
|
|
- real elevation data imported into Unreal;
|
|
- metadata tracked in JSON registry files;
|
|
- static delivery package available from the map tile server.
|
|
|
|
### Tile Server
|
|
|
|
Current MVP endpoint:
|
|
|
|
```text
|
|
http://maps.agrariangame.com:18080
|
|
```
|
|
|
|
Current backing VM:
|
|
|
|
```text
|
|
Agrarian-TileServer
|
|
```
|
|
|
|
The tile server currently serves static files through nginx:
|
|
|
|
- `/health`
|
|
- `/manifest.json`
|
|
- `/ground_zero_tiles.json`
|
|
- `/schemas/tile_registry.schema.json`
|
|
- `/tiles/<tile_id>/v<package_version>/...`
|
|
|
|
The current tile client verification script proves:
|
|
|
|
- manifest download;
|
|
- registry lookup;
|
|
- package file download;
|
|
- checksum validation;
|
|
- neighbor metadata presence;
|
|
- delete/redownload cache recovery.
|
|
|
|
### Long-Term Tile Direction
|
|
|
|
The long-term tile system should support:
|
|
|
|
- 1 km x 1 km canonical tile IDs;
|
|
- versioned tile packages;
|
|
- server-side registry and package metadata;
|
|
- client local tile cache;
|
|
- cache retention and scrub policy;
|
|
- package revalidation and redownload;
|
|
- tile adjacency/stitching contracts;
|
|
- safe terrain updates that do not corrupt persisted player/world state.
|
|
|
|
The first implementation should stay static and simple until gameplay proves
|
|
why a database-backed tile service is needed.
|
|
|
|
## Data Contracts
|
|
|
|
### Data Assets
|
|
|
|
Use Unreal Data Assets for designer-facing definitions such as:
|
|
|
|
- item definitions;
|
|
- recipes;
|
|
- gatherable resource configuration;
|
|
- wildlife configuration;
|
|
- buildable structure definitions;
|
|
- future skill/knowledge definitions.
|
|
|
|
Data Assets should describe content. Server code should enforce gameplay rules.
|
|
|
|
### JSON Metadata
|
|
|
|
Use JSON files for external terrain/tile pipeline metadata while the pipeline is
|
|
still early:
|
|
|
|
- tile registry;
|
|
- terrain generation metadata;
|
|
- heightmap metadata;
|
|
- landform analysis;
|
|
- water/shoreline analysis;
|
|
- neighbor edge verification.
|
|
|
|
JSON metadata should have schemas when it becomes a contract. The tile registry
|
|
already has an MVP schema.
|
|
|
|
### Save Data
|
|
|
|
Save data must be treated as a long-term compatibility contract. Do not store
|
|
temporary prototype assumptions in a way that blocks future migration.
|
|
|
|
Persistence should include version fields for:
|
|
|
|
- save format;
|
|
- game build;
|
|
- tile package version;
|
|
- world state records;
|
|
- player records;
|
|
- placed object records.
|
|
|
|
## Persistence Strategy
|
|
|
|
Persistence should begin narrow and explicit.
|
|
|
|
MVP persistence scope:
|
|
|
|
- player survival snapshot;
|
|
- inventory snapshot;
|
|
- placed campfire/shelter/basic structures;
|
|
- depleted/changed resource nodes where needed;
|
|
- world time/weather state;
|
|
- active Ground Zero tile/package version.
|
|
|
|
Do not persist every temporary actor by default. Actors should opt into
|
|
persistence with a stable identifier and a clear serialization contract.
|
|
|
|
Future persistence design should address:
|
|
|
|
- server database vs file save split;
|
|
- migration/versioning;
|
|
- world partition state;
|
|
- tile package changes;
|
|
- player-owned structures;
|
|
- family/generation data;
|
|
- economy and transaction records;
|
|
- settlement governance records.
|
|
|
|
## Multiplayer Strategy
|
|
|
|
The MVP should prove at least two players on the same server.
|
|
|
|
Near-term rule:
|
|
|
|
- server validates gameplay actions;
|
|
- replicated state is kept minimal;
|
|
- client prediction is deferred unless interaction feels bad without it;
|
|
- RPCs should be narrow and action-specific;
|
|
- avoid letting Blueprint-only paths mutate critical authoritative state.
|
|
|
|
Detailed replication policy belongs in the multiplayer/networking design
|
|
document.
|
|
|
|
## Build And Automation
|
|
|
|
### Windows Editor Build
|
|
|
|
Primary build path:
|
|
|
|
```text
|
|
Scripts\BuildEditor-Windows.bat
|
|
```
|
|
|
|
Codex runs this through Windows-Builder using:
|
|
|
|
```text
|
|
/home/nathan/bin/winbuilder cmd 'set AGRARIAN_NO_PAUSE=1 && pushd \\DevBox\projects\AgrarianGameBulid && Scripts\BuildEditor-Windows.bat'
|
|
```
|
|
|
|
### Unreal Python Verification
|
|
|
|
Command-mode Unreal Python scripts are used for repeatable editor validation:
|
|
|
|
- map checks;
|
|
- Ground Zero terrain verification;
|
|
- playable Blueprint verification;
|
|
- resource and foliage placement checks.
|
|
|
|
These scripts should remain deterministic and safe to run repeatedly.
|
|
|
|
### Packaged Demo Builds
|
|
|
|
Investor/demo packages should be produced when a milestone version's roadmap
|
|
items are complete. The build should use Ground Zero as the default map and
|
|
include current splash/startup/copyright notices.
|
|
|
|
### Linux Dedicated Server
|
|
|
|
Dedicated server build instructions exist, but the MVP can continue proving
|
|
gameplay through the current available server path until dedicated server
|
|
packaging is required for closed testing.
|
|
|
|
## Infrastructure
|
|
|
|
Current supporting machines:
|
|
|
|
- `DevBox` Unraid: shared project storage and VM host.
|
|
- `Ubuntu-Codex`: source-control/automation machine.
|
|
- `Windows-Builder`: Unreal/Visual Studio/GPU build machine.
|
|
- `Agrarian-TileServer`: dedicated Ubuntu VM for MVP tile delivery.
|
|
|
|
Current public tile DNS:
|
|
|
|
```text
|
|
maps.agrariangame.com:18080
|
|
```
|
|
|
|
Infrastructure rules:
|
|
|
|
- do not run project application services directly on the Unraid OS;
|
|
- run services inside VMs or external hosts;
|
|
- keep the tile server small and static for MVP;
|
|
- keep GitHub/LFS usage within free-tier guardrails as long as practical;
|
|
- avoid committing generated build output, local caches, or secrets.
|
|
|
|
## Source Control And Assets
|
|
|
|
The repo uses Git plus Git LFS for Unreal binary assets.
|
|
|
|
Rules:
|
|
|
|
- commit source, config, docs, scripts, and curated assets;
|
|
- do not commit `Binaries/`, `Intermediate/`, `Saved/`, local build artifacts,
|
|
or generated packages;
|
|
- keep large generated terrain packages out of Git unless explicitly curated;
|
|
- prefer small, focused commits tied to roadmap items;
|
|
- do not commit credentials or machine-local configuration.
|
|
|
|
The project currently has unrelated `.uasset` modifications in the working tree
|
|
from prior editor activity. Do not stage those unless intentionally addressing
|
|
that content.
|
|
|
|
## Security And Secrets
|
|
|
|
Secrets must stay out of the repository and handoff files.
|
|
|
|
Examples:
|
|
|
|
- DigitalOcean API tokens;
|
|
- server passwords;
|
|
- Mailgun credentials;
|
|
- database passwords;
|
|
- private SSH keys;
|
|
- admin reset files.
|
|
|
|
Use environment variables, machine-local config, or secret managers for
|
|
credentials. Documentation may describe where a secret is expected, but should
|
|
not include secret values.
|
|
|
|
## Testing Gates
|
|
|
|
Minimum gate for code changes:
|
|
|
|
- relevant C++ compiles through Windows-Builder;
|
|
- relevant Unreal Python verification passes when touching maps/assets;
|
|
- targeted script checks pass when touching scripts/data;
|
|
- docs-only changes receive a text sanity check.
|
|
|
|
Minimum gate for milestone/demo builds:
|
|
|
|
- editor build succeeds;
|
|
- Ground Zero map check passes;
|
|
- playable loop smoke test passes;
|
|
- package launches on Windows test machine;
|
|
- current roadmap milestone is marked complete;
|
|
- known blockers are documented.
|
|
|
|
## Performance Profiling
|
|
|
|
Agrarian gameplay code exposes a dedicated Unreal stat group named
|
|
`STATGROUP_Agrarian`. Use `stat Agrarian` during editor or packaged sessions for
|
|
game-specific cycle counters, and capture Unreal Insights traces for matching
|
|
CPU scopes. The current markers cover authoritative game-state time/weather
|
|
ticking, survival ticking, sky-light refresh, weather-audio refresh, foliage
|
|
instance mutation, and weather-provider request/parse/fallback work.
|
|
|
|
## Near-Term Technical Priorities
|
|
|
|
Next technical foundation work should focus on:
|
|
|
|
- technical details for multiplayer/networking;
|
|
- persistence contract and versioning;
|
|
- Earth-scale tile streaming design;
|
|
- real-weather provider adapter;
|
|
- real-region day/night presentation;
|
|
- local tile cache layout and retention;
|
|
- MVP character-selection landing page;
|
|
- first closed-test readiness gate.
|
|
|
|
## Open Questions
|
|
|
|
- Should public tile serving remain on the LAN-hosted `Agrarian-TileServer` VM
|
|
during closed testing, or move to an external cloud host before testers join?
|
|
- Which persistence backend should replace or supplement file saves first?
|
|
- How much client prediction is needed for gathering, inventory, and building?
|
|
- What is the first stable dedicated server packaging target?
|
|
- Which systems need migration/versioning before the first closed test?
|
|
- How much real sunrise/sunset accuracy is needed before the MVP feels
|
|
regionally grounded?
|