#ifndef EDICT_H #define EDICT_H #ifdef _WIN32 #pragma once #endif #include "vector.h" #include "cmodel.h" #include "const.h" #include "iserverentity.h" #include "globalvars_base.h" #include "ICollideable.h" #include "iservernetworkable.h" #include "bitvec.h" #include "convar.h" struct edict_t; enum MapLoadType_t { MapLoad_NewGame = 0, MapLoad_LoadGame, MapLoad_Transition, MapLoad_Background, }; class CGlobalVars : public CGlobalVarsBase { public: CGlobalVars(bool bIsClient); public: string_t mapname; string_t mapGroupName; int mapversion; string_t startspot; MapLoadType_t eLoadType; bool bMapLoadFailed; bool deathmatch; bool coop; bool teamplay; int maxEntities; int serverCount; edict_t* pEdicts; }; inline CGlobalVars::CGlobalVars(bool bIsClient) : CGlobalVarsBase(bIsClient) { serverCount = 0; } class CPlayerState; class IServerNetworkable; class IServerEntity; #define FL_EDICT_CHANGED (1<<0) #define FL_EDICT_FREE (1<<1) #define FL_EDICT_FULL (1<<2) #define FL_EDICT_FULLCHECK (0<<0) #define FL_EDICT_ALWAYS (1<<3) #define FL_EDICT_DONTSEND (1<<4) #define FL_EDICT_PVSCHECK (1<<5) #define FL_EDICT_PENDING_DORMANT_CHECK (1<<6) #define FL_EDICT_DIRTY_PVS_INFORMATION (1<<7) #define FL_FULL_EDICT_CHANGED (1<<8) #define MAX_CHANGE_OFFSETS 19 #define MAX_EDICT_CHANGE_INFOS 100 class CEdictChangeInfo { public: unsigned short m_ChangeOffsets[MAX_CHANGE_OFFSETS]; unsigned short m_nChangeOffsets; }; class CSharedEdictChangeInfo { public: CSharedEdictChangeInfo() { m_iSerialNumber = 1; } unsigned short m_iSerialNumber; #ifdef NETWORK_VARS_ENABLED CEdictChangeInfo m_ChangeInfos[MAX_EDICT_CHANGE_INFOS]; unsigned short m_nChangeInfos; #endif }; extern CSharedEdictChangeInfo* g_pSharedChangeInfo; class IChangeInfoAccessor { public: inline void SetChangeInfo(unsigned short info) { m_iChangeInfo = info; } inline void SetChangeInfoSerialNumber(unsigned short sn) { m_iChangeInfoSerialNumber = sn; } inline unsigned short GetChangeInfo() const { return m_iChangeInfo; } inline unsigned short GetChangeInfoSerialNumber() const { return m_iChangeInfoSerialNumber; } private: unsigned short m_iChangeInfo; unsigned short m_iChangeInfoSerialNumber; }; class CBaseEdict { public: IServerEntity* GetIServerEntity(); const IServerEntity* GetIServerEntity() const; IServerNetworkable* GetNetworkable(); IServerUnknown* GetUnknown(); void SetEdict(IServerUnknown* pUnk, bool bFullEdict); int AreaNum() const; const char* GetClassName() const; bool IsFree() const; void SetFree(); void ClearFree(); bool HasStateChanged() const; void ClearStateChanged(); void StateChanged(); void StateChanged(unsigned short offset); void ClearTransmitState(); void SetChangeInfo(unsigned short info); void SetChangeInfoSerialNumber(unsigned short sn); unsigned short GetChangeInfo() const; unsigned short GetChangeInfoSerialNumber() const; public: #ifdef _XBOX unsigned short m_fStateFlags; #else int m_fStateFlags; #endif int m_NetworkSerialNumber; IServerNetworkable* m_pNetworkable; protected: IServerUnknown* m_pUnk; public: IChangeInfoAccessor* GetChangeAccessor(); const IChangeInfoAccessor* GetChangeAccessor() const; friend void InitializeEntityDLLFields(edict_t* pEdict); }; inline IServerEntity* CBaseEdict::GetIServerEntity() { if (m_fStateFlags & FL_EDICT_FULL) return (IServerEntity*)m_pUnk; else return 0; } inline bool CBaseEdict::IsFree() const { return (m_fStateFlags & FL_EDICT_FREE) != 0; } inline bool CBaseEdict::HasStateChanged() const { return (m_fStateFlags & FL_EDICT_CHANGED) != 0; } inline void CBaseEdict::ClearStateChanged() { m_fStateFlags &= ~(FL_EDICT_CHANGED | FL_FULL_EDICT_CHANGED); SetChangeInfoSerialNumber(0); } inline void CBaseEdict::StateChanged() { m_fStateFlags |= (FL_EDICT_CHANGED | FL_FULL_EDICT_CHANGED); } inline void CBaseEdict::StateChanged(unsigned short offset) { #ifdef NETWORK_VARS_ENABLED if (m_fStateFlags & FL_FULL_EDICT_CHANGED) return; m_fStateFlags |= FL_EDICT_CHANGED; IChangeInfoAccessor* accessor = GetChangeAccessor(); if (accessor->GetChangeInfoSerialNumber() == g_pSharedChangeInfo->m_iSerialNumber) { CEdictChangeInfo* p = &g_pSharedChangeInfo->m_ChangeInfos[accessor->GetChangeInfo()]; for (unsigned short i = 0; i < p->m_nChangeOffsets; i++) if (p->m_ChangeOffsets[i] == offset) return; if (p->m_nChangeOffsets == MAX_CHANGE_OFFSETS) { accessor->SetChangeInfoSerialNumber(0); m_fStateFlags |= FL_FULL_EDICT_CHANGED; } else { p->m_ChangeOffsets[p->m_nChangeOffsets++] = offset; } } else { if (g_pSharedChangeInfo->m_nChangeInfos == MAX_EDICT_CHANGE_INFOS) { accessor->SetChangeInfoSerialNumber(0); m_fStateFlags |= FL_FULL_EDICT_CHANGED; } else { accessor->SetChangeInfo(g_pSharedChangeInfo->m_nChangeInfos); g_pSharedChangeInfo->m_nChangeInfos++; accessor->SetChangeInfoSerialNumber(g_pSharedChangeInfo->m_iSerialNumber); CEdictChangeInfo* p = &g_pSharedChangeInfo->m_ChangeInfos[accessor->GetChangeInfo()]; p->m_ChangeOffsets[0] = offset; p->m_nChangeOffsets = 1; } } #else StateChanged(); #endif } inline void CBaseEdict::SetFree() { m_fStateFlags |= FL_EDICT_FREE; } inline void CBaseEdict::ClearFree() { m_fStateFlags &= ~FL_EDICT_FREE; } inline void CBaseEdict::ClearTransmitState() { m_fStateFlags &= ~(FL_EDICT_ALWAYS | FL_EDICT_PVSCHECK | FL_EDICT_DONTSEND); } inline const IServerEntity* CBaseEdict::GetIServerEntity() const { if (m_fStateFlags & FL_EDICT_FULL) return (IServerEntity*)m_pUnk; else return 0; } inline IServerUnknown* CBaseEdict::GetUnknown() { return m_pUnk; } inline IServerNetworkable* CBaseEdict::GetNetworkable() { return m_pNetworkable; } inline void CBaseEdict::SetEdict(IServerUnknown* pUnk, bool bFullEdict) { m_pUnk = pUnk; if ((pUnk != NULL) && bFullEdict) { m_fStateFlags = FL_EDICT_FULL; } else { m_fStateFlags = 0; } } inline int CBaseEdict::AreaNum() const { if (!m_pUnk) return 0; return m_pNetworkable->AreaNum(); } inline const char* CBaseEdict::GetClassName() const { if (!m_pUnk) return ""; return m_pNetworkable->GetClassName(); } inline void CBaseEdict::SetChangeInfo(unsigned short info) { GetChangeAccessor()->SetChangeInfo(info); } inline unsigned short CBaseEdict::GetChangeInfo() const { return GetChangeAccessor()->GetChangeInfo(); } inline unsigned short CBaseEdict::GetChangeInfoSerialNumber() const { return GetChangeAccessor()->GetChangeInfoSerialNumber(); } struct edict_t : public CBaseEdict { public: ICollideable* GetCollideable(); }; inline ICollideable* edict_t::GetCollideable() { IServerEntity* pEnt = GetIServerEntity(); if (pEnt) return pEnt->GetCollideable(); else return NULL; } #endif