#ifndef __GAME_LOCAL_H__
#define	__GAME_LOCAL_H__

// RAVEN BEGIN
// jsinger: attempt to eliminate cross-DLL allocation issues
#ifdef RV_UNIFIED_ALLOCATOR
inline void *operator new( size_t s ) { return Memory::Allocate(s); }
inline void operator delete( void *p ) { Memory::Free(p); }
inline void *operator new[]( size_t s ) { return Memory::Allocate(s); }
inline void operator delete[]( void *p ) { Memory::Free(p); }
#endif
// RAVEN END

/*
===============================================================================

	Local implementation of the public game interface.

===============================================================================
*/


// if set to 1 the server sends the client PVS with snapshots and the client compares against what it sees
#ifndef ASYNC_WRITE_PVS
	#define ASYNC_WRITE_PVS 0
#endif

extern idRenderWorld *				gameRenderWorld;

// classes used by idGameLocal
class idEntity;
class idActor;
class idPlayer;
class idCamera;
class idWorldspawn;
class idTestModel;
class idAAS;
class idAI;
// RAVEN BEGIN
// bdube: not using id effects
//class idSmokeParticles;
//class idEntityFx;
// bdube: client side entities
class rvInstance;
class rvClientEntity;
class rvClientModel;
class rvCTFAssaultPlayerStart;
class idPlayerStart;
// RAVEN END
class idTypeInfo;
class idProgram;
class idThread;
class idEditEntities;
class idLocationEntity;

// RAVEN BEGIN
// dluetscher: reduced max clients for memory usage
#ifdef _XENON
#define	MAX_CLIENTS				16
#else
// RAVEN END
#define	MAX_CLIENTS				32
#endif

#define	GENTITYNUM_BITS			12
#define	MAX_GENTITIES			(1<<GENTITYNUM_BITS)
#define	ENTITYNUM_NONE			(MAX_GENTITIES-1)
#define	ENTITYNUM_WORLD			(MAX_GENTITIES-2)
// RAVEN BEGIN
// bdube: dummy entity for client side physics
#define ENTITYNUM_CLIENT		(MAX_GENTITIES-3)
#define	ENTITYNUM_MAX_NORMAL	(MAX_GENTITIES-3)
// RAVEN END

// RAVEN BEGIN
// bdube: client entities
#define	CENTITYNUM_BITS			12
#define	MAX_CENTITIES			(1<<CENTITYNUM_BITS)
// shouchard:  for ban lists and because I hate magic numbers
#define CLIENT_GUID_LENGTH		12
// RAVEN END

// Savegame restore limits for game-owned variable lists. Entity table counts
// still use MAX_GENTITIES/MAX_CENTITIES directly.
const int MAX_SAVEGAME_ENTITY_REFS						= 1024;
const int MAX_SAVEGAME_CLIENT_ENTITY_REFS				= 1024;
const int MAX_SAVEGAME_BRITTLE_SHARDS					= 1024;
const int MAX_SAVEGAME_BRITTLE_DECALS_PER_SHARD			= 64;
const int MAX_SAVEGAME_BRITTLE_EDGES_PER_SHARD			= 64;	// MAX_POINTS_ON_WINDING
const int MAX_SAVEGAME_AI_ANIM_INFOS					= 256;
const int MAX_SAVEGAME_AI_LOOK_JOINTS					= 128;
const int MAX_SAVEGAME_AI_ACTION_ANIMS					= 256;
const int MAX_SAVEGAME_AI_TRIGGER_TESTS					= 256;
const int MAX_SAVEGAME_STATE_CALLS						= 256;
const int MAX_SAVEGAME_SCRIPT_FUNC_PARMS				= 64;
const int MAX_SAVEGAME_INVENTORY_ITEMS					= 512;
const int MAX_SAVEGAME_LEVEL_TRIGGERS					= 256;
const int MAX_SAVEGAME_PICKUP_ITEMS						= 512;
const int MAX_SAVEGAME_OBJECTIVES						= 256;
const int MAX_SAVEGAME_AAS_LOCATIONS					= 128;
const int MAX_SAVEGAME_GUI_EVENTS						= 256;
const int MAX_SAVEGAME_SPAWNER_ACTIVE					= 512;
const int MAX_SAVEGAME_SPAWNER_POINTS					= 512;
const int MAX_SAVEGAME_SPAWNER_CALLBACKS				= 256;
const int MAX_SAVEGAME_VEHICLE_POSITIONS				= 64;
const int MAX_SAVEGAME_VEHICLE_PARTS					= 256;
const int MAX_SAVEGAME_VEHICLE_WEAPONS					= 128;
const int MAX_SAVEGAME_VEHICLE_WEAPON_JOINTS			= 128;
const int MAX_SAVEGAME_TRAM_OCCUPANTS					= 64;
const int MAX_SAVEGAME_TRAM_WEAPONS						= 32;
const int MAX_SAVEGAME_TRAM_VISIBLE_ENEMIES				= 256;
const int MAX_SAVEGAME_TRAM_GATE_DOORS					= 32;
const int MAX_SAVEGAME_TRIGGER_FUNCTIONS				= 256;
const int MAX_SAVEGAME_MOVER_GUI_TARGETS				= 128;
const int MAX_SAVEGAME_ELEVATOR_FLOORS					= 256;
const int MAX_SAVEGAME_SHAKING_TARGET_HISTORY			= 256;
const int MAX_SAVEGAME_CHAIN_LIGHTNING_TARGETS			= 64;
const int MAX_SAVEGAME_ROCKET_GUIDE_ENTS				= 128;
const int MAX_SAVEGAME_CLIENT_CRAWL_JOINTS				= 128;
const int MAX_SAVEGAME_PHYSICS_CONTACTS					= 256;
const int MAX_SAVEGAME_PHYSICS_CONTACT_ENTITIES			= 256;
const int MAX_SAVEGAME_STATIC_MULTI_STATES				= 256;
const int MAX_SAVEGAME_STATIC_MULTI_CLIP_MODELS			= 256;
const int MAX_SAVEGAME_TARGET_INFLUENCE_ITEMS			= 1024;
const int MAX_SAVEGAME_ACTOR_ENEMIES					= 512;
const int MAX_SAVEGAME_ACTOR_ATTACHMENTS				= 256;
const int MAX_SAVEGAME_ANIMATED_ANIMS					= 256;

// RAVEN BEGIN
// abahr: helper macros
#define SAFE_DELETE_PTR(p) if(p) { delete (p); (p) = NULL; }
#define SAFE_REMOVE(p) if(p) { (p)->PostEventMS(&EV_Remove, 0); (p) = NULL; }
// RAVEN END

//============================================================================

void gameError( const char *fmt, ... );
void rvNormalizeProjectedRenderLight( renderLight_t &light, const char *ownerName, const char *lightName );

//============================================================================

typedef enum {
	CHANNEL_DEST_NONE,
	CHANNEL_DEST_RELIABLE_SERVER,
	CHANNEL_DEST_RELIABLE_REPEATER,

	CHANNEL_DEST_COUNT
} channelDestType_t;

class idMessageSender {
public:
	virtual channelDestType_t GetChannelType( void ) const = 0;
	virtual void Send( const idBitMsg &msg ) const = 0;
};

class idNullMessageSender : public idMessageSender {
public:
	virtual channelDestType_t GetChannelType( void ) const { return CHANNEL_DEST_NONE; }
	virtual void Send( const idBitMsg &msg ) const { return; };
};

class idServerReliableMessageSender : public idMessageSender {
public:
	virtual channelDestType_t GetChannelType( void ) const { return CHANNEL_DEST_RELIABLE_SERVER; }
	virtual void Send( const idBitMsg &msg ) const {
// jmarshall - engine reliable sends no longer take an inhibitRepeater flag
		if ( excludeClient != -1 ) {
			networkSystem->ServerSendReliableMessageExcluding( excludeClient, msg );
		} else {
			networkSystem->ServerSendReliableMessage( clientNum, msg );
		}
// jmarshall end
	};
	const idMessageSender &To( int _clientNum, bool _inhibitRepeater = false ) {
		clientNum = _clientNum;
		excludeClient = -1;
		inhibitRepeater = _inhibitRepeater;
		return *this;
	}
	const idMessageSender &NotTo( int _excludeClient, bool _inhibitRepeater = false ) {
		clientNum = -1;
		excludeClient = _excludeClient;
		inhibitRepeater = _inhibitRepeater;
		return *this;
	}

private:
	int clientNum;
	int excludeClient;
	bool inhibitRepeater;
};

