//===========================================================================//
// File:	interest.cc                                                         //
// Project: MUNGA           Brick: Interest Manager								  //
// Contents: Interface specification Interest Manager								  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 10/28/94  ECH  Initial coding.                                            //
// 11/03/94  ECH  Develop to munga spec												  //
// 11/29/94  JMA  Changed Identities to IDs                                  //
// 02/10/95  CPB  Added GaugeInterestType                                    //
//---------------------------------------------------------------------------//
// 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(INTEREST_HPP)
#	include <interest.hpp>
#endif

#if !defined(REGISTRY_HPP)
#	include <registry.hpp>
#endif

#if !defined(MISSION_HPP)
#	include <mission.hpp>
#endif

#if !defined(BOXTREE_HPP)
#	include <boxtree.hpp>
#endif

#if !defined(RENDERER_HPP)
#	include <renderer.hpp>
#endif

#if !defined(CULTURAL_HPP)
#	include <cultural.hpp>
#endif

#if !defined(APP_HPP)
	#include <app.hpp>
#endif

#if !defined(HOSTMGR_HPP)
	#include <hostmgr.hpp>
#endif

//#############################################################################
//#######################    InterestManager    ###############################
//#############################################################################

//
//--------------------------------------------------------------------
// InterestManager data
//--------------------------------------------------------------------
//
unsigned char
	InterestManager::messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE];

InterestManager::SharedData
	InterestManager::DefaultData(
		InterestManager::ClassDerivations,
		InterestManager::MessageHandlers
	);

Derivation
	InterestManager::ClassDerivations(
   	NetworkClient::ClassDerivations,
      "InterestManager"
   );

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::MessageHandlers(
		ELEMENTS(InterestManager::MessageHandlerEntries),
		InterestManager::MessageHandlerEntries,
      NetworkClient::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(ClassDerivations))
	{
		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)
	//--------------------------------------------------------------------------
	//
	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)
		)
{
}

