#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 iterator(&remoteHostSocket); Check(&iterator); Verify(iterator.GetSize() == 0); } #endif #if DEBUG_LEVEL>0 { HashIteratorOf 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 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 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 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(&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_manager->remoteHostSocket) { } HostManager__RemoteHostIterator::~HostManager__RemoteHostIterator() { } //~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllHostIterator ~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllHostIterator::HostManager__AllHostIterator( HostManager *host_manager ): TableIteratorOf(&host_manager->allHostSocket) { } HostManager__AllHostIterator::~HostManager__AllHostIterator() { } #if 0 #if defined(TEST_CLASS) #include "host.tcp" #endif #endif