Files
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

698 lines
17 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "hostmgr.h"
#include "interest.h"
#include "app.h"
#include "entity.h"
//#############################################################################
//######################### HostManager #################################
//#############################################################################
//
// HACK - EntitySocketHashSize should come from somewhere else
//
const CollectionSize EntitySocketHashSize = 500;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HostManager data
//
HostManager::SharedData
HostManager::DefaultData(
HostManager::GetClassDerivations(),
HostManager::GetMessageHandlers()
);
Derivation* HostManager::GetClassDerivations()
{
static Derivation classDerivations(NetworkClient::GetClassDerivations(), "HostManager");
return &classDerivations;
}
const Receiver::HandlerEntry
HostManager::MessageHandlerEntries[]=
{
{
HostManager::NewHostMessageID,
"NewHost",
(HostManager::Handler)&Receiver::DefaultMessageHandler // HACK
},
{
HostManager::HostUpdateMessageID,
"HostUpdate",
(HostManager::Handler)&Receiver::DefaultMessageHandler // HACK
},
{
HostManager::EntityTransferOwnershipMessageID,
"EntityTransferOwnership",
(HostManager::Handler)&HostManager::EntityTransferOwnershipHandler
},
{
HostManager::EntityNewOwnershipMessageID,
"EntityNewOwnership",
(HostManager::Handler)&HostManager::EntityNewOwnershipHandler
}
};
Receiver::MessageHandlerSet& HostManager::GetMessageHandlers()
{
static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(HostManager::MessageHandlerEntries), HostManager::MessageHandlerEntries, Receiver::GetMessageHandlers());
return messageHandlers;
}
//
//#############################################################################
// HostManager
//#############################################################################
//
HostManager::HostManager():
NetworkClient(HostManagerClassID, DefaultData, HostManagerClientID),
remoteHostSocket(NULL, True),
allHostSocket(NULL, True),
entityIndexSocket(EntitySocketHashSize, NULL, True)
{
localHost = NULL;
allHostIterator = NULL;
}
//
//#############################################################################
//#############################################################################
//
HostManager::~HostManager()
{
if (allHostIterator != NULL)
{
Unregister_Object(allHostIterator);
delete allHostIterator;
allHostIterator = NULL;
}
Verify(localHost == NULL);
#if DEBUG_LEVEL>0
{
TableIteratorOf<Host*, HostID> iterator(&remoteHostSocket);
Check(&iterator);
Verify(iterator.GetSize() == 0);
}
#endif
#if DEBUG_LEVEL>0
{
HashIteratorOf<Entity*, EntityID> iterator(&entityIndexSocket);
Check(&iterator);
Verify(iterator.GetSize() == 0);
}
#endif
}
//
//#############################################################################
//#############################################################################
//
Logical
HostManager::TestInstance() const
{
if (!IsDerivedFrom(*GetClassDerivations()))
{
return False;
}
if (localHost != NULL)
{
Check(localHost)
}
if (allHostIterator != NULL)
{
Check(allHostIterator)
}
Check(&remoteHostSocket);
Check(&allHostSocket);
Check(&lastEntityID);
Check(&entityIndexSocket);
return True;
}
//
//#############################################################################
// Shutdown
//#############################################################################
//
void
HostManager::Shutdown()
{
Check(this);
#if 0 // HACK - Partial Implementation
//
//--------------------------------------------------------------------------
// For (each transferrable entity)
//--------------------------------------------------------------------------
//
//
// Find new host for ownership
//
//
// Send transfer entity ownership to that host
//
#else
//
//--------------------------------------------------------------------------
// Delete all of the entities
//--------------------------------------------------------------------------
//
if (localHost != NULL)
{
Check(localHost);
Host::AllEntityIterator iterator(localHost);
Check(&iterator);
iterator.DeletePlugs();
}
#endif
}
//
//#############################################################################
// AdoptLocalHost
//#############################################################################
//
void
HostManager::AdoptLocalHost(Host *local_host)
{
Check(this);
Check(local_host);
//
//--------------------------------------------------------------------------
// Verify that the local host is currently unassigned and then assign it
//--------------------------------------------------------------------------
//
Verify(lastEntityID == EntityID::Null);
Verify(localHost == NULL);
localHost = local_host;
EntityID entity_ID(local_host->GetHostID());
lastEntityID = entity_ID;
//
//--------------------------------------------------------------------------
// Add the local host to the all host socket
//--------------------------------------------------------------------------
//
allHostSocket.AddValue(local_host, local_host->GetHostID());
}
//
//#############################################################################
// OrphanLocalHost
//#############################################################################
//
Host*
HostManager::OrphanLocalHost()
{
Check(this);
//
//--------------------------------------------------------------------------
// Unassign the local host
//--------------------------------------------------------------------------
//
Host *local_host = localHost;
localHost = NULL;
lastEntityID = EntityID::Null;
//
//--------------------------------------------------------------------------
// Remove the local host from the all host socket
//--------------------------------------------------------------------------
//
if (local_host != NULL)
{
Check(local_host);
PlugIterator remover(local_host);
remover.RemoveSocket(&allHostSocket);
}
return local_host;
}
//
//#############################################################################
// AdoptRemoteHost
//#############################################################################
//
void
HostManager::AdoptRemoteHost(Host *remote_host)
{
Check(this);
Check(remote_host);
//
//--------------------------------------------------------------------------
// Add to the remote and all host socket
//--------------------------------------------------------------------------
//
remoteHostSocket.AddValue(remote_host, remote_host->GetHostID());
allHostSocket.AddValue(remote_host, remote_host->GetHostID());
}
//
//#############################################################################
// OrphanRemoteHost
//#############################################################################
//
void
HostManager::OrphanRemoteHost(Host *remote_host)
{
Check(this);
Check(remote_host);
//
//--------------------------------------------------------------------------
// Remove from the remote and all host socket
//--------------------------------------------------------------------------
//
{
PlugIterator remover(remote_host);
remover.RemoveSocket(&remoteHostSocket);
}
{
PlugIterator remover(remote_host);
remover.RemoveSocket(&allHostSocket);
}
}
//
//#############################################################################
// GetLocalHostID
//#############################################################################
//
HostID
HostManager::GetLocalHostID()
{
Check(this);
Check(localHost);
return localHost->GetHostID();
}
//
//#############################################################################
// GetRemoteHost
//#############################################################################
//
Host*
HostManager::GetRemoteHost(HostID host_ID)
{
Check(this);
Verify(host_ID >= FirstLegalHostID);
return remoteHostSocket.Find(host_ID);
}
//
//#############################################################################
// GetConsoleHost
//#############################################################################
//
Host*
HostManager::GetConsoleHost()
{
Check(this);
Host *host;
TableIteratorOf<Host*, HostID> iterator(&remoteHostSocket);
Check(&iterator);
while ((host = iterator.ReadAndNext()) != NULL)
{
Check(host);
if (host->GetHostType() == ConsoleHostType)
return host;
}
return NULL;
}
//
//#############################################################################
// FindHost
//#############################################################################
//
Host* HostManager::FindHost(SOCKADDR_IN &net_address)
{
Host *host;
TableIteratorOf<Host*, HostID> iterator(&allHostSocket);
while ((host = iterator.ReadAndNext()) != NULL)
if (*host->GetNetworkAddress() == net_address)
return host;
return NULL;
}
//
//#############################################################################
// MakeUniqueEntityID
//#############################################################################
//
EntityID
HostManager::MakeUniqueEntityID()
{
Check(this);
Verify(lastEntityID != EntityID::Null);
return (lastEntityID += 1);
}
//
//#############################################################################
// NotifyOfEntityCreation
//#############################################################################
//
void
HostManager::NotifyOfEntityCreation(
Entity *entity,
Entity::MakeMessage *creation_message
)
{
Check(this);
Check(entity);
Check(creation_message);
//
//--------------------------------------------------------------------------
// The host keeps track of all entities
//--------------------------------------------------------------------------
//
Check(localHost);
localHost->AddEntity(entity);
//
//--------------------------------------------------------------------------
// Link the entity to our index
//--------------------------------------------------------------------------
//
Verify(entity->GetEntityID() != EntityID::Null);
Check(&entityIndexSocket);
entityIndexSocket.AddValue(entity, entity->GetEntityID());
//
//--------------------------------------------------------------------------
// Call interest manager
//--------------------------------------------------------------------------
//
Check(application);
Check(application->GetInterestManager());
application->GetInterestManager()->NotifyOfEntityCreation(
entity,
creation_message
);
}
//
//#############################################################################
// NotifyOfReplacementEntityCreation
//#############################################################################
//
void
HostManager::NotifyOfReplacementEntityCreation(
Entity*,
EntityID,
ClassID,
LWord
)
{
Fail("HostManager::NotifyOfReplacementEntityCreation - under construction");
}
//
//#############################################################################
// NotifyOfEntityDestruction
//#############################################################################
//
void
HostManager::NotifyOfEntityDestruction(Entity *entity)
{
//
//--------------------------------------------------------------------------
// Perform any additional processing here...
//--------------------------------------------------------------------------
//
//
//--------------------------------------------------------------------------
// Notify interest manager of the destruction
//--------------------------------------------------------------------------
//
Check(application);
Check(application->GetInterestManager());
application->GetInterestManager()->NotifyOfEntityDestruction(entity);
}
//
//#############################################################################
// IdentifyNewMapEntityHost
//#############################################################################
//
HostID
HostManager::IdentifyNewMapEntityHost(
EntityID
)
{
Check(this);
//
//--------------------------------------------------------------------------
// HACK - Partial Implementation, since the entity IDs are not yet
// precomputed several assumptions are made. 1) The map stream read by each
// pilot is identical. 2) All of the hosts are connected at the point that
// the stream is read. => Therefore, it is easy to allocate the entities to
// each host.
//--------------------------------------------------------------------------
//
//
//--------------------------------------------------------------------------
// Verify that legal map entity hosts exist
//--------------------------------------------------------------------------
//
#if DEBUG_LEVEL>0
{
TableIteratorOf<Host*, HostID> iterator(&allHostSocket);
Host *host;
CollectionSize legal_map_entity_hosts = 0;
while ((host = iterator.ReadAndNext()) != NULL)
{
if (host->GetHostType() == GameMachineHostType)
{
legal_map_entity_hosts++;
}
}
Verify(legal_map_entity_hosts > 0);
}
#endif
//
//--------------------------------------------------------------------------
// Check the host iterator
//--------------------------------------------------------------------------
//
if (allHostIterator == NULL)
{
allHostIterator = new TableIteratorOf<Host*, HostID>(&allHostSocket);
Register_Object(allHostIterator);
}
Check(allHostIterator);
//
//--------------------------------------------------------------------------
// Get a legal map entity host
//--------------------------------------------------------------------------
//
Host *map_entity_host;
Logical is_legal_map_entity_host = False;
do
{
if ((map_entity_host = allHostIterator->GetCurrent()) == NULL)
{
allHostIterator->First();
map_entity_host = allHostIterator->GetCurrent();
}
Check(map_entity_host);
if (map_entity_host->GetHostType() == GameMachineHostType)
{
is_legal_map_entity_host = True;
}
else
{
allHostIterator->Next();
}
}
while (!is_legal_map_entity_host);
//
//--------------------------------------------------------------------------
// Move to the next host
//--------------------------------------------------------------------------
//
allHostIterator->Next();
//
//--------------------------------------------------------------------------
// Return the map entity host ID
//--------------------------------------------------------------------------
//
Check(map_entity_host);
Verify(map_entity_host->GetHostType() == GameMachineHostType);
Verify(map_entity_host->GetHostID() != NullHostID);
return map_entity_host->GetHostID();
}
//
//#############################################################################
// EntityTransferOwnership
//#############################################################################
//
void
HostManager::EntityTransferOwnershipHandler(
EntityTransferOwnershipMessage*
)
{
#if 0
//
// Find replicant for this entity
//
//
// If (replicant found)
//
//
// Morph the replicant into the master replicant
//
//
// If (the replicant was not found)
//
//
// Make a transferred master entity
//
//
// Broadcast new entity ownership
//
#else
Fail("HostManager::EntityTransferOwnershipHandler - under construction");
#endif
}
//
//#############################################################################
// EntityNewOwnership
//#############################################################################
//
void
HostManager::EntityNewOwnershipHandler(
EntityNewOwnershipMessage*
)
{
#if 0
//
// If (this host is the owner host)
//
//
// Return
//
//
// Find the replicant for this entity
//
//
// If (found the replicant)
//
//
// Point it at the new owner
//
#else
Fail("HostManager::EntityNewOwnershipHandler - under construction");
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllEntityIterator ~~~~~~~~~~~~~~~~~~~~~
HostManager__AllEntityIterator::HostManager__AllEntityIterator(
HostManager *host_manager
):
Host__AllEntityIterator(host_manager->localHost)
{
}
HostManager__AllEntityIterator::~HostManager__AllEntityIterator()
{
}
//~~~~~~~~~~~~~~~~~~ HostManager__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~~~
HostManager__DynamicMasterEntityIterator::
HostManager__DynamicMasterEntityIterator(
HostManager *host_manager
):
Host__DynamicMasterEntityIterator(host_manager->localHost)
{
}
HostManager__DynamicMasterEntityIterator::
~HostManager__DynamicMasterEntityIterator()
{
}
//~~~~~~~~~~~~~~~~~ HostManager__DynamicReplicantEntityIterator ~~~~~~~~~~~~~~~
HostManager__DynamicReplicantEntityIterator::
HostManager__DynamicReplicantEntityIterator(
HostManager *host_manager
):
Host__DynamicReplicantEntityIterator(host_manager->localHost)
{
}
HostManager__DynamicReplicantEntityIterator::
~HostManager__DynamicReplicantEntityIterator()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__RemoteHostIterator ~~~~~~~~~~~~~~~~~~~~
HostManager__RemoteHostIterator::HostManager__RemoteHostIterator(
HostManager *host_manager
):
TableIteratorOf<Host*, HostID>(&host_manager->remoteHostSocket)
{
}
HostManager__RemoteHostIterator::~HostManager__RemoteHostIterator()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllHostIterator ~~~~~~~~~~~~~~~~~~~~~~~
HostManager__AllHostIterator::HostManager__AllHostIterator(
HostManager *host_manager
):
TableIteratorOf<Host*, HostID>(&host_manager->allHostSocket)
{
}
HostManager__AllHostIterator::~HostManager__AllHostIterator()
{
}
#if 0
#if defined(TEST_CLASS)
#include "host.tcp"
#endif
#endif