diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /public/edict.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'public/edict.h')
| -rw-r--r-- | public/edict.h | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/public/edict.h b/public/edict.h new file mode 100644 index 0000000..37c701b --- /dev/null +++ b/public/edict.h @@ -0,0 +1,448 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef EDICT_H +#define EDICT_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "mathlib/vector.h" +#include "cmodel.h" +#include "const.h" +#include "iserverentity.h" +#include "globalvars_base.h" +#include "engine/ICollideable.h" +#include "iservernetworkable.h" +#include "bitvec.h" + +struct edict_t; + + +//----------------------------------------------------------------------------- +// Purpose: Defines the ways that a map can be loaded. +//----------------------------------------------------------------------------- +enum MapLoadType_t +{ + MapLoad_NewGame = 0, + MapLoad_LoadGame, + MapLoad_Transition, + MapLoad_Background, +}; + + +//----------------------------------------------------------------------------- +// Purpose: Global variables shared between the engine and the game .dll +//----------------------------------------------------------------------------- +class CGlobalVars : public CGlobalVarsBase +{ +public: + + CGlobalVars( bool bIsClient ); + +public: + + // Current map + string_t mapname; + int mapversion; + string_t startspot; + MapLoadType_t eLoadType; // How the current map was loaded + bool bMapLoadFailed; // Map has failed to load, we need to kick back to the main menu + + // game specific flags + bool deathmatch; + bool coop; + bool teamplay; + // current maxentities + int maxEntities; + + int serverCount; +}; + +inline CGlobalVars::CGlobalVars( bool bIsClient ) : + CGlobalVarsBase( bIsClient ) +{ + serverCount = 0; +} + + +class CPlayerState; +class IServerNetworkable; +class IServerEntity; + + +#define FL_EDICT_CHANGED (1<<0) // Game DLL sets this when the entity state changes + // Mutually exclusive with FL_EDICT_PARTIAL_CHANGE. + +#define FL_EDICT_FREE (1<<1) // this edict if free for reuse +#define FL_EDICT_FULL (1<<2) // this is a full server entity + +#define FL_EDICT_FULLCHECK (0<<0) // call ShouldTransmit() each time, this is a fake flag +#define FL_EDICT_ALWAYS (1<<3) // always transmit this entity +#define FL_EDICT_DONTSEND (1<<4) // don't transmit this entity +#define FL_EDICT_PVSCHECK (1<<5) // always transmit entity, but cull against PVS + +// Used by local network backdoor. +#define FL_EDICT_PENDING_DORMANT_CHECK (1<<6) + +// This is always set at the same time EFL_DIRTY_PVS_INFORMATION is set, but it +// gets cleared in a different place. +#define FL_EDICT_DIRTY_PVS_INFORMATION (1<<7) + +// This is used internally to edict_t to remember that it's carrying a +// "full change list" - all its properties might have changed their value. +#define FL_FULL_EDICT_CHANGED (1<<8) + + +// Max # of variable changes we'll track in an entity before we treat it +// like they all changed. +#define MAX_CHANGE_OFFSETS 19 +#define MAX_EDICT_CHANGE_INFOS 100 + + +class CEdictChangeInfo +{ +public: + // Edicts remember the offsets of properties that change + unsigned short m_ChangeOffsets[MAX_CHANGE_OFFSETS]; + unsigned short m_nChangeOffsets; +}; + +// Shared between engine and game DLL. +class CSharedEdictChangeInfo +{ +public: + CSharedEdictChangeInfo() + { + m_iSerialNumber = 1; + } + + // Matched against edict_t::m_iChangeInfoSerialNumber to determine if its + // change info is valid. + unsigned short m_iSerialNumber; + + CEdictChangeInfo m_ChangeInfos[MAX_EDICT_CHANGE_INFOS]; + unsigned short m_nChangeInfos; // How many are in use this frame. +}; +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; +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +// NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!! +class CBaseEdict +{ +public: + + // Returns an IServerEntity if FL_FULLEDICT is set or NULL if this + // is a lightweight networking entity. + IServerEntity* GetIServerEntity(); + const IServerEntity* GetIServerEntity() const; + + IServerNetworkable* GetNetworkable(); + IServerUnknown* GetUnknown(); + + // Set when initting an entity. If it's only a networkable, this is false. + 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: + + // NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it. + // NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!! +#ifdef _XBOX + unsigned short m_fStateFlags; +#else + int m_fStateFlags; +#endif + + // NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it. + // int m_NetworkSerialNumber; + + // NOTE: m_EdictIndex is an optimization since computing the edict index + // from a CBaseEdict* pointer otherwise requires divide-by-20. values for + // m_NetworkSerialNumber all fit within a 16-bit integer range, so we're + // repurposing the other 16 bits to cache off the index without changing + // the overall layout or size of this struct. existing mods compiled with + // a full 32-bit serial number field should still work. henryg 8/17/2011 +#if VALVE_LITTLE_ENDIAN + short m_NetworkSerialNumber; + short m_EdictIndex; +#else + short m_EdictIndex; + short m_NetworkSerialNumber; +#endif + + // NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it. + IServerNetworkable *m_pNetworkable; + +protected: + IServerUnknown *m_pUnk; + + +public: + + IChangeInfoAccessor *GetChangeAccessor(); // The engine implements this and the game .dll implements as + const IChangeInfoAccessor *GetChangeAccessor() const; // The engine implements this and the game .dll implements as + // as callback through to the engine!!! + + // NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!! + // This breaks HL2_VC6!!!!! + // References a CEdictChangeInfo with a list of modified network props. + //unsigned short m_iChangeInfo; + //unsigned short m_iChangeInfoSerialNumber; + + friend void InitializeEntityDLLFields( edict_t *pEdict ); +}; + + +//----------------------------------------------------------------------------- +// CBaseEdict inlines. +//----------------------------------------------------------------------------- +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() +{ + // Note: this should only happen for properties in data tables that used some + // kind of pointer dereference. If the data is directly offsetable + m_fStateFlags |= (FL_EDICT_CHANGED | FL_FULL_EDICT_CHANGED); + SetChangeInfoSerialNumber( 0 ); +} + +inline void CBaseEdict::StateChanged( unsigned short offset ) +{ + if ( m_fStateFlags & FL_FULL_EDICT_CHANGED ) + return; + + m_fStateFlags |= FL_EDICT_CHANGED; + + IChangeInfoAccessor *accessor = GetChangeAccessor(); + + if ( accessor->GetChangeInfoSerialNumber() == g_pSharedChangeInfo->m_iSerialNumber ) + { + // Ok, I still own this one. + CEdictChangeInfo *p = &g_pSharedChangeInfo->m_ChangeInfos[accessor->GetChangeInfo()]; + + // Now add this offset to our list of changed variables. + for ( unsigned short i=0; i < p->m_nChangeOffsets; i++ ) + if ( p->m_ChangeOffsets[i] == offset ) + return; + + if ( p->m_nChangeOffsets == MAX_CHANGE_OFFSETS ) + { + // Invalidate our change info. + accessor->SetChangeInfoSerialNumber( 0 ); + m_fStateFlags |= FL_FULL_EDICT_CHANGED; // So we don't get in here again. + } + else + { + p->m_ChangeOffsets[p->m_nChangeOffsets++] = offset; + } + } + else + { + if ( g_pSharedChangeInfo->m_nChangeInfos == MAX_EDICT_CHANGE_INFOS ) + { + // Shucks.. have to mark the edict as fully changed because we don't have room to remember this change. + accessor->SetChangeInfoSerialNumber( 0 ); + m_fStateFlags |= FL_FULL_EDICT_CHANGED; + } + else + { + // Get a new CEdictChangeInfo and fill it out. + 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; + } + } +} + + + +inline void CBaseEdict::SetFree() +{ + m_fStateFlags |= FL_EDICT_FREE; +} + +// WARNING: Make sure you don't really want to call ED_ClearFreeFlag which will also +// remove this edict from the g_FreeEdicts bitset. +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 void CBaseEdict::SetChangeInfoSerialNumber( unsigned short sn ) +{ + GetChangeAccessor()->SetChangeInfoSerialNumber( sn ); +} + +inline unsigned short CBaseEdict::GetChangeInfo() const +{ + return GetChangeAccessor()->GetChangeInfo(); +} + +inline unsigned short CBaseEdict::GetChangeInfoSerialNumber() const +{ + return GetChangeAccessor()->GetChangeInfoSerialNumber(); +} + +//----------------------------------------------------------------------------- +// Purpose: The engine's internal representation of an entity, including some +// basic collision and position info and a pointer to the class wrapped on top +// of the structure +//----------------------------------------------------------------------------- +struct edict_t : public CBaseEdict +{ +public: + ICollideable *GetCollideable(); + + // The server timestampe at which the edict was freed (so we can try to use other edicts before reallocating this one) + float freetime; +}; + +inline ICollideable *edict_t::GetCollideable() +{ + IServerEntity *pEnt = GetIServerEntity(); + if ( pEnt ) + return pEnt->GetCollideable(); + else + return NULL; +} + + +#endif // EDICT_H |