Wrayth protocol: Difference between revisions

The official GemStone IV encyclopedia.
Jump to navigation Jump to search
(Added pushBold, popBold, pushStream, popStream, clearStream)
(updates and expanded info)
 
(14 intermediate revisions by 6 users not shown)
Line 1: Line 1:
==Wrayth protocol==
The '''StormFront protocol''' is the XML protocol used to pass information between the game and the [[StormFront]] front end.
The '''Wrayth protocol''' is the XML protocol used to pass information between the GemStone IV game server and front-end clients. It is utilized by the official Wrayth client and unofficial frontends.


== Tags ==
==Protocol model==
The feed is '''interleaved text and markup''', not a document. Plain prose flows continuously, and tags either ''style'' the surrounding text, ''redirect'' it to a named stream, or carry ''structured state'' (vitals, room data, window declarations). A parser must handle text and tags on the same line.


* '''Streams are named text channels.''' Text between <code>pushStream</code>/<code>popStream</code> (or inside a paired <code>&lt;stream&gt;</code>) belongs to that channel; everything else belongs to <code>main</code>. Examples: <code>thoughts</code>, <code>speech</code>, <code>bounty</code>, <code>loot</code>, <code>inv</code>.
{| {{prettytable}}
* '''Dialogs are declared control surfaces.''' <code>dialogData</code> ships positioned controls (bars, labels, buttons) that the client lays out with an anchor system. Updates are '''incremental''' &mdash; a re-sent <code>dialogData</code> carries only the controls that changed, merged by control <code>id</code>.
! Tag name
* '''Ids are identity.''' Streams, dialogs, containers, creatures (<code>exist</code> numbers), and rooms (<code>nav rm</code>) are all keyed by id. Third-party tools (such as Lich scripts) may inject their own dialogs and streams through the same grammar, indistinguishable from Simutronics traffic.
! Description
* '''Timers are absolute.''' <code>roundTime</code>/<code>castTime</code> <code>value</code> attributes are epoch '''end-times''', not durations. The remaining span is computed as <code>value &minus; prompt time</code> (see [[#Character State Elements|Character State]]).
! Parameters
* '''Quoting is inconsistent by design.''' The same tag may arrive with single or double quotes depending on which server system emitted it, so parsers must accept both.
! Example
! Contents
! Notes
|-
| <a>
| Displays a link that is clickable to obtain a menu of interaction options
|
*exist - A unique identifier for the object, for use in menus
*noun - The noun of the object, for use in menus
| a <a exist="-26211" noun="door">heavy ironwood door</a>
| Displays the contents as a clickable link
| Does not suppress following newlines
|-
| <clearStream>
| Removes all text within the specified window
|
*id - The identifier for the window to remove text from
| <clearStream id="spellfront"/>
| No contents
|
|-
| <left>
<right>
| Changes the text of the left and right hand panels
|
*exist - Same as in <a>
*noun - Same as in <a>
| <right exist="674831" noun="dagger">dagger</right>
| Sends the contents to the left or right hand panel
|
|-
| <pushBold>
<popBold>
| Makes text bold until a matching <popBold> tag
|
None
| <pushBold/>You have unread news articles.<popBold/>
| No contents
| Does not suppress following newlines
May nest
|-
| <pushStream>
<popStream>
| Sends text to specified window if it exists (story window instead) until next <popStream> tag
|
*id - The identifier of the window to send text to
| <pushStream id="logons"/> * <a exist="-10374531" noun="Ildran">Ildran</a> joins the adventure.<br><popStream/>
| No contents
| May nest
|-
| <spell>
| Changes the text of the prepared spell panel
|
*exist - Same as in <a>
| <spell exist='spell'>Spirit Warding I</spell>
| Sends the contents to the prepared spell panel
|
|}


==Core System Elements==
== Special handling ==
{| class="wikitable"
* Tags followed by newlines suppress the newline output to the screen except where noted above.
|-
! Element !! Description !! Key Attributes
|-
| <code>mode</code> || Game mode indicator || id (GAME, LOGIN, CMGR)
|-
| <code>playerID</code> || Player identifier || id (numeric)
|-
| <code>settingsInfo</code> || Announces the server-stored client-settings blob || client, major, crc, instance
|-
| <code>settings</code> || The settings download itself, chunked by <code>major</code> section number (requested by the FE when its cached copy's crc mismatches) || client, major
|-
| <code>app</code> || Application metadata for window titling || char, game, title
|-
| <code>endSetup</code> || Marks end of initial setup; game text follows || (none)
|-
| <code>updateverbs</code> || Tells the FE to refresh its verb list for the game system || default
|-
| <code>cmdtimestamp</code> || Version stamp for the <code>cmdlist</code> command dictionary || data
|-
| <code>LaunchURL</code> || Asks the FE to open a play.net URL (payment, character manager, re-auth) || src
|-
| <code>FEStart</code> || Front-end launch marker (written by the FE side) || name, time
|}

===Command dictionary (cmdlist / cli)===
At login the server sends the point-and-click command dictionary: <code>&lt;cmdlist&gt;</code> containing many <code>&lt;cli&gt;</code> entries. Each <code>cli</code> maps a coordinate id to a menu label and a command template. In the template, <code>@</code> substitutes the object's noun and <code>#</code> substitutes its exist id. Context menus (see [[#Menu System|Menu System]]) reference these coordinates later &mdash; the menu response itself carries no labels.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>cmdlist</code> || Command-dictionary envelope || (none)
|-
| <code>cli</code> || One coordinate &rarr; label + command-template entry || coord, menu, command, menu_cat
|}

===Examples===
<pre>
<mode id="GAME"/>
<playerID id='XXXXXX'/>
<settingsInfo client='1.0.1.28' major='19313' crc='3508957330' instance='GS4'/>
<cmdlist>
<cli coord="2524,1703" menu="tackle @" command="tackle #" menu_cat="6"/>
</cmdlist>
<cmdtimestamp data='1767482628.1.1.1'/>
<endSetup/><app char="Nisugi" game="Prime" title="GemStone IV: Nisugi [Prime]"/>
<updateverbs default="GS4"/>
</pre>

==Stream Management==
Streams route text output to specific UI windows.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>streamWindow</code> || UI window definition / re-title || id, title, subtitle, location, target, ifClosed, styleIfClosed, resident, save, scroll, timestamp, nameFilterOption, appearance
|-
| <code>clearStream</code> || Clear stream contents || id, ifClosed
|-
| <code>pushStream</code> || Push following text to stream || id
|-
| <code>popStream</code> || Pop stream context (back to main) || id
|-
| <code>stream</code> || Inline (paired) redirect: <code>&lt;stream id&gt;&hellip;&lt;/stream&gt;</code> || id
|-
| <code>exposeStream</code> || Bring a stream window to front on demand || id
|}

The <code>streamWindow</code> tag fires on every room move for the <code>room</code>/<code>main</code> windows (carrying the room name as <code>subtitle</code>) and at login for feature windows. Notable attributes: <code>timestamp='on'</code> requests per-window timestamps, and <code>nameFilterOption</code> advertises a name filter (used by <code>logons</code>/<code>death</code>).

===Stream Window IDs===
{| class="wikitable"
|-
! Stream ID !! Title !! Purpose
|-
| main || Story || Main game output
|-
| room || Room || Room description display
|-
| inv || My Inventory || Worn items
|-
| Spells || Spells || Available spells list
|-
| familiar || Familiar || Familiar messages
|-
| thoughts || Thoughts || ESP/telepathy
|-
| logons || Arrivals || Player arrivals
|-
| death || Deaths || Death notices
|-
| speech || Speech || Speech window
|-
| ambients || Ambients || Ambient messages
|-
| announcements || Announcements || Game announcements
|-
| bounty || Bounties || Bounty task info
|-
| society || Society Tasks || Society task info
|-
| loot || Loot || Loot window
|-
| charprofile || Character's Profile || Character profile
|-
| charsheet || Character Sheet || Character sheet
|}

===Closed-window text routing (ifClosed / styleIfClosed)===
Each stream declares what happens to its text when its window is closed, via two attributes on <code>streamWindow</code>: <code>ifClosed</code> (a destination) and <code>styleIfClosed</code> (a style applied to fallen-through text). Four behaviors result:

{| class="wikitable"
|-
! Personality !! Declaration !! Closed-window behavior !! Examples
|-
| '''Exclusive''' || <code>ifClosed</code> absent, <code>styleIfClosed</code> set || Text falls through to the main/story window, wrapped in the named style &mdash; the classic inline-thoughts look || thoughts (<code>"thought"</code>), familiar (<code>"watching"</code>)
|-
| '''Routed''' || <code>ifClosed='&lt;window&gt;'</code> || Text is sent to another window instead; chains if that one is closed too (e.g. voln &rarr; thoughts &rarr; main-as-"thought") || voln &rarr; thoughts
|-
| '''Copy''' || <code>ifClosed=''</code> || The stream is a ''duplicate'' &mdash; the server also sends the same line to main, so the closed window's copy drops harmlessly || speech; room-window content
|-
| '''Unspecified''' || neither attribute || Falls through to main unstyled || logons, death
|}

===Examples===
<pre>
<streamWindow id='room' title='Room' subtitle=" - [Icemule Trace, South Road]" location='center' target='drop' ifClosed='' resident='true'/>
<streamWindow id='inv' title='My Inventory' target='wear' ifClosed='' resident='true'/>
<streamWindow id="Spells" title="Spells" ifClosed="" resident="true" scroll="manual"/>
<streamWindow id='thoughts' title='Thoughts' styleIfClosed='thought' resident='true'/>
<clearStream id='inv' ifClosed=''/>
<pushStream id='inv'/>Your worn items are:
<popStream/>
<clearStream id="Spells"/>
</pre>

'''Stream content example (thoughts/ESP):'''
<pre>
<pushStream id="thoughts"/>You hear the faint thoughts of Nisugi echo in your mind:
"Hello everyone!"
<popStream/>
</pre>

==Component System==
Components represent dynamic room/area content.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>compDef</code> || Component definition (full replacement of a named part) || id
|-
| <code>component</code> || Component instance (incremental replacement) || id
|}

'''Component IDs:'''
* room desc - Room description
* room objs - Room objects
* room players - Players in room
* room exits - Available exits
* sprite - Player's familiar/sprite

===Examples===
<pre>
<compDef id='room players'></compDef>
<compDef id='room exits'>Obvious paths: <d>east</d>, <d>west</d></compDef>
<compDef id='sprite'></compDef>

<component id='room players'>Also here: Lord <a exist="-10939058" noun="Huras">Huras</a></component>
<component id='room players'></component>
<component id='room objs'> You also see<b> <pushBold/>a <a exist="103330" noun="resident">disheveled resident</a><popBold/></b>.</component>
</pre>

==Room and World==
A room change is a fixed sequence: <code>nav</code> announces the room id, <code>compDef</code>/<code>component</code> replace the room's parts, <code>compass</code> lists exits, <code>streamWindow</code> re-titles the Room/Story windows with the room name as <code>subtitle</code>, and <code>resource</code> selects room art.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>nav</code> || Room change; <code>rm</code> is the room's unique id (the mapper's key) || rm
|-
| <code>compass</code> || Available exits (contains <code>dir</code> elements) || (none)
|-
| <code>dir</code> || Direction indicator || value (n, s, e, w, ne, nw, se, sw, up, down, out)
|-
| <code>roommeta</code> || Room environment flags (per-room) || weather, bonfire, inside, water, sanctuary, realm, climate, terrain
|-
| <code>resource</code> || Room artwork id for FEs that show room images || picture (<code>"0"</code> = none)
|}

===Examples===
<pre>
<nav rm='12345'/>
<compass><dir value="e"/><dir value="out"/></compass>
<compass><dir value="n"/><dir value="s"/><dir value="e"/><dir value="w"/></compass>
<roommeta weather='0' inside='0' water='0' sanctuary='0' terrain='forest'/>
<resource picture="0"/>
</pre>

==Container/Inventory System==
Containers are windows too, keyed by id. <code>stow</code> is a shortcut id for the character's default worn storage container.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>container</code> || Declares a container window || id, title, location, target, resident, save
|-
| <code>exposeContainer</code> || Bring a container window to front (e.g. on OPEN) || id
|-
| <code>clearContainer</code> || Clear container contents before a re-send || id
|-
| <code>deleteContainer</code> || Remove a container window entirely (container destroyed / out of scope) || id
|-
| <code>inv</code> || Inventory item line for a container's contents || id
|}

