Files
RP412/MUNGA_L4/L4APP.H
T
CydandClaude Fable 5 c66cb00a7e Network races: the local console marshals remote pods over the wire
The lobby-owner-as-console architecture, in-engine. RPL4CONSOLE gains
RPL4LocalConsole_InstallNetworkRace: the owner pod switches to network
mode and meshes like any pod (egg fed locally via FeedLocalEgg, which
now opens the ConsoleOnly state gate), while the console tick also
marshals REMOTE pods over NetTransport speaking the exact arcade
protocol - egg chunks with 5s-retry-until-ACK, 1Hz state polling,
RunMission once every pod stages at WaitingForLaunch, StopMission at
expiry (remotes first, local pod holds until their EndMission scores
land), score intake labeled with [pilots]-order names on the results
screen.

The front end builds the multi-pilot egg: RP412HOSTPODS lists member
console channels (lobby stand-in; the Steam lobby feeds the same
path), RP412HOSTPORT/RP412HOSTADDR set the owner side.

Winsock Connect now redials with a fresh socket per attempt (a refused
TCP socket is dead; the old loop reused it) bounded at 120s - needed
whenever a peer boots after the caller, which is the normal Steam
lobby launch order.

Verified on loopback: member pod in -net, owner hosting from its menu;
mesh completed both sides, 30s race, remote score collected over the
wire (host 3), local stop after the drain, results screen shows both
pilots by name in one process that returns to the menu.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 21:08:18 -05:00

238 lines
6.5 KiB
C++

//===========================================================================//
// File: l4app.hpp //
// Project: MUNGA Brick: L4Application //
// Contents: Interface specification for L4Application //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/21/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide. //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#pragma once
#include "..\munga\app.h"
#include "..\munga\APPMGR.h"
class DPLRenderer;
class L4AudioRenderer;
class L4GaugeRenderer;
class L4NetworkManager;
class LBE4ControlsManager;
class L4IcomManager;
//##########################################################################
//######################## L4Application #############################
//##########################################################################
class L4Application:
public Application
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
L4Application(
HINSTANCE hInstance,
HWND hWnd,
ResourceFile *resource_file,
ApplicationID application_ID,
ClassID class_ID=L4ApplicationClassID,
SharedData &shared_data=DefaultData
);
~L4Application();
Logical
TestInstance() const;
static Derivation *GetClassDerivations();
static SharedData DefaultData;
bool IsDead() {return mIsDead;}
void SetIsDead(bool isDead) {mIsDead = isDead;}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Command line parsing
//
public:
typedef Logical
(*TokenParser)(int *argument, int argc, LPWSTR argv[]);
static Logical
ParseToken(
int *argument,
int argc,
LPWSTR argv[]
);
static Logical
ParseCommandLine(
int argc,
LPWSTR argv[],
TokenParser parser = &L4Application::ParseToken
);
static int GetMissionReviewMode() { return missionReviewMode; }
static HINSTANCE GetAppInstance() { return mhInstance; }
static HWND GetMainWindow() { return ghWnd; }
static unsigned int GetScreenWidth() { return mScreenWidth; }
static unsigned int GetScreenHeight() { return mScreenHeight; }
static bool GetFullscreen() { return mFullscreen; }
static Logical GetSeeSolids() { return seeSolids; }
static unsigned long GetNetworkCommonFlatAddress() { return networkCommonFlatAddress; }
// The front end's multiplayer path turns network mode on at launch
// time (the owner pod meshes like any other pod); command-line -net
// keeps working exactly as before.
static void SetNetworkCommonFlatAddress(unsigned long address) { networkCommonFlatAddress = address; }
static CString GetEggNotationFileName() { return eggNotationFileName; }
// the in-game front end builds an egg and injects it here
static void SetEggNotationFileName(const char *name) { eggNotationFileName = name; }
static CString GetSpoolFileName() { return spoolFileName; }
static CString GetRIOPlaybackFileName() { return rioPlaybackFileName; }
static CString GetRIORecordingFileName() { return rioRecordingFileName; }
protected:
static HINSTANCE mhInstance;
static unsigned int mScreenWidth;
static unsigned int mScreenHeight;
static bool mFullscreen;
static Logical seeSolids;
static CString eggNotationFileName;
static CString spoolFileName;
static unsigned long networkCommonFlatAddress;
static int missionReviewMode;
static CString rioPlaybackFileName;
static CString rioRecordingFileName;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execution control
//
public:
void
Initialize();
void
InitializeTillConsole();
Entity*
MakeAndLinkViewpointEntity(Entity__MakeMessage *message);
Entity*
MakeViewpointEntity(Entity__MakeMessage *message);
void
Terminate();
void
TeslaCoil(Logical lights_on);
void
PilotIllumination(Logical lights_on); // includes 'Tesla coil'
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Module accesors
//
public:
DPLRenderer*
GetVideoRenderer();
L4AudioRenderer*
GetAudioRenderer();
L4GaugeRenderer*
GetGaugeRenderer();
L4NetworkManager*
GetNetworkManager()
{return (L4NetworkManager*)Application::GetNetworkManager();}
LBE4ControlsManager*
GetControlsManager()
{return (LBE4ControlsManager*)Application::GetControlsManager();}
L4IcomManager*
GetIntercomManager()
{return (L4IcomManager*)Application::GetIntercomManager();}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public data
//
public:
char
*divisionParameters;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Module Creation
//
protected:
ModeManager*
MakeModeManager();
ControlsManager*
MakeControlsManager();
IcomManager*
MakeIntercomManager();
NetworkManager*
MakeNetworkManager();
VideoRenderer*
MakeVideoRenderer();
AudioRenderer*
MakeAudioRenderer();
GaugeRenderer*
MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
enum
{
LightsOutMessageID = Application::NextMessageID,
NextMessageID
};
static const HandlerEntry
MessageHandlerEntries[];
//static MessageHandlerSet MessageHandlers;
static MessageHandlerSet& GetMessageHandlers();
void
LightsOutMessageHandler(Receiver::Message *message);
void
RunMissionMessageHandler(RunMissionMessage *message);
void
StopMissionMessageHandler(StopMissionMessage *message);
void // HACK - the 'int' is actually 'ControlsKey'
KeyCommandMessageHandler(ReceiverDataMessageOf<int> *message);
private:
bool mIsDead;
};
extern L4Application * &l4_application;
//~~~~~~~~~~~~~~~~~~~~~ L4Application inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
inline DPLRenderer*
L4Application::GetVideoRenderer()
{
Check(this);
return (DPLRenderer*)videoRenderer;
}
inline L4AudioRenderer*
L4Application::GetAudioRenderer()
{
Check(this);
return (L4AudioRenderer*)audioRenderer;
}
inline L4GaugeRenderer*
L4Application::GetGaugeRenderer()
{
Check(this);
return (L4GaugeRenderer*)gaugeRenderer;
}