EBLAN_ENGINE/docs/STABILIZATION.md
Игорь Федосеев 527d92411d chore: integrate main before stage 2
Preserve stage-1 stability fixes alongside v5 lighting, IPC v2, weapons and studio updates. Fix barrel AOE pointer corruption and extend modal gameplay gating.

Verify 137 editor checks, 191 ASM checks, lighting bake and preview parity. Document stage-2 scope without implementing it.
2026-10-31 22:10:07 +03:00

124 lines
7.2 KiB
Markdown

# Stabilization roadmap
Stages are delivered separately. Each completed stage is tested, committed and
pushed before work stops for confirmation. Editor and runtime UI redesign will
use an Unreal Engine 5-inspired visual style; stage 1 does not redesign UI.
## Stage 1 — correctness and data safety
Implemented:
- `DrawRectOutline` keeps loop counters in a callee-saved register, not the
volatile registers overwritten by `DrawPixel`. Nonpositive sizes draw nothing.
- `TraceShotWall` traverses current map cells independently of rendering. Distances
are 24.8 world units; closed doors, glass, portals and out-of-map cells block
shots. Open doors do not. Corner-adjacent walls block diagonal seam shots.
- Hitscan chooses the nearest live guard intersecting the forward billboard
hitbox. Half-width is 16 world units times authored scale (zero scale means
legacy 1.0), not a constant number of screen pixels.
- `IsGameplayBlocked` centralizes gameplay gating. `UpdatePlayer` latches blocked
ticks before processing cinematic state. AI, pickups and weapon timers freeze
during active/pending cutscenes and room fades. END/skip and instant transitions
cannot resume AI or fire stale input halfway through a tick. Death blocks player
movement, turning and firing; lethal damage stops the remaining entity pass.
- Packed entity metadata remains binary-compatible. Only `flags == 0` enables
legacy texture-based archetypes; any nonzero flags explicitly encode the low
type byte, including Prop. Health uses one byte: 1..255, zero = legacy 100 HP.
The C++ setter clamps before narrowing, and the inspector exposes 1..255.
- IDE source writes use a unique sibling temporary file, checked full write,
flush, close and atomic replacement. Failure preserves disk contents and dirty
buffer. Loading publishes a new document only after a complete valid text read.
File switches and builds stop on failed autosave. Saves target the file actually
opened, not a newly resolved fallback path.
- Compiler output is drained even with the IDE hidden. Process startup uses the
system command processor with quoting for project paths containing spaces.
### Verification
Windows commands:
```cmd
build.bat
editor\build_editor.bat
python tools\test_regressions.py
```
Results: editor **112/112**, ASM **148/148**. The suite also checks live x86/x64
preview IPC, DX11 pixel equality, cinematic trace equality and unchanged project
assets. New tests exercise production gameplay and IDE procedures, including
failed atomic replacement under a Windows sharing lock and hidden compiler output
exceeding pipe capacity. Interactive UI playtesting remains separate.
## Preparation for stage 2 — integration with current main
Integrated server history through `2bac213` with stage-1 commit `f42679f` in an
isolated worktree, preserving both histories and the original working directory.
Retained map v5, preview IPC v2, authored lighting, three weapons, explosive
barrels, modal dialogues, peaceful mode and the updated studio UI.
Compatibility adjustments:
- Pause and modal dialogue join the shared gameplay gate, including direct calls
to gameplay procedures. Blocked player updates cannot activate portal triggers.
- Knife/pistol/shotgun keep their range, damage, ammunition and reserved light
behavior. World-space half-widths are respectively 24/16/32 times sprite scale;
the shotgun remains a single-target wider hit test, not three separate rays.
- Barrel texture fallback is enabled only with zero flags in both editor and ASM.
Explicit Prop overrides barrel artwork and cannot explode.
- A new explosion regression reproduced access violation `0xC0000005`: the AOE
loop kept a sprite pointer in EDX and destroyed it with CDQ. The pointer now
stays in EBX. A nearby guard receives blast damage without crashing.
- IDE tab navigation, API catalog and docked view retain stage-1 safe writes.
Verification: both production builds succeeded; editor **137/137**, ASM
**191/191**. All 1024 baked RGB cells match between C++ and ASM; classic and lit
preview frames match direct ASM rendering, including the x86/x64/DX11 path.
Project assets remain byte-for-byte unchanged. The original working directory
still has only its pre-existing `editor/imgui.ini` modification. No separate
interactive UI playtest was performed during this preparation.
### Stage 2 implementation contract (not implemented here)
1. Separate message/input polling, fixed simulation ticks and drawing/presentation.
Use QPC and a 60 Hz accumulator with bounded catch-up. Consume edge-triggered
commands once, not once per catch-up tick. Reset timing debt after pause/focus
stalls; advance world timers/lights only on the appropriate simulation tick.
2. Keep movement fractions in runtime state without changing serialized raw-unit
coordinates. Cancel opposing inputs, normalize combined forward/strafe input,
and use symmetric signed accumulation. Clear fractions on load/teleport/restart.
3. Check the full collision body on each axis and preserve wall sliding; prevent
corner clipping and occupied-door closure. Keep portals intentionally walkable.
4. Centralize Playing/Cutscene/Transition/Dead/Paused/Dialog update rules, including
`Game_OnTick`, dynamic lights, fade, toasts and modal dismissal. Render routines
must not advance those timers or perform input-driven state changes.
5. Separate cinematic camera pose from gameplay/player position. Define END/skip
handoff explicitly and validate the restored gameplay collision body, including
paths crossing walls. Keep C++ preview and ASM cinematic traces aligned.
6. Track the current room path and its loaded entry spawn separately from startup
map. Restart restores that room and entry pose, resets gameplay transients and
fractional movement, and preserves project mode/settings. Failed reload must
not partially reset the current room. Make death-R and pause restart share it.
Acceptance checks: identical simulation after 60 ticks under different render
schedules; single consumption of edge inputs during catch-up; symmetric movement
for all quadrants and equal cardinal/diagonal speed; collision corner/slide cases;
no simulation advancement during pause/dialog; no pickups/AI along camera paths;
safe cinematic handoff; restart after a room transition; failed restart rollback;
unchanged v1..v5 loading, lighting bake parity and IPC v2 framebuffer parity.
## Remaining stages
2. Predictable simulation: fixed 60 Hz ticks, fractional movement, normalized
input, complete collision shape, current-room restart/reset policy. Extend
gameplay gating into explicit states and separate cinematic camera ownership.
3. Honest editor/gameplay: complete undo, keys/switches and supported interactions;
UE5-inspired editor/runtime UI redesign.
4. Project lifecycle and validated, safe standalone export.
5. Measurements and targeted renderer/editor optimizations.
6. Finished multi-room demo game and release verification.
7. Data-driven extensions and subsequent rendering features.
Stage 1 intentionally does not claim that all audit findings are fixed: restart
semantics, fixed timing, collision/AI visibility, full undo and exporter safety
remain assigned to subsequent stages. Existing map and texture assets are not
migrated or rewritten.