Build against plugin API 0.1.19-mm.1; item header words from the host

The contract now reports each object's description header, so the item
record carries the words the original's framework filed from it: the weenie
and second header flags, the physics description flags, the setup id, the
scale key (0.0 whenever a scale was sent, as recorded), the hook type, the
parent and parent location, and the framework's own summary word (key
218103831: stackable, has a position, lockable, inscribable, usable,
container), derived from the header by a rule that matches all 2,220 recorded
items carrying both words. With the header flags known, key presence follows
the header exactly instead of guessing from non-zero values: a recorded
Pyreal Mote now rebuilds key for key.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-25 12:58:43 +02:00
parent 0af4efb6b6
commit 50a173ef25
5 changed files with 121 additions and 5 deletions

View file

@ -61,8 +61,9 @@ internal interface IItemHeaderSource
}
/// <summary>
/// The contract this plugin builds against exposes none of these words, so
/// every one is absent. Replace this when the contract grows them.
/// The header words from the object description the host kept for the item.
/// An item without one (built from a vendor listing, say) has none, and every
/// word is then absent.
/// </summary>
internal sealed class HostItemHeaderSource : IItemHeaderSource
{
@ -72,5 +73,50 @@ internal sealed class HostItemHeaderSource : IItemHeaderSource
{
}
public ItemHeaderWords Read(in PluginInventoryItem item) => default;
public ItemHeaderWords Read(in PluginInventoryItem item)
{
if (item.Header is not { } header)
return default;
return new ItemHeaderWords
{
WeenieHeaderFlags = header.WeenieHeaderFlags,
WeenieHeaderFlags2 = header.WeenieHeaderFlags2,
PhysicsDescriptionFlags = header.PhysicsDescriptionFlags,
PhysicsWord = header.WeenieHeaderFlags is uint weenie
? FrameworkFlags(weenie, header.PhysicsDescriptionFlags ?? 0u, item.ItemType, header.ObjectDescriptionFlags ?? item.PublicFlags)
: null,
SetupId = header.SetupId,
// The framework filed 0.0 under its scale key whenever the
// physics description carried a scale, whatever the scale was.
Scale = header.Scale is null ? null : 0.0,
ParentObjectId = header.ParentObjectId,
ParentLocation = header.ParentLocation is uint location ? unchecked((int)location) : null,
HookType = header.HookType is uint hook ? unchecked((int)hook) : null,
};
}
/// <summary>
/// The framework's own summary word it kept per object (key 218103831),
/// derived from the header: stackable, has a position, lockable,
/// inscribable, usable, a container. Checked against every recorded item
/// that carries both this word and the header flags.
/// </summary>
internal static uint FrameworkFlags(uint weenieFlags, uint physicsFlags, uint itemType, uint descriptionFlags)
{
uint flags = 0u;
if ((weenieFlags & 0x3000u) != 0u)
flags |= 0x01u; // stack size or maximum stack size sent
if ((physicsFlags & 0x8000u) != 0u)
flags |= 0x02u; // a position sent
if ((itemType & 0x20000u) != 0u)
flags |= 0x04u; // a lockable type
if ((descriptionFlags & 0x2u) != 0u)
flags |= 0x10u; // inscribable
if ((weenieFlags & 0xC00u) != 0u)
flags |= 0x20u; // uses left or total uses sent
if ((weenieFlags & 0x6u) != 0u)
flags |= 0x80u; // item or pack capacity sent
return flags;
}
}

View file

@ -6,7 +6,7 @@
"apiVersion": 1,
"kinds": ["Gameplay"],
"hosts": ["Graphical", "Headless"],
"minHostVersion": "0.1.18",
"minHostVersion": "0.1.19",
"capabilitiesVersion": 1,
"capabilities": [
{ "name": "network", "note": "Streams telemetry, vitals, chat, inventory and stats to the Mosswart Overlord backend, and receives shared vitals and chat-box commands from it." },