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.
231 lines
6.5 KiB
231 lines
6.5 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#ifndef ENTITYLIST_BASE_H
|
|
#define ENTITYLIST_BASE_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
|
|
#include "const.h"
|
|
#include "basehandle.h"
|
|
#include "utllinkedlist.h"
|
|
#include "ihandleentity.h"
|
|
|
|
|
|
class CEntInfo
|
|
{
|
|
public:
|
|
IHandleEntity *m_pEntity;
|
|
int m_SerialNumber;
|
|
CEntInfo *m_pPrev;
|
|
CEntInfo *m_pNext;
|
|
#ifdef GAME_DLL
|
|
string_t m_iName;
|
|
string_t m_iClassName;
|
|
#endif
|
|
|
|
void ClearLinks();
|
|
};
|
|
|
|
|
|
class CBaseEntityList
|
|
{
|
|
public:
|
|
CBaseEntityList();
|
|
~CBaseEntityList();
|
|
|
|
// Add and remove entities. iForcedSerialNum should only be used on the client. The server
|
|
// gets to dictate what the networkable serial numbers are on the client so it can send
|
|
// ehandles over and they work.
|
|
CBaseHandle AddNetworkableEntity( IHandleEntity *pEnt, int index, int iForcedSerialNum = -1 );
|
|
CBaseHandle AddNonNetworkableEntity( IHandleEntity *pEnt );
|
|
void RemoveEntity( CBaseHandle handle );
|
|
|
|
// Get an ehandle from a networkable entity's index (note: if there is no entity in that slot,
|
|
// then the ehandle will be invalid and produce NULL).
|
|
CBaseHandle GetNetworkableHandle( int iEntity ) const;
|
|
|
|
// ehandles use this in their Get() function to produce a pointer to the entity.
|
|
IHandleEntity* LookupEntity( const CBaseHandle &handle ) const;
|
|
IHandleEntity* LookupEntityByNetworkIndex( int edictIndex ) const;
|
|
|
|
// Use these to iterate over all the entities.
|
|
CBaseHandle FirstHandle() const;
|
|
CBaseHandle NextHandle( CBaseHandle hEnt ) const;
|
|
static CBaseHandle InvalidHandle();
|
|
|
|
const CEntInfo *FirstEntInfo() const;
|
|
const CEntInfo *NextEntInfo( const CEntInfo *pInfo ) const;
|
|
const CEntInfo *GetEntInfoPtr( const CBaseHandle &hEnt ) const;
|
|
const CEntInfo *GetEntInfoPtrByIndex( int index ) const;
|
|
|
|
// Used by Foundry when an entity is respawned/edited.
|
|
// We force the new entity's ehandle to be the same so anyone pointing at it still gets a valid CBaseEntity out of their ehandle.
|
|
void ForceEntSerialNumber( int iEntIndex, int iSerialNumber );
|
|
|
|
// Overridables.
|
|
protected:
|
|
|
|
// These are notifications to the derived class. It can cache info here if it wants.
|
|
virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle );
|
|
|
|
// It is safe to delete the entity here. We won't be accessing the pointer after
|
|
// calling OnRemoveEntity.
|
|
virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle );
|
|
|
|
|
|
private:
|
|
|
|
CBaseHandle AddEntityAtSlot( IHandleEntity *pEnt, int iSlot, int iForcedSerialNum );
|
|
void RemoveEntityAtSlot( int iSlot );
|
|
|
|
|
|
private:
|
|
|
|
class CEntInfoList
|
|
{
|
|
public:
|
|
CEntInfoList();
|
|
|
|
const CEntInfo *Head() const { return m_pHead; }
|
|
const CEntInfo *Tail() const { return m_pTail; }
|
|
CEntInfo *Head() { return m_pHead; }
|
|
CEntInfo *Tail() { return m_pTail; }
|
|
void AddToHead( CEntInfo *pElement ) { LinkAfter( NULL, pElement ); }
|
|
void AddToTail( CEntInfo *pElement ) { LinkBefore( NULL, pElement ); }
|
|
|
|
void LinkBefore( CEntInfo *pBefore, CEntInfo *pElement );
|
|
void LinkAfter( CEntInfo *pBefore, CEntInfo *pElement );
|
|
void Unlink( CEntInfo *pElement );
|
|
bool IsInList( CEntInfo *pElement );
|
|
|
|
private:
|
|
CEntInfo *m_pHead;
|
|
CEntInfo *m_pTail;
|
|
};
|
|
|
|
int GetEntInfoIndex( const CEntInfo *pEntInfo ) const;
|
|
|
|
|
|
// The first MAX_EDICTS entities are networkable. The rest are client-only or server-only.
|
|
CEntInfo m_EntPtrArray[NUM_ENT_ENTRIES];
|
|
CEntInfoList m_activeList;
|
|
CEntInfoList m_freeNonNetworkableList;
|
|
};
|
|
|
|
|
|
// ------------------------------------------------------------------------------------ //
|
|
// Inlines.
|
|
// ------------------------------------------------------------------------------------ //
|
|
|
|
inline int CBaseEntityList::GetEntInfoIndex( const CEntInfo *pEntInfo ) const
|
|
{
|
|
Assert( pEntInfo );
|
|
int index = (int)(pEntInfo - m_EntPtrArray);
|
|
Assert( index >= 0 && index < NUM_ENT_ENTRIES );
|
|
return index;
|
|
}
|
|
|
|
inline CBaseHandle CBaseEntityList::GetNetworkableHandle( int iEntity ) const
|
|
{
|
|
Assert( iEntity >= 0 && iEntity < MAX_EDICTS );
|
|
if ( m_EntPtrArray[iEntity].m_pEntity )
|
|
return CBaseHandle( iEntity, m_EntPtrArray[iEntity].m_SerialNumber );
|
|
else
|
|
return CBaseHandle();
|
|
}
|
|
|
|
|
|
inline IHandleEntity* CBaseEntityList::LookupEntity( const CBaseHandle &handle ) const
|
|
{
|
|
if ( handle.m_Index == INVALID_EHANDLE_INDEX )
|
|
return NULL;
|
|
|
|
// You can use this to determine when something is trying to resolve
|
|
// handles to static props as if they were handles to ordinary props,
|
|
// but in practice this is done a great deal and seems benign.
|
|
/*
|
|
// 0x40000000 = STATICPROP_EHANDLE_MASK
|
|
AssertMsg( ( handle.GetSerialNumber() != (0x40000000 >> NUM_SERIAL_NUM_SHIFT_BITS) ) ,
|
|
"Tried to look up a static prop as if it was a regular entity, a bad pointer and doom are the result.\n" );
|
|
*/
|
|
|
|
const CEntInfo *pInfo = &m_EntPtrArray[ handle.GetEntryIndex() ];
|
|
if ( pInfo->m_SerialNumber == handle.GetSerialNumber() )
|
|
return pInfo->m_pEntity;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
inline IHandleEntity* CBaseEntityList::LookupEntityByNetworkIndex( int edictIndex ) const
|
|
{
|
|
// (Legacy support).
|
|
if ( edictIndex < 0 )
|
|
return NULL;
|
|
|
|
Assert( edictIndex < NUM_ENT_ENTRIES );
|
|
return m_EntPtrArray[edictIndex].m_pEntity;
|
|
}
|
|
|
|
|
|
inline CBaseHandle CBaseEntityList::FirstHandle() const
|
|
{
|
|
if ( !m_activeList.Head() )
|
|
return INVALID_EHANDLE;
|
|
|
|
int index = GetEntInfoIndex( m_activeList.Head() );
|
|
return CBaseHandle( index, m_EntPtrArray[index].m_SerialNumber );
|
|
}
|
|
|
|
inline CBaseHandle CBaseEntityList::NextHandle( CBaseHandle hEnt ) const
|
|
{
|
|
int iSlot = hEnt.GetEntryIndex();
|
|
CEntInfo *pNext = m_EntPtrArray[iSlot].m_pNext;
|
|
if ( !pNext )
|
|
return INVALID_EHANDLE;
|
|
|
|
int index = GetEntInfoIndex( pNext );
|
|
|
|
return CBaseHandle( index, m_EntPtrArray[index].m_SerialNumber );
|
|
}
|
|
|
|
inline CBaseHandle CBaseEntityList::InvalidHandle()
|
|
{
|
|
return INVALID_EHANDLE;
|
|
}
|
|
|
|
inline const CEntInfo *CBaseEntityList::FirstEntInfo() const
|
|
{
|
|
return m_activeList.Head();
|
|
}
|
|
|
|
inline const CEntInfo *CBaseEntityList::NextEntInfo( const CEntInfo *pInfo ) const
|
|
{
|
|
return pInfo->m_pNext;
|
|
}
|
|
|
|
inline const CEntInfo *CBaseEntityList::GetEntInfoPtr( const CBaseHandle &hEnt ) const
|
|
{
|
|
int iSlot = hEnt.GetEntryIndex();
|
|
return &m_EntPtrArray[iSlot];
|
|
}
|
|
|
|
inline const CEntInfo *CBaseEntityList::GetEntInfoPtrByIndex( int index ) const
|
|
{
|
|
return &m_EntPtrArray[index];
|
|
}
|
|
|
|
inline void CBaseEntityList::ForceEntSerialNumber( int iEntIndex, int iSerialNumber )
|
|
{
|
|
m_EntPtrArray[iEntIndex].m_SerialNumber = iSerialNumber;
|
|
}
|
|
|
|
extern CBaseEntityList *g_pEntityList;
|
|
|
|
#endif // ENTITYLIST_BASE_H
|