Skip to content

Conversation

@KitRifty
Copy link
Contributor

Adds an extra parameter to VScriptExecute's constructor to specify a script scope, or use root table by default.

Also added a VScript_ReleaseScript native to pair with VScript_CompileScript(File). Since it exists on the interface, I figured it'd be best to stay on the safe side in case more specialized code takes place versus releasing it using ReleaseValue.

I also corrected the offsets for both CompileScript and ReleaseScript for TF2. Both have been tested on TF2 Windows and Linux, but I haven't tested in other games so ReleaseScript's offsets in "#default" is just a guess. For TF2 specifically, I'm not sure if I should've used ExtraOffsets.

I used this code to test them along with the scopes:

Handle g_SDKCallGetScriptScope;

public void OnPluginStart()
{
	RegConsoleCmd("vscript_test", Command_Test);

	GameData gameData = new GameData("vscript_test");

	StartPrepSDKCall(SDKCall_Entity);
	PrepSDKCall_SetFromConf(gameData, SDKConf_Signature, "CBaseEntity::GetScriptScope");
	PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
	g_SDKCallGetScriptScope = EndPrepSDKCall();

	delete gameData;
}

ScriptStatus_t RunScript(const char[] code, HSCRIPT scope = view_as<HSCRIPT>(0))
{
	HSCRIPT script = VScript_CompileScript(code);
	if (!script)
	{
		return SCRIPT_ERROR;
	}

	VScriptExecute exec = new VScriptExecute(script, scope);
	ScriptStatus_t result = exec.Execute();
	delete exec;
	VScript_ReleaseScript(script);

	return result;
}

Action Command_Test(int client, int args)
{
	SetVariantString("self.ValidateScriptScope()");
	AcceptEntityInput(client, "RunScriptCode");

	HSCRIPT scope = SDKCall(g_SDKCallGetScriptScope, client);

	if (scope)
	{
		scope.SetValue("__test_value", FIELD_INTEGER, 7891);

		RunScript("__my_temp <- []; __my_temp.append(123)", scope);

		SetVariantString("__my_temp.append(64)");
		AcceptEntityInput(client, "RunScriptCode");

		SetVariantString("__DumpScope(1, self.GetScriptScope())");
		AcceptEntityInput(client, "RunScriptCode");
	}

	return Plugin_Handled;
}

vscript_test.txt:

"Games"
{
	"#default"
	{
		"Signatures"
		{
			"CBaseEntity::GetScriptScope"
			{
				"library"	"server"
				"linux"		"@_ZN11CBaseEntity14GetScriptScopeEv"
				"windows"	"\x8B\x89\x2A\x2A\x2A\x2A\x33\xC0\x83"
			}
		}
	}
}

Output:

   self = ([2] player)
   __test_value = 7891
   __vname = "_f730_player"
   __my_temp(ARRAY)
   [
      0 = 123
      1 = 64
   ]
   __vrefs = 1

Add VScript_ReleaseScript
Fix gamedata
Copy link
Owner

@FortyTwoFortyTwo FortyTwoFortyTwo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured it'd be best to stay on the safe side in case more specialized code takes place versus releasing it using ReleaseValue.

I don't think there a difference between it? Looking at cstrike leaked code it should follow the exact same steps. Although ReleaseScope have extra steps and that games may have handled it differently, so it may makes sense in the long term.

I haven't tested in other games so ReleaseScript's offsets in "#default" is just a guess. For TF2 specifically, I'm not sure if I should've used ExtraOffsets.

TF2's extra offset is above these script offsets, so it fine as it matches with CSGO's offsets.

// @param script Script address to execute.
public native VScriptExecute(HSCRIPT script);
// @param scope The script scope to execute the script inside of.
public native VScriptExecute(HSCRIPT script, HSCRIPT scope = view_as<HSCRIPT>(0));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HSCRIPT_RootTable variable can be used as default scope value, to make it more clearer that root table is used as default.

Comment on lines 327 to 338

"IScriptVM::CompileScript"
{
"linux" "9"
"windows" "11"
}

"IScriptVM::ReleaseScript"
{
"linux" "10"
"windows" "12"
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset looks correct, but now there duplicate offsets under same name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should both the CompileScript and ReleaseScript offsets be used in "#default" instead? I put these for TF2 specifically because I wasn't sure if they're the same for CSGO (which I'm assuming is the game that "#default" is based on).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah put in #default, TF2 will use default offsets but auto-adjusts its based on ExtraOffsets

Comment on lines 283 to 289
/**
* Releases a compiled script.
*
* @param hscript HSCRIPT of compiled script
*/
native void VScript_ReleaseScript(HSCRIPT hscript);

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer to have methodmap function HSCRIPT.ReleaseScript() to match with HSCRIPT.Release()

Add HSCRIPT.ReleaseScript
Use HSCRIPT_RootTable as default for scope
Copy link
Owner

@FortyTwoFortyTwo FortyTwoFortyTwo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@FortyTwoFortyTwo FortyTwoFortyTwo merged commit 5fd90a7 into FortyTwoFortyTwo:main Jun 10, 2023
@KitRifty KitRifty deleted the execute-in-scope branch June 10, 2023 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants