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) <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-11 12:11:06 -05:00
co-authored by Claude Opus 5
parent f5ad3036cc
commit 127b8077f5
2 changed files with 32 additions and 5 deletions
+17
View File
@@ -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)
+15 -5
View File
@@ -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;