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>
238 lines
6.5 KiB
C++
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;
|
|
} |