Live bring-up
Take the bots from tested logic to alive on a server — the full runbook.
Take the bots from "tested logic" to "alive on a server." Everything up to the in-client test can be done by anyone with server access; the final in-game verification (joining, seeing a bot move/react, hearing its voice) has to be done by a human in the DayZ client.
DayZ server (your private box)
├─ DayZServer + @ObscurumAI (server-side mod: PlayerBase bot, perception, combat, bridge)
└─ obscurum-brain sidecar (Rust HTTP service on 127.0.0.1:8088)
│ POST /tick {snapshot, profile} -> {agent, intents:[...]}
▼
the brain (reactive core + optional LLM tier + voice)The mod calls the sidecar each low-cadence tick; reflexes (locomotion/aim) run every frame locally, so a slow/dropped reply just means "keep the last intents." Never blocks the game.
1. Build + run the brain sidecar
Matches the project convention. The dev overlay publishes 127.0.0.1:8088 only (loopback,
not public).
cd obscurum-ai
docker compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.dev up -d --build
curl -fsS http://127.0.0.1:8088/health # -> okFastest to iterate.
cd obscurum-ai/brain
RUSTC_WRAPPER="" cargo build --release --features "server llm-http"
OBSCURUM_BRAIN_ADDR=127.0.0.1:8088 \
OBSCURUM_LLM_BASE_URL=$OBSCURUM_LLM_BASE_URL \
OBSCURUM_LLM_MODEL=$OBSCURUM_LLM_MODEL \
OBSCURUM_LLM_KEY=$OBSCURUM_LLM_KEY \
./target/release/obscurum-brain
# -> "obscurum-brain listening 127.0.0.1:8088"Env: OBSCURUM_BRAIN_ADDR (bind), OBSCURUM_BRAIN_TOKEN (optional bearer gate),
OBSCURUM_LLM_* (enable the dialogue tier; omit for silent reactive-only bots).
Config: the sidecar loads a ServerConfig — either from a local bundle dir (self-host) or
pulled from the SaaS control-plane by key (see the
API reference). Scaffold a local bundle with:
python3 ops/tools/voice/obsconfig.py init --game dayz --preset hardcore-pvp --out ./serverconfigSmoke-test the wire contract without the game:
curl -s localhost:8088/tick -H 'content-type: application/json' \
-d '{"snapshot":{"agent":1,"time_s":0,"self_state":{"pos":{"x":0,"y":0,"z":0},"heading_deg":0,"health":1,"blood":1,"hunger":0.5,"thirst":0.5,"has_weapon":true,"ammo":30},"targets":[]},"profile":{}}'
# -> {"agent":1,"intents":[ ... ]}2. Install the @ObscurumAI mod on the server
It is a server-side mod (no client download needed for the bot logic).
# copy the mod folder next to the server binary
cp -r obscurum-ai/dayz/mod/@ObscurumAI /path/to/DayZServer/
# add it to the SERVER mod list (note -servermod, not -mod)
./DayZServer -config=serverDZ.cfg -servermod=@ObscurumAI -profiles=profilesThe mod's config.cpp registers the scripts under 4_World/ObscurumAI/. The
obscurumai_bridge.c points at http://127.0.0.1:8088/tick — same box as the sidecar.
3. Spawn bots + verify the loop
The bots are modded PlayerBase survivors made via ObscurumAI_MakeBot(a, b)
(obscurumai_bot.c). Trigger a spawn from your mission init.c or an admin tool, then
watch:
- Server RPT log:
[OAI]lines (perceived counts, brain steps). - Sidecar log: incoming
POST /tickonce per bot per cadence. - A bot should start patrolling between its two waypoints and face/engage a hostile that comes into line of sight (reactive tier — works even with the LLM off).
If the sidecar sees no requests: check the bridge URL/port, the server's outbound loopback,
and that -servermod=@ObscurumAI actually loaded (RPT "Loading mod").
4. In-game verification (you, in the client)
Join your private server and confirm, in this order (cheapest first):
- A bot moves (patrol) and turns to face you.
- A hostile bot engages (closes/aims/fires); a coward flees; a wounded one investigates a lost contact.
- With the LLM tier on: the bot talks (an
Intent::Sayline) in character. - Voice (advanced, see §5): you hear the bot over proximity voice, and it reacts to what you say.
Tactics (tactics.rs) — flank-behind, ambush a waterhole, hold a prone snipe, conceal when
outmatched — surface as MoveTo/Engage targets the bridge already actuates; the only addition
the embodiment still needs is a posture channel to play prone/crouch animations (see §6).
5. Voice bring-up (advanced)
Voice is proven offline; live wiring on the server:
- Voice-IN (bots hear players): the eBPF uprobe on
VoNServer::retranslateVoiceDataops/tools/voice/von_stream.py(Opus decode -> STT) -> POST utterances onto the bot'sheard_speech. Root + an STT key.
- Voice-OUT (bots speak):
von_tts.py(TTS, with provider failover) -> encode Opus -> inject aVoNControlPacketvia the server relay. Per-voice consistency + emotes.
Run the voice sidecars on the same box; keep them off the hot path.
6. Known remaining work before "perfect live"
- Posture channel — DONE:
IntentSet.posture(standing/crouched/prone) is now in the wire contract and set by the brain (a bot crouches up close, drops prone for a long shot). The mod just readsintentset.postureand plays the matching stance animation. - Loadout application:
loadout.rspresets exist; wire the mod to equip them at spawn. - Waypoint routes / formations / hearing:
waypoint.rs/formation.rs/hearing.rslogic is ready; feed routes + POIs into the snapshot and consume the resulting targets. - These are embodiment wiring, not new brain logic — the decisions already exist and pass tests.
Checklist
-
curl localhost:8088/healthok -
/ticksmoke test returns intents -
@ObscurumAIloads (RPT) and bots spawn - sidecar receives
/tickper bot - bot patrols + faces + engages (reactive)
- bot talks (LLM tier)
- voice in/out (advanced)