Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
734 lines
19 KiB
C++
734 lines
19 KiB
C++
//===========================================================================//
|
|
// File: hostmgr.cpp //
|
|
// Project: MUNGA Brick: Connection Library //
|
|
// Contents: Interface specification for base Host class //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 10/28/94 ECH Initial coding. //
|
|
// 11/03/94 ECH Develop to munga spec //
|
|
// 11/29/94 JMA Moved EntityID to entity.cc //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <munga.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(HOSTMGR_HPP)
|
|
# include <hostmgr.hpp>
|
|
#endif
|
|
|
|
#if !defined(INTEREST_HPP)
|
|
# include <interest.hpp>
|
|
#endif
|
|
|
|
#if !defined(APP_HPP)
|
|
#include <app.hpp>
|
|
#endif
|
|
|
|
#if !defined(ENTITY_HPP)
|
|
#include <entity.hpp>
|
|
#endif
|
|
|
|
//#############################################################################
|
|
//######################### HostManager #################################
|
|
//#############################################################################
|
|
|
|
//
|
|
// HACK - EntitySocketHashSize should come from somewhere else
|
|
//
|
|
const CollectionSize EntitySocketHashSize = 500;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// HostManager data
|
|
//
|
|
HostManager::SharedData
|
|
HostManager::DefaultData(
|
|
HostManager::ClassDerivations,
|
|
HostManager::MessageHandlers
|
|
);
|
|
|
|
Derivation
|
|
HostManager::ClassDerivations(
|
|
NetworkClient::ClassDerivations,
|
|
"HostManager"
|
|
);
|
|
|
|
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::MessageHandlers(
|
|
ELEMENTS(HostManager::MessageHandlerEntries),
|
|
HostManager::MessageHandlerEntries,
|
|
Receiver::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(ClassDerivations))
|
|
{
|
|
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(NetworkAddress net_address)
|
|
{
|
|
Check(this);
|
|
|
|
Host *host;
|
|
TableIteratorOf<Host*, HostID> iterator(&allHostSocket);
|
|
|
|
Check(&iterator);
|
|
while ((host = iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(host);
|
|
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
|