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.
210 lines
5.6 KiB
210 lines
5.6 KiB
5 years ago
|
//========= Copyright 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;
|
||
|
|
||
|
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;
|
||
|
|
||
|
// 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;
|
||
|
|
||
|
const CEntInfo *pInfo = &m_EntPtrArray[ handle.GetEntryIndex() ];
|
||
|
if ( pInfo->m_SerialNumber == handle.GetSerialNumber() )
|
||
|
return (IHandleEntity*)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 (IHandleEntity*)m_EntPtrArray[edictIndex].m_pEntity;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline CBaseHandle CBaseEntityList::FirstHandle() const
|
||
|
{
|
||
|
if ( !m_activeList.Head() )
|
||
|
return INVALID_EHANDLE_INDEX;
|
||
|
|
||
|
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_INDEX;
|
||
|
|
||
|
int index = GetEntInfoIndex( pNext );
|
||
|
|
||
|
return CBaseHandle( index, m_EntPtrArray[index].m_SerialNumber );
|
||
|
}
|
||
|
|
||
|
inline CBaseHandle CBaseEntityList::InvalidHandle()
|
||
|
{
|
||
|
return INVALID_EHANDLE_INDEX;
|
||
|
}
|
||
|
|
||
|
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];
|
||
|
}
|
||
|
|
||
|
extern CBaseEntityList *g_pEntityList;
|
||
|
|
||
|
#endif // ENTITYLIST_BASE_H
|