Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

World

World data describes the current map and the objects this client can see. It is a client-sized view of the world, not a permanent list of everything on the map.

UseRoute or events
Read map and self positionGET /clients/{client}/status
Read visible objectsGET /clients/{client}/objects
Read one cached visible player by nameGET /clients/{client}/players/{player}
Refresh one visible playerPOST /clients/{client}/players/{player}/inspect
Watch objects and visualsWorld object events

Map and position

The current map is part of:

curl "http://127.0.0.1:2626/clients/ZiLo/status"

It includes the map ID, available name, zero-based x/y coordinates, width, and height.

Ordinary movement acknowledgements update the character’s absolute x/y position. A refresh or server correction can also replace it with an authoritative position.

A map change arrives in two parts. The client first receives the new map identity and size, then receives the character’s position on that map. daRPC holds the first part until the position arrives and publishes both together in one location.changed event. It does not expose a new map with coordinates left over from the previous map. The stream publishes location.changed first, then one disappearance event for each object retained from the previous view.

Visible objects

curl "http://127.0.0.1:2626/clients/ZiLo/objects"

The response can contain four object kinds:

KindAvailable data
playerID, optional name, x/y, direction, is_hidden, is_solid, optional visual, and optional inspected profile
monsterID, optional sprite, x/y, direction, and is_solid
mundaneID, optional name and sprite, x/y, direction, and is_solid
itemID, sprite, dye_color, x/y, per-tile z_index, and is_solid

Mundane is the Dark Ages name for a non-player character (NPC). The npc filter remains accepted as an alias. Item sprite values have the client’s internal item classification flag removed.

Players and mundanes are always solid, and items are never solid. Monsters use the draw packet’s creature type: type 0 is solid and type 1 is passable.

Ground-item z_index is local to one tile. Zero is the bottom item, and higher values are drawn above it.

WorldObjects {
    observation: ObservationMetadata,
    objects: WorldObject[]?,
}

WorldObject =
    Player { id, name?, x, y, direction, is_hidden, is_solid, visual?, profile? }
  | Monster { id, sprite?, x, y, direction, is_solid }
  | Mundane { id, sprite?, name?, x, y, direction, is_solid }
  | Item { id, sprite, dye_color, x, y, z_index, is_solid }

Filter the result with a comma-separated types query:

curl "http://127.0.0.1:2626/clients/ZiLo/objects?types=player,mundane,monster"

Without types, the route returns every observed kind. An unknown type or malformed filter returns 400 Bad Request.

Player visuals

Opcode 0x33 supplies a visual block for each drawn player. A normal player uses form: "human" and exposes every sprite used by the client renderer: head, body, arms, boots, pants, armor, weapon, shield, overcoat, and three accessories. hair_color and skin_color are top-level visual fields, alongside the boots, pants, overcoat, and accessory dye colors. The block also includes gender, rest position, face shape, and translucency flag used by the renderer.

HumanVisual {
    form: "human",
    gender,
    head_sprite, body_sprite, arms_sprite, boots_sprite, pants_sprite,
    armor_sprite, weapon_sprite, shield_sprite, overcoat_sprite,
    accessory1_sprite, accessory2_sprite, accessory3_sprite,
    hair_color, skin_color, boots_color, pants_color, overcoat_color,
    accessory1_color, accessory2_color, accessory3_color,
    rest_position, face_shape, is_translucent,
}

CreatureVisual {
    form: "creature",
    sprite, color, boots_color, pants_color,
}

A transformed player uses form: "creature" and exposes the creature sprite plus the three color bytes carried by that packet layout. Creature-form draws are not treated as hidden. visual: null means the player was synthesized from partial retained state before a complete packet or memory appearance was available; no sprite or color defaults are invented.

Player profiles

When opcode 0x33 draws a human, daRPC automatically requests that player’s object information. The successful response fills profile with nation, title, guild rank, display class, guild, user state, is_group_open, worn equipment, legend marks, and inspected_tick_ms. profile: null means the player is visible but the inspection has not completed.

is_hidden is true when the draw has a zero body sprite or the packet marks the player translucent. Hidden draws can zero other fields, so daRPC merges them by entity ID and retains the last observed name plus inspected profile. Monster-form draws use the creature visual layout and are not classified as hidden merely because they do not contain the normal human appearance block.

