mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-07-17 14:55:21 +00:00
701 lines
17 KiB
C++
701 lines
17 KiB
C++
//========== Copyright <20> 2008, Valve Corporation, All rights reserved. ========
|
||
//
|
||
// Purpose:
|
||
//
|
||
//=============================================================================
|
||
|
||
#include "cbase.h"
|
||
#include "vscript_shared.h"
|
||
#include "icommandline.h"
|
||
#include "tier1/utlbuffer.h"
|
||
#include "tier1/fmtstr.h"
|
||
#include "tier1/mapbase_con_groups.h"
|
||
#include "filesystem.h"
|
||
#include "characterset.h"
|
||
#include "isaverestore.h"
|
||
#include "gamerules.h"
|
||
#ifdef MAPBASE_VSCRIPT
|
||
#include "mapbase/vscript_singletons.h"
|
||
#endif
|
||
|
||
IScriptVM * g_pScriptVM;
|
||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||
|
||
// #define VMPROFILE 1
|
||
|
||
#ifdef VMPROFILE
|
||
|
||
#define VMPROF_START float debugStartTime = Plat_FloatTime();
|
||
#define VMPROF_SHOW( funcname, funcdesc ) DevMsg("***VSCRIPT PROFILE***: %s %s: %6.4f milliseconds\n", (##funcname), (##funcdesc), (Plat_FloatTime() - debugStartTime)*1000.0 );
|
||
|
||
#else // !VMPROFILE
|
||
|
||
#define VMPROF_START
|
||
#define VMPROF_SHOW
|
||
|
||
#endif // VMPROFILE
|
||
|
||
#ifdef MAPBASE_VSCRIPT
|
||
// This is to ensure a dependency exists between the vscript library and the game DLLs
|
||
extern int vscript_token;
|
||
int vscript_token_hack = vscript_token;
|
||
#endif
|
||
|
||
static const char *pszExtensions[] =
|
||
{
|
||
"", // SL_NONE
|
||
".gm", // SL_GAMEMONKEY
|
||
".nut", // SL_SQUIRREL
|
||
".lua", // SL_LUA
|
||
".py", // SL_PYTHON
|
||
};
|
||
|
||
|
||
|
||
HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing )
|
||
{
|
||
if ( !g_pScriptVM )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
const char *pszVMExtension = pszExtensions[g_pScriptVM->GetLanguage()];
|
||
const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' );
|
||
if ( pszIncomingExtension && V_strcmp( pszIncomingExtension, pszVMExtension ) != 0 )
|
||
{
|
||
#ifdef MAPBASE_VSCRIPT
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type (\"%s\", from \"%s\") does not match VM type (\"%s\")\n", pszIncomingExtension, pszScriptName, pszVMExtension );
|
||
#else
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type does not match VM type\n" );
|
||
#endif
|
||
return NULL;
|
||
}
|
||
|
||
CFmtStr scriptPath;
|
||
if ( pszIncomingExtension )
|
||
{
|
||
scriptPath.sprintf( "scripts/vscripts/%s", pszScriptName );
|
||
}
|
||
else
|
||
{
|
||
scriptPath.sprintf( "scripts/vscripts/%s%s", pszScriptName, pszVMExtension );
|
||
}
|
||
|
||
const char *pBase;
|
||
CUtlBuffer bufferScript;
|
||
|
||
if ( g_pScriptVM->GetLanguage() == SL_PYTHON )
|
||
{
|
||
// python auto-loads raw or precompiled modules - don't load data here
|
||
pBase = NULL;
|
||
}
|
||
else
|
||
{
|
||
bool bResult = filesystem->ReadFile( scriptPath, "GAME", bufferScript );
|
||
|
||
#ifdef MAPBASE_VSCRIPT
|
||
if ( !bResult && bWarnMissing )
|
||
#else
|
||
if( !bResult )
|
||
#endif
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Script not found (%s) \n", scriptPath.operator const char *() );
|
||
Assert( "Error running script" );
|
||
}
|
||
|
||
pBase = (const char *) bufferScript.Base();
|
||
|
||
if ( !pBase || !*pBase )
|
||
{
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
|
||
const char *pszFilename = V_strrchr( scriptPath, '/' );
|
||
pszFilename++;
|
||
HSCRIPT hScript = g_pScriptVM->CompileScript( pBase, pszFilename );
|
||
if ( !hScript )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "FAILED to compile and execute script file named %s\n", scriptPath.operator const char *() );
|
||
Assert( "Error running script" );
|
||
}
|
||
return hScript;
|
||
}
|
||
|
||
static int g_ScriptServerRunScriptDepth;
|
||
|
||
bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing )
|
||
{
|
||
if ( !g_pScriptVM )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if ( !pszScriptName || !*pszScriptName )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Cannot run script: NULL script name\n" );
|
||
return false;
|
||
}
|
||
|
||
// Prevent infinite recursion in VM
|
||
if ( g_ScriptServerRunScriptDepth > 16 )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "IncludeScript stack overflow\n" );
|
||
return false;
|
||
}
|
||
|
||
g_ScriptServerRunScriptDepth++;
|
||
HSCRIPT hScript = VScriptCompileScript( pszScriptName, bWarnMissing );
|
||
bool bSuccess = false;
|
||
if ( hScript )
|
||
{
|
||
// player is not yet spawned, this block is always skipped.
|
||
// It is registered in CBasePlayer instead.
|
||
#ifndef MAPBASE
|
||
#ifdef GAME_DLL
|
||
if ( gpGlobals->maxClients == 1 )
|
||
{
|
||
CBaseEntity *pPlayer = UTIL_GetLocalPlayer();
|
||
if ( pPlayer )
|
||
{
|
||
g_pScriptVM->SetValue( "player", pPlayer->GetScriptInstance() );
|
||
}
|
||
}
|
||
#endif
|
||
#endif
|
||
bSuccess = ( g_pScriptVM->Run( hScript, hScope ) != SCRIPT_ERROR );
|
||
if ( !bSuccess )
|
||
{
|
||
Warning( "Error running script named %s\n", pszScriptName );
|
||
Assert( "Error running script" );
|
||
}
|
||
}
|
||
g_ScriptServerRunScriptDepth--;
|
||
return bSuccess;
|
||
}
|
||
|
||
|
||
#ifdef MAPBASE_VSCRIPT
|
||
|
||
//
|
||
// These functions are currently only used for "mapspawn_addon" scripts.
|
||
//
|
||
HSCRIPT VScriptCompileScriptAbsolute( const char *pszScriptName, bool bWarnMissing, const char *pszRootFolderName )
|
||
{
|
||
if ( !g_pScriptVM )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
const char *pszVMExtension = pszExtensions[g_pScriptVM->GetLanguage()];
|
||
const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' );
|
||
if ( pszIncomingExtension && V_strcmp( pszIncomingExtension, pszVMExtension ) != 0 )
|
||
{
|
||
// Account for cases where there is no extension and the folder names just have dots (e.g. ".local")
|
||
if ( strchr( pszIncomingExtension, CORRECT_PATH_SEPARATOR ) )
|
||
{
|
||
pszIncomingExtension = NULL;
|
||
}
|
||
else
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Script file type (\"%s\", from \"%s\") does not match VM type (\"%s\")\n", pszIncomingExtension, pszScriptName, pszVMExtension );
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
CFmtStr scriptPath;
|
||
if ( pszIncomingExtension )
|
||
{
|
||
scriptPath = pszScriptName;
|
||
}
|
||
else
|
||
{
|
||
scriptPath.sprintf( "%s%s", pszScriptName, pszVMExtension );
|
||
}
|
||
|
||
const char *pBase;
|
||
CUtlBuffer bufferScript;
|
||
|
||
if ( g_pScriptVM->GetLanguage() == SL_PYTHON )
|
||
{
|
||
// python auto-loads raw or precompiled modules - don't load data here
|
||
pBase = NULL;
|
||
}
|
||
else
|
||
{
|
||
bool bResult = filesystem->ReadFile( scriptPath, NULL, bufferScript );
|
||
|
||
if ( !bResult && bWarnMissing )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Script not found (%s) \n", scriptPath.operator const char *() );
|
||
Assert( "Error running script" );
|
||
}
|
||
|
||
pBase = (const char *) bufferScript.Base();
|
||
|
||
if ( !pBase || !*pBase )
|
||
{
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
// Attach the folder to the script ID
|
||
const char *pszFilename = V_strrchr( scriptPath, '/' );
|
||
scriptPath.sprintf( "%s%s", pszRootFolderName, pszFilename );
|
||
|
||
HSCRIPT hScript = g_pScriptVM->CompileScript( pBase, scriptPath );
|
||
if ( !hScript )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "FAILED to compile and execute script file named %s\n", scriptPath.operator const char *() );
|
||
Assert( "Error running script" );
|
||
}
|
||
return hScript;
|
||
}
|
||
|
||
bool VScriptRunScriptAbsolute( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing, const char *pszRootFolderName )
|
||
{
|
||
if ( !g_pScriptVM )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if ( !pszScriptName || !*pszScriptName )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Cannot run script: NULL script name\n" );
|
||
return false;
|
||
}
|
||
|
||
// Prevent infinite recursion in VM
|
||
if ( g_ScriptServerRunScriptDepth > 16 )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "IncludeScript stack overflow\n" );
|
||
return false;
|
||
}
|
||
|
||
g_ScriptServerRunScriptDepth++;
|
||
HSCRIPT hScript = VScriptCompileScriptAbsolute( pszScriptName, bWarnMissing, pszRootFolderName );
|
||
bool bSuccess = false;
|
||
if ( hScript )
|
||
{
|
||
bSuccess = ( g_pScriptVM->Run( hScript, hScope ) != SCRIPT_ERROR );
|
||
if ( !bSuccess )
|
||
{
|
||
Warning( "Error running script named %s\n", pszScriptName );
|
||
Assert( "Error running script" );
|
||
}
|
||
}
|
||
g_ScriptServerRunScriptDepth--;
|
||
return bSuccess;
|
||
}
|
||
#endif
|
||
|
||
|
||
#ifdef GAME_DLL
|
||
#define IsCommandIssuedByServerAdmin() UTIL_IsCommandIssuedByServerAdmin()
|
||
#else
|
||
#define IsCommandIssuedByServerAdmin() true
|
||
#endif
|
||
|
||
#ifdef CLIENT_DLL
|
||
CON_COMMAND_F( script_client, "Run the text as a script", FCVAR_CHEAT )
|
||
#else
|
||
CON_COMMAND_F( script, "Run the text as a script", FCVAR_CHEAT )
|
||
#endif
|
||
{
|
||
if ( !IsCommandIssuedByServerAdmin() )
|
||
return;
|
||
|
||
if ( !*args[1] )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "No function name specified\n" );
|
||
return;
|
||
}
|
||
|
||
if ( !g_pScriptVM )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
||
return;
|
||
}
|
||
|
||
const char *pszScript = args.GetCommandString();
|
||
|
||
#ifdef CLIENT_DLL
|
||
pszScript += 13;
|
||
#else
|
||
pszScript += 6;
|
||
#endif
|
||
|
||
while ( *pszScript == ' ' )
|
||
{
|
||
pszScript++;
|
||
}
|
||
|
||
if ( !*pszScript )
|
||
{
|
||
return;
|
||
}
|
||
|
||
if ( *pszScript != '\"' )
|
||
{
|
||
g_pScriptVM->Run( pszScript );
|
||
}
|
||
else
|
||
{
|
||
pszScript++;
|
||
const char *pszEndQuote = pszScript;
|
||
while ( *pszEndQuote != '\"' )
|
||
{
|
||
pszEndQuote++;
|
||
}
|
||
if ( !*pszEndQuote )
|
||
{
|
||
return;
|
||
}
|
||
*((char *)pszEndQuote) = 0;
|
||
g_pScriptVM->Run( pszScript );
|
||
*((char *)pszEndQuote) = '\"';
|
||
}
|
||
}
|
||
|
||
#ifdef CLIENT_DLL
|
||
CON_COMMAND_F( script_execute_client, "Run a vscript file", FCVAR_CHEAT )
|
||
#else
|
||
CON_COMMAND_F( script_execute, "Run a vscript file", FCVAR_CHEAT )
|
||
#endif
|
||
{
|
||
if ( !IsCommandIssuedByServerAdmin() )
|
||
return;
|
||
|
||
if ( !*args[1] )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "No script specified\n" );
|
||
return;
|
||
}
|
||
|
||
if ( !g_pScriptVM )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
||
return;
|
||
}
|
||
|
||
VScriptRunScript( args[1], true );
|
||
}
|
||
|
||
#ifdef CLIENT_DLL
|
||
CON_COMMAND_F( script_debug_client, "Connect the vscript VM to the script debugger", FCVAR_CHEAT )
|
||
#else
|
||
CON_COMMAND_F( script_debug, "Connect the vscript VM to the script debugger", FCVAR_CHEAT )
|
||
#endif
|
||
{
|
||
if ( !IsCommandIssuedByServerAdmin() )
|
||
return;
|
||
|
||
if ( !g_pScriptVM )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
||
return;
|
||
}
|
||
g_pScriptVM->ConnectDebugger();
|
||
}
|
||
|
||
#ifdef CLIENT_DLL
|
||
CON_COMMAND_F( script_help_client, "Output help for script functions, optionally with a search string", FCVAR_CHEAT )
|
||
#else
|
||
CON_COMMAND_F( script_help, "Output help for script functions, optionally with a search string", FCVAR_CHEAT )
|
||
#endif
|
||
{
|
||
if ( !IsCommandIssuedByServerAdmin() )
|
||
return;
|
||
|
||
if ( !g_pScriptVM )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
||
return;
|
||
}
|
||
const char *pszArg1 = "*";
|
||
if ( *args[1] )
|
||
{
|
||
pszArg1 = args[1];
|
||
}
|
||
|
||
g_pScriptVM->Run( CFmtStr( "__Documentation.PrintHelp( \"%s\" );", pszArg1 ) );
|
||
}
|
||
|
||
#ifdef CLIENT_DLL
|
||
CON_COMMAND_F( script_dump_all_client, "Dump the state of the VM to the console", FCVAR_CHEAT )
|
||
#else
|
||
CON_COMMAND_F( script_dump_all, "Dump the state of the VM to the console", FCVAR_CHEAT )
|
||
#endif
|
||
{
|
||
if ( !IsCommandIssuedByServerAdmin() )
|
||
return;
|
||
|
||
if ( !g_pScriptVM )
|
||
{
|
||
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
||
return;
|
||
}
|
||
g_pScriptVM->DumpState();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
|
||
#ifdef MAPBASE_VSCRIPT
|
||
void RunAddonScripts()
|
||
{
|
||
char searchPaths[4096];
|
||
filesystem->GetSearchPath( "ADDON", true, searchPaths, sizeof( searchPaths ) );
|
||
|
||
for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) )
|
||
{
|
||
char folderName[MAX_PATH];
|
||
Q_FileBase( path, folderName, sizeof( folderName ) );
|
||
|
||
// mapspawn_addon
|
||
char fullpath[MAX_PATH];
|
||
Q_snprintf( fullpath, sizeof( fullpath ), "%sscripts/vscripts/mapspawn_addon", path );
|
||
Q_FixSlashes( fullpath );
|
||
|
||
VScriptRunScriptAbsolute( fullpath, NULL, false, folderName );
|
||
}
|
||
}
|
||
|
||
// UNDONE: "autorun" folder
|
||
/*
|
||
void RunAutorunScripts()
|
||
{
|
||
FileFindHandle_t fileHandle;
|
||
char szDirectory[MAX_PATH];
|
||
char szFileName[MAX_PATH];
|
||
char szPartialScriptPath[MAX_PATH];
|
||
|
||
// TODO: Scanning for VM extension would make this more efficient
|
||
Q_strncpy( szDirectory, "scripts/vscripts/autorun/*", sizeof( szDirectory ) );
|
||
|
||
const char *pszScriptFile = filesystem->FindFirst( szDirectory, &fileHandle );
|
||
while (pszScriptFile && fileHandle != FILESYSTEM_INVALID_FIND_HANDLE)
|
||
{
|
||
Q_FileBase( pszScriptFile, szFileName, sizeof( szFileName ) );
|
||
Q_snprintf( szPartialScriptPath, sizeof( szPartialScriptPath ), "autorun/%s", szFileName );
|
||
VScriptRunScript( szPartialScriptPath );
|
||
|
||
pszScriptFile = filesystem->FindNext( fileHandle );
|
||
}
|
||
|
||
// Non-shared scripts
|
||
#ifdef CLIENT_DLL
|
||
Q_strncpy( szDirectory, "scripts/vscripts/autorun/client/*", sizeof( szDirectory ) );
|
||
#else
|
||
Q_strncpy( szDirectory, "scripts/vscripts/autorun/server/*", sizeof( szDirectory ) );
|
||
#endif
|
||
|
||
pszScriptFile = filesystem->FindFirst( szDirectory, &fileHandle );
|
||
while (pszScriptFile && fileHandle != FILESYSTEM_INVALID_FIND_HANDLE)
|
||
{
|
||
Q_FileBase( pszScriptFile, szFileName, sizeof( szFileName ) );
|
||
#ifdef CLIENT_DLL
|
||
Q_snprintf( szPartialScriptPath, sizeof( szPartialScriptPath ), "autorun/client/%s", szFileName );
|
||
#else
|
||
Q_snprintf( szPartialScriptPath, sizeof( szPartialScriptPath ), "autorun/server/%s", szFileName );
|
||
#endif
|
||
VScriptRunScript( szPartialScriptPath );
|
||
|
||
pszScriptFile = filesystem->FindNext( fileHandle );
|
||
}
|
||
}
|
||
*/
|
||
#endif
|
||
|
||
//-----------------------------------------------------------------------------
|
||
|
||
static short VSCRIPT_SERVER_SAVE_RESTORE_VERSION = 2;
|
||
|
||
//-----------------------------------------------------------------------------
|
||
|
||
class CVScriptSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
|
||
{
|
||
public:
|
||
CVScriptSaveRestoreBlockHandler() :
|
||
m_InstanceMap( DefLessFunc(const char *) )
|
||
{
|
||
}
|
||
const char *GetBlockName()
|
||
{
|
||
#ifdef CLIENT_DLL
|
||
return "VScriptClient";
|
||
#else
|
||
return "VScriptServer";
|
||
#endif
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
void Save( ISave *pSave )
|
||
{
|
||
pSave->StartBlock();
|
||
|
||
int temp = g_pScriptVM != NULL;
|
||
pSave->WriteInt( &temp );
|
||
if ( g_pScriptVM )
|
||
{
|
||
temp = g_pScriptVM->GetLanguage();
|
||
pSave->WriteInt( &temp );
|
||
CUtlBuffer buffer;
|
||
g_pScriptVM->WriteState( &buffer );
|
||
temp = buffer.TellPut();
|
||
pSave->WriteInt( &temp );
|
||
if ( temp > 0 )
|
||
{
|
||
pSave->WriteData( (const char *)buffer.Base(), temp );
|
||
}
|
||
}
|
||
|
||
pSave->EndBlock();
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
void WriteSaveHeaders( ISave *pSave )
|
||
{
|
||
pSave->WriteShort( &VSCRIPT_SERVER_SAVE_RESTORE_VERSION );
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
void ReadRestoreHeaders( IRestore *pRestore )
|
||
{
|
||
// No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
|
||
short version;
|
||
pRestore->ReadShort( &version );
|
||
m_fDoLoad = ( version == VSCRIPT_SERVER_SAVE_RESTORE_VERSION );
|
||
}
|
||
|
||
//---------------------------------
|
||
|
||
void Restore( IRestore *pRestore, bool createPlayers )
|
||
{
|
||
if ( !m_fDoLoad && g_pScriptVM )
|
||
{
|
||
return;
|
||
}
|
||
#ifdef CLIENT_DLL
|
||
C_BaseEntity *pEnt = ClientEntityList().FirstBaseEntity();
|
||
#else
|
||
CBaseEntity *pEnt = gEntList.FirstEnt();
|
||
#endif
|
||
while ( pEnt )
|
||
{
|
||
if ( pEnt->m_iszScriptId != NULL_STRING )
|
||
{
|
||
#ifndef MAPBASE_VSCRIPT
|
||
g_pScriptVM->RegisterClass( pEnt->GetScriptDesc() );
|
||
#endif
|
||
m_InstanceMap.Insert( STRING( pEnt->m_iszScriptId ), pEnt );
|
||
}
|
||
#ifdef CLIENT_DLL
|
||
pEnt = ClientEntityList().NextBaseEntity( pEnt );
|
||
#else
|
||
pEnt = gEntList.NextEnt( pEnt );
|
||
#endif
|
||
}
|
||
|
||
pRestore->StartBlock();
|
||
if ( pRestore->ReadInt() && pRestore->ReadInt() == g_pScriptVM->GetLanguage() )
|
||
{
|
||
int nBytes = pRestore->ReadInt();
|
||
if ( nBytes > 0 )
|
||
{
|
||
CUtlBuffer buffer;
|
||
buffer.EnsureCapacity( nBytes );
|
||
pRestore->ReadData( (char *)buffer.AccessForDirectRead( nBytes ), nBytes, 0 );
|
||
g_pScriptVM->ReadState( &buffer );
|
||
}
|
||
}
|
||
pRestore->EndBlock();
|
||
}
|
||
|
||
void PostRestore( void )
|
||
{
|
||
for ( int i = m_InstanceMap.FirstInorder(); i != m_InstanceMap.InvalidIndex(); i = m_InstanceMap.NextInorder( i ) )
|
||
{
|
||
CBaseEntity *pEnt = m_InstanceMap[i];
|
||
if ( pEnt->m_hScriptInstance )
|
||
{
|
||
ScriptVariant_t variant;
|
||
if ( g_pScriptVM->GetValue( STRING(pEnt->m_iszScriptId), &variant ) && variant.m_type == FIELD_HSCRIPT )
|
||
{
|
||
pEnt->m_ScriptScope.Init( variant.m_hScript, false );
|
||
#ifndef CLIENT_DLL
|
||
pEnt->RunPrecacheScripts();
|
||
#endif
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Script system probably has no internal references
|
||
pEnt->m_iszScriptId = NULL_STRING;
|
||
}
|
||
}
|
||
m_InstanceMap.Purge();
|
||
|
||
#ifdef MAPBASE_VSCRIPT
|
||
GetScriptHookManager().OnRestore();
|
||
#endif
|
||
|
||
#if defined(MAPBASE_VSCRIPT) && defined(CLIENT_DLL)
|
||
VScriptSaveRestoreUtil_OnVMRestore();
|
||
#endif
|
||
}
|
||
|
||
|
||
CUtlMap<const char *, CBaseEntity *> m_InstanceMap;
|
||
|
||
private:
|
||
bool m_fDoLoad;
|
||
};
|
||
|
||
//-----------------------------------------------------------------------------
|
||
|
||
CVScriptSaveRestoreBlockHandler g_VScriptSaveRestoreBlockHandler;
|
||
|
||
//-------------------------------------
|
||
|
||
ISaveRestoreBlockHandler *GetVScriptSaveRestoreBlockHandler()
|
||
{
|
||
return &g_VScriptSaveRestoreBlockHandler;
|
||
}
|
||
|
||
bool CBaseEntityScriptInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
|
||
{
|
||
CBaseEntity *pEntity = (CBaseEntity *)p;
|
||
#ifdef CLIENT_DLL
|
||
if ( pEntity->GetEntityName() && pEntity->GetEntityName()[0] )
|
||
#else
|
||
if ( pEntity->GetEntityName() != NULL_STRING )
|
||
#endif
|
||
{
|
||
V_snprintf( pBuf, bufSize, "([%d] %s: %s)", pEntity->entindex(), pEntity->GetClassname(), STRING( pEntity->GetEntityName() ) );
|
||
}
|
||
else
|
||
{
|
||
V_snprintf( pBuf, bufSize, "([%d] %s)", pEntity->entindex(), pEntity->GetClassname() );
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void *CBaseEntityScriptInstanceHelper::BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId )
|
||
{
|
||
int iEntity = g_VScriptSaveRestoreBlockHandler.m_InstanceMap.Find( pszId );
|
||
if ( iEntity != g_VScriptSaveRestoreBlockHandler.m_InstanceMap.InvalidIndex() )
|
||
{
|
||
CBaseEntity *pEnt = g_VScriptSaveRestoreBlockHandler.m_InstanceMap[iEntity];
|
||
pEnt->m_hScriptInstance = hInstance;
|
||
return pEnt;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
|
||
CBaseEntityScriptInstanceHelper g_BaseEntityScriptInstanceHelper;
|