void HumanClientApp::HandleMessage(Message& msg) {
    if (INSTRUMENT_MESSAGE_HANDLING)
        std::cerr << "HumanClientApp::HandleMessage(" << msg.Type() << ")\n";

    switch (msg.Type()) {
    case Message::ERROR_MSG:            m_fsm->process_event(Error(msg));                   break;
    case Message::HOST_MP_GAME:         m_fsm->process_event(HostMPGame(msg));              break;
    case Message::HOST_SP_GAME:         m_fsm->process_event(HostSPGame(msg));              break;
    case Message::JOIN_GAME:            m_fsm->process_event(JoinGame(msg));                break;
    case Message::HOST_ID:              m_fsm->process_event(HostID(msg));                  break;
    case Message::LOBBY_UPDATE:         m_fsm->process_event(LobbyUpdate(msg));             break;
    case Message::LOBBY_CHAT:           m_fsm->process_event(LobbyChat(msg));               break;
    case Message::SAVE_GAME:            m_fsm->process_event(::SaveGame(msg));              break;
    case Message::GAME_START:           m_fsm->process_event(GameStart(msg));               break;
    case Message::TURN_UPDATE:          m_fsm->process_event(TurnUpdate(msg));              break;
    case Message::TURN_PARTIAL_UPDATE:  m_fsm->process_event(TurnPartialUpdate(msg));       break;
    case Message::TURN_PROGRESS:        m_fsm->process_event(TurnProgress(msg));            break;
    case Message::PLAYER_STATUS:        m_fsm->process_event(::PlayerStatus(msg));          break;
    case Message::PLAYER_CHAT:          m_fsm->process_event(PlayerChat(msg));              break;
    case Message::DIPLOMACY:            m_fsm->process_event(Diplomacy(msg));               break;
    case Message::DIPLOMATIC_STATUS:    m_fsm->process_event(DiplomaticStatusUpdate(msg));  break;
    case Message::VICTORY_DEFEAT :      m_fsm->process_event(VictoryDefeat(msg));           break;
    case Message::PLAYER_ELIMINATED:    m_fsm->process_event(PlayerEliminated(msg));        break;
    case Message::END_GAME:             m_fsm->process_event(::EndGame(msg));               break;
    default:
        ErrorLogger() << "HumanClientApp::HandleMessage : Received an unknown message type \""
                               << msg.Type() << "\".";
    }
}
void ServerArena::Update(GLib::Input* pInput, float dt)
{
	if(!IsGameStarted())
		return;
	
	mDamageCounter += dt;

	for(int i = 0; i < mPlayerList.size(); i++) 
	{
		if(mPlayerList[i]->GetEliminated())
			continue;

		// Deal damage to players outside the arena.
		if(mDamageCounter > 0.1f)
		{
			XMFLOAT3 pos = mPlayerList[i]->GetPosition();
			float distFromCenter = sqrt(pos.x * pos.x + pos.z * pos.z);

			// Arena is 60 units in radius.
			if(distFromCenter > mArenaRadius) {
				mPlayerList[i]->TakeDamage(mServer->GetCvarValue(Cvars::LAVA_DMG) * (1 - mPlayerList[i]->GetLavaImmunity()));

				// Set slow movement speed.
				mPlayerList[i]->SetSlow(mServer->GetCvarValue(Cvars::LAVA_SLOW));
			}
			else {
				// Restore movement speed.
				mPlayerList[i]->SetSlow(0.0f);
			}
		}
		
		// Player dead?
		if(mPlayerList[i]->GetCurrentHealth() <= 0 && mPlayerList[i]->GetCurrentAnimation() != 7) {
			static int cc = 0;
			cc++;
			if(cc == 1)
				int a = 1;

			mPlayerList[i]->SetDeathAnimation();
			PlayerEliminated(mPlayerList[i], mPlayerList[i]->GetLastHitter());
		}
	}

	mWorld->Update(dt);

	if(mDamageCounter > 0.1f)
		mDamageCounter = 0.0f;

	// Broadcast the world at a fixed rate.
	mTickCounter += dt;
	if(mTickCounter > mTickRate) {
		// Find out if there is only 1 player alive (round ended).
		string winner;
		if(mServer->IsRoundOver(winner))
		{
			mServer->AddRoundCompleted();

			RemoveStatusEffects();

			for(int i = 0; i < mPlayerList.size(); i++)
				mPlayerList[i]->SetGold(mPlayerList[i]->GetGold() + mServer->GetCvarValue(Cvars::GOLD_PER_ROUND));

			// Add extra gold to the winner.
			Player* winningPlayer = (Player*)mWorld->GetObjectByName(winner);
			winningPlayer->SetGold(winningPlayer->GetGold() + mServer->GetCvarValue(Cvars::GOLD_PER_WIN));

			RakNet::BitStream bitstream;
			if(mServer->IsGameOver())
				bitstream.Write((unsigned char)NMSG_GAME_OVER);
			else 
				bitstream.Write((unsigned char)NMSG_ROUND_ENDED);

			bitstream.Write(winner.c_str());
			mServer->SendClientMessage(bitstream);

			// Increment winners score.
			mServer->AddScore(winner, 1);

			gConsole->AddLine(winner + " wins the round!");
		}

		BroadcastWorld();
		mServer->GetRoundHandler()->BroadcastStateTimer();
		mTickCounter = 0.0f;
	}

	// Update lava.
	mFloodDelta += dt;

	if(mFloodDelta >= mServer->GetCvarValue(Cvars::FLOOD_INTERVAL))
	{
		mArenaFloodStartRadius = mArenaRadius;
		mFloodDelta = -5;

		// Send NMSG_FLOOD_START message.
		RakNet::BitStream bitstream;
		bitstream.Write((unsigned char)NMSG_FLOOD_START);
		mServer->SendClientMessage(bitstream);

		gConsole->AddLine("Lava flood started!");
	}
	else if(mFloodDelta < 0)
	{
		float floadSize = mServer->GetCvarValue(Cvars::FLOOD_SIZE);
		mArenaRadius = mArenaFloodStartRadius - floadSize * (1 - (-mFloodDelta / 5));
		GLib::Effects::TerrainFX->SetArenaRadius(mArenaRadius);

		// Send NMSG_ARENA_RADIUS message.
		RakNet::BitStream bitstream;
		bitstream.Write((unsigned char)NMSG_ARENA_RADIUS);
		bitstream.Write(mArenaRadius);
		mServer->SendClientMessage(bitstream);
	}
}