Role
Application architecture, implementation, and server operations
Environment
Private Final Fantasy XI server and headless game client
Stack
Python, Lua, SQLite, Linux
Status
Implemented prototype; model-backed workers remain parked in the recovered build

I built a self-hosted application that controlled an in-game character on a private Final Fantasy XI server. The work centered on keeping a client process available, turning its telemetry into dependable state, and recovering from failures without restarting healthy infrastructure.

Operate the client and server

The environment used LandSandBoat for the private game server and Wine with Xvfb for the headless client. Linux process supervision and tmux supported operation. A Windower Lua addon connected the game client to a multi-process Python application.

The addon published heartbeat and game-state events through an append-only bridge. Python workers evaluated that state and wrote prioritized commands back to the client. The Lua layer deduplicated and scheduled commands within the game's input-rate limit, then recorded execution failures as new events.

Keep game actions deterministic

Movement and party-follow behavior used explicit state and proximity rules. Healing and resource recovery ran through separate policies with action locks, cooldowns, and retry backoff. Circuit breakers bounded repeated failures.

Character provisioning reconciled client snapshots against authoritative server data. It checked equipment and learned spells against the local catalog, then applied a level-aware policy. Direct commands were isolated from ordinary chat so generated language could not accidentally trigger game actions.

Recover the failed component

The supervisor checked process health and heartbeat freshness alongside event-stream progress and server-session evidence. Recovery distinguished a dead client from a server failure. Grace periods and cooldowns prevented repeated restart attempts while an operation was still settling.

When needed, relog automation cleared only the affected stale server session and restarted the client path. Healthy server processes remained running. This required reconciling application state across the client bridge, database, and game server rather than relying on a process check alone.

Persist evidence and bound model access

The recorder filtered noisy telemetry, tagged important events, and preserved its position in the stream. SQLite stored session records and events, with summaries and other derived records linked back to their sources. Session consolidation separated temporary context from durable records.

Model context was assembled from bounded transcripts and selected source-backed records. Read-only retrieval exposed small searches instead of the full database. Output that violated the response contract was quarantined.

A provider-neutral router implemented structured OpenAI and Anthropic requests with budget auditing and per-domain cooldowns. Atomic state updates and missing-key refusal guarded the request path. Model availability never determined whether the deterministic workers could control the game client.

Implemented scope

The recovered project contained 40 Python source modules and a 56-table SQLite schema. The client bridge, control workers, and supervision were implemented, along with provisioning and relog recovery. Recorded operation demonstrated map login and a level-10 equipment-provisioning run that converged with no missing targets.

The recovered configuration had model routing disabled. Longer-term model behavior was not validated through sustained operation. The case study's strongest evidence is the implemented runtime and its state-management boundaries, with the model layer kept at its documented prototype scope.