<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://unwrittenlegends.net/wiki/index.php?action=history&amp;feed=atom&amp;title=GMCP</id>
	<title>GMCP - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://unwrittenlegends.net/wiki/index.php?action=history&amp;feed=atom&amp;title=GMCP"/>
	<link rel="alternate" type="text/html" href="https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;action=history"/>
	<updated>2026-05-13T10:56:12Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.42.5</generator>
	<entry>
		<id>https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;diff=958&amp;oldid=prev</id>
		<title>Dorandraco at 19:01, 30 August 2025</title>
		<link rel="alternate" type="text/html" href="https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;diff=958&amp;oldid=prev"/>
		<updated>2025-08-30T19:01:41Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 19:01, 30 August 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This document describes the GMCP (Generic MUD Communication Protocol) messages currently implemented by the Unwritten Legends server &amp;#039;&amp;#039;&amp;#039;as observed in the 1.0 engine&amp;#039;&amp;#039;&amp;#039;. It is intended for client authors (e.g., Mudlet packages) and for internal maintainers.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This document describes the GMCP (Generic MUD Communication Protocol) messages currently implemented by the Unwritten Legends server &amp;#039;&amp;#039;&amp;#039;as observed in the 1.0 engine&amp;#039;&amp;#039;&amp;#039;. It is intended for client authors (e.g., Mudlet packages) and for internal maintainers.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Transport &amp;amp;amp; Negotiation ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Transport &amp;amp;amp; Negotiation ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l15&quot;&gt;Line 15:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 14:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;UL recognizes client &amp;lt;code&amp;gt;Core.Supports.Set/Add&amp;lt;/code&amp;gt; and maintains a capability set but &amp;#039;&amp;#039;&amp;#039;does not require&amp;#039;&amp;#039;&amp;#039; capabilities to be declared to emit core messages. Custom UL messages are namespaced under &amp;lt;code&amp;gt;UL.*&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;UL recognizes client &amp;lt;code&amp;gt;Core.Supports.Set/Add&amp;lt;/code&amp;gt; and maintains a capability set but &amp;#039;&amp;#039;&amp;#039;does not require&amp;#039;&amp;#039;&amp;#039; capabilities to be declared to emit core messages. Custom UL messages are namespaced under &amp;lt;code&amp;gt;UL.*&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Namespaces ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Namespaces ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l26&quot;&gt;Line 26:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 24:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Versioning for the custom namespace is surfaced implicitly by the supported set (&amp;lt;code&amp;gt;&amp;quot;UL 1&amp;quot;&amp;lt;/code&amp;gt;). If/when a breaking schema appears, we will add &amp;lt;code&amp;gt;&amp;quot;UL 2&amp;quot;&amp;lt;/code&amp;gt; while leaving &amp;lt;code&amp;gt;UL 1&amp;lt;/code&amp;gt; available for a deprecation window.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Versioning for the custom namespace is surfaced implicitly by the supported set (&amp;lt;code&amp;gt;&amp;quot;UL 1&amp;quot;&amp;lt;/code&amp;gt;). If/when a breaking schema appears, we will add &amp;lt;code&amp;gt;&amp;quot;UL 2&amp;quot;&amp;lt;/code&amp;gt; while leaving &amp;lt;code&amp;gt;UL 1&amp;lt;/code&amp;gt; available for a deprecation window.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Emission Triggers &amp;amp;amp; Frequency ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Emission Triggers &amp;amp;amp; Frequency ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l37&quot;&gt;Line 37:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 34:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Client guidance:&amp;#039;&amp;#039;&amp;#039; handle idempotent updates and partial updates. Where keys are omitted on follow-up messages, merge into the client’s last known state.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Client guidance:&amp;#039;&amp;#039;&amp;#039; handle idempotent updates and partial updates. Where keys are omitted on follow-up messages, merge into the client’s last known state.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Message Catalog ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Message Catalog ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l52&quot;&gt;Line 52:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 48:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;client&amp;quot;: string, &amp;quot;version&amp;quot;: string }&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;client&amp;quot;: string, &amp;quot;version&amp;quot;: string }&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;client&amp;quot;: &amp;quot;Unwritten Legends&amp;quot;, &amp;quot;version&amp;quot;: &amp;quot;1.0.0.0&amp;quot; }&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;client&amp;quot;: &amp;quot;Unwritten Legends&amp;quot;, &amp;quot;version&amp;quot;: &amp;quot;1.0.0.0&amp;quot; }&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== Core.Supports.Set ====&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== Core.Supports.Set ====&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l63&quot;&gt;Line 63:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 58:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Also observed (client → server):&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Core.Supports.Set&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Core.Supports.Add&amp;lt;/code&amp;gt;. The server records client capabilities for future gating but does not currently require them to emit core messages.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Also observed (client → server):&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Core.Supports.Set&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Core.Supports.Add&amp;lt;/code&amp;gt;. The server records client capabilities for future gating but does not currently require them to emit core messages.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Room ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Room ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l89&quot;&gt;Line 89:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 83:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Future (not yet emitted): &amp;lt;code&amp;gt;Room.Players&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Future (not yet emitted): &amp;lt;code&amp;gt;Room.Players&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Character Identity &amp;amp;amp; State ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== Character Identity &amp;amp;amp; State ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l132&quot;&gt;Line 132:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 125:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;quot;level&amp;quot;:100&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;quot;level&amp;quot;:100&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== Char.Status ====&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== Char.Status ====&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l166&quot;&gt;Line 166:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 158:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;quot;willpower_max&amp;quot;:218&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;quot;willpower_max&amp;quot;:218&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== Char.Stats ====&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== Char.Stats ====&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l192&quot;&gt;Line 192:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 183:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;quot;lessons&amp;quot;:{&amp;quot;available&amp;quot;:4,&amp;quot;max&amp;quot;:4}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;quot;lessons&amp;quot;:{&amp;quot;available&amp;quot;:4,&amp;quot;max&amp;quot;:4}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== UL (Unwritten Legends) — custom namespace ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== UL (Unwritten Legends) — custom namespace ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l247&quot;&gt;Line 247:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 237:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;roundtime&amp;quot;: number, &amp;quot;stun&amp;quot;: number, &amp;quot;unconscious&amp;quot;: number }&amp;lt;/code&amp;gt; (seconds)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;roundtime&amp;quot;: number, &amp;quot;stun&amp;quot;: number, &amp;quot;unconscious&amp;quot;: number }&amp;lt;/code&amp;gt; (seconds)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;roundtime&amp;quot;: 0, &amp;quot;stun&amp;quot;: 0, &amp;quot;unconscious&amp;quot;: 0 }&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;roundtime&amp;quot;: 0, &amp;quot;stun&amp;quot;: 0, &amp;quot;unconscious&amp;quot;: 0 }&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== External.Discord — presence [In Progress] ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== External.Discord — presence [In Progress] ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l284&quot;&gt;Line 284:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 273:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Observed (client → server):&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;External.Discord.Hello&amp;lt;/code&amp;gt; with empty payload; UL treats support for &amp;lt;code&amp;gt;External.Discord&amp;lt;/code&amp;gt; as sufficient to emit &amp;lt;code&amp;gt;Info&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;Status&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Observed (client → server):&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;External.Discord.Hello&amp;lt;/code&amp;gt; with empty payload; UL treats support for &amp;lt;code&amp;gt;External.Discord&amp;lt;/code&amp;gt; as sufficient to emit &amp;lt;code&amp;gt;Info&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;Status&amp;lt;/code&amp;gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Handshake Transcript (illustrative) ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Handshake Transcript (illustrative) ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l294&quot;&gt;Line 294:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 282:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;GMCP -&amp;amp;gt; Core.Supports.Set [&amp;quot;Core 1&amp;quot;,&amp;quot;Char 1&amp;quot;,&amp;quot;Room 1&amp;quot;,&amp;quot;External.Discord 1&amp;quot;,&amp;quot;UL 1&amp;quot;]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;GMCP -&amp;amp;gt; Core.Supports.Set [&amp;quot;Core 1&amp;quot;,&amp;quot;Char 1&amp;quot;,&amp;quot;Room 1&amp;quot;,&amp;quot;External.Discord 1&amp;quot;,&amp;quot;UL 1&amp;quot;]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;... (Login Snapshot follows: Room.Info, Char.*, UL.*, External.Discord.*)&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;... (Login Snapshot follows: Room.Info, Char.*, UL.*, External.Discord.*)&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Client Expectations &amp;amp;amp; Best Practices ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Client Expectations &amp;amp;amp; Best Practices ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l303&quot;&gt;Line 303:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 290:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* For &amp;lt;code&amp;gt;UL.*&amp;lt;/code&amp;gt; messages, check for &amp;lt;code&amp;gt;&amp;quot;UL 1&amp;quot;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;Core.Supports.*&amp;lt;/code&amp;gt; if you want to be strict—UL currently emits them unconditionally to capable clients.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* For &amp;lt;code&amp;gt;UL.*&amp;lt;/code&amp;gt; messages, check for &amp;lt;code&amp;gt;&amp;quot;UL 1&amp;quot;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;Core.Supports.*&amp;lt;/code&amp;gt; if you want to be strict—UL currently emits them unconditionally to capable clients.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Time values in &amp;lt;code&amp;gt;External.Discord.Status.starttime&amp;lt;/code&amp;gt; are &amp;#039;&amp;#039;&amp;#039;Unix epoch seconds&amp;#039;&amp;#039;&amp;#039;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Time values in &amp;lt;code&amp;gt;External.Discord.Status.starttime&amp;lt;/code&amp;gt; are &amp;#039;&amp;#039;&amp;#039;Unix epoch seconds&amp;#039;&amp;#039;&amp;#039;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Future Additions (not yet emitted) ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Future Additions (not yet emitted) ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l310&quot;&gt;Line 310:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 296:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Incremental variants: &amp;lt;code&amp;gt;UL.Equipment.Add/Remove&amp;lt;/code&amp;gt;, etc.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Incremental variants: &amp;lt;code&amp;gt;UL.Equipment.Add/Remove&amp;lt;/code&amp;gt;, etc.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;UL.Info { version, schema }&amp;lt;/code&amp;gt; (alternative to advertising via &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt;)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;UL.Info { version, schema }&amp;lt;/code&amp;gt; (alternative to advertising via &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Change Log ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Change Log ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;#039;&amp;#039;&amp;#039;1.0&amp;#039;&amp;#039;&amp;#039; — Initial public spec for engine v1.0. Includes Core/Char/Room/External.Discord, and UL namespace (&amp;lt;code&amp;gt;Equipment/Languages/Spells/MartialArt(s)/Timers&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;#039;&amp;#039;&amp;#039;1.0&amp;#039;&amp;#039;&amp;#039; — Initial public spec for engine v1.0. Includes Core/Char/Room/External.Discord, and UL namespace (&amp;lt;code&amp;gt;Equipment/Languages/Spells/MartialArt(s)/Timers&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Dorandraco</name></author>
	</entry>
	<entry>
		<id>https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;diff=957&amp;oldid=prev</id>
		<title>Dorandraco: reformatting</title>
		<link rel="alternate" type="text/html" href="https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;diff=957&amp;oldid=prev"/>
		<updated>2025-08-30T19:01:02Z</updated>

		<summary type="html">&lt;p&gt;reformatting&lt;/p&gt;
