#pragma once

#include "MW4.hpp"
#include <Adept\Application.hpp>
#include <Stuff\Scalar.hpp>

// ngLog addition
#include "MechLabHeaders.h"
#include "InputTrainer.hpp"
#include "MemoryDiffKiller.hpp"

#define MAX_LANCEMATES 16

namespace NetMissionParameters
{
	class TeamParameters
	{
	public:
		int m_maxPlayersOnTeam;
		int m_minimumTonnage;
		int m_maximumTonnage;
		int m_maximumTotalTonnage;
		Stuff::Scalar m_currentTotalTonnage;
		int m_skin;
		int m_alignment;

		DWORD m_allowedMech[2];
		DWORD m_allowedBeam[2];
		DWORD m_allowedMissile[2];
		DWORD m_allowedProjectile[2];
		DWORD m_allowedSubsystem[2];

		TeamParameters();
		void ResetParameters(int index);
		void SaveParameters(Stuff::DynamicMemoryStream *stream);
		void LoadParameters(Stuff::MemoryStream *stream);
		void SaveParameters(Stuff::NotationFile *notefile);
		void LoadParameters(Stuff::NotationFile *notefile);

	};

	class MWNetMissionParameters:
		public AdeptNetMissionParameters
	{
	public:

		int m_joinInProgress;
		int m_joinInProgressCutOff;
		int m_joinInProgressCutOffTime;

		int m_heatOn;
		int m_killLimit;
		int m_killLimitNumber;
		int m_respawnLimit;
		int m_respawnLimitNumber;
		int m_forceRespawn;
		int m_splashOn;
		int m_weaponjamOn;
		int m_ammobayfireOn;
// MSL 5.05 Advance Mode
		int m_advancemodeOn;
// MSL 5.06 Armor Mode
		int m_armormodeOn;
		int m_splashPercentage;
		int m_unlimitedAmmo;
		int m_friendlyFirePercentage;
		int m_allowZoom;
		int m_allow3rdPerson;
		int m_allowAutoAim;
		int m_allowDeadToChat;
		int m_invulnerableDrop;
		int m_isNight;

		
		int m_weather;
		int m_reportStats;
		int m_serverConnection;
		int m_serverBandwidth;

		int m_radarMode;

		int m_onlyStockMech;
		int m_minimumTonnage;
		int m_maximumTonnage;

		int m_gameLength;
		int m_serverRecycle;
		int m_recycleDelay;
		int m_playMissionReview;

		int m_ruleType;
		int m_deadMechCantSee;
		int m_deadMechCantSeeOtherTeam;

		int m_allowdecaltransfer;
		int m_useMapCycle;
		int m_pureMapCycle;

		


		DWORD m_allowedMech[2];
		DWORD m_allowedBeam[2];
		DWORD m_allowedMissile[2];
		DWORD m_allowedProjectile[2];
		DWORD m_allowedSubsystem[2];

		// there are always 8 teams,
		// but sometimes a team won't allow players
		int m_teamAllowed;
		int m_teamCount;
		TeamParameters m_teamParams[8];

		int m_maxPlayers;
		int m_maxBots;
		int m_mapID;
		char m_mapName[128];
		char m_scenarioName[128];
		char m_scenarioPath[128];
		char m_serverName[256];
		char m_serverIP[256];
		char m_serverCPU[256];
		char m_scriptName[256];
		char m_scenarioText[1024];

		__int64 m_mapClientCRC;

		MWNetMissionParameters();

		void ResetParameters(void);
		void SaveParameters(Stuff::DynamicMemoryStream *stream);
		void LoadParameters(Stuff::MemoryStream *stream);
		void SaveParameters(Stuff::NotationFile *notefile);
		void LoadParameters(Stuff::NotationFile *notefile);
		void LoadOverideParameters(Stuff::NotationFile *notefile);
		void SaveServerParameters(NotationFile *notefile);

	};
};



namespace MechWarrior4
{
	class MWObject;
	class MWPlayer;
	class Team;
	class MWTable;
	class MWOptions;
	class Mech;
	class MissionReview;

	const char DefaultSkinPrefix=static_cast<char>('_');
	
	enum { Maximum_Lancemates = MAX_LANCEMATES };


    struct SWeaponInfo
    {
        Stuff::Scalar m_HudEffect;
    };
    extern SWeaponInfo g_aWIs[];

	//##########################################################################
	//#########################    HermitEntry    ##############################
	//##########################################################################

	class HermitEntry
	{
	public:
		HermitEntry(short file_id, WORD record_id, const Stuff::Point3D& position, const Stuff::YawPitchRoll& rotation)
			: m_rotation(rotation)
			, m_position(position)
		{
			m_fileID = file_id;
			m_recordID = record_id;
		};

		HermitEntry()
		{
			m_fileID = 0;
			m_recordID = 0;
			m_rotation = Stuff::YawPitchRoll::Identity;
			m_position = Stuff::Point3D::Identity;
		};

		short m_fileID;
		WORD m_recordID;
		Stuff::Point3D m_position;
		Stuff::YawPitchRoll m_rotation;
	};

	//##########################################################################
	//#########################    DecalEntry    ##############################
	//##########################################################################



	class DecalEntry:
		public Stuff::Plug
	{
	public:

		int refCount;
		int index;
		Stuff::MString decalName;

		DecalEntry():
			Stuff::Plug(DefaultData)
		{
			refCount = 0;
		}
	};


	//##########################################################################
	//#########################    ServedConnectionData    #####################
	//##########################################################################

	class ServedConnectionData
	{
	public:



		// ip
		// dplay id
		

		bool
			clientConnected,	    // they are connected to the server
			clientVehicleAccepted,	// they have a vehicle choosen and accepted
			clientReady,			// they are ready to load
			clientLaunched,			// they have been sent the load command
			clientLoaded,			// they are done with the load command
			clientReadyForPrerender,// they are ready to preload
			clientSentScoreFormat,	// if they have recieved the score format
			clientAllowTransfer,	// if the client allows transfers of decals
			clientSquelched,		// if the client is squelched
			clientStreamingReview,  // if the client is getting a mission review log
			clientQuedForLaunch,    // if the client is ready to be launched
			clientQuedForKick;
		
		bool
			waitingForClientShutdownConfirmation;


		int
			pilotTeam,				// the team the pilot is on
			pilotDecals,			// the index of their pilot decal
			teamDecals,				// the index of their team decal
			mechChasisID,			// what mech they are in
			nextReviewPacket;		// which mission review packet they have received last

		char
			pilotSkins;				// the skin prefix

		Stuff::Point3D
			vehiclePosition;		// the last position of their vehicle
		Stuff::YawPitchRange
			vehicleRotation;		// the last rotation of their vehicle

		Adept::ResourceFile*
			clientCustomResource;	// the pointer to their custom mech resource
		bool
			customResourceCRCFail; // the resource didn't pass the hash test.  bad little hacker.

		Stuff::MemoryStream
			*vehicleCreateMessage;  // the creation message of their vehicle
		
		MWPlayer*
			clientPlayer;			// pointer to their player object
		const char *
			pilotName;				// the players name

		char *
			clanName;	

		// connection status
		Stuff::Scalar
			effectivePing;			// thier effective ping taking into account frame rates
		

		AverageOf<Stuff::Scalar>
			averagePing;

		int
			clientConnectionRate,	// their reported connection rate
			clientConnectionType,   // their reported connection type
			packetLoss;				// not used yet

		int 
			bandwidthThrottle;
		Scalar
			timeSinceLastThrottleTest;


		Stuff::AverageOf<Stuff::Scalar>
			chatTimeLog;			// time total of last 20 chats used for overflow
		Stuff::Time
			lastChat;				// the last chat time

		ServedConnectionData();
		~ServedConnectionData();

		void Recycle();
		void Disconnect();

		GUID
			clientKey;				// unique client key
		DWORD
			clientISP;				// clients c-class ip address uses this mask 0xffffff00


#if !defined(NO_LOG)
		// ngLog additions
		// Need to make the sizes hardcoded to account for
		// non-weapon damage given/received (like Ramming).
		// Assuming # of weapons will be < 200 during the entire
		// making of the game, so I shove all non-bound weapon
		// stuff above 200.
		enum {
			NumWeaponsTracked=221
		};

		int
			stats_update;					// Stats update flag (for logging)

		int
			wep_atts[NumWeaponsTracked],	// # of shot attempts for a particular damage type.
			wep_hits[NumWeaponsTracked];	// # of hits for a particular damage type.

		float
			dmg_given[NumWeaponsTracked],	// Amount of damage given per client
			dmg_rcvd[NumWeaponsTracked];	// Amount of damage received per client

		float
			pdmg_given[Adept::Maximum_Players+Maximum_Lancemates],	// Damage given to another player
			pdmg_rcvd[Adept::Maximum_Players+Maximum_Lancemates];	// Damage received from another player

		int
			comp_inf[Adept::Maximum_Players+Maximum_Lancemates],	// # of inflicted internal components that have been destroyed
			comp_rcv[Adept::Maximum_Players+Maximum_Lancemates];	// # of received internal components that have been destroyed

		GUID
			ngLogID;				// Client name/password hash
#endif // !defined(NO_LOG)

		Stuff::Scalar tonnage;
	public: // jcem
        Mech* GetMech() const;
        ReplicatorID GetReplicatorID() const;
	};


	//##########################################################################
	//#########################    ServedConnectionData    #####################
	//##########################################################################


	// bots and lancemates...
	class LancemateConnectionData
	{
	public:
		
		LancemateConnectionData();
		~LancemateConnectionData();
		void Recycle();
		void Disconnect();

		// all this stuff is transmitted at differing times...
		Stuff::MemoryStream
			*lancemateCreateMessage;
		Adept::ResourceFile*
			lancemateCustomResource;
		bool
			customResourceCRCFail;

		Mech *lancemateMech;

		char lancemateName[256];
		char lancemateClan[256];
		bool lancemateConnected;
		bool lancemateVehicleAccepted;
		bool buildName;
		int pilotTeam;
		int	mechChasisID;

		
		// used by server, never transmitted by wire...
		char scriptName[256];
		Adept::ResourceID aiModel;
		int pilotSkill;
		int gunnerySkill;
		int eliteSkill;
		int minHeatSkill;
		int maxheatSkill;
		int sensorSkill;
		int blindFightSkill;
		int longRangeGunSkill;
		int shortRangeGunSkill;
		Adept::ObjectID dropZone;

#if !defined(NO_LOG)
		// ngLog additions
		// Need to make the sizes hardcoded to account for
		// non-weapon damage given/received (like Ramming).
		// Assuming # of weapons will be < 200 during the entire
		// making of the game, so I shove all non-bound weapon
		// stuff above 200.
		enum {
			NumWeaponsTracked=221
		};

		int
			stats_update;					// Stats update flag (for logging)

		int
			wep_atts[NumWeaponsTracked],	// # of shot attempts for a particular damage type.
			wep_hits[NumWeaponsTracked];	// # of hits for a particular damage type.

		float
			dmg_given[NumWeaponsTracked],	// Amount of damage given per client
			dmg_rcvd[NumWeaponsTracked];	// Amount of damage received per client

		float
			pdmg_given[Adept::Maximum_Players+Maximum_Lancemates],	// Damage given to another player
			pdmg_rcvd[Adept::Maximum_Players+Maximum_Lancemates];	// Damage received from another player

		int
			comp_inf[Adept::Maximum_Players+Maximum_Lancemates],	// # of inflicted internal components that have been destroyed
			comp_rcv[Adept::Maximum_Players+Maximum_Lancemates];	// # of received internal components that have been destroyed
#endif // !defined(NO_LOG)

		Stuff::Scalar tonnage;
	public: // jcem
        Mech* GetMech() const;
        ReplicatorID GetReplicatorID() const;
	};


	//##########################################################################
	//########################    MWApplication    #############################
	//##########################################################################

	

	const int ResourceIDType=static_cast<int>(0);
	const int ResourceStreamType=static_cast<int>(1);
	const int CreationMessageType=static_cast<int>(2);

    class SMechInfo;
    typedef SMechInfo* PMechInfo;
    class SMechInfo : public ReplicatorID
    {
    public:
        Mech* m_pMech;
        const char* m_pcszName;
        bool m_bBOT;
        int m_nTeam;
    public:
        void SetInfo(Mech* pMech, const char* pcszName, bool bBOT, int nTeam);
    };

    class MWApplication;
    #define MAX_TEAMORDER_COUNT         10
    struct STeamOrderCommand;
    typedef STeamOrderCommand* PTeamOrderCommand;
    struct STeamOrderCommand
    {
    public:
        int m_nType; // -1 - to player, 0 - invalid, 0 < : bot & count...
        Stuff::Time m_fArrived;
        WORD m_waBots[16]; // bots to be ordered
        int m_nFrom; // from...
	    int m_nMsgIndex;
        ReplicatorID m_Target;
    };
    struct STeamOrderCommandArray
    {
    public:
        int m_nCurTOC;
        int m_nMaxTOC;
        STeamOrderCommand m_aTOCs[MAX_TEAMORDER_COUNT];
    public:
        void ClearTOC();
        STeamOrderCommand& DoReserveTOC(int nType, int nFrom, int nMsgIndex);
        int NormalizeIndex(int nIndex) const;
        STeamOrderCommand& GetTOC(int nIndex) const;
        void CopyTOC(int nDest, int nSrc);
        void DoTOC(MWApplication& app);
        void DoRemoveTOCs(int connection);
        void AdvanceHead();
    };

	class MWApplication:
		public Adept::Application
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();
/*
		static void __stdcall MW4GetFileForGOS(
			const char* filename,
			BYTE** memory,
			DWORD* size
		);

		static bool __stdcall MW4FindFileForGOS(const char* filename);
*/
		static bool __stdcall TranslateMissionNameIfNecessary(Stuff::MString & res_name);
		static bool __stdcall TranslateMissionNameBackIfNecessary(Stuff::MString & res_name);
		
		static MWApplication*
			GetInstance()
		{
			return reinterpret_cast<MWApplication *>( GlobalPointers::GetGlobalPointer(ApplicationGlobalPointerIndex));
		};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction

	public:
		MWApplication(ClassData *class_data,
					  bool display_gui);
		~MWApplication();

		void
			Initialize();
		void
			Terminate();

		void
			TestInstance() const;

	//--------------------------------------------------------------------------
	// Flood Prevention and message senders
	public:
		Stuff::Time
			timeFromLastParameterSend;
		Stuff::Time
			timeFromLastLobbyStatus;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// auto recycle support

	public:
		Stuff::Time recycleStartTime;
		bool recycleTimerOn;
	

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Localization Support
	public:
		char *
			GetLocString(int index);

		DWORD
			langResources;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Lookup table support
	public:
		void
			LoadLookupTables();

		MWTable
			*m_mechTable;
		MWTable
			*m_subsystemTable;
		MWTable
			*m_mechChassisTable;
		MWTable
			*m_weaponsTable;
		MWTable
			*m_skinsTable;
		MWTable
			*m_missionsRenameTable;
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Options Support
	public:
		void
			InitializeOptions(MWOptions *new_options);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Pilot support
	public:
		Stuff::MString
			m_currentMissionName;
		int
			m_currentMissionStatus;

		Stuff::MString
			m_pilotName;
		int
			m_lastMissionKills,
			m_lastMissionDeaths;
		bool
			m_campaignIsComplete;

		bool
			m_isMasterTrial;

		int
			m_lastMechID;
		Stuff::MString
			m_lastMechName;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Gui Support
	public:
		bool
			DisplayGUI() const;

	private:
		const bool m_DisplayGUI;

	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//	Adept Message support
	public:
		void
			PauseGameMessageHandler(const Adept::ReceiverDataMessageOf<int> *message);
		
		virtual void
			EnterStoppingGameState(void* data);
		virtual void
			EnterRunningGameState(void* data);
		virtual void
			EnterPreRenderState(void* data);
		virtual void
			EnterLoadingGameState(void* data);
		virtual void
			EnterRecyclingGameState(void* data);
		

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Startup/Run/Shutdown support

	public:
		static void _stdcall
			DoShellLogic();

		static void _stdcall
			StartUpDoShellLogic();

		static void _stdcall
			DoGameLogic();
		
		static void _stdcall UpdateDisplay();

		bool
			GetMechResourceID(int player_id, Adept::ResourceID &vehicle_id, Stuff::MemoryStream *message);

		virtual Adept::Entity::CreateMessage *
			MakePlayerCreationMessage(int player_id);

		virtual Adept::Entity::CreateMessage *
			MakeLancemateCreationMessage(int lancemate_index);

		void
			ConstructEgg(
				const char* contents_file
			);

		void
			StartGame();
		
		void
			StartNetGame();

		void
			StartCampaignGame();
		
		void
			StopGame();

		void
			LaunchGame();

		void
			LogPlayerConnect(int i);

		void
			LogBotConnect(void);


		void
			LaunchPlayer(int connection);
		
		void
			BroadcastAddNewPlayer(int connection_id);
		
		void
			InitializeInstantAction();
		void
			InitializeCampaignGame();
		void
			InitializeWaveGame(int waves, int bots, int lancemates, int player_lives);
		void
			InitializeTrainingMission();

		void
			QueRespawnPlayer()
				{Check_Object(this); quedPlayerRespawn = true;}
		void
			UnQuePlayerRespawn()
				{Check_Object(this); quedPlayerRespawn = false;}

		bool
			QuedForPlayerRespawn()
				{Check_Object(this); return quedPlayerRespawn;}


		void
			QueStopGame(bool no_recycle = false)
				{Check_Object(this); quedStop = true; noRecycle = no_recycle;}

		

	protected:

		bool
			quedPlayerRespawn;
		bool
			noRecycle;

	public:
		static char
			*GameFile;

		static char
			*NetGameName;

		static char
			*NetPlayerName;

		static char
			*NetPassword;

		static bool
			SaveGameStats,
			DemoMode,
			AutoLaunchServerGame,
			AutoLaunchClientGame,
			RunFromLobby,
			SecureNetGame,
			DplayNetGame,
			Win32DedicatedServer;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  alignment 
		
	public:
		enum AlignmentSchema
		{
			SINGLE_PLAYER,
			MP_NON_TEAMPLAY,
			MP_TEAMPLAY
		};

		static AlignmentSchema GetAlignmentSchema();


#ifdef LAB_ONLY
		static bool
			ReKeyResources;
#endif

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  Animation load support
	public:
		
		Stuff::ChainOf<MWObject*>
			animationScriptsLoadQue;
		
		void AddToAnimationLoadQue(MWObject *object)
		{
			animationScriptsLoadQue.Add(object);
		}

		void MWApplication::LoadAnimations();



	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  Dynamic decal support

		enum 
		{
			MaxDecalSize = 5120
		};

		const char*
			GetDecalName(int decal_index);

		Stuff::SortedChainOf<DecalEntry*, int>
			decalNames;

		int
			AddDecal(const char *decal);

		void
			AddDecal(const char *decal, int index);

		DecalEntry*
			FindDecal(const char *decal);

		void
			RemoveDecal(int decal_index);
		
		bool
			IsDecalOnDisk(const char *decal);

		bool
			IsStockDecalOnDisk(const char *decal);

		void
			SendDecalQuery(int connection);


		int
			AllowDecalTransfer;
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Network Support

		void
			ConnectClient(int connection,Adept::Connection *con);

		void
			DisconnectClient(int connection,Adept::Connection *con);

		void
			RecycleNetworking();

		void
			StopNetworking();

		void
			ConnectServer();

		bool
			CullWhackedMessages(int connection, int message_type);

		void
			ReceiveDirectMessage(int connection, int message_type, Stuff::MemoryStream *message);

		void
			RunTimeOuts();


		bool validDrop;

		bool
			CheckValidDrop(Point3D position);

		static void CollisionCallBack(Adept::Entity *entity, Adept::Entity *original_caller, const Stuff::Sphere &sphere);

		static int
				MoveItAndShakeIt;

		MemoryDiffKiller 
			memoryDiffKiller;



	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Single Player Game Support
	public:
		enum{
			DefaultGameType = 0,
			WaveBattleGameType
		};

		enum{
			LanceConnectionStart = 0,
			BotConnectionStart = 3
		};

		enum{
			MaxWaveLanceCount = 3,
			MaxWaveBotCount = 4
		};

	int
		m_iaDisplayGameType;
	int
		m_iaGameType;
	int
		m_numberOfWaves;
	int
		m_numberOfCompletedWaves;
	int
		m_numberOfEnemiesPerWave;
	int
		m_numberOfLancematesPerWave;
	int
		m_numberQuedLancemates;
	int
		m_numberQuedBots;
	int 
		m_lancemateRespawnQueue[MaxWaveLanceCount];
	int
		m_botRespawnQueue[MaxWaveBotCount];

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Direct Network Message Support

		// for the most part these are in the order that they will be received.
		// apart from score, respawn and chat messages which will be received many
		// times during the game.
	public:
		enum {
			RequestConnectionMessageID = Adept::Network::FirstDirectApplicationMessageID,	// client asks to join the game - this is pre-game lobby join and CRC's
			DenyRequestConnectionMessageID,											// server tells the client it is out of date and it must now piss off.
			AcceptConnectionMessageID,												// server tells the client he may join and gives him any info he may need, like player authentication, cookies, xor codes game numbers and such.
			LoadGameMessageID,														// tells the client to load the mission
			LoadPersitantHermitObjectsID,											// tells the client to load non updated entites (hermits) that were not created at the start of the game, but created as side effects.
			AddPlayerMessageID,														// adds a player and his vehicle
			RemovePlayerMessageID,													// removes a player and his vehicle
			RequestPlayerVehicleMessageID,											// client sends vehicle to be accepted or denied
			AcceptPlayerVehicleMessageID,											// server replies yes request is valid
			DenyPlayerVehicleMessageID,												// server replies no request is denied
			AddLancemateMessageID,													// adds a lancemate
			ReadyToLaunchMessageID,													// client tells server it is ready to launch
			ClientLoadedMessageID,													// client tells server that the mission/map/vehicle is loaded
			RunGameMessageID,														// tells the client to start running state
			ScoreMessageID,															// current score and mission parameters
			RequestRespawnMessageID,												// player requests to be respawned
			RespawnMessageID,														// player is respawned
			ChatMessageID,															// chat message
			StopMissionMessageID,													// tells the client the mission is over
			PlayerLeavingMessageID,													// tells the server that the client is going to the shell,
			RequestMissionParameterMessageID,										// request the mission parameters
			MissionParameterMessageID,												// the mission parameters
			ScoreFormatMessageID,													// this is the format of the buckets
			RequestMapInfoMessageID,												// this request info on the map
			MapInfoMessageID,														// this is the maps info file
			SwitchToCameraMessageID,												// this switches the player to a camera
			DecalLayoutMessageID,													// asks if the client has decals
			RequestDecalsMessageID,													// request transfer of decal
			DecalPayLoadMessageID,													// transfer message of decal
			AddTeamMessageID,														// add a team
			LobbyStatusMessageID,													// server is telling clients what each players status is ( ready, mech chasis, team )
			RequestTeamMessageID,													// client is requsting a team
			RequestPreRenderMessageID,												// requests a preload message
			PreRenderMessageID,														// gives a preload message, includes drop
			MissionReviewAvailableMessageID,										// tells the client the server has a review to watch
			RequestMissionReviewMessageID,											// asks for the last review
			CancelMissionReviewMessageID,											// asks to stop receiving the review
			MissionReviewPartMessageID,												// a piece of the review
			RespawnFlagsMessageID,													// respawn all flags
			PlayerClanMessageID,													// the player clans
			RespawnLancemateMessageID,												// respawn a lancemate
			UnreadyLaunchMessageID,													// unreadies the launch button
			StopMissionConfirmationMessageID,										// from clients to confirm shutdown
			RequestNewDictionaryMessageID,											// client is confused and would like a new dictionary
			KickPlayerMessageID,													// kick the client from the game
			TeamBettyMessageID,														// for special team Betty sounds
			StartMusicMessageID,													// for allowing the host to start music on the clients
			TeamSetNavMessageID,													// for setting team nav points
			RequestScoreFormatMessageID,											// request the score format
			RespawnMissionMessageID,												// respawn the map
			RespawnIndexMessageID,													// sends the respawn counts of players and lancemates
            // team order
            TeamOrderMessageID,
            svrTeamOrderMessageID,
            RepTeamOrderMessageID,
            svrRepTeamOrderMessageID,
            // team order
			LastMessageID
		};


		enum {
			ServerAllowedRule = 0,
			ClientAllowedRule,
			WaitingForGameAllowedRule,
			LoadingGameAllowedRule,
			PreRenderAllowedRule,
			RunningGameAllowedRule,
			StoppingGameAllowedRule,
			RecycleGameAllowedRule,
			AllowedRuleCount
		};


		static int MessageRules[LastMessageID-Adept::Network::FirstDirectApplicationMessageID][AllowedRuleCount];

		
		enum {
			ServerResolution = 0,
			ClientResolution
		};
		
		enum {
			SilentResolution = 0,
			WarnResolution,
			ShellClientResolution
		};


		static int MessageResolution[LastMessageID-Adept::Network::FirstDirectApplicationMessageID][2];


		void
			RequestConnectionMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			DenyRequestConnectionMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			AcceptConnectionMessageHandler(int connection, Stuff::MemoryStream *message);
		virtual void
			LoadGameMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			LoadPersitantHermitObjectsMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			AddPlayerMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RemovePlayerMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestPlayerVehicleMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			AcceptPlayerVehicleMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			DenyPlayerVehicleMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			AddLancemateMessageHandler(int connection, Stuff::MemoryStream* message);
		void
			ReadyToLaunchMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			ClientLoadedMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RunGameMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestRespawnMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RespawnMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestMissionParametersMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			MissionParametersMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestScoreFormatMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			ScoreMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			ChatMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			StopMissionMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			PlayerLeavingMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			ScoreFormatMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestMapInfoMessageHandler(int connection, Stuff::MemoryStream *message);
		void	
			MapInfoMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			SwitchToCameraMessage(int connection, Stuff::MemoryStream *message);
		void
			DecalLayoutMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestDecalsMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			DecalPayLoadMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			AddTeamMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			LobbyStatusMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestTeamMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestPreRenderMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			PreRenderMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			MissionReviewAvailableMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestMissionReviewMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			CancelMissionReviewMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RespawnFlagsMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			MissionReviewPartMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			PlayerClanMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RespawnLancemateMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			UnreadyLaunchMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			StopMissionConfirmationMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RequestNewDictionaryMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			KickPlayerMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			TeamBettyMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			StartMusicMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			TeamSetNavMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RespawnMissionMessageHandler(int connection, Stuff::MemoryStream *message);
		void
			RespawnIndexMessageHandler(int connection, Stuff::MemoryStream *message);

		// add message to here and switch/case stmt and id above

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  Connection Denial types
	public:
		enum {
			NoError = 0,
			ExecutableOutOfDate,
			ExecutablesDoNotMatch,
			ResourcesOutOfDate,
			ResourcesDoNotMatch,
			VersionsDoNotMatch,
			BannedClient
		};

		void
			SendRequestConnectionMessage();


		__int64 CalculateExecutableDateCRC();
		__int64 CalculateExecutableCRC();
		__int64 CalculateVersionNumber();

		__int64 CalculateMapMissionCRC(const char *map_name);
		

		__int64 lastMapCRC;
		bool haveNetworkMap;

#if !defined(NO_MR)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  Mission review support;

		void SetMissionReviewWeaponFired(int player);
		void SetMissionReviewTakeDamage(int player);

		MissionReview  *m_recordLog;
		MissionReview  *m_playLog;
		
		int totalReviewPackets;
		Stuff::DynamicMemoryStream *reviewPackets;

		bool missionReviewAvailable;
		bool playingMissionReview;
#endif // !defined(NO_MR)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Chat support

	public:
		typedef void
			(*ChatCallback)(
				void *data,
				BYTE from,
				BYTE type,
				BYTE player_sent_to,
				char *message
			);

		void *
			chatCallbackData;
		ChatCallback
			chatCallback;

		void
			RegisterChatCallback(void *data, ChatCallback callback)
		{
			Check_Pointer(callback);
			Check_Pointer(data);

			chatCallbackData = data;
			chatCallback = callback;
		}


		enum {
			SystemBroadcast,
			ObserverBroadcast,
			AliveBroadcast,
			DeadBroadcast,
			TeamAliveBroadcast,
			TeamDeadBroadcast,
			PrivateBroadcast,
			LobbyBroadcast,
			LobbyTeamBroadcast
		};


		int motdLength; //max 5
		char motd[5][Adept::MaxChatSize];

		void
			LoadMOTD();

		bool
			CullChat(BYTE from, BYTE type, BYTE player_sent_to, BYTE local_connection);

		BYTE
			TypeCheckChat(BYTE from, BYTE type, BYTE &player_sent_to);

		void
			SendChat(BYTE from, BYTE type, BYTE player_sent_to, char *message);

		void
			DisplayChat(BYTE from, BYTE type, BYTE player_sent_to, char *message);

		void
			DisplayShellChat(BYTE from, BYTE type, BYTE player_sent_to, char *message);

		void
			HandleHUDInput(bool team_chat, bool dead, bool observer, BYTE from, char* message);


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Difficulty Data support
	//

	public:
		enum { EASY_DIFFICULTY,MEDIUM_DIFFICULTY,HARD_DIFFICULTY,IMPOSSIBLE_DIFFICULTY };

	protected:
		int m_DifficultyLevel;

	public:
		void
			SetDifficultyLevel(int new_level)
				{Check_Object(this); m_DifficultyLevel = new_level;}
		int
			GetDifficultyLevel (void) const
				{Check_Object(this); return m_DifficultyLevel;}

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

	// Message Senders

		bool 	
			scoreSaved;

		void 
			SaveScore();

		void
			SendScoreFormat();

		void
			SendScoreFormat(int connection);

		void
			SendScore();

		void
			SendPersitantHermitObjects(int connection);
		void
			SendTeams(int connection);
		void
			SendTeamRequest(int team);

		void
			SendLobbyStatus();

		void
			SendPlayerClanMessage();

		void
			SendRunGameMessage(int connection_id);

		void
			SendPreRenderMessage(int connection_id);

		void
			SendVehicleRequest();
		void
			SendCampaignVehicleRequest();
		void
			SendCampaignLancemateRequests();
		
		int GetClientReady();
		void
			SetClientReady();



		Scalar timeSinceLastUnready;
		void 
			SetClientUnready();

		void
			ServerGameOver();
		
		
		void
			SendStopGameMessage();

		void
			SendPlayerLeavingMessage(); // player sends this to server when he leaves

		void
			SendRemovePlayerMessage(int connection); // server sends this to everyone when player leaves

		
		void
			SendRequestNewDictionaryMessage();

		void
			AddReplicatedHermit(Adept::Entity *entity)
		{
			replicatedHermits.Add(entity);
		}

		void
			SendEveryoneRespawnIndex();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Client Server Stuff
	//
	public:
		
		enum {
			NoExitCode,
			KickedExitCode,
			BannedExitCode,
			BadServerExitCode,
			UnknownExitCode
		};

		int networkExitCode;


		void 
			SessionLost()
				{Check_Object(this);networkExitCode = UnknownExitCode; }

		// dead reckoned timers for shell and hud...
		// server updates these values in real time
		// messages send them out

		bool lockTimer;
		Stuff::Scalar lockTimerVal;

		bool gameTimer;
		Stuff::Scalar gameTimerVal;

		bool recycleTimer;
		Stuff::Scalar recycleTimerVal;


		bool
			waitingForRunMessage;

		BYTE
			m_isNight;

		bool
			missionReady;

		int
			localVehicelAccepted;


		ServedConnectionData
			servedConnectionData[Adept::Maximum_Players];

		enum { Maximum_Teams = 8 };
		enum { No_Team = 8 };


		Stuff::SlotOf<Team *>
			*teams[8];

		static int
			NameToTeamNumber(char* name);

		bool
			TeamHasAnyPlayers(int team_number);

		char*
			GetTeamCount();
	

		char *
			missionName;

		Stuff::ChainOf<Adept::Entity*>
			replicatedHermits;


		void
			VerifyAllPlayerVehicles();

		void
			ReverifyDeniedVehicles();

		void
			RemovePlayersFromTeam();

		void
			UnreadyPlayers();



		
		enum {
			MaxBuildErrorCount=255
		};

		int 
			lastErrors[MaxBuildErrorCount];
		int 
			lastErrorsParameter[MaxBuildErrorCount];
		int 
			lastErrorCount;



		int 
			lastBotErrors[MaxBuildErrorCount];
		int 
			lastBotErrorsParameter[MaxBuildErrorCount];
		int 
			lastBotErrorCount;


		void 
			UpdateAllTeamTotalTonnages();
		Stuff::Scalar 
			GetCurrentTeamTotalTonage(int team);
		void
			VerifyPlayerVehicle(int connection);
		void
			VerifyLancemateVehicle(int connection);


		virtual bool
			VerifyPlayerVehicle(int connection, Stuff::MemoryStream *message);

		int CheckAllowedChasis(int type, DWORD allowed_flags[2]);
		int CheckAllowedBeam(int type, DWORD allowed_flags[2]);
		int CheckAllowedMissile(int type, DWORD allowed_flags[2]);
		int CheckAllowedProjectile(int type, DWORD allowed_flags[2]);
		int CheckAllowedSubsystem(int type, DWORD allowed_flags[2]);

		void
			SetVehicleCreationMessage(int player_id, Stuff::MemoryStream *vehicle_message);

		void
			ClearVehicleCreationMessage(int player_id);

		Stuff::MemoryStream *
			GetVehicleCreationmessage(int player_id);

		// FWang:: Hack for BRB 6/16/00
		Stuff::MemoryStream *
			GetBRBVehicleCreationmessage(int player_id);

	

		void DeleteLancemateData();

		void
			SetMissionName(const char *name);
	
		const char *
			GetMissionName();

		bool
			TeamsAreFriendly(const Adept::ReplicatorID& inficting_id, const Adept::ReplicatorID& victim_id);

		void
			ResetMission();
		void
			RespawnMission();
		void
			RespawnConnection(int connection);

		void
			RespawnLancemate(int connection);
		void
			QueRespawnLancemate(int connection);
	
		bool
			BotsAllowed();

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Lancemate stuff

		enum { Maximum_Lancemates = MAX_LANCEMATES };