class idRepeaterReliableMessageSender : public idMessageSender {
public:
	virtual channelDestType_t GetChannelType( void ) const { return CHANNEL_DEST_RELIABLE_REPEATER; }
	virtual void Send( const idBitMsg &msg ) const {
// jmarshall - engine has no repeater reliable channel
		//if ( excludeClient != -1 ) {
		//	networkSystem->RepeaterSendReliableMessageExcluding( excludeClient, msg, inhibitHeader, repeaterClient );
		//} else {
		//	networkSystem->RepeaterSendReliableMessage( repeaterClient, msg, inhibitHeader, clientNum );
		//}
// jmarshall end
	};
	const idMessageSender &To( int _clientNum, int asClient = -1, bool _inhibitHeader = false ) {
		repeaterClient = _clientNum;
		clientNum = asClient;
		excludeClient = -1;
		inhibitHeader = _inhibitHeader;
		return *this;
	}
	const idMessageSender &ExcludingTo( int _excludeClient, int _clientNum, bool _inhibitHeader = false ) {
		repeaterClient = _clientNum;
		clientNum = -1;
		excludeClient = _excludeClient;
		inhibitHeader = _inhibitHeader;
		return *this;
	}

private:
	int repeaterClient;		// viewer number on repeater
	int clientNum;			// clientNum of real player to address exclusively to
	int excludeClient;		// clientNum of real player to exclude
	bool inhibitHeader;
};

extern idNullMessageSender nullSender;
extern idServerReliableMessageSender serverReliableSender;
extern idRepeaterReliableMessageSender repeaterReliableSender;

//============================================================================

#include "gamesys/Event.h"
// RAVEN BEGIN
// bdube: added
#include "gamesys/State.h"
// RAVEN END
#include "gamesys/Class.h"
#include "gamesys/SysCvar.h"
#include "gamesys/SysCmds.h"
#include "gamesys/SaveGame.h"
#include "gamesys/DebugGraph.h"

#include "script/Script_Program.h"

#include "anim/Anim.h"

#include "ai/AAS.h"

#include "physics/Clip.h"
#include "physics/Push.h"

#include "Pvs.h"

#include "Lagometer.h"

//============================================================================

const int MAX_GAME_MESSAGE_SIZE		= 8192;
const int MAX_ENTITY_STATE_SIZE		= 512;
const int ENTITY_PVS_SIZE			= ((MAX_GENTITIES+31)>>5);
// RAVEN BEGIN
// abahr: changed to NUM_PORTAL_ATTRIBUTES to take into account gravity
const int NUM_RENDER_PORTAL_BITS	= NUM_PORTAL_ATTRIBUTES;
// RAVEN END

typedef struct entityState_s {
	int						entityNumber;
	idBitMsg				state;
	byte					stateBuf[MAX_ENTITY_STATE_SIZE];
	struct entityState_s *	next;
} entityState_t;

typedef struct snapshot_s {
	int						sequence;
	entityState_t *			firstEntityState;
	int						pvs[ENTITY_PVS_SIZE];
	struct snapshot_s *		next;
} snapshot_t;

const int MAX_EVENT_PARAM_SIZE		= 128;

typedef struct entityNetEvent_s {
	int						spawnId;
	int						event;
	int						time;
	int						paramsSize;
	byte					paramsBuf[MAX_EVENT_PARAM_SIZE];
	struct entityNetEvent_s	*next;
	struct entityNetEvent_s *prev;
} entityNetEvent_t;

enum {
	GAME_RELIABLE_MESSAGE_SPAWN_PLAYER,
	GAME_RELIABLE_MESSAGE_DELETE_ENT,
	GAME_RELIABLE_MESSAGE_CHAT,
	GAME_RELIABLE_MESSAGE_TCHAT,
	GAME_RELIABLE_MESSAGE_DB,
	GAME_RELIABLE_MESSAGE_KILL,
	GAME_RELIABLE_MESSAGE_DROPWEAPON,
	GAME_RELIABLE_MESSAGE_RESTART,
	GAME_RELIABLE_MESSAGE_SERVERINFO,
	GAME_RELIABLE_MESSAGE_CALLVOTE,
	GAME_RELIABLE_MESSAGE_CASTVOTE,
	GAME_RELIABLE_MESSAGE_STARTVOTE,
	GAME_RELIABLE_MESSAGE_UPDATEVOTE,
	GAME_RELIABLE_MESSAGE_PORTALSTATES,
	GAME_RELIABLE_MESSAGE_PORTAL,
	GAME_RELIABLE_MESSAGE_VCHAT,
	GAME_RELIABLE_MESSAGE_STARTSTATE,
	GAME_RELIABLE_MESSAGE_MENU,
	GAME_RELIABLE_MESSAGE_EVENT,
	GAME_RELIABLE_MESSAGE_ITEMACQUIRESOUND,
	GAME_RELIABLE_MESSAGE_DEATH,
	GAME_RELIABLE_MESSAGE_GAMESTATE,
	GAME_RELIABLE_MESSAGE_STAT,
	GAME_RELIABLE_MESSAGE_ALL_STATS,
	GAME_RELIABLE_MESSAGE_INGAMEAWARD,
	GAME_RELIABLE_MESSAGE_SET_INSTANCE,
	GAME_RELIABLE_MESSAGE_VOICECHAT_MUTING,
	GAME_RELIABLE_MESSAGE_SERVER_ADMIN,
	GAME_RELIABLE_MESSAGE_CALLPACKEDVOTE,
	GAME_RELIABLE_MESSAGE_STARTPACKEDVOTE,
	GAME_RELIABLE_MESSAGE_GETADMINBANLIST,
	GAME_RELIABLE_MESSAGE_PRINT,
	GAME_RELIABLE_MESSAGE_VOICEDATA_CLIENT,
	GAME_RELIABLE_MESSAGE_VOICEDATA_CLIENT_ECHO,
	GAME_RELIABLE_MESSAGE_VOICEDATA_CLIENT_TEST,
	GAME_RELIABLE_MESSAGE_VOICEDATA_CLIENT_ECHO_TEST,
	GAME_RELIABLE_MESSAGE_GETVOTEMAPS,
	// unreliable message sent over the reliable channel
	// used as a debug solution when making sure some missing things are not due to packet drop
	GAME_RELIABLE_MESSAGE_UNRELIABLE_MESSAGE,
	// server acknowledges events from client, in response to specific GAME_RELIABLE_MESSAGE_EVENT situations
	GAME_RELIABLE_MESSAGE_EVENT_ACK,
};

enum {
	GAME_UNRELIABLE_MESSAGE_EVENT,
	GAME_UNRELIABLE_MESSAGE_EFFECT,
	GAME_UNRELIABLE_MESSAGE_HITSCAN,
	GAME_UNRELIABLE_MESSAGE_VOICEDATA_SERVER
};

enum {
	GAME_UNRELIABLE_RECORD_CLIENTNUM,
	GAME_UNRELIABLE_RECORD_AREAS,

	GAME_UNRELIABLE_RECORD_COUNT
};

typedef enum {
	GAMESTATE_UNINITIALIZED,		// prior to Init being called
	GAMESTATE_NOMAP,				// no map loaded
	GAMESTATE_STARTUP,				// inside InitFromNewMap().  spawning map entities.
	GAMESTATE_RESTART,				// spawning map entities from an instance restart, but not fully restarting
	GAMESTATE_ACTIVE,				// normal gameplay
	GAMESTATE_SHUTDOWN				// inside MapShutdown().  clearing memory.
} gameState_t;

typedef struct {
	idPlayerStart	*ent;
	int				dist;
} spawnSpot_t;

typedef struct {
	bool connected;
	bool active;
	bool priv;
	bool nopvs;
	userOrigin_t origin;
	int pvsArea;
	idDict info;
} viewer_t;

//============================================================================
class idEventQueue {
public:
	typedef enum {
		OUTOFORDER_IGNORE,
		OUTOFORDER_DROP,
		OUTOFORDER_SORT
	} outOfOrderBehaviour_t;

							idEventQueue() : start( NULL ), end( NULL ) {}

	entityNetEvent_t *		Alloc();
	void					Free( entityNetEvent_t *event );
	void					Shutdown();

	void					Init();
	void					Enqueue( entityNetEvent_t* event, outOfOrderBehaviour_t oooBehaviour );
	entityNetEvent_t *		Dequeue( void );
	entityNetEvent_t *		RemoveLast( void );

	entityNetEvent_t *		Start( void ) { return start; }

private:
	entityNetEvent_t *					start;
	entityNetEvent_t *					end;
// RAVEN BEGIN
// jnewquist: Mark memory tags for idBlockAlloc
	idBlockAlloc<entityNetEvent_t,32,MA_EVENT>	eventAllocator;
// RAVEN END
};

//============================================================================

template< class type >
class idEntityPtr {
public:
							idEntityPtr();

	// save games
	void					Save( idSaveGame *savefile ) const;					// archives object for save game file
	void					Restore( idRestoreGame *savefile );					// unarchives object from save game file

	idEntityPtr<type> &		operator=( type *ent );

	// synchronize entity pointers over the network
	int						GetSpawnId( void ) const { return spawnId; }
	bool					SetSpawnId( int id );
	bool					UpdateSpawnId( void );

	bool					IsValid( void ) const;
	type *					GetEntity( void ) const;
	int						GetEntityNum( void ) const;

// RAVEN BEGIN
// bdube: overloaded operators
							idEntityPtr( type* ent ) { *this = ent; }
	idEntityPtr<type>&		operator=( idEntityPtr<type>& ent ) { *this = ent.GetEntity(); return *this; }
	type *					operator->( void ) const;				
	operator				type *( void ) const;
// RAVEN END

private:
	int						spawnId;
};

// RAVEN BEGIN
// abahr: forward declaration
class rvGravityArea;
// RAVEN END

//============================================================================
// ddynerman: moved MultiplayerGame.h down here, so it can use more stuff in Game_local (idEntityPtr)
#include "MultiplayerGame.h"

//============================================================================

class idGameLocal : public idGame {
public:
	idDict					serverInfo;				// all the tunable parameters, like numclients, etc
	idDict					repeaterInfo;			// serverInfo + repeater specific stuff
	int						numClients;				// pulled from serverInfo and verified
	idDict					userInfo[MAX_CLIENTS];	// client specific settings
	const usercmd_t			*usercmds;				// client input commands
	idDict					persistentPlayerInfo[MAX_CLIENTS];
	idEntity *				entities[MAX_GENTITIES];// index to entities
	int						spawnIds[MAX_GENTITIES];// for use in idEntityPtr
	int						firstFreeIndex;			// first free index in the entities array
	int						minSpawnIndex;			// when spawning multiple instances, so nothing pollutes in between the instances
	int						num_entities;			// current number <= MAX_GENTITIES
	idHashIndex				entityHash;				// hash table to quickly find entities by name
	idWorldspawn *			world;					// world entity
	idLinkList<idEntity>	spawnedEntities;		// all spawned entities
	idLinkList<idEntity>	activeEntities;			// all thinking entities (idEntity::thinkFlags != 0)
	int						numEntitiesToDeactivate;// number of entities that became inactive in current frame
	bool					sortPushers;			// true if active lists needs to be reordered to place pushers at the front
	bool					sortTeamMasters;		// true if active lists needs to be reordered to place physics team masters before their slaves
	idDict					persistentLevelInfo;	// contains args that are kept around between levels

// RAVEN BEGIN
// bdube: client entities
	rvClientEntity *			clientEntities[MAX_CENTITIES];	// index to client entities
	int							clientSpawnIds[MAX_CENTITIES];	// for use in idClientEntityPtr
	idLinkList<rvClientEntity>	clientSpawnedEntities;			// all client side entities
	int							num_clientEntities;				// current number of client entities
	int							firstFreeClientIndex;			// first free index in the client entities array
	
	int							entityRegisterTime;
// RAVEN END

	int						maxViewers; // currently allocated
	int						maxViewer; // highest numbered active viewer + 1

	viewer_t				(*viewers);

	// can be used to automatically effect every material in the world that references globalParms
	float					globalShaderParms[ MAX_GLOBAL_SHADER_PARMS ];	

	idRandom				random;					// random number generator used throughout the game

	idProgram				program;				// currently loaded script and data space
	idThread *				frameCommandThread;

	idPush					push;					// geometric pushing
	idPVS					pvs;					// potential visible set
	pvsHandle_t				clientsPVS[MAX_CLIENTS];// PVS of multiplayer clients updated every frame

	idTestModel *			testmodel;				// for development testing of models
// RAVEN BEGIN
// bdube: not using id effects
//	idEntityFx *			testFx;					// for development testing of fx
// RAVEN END

	// only set when an end level is activated, which will take over camera positioning
	// and draw end-level guis, then 

	idStr					sessionCommand;			// a target_sessionCommand can set this to return something to the session 

	idMultiplayerGame		mpGame;					// handles rules for standard dm

	idEditEntities *		editEntities;			// in game editing

	int						cinematicSkipTime;		// don't allow skipping cinemetics until this time has passed so player doesn't skip out accidently from a firefight
	int						cinematicStopTime;		// cinematics have several camera changes, so keep track of when we stop them so that we don't reset cinematicSkipTime unnecessarily
	int						cinematicMaxSkipTime;	// time to end cinematic when skipping.  there's a possibility of an infinite loop if the map isn't set up right.
	bool					inCinematic;			// game is playing cinematic (player controls frozen)
	bool					skipCinematic;

													// are kept up to date with changes to serverInfo
	int						framenum;
	int						previousTime;			// time in msec of last frame
	int						time;					// in msec
	int						msec;					// time since last update in milliseconds
	int						mHz;					// hertz
	int						autoExecAfterMapLoadStartTime;
	bool					autoExecAfterMapLoadPending;
	bool					autoExecAfterMapLoadWaitingLogged;

	int						vacuumAreaNum;			// -1 if level doesn't have any outside areas

// RAVEN BEGIN
// abahr:
	idList<rvGravityArea*>	gravityInfo;			// area num for each gravity zone
	idList< idEntityPtr<idEntity> > scriptObjectProxies;
// RAVEN END

	gameType_t				gameType;
	bool					isMultiplayer;			// set if the game is run in multiplayer mode
	bool					isServer;				// set if the game is run for a dedicated or listen server
	bool					isClient;				// set if the game is run for a client
													// discriminates between the RunFrame path and the ClientPrediction path
													// NOTE: on a listen server, isClient is false
	bool					isRepeater;				// set if the game is repeating
	bool					isListenServer;			
	bool					isTVClient;
	int						localClientNum;			// number of the local client. MP: -1 on a dedicated, MAX_CLIENTS when playing a server demo
	idLinkList<idEntity>	snapshotEntities;		// entities from the last snapshot
	int						realClientTime;			// real client time
	bool					isNewFrame;				// true if this is a new game frame, not a rerun due to prediction
	int						entityDefBits;			// bits required to store an entity def number
	int						clientAckSequence;		// holds frame number updated through GAME_RELIABLE_MESSAGE_EVENT_ACK server->client messages

	static const char *		sufaceTypeNames[ MAX_SURFACE_TYPES ];	// text names for surface types

	idEntityPtr<idEntity>	lastGUIEnt;				// last entity with a GUI, used by Cmd_NextGUI_f
	int						lastGUI;				// last GUI on the lastGUIEnt

	int						editors;				// Mirrored editors flags from common determine which editors are running
	bool					isLastPredictFrame;		// on an MP server or in SP game this means 'last catchup frame' rather than predict

// RAVEN BEGIN
// rjohnson: entity usage stats
	idStr					mapFileNameStripped;		// name of the map, empty string if no map loaded, with path and extension removed.  If entity filter, that is appended
	idList<idDict>			entityUsageList;
// ddynerman: the entity currently thinking, used to play effects/etc only in the appropriate instance
	idEntity*				currentThinkingEntity;

	const static int		INITIAL_SPAWN_COUNT = 1;

// RAVEN END

	int filterMod;
	idList<idStr> modList;

	int						nextLagoCheck;

	// ---------------------- Public idGame Interface -------------------

							idGameLocal();

// RAVEN BEGIN
// jsinger: attempt to eliminate cross-DLL allocation issues
#ifdef RV_UNIFIED_ALLOCATOR
	virtual void			Init( void *(*allocator)( size_t size ), void (*deallocator)( void *ptr ), size_t (*msize)( void *ptr ) );
#else
	virtual void			Init( void );
#endif
// RAVEN END
	virtual void			Shutdown( void );
	virtual void			SetLocalClient( int clientNum );
	virtual void			ThrottleUserInfo( void );
	virtual const idDict *	SetUserInfo( int clientNum, const idDict &userInfo, bool isClient );
	virtual const idDict *	GetUserInfo( int clientNum );
	virtual bool			IsClientActive( int clientNum );
	virtual void			SetServerInfo( const idDict &serverInfo );

	virtual const idDict *	RepeaterSetUserInfo( int clientNum, const idDict &userInfo );

	virtual const idDict &	GetPersistentPlayerInfo( int clientNum );
	virtual void			SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo );
	virtual void			InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, bool isServer, bool isClient, int randSeed );
	virtual bool			InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idFile *saveGameFile );
// RAVEN BEGIN
// mekberg: added saveTypes
	virtual void			SaveGame( idFile *saveGameFile, saveType_t saveType = ST_REGULAR );
