Skip to content

Commit da56544

Browse files
Add forward and native on script vm initialized (#14)
1 parent 9fed663 commit da56544

5 files changed

Lines changed: 77 additions & 16 deletions

File tree

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ All builds can be found [here](https://github.com/FortyTwoFortyTwo/VScript/actio
1717

1818
Compiles and executes a script code with params and returns, helpful when `RunScriptCode` input does not support receiving returns.
1919
```sp
20-
public void OnPluginStart()
20+
public void OnAllPluginsLoaded()
2121
{
2222
HSCRIPT script = VScript_CompileScript("printl(\"Wow a message!\"); return 4242; function PrintMessage(param) { printl(param) }");
2323
@@ -44,7 +44,7 @@ This allows to directly call or detour a function without needing to manually ge
4444
```sp
4545
Handle g_SDKCallGetAngles;
4646
47-
public void OnPluginStart()
47+
public void OnAllPluginsLoaded()
4848
{
4949
VScriptFunction func = VScript_GetClassFunction("CBaseEntity", "GetAngles");
5050
g_SDKCallGetAngles = func.CreateSDKCall();
@@ -77,18 +77,22 @@ Creates a new native function where scripts can make use of it. Does nothing by
7777
```sp
7878
VScriptFunction g_NewFunction;
7979
80-
public void OnPluginStart()
80+
public void OnAllPluginsLoaded()
8181
{
8282
// Create a new function, or get an existing one if name already exists
8383
g_NewFunction = VScript_CreateGlobalFunction("NewFunction");
8484
g_NewFunction.SetParam(1, FIELD_FLOAT);
8585
g_NewFunction.Return = FIELD_INTEGER;
8686
g_NewFunction.SetFunctionEmpty();
87+
88+
// If plugin were to be lateloaded and that script vm is already initialized, just manually call it.
89+
if (VScript_IsScriptVMInitialized())
90+
VScript_OnScriptVMInitialized();
8791
}
8892
89-
public void OnMapStart()
93+
public void VScript_OnScriptVMInitialized()
9094
{
91-
// Global function need to be registered everytime g_pScriptVM has been reset, which usually happens on mapchange
95+
// Global function need to be registered everytime g_pScriptVM has been reset, which happens right before this forward
9296
g_NewFunction.Register();
9397
}
9498
```

scripting/include/vscript.inc

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ methodmap VScriptFunction < Address
225225
// @param from A function to copy from.
226226
public native void CopyFrom(VScriptFunction from);
227227

228-
// Register this as a global function until when g_pScriptVM has been reset.
228+
// Register this as a global function until when g_pScriptVM has been reset. This should be called inside VScript_OnScriptVMInitialized forward.
229229
public native void Register();
230230

231231
// Creates an SDKCall with parameters auto filled
@@ -302,7 +302,7 @@ methodmap VScriptClass < Address
302302
// @return Address of VScriptFunction.
303303
public native VScriptFunction CreateFunction();
304304

305-
// Register this class as an instance. This does not require calling VScript_ResetScriptVM unless if modifications were made afterward.
305+
// Register this class as an instance. This should be used inside VScript_OnScriptVMInitialized forward.
306306
//
307307
// @param instance Name of an instance in script.
308308
// @return Created HSCRIPT instance.
@@ -410,6 +410,20 @@ methodmap VScriptExecute < Handle
410410
public native void GetReturnVector(float buffer[3]);
411411
}
412412

413+
414+
/**
415+
* Called when g_pScriptVM has been fully initialized, this is where VScriptClass.RegisterInstance and VScriptFunction.Register should be called
416+
* @note This forward does not get called on plugin lateload, use VScript_IsScriptVMInitialized to determine whenever to manually call this forward
417+
*/
418+
forward void VScript_OnScriptVMInitialized();
419+
420+
/**
421+
* Returns whenever g_pScriptVM has been initialized, useful for plugin start to determine whenever to call VScript_ResetScriptVM or VScript_OnScriptVMInitialized if this were to return true
422+
*
423+
* @return True if script vm is initialized, false otherwise
424+
*/
425+
native bool VScript_IsScriptVMInitialized();
426+
413427
/**
414428
* Deletes g_pScriptVM and creates a new one. This should be used when VScriptClass or VScriptFunction has been modified, including adding new functions to class
415429
*/
@@ -675,6 +689,7 @@ public void __pl_vscript_SetNTVOptional()
675689
MarkNativeAsOptional("VScriptExecute.GetReturnString");
676690
MarkNativeAsOptional("VScriptExecute.GetReturnVector");
677691

692+
MarkNativeAsOptional("VScript_IsScriptVMInitialized");
678693
MarkNativeAsOptional("VScript_ResetScriptVM");
679694
MarkNativeAsOptional("VScript_CompileScript");
680695
MarkNativeAsOptional("VScript_CompileScriptFile");

scripting/vscript.sp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include "include/vscript.inc"
44

5-
#define PLUGIN_VERSION "1.9.0"
5+
#define PLUGIN_VERSION "1.9.1"
66
#define PLUGIN_VERSION_REVISION "manual"
77

88
char g_sOperatingSystem[16];
@@ -120,6 +120,7 @@ public APLRes AskPluginLoad2(Handle hMyself, bool bLate, char[] sError, int iLen
120120
CreateNative("VScriptExecute.GetReturnString", Native_Execute_GetReturnString);
121121
CreateNative("VScriptExecute.GetReturnVector", Native_Execute_GetReturnVector);
122122

123+
CreateNative("VScript_IsScriptVMInitialized", Native_IsScriptVMInitialized);
123124
CreateNative("VScript_ResetScriptVM", Native_ResetScriptVM);
124125
CreateNative("VScript_CompileScript", Native_CompileScript);
125126
CreateNative("VScript_CompileScriptFile", Native_CompileScriptFile);
@@ -763,6 +764,11 @@ public any Native_Execute_GetReturnVector(Handle hPlugin, int iNumParams)
763764
return 0;
764765
}
765766

767+
public any Native_IsScriptVMInitialized(Handle hPlugin, int iNumParams)
768+
{
769+
return GetScriptVM() != Address_Null;
770+
}
771+
766772
public any Native_ResetScriptVM(Handle hPlugin, int iNumParams)
767773
{
768774
if (!g_bAllowResetScriptVM)

scripting/vscript/list.sp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
static int g_iInitializing;
2+
static GlobalForward g_fOnScriptVMInitialized;
3+
14
static ArrayList g_aGlobalFunctions;
25
static ArrayList g_aClasses;
36

47
void List_LoadGamedata(GameData hGameData)
58
{
9+
g_fOnScriptVMInitialized = new GlobalForward("VScript_OnScriptVMInitialized", ET_Ignore);
10+
611
DynamicDetour hDetour;
712

813
hDetour = VTable_CreateDetour(hGameData, "IScriptVM", "Init", ReturnType_Bool);
@@ -13,6 +18,9 @@ void List_LoadGamedata(GameData hGameData)
1318

1419
hDetour = VTable_CreateDetour(hGameData, "IScriptVM", "RegisterClass", ReturnType_Bool, HookParamType_Int);
1520
hDetour.Enable(Hook_Post, List_RegisterClass);
21+
22+
hDetour = VTable_CreateDetour(hGameData, "IGameSystem", "LevelInitPreEntity", ReturnType_Bool);
23+
hDetour.Enable(Hook_Post, List_LevelInitPreEntity);
1624
}
1725

1826
void List_LoadDefaults()
@@ -26,10 +34,12 @@ void List_LoadDefaults()
2634
HSCRIPT pScriptVM = GetScriptVM();
2735

2836
// Create new vscriptvm and set back, so we can collect all of the default stuffs
37+
g_iInitializing = -1; // Don't want to call forward from this
2938
SetScriptVM(view_as<HSCRIPT>(Address_Null));
3039
GameSystem_ServerInit();
3140
GameSystem_ServerTerm();
3241
SetScriptVM(pScriptVM);
42+
g_iInitializing = 0;
3343

3444
int iEntity = INVALID_ENT_REFERENCE;
3545
while ((iEntity = FindEntityByClassname(iEntity, "*")) != INVALID_ENT_REFERENCE)
@@ -38,6 +48,9 @@ void List_LoadDefaults()
3848

3949
MRESReturn List_Init(Address pScriptVM, DHookReturn hReturn)
4050
{
51+
if (g_iInitializing == 0)
52+
g_iInitializing = 1;
53+
4154
g_aGlobalFunctions.Clear();
4255
g_aClasses.Clear();
4356
return MRES_Ignored;
@@ -63,6 +76,18 @@ MRESReturn List_RegisterClass(Address pScriptVM, DHookReturn hReturn, DHookParam
6376
return MRES_Ignored;
6477
}
6578

79+
MRESReturn List_LevelInitPreEntity(Address pGameSystem, DHookReturn hReturn)
80+
{
81+
if (g_iInitializing == 1)
82+
{
83+
g_iInitializing = 0;
84+
Call_StartForward(g_fOnScriptVMInitialized);
85+
Call_Finish();
86+
}
87+
88+
return MRES_Ignored;
89+
}
90+
6691
void List_AddEntityScriptDesc(int iEntity)
6792
{
6893
VScriptClass pClass = Entity_GetScriptDesc(iEntity);

scripting/vscript_test.sp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,15 @@ public Plugin myinfo =
2424
url = "https://github.com/FortyTwoFortyTwo/VScript",
2525
};
2626

27-
public void OnMapStart()
27+
public void OnAllPluginsLoaded()
2828
{
29-
VScriptFunction pFunction;
30-
VScriptExecute hExecute;
31-
int iValue;
32-
char sBuffer[256];
33-
float vecResult[3];
29+
// Best to do it in OnAllPluginsLoaded, to ensure that vscript plugin is fully loaded
3430

3531
/*
3632
* Test member call with bunch of params, this first because of resetting g_pScriptVM
3733
*/
3834

39-
pFunction = VScript_CreateClassFunction("CBaseEntity", "BunchOfParams");
35+
VScriptFunction pFunction = VScript_CreateClassFunction("CBaseEntity", "BunchOfParams");
4036
pFunction.SetParam(1, FIELD_INTEGER);
4137
pFunction.SetParam(2, FIELD_FLOAT);
4238
pFunction.SetParam(3, FIELD_BOOLEAN);
@@ -45,8 +41,22 @@ public void OnMapStart()
4541

4642
pFunction.Return = FIELD_FLOAT;
4743
pFunction.SetFunctionEmpty();
48-
VScript_ResetScriptVM();
4944

45+
// If script vm is already initialized, force reset it as we can use modified CBaseEntity.
46+
// If were only calling VScriptClass.RegisterInstance or VScriptFunction.Register, only need to manually call VScript_OnScriptVMInitialized() without resetting it.
47+
if (VScript_IsScriptVMInitialized())
48+
VScript_ResetScriptVM();
49+
}
50+
51+
public void VScript_OnScriptVMInitialized()
52+
{
53+
VScriptFunction pFunction;
54+
VScriptExecute hExecute;
55+
int iValue;
56+
char sBuffer[256];
57+
float vecResult[3];
58+
59+
// BunchOfParams created at OnAllPluginsLoaded
5060
RunScript("function BunchOfParams(entity, param1, param2, param3, param4, param5) { return entity.BunchOfParams(param1, param2, param3, param4, param5) }");
5161

5262
// Setup VScript Call
@@ -63,6 +73,7 @@ public void OnMapStart()
6373
AssertInt(FIELD_VOID, hExecute.ReturnType);
6474

6575
// Now detour the newly created function
76+
pFunction = VScript_GetClassFunction("CBaseEntity", "BunchOfParams");
6677
pFunction.CreateDetour().Enable(Hook_Pre, Detour_BunchOfParams);
6778

6879
// Test again

0 commit comments

Comments
 (0)