Separating state out of the location
This commit is contained in:
1 parent
5e9a663812
commit
297bd7377f
45 files changed
+2114
-778
No files matched your search
+57
-31
@@ -157,23 +157,30 @@ Loading and persistence restoration clear pending events and remain silent.
|
||||
`InternalGameServer` is the current `IGameServer` implementation. It:
|
||||
|
||||
- Exclusively owns the aggregate `GameState`.
|
||||
- Privately stores loaded runtime `Location` objects.
|
||||
- Executes typed commands against authoritative state.
|
||||
- Advances the active location simulation through `update(deltaMs)`.
|
||||
- Synchronizes non-bound auxiliary state such as dialogue, Lua globals, triggers, and teleports.
|
||||
- Builds and caches immutable snapshots.
|
||||
- Delegates save/load serialization to the aggregate state model.
|
||||
|
||||
`Game` remains a privileged lifecycle host, but it no longer holds or receives a
|
||||
mutable `GameState` reference. It uses private, focused internal-server operations
|
||||
for campaign loading and location construction. Those operations publish revisions
|
||||
themselves and are not exposed by `IGameServer`.
|
||||
`LocalGameServerHost` is the graphical client's integration adapter. It owns loaded
|
||||
runtime `Location` objects, forwards simulation events to them, and synchronizes
|
||||
dialogue, Lua, trigger, and teleport auxiliary state. `Game` uses the explicit
|
||||
`IGameServerHost` lifecycle interface and is no longer a friend of
|
||||
`InternalGameServer`. The standalone server does not compile this adapter.
|
||||
|
||||
Location loading has two phases. `LocationContentLoader` parses renderer-free
|
||||
`LocationDefinition` data, and `LocationGameState::setup()` creates/reconciles
|
||||
authoritative NPC, interactive-object, navigation, taxi, trigger, teleport, and
|
||||
animation state. The graphical `Location::setup()` runs afterward and only builds
|
||||
presentation objects from that definition and the prepared state. Lua and dialogue
|
||||
runtime behavior remains client-side.
|
||||
|
||||
### Animation and combat
|
||||
|
||||
Logical animation frame clocks live in `CharacterState`. Animation frame counts are
|
||||
copied from the loaded clip metadata during runtime construction, after which state
|
||||
transitions and frame-19 combat impacts are deterministic authoritative simulation.
|
||||
Logical animation frame clocks live in `CharacterState`. The renderer-free content
|
||||
loader reads animation frame metadata before authoritative entities are created.
|
||||
Runtime `Character` construction only loads models for presentation and does not
|
||||
submit metadata mutations back to the server.
|
||||
|
||||
`CharacterState::update()` returns value-only events containing arrival Lua function
|
||||
names, attack impacts, navigation requests, and death-animation completion. `LocationGameState` applies
|
||||
@@ -224,9 +231,9 @@ editor obstacles, and taxi reset. No whole-location commit command is exposed.
|
||||
Navigation target selection, replanning, stopping, facing, death reset, health
|
||||
assignment, and attack-combo clock changes are implemented by `CharacterState`.
|
||||
`Character` no longer exposes gameplay mutation helpers or a generic state mutation
|
||||
callback. Its only state-facing setup responsibility is reporting frame ranges from
|
||||
loaded animation assets through `SetCharacterAnimationMetadataCommand`; otherwise it
|
||||
focuses on model posing, rendering, audio, particles, and runtime callbacks.
|
||||
callback. Character construction is presentation-only; frame ranges are already
|
||||
present in `CharacterState` after content setup. It focuses on model posing,
|
||||
rendering, audio, particles, and runtime callbacks.
|
||||
|
||||
Death-animation and health-change callbacks remain runtime-only on `Character`.
|
||||
Arrival behavior is represented solely by the serialized Lua function name in
|
||||
@@ -242,10 +249,10 @@ by `Game`.
|
||||
|
||||
`GameObjectLoader` now:
|
||||
|
||||
1. Loads static creation data from location configuration.
|
||||
2. Creates or reuses server-owned state objects.
|
||||
3. Applies saved runtime fields over the configuration defaults.
|
||||
4. Constructs visual objects using stable IDs and state-backed creation data.
|
||||
1. Receives immutable object/NPC definitions parsed by `LocationContentLoader`.
|
||||
2. Resolves already-prepared authoritative entities by stable ID.
|
||||
3. Constructs meshes, textures, VBOs, `InteractiveObject`, and `Character`
|
||||
presentation wrappers without creating or overwriting authoritative state.
|
||||
|
||||
Configuration remains the source of visual assets, animation paths, meshes, textures, and fixed tuning data.
|
||||
|
||||
@@ -256,7 +263,8 @@ The normal frame flow is:
|
||||
1. SDL input is processed.
|
||||
2. UI code submits semantic commands through `IGameServer`.
|
||||
3. The internal server freezes location character observations and calls
|
||||
`CharacterState::update()` for the player and each NPC.
|
||||
`CharacterState::update()` for every present player and NPC. An empty player
|
||||
collection is valid.
|
||||
4. Attack impacts are queued, then damage is applied after all characters advance.
|
||||
5. The runtime location consumes value-only events. Navigation requests are sent
|
||||
back as semantic destination commands, whose server handler calls
|
||||
@@ -283,21 +291,28 @@ When a campaign starts:
|
||||
|
||||
- Existing campaign state and runtime locations are cleared.
|
||||
- Quest definitions are loaded.
|
||||
- A campaign-level player state is created under the `"player"` ID.
|
||||
- The visual player is created with its stable ID and resolves that state through snapshots.
|
||||
- The graphical single-player host requests a campaign-level `"player"` state and
|
||||
creates its visual wrapper.
|
||||
- A standalone host may deliberately create no players; locations continue to tick.
|
||||
- The battle-zone test bot is an explicit host option rather than an unconditional
|
||||
campaign side effect.
|
||||
|
||||
### Location loading
|
||||
|
||||
When a location is loaded:
|
||||
|
||||
- A `LocationGameState` record is created or reused.
|
||||
- Static configuration is loaded.
|
||||
- NPC and interactive-object visuals are created against state owned by the location record.
|
||||
- `LocationContentLoader` parses a renderer-free `LocationDefinition`.
|
||||
- `LocationGameState::setup()` creates or reconciles navigation, taxi, NPC,
|
||||
interactive-object, trigger, teleport, and animation state.
|
||||
- Saved mutable fields are overlaid on configuration defaults by stable ID.
|
||||
- `Location::setup()` builds static and entity visuals from the prepared definition
|
||||
without mutating authoritative state.
|
||||
- The shared campaign player is attached.
|
||||
- Runtime visuals are created for other player IDs currently present in the
|
||||
snapshot and are subsequently spawned or removed as snapshots change.
|
||||
- Dialogue, Lua, navigation, trigger, teleport, and presentation callbacks are initialized.
|
||||
- The runtime `Location` is registered privately with `InternalGameServer`.
|
||||
- Dialogue, Lua, trigger/teleport visuals, and presentation callbacks are initialized.
|
||||
- The runtime `Location` is owned and registered by `LocalGameServerHost`;
|
||||
`InternalGameServer` remains headless.
|
||||
|
||||
### Location unloading
|
||||
|
||||
@@ -387,7 +402,6 @@ Still required for real multiplayer:
|
||||
|
||||
- Network transport and command serialization.
|
||||
- Authentication and player/session assignment.
|
||||
- Server tick scheduling independent of rendering.
|
||||
- Snapshot delta generation or other replication strategy.
|
||||
- Latency handling, interpolation, reconciliation, and prediction.
|
||||
- Command validation, authorization, and anti-cheat rules.
|
||||
@@ -407,6 +421,12 @@ The new state and server files are registered in:
|
||||
|
||||
The refactor uses portable C++17 and introduces no Windows-only gameplay code.
|
||||
|
||||
The standalone target lives under `server/`. It links the authoritative state,
|
||||
campaign, content-definition, and portable resource sources only; SDL, OpenGL,
|
||||
audio, Lua, dialogue presentation, and rendering sources are absent. It can prepare
|
||||
a selected campaign/location with zero players and run the 50 ms fixed-step loop.
|
||||
Networking remains outside this milestone.
|
||||
|
||||
The Windows Debug target was verified with:
|
||||
|
||||
```powershell
|
||||
@@ -422,18 +442,24 @@ cmake --build proj-windows/build --config Debug --target ShadowOverBishkekDemo -
|
||||
location-local NPC ID).
|
||||
- Some top-level values remain mirrors for compatibility, notably player health used by the HUD and scripts.
|
||||
- Dialogue and Lua are synchronized as auxiliary location state rather than fully networked subsystems.
|
||||
- `Game` uses focused privileged internal-server APIs for local content
|
||||
construction, but cannot access the aggregate or its state maps directly. The
|
||||
private location-construction path still supplies `LocationGameState` to the
|
||||
local object loader. A remote client implementation will need a client-side
|
||||
runtime-location factory driven by configuration and snapshots.
|
||||
- `IGameServerLifecycle` is the graphics-free campaign/location administration
|
||||
boundary. `LocalGameServerHost` adds client-only runtime construction and
|
||||
auxiliary-state synchronization without making `Game` a server friend.
|
||||
- Empty player maps are valid. Player-specific interactions remain inactive until
|
||||
a player entity is added.
|
||||
- A remote client still needs a client-side runtime-location factory driven by
|
||||
configuration/definitions and replicated snapshots.
|
||||
|
||||
## Main Files
|
||||
|
||||
- `src/GameState.h` / `src/GameState.cpp` — aggregate state and top-level persistence.
|
||||
- `src/LocationGameState.h` / `src/LocationGameState.cpp` — typed location state, simulation, and ID-keyed persistence.
|
||||
- `src/content/LocationDefinition.h` / `.cpp` — renderer-free content definitions,
|
||||
parsing, and animation metadata loading.
|
||||
- `src/game_server/IGameServer.h` — public snapshot and command contract.
|
||||
- `src/game_server/IGameServerLifecycle.h` — graphics-free campaign/location lifecycle.
|
||||
- `src/game_server/InternalGameServer.h` / `.cpp` — in-process authoritative implementation.
|
||||
- `src/game_server/LocalGameServerHost.h` / `.cpp` — graphical-client runtime adapter.
|
||||
- `src/Game.h` / `src/Game.cpp` — application host, campaign lifecycle, and runtime wiring.
|
||||
- `src/Location.h` / `src/Location.cpp` — loaded location runtime, command routing,
|
||||
interactions, collisions, scripts, and presentation-event consumption.
|
||||
@@ -442,5 +468,5 @@ cmake --build proj-windows/build --config Debug --target ShadowOverBishkekDemo -
|
||||
- `src/CharacterState.h` / `src/CharacterState.cpp` — deterministic character
|
||||
simulation, navigation operations, combat state, and logical animation clock.
|
||||
- `src/items/InteractiveObject.h` / `.cpp` — visual object runtime bound to central object state.
|
||||
- `src/items/GameObjectLoader.h` / `.cpp` — configuration/state overlay and runtime construction.
|
||||
- `src/items/GameObjectLoader.h` / `.cpp` — presentation builders for prepared definitions.
|
||||
- `src/MenuManager.h` / `src/MenuManager.cpp` — snapshot-driven UI and command submission.
|
||||
Reference in new issue
Block a user