QuestionHelp with getting Client lua state when hooking from Menu State

Posts 1–4 of 4 · Page 1 of 1
Help with getting Client lua state when hooking from Menu State
What's up, guys. I'm having trouble getting Client Lua state when using a module from menu state. I am already hooking from CreateLuaInterfaceFn but I'm having trouble getting it all working. Any hooks you guys can recommend or headers I might be missing/not thinking about?
For reference, I'm trying to call lua hooks between menu and client for a bot I'm building. Due to the bot running in client and the management/'backend' running in menu I'd like to notify menu on completed tasks etc.

The codebase is from the loonix branch of 'gm_roc' (credits to LennyPenny and meepen) because it seemed the closest to my use case. So I hope that helps if you wanted to see the headers and structs I'm using

I've been a software engineer for a number of years but I've never really gone near C++ before. So sorry if any of this cringes you out. Simple modules seemed fluid but going into hooking and process level stuff, I'm lost. Appreciate any help!

Code:
using namespace GarrysMod;

Lua::Shared* luaShared;

VTable *luashared_vt;
VTable *client_vt;

Lua::Interface *cState;
Lua::ILuaBase *MENU;

int CallOnClient(lua_State *state)
{
	if (!cState)
		LUA->ThrowError("Not in game");
	
	//Lua::ILuaBase *CLIENT = cState->state->luabase;

	//CLIENT->PushSpecial(Lua::SPECIAL_GLOB);
	//CLIENT->GetField(-1, "hook");
	//CLIENT->GetField(-1, "Call");
	//CLIENT->PushString(LUA->GetString(1));
	//CLIENT->PushNil();
	//CLIENT->PushString(LUA->GetString(2));
	//CLIENT->Call(3, 1);
	//CLIENT->Pop(2);

	return 0;
}

int CallOnMenu(lua_State *state)
{
	const char *name = LUA->GetString(1);
	const char *data = LUA->GetString(2);
	if (!cState)
		LUA->ThrowError("Not in game");
	//MENU->PushSpecial(Lua::SPECIAL_GLOB);
	//MENU->GetField(-1, "hook");
	//MENU->GetField(-1, "Call");
	//MENU->PushString(name, strlen(name));
	//MENU->PushNil();
	//MENU->PushString(data, strlen(data));
	//MENU->Call(3, 1);
	//MENU->Pop(2);
	return 0;
}


typedef Lua::Interface *(__thiscall *hCreateLuaInterfaceFn)(Lua::Shared*, unsigned char, bool);
void *__hook hCreateLuaInterface(Lua::Shared *ths, HOOK_EDX(void *) uchar state, bool renew)
{
	Lua::Interface* hState = hCreateLuaInterfaceFn(luashared_vt->getold(Lua::Shared::CREATELUAINTERFACE))(ths, state, renew);

	if (state != Lua::Interface::CLIENT)
		return hState;

	cState = hState;

	//Push CallOnMenu to Client state

	client_vt = new VTable(cState);

	return cState;
}

typedef void *(__thiscall *hCloseLuaInterfaceFn)(Lua::Shared *, Lua::Interface *);
void *__hook hCloseLuaInterface(Lua::Shared *ths, HOOK_EDX(void *) Lua::Interface *iface)
{
	if (iface == cState)
		cState = NULL;

	return hCloseLuaInterfaceFn(luashared_vt->getold(Lua::Shared::CLOSELUAINTERFACE))(ths, iface);
}

GMOD_MODULE_OPEN()
{
	MENU = LUA;
	luaShared = GetInterface<Lua::Shared*>("lua_shared", "LUASHARED003");

	LUA->PushSpecial(Lua::SPECIAL_GLOB);
		LUA->PushString("CallOnClient");
		LUA->PushCFunction(CallOnClient);
		LUA->SetTable(-3);
	LUA->Pop();

	luashared_vt = new VTable(luaShared);
	luashared_vt->hook(Lua::Shared::CREATELUAINTERFACE, (void *)&hCreateLuaInterface);
	luashared_vt->hook(Lua::Shared::CLOSELUAINTERFACE, (void *)&hCloseLuaInterface);

	return 0;
}

GMOD_MODULE_CLOSE()
{
	return 0;
}
I've decided to just make 2 modules, one for menu and one for client. Getting the Client interface and pushing to it too early causes crashes, so it's easier just to load in a seperate module.

May be closed now.
This is null causing you to crash!

luaShared = GetInterface<Lua::Shared*>("lua_shared", "LUASHARED003");
in your create interface hook, the unsigned char is the interface type
it's called for menu, server, and client; but since you're already in menu, you'll only be seeing server and client
Posts 1–4 of 4 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Talk with us