fix #62: null-guard the PARTSDIAG read of ae.Animation

B.4c sets Animation = null! for sequencer-driven door entities (sites
at line 2867 + 7892), but the declared type is non-nullable. Today
doors never enter _remoteDeadReckon (ACE doesn't send UpdatePosition
for them), so the PARTSDIAG block's unguarded read is unreachable —
but the moment something flips that, ACDREAM_REMOTE_VEL_DIAG=1 would
NRE the tick.

Local-var + is-not-null check keeps the guard scoped to this block;
the legacy slerp branch downstream still treats ae.Animation as
non-null per its declared type, so the flow analysis doesn't propagate
nullable warnings to unrelated sites.
This commit is contained in:
Erik 2026-05-14 17:12:48 +02:00
parent e55ad48ade
commit ec9fd52cb2

View file

@ -7682,9 +7682,19 @@ public sealed class GameWindow : IDisposable
{
int seqCount = seqFrames?.Count ?? -1;
int setupParts = ae.Setup.Parts.Count;
int animFrame0Parts = ae.Animation.PartFrames.Count > 0
? ae.Animation.PartFrames[0].Frames.Count
: -1;
// #62: B.4c introduced `Animation = null!` for sequencer-driven
// door entities (parallel branch sites at line 2867 + 7892).
// Doors don't currently enter _remoteDeadReckon, so this
// path isn't reachable for them today — but the read was
// unguarded and would NRE the moment something flips.
// Local-var + `is not null` keeps the guard scoped: the
// legacy slerp branch below treats ae.Animation as non-
// null (per its non-nullable declared type) unchanged.
var animMaybeNull = ae.Animation;
int animFrame0Parts =
animMaybeNull is not null && animMaybeNull.PartFrames.Count > 0
? animMaybeNull.PartFrames[0].Frames.Count
: -1;
double seqHash = 0.0;
if (seqFrames is not null)
{