#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<PostEventMS(&EV_Remove, 0); (p) = NULL; } // RAVEN END //============================================================================ void gameError( const char *fmt, ... ); //============================================================================ 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 { if ( excludeClient != -1 ) { networkSystem->ServerSendReliableMessageExcluding( excludeClient, msg, inhibitRepeater ); } else { networkSystem->ServerSendReliableMessage( clientNum, msg, inhibitRepeater ); } }; 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 { if ( excludeClient != -1 ) { networkSystem->RepeaterSendReliableMessageExcluding( excludeClient, msg, inhibitHeader, repeaterClient ); } else { networkSystem->RepeaterSendReliableMessage( repeaterClient, msg, inhibitHeader, clientNum ); } }; 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 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 & 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& operator=( idEntityPtr& 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 spawnedEntities; // all spawned entities idLinkList 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 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 vacuumAreaNum; // -1 if level doesn't have any outside areas // RAVEN BEGIN // abahr: idList gravityInfo; // area num for each gravity zone idList< idEntityPtr > 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 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 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 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 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 ); 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 ); 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 ); 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 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 > &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 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 clip; // collision detection idList instances; // RAVEN END // keep watermarks on the high entity index // server transmits this to clients so they use the right entity layout idList 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 aasList; // area system idStrList aasNames; // RAVEN BEGIN // bdube: GetAlertActor idEntityPtr lastAIAlertActor; int lastAIAlertActorTime; idEntityPtr 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 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 entityStateAllocator; idBlockAlloc snapshotAllocator; // RAVEN END idEventQueue eventQueue; idList spawnSpots; // RAVEN BEGIN // ddynerman: two lists to hold team spawn points for team based games idList teamSpawnSpots[TEAM_MAX]; idList teamForwardSpawnSpots[TEAM_MAX]; // forward spawn positions, used in CTF // RAVEN END idDict newInfo; idStrList shakeSounds; 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 WeightSpawnSpots( idPlayer* player ); // RAVEN END static int sortSpawnPoints( const void *ptr1, const void *ptr2 ); void DumpOggSounds( void ); void GetShakeSounds( const idDict *dict ); 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 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( entity ); } template< class type > ID_INLINE idEntityPtr::idEntityPtr() { spawnId = 0; } template< class type > ID_INLINE void idEntityPtr::Save( idSaveGame *savefile ) const { savefile->WriteInt( spawnId ); } template< class type > ID_INLINE void idEntityPtr::Restore( idRestoreGame *savefile ) { savefile->ReadInt( spawnId ); } template< class type > ID_INLINE idEntityPtr &idEntityPtr::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::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::IsValid( void ) const { return ( gameLocal.spawnIds[ spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ] == ( spawnId >> GENTITYNUM_BITS ) ); } template< class type > ID_INLINE type *idEntityPtr::GetEntity( void ) const { int entityNum = spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ); if ( ( gameLocal.spawnIds[ entityNum ] == ( spawnId >> GENTITYNUM_BITS ) ) ) { return static_cast( gameLocal.entities[ entityNum ] ); } return NULL; } template< class type > ID_INLINE int idEntityPtr::GetEntityNum( void ) const { return ( spawnId & ( ( 1 << GENTITYNUM_BITS ) - 1 ) ); } // RAVEN BEGIN // bdube: overloaded operator template< class type > ID_INLINE type * idEntityPtr::operator->( void ) const { return GetEntity ( ); } template< class type > ID_INLINE idEntityPtr::operator type * ( void ) const { return GetEntity(); } // RAVEN END #include "../idlib/containers/ListGame.h" #endif /* !__GAME_LOCAL_H__ */