// RAVEN END
	virtual void			MapShutdown( void );
	virtual void			CacheDictionaryMedia( const idDict *dict );
	virtual void			SpawnPlayer( int clientNum, bool isBot = false, const char* botName = "" );
	virtual gameReturn_t	RunFrame( const usercmd_t *clientCmds, int activeEditors, bool lastCatchupFrame, int serverGameFrame );
	virtual	void			MenuFrame( void );
	virtual void			RepeaterFrame( const userOrigin_t *clientOrigins, bool lastCatchupFrame, int serverGameFrame );
	virtual bool			Draw( int clientNum );
	void					CheckAutoExecAfterMapLoad( void );
	virtual escReply_t		HandleESC( idUserInterface **gui );
	virtual idUserInterface	*StartMenu( void );
	virtual const char *	HandleGuiCommands( const char *menuCommand );
	virtual void			HandleMainMenuCommands( const char *menuCommand, idUserInterface *gui );
	virtual allowReply_t	ServerAllowClient( int clientId, int numClients, const char *IP, const char *guid, const char *password, const char *privatePassword, char reason[MAX_STRING_CHARS] );
	virtual void			ServerClientConnect( int clientNum, const char *guid );
	virtual void			ServerClientBegin( int clientNum, bool isBot = false, const char* botName = "" );
	virtual void			GetRandomBotName( int clientNum, idStr& name );
	virtual void			ServerClientDisconnect( int clientNum );
	virtual void			ServerWriteInitialReliableMessages( int clientNum );
	virtual allowReply_t	RepeaterAllowClient( int clientId, int numClients, const char *IP, const char *guid, bool repeater, const char *password, const char *privatePassword, char reason[MAX_STRING_CHARS] );
	virtual void			RepeaterClientConnect( int clientNum );
	virtual void			RepeaterClientBegin( int clientNum );
	virtual void			RepeaterClientDisconnect( int clientNum );
	virtual void			RepeaterWriteInitialReliableMessages( int clientNum );
	virtual void			WriteSnapshot( snapshot_t *&clientSnapshot, entityState_t *entityStates[MAX_GENTITIES], int PVS[ENTITY_PVS_SIZE], idMsgQueue &unreliable, int sequence, idBitMsg &msg, int transmitEntity, int transmitEntity2, int instance, bool doPVS, const idBounds &pvs_bounds, int lastSnapshotFrame );
	virtual void			ServerWriteSnapshot( int clientNum, int sequence, idBitMsg &msg, dword *clientInPVS, int numPVSClients, int lastSnapshotFrame );
	virtual bool			ServerApplySnapshot( int clientNum, int sequence );
	virtual void			ServerProcessReliableMessage( int clientNum, const idBitMsg &msg );
	virtual bool			RepeaterApplySnapshot( int clientNum, int sequence );
	virtual void			RepeaterProcessReliableMessage( int clientNum, const idBitMsg &msg );
	virtual void			ClientReadSnapshot( int clientNum, int snapshotSequence, const int gameFrame, const int gameTime, const int dupeUsercmds, const int aheadOfServer, const idBitMsg &msg );
	virtual bool			ClientApplySnapshot( int clientNum, int sequence );
	virtual void			ClientProcessReliableMessage( int clientNum, const idBitMsg &msg );
	virtual gameReturn_t	ClientPrediction( int clientNum, const usercmd_t *clientCmds, bool lastPredictFrame = true, ClientStats_t *cs = NULL );
// RAVEN BEGIN
// ddynerman: client game frame
	virtual void			ClientRun( void );
	virtual void			ClientEndFrame( void );

// jshepard: rcon password check
	virtual void			ProcessRconReturn( bool success );
	virtual void			ResetRconGuiStatus( void );
// RAVEN END
	
	virtual void			GetClientStats( int clientNum, char *data, const int len );
	virtual void			SwitchTeam( int clientNum, int team );

	virtual bool			DownloadRequest( const char *IP, const char *guid, const char *paks, char urls[ MAX_STRING_CHARS ] );

	virtual bool			HTTPRequest( const char *IP, const char *file, bool isGamePak );

// RAVEN BEGIN
// bdube: client hitscan
	virtual void			ClientHitScan( const idBitMsg &msg );
// jscott: for effects system
	virtual void			StartViewEffect( int type, float time, float scale );
	virtual void			GetPlayerView( idVec3 &origin, idMat3 &axis );
	virtual void			Translation( trace_t &trace, idVec3 &source, idVec3 &dest, idTraceModel *trm, int clipMask );
	virtual void			SpawnClientMoveable ( const char* name, int lifetime, const idVec3& origin, const idMat3& axis, const idVec3& velocity, const idVec3& angular_velocity );
// bdube: added debug methods
	virtual void			DebugSetString ( const char* name, const char* value );
	virtual void			DebugSetFloat ( const char* name, float value );
	virtual void			DebugSetInt ( const char* name, int value );
	virtual const char*		DebugGetStatString ( const char* name );
	virtual int				DebugGetStatInt ( const char* name );
	virtual float			DebugGetStatFloat ( const char* name );
	virtual bool			IsDebugHudActive ( void ) const;
// rjohnson: for new note taking mechanism
	virtual bool			GetPlayerInfo( idVec3 &origin, idMat3 &axis, int PlayerNum = -1, idAngles *deltaViewAngles = NULL, int reqClientNum = -1 );
	virtual void			SetPlayerInfo( idVec3 &origin, idMat3 &axis, int PlayerNum = -1 );
	virtual	bool			PlayerChatDisabled( int clientNum );
	virtual void			SetViewComments( const char *text = 0 );
// ddynerman: utility functions
	virtual void			GetPlayerName( int clientNum, char* name );
	virtual void			GetPlayerClan( int clientNum, char* clan );
	virtual void			SetFriend( int clientNum, bool isFriend );
	static  void			Cmd_PrintMapEntityNumbers_f( const idCmdArgs& args );
	static  void			Cmd_PrintSpawnIds_f( const idCmdArgs& args );
// abahr:
	virtual int				GetNumGravityAreas() const;
	virtual const rvGravityArea* GetGravityInfo( int index ) const;
	virtual void			SetGravityInfo( int index, rvGravityArea* info );
	virtual void			AddUniqueGravityInfo( rvGravityArea* info );

	virtual int				GetCurrentGravityInfoIndex( const idVec3& origin ) const;
	virtual bool			InGravityArea( idEntity* entity ) const;
	virtual int				GetCurrentGravityInfoIndex( idEntity* entity ) const;
	virtual const idVec3	GetCurrentGravity( idEntity* entity ) const;

	virtual const idVec3	GetCurrentGravity( const idVec3& origin, const idMat3& axis ) const;

	virtual bool			InGravityArea( rvClientEntity* entity ) const;
	virtual int				GetCurrentGravityInfoIndex( rvClientEntity* entity ) const;
	virtual const idVec3	GetCurrentGravity( rvClientEntity* entity ) const;
	virtual idEntity*		ReferenceScriptObjectProxy( const char* scriptObjectName );
	virtual void			ReleaseScriptObjectProxy( const char* proxyName );

// rjohnson: entity usage stats
	virtual void			ListEntityStats( const idCmdArgs &args );
// RAVEN END

	virtual void			SetDemoState( demoState_t state, bool serverDemo, bool timeDemo );
	virtual void			SetRepeaterState( bool isRepeater, bool serverIsRepeater );
	virtual void			WriteNetworkInfo( idFile* file, int clientNum );
	virtual void			ReadNetworkInfo( int gameTime, idFile* file, int clientNum );
	virtual bool			ValidateDemoProtocol( int minor_ref, int minor );

	virtual void			ServerWriteServerDemoSnapshot( int sequence, idBitMsg &msg, int lastSnapshotFrame );
	virtual void			ClientReadServerDemoSnapshot( int sequence, const int gameFrame, const int gameTime, const idBitMsg &msg );

	virtual void			RepeaterWriteSnapshot( int clientNum, int sequence, idBitMsg &msg, dword *clientInPVS, int numPVSClients, const userOrigin_t &pvs_origin, int lastSnapshotFrame );
	virtual void			RepeaterEndSnapshots( void );
	virtual void			ClientReadRepeaterSnapshot( int sequence, const int gameFrame, const int gameTime, const int aheadOfServer, const idBitMsg &msg );

	virtual int				GetDemoFollowClient( void ) { return IsServerDemoPlaying() ? followPlayer : -1; }

	virtual void			GetBotInput( int clientNum, usercmd_t &userCmd ) { Error( "Bot input requested\n" ); };

	virtual const char *	GetLoadingGui( const char *mapDeclName ) { return NULL; }
	virtual void			SetupLoadingGui( idUserInterface *gui ) {}

	// ---------------------- Public idGameLocal Interface -------------------

	void					Printf( const char *fmt, ... ) const;
	void					DPrintf( const char *fmt, ... ) const;
	void					Warning( const char *fmt, ... ) const;
	void					DWarning( const char *fmt, ... ) const;
	void					Error( const char *fmt, ... ) const;

							// Initializes all map variables common to both save games and spawned games
	void					LoadMap( const char *mapName, int randseed );

	void					LocalMapRestart( int instance = -1 );
	void					MapRestart( int instance = -1 );
	static void				VerifyServerSettings_f( const idCmdArgs &args );
	static void				MapRestart_f( const idCmdArgs &args );
	bool					NextMap( void );	// returns wether serverinfo settings have been modified
	static void				NextMap_f( const idCmdArgs &args );

	idMapFile *				GetLevelMap( void );
	const char *			GetMapName( void ) const;

	int						NumAAS( void ) const;
	idAAS *					GetAAS( int num ) const;
	idAAS *					GetAAS( const char *name ) const;
// RAVEN BEGIN
// jscott: added accessor for memory tracking
	int						GetNumAAS( void ) const { return( aasList.Num() ); }
// RAVEN END
	void					SetAASAreaState( const idBounds &bounds, const int areaContents, bool closed );
	aasHandle_t				AddAASObstacle( const idBounds &bounds );
	void					RemoveAASObstacle( const aasHandle_t handle );
	void					RemoveAllAASObstacles( void );
// RAVEN BEGIN
// mwhitlock: added entity memory usage stuff.
	size_t					GetEntityMemoryUsage ( void ) const;
// RAVEN END
	bool					CheatsOk( bool requirePlayer = true );
	void					SetSkill( int value );
	gameState_t				GameState( void ) const;
	void					SetGameState( gameState_t newState ) { gamestate = newState; }
	idEntity *				SpawnEntityType( const idTypeInfo &classdef, const idDict *args = NULL, bool bIsClientReadSnapshot = false );
	bool					SpawnEntityDef( const idDict &args, idEntity **ent = NULL, bool setDefaults = true );
	bool					SpawnClientEntityDef( const idDict &args, rvClientEntity **ent = NULL, bool setDefaults = true, const char* spawn = NULL );
// abahr:
	idEntity*				SpawnEntityDef( const char* entityDefName, const idDict* additionalArgs = NULL );
	template< class type >
	type*					SpawnSafeEntityDef( const char* entityDefName, const idDict* additionalArgs = NULL );
	int						GetPreviousTime() const { return previousTime; }
// RAVEN END
	int						GetSpawnId( const idEntity *ent ) const;

	const idDeclEntityDef *	FindEntityDef( const char *name, bool makeDefault = true ) const;
	const idDict *			FindEntityDefDict( const char *name, bool makeDefault = true ) const;

	void					RegisterEntity( idEntity *ent );
	void					UnregisterEntity( idEntity *ent );
	// used to skip one when registering entities, leaving an empty entity in the array
	void					SkipEntityIndex( void );

	bool					RequirementMet( idEntity *activator, const idStr &requires, int removeItem );

// RITUAL BEGIN
// squirrel: accessor for si_weaponStay checks
	bool					IsWeaponsStayOn( void );
// RITUAL END

// RAVEN BEGIN
// bdube: client entities
	void					RegisterClientEntity( rvClientEntity *cent );
	void					UnregisterClientEntity( rvClientEntity *cent );
// RAVEN END

	void					AlertAI( idEntity *ent );
// RAVEN BEGIN
// bdube: added get alert actor
	idActor *				GetAlertActor( void );
	idEntity *				GetAlertEntity( void );
// RAVEN END


	bool					InPlayerPVS( idEntity *ent ) const;
	bool					InPlayerConnectedArea( idEntity *ent ) const;

	void					SetCamera( idCamera *cam );
	idCamera *				GetCamera( void ) const;
	bool					SkipCinematic( void );

// RAVEN BEGIN
// jscott: for portal skies
	idCamera				*GetPortalSky( void ) const;
	void					SetPortalSky( idCamera *cam );
// RAVEN END

	float					GetScreenAspectRatio( void ) const;
	void					CalcFov( float base_fov, float &fov_x, float &fov_y ) const;

	void					AddEntityToHash( const char *name, idEntity *ent );
	bool					RemoveEntityFromHash( const char *name, idEntity *ent );
	int						GetTargets( const idDict &args, idList< idEntityPtr<idEntity> > &list, const char *ref ) const;

							// returns the master entity of a trace.  for example, if the trace entity is the player's head, it will return the player.
	idEntity *				GetTraceEntity( const trace_t &trace ) const;

	static void				ArgCompletion_EntityName( const idCmdArgs &args, void(*callback)( const char *s ) );
	idEntity *				FindTraceEntity( idVec3 start, idVec3 end, const idTypeInfo &c, const idEntity *skip ) const;
	static void				ArgCompletion_AIName( const idCmdArgs &args, void(*callback)( const char *s ) );

//RAVEN BEGIN
// bgeisler: added, I don't want to have to do this work myself every single time I have an entityNumber
	idEntity *				FindEntity( int entityNumber )	{ return ((entityNumber >= 0 && entityNumber < MAX_GENTITIES) ? entities[entityNumber] : NULL); }
//RAVEN BEGIN

	idEntity *				FindEntity( const char *name ) const;
	idEntity *				FindEntityUsingDef( idEntity *from, const char *match ) const;
	int						EntitiesWithinRadius( const idVec3 org, float radius, idEntity **entityList, int maxCount ) const;

	void					KillBox( idEntity *ent, bool catch_teleport = false );
	void					RadiusPush( const idVec3 &origin, const float radius, const float push, const idEntity *inflictor, const idEntity *ignore, float inflictorScale, const bool quake );
// RAVEN BEGIN
// ddynerman: return number of people damaged
	void					RadiusDamage( const idVec3 &origin, idEntity *inflictor, idEntity *attacker, idEntity *ignoreDamage, idEntity *ignorePush, const char *damageDefName, float dmgPower = 1.0f, int* hitCount = NULL );
// bdube: inflictor
	void					RadiusPushClipModel( idEntity* inflictor, const idVec3 &origin, const float push, const idClipModel *clipModel );
// RAVEN END

	void					ProjectDecal( const idVec3 &origin, const idVec3 &dir, float depth, bool parallel, float size, const char *material, float angle = 0 );
// RAVEN BEGIN
// ddynerman: multiple collision worlds
	void					BloodSplat( const idEntity* ent, const idVec3 &origin, const idVec3 &dir, float size, const char *material );
// RAVEN END

	void					CallFrameCommand( idEntity *ent, const function_t *frameCommand );
// RAVEN BEGIN
// bdube: added script object frame commands
	void					CallFrameCommand( idScriptObject* obj, const function_t* frameCommand );
	void					CallFrameCommand( idEntity* ent, const char* frameCommand );
// RAVEN END	

	void					CallObjectFrameCommand( idEntity *ent, const char *frameCommand );

	const idVec3 &			GetGravity( void ) const;

	// added the following to assist licensees with merge issues
	int						GetFrameNum() const { return framenum; }
	int						GetTime() const { return time; }
	int						GetMSec() const { return msec; }
	int						GetMHz() const { return mHz; }

	int						GetNextClientNum( int current ) const;
	idPlayer *				GetClientByNum( int current ) const;
	idPlayer *				GetClientByName( const char *name ) const;
	idPlayer *				GetClientByCmdArgs( const idCmdArgs &args ) const;
	int						GetClientNumByName( const char *name ) const;

	idPlayer *				GetLocalPlayer() const;
	
// RAVEN BEGIN
// jshepard: update player data after main menu close
	void					UpdatePlayerPostMainMenu();

// bdube: added
	int						GetSpawnCount ( void ) const;
	void					SetSpawnCount ( int newSpawnCount ) { spawnCount = newSpawnCount; }
// ddynerman: team type
	bool					IsTeamGame ( void ) const;
// RAVEN END	
	
	void					SpreadLocations();
	idLocationEntity *		LocationForPoint( const idVec3 &point );	// May return NULL
// RAVEN BEGIN
// bdube: added
	idLocationEntity*		AddLocation				( const idVec3& point, const char* name );
// ddynerman: new gametype specific spawn code
	bool					SpotWouldTelefrag( idPlayer* player, idPlayerStart* spawn );
	idEntity*				SelectSpawnPoint( idPlayer* player );
	void					UpdateForwardSpawns( rvCTFAssaultPlayerStart* point, int team );
	void					ClearForwardSpawns( void );
// RAVEN END

	void					SetPortalState( qhandle_t portal, int blockingBits );
	void					ServerSendChatMessage( int to, const char *name, const char *text, const char *parm = "" );

	void					SetGlobalMaterial( const idMaterial *mat );
	const idMaterial *		GetGlobalMaterial();

	void					SetGibTime( int _time ) { nextGibTime = _time; }
	int						GetGibTime() { return nextGibTime; }
// RITUAL BEGIN
// squirrel: added DeadZone multiplayer mode
	void					SetUnFreezeTime( int _time ) { unFreezeTime = _time; };
	int						GetUnFreezeTime() { return unFreezeTime; };
	void					SetIsFrozen( bool _isFrozen ) { isFrozen = _isFrozen; };
	bool					GetIsFrozen() { return isFrozen; };
// RITUAL END
	bool					NeedRestart();

// RAVEN BEGIN
// jshepard: update end of level on player hud
	void					UpdateEndLevel();
// MCG: added whizz-by sound
	void					CheckPlayerWhizzBy	( idVec3 start, idVec3 end, idEntity* hitEnt, idEntity *attacker );
// bdube: added hitscan
// twhitaker: added additionalIgnore parameter
	idEntity*				HitScan				( const idDict& hitscanDef, const idVec3& origin, const idVec3& dir, const idVec3& fxOrigin, idEntity* owner = NULL, bool noFX = false, float damageScale = 1.0f, idEntity * additionalIgnore = NULL, int *areas = NULL );
// bdube: added effect calls
	virtual rvClientEffect*	PlayEffect			( const idDecl *effect, const idVec3& origin, const idMat3& axis, bool loop = false, const idVec3& endOrigin = vec3_origin, bool broadcast = false, bool predictedBit = false, effectCategory_t category = EC_IGNORE, const idVec4& effectTint = vec4_one );
	rvClientEffect*			PlayEffect			( const idDict& args, const char* effectName, const idVec3& origin, const idMat3& axis, bool loop = false, const idVec3& endOrigin = vec3_origin, bool broadcast = false, bool predictedBit = false, effectCategory_t category = EC_IGNORE, const idVec4& effectTint = vec4_one );
	const idDecl			*GetEffect			( const idDict& args, const char* effectName, const rvDeclMatType* materialType = NULL );

	void					UpdateRepeaterInfo( bool transmit = false );

	idList<idEntity*>		ambientLights; // lights that cast ambient

