Domain correction from playtest: hand-fed eggs are a developer shortcut - a mission only ends on a console command, so the clock hits 00:00 and counts up forever. Even single-player games need a console marshal. RPL4CONSOLE is that console. Like the real one it lives on its own thread: it owns the mission clock and raises the stop request at the selected length; the app-manager per-frame hook (new gPerFrameHook seam in APPMGR, called while the application global is live - the loop condition NULLs it on exit, which ate the first attempt) executes the engine-safe part, dispatching the same StopMissionMessage TeslaConsole sent. Final scores flow in through a new RP-layer sink (gConsoleScoreSink in RPCNSL): RPPlayer feeds it the same score it sends a real console at mission end. It also inherits the launcher role: the application tears down after a stop (arcade pods were relaunched per mission by TeslaLauncher), so WinMain respawns the process when the console ended the mission, landing back on the race-setup screen. L4NetworkManager grows FeedLocalEgg (the single-user egg-inject path, callable mid-session) for the future in-process loop. Verified end to end: menu -> 3:00 race -> stop dispatched exactly on time -> final score collected (host 1 = 4113) -> process respawned with the front end up. -egg runs stay unmarshaled (the dev shortcut). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
85 lines
2.1 KiB
C++
85 lines
2.1 KiB
C++
#include "rp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "rpcnsl.h"
|
|
|
|
// see rpcnsl.h - the in-process console registers its intake here
|
|
void (*gConsoleScoreSink)(int player_host_ID, int final_score) = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoredMessage ~~~~~~~~~~~~~~~~~~~~~~
|
|
ConsolePlayerVTVScoredMessage::
|
|
ConsolePlayerVTVScoredMessage(HostID player_host_ID):
|
|
NetworkClient::Message(
|
|
ConsolePlayerVTVScoredMessageID,
|
|
sizeof(ConsolePlayerVTVScoredMessage)
|
|
)
|
|
{
|
|
playerHostID = player_host_ID;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVKilledMessage ~~~~~~~~~~~~~~~~~~~~~~
|
|
ConsolePlayerVTVKilledMessage::
|
|
ConsolePlayerVTVKilledMessage(
|
|
HostID player_host_ID,
|
|
HostID killer_host_ID
|
|
):
|
|
NetworkClient::Message(
|
|
ConsolePlayerVTVKilledMessageID,
|
|
sizeof(ConsolePlayerVTVKilledMessage)
|
|
)
|
|
{
|
|
playerHostID = player_host_ID;
|
|
killerHostID = killer_host_ID;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVBoosterMessage ~~~~~~~~~~~~~~~~~~~~~~
|
|
ConsolePlayerVTVBoosterMessage::
|
|
ConsolePlayerVTVBoosterMessage(
|
|
HostID player_host_ID,
|
|
int booster_on
|
|
):
|
|
NetworkClient::Message(
|
|
ConsolePlayerVTVBoosterMessageID,
|
|
sizeof(ConsolePlayerVTVBoosterMessage)
|
|
)
|
|
{
|
|
playerHostID = player_host_ID;
|
|
boosterOn = booster_on;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoreUpdateMessage ~~~~~~~~~~~~~~~~~~~~
|
|
ConsolePlayerVTVScoreUpdateMessage::
|
|
ConsolePlayerVTVScoreUpdateMessage(
|
|
HostID player_host_ID,
|
|
int score
|
|
):
|
|
NetworkClient::Message(
|
|
ConsolePlayerVTVScoreUpdateMessageID,
|
|
sizeof(ConsolePlayerVTVScoreUpdateMessage)
|
|
)
|
|
{
|
|
playerHostID = player_host_ID;
|
|
playerScore = score;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVDamagedMessage ~~~~~~~~~~~~~~~~~~~~~~
|
|
ConsolePlayerVTVDamagedMessage::
|
|
ConsolePlayerVTVDamagedMessage(
|
|
HostID player_host_ID,
|
|
HostID damager_host_ID,
|
|
int loss,
|
|
int points_transfered
|
|
):
|
|
NetworkClient::Message(
|
|
ConsolePlayerVTVDamagedMessageID,
|
|
sizeof(ConsolePlayerVTVDamagedMessage)
|
|
)
|
|
{
|
|
playerHostID = player_host_ID;
|
|
damagerHostID = damager_host_ID;
|
|
damageLoss = loss;
|
|
pointsTransfered = points_transfered;
|
|
}
|
|
|
|
//==============================================================================
|