Counter Strike : Global Offensive Source Code
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
//========= Copyright � 1996-2005, 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"
#include "tier1/convar.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; string_t mapGroupName; 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; edict_t *pEdicts; };
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(); private: void SetChangeInfo( unsigned short info ); void SetChangeInfoSerialNumber( unsigned short sn );
public: 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!!!!!
int m_fStateFlags;
// NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it.
int m_NetworkSerialNumber; // Game DLL sets this when it gets a serial number for its EHANDLE.
// 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 | FL_FULL_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, then changes will automatically be detected
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(); int nCurrSerialNumber = accessor->GetChangeInfoSerialNumber(); if ( nCurrSerialNumber == 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 { //see if we previously had a change info allocated, but with a bad serial number. If so, we don't know which properties
//we had changed (we lost them, so be all dirty)
if( nCurrSerialNumber != 0 ) { 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; }
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(); };
inline ICollideable *edict_t::GetCollideable() { IServerEntity *pEnt = GetIServerEntity(); if ( pEnt ) return pEnt->GetCollideable(); else return NULL; }
#endif // EDICT_H
|