Generated from uo_proto::msg (protocol version 3) by crates/uo-mcp/tests/protocol_doc.rs: don't edit by hand, run UO_BLESS=1 cargo test -p uo-mcp --test protocol_doc. Decision #3: one public protocol for the game client, scripts and agents alike; bots are ordinary players with the same limits. Guide: scripting.
Transport
Wire protocol. JSON over WebSocket, one message per text frame. The same protocol serves the game client, automation scripts and the MCP bridge — there is no privileged "bot API", bots are first-class players.
Client -> server: {"req": 7, "type": "walk_to", "x": 10, "y": 4}
Server -> client: {"type": "reply", "req": 7, "ok": true, "data": {...}} plus unsolicited delta, snapshot and event messages.
Version 2 (decision #87, docs/server-architecture.md): the world arrives as per-tick deltas of the player's area of interest (entities entering, changing and leaving, object damage); sessions can be resumed on any gateway with the token from Welcome; combat orders and the combat event stream of uo-combat (decision #68) travel with entity ids and world object keys.
Version 3 (decision #121, docs/economy.md): the economy — harvesting, crafting, eating, town markets (swaps, liquidity, vault deposits, plots, proposals), plunder and stolen goods, Aquais' mint and store, corpses and looting; the owner's sheet is pushed privately (GameEvent::Sheet).
Decision #123 (docs/npcs.md) adds townsfolk (EntityKind::Npc), talking to them (Talk, Choose -> GameEvent::Dialogue), the onboarding errands (SkipErrand; progress in the sheet's citizen) and hints (GameEvent::Hint).
Social play (decision #131, docs/social.md, still version 3: every addition is optional): chat channels, parties, guilds, murder counts and young colonists, appended at the ends of the enums.
- Connect a WebSocket to a gateway (
ws://host:7777 by default) and send JSON text frames, one message per frame.
- Getting in (decision #126): on servers with accounts,
sign_in (or sign_in_token with an API token from create_api_token, the way for scripts and bots), then play_character; development servers also take the login by name shown below. resume gets a dropped connection back. Every client message may carry req, a number of your choice; the server answers it with a reply carrying the same req, ok, and either data or a plain-words error.
- Unsolicited messages:
snapshot (the whole area of interest, after login or a gap), delta (what changed each tick, 20 per second), event (chat, work results, combat, your sheet).
- Field names are snake_case; enums are tagged (
type, kind, event). Tiles are x east, y south. Times are server milliseconds. Weights are tenths of a stone. Skill values are tenths (312 = 31.2).
- Unknown fields must be ignored: new versions add fields and message kinds.
A session, line by line (> sent, < received):
> {"req":1,"type":"login","name":"Ann"}
< {"type":"reply","req":1,"ok":true,"data":{"kind":"welcome","protocol":3,"entity_id":1001,"wallet":"dev:Ann","map_seed":1,"map_width":16384,"map_height":16384,"tick_hz":20,"ledger":"off","token":"2f6c…","server_ms":72000000,"region_size":64,"aoi_radius":18,"x":812,"y":455,"spells":["magic_arrow","heal"],"world":"felucca","world_hash":"9b1e…","day_ms":6900000,"time_scale":1}}
< {"type":"snapshot","tick":9120,"entities":[{"id":1001,"x":812,"y":455,"facing":"south","kind":"player","name":"Ann","moving":false,"equipment":[["main_hand",300]],"look":{"gender":"female","skin":"dark","hair":"long","hair_color":3,"beard":false},"guild":"IW","young":true,"tool":100,"materials":[["main_hand",851]],"keys":[["q","puncture"],["f","dash"]],"runes":[["main_hand",["rune_swift"]]],"exceptional":["main_hand"],"hits":50,"max_hits":50,"mana":20,"max_mana":20,"dead":false,"step_ms":250},{"id":77000001,"x":818,"y":450,"facing":"west","kind":"creature","species":"wolf","hits":18,"max_hits":30,"mana":0,"max_mana":0,"dead":false}]}
> {"req":2,"type":"harvest","target":{"kind":"object","key":4398046511617}}
< {"type":"reply","req":2,"ok":true}
< {"type":"event","event":"worked","text":"You put 2 logs in your pack.","item_id":1,"amount":2,"gain":["lumberjacking",313]}
< {"type":"delta","tick":9121,"update":[{"id":77000001,"x":817,"y":450,"facing":"west","kind":"creature","species":"wolf","hits":18,"max_hits":30,"mana":0,"max_mana":0,"dead":false}]}
> {"req":3,"type":"swap","town":3,"item":1,"side":"sell","amount":100,"limit":1}
< {"type":"reply","req":3,"ok":false,"error":"You don't have that many."}
Commands (client → server)
Every command is an object with type and, optionally, req.
login
Must be the first message (or Resume). name identifies the character; in dev mode it is created on first login.
{"req":1,"type":"login","name":"Ann"}
resume
Re-attach to a live session (after a dropped connection or a gateway failure) with the token from Welcome.
{"req":2,"type":"resume","token":"2f6c…"}
step
Take a single step.
{"req":3,"type":"step","dir":"north_east"}
walk_to
Path-find to a tile and walk there, one step at a time; the walk continues across region borders.
{"req":4,"type":"walk_to","x":812,"y":455}
stop
{"req":5,"type":"stop"}
move
Keep walking in a direction (UO's held right mouse button, WASD) until dir: null: one step per step time, sliding along what's in the way. Any other order ends it.
| field | type | |
|---|
dir | Option<Direction> | |
{"req":6,"type":"move","dir":"west"}
say
{"req":7,"type":"say","text":"Logs for sale!"}
look
Describe the surroundings (entities within radius tiles).
{"req":8,"type":"look","radius":12}
inventory
{"req":9,"type":"inventory"}
equip
Wear an item from the backpack.
{"req":10,"type":"equip","item_id":304}
unequip
{"req":11,"type":"unequip","slot":"off_hand"}
gather
Old on-chain gathering; refused (use Harvest).
{"req":12,"type":"gather","node_id":1}
craft
Run a recipe times times at a station within reach.
| field | type | |
|---|
recipe_id | RecipeId | |
times | u32 | |
{"req":13,"type":"craft","recipe_id":1,"times":5}
harvest
Work a resource node (a tree, vein or rock: Object) or fish (Tile of water). Repeats until stopped, the node is spent or the backpack is full; walking or any other order ends it.
{"req":14,"type":"harvest","target":{"kind":"object","key":4398046511617}}
use
Use an item from the backpack (eat food).
{"req":15,"type":"use","uid":17}
move_item
Put an item (with what it holds) into a container we carry: the backpack or a bag in it. Worn items come off first (Unequip). amount: only that many of a stack (split off; the rest stays where it was). onto: a stack in that container to join (same kind), as when one pile is dropped on another; it may be in the same container.
| field | type | |
|---|
uid | ItemUid | |
container | ItemUid | |
amount | Option<u32> | |
onto | Option<ItemUid> | |
{"req":16,"type":"move_item","uid":17,"container":7,"amount":20,"onto":12}
sheet
Ask for the character's sheet now (it is also pushed on change).
{"req":17,"type":"sheet"}
market
The market of the town whose exchange is within reach.
{"req":18,"type":"market","town":3}
swap
Buy or sell amount units of a good at its pool. limit: the most coin to pay (buy) or the least to receive (sell); 0 = none. The trade fails rather than fill worse.
| field | type | |
|---|
town | TownId | |
item | ItemId | |
side | Side | |
amount | u64 | |
limit | u64 | |
{"req":19,"type":"swap","town":3,"item":1,"side":"sell","amount":20,"limit":70}
deposit
Put coin or goods from the backpack into the town's vault.
| field | type | |
|---|
town | TownId | |
item | ItemId | |
amount | u64 | |
{"req":20,"type":"deposit","town":3,"item":8,"amount":500}
withdraw
| field | type | |
|---|
town | TownId | |
item | ItemId | |
amount | u64 | |
{"req":21,"type":"withdraw","town":3,"item":8,"amount":200}
add_liquidity
Add coin and goods to a pool in its ratio (the rest stays with you).
| field | type | |
|---|
town | TownId | |
item | ItemId | |
gold | u64 | |
goods | u64 | |
{"req":22,"type":"add_liquidity","town":3,"item":5,"gold":300,"goods":100}
remove_liquidity
| field | type | |
|---|
town | TownId | |
item | ItemId | |
shares | u64 | |
{"req":23,"type":"remove_liquidity","town":3,"item":5,"shares":1000}
claim_plot
Hold a plot by locking stake worth its price.
| field | type | |
|---|
town | TownId | |
plot | PlotId | |
{"req":24,"type":"claim_plot","town":3,"plot":12}
release_plot
| field | type | |
|---|
town | TownId | |
plot | PlotId | |
{"req":25,"type":"release_plot","town":3,"plot":12}
propose
| field | type | |
|---|
town | TownId | |
action | Action | |
{"req":26,"type":"propose","town":3,"action":{"action":"set_fee","fee":800}}
vote
| field | type | |
|---|
town | TownId | |
proposal | u32 | |
yes | bool | |
{"req":27,"type":"vote","town":3,"proposal":4,"yes":true}
plunder
Take goods out of a broken vault; they are stolen.
| field | type | |
|---|
town | TownId | |
item | ItemId | |
amount | u64 | |
{"req":28,"type":"plunder","town":3,"item":8,"amount":2000}
return_stolen
Hand stolen goods back to the town they were taken from.
{"req":29,"type":"return_stolen","town":3}
fence
Have a lawless town's fence clean stolen goods for a cut.
{"req":30,"type":"fence","town":9}
mint
Aquais: gold ingots to coins at the mint's rate.
{"req":31,"type":"mint","ingots":3}
buy
Aquais: buy from the mainland store.
| field | type | |
|---|
item | ItemId | |
amount | u32 | |
{"req":32,"type":"buy","item":14,"amount":2}
buy_patent
Any exchange: a work patent for a skill.
{"req":33,"type":"buy_patent","skill":"lumberjacking"}
export
Aquais: ship coins to the mainland (they leave the world).
{"req":34,"type":"export","coins":1000}
loot
Look into a corpse within reach.
{"req":35,"type":"loot","key":9007199254740993}
take
Take one item (or everything: no uid) from a corpse within reach; amount: only that many of a stack (the rest stays).
| field | type | |
|---|
key | ObjectKey | |
uid | Option<ItemUid> | |
amount | Option<u32> | |
{"req":36,"type":"take","key":9007199254740993,"uid":null}
attack
Approach and strike (then auto-attack) an entity or an object.
{"req":37,"type":"attack","target":{"kind":"entity","id":42}}
cast
Approach into range and cast.
| field | type | |
|---|
spell | SpellId | |
target | TargetRef | |
{"req":38,"type":"cast","spell":"fireball","target":{"kind":"entity","id":42}}
guard
{"req":39,"type":"guard"}
potion
{"req":40,"type":"potion"}
hold
Stop auto-attacking until the next order.
{"req":41,"type":"hold"}
open
Walk up to a closed door or gate and open it.
{"req":42,"type":"open","key":4398046511700}
plant
Walk up to an obstacle and plant a powder keg by it (needs charges).
{"req":43,"type":"plant","key":4398046511700}
ping
{"req":44,"type":"ping","client_ms":1234567}
talk
Talk to a townsperson: from afar the character walks up first. The dialogue arrives as GameEvent::Dialogue.
{"req":45,"type":"talk","npc":5764607523034243073}
choose
Answer a dialogue with one of its options (Choice::key).
| field | type | |
|---|
npc | EntityId | |
option | String | |
{"req":46,"type":"choose","npc":5764607523034243073,"option":"accept"}
skip_errand
Skip the current errand, or all of them.
{"req":47,"type":"skip_errand","all":false}
server_info
What the server is (protocol, sign-in methods, creation limits); works before signing in.
{"req":48,"type":"server_info"}
register
A new account; key is an alpha key (each opens one account).
| field | type | |
|---|
username | String | |
password | String | |
key | String | |
{"req":49,"type":"register","username":"ann","password":"correct horse","key":"FEL-K7QM-3XWD-9PRA"}
sign_in
| field | type | |
|---|
username | String | |
password | String | |
{"req":50,"type":"sign_in","username":"ann","password":"correct horse"}
sign_in_token
Sign in with an API token (scripts, bots: #3) or the session of an earlier AccountInfo.
{"req":51,"type":"sign_in_token","token":"uo_3f9a1c2e_…"}
account
The signed-in account and its characters.
{"req":52,"type":"account"}
create_character
A new character within the ruleset's creation limits; it lands in Aquais. Answered with Account.
| field | type | |
|---|
name | String | |
look | Look | |
str | u16 | |
dex | u16 | |
int | u16 | |
skills | Vec<(Skill, SkillValue)> | Up to three starting skills (tenths) summing to the ruleset's total. |
{"req":53,"type":"create_character","name":"Ann Lee","look":{"gender":"female","skin":"dark","hair":"long","hair_color":3,"beard":false},"str":30,"dex":40,"int":10,"skills":[["archery",500],["anatomy",300],["healing",200]]}
play_character
Enter the world as one of the account's characters (answered with Welcome, like Login).
{"req":54,"type":"play_character","name":"Ann Lee"}
delete_character
{"req":55,"type":"delete_character","name":"Ann Lee"}
create_api_token
A token for scripts and bots to sign in as this account.
{"req":56,"type":"create_api_token","label":"my bot"}
revoke_api_token
{"req":57,"type":"revoke_api_token","id":"3f9a1c2e"}
gm
A game master's console line (.tele 100 200, .help); refused for players who aren't GMs. Answered with ReplyData::Gm.
{"req":58,"type":"gm","line":".tele 1024 512"}
craft_with
Craft choosing the material: another ingot for the recipe's iron, another board for its plain boards (uo_proto::craft); for the build system's gear the material sets the tier (#148).
| field | type | |
|---|
recipe_id | RecipeId | |
times | u32 | |
material | Option<ItemId> | |
design | Option<String> | An armour piece's design, one the crafter knows: Head, Body, Feet the key of its D, R or F ability, Hands, Arms, Legs an affix design (uo_proto::builds::craft). |
affix | Option<String> | The second affix an exceptional Hands, Arms or Legs piece gets (any of its slot's pool but the design's own). |
{"req":59,"type":"craft_with","recipe_id":10301,"times":2,"material":772}
repair
Mend a worn item at the station of the trade that makes it, with one unit of its material.
{"req":60,"type":"repair","uid":21}
wear
Wear this item (Equip takes any of a kind).
{"req":61,"type":"wear","uid":21}
set_skill_lock
Set a skill's gain arrow: up, down (gives points to others at the cap) or locked.
| field | type | |
|---|
skill | Skill | |
lock | Lock | |
{"req":62,"type":"set_skill_lock","skill":"fishing","lock":"down"}
set_stat_lock
| field | type | |
|---|
stat | Stat | |
lock | Lock | |
{"req":63,"type":"set_stat_lock","stat":"int","lock":"locked"}
commission
At a town's exchange: commission design design of a plot you hold (uo_world::plots::designs); a building permit goes into the backpack.
| field | type | |
|---|
town | TownId | |
plot | PlotId | |
design | u32 | |
{"req":64,"type":"commission","town":17,"plot":0,"design":2}
break_ground
On the plot: open the construction site with a permit from the backpack.
{"req":65,"type":"break_ground","uid":12}
deliver
Hand materials to a construction site (a house key) within reach; no item: everything carried that the site still needs.
| field | type | |
|---|
key | ObjectKey | |
item | Option<ItemId> | |
amount | u32 | 0: as much as the site needs. |
{"req":66,"type":"deliver","key":462210957312,"item":null,"amount":0}
lock_house
Lock or unlock a house's front door (friends and up open it).
| field | type | |
|---|
key | ObjectKey | |
locked | bool | |
{"req":67,"type":"lock_house","key":462210957312,"locked":true}
house_access
Put a character (by name, in sight) on an access list, or take them off.
| field | type | |
|---|
key | ObjectKey | |
list | AccessList | |
name | String | |
add | bool | |
{"req":68,"type":"house_access","key":462210957312,"list":"friends","name":"Rowan","add":true}
stash
Put an item from the backpack into the house's secure chest (Loot / Take on the chest look and take).
| field | type | |
|---|
key | ObjectKey | |
uid | ItemUid | |
{"req":69,"type":"stash","key":462210960323,"uid":7}
place_furniture
Place furniture from the backpack on a ground-floor tile of the house.
| field | type | |
|---|
key | ObjectKey | |
uid | ItemUid | |
x | i32 | |
y | i32 | |
facing | Facing | |
{"req":70,"type":"place_furniture","key":462210957312,"uid":9,"x":11512,"y":6855,"facing":"south"}
pick_up_furniture
Take placed furniture back into the backpack.
| field | type | |
|---|
key | ObjectKey | |
slot | u16 | |
{"req":71,"type":"pick_up_furniture","key":462210957312,"slot":0}
repair_house
Mend every damaged or broken piece, paying its materials.
{"req":72,"type":"repair_house","key":462210957312}
demolish
Tear the house (or the site) down; the permit comes back.
{"req":73,"type":"demolish","key":462210957312}
tell
A private message to a character by name, wherever they are.
| field | type | |
|---|
to | String | |
text | String | |
{"req":74,"type":"tell","to":"Bram","text":"Meet me at the bridge."}
chat
A line on a channel: party, guild, alliance, region, trade.
| field | type | |
|---|
channel | Channel | |
text | String | |
{"req":75,"type":"chat","channel":"party","text":"Archers first."}
party_invite
Ask a character to join our party (we lead it, or found it).
{"req":76,"type":"party_invite","name":"Bram"}
party_answer
Join the party of whoever invited us (yes: false declines).
{"req":77,"type":"party_answer","yes":true}
party_leave
{"req":78,"type":"party_leave"}
party_kick
The leader removes a member.
{"req":79,"type":"party_kick","name":"Bram"}
guild_found
Found a guild (burns social::GUILD_FOUND_COST coins).
| field | type | |
|---|
name | String | |
tag | String | |
{"req":80,"type":"guild_found","name":"Iron Wardens","tag":"IW"}
guild_invite
Officers and the leader invite a character.
{"req":81,"type":"guild_invite","name":"Bram"}
guild_answer
Answer a guild's invitation.
| field | type | |
|---|
guild | GuildId | |
yes | bool | |
{"req":82,"type":"guild_answer","guild":7002195088111616,"yes":true}
guild_leave
Leave the guild (the last member's leaving disbands it).
{"req":83,"type":"guild_leave"}
guild_kick
{"req":84,"type":"guild_kick","name":"Bram"}
guild_rank
| field | type | |
|---|
name | String | |
rank | Rank | |
{"req":85,"type":"guild_rank","name":"Bram","rank":"officer"}
guild_stance
Set our stance towards another guild (by name or tag): war at once, an alliance once both propose it, neutral ends either.
| field | type | |
|---|
guild | String | |
stance | Stance | |
{"req":86,"type":"guild_stance","guild":"RV","stance":"war"}
social
Our party and guild now (they are also pushed on change).
{"req":87,"type":"social"}
renounce_young
Give up the young colonist's protection early.
{"req":88,"type":"renounce_young"}
report
Report a character to the game masters.
| field | type | |
|---|
name | String | |
reason | String | |
{"req":89,"type":"report","name":"Spammer","reason":"trade channel spam"}
drop
Put an item (with what it holds) on the ground: a pile anyone may loot like a corpse (Loot, Take; no crime), gone after a while. Worn items come off with it; stolen goods can't be dropped. at: a free tile within DROP_RANGE (#134; else, or none, at your feet); a pile already lying there takes it in. amount: only that many of a stack.
| field | type | |
|---|
uid | ItemUid | |
at | Option<(i32, i32)> | |
amount | Option<u32> | |
{"req":90,"type":"drop","uid":7,"at":[818,451]}
close
Walk up to an open door or gate and close it (Open opens one; an open door also swings shut by itself after a few seconds).
{"req":91,"type":"close","key":4398046511700}
raise_guard
Guard up (up: true, the key pressed) or down (released), at once, even while recovering. A press shortly before a blow lands turns it aside (a perfect guard); a held guard blocks part of every blow from the front. at: when the key was pressed, in server game ms (the clock the pongs carry), so lag doesn't eat the window; believed at most 150 ms back. (Guard is a short tap of the same.)
| field | type | |
|---|
up | bool | |
at | Option<u64> | |
{"req":92,"type":"raise_guard","up":true,"at":1761400000250}
dodge
Dodge a tile that way at once: a moment of invulnerability for some stamina, even while recovering.
{"req":93,"type":"dodge","dir":"south_east"}
ability
Use the ability on a key: the weapon's Q, W, E, the chest's R, the helmet's D, the boots' F (uo_proto::builds). Approaches until in reach when it needs a target; target none: yourself or where you stand (self abilities, escapes). Replaces #145's techniques: Cleave, Lunge, Puncture… are the families' Q and W.
| field | type | |
|---|
slot | Slot | |
target | Option<TargetRef> | |
{"req":94,"type":"ability","slot":"q","target":{"kind":"entity","id":77000001}}
set_loadout
Set the loadout (Q and W per weapon family; R, D, F for the chest, helmet and boots, any class, from their whole pools; passives), out of a fight only.
{"req":95,"type":"set_loadout","loadout":{"picks":[{"family":"sword","q":"riposte","w":"parry"}],"d":"blind","passives":["duelist"]}}
socket
Socket a rune from the pack into the next free socket of the weapon in hand (1 socket at T1–T2, 2 at T3–T4, 3 at T5, one more when exceptional; socket 1 changes Q, 2 W, 3 E), out of a fight only.
{"req":96,"type":"socket","rune":1172}
unsocket
Take the rune out of a socket (0 = the first) of the weapon in hand, out of a fight only: the rune is destroyed.
{"req":97,"type":"unsocket","socket":0}
Replies
{"type":"reply","req":N,"ok":true,"data":{"kind":…}} — data is one of these (many commands answer ok with no data):
welcome
Carries a Welcome (its fields sit beside kind).
{"type":"reply","req":1,"ok":true,"data":{"kind":"welcome","protocol":3,"entity_id":1001,"wallet":"dev:Ann","map_seed":1,"map_width":16384,"map_height":16384,"tick_hz":20,"ledger":"off","token":"2f6c…","server_ms":72000000,"region_size":64,"aoi_radius":18,"x":812,"y":455,"spells":["magic_arrow","heal"],"world":"felucca","world_hash":"9b1e…","day_ms":6900000,"time_scale":1}}
look
| field | type | |
|---|
me | EntityState | |
entities | Vec<EntityState> | |
{"type":"reply","req":8,"ok":true,"data":{"kind":"look","me":{"id":1001,"x":812,"y":455,"facing":"south","kind":"player","name":"Ann","moving":false,"equipment":[["main_hand",300]],"look":{"gender":"female","skin":"dark","hair":"long","hair_color":3,"beard":false},"guild":"IW","young":true,"tool":100,"materials":[["main_hand",851]],"keys":[["q","puncture"],["f","dash"]],"runes":[["main_hand",["rune_swift"]]],"exceptional":["main_hand"],"hits":50,"max_hits":50,"mana":20,"max_mana":20,"dead":false,"step_ms":250},"entities":[{"id":77000001,"x":818,"y":450,"facing":"west","kind":"creature","species":"wolf","hits":18,"max_hits":30,"mana":0,"max_mana":0,"dead":false}]}}
inventory
| field | type | |
|---|
wallet | String | |
items | Vec<ItemStack> | |
{"type":"reply","req":9,"ok":true,"data":{"kind":"inventory","wallet":"dev:Ann","items":[{"item_id":1,"qty":6}]}}
tx
Result of an on-chain action.
| field | type | |
|---|
signature | String | |
items | Vec<ItemStack> | |
{"type":"reply","req":12,"ok":true,"data":{"kind":"tx","signature":"","items":[]}}
pong
| field | type | |
|---|
client_ms | u64 | |
server_ms | u64 | |
{"type":"reply","req":44,"ok":true,"data":{"kind":"pong","client_ms":1234567,"server_ms":72000050}}
market
Carries a Box<MarketView> (its fields sit beside kind).
{"type":"reply","req":18,"ok":true,"data":{"kind":"market","town":0,"name":"Aquais","free_port":true,"lawless":false,"params":{"fee":1000,"split":{"reserves":6000,"treasury":0,"crown":4000},"plot_price":5000,"window":{"start_hour":19,"hours":2},"return_reward":1000},"treasury":0,"burned":0,"lord":null,"vault":{"hits":450,"max":450,"open_until":0},"raid_window":true,"pools":[{"item":1,"gold":20000,"goods":20000,"shares":20000,"mine":0,"locked":0},{"item":9,"gold":20000,"goods":11111,"shares":14907,"mine":0,"locked":0}],"deposits":[],"stake":0,"total_stake":0,"plots":[],"proposals":[],"log":[],"mint":{"rate":100,"books":{"minted_ingots":0,"coins_minted":0,"exported":0,"burned":0,"mainland_at":0,"mainland_coin":0,"mainland_goods":0},"store":[{"item":14,"price":5},{"item":101,"price":60},{"item":100,"price":50},{"item":102,"price":30},{"item":103,"price":40},{"item":104,"price":40},{"item":791,"price":40},{"item":792,"price":40},{"item":793,"price":30},{"item":794,"price":30},{"item":881,"price":40},{"item":750,"price":120},{"item":751,"price":25},{"item":752,"price":35},{"item":753,"price":60},{"item":754,"price":60},{"item":757,"price":8},{"item":766,"price":3},{"item":705,"price":2},{"item":758,"price":8},{"item":759,"price":8},{"item":760,"price":6},{"item":761,"price":6},{"item":762,"price":8},{"item":763,"price":6},{"item":703,"price":6},{"item":765,"price":6},{"item":901,"price":30},{"item":903,"price":35},{"item":905,"price":55},{"item":906,"price":60},{"item":907,"price":120},{"item":908,"price":90},{"item":909,"price":120},{"item":910,"price":90},{"item":912,"price":40},{"item":913,"price":30},{"item":914,"price":20}]},"server_ms":72000000}}
sheet
Carries a Box<SheetView> (its fields sit beside kind).
{"type":"reply","req":17,"ok":true,"data":{"kind":"sheet","sheet":{"name":"Ann","stats":{"str":{"base":60,"lock":"up"},"dex":{"base":50,"lock":"up"},"int":{"base":40,"lock":"up"}},"skills":{"lumberjacking":{"base":312,"lock":"up"}},"vitals":{"hits":60,"stamina":50,"mana":40},"items":{"7":{"def":200,"amount":1,"place":{"at":"equipped","slot":"backpack"}},"8":{"def":8,"amount":1000,"place":{"at":"in","container":7}},"9":{"def":1,"amount":6,"place":{"at":"in","container":7}}}},"citizen":{"patents":{"lumberjacking":604800000},"satiety":100,"fed_ms":0,"criminal_until":0,"hero_until":0,"ghost":false,"errands":{"step":0,"progress":0,"skipped":false,"skipped_steps":0,"started_ms":0,"finished_ms":0,"hints":0},"murders":0,"murder_decay_ms":0,"played_ms":0,"young":true,"shield_until":0},"notoriety":"innocent","weight":172,"capacity":2150,"task":"Lumberjacking","town":0,"server_ms":72000000}}
container
A corpse's contents.
| field | type | |
|---|
key | ObjectKey | |
name | String | |
items | Vec<(ItemUid, Item)> | |
until_ms | u64 | When it rots, server ms. |
pile | Option<(i32, i32)> | A pile of things on the ground (#130): its tile. Something let go into its window is dropped there (Drop { at }). |
{"type":"reply","req":35,"ok":true,"data":{"kind":"container","key":9007199254740993,"name":"the corpse of a wolf","items":[[31,{"def":11,"amount":1}],[32,{"def":13,"amount":1}]],"until_ms":72300000}}
server_info
Carries a Box<ServerInfo> (its fields sit beside kind).
{"type":"reply","req":1,"ok":true,"data":{"kind":"server_info","protocol":3,"accounts":true,"dev_login":false,"alpha_keys":true,"world":"felucca","world_hash":"9b1e…","max_characters":5,"creation":{"stat_total":80,"stat_min":10,"stat_max":60,"skill_count":3,"skill_total":1000,"skill_max":500,"name_min":2,"name_max":16},"online":12}}
account
Carries a Box<AccountInfo> (its fields sit beside kind).
{"type":"reply","req":2,"ok":true,"data":{"kind":"account","username":"ann","characters":[{"name":"Ann Lee","look":{"gender":"female","skin":"dark","hair":"long","hair_color":3,"beard":false},"stats":[30,40,10],"skills":[["archery",500],["anatomy",300],["healing",200]],"x":12443,"y":7244,"created_ms":72000000,"worn":[["shirt",{"def":500,"amount":1}]]}],"max_characters":5,"session":"8c1d…"}}
api_token
A new API token: the secret is shown only now.
| field | type | |
|---|
id | String | |
token | String | |
{"type":"reply","req":3,"ok":true,"data":{"kind":"api_token","id":"3f9a1c2e","token":"uo_3f9a1c2e_…"}}
gm
A GM console answer (text, may span lines).
{"type":"reply","req":51,"ok":true,"data":{"kind":"gm","text":"Ann is at 1024,512 (region 136)"}}
SheetView
Your own character, only ever sent to you (sheet reply and event).
| field | type | |
|---|
sheet | Character | |
citizen | Citizen | |
notoriety | Notoriety | |
weight | Weight | Carried and the most that can be carried, tenths of a stone. |
capacity | Weight | |
task | Option<String> | What the character is busy with ("Mining", "Cooking"…). |
town | Option<TownId> | The town whose guard zone they stand in. |
server_ms | u64 | |
{
"sheet": {
"name": "Ann",
"stats": {
"str": {
"base": 60,
"lock": "up"
},
"dex": {
"base": 50,
"lock": "up"
},
"int": {
"base": 40,
"lock": "up"
}
},
"skills": {
"lumberjacking": {
"base": 312,
"lock": "up"
}
},
"vitals": {
"hits": 60,
"stamina": 50,
"mana": 40
},
"items": {
"7": {
"def": 200,
"amount": 1,
"place": {
"at": "equipped",
"slot": "backpack"
}
},
"8": {
"def": 8,
"amount": 1000,
"place": {
"at": "in",
"container": 7
}
},
"9": {
"def": 1,
"amount": 6,
"place": {
"at": "in",
"container": 7
}
}
}
},
"citizen": {
"patents": {
"lumberjacking": 604800000
},
"satiety": 100,
"fed_ms": 0,
"criminal_until": 0,
"hero_until": 0,
"ghost": false,
"errands": {
"step": 0,
"progress": 0,
"skipped": false,
"skipped_steps": 0,
"started_ms": 0,
"finished_ms": 0,
"hints": 0
},
"murders": 0,
"murder_decay_ms": 0,
"played_ms": 0,
"young": true,
"shield_until": 0
},
"notoriety": "innocent",
"weight": 172,
"capacity": 2150,
"task": "Lumberjacking",
"town": 0,
"server_ms": 72000000
}
Welcome
| field | type | |
|---|
protocol | u32 | |
entity_id | EntityId | |
wallet | String | |
map_seed | u64 | |
map_width | u32 | |
map_height | u32 | |
tick_hz | u32 | |
ledger | String | |
token | String | Resume token for Command::Resume. |
server_ms | u64 | Server clock (ms) when the welcome was sent. |
region_size | u32 | |
aoi_radius | u32 | |
x | i32 | The character's tile. |
y | i32 | |
spells | Vec<SpellId> | Spells the character can cast (the spell bar). |
world | String | The baked world the map is read from (assets/world/<name>); empty: the seed's noise map. |
world_hash | String | Its world.json hash: the client must have the same bake. |
day_ms | u64 | One world day in game ms (decision #135): the client shows the hour clock::world_hour(server time, day_ms), the same for everyone. |
time_scale | u32 | Game time runs this many times faster than the wall clock (1 in play, more in test runs, --time-scale). |
World updates
snapshot
| field | type | |
|---|
tick | u64 | |
entities | Vec<EntityState> | |
objects | Vec<ObjectUpdate> | Every changed object in the area (damaged, broken, open, spawned). |
ground | Vec<GroundPatch> | Oiled and burning ground in the area (builds, decision #150): what a client joining mid-fight can't learn from Ground events it missed. |
delta
| field | type | |
|---|
tick | u64 | |
enter | Vec<EntityState> | |
update | Vec<EntityState> | |
leave | Vec<EntityId> | |
objects | Vec<ObjectUpdate> | |
EntityState
Every mobile in your area of interest. kind is flattened in: its tag and fields sit beside id.
| field | type | |
|---|
id | EntityId | |
x | i32 | |
y | i32 | |
facing | Direction | |
kind | EntityKind | |
hits | i32 | |
max_hits | i32 | |
mana | i32 | |
max_mana | i32 | |
dead | bool | |
step_ms | u32 | How long one step takes now, ms (players: a run out of a fight, a walk in one; 0: unknown, take 500). Clients time predicted steps by it. |
hidden | bool | A game master walking unseen (#128): gateways show it only to the GM itself and to other GMs. |
stam | i32 | Melee (decision #145): stamina (the melee resource), poise taken in permille of the maximum (full = broken), momentum pips (0..=5) and the stance (guarding, broken, exhausted). Zero for non-fighters. |
max_stam | i32 | |
poise | u16 | |
momentum | u8 | |
stance | CombatStance | |
states | Vec<(StateId, u8)> | Builds (decisions #147–#150): the states on it with their stacks. |
counters | Counters | Its chance counters (crit, block), visible to everyone (§ 16): percent towards the next one (at 100 it happens). |
cooldowns | Vec<u64> | When each ability key (Q W E R D F) is ready again, in server game ms (the clock the pongs carry; 0: ready); empty: every key ready. Absolute, so it changes only when an ability is used. |
live | Option<Box<LiveView>> | What else of a fighter's build the HUD shows (stream U1 of #150): when its states end, worn triggers' counts, stances, charges, marks, the Tome's spare spell. None when there is nothing. |
elite | Vec<crate::creatures::EliteMod> | An elite creature's modifiers (docs/builds.md § 14, stream E of #150): its name reads "a Hasted Vampiric grey wolf" (creatures::Elite::name). Empty for everyone else. |
{"id":1001,"x":812,"y":455,"facing":"south","kind":"player","name":"Ann","moving":false,"equipment":[["main_hand",300]],"look":{"gender":"female","skin":"dark","hair":"long","hair_color":3,"beard":false},"guild":"IW","young":true,"tool":100,"materials":[["main_hand",851]],"keys":[["q","puncture"],["f","dash"]],"runes":[["main_hand",["rune_swift"]]],"exceptional":["main_hand"],"hits":50,"max_hits":50,"mana":20,"max_mana":20,"dead":false,"step_ms":250}
Entity kinds
player
| field | type | |
|---|
name | String | |
moving | bool | |
equipment | Vec<(EquipSlot, ItemId)> | |
notoriety | Notoriety | |
ghost | bool | Walking dead, looking for a healer. |
look | Option<Look> | The body under the clothes (decision #126); None: by name. |
guild | String | Their guild's tag (#131), shown over the name. |
young | bool | A young colonist (#131): other players can't harm them. |
tool | Option<ItemId> | The tool they are working with (#134: chopping, mining, fishing, crafting): drawn in their hand instead of their weapon while the task lasts. |
materials | Vec<(EquipSlot, ItemId)> | Worn pieces made of a material above tier 1 (decision #148): the slot and the material item (ItemProps::material), so clients tint them as their wearer sees them. Pieces not listed wear their tier 1 look. |
keys | Vec<(crate::builds::Slot, crate::builds::AbilityId)> | The abilities on their keys, Q W E R D F (decision #172): the target card reads their build, as the build's code would. |
runes | Vec<(EquipSlot, Vec<String>)> | Worn pieces with runes in their sockets (rune item keys, socket order) (#172). |
exceptional | Vec<EquipSlot> | Worn pieces of exceptional quality (#172). |
resource_node
| field | type | |
|---|
node_id | u32 | |
item_id | ItemId | |
mob
A server-played mobile (camp bandits).
| field | type | |
|---|
name | String | |
archetype | String | uo_combat::Archetype, snake_case. |
equipment | Vec<(EquipSlot, ItemId)> | |
creature
An animal (placeholder art: a capsule).
npc
A townsperson (crate::npc): drawn as a human of its role, can't be attacked; click to talk.
| field | type | |
|---|
name | String | |
role | NpcRole | |
equipment | Vec<(EquipSlot, ItemId)> | |
ObjectUpdate
A world object whose state differs from the baked world (damaged, broken, open, regrowing (look), or spawned at run time: corpses, carcasses, vaults, Wall of Stone, kegs).
| field | type | |
|---|
key | ObjectKey | |
hits | u16 | |
broken | bool | |
open | bool | |
spawn | Option<StaticObject> | Objects created at run time (Wall of Stone, powder kegs) carry their static; generated ones are known from the seed. |
building | Option<Box<HouseView>> | A player house's record (decision #129): its pieces are rebuilt from it (uo_world::plots) and keyed under it. |
remains | Option<Box<Remains>> | A corpse or carcass (decision #134): whose body it is. Clients draw that body lying dead (a creature's capsules, a dressed human) and open it with Loot; the static's sprite is the fallback art. |
look | Option<String> | A worked-out resource node coming back (#133): while broken, it is drawn as this sprite instead (a felled tree's sapling, then a young tree); it can't be worked until it stands whole again. |
burning | bool | A wooden object on fire (Wildfire, decision #150): drawn burning until an update says otherwise (ObjectBurning events change it). |
{"key":9007199254740993,"hits":1,"broken":false,"open":false,"spawn":{"sprite":"corpse","x":818,"y":450,"z":0.0,"facing":"south"},"remains":{"kind":{"kind":"creature","species":"orc"},"facing":"south"}}
Events
{"type":"event","event":…}
chat
| field | type | |
|---|
from | String | |
text | String | |
{"type":"event","event":"chat","from":"Bram","text":"Selling stone in Skartor"}
gathered
| field | type | |
|---|
entity_id | EntityId | |
item_id | ItemId | |
signature | String | |
{"type":"event","event":"gathered","entity_id":1001,"item_id":1,"signature":""}
crafted
| field | type | |
|---|
entity_id | EntityId | |
recipe_id | RecipeId | |
signature | String | |
{"type":"event","event":"crafted","entity_id":1001,"recipe_id":1,"signature":""}
system
{"type":"event","event":"system","text":"You are starving: eat something."}
sheet
The owner's sheet changed (private).
Carries a Box<SheetView> (its fields sit beside event).
(a sheet reply's SheetView, as an event: {"type":"event","event":"sheet","sheet":{…},"citizen":{…},…})
worked
A harvest or craft attempt finished (private): what came of it.
| field | type | |
|---|
text | String | |
item_id | Option<ItemId> | |
amount | u32 | |
gain | Option<(Skill, SkillValue)> | A skill went up to this value. |
{"type":"event","event":"worked","text":"You put 2 logs in your pack.","item_id":1,"amount":2,"gain":["lumberjacking",313]}
combat
Something happened in a fight; at_ms is server time.
| field | type | |
|---|
at_ms | u64 | |
combat | CombatEvent | |
{"type":"event","event":"combat","at_ms":72000400,"combat":{"kind":"hit","by":77000001,"id":1001,"damage":6,"cause":{"kind":"weapon"}}}
respawned
A dead character stands again (x, y).
| field | type | |
|---|
id | EntityId | |
x | i32 | |
y | i32 | |
{"type":"event","event":"respawned","id":1001,"x":810,"y":452}
step_rejected
The character's step or walk was refused: it stands at x, y (clients that predicted their own steps roll back to it).
| field | type | |
|---|
id | EntityId | |
x | i32 | |
y | i32 | |
{"type":"event","event":"step_rejected","id":1001,"x":812,"y":455}
dialogue
An NPC speaks to the player (private).
Carries a Box<DialogueView> (its fields sit beside event).
{"type":"event","event":"dialogue","npc":5764607523034243073,"name":"Hester","role":"harbour_master","text":"Welcome ashore, colonist. Run a few errands for me and I'll see you're paid in kind.","options":[{"key":"accept","label":"Yes, give me work"},{"key":"skip_all","label":"I know the colony: no errands"},{"key":"bye","label":"Goodbye"}]}
hint
Something worth knowing, shown as a toast and in the journal (private): a first-time hint (errands::Hint::key) or an errand done (errand).
| field | type | |
|---|
key | String | |
title | String | |
text | String | |
{"type":"event","event":"hint","key":"errand","title":"Errand done: The exchange","text":"You receive 2 bread. Next: Chop 5 logs from trees outside the walls."}
skill_gained
A skill rose by use (private); lowered: a skill locked down that gave the points.
| field | type | |
|---|
skill | Skill | |
value | SkillValue | |
lowered | Option<(Skill, SkillValue)> | |
{"type":"event","event":"skill_gained","skill":"melee","value":412,"lowered":["fishing",299]}
stat_gained
A stat rose by use (private).
| field | type | |
|---|
stat | Stat | |
value | u16 | |
lowered | Option<(Stat, u16)> | |
{"type":"event","event":"stat_gained","stat":"str","value":41}
message
A chat line on a channel (local speech stays Chat).
Carries a ChatLine (its fields sit beside event).
{"type":"event","event":"message","channel":"guild","from":"Bram","tag":"IW","text":"Vipers west of the bridge!","at_ms":72000400}
party
Our party changed (None: we are in none).
| field | type | |
|---|
party | Option<PartyView> | |
{"type":"event","event":"party","party":{"id":3377699720527873,"leader":1001,"members":[{"char":1001,"name":"Ann"},{"char":1002,"name":"Bram"}]}}
party_status
Where our party's members are and how they fare.
| field | type | |
|---|
members | Vec<MemberStatus> | |
{"type":"event","event":"party_status","members":[{"char":1002,"x":830,"y":440,"hits":41,"max_hits":60,"mana":12,"max_mana":30,"dead":false}]}
guild
Our guild changed (None: we are in none).
| field | type | |
|---|
guild | Option<Box<GuildView>> | |
({"type":"event","event":"guild","guild":{"id":…,"name":"Iron Wardens","tag":"IW","members":[…],"allies":[…],"enemies":[…],…}}, or "guild":null)
party_invited
Someone asks us into their party (PartyAnswer).
{"type":"event","event":"party_invited","from":"Bram"}
guild_invited
A guild asks us to join (GuildAnswer).
| field | type | |
|---|
guild | GuildId | |
name | String | |
tag | String | |
from | String | |
{"type":"event","event":"guild_invited","guild":7002195088111616,"name":"Iron Wardens","tag":"IW","from":"Bram"}
law
The law speaks (#131): a crime, a murder count, youth's end, a town refusing a murderer. reason is a short key for scripts.
| field | type | |
|---|
reason | String | |
text | String | |
{"type":"event","event":"law","reason":"criminal","text":"You attacked Bram, an innocent: you are a criminal (grey) for a while."}
Combat events
Inside {"event":"combat","at_ms":…,"combat":{"kind":…}}. Fighters are entity ids, obstacles object keys, tiles [x, y]; ms is how long the action takes.
engaged
{"kind":"engaged","id":1001}
disengaged
{"kind":"disengaged","id":1001}
moved
| field | type | |
|---|
id | EntityId | |
from | (i32, i32) | |
to | (i32, i32) | |
ms | u32 | |
{"kind":"moved","id":77000001,"from":[818,450],"to":[817,451],"ms":500}
swing
| field | type | |
|---|
id | EntityId | |
target | TargetRef | |
impact_ms | u32 | |
ms | u32 | |
{"kind":"swing","id":1001,"target":{"kind":"entity","id":77000001},"impact_ms":300,"ms":1000}
shot
| field | type | |
|---|
id | EntityId | |
target | TargetRef | |
stop | StopRef | |
spell | Option<SpellId> | |
flight_ms | u32 | |
ms | u32 | |
{"kind":"shot","id":1001,"target":{"kind":"entity","id":77000001},"stop":{"kind":"clear"},"spell":null,"flight_ms":240,"ms":2000}
hit
flags: what made the hit what it was (uo_combat::melee::hit bits: 1 counter, 2 rear, 4 crit, 8 weakness, 16 resisted, 32 blocked, 64 empowered, 128 execute, 256 technique, 512 broken, 1024 knocked into something, 2048 bleeding).
| field | type | |
|---|
by | Option<EntityId> | |
id | EntityId | |
damage | i32 | |
cause | CauseRef | |
flags | u16 | |
{"kind":"hit","by":1001,"id":77000001,"damage":9,"cause":{"kind":"spell","spell":"magic_arrow"}}
missed
| field | type | |
|---|
by | EntityId | |
id | EntityId | |
{"kind":"missed","by":1001,"id":77000001}
parried
| field | type | |
|---|
by | EntityId | |
id | EntityId | |
{"kind":"parried","by":1001,"id":77000001}
whiffed
{"kind":"whiffed","id":1001}
object_hit
A blow on an object; also every stroke of an axe or pickaxe on a tree, rock or vein (#133, damage 0 when it doesn't crack further): clients shake and flash it.
| field | type | |
|---|
by | Option<EntityId> | |
key | ObjectKey | |
damage | u16 | |
left | u16 | |
from | (i32, i32) | |
{"kind":"object_hit","by":1001,"key":4398046511700,"damage":1,"left":4,"from":[812,455]}
object_broken
{"kind":"object_broken","key":4398046511700}
object_spawned
| field | type | |
|---|
key | ObjectKey | |
by | EntityId | |
{"kind":"object_spawned","key":4398046511701,"by":1001}
detonated
| field | type | |
|---|
key | ObjectKey | |
at | (i32, i32) | |
{"kind":"detonated","key":4398046511701,"at":[813,455]}
door_opened
| field | type | |
|---|
key | ObjectKey | |
by | EntityId | |
{"kind":"door_opened","key":4398046511700,"by":1001}
object_expired
{"kind":"object_expired","key":4398046511701}
cast_started
| field | type | |
|---|
id | EntityId | |
spell | SpellId | |
target | TargetRef | |
ms | u32 | |
{"kind":"cast_started","id":1001,"spell":"fireball","target":{"kind":"entity","id":77000001},"ms":1500}
fizzled
| field | type | |
|---|
id | EntityId | |
spell | SpellId | |
{"kind":"fizzled","id":1001,"spell":"fireball"}
spell_struck
| field | type | |
|---|
id | EntityId | |
spell | SpellId | |
target | TargetRef | |
stop | StopRef | |
at | (i32, i32) | |
{"kind":"spell_struck","id":1001,"spell":"fireball","target":{"kind":"entity","id":77000001},"stop":{"kind":"clear"},"at":[818,450]}
healed
| field | type | |
|---|
by | EntityId | |
id | EntityId | |
amount | i32 | |
{"kind":"healed","by":1001,"id":1001,"amount":12}
guarding
{"kind":"guarding","id":1001,"ms":3000}
drank
| field | type | |
|---|
id | EntityId | |
amount | i32 | |
ms | u32 | |
{"kind":"drank","id":1001,"amount":20,"ms":500}
died
{"kind":"died","id":77000001}
order_failed
| field | type | |
|---|
id | EntityId | |
reason | String | |
{"kind":"order_failed","id":1001,"reason":"no line of fire"}
door_closed
A door or gate closed: by by, or by itself (decision #136).
| field | type | |
|---|
key | ObjectKey | |
by | Option<EntityId> | |
{"kind":"door_closed","key":4398046511700,"by":null}
ability_used
An ability starts (decisions #145, #150; generalises #145's telegraph): the tiles it will strike and when it lands as everyone sees it (impact_ms from now; a feint really lands earlier), ms the whole action. Clients paint the tiles.
| field | type | |
|---|
id | EntityId | |
ability | AbilityId | |
slot | Slot | |
target | TargetRef | |
tiles | Vec<(i32, i32)> | |
impact_ms | u32 | |
ms | u32 | |
empowered | bool | |
{"kind":"ability_used","id":77000001,"ability":"cleave","slot":"q","target":{"kind":"entity","id":1001},"tiles":[[818,449],[817,449],[819,449]],"impact_ms":750,"ms":2250}
perfect_guard
id turned by's blow aside with a guard pressed in time.
| field | type | |
|---|
by | EntityId | |
id | EntityId | |
{"kind":"perfect_guard","by":77000001,"id":1001}
evaded
by's blow found id mid-dodge.
| field | type | |
|---|
by | EntityId | |
id | EntityId | |
{"kind":"evaded","by":77000001,"id":1001}
dodged
| field | type | |
|---|
id | EntityId | |
from | (i32, i32) | |
to | (i32, i32) | |
{"kind":"dodged","id":1001,"from":[818,449],"to":[819,449]}
guard_lowered
The guard went down: released, or broken by running out of stamina.
| field | type | |
|---|
id | EntityId | |
broken | bool | |
{"kind":"guard_lowered","id":1001,"broken":true}
broken
Poise broken: staggered ms, open to an Execute.
{"kind":"broken","id":77000001,"ms":2500}
executed
| field | type | |
|---|
by | EntityId | |
id | EntityId | |
{"kind":"executed","by":1001,"id":77000001}
knocked_back
Pushed or pulled to to (to == from: stopped, by the object against if any).
| field | type | |
|---|
id | EntityId | |
from | (i32, i32) | |
to | (i32, i32) | |
against | Option<ObjectKey> | |
{"kind":"knocked_back","id":77000001,"from":[818,450],"to":[818,450],"against":4398046511700}
interrupted
A wind-up or cast was broken off.
{"kind":"interrupted","id":77000001}
state_applied
A state landed on id (stacks now, for ms).
| field | type | |
|---|
id | EntityId | |
state | StateId | |
stacks | u8 | |
ms | u32 | |
by | Option<EntityId> | |
{"kind":"state_applied","id":77000001,"state":"bleeding","stacks":1,"ms":3000,"by":1001}
state_ended
A state ran out or was cleansed.
| field | type | |
|---|
id | EntityId | |
state | StateId | |
{"kind":"state_ended","id":77000001,"state":"bleeding"}
reaction
A reaction fired on id (Electrocute, Freeze, Shatter…).
| field | type | |
|---|
id | EntityId | |
reaction | ReactionId | |
by | Option<EntityId> | |
{"kind":"reaction","id":77000001,"reaction":"electrocute","by":1001}
triggered
A clothing piece, jewel, rune or keystone of id fired (its key).
| field | type | |
|---|
id | EntityId | |
trigger | String | |
target | Option<EntityId> | |
{"kind":"triggered","id":1001,"trigger":"storm_ring","target":77000001}
escaped
An escape took id from from to to (the same tile for one that doesn't move: evasion, breaking control).
| field | type | |
|---|
id | EntityId | |
ability | AbilityId | |
from | (i32, i32) | |
to | (i32, i32) | |
{"kind":"escaped","id":1001,"ability":"dash","from":[818,449],"to":[821,449]}
A formation (a surcoat's drill) formed or broke around id.
| field | type | |
|---|
id | EntityId | |
formation | String | |
{"kind":"formation_on","id":1001,"formation":"shield_wall"}
| field | type | |
|---|
id | EntityId | |
formation | String | |
{"kind":"formation_off","id":1001,"formation":"shield_wall"}
ground
Tiles turned Oiled or into burning ground (state oiled or burning) for ms; ms 0: back to plain ground (stream S).
| field | type | |
|---|
tiles | Vec<(i32, i32)> | |
state | StateId | |
ms | u32 | |
by | Option<EntityId> | |
{"kind":"ground","tiles":[[818,450],[819,450]],"state":"oiled","ms":10000,"by":1001}
object_burning
A wooden object caught fire (on) or went out (Wildfire).
| field | type | |
|---|
key | ObjectKey | |
on | bool | |
by | Option<EntityId> | |
{"kind":"object_burning","key":4398046511700,"on":true,"by":1001}
Shared shapes
TargetRef
entity
{"kind":"entity","id":42}
object
{"kind":"object","key":4398046511617}
tile
{"kind":"tile","x":812,"y":455}
Directions
north, north_east, east, south_east, south, south_west, west, north_west
Spells
magic_arrow, heal, fireball, wall_of_stone, lightning, explosion, mega_explosion
Items
Ids are permanent (append-only). Weight in tenths of a stone per per units.
| id | key | name | weight | per |
|---|
| 1 | log | Log | 20 | 1 |
| 2 | board | Board | 10 | 1 |
| 3 | iron_ore | Iron Ore | 120 | 1 |
| 4 | iron_ingot | Iron Ingot | 1 | 1 |
| 5 | stone | Stone | 100 | 1 |
| 6 | gold_ore | Gold Ore | 120 | 1 |
| 7 | gold_ingot | Gold Ingot | 2 | 1 |
| 8 | gold_coin | Gold Coin | 1 | 25 |
| 9 | raw_fish | Raw Fish | 10 | 1 |
| 10 | cooked_fish | Cooked Fish | 10 | 1 |
| 11 | raw_meat | Raw Meat | 10 | 1 |
| 12 | cooked_meat | Cooked Meat | 10 | 1 |
| 13 | hide | Hide | 10 | 1 |
| 14 | bread | Bread | 10 | 1 |
| 100 | hatchet | Hatchet | 40 | 1 |
| 101 | pickaxe | Pickaxe | 110 | 1 |
| 102 | fishing_pole | Fishing Pole | 80 | 1 |
| 103 | smith_hammer | Smith's Hammer | 80 | 1 |
| 104 | saw | Saw | 20 | 1 |
| 200 | backpack | Backpack | 30 | 1 |
| 201 | bag | Bag | 20 | 1 |
| 202 | pouch | Pouch | 10 | 1 |
| 300 | dagger | Dagger | 10 | 1 |
| 301 | longsword | Longsword | 70 | 1 |
| 302 | mace | Mace | 140 | 1 |
| 303 | quarterstaff | Quarterstaff | 40 | 1 |
| 304 | bow | Bow | 60 | 1 |
| 305 | halberd | Halberd | 160 | 1 |
| 350 | buckler | Buckler | 50 | 1 |
| 351 | heater_shield | Heater Shield | 80 | 1 |
| 500 | shirt | Shirt | 10 | 1 |
| 501 | long_pants | Long Pants | 20 | 1 |
| 502 | shoes | Shoes | 20 | 1 |
| 503 | boots | Boots | 30 | 1 |
| 504 | tunic | Tunic | 50 | 1 |
| 505 | robe | Robe | 30 | 1 |
| 506 | skirt | Skirt | 40 | 1 |
| 507 | cloak | Cloak | 50 | 1 |
| 508 | half_apron | Half Apron | 10 | 1 |
| 509 | wizards_hat | Wizard's Hat | 10 | 1 |
| 550 | gold_ring | Gold Ring | 1 | 1 |
| 551 | gold_bracelet | Gold Bracelet | 1 | 1 |
| 552 | gold_necklace | Gold Necklace | 1 | 1 |
| 553 | gold_earrings | Gold Earrings | 1 | 1 |
| 700 | bones | Bones | 10 | 1 |
| 701 | fur | Fur | 10 | 1 |
| 702 | boar_tusk | Boar Tusk | 2 | 1 |
| 703 | spider_silk | Spider's Silk | 1 | 10 |
| 704 | bat_wing | Bat Wing | 1 | 10 |
| 705 | feather | Feather | 1 | 10 |
| 706 | grave_dust | Grave Dust | 1 | 10 |
| 707 | troll_fat | Troll Fat | 10 | 1 |
| 708 | lizard_scales | Lizard Scales | 1 | 5 |
| 709 | drake_scale | Drake Scale | 2 | 1 |
| 710 | dragon_scale | Dragon Scale | 3 | 1 |
| 711 | dragons_blood | Dragon's Blood | 1 | 10 |
| 712 | wisp_essence | Wisp Essence | 1 | 10 |
| 713 | treant_bark | Treant Bark | 20 | 1 |
| 714 | fire_essence | Fire Essence | 1 | 10 |
| 715 | ectoplasm | Ectoplasm | 1 | 10 |
| 716 | amber | Amber | 1 | 1 |
| 717 | sapphire | Sapphire | 1 | 1 |
| 718 | ruby | Ruby | 1 | 1 |
| 719 | diamond | Diamond | 1 | 1 |
| 720 | orcish_idol | Orcish Idol | 30 | 1 |
| 721 | giant_tooth | Frost Giant's Tooth | 10 | 1 |
| 750 | spellbook | Spellbook | 30 | 1 |
| 751 | scroll_magic_arrow | Magic Arrow Scroll | 1 | 1 |
| 752 | scroll_heal | Heal Scroll | 1 | 1 |
| 753 | scroll_fireball | Fireball Scroll | 1 | 1 |
| 754 | scroll_wall_of_stone | Wall of Stone Scroll | 1 | 1 |
| 755 | scroll_lightning | Lightning Scroll | 1 | 1 |
| 756 | scroll_explosion | Explosion Scroll | 1 | 1 |
| 757 | blank_scroll | Blank Scroll | 1 | 1 |
| 758 | black_pearl | Black Pearl | 1 | 1 |
| 759 | blood_moss | Blood Moss | 1 | 1 |
| 760 | garlic | Garlic | 1 | 1 |
| 761 | ginseng | Ginseng | 1 | 1 |
| 762 | mandrake_root | Mandrake Root | 1 | 1 |
| 763 | nightshade | Nightshade | 1 | 1 |
| 765 | sulfurous_ash | Sulfurous Ash | 1 | 1 |
| 766 | empty_bottle | Empty Bottle | 5 | 1 |
| 767 | heal_potion | Heal Potion | 5 | 1 |
| 768 | refresh_potion | Refresh Potion | 5 | 1 |
| 769 | strength_potion | Strength Potion | 5 | 1 |
| 770 | agility_potion | Agility Potion | 5 | 1 |
| 771 | copper_ore | Copper Ore | 120 | 1 |
| 772 | copper_ingot | Copper Ingot | 1 | 1 |
| 773 | verite_ore | Verite Ore | 120 | 1 |
| 774 | verite_ingot | Verite Ingot | 1 | 1 |
| 775 | oak_log | Oak Log | 20 | 1 |
| 776 | oak_board | Oak Board | 10 | 1 |
| 777 | yew_log | Yew Log | 20 | 1 |
| 778 | yew_board | Yew Board | 10 | 1 |
| 779 | flax | Flax | 5 | 1 |
| 780 | cloth | Cloth | 1 | 1 |
| 781 | leather | Leather | 1 | 1 |
| 782 | wheat | Wheat | 5 | 1 |
| 783 | flour | Flour | 5 | 1 |
| 785 | shaft | Shaft | 1 | 10 |
| 786 | arrow | Arrow | 1 | 10 |
| 787 | beam | Beam | 50 | 1 |
| 788 | nails | Nails | 1 | 20 |
| 789 | bandage | Bandage | 1 | 10 |
| 790 | meat_pie | Meat Pie | 10 | 1 |
| 791 | sewing_kit | Sewing Kit | 20 | 1 |
| 792 | fletching_kit | Fletcher's Tools | 20 | 1 |
| 793 | scribes_pen | Scribe's Pen | 5 | 1 |
| 794 | mortar_pestle | Mortar and Pestle | 10 | 1 |
| 800 | wooden_chest | Wooden Chest | 150 | 1 |
| 801 | wooden_box | Wooden Box | 100 | 1 |
| 802 | stool | Stool | 50 | 1 |
| 803 | table | Table | 200 | 1 |
| 810 | broadsword | Broadsword | 60 | 1 |
| 811 | katana | Katana | 60 | 1 |
| 812 | kryss | Kryss | 20 | 1 |
| 813 | spear | Spear | 70 | 1 |
| 814 | war_axe | War Axe | 80 | 1 |
| 815 | war_hammer | War Hammer | 100 | 1 |
| 816 | club | Club | 90 | 1 |
| 820 | wooden_shield | Wooden Shield | 50 | 1 |
| 821 | metal_shield | Metal Shield | 60 | 1 |
| 822 | kite_shield | Kite Shield | 70 | 1 |
| 850 | dull_copper_ore | Dull Copper Ore | 120 | 1 |
| 851 | dull_copper_ingot | Dull Copper Ingot | 1 | 1 |
| 852 | shadow_iron_ore | Shadow Iron Ore | 120 | 1 |
| 853 | shadow_iron_ingot | Shadow Iron Ingot | 1 | 1 |
| 854 | bronze_ore | Bronze Ore | 120 | 1 |
| 855 | bronze_ingot | Bronze Ingot | 1 | 1 |
| 856 | agapite_ore | Agapite Ore | 120 | 1 |
| 857 | agapite_ingot | Agapite Ingot | 1 | 1 |
| 858 | valorite_ore | Valorite Ore | 120 | 1 |
| 859 | valorite_ingot | Valorite Ingot | 1 | 1 |
| 860 | ash_log | Ash Log | 20 | 1 |
| 861 | ash_board | Ash Board | 10 | 1 |
| 862 | frostwood_log | Frostwood Log | 20 | 1 |
| 863 | frostwood_board | Frostwood Board | 10 | 1 |
| 864 | heartwood_log | Heartwood Log | 20 | 1 |
| 865 | heartwood_board | Heartwood Board | 10 | 1 |
| 866 | bloodwood_log | Bloodwood Log | 20 | 1 |
| 867 | bloodwood_board | Bloodwood Board | 10 | 1 |
| 868 | spined_leather | Spined Leather | 1 | 1 |
| 869 | horned_hide | Horned Hide | 15 | 1 |
| 870 | horned_leather | Horned Leather | 1 | 1 |
| 871 | barbed_leather | Barbed Leather | 1 | 1 |
| 872 | dragonscale | Dragonscale Leather | 1 | 1 |
| 873 | dyed_linen | Dyed Linen | 1 | 1 |
| 874 | silk_cloth | Spider Silk Cloth | 1 | 1 |
| 875 | ghostweave | Ghostweave | 1 | 1 |
| 876 | starweave | Starweave | 1 | 1 |
| 877 | quartz | Quartz | 1 | 1 |
| 878 | star_sapphire | Star Sapphire | 1 | 1 |
| 879 | tanning_oil | Tanning Oil | 5 | 1 |
| 880 | design_scroll | Design Scroll | 1 | 1 |
| 881 | tinker_tools | Tinker's Tools | 20 | 1 |
| 900 | building_permit | Building Permit | 1 | 1 |
| 901 | chair | Chair | 50 | 1 |
| 903 | bench | Bench | 60 | 1 |
| 905 | round_table | Round Table | 100 | 1 |
| 906 | writing_table | Writing Table | 90 | 1 |
| 907 | bed | Bed | 200 | 1 |
| 908 | bookcase | Bookcase | 150 | 1 |
| 909 | armoire | Armoire | 200 | 1 |
| 910 | dresser | Dresser | 150 | 1 |
| 912 | candelabra | Candelabra | 40 | 1 |
| 913 | rug | Rug | 30 | 1 |
| 914 | barrel | Barrel | 60 | 1 |
Recipes
| id | key | inputs | output | skill (min) |
|---|
| 1 | boards | 1 log | 2 board | carpentry (0) |
| 2 | iron_ingot | 2 iron_ore | 1 iron_ingot | mining (0) |
| 3 | hatchet | 1 board + 2 iron_ingot | 1 hatchet | blacksmithy (0) |
| 4 | pickaxe | 1 board + 3 iron_ingot | 1 pickaxe | blacksmithy (0) |
| 5 | gold_ingot | 2 gold_ore | 1 gold_ingot | mining (400) |
| 6 | fishing_pole | 2 board | 1 fishing_pole | carpentry (0) |
| 7 | smith_hammer | 1 board + 2 iron_ingot | 1 smith_hammer | blacksmithy (0) |
| 8 | saw | 1 board + 2 iron_ingot | 1 saw | blacksmithy (0) |
| 9 | cooked_fish | 1 raw_fish | 1 cooked_fish | cooking (0) |
| 10 | cooked_meat | 1 raw_meat | 1 cooked_meat | cooking (0) |
| 11 | copper_ingot | 2 copper_ore | 1 copper_ingot | mining (400) |
| 12 | verite_ingot | 2 verite_ore | 1 verite_ingot | mining (600) |
| 13 | oak_boards | 1 oak_log | 2 oak_board | carpentry (200) |
| 14 | yew_boards | 1 yew_log | 2 yew_board | carpentry (600) |
| 26 | metal_shield | 14 iron_ingot | 1 metal_shield | blacksmithy (200) |
| 42 | nails | 1 iron_ingot | 20 nails | blacksmithy (0) |
| 43 | sewing_kit | 2 iron_ingot | 1 sewing_kit | blacksmithy (0) |
| 44 | scribes_pen | 1 board + 1 feather | 1 scribes_pen | carpentry (0) |
| 45 | fletching_kit | 2 board + 1 iron_ingot | 1 fletching_kit | carpentry (0) |
| 46 | mortar_pestle | 1 board + 1 stone | 1 mortar_pestle | carpentry (0) |
| 47 | beam | 4 board | 1 beam | carpentry (100) |
| 50 | wooden_shield | 9 board | 1 wooden_shield | carpentry (100) |
| 51 | wooden_box | 10 board + 5 nails | 1 wooden_box | carpentry (200) |
| 52 | wooden_chest | 15 board + 10 nails | 1 wooden_chest | carpentry (400) |
| 53 | stool | 9 board | 1 stool | carpentry (100) |
| 54 | table | 17 board + 10 nails | 1 table | carpentry (450) |
| 55 | shafts | 1 board | 8 shaft | fletching (0) |
| 56 | arrows | 1 shaft + 1 feather | 1 arrow | fletching (0) |
| 58 | leather | 1 hide | 1 leather | tailoring (0) |
| 59 | cloth | 2 flax | 1 cloth | tailoring (0) |
| 60 | bandages | 1 cloth | 2 bandage | tailoring (0) |
| 61 | shirt | 8 cloth | 1 shirt | tailoring (0) |
| 62 | long_pants | 8 cloth | 1 long_pants | tailoring (50) |
| 63 | tunic | 8 cloth | 1 tunic | tailoring (100) |
| 64 | skirt | 10 cloth | 1 skirt | tailoring (100) |
| 65 | robe | 16 cloth | 1 robe | tailoring (200) |
| 66 | cloak | 14 cloth | 1 cloak | tailoring (250) |
| 67 | half_apron | 6 cloth | 1 half_apron | tailoring (50) |
| 68 | wizards_hat | 15 cloth | 1 wizards_hat | tailoring (300) |
| 69 | bag | 2 leather | 1 bag | tailoring (0) |
| 70 | pouch | 1 leather | 1 pouch | tailoring (0) |
| 71 | backpack | 4 leather | 1 backpack | tailoring (100) |
| 72 | shoes | 5 leather | 1 shoes | tailoring (0) |
| 73 | boots | 8 leather | 1 boots | tailoring (200) |
| 85 | heal_potion | 1 ginseng + 1 empty_bottle | 1 heal_potion | alchemy (0) |
| 86 | refresh_potion | 1 black_pearl + 1 empty_bottle | 1 refresh_potion | alchemy (0) |
| 87 | agility_potion | 1 blood_moss + 1 empty_bottle | 1 agility_potion | alchemy (150) |
| 88 | strength_potion | 2 mandrake_root + 1 empty_bottle | 1 strength_potion | alchemy (250) |
| 89 | blank_scroll | 1 flax | 2 blank_scroll | inscription (0) |
| 90 | scroll_magic_arrow | 1 blank_scroll + 1 sulfurous_ash | 1 scroll_magic_arrow | inscription (0) |
| 91 | scroll_heal | 1 blank_scroll + 1 garlic + 1 ginseng + 1 spider_silk | 1 scroll_heal | inscription (100) |
| 92 | scroll_fireball | 1 blank_scroll + 1 black_pearl | 1 scroll_fireball | inscription (250) |
| 93 | scroll_wall_of_stone | 1 blank_scroll + 1 blood_moss + 1 garlic | 1 scroll_wall_of_stone | inscription (250) |
| 94 | scroll_lightning | 1 blank_scroll + 1 mandrake_root + 1 sulfurous_ash | 1 scroll_lightning | inscription (400) |
| 95 | scroll_explosion | 1 blank_scroll + 1 blood_moss + 1 mandrake_root | 1 scroll_explosion | inscription (650) |
| 96 | spellbook | 10 blank_scroll + 2 leather | 1 spellbook | inscription (200) |
| 97 | flour | 2 wheat | 1 flour | cooking (0) |
| 98 | bread | 1 flour | 1 bread | cooking (0) |
| 99 | meat_pie | 1 flour + 1 raw_meat | 1 meat_pie | cooking (200) |
| 130 | chair | 6 board | 1 chair | carpentry (200) |
| 131 | bench | 8 board | 1 bench | carpentry (200) |
| 132 | round_table | 14 board | 1 round_table | carpentry (400) |
| 133 | writing_table | 12 board + 1 iron_ingot | 1 writing_table | carpentry (450) |
| 134 | bed | 18 board + 4 hide | 1 bed | carpentry (500) |
| 135 | bookcase | 16 board | 1 bookcase | carpentry (500) |
| 136 | armoire | 20 board + 2 iron_ingot | 1 armoire | carpentry (600) |
| 137 | dresser | 14 board + 1 iron_ingot | 1 dresser | carpentry (500) |
| 138 | barrel | 10 board + 2 iron_ingot | 1 barrel | carpentry (300) |
| 139 | candelabra | 4 iron_ingot | 1 candelabra | blacksmithy (300) |
| 140 | rug | 4 hide | 1 rug | tailoring (200) |
| 141 | dull_copper_ingot | 2 dull_copper_ore | 1 dull_copper_ingot | mining (200) |
| 142 | shadow_iron_ingot | 2 shadow_iron_ore | 1 shadow_iron_ingot | mining (200) |
| 143 | bronze_ingot | 2 bronze_ore | 1 bronze_ingot | mining (400) |
| 144 | agapite_ingot | 2 agapite_ore | 1 agapite_ingot | mining (600) |
| 145 | valorite_ingot | 2 valorite_ore | 1 valorite_ingot | mining (800) |
| 146 | ash_boards | 1 ash_log | 2 ash_board | carpentry (400) |
| 147 | frostwood_boards | 1 frostwood_log | 2 frostwood_board | carpentry (600) |
| 148 | heartwood_boards | 1 heartwood_log | 2 heartwood_board | carpentry (800) |
| 149 | bloodwood_boards | 1 bloodwood_log | 2 bloodwood_board | carpentry (800) |
| 150 | spined_leather | 1 fur | 1 spined_leather | tailoring (200) |
| 151 | horned_leather | 1 horned_hide | 1 horned_leather | tailoring (400) |
| 152 | barbed_leather | 2 lizard_scales | 1 barbed_leather | tailoring (600) |
| 153 | dragonscale | 1 drake_scale | 1 dragonscale | tailoring (800) |
| 154 | dragonscale_great | 1 dragon_scale | 2 dragonscale | tailoring (800) |
| 155 | dyed_linen | 1 cloth + 1 nightshade | 1 dyed_linen | tailoring (200) |
| 156 | silk_cloth | 4 spider_silk | 1 silk_cloth | tailoring (400) |
| 157 | ghostweave | 1 cloth + 2 ectoplasm | 1 ghostweave | tailoring (600) |
| 158 | starweave | 1 cloth + 2 wisp_essence | 1 starweave | tailoring (800) |
| 159 | tanning_oil | 2 raw_fish + 1 empty_bottle | 2 tanning_oil | alchemy (0) |
| 160 | tinker_tools | 2 iron_ingot | 1 tinker_tools | blacksmithy (0) |
| 161 | rune_research | 10 blank_scroll + 1 sapphire | 1 design_scroll | inscription (400) |
| 162 | mana_potion | 1 nightshade + 1 empty_bottle | 1 mana_potion | alchemy (100) |
| 163 | cure_potion | 1 garlic + 1 empty_bottle | 1 cure_potion | alchemy (150) |
| 164 | fire_resist_potion | 1 sulfurous_ash + 1 blood_moss + 1 empty_bottle | 1 fire_resist_potion | alchemy (300) |
| 165 | invisibility_potion | 2 nightshade + 1 bat_wing + 1 empty_bottle | 1 invisibility_potion | alchemy (500) |
| 166 | haste_potion | 2 blood_moss + 2 feather + 1 empty_bottle | 1 haste_potion | alchemy (400) |
| 167 | oil_flask | 2 raw_fish + 1 empty_bottle | 1 oil_flask | alchemy (200) |
| 168 | frost_flask | 1 black_pearl + 1 nightshade + 1 empty_bottle | 1 frost_flask | alchemy (300) |
| 169 | fish_stew | 2 raw_fish + 1 garlic | 1 fish_stew | cooking (200) |
| 170 | roast_feast | 4 raw_meat + 1 bread + 1 garlic | 1 roast_feast | cooking (400) |
Skills
Skill keys (the number is UO's skill id):
alchemy 0, anatomy 1, animal_lore 2, item_identification 3, arms_lore 4, parrying 5, begging 6, blacksmithy 7, fletching 8, peacemaking 9, camping 10, carpentry 11, cartography 12, cooking 13, detecting_hidden 14, discordance 15, evaluating_intelligence 16, healing 17, fishing 18, forensic_evaluation 19, herding 20, hiding 21, provocation 22, inscription 23, lockpicking 24, magery 25, resisting_spells 26, snooping 28, musicianship 29, poisoning 30, archery 31, spirit_speak 32, stealing 33, tailoring 34, animal_taming 35, taste_identification 36, tinkering 37, tracking 38, veterinary 39, melee 40, lumberjacking 44, mining 45, meditation 46, stealth 47, remove_trap 48
Equipment slots
main_hand, off_hand, head, body, neck, hands, arms, legs, feet, shirt, pants, tunic, robe, skirt, cloak, waist, ring, bracelet, earrings, backpack
Versions
- 3 (#121): the economy — harvesting, crafting, eating, markets, plunder, Aquais, corpses; the private sheet.
- 2 (#87): snapshots and deltas of the area of interest, resume tokens, combat orders and events.
- 1: the first protocol (login, walk, look, chat, on-chain gather/craft).
Welcome.protocol says which version the server speaks. New fields and message kinds may appear within a version; a field is never removed or changes meaning without a version bump.