===Examples===
'''Looking in a container:'''
<pre>
<container id='393944944' title='Chest' target='#393944944' location='right'/>
<clearContainer id="393944944"/>
<inv id='393944944'>In the <a exist="393944944" noun="chest">chest</a>:</inv>
<inv id='393944944'> <a exist="393944946" noun="coins">some silver coins</a></inv>
<inv id='393944944'> a <a exist="393944945" noun="garnet">dark red-violet garnet</a></inv>
</pre>

'''Stow container (default storage):'''
<pre>
<exposeContainer id='stow'/>
<container id='stow' title="My Cloak" target='#225766691' location='right' save='' resident='true'/>
<clearContainer id="stow"/>
<inv id='stow'>In the <a exist="225766691" noun="cloak">cloak</a>:</inv>
<inv id='stow'> a <a exist="225766734" noun="feather">nacreous disir feather</a></inv>
</pre>

==Dialog System==
Dialogs are UI panels with controls and data. A dialog's life cycle: <code>openDialog</code> declares the frame (or a bare <code>dialogData</code> arrives for a well-known id) &rarr; <code>dialogData</code> ships/updates controls incrementally &rarr; <code>exposeDialog</code> shows it on demand &rarr; <code>closeDialog</code> dismisses it. Streams mirror this with <code>streamWindow</code>/<code>exposeStream</code>.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>openDialog</code> || Create dialog window; may embed initial <code>dialogData</code> || id, type, title, location, target, height, width, resident, save, noResize, noDock
|-
| <code>dialogData</code> || Ship/update a dialog's controls, merged by control id || id ''or'' name, clear
|-
| <code>closeDialog</code> || Close a dialog window || id
|-
| <code>exposeDialog</code> || Show a hidden dialog now (user-action echo) || id
|-
| <code>dynaStream</code> || Text-content feed for a <code>streamBox</code> control inside a dialog || id
|-
| <code>clearDynaStream</code> || Clear a <code>streamBox</code>'s content || id
|}

Two quirks worth noting:
* <code>dialogData</code> may key on either <code>id=</code> '''or''' <code>name=</code> depending on the emitter.
* <code>clear='t'</code> on <code>dialogData</code> resets the dialog's controls before the new set is applied. Locations seen on <code>openDialog</code> include <code>right</code>, <code>center</code>, <code>quickBar</code>, <code>statBar</code>, and <code>detach</code>.

===Dialog IDs===
{| class="wikitable"
|-
! Dialog ID !! Purpose
|-
| combat || Combat controls (the most active dialog)
|-
| injuries || Injury display (player)
|-
| minivitals || Health/mana/stamina bars
|-
| stance || Stance indicator
|-
| expr || Experience/level info
|-
| encum || Encumbrance
|-
| Active Spells || Active spell list
|-
| Buffs || Active buffs
|-
| Debuffs || Active debuffs
|-
| Cooldowns || Ability cooldowns
|-
| mapMaster || Map controls
|-
| mapViewMain || Map view
|-
| espMasterDialog / espMasterData || ESP/telepathy thought-network panel
|-
| quick || Quick action bar (main)
|-
| quick-combat || Combat quick bar
|-
| quick-simu || Information quick bar
|-
| BetrayerPanel || Blood Points tracking
|-
| befriend || Friends & Enemies list
|-
| bank || Banking interface
|-
| bugDialogBox || Bug-report form
|-
| dlgCustomize || Customization dialog
|-
| injuries-{existID} || Target character injuries appraisal
|}

===Examples===
'''Opening and populating a dialog:'''
<pre>
<openDialog type='dynamic' id='minivitals' title='Stats' location='statBar'>
<dialogData id='minivitals'></dialogData>
</openDialog>

<openDialog type='dynamic' id='stance' title='Stance' location='right' height='50' width='190' resident='true'>
<dialogData id='stance'>
<progressBar id='pbarStance' value='100' text='defensive (100%)' top='5' left='-5' height='16' width='160' align='n' tooltip='Percent of stance contributing to defense'/>
</dialogData>
</openDialog>
</pre>

'''Updating dialog data:'''
<pre>
<dialogData id='combat'>
<progressBar id='pbarStance' value='100' text='defensive (100%)' top='51' width='130' height='16' left='0' align='n' tooltip='Percent of stance contributing to defense'/>
</dialogData>
</pre>

'''Banking dialog:'''
<pre>
<dialogData id='bank'>
<link id='depositallLnk' value='Deposit All' cmd='deposit all' align='w' top='30' left='0' height='30' width='90' echo='deposit all'/>
<link id='wealthnotesLnk' value='Check Notes' cmd='wealth notes' align='e' top='30' left='0' height='30' width='90' echo='wealth notes'/>
<closeButton id='closeMe' value='Close' cmd='' align='s' left='0' top='0' width='80'/>
</dialogData>
<exposeDialog id='bank'/>
<closeDialog id="bank"/>
</pre>

===Target Injuries Appraisal Dialog===
When you <code>appraise</code> another character, a dynamic injuries dialog opens showing their wounds:

<pre>
<openDialog type='dynamic' id='injuries-10070682' title='Dicate&apos;s Injuries' location='right'>
<dialogData id='injuries'>
<skin id='injuredSkin' name='InjuriesPanel'
controls='nsys,leftArm,rightArm,rightLeg,leftLeg,head,rightFoot,leftFoot,rightHand,leftHand,rightEye,leftEye,back,neck,chest,abdomen'/>
<closeButton id='cancel' value='Close' cmd=''/>
</dialogData>
</openDialog>
<dialogData id="injuries-10070682">
<image id="head" name="Injury1"/>
<image id="neck" name="Injury2" cmd="tend Dicate neck" tooltip="tend Dicate's neck"/>
<image id="rightArm" name="Injury3" cmd="tend Dicate right arm"/>
...
</dialogData>
</pre>

'''Key Elements:'''
* Dialog ID: injuries-{existID} where existID is the target's object ID
* Body part images with injury levels: Injury1 (minor), Injury2 (moderate), Injury3 (severe)
* Clickable cmd attributes for tending wounds
* Body parts tracked: head, neck, rightArm, leftArm, rightLeg, leftLeg, rightHand, leftHand, chest, abdomen, back, rightEye, leftEye, rightFoot, leftFoot, nsys

==UI Control Elements==
Controls appear inside <code>dialogData</code>. Every control shares the layout attributes <code>top left width height</code> (pixels; negatives allowed, and percentages are used in vitals bars) plus positioning:
* <code>align</code> &mdash; a compass value (<code>nw n ne w c e sw s se</code>) placing the control relative to the dialog edge.
* Sibling anchors <code>anchor_top</code> / <code>anchor_left</code> / <code>anchor_right</code> &mdash; position relative to another control by id. Supplying both <code>anchor_left</code> and <code>anchor_right</code> stretches the control between them.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>progressBar</code> || Value bar with optional custom text || id, value, text, customText, top, left, height, width
|-
| <code>cmdButton</code> || Command button || id, value, cmd, echo, tooltip
|-
| <code>closeButton</code> || Button that also dismisses the dialog || id, value, cmd
|-
| <code>radio</code> || Toggle-group button || id, value, text, cmd, group
|-
| <code>dropDownBox</code> || Dropdown selector; <code>%id%</code> in <code>cmd</code> substitutes the selection || id, value, cmd, content_text, content_value, tooltip
|-
| <code>label</code> || Text label; see justify note below || id, value, justify
|-
| <code>link</code> || Inline command hyperlink || id, value, cmd, echo, URL
|-
| <code>menuLink</code> || Entity-bound link row (keyed by exist) || id, value, name, exist, noun, tooltip
|-
| <code>menuImage</code> || Entity-bound image row (keyed by exist) || id, name, exist, noun, tooltip
|-
| <code>image</code> || Named image / button (also used as an anchor target) || id, name, cmd, tooltip
|-
| <code>skin</code> || Named art layer painted behind sibling controls || id, name, controls
|-
| <code>editBox</code> || Text input || id, value, maxChars, enterButton, focus
|-
| <code>upDownEditBox</code> || Numeric spinner input || id, value, maxChars, enterButton, focus
|-
| <code>streamBox</code> || Scrolling text region inside a dialog, fed by <code>dynaStream</code> || id, height, width, save
|-
| <code>sep</code> || Separator row (quickbars, menus) || (none)
|}

'''Text alignment (<code>justify</code>):''' <code>justify</code> is the only text-alignment mechanism on the wire. It decodes as low-two-bits alignment (0 = left, 1 = center, 2 = right) plus a bit-4 flag, so values 4/5/6 are "flagged" left/center/right. Text-input controls (<code>editBox</code>/<code>upDownEditBox</code>) and dropdowns support <code>%id%</code> substitution: the token is replaced with the control's current value in the submitting button's <code>cmd</code>.

===Progress Bar IDs===
{| class="wikitable"
|-
! ProgressBar ID !! Dialog !! Purpose
|-
| health || minivitals || Health bar (main)
|-
| health2 || injuries || Health bar (injuries)
|-
| mana || minivitals || Mana bar
|-
| spirit || minivitals || Spirit bar
|-
| stamina || minivitals || Stamina bar
|-
| pbarStance || combat/stance || Stance indicator
|-
| encumlevel || encum || Encumbrance level
|-
| mindState || expr || Mind state (experience absorption)
|-
| nextLvlPB || expr || Progress to next level
|}

===Examples===
'''Progress bars (vitals):'''
<pre>
<progressBar id='health' value='100' text='health 223/223' customText='t' left='0%' top='0%' width='25%' height='100%'/>
<progressBar id='mana' value='98' text='mana 426/431' left='25%' customText='t' top='0%' width='25%' height='100%'/>
<progressBar id='spirit' value='100' text='spirit 10/10' left='50%' customText='t' top='0%' width='25%' height='100%'/>
<progressBar id='stamina' value='100' text='stamina 112/112' left='75%' customText='t' top='0%' width='25%' height='100%'/>
<progressBar id='encumlevel' value='0' text='None' top='5' left='-5' align='n' width='160' height='15'/>
</pre>

'''Command buttons:'''
<pre>
<cmdButton id='cmdDefStance' value='defense' cmd='_stance defensive' tooltip='Assume a Defensive Stance' echo='stance defensive' height='20' width='55' top='70' left='0' align='nw'/>
<cmdButton id='cmdTarget' value='target' cmd='target random' tooltip='Select a Random Target' height='20' width='55' top='93' left='0' align='nw'/>
<cmdButton id='cmdAttack' value='attack' cmd='attack' height='20' width='50' left='0' top='93' tooltip='Attack Current Target' align='ne'/>
</pre>

'''Dropdown box:'''
<pre>
<dropDownBox id='dDBStance' value="defensive" cmd='_stance %dDBStance%' content_text='offensive,advance,forward,neutral,guarded,defensive' content_value='offensive,advance,forward,neutral,guarded,defensive' align='n' top='70' left='0' height='20' width='80' tooltip='Stance Selection'/>
</pre>

'''Labels:'''
<pre>
<label id='encumblurb' value='You are not encumbered enough to notice.' top='10' left='0' align='n' width='160' height='50' justify='0'/>
</pre>

'''Streaming text into a dialog (bug-report box):'''
<pre>
<dialogData id='bugDialogBox'>
<streamBox id='bugStream' height='200' width='400' save=''/>
</dialogData>
<dynaStream id='bugStream'>Please describe the problem in detail...</dynaStream>
<clearDynaStream id='bugStream'/>
</pre>

