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