		LancemateConnectionData
			lancemateConnectionData[Maximum_Lancemates];

		void
			SetLancemateCreationMessage(int lancemate_index, Stuff::MemoryStream* lancemate_message);

		Stuff::MemoryStream*
			GetLancemateCreationMessage(int lancemate_index);


		int 
			GetNextLancemateID();
		void
			RequestLancemateTeam(int bot, int team);
		void
			RequestLancemateMech(int bot, Adept::ResourceID mech_id, Stuff::MString &mech_name);
		void
			ClearLancemateCreationMessage(int bot);
		bool 
			VerifyLancemateVehicle(int bot, Stuff::MemoryStream *stream);
		bool
			GetLanceMateResourceID(int bot_id, Adept::ResourceID &vehicle_id, Stuff::MemoryStream *stream);


		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// ----------------------------SECURITY-------------------------------------

		void
			SquelchPlayer(int conneciton);

		void
			KickPlayer(int connection, bool print_msg = true);

		void
			BanPlayer(int connection);

		void
			BanPlayersISP(int connection);

		
		bool IsPlayerBanned(const GUID& unique_key, const GUID& ngstat_id, DWORD isp);

		void LoadBans();


		GUID
			GetUniqueKey();

		GUID
			localKey;


		int ngLogBanCount;
		int keyBanCount;
		int ispBanCount;

		GUID
			*ngLogBans;
		
		GUID
			*keyBans;
		
		DWORD
			*ispBans;



		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Network Options
		//
		public:
			enum Bandwidth_Type{
				c_14_4kbps = 0,
				c_28_8kbps,
				c_56_6kbps,
				c_64_kbps,
				c_128_kbps,
				c_384_kbps,
				c_768_kbps,
				c_1500_kbps,
				c_10_Mbps,
				c_100_Mbps
			};

			enum Connection_Type{
				Modem = 0,
				ISDN,
				xDSL,
				Cable,
				LAN
			};

			static Bandwidth_Type
				MyConnectionSpeed;
			static Connection_Type
				MyConnectionType;
			static int
				NetworkDebugLevel;
			static int
				DefaultPacketSize;
			static int
				ForceConnectionSpeed;
			
		
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Mission Parameter Support
		
		bool
			parametersDirty;

		void
			SendMissonParameters(int connection);

		void
			ReceiveMissionParameters(Stuff::MemoryStream *message);

		void
			BroadcastMissionParameters();


		NetMissionParameters::MWNetMissionParameters *
			GetLocalNetParams() const
		{
			return (NetMissionParameters::MWNetMissionParameters *)m_localMissionParameters;
		}

		NetMissionParameters::MWNetMissionParameters *
			GetServerNetParams() const
		{
			return (NetMissionParameters::MWNetMissionParameters *)m_serverMissionParameters;
		}

		void
			SaveServerOptions();
		void
			LoadServerOptions();

		int
			GetGameType();

		int
			GetTeamAlignment(int team);

		void
			SaveGameLog();

	protected:
		static const MessageEntry
			MessageEntries[];

		InputTrainer
			m_InputTrainer;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Verification functions
	public:
		static bool
			ValidateName(char *pszData, bool fCheckBSlash);
		static bool
			ValidatePath(char *pszData, bool fDirectory);

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

	public:
		static void
			OpenResources(
				bool read_only,
				DWORD content_version
			);

		virtual void
			LoadMissionResources(const char *mission_name);

	public: // jcem
        STeamOrderCommandArray m_aPTOCs; // to player...
        STeamOrderCommandArray m_aBTOCs; // to bots...
        void ClearTOC();
        void DoTOCs();
        void EndTOC(bool bAutoDeny = false);
        void DoRemoveTOCs(int connection);
	public: // jcem
        void CTCL_CheckRunningStart();
        void CTCL_GoRunningState();
        void CTCL_DoEndMission();
        void SendSound(const Adept::ReplicatorID& inflicting_id, int nSound);
        // team order
        bool IsTeamAllowed() const;
        int GetMechInfos(int nMode, SMechInfo aMechInfos[16], int& nOthers) const;
        void TeamOrderMessageHandler(int connection, Stuff::MemoryStream *message);
        void svrTeamOrderMessageHandler(int connection, Stuff::MemoryStream *message);
        void RepTeamOrderMessageHandler(int connection, Stuff::MemoryStream *message);
        void svrRepTeamOrderMessageHandler(int connection, Stuff::MemoryStream *message);
        void DoTeamOrderSoundPlay(int nFrom, int nMsgIndex);
        // team order
	public:
		static ClassData
			*DefaultData;
	public: // jcem
		int m_nCamp_Stage;
		int m_nCamp_Score, m_nCamp_Kills, m_nCamp_Deaths;
        int m_nCamp_Time, m_nCamp_Mech, m_bCamp_Success;
		virtual int CheckCampaign(int nType) const;
		void CheckCampaignEnd();
	};
    extern STeamOrderCommand* g_pCurTOC;
}
MWObject* MWObjectFromRepId(const Adept::ReplicatorID& id);
Mech* MechFromRepId(const Adept::ReplicatorID& id);