==Navigation Elements==
See [[#Room and World|Room and World]] for the <code>nav</code>, <code>compass</code>, and <code>dir</code> elements, which drive room changes and exits.

==Interactive/Link Elements==
===Hyperlink Element (<code><a></code>)===
Creates clickable links for objects, players, and coordinates. This is the single most common tag on the wire.

{| class="wikitable"
|-
! Attribute !! Description
|-
| exist || Game object ID (numeric, can be negative)
|-
| noun || Object noun/type
|-
| coord || Click coordinates (x,y format)
|-
| char || Character name (for player links)
|-
| game || Game code (GSIV, GST)
|}

===Examples===
<pre>
<a exist="225766824" noun="bandolier">leather bandolier</a>
<a exist="-11225598" noun="Ludge">Ludge</a>
<a exist="103330" noun="resident">disheveled resident</a>
<a exist="-10939058" noun="Huras">Huras</a>
</pre>

===Direct Command Link Element (<code><d></code>)===
Creates clickable command links in text. When clicked, executes the command specified in the <code>cmd</code> attribute (or the tag contents if <code>cmd</code> is omitted). Commonly used for compass directions but works for any command. A <code>&lt;d&gt;</code> may be nested inside an <code>&lt;a&gt;</code>; the outer command wins.

{| class="wikitable"
|-
! Attribute !! Description
|-
| cmd || Command to execute (optional - if omitted, executes tag contents as the command)
|}

===Examples===
'''Compass directions (no cmd attribute - executes tag contents):'''
<pre>
<compDef id='room exits'>Obvious paths: <d>east</d>, <d>west</d></compDef>
<compDef id='room exits'>Obvious exits: <d>northeast</d>, <d>out</d></compDef>
</pre>

'''Movement message (with cmd attribute):'''
<pre>
Lord <a exist="-10939058" noun="Huras">Huras</a> just went <d cmd='go west'>west</d>.
</pre>

'''Store commands:'''
<pre>
shield: <d cmd="store SHIELD clear">an <a exist="412277454" noun="buckler">old krodera buckler</a></d> (<d cmd='store set'>put in sheath</d>)
weapon: <d cmd="store WEAPON clear">a <a exist="412277485" noun="baselard">sleek gleaming steel baselard</a></d> (<d cmd='store set'>put in sheath</d>)
</pre>

==Character State Elements==
{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>indicator</code> || Boolean status icon || id, visible (y/n)
|-
| <code>spell</code> || Current prepared spell || (text content)
|-
| <code>left</code> || Left hand item || exist, noun
|-
| <code>right</code> || Right hand item || exist, noun
|-
| <code>prompt</code> || Command prompt; its epoch <code>time</code> is the client's clock reference for RT/CT math || time (epoch seconds)
|-
| <code>roundTime</code> || Action round time; <code>value</code> is the epoch '''end time''' || value (epoch seconds)
|-
| <code>castTime</code> || Spell cast time; <code>value</code> is the epoch '''end time''' || value (epoch seconds)
|-
| <code>pulse</code> || Mana pulse tick marker || mana (0/1)
|-
| <code>crtrStatus</code> || Creature status snapshot keyed by <code>exist</code> id || exist, plus flags below
|-
| <code>objectives</code> / <code>group</code> || Task/bounty system: full-refresh / delete-group actions over typed groups || id, type, action
|}

'''Timers are absolute.''' <code>roundTime</code> and <code>castTime</code> report an epoch '''end time''', not a duration. Compute the remaining span as <code>value &minus; prompt time</code>, using the most recent <code>&lt;prompt time&gt;</code> as the clock reference.

'''Creature status flags (<code>crtrStatus</code>):''' the snapshot is keyed by <code>exist</code> id (which may be negative); a missing flag or a value of "0" means inactive. Observed flags: <code>inferior</code>, <code>flying</code>, <code>hostile</code>, <code>hovering</code>, <code>ascended</code>, <code>challenging</code>, <code>sleeping</code>, <code>kneeling</code>, <code>sitting</code>, <code>prone</code>, <code>dead</code>.

===Indicator IDs===
{| class="wikitable"
|-
! Indicator ID !! Status
|-
| IconKNEELING || Kneeling
|-
| IconPRONE || Prone
|-
| IconSITTING || Sitting
|-
| IconSTANDING || Standing
|-
| IconSTUNNED || Stunned
|-
| IconHIDDEN || Hidden
|-
| IconINVISIBLE || Invisible
|-
| IconDEAD || Dead
|-
| IconWEBBED || Webbed
|-
| IconJOINED || Joined group
|}

===Examples===
'''Character state elements:'''
<pre>
<indicator id='IconSTANDING' visible='y'/>
<indicator id='IconHIDDEN' visible='y'/>
<indicator id='IconHIDDEN' visible='n'/>
<indicator id='IconSTUNNED' visible='y'/>
<indicator id='IconINVISIBLE' visible='n'/>

<spell>None</spell>
<spell>Fire Spirit (111)</spell>

<left exist="394466807" noun="bow">ghezyte long bow</left>
<left exist="" noun=""/>
<right exist="417169523" noun="arrows">glowbark arrows</right>

<prompt time="1767310975">&gt;</prompt>
<roundTime value='1767333503'/>
<castTime value='1767250287'/>
<pulse mana='1'/>
<crtrStatus exist="194485" hostile="1" inferior="1"/>
</pre>

==Text Formatting Elements==
{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>pushBold</code> || Start bold text (monster highlighting) || (none)
|-
| <code>popBold</code> || End bold text || (none)
|-
| <code>b</code> || Bold wrapper || (none)
|-
| <code>output</code> || Output formatting/font switch || class
|-
| <code>style</code> || Opens/closes a named text style; empty id closes || id (roomName, roomDesc, etc.)
|-
| <code>preset</code> || Wraps text in a user-configurable color preset || id (speech, whisper, thought)
|}

===Output Class Values===
* <code><output class="mono"/></code> - Switch to monospace font (tables/ASCII art)
* <code><output class=""/></code> - Switch back to normal font

===Examples===
'''Bold text (monster highlighting):'''
<pre>
<b> <pushBold/>a <a exist="103330" noun="resident">disheveled resident</a><popBold/></b>
</pre>

'''Room styling:'''
<pre>
<popBold/><resource picture="0"/><style id="roomName" />[Cobblestone Path]
<style id="roomDesc"/>The narrow cobblestone path winds between aged buildings...
</pre>

'''Speech/whisper preset:'''
<pre>
<preset id="whisper">(OOC) You whisper,</preset> "Rallying at 0d7d2dc1." to your group.
<preset id="whisper">(OOC) <a exist="-10070682" noun="Dicate">Dicate's</a> player whispers to the group,</preset> "Joined cluster group 0d7d2dc1."
<preset id="speech">Nisugi says,</preset> "Hello!"
</pre>

'''Font switching:'''
<pre>
<output class="mono"/>
Name Mana Known/Cast
Minor Elemental Edge (902) 1 Yes
Elemental Defense I (401) 1 Yes
<output class=""/>
</pre>

==Menu System==
Right-click context menus are coordinate lookups against the <code>cli</code> dictionary sent at login (see [[#Command dictionary (cmdlist / cli)|Command dictionary]]). When the user requests a menu (e.g. <code>_menu #exist</code>), the server answers with a <code>&lt;menu&gt;</code> containing <code>&lt;mi coord="&hellip;"/&gt;</code> items. Each <code>coord</code> is a key into the dictionary &mdash; the menu carries no labels; the client resolves coord &rarr; label + command template, substituting the object's noun/exist. <code>&lt;nomenu/&gt;</code> means nothing is available for that object.

{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>menu</code> || Context-menu response envelope || id, path, cat_list (category ordering)
|-
| <code>mi</code> || One menu item, by cli coordinate || coord
|-
| <code>nomenu</code> || No menu exists for the requested object || (none)
|-
| <code>menuImage</code> || Image in a menu (e.g. quick-bar menus) || (see UI Controls)
|}

===Examples===
<pre>
<menu id='objectMenu' path=" in #103330" cat_list="1 2 3 6">
<mi coord="2524,1703"/>
<mi coord="1180,904"/>
</menu>
<nomenu/>
</pre>

==Settings/Flags System==
{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>flag</code> || Player setting flag || id, status (on/off), desc
|}

'''Example flags:'''
* Player Log On, Player Log Off, Player Disconnect
* Room Names, Room Descriptions, Brief Room Description
* Monster Bold, Default Group Open

===Examples===
<pre>
<flag id="Player Log On" status='off' desc="Show logon messages."/>
<flag id="Player Log Off" status='off' desc="Show logoff messages."/>
<flag id="Player Disconnect" status='off' desc="Show disconnection messages."/>
<flag id="Room Names" status='on' desc="Display the name of the room in which you are located."/>
<flag id="Room Descriptions" status='on' desc="Display room descriptions."/>
<flag id="Brief Room Description" status='off' desc="Display room descriptions in shortened form."/>
<flag id="Monster Bold" status='on' desc="Highlight monster names."/>
<flag id="Default Group Open" status='on' desc="Allow others to join your group."/>
<flag id="Automatically Activate ESP Amulets" status='on' desc="Activate items for THINKing automatically."/>
<flag id="Automatically Gather Coins" status='on' desc="Gather coins when searching your kills."/>
</pre>

==Client Settings (stgupd)==
The official Wrayth client uploads its own window-state to the server so that layout survives across sessions. These blocks appear inside <code>&lt;!-- CLIENT --&gt;</code> / <code>&lt;!-- ENDCLIENT --&gt;</code> markers and travel from client to server. Unofficial frontends generally manage their own layout and need not emit or parse these, but they document Wrayth's internal window model precisely: every window is '''id + kind (dialog | stream | builtin) + zone/panel + frame + rect + open/vis + detach'''.

<pre>
<!-- CLIENT --><stgupd><panels>...</panels><!-- ENDCLIENT -->
<!-- CLIENT --><stgupd><stream>...</stream><!-- ENDCLIENT -->

<w id="combat" vis="t" frame="panel|float" location="center"
panel="Left" open="t" height="323" width="200" x="auto" y="905"
detach="f" ts="20663"/>

<panels><group id='Left' open='t'>
<dialog id='UberBar'/> <stream id='sbounty'/> <builtin id='windows'/>
</group></panels>
</pre>

===Nested Elements in stgupd===
{| class="wikitable"
|-
! Element !! Description
|-
| panels || Panel layout configuration
|-
| group || Group container (id: Left, Right)
|-
| stream || Stream window settings
|-
| dialog || Dialog window reference
|-
| builtin || Built-in window reference
|-
| w || Window configuration (id, vis, frame, location, panel, open, rect, detach)
|-
| detach || Torn-off window geometry (x, y, width, height)
|-
| font / columnFont || Per-window font settings
|-
| misc || Miscellaneous settings
|-
| toggles || Toggle settings
|-
| m || Setting value
|-
| s || Toggle state
|}

==UI State Control==
===Monopolize Element===
{| class="wikitable"
|-
! Element !! Description
|-
| <code>monopolize</code> || Game takes exclusive control of a stream
|}

When <code>monopolize id="main"</code> is set, the game blocks all other text/streams until released with <code>monopolize id=""</code>.

===Examples===
<pre>
<monopolize id="main"/>You get a room key from the innkeeper and wander off to your room...
... (inn rest sequence) ...
<indicator id='IconINVISIBLE' visible='n'/><monopolize id=""/><output class=""/>
</pre>

===Input State===
{| class="wikitable"
|-
! Element !! Description !! Key Attributes
|-
| <code>pushInputState</code> || Push an input-mode change || state
|-
| <code>popInputState</code> || Restore the previous input mode || (none)
|-
| <code>switchQuickBar</code> || Switch the active quick bar || id
|}

===Examples===
<pre>
<switchQuickBar id="quick"/>
<switchQuickBar id="quick-simu"/>
<switchQuickBar id="quick-combat"/>
</pre>

==Special Behaviors==
===Newline Suppression===
Tags followed by newlines suppress newline output '''except''' for:
* <code><a></code> (hyperlinks)
* <code><pushBold></code> (bold start)

===Mixed Content===
Output contains both XML tags and plain text on the same lines. Parsers must handle interleaved content.

===Negative Exist IDs===
Room/NPC objects often have negative exist values (e.g., -11225598).

===Inconsistent Quoting===
The same tag may arrive with single or double quotes depending on which server system emitted it. Parsers must accept both.

==Third-party client extensions==
Because dialogs and streams are keyed only by id, third-party tools can inject their own windows through the ordinary <code>openDialog</code>/<code>dialogData</code>/<code>streamWindow</code> grammar &mdash; this traffic is indistinguishable from Simutronics traffic by design. A frontend that sees an unknown dialog id should fall back to a generic dialog renderer rather than assume the id is unknown-bad.

Examples of locally-injected dialog ids seen from the Lich scripting environment include <code>UberBar</code>, <code>UberBounty</code>, <code>FlareLog</code>, <code>InfoCenter</code>, <code>TargetWindow</code>, and <code>Missing Spells</code>. In addition, Lich 5 exposes a native WebUI bridge via a <code>&lt;LichWebUI/&gt;</code> tag. Individual frontends may also define their own private extension tags; these are not part of the Simutronics wire protocol.

==Common Attributes Reference==
{| class="wikitable"
|-
! Category !! Attributes
|-
| Layout || top, left, height, width, align, anchor_top, anchor_left, anchor_right, justify, location
|-
| Identity || id, exist, noun
|-
| Behavioral || cmd, echo, value, visible, resident, save, ifClosed, styleIfClosed
|-
| Content || title, subtitle, text, tooltip, content_text, content_value
|}

==Complete Element Summary==
{| class="wikitable"
|-
! Category !! Elements
|-
| Core / setup || mode, playerID, settingsInfo, settings, app, endSetup, updateverbs, cmdtimestamp, LaunchURL, FEStart
|-
| Command dictionary || cmdlist, cli
|-
| Streams || streamWindow, clearStream, pushStream, popStream, stream, exposeStream
|-
| Components || compDef, component
|-
| Room / world || nav, compass, dir, roommeta, resource
|-
| Containers || container, exposeContainer, clearContainer, deleteContainer, inv
|-
| Dialogs || openDialog, dialogData, closeDialog, exposeDialog, dynaStream, clearDynaStream
|-
| Controls || progressBar, cmdButton, closeButton, radio, dropDownBox, label, link, menuLink, menuImage, image, skin, editBox, upDownEditBox, streamBox, sep
|-
| Interactive || a, d
|-
| Character state || indicator, spell, left, right, prompt, roundTime, castTime, pulse, crtrStatus, objectives, group
|-
| Formatting || pushBold, popBold, b, output, style, preset
|-
| Menu || menu, mi, nomenu, menuImage
|-
| Settings || flag
|-
| Client settings || stgupd, panels, group, w, dialog, stream, builtin, detach, font, columnFont
|-
| UI state || monopolize, pushInputState, popInputState, switchQuickBar
|-
| Extensions || LichWebUI (third-party / client-specific)
|}

[[Category:Front Ends]]

Latest revision as of 14:25, 6 August 2026

Wrayth protocol

The Wrayth protocol is the XML protocol used to pass information between the GemStone IV game server and front-end clients. It is utilized by the official Wrayth client and unofficial frontends.

Protocol model

The feed is interleaved text and markup, not a document. Plain prose flows continuously, and tags either style the surrounding text, redirect it to a named stream, or carry structured state (vitals, room data, window declarations). A parser must handle text and tags on the same line.

  • Streams are named text channels. Text between pushStream/popStream (or inside a paired <stream>) belongs to that channel; everything else belongs to main. Examples: thoughts, speech, bounty, loot, inv.
  • Dialogs are declared control surfaces. dialogData ships positioned controls (bars, labels, buttons) that the client lays out with an anchor system. Updates are incremental — a re-sent dialogData carries only the controls that changed, merged by control id.
  • Ids are identity. Streams, dialogs, containers, creatures (exist numbers), and rooms (nav rm) are all keyed by id. Third-party tools (such as Lich scripts) may inject their own dialogs and streams through the same grammar, indistinguishable from Simutronics traffic.
  • Timers are absolute. roundTime/castTime value attributes are epoch end-times, not durations. The remaining span is computed as value − prompt time (see Character State).
  • Quoting is inconsistent by design. The same tag may arrive with single or double quotes depending on which server system emitted it, so parsers must accept both.

Core System Elements

Element Description Key Attributes
mode Game mode indicator id (GAME, LOGIN, CMGR)
playerID Player identifier id (numeric)
settingsInfo Announces the server-stored client-settings blob client, major, crc, instance
settings The settings download itself, chunked by major section number (requested by the FE when its cached copy's crc mismatches) client, major
app Application metadata for window titling char, game, title
endSetup Marks end of initial setup; game text follows (none)
updateverbs Tells the FE to refresh its verb list for the game system default
cmdtimestamp Version stamp for the cmdlist command dictionary data
LaunchURL Asks the FE to open a play.net URL (payment, character manager, re-auth) src
FEStart Front-end launch marker (written by the FE side) name, time

Command dictionary (cmdlist / cli)

At login the server sends the point-and-click command dictionary: <cmdlist> containing many <cli> entries. Each cli maps a coordinate id to a menu label and a command template. In the template, @ substitutes the object's noun and # substitutes its exist id. Context menus (see Menu System) reference these coordinates later — the menu response itself carries no labels.

Element Description Key Attributes
cmdlist Command-dictionary envelope (none)
cli One coordinate → label + command-template entry coord, menu, command, menu_cat

Examples

<mode id="GAME"/>
<playerID id='XXXXXX'/>
<settingsInfo client='1.0.1.28' major='19313' crc='3508957330' instance='GS4'/>
<cmdlist>
  <cli coord="2524,1703" menu="tackle @" command="tackle #" menu_cat="6"/>
</cmdlist>
<cmdtimestamp data='1767482628.1.1.1'/>
<endSetup/><app char="Nisugi" game="Prime" title="GemStone IV: Nisugi [Prime]"/>
<updateverbs default="GS4"/>

Stream Management

Streams route text output to specific UI windows.

Element Description Key Attributes
streamWindow UI window definition / re-title id, title, subtitle, location, target, ifClosed, styleIfClosed, resident, save, scroll, timestamp, nameFilterOption, appearance
clearStream Clear stream contents id, ifClosed
pushStream Push following text to stream id
popStream Pop stream context (back to main) id
stream Inline (paired) redirect: <stream id>…</stream> id
exposeStream Bring a stream window to front on demand id

The streamWindow tag fires on every room move for the room/main windows (carrying the room name as subtitle) and at login for feature windows. Notable attributes: timestamp='on' requests per-window timestamps, and nameFilterOption advertises a name filter (used by logons/death).

Stream Window IDs

Stream ID Title Purpose
main Story Main game output
room Room Room description display
inv My Inventory Worn items
Spells Spells Available spells list
familiar Familiar Familiar messages
thoughts Thoughts ESP/telepathy
logons Arrivals Player arrivals
death Deaths Death notices
speech Speech Speech window
ambients Ambients Ambient messages
announcements Announcements Game announcements
bounty Bounties Bounty task info
society Society Tasks Society task info
loot Loot Loot window
charprofile Character's Profile Character profile
charsheet Character Sheet Character sheet

Closed-window text routing (ifClosed / styleIfClosed)

Each stream declares what happens to its text when its window is closed, via two attributes on streamWindow: ifClosed (a destination) and styleIfClosed (a style applied to fallen-through text). Four behaviors result:

Personality Declaration Closed-window behavior Examples
Exclusive ifClosed absent, styleIfClosed set Text falls through to the main/story window, wrapped in the named style — the classic inline-thoughts look thoughts ("thought"), familiar ("watching")
Routed ifClosed='<window>' Text is sent to another window instead; chains if that one is closed too (e.g. voln → thoughts → main-as-"thought") voln → thoughts
Copy ifClosed= The stream is a duplicate — the server also sends the same line to main, so the closed window's copy drops harmlessly speech; room-window content
Unspecified neither attribute Falls through to main unstyled logons, death

Examples

<streamWindow id='room' title='Room' subtitle=" - [Icemule Trace, South Road]" location='center' target='drop' ifClosed='' resident='true'/>
<streamWindow id='inv' title='My Inventory' target='wear' ifClosed='' resident='true'/>
<streamWindow id="Spells" title="Spells" ifClosed="" resident="true" scroll="manual"/>
<streamWindow id='thoughts' title='Thoughts' styleIfClosed='thought' resident='true'/>
<clearStream id='inv' ifClosed=''/>
<pushStream id='inv'/>Your worn items are:
<popStream/>
<clearStream id="Spells"/>

Stream content example (thoughts/ESP):

<pushStream id="thoughts"/>You hear the faint thoughts of Nisugi echo in your mind:
"Hello everyone!"
<popStream/>

Component System

Components represent dynamic room/area content.

Element Description Key Attributes
compDef Component definition (full replacement of a named part) id
component Component instance (incremental replacement) id

Component IDs:

  • room desc - Room description
  • room objs - Room objects
  • room players - Players in room
  • room exits - Available exits
  • sprite - Player's familiar/sprite

Examples

<compDef id='room players'></compDef>
<compDef id='room exits'>Obvious paths: <d>east</d>, <d>west</d></compDef>
<compDef id='sprite'></compDef>

<component id='room players'>Also here: Lord <a exist="-10939058" noun="Huras">Huras</a></component>
<component id='room players'></component>
<component id='room objs'>  You also see<b> <pushBold/>a <a exist="103330" noun="resident">disheveled resident</a><popBold/></b>.</component>

Room and World

A room change is a fixed sequence: nav announces the room id, compDef/component replace the room's parts, compass lists exits, streamWindow re-titles the Room/Story windows with the room name as subtitle, and resource selects room art.

Element Description Key Attributes
nav Room change; rm is the room's unique id (the mapper's key) rm
compass Available exits (contains dir elements) (none)
dir Direction indicator value (n, s, e, w, ne, nw, se, sw, up, down, out)
roommeta Room environment flags (per-room) weather, bonfire, inside, water, sanctuary, realm, climate, terrain
resource Room artwork id for FEs that show room images picture ("0" = none)

Examples

<nav rm='12345'/>
<compass><dir value="e"/><dir value="out"/></compass>
<compass><dir value="n"/><dir value="s"/><dir value="e"/><dir value="w"/></compass>
<roommeta weather='0' inside='0' water='0' sanctuary='0' terrain='forest'/>
<resource picture="0"/>

Container/Inventory System

Containers are windows too, keyed by id. stow is a shortcut id for the character's default worn storage container.

Element Description Key Attributes
container Declares a container window id, title, location, target, resident, save
exposeContainer Bring a container window to front (e.g. on OPEN) id
clearContainer Clear container contents before a re-send id
deleteContainer Remove a container window entirely (container destroyed / out of scope) id
inv Inventory item line for a container's contents id

Examples

Looking in a container:

<container id='393944944' title='Chest' target='#393944944' location='right'/>
<clearContainer id="393944944"/>
<inv id='393944944'>In the <a exist="393944944" noun="chest">chest</a>:</inv>
<inv id='393944944'> <a exist="393944946" noun="coins">some silver coins</a></inv>
<inv id='393944944'> a <a exist="393944945" noun="garnet">dark red-violet garnet</a></inv>

Stow container (default storage):

<exposeContainer id='stow'/>
<container id='stow' title="My Cloak" target='#225766691' location='right' save='' resident='true'/>
<clearContainer id="stow"/>
<inv id='stow'>In the <a exist="225766691" noun="cloak">cloak</a>:</inv>
<inv id='stow'> a <a exist="225766734" noun="feather">nacreous disir feather</a></inv>

Dialog System

Dialogs are UI panels with controls and data. A dialog's life cycle: openDialog declares the frame (or a bare dialogData arrives for a well-known id) → dialogData ships/updates controls incrementally → exposeDialog shows it on demand → closeDialog dismisses it. Streams mirror this with streamWindow/exposeStream.

Element Description Key Attributes
openDialog Create dialog window; may embed initial dialogData id, type, title, location, target, height, width, resident, save, noResize, noDock
dialogData Ship/update a dialog's controls, merged by control id id or name, clear
closeDialog Close a dialog window id
exposeDialog Show a hidden dialog now (user-action echo) id
dynaStream Text-content feed for a streamBox control inside a dialog id
clearDynaStream Clear a streamBox's content id

Two quirks worth noting:

  • dialogData may key on either id= or name= depending on the emitter.
  • clear='t' on dialogData resets the dialog's controls before the new set is applied. Locations seen on openDialog include right, center, quickBar, statBar, and detach.

Dialog IDs

Dialog ID Purpose
combat Combat controls (the most active dialog)
injuries Injury display (player)
minivitals Health/mana/stamina bars
stance Stance indicator
expr Experience/level info
encum Encumbrance
Active Spells Active spell list
Buffs Active buffs
Debuffs Active debuffs
Cooldowns Ability cooldowns
mapMaster Map controls
mapViewMain Map view
espMasterDialog / espMasterData ESP/telepathy thought-network panel
quick Quick action bar (main)
quick-combat Combat quick bar
quick-simu Information quick bar
BetrayerPanel Blood Points tracking
befriend Friends & Enemies list
bank Banking interface
bugDialogBox Bug-report form
dlgCustomize Customization dialog
injuries-{existID} Target character injuries appraisal

Examples

Opening and populating a dialog:

<openDialog type='dynamic' id='minivitals' title='Stats' location='statBar'>
  <dialogData id='minivitals'></dialogData>
</openDialog>

<openDialog type='dynamic' id='stance' title='Stance' location='right' height='50' width='190' resident='true'>
  <dialogData id='stance'>
    <progressBar id='pbarStance' value='100' text='defensive (100%)' top='5' left='-5' height='16' width='160' align='n' tooltip='Percent of stance contributing to defense'/>
  </dialogData>
</openDialog>

Updating dialog data:

<dialogData id='combat'>
  <progressBar id='pbarStance' value='100' text='defensive (100%)' top='51' width='130' height='16' left='0' align='n' tooltip='Percent of stance contributing to defense'/>
</dialogData>

Banking dialog:

<dialogData id='bank'>
  <link id='depositallLnk' value='Deposit All' cmd='deposit all' align='w' top='30' left='0' height='30' width='90' echo='deposit all'/>
  <link id='wealthnotesLnk' value='Check Notes' cmd='wealth notes' align='e' top='30' left='0' height='30' width='90' echo='wealth notes'/>
  <closeButton id='closeMe' value='Close' cmd='' align='s' left='0' top='0' width='80'/>
</dialogData>
<exposeDialog id='bank'/>
<closeDialog id="bank"/>

Target Injuries Appraisal Dialog

When you appraise another character, a dynamic injuries dialog opens showing their wounds:

<openDialog type='dynamic' id='injuries-10070682' title='Dicate's Injuries' location='right'>
  <dialogData id='injuries'>
    <skin id='injuredSkin' name='InjuriesPanel'
          controls='nsys,leftArm,rightArm,rightLeg,leftLeg,head,rightFoot,leftFoot,rightHand,leftHand,rightEye,leftEye,back,neck,chest,abdomen'/>
    <closeButton id='cancel' value='Close' cmd=''/>
  </dialogData>
</openDialog>
<dialogData id="injuries-10070682">
  <image id="head" name="Injury1"/>
  <image id="neck" name="Injury2" cmd="tend Dicate neck" tooltip="tend Dicate's neck"/>
  <image id="rightArm" name="Injury3" cmd="tend Dicate right arm"/>
  ...
</dialogData>

Key Elements:

  • Dialog ID: injuries-{existID} where existID is the target's object ID
  • Body part images with injury levels: Injury1 (minor), Injury2 (moderate), Injury3 (severe)
  • Clickable cmd attributes for tending wounds
  • Body parts tracked: head, neck, rightArm, leftArm, rightLeg, leftLeg, rightHand, leftHand, chest, abdomen, back, rightEye, leftEye, rightFoot, leftFoot, nsys

UI Control Elements

Controls appear inside dialogData. Every control shares the layout attributes top left width height (pixels; negatives allowed, and percentages are used in vitals bars) plus positioning:

  • align — a compass value (nw n ne w c e sw s se) placing the control relative to the dialog edge.
  • Sibling anchors anchor_top / anchor_left / anchor_right — position relative to another control by id. Supplying both anchor_left and anchor_right stretches the control between them.
Element Description Key Attributes
progressBar Value bar with optional custom text id, value, text, customText, top, left, height, width
cmdButton Command button id, value, cmd, echo, tooltip
closeButton Button that also dismisses the dialog id, value, cmd
radio Toggle-group button id, value, text, cmd, group
dropDownBox Dropdown selector; %id% in cmd substitutes the selection id, value, cmd, content_text, content_value, tooltip
label Text label; see justify note below id, value, justify
link Inline command hyperlink id, value, cmd, echo, URL
menuLink Entity-bound link row (keyed by exist) id, value, name, exist, noun, tooltip
menuImage Entity-bound image row (keyed by exist) id, name, exist, noun, tooltip
image Named image / button (also used as an anchor target) id, name, cmd, tooltip
skin Named art layer painted behind sibling controls id, name, controls
editBox Text input id, value, maxChars, enterButton, focus
upDownEditBox Numeric spinner input id, value, maxChars, enterButton, focus
streamBox Scrolling text region inside a dialog, fed by dynaStream id, height, width, save
sep Separator row (quickbars, menus) (none)

Text alignment (justify): justify is the only text-alignment mechanism on the wire. It decodes as low-two-bits alignment (0 = left, 1 = center, 2 = right) plus a bit-4 flag, so values 4/5/6 are "flagged" left/center/right. Text-input controls (editBox/upDownEditBox) and dropdowns support %id% substitution: the token is replaced with the control's current value in the submitting button's cmd.

Progress Bar IDs

ProgressBar ID Dialog Purpose
health minivitals Health bar (main)
health2 injuries Health bar (injuries)
mana minivitals Mana bar
spirit minivitals Spirit bar
stamina minivitals Stamina bar
pbarStance combat/stance Stance indicator
encumlevel encum Encumbrance level
mindState expr Mind state (experience absorption)
nextLvlPB expr Progress to next level

Examples

Progress bars (vitals):

<progressBar id='health' value='100' text='health 223/223' customText='t' left='0%' top='0%' width='25%' height='100%'/>
<progressBar id='mana' value='98' text='mana 426/431' left='25%' customText='t' top='0%' width='25%' height='100%'/>
<progressBar id='spirit' value='100' text='spirit 10/10' left='50%' customText='t' top='0%' width='25%' height='100%'/>
<progressBar id='stamina' value='100' text='stamina 112/112' left='75%' customText='t' top='0%' width='25%' height='100%'/>
<progressBar id='encumlevel' value='0' text='None' top='5' left='-5' align='n' width='160' height='15'/>

Command buttons:

<cmdButton id='cmdDefStance' value='defense' cmd='_stance defensive' tooltip='Assume a Defensive Stance' echo='stance defensive' height='20' width='55' top='70' left='0' align='nw'/>
<cmdButton id='cmdTarget' value='target' cmd='target random' tooltip='Select a Random Target' height='20' width='55' top='93' left='0' align='nw'/>
<cmdButton id='cmdAttack' value='attack' cmd='attack' height='20' width='50' left='0' top='93' tooltip='Attack Current Target' align='ne'/>

Dropdown box:

<dropDownBox id='dDBStance' value="defensive" cmd='_stance %dDBStance%' content_text='offensive,advance,forward,neutral,guarded,defensive' content_value='offensive,advance,forward,neutral,guarded,defensive' align='n' top='70' left='0' height='20' width='80' tooltip='Stance Selection'/>

Labels:

<label id='encumblurb' value='You are not encumbered enough to notice.' top='10' left='0' align='n' width='160' height='50' justify='0'/>

Streaming text into a dialog (bug-report box):

<dialogData id='bugDialogBox'>
  <streamBox id='bugStream' height='200' width='400' save=''/>
</dialogData>
<dynaStream id='bugStream'>Please describe the problem in detail...</dynaStream>
<clearDynaStream id='bugStream'/>

Navigation Elements

See Room and World for the nav, compass, and dir elements, which drive room changes and exits.

Interactive/Link Elements

Hyperlink Element (<a>)

Creates clickable links for objects, players, and coordinates. This is the single most common tag on the wire.

Attribute Description
exist Game object ID (numeric, can be negative)
noun Object noun/type
coord Click coordinates (x,y format)
char Character name (for player links)
game Game code (GSIV, GST)

Examples

<a exist="225766824" noun="bandolier">leather bandolier</a>
<a exist="-11225598" noun="Ludge">Ludge</a>
<a exist="103330" noun="resident">disheveled resident</a>
<a exist="-10939058" noun="Huras">Huras</a>

Direct Command Link Element (<d>)

Creates clickable command links in text. When clicked, executes the command specified in the cmd attribute (or the tag contents if cmd is omitted). Commonly used for compass directions but works for any command. A <d> may be nested inside an <a>; the outer command wins.

Attribute Description
cmd Command to execute (optional - if omitted, executes tag contents as the command)

Examples

Compass directions (no cmd attribute - executes tag contents):

<compDef id='room exits'>Obvious paths: <d>east</d>, <d>west</d></compDef>
<compDef id='room exits'>Obvious exits: <d>northeast</d>, <d>out</d></compDef>

Movement message (with cmd attribute):

Lord <a exist="-10939058" noun="Huras">Huras</a> just went <d cmd='go west'>west</d>.

Store commands:

  shield: <d cmd="store SHIELD clear">an <a exist="412277454" noun="buckler">old krodera buckler</a></d> (<d cmd='store set'>put in sheath</d>)
  weapon: <d cmd="store WEAPON clear">a <a exist="412277485" noun="baselard">sleek gleaming steel baselard</a></d> (<d cmd='store set'>put in sheath</d>)

Character State Elements

Element Description Key Attributes
indicator Boolean status icon id, visible (y/n)
spell Current prepared spell (text content)
left Left hand item exist, noun
right Right hand item exist, noun
prompt Command prompt; its epoch time is the client's clock reference for RT/CT math time (epoch seconds)
roundTime Action round time; value is the epoch end time value (epoch seconds)
castTime Spell cast time; value is the epoch end time value (epoch seconds)
pulse Mana pulse tick marker mana (0/1)
crtrStatus Creature status snapshot keyed by exist id exist, plus flags below
objectives / group Task/bounty system: full-refresh / delete-group actions over typed groups id, type, action

Timers are absolute. roundTime and castTime report an epoch end time, not a duration. Compute the remaining span as value − prompt time, using the most recent <prompt time> as the clock reference.

Creature status flags (crtrStatus): the snapshot is keyed by exist id (which may be negative); a missing flag or a value of "0" means inactive. Observed flags: inferior, flying, hostile, hovering, ascended, challenging, sleeping, kneeling, sitting, prone, dead.

Indicator IDs

Indicator ID Status
IconKNEELING Kneeling
IconPRONE Prone
IconSITTING Sitting
IconSTANDING Standing
IconSTUNNED Stunned
IconHIDDEN Hidden
IconINVISIBLE Invisible
IconDEAD Dead
IconWEBBED Webbed
IconJOINED Joined group

Examples

Character state elements:

<indicator id='IconSTANDING' visible='y'/>
<indicator id='IconHIDDEN' visible='y'/>
<indicator id='IconHIDDEN' visible='n'/>
<indicator id='IconSTUNNED' visible='y'/>
<indicator id='IconINVISIBLE' visible='n'/>

<spell>None</spell>
<spell>Fire Spirit (111)</spell>

<left exist="394466807" noun="bow">ghezyte long bow</left>
<left exist="" noun=""/>
<right exist="417169523" noun="arrows">glowbark arrows</right>

<prompt time="1767310975">></prompt>
<roundTime value='1767333503'/>
<castTime value='1767250287'/>
<pulse mana='1'/>
<crtrStatus exist="194485" hostile="1" inferior="1"/>

Text Formatting Elements

Element Description Key Attributes
pushBold Start bold text (monster highlighting) (none)
popBold End bold text (none)
b Bold wrapper (none)
output Output formatting/font switch class
style Opens/closes a named text style; empty id closes id (roomName, roomDesc, etc.)
preset Wraps text in a user-configurable color preset id (speech, whisper, thought)

Output Class Values

  • <output class="mono"/> - Switch to monospace font (tables/ASCII art)
  • <output class=""/> - Switch back to normal font

Examples

Bold text (monster highlighting):

<b> <pushBold/>a <a exist="103330" noun="resident">disheveled resident</a><popBold/></b>

Room styling:

<popBold/><resource picture="0"/><style id="roomName" />[Cobblestone Path]
<style id="roomDesc"/>The narrow cobblestone path winds between aged buildings...

Speech/whisper preset:

<preset id="whisper">(OOC) You whisper,</preset> "Rallying at 0d7d2dc1." to your group.
<preset id="whisper">(OOC) <a exist="-10070682" noun="Dicate">Dicate's</a> player whispers to the group,</preset> "Joined cluster group 0d7d2dc1."
<preset id="speech">Nisugi says,</preset> "Hello!"

Font switching:

<output class="mono"/>
   Name                            Mana     Known/Cast
   Minor Elemental Edge (902)        1          Yes
   Elemental Defense I (401)         1          Yes
<output class=""/>

Menu System

Right-click context menus are coordinate lookups against the cli dictionary sent at login (see Command dictionary). When the user requests a menu (e.g. _menu #exist), the server answers with a <menu> containing <mi coord="…"/> items. Each coord is a key into the dictionary — the menu carries no labels; the client resolves coord → label + command template, substituting the object's noun/exist. <nomenu/> means nothing is available for that object.

Element Description Key Attributes
menu Context-menu response envelope id, path, cat_list (category ordering)
mi One menu item, by cli coordinate coord
nomenu No menu exists for the requested object (none)
menuImage Image in a menu (e.g. quick-bar menus) (see UI Controls)

Examples

<menu id='objectMenu' path=" in #103330" cat_list="1 2 3 6">
  <mi coord="2524,1703"/>
  <mi coord="1180,904"/>
</menu>
<nomenu/>

Settings/Flags System

Element Description Key Attributes
flag Player setting flag id, status (on/off), desc

Example flags:

  • Player Log On, Player Log Off, Player Disconnect
  • Room Names, Room Descriptions, Brief Room Description
  • Monster Bold, Default Group Open

Examples

<flag id="Player Log On" status='off' desc="Show logon messages."/>
<flag id="Player Log Off" status='off' desc="Show logoff messages."/>
<flag id="Player Disconnect" status='off' desc="Show disconnection messages."/>
<flag id="Room Names" status='on' desc="Display the name of the room in which you are located."/>
<flag id="Room Descriptions" status='on' desc="Display room descriptions."/>
<flag id="Brief Room Description" status='off' desc="Display room descriptions in shortened form."/>
<flag id="Monster Bold" status='on' desc="Highlight monster names."/>
<flag id="Default Group Open" status='on' desc="Allow others to join your group."/>
<flag id="Automatically Activate ESP Amulets" status='on' desc="Activate items for THINKing automatically."/>
<flag id="Automatically Gather Coins" status='on' desc="Gather coins when searching your kills."/>

Client Settings (stgupd)

The official Wrayth client uploads its own window-state to the server so that layout survives across sessions. These blocks appear inside <!-- CLIENT --> / <!-- ENDCLIENT --> markers and travel from client to server. Unofficial frontends generally manage their own layout and need not emit or parse these, but they document Wrayth's internal window model precisely: every window is id + kind (dialog | stream | builtin) + zone/panel + frame + rect + open/vis + detach.

<!-- CLIENT --><stgupd><panels>...</panels><!-- ENDCLIENT -->
<!-- CLIENT --><stgupd><stream>...</stream><!-- ENDCLIENT -->

<w id="combat" vis="t" frame="panel|float" location="center"
   panel="Left" open="t" height="323" width="200" x="auto" y="905"
   detach="f" ts="20663"/>

<panels><group id='Left' open='t'>
  <dialog id='UberBar'/> <stream id='sbounty'/> <builtin id='windows'/>
</group></panels>

Nested Elements in stgupd

Element Description
panels Panel layout configuration
group Group container (id: Left, Right)
stream Stream window settings
dialog Dialog window reference
builtin Built-in window reference
w Window configuration (id, vis, frame, location, panel, open, rect, detach)
detach Torn-off window geometry (x, y, width, height)
font / columnFont Per-window font settings
misc Miscellaneous settings
toggles Toggle settings
m Setting value
s Toggle state

UI State Control

Monopolize Element

Element Description
monopolize Game takes exclusive control of a stream

When monopolize id="main" is set, the game blocks all other text/streams until released with monopolize id="".

Examples

<monopolize id="main"/>You get a room key from the innkeeper and wander off to your room...
... (inn rest sequence) ...
<indicator id='IconINVISIBLE' visible='n'/><monopolize id=""/><output class=""/>

Input State

Element Description Key Attributes
pushInputState Push an input-mode change state
popInputState Restore the previous input mode (none)
switchQuickBar Switch the active quick bar id

Examples

<switchQuickBar id="quick"/>
<switchQuickBar id="quick-simu"/>
<switchQuickBar id="quick-combat"/>

Special Behaviors

Newline Suppression

Tags followed by newlines suppress newline output except for:

  • <a> (hyperlinks)
  • <pushBold> (bold start)

Mixed Content

Output contains both XML tags and plain text on the same lines. Parsers must handle interleaved content.

Negative Exist IDs

Room/NPC objects often have negative exist values (e.g., -11225598).

Inconsistent Quoting

The same tag may arrive with single or double quotes depending on which server system emitted it. Parsers must accept both.

Third-party client extensions

Because dialogs and streams are keyed only by id, third-party tools can inject their own windows through the ordinary openDialog/dialogData/streamWindow grammar — this traffic is indistinguishable from Simutronics traffic by design. A frontend that sees an unknown dialog id should fall back to a generic dialog renderer rather than assume the id is unknown-bad.

Examples of locally-injected dialog ids seen from the Lich scripting environment include UberBar, UberBounty, FlareLog, InfoCenter, TargetWindow, and Missing Spells. In addition, Lich 5 exposes a native WebUI bridge via a <LichWebUI/> tag. Individual frontends may also define their own private extension tags; these are not part of the Simutronics wire protocol.

Common Attributes Reference

Category Attributes
Layout top, left, height, width, align, anchor_top, anchor_left, anchor_right, justify, location
Identity id, exist, noun
Behavioral cmd, echo, value, visible, resident, save, ifClosed, styleIfClosed
Content title, subtitle, text, tooltip, content_text, content_value

Complete Element Summary

Category Elements
Core / setup mode, playerID, settingsInfo, settings, app, endSetup, updateverbs, cmdtimestamp, LaunchURL, FEStart
Command dictionary cmdlist, cli
Streams streamWindow, clearStream, pushStream, popStream, stream, exposeStream
Components compDef, component
Room / world nav, compass, dir, roommeta, resource
Containers container, exposeContainer, clearContainer, deleteContainer, inv
Dialogs openDialog, dialogData, closeDialog, exposeDialog, dynaStream, clearDynaStream
Controls progressBar, cmdButton, closeButton, radio, dropDownBox, label, link, menuLink, menuImage, image, skin, editBox, upDownEditBox, streamBox, sep
Interactive a, d
Character state indicator, spell, left, right, prompt, roundTime, castTime, pulse, crtrStatus, objectives, group
Formatting pushBold, popBold, b, output, style, preset
Menu menu, mi, nomenu, menuImage
Settings flag
Client settings stgupd, panels, group, w, dialog, stream, builtin, detach, font, columnFont
UI state monopolize, pushInputState, popInputState, switchQuickBar
Extensions LichWebUI (third-party / client-specific)