//===========================================================================//
// File:	EntityUpdateManager.cpp											
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 07/26/1999  JSE  Inital coding
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Microsoft Corp.										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "MW4Headers.hpp"

#include "MWEntityManager.hpp"
#include "MWApplication.hpp"

#include "ObservationVehicle.hpp"
#include "Mech.hpp"
#include "Torso.hpp"
#include "VehicleInterface.hpp"
#include "MWPlayer.hpp"
#include "Weapon.hpp"
#include "MissileWeapon.hpp"
// MSL 5.03 RTX
//#include "rtxweaponsub.hpp"
#include "GameInfo.hpp"
#include "SubsystemClassData.hpp"
#include "NetAutoPacketSpliter.hpp"
#include "MissionReview.hpp"
#include "Flag.hpp"

#include <Adept\Map.hpp>
#include <Adept\Player.hpp>
#include <Adept\CollisionGrid.hpp>
#include <Adept\CollisionVolume.hpp>
#include <Adept\Mission.hpp>
#include <Adept\NetStatCollector.hpp>
#include "MechLabHeaders.h"

#include "mwmission.hpp"
#include <Adept\Site.hpp>

#pragma warning(push)
#include <stlport\string>
#pragma warning(pop)


// ngLog addition	// JKK
#if !defined(NO_LOG)
#include "nglog_mw4.hpp"
#endif // !defined(NO_LOG)
#include "BeamWeapon.hpp"
#include <Adept\DamageObject.hpp>


// jcem - start
#include "windows.h"
#include "ctcls.h"
#include "ctcl.h"
#include "recscore.h"

// jcem - mission replay
#define DIRECTINPUT_VERSION 0x700
#include <dinput.h>
#include <dsetup.h>
#include <dsound.h>
#include <d3d.h>
#include <dplay.h>
#include <dplobby.h>

#pragma warning( disable: 4201 )	// nameless struct/union (again - something reenables this!)
#include <amstream.h>
#include <control.h>
#include <process.h>
#include <mmreg.h>
#include <msacm.h>
#ifndef __IDDrawExclModeVideo_FWD_DEFINED__
#error DirectX Media 6.0 SDK is required
#endif

#include "gameos\Net_header.hpp"
#include "gameos\mreplay.h"
#include "mreplay2.h"
extern bool g_bCOOP;
// jcem - mission replay
// jcem - end

BYTE *MWEntityManager::Packet_Buffer = NULL;



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//###########################    MWEntityManager    #############################
//#############################################################################

MWEntityManager::ClassData*
	MWEntityManager::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

__int64 tServerRewind;
__int64 tServerEncode;
__int64 tClientDecode;
__int64 tClientEncode;


extern DWORD g_clientControlPackets;
extern DWORD g_clientPacketsWaitingConfirmation;
extern DWORD g_clientSkippedPackets;
extern DWORD g_clientForgotenPackets;
extern DWORD g_clientTimedOutPackets;
extern DWORD g_clientLatePackets;
extern DWORD g_clientFullConfirms;
extern DWORD g_clientSmallConfirms;

extern DWORD g_serverControlsApplied;
extern DWORD g_serverFullRetransmits;
extern DWORD g_serverSmallRetransmits;
extern DWORD g_serverPacketsOutOfRange;
extern DWORD g_serverFullConfirms;
extern DWORD g_serverSmallConfirms;
extern DWORD g_serverTimeOuts;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWEntityManager::InitializeClass()
{
	g_clientControlPackets = 0;
	g_clientPacketsWaitingConfirmation = 0;
	g_clientSkippedPackets = 0;
	g_clientForgotenPackets = 0;
	g_clientTimedOutPackets = 0;
	g_clientLatePackets = 0;
	g_clientFullConfirms = 0;
	g_clientSmallConfirms = 0;

	g_serverControlsApplied = 0;
	g_serverFullConfirms = 0;
	g_serverSmallConfirms = 0;
	g_serverFullRetransmits = 0;
	g_serverSmallRetransmits = 0;
	g_serverPacketsOutOfRange = 0;
	g_serverTimeOuts = 0;

#if !(defined(NO_TIMERS) && defined(NO_STATS))
	StatisticFormat("");
	StatisticFormat("MW4 Networking Entity Manager");
	StatisticFormat("=============");
#endif


#if !defined(NO_TIMERS)
	AddStatistic( "Server Rewind",			"%",		gos_timedata, &tServerRewind, 0);
	AddStatistic( "Server Encode",			"%",		gos_timedata, &tServerEncode, 0);
	AddStatistic( "Client Encode",			"%",		gos_timedata, &tClientEncode, 0);
	AddStatistic( "Client Decode",			"%",		gos_timedata, &tClientDecode, 0);
#endif


#if !defined(NO_STATS)
	AddStatistic( "C: ControlPacket","m",	gos_DWORD, &g_clientControlPackets, 0);
	AddStatistic( "C: Qued",		"m",	gos_DWORD, &g_clientPacketsWaitingConfirmation, 0);
	AddStatistic( "C: Skipped",	"m",		gos_DWORD, &g_clientSkippedPackets, 0);
	AddStatistic( "C: Forgotten",	"m",	gos_DWORD, &g_clientForgotenPackets, 0);
	AddStatistic( "C: TimedOut",	"m",	gos_DWORD, &g_clientTimedOutPackets, 0);
	AddStatistic( "C: Late",		"m",	gos_DWORD, &g_clientLatePackets, 0);
	AddStatistic( "C: FConfirm",	"m",	gos_DWORD, &g_clientFullConfirms, 0);
	AddStatistic( "C: SConfirm",	"m",	gos_DWORD, &g_clientSmallConfirms, 0);

	AddStatistic( "S: ControlsApplied","m", gos_DWORD, &g_serverControlsApplied, 0);
	AddStatistic( "S: OutOfRange",	"m",	gos_DWORD, &g_serverPacketsOutOfRange, 0);
	AddStatistic( "S: FConfirm",	"m",	gos_DWORD, &g_serverFullConfirms, 0);
	AddStatistic( "S: SConfirm",	"m",	gos_DWORD, &g_serverSmallConfirms, 0);
	AddStatistic( "S: FRetransmits", "m",	gos_DWORD, &g_serverFullRetransmits, 0);
	AddStatistic( "S: SRetransmits", "m",	gos_DWORD, &g_serverSmallRetransmits, 0);
	AddStatistic( "S: TimeOuts", "m",	gos_DWORD,	   &g_serverTimeOuts, 0);
#endif

	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MWEntityManagerClassID,
			"MechWarrior4::MWEntityManager",
			Adept::EntityManager::DefaultData
		);
	Check_Object(DefaultData);


	

	WeaponUpdate::InitializeClass();


	Packet_Buffer = new BYTE[DefaultPacketBufferSize];

	Network::HashMessageTypeFlags[FirstPersonControlMessageID] = Network::GameSpecificHash;
	//Network::HashMessageTypeFlags[FirstPersonObserverControlMessageID] = Network::GameSpecificHash;
	Network::HashMessageTypeFlags[FirstPersonSmallConfirmationMessageID] = Network::GameSpecificHash;
	Network::HashMessageTypeFlags[FirstPersonFullConfirmationMessageID] = Network::GameSpecificHash;

	Network::HashMessageTypeFlags[FirstPersonWeaponToMechCommandMessageID] = Network::GameSpecificHash;
	Network::HashMessageTypeFlags[FirstPersonWeaponToGroundCommandMessageID] = Network::GameSpecificHash;
	Network::HashMessageTypeFlags[FirstPersonWeaponToServerObjectCommandMessageID] = Network::GameSpecificHash;
	Network::HashMessageTypeFlags[FirstPersonWeaponNoTargetCommandMessageID] = Network::GameSpecificHash;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWEntityManager::TerminateClass()
{
	Check_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;

	

	delete[] Packet_Buffer;

	WeaponUpdate::TerminateClass();

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool MWEntityManager::IsNumberAhead(int value, int position, int number_ahead, int wrap_around_number)
{
	Verify(number_ahead < wrap_around_number);

	int result = value - position;
	if (result >= 0 && result <= number_ahead)
		return true;

	result = value + wrap_around_number - position;
	if (result >= 0 && result <= number_ahead)
		return true;

	return false;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool MWEntityManager::IsNumberBehind(int value, int position, int number_behind, int wrap_around_number)
{
	Verify(number_behind < wrap_around_number);

	int result = position - value; 
	if (result > 0 && result <= number_behind)
		return true;

	result = position + wrap_around_number - value;
	if (result > 0 && result <= number_behind)
		return true;

	return false;
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool MWEntityManager::IsNumberWithin(int value, int positoin, int number_within, int wrap_around_number)
{
	if (IsNumberAhead(value, positoin, number_within, wrap_around_number)||IsNumberBehind(value, positoin, number_within, wrap_around_number))
	{
		return true;
	}
	return  false;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void MWEntityManager::SetPlayerReady(Entity *entity)
{
	EntityManager::SetPlayerReady(entity);
	Check_Object(entity);
	Vehicle *vehicle = Cast_Object(Vehicle *, entity);
	vehicle->TurnOn();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


void
	MWEntityManager::StartUpdates()
{
	tServerRewind = 0;
	tServerEncode = 0;
	tClientDecode = 0;
	tClientEncode = 0;

	//SPEW(("jerryeds","SIM EXECUTE"));
	// clear out any frame by frame stuff here.

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::EndUpdates()
{
    if (m_uPostDeathFlags) {
        if (m_uPostDeathFlags & 1) {
            VehicleInterface* pVI = VehicleInterface::GetInstance();
            if (pVI) {
                pVI->ReactToEvent(VehicleInterface::CRITICAL_HIT_GIMP);
            }
        }
        m_uPostDeathFlags = 0;
    }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::StartClient()
{
	Verify(clientController == NULL);
	clientController = new ClientController;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


void
	MWEntityManager::StopClient()
{
	if (clientController != NULL)
	{
		delete clientController;
		clientController = NULL;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::StartServer()
{
	Verify(serverController == NULL);
	serverController = new ServerController;
    if (g_nMR == 2) {
        StartClient();
    }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


void
	MWEntityManager::StopServer()
{
    if (g_nMR == 2) {
        StopClient();
    }
	if (serverController != NULL)
	{
		delete serverController;
		serverController = NULL;
	}
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::Reset()
{
	
	maximumNearBuildings = 124;
	maximumMidBuildings = 256;
	maximumFarBuildings = 256;


	if (clientController != NULL)
	{
		clientController->Reset();
	}
	if (serverController != NULL)
	{
		serverController->Reset();
	}


	lastExecuted = 0.0f;

	for (int i = 0; i < Maximum_Players; ++i)
	{
		playerVehicle[i] = NULL;

		if (dictionaryManager[i] != NULL)
		{
			delete dictionaryManager[i];
			dictionaryManager[i] = NULL;
		}
	}

	Stuff::ChainIteratorOf<WeaponUpdate*> iterator(&weaponUpdates);
	WeaponUpdate *update;
	
	while ((update = iterator.GetCurrent()) != NULL)
	{
		iterator.Remove();
		delete update;
	}

	Stuff::ChainIteratorOf<WeaponUpdate*> iterator1(&networkWeaponsQue);

	while ((update = iterator1.GetCurrent()) != NULL)
	{
		iterator1.Remove();
		delete update;
	}




	ChainIteratorOf<VehicleCommand*> command_iterator(&quedCommands);
	VehicleCommand *command;
	while ((command = command_iterator.GetCurrent()) != NULL)
	{
		command_iterator.Remove();
		delete command;
	}

	commandCount = 0;
    m_uPostDeathFlags = 0;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::PreCollisionNetworkEvents()
{
	Stuff::ChainIteratorOf<WeaponUpdate*> iterator1(&networkWeaponsQue);
	WeaponUpdate *update;
	
	while ((update = iterator1.GetCurrent()) != NULL)
	{
		CreateWeaponEffect(*update);
		iterator1.Remove();
		delete update;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

MWEntityManager::MWEntityManager():
	EntityManager(DefaultData),
	servedMechs(NULL, false),
    servedRespawnLances(NULL), // jcem - for delayed lancemate respawn
	servedAirplanes(NULL),
	servedBoats(NULL),
	servedDropships(NULL),
	servedHelicopters(NULL),
	servedHovercraft(NULL),
	servedTanks(NULL),
	servedTrucks(NULL),
	servedTurrets(NULL),
	weaponUpdates(NULL),
	networkWeaponsQue(NULL),
	quedCommands(NULL)
{
	Check_Pointer(this);
	dictionaryDirtyFlag = false;

	lastExecuted = 0.0f;
	lastScore = 0.0;
	lastWeapon = 0.0;
	lastActiveReset = 0.0f;

	maximumNearBuildings = 124;
	maximumMidBuildings = 256;
	maximumFarBuildings = 256;


	
	for (int i = 0; i < Maximum_Players; ++i)
	{
		playerVehicle[i] = NULL;
		dictionaryManager[i] = NULL;
	}

	serverController = NULL;
	clientController = NULL;

	commandCount = 0;
    m_uPostDeathFlags = 0;

	//open the bitdepth file
	bitManager = new BitDepthManager;
	bitManager->InitilizeBitDepths();


}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWEntityManager::~MWEntityManager()
{
	Check_Pointer(this);

	bitManager->TerminateBitDepths();
	delete bitManager;

	Verify(serverController == NULL);
	Verify(clientController == NULL);

	for (int i = 0; i < Maximum_Players; ++i)
	{
		if (dictionaryManager[i] != NULL)
		{
			delete dictionaryManager[i];
			dictionaryManager[i] = NULL;
		}
	}

	Stuff::ChainIteratorOf<WeaponUpdate*> iterator(&weaponUpdates);
	WeaponUpdate *update;
	
	while ((update = iterator.GetCurrent()) != NULL)
	{
		iterator.Remove();
		delete update;
	}


	Stuff::ChainIteratorOf<WeaponUpdate*> iterator1(&networkWeaponsQue);
	while ((update = iterator1.GetCurrent()) != NULL)
	{
		iterator1.Remove();
		delete update;
	}


	ChainIteratorOf<VehicleCommand*> command_iterator(&quedCommands);
	VehicleCommand *command;
	while ((command = command_iterator.GetCurrent()) != NULL)
	{
		command_iterator.Remove();
		delete command;
	}

	commandCount = 0;
	m_uPostDeathFlags = 0;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


void MWEntityManager::ServeLocalEntities(Time till)
{

	Scalar time_slice = GetTimeSlice(till);

	if (!Application::GetInstance()->networkingFlag)
	{
		lastExecuted = till;
		return;
	}


	if (Mission::GetInstance() && ((till - lastScore) > 5.0))
	{
		lastScore = till;
		Mission::GetInstance()->scoreDirty = true;
	}

	MWApplication *app = MWApplication::GetInstance();

	if (!app->serverFlag)
	{
		// client control updates

		
	




		__int64 temp=GetCycles();
	
		{
			#ifdef GROUP_ADEPT_NETWORK
			LOG_BLOCK("Game Logic::Network::Send Weapon Packets To Server");
			#endif
			clientController->SendWeaponCommands();
		}

		{
			#ifdef GROUP_ADEPT_NETWORK
			LOG_BLOCK("Game Logic::Network::Send Control Packets To Server");
			#endif
	

			clientController->SendControlPacketToServer(time_slice);
		}


		tClientEncode+=GetCycles() - temp;
		lastExecuted = till;
		return;
	}
	else
	{
		//we are server 

		#ifdef GROUP_ADEPT_NETWORK
			LOG_BLOCK("Game Logic::Network::Encode Dictionary");
		#endif

		

		if ((till - lastWeapon) > 0.25)
		{
			lastWeapon = till;
			while(serverController->SendWeaponCommands())
			{
			}
		}
		

		if ((dictionaryDirtyFlag == true) || ((g_nMR == 1) && !dictionaryManager[1]))
		{
			// make and send a new dictionary

			UpdateDictionaries();
			app->SendScore();
			Mission::GetInstance()->scoreDirty = false;

		}
		else if (Mission::GetInstance()->scoreDirty)
		{
			app->SendScore();
			Mission::GetInstance()->scoreDirty = false;
		}

		// run through the updates...
		// right now we just count em down...

        if ((g_nMR == 1) && dictionaryManager[1]) {
            Dictionary *dictionary = dictionaryManager[1]->GetCurrentDictionary();
            if (dictionary) {
                int nWritten = 0;

		        DynamicMemoryStream movement_packet(MWEntityManager::Packet_Buffer, DefaultPacketBufferSize);

		        movement_packet.WriteBits(&dictionary->versionNumber,8);

	            Stuff::SortedChainIteratorOf<Mech*, Adept::ReplicatorID> iterator(&servedMechs);
	            Mech* mech;
	            while ((mech = iterator.ReadAndNext()) != NULL)
	            {
		            Check_Object(mech);

                    ReplicatorID id = mech->GetReplicatorID();
                    movement_packet.WriteBits(&id.connectionID, 8);
                    movement_packet.WriteBits(&id.localID, 16);

		            MechPositionUpdate::Encode(mech, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
		            ExternalJumpJetUpdate::Encode(mech, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
                    MechInternalDamageUpdate::Encode(mech, &movement_packet, id.connectionID, dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);
		            movement_packet.WriteByteAlign();

                    nWritten++;
                }

                if (nWritten > 0) {
		            movement_packet.Rewind();
                }
                g_MRF.SendMessage(nWritten, &movement_packet, MRP_FULLCONFIRM);
            }
        }
		__int64 temp=GetCycles();

      if (g_nMR != 2) {
		for (int i = 0; i < Maximum_Players; ++i)
		{
			if (app->servedConnectionData[i].clientLoaded && dictionaryManager[i])
			{	

                if (i == Connection::Server->GetID()) {
                    if ((g_nMR != 1) || (g_MRF.m_nCount < 0))
				        continue;
                }

				Check_Object(dictionaryManager[i]);
				dictionaryManager[i]->Encode(till);
			}
		}
      }


		if (((till - lastActiveReset) > 2.0))
		{
			lastActiveReset = till;

			ResetActivityFlags();
		}

		tServerEncode+=GetCycles()-temp;

		
	}

	

	lastExecuted = till;

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void
	MWEntityManager::ResetActivityFlags()
{

	Stuff::SortedChainIteratorOf<Mech*, Adept::ReplicatorID> iterator(&servedMechs);
	Mech *mech;
	Scalar current_time = (Scalar)gos_GetElapsedTime();

	while ((mech = iterator.ReadAndNext()) != NULL)
	{
		if (mech->takenDamageThisFrame)
		{
			if (current_time - mech->lastDamageTaken > 2.0f)
	{
		mech->takenDamageThisFrame = false;
				mech->lastDamageTaken = 0.0f;
			}
	}
	}
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void
	MWEntityManager::UpdateEntities()
{

	// NO MORE CLIENT UPDATES

	return;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

int Exit_Count = 0;

void MWEntityManager::UpdateClientEntites(int connection, int message_type, Stuff::MemoryStream *message)
{
	
	MWApplication *app = MWApplication::GetInstance();

	switch (app->GetApplicationState())
	{
		case ApplicationStateEngine::RunningGameState:
			break;
		default:
			return;
	};


	// decode and update the entites...
	if (message_type == DictionaryIndexMessageID)
	{
#if defined(_DEBUG) && 0 // jcem - for MR test
  {
	char Buffer[128];
	sprintf(Buffer, "EntityMgr:: DictionaryIndexMessageID\n");
	OutputDebugString(Buffer);
  }
#endif // _DEBUG && ...
		//SPEW(("jerryeds", "%d : RECIEVE INDEX", Connection::Local->GetID()));


		Network::GetInstance()->netStatCollector[Network::IncomingSystemMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8);

		Verify(!Network::GetInstance()->AmIServer());

		// make the index
		__int64 temp=GetCycles();
		

		// we might as well use our own id!
		if (dictionaryManager[Connection::Local->GetID()] == NULL)
		{
			dictionaryManager[Connection::Local->GetID()] = new DictionaryManager(Connection::Local->GetID());
		}

		int version = 0;
		int debug_level = 0;
		int bandwidth = 0;
		
		message->ReadBits(&version, 8);
		message->ReadBits(&debug_level, 2);
		message->ReadBits(&bandwidth, 2);


		int player_count = 0; // jcem: critical error - should clear before ReadBits(...)...
		message->ReadBits(&player_count, 8);

		int vehicle_id[Maximum_Players];
		for (int j = 0; j < Maximum_Players; ++j)
		{
			vehicle_id[j] = -1;
		}


		for(j = 0; j < player_count; ++j)
		{
				
			BYTE player;
			int id;

			message->ReadBits(&player,8);
			message->ReadBits(&id, 32);
			
			vehicle_id[player] = id;

		}


		bool error = false;

		for ( j = 0; j < Maximum_Players; ++j)
		{
			if (vehicle_id[j] == -1)
			{
				if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer)
				{
					//STOP(("GAME STATE DOESNT MATCH ---- %d : LOADED BUT SHOULDNT BE", j));
					// FAIL
					
					#ifdef LAB_ONLY 
						PAUSE(("GAME STATE DOESNT MATCH ---- %d : LOADED BUT SHOULDNT BE", j));
					#endif

					error = true;
				}
				
			}
			else
			{

				if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer)
				{
					ResourceID id = app->servedConnectionData[j].clientPlayer->vehicle->GetGameModelResourceID();

					if (id.GetRecordID() != vehicle_id[j])
					{
						//STOP(("GAME STATE DOESNT MATCH ---- %d : Not in correct vehicle", j));
					
						#ifdef LAB_ONLY 
							PAUSE(("GAME STATE DOESNT MATCH ---- %d : Not in correct vehicle", j));
						#endif
						
						error = true;
					}
					
				}
				else
				{
					//STOP(("GAME STATE DOESNT MATCH ---- %d : Not loaded", j));
					#ifdef LAB_ONLY
						PAUSE(("GAME STATE DOESNT MATCH ---- %d : Not in correct vehicle", j));
					#endif
					error = true;
				}
			}
			
		}


		if (error)
		{
			++Exit_Count;
		}
		else
		{
			Exit_Count = 0;
		}

		if (Exit_Count)
		{
			if(Exit_Count < 10)
				MWApplication::GetInstance()->SendRequestNewDictionaryMessage();
			else
				MWApplication::GetInstance()->QueStopGame();

			return;
		}


		Dictionary *dictionary = dictionaryManager[Connection::Local->GetID()]->MakeNewDictionary(version, debug_level, bandwidth);
		
		MakeDictionaryPages(dictionary);

		#if defined(LAB_ONLY)
			MWGameInfo::g_networkDebugLevel[Connection::Local->GetID()] = dictionary->debugDictionaryLevel;
			MWGameInfo::g_connectRate[Connection::Local->GetID()] = dictionary->dictionaryBandwidth;
		#endif

		

		tClientDecode+=GetCycles()-temp;

		return;
	}

	// we will take dictionaries but nothing else unless we are running...
	// we will be loaded by the time that message arrives...

	if (
		app->GetApplicationState() !=
			ApplicationStateEngine::RunningGameState
	)
	{
		return;
	}


	if(message_type == FirstPersonControlMessageID && playerVehicle[connection] != NULL)
	{
		
		Verify(Network::GetInstance()->AmIServer());

#if defined(_DEBUG) && 0 // jcem - for MR test
  {
	char Buffer[128];
	sprintf(Buffer, "EntityMgr:: FirstPersonControlMessageID\n");
	OutputDebugString(Buffer);
  }
#endif // _DEBUG && ...
		serverController->ReceivePlayerControl(connection,message);

	}
	else if (message_type == FirstPersonObserverControlMessageID)
	{
		Verify(Network::GetInstance()->AmIServer());

#if defined(_DEBUG) && 0 // jcem - for MR test
  {
	char Buffer[128];
	sprintf(Buffer, "EntityMgr:: FirstPersonObserverControlMessageID\n");
	OutputDebugString(Buffer);
  }
#endif // _DEBUG && ...
		serverController->ReceivePlayerObserverControl(connection,message);
	}
	else if (message_type == FirstPersonControlMessageID && playerVehicle[connection] == NULL)
	{
		SPEW(("jerryeds", "received control message from %d but do not have mech in list!!!!", connection));
	}
	else if (message_type == FirstPersonFullConfirmationMessageID)
	{

		
		Verify(!Network::GetInstance()->AmIServer());

#if defined(_DEBUG) && 0 // jcem - for MR test
  {
	char Buffer[128];
	sprintf(Buffer, "EntityMgr:: FirstPersonFullConfirmationMessageID\n");
	OutputDebugString(Buffer);
  }
#endif // _DEBUG && ...
		clientController->ReceiveFullConfirmation(message);
		
	}
	else if (message_type == FirstPersonSmallConfirmationMessageID)
	{

		Network::GetInstance()->netStatCollector[Network::MovementConfirmationBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8);

		Verify(!Network::GetInstance()->AmIServer());

#if defined(_DEBUG) && 0 // jcem - for MR test
  {
	char Buffer[128];
	sprintf(Buffer, "EntityMgr:: FirstPersonSmallConfirmationMessageID\n");
	OutputDebugString(Buffer);
  }
#endif // _DEBUG && ...
		clientController->ReceiveSmallConfirmation(message);
		
	}
	else if (message_type >= MWEntityManager::StartThirdPersonWeaponMessageID && message_type <= MWEntityManager::EndThirdPersonWeaponMessageID)
	{
		Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8);

		clientController->ReceiveWeaponCommand(connection, message_type, message);
	}
	else if (message_type >= MWEntityManager::StartFirstPersonWeaponMessageID && message_type <= MWEntityManager::EndFirstPersonWeaponMessageID)
	{
		Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8);

		serverController->ReceiveWeaponCommand(connection, message_type, message);

	}
	else if (message_type >= MWEntityManager::StartAIWeaponMessageID && message_type <= MWEntityManager::EndAIWeaponMessageID)
	{
		Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8);

		clientController->ReceiveWeaponCommand(connection, message_type, message);

	}
	else if (message_type == MWEntityManager::WeaponBundleMessageID)
	{
		Network::GetInstance()->netStatCollector[Network::IncomingWeaponMessageBitSizeStat].AddToStatistic(connection,message->GetBufferBytesUsed()*8);

#if defined(_DEBUG) && 0 // jcem - for MR test
  {
	char Buffer[128];
	sprintf(Buffer, "EntityMgr:: MWEntityManager::WeaponBundleMessageID\n");
	OutputDebugString(Buffer);
  }
#endif // _DEBUG && ...
		clientController->ReceiveWeaponBundle(connection, message_type, message);

	}
	else if (message_type >= MWEntityManager::DictionaryPage0MessageID && message_type <= MWEntityManager::DictionaryPageMaxMessageID)
	{
		if (dictionaryManager[Connection::Local->GetID()] == NULL)
			return;

#if defined(_DEBUG) && 0 // jcem - for MR test
  {
	char Buffer[128];
	sprintf(Buffer, "EntityMgr:: MWEntityManager::DictionaryPage###\n");
	OutputDebugString(Buffer);
  }
#endif // _DEBUG && ...
        if (g_nMR != 2)
		NetVerify(!Network::GetInstance()->AmIServer());
		NetVerify(message != NULL);
		NetVerify(message->GetBytesRemaining() > 0);
		dictionaryManager[Connection::Local->GetID()]->Decode(message_type, message);
	}
	else
	{
		STOP(("MWEntityManager::UNHANDLED PACKET!!!!!"));

	}
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void MWEntityManager::CreateWeaponEffect(WeaponUpdate &weapon_packet)
{

	if (weapon_packet.obsolete)
		return;


	if (weapon_packet.originator.GetCurrent() == NULL)
		return;




	//make the collision query...

	Stuff::Point3D local_point;
	Stuff::Point3D origin_point;
	LinearMatrix4D our_matrix;

	MWObject *vehicle = Cast_Object(MWObject *, weapon_packet.originator.GetCurrent());


	// the packet originiated locally.
  if (g_nMR != 2) {
	if (vehicle->GetReplicatorID().connectionID == Connection::Local->GetID())
	{
		return;
	}
  }


	LinearMatrix4D eye_mat;
	origin_point = vehicle->GetLocalToWorld();
	eye_mat = vehicle->GetLocalToWorld();

	if(vehicle->eyeSitePointer.GetCurrent())
	{
		origin_point = vehicle->eyeSitePointer.GetCurrent()->GetLocalToWorld();
		eye_mat = vehicle->eyeSitePointer.GetCurrent()->GetLocalToWorld();
	}
	else
	{
		Stuff::ChainIteratorOf<Weapon*> iterator(&vehicle->weaponChain);
		Weapon *weapon;

		if ((weapon = iterator.ReadAndNext()) != NULL)
		{
			if (weapon->sitePointer)
			{
				origin_point = weapon->sitePointer->GetLocalToWorld();
				eye_mat = weapon->sitePointer->GetLocalToWorld();
			}
		}
	}

	Vector3D line_direction;

	Point3D target_point = Point3D::Identity;

	if (weapon_packet.target.GetCurrent() != NULL)
	{
		

		if (weapon_packet.target.GetCurrent() != Map::GetInstance())
		{
//			SPEWALWAYS(("jackyc", "CreateWeaponEffect - packet target is not a map"));	

			//target_point = weapon_packet.target->GetLocalToWorld();
			//target_point += weapon_packet.targetOffset;

			target_point.Multiply(weapon_packet.targetOffset, weapon_packet.target.GetCurrent()->GetLocalToWorld());

			
		}
		else
		{
//			SPEWALWAYS(("jackyc", "CreateWeaponEffect - packet target is a map"));	
	
			target_point = weapon_packet.targetOffset;
		}


		line_direction.Subtract(target_point, origin_point);


	}
	else
	{
//		SPEWALWAYS(("jackyc", "CreateWeaponEffect - packet target is NULL"));	

		//UnitVector3D temp_vector;	
		//eye_mat.GetLocalForwardInWorld(&temp_vector);
		//line_direction = temp_vector;

		Point3D target_point;
		target_point = weapon_packet.targetOffset;
		line_direction.Subtract(target_point, origin_point);

	}


	

	Stuff::Normal3D normal(0.0f, 1.0f, 0.0f);
	Stuff::Line3D target_line;
	target_line.SetOrigin(origin_point);
	target_line.SetDirection(line_direction);
	target_line.m_length = 1500.0f;

//	SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_line origin, %f, %f, %f", origin_point.x, origin_point.y, origin_point.z));
//	SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_line direction, %f, %f, %f", line_direction.x, line_direction.y, line_direction.z));
//	SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_line length, %f", 1500));	

	Adept::Entity::CollisionQuery query(&target_line, &normal, Adept::Entity::CanBeShotFlag, weapon_packet.originator.GetCurrent());

	Adept::Entity *entity_hit = NULL;
	Check_Object(CollisionGrid::Instance);
	entity_hit = CollisionGrid::Instance->ProjectLine(&query);
	
//	SPEWALWAYS(("jackyc", "CreateWeaponEffect - query line origin, %f, %f, %f", query.m_line->m_origin.x, query.m_line->m_origin.y, query.m_line->m_origin.z));
//	SPEWALWAYS(("jackyc", "CreateWeaponEffect - query line direction, %f, %f, %f", query.m_line->m_direction.x, query.m_line->m_direction.y, query.m_line->m_direction.z));
//	SPEWALWAYS(("jackyc", "CreateWeaponEffect - query line length, %f", query.m_line->m_length));	
//	SPEWALWAYS(("jackyc", "CreateWeaponEffect - query normal, %f, %f, %f", query.m_normal->x, query.m_normal->y, query.m_normal->z));

//	{
//		Stuff::Point3D target_point;
//		query.m_line->FindEnd(&target_point);
//
//		SPEWALWAYS(("jackyc", "CreateWeaponEffect - target_point, %f, %f, %f", 
//			target_point.x, 
//			target_point.y, 
//			target_point.z));
//	}

#ifdef _ARMOR
//	if (entity_hit != NULL && weapon_packet.target != NULL && weapon_packet.target->instanceName && entity_hit->instanceName )
//		SPEW(("jerryeds", "AIMED AT %s, HIT : %s", (char*)weapon_packet.target->instanceName, (char*)entity_hit->instanceName));
//	else if (weapon_packet.target != NULL && weapon_packet.target->instanceName)
//		SPEW(("jerryeds", "AIMED AT %s, MISSEd", (char*)weapon_packet.target->instanceName));
//	else
//		SPEW(("jerryeds", "NO NAMES"));
//
//	SPEW(("jerryeds", "TARGETPOINT : <%f:%f:%f> ", target_point.x, target_point.y, target_point.z));
#endif

	if (weapon_packet.target.GetCurrent() && weapon_packet.target.GetCurrent()->IsDerivedFrom(Vehicle::DefaultData))
	{
		/*
		SPEWALWAYS(("jackyc", "CreateWeaponEffect - weapon_packet.target.GetCurrent()"));
		if (weapon_packet.target.GetCurrent() == NULL)
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To No Target"));
		}
		else if (weapon_packet.target.GetCurrent() == Map::GetInstance())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground or No Target"));
		}
		else if (weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID == Connection::Hermit->GetID())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground"));
		}
		else if (weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID != Connection::Server->GetID())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech"));
			
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech"));
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mech connection ID, %d, %d", 
				weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID, 
				weapon_packet.target.GetCurrent()->GetReplicatorID().localID));
			
			Entity* parent_target = weapon_packet.target.GetCurrent();
			int class_id = parent_target->GetClassID();
			if (class_id == MWMoverClassID)
			{
				SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mover Name - NOT AVAILABLE"));
			}
			else
			{
				SPEWALWAYS(("jackyc", "CreateWeaponEffect - Not a MWMover"));
			}
		}
		else if (weapon_packet.target.GetCurrent()->GetReplicatorID().connectionID == Connection::Server->GetID())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Server"));
		}
		*/

		query.m_raySource = weapon_packet.target.GetCurrent();
	}
	else
	{
		/*
		SPEWALWAYS(("jackyc", "CreateWeaponEffect - entity_hit"));
		if (entity_hit == NULL)
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To No Target"));
		}
		else if (entity_hit == Map::GetInstance())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground or No Target"));
		}
		else if (entity_hit->GetReplicatorID().connectionID == Connection::Hermit->GetID())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Ground"));
		}
		else if (entity_hit->GetReplicatorID().connectionID != Connection::Server->GetID())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech"));
			
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Mech"));
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mech connection ID, %d, %d", 
				entity_hit->GetReplicatorID().connectionID, 
				entity_hit->GetReplicatorID().localID));
			
			Entity* parent_target = entity_hit;
			int class_id = parent_target->GetClassID();
			if (class_id == MWMoverClassID)
			{
//				MWMover* mover = Cast_Object(MWMover*, parent_target);
//				if (entity_hit->instanceName)
//				{
//					SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mover Name - %s", (char*)entity_hit->instanceName));
//				}
//				else
				{
					SPEWALWAYS(("jackyc", "CreateWeaponEffect - Mover Name - NOT AVAILABLE"));
				}
			}
			else
			{
				SPEWALWAYS(("jackyc", "CreateWeaponEffect - Not a MWMover"));
			}
		}
		else if (entity_hit->GetReplicatorID().connectionID == Connection::Server->GetID())
		{
			SPEWALWAYS(("jackyc", "CreateWeaponEffect - First Person Weapon To Server"));
		}
		*/

		query.m_raySource = entity_hit;
	}


	// missile lock vector is straight ahead...
	//UnitVector3D temp_vector;	
	//eye_mat.GetLocalForwardInWorld(&temp_vector);
	//line_direction = temp_vector;

#if 0
	Stuff::Normal3D lock_normal(0.0f, 1.0f, 0.0f);
	Stuff::Line3D locktarget_line;
	locktarget_line.SetOrigin(origin_point);
	locktarget_line.SetDirection(line_direction);
	locktarget_line.m_length = 1000.0f;
	

	Adept::Entity::CollisionQuery lock_query(&locktarget_line, &lock_normal, Adept::Entity::CanBeShotFlag, weapon_packet.originator.GetCurrent());
	
	lock_query.m_raySource = weapon_packet.target.GetCurrent();
#endif

	Stuff::ChainIteratorOf<Weapon*> iterator(&vehicle->weaponChain);
	Weapon *weapon;
	
	while ((weapon = iterator.ReadAndNext()) != NULL)
	{
		int id = weapon->GetWeaponID();
		if (weapon_packet.weaponFired & (0x1 << id))
		{

			if (weapon->IsDerivedFrom(MissileWeapon::DefaultData))
			{
				
				MissileWeapon *missile_weapon;
				missile_weapon = Cast_Object(MissileWeapon *, weapon);

				query.m_raySource = weapon_packet.target.GetCurrent();

				if (missile_weapon->IsAMSValid(weapon_packet.target.GetCurrent()))
				{
					missile_weapon->SetAMSNumber(weapon_packet.AntiWeaponCount[id]);
				}
				weapon->FireWeapon(&query, weapon_packet.lockTime, Stuff::Point3D::Identity);
				
			}
			else
			{

				weapon->FireWeapon(&query, weapon_packet.lockTime, Stuff::Point3D::Identity);
			}
		}
	}


}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


void MWEntityManager::UpdateDictionaries(void)
{
  if (g_nMR != 2) {
	MWApplication *app = MWApplication::GetInstance();


	for (int i = 0; i < Maximum_Players; ++i)
	{


		// if they are connected and have a vehicle
		// than make them one.
		if (app->servedConnectionData[i].clientConnected && app->servedConnectionData[i].clientLoaded)
		{

			//SPEW(("jerryeds", "%d : SEND INDEX : %d", Connection::Local->GetID(), i));
            if (i == Connection::Server->GetID()) {
                if ((g_nMR != 1) || (g_MRF.m_nCount < 0))
                    continue;
                int nForceConnectionSpeedOld = MWApplication::ForceConnectionSpeed;
                MWApplication::ForceConnectionSpeed = BitDepthManager::HighBandwidth; // BitDepthManager::LowBandwidth, BitDepthManager::MediumBandwidth

                UpdateDictionaries(i);

                MWApplication::ForceConnectionSpeed = nForceConnectionSpeedOld;
            } else {
			    UpdateDictionaries(i);
            }
		}
		else
		{
			if (dictionaryManager[i] != NULL)
			{
				Unregister_Object(dictionaryManager[i]);
				delete dictionaryManager[i];
				dictionaryManager[i] = NULL;
			}
		}

	}
  }

	dictionaryDirtyFlag = false;
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



void MWEntityManager::UpdateDictionaries(int i)
{

  if (g_nMR != 2) {
	MWApplication *app = MWApplication::GetInstance();

	if (dictionaryManager[i] == NULL)
	{
		dictionaryManager[i] = new DictionaryManager(i);
		Register_Object(dictionaryManager[i]);
	}


	
	int connection_rate = BitDepthManager::LowBandwidth;

	if (MWApplication::ForceConnectionSpeed != -1)
	{
		connection_rate = MWApplication::ForceConnectionSpeed;
	}
	else if (app->servedConnectionData[i].bandwidthThrottle)
	{
		connection_rate = BitDepthManager::LowBandwidth;
	}
	else if (MWApplication::MyConnectionSpeed >= MWApplication::c_1500_kbps)
	{
	
		if (app->servedConnectionData[i].clientConnectionRate >= MWApplication::c_1500_kbps)
		{
			connection_rate = BitDepthManager::HighBandwidth;
		}
		else if (app->servedConnectionData[i].clientConnectionRate >= MWApplication::c_128_kbps)
		{
			connection_rate = BitDepthManager::MediumBandwidth;
		}
		else
		{
			connection_rate = BitDepthManager::LowBandwidth;
		}

	}
	else if (MWApplication::MyConnectionSpeed >= MWApplication::c_768_kbps)
	{
		if (app->servedConnectionData[i].clientConnectionRate > MWApplication::c_64_kbps)
		{
			connection_rate = BitDepthManager::MediumBandwidth;
		}
		else
		{
			connection_rate = BitDepthManager::LowBandwidth;
		}
	}
	else
	{
		connection_rate = BitDepthManager::LowBandwidth;
	}

	#if defined(LAB_ONLY)
		MWGameInfo::g_networkDebugLevel[i] = MWApplication::NetworkDebugLevel;
		MWGameInfo::g_connectRate[i] = connection_rate;
	#endif

	Dictionary *dictionary = dictionaryManager[i]->MakeNewDictionary(dictionaryManager[i]->GetNextDictionaryID(), MWApplication::NetworkDebugLevel, connection_rate);
	
	MakeDictionaryPages(dictionary);


	DynamicMemoryStream stream;
	
	//dictionaryManager[i]->EncodeDictionary(&stream);
	
	stream.WriteBits(&dictionary->versionNumber, 8);
	stream.WriteBits(&dictionary->debugDictionaryLevel, 2);
	stream.WriteBits(&dictionary->dictionaryBandwidth, 2);

	BYTE player_count = 0;
	for (int j = 0; j < Maximum_Players; ++j)
	{
		if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer)
		{
			++player_count;
		}
	}

	stream.WriteBits(&player_count, 8);

	for ( j = 0; j < Maximum_Players; ++j)
	{
		if (app->servedConnectionData[j].clientConnected && app->servedConnectionData[j].clientPlayer)
		{
			ResourceID id = app->servedConnectionData[j].clientPlayer->vehicle->GetGameModelResourceID();
		
			int sub_id = id.GetRecordID();

			stream.WriteBits(&j,8);
			stream.WriteBits(&sub_id, 32);
		}
	}

	
	stream.WriteByteAlign();
	stream.Rewind();


	// This is dangerous as it creates NEW pages that will
	// be updated.  ICK.  That doubles the bandwidth on 
	// a armor build!!!!

	//#if defined(_ARMOR)
	//dictionaryManager[i]->DecodeDictionary(&stream);
	//stream.Rewind();
	//#endif

	// send the dictionary
	Check_Object(Application::GetInstance());

	// break up the message...

	Network::GetInstance()->netStatCollector[Network::OutgoingSystemMessageBitSizeStat].AddToStatistic(i,stream.GetBufferBytesUsed()*8);
	Network::GetInstance()->SendNetMessage(i, DictionaryIndexMessageID, &stream, true);
  }
}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void MWEntityManager::MakeDictionaryPages(Dictionary *dictionary)
{
	
			
	Stuff::SortedChainIteratorOf<Mech*, Adept::ReplicatorID> iterator(&servedMechs);

	int connection_rate = dictionary->dictionaryBandwidth;

	NetUpdateSorter sorter(dictionary->debugDictionaryLevel, dictionary->dictionaryBandwidth);


	Entity *entity;
  if (g_nMR && (dictionary->connectionID == 1)) {
	while ((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);

		//-sorter.AddUpdateToList(entity, UpdateManager::MechPositionUpdateID, bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, connection_rate));
		//sorter.AddUpdateToList(entity, UpdateManager::MechAnimationUpdateID, bitManager->GetUpdateRate(UpdateManager::MechAnimationUpdateID, connection_rate));		
		//sorter.AddUpdateToList(entity, UpdateManager::MechMovemntUpdateID, bitManager->GetUpdateRate(UpdateManager::MechMovemntUpdateID, connection_rate));
		//sorter.AddUpdateToList(entity, UpdateManager::MechExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate));
		//jcem-dead or alive-sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate));
        //--sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalDamageUpdateID, connection_rate));
        sorter.AddUpdateToList(entity, UpdateManager::MechInternalHeatUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalHeatUpdateID, connection_rate)); //
		sorter.AddUpdateToList(entity, UpdateManager::SubsystemUpdateID, bitManager->GetUpdateRate(UpdateManager::SubsystemUpdateID, connection_rate));
		sorter.AddUpdateToList(entity, UpdateManager::FlushUpdateID, bitManager->GetUpdateRate(UpdateManager::FlushUpdateID, connection_rate));
		sorter.AddUpdateToList(entity, UpdateManager::SearchLightUpdateID, bitManager->GetUpdateRate(UpdateManager::SearchLightUpdateID, connection_rate));
		sorter.AddUpdateToList(entity, UpdateManager::ExternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalAMSAmmoUpdateID, connection_rate));
		//-sorter.AddUpdateToList(entity, UpdateManager::ExternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalJumpJetUpdateID, connection_rate));
		//--sorter.AddUpdateToList(entity, UpdateManager::InternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalAMSAmmoUpdateID, connection_rate));
		//--sorter.AddUpdateToList(entity, UpdateManager::InternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalJumpJetUpdateID, connection_rate));

	    sorter.AddUpdateToList(entity, UpdateManager::NearBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::NearBuildingExternalDamageUpdateID, connection_rate));
	    sorter.AddUpdateToList(entity, UpdateManager::SecondaryBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::SecondaryBuildingExternalDamageUpdateID, connection_rate));
	    sorter.AddUpdateToList(entity, UpdateManager::FarBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::FarBuildingExternalDamageUpdateID, connection_rate));
		if (entity->IsPlayerVehicle())
		{
			//sorter.AddUpdateToList(entity, UpdateManager::PingUpdateID, bitManager->GetUpdateRate(UpdateManager::PingUpdateID, connection_rate));
		}

	}
	entity = MWApplication::GetInstance()->servedConnectionData[dictionary->connectionID].clientPlayer->vehicle;

	//-sorter.AddUpdateToList(entity, UpdateManager::SecurityResponseID, bitManager->GetUpdateRate(UpdateManager::SecurityResponseID, connection_rate));
	//-sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate));

	//-sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate));
	//-sorter.AddUpdateToList(entity, UpdateManager::TimeUpdateID, bitManager->GetUpdateRate(UpdateManager::TimeUpdateID, connection_rate));

    // moved to above : 3 lines
	//-sorter.AddUpdateToList(entity, UpdateManager::NearBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::NearBuildingExternalDamageUpdateID, connection_rate));
	//-sorter.AddUpdateToList(entity, UpdateManager::SecondaryBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::SecondaryBuildingExternalDamageUpdateID, connection_rate));
	//-sorter.AddUpdateToList(entity, UpdateManager::FarBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::FarBuildingExternalDamageUpdateID, connection_rate));

	//-sorter.AddUpdateToList(entity, UpdateManager::MissionObjectiveUpdateID, bitManager->GetUpdateRate(UpdateManager::MissionObjectiveUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::VehicleDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::VehicleDamageUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::NavPointUpdateID, bitManager->GetUpdateRate(UpdateManager::NavPointUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::FlagUpdateID, bitManager->GetUpdateRate(UpdateManager::FlagUpdateID, connection_rate));
  } else {
    gosASSERT(g_nMR != 2);
	while ((entity = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(entity);
		
		if (entity->GetReplicatorID().connectionID != dictionary->connectionID)
		{

			sorter.AddUpdateToList(entity, UpdateManager::MechPositionUpdateID, bitManager->GetUpdateRate(UpdateManager::MechPositionUpdateID, connection_rate));
			//sorter.AddUpdateToList(entity, UpdateManager::MechAnimationUpdateID, bitManager->GetUpdateRate(UpdateManager::MechAnimationUpdateID, connection_rate));		
			//sorter.AddUpdateToList(entity, UpdateManager::MechMovemntUpdateID, bitManager->GetUpdateRate(UpdateManager::MechMovemntUpdateID, connection_rate));
			//sorter.AddUpdateToList(entity, UpdateManager::MechExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate));
			sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechExternalDamageUpdateID, connection_rate));
			sorter.AddUpdateToList(entity, UpdateManager::SubsystemUpdateID, bitManager->GetUpdateRate(UpdateManager::SubsystemUpdateID, connection_rate));
			sorter.AddUpdateToList(entity, UpdateManager::FlushUpdateID, bitManager->GetUpdateRate(UpdateManager::FlushUpdateID, connection_rate));
			sorter.AddUpdateToList(entity, UpdateManager::SearchLightUpdateID, bitManager->GetUpdateRate(UpdateManager::SearchLightUpdateID, connection_rate));
			sorter.AddUpdateToList(entity, UpdateManager::ExternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalAMSAmmoUpdateID, connection_rate));
			sorter.AddUpdateToList(entity, UpdateManager::ExternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::ExternalJumpJetUpdateID, connection_rate));
	
			if (entity->IsPlayerVehicle())
			{
				sorter.AddUpdateToList(entity, UpdateManager::PingUpdateID, bitManager->GetUpdateRate(UpdateManager::PingUpdateID, connection_rate));
			}
		
		}
		else
		{
			if (entity->IsPlayerVehicle())
			{
				sorter.AddUpdateToList(entity, UpdateManager::MechInternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalDamageUpdateID, connection_rate));
				sorter.AddUpdateToList(entity, UpdateManager::MechInternalHeatUpdateID, bitManager->GetUpdateRate(UpdateManager::MechInternalHeatUpdateID, connection_rate));
				sorter.AddUpdateToList(entity, UpdateManager::SubsystemUpdateID, bitManager->GetUpdateRate(UpdateManager::SubsystemUpdateID, connection_rate));
				//sorter.AddUpdateToList(entity, UpdateManager::FlushUpdateID, bitManager->GetUpdateRate(UpdateManager::FlushUpdateID, connection_rate));
				sorter.AddUpdateToList(entity, UpdateManager::SearchLightUpdateID, bitManager->GetUpdateRate(UpdateManager::SearchLightUpdateID, connection_rate));
				sorter.AddUpdateToList(entity, UpdateManager::InternalAMSAmmoUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalAMSAmmoUpdateID, connection_rate));
				sorter.AddUpdateToList(entity, UpdateManager::InternalJumpJetUpdateID, bitManager->GetUpdateRate(UpdateManager::InternalJumpJetUpdateID, connection_rate));
				
			}
		}

	}
	entity = MWApplication::GetInstance()->servedConnectionData[dictionary->connectionID].clientPlayer->vehicle;

	sorter.AddUpdateToList(entity, UpdateManager::SecurityResponseID, bitManager->GetUpdateRate(UpdateManager::SecurityResponseID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate));

//	sorter.AddUpdateToList(entity, UpdateManager::SecurityQueryID, bitManager->GetUpdateRate(UpdateManager::SecurityQueryID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::TimeUpdateID, bitManager->GetUpdateRate(UpdateManager::TimeUpdateID, connection_rate));

	sorter.AddUpdateToList(entity, UpdateManager::NearBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::NearBuildingExternalDamageUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::SecondaryBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::SecondaryBuildingExternalDamageUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::FarBuildingExternalDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::FarBuildingExternalDamageUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::MissionObjectiveUpdateID, bitManager->GetUpdateRate(UpdateManager::MissionObjectiveUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::VehicleDamageUpdateID, bitManager->GetUpdateRate(UpdateManager::VehicleDamageUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::NavPointUpdateID, bitManager->GetUpdateRate(UpdateManager::NavPointUpdateID, connection_rate));
	sorter.AddUpdateToList(entity, UpdateManager::FlagUpdateID, bitManager->GetUpdateRate(UpdateManager::FlagUpdateID, connection_rate));
  }


	Stuff::ChainIteratorOf<Airplane*> iterator1(&servedAirplanes);
	while ((entity = iterator1.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::AirMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::AirMovementUpdateID, connection_rate));
		
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
	}
	Stuff::ChainIteratorOf<Boat*> iterator2(&servedBoats);
	while ((entity = iterator2.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate));
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
		
	}
	Stuff::ChainIteratorOf<Dropship*> iterator3(&servedDropships);
	while ((entity = iterator3.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::AirMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::AirMovementUpdateID, connection_rate));
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
		
	}
	Stuff::ChainIteratorOf<Helicopter*> iterator4(&servedHelicopters);
	while ((entity = iterator4.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::AirMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::AirMovementUpdateID, connection_rate));
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
		
	}
	Stuff::ChainIteratorOf<Hovercraft*> iterator5(&servedHovercraft);
	while ((entity = iterator5.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate));
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
	}
	Stuff::ChainIteratorOf<Tank*> iterator7(&servedTanks);
	while ((entity = iterator7.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate));
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
	}
	Stuff::ChainIteratorOf<Truck*> iterator8(&servedTrucks);
	while ((entity = iterator8.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::GroundMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::GroundMovementUpdateID, connection_rate));
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
	}
	Stuff::ChainIteratorOf<Turret*> iterator9(&servedTurrets);
	while ((entity = iterator9.ReadAndNext()) != NULL)
	{
		sorter.AddUpdateToList(entity, UpdateManager::TurretMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TurretMovementUpdateID, connection_rate));
		MWObject *object = Cast_Object(MWObject*, entity);
		if (object->GetTorso())
		{
			sorter.AddUpdateToList(object->GetTorso(), UpdateManager::TorsoMovementUpdateID, bitManager->GetUpdateRate(UpdateManager::TorsoMovementUpdateID, connection_rate));
		}
	}

	sorter.MakeDictionaryPages(dictionary);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void MWEntityManager::QueCommand(int command)
{
#if defined(LAB_ONLY)
	if (commandCount >= 4)
	{
		SPEWALWAYS(("jerryeds", "TOO MANY COMMANDS"));
	}
#endif

	if (Application::GetInstance()->networkingFlag && !Application::GetInstance()->serverFlag)
	{
		commandCount++;
		VehicleCommand *new_command = new VehicleCommand();
		new_command->m_Command = command;
		quedCommands.Add(new_command);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



void MWEntityManager::RespawnClient(int connection_id, Point3D trans)
{

	if (serverController != NULL)
	{
		serverController->RespawnClient(connection_id, trans);
	}

	if (clientController != NULL)
	{
		clientController->RespawnClient(connection_id);
	}

	// ngLog addition	// JKK
#if !defined(NO_LOG)
	MW4log_generic(MW4P_RESPAWN, va("Player_Respawn\t%d", connection_id));
#endif // !defined(NO_LOG)
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


void MWEntityManager::AddPlayerVehicle(Mover *mover)
{

	if (mover->GetClassData() == Mech::DefaultData)
	{
		Verify(mover->GetClassData() == Mech::DefaultData);
		Verify(mover->IsPlayerVehicle());

		int mech_id = mover->GetReplicatorID().connectionID;
		Verify(playerVehicle[mech_id] == NULL);
		playerVehicle[mech_id] = Cast_Object(Vehicle*, mover);

		// add score member for the player mech
		Mission::GetInstance()->AddScoreMember (mover->GetReplicatorID(), mover->instanceName);

		// reset security response
		if (Application::GetInstance()->serverFlag && serverController != NULL)
		{
			serverController->ResetClient(mech_id);
		}

		#if defined(LAB_ONLY)
			int connection = mover->GetReplicatorID().connectionID;

			MWGameInfo::g_playerJoinTime[connection] = gos_GetElapsedTime();

			++MWGameInfo::g_totalNetworkJoins;
			++MWGameInfo::g_currentlyJoined;
			++MWGameInfo::g_playerJoins[connection];

			MWGameInfo::g_lastJoinID = connection;

			const char *name;
			name = mover->GetModelName ();

			std::string s(name);
			std::string::size_type last_period = s.find_last_of('.');
			if (last_period != std::string::npos)
			{
				s.erase(last_period,s.size() - 1 - last_period);
			}

			std::string::size_type last_slash = s.find_last_of('\\');
			if (last_slash != std::string::npos)
			{
				s.erase(0,last_slash + 1);
			}

			strncpy (MWGameInfo::g_playerVehicleNames[connection],s.c_str(),s.size() - 1);
			MWGameInfo::g_playerVehicleNames[connection][s.size()] = 0;

			if (mover->IsDerivedFrom(Vehicle::DefaultData) == true)
			{
				Vehicle* v = Cast_Object(Vehicle*,mover);
				MWGameInfo::g_playerTeams[connection] = v->GetTeam();
			}
		#endif

#if !defined(NO_MR)
		int conn = mover->GetReplicatorID().connectionID;
		MWApplication *app = MWApplication::GetInstance();

		if(app->m_recordLog) {
			app->m_recordLog->AddPlayer(Network::GetInstance()->GetConnection(conn)->GetConnectionName(), conn);
		}
#endif // !defined(NO_MR)
	}
	//else we are in brb or something

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


void MWEntityManager::RemovePlayerVehicle(Mover *mover)
{

	#if defined(LAB_ONLY)
			int connection = mover->GetReplicatorID().connectionID;

			MWGameInfo::g_playerLeaveTime[connection] = gos_GetElapsedTime();

			++MWGameInfo::g_totalNetworkLeaves;
			--MWGameInfo::g_currentlyJoined;
			++MWGameInfo::g_playerLeaves[connection];
			MWGameInfo::g_lastLeaveID = mover->GetReplicatorID().connectionID;
	#endif

    if (MWApplication::GetInstance()->serverFlag) {
        if (mover->GetClassData() == Mech::DefaultData) {
            Mech* mech = Cast_Pointer(Mech*, mover);
            g_RSF.RemoveScoreObject(mech); // jcem
        }
    }

#if !defined(NO_MR)
	if (MWApplication::GetInstance()->m_recordLog)
	{
		int connection = mover->GetReplicatorID().connectionID;
		MWApplication::GetInstance()->m_recordLog->RemovePlayer(connection);
	}
#endif // !defined(NO_MR)



	int mech_id = mover->GetReplicatorID().connectionID;
	playerVehicle[mech_id] = NULL;


	if (MWApplication::GetInstance()->servedConnectionData[mech_id].clientPlayer != NULL)
	{
		MWApplication::GetInstance()->servedConnectionData[mech_id].clientPlayer->vehicle = NULL;
	}




	if(Mission::GetInstance())
	{
		Check_Object(this);
		Mission::GetInstance()->RemoveScoreMember (mover->GetReplicatorID());
	}

	if (mover != 0)
	{
		Flag::RemoveAllFlagsFrom(*mover);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void MWEntityManager::AddMover(Mover *mover)
{
	SetDirtyFlag();

	if(mover->GetClassData() == Mech::DefaultData)
	{
		Mech *mech = Cast_Object(Mech*, mover);


		servedMechs.AddValue(mech, mech->GetReplicatorID());

		/*
		if (mover->GetReplicatorMode() == Replicator::MasterMode)
		{
			servedMechs.AddValue(mech, mech->GetReplicatorID());
		}
		else if (mover->GetReplicatorMode() == Replicator::ServerMasterMode)
		{

			// turn this mech off

			// mech->executionState->RequestState(Mech::ExecutionStateEngine::NeverExecuteState);
			servedMechs.AddValue(mech, mech->GetReplicatorID());
		}

		*/
	}
	else
	{
		
		switch(mover->GetClassID())
		{
			case AirplaneClassID:
				{
					Airplane *obj = Cast_Object(Airplane*, mover);
					servedAirplanes.Add(obj);
				}
				break;
			case BoatClassID:
				{
					Boat *obj = Cast_Object(Boat*, mover);
					servedBoats.Add(obj);
				}
				break;
			case DropshipClassID:
				{
					Dropship *obj = Cast_Object(Dropship*, mover);
					servedDropships.Add(obj);
				}
				break;
			case HelicopterClassID:
				{
					Helicopter *obj = Cast_Object(Helicopter*, mover);
					servedHelicopters.Add(obj);
				}
				break;
			case HovercraftClassID:
				{
					Hovercraft *obj = Cast_Object(Hovercraft*, mover);
					servedHovercraft.Add(obj);
				}
				break;
			case TankClassID:
				{
					Tank *obj = Cast_Object(Tank*, mover);
					servedTanks.Add(obj);
				}
				break;
			case TruckClassID:
				{
					Truck *obj = Cast_Object(Truck*, mover);
					servedTrucks.Add(obj);
				}
				break;
			case TurretClassID:
				{
					Turret *obj = Cast_Object(Turret*, mover);
					servedTurrets.Add(obj);
				}
				break;			
		}
		

	}

	EntityManager::AddMover(mover);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void MWEntityManager::RemoveMover(Mover *mover)
{
	SetDirtyFlag();

	
	if(mover->GetClassData() == Mech::DefaultData)
	{
		//Mech *mech = Cast_Object(Mech*, mover);

		Mech *mech = Cast_Pointer(Mech*, mover);
		if (mech->IsPlayerVehicle())
		{
			RemovePlayerVehicle(mover);
		}


		servedMechs.Remove(mech);

		/*
		if (mover->GetReplicatorMode() == Replicator::MasterMode)
		{
			servedMechs.Remove(mech);
		}
		else if (mover->GetReplicatorMode() == Replicator::ServerMasterMode)
		{
			// remove all the server side control buffers for this player
			if (Application::GetInstance()->serverFlag)
			{
				int mech_id = mech->GetReplicatorID().connectionID;
				if (serverController != NULL)
				{
					serverController->RemovePlayer(mech_id);
				}
			}


			servedMechs.Remove(mech);
		}
		*/
	}
	else
	{
		switch(mover->GetClassID())
		{
			case AirplaneClassID:
				{
					Airplane *obj = Cast_Pointer(Airplane*, mover);
					Check_Object(obj);
					servedAirplanes.Remove(obj);
				}
				break;
			case BoatClassID:
				{
					Boat *obj = Cast_Pointer(Boat*, mover);
					Check_Object(obj);
					servedBoats.Remove(obj);
				}
				break;
			case DropshipClassID:
				{
					Dropship *obj = Cast_Pointer(Dropship*, mover);
					Check_Object(obj);
					servedDropships.Remove(obj);
				}
				break;
			case HelicopterClassID:
				{
					Helicopter *obj = Cast_Pointer(Helicopter*, mover);
					Check_Object(obj);
					servedHelicopters.Remove(obj);
				}
				break;
			case HovercraftClassID:
				{
					Hovercraft *obj = Cast_Pointer(Hovercraft*, mover);
					Check_Object(obj);
					servedHovercraft.Remove(obj);
				}
				break;
			case TankClassID:
				{
					Tank *obj = Cast_Pointer(Tank*, mover);
					Check_Object(obj);
					servedTanks.Remove(obj);
				}
				break;
			case TruckClassID:
				{
					Truck *obj = Cast_Pointer(Truck*, mover);
					Check_Object(obj);
					servedTrucks.Remove(obj);
				}
				break;
			case TurretClassID:
				{
					Turret *obj = Cast_Pointer(Turret*, mover);
					Check_Object(obj);
					servedTurrets.Remove(obj);
				}
				break;			
		}
		
	}

	EntityManager::RemoveMover(mover);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


Scalar MWEntityManager::FindGroundHeight(Stuff::Scalar x_position, Stuff::Scalar z_position)
{
	
	
	// one would think I can just get the
	Point3D test_point;
	test_point.x = x_position;
	test_point.y = 500.0f;
	test_point.z = z_position;
	

	Stuff::Vector3D world_avg_normal(Stuff::Vector3D::Identity);
	

	Stuff::Normal3D normal;
	Stuff::Line3D line;
	Adept::Entity::CollisionQuery query(&line, &normal, Adept::Entity::CanBeWalkedOnFlag, NULL);

	//
	// Cast ray
	//
	Adept::Entity *entity_hit;
	Check_Object(CollisionGrid::Instance);
	
	line.m_length = 1000.0f;
	line.m_direction = Vector3D::Down;
	line.m_origin = test_point;



	entity_hit = CollisionGrid::Instance->ProjectLine(&query);
	if(entity_hit != NULL)
	{
		// if we hit ground, great!
		Point3D end_point;
		line.FindEnd(&end_point);
		return end_point.y;
	}
	return 0.0f;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::AIWeaponUpdate(WeaponUpdate *weapon)
{

	if (Application::GetInstance()->networkingFlag)
	{
		Check_Object(weapon);
		Check_Object(weapon->originator.GetCurrent());

	#if defined (_ARMOR)
		if (weapon->target.GetCurrent() != NULL)
		{
			Check_Object(weapon->target.GetCurrent());
		}
	#endif

		weaponUpdates.Add(weapon);
	}
	else
		delete weapon;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::PlayerWeaponUpdate(WeaponUpdate *weapon)
{

	if (Application::GetInstance()->networkingFlag && weapon->weaponFired)
	{
		Check_Object(weapon);
		Check_Object(weapon->originator.GetCurrent());

	#if defined (_ARMOR)
		if (weapon->target.GetCurrent() != NULL)
		{
			Check_Object(weapon->target.GetCurrent());
		}
	#endif


		WeaponUpdate *copy = new WeaponUpdate;
		
		if (weapon->originator.GetCurrent())
			copy->originator.Add(weapon->originator.GetCurrent());

		if (weapon->target.GetCurrent())
			copy->target.Add(weapon->target.GetCurrent());

		copy->weaponFired = weapon->weaponFired;
		copy->targetOffset = weapon->targetOffset;
		copy->lockTime = weapon->lockTime;
		for (int i = 0; i < 32; ++i)
		{
			copy->AntiWeaponCount[i] = weapon->AntiWeaponCount[i];
		}

		weaponUpdates.Add(copy);
	}
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::QueWeapon(WeaponUpdate *weapon)
{
	Verify (Application::GetInstance()->networkingFlag);

	Verify(!weapon->obsolete);

	networkWeaponsQue.Add(weapon);
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::BuildTileBoundDamageList()
{
	
	EntityManager::BuildTileBoundDamageList();




}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	MWEntityManager::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}


void MWEntityManager::QueRespawnLancemate(Mech* lancemateMech)
{
    Check_Object(lancemateMech);
    // jcem - for delayed lancemate respawn
    MWMission* mission = Cast_Object(MWMission*, MWMission::GetInstance());
    Check_Object(mission);
    VehicleInterface* pVH = VehicleInterface::GetInstance();
    Check_Object(pVH);
    lancemateMech->m_fTimeRespawnRequestEnd = mission->GetMissionTime() + pVH->GetGameModel()->deathTimer;
    servedRespawnLances.Add(lancemateMech);
}
