feat(D.5.4): add item fields to ClientObject + WeenieData ingest DTO
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b00a373c5a
commit
b83f17a927
2 changed files with 73 additions and 1 deletions
|
|
@ -127,7 +127,7 @@ public sealed class PropertyBundle
|
||||||
public sealed class ClientObject
|
public sealed class ClientObject
|
||||||
{
|
{
|
||||||
public uint ObjectId { get; init; }
|
public uint ObjectId { get; init; }
|
||||||
public uint WeenieClassId { get; init; } // "blueprint"
|
public uint WeenieClassId { get; set; } // "blueprint"
|
||||||
public string Name { get; set; } = "";
|
public string Name { get; set; } = "";
|
||||||
public ItemType Type { get; set; }
|
public ItemType Type { get; set; }
|
||||||
public EquipMask ValidLocations { get; set; }
|
public EquipMask ValidLocations { get; set; }
|
||||||
|
|
@ -150,9 +150,49 @@ public sealed class ClientObject
|
||||||
public int ContainerSlot { get; set; } = -1;
|
public int ContainerSlot { get; set; } = -1;
|
||||||
public bool Attuned { get; set; }
|
public bool Attuned { get; set; }
|
||||||
public bool Bonded { get; set; }
|
public bool Bonded { get; set; }
|
||||||
|
public uint WielderId { get; set; } // PropertyInstanceId.Wielder; 0 = not wielded
|
||||||
|
public int ItemsCapacity { get; set; } // main-pack slots (containers)
|
||||||
|
public int ContainersCapacity{ get; set; } // side-pack slots (containers)
|
||||||
|
public uint Priority { get; set; } // ClothingPriority / CoverageMask layer order
|
||||||
|
public int Structure { get; set; } // charges/uses remaining
|
||||||
|
public int MaxStructure { get; set; }
|
||||||
|
public float Workmanship { get; set; } // 0..10 (fractional on the wire)
|
||||||
public PropertyBundle Properties { get; } = new();
|
public PropertyBundle Properties { get; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The wire-delivered patch from a <c>CreateObject</c> (0xF745). Nullable fields
|
||||||
|
/// were gated by a WeenieHeader flag that was ABSENT — the merge upsert
|
||||||
|
/// (ClientObjectTable.Ingest) leaves the existing value untouched
|
||||||
|
/// for those, matching retail's <c>SetWeenieDesc</c> (patches only present fields).
|
||||||
|
/// Non-nullable id/effect fields use 0 = "not sent". Effects is assigned
|
||||||
|
/// unconditionally (0 clears) — the D.5.2 icon contract. Quantity fields are
|
||||||
|
/// int? (ACE PropertyInt convention); id/mask fields are uint?.
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct WeenieData(
|
||||||
|
uint Guid,
|
||||||
|
string? Name,
|
||||||
|
ItemType? Type,
|
||||||
|
uint WeenieClassId,
|
||||||
|
uint IconId,
|
||||||
|
uint IconOverlayId,
|
||||||
|
uint IconUnderlayId,
|
||||||
|
uint Effects,
|
||||||
|
int? Value,
|
||||||
|
int? StackSize,
|
||||||
|
int? StackSizeMax,
|
||||||
|
int? Burden,
|
||||||
|
uint? ContainerId,
|
||||||
|
uint? WielderId,
|
||||||
|
uint? ValidLocations,
|
||||||
|
uint? CurrentWieldedLocation,
|
||||||
|
uint? Priority,
|
||||||
|
int? ItemsCapacity,
|
||||||
|
int? ContainersCapacity,
|
||||||
|
int? Structure,
|
||||||
|
int? MaxStructure,
|
||||||
|
float? Workmanship);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Container = inventory pack. Hierarchy is strictly 2-deep: character
|
/// Container = inventory pack. Hierarchy is strictly 2-deep: character
|
||||||
/// → side packs; a side pack cannot hold another side pack (r06 §7).
|
/// → side packs; a side pack cannot hold another side pack (r06 §7).
|
||||||
|
|
|
||||||
|
|
@ -198,4 +198,36 @@ public sealed class ClientObjectTableTests
|
||||||
Assert.True(ok);
|
Assert.True(ok);
|
||||||
Assert.Equal(0u, repo.Get(0x500000ADu)!.Effects);
|
Assert.Equal(0u, repo.Get(0x500000ADu)!.Effects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ClientObject_NewFields_DefaultAndSettable()
|
||||||
|
{
|
||||||
|
var o = new ClientObject
|
||||||
|
{
|
||||||
|
ObjectId = 1, WielderId = 0x42u, ItemsCapacity = 24, ContainersCapacity = 7,
|
||||||
|
Priority = 8u, Structure = 5, MaxStructure = 10, Workmanship = 7.5f,
|
||||||
|
};
|
||||||
|
o.WeenieClassId = 0xABCDu; // now settable
|
||||||
|
Assert.Equal(0x42u, o.WielderId);
|
||||||
|
Assert.Equal(24, o.ItemsCapacity);
|
||||||
|
Assert.Equal(7, o.ContainersCapacity);
|
||||||
|
Assert.Equal(8u, o.Priority);
|
||||||
|
Assert.Equal(5, o.Structure);
|
||||||
|
Assert.Equal(10, o.MaxStructure);
|
||||||
|
Assert.Equal(7.5f, o.Workmanship);
|
||||||
|
Assert.Equal(0xABCDu, o.WeenieClassId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WeenieData_Construct()
|
||||||
|
{
|
||||||
|
var d = new WeenieData(Guid: 1, Name: "x", Type: ItemType.Misc, WeenieClassId: 2,
|
||||||
|
IconId: 0x06001234u, IconOverlayId: 0, IconUnderlayId: 0, Effects: 0,
|
||||||
|
Value: 5, StackSize: 1, StackSizeMax: 1, Burden: 10,
|
||||||
|
ContainerId: 0x99u, WielderId: null, ValidLocations: null,
|
||||||
|
CurrentWieldedLocation: null, Priority: null,
|
||||||
|
ItemsCapacity: null, ContainersCapacity: null,
|
||||||
|
Structure: null, MaxStructure: null, Workmanship: null);
|
||||||
|
Assert.Equal(0x99u, d.ContainerId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue