From 0906d1efa6a311fee8769bc6c8d14c7917ae72f7 Mon Sep 17 00:00:00 2001 From: Cyd Date: Sun, 19 Jul 2026 19:57:04 -0500 Subject: [PATCH] 4.10 reconstruction: real l4net standalone path + full BTL4Mission::SetPlayerData Boot ladder progress (each step verified live under DOSBox-X + 32RTM): - L4NET.CPP v2: real statics (ClassDerivations/MessageHandlers/DefaultData), real single-user ctor (egg NotationFile -> last.egg -> local ReceiveEggFile post), real StartConnecting/Shutdown/CreateConsoleHost single-user branches, all four message handlers (egg assembly, ack, host connect/disconnect), 1995 netnub-guard idiom (Net_Common_Ptr NULL => benign return) throughout; netnub wire primitives remain Fail-staged. Sources: BT411 engine/MUNGA_L4/ L4NET.cpp (preserves the 1995 netnub code as comments beside its Winsock port) cross-checked against the surviving 1995 L4NET.HPP. - BTL4MSSN.CPP: full SetPlayerData reconstruction (vehicle/dropzone/color/ patch/badge/team/experience/advancedDamage/role + score modifiers + plasma badge blit), backdated from BT411's Ghidra-recovered body (@004d2c30); every API pinned to the surviving 1995 headers (NOTATION/MISSION/SCNROLE/ L4GREND/BTMSSN). Boot now runs: banner -> resource load -> app ctor chain -> network manager single-user init -> egg dispatch -> mission creation -> SetPlayerData (parses the real TEST.EGG) -> halts at BTPlayer ctor (next staged brick). Co-Authored-By: Claude Fable 5 --- restoration/source410/BT_L4/BTL4MSSN.CPP | 342 +++++++++- restoration/source410/MUNGA_L4/L4NET.CPP | 804 ++++++++++++++++++++--- 2 files changed, 1054 insertions(+), 92 deletions(-) diff --git a/restoration/source410/BT_L4/BTL4MSSN.CPP b/restoration/source410/BT_L4/BTL4MSSN.CPP index a0217e67..7d240c0c 100644 --- a/restoration/source410/BT_L4/BTL4MSSN.CPP +++ b/restoration/source410/BT_L4/BTL4MSSN.CPP @@ -1,7 +1,12 @@ //===========================================================================// // File: btl4mssn.cpp // -// Project: BattleTech // -// Contents: Implementation details for the BT L4 mission // +// Project: BattleTech Brick: // +// Contents: Implementation for the L4 (game-level) mission // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/07/95 ECH Initial coding. // +// 09/12/95 JM Derived from L4Mission // //---------------------------------------------------------------------------// // Copyright (C) 1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // @@ -15,20 +20,349 @@ # include #endif +#if !defined(BTL4APP_HPP) +# include +#endif + +#if !defined(L4GREND_HPP) +# include +#endif + +#if !defined(L4HOST_HPP) +# include +#endif + +#if !defined(HOSTMGR_HPP) +# include +#endif + +#if !defined(NOTATION_HPP) +# include +#endif + +#if !defined(SCNROLE_HPP) +# include +#endif + +//########################################################################## +//########################### BTL4Mission ############################ +//########################################################################## + +// +//############################################################################# +//############################################################################# +// BTL4Mission::BTL4Mission( NotationFile *notation_file, ResourceFile *resources ): BTMission(notation_file, resources) { + Check_Fpu(); } +// +//############################################################################# +//############################################################################# +// BTL4Mission::~BTL4Mission() { + Check(this); + Check_Fpu(); } +// +//############################################################################# +// SetPlayerData Pulls this host's player page out of the notation file and +// populates the mission's player description: model, dropzone, color, badge, +// patch, experience level, advanced-damage flag, scenario role (+ its damage +// modifiers), and the plasma-display badge bitmap. +//############################################################################# +// void - BTL4Mission::SetPlayerData(NotationFile *) + BTL4Mission::SetPlayerData(NotationFile *notation_file) { - Fail("BTL4Mission::SetPlayerData -- btl4mssn.cpp not yet reconstructed"); + Check(this); + + // + //-------------------------------------------------------------- + // Figure out which page we should be using to create the player + //-------------------------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + L4Host *host = (L4Host*)host_manager->GetLocalHost(); + Check(host); + CString + player_node = host->GetSymbolicName(); + + // + //---------------------------------------------------------- + // Copy the game model and dropzone strings into the mission + //---------------------------------------------------------- + // + gameModel = NULL; + const char *player_model = NULL; + notation_file->GetEntry(player_node, "vehicle", &player_model); + if (!player_model) + { + DEBUG_STREAM << "Error: vehicle not specified!\n"; + Fail("Exiting"); + } + Check_Pointer(player_model); + gameModel = strdup(player_model); + Register_Pointer(gameModel); + + dropZoneName = NULL; + const char *drop_zone = NULL; + notation_file->GetEntry(player_node, "dropzone", &drop_zone); + if (!drop_zone) + { + DEBUG_STREAM << "Error: dropzone not specified!\n"; + Fail("Exiting"); + } + Check_Pointer(drop_zone); + dropZoneName = strdup(drop_zone); + Register_Pointer(dropZoneName); + + dropZoneHost = False; + notation_file->GetEntry(player_node, "loadzones", &dropZoneHost); + + // + //---------------------------------------------------------- + // Color + //---------------------------------------------------------- + // + colorName = NULL; + const char *color_name = NULL; + notation_file->GetEntry(player_node, "color", &color_name); + if (!color_name) + { + DEBUG_STREAM << "Error: color not specified!\n"; + Fail("Exiting"); + } + Check_Pointer(color_name); + colorName = strdup(color_name); + Register_Pointer(colorName); + + // + //---------------------------------------------------------- + // Patch + //---------------------------------------------------------- + // + const char *patch_name = NULL; + notation_file->GetEntry(player_node, "patch", &patch_name); + if (!patch_name) + { + DEBUG_STREAM << "Error: patch not specified!\n"; + Fail("Exiting"); + } + Check_Pointer(patch_name); + patchName = patch_name; + + // + //---------------------------------------------------------- + // Badge + //---------------------------------------------------------- + // + badgeName = NULL; + const char *badge_name = NULL; + notation_file->GetEntry(player_node, "badge", &badge_name); + if (!badge_name) + { + DEBUG_STREAM << "Error: badge not specified!\n"; + Fail("Exiting"); + } + Check_Pointer(badge_name); + badgeName = strdup(badge_name); + Register_Pointer(badgeName); + + // + //---------------------------------------------------------- + // Team name. NOTE: the shipped binary reads the "badge" key here + // as well and defaults to "DEFAULT" when the page omits it. + //---------------------------------------------------------- + // + const char *team_name = NULL; + if (!notation_file->GetEntry(player_node, "badge", &team_name)) + { + teamName = "DEFAULT"; + } + else + { + Check_Pointer(team_name); + teamName = team_name; + } + + // + //---------------------------------------------------------- + // Experience level. Absence is tolerated only for the "camera" + // page; "Unspecified" leaves the default. + //---------------------------------------------------------- + // + const char *experience = "Unspecified"; + if (!notation_file->GetEntry(player_node, "experience", &experience)) + { + if (strcmp(gameModel, "camera") != 0) + { + DEBUG_STREAM << player_node << " page missing expereince!" << endl; + Fail("Exiting"); + } + } + + if (strcmp("Unspecified", experience) != 0) + { + if (strcmp(experience, "novice") == 0) + { + experienceLevel = BTMission::NoviceMode; + } + else if (strcmp(experience, "standard") == 0) + { + experienceLevel = BTMission::StandardMode; + } + else if (strcmp(experience, "veteran") == 0) + { + experienceLevel = BTMission::VeteranMode; + } + else if (strcmp(experience, "expert") == 0) + { + experienceLevel = BTMission::ExpertMode; + } + else + { + DEBUG_STREAM << player_node + << " has an unknown experience field of " + << experience; + Fail("Exiting"); + } + } + + // + //---------------------------------------------------------- + // Advanced damage flag + //---------------------------------------------------------- + // + Logical advanced_damage = False; + if (notation_file->GetEntry(player_node, "advancedDamage", &advanced_damage)) + { + advancedDamageOn = advanced_damage ? True : False; + } + + // + //---------------------------------------------------------- + // Scenario role -- every player page must name a role, and the role + // page must name a model. The ScenarioRole is looked up (and created + // on first use) in the mission's role dictionary, then its per-page + // score modifiers applied. + //---------------------------------------------------------- + // + const char *role_node = NULL; + if (!notation_file->GetEntry(player_node, "role", &role_node)) + { + DEBUG_STREAM << "Each Player page must have a role field !" << endl; + Fail("Exiting"); + } + else + { + Check_Pointer(role_node); + roleName = role_node; + + const char *role_model = NULL; + if (!notation_file->GetEntry(role_node, "model", &role_model)) + { + DEBUG_STREAM << role_node << " page or model field missing !" << endl; + Fail("Exiting"); + } + else + { + ScenarioRole *role = GetScenarioRole(roleName); + if (role == NULL) + { + role = new ScenarioRole(roleName, CString(role_model)); + Register_Object(role); + AddScenarioRole(role); + } + + // + // Optional per-page score modifiers. + // + Scalar value; + if (notation_file->GetEntry(role_node, "dmgInflctdMdfr", &value)) + { + role->SetDamageInflictedModifier(value); + } + if (notation_file->GetEntry(role_node, "dmgRcvdMdfr", &value)) + { + role->SetDamageReceivedModifier(value); + } + if (notation_file->GetEntry(role_node, "dmgBias", &value)) + { + role->SetDamageBias(value); + } + if (notation_file->GetEntry(role_node, "friendlyFire", &value)) + { + role->SetFriendlyFirePenalty(value); + } + int return_from_death; + if (notation_file->GetEntry(role_node, "return", &return_from_death)) + { + role->SetReturnFromDeath(return_from_death); + } + if (notation_file->GetEntry(role_node, "killBonus", &value)) + { + role->SetKillBonus(value); + } + } + } + + // + //~~~~~~~~~~~~~~~~~~~~~~ + // Get playerBitmapIndex and, if present, blit the badge bitmap onto + // the external (plasma) display. + //~~~~~~~~~~~~~~~~~~~~~~ + // + if (!notation_file->GetEntry(player_node, "bitmapindex", &playerBitmapIndex)) + { + DEBUG_STREAM << "No Bitmap for player" << player_node; + DEBUG_STREAM << flush; + } + else + { + BitMap *bitmap = GetLargeNameBitmap(playerBitmapIndex); + if (bitmap != NULL) + { + Check(application); + L4GaugeRenderer + *gauge_renderer = + (L4GaugeRenderer*)application->GetGaugeRenderer(); + if (gauge_renderer != NULL) + { + Check(gauge_renderer); + GraphicsDisplay *graphics_display = + gauge_renderer->GetExternalDisplay(); + + if (graphics_display != NULL) + { + graphics_display->DrawBitMapOpaque( + 1, // foreground color + 0, // background color + 0xFF, // bitmask + GraphicsDisplay::Replace, // operation + 0, // rotation + 0, 0, // position + bitmap, + 0, // sx1 + 0, // sy1 + bitmap->Data.Size.x - 1, // sx2 + bitmap->Data.Size.y - 1 // sy2 + ); + graphics_display->Update(True); + graphics_display->WaitForUpdate(); + } + } + } + } + + Check_Fpu(); } diff --git a/restoration/source410/MUNGA_L4/L4NET.CPP b/restoration/source410/MUNGA_L4/L4NET.CPP index 38117cad..dac9482d 100644 --- a/restoration/source410/MUNGA_L4/L4NET.CPP +++ b/restoration/source410/MUNGA_L4/L4NET.CPP @@ -1,8 +1,13 @@ //===========================================================================// // File: l4net.cpp // -// Project: MUNGA Brick: L4 Network // +// Project: MUNGA Brick: Network Manager // // Contents: Implementation details for the L4 network manager // //---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/02/95 GAC Initial coding. // +// 04/08/95 GAC Netnow Removed, TCP/NetNub support added // +//---------------------------------------------------------------------------// // Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // @@ -15,98 +20,27 @@ # include #endif -L4NetworkManager::L4NetworkManager(): - NetworkManager(NetworkManager::DefaultData), - messageBuffer(this) -{ - Fail("L4NetworkManager -- l4net.cpp not yet reconstructed"); -} +#if !defined(L4APP_HPP) +# include +#endif -void - L4NetworkManager::CreateConsoleHost() -{ - Fail("L4NetworkManager::CreateConsoleHost -- l4net.cpp not yet reconstructed"); -} +#if !defined(L4HOST_HPP) +# include +#endif -L4NetworkManager__MessageBuffer::L4NetworkManager__MessageBuffer(L4NetworkManager *network_manager): - messageQueueSocket(NULL, 1) -{ - networkManager = network_manager; - bufferSize = 0; -} +#if !defined(MISSION_HPP) +# include +#endif -L4NetworkManager__MessageBuffer::~L4NetworkManager__MessageBuffer() -{ -} +#if !defined(NOTATION_HPP) +# include +#endif // //############################################################################# -// Staged bodies: real l4net.cpp not yet reconstructed. Methods that a -// standalone (non-networked) boot may touch are benign no-ops; methods that -// imply real network traffic Fail loudly. -//############################################################################# -// -L4NetworkManager::~L4NetworkManager() -{ -} - -void - L4NetworkManager::Send(Message *, ClientID, HostID) -{ - Fail("L4NetworkManager::Send -- l4net.cpp not yet reconstructed"); -} - -void - L4NetworkManager::ExclusiveBroadcast(Message *, ClientID) -{ - Fail("L4NetworkManager::ExclusiveBroadcast -- l4net.cpp not yet reconstructed"); -} - -void - L4NetworkManager::StartConnecting(Mission *) -{ - Fail("L4NetworkManager::StartConnecting -- l4net.cpp not yet reconstructed"); -} - -Logical - L4NetworkManager::Shutdown() -{ - return 1; -} - -Logical - L4NetworkManager::CheckBuffers(NetworkPacket *) -{ - Fail("L4NetworkManager::CheckBuffers -- l4net.cpp not yet reconstructed"); - return 0; -} - -void - L4NetworkManager::RemovePacket(NetworkPacket *) -{ - Fail("L4NetworkManager::RemovePacket -- l4net.cpp not yet reconstructed"); -} - -Logical - L4NetworkManager::ExecuteBackground() -{ - return 0; -} - -void - L4NetworkManager::Marker(char *) -{ -} - -void - L4NetworkManager::Mode(NetworkMode) -{ -} - -// -//############################################################################# -// NetNub client-side globals (real home: l4net.cpp). Net_Common_Ptr NULL = -// no NetNub TSR loaded; L4File then takes its plain-DOS path (L4FILE.CPP:32). +// NetNub client-side globals. Net_Common_Ptr NULL = no NetNub TSR loaded; +// L4File then takes its plain-DOS path (L4FILE.CPP:32) and the network +// manager runs in single user mode. //############################################################################# // Netcom_Ptr @@ -115,5 +49,699 @@ Netcom_Ptr void NetNub::SendCommand() { - Fail("NetNub::SendCommand -- l4net.cpp not yet reconstructed"); + Fail("NetNub::SendCommand -- netnub interface not yet reconstructed"); +} + +// +//############################################################################# +// Shared data support +//############################################################################# +// +Derivation + L4NetworkManager::ClassDerivations( + NetworkManager::ClassDerivations, + "L4NetworkManager" + ); + +const Receiver::HandlerEntry + L4NetworkManager::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(L4NetworkManager,ReceiveEggFile), + MESSAGE_ENTRY(L4NetworkManager,AcknowledgeEggFile), + MESSAGE_ENTRY(L4NetworkManager,HostConnected), + MESSAGE_ENTRY(L4NetworkManager,HostDisconnected) +}; + +L4NetworkManager::MessageHandlerSet + L4NetworkManager::MessageHandlers( + ELEMENTS(L4NetworkManager::MessageHandlerEntries), + L4NetworkManager::MessageHandlerEntries, + NetworkManager::MessageHandlers + ); + +L4NetworkManager::SharedData + L4NetworkManager::DefaultData( + L4NetworkManager::ClassDerivations, + L4NetworkManager::MessageHandlers + ); + +// +//############################################################################# +// Code for the network manager class +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the L4NetworkManager +// +L4NetworkManager::L4NetworkManager(): + NetworkManager(DefaultData), + messageBuffer(this) +{ + unsigned long + network_common_flat_address; + + network_common_flat_address = + L4Application::GetNetworkCommonFlatAddress(); + lastHostIteratorPosition = 0; + nextOpenHostID = FirstLegalHostID+1; // Reserve first legal id for console + currentNetworkState = NormalState; + myConsoleHost = NULL; + eggAcknowledged = False; + networkStartupMode = SlaveMode; + numberOfMungaHostsConnected = 0; + numberOfConsoleHostsConnected = 0; + remoteHostCount = 0x7FFFFFFF; + + // + // If there is no net common, set things up for single user mode + // + if (network_common_flat_address == 0) + { + Net_Common_Ptr = NULL; + + // + //--------------------------------------------------------------------- + // Retrieve the egg as specified on the command line, and send it as an + // egg message + //--------------------------------------------------------------------- + // + CString egg_name = L4Application::GetEggNotationFileName(); + if (!strlen(egg_name)) + { + Fail("ERROR: No source exists for egg!"); + } + networkEggNotationFile = new NotationFile(egg_name); + Register_Object(networkEggNotationFile); + networkEggNotationFile->WriteFile("last.egg"); + currentNetworkState = NormalState; + + ReceiveEggFileMessage egg_message(-1, 10, "local egg", 10); + application->Post(DefaultEventPriority, this, &egg_message); + return; + } + + // + // Setup the local netcom structure and some pointers to things inside it + // + Fail("L4NetworkManager -- netnub (networked) path not yet reconstructed"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4NetworkManager::~L4NetworkManager() +{ + if (networkEggNotationFile) + { + Unregister_Object(networkEggNotationFile); + delete networkEggNotationFile; + networkEggNotationFile = NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::CreateConsoleHost This routine creates the console remote +// host and posts a listen for the console connection. +// +void + L4NetworkManager::CreateConsoleHost() +{ + // + // Die if there is no network common around + // + if (Net_Common_Ptr == NULL) + { + return; + } + + // + // Initialize a bunch of stuff to sane states + // + nextOpenHostID = FirstLegalHostID+1; // Reserve first legal id for console + networkStartupMode = SlaveMode; // We're a slave, (not a simulated console) + currentNetworkState = ConsoleOnly; // Only accept messages from the console + numberOfConsoleHostsConnected = 0; // Shouldn't be any consoles yet + numberOfMungaHostsConnected = 0; // No game machines either + + Fail("L4NetworkManager::CreateConsoleHost -- netnub path not yet reconstructed"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::StartConnecting This routine is called when a mission +// starts to allow the network management system to establish communications +// with all the participants. +// +void + L4NetworkManager::StartConnecting(Mission *mission) +{ + L4Host *my_l4host; + + // + // This should be entered with no network connections to other game hosts + // up, so we initialize this count to zero. + // + numberOfMungaHostsConnected = 0; + + // + // Create the host iterator for the mission egg + // + Mission::HostIterator mission_host_iterator(mission); + MissionHostData *mission_host_data; + + // + // If there is no net common, set things up for single user mode + // + if (Net_Common_Ptr == NULL) + { + // + // Make the local host for single user testing, we give the host ID#1 + // and assign the first symbolic name in the egg to it. + // + mission_host_data = mission_host_iterator.ReadAndNext(); + Check(mission_host_data); + + my_l4host = new L4Host( + 1, // Host ID + mission_host_data->GetHostType(), // Host Type + NullNetworkAddress, // Net Address + 0, // Socket address + mission_host_data->GetAddressString() + ); + Register_Object(my_l4host); + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptLocalHost(my_l4host); + + // + //-------------------------------------------------------------------- + // Now, since this host creator is for stand-alone mode, send the load + // mission message to the application + //-------------------------------------------------------------------- + // + Check(application); + Application::Message + load_message( + Application::LoadMissionMessageID, + sizeof(Application::Message) + ); + application->Post(DefaultEventPriority, application, &load_message); + return; + } + + Fail("L4NetworkManager::StartConnecting -- netnub path not yet reconstructed"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Shutdown This routine is called when a mission ends to +// allow the network management system to drop all the connections. +// +Logical + L4NetworkManager::Shutdown() +{ + Host + *base_host; + L4Host + *my_l4host; + unsigned long + network_common_flat_address; + + network_common_flat_address = + L4Application::GetNetworkCommonFlatAddress(); + + if (networkEggNotationFile) + { + Unregister_Object(networkEggNotationFile); + delete networkEggNotationFile; + networkEggNotationFile = NULL; + } + + // + // If there is no net common, all we do is deregister the local host + // + if (network_common_flat_address == 0) + { + base_host = application->GetHostManager()->OrphanLocalHost(); + my_l4host = Cast_Object(L4Host*, base_host); + Check(my_l4host); + Unregister_Object(my_l4host); + delete my_l4host; + return True; + } + + Fail("L4NetworkManager::Shutdown -- netnub path not yet reconstructed"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Send Sends a message to a single host. +// +void + L4NetworkManager::Send(Message *message, ClientID, HostID host_ID) +{ + Host *base_host; + L4Host *l4host; + + Check_Pointer(message); + Check(application); + Check(application->GetHostManager()); + base_host = application->GetHostManager()->GetRemoteHost(host_ID); + if (base_host == NULL) + { + return; + } + l4host = Cast_Object(L4Host*, base_host); + if (l4host->GetConnectStatus() != L4Host::OnLineConnectionStatus) + { + return; + } + + Fail("L4NetworkManager::Send -- netnub path not yet reconstructed"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::ExclusiveBroadcast Sends a message to every online host +// except the named client. +// +void + L4NetworkManager::ExclusiveBroadcast(Message *message, ClientID) +{ + Check_Pointer(message); + Check(application); + + // + // With no hosts online there is no one to broadcast to + // + if (numberOfMungaHostsConnected == 0 && numberOfConsoleHostsConnected == 0) + { + return; + } + + Fail("L4NetworkManager::ExclusiveBroadcast -- netnub path not yet reconstructed"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::CheckBuffers Checks to see if there is a message for us +// buffered up in the network interface card. +// +Logical + L4NetworkManager::CheckBuffers(NetworkPacket *) +{ + // + // No netnub present? Nothing can have arrived. + // + if (Net_Common_Ptr == NULL) + { + return False; + } + + Fail("L4NetworkManager::CheckBuffers -- netnub path not yet reconstructed"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4NetworkManager::RemovePacket(NetworkPacket *) +{ + // + // No netnub present? Just return + // + if (Net_Common_Ptr == NULL) + { + return; + } + + Fail("L4NetworkManager::RemovePacket -- netnub path not yet reconstructed"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4NetworkManager::ExecuteBackground() +{ + Check(this); + if (!messageBuffer.IsEmpty()) + { + messageBuffer.AttemptToSend(); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Marker Sends a text marker down the netnub spool for +// mission review annotation. +// +void + L4NetworkManager::Marker(char *) +{ + // + // No netnub present? Just return + // + if (Net_Common_Ptr == NULL) + { + return; + } + + Fail("L4NetworkManager::Marker -- netnub path not yet reconstructed"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Mode Switches the netnub between reliable and unreliable +// delivery. +// +void + L4NetworkManager::Mode(NetworkMode) +{ + // + // No netnub present? Just return + // + if (Net_Common_Ptr == NULL) + { + return; + } + + Fail("L4NetworkManager::Mode -- netnub path not yet reconstructed"); +} + +// +//############################################################################# +// Message handlers +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::ReceiveEggFileMessageHandler +// +void + L4NetworkManager::ReceiveEggFileMessageHandler( + ReceiveEggFileMessage *EggMessage + ) +{ + #if defined(LAB_ONLY) + DEBUG_STREAM << "Received Egg message #" << EggMessage->sequenceNumber + << endl; + #endif + + // + // An egg sequence number of -1 means that the egg is posted locally, and + // should just call create mission + // + if (EggMessage->sequenceNumber == -1) + { + application->CreateMission(networkEggNotationFile); + return; + } + + if (EggMessage->sequenceNumber == 0) + { + // + // Make a buffer + // + eggTempBuffer = new char[EggMessage->notationFileLength]; + Register_Pointer(eggTempBuffer); + eggTempNext = 0; + } + + // + // Write the egg data into the buffer + // + memcpy( + (eggTempBuffer+eggTempNext), + EggMessage->notationData, + EggMessage->thisMessageLength + ); + eggTempNext += EggMessage->thisMessageLength; + + // + // If we don't have all the data, return and wait for more + // + if (eggTempNext < EggMessage->notationFileLength) + { + return; + } + + // + // We've got all the data, make the notation file + // + networkEggNotationFile = new NotationFile(); + Register_Object(networkEggNotationFile); + networkEggNotationFile->ReadText(eggTempBuffer, eggTempNext); + networkEggNotationFile->WriteFile("last.egg"); + currentNetworkState = NormalState; + + // + // Now turn the notation file into a mission + // + application->CreateMission(networkEggNotationFile); + + // + // Get rid of the ram buffer now that we're done with it + // + Unregister_Pointer(eggTempBuffer); + delete eggTempBuffer; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::AcknowledgeEggFileMessageHandler +// +void + L4NetworkManager::AcknowledgeEggFileMessageHandler( + AcknowledgeEggFileMessage * + ) +{ + #if defined(LAB_ONLY) + DEBUG_STREAM << "\nReceived egg acknowledged message\n"; + #endif + eggAcknowledged = True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::HostConnectedMessageHandler +// +void + L4NetworkManager::HostConnectedMessageHandler( + HostConnectedMessage *HostConnected + ) +{ + // + // Get a pointer to the L4 host + // + Check(application); + Check(application->GetHostManager()); + Host *connected_host = + application->GetHostManager()->GetRemoteHost(HostConnected->hostID); + L4Host *l4connected_host = Cast_Object(L4Host*, connected_host); + Check(l4connected_host); + + // + // Set the host connection status to on line and increment the + // counter of hosts online. + // + l4connected_host->SetConnectStatus(L4Host::OnLineConnectionStatus); + switch (l4connected_host->GetHostType()) + { + case GameMachineHostType: + numberOfMungaHostsConnected++; + DEBUG_STREAM << "Connected to GameMachineHost at "; + break; + case CameraShipHostType: + numberOfMungaHostsConnected++; + DEBUG_STREAM << "Connected to CameraShipHost at "; + break; + case MissionReviewHostType: + numberOfMungaHostsConnected++; + DEBUG_STREAM << "Connected to MissionReviewHost at "; + break; + case ConsoleHostType: + numberOfConsoleHostsConnected++; + DEBUG_STREAM << "Connected to ConsoleHost at "; + break; + default: + Fail("L4NetworkManager::HostConnectedMessageHandler - unknown host type"); + break; + } + DEBUG_STREAM << HostConnected->networkAddress << endl; + + if (numberOfMungaHostsConnected >= remoteHostCount) + { + DEBUG_STREAM << "All connections completed!\n"; + Marker("MUNGA MARKER--All connections completed!\n"); + + // + //-------------------------------------------------------------------- + // All hosts are up; send the load mission message to the application + //-------------------------------------------------------------------- + // + Check(application); + Application::Message + load_message( + Application::LoadMissionMessageID, + sizeof(Application::Message) + ); + application->Post(DefaultEventPriority, application, &load_message); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::HostDisconnectedMessageHandler +// This message is assumed only to be sent by the console just prior to it +// disconnecting. It clues us to locally close and destroy the console host +// so the game will start normally even if the console isn't around. +// +void + L4NetworkManager::HostDisconnectedMessageHandler( + HostDisconnectedMessage *HostDisconnected + ) +{ + // + // Get a pointer to the L4 host + // + Check(application->GetHostManager()); + Host *connected_host = + application->GetHostManager()->GetRemoteHost(HostDisconnected->hostID); + L4Host *l4connected_host = Cast_Object(L4Host*, connected_host); + Check(l4connected_host); + + // + // Set the host connection status to off line, then close the connection. + // + l4connected_host->SetConnectStatus(L4Host::NoNetworkConnectionStatus); + NetworkAddress temp_net_address = l4connected_host->GetNetworkAddress(); + CloseConnection(HostDisconnected->streamPointer); + + // + // See what type of host it was that disconnected + // + switch (l4connected_host->GetHostType()) + { + case GameMachineHostType: + numberOfMungaHostsConnected--; + DEBUG_STREAM << "\nDisconnected from GameMachineHost at "; + break; + case CameraShipHostType: + numberOfMungaHostsConnected--; + DEBUG_STREAM << "\nDisconnected from CameraShipHost at "; + break; + case MissionReviewHostType: + numberOfMungaHostsConnected--; + DEBUG_STREAM << "\nDisconnected from MissionReviewHost at "; + break; + case ConsoleHostType: + // + // Knock down the number of consoles online, then destroy the + // console host and recreate it; this resets all the internal + // buffers and pointers so check_buffers won't go crazy + // + numberOfConsoleHostsConnected--; + DEBUG_STREAM << "\nDisconnected from ConsoleHost at "; + application->GetHostManager()->OrphanRemoteHost(l4connected_host); + Unregister_Object(l4connected_host); + delete l4connected_host; + CreateConsoleHost(); + break; + default: + Fail("L4NetworkManager::HostDisconnectedMessageHandler - unknown host type"); + break; + } + DEBUG_STREAM << temp_net_address << "\n"; +} + +// +//############################################################################# +// Netnub wire primitives -- not yet reconstructed +//############################################################################# +// +unsigned long + L4NetworkManager::CheckSocket(unsigned long) +{ + Fail("L4NetworkManager::CheckSocket -- netnub path not yet reconstructed"); + return 0; +} + +unsigned long + L4NetworkManager::ResolveAddress(CString) +{ + Fail("L4NetworkManager::ResolveAddress -- netnub path not yet reconstructed"); + return 0; +} + +unsigned long + L4NetworkManager::GetMyAddress() +{ + Fail("L4NetworkManager::GetMyAddress -- netnub path not yet reconstructed"); + return 0; +} + +unsigned long + L4NetworkManager::OpenConnection(int, int, int, int) +{ + Fail("L4NetworkManager::OpenConnection -- netnub path not yet reconstructed"); + return 0; +} + +void + L4NetworkManager::CloseConnection(unsigned long) +{ + Fail("L4NetworkManager::CloseConnection -- netnub path not yet reconstructed"); +} + +Logical + L4NetworkManager::GetNextMungaPacket( + NetworkPacket *, + HostManager::RemoteHostIterator * + ) +{ + Fail("L4NetworkManager::GetNextMungaPacket -- netnub path not yet reconstructed"); + return False; +} + +Logical + L4NetworkManager::SendMessageToNetnub(Message *, ClientID, HostID) +{ + Fail("L4NetworkManager::SendMessageToNetnub -- netnub path not yet reconstructed"); + return False; +} + +void + L4NetworkManager::SendBatchedMessageToNetnub( + Message *, + ClientID, + DroppedMessageHostSocket * + ) +{ + Fail("L4NetworkManager::SendBatchedMessageToNetnub -- netnub path not yet reconstructed"); +} + +// +//############################################################################# +// L4NetworkManager__MessageBuffer +//############################################################################# +// +L4NetworkManager__MessageBuffer::L4NetworkManager__MessageBuffer( + L4NetworkManager *network_manager +): + messageQueueSocket(NULL, 1) +{ + networkManager = network_manager; + currentQueueIndex = 0; + bufferSize = 0; +} + +L4NetworkManager__MessageBuffer::~L4NetworkManager__MessageBuffer() +{ +} + +void + L4NetworkManager__MessageBuffer::AddSendRequest( + HostID, + NetworkClient::ClientID, + Receiver::Message * + ) +{ + Fail("L4NetworkManager__MessageBuffer::AddSendRequest -- netnub path not yet reconstructed"); +} + +void + L4NetworkManager__MessageBuffer::AttemptToSend() +{ + Fail("L4NetworkManager__MessageBuffer::AttemptToSend -- netnub path not yet reconstructed"); }