The profile equipment uses the same slot, sprite, and dye-color names as local equipment. Other-player packets do not provide item names or durability, so those fields are not invented. display_class is separate from the base class; for example, it can be Summoner for a Wizard.

Automatic requests do not open the game’s other-player information pane. A normal player click still opens it and also refreshes daRPC’s cache. Leaving view removes the player object, and the next 0x33 redraw starts a fresh inspection.

Read one visible player’s retained object and latest profile without sending a packet to the game server:

curl "http://127.0.0.1:2626/clients/ZiLo/players/Eidolon"

The cached lookup is case-insensitive and returns the same WorldObject shape as the objects collection. It can return profile: null while the automatic inspection is pending. It searches only the current visible-object set; daRPC does not retain a historical profile after that player leaves view.

Use a manual refresh for changes that do not redraw the player, such as a belt or necklace change:

curl -X POST "http://127.0.0.1:2626/clients/ZiLo/players/Eidolon/inspect"

Both player-name routes use the same case-insensitive visible-player lookup. Missing names return 404 and ambiguous names return 409. Only the refresh route can return 504 when the game server does not respond.

The initial baseline walks the client’s retained object collection. A creature name or numeric sprite can be unavailable after a late attach when the client no longer retains the original draw details. Pressing the normal client refresh key asks the server to redraw nearby objects. daRPC reconciles those packets against the retained visible-object set. Numeric creature sprites learned from the redraw are retained through the follow-up snapshot.

Object events

The complete object and visual payload structures are in World object events.

Players, monsters, and Mundanes publish the same core object actions. Players also publish two events for identity and profile changes:

ObjectEvents
Playerplayer.appeared, player.replaced, player.inspected, player.disappeared, player.moved, player.direction_changed
Monstermonster.appeared, monster.disappeared, monster.moved, monster.direction_changed
Mundanemundane.appeared, mundane.disappeared, mundane.moved, mundane.direction_changed

player.replaced is emitted instead of player.appeared when a newly drawn player has the same name as one or more retained players but a different object ID. Its payload contains every stale player snapshot in previous and the authoritative replacement in current.

Ground items use:

item.appeared
item.disappeared
item.moved

Each object event carries the complete public object after the change. Treat appeared, moved, and direction-changed events as upserts by stable object ID. A redraw can publish an appeared event with replacement fields for an ID that is already retained. Disappearance carries the last retained object and removes that ID. player.replaced removes every ID in previous and upserts current; player.inspected upserts player when profile state is retained.

Map changes remove the previous view through ordinary disappearance events. Consumers update the map on location.changed, then apply the following object events in delivery order. They do not clear the collection in response to the location event or a separate world-boundary event.

An F5 or POST /clients/{client}/resync refresh also uses normal lifecycle events. daRPC retains the current set while redraw packets arrive, suppresses unchanged stable IDs, publishes appearances for new IDs, and publishes disappearances for retained IDs that do not return. Reconciliation completes when RefreshUserOK follows redraw activity or when the one-second refresh window closes. No authoritative position or redraw response leaves the last-known view intact. client.resync reports only that the request was sent. The matching client.resync_completed is ordered after the lifecycle changes and closes the refresh window whether or not RefreshUserOK arrived. See Refresh and resynchronization for the complete behavior. A concurrent GET /objects returns the retained, progressively reconciled view rather than an intentionally empty intermediate collection.

The server normally sends draw events for objects entering view but may not send an explicit removal when the local character simply walks out of range. After accepted self movement, daRPC culls retained objects outside the client-sized view and reports their disappearance. The collection is still this client’s latest observation rather than an authoritative map population.

Entity visual events

The stream also reports temporary visuals for visible players, monsters, and Mundanes:

player.animated              monster.animated              mundane.animated
player.effect                monster.effect                mundane.effect
player.damaged               monster.damaged               mundane.damaged

An *.animated payload contains the complete entity, the client animation number, and initial_duration_ms. That timer is the initial value sent by the server, not a promise that the animation remains visible for exactly that long.

An *.effect payload contains the entity and the one-based effect number sent by the server. It can also contain a source entity and a frame interval when the packet supplies them. Effects drawn only at ground coordinates are not published yet.

An *.damaged payload contains the entity and health_percent, the server’s 0 through 100 value used for the temporary health meter. It is a percentage, not the amount of damage dealt.