More work on states, added bot
This commit is contained in:
1 parent
66e93d46f4
commit
5e9a663812
25 files changed
+1595
-740
No files matched your search
+85
-31
@@ -12,7 +12,7 @@ The architecture has four layers:
|
||||
|
||||
1. `GameState` is the aggregate root for persistent, authoritative state.
|
||||
2. `InternalGameServer` owns `GameState`, advances the local simulation, handles commands, and produces immutable snapshots.
|
||||
3. Runtime objects such as `Location`, `Character`, and `InteractiveObject` hold rendering resources and non-owning bindings to server-owned state. `Location` also translates local input, scripts, and collision results into semantic server commands.
|
||||
3. Runtime objects hold rendering resources. `Character` and `Location` read immutable server snapshots by stable ID, while `InteractiveObject` still uses a transitional non-owning binding to server-owned state. `Location` also translates local input, scripts, and collision results into semantic server commands.
|
||||
4. Client-facing systems such as `MenuManager` read immutable snapshots and submit typed commands through `IGameServer`.
|
||||
|
||||
```text
|
||||
@@ -47,6 +47,8 @@ IGameServer ---- immutable GameSnapshot ----> UI and other clients
|
||||
- Inventory, money, player-health HUD values, quests, tutorial progress, chat data, taxi state, and script-global values.
|
||||
|
||||
Live `Location` pointers and rendering objects are no longer stored in `GameState`.
|
||||
Embedded state models such as `Inventory` and `QuestJournal` contain only value
|
||||
data and deterministic operations; they do not retain runtime callbacks.
|
||||
|
||||
### Campaign-level players
|
||||
|
||||
@@ -54,6 +56,11 @@ Player `CharacterState` objects are stored in `GameState::players`. The current
|
||||
|
||||
The player state is no longer owned by a `Character` or duplicated as a separately authoritative state for each loaded location. This permits additional player IDs to be introduced later without changing the aggregate ownership model.
|
||||
|
||||
Every player, including the one controlled by the current client, remains in this
|
||||
same authoritative collection. `IGameServer::localPlayerId()` identifies which
|
||||
entry is local to a particular client connection; it is not a separate state
|
||||
object.
|
||||
|
||||
`LocationGameState` does not retain a player pointer or back-reference to `GameState`.
|
||||
Its update boundary receives `GameState::players` by reference, allowing character
|
||||
lookup and simulation to treat every campaign player by stable ID.
|
||||
@@ -70,7 +77,12 @@ Each location record owns:
|
||||
- Serialized dialogue runtime state.
|
||||
- Serialized Lua runtime globals.
|
||||
|
||||
State objects use `shared_ptr` internally to keep their addresses stable while local runtime objects are bound to them. These pointers never appear in public snapshots.
|
||||
World-mode flags (`darklands`, `night`, and `dawn`) exist only at the aggregate
|
||||
`GameState` level. Location rendering and scripts read those values from the
|
||||
top-level snapshot rather than maintaining per-location mirrors.
|
||||
|
||||
State objects use `shared_ptr` internally to keep addresses stable for the
|
||||
remaining local runtime bindings. These pointers never appear in public snapshots.
|
||||
|
||||
### Stable identity
|
||||
|
||||
@@ -121,6 +133,7 @@ Snapshots have a monotonically increasing revision. `InternalGameServer` caches
|
||||
- Chat history and unread state.
|
||||
- Taxi state.
|
||||
- Inventory additions and removals.
|
||||
- Quest status, objective completion/visibility, and active-objective changes.
|
||||
- Script globals.
|
||||
- Character transforms, attack targets, navigation destinations, stopping,
|
||||
facing, replanning, health, damage, death reset, attack combos, and animation
|
||||
@@ -131,6 +144,14 @@ Snapshots have a monotonically increasing revision. `InternalGameServer` caches
|
||||
|
||||
A future network implementation can serialize equivalent requests instead of mutating local state.
|
||||
|
||||
### Presentation events
|
||||
|
||||
`IGameServer::drainEvents()` returns value-only events produced by successful
|
||||
authoritative mutations. Inventory add/remove and quest unlock/complete/fail/
|
||||
objective-complete events contain stable IDs only. `Game` drains these events and
|
||||
performs local tutorial, toast, and audio presentation through `MenuManager`.
|
||||
Loading and persistence restoration clear pending events and remain silent.
|
||||
|
||||
## Internal Server
|
||||
|
||||
`InternalGameServer` is the current `IGameServer` implementation. It:
|
||||
@@ -143,10 +164,10 @@ A future network implementation can serialize equivalent requests instead of mut
|
||||
- Builds and caches immutable snapshots.
|
||||
- Delegates save/load serialization to the aggregate state model.
|
||||
|
||||
`Game` remains a privileged host during this migration. It can access private
|
||||
internal-server operations for campaign loading, location construction, callback
|
||||
wiring, and persistence restoration. These host operations are not exposed by
|
||||
`IGameServer`.
|
||||
`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`.
|
||||
|
||||
### Animation and combat
|
||||
|
||||
@@ -180,16 +201,25 @@ collision handling, and presentation-event processing.
|
||||
|
||||
## Runtime and Visual Object Bindings
|
||||
|
||||
`Location`, `Character`, and `InteractiveObject` no longer own their authoritative state objects.
|
||||
Runtime visual objects do not own their authoritative state objects.
|
||||
|
||||
- `Location` keeps a private non-owning reference to its `LocationState` and a stable location ID.
|
||||
- `Character` keeps a private non-owning **const** reference named `characterState`, plus stable entity and location IDs.
|
||||
- `Location` keeps only its `IGameServer` reference and stable location ID. It resolves its immutable `LocationState` view from `IGameServer::snapshot()`.
|
||||
- `Character` keeps only its `IGameServer` reference plus stable entity and location IDs. It resolves the player-first character view from `IGameServer::snapshot()`.
|
||||
- `InteractiveObject` keeps a private non-owning reference to its `InteractiveObjectState`; its configured object name is its stable ID.
|
||||
|
||||
The bound state objects are owned by `GameState` or `LocationGameState`. The internal
|
||||
server advances them directly before runtime presentation. Rendering reads the bound
|
||||
state; runtime input, scripts, and collision handling submit semantic commands that
|
||||
invoke `CharacterState` operations against the authoritative `LocationState`.
|
||||
`Character::stateSnapshot()` and `Location::stateSnapshot()` return aliasing
|
||||
`shared_ptr` views. Each pointer addresses a state copy inside a `GameSnapshot`,
|
||||
while shared ownership keeps that whole immutable snapshot alive. Update, input,
|
||||
editor, and draw operations capture one such pointer and use it consistently
|
||||
throughout the operation. A missing or unloaded entity produces an empty pointer
|
||||
and presentation or input work is skipped.
|
||||
|
||||
The authoritative state objects are owned by `GameState` or `LocationGameState`.
|
||||
The internal server advances them before publishing a new snapshot revision.
|
||||
Runtime input, scripts, and collision handling submit semantic commands that invoke
|
||||
authoritative character and location operations. Location commands cover camera
|
||||
orientation, pending interaction targets, navigation switching and area changes,
|
||||
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`.
|
||||
@@ -203,12 +233,19 @@ Arrival behavior is represented solely by the serialized Lua function name in
|
||||
`CharacterState`; `Location` resolves and invokes that name through `ScriptEngine`
|
||||
when it consumes the arrival event.
|
||||
|
||||
`Location` owns presentation-only runtime characters for all non-local entries in
|
||||
`GameSnapshot::players`. It reconciles them by stable ID as snapshots change,
|
||||
reuses the local-player assets and animation set, and includes them in all render,
|
||||
shadow, lighting, animation, damage, and name-tag passes. The local entry is
|
||||
excluded using `IGameServer::localPlayerId()` because its visual is already owned
|
||||
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 bound to those state objects.
|
||||
4. Constructs visual objects using stable IDs and state-backed creation data.
|
||||
|
||||
Configuration remains the source of visual assets, animation paths, meshes, textures, and fixed tuning data.
|
||||
|
||||
@@ -225,11 +262,14 @@ The normal frame flow is:
|
||||
back as semantic destination commands, whose server handler calls
|
||||
`CharacterState::setTarget()` with the authoritative `LocationState`; arrival
|
||||
function names are resolved through `ScriptEngine`.
|
||||
6. Runtime characters apply the authoritative animation frame to loaded models and
|
||||
6. The server invalidates its cached snapshot and advances the revision so runtime
|
||||
presentation can observe the completed simulation tick.
|
||||
7. Runtime characters read one immutable snapshot per operation, apply the
|
||||
authoritative animation frame to loaded models, and
|
||||
play audio, particles, and presentation callbacks.
|
||||
7. Auxiliary dialogue, Lua, trigger, and teleport state is captured into `LocationGameState`.
|
||||
8. The server increments its revision and invalidates the cached snapshot.
|
||||
9. Rendering reads the bound local state; UI and external-style consumers read an immutable snapshot.
|
||||
8. Auxiliary dialogue, Lua, trigger, and teleport state is captured into `LocationGameState`.
|
||||
9. The server publishes those auxiliary changes in a later revision.
|
||||
10. Rendering, UI, and external-style consumers read immutable snapshots.
|
||||
|
||||
Commands that update bound character or object state do not reload the whole location. This avoids replaying dialogue-node effects or Lua callbacks.
|
||||
|
||||
@@ -244,7 +284,7 @@ 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 and bound to that state.
|
||||
- The visual player is created with its stable ID and resolves that state through snapshots.
|
||||
|
||||
### Location loading
|
||||
|
||||
@@ -254,6 +294,8 @@ When a location is loaded:
|
||||
- Static configuration is loaded.
|
||||
- NPC and interactive-object visuals are created against state owned by the location record.
|
||||
- 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`.
|
||||
|
||||
@@ -278,8 +320,8 @@ unsupported versions are rejected rather than migrated.
|
||||
- Pending interaction targets and character references use stable IDs.
|
||||
- Immutable content such as meshes, initial taxi configuration, and object
|
||||
definitions is reconstructed from campaign configuration.
|
||||
- Configuration is loaded first and mutable saved state is overlaid in place, so
|
||||
runtime render bindings keep stable addresses.
|
||||
- Configuration is loaded first and mutable saved state is overlaid in place.
|
||||
Snapshot-backed runtime objects then resolve the resulting state by stable ID.
|
||||
|
||||
Old user save slots are intentionally unsupported. Bundled start-state snapshots
|
||||
must be regenerated with `Game::saveInitialState()` whenever the schema changes.
|
||||
@@ -298,11 +340,14 @@ It now:
|
||||
|
||||
### Scripts
|
||||
|
||||
Lua remains an in-process single-player runtime. Character bindings submit semantic
|
||||
commands through `Location`; the server invokes `CharacterState` operations on the
|
||||
centrally owned state. NPC, interactive-object, trigger-zone, and teleport-zone
|
||||
bindings address entities by configured ID. Object, inventory, quest, and
|
||||
global-state bindings remain trusted local integrations.
|
||||
Lua remains an in-process single-player runtime. Character, inventory, quest, and
|
||||
campaign-global bindings submit semantic commands through `Location`; the server
|
||||
invokes operations on centrally owned state. Snapshot queries provide global
|
||||
values, inventory counts, item presence, and synchronous quest validation for the
|
||||
existing Lua API. NPC,
|
||||
interactive-object, trigger-zone, and teleport-zone bindings address entities by
|
||||
configured ID. Other object and global-state bindings remain trusted local
|
||||
integrations.
|
||||
|
||||
Each location script registers initialization, enter, and exit callbacks.
|
||||
Initialization runs only when the location has no retained state; loading the Lua
|
||||
@@ -313,13 +358,18 @@ The scalar Lua runtime state for each location is stored under `LocationGameStat
|
||||
|
||||
### Dialogue and cutscenes
|
||||
|
||||
Dialogue runtime state is captured in each `LocationGameState`. Dialogue and cutscene rendering remain local presentation systems.
|
||||
Dialogue runtime state is captured in each `LocationGameState`. Dialogue global
|
||||
flags use snapshot getter and command setter callbacks rather than retaining a
|
||||
mutable map pointer. Dialogue and cutscene rendering remain local presentation
|
||||
systems.
|
||||
|
||||
Dialogues and cutscenes are outside the planned multiplayer gameplay mode, but their existing single-player save and callback behavior is retained.
|
||||
|
||||
### Quests, inventory, and tutorial
|
||||
|
||||
These systems remain part of `GameState` for single-player compatibility. UI access now crosses the server interface. They can remain empty or disabled in multiplayer mode as planned.
|
||||
These callback-free state systems remain part of `GameState` for single-player
|
||||
compatibility. UI access, mutations, and presentation notifications cross the
|
||||
server interface. They can remain empty or disabled in multiplayer mode as planned.
|
||||
|
||||
## Multiplayer Readiness
|
||||
|
||||
@@ -372,7 +422,11 @@ 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` currently uses privileged internal-server APIs for local content construction. A remote client implementation will need a client-side runtime-location factory driven by configuration and snapshots.
|
||||
- `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.
|
||||
|
||||
## Main Files
|
||||
|
||||
@@ -383,8 +437,8 @@ cmake --build proj-windows/build --config Debug --target ShadowOverBishkekDemo -
|
||||
- `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.
|
||||
- `src/Character.h` / `src/Character.cpp` — passive character presentation bound to
|
||||
a const authoritative `CharacterState`.
|
||||
- `src/Character.h` / `src/Character.cpp` — passive character presentation resolving
|
||||
immutable `CharacterState` snapshots by stable ID.
|
||||
- `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.
|
||||
|
||||
Reference in new issue
Block a user