refactor(D.5.4): retire _liveEntityInfoByGuid; selection resolves from ClientObjectTable
The one weenie table now holds every object's name+type, so the redundant Name+ItemType dictionary is gone (retail: one weenie_object_table). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
50cee50df1
commit
a9d40addac
1 changed files with 16 additions and 34 deletions
|
|
@ -837,7 +837,6 @@ public sealed class GameWindow : IDisposable
|
|||
/// keys the render list; this parallel dictionary keys by server guid.
|
||||
/// </summary>
|
||||
private readonly Dictionary<uint, AcDream.Core.World.WorldEntity> _entitiesByServerGuid = new();
|
||||
private readonly Dictionary<uint, LiveEntityInfo> _liveEntityInfoByGuid = new();
|
||||
/// <summary>
|
||||
/// Latest <see cref="AcDream.Core.Net.WorldSession.EntitySpawn"/> for each
|
||||
/// guid. Captured at the end of <see cref="OnLiveEntitySpawnedLocked"/> so
|
||||
|
|
@ -854,9 +853,6 @@ public sealed class GameWindow : IDisposable
|
|||
// far-range sends fire the wire packet immediately at SendUse/SendPickUp
|
||||
// time. Cleared before the deferred send fires — single-fire, no retry.
|
||||
private (uint Guid, bool IsPickup)? _pendingPostArrivalAction;
|
||||
private readonly record struct LiveEntityInfo(
|
||||
string? Name,
|
||||
AcDream.Core.Items.ItemType ItemType);
|
||||
private static bool IsPlayerGuid(uint guid) => (guid & 0xFF000000u) == 0x50000000u;
|
||||
private const double ServerControlledVelocityStaleSeconds = 0.60;
|
||||
private int _liveSpawnReceived; // diagnostics
|
||||
|
|
@ -1302,7 +1298,7 @@ public sealed class GameWindow : IDisposable
|
|||
// live state from this GameWindow instance every frame:
|
||||
// - selected guid → _selectedGuid (set by PickAndStoreSelection)
|
||||
// - entity resolver → position from _entitiesByServerGuid +
|
||||
// itemType / PWD bits from cached LiveEntityInfo + last spawn
|
||||
// itemType from ClientObjectTable (Objects) + last spawn
|
||||
// - camera → _cameraController.Active or (zero) when not
|
||||
// yet ready, in which case the panel bails on viewport==0.
|
||||
_targetIndicator = new AcDream.App.UI.TargetIndicatorPanel(
|
||||
|
|
@ -1311,9 +1307,7 @@ public sealed class GameWindow : IDisposable
|
|||
{
|
||||
if (!_entitiesByServerGuid.TryGetValue(guid, out var entity))
|
||||
return null;
|
||||
uint rawItemType = 0;
|
||||
if (_liveEntityInfoByGuid.TryGetValue(guid, out var info))
|
||||
rawItemType = (uint)info.ItemType;
|
||||
uint rawItemType = (uint)LiveItemType(guid);
|
||||
uint pwdBits = 0;
|
||||
uint? useability = null;
|
||||
if (_lastSpawnByGuid.TryGetValue(guid, out var spawn))
|
||||
|
|
@ -2706,12 +2700,6 @@ public sealed class GameWindow : IDisposable
|
|||
$"itemType={itemTypeStr} animParts={animPartCount} texChanges={texChangeCount} subPalettes={subPalCount}");
|
||||
}
|
||||
|
||||
_liveEntityInfoByGuid[spawn.Guid] = new LiveEntityInfo(
|
||||
spawn.Name,
|
||||
spawn.ItemType is { } rawItemType
|
||||
? (AcDream.Core.Items.ItemType)rawItemType
|
||||
: AcDream.Core.Items.ItemType.None);
|
||||
|
||||
// Target the statue specifically for full diagnostic dump: Name match
|
||||
// is cheap and gives us exactly one entity's worth of log regardless
|
||||
// of arrival order.
|
||||
|
|
@ -3717,7 +3705,6 @@ public sealed class GameWindow : IDisposable
|
|||
// clear using the same guid the next spawn/update would use.
|
||||
_remoteDeadReckon.Remove(serverGuid);
|
||||
_remoteLastMove.Remove(serverGuid);
|
||||
_liveEntityInfoByGuid.Remove(serverGuid);
|
||||
_entitiesByServerGuid.Remove(serverGuid);
|
||||
_lastSpawnByGuid.Remove(serverGuid);
|
||||
if (_selectedGuid == serverGuid)
|
||||
|
|
@ -3809,8 +3796,7 @@ public sealed class GameWindow : IDisposable
|
|||
|
||||
// Per-Door UM dispatch trail; grep [door-cycle] in launch.log to verify door animation.
|
||||
if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeBuildingEnabled
|
||||
&& _liveEntityInfoByGuid.TryGetValue(update.Guid, out var doorInfo)
|
||||
&& IsDoorName(doorInfo.Name))
|
||||
&& IsDoorName(LiveName(update.Guid)))
|
||||
{
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[door-cycle] guid=0x{update.Guid:X8} stance=0x{stance:X4} cmd=0x{(command ?? 0u):X4}"));
|
||||
|
|
@ -11590,9 +11576,7 @@ public sealed class GameWindow : IDisposable
|
|||
// RadarBlipColor are produced for the just-picked entity.
|
||||
// Helps verify whether a "green NPC" really is flagged as
|
||||
// Vendor server-side or whether our lookup is wrong.
|
||||
uint rawItemType = 0;
|
||||
if (_liveEntityInfoByGuid.TryGetValue(guid, out var info))
|
||||
rawItemType = (uint)info.ItemType;
|
||||
uint rawItemType = (uint)LiveItemType(guid);
|
||||
uint pwdBits = 0;
|
||||
uint? pickUseability = null;
|
||||
float? pickUseRadius = null;
|
||||
|
|
@ -11649,8 +11633,7 @@ public sealed class GameWindow : IDisposable
|
|||
// Retail string at acclient_2013_pseudo_c.txt:1033115
|
||||
// (data_7e2a70): "The %s cannot be used".
|
||||
|
||||
bool isCreature = _liveEntityInfoByGuid.TryGetValue(sel, out var info)
|
||||
&& (info.ItemType & AcDream.Core.Items.ItemType.Creature) != 0;
|
||||
bool isCreature = (LiveItemType(sel) & AcDream.Core.Items.ItemType.Creature) != 0;
|
||||
|
||||
if (isCreature)
|
||||
{
|
||||
|
|
@ -11891,8 +11874,7 @@ public sealed class GameWindow : IDisposable
|
|||
|
||||
// Mirror InstallSpeculativeTurnToTarget's per-type radius heuristic.
|
||||
float useRadius = 0.6f;
|
||||
if (_liveEntityInfoByGuid.TryGetValue(targetGuid, out var info)
|
||||
&& (info.ItemType & AcDream.Core.Items.ItemType.Creature) != 0)
|
||||
if ((LiveItemType(targetGuid) & AcDream.Core.Items.ItemType.Creature) != 0)
|
||||
{
|
||||
useRadius = 3.0f;
|
||||
}
|
||||
|
|
@ -11919,8 +11901,7 @@ public sealed class GameWindow : IDisposable
|
|||
// Per-type use radius — same heuristic as the picker's
|
||||
// radiusForGuid callback.
|
||||
float useRadius = 0.6f;
|
||||
if (_liveEntityInfoByGuid.TryGetValue(targetGuid, out var info)
|
||||
&& (info.ItemType & AcDream.Core.Items.ItemType.Creature) != 0)
|
||||
if ((LiveItemType(targetGuid) & AcDream.Core.Items.ItemType.Creature) != 0)
|
||||
{
|
||||
useRadius = 3.0f;
|
||||
}
|
||||
|
|
@ -12001,10 +11982,8 @@ public sealed class GameWindow : IDisposable
|
|||
return false;
|
||||
if (!_entitiesByServerGuid.ContainsKey(guid))
|
||||
return false;
|
||||
if (!_liveEntityInfoByGuid.TryGetValue(guid, out var info))
|
||||
return false;
|
||||
|
||||
return (info.ItemType & AcDream.Core.Items.ItemType.Creature) != 0;
|
||||
return (LiveItemType(guid) & AcDream.Core.Items.ItemType.Creature) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -12171,8 +12150,7 @@ public sealed class GameWindow : IDisposable
|
|||
// `ItemUseable = null`; without the fallback the M1 "click NPC"
|
||||
// flow regresses. The diagnostic line below lets us measure
|
||||
// how often this branch fires in real play.
|
||||
if (_liveEntityInfoByGuid.TryGetValue(guid, out var info)
|
||||
&& (info.ItemType & AcDream.Core.Items.ItemType.Creature) != 0)
|
||||
if ((LiveItemType(guid) & AcDream.Core.Items.ItemType.Creature) != 0)
|
||||
{
|
||||
if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeUseabilityFallbackEnabled)
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
|
|
@ -12280,11 +12258,15 @@ public sealed class GameWindow : IDisposable
|
|||
return (it & SmallItemMask) != 0u;
|
||||
}
|
||||
|
||||
private AcDream.Core.Items.ItemType LiveItemType(uint guid) =>
|
||||
Objects.Get(guid)?.Type ?? AcDream.Core.Items.ItemType.None;
|
||||
|
||||
private string? LiveName(uint guid) => Objects.Get(guid)?.Name;
|
||||
|
||||
private string DescribeLiveEntity(uint guid)
|
||||
{
|
||||
if (_liveEntityInfoByGuid.TryGetValue(guid, out var info)
|
||||
&& !string.IsNullOrWhiteSpace(info.Name))
|
||||
return info.Name!;
|
||||
var name = LiveName(guid);
|
||||
if (!string.IsNullOrWhiteSpace(name)) return name!;
|
||||
return $"0x{guid:X8}";
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue