Commit Graph
3 Commits
Author SHA1 Message Date
Joe DiPrimaandClaude Fable 5 bf0555ccf1 #81: every MP respawn is a cross-machine round trip -- one degraded peer ghosts everyone
Two-node bench with the fixed host:local labels shows each player's drop-zone
request is answered by the OTHER machine's DropZone: A asks, B grants; B asks, A
grants.  FindGroup("DropZones") iterates replicants of remotely-mastered zones
too and takes the geometrically closest, so a respawn is
  my request -> an arbitrary peer's DropZone -> that peer's reply -> back to me.
With 5 players that is 5 round trips through arbitrary peers, and ONE degraded
peer can strand everybody else's respawn.  That finally explains the otherwise
unexplained field datum that one machine stopped processing the death-transition
stream 57% into a match and never recovered (0 explosions/wreck swaps/burials
while four other machines logged 4/4/4) -- a node in that state cannot answer
anyone's respawn.  It also explains why solo is 100% reliable (in-process) and
why a healthy 2-node bench passes.

Also fixes the instrumentation before it costs a night: every [dz] line printed
"entity 1" because a player's LOCAL entity id is 1 on every machine -- with five
players the log would have said a respawn stalled but not WHOSE.  All [dz] lines
now print host:local (including the usedBy= owner of each busy slot).

Doc: two candidate fixes recorded (prefer a locally-mastered DropZone / make the
reply path tolerant of a deathCount that is ahead of ours), neither to be guessed
at -- the [ghost] DISCARDED line's mismatch direction decides it in one line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 01:20:13 -05:00
Joe DiPrimaandClaude Fable 5 ba6756c40a drop-zone / respawn instrumentation: make the GHOST MECH visible in field logs
The ghost (a player who dies, never respawns, stays dead-but-driveable and is a
wreck on every peer) traces to a respawn stalling on drop-zone acquisition:
DropZone::AssignDropZoneMessageHandler grants a slot only if IsAvailable(), and
when none is free it reposts to ITSELF every 0.1s at MaxEventPriority and never
replies -- so deathPending is never cleared.  This whole subsystem was DARK: not
one drop-zone line in a full night of field logs.

ALWAYS-ON (no env gate -- rare, catastrophic, field-only, same rationale as the
#57/#59 guards; volume bounded and rate-limited):
  [dz] POOL   -- slots + downTime + proximity radius, once per mission
  [dz] GRANTED-- one per respawn, with the WAIT time; tags (GHOST RECOVERED)
                 when a long-stalled request finally lands (what testers see as
                 "it fixed itself")
  [dz] STALL / GHOST LIKELY -- escalating, per-waiter rate-limited, and it names
                 WHY each slot is busy (age + last user), which discriminates
                 cooldown saturation from proximity blocking -- different fixes
  [dzreq]     -- the REQUESTER half: re-try count for this death, and msgDeath vs
                 our own deathCount.  The engine gates the hunt on those being
                 equal AND the DropZone resend net is keyed on the same value, so
                 a mismatch breaks both silently (cf #45, tally replication).
BT_DROPZONE_LOG=1 adds the verbose per-request slot dump for bench work.

First run already overturned a theory: slots=8, so an 8-slot pool cannot be
cooldown-starved by 5 players (max 5 on cooldown at once) -- the shared
dropzone=one in eggmodel.py is NOT the bottleneck.  Suspicion moves to the
handshake (lost reply / deathCount mismatch).

Verified with NO env vars set, exactly as a tester runs it: 4 probe lines for a
full death+respawn cycle, all in the normal day log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 00:13:14 -05:00
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00