feat(core): D.2b-B — ClientObjectTable.SumCarriedBurden (carried-Burden fallback)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-21 08:55:35 +02:00
parent 5875ac857d
commit fb050aed4d
2 changed files with 61 additions and 0 deletions

View file

@ -274,6 +274,35 @@ public sealed class ClientObjectTable
_containerIndex.TryGetValue(containerId, out var l) _containerIndex.TryGetValue(containerId, out var l)
? l.ToArray() : System.Array.Empty<uint>(); ? l.ToArray() : System.Array.Empty<uint>();
/// <summary>
/// Σ Burden over every object carried by <paramref name="ownerGuid"/>: items
/// whose container chain roots at the owner (pack + side-bag contents, retail
/// hierarchy is 2-deep) plus items wielded by the owner. The client-side
/// equivalent of the server's <c>EncumbranceVal</c> (PropertyInt 5) — used by
/// the inventory burden bar until the wire value is parsed (B-Wire). The hop
/// cap (8) is a cycle guard; real chains are ≤2.
/// </summary>
public int SumCarriedBurden(uint ownerGuid)
{
int total = 0;
foreach (var o in _objects.Values)
if (IsCarriedBy(o, ownerGuid))
total += o.Burden;
return total;
}
private bool IsCarriedBy(ClientObject o, uint ownerGuid)
{
if (o.WielderId == ownerGuid) return true;
uint c = o.ContainerId;
for (int hops = 0; c != 0 && hops < 8; hops++)
{
if (c == ownerGuid) return true;
c = _objects.TryGetValue(c, out var parent) ? parent.ContainerId : 0u;
}
return false;
}
/// <summary> /// <summary>
/// Flush the table — typically called on logoff or teleport /// Flush the table — typically called on logoff or teleport
/// that drops the session's object state. /// that drops the session's object state.

View file

@ -0,0 +1,32 @@
using AcDream.Core.Items;
using Xunit;
namespace AcDream.Core.Tests.Items;
public class ClientObjectTableBurdenTests
{
private const uint Player = 0x50000001u;
[Fact]
public void SumCarriedBurden_sums_pack_sidebag_and_wielded_but_not_unrelated()
{
var t = new ClientObjectTable();
// loose pack item
t.AddOrUpdate(new ClientObject { ObjectId = 0xA, ContainerId = Player, Burden = 100 });
// side bag in pack
t.AddOrUpdate(new ClientObject { ObjectId = 0xB, ContainerId = Player, Burden = 50,
Type = ItemType.Container });
// item inside the side bag (2-deep)
t.AddOrUpdate(new ClientObject { ObjectId = 0xC, ContainerId = 0xB, Burden = 30 });
// wielded (ContainerId 0, WielderId = player)
t.AddOrUpdate(new ClientObject { ObjectId = 0xD, WielderId = Player, Burden = 200 });
// unrelated object in the world
t.AddOrUpdate(new ClientObject { ObjectId = 0xE, ContainerId = 0, Burden = 999 });
Assert.Equal(380, t.SumCarriedBurden(Player)); // 100+50+30+200
}
[Fact]
public void SumCarriedBurden_unknown_owner_is_zero()
=> Assert.Equal(0, new ClientObjectTable().SumCarriedBurden(Player));
}