2023-05-06 16:23:56 +02:00
|
|
|
//===============================================================================//
|
|
|
|
//
|
|
|
|
// Purpose: VSquirrel VM
|
|
|
|
//
|
|
|
|
//===============================================================================//
|
|
|
|
#include "core/stdafx.h"
|
|
|
|
#include "vscript/vscript.h"
|
|
|
|
#include "pluginsystem/modsystem.h"
|
2023-05-10 00:05:38 +02:00
|
|
|
#include "vsquirrel.h"
|
2023-05-06 16:23:56 +02:00
|
|
|
|
2023-07-18 00:17:49 +02:00
|
|
|
// Callbacks for registering abstracted script functions.
|
|
|
|
void(*ServerScriptRegister_Callback)(CSquirrelVM* s) = nullptr;
|
|
|
|
void(*ClientScriptRegister_Callback)(CSquirrelVM* s) = nullptr;
|
|
|
|
void(*UiScriptRegister_Callback)(CSquirrelVM* s) = nullptr;
|
|
|
|
|
2023-05-06 16:23:56 +02:00
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Initialises a Squirrel VM instance
|
|
|
|
// Output : True on success, false on failure
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
SQBool CSquirrelVM::Init(CSquirrelVM* s, SQCONTEXT context, SQFloat curTime)
|
|
|
|
{
|
|
|
|
// original func always returns true, added check just in case.
|
|
|
|
if (!v_CSquirrelVM_Init(s, context, curTime))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DevMsg((eDLL_T)context, "Created %s VM: '0x%p'\n", s->GetVM()->_sharedstate->_contextname, s);
|
|
|
|
|
|
|
|
switch (context)
|
|
|
|
{
|
|
|
|
#ifndef CLIENT_DLL
|
|
|
|
case SQCONTEXT::SERVER:
|
|
|
|
g_pServerScript = s;
|
2023-07-18 00:17:49 +02:00
|
|
|
if (ServerScriptRegister_Callback)
|
|
|
|
ServerScriptRegister_Callback(s);
|
|
|
|
|
2023-05-06 16:23:56 +02:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifndef DEDICATED
|
|
|
|
case SQCONTEXT::CLIENT:
|
|
|
|
g_pClientScript = s;
|
2023-07-18 00:17:49 +02:00
|
|
|
if (ClientScriptRegister_Callback)
|
|
|
|
ClientScriptRegister_Callback(s);
|
|
|
|
|
2023-05-06 16:23:56 +02:00
|
|
|
break;
|
|
|
|
case SQCONTEXT::UI:
|
|
|
|
g_pUIScript = s;
|
2023-07-18 00:17:49 +02:00
|
|
|
if (UiScriptRegister_Callback)
|
|
|
|
UiScriptRegister_Callback(s);
|
|
|
|
|
2023-05-06 16:23:56 +02:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: destroys the signal entry list head
|
|
|
|
// Input : *s -
|
|
|
|
// v -
|
|
|
|
// f -
|
|
|
|
// Output : true on success, false otherwise
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
SQBool CSquirrelVM::DestroySignalEntryListHead(CSquirrelVM* s, HSQUIRRELVM v, SQFloat f)
|
|
|
|
{
|
|
|
|
SQBool result = v_CSquirrelVM_DestroySignalEntryListHead(s, v, f);
|
|
|
|
s->RegisterConstant("DEVELOPER", developer->GetInt());
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: registers a global constant
|
|
|
|
// Input : *name -
|
|
|
|
// value -
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
SQRESULT CSquirrelVM::RegisterConstant(const SQChar* name, SQInteger value)
|
|
|
|
{
|
|
|
|
return v_CSquirrelVM_RegisterConstant(this, name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: registers a code function
|
|
|
|
// Input : *s -
|
|
|
|
// *scriptName -
|
|
|
|
// *nativeName -
|
|
|
|
// *helpString -
|
|
|
|
// *returnString -
|
|
|
|
// *parameters -
|
|
|
|
// *function -
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
SQRESULT CSquirrelVM::RegisterFunction(const SQChar* scriptName, const SQChar* nativeName,
|
|
|
|
const SQChar* helpString, const SQChar* returnString, const SQChar* parameters, void* function)
|
|
|
|
{
|
|
|
|
ScriptFunctionBinding_t binding;
|
|
|
|
binding.Init(scriptName, nativeName, helpString, returnString, parameters, 5, function);
|
|
|
|
|
|
|
|
SQRESULT results = v_CSquirrelVM_RegisterFunction(this, &binding, 1);
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: sets current VM as the global precompiler
|
|
|
|
// Input : *name -
|
|
|
|
// value -
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
void CSquirrelVM::SetAsCompiler(RSON::Node_t* rson)
|
|
|
|
{
|
|
|
|
const SQCONTEXT context = GetContext();
|
|
|
|
switch (context)
|
|
|
|
{
|
|
|
|
#ifndef CLIENT_DLL
|
|
|
|
case SQCONTEXT::SERVER:
|
|
|
|
{
|
|
|
|
v_Script_SetServerPrecompiler(context, rson);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef DEDICATED
|
|
|
|
case SQCONTEXT::CLIENT:
|
|
|
|
case SQCONTEXT::UI:
|
|
|
|
{
|
|
|
|
v_Script_SetClientPrecompiler(context, rson);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
// Purpose: Precompiles mod scripts
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
void CSquirrelVM::CompileModScripts()
|
|
|
|
{
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
FOR_EACH_VEC(g_pModSystem->GetModList(), i)
|
2023-05-06 16:23:56 +02:00
|
|
|
{
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
const CModSystem::ModInstance_t* mod = g_pModSystem->GetModList()[i];
|
|
|
|
|
|
|
|
if (!mod->IsEnabled())
|
2023-05-06 16:23:56 +02:00
|
|
|
continue;
|
|
|
|
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
if (!mod->m_bHasScriptCompileList)
|
2023-05-06 16:23:56 +02:00
|
|
|
continue;
|
|
|
|
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
// allocs parsed rson buffer
|
|
|
|
RSON::Node_t* rson = mod->LoadScriptCompileList();
|
2023-05-06 16:23:56 +02:00
|
|
|
|
|
|
|
if (!rson)
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
Error(GetVM()->GetNativeContext(), NO_ERROR,
|
|
|
|
"%s: Failed to load RSON file '%s'\n",
|
|
|
|
__FUNCTION__, mod->GetScriptCompileListPath().Get());
|
2023-05-06 16:23:56 +02:00
|
|
|
|
|
|
|
const char* scriptPathArray[MAX_PRECOMPILED_SCRIPTS];
|
|
|
|
int scriptCount = 0;
|
|
|
|
|
|
|
|
SetAsCompiler(rson);
|
|
|
|
|
|
|
|
if (Script_ParseScriptList(
|
|
|
|
GetContext(),
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
mod->GetScriptCompileListPath().Get(),
|
2023-05-06 16:23:56 +02:00
|
|
|
rson,
|
|
|
|
(char**)scriptPathArray, &scriptCount,
|
|
|
|
nullptr, 0))
|
|
|
|
{
|
|
|
|
std::vector<char*> newScriptPaths;
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
for (int j = 0; j < scriptCount; ++j)
|
2023-05-06 16:23:56 +02:00
|
|
|
{
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
// add "::MOD::" to the start of the script path so it can be
|
|
|
|
// identified from Script_LoadScript later, this is so we can
|
|
|
|
// avoid script naming conflicts by removing the engine's
|
|
|
|
// forced directory of "scripts/vscripts/" and adding the mod
|
|
|
|
// path to the start
|
|
|
|
CUtlString scriptPath;
|
|
|
|
scriptPath.Format("%s%s%s%s",
|
|
|
|
MOD_SCRIPT_PATH_IDENTIFIER, mod->GetBasePath().Get(),
|
|
|
|
GAME_SCRIPT_PATH, scriptPathArray[j]);
|
|
|
|
|
|
|
|
char* pszScriptPath = _strdup(scriptPath.Get());
|
2023-05-06 16:23:56 +02:00
|
|
|
|
|
|
|
// normalise slash direction
|
|
|
|
V_FixSlashes(pszScriptPath);
|
|
|
|
|
|
|
|
newScriptPaths.emplace_back(pszScriptPath);
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
scriptPathArray[j] = pszScriptPath;
|
2023-05-06 16:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (GetVM()->GetContext())
|
|
|
|
{
|
|
|
|
#ifndef CLIENT_DLL
|
|
|
|
case SQCONTEXT::SERVER:
|
|
|
|
{
|
|
|
|
v_CSquirrelVM_PrecompileServerScripts(this, GetContext(), (char**)scriptPathArray, scriptCount);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef DEDICATED
|
|
|
|
case SQCONTEXT::CLIENT:
|
|
|
|
case SQCONTEXT::UI:
|
|
|
|
{
|
|
|
|
v_CSquirrelVM_PrecompileClientScripts(this, GetContext(), (char**)scriptPathArray, scriptCount);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// clean up our allocated script paths
|
|
|
|
for (char* path : newScriptPaths)
|
|
|
|
{
|
Modsystem improvements
- Added command line parameter '-modsystem_debug' to allow debugging during init, as we initialize before the first Cbuf_Execute() call (responsible for executing command line post engine init).
- Added warning to 'CLocalize::LoadLocalizationFileLists', when a mod localization file fails to load.
- All mod instances are now added to a single vector, but their 'state' determine whether or not they are enabled. This allows for toggling them on while in-game in the future, without having to rebuild the engine mod list.
- Changed all filesystem calls to use that of the engine instead.
- Changed all container types to valve ones, to maintain compatibility with the filesystem of the engine, and perhaps other things in the future.
- Forced all loads/writes to "PLATFORM" path (this is where the 'mods' folder resides).
- Forced localization files to be only read from the mod instance's directory.
- Allocated each mod instance dynamically, and stored their pointers in the modlist vector to reduce memory overhead during the move operation to modlist, and potential growth of modlist vector (which if required, will reallocate everything, and thus move it all. This especially is expensive with nested vectors (CUtlVector anly supports being nested as a pointer)).
2023-07-09 22:49:46 +02:00
|
|
|
free(path);
|
2023-05-06 16:23:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-10 13:50:05 +02:00
|
|
|
RSON_Free(rson, AlignedMemAlloc());
|
|
|
|
AlignedMemAlloc()->Free(rson);
|
2023-05-06 16:23:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
void VSquirrel::Attach() const
|
|
|
|
{
|
|
|
|
DetourAttach((LPVOID*)&v_CSquirrelVM_Init, &CSquirrelVM::Init);
|
|
|
|
DetourAttach((LPVOID*)&v_CSquirrelVM_DestroySignalEntryListHead, &CSquirrelVM::DestroySignalEntryListHead);
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
void VSquirrel::Detach() const
|
|
|
|
{
|
|
|
|
DetourDetach((LPVOID*)&v_CSquirrelVM_Init, &CSquirrelVM::Init);
|
|
|
|
DetourDetach((LPVOID*)&v_CSquirrelVM_DestroySignalEntryListHead, &CSquirrelVM::DestroySignalEntryListHead);
|
|
|
|
}
|