acdream/tests/AcDream.Core.Tests
Erik 07c5b832cf fix(#185): landblock collision part-id uint32 overflow dropped stair steps
Root cause (live capture #3 + code): GameWindow's per-part landblock shadow
registration used a synthetic part-id `entity.Id * 256u + partIndex` that
OVERFLOWS uint32 for class-prefixed landblock ids (0x40/0x80/0xC0...). The << 8
drops the prefix byte, so different-class entities sharing the low 24 bits
collide on ONE shadow part-id and Register's deregister-then-insert silently
overwrites one entity's collision geometry. Landblock 0xF682 had 23 such
collisions incl. the stair runs (0xF6822100 <- {0x40F68221, 0xC0F68221}, ...),
so 3 mid-staircase steps rendered but had no collision -> the player floats into
the hole and the (faithful) PrecipiceSlide wedge fires = the 'invisible wall
half-way up the stairs'.

Fix (Option A, retail-faithful): register each multi-part landblock entity via
ShadowObjectRegistry.RegisterMultiPart under its UNIQUE 32-bit entity.Id
(retail CPhysicsObj::add_shadows_to_cells 0x00514ae0 -> CPartArray::AddPartsShadow
- one object, a part array; no synthetic per-part id). New testable builder
ShadowShapeBuilder.FromLandblockBspParts decomposes each MeshRef.PartTransform to
local pos/rot/scale; RegisterMultiPart reconstructs the identical world placement.
Building shells stay excluded (building channel); the Setup cyl/sphere path is
unchanged (runs only when entityBsp==0, retail BSP-xor-cyl dispatch). Despawn is
landblock-scoped (RemoveLandblock by cell prefix), so the id change is safe.

Tests: ShadowRegistrationOverflowTests (overflow arithmetic; old scheme drops one;
RegisterMultiPart keeps both; builder). Issue185OutdoorStairsSeamReplayTests
(dat-free clean-climb pin). Core 2629 / App 741 green, 0 warnings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 10:07:50 +02:00
..
Allegiance feat(allegiance): Phase H.2 AllegianceRequests + AllegianceTree model 2026-04-18 17:17:45 +02:00
Audio feat(audio): Phase E.2 OpenAL engine + SoundTable cookbook + hook wiring 2026-04-18 16:38:26 +02:00
Chat fix(chat): /help client-side handler + System dedup + ThatIsNotAValidCommand template 2026-04-25 21:22:07 +02:00
Combat fix(combat): #159 — derive CombatAnimationMotionCommands from the DRW enum 2026-07-04 09:08:11 +02:00
Conformance refactor(pipeline): MP1a cleanup - narrow public surface, csproj parity, move residue 2026-07-05 20:52:01 +02:00
Fixtures fix(#185): landblock collision part-id uint32 overflow dropped stair steps 2026-07-08 10:07:50 +02:00
Input fix #174: RemoveLinkAnimations seam is HandleEnterWorld (strip + drain) 2026-07-05 16:33:41 +02:00
Items fix(D.2b): wield is ContainerId-based — drop the WielderId write (code review) 2026-06-22 22:15:18 +02:00
Lighting fix #176: light pool tracked the camera via flood scoping - collect residents, anchor at player 2026-07-06 15:12:31 +02:00
Meshing fix(render): hide editor-only placement markers in dungeons — port retail's degrade-to-nothing (#136) 2026-06-14 19:03:08 +02:00
Physics fix(#185): landblock collision part-id uint32 overflow dropped stair steps 2026-07-08 10:07:50 +02:00
Player feat(player): #5 PlayerDescription parser — Stam/Mana via attribute block 2026-04-25 16:42:24 +02:00
Plugins feat(D.2b): IUiRegistry plugin UI surface + buffered drain into UiHost 2026-06-14 17:46:37 +02:00
Rendering feat(lighting): SelectForCell (all dynamic lights per EnvCell) + #176 handoff — residual is a runtime z-fight 2026-07-06 13:55:16 +02:00
Selection test(picker): Cluster A #86 — screen-rect cell-occlusion tests 2026-05-19 14:56:51 +02:00
Spells fix(player): EnchantmentMask bit fix + Vitae key=0 + absolute Vitals overlay 2026-04-25 18:15:20 +02:00
Streaming fix(streaming): recover the player from the pending bucket — invisible-player / world-not-loading bug 2026-07-03 22:03:44 +02:00
Terrain fix #108-residual (root cause): terrain drew DOUBLE-SIDED - port retail landPolysDraw eye-side gate as terrain backface cull 2026-06-12 22:05:31 +02:00
Textures fix(textures): DecodeSolidColor null-safe against null ColorValue 2026-06-14 14:36:07 +02:00
Ui fix(retail): rotation rate, useability gate, retail toast strings 2026-05-16 12:17:54 +02:00
Vfx fix(vfx #56): ParticleHookSink applies CreateParticleHook.PartIndex transform 2026-05-11 23:57:20 +02:00
World feat(streaming): PhysicsDatBundle on LoadedLandblock (datLock fix scaffold) 2026-06-23 09:31:26 +02:00
AcDream.Core.Tests.csproj test: fix PhysicsResolveCapture/PhysicsDiagnostics static-leak isolation 2026-06-02 15:20:24 +02:00
SmokeTest.cs chore: phase 1 — add Core, Abstractions, App, Tests projects 2026-04-10 09:22:33 +02:00
xunit.runner.json test: fix PhysicsResolveCapture/PhysicsDiagnostics static-leak isolation 2026-06-02 15:20:24 +02:00