fix(interaction): bind selection to live incarnations
Carry local WorldEntity identity through render hits, lighting pulses, and deferred movement actions so GUID reuse cannot target a replacement. Reset all session-owned selection and ItemHolder state and prevent combat auto-target during teardown.
This commit is contained in:
parent
c271383714
commit
047a4c83b5
19 changed files with 374 additions and 42 deletions
|
|
@ -11,7 +11,7 @@ namespace AcDream.App.Rendering.Selection;
|
|||
/// </summary>
|
||||
internal sealed class RetailSelectionScene : IRetailSelectionRenderSink, IRetailSelectionLightingSource
|
||||
{
|
||||
private readonly RetailSelectionGeometryCache _geometry;
|
||||
private readonly IRetailSelectionGeometrySource _geometry;
|
||||
private readonly RetailSelectionLightingPulse _lightingPulse;
|
||||
private List<RetailSelectionPart> _building = new();
|
||||
private List<RetailSelectionPart> _published = new();
|
||||
|
|
@ -21,7 +21,7 @@ internal sealed class RetailSelectionScene : IRetailSelectionRenderSink, IRetail
|
|||
private readonly record struct PartKey(uint LocalEntityId, int PartIndex, uint GfxObjId);
|
||||
|
||||
public RetailSelectionScene(
|
||||
RetailSelectionGeometryCache geometry,
|
||||
IRetailSelectionGeometrySource geometry,
|
||||
RetailSelectionLightingPulse? lightingPulse = null)
|
||||
{
|
||||
_geometry = geometry ?? throw new ArgumentNullException(nameof(geometry));
|
||||
|
|
@ -32,14 +32,27 @@ internal sealed class RetailSelectionScene : IRetailSelectionRenderSink, IRetail
|
|||
/// Starts retail's SmartBox click pulse independently of persistent target
|
||||
/// selection. Examine, use, and targeted-use clicks receive the same pulse.
|
||||
/// </summary>
|
||||
public void BeginLightingPulse(uint serverGuid)
|
||||
=> _lightingPulse.Start(serverGuid);
|
||||
public void BeginLightingPulse(uint serverGuid, uint localEntityId)
|
||||
=> _lightingPulse.Start(serverGuid, localEntityId);
|
||||
|
||||
public void TickLighting()
|
||||
=> _lightingPulse.Tick();
|
||||
|
||||
public bool TryGetLighting(uint serverGuid, out RetailSelectionLighting lighting)
|
||||
=> _lightingPulse.TryGet(serverGuid, out lighting);
|
||||
public bool TryGetLighting(
|
||||
uint serverGuid,
|
||||
uint localEntityId,
|
||||
out RetailSelectionLighting lighting)
|
||||
=> _lightingPulse.TryGet(serverGuid, localEntityId, out lighting);
|
||||
|
||||
/// <summary>Clears every session-owned frame and material pulse.</summary>
|
||||
public void Reset()
|
||||
{
|
||||
_building.Clear();
|
||||
_published.Clear();
|
||||
_buildingKeys.Clear();
|
||||
_viewFrustum = null;
|
||||
_lightingPulse.Clear();
|
||||
}
|
||||
|
||||
public void BeginFrame()
|
||||
{
|
||||
|
|
@ -76,6 +89,7 @@ internal sealed class RetailSelectionScene : IRetailSelectionRenderSink, IRetail
|
|||
|
||||
_building.Add(new RetailSelectionPart(
|
||||
entity.ServerGuid,
|
||||
entity.Id,
|
||||
partIndex,
|
||||
partWorld,
|
||||
mesh));
|
||||
|
|
@ -86,7 +100,7 @@ internal sealed class RetailSelectionScene : IRetailSelectionRenderSink, IRetail
|
|||
(_published, _building) = (_building, _published);
|
||||
}
|
||||
|
||||
public uint? Pick(
|
||||
public RetailSelectionHit? Pick(
|
||||
float mouseX,
|
||||
float mouseY,
|
||||
Vector2 viewport,
|
||||
|
|
@ -99,7 +113,7 @@ internal sealed class RetailSelectionScene : IRetailSelectionRenderSink, IRetail
|
|||
var ray = WorldPicker.BuildRay(
|
||||
mouseX, mouseY, viewport.X, viewport.Y, view, projection);
|
||||
return RetailWorldPicker.Pick(
|
||||
ray.Origin, ray.Direction, _published, skipServerGuid)?.ServerGuid;
|
||||
ray.Origin, ray.Direction, _published, skipServerGuid);
|
||||
}
|
||||
|
||||
internal static bool DrawingSphereIntersectsFrustum(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue