feat(core): D.2b-B B-Wire — ClientObjectTable.UpsertProperties (create-if-absent)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ca94d1d2f6
commit
b56087b498
2 changed files with 67 additions and 0 deletions
|
|
@ -163,6 +163,32 @@ public sealed class ClientObjectTable
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a <see cref="PropertyBundle"/> patch, creating the object if it does not
|
||||
/// exist yet. Used for the local player's own properties from PlayerDescription
|
||||
/// (0x0013), which may arrive BEFORE the player's CreateObject — unlike
|
||||
/// <see cref="UpdateProperties"/>, which no-ops on an unknown object. Fires
|
||||
/// ObjectAdded on create, else ObjectUpdated.
|
||||
/// </summary>
|
||||
public void UpsertProperties(uint guid, PropertyBundle incoming)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(incoming);
|
||||
bool existed = _objects.TryGetValue(guid, out var item);
|
||||
if (!existed || item is null)
|
||||
{
|
||||
item = new ClientObject { ObjectId = guid };
|
||||
_objects[guid] = item;
|
||||
}
|
||||
foreach (var kv in incoming.Ints) item.Properties.Ints[kv.Key] = kv.Value;
|
||||
foreach (var kv in incoming.Int64s) item.Properties.Int64s[kv.Key] = kv.Value;
|
||||
foreach (var kv in incoming.Bools) item.Properties.Bools[kv.Key] = kv.Value;
|
||||
foreach (var kv in incoming.Floats) item.Properties.Floats[kv.Key] = kv.Value;
|
||||
foreach (var kv in incoming.Strings) item.Properties.Strings[kv.Key] = kv.Value;
|
||||
foreach (var kv in incoming.DataIds) item.Properties.DataIds[kv.Key] = kv.Value;
|
||||
foreach (var kv in incoming.InstanceIds) item.Properties.InstanceIds[kv.Key] = kv.Value;
|
||||
if (!existed) ObjectAdded?.Invoke(item); else ObjectUpdated?.Invoke(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a single PropertyInt update (from PublicUpdatePropertyInt 0x02CE) to an
|
||||
/// object: store it in the bundle and, for known typed ints, mirror to the typed
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
using AcDream.Core.Items;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.Core.Tests.Items;
|
||||
|
||||
public sealed class ClientObjectTableUpdateTests
|
||||
{
|
||||
[Fact]
|
||||
public void UpsertProperties_unknownObject_createsThenMerges()
|
||||
{
|
||||
var t = new ClientObjectTable();
|
||||
bool added = false;
|
||||
t.ObjectAdded += _ => added = true;
|
||||
|
||||
var bundle = new PropertyBundle();
|
||||
bundle.Ints[5] = 1234; // EncumbranceVal
|
||||
|
||||
t.UpsertProperties(0x50000001u, bundle);
|
||||
|
||||
var o = t.Get(0x50000001u);
|
||||
Assert.NotNull(o);
|
||||
Assert.Equal(1234, o!.Properties.Ints[5]);
|
||||
Assert.True(added);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpsertProperties_existingObject_mergesAndFiresUpdated()
|
||||
{
|
||||
var t = new ClientObjectTable();
|
||||
t.AddOrUpdate(new ClientObject { ObjectId = 0x50000001u });
|
||||
bool updated = false;
|
||||
t.ObjectUpdated += _ => updated = true;
|
||||
|
||||
var bundle = new PropertyBundle();
|
||||
bundle.Ints[5] = 99;
|
||||
t.UpsertProperties(0x50000001u, bundle);
|
||||
|
||||
Assert.Equal(99, t.Get(0x50000001u)!.Properties.Ints[5]);
|
||||
Assert.True(updated);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue