feat(items): port retail external-container looting
Add the ClientUISystem ground-object lifecycle, authoritative root and nested ViewContents projections, replacement and close semantics, and the DAT-authored gmExternalContainerUI strip for chests and corpses. Route double-click loot and full or partial drag transfers through the shared retail item policy without optimistic external ownership. Remove the incorrect NoLongerViewingContents behavior from owned side packs and retire AP-106/#196. Release build succeeds and all 5,875 tests pass with five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
48a118db91
commit
20ce67b625
27 changed files with 1750 additions and 45 deletions
|
|
@ -0,0 +1,50 @@
|
|||
using AcDream.App.World;
|
||||
using AcDream.Core.Items;
|
||||
|
||||
namespace AcDream.App.Tests.World;
|
||||
|
||||
public sealed class ExternalContainerLifecycleControllerTests
|
||||
{
|
||||
[Fact]
|
||||
public void Replacement_RetiresPreviousRootExactlyOnce()
|
||||
{
|
||||
var state = new ExternalContainerState();
|
||||
var objects = new ClientObjectTable();
|
||||
var retired = new List<uint>();
|
||||
using var controller = new ExternalContainerLifecycleController(state, objects, retired.Add);
|
||||
objects.AddOrUpdate(new ClientObject { ObjectId = 100u });
|
||||
objects.ReplaceContents(10u, new[] { new ContainerContentEntry(100u, 0u) });
|
||||
|
||||
state.RequestOpen(10u);
|
||||
state.ApplyViewContents(10u);
|
||||
state.RequestOpen(20u);
|
||||
state.ApplyViewContents(20u);
|
||||
state.ApplyViewContents(20u);
|
||||
|
||||
Assert.Equal(new uint[] { 10u }, retired);
|
||||
Assert.Empty(objects.GetContents(10u));
|
||||
Assert.NotNull(objects.Get(100u));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AuthoredCloseAndReset_DoNotSendNoLongerViewing()
|
||||
{
|
||||
var state = new ExternalContainerState();
|
||||
var objects = new ClientObjectTable();
|
||||
var retired = new List<uint>();
|
||||
using var controller = new ExternalContainerLifecycleController(state, objects, retired.Add);
|
||||
|
||||
state.RequestOpen(10u);
|
||||
state.ApplyViewContents(10u);
|
||||
objects.ReplaceContents(10u, new[] { new ContainerContentEntry(100u, 0u) });
|
||||
state.ApplyClose(10u);
|
||||
Assert.Empty(objects.GetContents(10u));
|
||||
state.RequestOpen(20u);
|
||||
state.ApplyViewContents(20u);
|
||||
objects.ReplaceContents(20u, new[] { new ContainerContentEntry(200u, 0u) });
|
||||
state.Reset();
|
||||
|
||||
Assert.Empty(retired);
|
||||
Assert.Empty(objects.GetContents(20u));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue