
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Client.cpp
// Author : Andy Tate
// Date   : 12-Jan-2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "Network/AVP_Client.h"

// Asura independent header-files...

#include "Animation/Asura_Animation.h"
#include "Blueprint/Asura_Blueprint_System.h"
#ifdef ASURA_USE_BOTANICALS 
#include "Botanicals/Asura_Botanical_Game_Render_Instance.h"
#include "Botanicals/Asura_Botanical_Game_Render_Instance_Header.h"
#include "Botanicals/Asura_Botanical_Game_Render_Manager.h"
#endif //ASURA_USE_BOTANICALS
#include "Core/Asura_Material_System.h"
#include "Entity/Asura_Entity.h"
#include "Network/Asura_Message.h"

#ifdef ASURA_USE_DECAL_MANAGER
#include "SpecialFX/Asura_Decal_Manager.h"
#else
#include "SpecialFX/Asura_Decal_System.h"
#endif

#include "SpecialFX/PFX/Asura_PFX_Entity_Effect.h"

// Game independent header-files...
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Camera/AVP_CameraShake_System.h"
#include "Core/AVP_Core.h"
#include "Core/AVP_Game_Core.h"
#include "Core/AVP_GameStatus.h"
#include "Core/AVP_SurfaceEffects.h"
#include "Core/Asura_MaterialResponse_System.h"
#include "Entity/AVP_Messages.h"
#include "Entity/Damage/AVP_EntityDamage_BotanicalCallback.h"
#include "Entity/Damage/AVP_EntityDamage_Messages.h"
#include "SpecialFX/pfx/AVP_DamagePFX.h"

#if defined(ASURA_TOOLS)
// Tools header-files...
#include "Particles/Tools_Mode_PFX.h"
#endif	// defined(ASURA_TOOLS)

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ProcessJoinResponseMessage
// Author       : Andy Tate
// Date         : 16-Mar-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ProcessJoinResponseMessage(const Asura_Message* pxMessage)
{
	if(Asura_Network::IsClient())
	{
#if 0
		Log(AVP_GAME_LOG_FLAGS, L"Received join response");

		if(pxMessage->GetSentTime() < s_fTimeStamp_JoinTheGame)
		{
			Asura_Assert(false, "Messages out of order");
			return(false);
		}
		else
		{
			s_fTimeStamp_JoinTheGame = pxMessage->GetSentTime();

			if (!Asura_Network::IsServer())
			{
				// Copy from the servers settings, which contains the current game rules.
				const Gun_NetworkSession* const pxData = static_cast<const Gun_NetworkSession*>(pxMessage->GetData());
				if (pxData)
				{
					pxData->CopyToSettings();
				}

				// Make sure the score table is disabled.
				// Now handled outside the if
				//Gun_Game_Core::ResetLevelStatus();
			}

			// TDP 17/1/06 
			// The death timer needs to be reset
			Gun_Game_Core::ResetLevelStatus(false);

			s_bJoinTheGameAccepted = true;

			return true;
		}
#else
		Asura_Assert(false, "AVP_Client::ProcessJoinResponseMessage(): Not yet implemented.");
		return(false);
#endif
	}
	else
	{
		Asura_Assert(false, "Should only be called on clients");
		return(false);
	}
}

/// End of function 'AVP_Client::ProcessJoinResponseMessage'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ProcessTerminationMessage
// Author       : Andy Tate
// Date         : 16-Mar-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ProcessTerminationMessage(const Asura_Message* pxMessage)
{
	if(Asura_Network::IsServer())
	{
		Asura_Assert(false, "Should only be called on non-server machines");
		return(false);
	}
	else
	{
		// put game into disconnection state handler
		AVP_Core::RequestDisconnecting();
		return(true);
	}
}

/// End of function 'AVP_Client::ProcessTerminationMessage'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ProcessRestartMessage
// Author       : Andy Tate
// Date         : 16-Mar-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ProcessRestartMessage(const Asura_Message* pxMessage)
{
#if 0
	if (Gun_Settings::IsSinglePlayer())
	{
		Asura_Assert(0, "Restart message only allowed in MP games.");
		return(false);
	}
	else if (pxMessage->GetSentTime() < s_fTimeStamp_RestartMission)
	{
		Asura_Assert(false, "Messages out of order");
		return(false);
	}
	else
	{
		s_fTimeStamp_RestartMission = pxMessage->GetSentTime();

		const Gun_Message_Game_Restart* pxData = static_cast<const Gun_Message_Game_Restart*>(pxMessage->GetData());
		if (pxData)
		{
			Gun_ClientHuman_Player* const pxLocal = Gun_Game_Core::GetLocalPlayer();
			if (pxLocal)
			{
				//			const int iSpawnPoint = pxData->m_sSpawnPoint;
				//			pxLocal->Respawn(pxMessage->GetSentTime(), false, iSpawnPoint);			
			}
		}


		// Remove any ragdolls
		const Asura_Hashed_List<Gun_ClientEntity_Actor>* xListEntities = Gun_ClientEntity_Actor::GetList();
		Asura_Hashed_List_It<Gun_ClientEntity_Actor>	xIt(xListEntities);
		while(!xIt.Done())
		{
			Gun_ClientEntity_Actor* pxActor = static_cast<Gun_ClientEntity_Actor*>(xIt.GetCurrent());
			xIt.Next();

			//pxActor->RemoveRagdoll();
			pxActor->SetPlayingDeathAnim(false);
		}

		// Delete the ragdoll.
		//Asura_ClientEntity_Ragdoll * pxRagdollEntity = Asura_ClientEntity_Ragdoll::FindRagdollEntity(GetRagdollID());
		//if (pxRagdollEntity)
		//{
		//	delete pxRagdollEntity;
		//}

		/*
		const Asura_Hashed_List<Asura_ClientEntity_Ragdoll>* xListEntities = Asura_ClientEntity_Ragdoll::GetList();
		Asura_Hashed_List_It<Asura_ClientEntity_Ragdoll>	xIt(xListEntities);
		while(!xIt.Done())
		{
		Asura_ClientEntity_Ragdoll* pxRagdoll = static_cast<Asura_ClientEntity_Ragdoll*>(xIt.GetCurrent());
		xIt.Next();

		//pxActor->RemoveRagdoll();
		Asura_OutputToDebugger( ("Ragdoll %ld\n", pxRagdoll->GetGuid()) );
		}
		*/

		// Reset effects.
		Asura_Decal_System::Reset();

		// Reset any client PFX effect entities.
		// Some smoke/fire effects last a long time and need to be stopped quickly.
		for( Asura_Hashed_List_It<Asura_ClientEntity_PFX_Effect> xIt(Asura_ClientEntity_PFX_Effect::GetList());
			!xIt.Done();
			xIt.Next() )
		{
			Asura_ClientEntity_PFX_Effect* pxEffectEntity = xIt.GetCurrent();
			if (pxEffectEntity)
			{
				// Deactivate and stop the PFX immediately.
				pxEffectEntity->StopEffect(true);
			}
		}


		if (Asura_Network::IsServer())
		{
			// This message came from the server originally anyway and
			// the server has already changed gameflow state.
			return true;
		}
		else
		{
			if (pxData)
			{
				// Copy game settings to client.
				pxData->CopyToSettings();
			}

			// Clear out any recently destroyed guids. So that creation messages will be accepted.
			Asura_Entity_System::ResetRecentlyDestroyedSystem();

			Gun_MP_Scoring::Restart();

			if ((s_eGameflowState == AVP_GAMEFLOW_PLAYING || s_eGameflowState == AVP_GAMEFLOW_GAME_OVER) &&
				s_eGameFlowRequestedState != AVP_GAMEFLOW_RESTARTING)
			{
				// Playing the game and haven't requested restart yet.
				Log(AVP_GAME_LOG_FLAGS, L"Received restart msg");
				RequestState(AVP_GAMEFLOW_RESTARTING);
				return true;
			}
			else
			{
				return false;
			}
		}
	}
#else
	AVP_Core::RequestRestartLevel();

	Asura_Assert(false, "AVP_Client::ProcessRestartMessage(): Not yet implemented.");
	return(false);
#endif
}

/// End of function 'AVP_Client::ProcessRestartMessage'. ///


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ProcessRestartAtCheckPointMessage
// Author       : Chris Wallace
// Date         : 28-June-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ProcessRestartAtCheckPointMessage(const Asura_Message* pxMessage)
{
#if 0
	if (Gun_Settings::IsSinglePlayer())
	{
		Asura_Assert(0, "Restart message only allowed in MP games.");
		return(false);
	}
	else if (pxMessage->GetSentTime() < s_fTimeStamp_RestartMission)
	{
		Asura_Assert(false, "Messages out of order");
		return(false);
	}
	else
	{
		s_fTimeStamp_RestartMission = pxMessage->GetSentTime();

		const Gun_Message_Game_Restart* pxData = static_cast<const Gun_Message_Game_Restart*>(pxMessage->GetData());
		if (pxData)
		{
			Gun_ClientHuman_Player* const pxLocal = Gun_Game_Core::GetLocalPlayer();
			if (pxLocal)
			{
				//			const int iSpawnPoint = pxData->m_sSpawnPoint;
				//			pxLocal->Respawn(pxMessage->GetSentTime(), false, iSpawnPoint);			
			}
		}


		// Remove any ragdolls
		const Asura_Hashed_List<Gun_ClientEntity_Actor>* xListEntities = Gun_ClientEntity_Actor::GetList();
		Asura_Hashed_List_It<Gun_ClientEntity_Actor>	xIt(xListEntities);
		while(!xIt.Done())
		{
			Gun_ClientEntity_Actor* pxActor = static_cast<Gun_ClientEntity_Actor*>(xIt.GetCurrent());
			xIt.Next();

			//pxActor->RemoveRagdoll();
			pxActor->SetPlayingDeathAnim(false);
		}

		// Delete the ragdoll.
		//Asura_ClientEntity_Ragdoll * pxRagdollEntity = Asura_ClientEntity_Ragdoll::FindRagdollEntity(GetRagdollID());
		//if (pxRagdollEntity)
		//{
		//	delete pxRagdollEntity;
		//}

		/*
		const Asura_Hashed_List<Asura_ClientEntity_Ragdoll>* xListEntities = Asura_ClientEntity_Ragdoll::GetList();
		Asura_Hashed_List_It<Asura_ClientEntity_Ragdoll>	xIt(xListEntities);
		while(!xIt.Done())
		{
		Asura_ClientEntity_Ragdoll* pxRagdoll = static_cast<Asura_ClientEntity_Ragdoll*>(xIt.GetCurrent());
		xIt.Next();

		//pxActor->RemoveRagdoll();
		Asura_OutputToDebugger( ("Ragdoll %ld\n", pxRagdoll->GetGuid()) );
		}
		*/

		// Reset effects.
		Asura_Decal_System::Reset();

		// Reset any client PFX effect entities.
		// Some smoke/fire effects last a long time and need to be stopped quickly.
		for( Asura_Hashed_List_It<Asura_ClientEntity_PFX_Effect> xIt(Asura_ClientEntity_PFX_Effect::GetList());
			!xIt.Done();
			xIt.Next() )
		{
			Asura_ClientEntity_PFX_Effect* pxEffectEntity = xIt.GetCurrent();
			if (pxEffectEntity)
			{
				// Deactivate and stop the PFX immediately.
				pxEffectEntity->StopEffect(true);
			}
		}


		if (Asura_Network::IsServer())
		{
			// This message came from the server originally anyway and
			// the server has already changed gameflow state.
			return true;
		}
		else
		{
			if (pxData)
			{
				// Copy game settings to client.
				pxData->CopyToSettings();
			}

			// Clear out any recently destroyed guids. So that creation messages will be accepted.
			Asura_Entity_System::ResetRecentlyDestroyedSystem();

			Gun_MP_Scoring::Restart();

			if ((s_eGameflowState == AVP_GAMEFLOW_PLAYING || s_eGameflowState == AVP_GAMEFLOW_GAME_OVER) &&
				s_eGameFlowRequestedState != AVP_GAMEFLOW_RESTARTING)
			{
				// Playing the game and haven't requested restart yet.
				Log(AVP_GAME_LOG_FLAGS, L"Received restart msg");
				RequestState(AVP_GAMEFLOW_RESTARTING);
				return true;
			}
			else
			{
				return false;
			}
		}
	}
#else
	AVP_Core::RequestRestartAtCheckPoint();

	Asura_Assert(false, "AVP_Client::ProcessRestartAtCheckPointMessage(): Not yet implemented.");
	return(false);
#endif
}

/// End of function 'AVP_Client::ProcessRestartAtCheckPointMessage'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ProcessRotateMessage
// Author       : Andy Tate
// Date         : 16-Mar-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ProcessRotateMessage(const Asura_Message* pxMessage)
{
#if 0
	if (Gun_Settings::IsSinglePlayer())
	{
		Asura_Assert(0, "Rotate message only allowed in MP games.");
		return false;
	}
	else if (Asura_Network::IsServer())
	{
		Asura_Assert(0,"Rotate message ignored by server");
		return false;
	}
	else if (pxMessage->GetSentTime() < s_fTimeStamp_NextMission)
	{
		Asura_Assert(false, "Messages out of order");
		return false;
	}
	else
	{
		s_fTimeStamp_NextMission = pxMessage->GetSentTime();

		const Gun_Message_Game_Rotate* pxData = static_cast<const Gun_Message_Game_Rotate*>(pxMessage->GetData());
		if (pxData)
		{
			// Copy settings. Includes new map.
			pxData->CopyToSettings();
		}

		if (s_eGameflowState == AVP_GAMEFLOW_JOINING &&
			s_eGameFlowRequestedState != AVP_GAMEFLOW_ROTATING)
		{
			// Tried to join game whilst server was rotating.
			// Fix the problem by rotating to the new map...
			Asura_Assert(0, "Rotating to correct level!");
			s_bJoined = true; // Fake this to prevent an assert.
			RequestState(AVP_GAMEFLOW_ROTATING);
			return true;
		}
		else if (s_eGameflowState != AVP_GAMEFLOW_ROTATING &&
			s_eGameflowState != AVP_GAMEFLOW_DISCONNECTING &&
			s_eGameFlowRequestedState != AVP_GAMEFLOW_ROTATING)
		{
			Log(AVP_GAME_LOG_FLAGS, L"Received rotate message");
			RequestState(AVP_GAMEFLOW_ROTATING);
			return true;
		}
		else
		{
			return false;
		}
	}
#else
	Asura_Assert(false, "AVP_Client::ProcessRotateMessage(): Not yet implemented.");
	return(false);
#endif
}

/// End of function 'AVP_Client::ProcessRotateMessage'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ProcessGameOverMessage
// Author       : Steve Jones
// Date         : 22-Mar-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ProcessGameOverMessage(const Asura_Message* pxMessage)
{
	// put game into disconnection state handler
	AVP_Core::RequestGameOver();
	return(true);
}

/// End of function 'AVP_Client::ProcessGameOverMessage'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ApplyDamage
// Author       : Andy Tate
// Date         : 11-Jan-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ApplyDamage(const AVP_EntityDamage_ApplyToEnvironment& xDamage)
{
	const Asura_Hash_ID				uMaterialID	= xDamage.GetMaterialResponseHash();
	const Asura_MaterialResponse*	pxMaterial	= Asura_MaterialResponse_System::GetMaterialByHashID(uMaterialID);
		
	// AS 4/10/07 - Not sure if this is needed normally but it crashed due to NULL Material while playing with a dodgy export.
	// AJG - 21/11/08 - Yes, it is needed then.
	if(pxMaterial == NULL)
	{
		return(false);
	}
	else
	{
		// Just create using the surface effect system in this case.
		Asura_Vector_3	xPosition;
		Asura_Vector_3	xSurfaceNormal;

		xDamage.GetPointOfImpact(xPosition);
		xDamage.GetNormal(xSurfaceNormal);

		AVP_SurfaceEffect_System::PlayDamageSurfaceEffect(pxMaterial->GetSurfaceTypeHash(), xDamage.GetTypeHash(), xPosition, xSurfaceNormal);
		return true;
	}
}

/// End of function 'AVP_Client::ApplyDamage'. ///


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::ApplyDamage
// Author       : Andy Tate
// Date         : 11-Jan-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::ApplyDamage(const AVP_EntityDamage_ApplyRadialToBotanicals& xDamage)
{
#ifdef ASURA_USE_BOTANICALS
	Asura_BGR_Manager&		xManager	= Asura_BGR_Manager::GetBGRManager();
	Asura_Bounding_Box xBB;
	xBB.SetToPoint( xDamage.GetPosition() );
	xBB.Grow( xDamage.GetFarRange() );
	
	AVP_EntityDamage_RadialBotanicalCallback xCallback( xDamage );
	return ( xManager.ProcessArea(xCallback, xBB ) > 0 );
#else //ifdef ASURA_USE_BOTANICALS
	return false;
#endif //ifdef ASURA_USE_BOTANICALS
}
/// End of function 'AVP_Client::ApplyDamage'. ///


bool AVP_Client::ApplyDamage(const AVP_EntityDamage_ApplyLinearToBotanicals& xDamage)
{
#ifdef ASURA_USE_BOTANICALS
	Asura_BGR_Manager&		xManager	= Asura_BGR_Manager::GetBGRManager();
	Asura_Bounding_Box xBB;
	xBB.SetToPoint( xDamage.GetOrigin() );
	xBB.Set( xDamage.GetOrigin() + xDamage.GetDisplacement() );

	AVP_EntityDamage_LinearBotanicalCallback xCallback( xDamage );
	return ( xManager.ProcessArea(xCallback, xBB ) > 0 );
#else //ifdef ASURA_USE_BOTANICALS
	return false;
#endif //ifdef ASURA_USE_BOTANICALS
}

////////////////////////////////////////////////////////////////////////////////
// Public functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::MessageHandler
// Author       : Andy Tate
// Date         : 12-Jan-2007
////////////////////////////////////////////////////////////////////////////////

void AVP_Client::MessageHandler (const Asura_Message *pxMessage)
{
	switch(pxMessage->GetMsgID())
	{
		case AVP_MSGID_ENTITYDAMAGE_APPLY_TO_ENTITY:
		{
			const AVP_Message_EntityDamage_ApplyToEntity*	pxData	= static_cast<const AVP_Message_EntityDamage_ApplyToEntity*>( pxMessage->GetData());
			AVP_EntityDamage_ApplyToEntity					xDamage;

			pxData->GetDamage(xDamage);

			{
				const Asura_Guid		uGuidToDamage	= xDamage.GetHitGuid();
				Asura_Entity_Client*	pxClient		= Asura_Entity_Client::FindEntity(uGuidToDamage);

				if(pxClient == NULL)
				{
					Asura_Assertf(false, ("Unable to find client entity with GUID %d", uGuidToDamage));
				}
				else
				{
					pxClient->HandleMessage(pxMessage);
				}
			}

			break;
		}

		case AVP_MSGID_ENTITYDAMAGE_APPLYRADIAL_TO_BOTANICALS:
		{
			const AVP_Message_EntityDamage_ApplyRadialToBotanicals*	pxData	= static_cast<const AVP_Message_EntityDamage_ApplyRadialToBotanicals*>(pxMessage->GetData());
			AVP_EntityDamage_ApplyRadialToBotanicals				xDamage;

			pxData->GetDamage(xDamage);
			ApplyDamage(xDamage);
			break;
		}

		case AVP_MSGID_ENTITYDAMAGE_APPLYLINEAR_TO_BOTANICALS:
		{
			const AVP_Message_EntityDamage_ApplyLinearToBotanicals*	pxData	= static_cast<const AVP_Message_EntityDamage_ApplyLinearToBotanicals*>(pxMessage->GetData());
			AVP_EntityDamage_ApplyLinearToBotanicals				xDamage;

			pxData->GetDamage(xDamage);
			ApplyDamage(xDamage);
			break;
		}

		case AVP_MSGID_ENTITYDAMAGE_APPLY_TO_ENVIRONMENT:
		{
			const AVP_Message_EntityDamage_ApplyToEnvironment*	pxData	= static_cast<const AVP_Message_EntityDamage_ApplyToEnvironment*>(pxMessage->GetData());
			AVP_EntityDamage_ApplyToEnvironment					xDamage;

			pxData->GetDamage(xDamage);
			ApplyDamage(xDamage);
			break;
		}

		case AVP_MSGID_JOINGAME_RESPONSE:
		{
			ProcessJoinResponseMessage(pxMessage);
			break;
		}

		case AVP_MSGID_GAME_TERMINATED:
		{
			ProcessTerminationMessage(pxMessage);
			break;
		}

		case AVP_MSGID_GAME_RESTART:
		{
			ProcessRestartMessage(pxMessage);
			break;
		}

		case AVP_MSGID_GAME_ROTATE:
		{
			ProcessRotateMessage(pxMessage);
			break;
		}

		case AVP_MSGID_GAME_OVER:
		{
			ProcessGameOverMessage(pxMessage);
			break;
		}

		case AVP_MSGID_GAMESTATUS_FULLUPDATE:
		{
			AVP_GameStatus::HandleMessage(pxMessage);
			break;
		}

		case AVP_MSGID_INITIALISECOMPLETE:
		{
			AVP_Game_Core::SetReceivedInitialiseCompleteMessage(true);
			break;
		}

		case AVP_MSGID_START_CAMERA_SHAKE:
		{
			const AVP_Msg_CameraShake* pxData = static_cast<const AVP_Msg_CameraShake*>(pxMessage->GetData());
			if (pxData)
			{
				AVP_CameraShake_System::StartShake( pxData->m_uShake, pxData->m_uSourceGuid );
			}
			break;
		}

		case AVP_MSGID_STOP_CAMERA_SHAKE:
		{
			const AVP_Msg_CameraShake* pxData = static_cast<const AVP_Msg_CameraShake*>(pxMessage->GetData());
			if (pxData)
			{
				AVP_CameraShake_System::StopShake( pxData->m_uSourceGuid );
			}
			break;
		}

		default:
		{
			Asura_Assert(false, "Unexpected message sent to the client-machine.");
			break;
		}
	}		// End of switch.
}

/// End of function 'AVP_Client::MessageHandler'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Client::SendJoinRequestMessage
// Author       : Andy Tate
// Date         : 16-Mar-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_Client::SendJoinRequestMessage(void)
{
#if 0
	// request to join this server's game. TODO: send file checksums etc

	// first u_char contains the number of players. Then there is a struct for each of those players.
	// KOR - 1 local player
	const u_int uNumLocalPlayers = 1 /* Gun_Settings::GetNumberOfLocalPlayers()); */;
	u_int uDataSize = sizeof(u_char) + (sizeof(Gun_Msg_Player_JoinRequest_Data) * uNumLocalPlayers);

	Asura_Message* pxRequest = Asura_Network::CreateMessage(AVP_MSG_JOINGAME_REQUEST, uDataSize);

	if (!pxRequest)
	{
		return false;
	}

	s_bJoinTheGameAccepted = false;
	s_bJoinTheGameRefused = false;

	Log(AVP_GAME_LOG_FLAGS, L"Sending join request");

	u_char* pucData = static_cast<u_char*>(pxRequest->GetData());

#if defined ASURA_ASSERT
	u_char* pucStartOfData = pucData;
#endif

	*pucData = static_cast<u_char>(uNumLocalPlayers);
	pucData++;

	//	for(u_int uPlayer = 0; uPlayer < uNumLocalPlayers; ++uPlayer)
	{
		Gun_PlayerProfile const*	pxPlayerProfile	= Gun_Settings::GetPlayerProfile (0);
		// NY - 03 July 2006 - this was trying to use the MP skin regardless of if we were in MP or not. eep!
		AVP_CHARACTER_SKIN eSkin = Gun_ServerHuman_Player::GetColtonSkinEnum();
		if (Gun_Settings::IsMultiplayer())
		{
			eSkin = Gun_SkinNames::GetMultiplayerSkinEnum(pxPlayerProfile->GetMPSkin());
		}

		Gun_Msg_Player_JoinRequest_Data xPlayerData;
		xPlayerData.m_ucSkin = static_cast<u_char>(eSkin);
		xPlayerData.m_ucLevel = static_cast<u_char>(Gun_Settings::GetLevel());

		Gun_ClientHuman_Player* pxPlayer = Gun_Game_Core::GetLocalPlayer();

		if(pxPlayer)
		{
			xPlayerData.m_uGuid = pxPlayer->GetGuid();

			if(!Platform_SetPlayerName(0, xPlayerData))
			{
				if(pxPlayerProfile)
				{
					Asura_PrintfToBfr(xPlayerData.m_wszPlayerName, L"%ls", uAVP_PLAYER_NAME_MAX_CHARS, true, pxPlayerProfile->GetProfileName());
				}
				else
				{
					xPlayerData.m_wszPlayerName[0] = 0;
				}
			}
		}
		else
		{
			Asura_Assert(false, "Can't get client actor");
			xPlayerData.m_uGuid = ASURA_GUID_UNREGISTERED;
		}
		memcpy(pucData, &xPlayerData, sizeof(Gun_Msg_Player_JoinRequest_Data));
		pucData += sizeof(Gun_Msg_Player_JoinRequest_Data);
	}

	Asura_Assert((pucStartOfData + uDataSize) == pucData, "Data sizes don't match");

	pxRequest->From = Gun_Game_Core::GetLocalPlayer()->GetGuid();
	pxRequest->To   = ASURA_GUID_SERVER;
	pxRequest->UseGuaranteedDelivery();
	Asura_Network::Send(pxRequest);

	return true;
#else
	Asura_Assert(false, "AVP_Client::SendJoinRequestMessage(): Not yet implemented.");
	return(false);
#endif
}

/// End of function 'AVP_Client::SendJoinRequestMessage'. ///


/// End of file. ///
