#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>
This commit is contained in:
Joe DiPrima
2026-07-30 01:20:13 -05:00
co-authored by Claude Fable 5
parent 0dbdad17f3
commit bf0555ccf1
3 changed files with 86 additions and 11 deletions
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# #81 GHOST REPRO: two nodes, BOTH die, watch the respawn handshake.
#
# Looking for, on either node:
# [dzreq] ... msgDeath= ourDeathCount= (the request side)
# [dz] GRANTED / STALL (the drop zone's answer)
# [ghost] DROP-ZONE REPLY DISCARDED (the silent-discard path)
# [respawn] ... RESET at drop zone (success)
# A node with a death cycle START and no RESET has reproduced the field ghost.
set -x
cd /c/git/bt411/content || exit 1
rm -f mp_a.log mp_b.log
sed 's/^experience=expert/experience=novice/' MP.EGG > MPG.EGG
# B first (listener), then A -- same order as the working mp_skate.sh
BT_LOG=mp_b.log BT_AFFINITY=0x2 BT_MP_LOG=1 BT_SCORE_LOG=1 BT_DEATH_LOG=1 \
BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_DELAY=40 \
../build/Release/btl4.exe -egg MPG.EGG -net 1601 &
sleep 2
BT_LOG=mp_a.log BT_AFFINITY=0x1 BT_MP_LOG=1 BT_SCORE_LOG=1 BT_DEATH_LOG=1 \
BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_DELAY=55 \
../build/Release/btl4.exe -egg MPG.EGG -net 1501 &
sleep 4
python ../tools/btconsole.py MPG.EGG 127.0.0.1:1501 127.0.0.1:1601 &
PC=$!
sleep 175
kill $PC 2>/dev/null
taskkill //F //IM btl4.exe 2>/dev/null
rm -f MPG.EGG
echo "=== DONE ==="