What the first six-player night found

Playtest of 2026-08-11: sixteen logs, three crash dumps, six players. The
great races were most of the evening; this commit is about the rest.

Two of the three dumps are the same crash on the same instruction:
L4NetworkManager::Send at cmp [ebx+24h],3 with ebx NULL - GetConnectStatus
called on the nothing GetRemoteHost returned. Both machines show the same
scene: podium up, a peer just disconnected, and
DropZone::AssignDropZoneMessageHandler dispatching through Entity::Dispatch
to a host with no row in the table. Rows never leave the table (disconnect
only marks a host offline), so the ID was never adopted - and host -1 is
sitting in every log as 'Entity -1:106 class42', the ownerless map
entities, with GetRemoteHost's Verify(host_ID >= FirstLegalHostID)
compiled out in release. Send and SendMessageToNetnub now treat an absent
host exactly like an offline one - message dropped - and Send logs the ID,
client and message so the next occurrence names the actual sender instead
of needing a debugger.

The sync-to-start failures are one badly-NATed machine plus a deadline of
mine. Steam's first attempt at that peer goes direct, burns about ten
seconds, and dies (reasons 5003/5008); the second attempt comes up through
the relay and succeeds WHENEVER IT IS GIVEN TIME. RP412CONNECTWAIT was a
single budget across all attempts, so the relay attempt inherited the
scraps - the logs show 'attempt 2 ended in state 1', still connecting, at
the 20s cutoff. The deadline is per attempt now, three attempts at most:
the awkward router connects in about half a minute, a truly absent peer
costs under a minute, the title bar names the try, ESC still works.

The third dump is different: a DirectSound teardown race on an audio
worker thread (CEngineRendererConnection releasing audio-session
interfaces at exit). One occurrence, filed, not chased.

Also in every log, benign but noisy: 'Entity -1:106 class42 couldn't
figure out how to MakeEntityRenderables' twice per mission - drop zones
have no renderables and nothing to draw them with. Left alone tonight.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-11 20:36:52 -05:00
co-authored by Claude Opus 5
parent 056ee0bdad
commit 13a2109918
7 changed files with 235 additions and 18 deletions
+38
View File
@@ -1198,6 +1198,34 @@ void L4NetworkManager::Send(
our_host_manager = application->GetHostManager();
Check(our_host_manager);
base_host = our_host_manager->GetRemoteHost(host_ID);
//
// A host that is not in the table at all. Two playtest machines died
// here on the same instruction - the podium was up, a peer had left,
// and a drop zone assignment dispatched to a host GetRemoteHost had
// no row for, so GetConnectStatus read offset 0x24 off a NULL. The
// table's rows never leave it (disconnect only marks a host offline),
// so an absent ID was never adopted: host -1 is the known case, the
// ownerless map entities every log shows as 'Entity -1:106'. Whatever
// the ID's provenance, a message to a host that does not exist gets
// the same answer as one to a host that is offline - dropped - and
// the log names the ID so the next occurrence explains itself.
//
if (base_host == NULL)
{
static int said = 0;
if (said < 8)
{
++said;
DEBUG_STREAM << "Send: no host " << host_ID
<< " in the table (client " << (int) client
<< ", message " << message->messageID
<< ") - dropped, not crashed\n" << std::flush;
}
CLEAR_SEND_PACKET();
return;
}
l4host = Cast_Object(L4Host*, base_host);
if(l4host->GetConnectStatus() != L4Host::OnLineConnectionStatus)
{
@@ -1329,6 +1357,16 @@ Logical L4NetworkManager::SendMessageToNetnub(
Check(host_manager);
receiving_host = Cast_Object(L4Host*, host_manager->GetRemoteHost(host_ID));
//
// Same guard as Send, one layer down: an ID with no row in the table
// answers True - message consumed, nothing to retry - exactly like a
// host that is offline.
//
if (receiving_host == NULL)
{
return True;
}
if (receiving_host->GetConnectStatus() != L4Host::OnLineConnectionStatus)
{
return True;
+31 -6
View File
@@ -395,10 +395,30 @@ namespace
// render loop yet at this point - this runs before the engine
// block - so nothing else is keeping it alive.
//
//
// The deadline is PER ATTEMPT, and attempts are capped, rather
// than one budget across all attempts.
//
// The 2026-08-11 playtest showed why, on every machine that met
// the one badly-NATed peer: the first attempt goes for a direct
// path, burns around ten seconds, and dies with 'timed out
// attempting to connect' (5003) or 'negotiate rendezvous'
// (5008); the SECOND attempt comes up through Valve's relay and
// succeeds - whenever it is given time. Under one shared budget
// the relay attempt inherited whatever the direct attempt left,
// and the logs show it being cut off mid-connect ('attempt 2
// ended in state 1' - still connecting) at the 20s mark. Races
// then could not assemble, because the mesh needs every pair.
//
// Three attempts at RP412CONNECTWAIT each: the observed failure
// connects on attempt 2 at about half a minute, the truly
// unreachable peer costs about a minute instead of twenty
// seconds, and ESC still works throughout.
//
DWORD wait_seconds = (DWORD) NetTransport_ConnectWaitSeconds();
DWORD started = GetTickCount();
DWORD deadline = started + wait_seconds * 1000;
int attempt = 0;
const int kMaxAttempts = 3;
char progress[256];
sprintf(
@@ -411,6 +431,7 @@ namespace
for (;;)
{
++attempt;
DWORD deadline = GetTickCount() + wait_seconds * 1000;
HSteamNetConnection handle =
SteamNetworkingSockets()->ConnectByIPAddress(target, 0, NULL);
if (handle == k_HSteamNetConnection_Invalid)
@@ -455,8 +476,9 @@ namespace
sprintf(
progress,
"Red Planet - connecting to %s ... %us left, ESC to cancel",
"Red Planet - connecting to %s (try %d of %d) ... %us left, ESC to cancel",
inet_ntoa(remote->sin_addr),
attempt, kMaxAttempts,
(unsigned) left
);
NetTransport_SetWaitProgress(progress);
@@ -487,15 +509,18 @@ namespace
return (Connection) handle;
}
// attempt failed - drop it and retry until the deadline
// attempt failed - drop it and retry with a fresh window
DEBUG_STREAM << "SteamNetTransport: attempt " << attempt
<< " ended in state " << (int) state << "\n" << std::flush;
SteamNetworkingSockets()->CloseConnection(handle, 0, "retry", false);
RemoveConnection(handle);
if ((LONG)(GetTickCount() - deadline) >= 0)
if (attempt >= kMaxAttempts)
{
DEBUG_STREAM << "SteamNetTransport: connect timed out after "
<< wait_seconds << "s (RP412CONNECTWAIT)\n" << std::flush;
DEBUG_STREAM << "SteamNetTransport: gave up after "
<< attempt << " attempts of " << wait_seconds
<< "s each (RP412CONNECTWAIT), "
<< ((GetTickCount() - started) / 1000)
<< "s in all\n" << std::flush;
NetTransport_SetWaitProgress(NULL);
return InvalidConnection;
}
+12 -12
View File
@@ -321,20 +321,20 @@ namespace
"# the old arrival-time behaviour if you want to compare.\n"
"#RP412NETCLOCK=0\n"
"\n"
"# How long to keep redialling a player who has not answered yet, in\n"
"# seconds. 2 to 300, default 20.\n"
"# How long each connection attempt to another machine may take, in\n"
"# seconds. 2 to 300, default 20, and up to three attempts are made.\n"
"#\n"
"# Launching a race connects to each machine in turn, and retries while\n"
"# one is not listening yet, because they finish loading at different\n"
"# moments. The wait used to be two minutes, which suited the arcade: a\n"
"# pod that was still booting would always answer eventually, on a LAN\n"
"# with nothing else to go wrong. Over the internet a machine that has\n"
"# been silent for twenty seconds is not coming - it never launched, or\n"
"# something between you cannot be crossed - so the default is twenty.\n"
"# Per attempt matters. Steam tries a direct path first, and behind some\n"
"# routers that burns ten seconds and fails; the second attempt comes up\n"
"# through Valve's relay and succeeds - if it is given time. The first\n"
"# playtest with six players showed a shared budget cutting that second\n"
"# attempt off mid-connect, and races could not assemble because the\n"
"# mesh needs every machine to reach every other. Three attempts of\n"
"# twenty seconds each connects the awkward router in about half a\n"
"# minute, and gives up on a truly unreachable one inside a minute.\n"
"#\n"
"# The window stays alive throughout and the title bar counts down, and\n"
"# ESC gives up immediately. Raise this if you play with someone whose\n"
"# machine loads very slowly.\n"
"# The window stays alive throughout, the title bar names the peer and\n"
"# counts down each attempt, and ESC gives up immediately.\n"
"RP412CONNECTWAIT=20\n"
"\n"
"# How much memory to set aside for a recording, in megabytes. 1 to 512,\n"
+154
View File
@@ -0,0 +1,154 @@
Red Planet 4.12.217 (056ee0b)
Environ: 12 setting(s) from environ.ini
Environ: environ.ini does not mention 24 option(s) this build knows: RP412INPUTFOCUS, L4MAPPOS, L4MAPSCALE, RP412PODIUMHOLD, RP412PHYSICSHZ, RP412INTERP, RP412NETPREDICT, RP412GAUGESLICE, RP412MAPRATE, RP412GAUGEDIAG, RP412LAMPSWEEP, RP412CONNECTWAIT, RP412RECORDSIZE, RP412GAUGEPROFILE, RP412RENDERDIAG, RP412PHYSTRACE, RP412SPAWNZONE, RP412INPUTSCRIPT, RP412JOYLOG, RP412AUDIOVOLUME, RP412AUDIOBASS, RP412VERTEXPROC, RP412VSYNC, RP412CAMLOG
Environ: they are at their built-in defaults - delete environ.ini to get the documented file back
L4CONTROLS=PAD;KEYBOARD
Video: frame target 60 fps, drawing interpolated across the physics step
SteamNetTransport: up as 169.254.8.177 (fake ports 33416 console, 33417 game)
L4Application: -fit chose -res 1920 1080 (100% canvas) for the 2560x1080 monitor
L4Application: -fit placed the window borderless at 2560x1080 before the first mission
FrontEnd: callsign "Pilot" and loadout from pilot.cfg
FrontEnd: saved callsign "PoorImpulseControl" and loadout to pilot.cfg
Lobby: joined 109775241819393971
SteamNetTransport: peer registered: 169.254.88.186 (console 10608, game 10609, id 76561198659597127)
SteamNetTransport: peer registered: 169.254.35.214 (console 62256, game 62257, id 76561197995508393)
SteamNetTransport: peer registered: 169.254.105.170 (console 4648, game 4649, id 76561197970536135)
SteamNetTransport: peer registered: 169.254.240.193 (console 7168, game 7169, id 76561197976435895)
SteamNetTransport: peer registered: 169.254.8.177 (console 33416, game 33417, id 76561197969401853)
SteamNetTransport: peer registered: 169.254.122.50 (console 41360, game 41361, id 76561198022091594)
PadBindings: 59 key buttons, 8 key axes, 10 pad buttons, 5 pad axes
PadRIO: virtual RIO active (XInput pad + keyboard)
PadRIO: controls answer only while the game window has focus
Trying to find the monitor marked as active in Windows...
Monitor 0 was set as active in Windows... setting it as the primary monitor.
Either MFDs are explicitly disabled, we're running in windowed mode, or we don't have enough monitors attached to this machine. MFD monitors will not be detected.
Game is currently running windowed mode- will set all remaining undefined monitors to be the same as the primary monitor.
Video: presentation interval vsync
Video: vertex processing HARDWARE
SVGA16: cockpit canvas at 100% for the 2560x1080 work area
SVGA16: secondary displays at UL 100% UC 100% UR 100% LL 100% LR 100% radar 100%
SVGA16: radar on the bottom centre (L4RADARPOS)
SVGA16: cockpit fitted 1920x1080 at 100% in a 2560x1080 client
GaugeInterpreter: undefined label 'Initialization'
SteamNetTransport: listening on engine port 1501 (fake port 33416)...
PadRIO: controller 0 connected
SteamNetTransport: incoming [#4027028733 P2P steamid:76561198659597127@169.254.248.212:15404 fakeport #0] - accepting
SteamNetTransport: connected [#4027028733 P2P SDR steamid:76561198659597127@169.254.248.212:15404 fakeport #0]
STATUS: socket accepted from 169.254.88.186:1501!
Connected to ConsoleHost at 169.254.88.186:1501
SteamNetTransport: connecting to 169.254.88.186:1502 (fake port 10609)...
SteamNetTransport: connected [#2546421614 P2P SDR steamid:76561198659597127@169.254.88.186:10609]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.35.214:1502 (fake port 62257)...
SteamNetTransport: connected [#3892042932 P2P SDR steamid:76561197995508393@169.254.35.214:62257]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.105.170:1502 (fake port 4649)...
SteamNetTransport: dropped [#1183141278 P2P ?@169.254.105.170:4649] end reason 5003: Timed out attempting to connect
SteamNetTransport: attempt 1 ended in state 5
SteamNetTransport: attempt 2 ended in state 1
SteamNetTransport: connect timed out after 20s (RP412CONNECTWAIT)
Could not open connection to 169.254.105.170:1502.
SteamNetTransport: connecting to 169.254.240.193:1502 (fake port 7169)...
SteamNetTransport: connected [#555564226 P2P SDR steamid:76561197976435895@169.254.240.193:7169]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: listening on engine port 1502 (fake port 33417)...
Connected to GameMachineHost at 169.254.88.186:1502
Connected to GameMachineHost at 169.254.35.214:1502
Connected to GameMachineHost at 169.254.240.193:1502
SteamNetTransport: connecting to 169.254.88.186:1502 (fake port 10609)...
SteamNetTransport: incoming [#1946318435 P2P steamid:76561198022091594@169.254.251.68:21949 fakeport #1] - accepting
SteamNetTransport: connected [#1380037914 P2P SDR steamid:76561198659597127@169.254.88.186:10609]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.35.214:1502 (fake port 62257)...
SteamNetTransport: connected [#1946318435 P2P SDR steamid:76561198022091594@169.254.251.68:21949 fakeport #1]
SteamNetTransport: connected [#371675616 P2P SDR steamid:76561197995508393@169.254.35.214:62257]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.105.170:1502 (fake port 4649)...
SteamNetTransport: dropped [#1416324186 P2P ?@169.254.105.170:4649] end reason 5003: Timed out attempting to connect
SteamNetTransport: attempt 1 ended in state 5
SteamNetTransport: connected [#2299564679 P2P SDR steamid:76561197970536135@169.254.105.170:4649]
SteamNetTransport: connect succeeded (attempt 2)
SteamNetTransport: connecting to 169.254.240.193:1502 (fake port 7169)...
SteamNetTransport: connected [#1693276213 P2P SDR steamid:76561197976435895@169.254.240.193:7169]
SteamNetTransport: connect succeeded (attempt 1)
Listen requested on port 1502 but gameListenerSocket already existed!
STATUS: socket accepted from 169.254.122.50:1502!
Connected to GameMachineHost at 169.254.122.50:1502
Connected to GameMachineHost at 169.254.88.186:1502
Connected to GameMachineHost at 169.254.35.214:1502
Connected to GameMachineHost at 169.254.105.170:1502
Connected to GameMachineHost at 169.254.240.193:1502
All connections completed!
SteamNetTransport: connecting to 169.254.88.186:1502 (fake port 10609)...
SteamNetTransport: incoming [#418395659 P2P steamid:76561198022091594@169.254.251.68:21949 fakeport #1] - accepting
SteamNetTransport: connected [#3771470973 P2P SDR steamid:76561198659597127@169.254.88.186:10609]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.35.214:1502 (fake port 62257)...
SteamNetTransport: connected [#418395659 P2P SDR steamid:76561198022091594@169.254.251.68:21949 fakeport #1]
SteamNetTransport: connected [#107458131 P2P SDR steamid:76561197995508393@169.254.35.214:62257]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.105.170:1502 (fake port 4649)...
SteamNetTransport: connected [#173068106 P2P SDR steamid:76561197970536135@169.254.105.170:4649]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.240.193:1502 (fake port 7169)...
SteamNetTransport: connected [#1962487129 P2P SDR steamid:76561197976435895@169.254.240.193:7169]
SteamNetTransport: connect succeeded (attempt 1)
Listen requested on port 1502 but gameListenerSocket already existed!
STATUS: socket accepted from 169.254.122.50:1502!
Connected to GameMachineHost at 169.254.122.50:1502
Connected to GameMachineHost at 169.254.88.186:1502
Connected to GameMachineHost at 169.254.35.214:1502
Connected to GameMachineHost at 169.254.105.170:1502
Connected to GameMachineHost at 169.254.240.193:1502
All connections completed!
SteamNetTransport: connecting to 169.254.88.186:1502 (fake port 10609)...
SteamNetTransport: connected [#3345733046 P2P SDR steamid:76561198659597127@169.254.88.186:10609]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.35.214:1502 (fake port 62257)...
SteamNetTransport: connected [#488432965 P2P SDR steamid:76561197995508393@169.254.35.214:62257]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.105.170:1502 (fake port 4649)...
SteamNetTransport: incoming [#1418378592 P2P steamid:76561198022091594@169.254.251.68:21949 fakeport #1] - accepting
SteamNetTransport: connected [#1418378592 P2P SDR steamid:76561198022091594@169.254.251.68:21949 fakeport #1]
SteamNetTransport: dropped [#1982903022 P2P steamid:76561197970536135@169.254.105.170:4649] end reason 5003: Timed out attempting to connect
SteamNetTransport: attempt 1 ended in state 5
SteamNetTransport: attempt 2 ended in state 1
SteamNetTransport: connect timed out after 20s (RP412CONNECTWAIT)
Could not open connection to 169.254.105.170:1502.
SteamNetTransport: connecting to 169.254.240.193:1502 (fake port 7169)...
SteamNetTransport: connected [#3943096642 P2P SDR steamid:76561197976435895@169.254.240.193:7169]
SteamNetTransport: connect succeeded (attempt 1)
Listen requested on port 1502 but gameListenerSocket already existed!
STATUS: socket accepted from 169.254.122.50:1502!
Connected to GameMachineHost at 169.254.122.50:1502
Connected to GameMachineHost at 169.254.88.186:1502
Connected to GameMachineHost at 169.254.35.214:1502
Connected to GameMachineHost at 169.254.240.193:1502
SteamNetTransport: connecting to 169.254.88.186:1502 (fake port 10609)...
SteamNetTransport: connected [#1251939970 P2P SDR steamid:76561198659597127@169.254.88.186:10609]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.35.214:1502 (fake port 62257)...
SteamNetTransport: connected [#389222490 P2P SDR steamid:76561197995508393@169.254.35.214:62257]
SteamNetTransport: connect succeeded (attempt 1)
SteamNetTransport: connecting to 169.254.105.170:1502 (fake port 4649)...
SteamNetTransport: incoming [#2399032524 P2P steamid:76561198022091594@169.254.251.68:21949 fakeport #1] - accepting
SteamNetTransport: connected [#2399032524 P2P SDR steamid:76561198022091594@169.254.251.68:21949 fakeport #1]
SteamNetTransport: dropped [#3050802723 P2P steamid:76561197970536135@169.254.105.170:4649] end reason 5003: Timed out attempting to connect
SteamNetTransport: attempt 1 ended in state 5
SteamNetTransport: connected [#4019172527 P2P SDR steamid:76561197970536135@169.254.105.170:4649]
SteamNetTransport: connect succeeded (attempt 2)
SteamNetTransport: connecting to 169.254.240.193:1502 (fake port 7169)...
SteamNetTransport: connected [#2022716960 P2P SDR steamid:76561197976435895@169.254.240.193:7169]
SteamNetTransport: connect succeeded (attempt 1)
Listen requested on port 1502 but gameListenerSocket already existed!
STATUS: socket accepted from 169.254.122.50:1502!
Connected to GameMachineHost at 169.254.122.50:1502
Connected to GameMachineHost at 169.254.88.186:1502
Connected to GameMachineHost at 169.254.35.214:1502
Connected to GameMachineHost at 169.254.105.170:1502
Connected to GameMachineHost at 169.254.240.193:1502
All connections completed!
NetClock: host 2 first sample, offset -51745 ms
NetClock: host 3 first sample, offset -16521 ms
NetClock: host 4 first sample, offset 20923 ms
Physics: fixed step, 50 Hz
Binary file not shown.
Binary file not shown.
Binary file not shown.