2013-12-02 19:31:46 -08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
# include "cbase.h"
# include "const.h"
# include "toolframework/itoolentity.h"
# include "entitylist.h"
# include "toolframework/itoolsystem.h"
# include "KeyValues.h"
# include "icliententity.h"
# include "iserverentity.h"
# include "sceneentity.h"
# include "particles/particles.h"
//-----------------------------------------------------------------------------
// Interface from engine to tools for manipulating entities
//-----------------------------------------------------------------------------
class CServerTools : public IServerTools
{
public :
// Inherited from IServerTools
virtual IServerEntity * GetIServerEntity ( IClientEntity * pClientEntity ) ;
virtual bool GetPlayerPosition ( Vector & org , QAngle & ang , IClientEntity * pClientPlayer = NULL ) ;
virtual bool SnapPlayerToPosition ( const Vector & org , const QAngle & ang , IClientEntity * pClientPlayer = NULL ) ;
virtual int GetPlayerFOV ( IClientEntity * pClientPlayer = NULL ) ;
virtual bool SetPlayerFOV ( int fov , IClientEntity * pClientPlayer = NULL ) ;
virtual bool IsInNoClipMode ( IClientEntity * pClientPlayer = NULL ) ;
virtual CBaseEntity * FirstEntity ( void ) ;
virtual CBaseEntity * NextEntity ( CBaseEntity * pEntity ) ;
virtual CBaseEntity * FindEntityByHammerID ( int iHammerID ) ;
virtual bool GetKeyValue ( CBaseEntity * pEntity , const char * szField , char * szValue , int iMaxLen ) ;
virtual bool SetKeyValue ( CBaseEntity * pEntity , const char * szField , const char * szValue ) ;
virtual bool SetKeyValue ( CBaseEntity * pEntity , const char * szField , float flValue ) ;
virtual bool SetKeyValue ( CBaseEntity * pEntity , const char * szField , const Vector & vecValue ) ;
virtual CBaseEntity * CreateEntityByName ( const char * szClassName ) ;
virtual void DispatchSpawn ( CBaseEntity * pEntity ) ;
virtual void ReloadParticleDefintions ( const char * pFileName , const void * pBufData , int nLen ) ;
virtual void AddOriginToPVS ( const Vector & org ) ;
virtual void MoveEngineViewTo ( const Vector & vPos , const QAngle & vAngles ) ;
virtual bool DestroyEntityByHammerId ( int iHammerID ) ;
virtual CBaseEntity * GetBaseEntityByEntIndex ( int iEntIndex ) ;
virtual void RemoveEntity ( CBaseEntity * pEntity ) ;
virtual void RemoveEntityImmediate ( CBaseEntity * pEntity ) ;
virtual IEntityFactoryDictionary * GetEntityFactoryDictionary ( void ) ;
virtual void SetMoveType ( CBaseEntity * pEntity , int val ) ;
virtual void SetMoveType ( CBaseEntity * pEntity , int val , int moveCollide ) ;
virtual void ResetSequence ( CBaseAnimating * pEntity , int nSequence ) ;
virtual void ResetSequenceInfo ( CBaseAnimating * pEntity ) ;
virtual void ClearMultiDamage ( void ) ;
virtual void ApplyMultiDamage ( void ) ;
virtual void AddMultiDamage ( const CTakeDamageInfo & pTakeDamageInfo , CBaseEntity * pEntity ) ;
virtual void RadiusDamage ( const CTakeDamageInfo & info , const Vector & vecSrc , float flRadius , int iClassIgnore , CBaseEntity * pEntityIgnore ) ;
virtual ITempEntsSystem * GetTempEntsSystem ( void ) ;
} ;
//-----------------------------------------------------------------------------
// Singleton
//-----------------------------------------------------------------------------
static CServerTools g_ServerTools ;
// VSERVERTOOLS_INTERFACE_VERSION_1 is compatible with the latest since we're only adding things to the end, so expose that as well.
EXPOSE_SINGLE_INTERFACE_GLOBALVAR ( CServerTools , IServerTools001 , VSERVERTOOLS_INTERFACE_VERSION_1 , g_ServerTools ) ;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR ( CServerTools , IServerTools , VSERVERTOOLS_INTERFACE_VERSION , g_ServerTools ) ;
// When bumping the version to this interface, check that our assumption is still valid and expose the older version in the same way
COMPILE_TIME_ASSERT ( VSERVERTOOLS_INTERFACE_VERSION_INT = = 2 ) ;
IServerEntity * CServerTools : : GetIServerEntity ( IClientEntity * pClientEntity )
{
if ( pClientEntity = = NULL )
return NULL ;
CBaseHandle ehandle = pClientEntity - > GetRefEHandle ( ) ;
if ( ehandle . GetEntryIndex ( ) > = MAX_EDICTS )
return NULL ; // the first MAX_EDICTS entities are networked, the rest are client or server only
#if 0
// this fails, since the server entities have extra bits in their serial numbers,
// since 20 bits are reserved for serial numbers, except for networked entities, which are restricted to 10
// Brian believes that everything should just restrict itself to 10 to make things simpler,
// so if/when he changes NUM_SERIAL_NUM_BITS to 10, we can switch back to this simpler code
IServerNetworkable * pNet = gEntList . GetServerNetworkable ( ehandle ) ;
if ( pNet = = NULL )
return NULL ;
CBaseEntity * pServerEnt = pNet - > GetBaseEntity ( ) ;
return pServerEnt ;
# else
IHandleEntity * pEnt = gEntList . LookupEntityByNetworkIndex ( ehandle . GetEntryIndex ( ) ) ;
if ( pEnt = = NULL )
return NULL ;
CBaseHandle h = gEntList . GetNetworkableHandle ( ehandle . GetEntryIndex ( ) ) ;
const int mask = ( 1 < < NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS ) - 1 ;
if ( ! h . IsValid ( ) | | ( ( h . GetSerialNumber ( ) & mask ) ! = ( ehandle . GetSerialNumber ( ) & mask ) ) )
return NULL ;
IServerUnknown * pUnk = static_cast < IServerUnknown * > ( pEnt ) ;
return pUnk - > GetBaseEntity ( ) ;
# endif
}
bool CServerTools : : GetPlayerPosition ( Vector & org , QAngle & ang , IClientEntity * pClientPlayer )
{
IServerEntity * pServerPlayer = GetIServerEntity ( pClientPlayer ) ;
CBasePlayer * pPlayer = pServerPlayer ? ( CBasePlayer * ) pServerPlayer : UTIL_GetLocalPlayer ( ) ;
if ( pPlayer = = NULL )
return false ;
org = pPlayer - > EyePosition ( ) ;
ang = pPlayer - > EyeAngles ( ) ;
return true ;
}
bool CServerTools : : SnapPlayerToPosition ( const Vector & org , const QAngle & ang , IClientEntity * pClientPlayer )
{
IServerEntity * pServerPlayer = GetIServerEntity ( pClientPlayer ) ;
CBasePlayer * pPlayer = pServerPlayer ? ( CBasePlayer * ) pServerPlayer : UTIL_GetLocalPlayer ( ) ;
if ( pPlayer = = NULL )
return false ;
pPlayer - > SetAbsOrigin ( org - pPlayer - > GetViewOffset ( ) ) ;
pPlayer - > SnapEyeAngles ( ang ) ;
// Disengage from hierarchy
pPlayer - > SetParent ( NULL ) ;
return true ;
}
int CServerTools : : GetPlayerFOV ( IClientEntity * pClientPlayer )
{
IServerEntity * pServerPlayer = GetIServerEntity ( pClientPlayer ) ;
CBasePlayer * pPlayer = pServerPlayer ? ( CBasePlayer * ) pServerPlayer : UTIL_GetLocalPlayer ( ) ;
if ( pPlayer = = NULL )
return 0 ;
return pPlayer - > GetFOV ( ) ;
}
bool CServerTools : : SetPlayerFOV ( int fov , IClientEntity * pClientPlayer )
{
IServerEntity * pServerPlayer = GetIServerEntity ( pClientPlayer ) ;
CBasePlayer * pPlayer = pServerPlayer ? ( CBasePlayer * ) pServerPlayer : UTIL_GetLocalPlayer ( ) ;
if ( pPlayer = = NULL )
return false ;
pPlayer - > SetDefaultFOV ( fov ) ;
CBaseEntity * pFOVOwner = pPlayer - > GetFOVOwner ( ) ;
return pPlayer - > SetFOV ( pFOVOwner ? pFOVOwner : pPlayer , fov ) ;
}
bool CServerTools : : IsInNoClipMode ( IClientEntity * pClientPlayer )
{
IServerEntity * pServerPlayer = GetIServerEntity ( pClientPlayer ) ;
CBasePlayer * pPlayer = pServerPlayer ? ( CBasePlayer * ) pServerPlayer : UTIL_GetLocalPlayer ( ) ;
if ( pPlayer = = NULL )
return true ;
return pPlayer - > GetMoveType ( ) = = MOVETYPE_NOCLIP ;
}
CBaseEntity * CServerTools : : FirstEntity ( void )
{
return gEntList . FirstEnt ( ) ;
}
CBaseEntity * CServerTools : : NextEntity ( CBaseEntity * pEntity )
{
CBaseEntity * pEnt ;
if ( pEntity = = NULL )
{
pEnt = gEntList . FirstEnt ( ) ;
}
else
{
pEnt = gEntList . NextEnt ( ( CBaseEntity * ) pEntity ) ;
}
return pEnt ;
}
CBaseEntity * CServerTools : : FindEntityByHammerID ( int iHammerID )
{
CBaseEntity * pEntity = gEntList . FirstEnt ( ) ;
while ( pEntity )
{
if ( pEntity - > m_iHammerID = = iHammerID )
return pEntity ;
pEntity = gEntList . NextEnt ( pEntity ) ;
}
return NULL ;
}
bool CServerTools : : GetKeyValue ( CBaseEntity * pEntity , const char * szField , char * szValue , int iMaxLen )
{
return pEntity - > GetKeyValue ( szField , szValue , iMaxLen ) ;
}
bool CServerTools : : SetKeyValue ( CBaseEntity * pEntity , const char * szField , const char * szValue )
{
return pEntity - > KeyValue ( szField , szValue ) ;
}
bool CServerTools : : SetKeyValue ( CBaseEntity * pEntity , const char * szField , float flValue )
{
return pEntity - > KeyValue ( szField , flValue ) ;
}
bool CServerTools : : SetKeyValue ( CBaseEntity * pEntity , const char * szField , const Vector & vecValue )
{
return pEntity - > KeyValue ( szField , vecValue ) ;
}
//-----------------------------------------------------------------------------
// entity spawning
//-----------------------------------------------------------------------------
CBaseEntity * CServerTools : : CreateEntityByName ( const char * szClassName )
{
return : : CreateEntityByName ( szClassName ) ;
}
void CServerTools : : DispatchSpawn ( CBaseEntity * pEntity )
{
: : DispatchSpawn ( pEntity ) ;
}
//-----------------------------------------------------------------------------
// Reload particle definitions
//-----------------------------------------------------------------------------
void CServerTools : : ReloadParticleDefintions ( const char * pFileName , const void * pBufData , int nLen )
{
// FIXME: Use file name to determine if we care about this data
CUtlBuffer buf ( pBufData , nLen , CUtlBuffer : : READ_ONLY ) ;
g_pParticleSystemMgr - > ReadParticleConfigFile ( buf , true ) ;
}
void CServerTools : : AddOriginToPVS ( const Vector & org )
{
engine - > AddOriginToPVS ( org ) ;
}
void CServerTools : : MoveEngineViewTo ( const Vector & vPos , const QAngle & vAngles )
{
CBasePlayer * pPlayer = UTIL_GetListenServerHost ( ) ;
if ( ! pPlayer )
return ;
extern void EnableNoClip ( CBasePlayer * pPlayer ) ;
EnableNoClip ( pPlayer ) ;
Vector zOffset = pPlayer - > EyePosition ( ) - pPlayer - > GetAbsOrigin ( ) ;
pPlayer - > SetAbsOrigin ( vPos - zOffset ) ;
pPlayer - > SnapEyeAngles ( vAngles ) ;
}
bool CServerTools : : DestroyEntityByHammerId ( int iHammerID )
{
CBaseEntity * pEntity = ( CBaseEntity * ) FindEntityByHammerID ( iHammerID ) ;
if ( ! pEntity )
return false ;
UTIL_Remove ( pEntity ) ;
return true ;
}
void CServerTools : : RemoveEntity ( CBaseEntity * pEntity )
{
UTIL_Remove ( pEntity ) ;
}
void CServerTools : : RemoveEntityImmediate ( CBaseEntity * pEntity )
{
UTIL_RemoveImmediate ( pEntity ) ;
}
CBaseEntity * CServerTools : : GetBaseEntityByEntIndex ( int iEntIndex )
{
edict_t * pEdict = INDEXENT ( iEntIndex ) ;
if ( pEdict )
return CBaseEntity : : Instance ( pEdict ) ;
else
return NULL ;
}
IEntityFactoryDictionary * CServerTools : : GetEntityFactoryDictionary ( void )
{
return : : EntityFactoryDictionary ( ) ;
}
void CServerTools : : SetMoveType ( CBaseEntity * pEntity , int val )
{
pEntity - > SetMoveType ( ( MoveType_t ) val ) ;
}
void CServerTools : : SetMoveType ( CBaseEntity * pEntity , int val , int moveCollide )
{
pEntity - > SetMoveType ( ( MoveType_t ) val , ( MoveCollide_t ) moveCollide ) ;
}
void CServerTools : : ResetSequence ( CBaseAnimating * pEntity , int nSequence )
{
pEntity - > ResetSequence ( nSequence ) ;
}
void CServerTools : : ResetSequenceInfo ( CBaseAnimating * pEntity )
{
pEntity - > ResetSequenceInfo ( ) ;
}
void CServerTools : : ClearMultiDamage ( void )
{
: : ClearMultiDamage ( ) ;
}
void CServerTools : : ApplyMultiDamage ( void )
{
: : ApplyMultiDamage ( ) ;
}
void CServerTools : : AddMultiDamage ( const CTakeDamageInfo & pTakeDamageInfo , CBaseEntity * pEntity )
{
: : AddMultiDamage ( pTakeDamageInfo , pEntity ) ;
}
void CServerTools : : RadiusDamage ( const CTakeDamageInfo & info , const Vector & vecSrc , float flRadius , int iClassIgnore , CBaseEntity * pEntityIgnore )
{
: : RadiusDamage ( info , vecSrc , flRadius , iClassIgnore , pEntityIgnore ) ;
}
ITempEntsSystem * CServerTools : : GetTempEntsSystem ( void )
{
return ( ITempEntsSystem * ) te ;
}
// Interface from engine to tools for manipulating entities
class CServerChoreoTools : public IServerChoreoTools
{
public :
// Iterates through ALL entities (separate list for client vs. server)
virtual EntitySearchResult NextChoreoEntity ( EntitySearchResult currentEnt )
{
CBaseEntity * ent = reinterpret_cast < CBaseEntity * > ( currentEnt ) ;
ent = gEntList . FindEntityByClassname ( ent , " logic_choreographed_scene " ) ;
return reinterpret_cast < EntitySearchResult > ( ent ) ;
}
virtual const char * GetSceneFile ( EntitySearchResult sr )
{
CBaseEntity * ent = reinterpret_cast < CBaseEntity * > ( sr ) ;
if ( ! sr )
return " " ;
if ( Q_stricmp ( ent - > GetClassname ( ) , " logic_choreographed_scene " ) )
return " " ;
return GetSceneFilename ( ent ) ;
}
// For interactive editing
virtual int GetEntIndex ( EntitySearchResult sr )
{
CBaseEntity * ent = reinterpret_cast < CBaseEntity * > ( sr ) ;
if ( ! ent )
return - 1 ;
return ent - > entindex ( ) ;
}
virtual void ReloadSceneFromDisk ( int entindex )
{
CBaseEntity * ent = CBaseEntity : : Instance ( entindex ) ;
if ( ! ent )
return ;
: : ReloadSceneFromDisk ( ent ) ;
}
} ;
static CServerChoreoTools g_ServerChoreoTools ;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR ( CServerChoreoTools , IServerChoreoTools , VSERVERCHOREOTOOLS_INTERFACE_VERSION , g_ServerChoreoTools ) ;
//------------------------------------------------------------------------------
// Applies keyvalues to the entity by hammer ID.
//------------------------------------------------------------------------------
void CC_Ent_Keyvalue ( const CCommand & args )
{
// Must have an odd number of arguments.
if ( ( args . ArgC ( ) < 4 ) | | ( args . ArgC ( ) & 1 ) )
{
Msg ( " Format: ent_keyvalue <entity id> \" key1 \" \" value1 \" \" key2 \" \" value2 \" ... \" keyN \" \" valueN \" \n " ) ;
return ;
}
int nID = atoi ( args [ 1 ] ) ;
CBaseEntity * pEnt = g_ServerTools . FindEntityByHammerID ( nID ) ;
if ( ! pEnt )
{
Msg ( " Entity ID %d not found. \n " , nID ) ;
return ;
}
int nArg = 2 ;
while ( nArg < args . ArgC ( ) )
{
const char * pszKey = args [ nArg ] ;
const char * pszValue = args [ nArg + 1 ] ;
nArg + = 2 ;
g_ServerTools . SetKeyValue ( pEnt , pszKey , pszValue ) ;
}
}
static ConCommand ent_keyvalue ( " ent_keyvalue " , CC_Ent_Keyvalue , " Applies the comma delimited key=value pairs to the entity with the given Hammer ID. \n \t Format: ent_keyvalue <entity id> <key1> <value1> <key2> <value2> ... <keyN> <valueN> \n " , FCVAR_CHEAT ) ;