mirror of
https://github.com/celisej567/source-sdk-2013.git
synced 2026-09-23 20:09:45 +03:00
Added save/restore to client-side VScript
This commit is contained in:
@@ -161,6 +161,32 @@ public:
|
||||
|
||||
BaseClass::ClientThink();
|
||||
}
|
||||
|
||||
void OnSave()
|
||||
{
|
||||
// HACKHACK: Save the next think in the VM since the VM is saved
|
||||
if (m_bClientThink)
|
||||
{
|
||||
g_pScriptVM->SetValue( m_ScriptScope, "__c_think", GetNextThink() );
|
||||
}
|
||||
|
||||
BaseClass::OnSave();
|
||||
}
|
||||
|
||||
void OnRestore()
|
||||
{
|
||||
// HACKHACK: See OnSave()
|
||||
if (m_bClientThink)
|
||||
{
|
||||
ScriptVariant_t flNextThink;
|
||||
if (g_pScriptVM->GetValue( m_ScriptScope, "__c_think", &flNextThink ))
|
||||
{
|
||||
SetNextClientThink( flNextThink );
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::OnRestore();
|
||||
}
|
||||
#else
|
||||
void InputCallScriptFunctionClient( inputdata_t &inputdata )
|
||||
{
|
||||
|
||||
@@ -757,7 +757,12 @@ public: // IGameSystem
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
// On the client, OnRestore() is called before VScript is actually restored, so this has to be called manually from VScript save/restore instead
|
||||
void OnVMRestore()
|
||||
#else
|
||||
void OnRestore()
|
||||
#endif
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
{
|
||||
@@ -783,6 +788,13 @@ private:
|
||||
|
||||
} g_ScriptSaveRestoreUtil;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
void VScriptSaveRestoreUtil_OnVMRestore()
|
||||
{
|
||||
g_ScriptSaveRestoreUtil.OnVMRestore();
|
||||
}
|
||||
#endif
|
||||
|
||||
CUtlMap< unsigned int, KeyValues* > CScriptSaveRestoreUtil::m_Lookup( DefLessFunc(unsigned int) );
|
||||
StringHashFunctor CScriptSaveRestoreUtil::Hash;
|
||||
|
||||
@@ -1164,6 +1176,13 @@ void CNetMsgScriptHelper::RecieveMessage( bf_read &msg )
|
||||
|
||||
word hash = m_MsgIn_()ReadWord();
|
||||
|
||||
// Don't do anything if there's no VM here. This can happen if a message from the server goes to a VM-less client, or vice versa.
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
CGWarning( 0, CON_GROUP_VSCRIPT, "CNetMsgScriptHelper: No VM on receiving side\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptVariant_t hfn;
|
||||
if ( g_pScriptVM->GetValue( m_Hooks, hash, &hfn ) )
|
||||
{
|
||||
|
||||
@@ -136,4 +136,8 @@ public:
|
||||
|
||||
extern CNetMsgScriptHelper *g_ScriptNetMsg;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
void VScriptSaveRestoreUtil_OnVMRestore();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#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 * );
|
||||
@@ -278,3 +281,187 @@ CON_COMMAND_SHARED( script_dump_all, "Dump the state of the VM to the console" )
|
||||
}
|
||||
g_pScriptVM->DumpState();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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();
|
||||
|
||||
#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;
|
||||
if ( pEntity->GetEntityName() != NULL_STRING )
|
||||
{
|
||||
V_snprintf( pBuf, bufSize, "([%d] %s: %s)", pEntity->entindex(), STRING(pEntity->m_iClassname), STRING( pEntity->GetEntityName() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
V_snprintf( pBuf, bufSize, "([%d] %s)", pEntity->entindex(), STRING(pEntity->m_iClassname) );
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -31,6 +31,17 @@ inline bool VScriptRunScript( const char *pszScriptName, bool bWarnMissing = fal
|
||||
// Only allow scripts to create entities during map initialization
|
||||
bool IsEntityCreationAllowedInScripts( void );
|
||||
|
||||
class ISaveRestoreBlockHandler;
|
||||
ISaveRestoreBlockHandler *GetVScriptSaveRestoreBlockHandler();
|
||||
|
||||
class CBaseEntityScriptInstanceHelper : public IScriptInstanceHelper
|
||||
{
|
||||
bool ToString( void *p, char *pBuf, int bufSize );
|
||||
void *BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId );
|
||||
};
|
||||
|
||||
extern CBaseEntityScriptInstanceHelper g_BaseEntityScriptInstanceHelper;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
void RegisterSharedScriptConstants();
|
||||
void RegisterSharedScriptFunctions();
|
||||
|
||||
Reference in New Issue
Block a user