cyberia 3.2.9 → 3.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/engine-cyberia.cd.yml +7 -0
- package/.github/workflows/engine-cyberia.ci.yml +14 -2
- package/.github/workflows/ghpkg.ci.yml +1 -0
- package/.github/workflows/npmpkg.ci.yml +10 -5
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/.github/workflows/release.cd.yml +1 -0
- package/.vscode/extensions.json +9 -9
- package/.vscode/settings.json +20 -4
- package/CHANGELOG.md +363 -1
- package/CLI-HELP.md +975 -1061
- package/README.md +190 -348
- package/bin/build.js +102 -125
- package/bin/build.template.js +33 -0
- package/bin/cyberia.js +238 -56
- package/bin/deploy.js +16 -3
- package/bin/index.js +238 -56
- package/bump.config.js +26 -0
- package/conf.js +131 -24
- package/deployment.yaml +76 -2
- package/hardhat/package-lock.json +113 -144
- package/hardhat/package.json +4 -3
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +76 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/kind-config-dev.yaml +8 -0
- package/manifests/lxd/lxd-admin-profile.yaml +12 -3
- package/manifests/mongodb/pv-pvc.yaml +44 -8
- package/manifests/mongodb/statefulset.yaml +55 -68
- package/manifests/mongodb-4.4/headless-service.yaml +10 -0
- package/manifests/mongodb-4.4/kustomization.yaml +3 -1
- package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
- package/manifests/mongodb-4.4/pv-pvc.yaml +10 -14
- package/manifests/mongodb-4.4/statefulset.yaml +79 -0
- package/manifests/mongodb-4.4/storage-class.yaml +9 -0
- package/manifests/valkey/statefulset.yaml +1 -1
- package/manifests/valkey/valkey-nodeport.yaml +17 -0
- package/package.json +31 -19
- package/scripts/ipxe-setup.sh +52 -49
- package/scripts/k3s-node-setup.sh +81 -46
- package/scripts/link-local-underpost-cli.sh +6 -0
- package/scripts/lxd-vm-setup.sh +193 -8
- package/scripts/maas-nat-firewalld.sh +145 -0
- package/scripts/test-monitor.sh +250 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +38 -33
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +16 -16
- package/src/api/core/core.router.js +19 -14
- package/src/api/core/core.service.js +5 -5
- package/src/api/crypto/crypto.router.js +18 -12
- package/src/api/crypto/crypto.service.js +3 -3
- package/src/api/cyberia-action/cyberia-action.model.js +1 -1
- package/src/api/cyberia-action/cyberia-action.router.js +22 -18
- package/src/api/cyberia-action/cyberia-action.service.js +5 -5
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +74 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +99 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +98 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +25 -20
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +6 -6
- package/src/api/cyberia-entity/cyberia-entity.router.js +22 -18
- package/src/api/cyberia-entity/cyberia-entity.service.js +5 -5
- package/src/api/cyberia-instance/cyberia-fallback-world.js +79 -4
- package/src/api/cyberia-instance/cyberia-instance.router.js +57 -52
- package/src/api/cyberia-instance/cyberia-instance.service.js +10 -10
- package/src/api/cyberia-instance/cyberia-world-generator.js +3 -3
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +14 -48
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +22 -18
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +5 -5
- package/src/api/cyberia-map/cyberia-map.router.js +35 -30
- package/src/api/cyberia-map/cyberia-map.service.js +7 -7
- package/src/api/cyberia-quest/cyberia-quest.model.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +22 -18
- package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +22 -18
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +5 -5
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +458 -0
- package/src/api/default/default.router.js +22 -18
- package/src/api/default/default.service.js +5 -5
- package/src/api/document/document.router.js +28 -23
- package/src/api/document/document.service.js +100 -23
- package/src/api/file/file.router.js +19 -13
- package/src/api/file/file.service.js +9 -7
- package/src/api/instance/instance.router.js +29 -24
- package/src/api/instance/instance.service.js +6 -6
- package/src/api/ipfs/ipfs.router.js +21 -16
- package/src/api/ipfs/ipfs.service.js +8 -8
- package/src/api/object-layer/object-layer.router.js +512 -507
- package/src/api/object-layer/object-layer.service.js +17 -14
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +22 -18
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +5 -5
- package/src/api/test/test.router.js +17 -12
- package/src/api/types.js +24 -0
- package/src/api/user/guest.service.js +5 -4
- package/src/api/user/user.router.js +297 -288
- package/src/api/user/user.service.js +100 -35
- package/src/cli/baremetal.js +132 -101
- package/src/cli/cluster.js +700 -232
- package/src/cli/db.js +59 -60
- package/src/cli/deploy.js +291 -294
- package/src/cli/env.js +1 -4
- package/src/cli/fs.js +13 -3
- package/src/cli/image.js +58 -4
- package/src/cli/index.js +127 -15
- package/src/cli/ipfs.js +4 -6
- package/src/cli/kubectl.js +4 -1
- package/src/cli/lxd.js +1099 -223
- package/src/cli/monitor.js +396 -9
- package/src/cli/release.js +355 -146
- package/src/cli/repository.js +169 -30
- package/src/cli/run.js +347 -117
- package/src/cli/secrets.js +11 -2
- package/src/cli/test.js +9 -3
- package/src/client/Default.index.js +9 -3
- package/src/client/components/core/Auth.js +5 -0
- package/src/client/components/core/ClientEvents.js +76 -0
- package/src/client/components/core/EventBus.js +4 -0
- package/src/client/components/core/Modal.js +82 -41
- package/src/client/components/core/PanelForm.js +14 -10
- package/src/client/components/core/Worker.js +162 -363
- package/src/client/components/cyberia/MapEngineCyberia.js +1 -1
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +330 -0
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +55 -1
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +223 -361
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +114 -327
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +200 -222
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +212 -185
- package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
- package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +2 -2
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +23 -1
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
- package/src/client/ssr/views/CyberiaServerMetrics.js +982 -0
- package/src/client/sw/core.sw.js +174 -112
- package/src/db/DataBaseProvider.js +115 -15
- package/src/db/mariadb/MariaDB.js +2 -1
- package/src/db/mongo/MongoBootstrap.js +657 -0
- package/src/db/mongo/MongooseDB.js +130 -21
- package/src/grpc/cyberia/grpc-server.js +25 -57
- package/src/index.js +1 -1
- package/src/runtime/cyberia-client/Dockerfile +10 -7
- package/src/runtime/cyberia-client/Dockerfile.dev +67 -0
- package/src/runtime/cyberia-server/Dockerfile +11 -6
- package/src/runtime/cyberia-server/Dockerfile.dev +47 -0
- package/src/runtime/express/Express.js +2 -2
- package/src/runtime/wp/Dockerfile +3 -3
- package/src/runtime/wp/Wp.js +8 -5
- package/src/server/auth.js +2 -2
- package/src/server/catalog-underpost.js +61 -0
- package/src/server/catalog.js +77 -0
- package/src/server/client-build-docs.js +1 -1
- package/src/server/client-build.js +94 -129
- package/src/server/conf.js +496 -135
- package/src/server/ipfs-client.js +5 -3
- package/src/server/process.js +180 -19
- package/src/server/proxy.js +9 -2
- package/src/server/runtime-status.js +235 -0
- package/src/server/runtime.js +1 -1
- package/src/server/start.js +44 -11
- package/src/server/valkey.js +2 -0
- package/src/ws/IoInterface.js +16 -16
- package/src/ws/core/channels/core.ws.chat.js +11 -11
- package/src/ws/core/channels/core.ws.mailer.js +29 -29
- package/src/ws/core/channels/core.ws.stream.js +19 -19
- package/src/ws/core/core.ws.connection.js +8 -8
- package/src/ws/core/core.ws.server.js +6 -5
- package/src/ws/default/channels/default.ws.main.js +10 -10
- package/src/ws/default/default.ws.connection.js +4 -4
- package/src/ws/default/default.ws.server.js +4 -3
- package/test/deploy-monitor.test.js +251 -0
- package/bin/file.js +0 -202
- package/bin/vs.js +0 -74
- package/bin/zed.js +0 -84
- package/manifests/deployment/dd-test-development/deployment.yaml +0 -254
- package/manifests/deployment/dd-test-development/proxy.yaml +0 -102
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +0 -574
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +0 -467
- package/src/client/ssr/email/DefaultRecoverEmail.js +0 -21
- package/src/client/ssr/email/DefaultVerifyEmail.js +0 -17
- package/src/client/ssr/pages/CyberiaServerMetrics.js +0 -461
- /package/src/client/ssr/{offline → views}/Maintenance.js +0 -0
- /package/src/client/ssr/{offline → views}/NoNetworkConnection.js +0 -0
- /package/src/client/ssr/{pages → views}/Test.js +0 -0
|
@@ -1,443 +1,305 @@
|
|
|
1
|
-
# Cyberia
|
|
1
|
+
# Cyberia — Architecture
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Cyberia is the real-time MMO extension that runs on Underpost Platform. This document describes the three Cyberia processes, their boundaries, the data flow between them, and the canonical model for tick, snapshot, prediction, reconciliation, interpolation, and replication.
|
|
4
|
+
|
|
5
|
+
Underpost Platform provides the toolchain, deployment surface, PWA delivery, and base infrastructure. The three Cyberia processes operate on top of it.
|
|
4
6
|
|
|
5
7
|
---
|
|
6
8
|
|
|
7
|
-
##
|
|
9
|
+
## Process model
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ UNDERPOST PLATFORM (infra · toolchain · deploy · PWA/Workbox) │
|
|
14
|
+
│ │
|
|
15
|
+
│ ┌─────────────────────┐ │
|
|
16
|
+
│ │ Persistent backend │ ← Cyberia content authority + asset backend │
|
|
17
|
+
│ │ ────────────────── │ │
|
|
18
|
+
│ │ engine-cyberia │ Node.js │
|
|
19
|
+
│ │ MongoDB │ │
|
|
20
|
+
│ │ IPFS / Cloudinary │ │
|
|
21
|
+
│ │ ObjectLayerToken │ Hyperledger Besu (off-line dependency) │
|
|
22
|
+
│ └─────────┬───────────┘ │
|
|
23
|
+
│ │ gRPC (world load, hot reload) │
|
|
24
|
+
│ ▼ │
|
|
25
|
+
│ ┌─────────────────────┐ │
|
|
26
|
+
│ │ Authoritative │ ← Cyberia simulation authority │
|
|
27
|
+
│ │ simulation runtime │ │
|
|
28
|
+
│ │ ────────────────── │ │
|
|
29
|
+
│ │ cyberia-server │ Go │
|
|
30
|
+
│ └─────────┬───────────┘ │
|
|
31
|
+
│ │ WebSocket (binary AOI snapshots, typed input commands) │
|
|
32
|
+
│ ▼ │
|
|
33
|
+
│ ┌─────────────────────┐ │
|
|
34
|
+
│ │ Presentation │ ← Cyberia render + prediction client │
|
|
35
|
+
│ │ runtime │ │
|
|
36
|
+
│ │ ────────────────── │ │
|
|
37
|
+
│ │ cyberia-client │ C / WebAssembly (Raylib · Emscripten) │
|
|
38
|
+
│ └─────────────────────┘ │
|
|
39
|
+
│ │ │
|
|
40
|
+
│ │ REST (atlas frames, asset metadata, optional client hints) │
|
|
41
|
+
│ └──→ engine-cyberia │
|
|
42
|
+
└─────────────────────────────────────────────────────────────────────────┘
|
|
43
|
+
```
|
|
10
44
|
|
|
11
|
-
|
|
12
|
-
2. **cyberia-server** (Go) — real-time multiplayer game logic, binary WebSocket AOI protocol.
|
|
13
|
-
3. **cyberia-client** (C/WASM) — game rendering client compiled to WebAssembly.
|
|
45
|
+
Three processes, strict role separation. The ecosystem is fully operational only when all three are running and healthy at the same time.
|
|
14
46
|
|
|
15
47
|
---
|
|
16
48
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
```mermaid
|
|
20
|
-
graph TB
|
|
21
|
-
subgraph Client["cyberia-client (C/WASM)"]
|
|
22
|
-
SDL["SDL2 + OpenGL ES2\nRendering Pipeline"]
|
|
23
|
-
BinDecoder["Binary AOI Decoder"]
|
|
24
|
-
OLEngine["Object Layer Engine\nAtlas Sprite Compositor"]
|
|
25
|
-
Input["Tap/Click Input Handler"]
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
subgraph GoServer["cyberia-server (Go)"]
|
|
29
|
-
WS["WebSocket Server :8081\nBinary AOI Protocol"]
|
|
30
|
-
AOI["Area of Interest (AOI)\nSpatial Filtering"]
|
|
31
|
-
PathFinding["A* Pathfinding\n(Bot Navigation)"]
|
|
32
|
-
Skills["Skill Dispatcher\nProjectile · Doppelganger"]
|
|
33
|
-
Economy["Economy Module\nFountain & Sink"]
|
|
34
|
-
gRPCClient["gRPC Client\nWorld Builder"]
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
subgraph Engine["engine-cyberia (Node.js)"]
|
|
38
|
-
Express["Express REST API\n:4005–4014"]
|
|
39
|
-
gRPCServer["gRPC Server :50051\nCyberiaDataService"]
|
|
40
|
-
MongoDB["MongoDB\nMongoose ORM"]
|
|
41
|
-
Valkey["Valkey\n(Redis-compatible)"]
|
|
42
|
-
IPFS["IPFS Cluster + Kubo\nAsset Pinning"]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
subgraph Blockchain["Hyperledger Besu :8545"]
|
|
46
|
-
OLT["ObjectLayerToken\nERC-1155 Contract"]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
Client <-->|"WS binary messages\n(little-endian)"| GoServer
|
|
50
|
-
Client <-->|"REST: atlas PNG\nmetadata JSON"| Engine
|
|
51
|
-
GoServer <-->|"gRPC :50051\nGetFullInstance\nGetObjectLayerBatch\nGetMapData · Ping"| Engine
|
|
52
|
-
Engine <-->|"ethers.js\nEIP-712 + ERC-1155"| Blockchain
|
|
53
|
-
Engine <-->|"IPFS API"| IPFS
|
|
54
|
-
Engine <-->|"mongoose"| MongoDB
|
|
55
|
-
```
|
|
49
|
+
## Role definitions
|
|
56
50
|
|
|
57
|
-
|
|
51
|
+
### engine-cyberia (Node.js) — content authority
|
|
58
52
|
|
|
59
|
-
|
|
53
|
+
The content-authoring backend and persistence layer for Cyberia. Owns persisted data and exposes it through two transports: gRPC (consumed by `cyberia-server` at boot and during hot reload) and REST (consumed by `cyberia-client` for asset distribution and optional presentation overrides).
|
|
60
54
|
|
|
61
|
-
|
|
55
|
+
What it owns:
|
|
62
56
|
|
|
63
|
-
|
|
57
|
+
- Content generation, validation, and persistence.
|
|
58
|
+
- Maps, portals, object layers, atlas/sprite-sheet metadata.
|
|
59
|
+
- World configuration: AOI radius, economy rules, skill rules, equipment rules, entity gameplay defaults.
|
|
60
|
+
- Persisted character/quest/dialogue/action data.
|
|
61
|
+
- gRPC `CyberiaDataService` for world load and content streaming.
|
|
62
|
+
- REST APIs for assets and the optional client-hints overrides.
|
|
63
|
+
- Static content distribution + Cloudinary-backed asset flow.
|
|
64
|
+
- Editor and CLI integration for content workflows.
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
What it does NOT own:
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
| `atlas-sprite-sheet` | Consolidated atlas PNG + metadata |
|
|
72
|
-
| `cyberia-instance` | Instance graph (maps + portal topology) |
|
|
73
|
-
| `cyberia-map` | Map grid, entity placements, metadata |
|
|
74
|
-
| `cyberia-entity` | Entity definitions |
|
|
75
|
-
| `cyberia-instance-conf` | Instance configuration (skills, economy, equipment) |
|
|
76
|
-
| `cyberia-quest` | Quest definitions |
|
|
77
|
-
| `cyberia-quest-progress` | Per-player quest progress |
|
|
78
|
-
| `cyberia-action` | NPC action definitions |
|
|
79
|
-
| `cyberia-dialogue` | Dialogue lines |
|
|
68
|
+
- Real-time simulation. It is not a gameplay runtime.
|
|
69
|
+
- Per-tick state advancement.
|
|
70
|
+
- Client presentation policy (palette, camera, dev overlay, icon visuals).
|
|
71
|
+
- World mutation during gameplay.
|
|
80
72
|
|
|
81
|
-
|
|
73
|
+
### cyberia-server (Go) — authoritative simulation runtime
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
| ------------------------------- | ---------------------------------------------------------------- |
|
|
85
|
-
| `GetFullInstance(instanceCode)` | Instance graph + maps + entities + ObjectLayers + InstanceConfig |
|
|
86
|
-
| `GetMapData(mapCode)` | Single map grid and entity data |
|
|
87
|
-
| `GetObjectLayerBatch()` | Stream all ObjectLayers (cache warm-up) |
|
|
88
|
-
| `GetObjectLayer(itemId)` | Single ObjectLayer by item ID |
|
|
89
|
-
| `GetObjectLayerManifest()` | All `itemId + sha256` pairs (hot-reload diff) |
|
|
90
|
-
| `Ping()` | Engine liveness check |
|
|
75
|
+
The tick-based authoritative simulation. Owns world state and the gameplay rules that mutate it.
|
|
91
76
|
|
|
92
|
-
|
|
77
|
+
What it owns:
|
|
93
78
|
|
|
94
|
-
|
|
79
|
+
- Authoritative world state.
|
|
80
|
+
- The tick: a `uint32` advanced once per simulation step at a fixed `tickRate`.
|
|
81
|
+
- Simulation phases — the only allowed mutators of world state.
|
|
82
|
+
- AOI replication: per-player interest filtering and snapshot emission.
|
|
83
|
+
- Input command processing: typed input commands drained from per-player queues each tick.
|
|
84
|
+
- Snapshot generation and delivery via WebSocket.
|
|
95
85
|
|
|
96
|
-
|
|
86
|
+
What it does NOT own:
|
|
97
87
|
|
|
98
|
-
|
|
88
|
+
- Persistence (loaded once at boot from engine-cyberia).
|
|
89
|
+
- Client presentation. The server holds no palette, no camera knobs, no dev-overlay flag, no status-icon visuals.
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
graph LR
|
|
102
|
-
A["gRPC\nGetFullInstance"] --> B["BuildWorldFromInstance\ninstance_loader.go"]
|
|
103
|
-
B --> C["Maps + Portals\n+ Entity Registry"]
|
|
104
|
-
C --> D["Game Loop\nserver.go"]
|
|
105
|
-
D --> E["AOI Ticks\naoi_binary.go"]
|
|
106
|
-
E --> F["Binary WS Messages\nto C clients"]
|
|
107
|
-
```
|
|
91
|
+
### cyberia-client (C / WebAssembly) — presentation runtime
|
|
108
92
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
| File | Responsibility |
|
|
112
|
-
| ----------------------- | ----------------------------------------------------- |
|
|
113
|
-
| `server.go` | WebSocket lifecycle, game loop, player registry |
|
|
114
|
-
| `aoi_binary.go` | Binary AOI wire format encoder/decoder |
|
|
115
|
-
| `object_layer.go` | ObjectLayer Go types mirroring the MongoDB schema |
|
|
116
|
-
| `collision.go` | Grid collision detection, portal transitions |
|
|
117
|
-
| `pathfinding.go` | A\* pathfinding for bot navigation |
|
|
118
|
-
| `skill.go` | Skill entry points: tap action trigger, on-kill hooks |
|
|
119
|
-
| `skill_dispatcher.go` | Skill registry: `InitSkills`, `DispatchSkill` |
|
|
120
|
-
| `skill_projectile.go` | Projectile skill handler |
|
|
121
|
-
| `skill_doppelganger.go` | Doppelganger skill handler |
|
|
122
|
-
| `economy.go` | Fountain & Sink coin economy |
|
|
123
|
-
| `frozen_state.go` | FrozenInteractionState (modal protection) |
|
|
124
|
-
| `entity_status.go` | Entity Status Indicator (ESI) computation |
|
|
125
|
-
| `life_regen.go` | HP regeneration loop |
|
|
126
|
-
| `ai.go` | Bot AI behavior (hostile/passive) |
|
|
127
|
-
| `stats.go` | Stat aggregation and sum-stats limit enforcement |
|
|
128
|
-
| `instance_loader.go` | World reconstruction from gRPC data |
|
|
129
|
-
| `handlers.go` | WebSocket message handlers |
|
|
130
|
-
| `grpcclient/` | gRPC client implementation |
|
|
93
|
+
The render and interactive runtime. Compiled to WASM via Emscripten and served as a Progressive Web App through the Underpost Platform delivery pipeline.
|
|
131
94
|
|
|
132
|
-
|
|
95
|
+
What it owns:
|
|
133
96
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
| `object_layer.c` | ObjectLayer metadata store |
|
|
148
|
-
| `object_layers_management.c` | Multi-layer management per entity |
|
|
149
|
-
| `entity_render.c` | Per-entity layer compositing |
|
|
150
|
-
| `layer_z_order.c` | Z-order sorting for rendering |
|
|
151
|
-
| `ol_as_animated_ico.c` | Animated Object Layer rendering |
|
|
152
|
-
| `ol_stack_ico.c` | Stacked icon rendering |
|
|
153
|
-
| `texture_manager.c` | Atlas texture loading and caching |
|
|
154
|
-
| `input.c` | Tap/click input handling |
|
|
155
|
-
| `floating_combat_text.c` | FCT event rendering |
|
|
156
|
-
| `inventory_bar.c` | Bottom inventory bar UI |
|
|
157
|
-
| `inventory_modal.c` | Full inventory modal |
|
|
158
|
-
| `entity_overhead_ui.c` | Nameplate + status icon rendering |
|
|
159
|
-
| `interaction_bubble.c` | NPC interaction prompt bubble |
|
|
160
|
-
| `tap_effect.c` | Tap visual feedback animation |
|
|
161
|
-
| `modal_dialogue.c` | NPC dialogue modal |
|
|
162
|
-
| `modal_player.c` | Player info modal |
|
|
163
|
-
| `message_parser.c` | Server message routing |
|
|
164
|
-
|
|
165
|
-
**Build system:**
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
# Development build
|
|
169
|
-
make -f Web.mk clean && make -f Web.mk web
|
|
170
|
-
|
|
171
|
-
# Production / release build
|
|
172
|
-
make -f Web.mk clean && make -f Web.mk web BUILD_MODE=RELEASE
|
|
173
|
-
```
|
|
97
|
+
- Rendering and UI.
|
|
98
|
+
- Input capture: raw OS events → typed input commands with monotonic sequence numbers.
|
|
99
|
+
- Prediction of the local player.
|
|
100
|
+
- Reconciliation against authoritative snapshots.
|
|
101
|
+
- Interpolation of remote entities.
|
|
102
|
+
- Presentation defaults (palette, status-icon visuals, camera knobs, interpolation window, dev-overlay flag) — loaded at startup from the client-hints REST endpoint.
|
|
103
|
+
- Optional client-hints fetch for per-instance presentation overrides.
|
|
104
|
+
|
|
105
|
+
What it does NOT own:
|
|
106
|
+
|
|
107
|
+
- World simulation.
|
|
108
|
+
- Economy outcomes, combat resolution, skill dispatch decisions.
|
|
109
|
+
- Any state another client depends on for correctness.
|
|
174
110
|
|
|
175
111
|
---
|
|
176
112
|
|
|
177
|
-
##
|
|
113
|
+
## Runtime operating model
|
|
178
114
|
|
|
179
|
-
The
|
|
115
|
+
The three processes are supervised independently. Each service owns its own monitor and reconnector. The game is playable only when all three are healthy at the same time.
|
|
180
116
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
0x03 = full_aoi (complete world snapshot)
|
|
187
|
-
0x04 = FCT (Floating Combat Text, 14 bytes fixed)
|
|
188
|
-
0x05 = ItemFCT (Item quantity FCT, variable)
|
|
189
|
-
[1..2] u16 reserved (0)
|
|
190
|
-
[3..4] u16 entityCount
|
|
191
|
-
|
|
192
|
-
Per-entity block (variable):
|
|
193
|
-
[0] u8 flags
|
|
194
|
-
bits 0-2: entity type (0=player, 1=bot, 2=floor, 3=obstacle, 4=portal, 5=foreground)
|
|
195
|
-
bit 3: removed (entity left AOI)
|
|
196
|
-
bit 4: has life data
|
|
197
|
-
bit 5: has respawn timer
|
|
198
|
-
bit 6: has behavior string
|
|
199
|
-
bit 7: has color data (RGBA)
|
|
200
|
-
[1..36] 36B entity UUID (zero-padded)
|
|
201
|
-
-- if not removed: --
|
|
202
|
-
f32 posX, posY, dimW, dimH
|
|
203
|
-
u8 direction (0–8: UP, UP_RIGHT, RIGHT, DOWN_RIGHT, DOWN, DOWN_LEFT, LEFT, UP_LEFT, NONE)
|
|
204
|
-
u8 mode (0=idle, 1=walking, 2=teleporting)
|
|
205
|
-
-- if bit 4: f32 life, f32 maxLife --
|
|
206
|
-
-- if bit 5: f32 respawnIn --
|
|
207
|
-
-- if bit 6: u8 behaviorLen + str behavior --
|
|
208
|
-
-- if bit 7: u8 r, g, b, a --
|
|
209
|
-
-- item ID stack: --
|
|
210
|
-
u8 itemIdCount
|
|
211
|
-
per item: u8 len + str itemId
|
|
212
|
-
|
|
213
|
-
Self-player section (appended after entity blocks):
|
|
214
|
-
<entity block fields>
|
|
215
|
-
f32 aoiMinX, aoiMinY, aoiMaxX, aoiMaxY
|
|
216
|
-
u8 onPortal
|
|
217
|
-
u16 sumStatsLimit
|
|
218
|
-
u16 activeStatsSum
|
|
219
|
-
u8+str mapCode
|
|
220
|
-
u8 pathLen
|
|
221
|
-
per path point: i16 x, i16 y
|
|
222
|
-
i16 targetPosX, targetPosY
|
|
223
|
-
u8+str activePortalID
|
|
224
|
-
u32 coinBalance
|
|
225
|
-
<full inventory>
|
|
226
|
-
u8 frozen (FrozenInteractionState)
|
|
227
|
-
```
|
|
117
|
+
| State | Meaning |
|
|
118
|
+
| ---------- | -------------------------------------------------------------------- |
|
|
119
|
+
| `healthy` | all three Cyberia services are up and connected |
|
|
120
|
+
| `degraded` | at least one service is reconnecting or unavailable |
|
|
121
|
+
| `standby` | gameplay is paused because the full three-service set is not healthy |
|
|
228
122
|
|
|
229
|
-
|
|
123
|
+
Dependency between services is handled by supervision and reconnect loops:
|
|
230
124
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
| `0x01` | `FCTTypeRegen` | Green | `+N` HP gained |
|
|
235
|
-
| `0x02` | `FCTTypeCoinGain` | Yellow | `+N` coins |
|
|
236
|
-
| `0x03` | `FCTTypeCoinLoss` | Yellow | `-N` coins |
|
|
237
|
-
| `0x04` | `FCTTypeItemGain` | Cyan | `+N ItemID` |
|
|
238
|
-
| `0x05` | `FCTTypeItemLoss` | Purple | `-N ItemID` |
|
|
125
|
+
- `cyberia-server` dials `engine-cyberia` gRPC at boot and exits on dial failure rather than fabricate a world. On reconnect, it reloads world configuration.
|
|
126
|
+
- `cyberia-client` reconnects to `cyberia-server` over WebSocket and re-fetches content from `engine-cyberia` over REST independently.
|
|
127
|
+
- If any one of the three services goes unhealthy, the game moves to standby until all three recover.
|
|
239
128
|
|
|
240
|
-
|
|
129
|
+
Underpost Platform deploy orchestration ensures the backend layer is ready before the simulation layer is started, and the simulation layer is ready before the presentation layer connects. This ordering is an infrastructure concern, not a documentation model: the processes themselves are supervised and reconnect without requiring a manual restart chain.
|
|
241
130
|
|
|
242
|
-
|
|
131
|
+
---
|
|
243
132
|
|
|
244
|
-
|
|
245
|
-
graph LR
|
|
246
|
-
Engine["Node.js Engine\nMongoDB + Express\ngrpc-server.js :50051"]
|
|
247
|
-
GoServer["Go Game Server\ncyberia-server\ngrpcclient/"]
|
|
133
|
+
## Tick model
|
|
248
134
|
|
|
249
|
-
|
|
250
|
-
```
|
|
135
|
+
The tick is the universal coordinate of the simulation. Every server→client snapshot and every client→server input command carries a tick value.
|
|
251
136
|
|
|
252
|
-
|
|
137
|
+
| Concept | Value | Notes |
|
|
138
|
+
| ------------------------ | ------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
139
|
+
| **tick** | `uint32` | Monotonic simulation step counter on `cyberia-server`. Resets only on world rebuild. |
|
|
140
|
+
| **tick rate** | Hz (default `30`) | Simulation frequency. Authoritative; comes from world configuration. The string "fps" is never used to describe the server. |
|
|
141
|
+
| **snapshot rate** | Hz (default `20`) | AOI replication frequency. Decoupled from tick rate so bandwidth scales independently of simulation fidelity. |
|
|
142
|
+
| **tick duration** | `1 / tick_rate` | The dt used by every simulation phase. |
|
|
143
|
+
| **client tick estimate** | derived | Client estimate of the server's current tick, used to stamp outgoing input commands. |
|
|
144
|
+
| **render tick** | `server_tick_estimate − INTERP_TICKS` | The tick the interpolation module samples remote entities at. |
|
|
253
145
|
|
|
254
|
-
|
|
255
|
-
MongoDB (CyberiaInstance + CyberiaMap + ObjectLayer)
|
|
256
|
-
│
|
|
257
|
-
▼
|
|
258
|
-
Node.js Engine (grpc-server.js)
|
|
259
|
-
│ GetFullInstance → instance graph + maps + entities + ObjectLayers + InstanceConfig
|
|
260
|
-
│ GetObjectLayerBatch → stream all ObjectLayers
|
|
261
|
-
│ GetObjectLayerManifest → itemId + sha256 pairs (hot-reload diffing)
|
|
262
|
-
│ Ping → liveness check
|
|
263
|
-
▼
|
|
264
|
-
Go Game Server (world_builder.go → instance_loader.go → server.go)
|
|
265
|
-
│ ApplyInstanceConfig → sets all game parameters from gRPC
|
|
266
|
-
│ BuildWorldFromInstance → builds maps, entities, portals
|
|
267
|
-
│ ReplaceObjectLayerCache → caches ObjectLayer metadata
|
|
268
|
-
▼
|
|
269
|
-
C/WASM Client (WebSocket binary AOI protocol)
|
|
270
|
-
│ init_data → game config, player state, grid dimensions
|
|
271
|
-
│ metadata → ObjectLayer cache (delivered once after connect)
|
|
272
|
-
│ aoi_update → binary-encoded entity positions, directions, modes, colors, item stacks
|
|
273
|
-
```
|
|
146
|
+
Three clocks, one tick number: simulation tick (server), snapshot tick (server replication), render frame (client). The tick number is the only synchronization point.
|
|
274
147
|
|
|
275
148
|
---
|
|
276
149
|
|
|
277
|
-
##
|
|
150
|
+
## Simulation phases
|
|
278
151
|
|
|
279
|
-
|
|
152
|
+
Inside one simulation tick, `cyberia-server` runs the following phases in fixed order. These are the only functions that mutate authoritative world state:
|
|
280
153
|
|
|
281
|
-
|
|
282
|
-
|
|
154
|
+
1. `phaseInput` — drain each player's `InputQueue`; dispatch typed input commands to gameplay handlers.
|
|
155
|
+
2. `phaseLifecycle` — respawn timers, despawn expirations.
|
|
156
|
+
3. `phaseSkills` — skill projectile collisions.
|
|
157
|
+
4. `phaseAI` — bot behaviour decisions.
|
|
158
|
+
5. `phaseMovement` — integrate positions using `tickDuration`.
|
|
159
|
+
6. `phasePortals` — portal entry and teleport.
|
|
283
160
|
|
|
284
|
-
|
|
161
|
+
A separate ticker runs replication independently of the simulation:
|
|
285
162
|
|
|
286
|
-
|
|
287
|
-
| -------------- | ------------------------------------------- |
|
|
288
|
-
| `inter-portal` | Teleport to specific cell on target map |
|
|
289
|
-
| `inter-random` | Teleport to random valid cell on target map |
|
|
290
|
-
| `intra-portal` | Teleport within same map to specific cell |
|
|
291
|
-
| `intra-random` | Teleport within same map to random cell |
|
|
163
|
+
- `phaseReplication` — per player: compute AOI, encode snapshot, dispatch. Runs at `snapshotRate`.
|
|
292
164
|
|
|
293
|
-
|
|
165
|
+
Phases never read presentation data. They consume world configuration loaded at boot (gameplay rules) and the input queue.
|
|
294
166
|
|
|
295
167
|
---
|
|
296
168
|
|
|
297
|
-
##
|
|
169
|
+
## Client render frame
|
|
298
170
|
|
|
299
|
-
|
|
171
|
+
The render frame runs at vsync. Inside one render frame, `cyberia-client` performs:
|
|
300
172
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
| `obstacle` | static | Collision tile |
|
|
310
|
-
| `portal` | static | Zone transition trigger |
|
|
311
|
-
| `foreground` | static | Foreground decoration |
|
|
312
|
-
| `resource` | extractable | Exploitable world object |
|
|
313
|
-
|
|
314
|
-
### Entity Status Indicator (ESI)
|
|
315
|
-
|
|
316
|
-
The Go server computes a status `u8` per entity on each AOI tick. The C client renders the corresponding icon above the entity nameplate:
|
|
317
|
-
|
|
318
|
-
| `id` | Name | Icon | Description |
|
|
319
|
-
| ---- | -------------------- | --------------- | -------------------------------- |
|
|
320
|
-
| 0 | `none` | — | Skill/coin bots, world objects |
|
|
321
|
-
| 1 | `passive` | arrow-down-gray | Non-aggressive bot |
|
|
322
|
-
| 2 | `hostile` | arrow-down-red | Aggressive bot (will aggro) |
|
|
323
|
-
| 3 | `frozen` | chat | Player in FrozenInteractionState |
|
|
324
|
-
| 4 | `player` | arrow-down | Normal alive player |
|
|
325
|
-
| 5 | `dead` | skull | Dead / respawning entity |
|
|
326
|
-
| 6 | `resource` | arrow-down-gray | Static exploitable resource |
|
|
327
|
-
| 7 | `resource-extracted` | clock | Depleted resource (respawning) |
|
|
328
|
-
| 8 | `action-provider` | chat (bounce) | NPC with available actions |
|
|
173
|
+
1. Poll any pending optional client-hints fetch.
|
|
174
|
+
2. Capture raw input → build typed input command (`kind`, `clientTick`, `sequence`, payload) → apply to prediction → send on the wire.
|
|
175
|
+
3. Reconcile against the latest snapshot: drop input commands ≤ `lastAckedSequence`, rewind self to authoritative position, replay unacked commands.
|
|
176
|
+
4. Fixed-timestep simulation: while accumulator ≥ `tickDuration`, advance prediction one tick.
|
|
177
|
+
5. Interpolation: compute remote-entity view positions at `renderTick`.
|
|
178
|
+
6. Render. Read view models; never mutate world state.
|
|
179
|
+
|
|
180
|
+
Render frame rate is independent of simulation tick rate. The fixed-timestep accumulator ensures the predicted simulation advances at the authoritative `tickRate` regardless of FPS.
|
|
329
181
|
|
|
330
182
|
---
|
|
331
183
|
|
|
332
|
-
##
|
|
184
|
+
## Wire protocol — AOI snapshot header
|
|
185
|
+
|
|
186
|
+
Snapshots travel as binary WebSocket frames. The header carries the simulation tick and the per-player acknowledged input sequence.
|
|
333
187
|
|
|
334
|
-
|
|
188
|
+
```
|
|
189
|
+
Header (binary, little-endian, 11 bytes for AOI snapshots):
|
|
190
|
+
[0] u8 msgType 0x01 = aoi_update, 0x03 = full_aoi
|
|
191
|
+
[1..4] u32 tick simulation tick at which the snapshot was produced
|
|
192
|
+
[5..8] u32 lastAcked highest InputCommand.Sequence applied for this player
|
|
193
|
+
[9..10] u16 entityCount entity blocks that follow
|
|
194
|
+
```
|
|
335
195
|
|
|
336
|
-
|
|
337
|
-
- Cannot send or receive movement events.
|
|
338
|
-
- The rest of the world continues normally.
|
|
339
|
-
- Managed exclusively by `FreezePlayer` / `ThawPlayer` in `frozen_state.go`.
|
|
196
|
+
Other message types (init data, FCT) use their own headers and are not part of the per-tick replication stream.
|
|
340
197
|
|
|
341
198
|
---
|
|
342
199
|
|
|
343
|
-
##
|
|
200
|
+
## Input command pipeline
|
|
344
201
|
|
|
345
|
-
|
|
202
|
+
Client input flows through a typed pipeline. There is no JSON intermediate on the binary path. The simulation tick is the only consumer.
|
|
346
203
|
|
|
347
204
|
```
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
205
|
+
WS frame (binary) → decode → typed InputCommand{kind, clientTick, sequence, payload}
|
|
206
|
+
↓
|
|
207
|
+
dispatchInputCommand
|
|
208
|
+
↓
|
|
209
|
+
PlayerState.InputQueue (per-player, bounded)
|
|
210
|
+
↓
|
|
211
|
+
phaseInput (under world mutex, once per simulation tick)
|
|
212
|
+
↓
|
|
213
|
+
phase_input_handlers.go — typed dispatch per InputKind
|
|
214
|
+
↓
|
|
215
|
+
authoritative world state
|
|
351
216
|
```
|
|
352
217
|
|
|
353
|
-
|
|
218
|
+
`InputCommand.Sequence` is monotonic per client. The server tracks the highest applied sequence per player; `phaseReplication` writes it into every snapshot header. The client drops acknowledged input commands from its prediction replay buffer using this value.
|
|
354
219
|
|
|
355
|
-
|
|
356
|
-
| -------------------------- | ---------------------------- | ------------------------------------------------ |
|
|
357
|
-
| `projectile` | `executeProjectileSkill()` | Spawn a directional projectile entity |
|
|
358
|
-
| `doppelganger` | `executeDoppelgangerSkill()` | Spawn a temporary allied duplicate |
|
|
359
|
-
| `coin_drop_or_transaction` | economy handler | Spawn a coin entity at target position (economy) |
|
|
220
|
+
---
|
|
360
221
|
|
|
361
|
-
|
|
222
|
+
## Presentation metadata ownership
|
|
362
223
|
|
|
363
|
-
|
|
364
|
-
| --------------------------------- | ------------------------------------------------ |
|
|
365
|
-
| `projectileSpawnChance` | Probability of spawning a projectile per trigger |
|
|
366
|
-
| `projectileLifetimeMs` | Projectile lifetime in milliseconds |
|
|
367
|
-
| `projectileWidth/Height` | Projectile entity dimensions |
|
|
368
|
-
| `projectileSpeedMultiplier` | Speed relative to base entity speed |
|
|
369
|
-
| `doppelgangerSpawnChance` | Probability of spawning a doppelganger |
|
|
370
|
-
| `doppelgangerLifetimeMs` | Doppelganger lifetime |
|
|
371
|
-
| `doppelgangerSpawnRadius` | Max spawn distance from player |
|
|
372
|
-
| `doppelgangerInitialLifeFraction` | Initial HP as fraction of player max HP |
|
|
224
|
+
Presentation is client-owned. The authoritative server holds no presentation state.
|
|
373
225
|
|
|
374
|
-
|
|
226
|
+
| Concern | Owner | Mechanism |
|
|
227
|
+
| ------------------------------------------------ | --------------------- | ------------------------------------------------------------------------------- |
|
|
228
|
+
| Palette (named ColorRGBA entries) | engine-cyberia (REST) | served by `GET /api/cyberia-client-hints/:CYBERIA_CLIENT_HINTS_CODE`. Source schema: `SharedDefaultsCyberia.js`. |
|
|
229
|
+
| Status-icon visuals (icon stems + border colors) | engine-cyberia (REST) | same |
|
|
230
|
+
| Per-entity-type fallback color keys | engine-cyberia (REST) | same |
|
|
231
|
+
| Camera defaults (smoothing, zoom) | engine-cyberia (REST) | same |
|
|
232
|
+
| Cell-pixel size, default object dims | engine-cyberia (REST) | same |
|
|
233
|
+
| Interpolation window | engine-cyberia (REST) | same |
|
|
234
|
+
| Dev-overlay flag | engine-cyberia (REST) | same |
|
|
235
|
+
| World configuration (gameplay rules) | engine-cyberia (gRPC) | `CyberiaInstanceConf` — no presentation; only simulation |
|
|
375
236
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
```bash
|
|
379
|
-
# Terminal 1: Engine (Node.js)
|
|
380
|
-
cd /home/dd/engine
|
|
381
|
-
npm run dev
|
|
382
|
-
# Starts Express :4005+, gRPC :50051, connects to MongoDB
|
|
383
|
-
|
|
384
|
-
# Terminal 2: Go game server
|
|
385
|
-
cd /home/dd/engine/cyberia-server
|
|
386
|
-
cat > .env << 'EOF'
|
|
387
|
-
ENGINE_GRPC_ADDRESS=localhost:50051
|
|
388
|
-
INSTANCE_CODE=cyberia-main
|
|
389
|
-
ENGINE_API_BASE_URL=http://localhost:4005
|
|
390
|
-
SERVER_PORT=8081
|
|
391
|
-
EOF
|
|
392
|
-
go run main.go
|
|
393
|
-
|
|
394
|
-
# Terminal 3: C/WASM client
|
|
395
|
-
cd /home/dd/engine/cyberia-client
|
|
396
|
-
# Edit src/config.h: WS_URL="ws://localhost:8081/ws", API_BASE_URL="http://localhost:4005"
|
|
397
|
-
source ~/.emsdk/emsdk_env.sh
|
|
398
|
-
make -f Web.mk clean && make -f Web.mk web
|
|
399
|
-
make -f Web.mk serve-development # http://localhost:8082
|
|
400
|
-
```
|
|
237
|
+
The cyberia-client carries **no** compile-time palette. `domain/presentation_runtime.{c,h}` fetches the full presentation surface on startup; until the fetch settles the runtime returns a tiny inline neutral-grey bootstrap so the splash screen has something to draw. The simulation is unaffected by the fetch outcome.
|
|
401
238
|
|
|
402
|
-
|
|
239
|
+
`cyberia-server` never reads any presentation field. The only "representational" data on the simulation wire is the **active item IDs** carried inside each AOI snapshot. Everything else visual is the client's job, fed by the hints REST endpoint.
|
|
403
240
|
|
|
404
|
-
|
|
241
|
+
---
|
|
405
242
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
|
411
|
-
|
|
|
243
|
+
## Canonical vocabulary
|
|
244
|
+
|
|
245
|
+
Every Cyberia document uses the same terms. Aliases are not permitted.
|
|
246
|
+
|
|
247
|
+
| Term | Definition |
|
|
248
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
249
|
+
| **tick** | Monotonic simulation step counter. |
|
|
250
|
+
| **tick rate** | Simulation Hz on `cyberia-server`. |
|
|
251
|
+
| **snapshot** | AOI-filtered world view at one tick for one player. |
|
|
252
|
+
| **prediction** | Optimistic local apply of input commands to the predicted self entity. |
|
|
253
|
+
| **reconciliation** | Drop acknowledged inputs, rewind self to authoritative position, replay unacked inputs. |
|
|
254
|
+
| **display smoothing** | Per-render-frame exponential lerp from the discrete predicted self position to a continuous on-screen position. Decouples the visible main player from sim-tick boundaries. |
|
|
255
|
+
| **interpolation** | Render-time smoothing of remote entities, sampled from snapshot history. |
|
|
256
|
+
| **authoritative server** | `cyberia-server`. Sole authority on world state. |
|
|
257
|
+
| **content authority** | `engine-cyberia`. Sole authority on persisted content and world configuration. |
|
|
258
|
+
| **client hints** | Optional presentation overrides served by engine-cyberia. |
|
|
259
|
+
| **world configuration** | Gameplay parameters loaded at server boot from engine-cyberia. |
|
|
260
|
+
| **presentation metadata** | Render-only data. Client-owned. |
|
|
261
|
+
| **input command** | Typed client→server frame with kind, clientTick, sequence, payload. |
|
|
262
|
+
| **AOI** | Area of interest — the spatial filter that defines which entities a given player receives. |
|
|
263
|
+
| **replication** | Production and delivery of snapshots from server to clients. |
|
|
264
|
+
| **simulation phase** | A named step inside one simulation tick. |
|
|
265
|
+
| **healthy** | All three Cyberia services up and connected; game is playable. |
|
|
266
|
+
| **standby** | Game paused because at least one of the three services is not healthy. |
|
|
267
|
+
|
|
268
|
+
Forbidden usages:
|
|
269
|
+
|
|
270
|
+
- "fps" on `cyberia-server` (use **tick rate**).
|
|
271
|
+
- "frame-based" simulation language on the server.
|
|
272
|
+
- "game_state" as a god object on the client.
|
|
273
|
+
- Render metadata in `cyberia-server` state.
|
|
274
|
+
- "engine" without qualifier when the project name is intended. Use **engine-cyberia** for the Cyberia content backend; use **Underpost Platform** for the umbrella product.
|
|
412
275
|
|
|
413
276
|
---
|
|
414
277
|
|
|
415
|
-
##
|
|
278
|
+
## Instance topology
|
|
416
279
|
|
|
417
|
-
|
|
280
|
+
A `CyberiaInstance` (persisted in MongoDB, served by engine-cyberia) is a directed graph:
|
|
418
281
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
2. Go server (mmo-server) ← ENGINE_GRPC_ADDRESS=<engine-clusterIP>:50051
|
|
422
|
-
3. C client (mmo-client) ← static WASM files served on :8082
|
|
423
|
-
```
|
|
282
|
+
- **Vertices** — `CyberiaMap` documents (grid-based maps).
|
|
283
|
+
- **Edges** — `PortalEdge` records connecting source cell → target map/cell.
|
|
424
284
|
|
|
425
|
-
|
|
285
|
+
Portal modes:
|
|
426
286
|
|
|
427
|
-
|
|
287
|
+
| Mode | Behaviour |
|
|
288
|
+
| -------------- | ----------------------------------------------- |
|
|
289
|
+
| `inter-portal` | Teleport to a specific cell on a target map |
|
|
290
|
+
| `inter-random` | Teleport to a random valid cell on a target map |
|
|
291
|
+
| `intra-portal` | Teleport within the same map to a specific cell |
|
|
292
|
+
| `intra-random` | Teleport within the same map to a random cell |
|
|
428
293
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
| `INSTANCE_CODE` | `default` | Instance code to load on startup |
|
|
433
|
-
| `SERVER_PORT` | `8081` | WebSocket + HTTP server listen port |
|
|
434
|
-
| `STATIC_DIR` | `./public` | Directory for static WASM client files |
|
|
435
|
-
| `ENGINE_GRPC_RELOAD_INTERVAL_SEC` | _(disabled)_ | ObjectLayer hot-reload polling interval |
|
|
436
|
-
| `READY_CMD` | _(empty)_ | Shell command to run after server starts (orchestration readiness signal) |
|
|
294
|
+
Topology modes: `linear`, `hub-spoke`, `open`, `grid`.
|
|
295
|
+
|
|
296
|
+
---
|
|
437
297
|
|
|
438
|
-
|
|
298
|
+
## Entity types
|
|
439
299
|
|
|
440
|
-
|
|
|
441
|
-
| -------------- |
|
|
442
|
-
| `
|
|
443
|
-
| `
|
|
300
|
+
| Type | Behavior | Description |
|
|
301
|
+
| -------------- | --------------------- | --------------------------- |
|
|
302
|
+
| `player` | interactive | Local player (self) |
|
|
303
|
+
| `other_player` | interactive | Remote players inside AOI |
|
|
304
|
+
| `bot` | `hostile` / `passive` | AI-controlled entities |
|
|
305
|
+
| `skill` | `skill` | Runtime-spawned projectile |
|