Files
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

2598 lines
67 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "interest.h"
#include "registry.h"
#include "mission.h"
#include "boxtree.h"
#include "renderer.h"
#include "cultural.h"
#include "app.h"
#include "hostmgr.h"
//#############################################################################
//####################### InterestManager ###############################
//#############################################################################
//
//--------------------------------------------------------------------
// InterestManager data
//--------------------------------------------------------------------
//
unsigned char
InterestManager::messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE];
InterestManager::SharedData
InterestManager::DefaultData(
InterestManager::GetClassDerivations(),
InterestManager::GetMessageHandlers()
);
Derivation* InterestManager::GetClassDerivations()
{
static Derivation classDerivations(NetworkClient::GetClassDerivations(), "InterestManager");
return &classDerivations;
}
const Receiver::HandlerEntry
InterestManager::MessageHandlerEntries[]=
{
//
// NewDynamicEntityMessageID
//
{
InterestManager::NewDynamicEntityMessageID,
"NewDynamicEntity",
(InterestManager::Handler)&InterestManager::NewDynamicEntityHandler
},
//
// DestroyDynamicEntityMessageID
//
{
InterestManager::DestroyDynamicEntityMessageID,
"DestroyDynamicEntity",
(InterestManager::Handler)&InterestManager::DestroyDynamicEntityHandler
},
//
// EntitySubscribeToUpdatesMessageID
//
{
InterestManager::EntitySubscribeToUpdatesMessageID,
"EntitySubscribeToUpdates",
(InterestManager::Handler)&InterestManager::EntitySubscribeToUpdatesHandler
},
//
// EntityUpdateReplicantsMessageID
//
{
InterestManager::EntityUpdateReplicantsMessageID,
"EntityUpdateReplicants",
(InterestManager::Handler)&InterestManager::EntityUpdateReplicantsHandler
},
//
// EntityBroadcastToReplicantsMessageID
//
{
InterestManager::EntityBroadcastToReplicantsMessageID,
"EntityBroadcastToReplicants",
(InterestManager::Handler)&InterestManager::EntityBroadcastToReplicantsHandler
},
//
// EntityNewInterestZoneMessageID
//
{
InterestManager::EntityNewInterestZoneMessageID,
"EntityNewInterestZone",
(InterestManager::Handler)&InterestManager::EntityNewInterestZoneHandler
},
//
// HostInterestArenaChangedMessageID
//
{
InterestManager::HostInterestArenaChangedMessageID,
"HostInterestArenaChanged",
(InterestManager::Handler)&InterestManager::HostInterestArenaChangedHandler
},
//
// InterestZoneDeltaMessageID
//
{
InterestManager::InterestZoneDeltaMessageID,
"InterestZoneDelta",
(InterestManager::Handler)&InterestManager::InterestZoneDeltaHandler
},
//
// LoadResourceFinishedMessageID
//
{
Receiver::LoadResourceFinishedMessageID,
"LoadResourceFinished",
(InterestManager::Handler)&InterestManager::LoadResourceFinishedHandler
}
};
Receiver::MessageHandlerSet& InterestManager::GetMessageHandlers()
{
static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(InterestManager::MessageHandlerEntries), InterestManager::MessageHandlerEntries, NetworkClient::GetMessageHandlers());
return messageHandlers;
}
//
//#############################################################################
// InterestManager
//#############################################################################
//
InterestManager::InterestManager():
NetworkClient(InterestManagerClassID, DefaultData, InterestManagerClientID),
interestOriginSocket(NULL)
{
interestArena = NULL;
}
//
//#############################################################################
// ~InterestManager
//#############################################################################
//
InterestManager::~InterestManager()
{
if (interestArena != NULL)
{
Unregister_Object(interestArena);
delete interestArena;
}
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
InterestManager::TestInstance() const
{
if (!IsDerivedFrom(*GetClassDerivations()))
{
return False;
}
Check(&interestLatticeManager);
return True;
}
//
//#############################################################################
// LoadMission
//#############################################################################
//
void
InterestManager::LoadInterestArenas(Mission*)
{
Check(this);
#if 0 // HACK - Partial Implementation
//
//--------------------------------------------------------------------------
// Load the interest zones that are accessed by the pilot's drop zone
//--------------------------------------------------------------------------
//
#else
//
//--------------------------------------------------------------------------
// Make one interest arena manually
//--------------------------------------------------------------------------
//
#if DEBUG_LEVEL>0
{
Check(&interestOriginSocket);
SChainIteratorOf<InterestOrigin*> iterator(&interestOriginSocket);
Check(&iterator);
Verify(iterator.GetSize() == 0);
}
#endif
Verify(interestArena == NULL);
interestArena = interestLatticeManager.MakeInterestArena(
(InterestZoneID)0,
(InterestType)0,
(InterestDepth)0
);
Register_Object(interestArena);
#endif
}
//
//#############################################################################
// LoadMission
//#############################################################################
//
void
InterestManager::LoadMission(Mission *mission)
{
Check(this);
Check(mission);
//
//--------------------------------------------------------------------------
// Return if the map ID is not valid
//--------------------------------------------------------------------------
//
if (mission->GetMapID() == ResourceDescription::NullResourceID)
return;
//
//--------------------------------------------------------------------------
// Get the resource description
//--------------------------------------------------------------------------
//
ResourceFile *resource_file;
ResourceDescription *resource_description;
Check(application);
resource_file = application->GetResourceFile();
Check(resource_file);
resource_description =
resource_file->FindResourceDescription(mission->GetMapID());
Check(resource_description);
resource_description->Lock();
//
//--------------------------------------------------------------------------
// Create the map stream and load
//--------------------------------------------------------------------------
//
MemoryStream
map_stream(
resource_description->resourceAddress,
resource_description->resourceSize
);
Check(&map_stream);
EntityID last_entity_id(MapHostID);
int landmark_id=0;
LoadMapStream(&map_stream, Origin::Identity, last_entity_id, landmark_id);
resource_description->Unlock();
//
//--------------------------------------------------------------------------
// HACK - load in the collision resources into the tree pointed to by
// this resource
//--------------------------------------------------------------------------
//
resource_description =
resource_file->FindResourceDescription(mission->GetExistanceMapID());
if (resource_description)
{
Check(resource_description);
resource_description->Lock();
InterestZone *zone =
GetInterestZone(interestArena->GetInterestZoneID());
Check(zone);
BoundingBoxTree* tree = zone->GetExistanceRoot();
Check(tree);
ExtentBox* zones = (ExtentBox*)resource_description->resourceAddress;
int size = resource_description->resourceSize / sizeof(ExtentBox);
while (size--)
{
BoundingBox *box;
box = new BoundingBox(*zones);
Register_Object(box);
tree->Add(box, *box);
++zones;
}
resource_description->Unlock();
}
resource_file->ReleaseUnlockedResources();
}
//
//#############################################################################
// LoadMapStream
//#############################################################################
//
void
InterestManager::LoadMapStream(
MemoryStream *map_stream,
const Origin &root,
EntityID &last_entity_id,
int &landmark_id
)
{
Check(this);
Check(map_stream);
//
//--------------------------------------------------------------------------
// Read the map stream and post creation messages
//--------------------------------------------------------------------------
//
int map_count;
*map_stream >> map_count;
for (int i=0; i<map_count; ++i)
{
Entity::MakeMessage *message =
Cast_Object(Entity::MakeMessage*, map_stream->GetPointer());
Check(message);
//
//-----------------------------------------------------------
// If this is an include message, recurse into a new map load
//-----------------------------------------------------------
//
if (message->messageFlags & Entity::MakeMessage::MapStreamMarkerFlag)
{
if (message->messageID == Entity::MakeMessageID)
{
Verify(message->messageLength == sizeof(Entity::MakeMapMessage));
Entity::MakeMapMessage *map_message =
Cast_Object(Entity::MakeMapMessage*, message);
Check(map_message);
//
//
//-----------------------------
// Get the resource description
//-----------------------------
//
Check(application);
ResourceFile *resource_file = application->GetResourceFile();
Check(resource_file);
ResourceDescription *resource_description =
resource_file->FindResourceDescription(
map_message->resourceID
);
Check(resource_description);
resource_description->Lock();
//
//--------------------------------------------------
// Figure out the origin to use for this map include
// HACK - map rotation is not supported
//--------------------------------------------------
//
Origin local = map_message->localOrigin;
local.linearPosition += root.linearPosition;
//
//-------------------------------
// Create the map stream and load
//-------------------------------
//
MemoryStream
map_stream(
resource_description->resourceAddress,
resource_description->resourceSize
);
Check(&map_stream);
LoadMapStream(&map_stream, local, last_entity_id, landmark_id);
resource_description->Unlock();
}
else
{
Fail("Unknown message marker in map stream!\n");
}
map_stream->AdvancePointer((message->messageLength+3)&~3);
continue;
}
//
//-------------------
// Verify the message
//-------------------
//
#if DEBUG_LEVEL>0
//
//----------------------------------------------------------
// These classes should be stored in the map as map entities
//----------------------------------------------------------
//
switch (message->classToCreate)
{
case DropZoneClassID:
case ScoreZoneClassID:
case DoorFrameClassID:
case CulturalIconClassID:
case LandmarkClassID:
if ((message->instanceFlags & Entity::MapFlag) == 0)
{
Fail("InterestManager::LoadMapStream - MapFlag disabled");
}
break;
default:
break;
}
#endif
//
//---------------------------------------------------------------------
// If the message id is for a map entity, only make the thing if we are
// supposed to
//---------------------------------------------------------------------
//
Logical post_make_message = True;
if (Entity::EntityFlagsIsMap(message->instanceFlags))
{
Check(application);
HostManager *host_manager = application->GetHostManager();
Check(host_manager);
if (
host_manager->GetLocalHostID() !=
host_manager->IdentifyNewMapEntityHost(message->entityID)
)
{
post_make_message = False;
}
}
//
//-----------------------------------------------------
// Make a MakeEntityMessage and post it to the registry
//-----------------------------------------------------
//
if (post_make_message)
{
//
//--------------------------------------------------------------
// Make a copy of the message for modification by the map origin
// HACK - map rotation is not supported
//--------------------------------------------------------------
//
Entity::MakeMessage *local_msg =
(Entity::MakeMessage*)new char[message->messageLength];
Register_Pointer(local_msg);
Mem_Copy(
local_msg,
message,
message->messageLength,
message->messageLength
);
local_msg->localOrigin.linearPosition += root.linearPosition;
//
//---------------------------------------------------
// If this is a landmark, assign the next landmark ID
//---------------------------------------------------
//
if (local_msg->classToCreate == LandmarkClassID)
{
Landmark::MakeMessage *land_msg =
(Landmark::MakeMessage*)local_msg;
land_msg->landmarkID = landmark_id++;
}
//
//--------------------------------------------------------
// If this is not a dynamic object, assign it an entity ID
//--------------------------------------------------------
//
if (!(local_msg->instanceFlags & Entity::DynamicFlag))
{
last_entity_id += 1;
local_msg->entityID = last_entity_id;
}
Registry::MakeEntityMessage
*make_entity_message =
Registry::MakeEntityMessage::Make(local_msg);
Register_Object(make_entity_message);
Check(application);
// ECH 1/28/96 - application->PostCreationEvent(make_entity_message);
PostCreationEvent(make_entity_message);
#if 0
Tell(
"InterestManager::LoadMapStream - Posted creation event: " <<
"class=" << message->classToCreate << "; " <<
"entityID=" << message->entityID << "\n"
);
#endif
Unregister_Object(make_entity_message);
delete make_entity_message;
Unregister_Pointer(local_msg);
delete (char*)local_msg;
}
//
//-----------------------------------------------------------------------
// Advance to the next message
//-----------------------------------------------------------------------
//
map_stream->AdvancePointer((message->messageLength+3)&~3);
}
Check_Fpu();
}
//
//#############################################################################
// Shutdown
//#############################################################################
//
void
InterestManager::Shutdown()
{
Check(this);
#if 0 // HACK - Partial Implementation
//
//--------------------------------------------------------------------------
// Delete interest zones
//--------------------------------------------------------------------------
//
#else
//
// Delete the one interest arena
//
if (interestArena)
{
Unregister_Object(interestArena);
delete interestArena;
interestArena = NULL;
}
#endif
}
//
//#############################################################################
// Execute
//#############################################################################
//
void
InterestManager::Execute()
{
#if 0
//
// If (the changed origin list is empty)
//
//
// return
//
//
// Update the net interest arena with the changes from the
// changed interest origin list
//
//
// Calculate which interest zones should be released and which
// interest zones should be loaded
//
//
// For (the interest zones which should be released)
//
//
// For (the static entities in the interest zones to be released)
//
//
// Send a becoming uninteresting event to the entity
//
//
// For (the dynamic master entities in the interest zones to be released)
//
//
// Send a becoming uninteresting event to the entity
//
//
// For (the dynamic map entities in the interest zones to be released)
//
//
// Send a becoming uninteresting event to the entity
//
//
// For (the replicants in the interest zones to be released)
//
//
// Unsubscribe the replicants from changes
//
//
// Send a becoming uninteresting event to the entity
//
//
// Call the resource manager releasing the interest zone
//
//
// For (the interest zones which should be loaded)
//
//
// Call the resource manager, requesting the interest zones
//
//
// Broadcast the interest arena change
//
{
HostInterestArenaChangedMessage message;
//
// Send at the end of the current frame
//
Check(application);
application->BroadcastEvent(
DefaultEventPriority,
InterestManagerID,
&message
);
}
#endif
}
//
//#############################################################################
// AdoptInterestOrigin
//#############################################################################
//
void
InterestManager::AdoptInterestOrigin(InterestOrigin *interest_origin)
{
Check(this);
Check(interest_origin);
//
//--------------------------------------------------------------------------
// Add the interest origin to managers socket
//--------------------------------------------------------------------------
//
Check(&interestOriginSocket);
interestOriginSocket.Add(interest_origin);
#if 0 // HACK - Partial Implementation
//
//--------------------------------------------------------------------------
// Add to net interest arena...
//--------------------------------------------------------------------------
//
#else
//
//--------------------------------------------------------------------------
// HACK - add interesting entities to the interest origin manually
//--------------------------------------------------------------------------
//
interest_origin->Update(interest_origin->GetInterestZoneID());
AddInterestingEntitiesToInterestOrigin(interest_origin);
#endif
}
//
//#############################################################################
// OrphanInterestOrigin
//#############################################################################
//
void
InterestManager::OrphanInterestOrigin(InterestOrigin *interest_origin)
{
Check(this);
Check(interest_origin);
#if 0 // HACK - Partial Implementation
//
//--------------------------------------------------------------------------
// Remove from net interest arena
//--------------------------------------------------------------------------
//
#else
//
//--------------------------------------------------------------------------
// HACK - remove interesting entities manually
//--------------------------------------------------------------------------
//
RemoveUninterestingEntitiesFromInterestOrigin(interest_origin);
#endif
}
//
//#############################################################################
// NotifyOfEntityCreation
//#############################################################################
//
void
InterestManager::NotifyOfEntityCreation(
Entity *entity,
Entity::MakeMessage *creation_message
)
{
Check(this);
Check(entity);
Check(creation_message);
#if 0
Tell(
"InterestManager::NotifyOfEntityCreation - " <<
"class=" << entity->GetClassID() << "; " <<
"entityID=" << entity->GetEntityID() << "\n"
);
#endif
//
//--------------------------------------------------------------------------
// Call appropriate service routine
//--------------------------------------------------------------------------
//
switch (entity->GetInstance())
{
case Entity::IndependantInstance:
{
Check(application);
Check(application->GetHostManager());
if (
entity->GetOwnerID() ==
application->GetHostManager()->GetLocalHostID()
)
{
DynamicEntityCreation(entity, creation_message);
}
else
{
ReplicantEntityCreation(entity, creation_message);
}
}
break;
case Entity::MasterInstance:
DynamicEntityCreation(entity, creation_message);
break;
case Entity::HermitInstance:
if (entity->IsDynamic())
{
DynamicEntityCreation(entity, creation_message);
}
else
{
StaticEntityCreation(entity, creation_message);
}
break;
case Entity::ReplicantInstance:
ReplicantEntityCreation(entity, creation_message);
break;
default:
Fail("InterestManager::NotifyOfEntityCreation - should never reach here");
break;
}
}
//
//#############################################################################
// StaticEntityCreation
//#############################################################################
//
void
InterestManager::StaticEntityCreation(
#if DEBUG_LEVEL>0
Entity *entity,
Entity::MakeMessage *creation_message
#else
Entity *entity,
Entity::MakeMessage *
#endif
)
{
Check(this);
Check(entity);
Check(creation_message);
//
//--------------------------------------------------------------------------
// Verify entityID, instance, and flags
//--------------------------------------------------------------------------
//
Verify(entity->GetEntityID() != EntityID::Null);
Verify(
entity->GetInstance() == Entity::MasterInstance ||
entity->GetInstance() == Entity::HermitInstance
);
// Verify(entity->IsStatic()); // HACK - Partial Implementation
// Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// The interest zone of the static entity should already be calculated
// correctly
//--------------------------------------------------------------------------
//
#else
//
//--------------------------------------------------------------------------
// Find the interest zone for the static entity and set the interest zone
//--------------------------------------------------------------------------
//
InterestZoneID interest_zone_ID;
interest_zone_ID =
interestLatticeManager.SearchForEntityInterestZone(
(InterestZoneID)0,
entity->GetEntityID()
);
entity->SetInterestZoneID(interest_zone_ID);
#endif
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If within any existing interest arenas, then add to the interest origin
//--------------------------------------------------------------------------
//
#else
//
//--------------------------------------------------------------------------
// HACK - Manually add to all interest origins
//--------------------------------------------------------------------------
//
AddInterestingEntityToInterestOrigins(entity);
#endif
}
//
//#############################################################################
// DynamicEntityCreation
//#############################################################################
//
void
InterestManager::DynamicEntityCreation(
Entity *entity,
Entity::MakeMessage *creation_message
)
{
Check(this);
Check(entity);
Check(creation_message);
//
//--------------------------------------------------------------------------
// Verify entityID, instance, and flags
//--------------------------------------------------------------------------
//
#if DEBUG_LEVEL>0
Verify(entity->GetEntityID() != EntityID::Null);
Verify(
entity->GetInstance() == Entity::MasterInstance ||
entity->GetInstance() == Entity::IndependantInstance ||
entity->GetInstance() == Entity::HermitInstance
);
// Verify(entity->IsDynamic()); // HACK - Partial Implementation
// Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities
if (entity->GetInstance() == Entity::IndependantInstance)
{
Check(application);
Check(application->GetHostManager());
Verify(
entity->GetOwnerID() ==
application->GetHostManager()->GetLocalHostID()
);
}
#endif
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// Set the interest zone id of the entity. Use the spatializer to locate
// the interest zone that the entity is located in
//--------------------------------------------------------------------------
//
#else
//
//--------------------------------------------------------------------------
// Find the interest zone for the static entity and set the interest zone
//--------------------------------------------------------------------------
//
InterestZoneID interest_zone_ID;
interest_zone_ID =
interestLatticeManager.SearchForEntityInterestZone(
(InterestZoneID)0,
entity->GetEntityID()
);
entity->SetInterestZoneID(interest_zone_ID);
#endif
//
//--------------------------------------------------------------------------
// Send new dynamic entity message
//--------------------------------------------------------------------------
//
//
// Setup and verify network fields in creation message
//
entity->SetupNetworkMessage(creation_message);
#if DEBUG_LEVEL>0
Check(&creation_message->entityID);
Verify(creation_message->entityID != EntityID::Null);
Verify(creation_message->interestZoneID != NullInterestZoneID);
Check(application);
Check(application->GetHostManager());
Verify(
creation_message->ownerID ==
application->GetHostManager()->GetLocalHostID()
);
#endif
//
// HACK - Spoof the make entity message into a NewDynamicEntityMessageID
// for the purposes of sending to interest managers
//
Verify(creation_message->messageID == Entity::MakeMessageID);
creation_message->messageID = NewDynamicEntityMessageID;
//
//--------------------------------------------------------------------------
// If the entity is replicated
//--------------------------------------------------------------------------
//
if (
entity->GetInstance() == Entity::MasterInstance ||
entity->GetInstance() == Entity::IndependantInstance
)
{
//
// Broadcast the message
//
Check(application);
application->BroadcastMessage(InterestManagerClientID, creation_message);
}
//
//--------------------------------------------------------------------------
// Else (the entity is not replicated)
//--------------------------------------------------------------------------
//
else
{
Verify(entity->GetInstance() == Entity::HermitInstance);
//
// Post the message to ourselves
//
Check(application);
// ECH 1/28/96 - application->Post(DefaultEventPriority, this, creation_message);
Dispatch(creation_message);
}
}
//
//#############################################################################
// NewDynamicEntityHandler
//#############################################################################
//
void
InterestManager::NewDynamicEntityHandler(
NewDynamicEntityMessage *creation_message
)
{
Check(this);
Check(creation_message);
//
// Verify the creation message
//
Check(&creation_message->entityID);
Verify(creation_message->entityID != EntityID::Null);
Verify(creation_message->interestZoneID != NullInterestZoneID);
Verify(creation_message->ownerID >= FirstLegalHostID);
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If (the new entity is not in any of the interest arenas)
//--------------------------------------------------------------------------
//
//
// return
//
#endif
//
//--------------------------------------------------------------------------
// Get the local host id
//--------------------------------------------------------------------------
//
HostID local_host_ID;
Check(application);
Check(application->GetHostManager());
local_host_ID = application->GetHostManager()->GetLocalHostID();
//
//--------------------------------------------------------------------------
// If (this host is not the owner host)
//--------------------------------------------------------------------------
//
if (local_host_ID != creation_message->ownerID)
{
//
//-----------------------------------------------------------------------
// Make the replicant
//-----------------------------------------------------------------------
//
//
// HACK - Message was spoofed as NewDynamicEntityMessageID, now
// turn back to make entity message ID
//
Verify(creation_message->messageID == NewDynamicEntityMessageID);
creation_message->messageID = Entity::MakeMessageID;
//
// Turn on the replicant flag if this is a master instance,
// otherwise, the instance should be an independant
//
if (
Entity::EntityFlagsGetInstance(creation_message->instanceFlags) ==
Entity::MasterInstance
)
{
creation_message->instanceFlags = Entity::EntityFlagsSetInstance(
creation_message->instanceFlags,
Entity::ReplicantInstance
);
}
else
{
Verify(
Entity::EntityFlagsGetInstance(creation_message->instanceFlags) ==
Entity::IndependantInstance
);
}
//
//-----------------------------------------------------------------------
// Make a MakeEntityMessage and post it to the registry
//-----------------------------------------------------------------------
//
Registry::MakeEntityMessage *make_entity_message;
make_entity_message = Registry::MakeEntityMessage::Make(creation_message);
Register_Object(make_entity_message);
Check(application);
//
// Implicit assumption that this will be a higher
// priority and/or earlier sequence than any update message
//
Check(application->GetRegistry());
application->GetRegistry()->Dispatch(make_entity_message);
Unregister_Object(make_entity_message);
delete make_entity_message;
}
//
//--------------------------------------------------------------------------
// If (this host is the owner host)
//--------------------------------------------------------------------------
//
else
{
//
//-----------------------------------------------------------------------
// Get the entity pointer
//-----------------------------------------------------------------------
//
Entity *entity;
Check(application);
Check(application->GetHostManager());
entity = application->GetHostManager()->GetEntityPointer(
creation_message->entityID
);
Check(entity);
//
//-----------------------------------------------------------------------
// Tell the master that it is interesting
// Should this wait until next interest frame?
//-----------------------------------------------------------------------
//
entity->BecomeInteresting();
//
//-----------------------------------------------------------------------
// HACK - Manually add to all interest origins
//-----------------------------------------------------------------------
//
AddInterestingEntityToInterestOrigins(entity);
}
}
#if 0 // HACK - Partial Implementation
//
//#############################################################################
// NotifyOfMapEntityCreation
//#############################################################################
//
void
InterestManager::NotifyOfMapEntityCreation(
Entity *entity,
Entity::MakeMessage *creation_message,
Time
)
{
Check(this);
Check(entity);
Check(creation_message);
Verify(creation_message->entityID != EntityID::Null);
Verify(creation_message->interestZoneID != NullInterestZoneID);
//
// Verify instance type, and interest characterisitics
//
Verify(entity->GetInstance() == Entity::MasterInstance);
Verify(entity->IsDynamic());
Verify(entity->IsMap());
#if 0
//
// Call the resource manager, storing the interest zone delta
//
//
// Broadcast the interest zone delta
//
{
InterestZoneDeltaMessage message;
Check(application);
application->SendMessage(
DefaultEventPriority,
InterestManagerID,
&message
);
}
//
// Broadcast the new map entity message
//
{
Verify(creation_message->messageID == Entity::MakeMessageID);
creation_message->messageID = NewMapEntityMessageID;
Check(application);
application->SendMessage(
DefaultEventPriority,
InterestManagerID,
creation_message
);
}
#else
Fail("InterestManager::NotifyOfMapEntityCreation - under construction");
#endif
}
#endif
#if 0 // HACK - Partial Implementation
//
//#############################################################################
// NewMapEntityHandler
//#############################################################################
//
void
InterestManager::NewMapEntityHandler(
NewMapEntityMessage *message
)
{
Check(this);
Check(message);
#if 0
//
// If (the entity is outside of the interest arena)
//
//
// Return
//
//
// If (this is the owner host)
//
//
// Tell the entity that it is interesting
//
//
// If (this host is not the owner host)
//
//
// Find the replicant or local master entity
//
//
// If (the entity does not exist)
//
//
// Make the replicant
//
//
// Tell the replicant that it is interesting
//
//
// Subscribe the replicant to updates from the master
//
//
// If (the entity does exist)
//
//
// If (the entity is a replicant)
//
//
// Point it at the new owner
//
//
// If (the entity is a master)
//
//
// If (creation time of new master > creation time of local master)
//
//
// Morph the local master into a replicant pointing at new master
//
//
// Tell the replicant that it is interesting
//
//
// Subscribe the replicant to updates from the master
//
#else
Fail("InterestManager::NewMapEntityHandler - under construction");
#endif
}
#endif
//
//#############################################################################
// ReplicantEntityCreation
//#############################################################################
//
void
InterestManager::ReplicantEntityCreation(
#if DEBUG_LEVEL>0
Entity *entity,
Entity::MakeMessage *creation_message
#else
Entity *entity,
Entity::MakeMessage *
#endif
)
{
Check(this);
Check(entity);
Check(creation_message);
//
//--------------------------------------------------------------------------
// Verify entityID, instance, and flags
//--------------------------------------------------------------------------
//
#if DEBUG_LEVEL>0
Verify(entity->GetEntityID() != EntityID::Null);
Verify(
entity->GetInstance() == Entity::ReplicantInstance ||
entity->GetInstance() == Entity::IndependantInstance
);
// Verify(entity->IsDynamic()); // HACK - Partial Implementation
// Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities
if (entity->GetInstance() == Entity::IndependantInstance)
{
Check(application);
Check(application->GetHostManager());
Verify(
entity->GetOwnerID() !=
application->GetHostManager()->GetLocalHostID()
);
}
#endif
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// The interest zone of the static entity should already be calculated
// correctly
//--------------------------------------------------------------------------
//
#endif
//
//--------------------------------------------------------------------------
// Get the local host id
//--------------------------------------------------------------------------
//
HostID local_host_ID;
Check(application);
Check(application->GetHostManager());
local_host_ID = application->GetHostManager()->GetLocalHostID();
//
//--------------------------------------------------------------------------
// Subscribe the replicant to updates from the master
//--------------------------------------------------------------------------
//
EntitySubscribeToUpdates(
entity->GetEntityID(),
entity->GetOwnerID(),
local_host_ID
);
//
//--------------------------------------------------------------------------
// Tell the replicant that it is interesting
//--------------------------------------------------------------------------
//
entity->BecomeInteresting();
//
//--------------------------------------------------------------------------
// HACK - Manually add to all interest origins
//--------------------------------------------------------------------------
//
AddInterestingEntityToInterestOrigins(entity);
}
//
//#############################################################################
// NotifyOfEntityDestruction
//#############################################################################
//
void
InterestManager::NotifyOfEntityDestruction(Entity *entity)
{
Check(this);
Check(entity);
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If (this is a map entity)
//--------------------------------------------------------------------------
//
//
// Store an interest zone delta with the owner set to MapHostID
//
//
// Broadcast an interest zone delta
//
#endif
//
//--------------------------------------------------------------------------
// HACK - Manually remove from all interest origins
//--------------------------------------------------------------------------
//
RemoveUninterestingEntityFromInterestOrigins(entity);
//
//--------------------------------------------------------------------------
// Broadcast delete entity message for master entities that have replicants
//--------------------------------------------------------------------------
//
if (
entity->GetInstance() == Entity::MasterInstance // && // HACK - Partial Implementation
// entity->IsDynamic() // HACK - Partial Implementation
)
{
//
// Create destruction message
//
DestroyDynamicEntityMessage
destroy_message(
DestroyDynamicEntityMessageID,
sizeof(DestroyDynamicEntityMessage)
);
Check(&destroy_message);
//
// Setup and verify network fields in destruction message
//
entity->SetupNetworkMessage(&destroy_message);
#if DEBUG_LEVEL>0
Check(&destroy_message.entityID);
Verify(destroy_message.entityID == entity->entityID);
Verify(destroy_message.interestZoneID == entity->interestZoneID);
Check(application);
Check(application->GetHostManager());
Verify(
destroy_message.ownerID ==
application->GetHostManager()->GetLocalHostID()
);
#endif
//
// Broadcast destruction message
//
Check(application);
application->ExclusiveBroadcastMessage(
InterestManagerClientID,
&destroy_message
);
}
}
//
//#############################################################################
// DestroyDynamicEntityHandler
//#############################################################################
//
void
InterestManager::DestroyDynamicEntityHandler(
DestroyDynamicEntityMessage *destroy_message
)
{
Check(this);
Check(destroy_message);
//
// Verify destruction message
//
Check(&destroy_message->entityID);
Verify(destroy_message->entityID != EntityID::Null);
Verify(destroy_message->interestZoneID != NullInterestZoneID);
Verify(destroy_message->ownerID >= FirstLegalHostID);
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If entity is not within interest zone
//--------------------------------------------------------------------------
//
//
// return
//
#endif
//
//--------------------------------------------------------------------------
// Verify the local host id
//--------------------------------------------------------------------------
//
#if DEBUG_LEVEL>0
HostID local_host_ID;
Check(application);
Check(application->GetHostManager());
local_host_ID = application->GetHostManager()->GetLocalHostID();
Verify(destroy_message->ownerID != local_host_ID);
#endif
//
//--------------------------------------------------------------------------
// Find the replicant to destroy
//--------------------------------------------------------------------------
//
Entity *replicant;
Check(application);
Check(application->GetHostManager());
replicant = application->GetHostManager()->GetEntityPointer(
destroy_message->entityID
);
//
//--------------------------------------------------------------------------
// If (the replicant exists)
//--------------------------------------------------------------------------
//
if (replicant != NULL)
{
Check(replicant);
Verify(replicant->GetInstance() == Entity::ReplicantInstance);
//
// HACK - Message was spoofed as DestroyDynamicEntityMessage, now
// turn back to DestroyEntityMessage
//
Verify(destroy_message->messageID == DestroyDynamicEntityMessageID);
destroy_message->messageID = Entity::DestroyEntityMessageID;
Check(application);
// ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, destroy_message);
PostDestructionEvent(replicant, destroy_message);
}
}
//
//#############################################################################
// EntityUpdateInterestZone
//#############################################################################
//
void
InterestManager::EntityUpdateInterestZone(
#if DEBUG_LEVEL>0
Entity *entity
#else
Entity *
#endif
)
{
Check(this);
Check(entity);
Verify(entity->IsDynamic());
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------
// Update the interest zone id if the entity is not trapped
//--------------------------------------------------------------------
//
if (entity->IsTrapped())
return;
//
//--------------------------------------------------------------------
// Find the entities new interest zone
//--------------------------------------------------------------------
//
InterestZoneID
old_interest_zone_ID,
new_interest_zone_ID;
old_interest_zone_ID = entity->GetInterestZoneID();
new_interest_zone_ID =
interestLatticeManager.SearchForEntityInterestZone(
old_interest_zone_ID,
entity->GetEntityID()
);
//
//--------------------------------------------------------------------
// If the interest zone has changed, then update the entity
// and broadcast the change
//--------------------------------------------------------------------
//
if (old_interest_zone_ID != new_interest_zone_ID)
{
entity->SetInterestZoneID(new_interest_zone_ID);
//
// HACK - a way is needed to get from the entity the information
// required for another host to create the replicant
//
EntityNewInterestZoneMessage
message(entity->GetEntityID(),new_interest_zone_ID);
//
// This message should be handled locally before the end of
// the current render frame?
//
#if 0
Check(application);
application->SendEvent(
DefaultEventPriority,
InterestManagerID,
&message
);
#else
Check(application);
application->BroadcastMessage(
InterestManagerClientID,
&message
);
#endif
}
#endif
}
//
//#############################################################################
// EntityNewInterestZoneHandler
//#############################################################################
//
void
InterestManager::EntityNewInterestZoneHandler(
EntityNewInterestZoneMessage*
)
{
#if 0
//
// If (the master entity is on this host)
//
//
// Determine if the entity is interesting given its new
// interest zone
//
//
// If (the entity was and still is interesting)
// then (do nothing)
//
//
// If (the entity was not interesting and still is not interesting)
// then (do nothing)
//
//
// If (the entity was interesting and now is not interesting)
//
//
// Send BecomeUninteresting message to the entity
//
//
// If (the entity was not interesting and now is interesting)
//
//
// Send BecomeInteresting message to the entity
//
//
// If (the master entity is not on this host)
//
//
// Determine if the entity is interesting given its new
// interest zone
//
//
// If (the entity was and still is interesting)
// then (do nothing)
//
//
// If (the entity was not interesting and still is not interesting)
// then (do nothing)
//
//
// If (the entity was interesting and now is not interesting)
//
//
// Unsubscribe the replicant entity from updates
//
//
// Send BecomeUninteresting message to the entity
//
//
// If (the entity was not interesting and now is interesting)
//
//
// If (the replicant does not exist)
//
//
// Create the replicant
//
//
// Send BecomeInteresting message to the entity
//
//
// Subscribe the replicant to updates
//
#else
Fail("InterestManager::EntityNewInterestZoneHandler - under construction");
#endif
}
//
//#############################################################################
// LoadResourceFinishedHandler
//#############################################################################
//
void
InterestManager::LoadResourceFinishedHandler(Receiver::Message*)
{
#if 0
//
// If (an interest origin request for interest zone finished)
//
//
// For (the static entities in the interest zone)
//
//
// If (the static entity does not exist)
//
//
// Make the static entity
//
//
// For (the map entities in the interest zone)
//
//
// If (the owner of the map entity is MapHostID)
//
//
// This entity has not been created by any other hosts,
// so create it with this host as owner
//
//
// Need to somehow put in a small random delay for map
// entity creation resolution between two hosts?
//
//
// Make the map entity
//
#if 0
{
Entity entity_ID; // From the interest zone
ClassID class_ID; // From the interest zone
HostID owner_ID; // From this host
application->registry->MakeEntity(entity_ID, class_ID);
}
#endif
#else
Fail("InterestManager::LoadResourceFinishedHandler - under construction");
#endif
}
//
//#############################################################################
// EntitySubscribeToUpdates
//#############################################################################
//
void
InterestManager::EntitySubscribeToUpdates(
EntityID,
HostID,
HostID
)
{
// HACK - Partial implementation
}
//
//#############################################################################
// EntitySubscribeToUpdatesHandler
//#############################################################################
//
void
InterestManager::EntitySubscribeToUpdatesHandler(
EntitySubscribeToUpdatesMessage*
)
{
// HACK - Partial implementation
}
//
//#############################################################################
// EntityUpdateReplicants
//#############################################################################
//
void
InterestManager::EntityUpdateReplicants(
Entity *entity,
Entity::UpdateMessage *update_message
)
{
Check(this);
Check(entity);
Check(update_message);
//
//--------------------------------------------------------------------------
// Verify entityID, instance, and flags
//--------------------------------------------------------------------------
//
Verify(entity->GetEntityID() != EntityID::Null);
Verify(entity->GetInstance() == Entity::MasterInstance);
Verify(entity->IsDynamic());
// Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If (no replicants are subscribed to this entity)
//--------------------------------------------------------------------------
//
//
// return
//
#endif
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// Send it to the subscribed replicants
//
// LAN Solution:
// If (subscriber list is not empty)
// Broadcast the update
//
// WAN Solution:
// If (subscriber list is not empty)
// Send the update via point-to-point messages
//
// A way is needed to get from the entity the information
// required for another host to create the replicant
//--------------------------------------------------------------------------
//
#else
//
// Setup and verify network fields in message
//
entity->SetupNetworkMessage(update_message);
#if DEBUG_LEVEL>0
Check(&update_message->entityID);
Verify(update_message->entityID != EntityID::Null);
Verify(update_message->interestZoneID != NullInterestZoneID);
Check(application);
Check(application->GetHostManager());
Verify(
update_message->ownerID ==
application->GetHostManager()->GetLocalHostID()
);
#endif
//
// HACK - Spoof the update message into EntityUpdateReplicantsMessageID
//
Verify(update_message->messageID == Entity::UpdateMessageID);
update_message->messageID = EntityUpdateReplicantsMessageID;
//
// Broadcast update message
//
Check(application);
application->ExclusiveBroadcastMessage(
InterestManagerClientID,
update_message
);
#endif
}
//
//#############################################################################
// EntityUpdateReplicantsHandler
//#############################################################################
//
void
InterestManager::EntityUpdateReplicantsHandler(
EntityUpdateReplicantsMessage *update_message
)
{
Check(this);
Check(update_message);
//
// Verify update message
//
Check(&update_message->entityID);
Verify(update_message->entityID != EntityID::Null);
Verify(update_message->interestZoneID != NullInterestZoneID);
Verify(update_message->ownerID >= FirstLegalHostID);
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If (interest zone id is outside of our interest arenas)
//--------------------------------------------------------------------------
//
//
// return
//
#endif
//
//--------------------------------------------------------------------------
// Verify the local host id
//--------------------------------------------------------------------------
//
#if DEBUG_LEVEL>0
HostID local_host_ID;
Check(application);
Check(application->GetHostManager());
local_host_ID = application->GetHostManager()->GetLocalHostID();
Verify(update_message->ownerID != local_host_ID);
#endif
//
//--------------------------------------------------------------------------
// Find the replicant to update
//--------------------------------------------------------------------------
//
Entity *replicant;
Check(application);
Check(application->GetHostManager());
replicant = application->GetHostManager()->GetEntityPointer(
update_message->entityID
);
//
//--------------------------------------------------------------------------
// If (the replicant exists)
//--------------------------------------------------------------------------
//
// BT bring-up trace (env BT_NET_TRACE): update-lookup outcome (a failed
// lookup is a SILENT drop in the original).
if (getenv("BT_NET_TRACE"))
{
static int s_updTrace = 0;
if (s_updTrace++ < 8 || !replicant)
{
DEBUG_STREAM << "[net-upd] entity " << update_message->entityID
<< (replicant ? " FOUND" : " NOT FOUND") << "\n" << std::flush;
}
}
if (replicant)
{
//
// Update the replicant
//
Check(replicant);
Verify(replicant->GetInstance() == Entity::ReplicantInstance);
Verify(replicant->IsDynamic());
//
// HACK - Message was spoofed as EntityUpdateReplicantsMessageID, now
// turn back to update entity message ID
//
Verify(update_message->messageID == EntityUpdateReplicantsMessageID);
update_message->messageID = Entity::UpdateMessageID;
Check(application);
// ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, update_message);
PostUpdateEvent(replicant, update_message);
}
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If (the replicant does not exist)
//--------------------------------------------------------------------------
//
//
// Create the replicant
//
//
// Send BecomeInteresting message to the entity
//
//
// Subscribe the replicant to updates
//
#endif
}
//
//#############################################################################
// EntityBroadcastToReplicants
//#############################################################################
//
void
InterestManager::EntityBroadcastToReplicants(
Entity *entity,
Entity::Message *broadcast_message
)
{
Check(this);
Check(entity);
Check(broadcast_message);
//
//--------------------------------------------------------------------------
// Verify entityID, instance, and flags
//--------------------------------------------------------------------------
//
Verify(entity->GetEntityID() != EntityID::Null);
Verify(entity->GetInstance() == Entity::MasterInstance);
// Verify(entity->IsDynamic()); // HACK - Partial Implementation
// Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If (no replicants are subscribed to this entity)
//--------------------------------------------------------------------------
//
//
// return
//
#endif
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// Send it to the subscribed replicants
//
// LAN Solution:
// If (subscriber list is not empty)
// Broadcast the update
//
// WAN Solution:
// If (subscriber list is not empty)
// Send the update via point-to-point messages
//
// A way is needed to get from the entity the information
// required for another host to create the replicant
//
//--------------------------------------------------------------------------
//
#else
//
//--------------------------------------------------------------------------
// Setup and verify network fields in message
//--------------------------------------------------------------------------
//
entity->SetupNetworkMessage(broadcast_message);
#if DEBUG_LEVEL>0
Check(&broadcast_message->entityID);
Verify(broadcast_message->entityID != EntityID::Null);
Verify(broadcast_message->interestZoneID != NullInterestZoneID);
Check(application);
Check(application->GetHostManager());
Verify(
broadcast_message->ownerID ==
application->GetHostManager()->GetLocalHostID()
);
#endif
//
//--------------------------------------------------------------------------
// Build the interest manager message
//--------------------------------------------------------------------------
//
MemoryStream
memory_stream(messageBuildBuffer, INTERESTMANAGER_MESSAGE_BUFFER_SIZE);
EntityBroadcastToReplicantsMessage
*interest_manager_message;
size_t
total_length;
total_length =
sizeof (EntityBroadcastToReplicantsMessage) +
broadcast_message->messageLength;
Verify(total_length < memory_stream.GetBytesRemaining());
Check_Pointer(memory_stream.GetPointer());
interest_manager_message =
new (memory_stream.GetPointer()) EntityBroadcastToReplicantsMessage(
total_length
);
Check(interest_manager_message);
memory_stream.AdvancePointer(sizeof(EntityBroadcastToReplicantsMessage));
Mem_Copy(
memory_stream.GetPointer(),
broadcast_message,
broadcast_message->messageLength,
memory_stream.GetBytesRemaining()
);
//
//--------------------------------------------------------------------------
// Broadcast update message
//--------------------------------------------------------------------------
//
#if 0
Tell(
"InterestManager::EntityBroadcastToReplicants - Send entity message ID " <<
broadcast_message->messageID << "\n"
);
#endif
Check(application);
application->ExclusiveBroadcastMessage(
InterestManagerClientID,
interest_manager_message
);
#endif
}
//
//#############################################################################
// EntityBroadcastToReplicantsHandler
//#############################################################################
//
void
InterestManager::EntityBroadcastToReplicantsHandler(
EntityBroadcastToReplicantsMessage *interest_manager_message
)
{
Check(this);
Check(interest_manager_message);
#if 0 // HACK - Partial Implementation
//
//--------------------------------------------------------------------------
// If (interest zone id is outside of our interest arenas)
//--------------------------------------------------------------------------
//
//
// return
//
#endif
//
//--------------------------------------------------------------------------
// Parse broadcast message
//--------------------------------------------------------------------------
//
MemoryStream
memory_stream(
interest_manager_message,
interest_manager_message->messageLength
);
Entity::Message *broadcast_message;
memory_stream.AdvancePointer(sizeof(EntityBroadcastToReplicantsMessage));
broadcast_message = Cast_Object(Entity::Message*, memory_stream.GetPointer());
Check(broadcast_message);
Check(&broadcast_message->entityID);
Verify(broadcast_message->entityID != EntityID::Null);
Verify(broadcast_message->interestZoneID != NullInterestZoneID);
Verify(broadcast_message->ownerID >= FirstLegalHostID);
#if 0
Tell(
"InterestManager::EntityBroadcastToReplicantsHandler - Receive entity message ID " <<
broadcast_message->messageID << "\n"
);
#endif
//
//--------------------------------------------------------------------------
// Verify the local host id
//--------------------------------------------------------------------------
//
#if DEBUG_LEVEL>0
HostID local_host_ID;
Check(application);
Check(application->GetHostManager());
local_host_ID = application->GetHostManager()->GetLocalHostID();
Verify(broadcast_message->ownerID != local_host_ID);
#endif
//
//--------------------------------------------------------------------------
// Find the replicant to update
//--------------------------------------------------------------------------
//
Entity *replicant;
Check(application);
Check(application->GetHostManager());
replicant = application->GetHostManager()->GetEntityPointer(
broadcast_message->entityID
);
#if 0
Tell(
"InterestManager::EntityBroadcastToReplicantsHandler - Replicant=" <<
(long)replicant << "\n"
);
#endif
//
//--------------------------------------------------------------------------
// If the replicant exists, update it
//--------------------------------------------------------------------------
//
if (replicant)
{
Check(replicant);
Verify(replicant->GetInstance() == Entity::ReplicantInstance);
Check(application);
// ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, broadcast_message);
PostUpdateEvent(replicant, broadcast_message);
}
#if 0 // HACK - Partial implementation
//
//--------------------------------------------------------------------------
// If (the replicant does not exist)
//--------------------------------------------------------------------------
//
else
{
//
// Create the replicant
//
//
// Send BecomeInteresting message to the entity
//
//
// Subscribe the replicant to updates
//
#if 0
Tell("Unknown replicant " << broadcast_message->entityID << endl);
#endif
}
#endif
}
//
//#############################################################################
// HostInterestArenaChangedHandler
//#############################################################################
//
void
InterestManager::HostInterestArenaChangedHandler(
HostInterestArenaChangedMessage*
)
{
#if 0
//
// Get all hosted dynamic entities
//
//
// For (each entity within the given interest arena)
//
{
//
// HACK - need someway of doing the following point-to-point,
// potentially to ourselves
//
Entity::UpdateMessage
*update_message = NULL;
Check(update_message);
Check(application);
application->interestManager.EntityUpdateReplicants(
entity,
update_message
);
}
#else
Fail("InterestManager::HostInterestArenaChangedHandler - under construction");
#endif
}
//
//#############################################################################
// InterestZoneDeltaHandler
//#############################################################################
//
void
InterestManager::InterestZoneDeltaHandler(
InterestZoneDeltaMessage*
)
{
#if 0
//
// If (a delta already exists for this interest zone)
//
//
// Get the timestamp of the existing delta
//
//
// If (the timestamp of the incoming delta is > then current delta)
//
//
// Store the incoming delta
//
//
// If (a delta does not exist for this interest zone)
//
//
// Store the incoming data
//
#else
Fail("InterestManager::InterestZoneDeltaHandler - under construction");
#endif
}
//
//#############################################################################
//#############################################################################
//
void
InterestManager::AddInterestingEntityToInterestOrigins(Entity *new_entity)
{
Check(this);
Check(new_entity);
Check(&interestOriginSocket);
InterestOrigin
*interest_origin;
SChainIteratorOf<InterestOrigin*>
iterator(&interestOriginSocket);
Check(&iterator);
while((interest_origin = iterator.ReadAndNext()) != NULL)
{
Check(interest_origin);
interest_origin->AddInterestingEntity(new_entity);
}
}
//
//#############################################################################
//#############################################################################
//
void
InterestManager::RemoveUninterestingEntityFromInterestOrigins(Entity *entity)
{
Check(this);
Check(entity);
Check(&interestOriginSocket);
InterestOrigin
*interest_origin;
SChainIteratorOf<InterestOrigin*>
iterator(&interestOriginSocket);
Check(&iterator);
while((interest_origin = iterator.ReadAndNext()) != NULL)
{
Check(interest_origin);
interest_origin->RemoveUninterestingEntity(entity);
}
}
//
//#############################################################################
//#############################################################################
//
void
InterestManager::AddInterestingEntitiesToInterestOrigin(
InterestOrigin *interest_origin
)
{
Check(this);
Check(interest_origin);
//
// Get an iterator for all the entities on this host
//
Check(application);
Check(application->GetHostManager());
HostManager::AllEntityIterator
iterator(application->GetHostManager());
Entity
*entity;
Check(&iterator);
while((entity = iterator.ReadAndNext()) != NULL)
{
Check(entity);
interest_origin->AddInterestingEntity(entity);
}
}
//
//#############################################################################
// PostCreationEvent
//#############################################################################
//
void
InterestManager::PostCreationEvent(Receiver::Message *make_entity_message)
{
Check(this);
Check(make_entity_message);
Check(application);
#if 0 // ECH 1/28/96
EventPriorities priority =
(application->GetApplicationState() != Application::RunningMission) ?
LowEventPriority :
DefaultEventPriority;
#else
EventPriorities priority =
(application->GetApplicationState() != Application::RunningMission) ?
LowEventPriority :
CreationEventPriority;
#endif
Check(application);
Registry *registry = application->GetRegistry();
Check(registry);
application->Post(priority, registry, make_entity_message);
}
//
//#############################################################################
// PostRendererEvent
//#############################################################################
//
void
InterestManager::PostRendererEvent(
Entity *entity,
Renderer *renderer,
Receiver::Message *message
)
{
Check(this);
Check(entity);
Check(renderer);
#if 0 // ECH 1/26/96
EventPriorities priority =
(applicationState.GetState() != Application::RunningMission) ?
MinEventPriority :
DefaultEventPriority;
#endif
EventPriorities priority;
switch (entity->GetInterestPriority(renderer->GetLinkedEntity()))
{
case LowInterestPriority:
priority =
(application->GetApplicationState() != Application::RunningMission) ?
MinEventPriority :
LowInterestEventPriority;
break;
case HighInterestPriority:
priority =
(application->GetApplicationState() != Application::RunningMission) ?
MinEventPriority :
HighInterestEventPriority;
break;
default:
Fail("Application::PostInterestEvent - Should never reach here");
break;
}
application->Post(priority, renderer, message);
}
//
//#############################################################################
// PostUpdateEvent
//#############################################################################
//
void
InterestManager::PostUpdateEvent(
Entity *entity,
Receiver::Message *message
)
{
Check(this);
Check(entity);
Check(message);
//
// Note that the priority of the update can be greater than the
// creation priority since the replicants are created via dispatch
// in the interest manager.
//
EventPriorities priority =
(application->GetApplicationState() != Application::RunningMission) ?
DefaultEventPriority :
UpdateEventPriority;
Check(application);
application->Post(priority, entity, message);
}
//
//#############################################################################
// PostDestructionEvent
//#############################################################################
//
void
InterestManager::PostDestructionEvent(
Entity *entity,
Receiver::Message *message
)
{
Check(this);
Check(entity);
Check(message);
EventPriorities priority = DestructionEventPriority;
#if 0
switch (entity->GetInterestPriority(renderer->GetLinkedEntity()))
{
case LowInterestPriority:
priority = LowEventPriority;
break;
case HighInterestPriority:
priority = DefaultEventPriority;
break;
default:
Fail("Application::PostInterestEvent - Should never reach here");
break;
}
#endif
Check(application);
application->Post(priority, entity, message);
}
//
//#############################################################################
//#############################################################################
//
void
InterestManager::RemoveUninterestingEntitiesFromInterestOrigin(
InterestOrigin *interest_origin
)
{
Check(this);
Check(interest_origin);
interest_origin->RemoveUninterestingEntities();
}
//~~~~~~~~~~~~~~~~~ InterestManager__EntitySubscribeToUpdatesMessage ~~~~~~~~~~
InterestManager__EntitySubscribeToUpdatesMessage::
InterestManager__EntitySubscribeToUpdatesMessage():
NetworkClient::Message(
InterestManager::EntitySubscribeToUpdatesMessageID,
sizeof(InterestManager__EntitySubscribeToUpdatesMessage)
)
{
}
//~~~~~~~~~~~~~~ InterestManager__EntityBroadcastToReplicantsMessage ~~~~~~~~~~
InterestManager__EntityBroadcastToReplicantsMessage::
InterestManager__EntityBroadcastToReplicantsMessage(size_t message_length):
NetworkClient::Message(
InterestManager::EntityBroadcastToReplicantsMessageID,
message_length
)
{
}
//~~~~~~~~~~~~~~~~~ InterestManager__EntityNewInterestZoneMessage ~~~~~~~~~~~~~
InterestManager__EntityNewInterestZoneMessage::
InterestManager__EntityNewInterestZoneMessage(
const EntityID &entity_ID,
InterestZoneID interest_zone_ID
):
NetworkClient::Message(
InterestManager::EntityNewInterestZoneMessageID,
sizeof(InterestManager__EntityNewInterestZoneMessage)
)
{
entityID = entity_ID;
interestZoneID = interest_zone_ID;
}
//~~~~~~~~~~~~~~~~~ InterestManager__HostInterestArenaChangedMessage ~~~~~~~~~~
InterestManager__HostInterestArenaChangedMessage::
InterestManager__HostInterestArenaChangedMessage():
NetworkClient::Message(
InterestManager::HostInterestArenaChangedMessageID,
sizeof(InterestManager__HostInterestArenaChangedMessage)
)
{
}
//~~~~~~~~~~~~~~~~~ InterestManager__InterestZoneDeltaMessage ~~~~~~~~~~~~~~~~~
InterestManager__InterestZoneDeltaMessage::
InterestManager__InterestZoneDeltaMessage():
NetworkClient::Message(
InterestManager::InterestZoneDeltaMessageID,
sizeof(InterestManager__InterestZoneDeltaMessage)
)
{
}