&lt;a href=&quot;https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;amp;diff=957&amp;amp;oldid=956&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Dorandraco</name></author>
	</entry>
	<entry>
		<id>https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;diff=956&amp;oldid=prev</id>
		<title>Dorandraco: Created page with &quot;This document describes the GMCP (Generic MUD Communication Protocol) messages currently implemented by the Unwritten Legends server &#039;&#039;&#039;as observed in the 1.0 engine&#039;&#039;&#039;. It is intended for client authors (e.g., Mudlet packages) and for internal maintainers.   == Transport &amp;amp; Negotiation ==  UL implements GMCP as a Telnet subnegotiation:  * The server offers and accepts GMCP via Telnet &#039;&#039;&#039;DO/WILL GMCP&#039;&#039;&#039;. * After subnegotiation is active, the client typically sends &lt;co...&quot;</title>
		<link rel="alternate" type="text/html" href="https://unwrittenlegends.net/wiki/index.php?title=GMCP&amp;diff=956&amp;oldid=prev"/>
		<updated>2025-08-30T18:34:19Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;This document describes the GMCP (Generic MUD Communication Protocol) messages currently implemented by the Unwritten Legends server &amp;#039;&amp;#039;&amp;#039;as observed in the 1.0 engine&amp;#039;&amp;#039;&amp;#039;. It is intended for client authors (e.g., Mudlet packages) and for internal maintainers.   == Transport &amp;amp; Negotiation ==  UL implements GMCP as a Telnet subnegotiation:  * The server offers and accepts GMCP via Telnet &amp;#039;&amp;#039;&amp;#039;DO/WILL GMCP&amp;#039;&amp;#039;&amp;#039;. * After subnegotiation is active, the client typically sends &amp;lt;co...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This document describes the GMCP (Generic MUD Communication Protocol) messages currently implemented by the Unwritten Legends server &amp;#039;&amp;#039;&amp;#039;as observed in the 1.0 engine&amp;#039;&amp;#039;&amp;#039;. It is intended for client authors (e.g., Mudlet packages) and for internal maintainers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Transport &amp;amp;amp; Negotiation ==&lt;br /&gt;
&lt;br /&gt;
UL implements GMCP as a Telnet subnegotiation:&lt;br /&gt;
&lt;br /&gt;
* The server offers and accepts GMCP via Telnet &amp;#039;&amp;#039;&amp;#039;DO/WILL GMCP&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* After subnegotiation is active, the client typically sends &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt; and its &amp;lt;code&amp;gt;Core.Supports.Set/Add&amp;lt;/code&amp;gt; list. UL tracks the client’s advertised packages.&lt;br /&gt;
* The server replies with:&lt;br /&gt;
** &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt; (server identity/version)&lt;br /&gt;
** &amp;lt;code&amp;gt;Core.Supports.Set&amp;lt;/code&amp;gt; advertising what UL can emit.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Current advertised packages (server → client):&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;[&amp;quot;Core 1&amp;quot;, &amp;quot;Char 1&amp;quot;, &amp;quot;Room 1&amp;quot;, &amp;quot;External.Discord 1&amp;quot;, &amp;quot;UL 1&amp;quot;]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
UL recognizes client &amp;lt;code&amp;gt;Core.Supports.Set/Add&amp;lt;/code&amp;gt; and maintains a capability set but &amp;#039;&amp;#039;&amp;#039;does not require&amp;#039;&amp;#039;&amp;#039; capabilities to be declared to emit core messages. Custom UL messages are namespaced under &amp;lt;code&amp;gt;UL.*&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Namespaces ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Core.&amp;#039;&amp;#039;&amp;#039;* – handshake and feature advertisement.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Char.&amp;#039;&amp;#039;&amp;#039;* – character identity, state, vitals, stats.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Room.&amp;#039;&amp;#039;&amp;#039;* – current room/area summary.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;External.Discord.&amp;#039;&amp;#039;&amp;#039;* – rich presence metadata for Discord bridge.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;UL.&amp;#039;&amp;#039;&amp;#039;* – Unwritten Legends–specific messages (equipment, languages, spells, martial arts, timers, etc.).&lt;br /&gt;
&lt;br /&gt;
Versioning for the custom namespace is surfaced implicitly by the supported set (&amp;lt;code&amp;gt;&amp;quot;UL 1&amp;quot;&amp;lt;/code&amp;gt;). If/when a breaking schema appears, we will add &amp;lt;code&amp;gt;&amp;quot;UL 2&amp;quot;&amp;lt;/code&amp;gt; while leaving &amp;lt;code&amp;gt;UL 1&amp;lt;/code&amp;gt; available for a deprecation window.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Emission Triggers &amp;amp;amp; Frequency ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;On login/character entry:&amp;#039;&amp;#039;&amp;#039; the server emits a snapshot (marked &amp;#039;&amp;#039;Login Snapshot&amp;#039;&amp;#039; below).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;On pulse:&amp;#039;&amp;#039;&amp;#039; UL’s game loop runs a &amp;#039;&amp;#039;Pulse&amp;#039;&amp;#039; (about 5 s). Certain values (e.g., experience absorption, vitality regen) produce periodic GMCP updates even if unchanged elsewhere. Expect duplicates; clients should de-dup by content or simply accept repeats.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;On change:&amp;#039;&amp;#039;&amp;#039; Some messages are resent when values change (e.g., equipment, active language, room).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Client guidance:&amp;#039;&amp;#039;&amp;#039; handle idempotent updates and partial updates. Where keys are omitted on follow-up messages, merge into the client’s last known state.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Message Catalog ==&lt;br /&gt;
&lt;br /&gt;
Each entry lists &amp;#039;&amp;#039;&amp;#039;Topic&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;Direction&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;When&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;Schema&amp;#039;&amp;#039;&amp;#039;, and an &amp;#039;&amp;#039;&amp;#039;Example&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== Core ===&lt;br /&gt;
&lt;br /&gt;
==== Core.Hello ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; after GMCP negotiation and after receiving client hello (once per session)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;client&amp;quot;: string, &amp;quot;version&amp;quot;: string }&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;client&amp;quot;: &amp;quot;Unwritten Legends&amp;quot;, &amp;quot;version&amp;quot;: &amp;quot;1.0.0.0&amp;quot; }&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Core.Supports.Set ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; once after &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; array of strings &amp;lt;code&amp;gt;&amp;amp;lt;Package&amp;amp;gt; &amp;amp;lt;major&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;[&amp;quot;Core 1&amp;quot;, &amp;quot;Char 1&amp;quot;, &amp;quot;Room 1&amp;quot;, &amp;quot;External.Discord 1&amp;quot;, &amp;quot;UL 1&amp;quot;]&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;#039;&amp;#039;&amp;#039;Also observed (client → server):&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Core.Supports.Set&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Core.Supports.Add&amp;lt;/code&amp;gt;. The server records client capabilities for future gating but does not currently require them to emit core messages.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
=== 4.2 Room ===&lt;br /&gt;
&lt;br /&gt;
==== Room.Info ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; on room change; occasionally repeated for resilience&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;area&amp;quot;: string, &amp;quot;name&amp;quot;: string }&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;or&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;exits&amp;quot;: { string, ... } }&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;or&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;id&amp;quot;: { string } }&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;area&amp;quot;: &amp;quot;City of Kaezar&amp;quot;, &amp;quot;name&amp;quot;: &amp;quot;Tempest Road at Avanil Way, Crossroads&amp;quot; }&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;or&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;exits&amp;quot;: { &amp;quot;large stone building&amp;quot;, &amp;quot;west&amp;quot;, &amp;quot;south&amp;quot;, &amp;quot;east&amp;quot;, &amp;quot;north&amp;quot; } }&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;or&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;id&amp;quot;: { &amp;quot;8df6a052-9af2-5188-aff0-095e5d3d37a8&amp;quot; } }&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Future (not yet emitted): &amp;lt;code&amp;gt;Room.Players&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
=== 4.3 Character Identity &amp;amp;amp; State ===&lt;br /&gt;
&lt;br /&gt;
==== Char.Info ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; on identity changes (rare)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;pretitlename&amp;quot;: string,     // may be empty&lt;br /&gt;
  &amp;quot;name&amp;quot;: string,              // first name&lt;br /&gt;
  &amp;quot;lastname&amp;quot;: string,          // surname&lt;br /&gt;
  &amp;quot;truename&amp;quot;: string,&lt;br /&gt;
  &amp;quot;posttitle&amp;quot;: string,         // may be empty, includes punctuation&lt;br /&gt;
  &amp;quot;race&amp;quot;: string,              // lowercase&lt;br /&gt;
  &amp;quot;subrace&amp;quot;: string,           // lowercase&lt;br /&gt;
  &amp;quot;gender&amp;quot;: string,            // lowercase (e.g., &amp;quot;male&amp;quot;, &amp;quot;female&amp;quot;, &amp;quot;neuter&amp;quot;)&lt;br /&gt;
  &amp;quot;age&amp;quot;: number,               // years&lt;br /&gt;
  &amp;quot;profession&amp;quot;: string,        // lowercase&lt;br /&gt;
  &amp;quot;deity&amp;quot;: string,             // lowercase&lt;br /&gt;
  &amp;quot;patronmoon&amp;quot;: string,        // lowercase&lt;br /&gt;
  &amp;quot;dominant_hand&amp;quot;: string,     // &amp;quot;left&amp;quot; | &amp;quot;right&amp;quot;&lt;br /&gt;
  &amp;quot;level&amp;quot;: number&lt;br /&gt;
}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;pretitlename&amp;quot;:&amp;quot;Sir&amp;quot;,&lt;br /&gt;
  &amp;quot;name&amp;quot;:&amp;quot;Martaigne&amp;quot;,&lt;br /&gt;
  &amp;quot;lastname&amp;quot;:&amp;quot;Shardleigh&amp;quot;,&lt;br /&gt;
  &amp;quot;truename&amp;quot;:&amp;quot;Martaigne&amp;quot;,&lt;br /&gt;
  &amp;quot;posttitle&amp;quot;:&amp;quot;, Plydia&amp;#039;s Scourge&amp;quot;,&lt;br /&gt;
  &amp;quot;race&amp;quot;:&amp;quot;human&amp;quot;,&lt;br /&gt;
  &amp;quot;subrace&amp;quot;:&amp;quot;kivian&amp;quot;,&lt;br /&gt;
  &amp;quot;gender&amp;quot;:&amp;quot;male&amp;quot;,&lt;br /&gt;
  &amp;quot;age&amp;quot;:57,&lt;br /&gt;
  &amp;quot;profession&amp;quot;:&amp;quot;cleric&amp;quot;,&lt;br /&gt;
  &amp;quot;deity&amp;quot;:&amp;quot;thine&amp;quot;,&lt;br /&gt;
  &amp;quot;patronmoon&amp;quot;:&amp;quot;tallow&amp;quot;,&lt;br /&gt;
  &amp;quot;dominant_hand&amp;quot;:&amp;quot;right&amp;quot;,&lt;br /&gt;
  &amp;quot;level&amp;quot;:100&lt;br /&gt;
}&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Char.Status ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; when status elements change&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;position&amp;quot;: string, &amp;quot;stance&amp;quot;: string }&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;position&amp;quot;:&amp;quot;standing&amp;quot;, &amp;quot;stance&amp;quot;:&amp;quot;parry&amp;quot; }&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Char.Vitals ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; Pulse; any change&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;vitality&amp;quot;: number, &amp;quot;vitality_max&amp;quot;: number,&lt;br /&gt;
  &amp;quot;essence&amp;quot;: number,  &amp;quot;essence_max&amp;quot;: number,&lt;br /&gt;
  &amp;quot;stamina&amp;quot;: number,  &amp;quot;stamina_max&amp;quot;: number,&lt;br /&gt;
  &amp;quot;willpower&amp;quot;: number, &amp;quot;willpower_max&amp;quot;: number&lt;br /&gt;
}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;vitality&amp;quot;:320, &amp;quot;vitality_max&amp;quot;:360, &amp;quot;essence&amp;quot;:314, &amp;quot;essence_max&amp;quot;:314, &amp;quot;stamina&amp;quot;:310, &amp;quot;stamina_max&amp;quot;:310, &amp;quot;willpower&amp;quot;:218, &amp;quot;willpower_max&amp;quot;:218 }&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Char.Stats ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot (full); Pulse (partial: often just &amp;lt;code&amp;gt;experience_total&amp;lt;/code&amp;gt;); on changes&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema (full snapshot):&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;experience_total&amp;quot;: number,&lt;br /&gt;
  &amp;quot;experience_to_level&amp;quot;: number,&lt;br /&gt;
  &amp;quot;fame&amp;quot;: { &amp;quot;current&amp;quot;: number, &amp;quot;lifetime&amp;quot;: number },&lt;br /&gt;
  &amp;quot;skillpoints&amp;quot;: number,&lt;br /&gt;
  &amp;quot;arcana&amp;quot;: number,&lt;br /&gt;
  &amp;quot;lessons&amp;quot;: { &amp;quot;available&amp;quot;: number, &amp;quot;max&amp;quot;: number }&lt;br /&gt;
}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Partial updates:&amp;#039;&amp;#039;&amp;#039; UL may send only the keys that changed (e.g., &amp;lt;code&amp;gt;{ &amp;quot;experience_total&amp;quot;: 217000943 }&amp;lt;/code&amp;gt;). Clients should merge by key.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example (full):&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;experience_total&amp;quot;:216265943,&lt;br /&gt;
  &amp;quot;experience_to_level&amp;quot;:4410000000,&lt;br /&gt;
  &amp;quot;fame&amp;quot;:{&amp;quot;current&amp;quot;:102650,&amp;quot;lifetime&amp;quot;:193400},&lt;br /&gt;
  &amp;quot;skillpoints&amp;quot;:635,&lt;br /&gt;
  &amp;quot;arcana&amp;quot;:2265,&lt;br /&gt;
  &amp;quot;lessons&amp;quot;:{&amp;quot;available&amp;quot;:4,&amp;quot;max&amp;quot;:4}&lt;br /&gt;
}&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
=== 4.4 UL (Unwritten Legends) — custom namespace ===&lt;br /&gt;
&lt;br /&gt;
==== UL.Equipment.Set ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; on equipment/hand changes&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;slots&amp;quot;: { &amp;quot;left&amp;quot;: string, &amp;quot;right&amp;quot;: string, ... } }&lt;br /&gt;
Slot keys are lowercase; value is an item short name or &amp;lt;code&amp;gt;&amp;quot;none&amp;quot;&amp;lt;/code&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;slots&amp;quot;: { &amp;quot;left&amp;quot;: &amp;quot;none&amp;quot;, &amp;quot;right&amp;quot;: &amp;quot;battle-worn t&amp;#039;elt claidheamh-mor&amp;quot; } }&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== UL.Languages.Set ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; on language change&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{&amp;quot;active&amp;quot;: string, &amp;quot;known&amp;quot;: string[]}&amp;lt;/code&amp;gt; (all lowercase language ids)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{ &amp;quot;active&amp;quot;: &amp;quot;common&amp;quot;, &amp;quot;known&amp;quot;: [&amp;quot;orcish&amp;quot;,&amp;quot;elvish&amp;quot;,&amp;quot;anjour&amp;quot;, &amp;quot;common&amp;quot;] }&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== UL.Spells.Set ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; when circles known change&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;circles&amp;quot;: string[] }&amp;lt;/code&amp;gt; (string constants as used server-side)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;circles&amp;quot;: [&amp;quot;VIA_FIDE_NIVI&amp;quot;, &amp;quot;VIA_GLAS&amp;quot;, &amp;quot;VIA_TEG&amp;quot;] }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== UL.Spells.PreparedSpell ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; When spell is prepared or released&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;spelllongname&amp;quot;: string, &amp;quot;spellshortname&amp;quot;: string }&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ spelllongname = &amp;quot;Fire Cantrip&amp;quot;, spellshortname = &amp;quot;vf01&amp;quot; }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== UL.MartialArt.Active ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; when active style changes&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;style&amp;quot;: string, &amp;quot;moves&amp;quot;: string[] }&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;style&amp;quot;:&amp;quot;Qai Sun Crane&amp;quot;, &amp;quot;moves&amp;quot;:[&amp;quot;crescentkick&amp;quot;,&amp;quot;spinkick&amp;quot;,&amp;quot;roundhouse&amp;quot;] }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== UL.MartialArts.Set ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; when learned styles change&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;styles&amp;quot;: string[] }&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;styles&amp;quot;:[&amp;quot;Assault&amp;quot;,&amp;quot;Qai Sun Bear&amp;quot;,&amp;quot;Berserk&amp;quot;,&amp;quot;Brawling&amp;quot;] }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== UL.Timers ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; Pulse; on timer changes&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;roundtime&amp;quot;: number, &amp;quot;stun&amp;quot;: number, &amp;quot;unconscious&amp;quot;: number }&amp;lt;/code&amp;gt; (seconds)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;roundtime&amp;quot;: 0, &amp;quot;stun&amp;quot;: 0, &amp;quot;unconscious&amp;quot;: 0 }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
=== 4.5 External.Discord — presence [In Progress] ===&lt;br /&gt;
&lt;br /&gt;
==== External.Discord.Info ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot (if client supports &amp;lt;code&amp;gt;External.Discord&amp;lt;/code&amp;gt;); may be resent on config change&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;applicationid&amp;quot;: string, &amp;quot;inviteurl&amp;quot;: string, &amp;quot;gamename&amp;quot;: string }&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;{ &amp;quot;applicationid&amp;quot;:&amp;quot;1409606830350401667&amp;quot;, &amp;quot;inviteurl&amp;quot;:&amp;quot;https://discord.gg/yourinvite&amp;quot;, &amp;quot;gamename&amp;quot;:&amp;quot;Unwritten Legends&amp;quot; }&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Known Issues:&amp;#039;&amp;#039;&amp;#039; inviteurl is currently disabled from send as the Discord server is not public&lt;br /&gt;
&lt;br /&gt;
==== External.Discord.Status ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Dir:&amp;#039;&amp;#039;&amp;#039; server → client&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;When:&amp;#039;&amp;#039;&amp;#039; Login Snapshot; on presence changes (details/state/party/time)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Schema:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;details&amp;quot;: string,        // e.g., &amp;quot;martaigne • Adventurer&amp;quot;&lt;br /&gt;
  &amp;quot;state&amp;quot;: string,          // freeform (e.g., &amp;quot;Logging in...&amp;quot;)&lt;br /&gt;
  &amp;quot;largeimage&amp;quot;: string,     // key for Discord rich presence image&lt;br /&gt;
  &amp;quot;partysize&amp;quot;: number,&lt;br /&gt;
  &amp;quot;partymax&amp;quot;: number,&lt;br /&gt;
  &amp;quot;starttime&amp;quot;: number       // Unix epoch seconds&lt;br /&gt;
}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Example:&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;details&amp;quot;:&amp;quot;martaigne • Adventurer&amp;quot;,&lt;br /&gt;
  &amp;quot;state&amp;quot;:&amp;quot;Logging in...&amp;quot;,&lt;br /&gt;
  &amp;quot;largeimage&amp;quot;:&amp;quot;server-icon&amp;quot;,&lt;br /&gt;
  &amp;quot;partysize&amp;quot;:1,&lt;br /&gt;
  &amp;quot;partymax&amp;quot;:1,&lt;br /&gt;
  &amp;quot;starttime&amp;quot;:1756234455&lt;br /&gt;
}&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;#039;&amp;#039;&amp;#039;Observed (client → server):&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;External.Discord.Hello&amp;lt;/code&amp;gt; with empty payload; UL treats support for &amp;lt;code&amp;gt;External.Discord&amp;lt;/code&amp;gt; as sufficient to emit &amp;lt;code&amp;gt;Info&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;Status&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== 5) Handshake Transcript (illustrative) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;GMCP &amp;amp;lt;- Core.Hello { &amp;quot;client&amp;quot;:&amp;quot;Mudlet&amp;quot;, &amp;quot;version&amp;quot;:&amp;quot;4.19.1&amp;quot; }&lt;br /&gt;
GMCP &amp;amp;lt;- Core.Supports.Set [ &amp;quot;Char 1&amp;quot;, &amp;quot;Char.Skills 1&amp;quot;, &amp;quot;Char.Items 1&amp;quot;, &amp;quot;Room 1&amp;quot;, &amp;quot;IRE.Rift 1&amp;quot;, &amp;quot;IRE.Composer 1&amp;quot;, &amp;quot;External.Discord 1&amp;quot;, &amp;quot;Client.Media 1&amp;quot;, &amp;quot;Char.Login 1&amp;quot; ]&lt;br /&gt;
GMCP &amp;amp;lt;- External.Discord.Hello&lt;br /&gt;
GMCP -&amp;amp;gt; Core.Hello { &amp;quot;client&amp;quot;:&amp;quot;Unwritten Legends&amp;quot;, &amp;quot;version&amp;quot;:&amp;quot;1.0.0.0&amp;quot; }&lt;br /&gt;
GMCP -&amp;amp;gt; Core.Supports.Set [&amp;quot;Core 1&amp;quot;,&amp;quot;Char 1&amp;quot;,&amp;quot;Room 1&amp;quot;,&amp;quot;External.Discord 1&amp;quot;,&amp;quot;UL 1&amp;quot;]&lt;br /&gt;
... (Login Snapshot follows: Room.Info, Char.*, UL.*, External.Discord.*)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== 6) Client Expectations &amp;amp;amp; Best Practices ==&lt;br /&gt;
&lt;br /&gt;
* Treat repeated messages as &amp;#039;&amp;#039;&amp;#039;idempotent&amp;#039;&amp;#039;&amp;#039;; ignore duplicates or update your HUD accordingly.&lt;br /&gt;
* Expect &amp;#039;&amp;#039;&amp;#039;partial updates&amp;#039;&amp;#039;&amp;#039; (e.g., &amp;lt;code&amp;gt;Char.Stats&amp;lt;/code&amp;gt; with only &amp;lt;code&amp;gt;experience_total&amp;lt;/code&amp;gt;). Merge by key.&lt;br /&gt;
* Unknown keys are &amp;#039;&amp;#039;&amp;#039;forward-compatible&amp;#039;&amp;#039;&amp;#039;; ignore them safely.&lt;br /&gt;
* For &amp;lt;code&amp;gt;UL.*&amp;lt;/code&amp;gt; messages, check for &amp;lt;code&amp;gt;&amp;quot;UL 1&amp;quot;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;Core.Supports.*&amp;lt;/code&amp;gt; if you want to be strict—UL currently emits them unconditionally to capable clients.&lt;br /&gt;
* Time values in &amp;lt;code&amp;gt;External.Discord.Status.starttime&amp;lt;/code&amp;gt; are &amp;#039;&amp;#039;&amp;#039;Unix epoch seconds&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== 7) Future Additions (not yet emitted) ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Char.Affects.Set/Add/Remove&amp;lt;/code&amp;gt;&lt;br /&gt;
* Incremental variants: &amp;lt;code&amp;gt;UL.Equipment.Add/Remove&amp;lt;/code&amp;gt;, etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;UL.Info { version, schema }&amp;lt;/code&amp;gt; (alternative to advertising via &amp;lt;code&amp;gt;Core.Hello&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== 8) Change Log ==&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;1.0&amp;#039;&amp;#039;&amp;#039; — Initial public spec for engine v1.0. Includes Core/Char/Room/External.Discord, and UL namespace (&amp;lt;code&amp;gt;Equipment/Languages/Spells/MartialArt(s)/Timers&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Questions or schema proposals?&amp;#039;&amp;#039; Open an issue, or add examples at the bottom of this doc and tag maintainers.&lt;/div&gt;</summary>
		<author><name>Dorandraco</name></author>
	</entry>
</feed>