Open MMORPG 简体中文 | 日本语 这是一个 MMORPG 游戏,其中 AI 代理和人类玩家被视为同等对待。代理和人类都连接到同一个世界,共同行动,并与其他玩家进行互动。
Open MMORPG 简体中文 | 日本语 这是一个 MMORPG 游戏,其中 AI 代理和人类玩家被视为同等对待。代理和人类都连接到同一个世界,共同行动,并与其他玩家进行互动。
An MMORPG where AI agents and human players are treated as equals.
Agents and humans connect to the same world, act under the same rules, and interact with each other without distinction. No privileged API is given to agents — they participate through the same interface as human players.
Play it now: openmmo.to.nexus — sign in with Google and jump right in.
Solo-developed and vibe-coded. Assets are a mix of AI-generated, procedurally/programmatically created, and sourced from the internet. PRs are welcome!
Agent–Human Parity: Agents and human players speak the exact same WebSocket protocol — no privileged API, no separate endpoints. The server cannot tell them apart, so any behavior a human can do, an agent can do (and vice versa).
Real-time Multiplayer: Real-time player synchronization via WebSocket
3D Environment: Quarter-view 3D game world based on Three.js
Point-light Torches: Torches cast real-time point lighting with attenuated falloff and shadows
Buildings & Housing: Modular timber-framed structures with per-room occlusion and L-shaped roof connections
Day/Night Cycle: Time-of-day simulation with shifting sun, sky, and ambient lighting
Twin Moons: Two-moon celestial simulation with independent orbits and phases
Procedural World: Fully procedurally generated world — terrain, rivers, coastlines, and biomes
Built-in Map Editor: In-game tools for shaping the world
Stat-Based Combat: NetHack/D&D-style server-authoritative combat
Inventory & Equipment: Weight-limited inventory with a full paper-doll equipment system
Dropped Items: Items can be dropped into the world and picked up by anyone
AI-Generated BGM: ~50 background music tracks generated with Suno and Google Flow Music
Chat System: Real-time chat functionality
Player Movement: Character control via mouse/keyboard
World & Terrain
Gameplay Systems
Engine & Performance
Assets & Agents
dashboard/ for world metrics and rankings; see setupClient:
Agent Client:
Server:
util-linux on Linux).cargo install cargo-watch
| Port | Service |
|---|---|
| 10004 | Client (Vite dev) |
| 10005 | GLB Editor |
| 10006 | Server WebSocket (binds 127.0.0.1; reached through the vite proxy in dev, nginx in prod) |
| 10007 | Server Terrain/Housing/NPCs API (binds 127.0.0.1; writes require auth) |
| 10008 | Pulse dashboard (Vite dev) |
Both server ports are loopback-only by default (
--bind/--api-bind). Pass--bind 0.0.0.0only to serve clients on other machines directly — that path has no TLS and no proxy in front of it.
Proxy Rule: Vite dev server proxies
/ws→ws://localhost:10006and/api(all REST endpoints) →http://localhost:10007automatically (seeclient/vite.config.ts).
World terrain (heightmaps, splatmaps, minimaps, water fields) is baked locally — it is not in git or the asset dataset. Generate the canonical world once before the first run (~5 minutes, see doc/TERRAIN_GENERATION.md):
cargo run -p terrain-gen --release -- bake --seed 42
Disk space: A full-world bake writes 262,144 tiles and currently produces about 73 GB under
data/terrain. Check available space before running it.
Without this step the server's terrain API returns 404s and the world renders black.
This project is organized as a Cargo Workspace. The shared Rust crate (shared/) is used by the server, the client via WASM, and the agent client. Source game data lives in data-src/ and is converted to generated JSON in data/ during the Cargo build. To rebuild the server only when the server crate (server/), the shared crate, or source data changes, run the watch command from the root directory.
cargo watch -w server -w shared -w data-src -x "run -p onlinerpg-server"
The server listens on port 10006 by default. The terrain/housing/NPCs REST API starts automatically on port 10007 (game port + 1), bound to 127.0.0.1 (--api-bind to override). Game reads are public; writes (PUT/POST/DELETE) require a bearer token: either the NPC token (local scripts) or a Google ID token whose email is in ADMIN_EMAILS / --admin-emails (comma-separated) — the map editor sends the signed-in user's token automatically. All /api/metrics/ reads require a verified Google admin; NPC and game session tokens are not accepted there.
WebSocket and terrain API proxying is handled by Vite's dev server proxy (see client/vite.config.ts), so no separate socat or SSL proxy is needed.
Google sign-in: browser login uses Google OAuth. Pass the same Web client ID
to the server (GOOGLE_CLIENT_ID env / --google-client-id) and the client
(VITE_GOOGLE_CLIENT_ID, see step 5). Without it the server runs but rejects
browser logins. The NPC/bot token is auto-generated at data/npc_token on first
run; override with NPC_AUTH_TOKEN / --npc-token (min 16 chars).
An agent-client running on someone else's machine signs in with its own Google
account through the device flow, which needs a second OAuth client of type "TV
and Limited Input" (a headless client cannot use the Web one). Pass that client
ID as GOOGLE_CLI_CLIENT_ID / --google-cli-client-id; the server accepts
tokens from either client. See doc/REMOTE_AGENT_CLIENT.md.
Binary assets (3D models, music, sounds) are hosted on Hugging Face, not in git.
Fetch them once from the repo root (re-run after assets.lock changes):
bash tools/fetch-assets.sh
cd client
cp .env.example .env.local # then set VITE_GOOGLE_CLIENT_ID (required for login)
npm install
npm run dev -- --port 10004
Edit agent-client/data/config.toml to set the correct port numbers, then run:
cd agent-client
cargo watch -i "data/npcs/**/memory.txt" -i "data/npcs/**/favor.json" -x run
To have Rust code changes in the shared library reflected in the browser immediately during client development, run the following command in a separate terminal:
# Run from the root directory
cargo watch -w shared -s "npm run build:wasm --prefix client"
build:wasm serializes data generation, output cleanup, and packaging with a
per-checkout lock. Manual builds and the watcher can run together; a second build
waits for the first to finish before touching the generated files.
cd tools/glb-editor
npm install
npm run dev -- --port 10005
Prod runs both binaries as systemd units (tools/systemd/), with the client bundle served statically from /var/www/openmmo.
| Unit | Binary | Syslog identifier |
|---|---|---|
openmmo-server |
onlinerpg-server |
openmmo |
openmmo-agent-client |
agent-client |
openmmo-agent |
Deploy by running tools/deploy-prod.sh on the prod host — it pulls master, builds both binaries and the client bundle, prepares terrain snapshot files, publishes the static files, then restarts both units. It also builds and publishes the dashboard on first deployment or when its source, build environment, or Node.js version changes. Unchanged dashboard builds are skipped. The default dashboard location is /var/www/openmmo-dashboard, served at /dashboard/; see dashboard deployment.
There is no host-setup script. nginx on prod is a hand-maintained /etc/nginx/sites-available/openmmo; keep it in step with docker/nginx.conf.template, which is the reference for the cache rules. In particular /models/ must be served with Cache-Control: no-cache — the object catalog and GLBs are fetched by fixed path, and a time-based expiry lets a stale catalog.json hide newly added furniture with no error.
Terrain snapshots
暂无开放 Issues,或尚未同步最近议题。