From 127b8077f5828bba86db8a3b4d6e61921216ab83 Mon Sep 17 00:00:00 2001 From: Cyd Date: Tue, 11 Aug 2026 12:11:06 -0500 Subject: [PATCH] A solo race has no packets to keep The SPOOLS folder was empty after a solo run because there was nothing to put in it, and the code said so nowhere. Recording captures the packets this station RECEIVES. A race with no other machines in it neither sends nor receives any - L4NetworkManager::ExclusiveBroadcast walks the remote host list and a solo race has none - so the tee is never called, the recorder never arms, and Save returned in silence. Correct behaviour, invisible reasoning. The comment I put in the front end claimed the opposite, that "a single-player run records as readily as a lobby one". It does not, and the claim is now the truth instead. The same gap has a consequence I had not drawn out either: a RACER's recording is not the whole race, because its own pod is simulated locally and never arrives as a packet. A Live Cam races nothing, so every pod reaches it over the wire - it is the only station that hears the lot, which is a better argument for the feature than the one I started with. Say all of this where it will be read: the log now explains an empty recording instead of leaving the folder to be puzzled over, and the front end explains why the row is offered on races that cannot use it (hiding it conditionally would read as a bug of its own). Not fixed here: capturing locally simulated entities, which would make solo recordable and a racer's spool complete. It is feasible - Entity::Execute already produces each local update in wire form every frame whether or not anyone is listening, and NetworkPacketHeader is four fields, all of them available locally - but it means synthesising packets that were never sent, and that wants proving against playback rather than landing on the evening of a test with players. Co-Authored-By: Claude Opus 5 (1M context) --- MUNGA/SPOOLER.cpp | 17 +++++++++++++++++ RP_L4/RPL4FE.cpp | 20 +++++++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/MUNGA/SPOOLER.cpp b/MUNGA/SPOOLER.cpp index 12143e8..0d90faf 100644 --- a/MUNGA/SPOOLER.cpp +++ b/MUNGA/SPOOLER.cpp @@ -302,8 +302,25 @@ void { Check(this); + // + // Never armed means not one packet arrived all race. + // + // Recording captures the packets this station RECEIVES, and a race + // with no other machines in it sends and receives nothing at all - + // L4NetworkManager::ExclusiveBroadcast walks the remote hosts, and a + // solo race has none. So there is nothing to keep, and the reason is + // worth saying rather than leaving an empty folder to be puzzled over. + // + // The same gap is why a RACER's recording is not the whole race: its + // own pod is simulated locally and never arrives as a packet. A Live + // Cam races nothing, so every pod reaches it over the wire, which + // makes it the only station that hears the lot. + // if (!armed || spool == NULL) { + DEBUG_STREAM << "Record: nothing to write - no packets were received" + << " this race. Recording keeps what arrives over the network," + << " so a single-player race has nothing to keep.\n" << std::flush; return; } if (packetsRecorded == 0) diff --git a/RP_L4/RPL4FE.cpp b/RP_L4/RPL4FE.cpp index fcefbf6..1cccdb1 100644 --- a/RP_L4/RPL4FE.cpp +++ b/RP_L4/RPL4FE.cpp @@ -701,11 +701,21 @@ namespace groups[n++] = GroupRole; } // - // Directly under the role, and offered for every kind of race. - // A recording is just this station's received packets, so a - // single-player run records as readily as a lobby one - and - // unlike the role, a camera with nothing to watch is not a - // hazard here, so there is nothing to gate it on. + // Directly under the role, because it is the same question asked + // twice - what am I here to do. + // + // Offered on every race even though only a networked one has + // anything to record: a recording is this station's RECEIVED + // packets, and a solo race neither sends nor receives any. Hiding + // the row on solo would make the setting appear and disappear + // depending on what else was picked, which reads as a bug; the + // log says plainly why a solo race wrote nothing. + // + // Worth knowing when reading a spool back: a racer's recording + // leaves out its OWN pod, which is simulated locally and never + // arrives over the wire. A Live Cam races nothing, so every pod + // reaches it as packets - it is the only station that hears the + // whole race. // groups[n++] = GroupRecord; groups[n++] = GroupVehicle;