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:
parent
5875ac857d
commit
fb050aed4d
2 changed files with 61 additions and 0 deletions
|
|
@ -274,6 +274,35 @@ public sealed class ClientObjectTable
|
|||
_containerIndex.TryGetValue(containerId, out var l)
|
||||
? 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>
|
||||
/// Flush the table — typically called on logoff or teleport
|
||||
/// that drops the session's object state.
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue