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)
|
_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.
|
||||||
|
|
|
||||||
|
|
@ -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