Skip to content

Commit

Permalink
Return null from binding when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
FortyTwoFortyTwo committed Jun 22, 2023
1 parent 5eb3d35 commit 3b654f6
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 38 deletions.
4 changes: 2 additions & 2 deletions scripting/include/vscript.inc
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ methodmap VScriptFunction < Address
}

// Set the function as empty, doing nothing. This is used when wanting to create a new function only to be used for detour.
// This MUST be used after return and params has been set. If return is not void, 0 is returned by default.
// This MUST be used after return and params has been set. If return is not void, 0 or null is returned by default.
public native void SetFunctionEmpty();

// Gets/Sets the return field type
Expand Down Expand Up @@ -313,7 +313,7 @@ methodmap VScriptExecute < Handle
// @return Script status after executed.
public native ScriptStatus_t Execute();

// Gets return field type
// Gets return field type, FIELD_VOID if null
property fieldtype_t ReturnType
{
public native get();
Expand Down
12 changes: 11 additions & 1 deletion scripting/vscript.sp
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,17 @@ public any Native_Function_CopyFrom(Handle hPlugin, int iNumParams)

public any Native_Function_Register(Handle hPlugin, int iNumParams)
{
Function_Register(GetNativeCell(1));
VScriptFunction pFunction = GetNativeCell(1);

char sBuffer[64];
Function_GetScriptName(pFunction, sBuffer, sizeof(sBuffer));
if (!sBuffer[0])
ThrowNativeError(SP_ERROR_NATIVE, "Function must have script name set before registering it");

if (Function_GetFunction(pFunction) == Address_Null)
ThrowNativeError(SP_ERROR_NATIVE, "Function must have address set before registering it");

Function_Register(pFunction);
return 0;
}

Expand Down
36 changes: 27 additions & 9 deletions scripting/vscript/binding.sp
Original file line number Diff line number Diff line change
Expand Up @@ -154,21 +154,39 @@ public MRESReturn Binding_Detour(DHookReturn hReturn, DHookParam hParam)
// No other simple way to do it /shrug
any nResult = SDKCall(info.hSDKCall, a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15]);

if (Field_GetSMField(nField) == SMField_Vector)
if (nField == FIELD_FLOAT)
{
// Prevent memory crash by creating new memory
float vecResult[3];
LoadVectorFromAddress(nResult, vecResult);
MemoryBlock hVector = CreateVectorMemory(vecResult);
nResult = hVector.Address;
hVector.Disown();
delete hVector;
if (nResult == 0xFFC00000)
{
// from SetFunctionEmpty returning "0", return null instead
nField = FIELD_VOID;
nResult = 0;
}
}
else if (Field_GetSMField(nField) == SMField_Vector)
{
if (nResult == 0)
{
// null vector
nField = FIELD_VOID;
nResult = 0;
}
else
{
// Prevent memory crash by creating new memory
float vecResult[3];
LoadVectorFromAddress(nResult, vecResult);
MemoryBlock hVector = CreateVectorMemory(vecResult);
nResult = hVector.Address;
hVector.Disown();
delete hVector;
}
}

if (pReturn)
{
StoreToAddress(pReturn + view_as<Address>(g_iScriptVariant_union), nResult, NumberType_Int32);
StoreToAddress(pReturn + view_as<Address>(g_iScriptVariant_type), Field_EnumToGame(nField), NumberType_Int16);
StoreToAddress(pReturn + view_as<Address>(g_iScriptVariant_union), nResult, NumberType_Int32);
}

hReturn.Value = true;
Expand Down
8 changes: 8 additions & 0 deletions scripting/vscript/execute.sp
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,16 @@ ScriptStatus_t Execute_Execute(VScriptExecute aExecute)
{
pReturn.GetVector(execute.nReturn.vecValue);
}
default:
{
execute.nReturn.nValue = 0;
}
}
}
else
{
execute.nReturn.nValue = 0;
}

execute.nReturn.nType = pReturn.nType;
Execute_SetInfo(aExecute, execute);
Expand Down
96 changes: 70 additions & 26 deletions scripting/vscript_test.sp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ public void OnMapStart()
SetVariantString("self.ValidateScriptScope()");
AcceptEntityInput(TEST_ENTITY, "RunScriptCode");

//Test this first, because of resetting g_pScriptVM
/*
* Test member call with bunch of params, this first because of resetting g_pScriptVM
*/

pFunction = VScript_GetClassFunction("CBaseEntity", "BunchOfParams");
if (!pFunction)
{
Expand All @@ -53,31 +56,37 @@ public void OnMapStart()
VScript_ResetScriptVM();
}

// Create a detour for newly created function
pFunction.CreateDetour().Enable(Hook_Pre, Detour_BunchOfParams);

// Test with SDKCall
float flValue = SDKCall(pFunction.CreateSDKCall(), TEST_ENTITY, TEST_INTEGER, TEST_FLOAT, TEST_BOOLEAN, TEST_CSTRING, TEST_VECTOR);
AssertFloat(TEST_FLOAT, flValue);

// Test again but with vscript
RunScript("function BunchOfParams(entity, param1, param2, param3, param4, param5) { return entity.BunchOfParams(param1, param2, param3, param4, param5) }");

// Setup VScript Call
hExecute = new VScriptExecute(HSCRIPT_RootTable.GetValue("BunchOfParams"));

hExecute.SetParam(1, FIELD_HSCRIPT, VScript_EntityToHScript(TEST_ENTITY));
hExecute.SetParam(2, FIELD_INTEGER, TEST_INTEGER);
hExecute.SetParam(3, FIELD_FLOAT, TEST_FLOAT);
hExecute.SetParam(4, FIELD_BOOLEAN, TEST_BOOLEAN);
hExecute.SetParamString(5, FIELD_CSTRING, TEST_CSTRING);
hExecute.SetParamVector(6, FIELD_VECTOR, TEST_VECTOR);

// Test binding without detour
hExecute.Execute();
AssertInt(FIELD_VOID, hExecute.ReturnType);

// Now detour the newly created function
pFunction.CreateDetour().Enable(Hook_Pre, Detour_BunchOfParams);

// Test again
hExecute.Execute();
AssertInt(FIELD_FLOAT, hExecute.ReturnType);
AssertFloat(TEST_FLOAT, hExecute.ReturnValue);
delete hExecute;

// Create AnotherRandomInt function that does the exact same as RandomInt
// Test with SDKCall
float flValue = SDKCall(pFunction.CreateSDKCall(), TEST_ENTITY, TEST_INTEGER, TEST_FLOAT, TEST_BOOLEAN, TEST_CSTRING, TEST_VECTOR);
AssertFloat(TEST_FLOAT, flValue);

/*
* Create AnotherRandomInt function that does the exact same as RandomInt
*/
pFunction = VScript_GetGlobalFunction("AnotherRandomInt");
if (!pFunction)
{
Expand All @@ -93,6 +102,10 @@ public void OnMapStart()
hDetour.Disable(Hook_Post, Detour_RandomInt);
AssertInt(TEST_INTEGER, iValue);

/*
* Test ReturnString function
*/

pFunction = VScript_GetGlobalFunction("ReturnString");
if (!pFunction)
{
Expand All @@ -103,19 +116,29 @@ public void OnMapStart()
pFunction.Register();
}

// Test ReturnString with SDKCall
hExecute = new VScriptExecute(HSCRIPT_RootTable.GetValue("ReturnString"));

// Binding without detour
hExecute.Execute();
AssertInt(FIELD_VOID, hExecute.ReturnType); // null

pFunction.CreateDetour().Enable(Hook_Pre, Detour_ReturnString);
SDKCall(pFunction.CreateSDKCall(), sBuffer, sizeof(sBuffer));
AssertString(TEST_CSTRING, sBuffer);

// Test ReturnString with VScript
hExecute = new VScriptExecute(HSCRIPT_RootTable.GetValue("ReturnString"));
// Binding with detour
hExecute.Execute();
AssertInt(FIELD_CSTRING, hExecute.ReturnType);
hExecute.GetReturnString(sBuffer, sizeof(sBuffer));
AssertString(TEST_CSTRING, sBuffer);
delete hExecute;

// Test ReturnString with SDKCall
SDKCall(pFunction.CreateSDKCall(), sBuffer, sizeof(sBuffer));
AssertString(TEST_CSTRING, sBuffer);

/*
* Test ReturnVector function
*/

pFunction = VScript_GetGlobalFunction("ReturnVector");
if (!pFunction)
{
Expand All @@ -126,27 +149,40 @@ public void OnMapStart()
pFunction.Register();
}

// Test ReturnVector with SDKCall
hExecute = new VScriptExecute(HSCRIPT_RootTable.GetValue("ReturnVector"));

// Binding without detour
hExecute.Execute();
AssertInt(FIELD_VOID, hExecute.ReturnType); // null

pFunction.CreateDetour().Enable(Hook_Pre, Detour_ReturnVector);
SDKCall(pFunction.CreateSDKCall(), vecResult);
AssertVector(TEST_VECTOR, vecResult);

// Test ReturnVector with VScript
hExecute = new VScriptExecute(HSCRIPT_RootTable.GetValue("ReturnVector"));
// Binding with detour
hExecute.Execute();
AssertInt(FIELD_VECTOR, hExecute.ReturnType);
hExecute.GetReturnVector(vecResult);
AssertVector(TEST_VECTOR, vecResult);
delete hExecute;

// Test out instance function
// Test ReturnVector with SDKCall
SDKCall(pFunction.CreateSDKCall(), vecResult);
AssertVector(TEST_VECTOR, vecResult);

/*
* Test instance function
*/

pFunction = VScript_GetClassFunction("CEntities", "FindByClassname");
pFunction.CreateDetour().Enable(Hook_Pre, Detour_FindByClassname);

HSCRIPT pEntities = HSCRIPT_RootTable.GetValue("Entities");
HSCRIPT pEntity = SDKCall(pFunction.CreateSDKCall(), pEntities.Instance, 0, TEST_CLASSNAME);
AssertInt(TEST_ENTITY, VScript_HScriptToEntity(pEntity));

/*
* Check that all function params have proper field
*/

CheckFunctions(VScript_GetAllGlobalFunctions());

ArrayList aList = VScript_GetAllClasses();
Expand All @@ -159,7 +195,9 @@ public void OnMapStart()

delete aList;

// Test compile script with param and returns
/*
* Test compile script with param and returns
*/

RunScript("function ReturnParam(param) { return param }");

Expand All @@ -182,7 +220,10 @@ public void OnMapStart()

delete hExecute;

// Multiple params, test if ScriptVariant_t size is correct
/*
* Multiple params, test if ScriptVariant_t size is correct
*/

RunScript("function MoreParam(param1, param2, param3) { return param3 }");

hExecute = new VScriptExecute(HSCRIPT_RootTable.GetValue("MoreParam"));
Expand All @@ -192,7 +233,10 @@ public void OnMapStart()
hExecute.Execute();
AssertInt(TEST_INTEGER, hExecute.ReturnValue);

// Test table stuffs
/*
* Test table stuffs
*/

HSCRIPT pTable = RunScript("return { thing = 322, empty = null, }");

AssertInt(322, pTable.GetValue("thing"));
Expand Down Expand Up @@ -274,7 +318,7 @@ public MRESReturn Detour_BunchOfParams(int iEntity, DHookReturn hReturn, DHookPa

AssertVector(TEST_VECTOR, vecBuffer);

hReturn.Value = TEST_FLOAT; // TODO fix this, dont always work
hReturn.Value = TEST_FLOAT;
return MRES_Supercede;
}

Expand Down

0 comments on commit 3b654f6

Please sign in to comment.