// ddynerman:	multiple collision world - game collision wrapper functions to
//				use the correct idClip
//				---------------------------------------------------------------
//				These are wrapper functions around idClip collision detection 
//				functions.  They expose the collision detection engine to the 
//				game code, but do collision world determination in one spot.
//              'ent' refers to the entity we want collision information about
	bool					Translation	( const idEntity* ent, trace_t &results, const idVec3 &start, const idVec3 &end, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity, const idEntity *passEntity2 = 0 );
	bool					Rotation	( const idEntity* ent, trace_t &results, const idVec3 &start, const idRotation &rotation, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
	bool					Motion		( const idEntity* ent, trace_t &results, const idVec3 &start, const idVec3 &end, const idRotation &rotation, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
	int						Contacts	( const idEntity* ent, contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity );
	int						Contents	( const idEntity* ent, const idVec3 &start, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity, idEntity **touchedEntity = NULL );
	// special case translations versus the rest of the world
	bool					TracePoint	( const idEntity* ent, trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask, const idEntity *passEntity );
	bool					TraceBounds	( const idEntity* ent, trace_t &results, const idVec3 &start, const idVec3 &end, const idBounds &bounds, int contentMask, const idEntity *passEntity );
	// clip versus a specific model
	void					TranslationModel( const idEntity* ent, trace_t &results, const idVec3 &start, const idVec3 &end, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
	void					RotationModel	( const idEntity* ent, trace_t &results, const idVec3 &start, const idRotation &rotation, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
	int						ContactsModel	( const idEntity* ent, contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
	int						ContentsModel	( const idEntity* ent, const idVec3 &start, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, idCollisionModel *model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
	// clip versus all entities but not the world
	void					TranslationEntities( const idEntity* ent, trace_t &results, const idVec3 &start, const idVec3 &end, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity, const idEntity *passEntity2 = 0 );
	// get a contact feature
	bool					GetModelContactFeature( const idEntity* ent, const contactInfo_t &contact, const idClipModel *clipModel, idFixedWinding &winding ) const;
	// get entities/clip models within or touching the given bounds
	int						EntitiesTouchingBounds	( const idEntity* ent, const idBounds &bounds, int contentMask, idEntity **entityList, int maxCount ) const;
	int						ClipModelsTouchingBounds( const idEntity* ent, const idBounds &bounds, int contentMask, idClipModel **clipModelList, int maxCount ) const;
	int						PlayersTouchingBounds	( const idEntity* ent, const idBounds &bounds, int contentMask, idPlayer **entityList, int maxCount ) const;
	const idBounds &		GetWorldBounds( const idEntity* ent ) const;

	void					Link( idClipModel* clip, idEntity *ent, int newId, const idVec3 &newOrigin, const idMat3 &newAxis, int renderModelHandle = -1 );

	idClip*					GetEntityClipWorld( const idEntity* ent );
	const idClip*			GetEntityClipWorld( const idEntity* ent ) const;
	int						GetNumMapEntities( void ) const;

	int						AddClipWorld( int id );
	void					RemoveClipWorld( int id );
	int						AddInstance( int id = -1, bool deferPopulate = false );
	void					RemoveInstance( int id );
	rvInstance*				GetInstance( int id );
	int						GetNumInstances( void );
// ddynerman: multiple game instances
	void					SpawnMapEntities( int instance = 0, unsigned short* entityNumIn = NULL, unsigned short* entityNumOut = NULL, int* startSpawnCount = NULL );
	void					InstanceClear( void );
// ddynerman: utility function
	virtual const char*		GetLongGametypeName( const char* gametype );
	virtual void			ReceiveRemoteConsoleOutput( const char* output );

	bool					IsFlagGameType( void ) { return ( gameType == GAME_CTF || gameType == GAME_1F_CTF || gameType == GAME_ARENA_CTF || gameType == GAME_ARENA_1F_CTF ); }
	bool					IsTeamGameType( void ) { return ( gameType == GAME_TDM || gameType == GAME_CTF || gameType == GAME_ARENA_CTF || gameType == GAME_DEADZONE ); }
	bool					IsTeamPowerups( void );

	// twhitaker: needed this for difficulty settings
	float					GetDifficultyModifier( void ) { const static float difficulty[] = { -0.3f, 0.0f, 0.4f, 0.8f }; return difficulty[ idMath::ClampInt( 0, 3, g_skill.GetInteger() ) ]; }

	bool					IsMultiplayer( void ) { return isMultiplayer; }

// mekberg: added
	bool					InCinematic( void ) { return inCinematic; }

	// mekberg: so ban list can be populated outside of multiplayer game
	void					PopulateBanList( idUserInterface* hud );
// RAVEN END

// RAVEN BEGIN
// mwhitlock: Dynamic memory consolidation
#if defined(_RV_MEM_SYS_SUPPORT)
	virtual void			FlushBeforelevelLoad( void );
#endif
// RAVEN END

	void					ServerSendInstanceReliableMessageExcluding( const idEntity* owner, int excludeClient, const idBitMsg& msg );
	void					ServerSendInstanceReliableMessage( const idEntity* owner, int clientNum, const idBitMsg& msg );	

	void					SendUnreliableMessage( const idBitMsg &msg, const int clientNum );
	// note: listen server client is always excluded
	void					SendUnreliableMessagePVS( const idBitMsg &msg, const idEntity *instanceEnt, int area1 = -1, int area2 = -1 );

	void					RepeaterAppendUnreliableMessage( int icl, const idBitMsg &msg, const idBitMsg *header = NULL );
	void					RepeaterUnreliableMessage( const idBitMsg &msg, const int clientNum, const idBitMsg *header = NULL );
	void					RepeaterUnreliableMessagePVS( const idBitMsg &msg, const int *areas, int numAreas, const idBitMsg *header = NULL );

	demoState_t				GetDemoState( void ) const { return demoState; }
	bool					IsServerDemoPlaying( void ) const { return (demoState == DEMO_PLAYING && serverDemo) || serverIsRepeater; }
	bool					IsServerDemoRecording( void ) const { return demoState == DEMO_RECORDING && serverDemo; }
	bool					IsRepeaterDemoPlaying( void ) const { return (demoState == DEMO_PLAYING && !serverDemo) && serverIsRepeater; }
	bool					IsTimeDemo( void ) const { return timeDemo; }

	/*
	do not synchronize implicit decls over the network
	implicit decls are created when loading sounds and materials that don't have an explicit entry in the def files
	clients and server may load those in different orders in a same map, or even join in with different orders because of different map histories before this game
	in D3 we maintain remap tables, but it's much better to have tighter multiplayer assets so we have no need at all
	still, you want to catch when bad things happen, so indexes should ALL be read and written through these functions
	*/
	static void				WriteDecl( idBitMsg &msg, const idDecl *decl );
	static const idDecl*	ReadDecl( const idBitMsg &msg, declType_t type );
	static void				WriteDecl( idBitMsgDelta &msg, const idDecl *decl );
	static const idDecl*	ReadDecl( const idBitMsgDelta &msg, declType_t type );

	idPlayerStart			*RandomSpawn( void );

	int						GetStartingIndexForInstance( int instanceID );
	void					ClientSetStartingIndex( int i ) { clientInstanceFirstFreeIndex = i; }
	void					ServerSetMinSpawnIndex( void );
	void					ServerSetEntityIndexWatermark( int instanceID );

	idLagometer				lagometer;
private:
// RAVEN BEGIN
// ddynerman: multiple instance for MP
	idList<idClip*>			clip;					// collision detection
	idList<rvInstance*>		instances;
// RAVEN END

	// keep watermarks on the high entity index
	// server transmits this to clients so they use the right entity layout
	idList<int>				instancesEntityIndexWatermarks;
	int						clientInstanceFirstFreeIndex;

	idStr					mapFileName;			// name of the map, empty string if no map loaded
	idMapFile *				mapFile;				// will be NULL during the game unless in-game editing is used
	bool					mapCycleLoaded;
	int						incompatibleMaps;

	int						spawnCount;
	bool					isMapEntity[ MAX_GENTITIES ]; // it's handy to know which entities are part of the map
// RAVEN BEGIN
// bdube: client entities	
	int						clientSpawnCount;
// RAVEN END

	idLocationEntity **		locationEntities;		// for location names, etc

	idCamera *				camera;
	const idMaterial *		globalMaterial;			// for overriding everything

// RAVEN BEGIN
// jscott: for portal skies
	idCamera				*portalSky;
	bool					portalSkyVisible;
// RAVEN END

	idList<idAAS *>			aasList;				// area system
	idStrList				aasNames;

// RAVEN BEGIN
// bdube: GetAlertActor
	idEntityPtr<idActor>	lastAIAlertActor;
	int						lastAIAlertActorTime;
	idEntityPtr<idEntity>	lastAIAlertEntity;
	int						lastAIAlertEntityTime;
// RAVEN END

	idDict					spawnArgs;				// spawn args used during entity spawning  FIXME: shouldn't be necessary anymore
// RAVEN BEGIN
// nmckenzie:
	const idDeclEntityDef *	spawnOverrides;
// RAVEN END

	pvsHandle_t				playerPVS;				// merged pvs of all players
	bool					freePlayerPVS;			// tracks if playerPVS needs to be released
	pvsHandle_t				playerConnectedAreas;	// all areas connected to any player area

	idVec3					gravity;				// global gravity vector
	gameState_t				gamestate;				// keeps track of whether we're spawning, shutting down, or normal gameplay
	bool					influenceActive;		// true when a phantasm is happening
	int						nextGibTime;
// RITUAL BEGIN
// squirrel: added DeadZone multiplayer mode
	int						unFreezeTime;			// time at which players unfreeze and the match begins
	bool					isFrozen;				// true if the match is frozen (for buying, etc.)
// RITUAL END

	entityState_t *			clientEntityStates[MAX_CLIENTS+1][MAX_GENTITIES];	// MAX_CLIENTS slot is for server demo recordings
	int						clientPVS[MAX_CLIENTS+1][ENTITY_PVS_SIZE];
	snapshot_t *			clientSnapshots[MAX_CLIENTS+1];

	idList<int>				privateViewerIds, nopvsViewerIds;

	entityState_t *			(*viewerEntityStates)[MAX_GENTITIES];	// MAX_CLIENTS slot is for server demo recordings
	int						(*viewerPVS)[ENTITY_PVS_SIZE];
	snapshot_t *			(*viewerSnapshots);

	idMsgQueue				(*viewerUnreliableMessages);

// RAVEN BEGIN
// jnewquist: Mark memory tags for idBlockAlloc
	idBlockAlloc<entityState_t,256,MA_ENTITY> entityStateAllocator;
	idBlockAlloc<snapshot_t,64,MA_ENTITY> snapshotAllocator;
// RAVEN END

	idEventQueue			eventQueue;

	idList<idPlayerStart*>	spawnSpots;
// RAVEN BEGIN
// ddynerman: two lists to hold team spawn points for team based games
	idList<idPlayerStart*>	teamSpawnSpots[TEAM_MAX];	
	idList<idPlayerStart*>	teamForwardSpawnSpots[TEAM_MAX]; // forward spawn positions, used in CTF
// RAVEN END

	idDict					newInfo;

	idStrList				shakeSounds;
	bool					mapMediaPrecacheActive;
	idHashTable<int>		mapMediaPrecacheSeen;
	int						mapMediaPrecacheRequests;
	int						mapMediaPrecacheSkips;

	idMsgQueue				unreliableMessages[ MAX_CLIENTS+1 ];	// MAX_CLIENTS slot for server demo recording

	demoState_t				demoState;
	bool					serverDemo;
	bool					timeDemo;
	bool					serverIsRepeater;

	// demo interaction usercmds
	usercmd_t				usercmd, oldUsercmd;
	int						followPlayer;	// free fly or spectate follow through local interaction during server demo replays

	int						demo_protocol;	// keep track of the protocol of the demo we're replaying

private:

	void					Clear( void );
							// returns true if the entity shouldn't be spawned at all in this game type or difficulty level
	bool					InhibitEntitySpawn( idDict &spawnArgs );
							// spawn entities from the map file
							// commons used by init, shutdown, and restart
	void					MapPopulate( int instance = -1 );
	void					MapClear( bool clearClients, int instance = -1 );

	bool					SetupPortalSkyPVS( idPlayer *player );
// RAVEN END
	void					SetupPlayerPVS( void );
	void					FreePlayerPVS( void );
	void					UpdateGravity( void );
	void					SortActiveEntityList( void );
	void					ShowTargets( void );
	void					RunDebugInfo( void );

	void					InitScriptForMap( void );
	void					InitConsoleCommands( void );
	void					ShutdownConsoleCommands( void );

	void					InitAsyncNetwork( void );
	void					ShutdownAsyncNetwork( void );
	void					InitLocalClient( int clientNum );
	void					FreeSnapshotsOlderThanSequence( snapshot_t *&clientSnapshot, int sequence );
	void					FreeSnapshotsOlderThanSequence( int clientNum, int sequence );
	bool					ApplySnapshot( snapshot_t *&clientSnapshot, entityState_t *entityStates[MAX_GENTITIES], int PVS[ENTITY_PVS_SIZE], int sequence );
	bool					ApplySnapshot( int clientNum, int sequence );
	void					WriteGameStateToSnapshot( idBitMsgDelta &msg ) const;
	void					ReadGameStateFromSnapshot( const idBitMsgDelta &msg );
	void					NetworkEventWarning( const entityNetEvent_t *event, const char *fmt, ... ) id_attribute((format(printf,3,4)));
	void					ServerProcessEntityNetworkEventQueue( void );
	void					ClientProcessEntityNetworkEventQueue( void );
	void					ClientShowSnapshot( int clientNum ) const;
	void					SetGameType( void );
// RAVEN BEGIN
// ddynerman: gametype specific spawn code
	void					InitializeSpawns( void );
	idList<spawnSpot_t>		WeightSpawnSpots( idPlayer* player );
// RAVEN END
	static int				sortSpawnPoints( const void *ptr1, const void *ptr2 );

	void					DumpOggSounds( void );
	void					GetShakeSounds( const idDict *dict );
	void					BeginMapMediaPrecache( void );
	void					EndMapMediaPrecache( void );
	bool					RememberMapMediaPrecache( const char *kind, const char *value );
	bool					ValidateServerSettings( const char *map, const char *gametype );

	void					Tokenize( idStrList &out, const char *in );

// RAVEN BEGIN
// ddynerman: multiple clip worlds
	void					ShutdownInstances( void );
// shouchard:  ban list support (lives in game_network.cpp)

	void					ClientReadUnreliableMessages( const idBitMsg &msg );
	void					ProcessUnreliableMessage( const idBitMsg &msg );

	void					UpdateClientsPVS( void );

	bool					IsDemoReplayInAreas( const int areas[2], int numAreas );

	void					ReallocViewers( int newMaxViewers );

	void					BuildModList( void );

public:
	void					LoadBanList();
	void					SaveBanList();
	void					FlushBanList();
	bool					IsPlayerBanned( const char *name );
	bool					IsGuidBanned( const char *guid );
	void					AddGuidToBanList( const char *guid );
	void					RemoveGuidFromBanList( const char *guid );
	virtual void			RegisterClientGuid( int clientNum, const char *guid );

	int						GetBanListCount();
	const mpBanInfo_t*		GetBanListEntry( int entry );	// returns client name
	const char*				GetGuidByClientNum( int clientNum );	// returns GUID
	int						GetClientNumByGuid( const char* );		// returns clientNum

// mekberg: get and send ban list
	void					ServerSendBanList( int clientNum );

// jscott: made public
	pvsHandle_t				GetClientPVS( idPlayer *player, pvsType_t type );

	int						GetCurrentDemoProtocol( void ) { return demo_protocol; }

private:
	char					clientGuids[ MAX_CLIENTS ][ CLIENT_GUID_LENGTH ];
	idList<mpBanInfo_t>		banList;
	bool					banListLoaded;
	bool					banListChanged;
// RAVEN END
};

//============================================================================

extern idGameLocal			gameLocal;
// RAVEN BEGIN
// jsinger: animationLib changed to a pointer to prevent it from allocating memory
//          before the unified allocator is initialized
extern idAnimManager		*animationLib;
// RAVEN END

//============================================================================

ID_INLINE void idGameLocal::WriteDecl( idBitMsg &msg, const idDecl *decl ) {
	assert( decl );
	if ( decl->IsImplicit() ) {
		gameLocal.Error( "WriteDecl: %s decl %s ( index %d ) is implicit", declManager->GetDeclNameFromType( decl->GetType() ), decl->GetName(), decl->Index() );
	}
	msg.WriteLong( decl->Index() );
}

ID_INLINE const idDecl* idGameLocal::ReadDecl( const idBitMsg &msg, declType_t type ) {
	int index = msg.ReadLong();
	const idDecl *decl = declManager->DeclByIndex( type, index );
	if ( !decl ) {
		gameLocal.Error( "ReadDecl: NULL %s decl at index %d", declManager->GetDeclNameFromType( type ), index );
	}
	if ( decl->IsImplicit() ) {
		gameLocal.Error( "ReadDecl: %s decl %s ( index %d ) is implicit", declManager->GetDeclNameFromType( type ), decl->GetName(), decl->Index() );
	}
	return decl;
}

ID_INLINE void idGameLocal::WriteDecl( idBitMsgDelta &msg, const idDecl *decl ) {
	assert( decl );
	if ( decl->IsImplicit() ) {
		gameLocal.Error( "WriteDecl: %s decl %s ( index %d ) is implicit", declManager->GetDeclNameFromType( decl->GetType() ), decl->GetName(), decl->Index() );
	}
	msg.WriteLong( decl->Index() );
}

ID_INLINE const idDecl* idGameLocal::ReadDecl( const idBitMsgDelta &msg, declType_t type ) {
	int index = msg.ReadLong();
	const idDecl *decl = declManager->DeclByIndex( type, index );
	if ( !decl ) {
		gameLocal.Error( "ReadDecl: NULL %s decl at index %d", declManager->GetDeclNameFromType( type ), index );
	}
	if ( decl->IsImplicit() ) {
		gameLocal.Error( "ReadDecl: %s decl %s ( index %d ) is implicit", declManager->GetDeclNameFromType( type ), decl->GetName(), decl->Index() );
	}
	return decl;
}

//============================================================================

class idGameError : public idException {
public:
	idGameError( const char *text ) : idException( text ) {}
};

//============================================================================


// content masks
#define	MASK_ALL					(-1)
#define	MASK_SOLID					(CONTENTS_SOLID)
#define	MASK_MONSTERSOLID			(CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_BODY)
#define	MASK_PLAYERSOLID			(CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_BODY)
#define	MASK_DEADSOLID				(CONTENTS_SOLID|CONTENTS_PLAYERCLIP)
#define	MASK_WATER					(CONTENTS_WATER)
#define	MASK_OPAQUE					(CONTENTS_OPAQUE|CONTENTS_SIGHTCLIP)
#define	MASK_SHOT_RENDERMODEL		(CONTENTS_SOLID|CONTENTS_RENDERMODEL)
#define	MASK_SHOT_BOUNDINGBOX		(CONTENTS_SOLID|CONTENTS_BODY)
#define MASK_LARGESHOT_RENDERMODEL	(CONTENTS_SOLID|CONTENTS_RENDERMODEL|CONTENTS_LARGESHOTCLIP)
#define MASK_LARGESHOT_BOUNDINGBOX	(CONTENTS_SOLID|CONTENTS_BODY|CONTENTS_LARGESHOTCLIP)
#define MASK_DMGSOLID				(CONTENTS_SOLID|CONTENTS_LARGESHOTCLIP)

// RAVEN BEGIN
// creed: added monster clip
#define	MASK_MONSTERCLIP			(CONTENTS_SOLID|CONTENTS_MONSTERCLIP)
// RAVEN END

const float DEFAULT_GRAVITY			= 1066.0f;
const float DEFAULT_GRAVITY_MP		= 800.0f;

#define DEFAULT_GRAVITY_STRING		"1066"
#define DEFAULT_MP_GRAVITY_STRING	"800"
const idVec3 DEFAULT_GRAVITY_VEC3( 0, 0, -DEFAULT_GRAVITY );

const int	CINEMATIC_SKIP_DELAY	= SEC2MS( 2.0f );

//============================================================================

#include "physics/Force.h"
#include "physics/Force_Constant.h"
#include "physics/Force_Drag.h"
#include "physics/Force_Field.h"
#include "physics/Force_Spring.h"
#include "physics/Physics.h"
#include "physics/Physics_Static.h"
#include "physics/Physics_StaticMulti.h"
#include "physics/Physics_Base.h"
#include "physics/Physics_Actor.h"
#include "physics/Physics_Monster.h"
#include "physics/Physics_Player.h"
#include "physics/Physics_Parametric.h"
#include "physics/Physics_RigidBody.h"
#include "physics/Physics_AF.h"
#include "physics/Physics_Particle.h"
#include "physics/Physics_VehicleMonster.h"

#include "vehicle/VehicleController.h"

#include "Entity.h"
#include "Game_Debug.h"
#include "IconManager.h"
#include "GameEdit.h"
#include "AF.h"
#include "IK.h"
#include "AFEntity.h"
#include "Misc.h"
#include "Actor.h"

// client entities
#include "client/ClientEntity.h"
#include "client/ClientEffect.h"
#include "client/ClientMoveable.h"
#include "client/ClientModel.h"
#include "client/ClientAFEntity.h"

#include "Weapon.h"

#include "script/ScriptFuncUtility.h"

#include "Light.h"
#include "WorldSpawn.h"
#include "Item.h"
#include "PlayerView.h"
// TTimo: moved AI.h up, can't do template instanciation on forward declared-classes
#include "ai/AI.h"
#include "Player.h"
#include "Mover.h"
// RAVEN BEGIN
// abahr:
#include "vehicle/VehicleParts.h"
#include "vehicle/Vehicle.h"
#include "SplineMover.h"
#include "TramGate.h"
#include "vehicle/VehicleDriver.h"
// RAVEN END
#include "Camera.h"
#include "Moveable.h"
#include "Target.h"
#include "Trigger.h"
#include "Sound.h"
#include "SecurityCamera.h"
#include "BrittleFracture.h"

// RAVEN BEGIN
// nmckenzie: Reduce dependencies.
#include "mp/CTF.h"
#include "mp/stats/StatManager.h"
#include "mp/Tourney.h"
#include "Instance.h"
// RAVEN END
#include "anim/Anim_Testmodel.h"

// RAVEN BEGIN
// jscott: for lip syncing
#include "LipSync.h"
// RAVEN END

#include "script/Script_Compiler.h"
#include "script/Script_Interpreter.h"
#include "script/Script_Thread.h"

#ifdef _XENON
#define PACIFIER_UPDATE session->PacifierUpdate()
#else
#define PACIFIER_UPDATE
#endif

ID_INLINE rvClientEffect* idGameLocal::PlayEffect( const idDict& args, const char* effectName, const idVec3& origin, const idMat3& axis, bool loop, const idVec3& endOrigin, bool broadcast, bool predictBit, effectCategory_t category, const idVec4& effectTint ) {
	return PlayEffect( GetEffect( args, effectName ), origin, axis, loop, endOrigin, broadcast, predictBit, category, effectTint );
}

ID_INLINE bool idGameLocal::IsTeamGame( void ) const {
	return ( isMultiplayer && ( gameType == GAME_CTF || gameType == GAME_TDM || gameType == GAME_1F_CTF || gameType == GAME_ARENA_CTF || gameType == GAME_DEADZONE ) );
}

ID_INLINE int idGameLocal::GetNumMapEntities( void ) const {
	if ( mapFile == NULL ) {
		return -1;
	} else {
		return mapFile->GetNumEntities();
	}
}

ID_INLINE rvInstance* idGameLocal::GetInstance( int id ) {
	return instances[ id ];
}

ID_INLINE int idGameLocal::GetNumInstances( void ) {
	return instances.Num();
}

ID_INLINE void idGameLocal::ReceiveRemoteConsoleOutput( const char* output ) {
	if( isMultiplayer ) {
		mpGame.ReceiveRemoteConsoleOutput( output );
	}
}

template< class type >
type* idGameLocal::SpawnSafeEntityDef( const char* entityDefName, const idDict* additionalArgs ) {
	idEntity* entity = SpawnEntityDef( entityDefName, additionalArgs );
	if( !entity ) {
		return NULL;
	}
	
	if( !entity->IsType(type::GetClassType()) ) {
		entity->PostEventMS( &EV_Remove, 0 );
		return NULL;
	}
	
	return static_cast<type*>( entity );
}

template< class type >
ID_INLINE idEntityPtr<type>::idEntityPtr() {
	spawnId = 0;
}

template< class type >
ID_INLINE void idEntityPtr<type>::Save( idSaveGame *savefile ) const {
	savefile->WriteInt( spawnId );
}

template< class type >
ID_INLINE void idEntityPtr<type>::Restore( idRestoreGame *savefile ) {
	savefile->ReadInt( spawnId );
}

template< class type >
ID_INLINE idEntityPtr<type> &idEntityPtr<type>::operator=( type *ent ) {
	if ( ent == NULL ) {
		spawnId = 0;
	} else {
		spawnId = ( gameLocal.spawnIds[ent->entityNumber] << GENTITYNUM_BITS ) | ent->entityNumber;
	}
	return *this;
}

template< class type >
ID_INLINE bool idEntityPtr<type>::SetSpawnId( int id ) {
	if ( ( id >> GENTITYNUM_BITS ) == gameLocal.spawnIds[ id & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] ) {
		spawnId = id;
		return true;
	}
	return false;
}

template< class type >
ID_INLINE bool idEntityPtr<type>::IsValid( void ) const {
	return ( gameLocal.spawnIds[ spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] == ( spawnId >> GENTITYNUM_BITS ) );
}

template< class type >
ID_INLINE type *idEntityPtr<type>::GetEntity( void ) const {
	int entityNum = spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 );
	if ( ( gameLocal.spawnIds[ entityNum ] == ( spawnId >> GENTITYNUM_BITS ) ) ) {
		return static_cast<type *>( gameLocal.entities[ entityNum ] );
	}
	return NULL;
}

template< class type >
ID_INLINE int idEntityPtr<type>::GetEntityNum( void ) const {
	return ( spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) );
}

// RAVEN BEGIN
// bdube: overloaded operator
template< class type >
ID_INLINE type * idEntityPtr<type>::operator->( void ) const {
	return GetEntity ( );
}

template< class type >
ID_INLINE idEntityPtr<type>::operator type * ( void ) const { 
	return GetEntity(); 
}
// RAVEN END

#include "../idlib/containers/ListGame.h"

#endif	/* !__GAME_LOCAL_H__ */
