cyberia 3.2.5 → 3.2.9
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 +2 -2
- package/.github/workflows/release.cd.yml +1 -2
- package/CHANGELOG.md +351 -1
- package/CLI-HELP.md +40 -13
- package/Dockerfile +0 -4
- package/README.md +242 -497
- package/bin/build.js +19 -5
- package/bin/cyberia.js +1149 -240
- package/bin/deploy.js +570 -1
- package/bin/file.js +6 -0
- package/bin/index.js +1149 -240
- package/bin/vs.js +1 -1
- package/conf.js +67 -89
- package/deployment.yaml +4 -222
- package/hardhat/package-lock.json +32 -32
- package/hardhat/package.json +3 -3
- package/jsconfig.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +2 -2
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +4 -222
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +10 -118
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -6
- package/manifests/deployment/dd-test-development/deployment.yaml +136 -66
- package/manifests/deployment/dd-test-development/proxy.yaml +41 -5
- package/package.json +23 -14
- package/proxy.yaml +10 -118
- package/scripts/k3s-node-setup.sh +2 -2
- package/scripts/nat-iptables.sh +103 -18
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +18 -18
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +7 -14
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +76 -21
- package/src/api/core/core.controller.js +10 -10
- package/src/api/core/core.service.js +10 -10
- package/src/api/crypto/crypto.controller.js +8 -8
- package/src/api/crypto/crypto.service.js +8 -8
- package/src/api/cyberia-action/cyberia-action.controller.js +74 -0
- package/src/api/cyberia-action/cyberia-action.model.js +87 -0
- package/src/api/cyberia-action/cyberia-action.router.js +27 -0
- package/src/api/cyberia-action/cyberia-action.service.js +42 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +13 -13
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +11 -11
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +2 -2
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +16 -16
- package/src/api/cyberia-entity/cyberia-entity.controller.js +10 -10
- package/src/api/cyberia-entity/cyberia-entity.service.js +10 -10
- package/src/api/cyberia-instance/cyberia-fallback-world.js +19 -209
- package/src/api/cyberia-instance/cyberia-instance.controller.js +14 -14
- package/src/api/cyberia-instance/cyberia-instance.model.js +3 -0
- package/src/api/cyberia-instance/cyberia-instance.service.js +22 -57
- package/src/api/cyberia-instance/cyberia-portal-connector.js +20 -246
- package/src/api/cyberia-instance/cyberia-world-generator.js +505 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +10 -10
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +216 -55
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +4 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +18 -14
- package/src/api/cyberia-map/cyberia-map.controller.js +10 -10
- package/src/api/cyberia-map/cyberia-map.service.js +10 -10
- package/src/api/cyberia-quest/cyberia-quest.controller.js +74 -0
- package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
- package/src/api/cyberia-quest/cyberia-quest.router.js +27 -0
- package/src/api/cyberia-quest/cyberia-quest.service.js +42 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +74 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +27 -0
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
- package/src/api/default/default.controller.js +10 -10
- package/src/api/default/default.service.js +10 -10
- package/src/api/document/document.controller.js +12 -12
- package/src/api/document/document.model.js +10 -16
- package/src/api/file/file.controller.js +8 -8
- package/src/api/file/file.model.js +10 -10
- package/src/api/file/file.service.js +36 -36
- package/src/api/instance/instance.controller.js +10 -10
- package/src/api/instance/instance.model.js +4 -10
- package/src/api/instance/instance.service.js +10 -10
- package/src/api/ipfs/ipfs.controller.js +12 -12
- package/src/api/ipfs/ipfs.model.js +4 -13
- package/src/api/ipfs/ipfs.service.js +14 -28
- package/src/api/object-layer/object-layer.controller.js +12 -12
- package/src/api/object-layer/object-layer.model.js +4 -17
- package/src/api/object-layer/object-layer.service.js +12 -12
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +10 -10
- package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +6 -16
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +18 -14
- package/src/api/test/test.controller.js +8 -8
- package/src/api/test/test.service.js +8 -8
- package/src/api/user/guest.service.js +99 -0
- package/src/api/user/user.controller.js +6 -6
- package/src/api/user/user.model.js +8 -13
- package/src/api/user/user.service.js +3 -20
- package/src/cli/cluster.js +61 -14
- package/src/cli/db.js +47 -2
- package/src/cli/deploy.js +67 -35
- package/src/cli/fs.js +79 -8
- package/src/cli/image.js +43 -1
- package/src/cli/index.js +26 -1
- package/src/cli/release.js +57 -1
- package/src/cli/repository.js +69 -31
- package/src/cli/run.js +415 -36
- package/src/cli/ssh.js +1 -1
- package/src/cli/static.js +43 -115
- package/src/client/Cryptokoyn.index.js +18 -21
- package/src/client/CyberiaPortal.index.js +19 -23
- package/src/client/Default.index.js +21 -33
- package/src/client/Itemledger.index.js +20 -26
- package/src/client/Underpost.index.js +19 -23
- package/src/client/components/core/404.js +4 -4
- package/src/client/components/core/500.js +4 -4
- package/src/client/components/core/Account.js +73 -60
- package/src/client/components/core/AgGrid.js +23 -33
- package/src/client/components/core/Alert.js +12 -13
- package/src/client/components/core/AppStore.js +1 -1
- package/src/client/components/core/Auth.js +35 -37
- package/src/client/components/core/Badge.js +7 -13
- package/src/client/components/core/BtnIcon.js +15 -17
- package/src/client/components/core/CalendarCore.js +42 -63
- package/src/client/components/core/Chat.js +13 -15
- package/src/client/components/core/ClientEvents.js +87 -0
- package/src/client/components/core/ColorPaletteElement.js +309 -0
- package/src/client/components/core/Content.js +17 -14
- package/src/client/components/core/Css.js +15 -71
- package/src/client/components/core/CssCore.js +12 -16
- package/src/client/components/core/D3Chart.js +4 -4
- package/src/client/components/core/Docs.js +64 -91
- package/src/client/components/core/DropDown.js +69 -91
- package/src/client/components/core/EventBus.js +92 -0
- package/src/client/components/core/EventsUI.js +14 -17
- package/src/client/components/core/FileExplorer.js +96 -228
- package/src/client/components/core/FullScreen.js +47 -75
- package/src/client/components/core/Input.js +24 -69
- package/src/client/components/core/Keyboard.js +25 -18
- package/src/client/components/core/KeyboardAvoidance.js +145 -0
- package/src/client/components/core/LoadingAnimation.js +25 -31
- package/src/client/components/core/LogIn.js +41 -41
- package/src/client/components/core/LogOut.js +23 -14
- package/src/client/components/core/Modal.js +462 -178
- package/src/client/components/core/NotificationManager.js +14 -18
- package/src/client/components/core/Panel.js +54 -50
- package/src/client/components/core/PanelForm.js +25 -125
- package/src/client/components/core/Polyhedron.js +110 -214
- package/src/client/components/core/PublicProfile.js +39 -32
- package/src/client/components/core/Recover.js +48 -44
- package/src/client/components/core/Responsive.js +88 -32
- package/src/client/components/core/RichText.js +9 -18
- package/src/client/components/core/Router.js +24 -3
- package/src/client/components/core/SearchBox.js +37 -37
- package/src/client/components/core/SignUp.js +39 -30
- package/src/client/components/core/SocketIo.js +31 -2
- package/src/client/components/core/SocketIoHandler.js +6 -6
- package/src/client/components/core/ToggleSwitch.js +8 -20
- package/src/client/components/core/ToolTip.js +5 -17
- package/src/client/components/core/Translate.js +56 -59
- package/src/client/components/core/Validator.js +26 -16
- package/src/client/components/core/Wallet.js +15 -26
- package/src/client/components/core/Worker.js +163 -27
- package/src/client/components/core/windowGetDimensions.js +7 -7
- package/src/client/components/cryptokoyn/{MenuCryptokoyn.js → AppShellCryptokoyn.js} +57 -57
- package/src/client/components/cryptokoyn/CssCryptokoyn.js +15 -15
- package/src/client/components/cryptokoyn/LogInCryptokoyn.js +6 -4
- package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +6 -4
- package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +4 -4
- package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +6 -4
- package/src/client/components/cyberia/InstanceEngineCyberia.js +141 -60
- package/src/client/components/cyberia/MapEngineCyberia.js +691 -214
- package/src/client/components/cyberia/ObjectLayerEngine.js +19 -0
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +1204 -94
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +196 -298
- package/src/client/components/cyberia-portal/{MenuCyberiaPortal.js → AppShellCyberiaPortal.js} +102 -102
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +305 -61
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +15 -15
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +6 -4
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +6 -4
- package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +4 -4
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +60 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +4 -4
- package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +6 -4
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -4
- package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
- package/src/client/components/default/CssDefault.js +12 -12
- package/src/client/components/default/LogInDefault.js +6 -4
- package/src/client/components/default/LogOutDefault.js +6 -4
- package/src/client/components/default/RouterDefault.js +47 -0
- package/src/client/components/default/SettingsDefault.js +4 -4
- package/src/client/components/default/SignUpDefault.js +6 -4
- package/src/client/components/default/TranslateDefault.js +3 -3
- package/src/client/components/itemledger/{MenuItemledger.js → AppShellItemledger.js} +57 -57
- package/src/client/components/itemledger/CssItemledger.js +15 -15
- package/src/client/components/itemledger/LogInItemledger.js +6 -4
- package/src/client/components/itemledger/LogOutItemledger.js +6 -4
- package/src/client/components/itemledger/RouterItemledger.js +38 -0
- package/src/client/components/itemledger/SettingsItemledger.js +4 -4
- package/src/client/components/itemledger/SignUpItemledger.js +6 -4
- package/src/client/components/itemledger/TranslateItemledger.js +3 -3
- package/src/client/components/underpost/{MenuUnderpost.js → AppShellUnderpost.js} +88 -88
- package/src/client/components/underpost/CssUnderpost.js +14 -14
- package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +4 -4
- package/src/client/components/underpost/DocumentSearchProvider.js +1 -1
- package/src/client/components/underpost/LabGalleryUnderpost.js +12 -15
- package/src/client/components/underpost/LogInUnderpost.js +6 -4
- package/src/client/components/underpost/LogOutUnderpost.js +6 -4
- package/src/client/components/underpost/RouterUnderpost.js +45 -0
- package/src/client/components/underpost/SettingsUnderpost.js +4 -4
- package/src/client/components/underpost/SignUpUnderpost.js +6 -4
- package/src/client/components/underpost/TranslateUnderpost.js +4 -4
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +235 -0
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +443 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +417 -0
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +313 -0
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +260 -0
- package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +241 -0
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
- package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +279 -0
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +206 -0
- package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +732 -0
- package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +14 -20
- package/src/client/services/core/core.service.js +17 -49
- package/src/client/services/crypto/crypto.service.js +8 -13
- package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
- package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +10 -16
- package/src/client/services/cyberia-entity/cyberia-entity.management.js +5 -5
- package/src/client/services/cyberia-entity/cyberia-entity.service.js +10 -16
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +6 -6
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +12 -18
- package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +10 -16
- package/src/client/services/cyberia-map/cyberia-map.management.js +6 -6
- package/src/client/services/cyberia-map/cyberia-map.service.js +12 -18
- package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
- package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
- package/src/client/services/default/default.management.js +159 -267
- package/src/client/services/default/default.service.js +10 -16
- package/src/client/services/document/document.service.js +14 -19
- package/src/client/services/file/file.service.js +8 -13
- package/src/client/services/instance/instance.management.js +5 -5
- package/src/client/services/instance/instance.service.js +10 -15
- package/src/client/services/ipfs/ipfs.service.js +12 -18
- package/src/client/services/object-layer/object-layer.management.js +12 -12
- package/src/client/services/object-layer/object-layer.service.js +20 -26
- package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +10 -16
- package/src/client/services/test/test.service.js +8 -13
- package/src/client/services/user/guest.service.js +86 -0
- package/src/client/services/user/user.management.js +5 -5
- package/src/client/services/user/user.service.js +14 -20
- package/src/client/ssr/body/404.js +3 -3
- package/src/client/ssr/body/500.js +3 -3
- package/src/client/ssr/body/CacheControl.js +5 -2
- package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +13 -6
- package/src/client/ssr/head/PwaItemledger.js +197 -60
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
- package/src/client/ssr/offline/Maintenance.js +12 -11
- package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
- package/src/client/ssr/pages/Test.js +2 -2
- package/src/client/sw/core.sw.js +212 -0
- package/src/grpc/cyberia/grpc-server.js +179 -67
- package/src/index.js +1 -1
- package/src/runtime/cyberia-client/Dockerfile +80 -0
- package/src/runtime/cyberia-server/Dockerfile +37 -0
- package/src/runtime/express/Dockerfile +4 -4
- package/src/runtime/lampp/Dockerfile +8 -7
- package/src/runtime/wp/Dockerfile +11 -17
- package/src/server/atlas-sprite-sheet-generator.js +4 -2
- package/src/server/client-build-docs.js +45 -46
- package/src/server/client-build.js +334 -60
- package/src/server/client-formatted.js +47 -16
- package/src/server/conf.js +5 -4
- package/src/server/data-query.js +32 -20
- package/src/server/dns.js +22 -0
- package/src/server/ipfs-client.js +232 -91
- package/src/server/object-layer.js +1 -6
- package/src/server/process.js +13 -27
- package/src/server/semantic-layer-generator-floor.js +11 -51
- package/src/server/semantic-layer-generator-resource.js +259 -0
- package/src/server/semantic-layer-generator-skin.js +41 -171
- package/src/server/semantic-layer-generator.js +122 -14
- package/src/server/shape-generator.js +108 -0
- package/src/server/start.js +17 -3
- package/src/server/valkey.js +141 -235
- package/tsconfig.docs.json +15 -0
- package/typedoc.dd-cyberia.json +29 -0
- package/typedoc.json +29 -0
- package/WHITE-PAPER.md +0 -1540
- package/hardhat/README.md +0 -531
- package/hardhat/WHITE-PAPER.md +0 -1540
- package/jsdoc.dd-cyberia.json +0 -68
- package/jsdoc.json +0 -68
- package/src/api/object-layer/README.md +0 -672
- package/src/client/components/core/ColorPalette.js +0 -5267
- package/src/client/components/core/JoyStick.js +0 -80
- package/src/client/components/cryptokoyn/RoutesCryptokoyn.js +0 -39
- package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +0 -62
- package/src/client/components/cyberia-portal/ServerCyberiaPortal.js +0 -136
- package/src/client/components/default/RoutesDefault.js +0 -49
- package/src/client/components/itemledger/RoutesItemledger.js +0 -40
- package/src/client/components/underpost/RoutesUnderpost.js +0 -47
- package/src/client/sw/default.sw.js +0 -127
- package/src/client/sw/template.sw.js +0 -84
- package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +0 -305
- package/src/grpc/cyberia/README.md +0 -326
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Cyberia Client
|
|
2
|
+
|
|
3
|
+
**Path:** `cyberia-client/` | **Language:** C (C11/GNU11) → WebAssembly via Emscripten
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`cyberia-client` is the real-time game client for Cyberia Online. It is written in C, compiled to WebAssembly via Emscripten, and rendered in a `<canvas>` element inside a browser. It uses **Raylib** for rendering (OpenGL ES2 under WASM) and connects to the Go game server via a persistent binary WebSocket.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
┌────────────────────────────────────────────────────────────┐
|
|
17
|
+
│ Browser │
|
|
18
|
+
│ ┌──────────────────────────────────────────────────────┐ │
|
|
19
|
+
│ │ index.html + shell.html │ │
|
|
20
|
+
│ │ JS glue (Emscripten + services.js + interact_overlay.js + notify_badge.js) │
|
|
21
|
+
│ │ │ │
|
|
22
|
+
│ │ ┌────────────────────────────────────────────────┐ │ │
|
|
23
|
+
│ │ │ index.wasm (main.c → game loop) │ │ │
|
|
24
|
+
│ │ │ │ │ │
|
|
25
|
+
│ │ │ Raylib (OpenGL ES2) ← game_render.c │ │ │
|
|
26
|
+
│ │ │ Input system ← input.c │ │ │
|
|
27
|
+
│ │ │ AOI decoder ← binary_aoi_decoder.c │ │ │
|
|
28
|
+
│ │ │ ObjectLayer cache ← object_layer.c │ │ │
|
|
29
|
+
│ │ │ Texture manager ← texture_manager.c │ │ │
|
|
30
|
+
│ │ │ Game state ← game_state.c │ │ │
|
|
31
|
+
│ │ │ Network I/O ← network.c │ │ │
|
|
32
|
+
│ │ │ UI components ← modal.c, inventory_*.c│ │ │
|
|
33
|
+
│ │ └────────────────────────────────────────────────┘ │ │
|
|
34
|
+
│ └──────────────────────────────────────────────────────┘ │
|
|
35
|
+
│ │ WebSocket binary ↑ HTTP JSON │
|
|
36
|
+
└───────┼─────────────────────────────────┼──────────────────┘
|
|
37
|
+
│ │
|
|
38
|
+
▼ ▼
|
|
39
|
+
Go Game Server :8081 Engine REST API :4005
|
|
40
|
+
(AOI binary protocol) (atlas, file/blob, object-layer)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Source Files
|
|
46
|
+
|
|
47
|
+
| File | Responsibility |
|
|
48
|
+
| --------------------------------------------------------- | -------------------------------------------------------- |
|
|
49
|
+
| `main.c` | Entry point, Raylib init, main game loop, event dispatch |
|
|
50
|
+
| `client.c / client.h` | Client session state (player UUID, position, coins) |
|
|
51
|
+
| `game_state.c / game_state.h` | World state: entity registry, map grid, frame tick |
|
|
52
|
+
| `game_render.c / game_render.h` | Top-level render pipeline (map tiles → entities → UI) |
|
|
53
|
+
| `entity_render.c / entity_render.h` | Per-entity composited layer stack rendering |
|
|
54
|
+
| `binary_aoi_decoder.c / binary_aoi_decoder.h` | Binary AOI message parser (0x01–0x05 messages) |
|
|
55
|
+
| `message_parser.c / message_parser.h` | JSON message parser for `init_data` (0x02) |
|
|
56
|
+
| `network.c / network.h` | WebSocket connect, send, receive wrappers |
|
|
57
|
+
| `object_layer.c / object_layer.h` | ObjectLayer metadata struct + LRU cache |
|
|
58
|
+
| `object_layers_management.c / object_layers_management.h` | ObjectLayer fetch pipeline (API → cache → render) |
|
|
59
|
+
| `texture_manager.c / texture_manager.h` | Atlas texture LRU cache keyed by IPFS CID |
|
|
60
|
+
| `layer_z_order.c / layer_z_order.h` | Z-order comparator for entity layer stack rendering |
|
|
61
|
+
| `serial.c / serial.h` | IDBFS-based persistent local storage |
|
|
62
|
+
| `input.c / input.h` | Mouse/touch event → game action translation |
|
|
63
|
+
| `tap_effect.c / tap_effect.h` | Visual tap ripple animation |
|
|
64
|
+
| `floating_combat_text.c / floating_combat_text.h` | FCT pop-up renderer (damage, regen, coin, item) |
|
|
65
|
+
| `interaction_bubble.c / interaction_bubble.h` | NPC interaction indicator bubble above entity |
|
|
66
|
+
| `entity_overhead_ui.c / entity_overhead_ui.h` | Name plates, HP bars above entities |
|
|
67
|
+
| `nameplate.c / nameplate.h` | Entity nameplate rendering |
|
|
68
|
+
| `inventory_bar.c / inventory_bar.h` | Equipped items bar (bottom of screen) |
|
|
69
|
+
| `inventory_modal.c / inventory_modal.h` | Full inventory grid modal |
|
|
70
|
+
| `modal.c / modal.h` | Base modal container (backdrop, open/close animation) |
|
|
71
|
+
| `modal_dialogue.c / modal_dialogue.h` | Dialogue modal — renders NPC conversation + choices |
|
|
72
|
+
| `modal_player.c / modal_player.h` | Player profile modal (stats, wallet, equipment) |
|
|
73
|
+
| `dialogue_data.c / dialogue_data.h` | Dialogue tree data structure |
|
|
74
|
+
| `ol_as_animated_ico.c / ol_as_animated_ico.h` | Render ObjectLayer as animated icon (inventory cells) |
|
|
75
|
+
| `ol_stack_ico.c / ol_stack_ico.h` | Render ObjectLayer stack as composite icon |
|
|
76
|
+
| `ui_icon.c / ui_icon.h` | Generic icon primitives |
|
|
77
|
+
| `dev_ui.c / dev_ui.h` | Development overlay (coords, FPS, entity count) |
|
|
78
|
+
| `helper.h` | Common macros and utility definitions |
|
|
79
|
+
| `config.h` | Compile-time configuration constants |
|
|
80
|
+
| `shell.html` | Emscripten HTML shell template |
|
|
81
|
+
| `js/services.js` | JS↔WASM bridge: fetch atlas, file blob, object-layer |
|
|
82
|
+
| `js/interact_overlay.js` | JS overlay for tap-to-interact element |
|
|
83
|
+
| `js/notify_badge.js` | Browser notification badge helper |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Rendering Pipeline
|
|
88
|
+
|
|
89
|
+
Each frame:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
BeginDrawing()
|
|
93
|
+
└─ game_render_frame()
|
|
94
|
+
├─ RenderMapLayer(ground tiles) ← atlas-clipped tile sprites
|
|
95
|
+
├─ RenderMapLayer(object tiles) ← decorative overlay tiles
|
|
96
|
+
├─ for each entity in z-sorted list:
|
|
97
|
+
│ entity_render_entity()
|
|
98
|
+
│ ├─ for each ObjectLayer in entity stack (bottom → top z-order):
|
|
99
|
+
│ │ texture_manager_get_texture(layer.cid)
|
|
100
|
+
│ │ DrawTextureRec(atlas, frame_rect, position)
|
|
101
|
+
│ ├─ entity_overhead_ui (nameplate + HP bar)
|
|
102
|
+
│ └─ interaction_bubble (if NPC with action)
|
|
103
|
+
├─ floating_combat_text_tick() ← animated pop-ups
|
|
104
|
+
├─ tap_effect_tick() ← tap ripple animations
|
|
105
|
+
├─ inventory_bar_render() ← equipped items (bottom HUD)
|
|
106
|
+
└─ dev_ui_render() ← debug overlay (if ENABLE_DEV_UI)
|
|
107
|
+
EndDrawing()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Atlas clipping:** Every sprite is a rectangular clip from a texture atlas. The atlas CID (IPFS) is fetched from the Engine API at `/api/atlas-sprite-sheet/{cid}`. The engine returns frame metadata JSON; the client clips `DrawTextureRec(atlas, {x,y,w,h}, screenPos)`.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Binary AOI Protocol (Decoder)
|
|
115
|
+
|
|
116
|
+
`binary_aoi_decoder.c` parses all server → client messages:
|
|
117
|
+
|
|
118
|
+
| Message Type | Byte | Decoder Function | Description |
|
|
119
|
+
| ------------ | ------ | ------------------- | ----------------------------------------- |
|
|
120
|
+
| `aoi_update` | `0x01` | `decode_aoi_update` | Delta AOI — entities entered/left view |
|
|
121
|
+
| `init_data` | `0x02` | `decode_init_data` | Full config on connect (JSON sub-payload) |
|
|
122
|
+
| `full_aoi` | `0x03` | `decode_full_aoi` | Full AOI snapshot |
|
|
123
|
+
| `FCT` | `0x04` | `decode_fct` | Floating Combat Text (14-byte fixed) |
|
|
124
|
+
| `ItemFCT` | `0x05` | `decode_item_fct` | Item FCT with string item ID (variable) |
|
|
125
|
+
|
|
126
|
+
**All multi-byte integers: little-endian.**
|
|
127
|
+
|
|
128
|
+
**FCT type → visual:**
|
|
129
|
+
|
|
130
|
+
| FCT Type | Byte | Color |
|
|
131
|
+
| -------- | ------ | ------ |
|
|
132
|
+
| Damage | `0x00` | Red |
|
|
133
|
+
| Regen | `0x01` | Green |
|
|
134
|
+
| CoinGain | `0x02` | Yellow |
|
|
135
|
+
| CoinLoss | `0x03` | Yellow |
|
|
136
|
+
| ItemGain | `0x04` | Cyan |
|
|
137
|
+
| ItemLoss | `0x05` | Purple |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## ObjectLayer Cache
|
|
142
|
+
|
|
143
|
+
`object_layer.c` maintains an LRU cache (`MAX_LAYER_CACHE_SIZE = 256`) of parsed `ObjectLayerMetadata` structs:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
Fetch pipeline per item ID:
|
|
147
|
+
1. Check LRU cache → hit? return immediately
|
|
148
|
+
2. Call JS bridge: services.fetchObjectLayer(itemId)
|
|
149
|
+
→ GET {API_BASE_URL}/api/object-layer/{itemId}
|
|
150
|
+
3. Parse JSON response → populate ObjectLayerMetadata
|
|
151
|
+
4. Evict LRU entry if cache full → insert new entry
|
|
152
|
+
5. Trigger texture fetch for each layer CID
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Texture Manager
|
|
158
|
+
|
|
159
|
+
`texture_manager.c` maintains an LRU cache (`MAX_TEXTURE_CACHE_SIZE = 512`) of Raylib `Texture2D` objects:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
Fetch pipeline per CID:
|
|
163
|
+
1. Check cache by CID → hit? return Texture2D*
|
|
164
|
+
2. Call JS bridge: services.fetchFileBlob(cid)
|
|
165
|
+
→ GET {API_BASE_URL}/api/file/blob/{cid}
|
|
166
|
+
3. Decode PNG blob → Raylib Image → Texture2D (GPU upload)
|
|
167
|
+
4. Evict LRU on full cache → insert new entry
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Input System (Tap-Based)
|
|
173
|
+
|
|
174
|
+
The client uses a **tap-first** interaction model:
|
|
175
|
+
|
|
176
|
+
| Input | Action |
|
|
177
|
+
| ------------------------------- | ------------------------------------------------------------ |
|
|
178
|
+
| Tap empty tile | Send `tap_move` WS message → player moves to cell |
|
|
179
|
+
| Tap entity (NPC/resource) | Send `tap_entity` WS message → server dispatches interaction |
|
|
180
|
+
| Tap inventory item | Toggle equip/unequip → send `item_activation` |
|
|
181
|
+
| Tap interact overlay (JS layer) | Opens action modal via `_c_open_dialogue_from_js` |
|
|
182
|
+
|
|
183
|
+
`input.c` translates raw Raylib mouse/touch events into game-world cell coordinates using the current camera offset, then dispatches the appropriate WS message via `network_send_message`.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## JS↔WASM Bridge
|
|
188
|
+
|
|
189
|
+
Emscripten exported C functions (callable from JavaScript):
|
|
190
|
+
|
|
191
|
+
| C Function | Description |
|
|
192
|
+
| --------------------------------- | --------------------------------------------- |
|
|
193
|
+
| `_c_send_ws_message(ptr, len)` | Send raw bytes over the WebSocket |
|
|
194
|
+
| `_c_open_dialogue_from_js(ptr)` | Open dialogue modal with serialized JSON |
|
|
195
|
+
| `_c_interact_overlay_did_close()` | Notify WASM that the JS overlay was dismissed |
|
|
196
|
+
|
|
197
|
+
JavaScript library functions (callable from C via `EM_ASM` / `--js-library`):
|
|
198
|
+
|
|
199
|
+
| JS Function | Source | Description |
|
|
200
|
+
| ----------------------------------------- | ------------------------ | -------------------------------------- |
|
|
201
|
+
| `services.fetchObjectLayer(itemId, cb)` | `js/services.js` | Fetch ObjectLayer JSON from Engine API |
|
|
202
|
+
| `services.fetchAtlasSpriteSheet(cid, cb)` | `js/services.js` | Fetch atlas frame metadata |
|
|
203
|
+
| `services.fetchFileBlob(cid, cb)` | `js/services.js` | Fetch raw IPFS-addressed blob |
|
|
204
|
+
| `interact_overlay.show(entityId)` | `js/interact_overlay.js` | Show tap-to-interact HTML overlay |
|
|
205
|
+
| `notify_badge.set(count)` | `js/notify_badge.js` | Update browser notification badge |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Compile-Time Configuration (`config.h`)
|
|
210
|
+
|
|
211
|
+
| Constant | Default | Description |
|
|
212
|
+
| --------------------------- | ----------------------------------- | ---------------------------------------------- |
|
|
213
|
+
| `WS_URL` | `wss://server.cyberiaonline.com/ws` | WebSocket endpoint |
|
|
214
|
+
| `API_BASE_URL` | `https://www.cyberiaonline.com` | Engine REST API base URL |
|
|
215
|
+
| `HTTP_TIMEOUT_SECONDS` | `10` | HTTP request timeout (asset fetching) |
|
|
216
|
+
| `MAX_TEXTURE_CACHE_SIZE` | `512` | Max atlas textures in VRAM cache |
|
|
217
|
+
| `MAX_LAYER_CACHE_SIZE` | `256` | Max ObjectLayer metadata entries in cache |
|
|
218
|
+
| `MAX_ATLAS_CACHE_SIZE` | `256` | Max atlas sprite sheet metadata entries |
|
|
219
|
+
| `DEFAULT_FRAME_DURATION_MS` | `100` | Default animation frame rate |
|
|
220
|
+
| `ENABLE_DEV_UI` | `false` | Force dev overlay on (override server setting) |
|
|
221
|
+
| `APP_VERSION` | `"1.0.0"` | Application version string |
|
|
222
|
+
|
|
223
|
+
For local development, change `WS_URL` and `API_BASE_URL` to `localhost` variants before rebuilding.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Build System
|
|
228
|
+
|
|
229
|
+
### Dependencies
|
|
230
|
+
|
|
231
|
+
| Library | Version | Usage |
|
|
232
|
+
| ---------- | ------- | ----------------------------------- |
|
|
233
|
+
| Emscripten | ≥ 3.1 | C → WASM compiler + JS runtime |
|
|
234
|
+
| Raylib | ≥ 5.0 | Rendering (OpenGL ES2 via WebGL) |
|
|
235
|
+
| cJSON | 1.7.x | JSON parsing (ObjectLayer metadata) |
|
|
236
|
+
|
|
237
|
+
Raylib and cJSON are vendored under `libs/`.
|
|
238
|
+
|
|
239
|
+
### Build Modes
|
|
240
|
+
|
|
241
|
+
| Mode | Flags | Use |
|
|
242
|
+
| ----------------- | -------------------- | ----------------------------------------------- |
|
|
243
|
+
| `DEBUG` (default) | `-O0 -g --profiling` | Development — includes symbols, no optimization |
|
|
244
|
+
| `RELEASE` | `-O3 -DNDEBUG` | Production — fully optimized |
|
|
245
|
+
|
|
246
|
+
### Build Commands
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
cd cyberia-client
|
|
250
|
+
|
|
251
|
+
# Debug build (default)
|
|
252
|
+
make -f Web.mk
|
|
253
|
+
|
|
254
|
+
# Release build
|
|
255
|
+
make -f Web.mk BUILD_MODE=RELEASE
|
|
256
|
+
|
|
257
|
+
# Build + serve on dev port :8082
|
|
258
|
+
make -f Web.mk serve-development
|
|
259
|
+
|
|
260
|
+
# Build release + serve on production port :8081
|
|
261
|
+
make -f Web.mk serve-production
|
|
262
|
+
|
|
263
|
+
# Clean build artifacts
|
|
264
|
+
make -f Web.mk clean
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Output
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
bin/
|
|
271
|
+
index.html — Emscripten HTML container (from shell.html template)
|
|
272
|
+
index.wasm — Compiled WebAssembly module
|
|
273
|
+
index.js — Emscripten JS glue
|
|
274
|
+
index.data — Preloaded data bundle (assets)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Persistent Storage
|
|
280
|
+
|
|
281
|
+
`serial.c` uses Emscripten's **IDBFS** (IndexedDB File System) to persist:
|
|
282
|
+
|
|
283
|
+
- Player authentication token (EIP-712 signature)
|
|
284
|
+
- Local game settings (audio volume, key bindings)
|
|
285
|
+
- Cached ObjectLayer metadata (session cache warm-up)
|
|
286
|
+
|
|
287
|
+
Data is stored at `/persistent/` in the virtual IDBFS mount.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Environment: Local Development
|
|
292
|
+
|
|
293
|
+
Change these two constants in `src/config.h` and rebuild:
|
|
294
|
+
|
|
295
|
+
```c
|
|
296
|
+
static const char* WS_URL = "ws://localhost:8081/ws";
|
|
297
|
+
static const char* API_BASE_URL = "http://localhost:4005";
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Then:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Terminal 1 — Engine (Node.js)
|
|
304
|
+
cd /path/to/engine && node src/index.js
|
|
305
|
+
|
|
306
|
+
# Terminal 2 — Go game server
|
|
307
|
+
cd cyberia-server && go run main.go
|
|
308
|
+
|
|
309
|
+
# Terminal 3 — Client build + serve
|
|
310
|
+
cd cyberia-client && make -f Web.mk serve-development
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Open `http://localhost:8082` in a browser.
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Cyberia Server
|
|
2
|
+
|
|
3
|
+
**Path:** `cyberia-server/` | **Language:** Go
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`cyberia-server` is the real-time multiplayer game server for Cyberia Online. It maintains the authoritative game state, runs the AI and physics simulation, and communicates with clients via a custom binary WebSocket protocol. It connects to the Node.js Engine at startup via gRPC to load the game world and Object Layer data.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```mermaid
|
|
16
|
+
graph TB
|
|
17
|
+
subgraph cyberia-server["cyberia-server (Go)"]
|
|
18
|
+
main["main.go\nHTTP + WS listener"]
|
|
19
|
+
loader["instance_loader.go\nWorld Builder from gRPC"]
|
|
20
|
+
server["server.go\nGame loop + Player registry"]
|
|
21
|
+
aoi["aoi_binary.go\nBinary AOI Protocol"]
|
|
22
|
+
collision["collision.go\nGrid collision + portals"]
|
|
23
|
+
pathfind["pathfinding.go\nA* bot navigation"]
|
|
24
|
+
skills["skill.go\nSkill tap/kill entry\nskill_dispatcher.go\nSkill registry"]
|
|
25
|
+
economy["economy.go\nFountain & Sink"]
|
|
26
|
+
ai["ai.go\nBot behavior"]
|
|
27
|
+
frozen["frozen_state.go\nModal protection"]
|
|
28
|
+
static["static.go\nStatic file serving (WASM client)"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
grpcClient["grpcclient/\nEngine gRPC client"] --> loader
|
|
32
|
+
loader --> server
|
|
33
|
+
server --> aoi
|
|
34
|
+
server --> collision
|
|
35
|
+
server --> pathfind
|
|
36
|
+
server --> skills
|
|
37
|
+
server --> economy
|
|
38
|
+
server --> ai
|
|
39
|
+
server --> frozen
|
|
40
|
+
|
|
41
|
+
Engine["engine-cyberia :50051\n(gRPC)"] <-->|gRPC| grpcClient
|
|
42
|
+
Client["cyberia-client\n(C/WASM)"] <-->|WS binary| aoi
|
|
43
|
+
Client <-->|REST /api/v1/*| server
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Source Files
|
|
49
|
+
|
|
50
|
+
| File | Responsibility |
|
|
51
|
+
| ----------------------- | ---------------------------------------------------------------------------------------------- |
|
|
52
|
+
| `main.go` | Entry point — HTTP/WS server, signal handling |
|
|
53
|
+
| `server.go` | WebSocket lifecycle, game loop, player/bot registry |
|
|
54
|
+
| `types.go` | Core data structures (PlayerState, BotState, ObjectLayer, etc.) |
|
|
55
|
+
| `aoi_binary.go` | Binary AOI wire format encoder + message type constants |
|
|
56
|
+
| `object_layer.go` | ObjectLayer Go types mirroring MongoDB schema |
|
|
57
|
+
| `instance_loader.go` | Reconstructs world from gRPC `GetFullInstanceResponse` |
|
|
58
|
+
| `collision.go` | Grid collision detection, portal transitions, death handling |
|
|
59
|
+
| `pathfinding.go` | A\* pathfinding for bot/player navigation |
|
|
60
|
+
| `skill.go` | Skill entry points: `HandlePlayerTapAction`, `HandleOnKillSkills`, `GetAssociatedSkillItemIDs` |
|
|
61
|
+
| `skill_dispatcher.go` | Skill registry: `InitSkills()`, `DispatchSkill()`, `dispatchSkillsForEntity()` |
|
|
62
|
+
| `skill_projectile.go` | Projectile skill handler (spawns `skill` bot entities) |
|
|
63
|
+
| `skill_doppelganger.go` | Doppelganger skill handler (spawns allied clone bots) |
|
|
64
|
+
| `economy.go` | Fountain & Sink coin economy — all economy methods |
|
|
65
|
+
| `life_regen.go` | HP regeneration ticker |
|
|
66
|
+
| `ai.go` | Bot AI — aggro, wander, target selection |
|
|
67
|
+
| `stats.go` | Active stat aggregation, sum-stats limit enforcement |
|
|
68
|
+
| `entity_status.go` | Entity Status Indicator (ESI) computation |
|
|
69
|
+
| `frozen_state.go` | FrozenInteractionState — modal protection for players |
|
|
70
|
+
| `handlers.go` | WebSocket message handlers (move, action, inventory, etc.) |
|
|
71
|
+
| `static.go` | Static file serving for the WASM client |
|
|
72
|
+
| `grpcclient/` | gRPC client for the Engine data service |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## gRPC World Loading
|
|
77
|
+
|
|
78
|
+
At startup, the Go server dials the Engine gRPC endpoint and calls `GetFullInstance(instanceCode)`:
|
|
79
|
+
|
|
80
|
+
```mermaid
|
|
81
|
+
sequenceDiagram
|
|
82
|
+
participant G as Go Server
|
|
83
|
+
participant E as Engine (gRPC :50051)
|
|
84
|
+
participant DB as MongoDB
|
|
85
|
+
|
|
86
|
+
G->>E: GetFullInstance("cyberia-main")
|
|
87
|
+
E->>DB: Query CyberiaInstance + all CyberiaMap + CyberiaEntity + ObjectLayer
|
|
88
|
+
E-->>G: GetFullInstanceResponse { instance, maps[], entities[], objectLayers[], config }
|
|
89
|
+
G->>G: BuildWorldFromInstance → in-memory map grid + entity registry
|
|
90
|
+
G->>G: ApplyInstanceConfig → sets economy rules, skill config, equipment rules
|
|
91
|
+
G->>G: ReplaceObjectLayerCache → indexes all ObjectLayer metadata by itemId
|
|
92
|
+
G->>E: GetObjectLayerBatch() (stream — cache warm-up)
|
|
93
|
+
Note over G: gRPC load complete — WebSocket server ready
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Fallback:** If the `instanceCode` doesn't match any MongoDB record, the Engine returns a minimal playable fallback (empty 64×64 map) instead of `NOT_FOUND`. If the Engine is unreachable, the Go server exits with a fatal error (gRPC is required).
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## WebSocket Message Handlers
|
|
101
|
+
|
|
102
|
+
Incoming client messages dispatch through `handlers.go`:
|
|
103
|
+
|
|
104
|
+
| Message Type | Description |
|
|
105
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
106
|
+
| `player_action` | Player tap action — carries `targetX`/`targetY`; triggers `HandlePlayerTapAction` (movement + skill dispatch) |
|
|
107
|
+
| `item_activation` | Equip/unequip an Object Layer item; enforces one-per-type and `maxActiveLayers` rules |
|
|
108
|
+
| `get_items_ids` | Given an `itemId`, returns the list of associated skill entity item IDs (`skill_item_ids` response) |
|
|
109
|
+
| `freeze_start` / `dialogue_start` | Enter FrozenInteractionState (blocks movement and damage); `dialogue_start` accepted for backward compat |
|
|
110
|
+
| `freeze_end` / `dialogue_end` | Exit FrozenInteractionState |
|
|
111
|
+
| `chat` | Pure relay — forward JSON chat message to target player, no game-state mutation |
|
|
112
|
+
|
|
113
|
+
> **Pre-alpha scope:** Action/quest/shop/craft/portal WS handlers are not yet implemented in the Go server. These systems are defined in the Node.js Engine API (`src/api/cyberia-action`, `src/api/cyberia-quest`) and are planned for the alpha milestone.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Area of Interest (AOI)
|
|
118
|
+
|
|
119
|
+
The AOI system ensures each client receives only data about nearby entities, reducing bandwidth and server load:
|
|
120
|
+
|
|
121
|
+
- Each player has a rectangular AOI bounding box centered on their position.
|
|
122
|
+
- AOI size is configured per instance (`aoi_width`, `aoi_height` in `CyberiaInstanceConf`).
|
|
123
|
+
- On each tick, the server computes the delta (entities entered/left AOI) and sends a binary `aoi_update` (0x01) message.
|
|
124
|
+
- On initial connect, the server sends a full AOI snapshot (`full_aoi`, 0x03) plus `init_data` (0x02).
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Skill System
|
|
129
|
+
|
|
130
|
+
### Trigger Pipeline
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
player_action WS message
|
|
134
|
+
→ HandlePlayerTapAction(player, mapState, target)
|
|
135
|
+
→ dispatchSkillsForEntity(player, mapState, target)
|
|
136
|
+
→ iterate player.ObjectLayers (active items)
|
|
137
|
+
→ build skillMap: itemId → []SkillDefinition
|
|
138
|
+
→ for each SkillDefinition:
|
|
139
|
+
DispatchSkill(logicEventId, SkillContext)
|
|
140
|
+
"projectile" → skill_projectile.go handler
|
|
141
|
+
"doppelganger" → skill_doppelganger.go handler
|
|
142
|
+
"coin_drop_or_transaction" → economy.go handler
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Skill Rules (SkillRules proto message → server fields)
|
|
146
|
+
|
|
147
|
+
| Field | Description |
|
|
148
|
+
| --------------------------------- | ------------------------------------------------------ |
|
|
149
|
+
| `projectileSpawnChance` | Probability [0–1] of spawning a projectile per trigger |
|
|
150
|
+
| `projectileLifetimeMs` | Projectile lifetime in milliseconds |
|
|
151
|
+
| `projectileWidth/Height` | Entity dimensions (in cells) |
|
|
152
|
+
| `projectileSpeedMultiplier` | Speed multiplier relative to base entity speed |
|
|
153
|
+
| `doppelgangerSpawnChance` | Probability of spawning a doppelganger |
|
|
154
|
+
| `doppelgangerLifetimeMs` | Doppelganger lifetime |
|
|
155
|
+
| `doppelgangerSpawnRadius` | Max spawn distance from triggering player (cells) |
|
|
156
|
+
| `doppelgangerInitialLifeFraction` | Starting HP as fraction of player max HP |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Bot AI
|
|
161
|
+
|
|
162
|
+
Bots are spawned from `CyberiaEntity` records with `entityType: "bot"`. The `ai.go` module drives their behavior:
|
|
163
|
+
|
|
164
|
+
| Behavior | Description |
|
|
165
|
+
| --------- | ---------------------------------------------------------------------------------------- |
|
|
166
|
+
| `hostile` | Has a weapon; will pathfind to and attack players/other bots within `aggroRange` |
|
|
167
|
+
| `passive` | No weapon; wanders randomly within `spawnRadius` |
|
|
168
|
+
| `skill` | Projectile entity — moves in a fixed direction, despawns on collision or lifetime expiry |
|
|
169
|
+
| `coin` | Static collectible — grants coins on player contact, then despawns |
|
|
170
|
+
|
|
171
|
+
**Bot respawn:** Dead bots respawn at their `spawnPoint` after a configurable delay. Each respawn calls `FountainInitBot(bot)` to reset the coin wallet to `botSpawnCoins`.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## FrozenInteractionState
|
|
176
|
+
|
|
177
|
+
While a player has a modal open (dialogue, shop, inventory, craft), they enter **FrozenInteractionState**:
|
|
178
|
+
|
|
179
|
+
```go
|
|
180
|
+
// frozen_state.go
|
|
181
|
+
FreezePlayer(player, reason string) // freezes: no damage, no movement, no events
|
|
182
|
+
ThawPlayer(player) // unfreezes: returns to normal gameplay
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The player's `Frozen` flag is broadcast to clients on each AOI tick so other players see the frozen (chat-icon) status indicator.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Hot-Reload
|
|
190
|
+
|
|
191
|
+
The Go server supports **incremental ObjectLayer hot-reload** without restart:
|
|
192
|
+
|
|
193
|
+
1. At interval `ENGINE_GRPC_RELOAD_INTERVAL_SEC`, the server calls `GetObjectLayerManifest()`.
|
|
194
|
+
2. It diffs the returned `{ itemId, sha256 }` pairs against the cached manifest.
|
|
195
|
+
3. For changed items, it calls `GetObjectLayer(itemId)` to fetch updated data.
|
|
196
|
+
4. `ReplaceObjectLayerCache` atomically replaces the stale entry.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## REST API
|
|
201
|
+
|
|
202
|
+
The Go server exposes a metrics and health REST API under `/api/v1/`:
|
|
203
|
+
|
|
204
|
+
| Endpoint | Method | Description |
|
|
205
|
+
| --------------------------- | ------ | ------------------------------------------------------------- |
|
|
206
|
+
| `/api/v1/health` | GET | Simple health check — `{"status":"ok"}` |
|
|
207
|
+
| `/api/v1/metrics` | GET | Complete server metrics snapshot |
|
|
208
|
+
| `/api/v1/metrics/health` | GET | Detailed health with entity/player counts |
|
|
209
|
+
| `/api/v1/metrics/entities` | GET | Entity type breakdown and active counts |
|
|
210
|
+
| `/api/v1/metrics/websocket` | GET | Active WebSocket connections, message rates |
|
|
211
|
+
| `/api/v1/metrics/workload` | GET | Per-map entity workload (players, bots, floors, ObjectLayers) |
|
|
212
|
+
|
|
213
|
+
All other game data (ObjectLayer metadata, instance config, file blobs) is served by the **Node.js Engine REST API** directly to the client — the Go server does not proxy Engine data.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Environment Variables
|
|
218
|
+
|
|
219
|
+
| Variable | Default | Description |
|
|
220
|
+
| --------------------------------- | ----------------- | ------------------------------------------------------------------------------------ |
|
|
221
|
+
| `ENGINE_GRPC_ADDRESS` | `localhost:50051` | Engine gRPC address (**required**) |
|
|
222
|
+
| `INSTANCE_CODE` | `default` | Instance code to load on startup |
|
|
223
|
+
| `ENGINE_GRPC_RELOAD_INTERVAL_SEC` | _(disabled)_ | ObjectLayer hot-reload polling interval |
|
|
224
|
+
| `SERVER_PORT` | `8081` | HTTP + WS listen port |
|
|
225
|
+
| `STATIC_DIR` | `./public` | Directory for static WASM client files |
|
|
226
|
+
| `READY_CMD` | _(empty)_ | Shell command to run after server starts (used by orchestration to signal readiness) |
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Build and Run
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# Development
|
|
234
|
+
cd cyberia-server
|
|
235
|
+
go run main.go
|
|
236
|
+
|
|
237
|
+
# Production binary
|
|
238
|
+
go build -o cyberia-server .
|
|
239
|
+
./cyberia-server
|
|
240
|
+
|
|
241
|
+
# Docker
|
|
242
|
+
docker build -t cyberia-server .
|
|
243
|
+
docker run -e ENGINE_GRPC_ADDRESS=engine:50051 -e INSTANCE_CODE=cyberia-main cyberia-server
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Kubernetes Deployment
|
|
249
|
+
|
|
250
|
+
The Go server deploys as `mmo-server` in the Kubernetes cluster:
|
|
251
|
+
|
|
252
|
+
```yaml
|
|
253
|
+
# Key environment variables in deployment.yaml
|
|
254
|
+
- name: ENGINE_GRPC_ADDRESS
|
|
255
|
+
value: 'dd-cyberia-service:50051' # cluster-internal Engine service
|
|
256
|
+
- name: INSTANCE_CODE
|
|
257
|
+
value: 'cyberia-main'
|
|
258
|
+
- name: SERVER_PORT
|
|
259
|
+
value: '8081'
|
|
260
|
+
```
|