feat(lua): lua sprint

This commit is contained in:
maybegreat48
2025-06-27 13:41:11 -04:00
parent d0816571ea
commit 1f1b924077
8 changed files with 420 additions and 33 deletions
-4
View File
@@ -8,10 +8,6 @@ namespace YimMenu
class LuaManager
{
public:
enum class ScriptPermission
{
};
struct UnloadedScript
{
std::string m_Name;
+104
View File
@@ -0,0 +1,104 @@
#include "lua.hpp"
#undef GetObject // another dumb Windows.h definition
namespace YimMenu::Lua
{
template<typename T>
class Metatable
{
static int m_Index;
public:
static inline void Register(lua_State* state)
{
m_Index = luaL_ref(state, LUA_REGISTRYINDEX);
}
static inline int Get()
{
return m_Index;
}
};
// Tries to get the userdata or errors out
template <typename T>
inline T& GetObject(lua_State* state, int idx)
{
auto data = lua_touserdata(state, idx);
if (!data)
luaL_argerror(state, idx, "cannot get userdata at this index");
if (!lua_getmetatable(state, idx))
luaL_argerror(state, idx, "cannot get metatable for the userdata at this index");
lua_rawgeti(state, LUA_REGISTRYINDEX, Metatable<T>::Get());
auto equals = lua_rawequal(state, -1, -2);
lua_pop(state, 2);
if (!equals)
luaL_argerror(state, idx, "the metatable for this userdata at this index is incorrect");
return *reinterpret_cast<T*>(data);
}
inline void SetFunction(lua_State* state, lua_CFunction func, const char* name)
{
lua_pushcfunction(state, func);
lua_setfield(state, -2, name);
}
// This is a terrible hack
template<lua_CFunction actual_func>
inline int DropSelf(lua_State* state)
{
lua_remove(state, 1);
return actual_func(state);
}
// Requires your table to be at the top of stack
// Creates a metatable for the table, which might not desirable
template<lua_CFunction ctor>
inline void SetConstructor(lua_State* state)
{
SetFunction(state, ctor, "new");
lua_newtable(state);
SetFunction(state, DropSelf<ctor>, "__call");
lua_setmetatable(state, -2);
}
// Creates an object and pushes it on the stack
template<typename T, class... Args>
inline T* CreateObject(lua_State* state, Args&& ...args)
{
void* data = lua_newuserdata(state, sizeof(T));
new (data) T(std::forward<Args>(args)...); // construct in-place
lua_rawgeti(state, LUA_REGISTRYINDEX, Metatable<T>::Get());
lua_setmetatable(state, -2);
return reinterpret_cast<T*>(data);
}
// Copies an existing object and pushes it on the stack
// A copy ctor must be defined or something like that
template<typename T, class... Args>
inline T* CopyObject(lua_State* state, const T& existing)
{
void* data = lua_newuserdata(state, sizeof(T));
*reinterpret_cast<T*>(data) = existing;
lua_rawgeti(state, LUA_REGISTRYINDEX, Metatable<T>::Get());
lua_setmetatable(state, -2);
return reinterpret_cast<T*>(data);
}
// Moves an existing object and pushes it on the stack
// A move ctor must be defined or something like that
template<typename T, class... Args>
inline T* MoveObject(lua_State* state, T&& existing)
{
void* data = lua_newuserdata(state, sizeof(T));
*reinterpret_cast<T*>(data) = std::move(existing);
lua_rawgeti(state, LUA_REGISTRYINDEX, Metatable<T>::Get());
lua_setmetatable(state, -2);
return reinterpret_cast<T*>(data);
}
}
+6 -16
View File
@@ -1,5 +1,6 @@
#include "core/scripting/LuaLibrary.hpp"
#include "core/scripting/LuaScript.hpp"
#include "core/scripting/LuaUtils.hpp"
namespace YimMenu::Lua
{
@@ -47,22 +48,11 @@ namespace YimMenu::Lua
virtual void Register(lua_State* state) override
{
lua_newtable(state);
lua_pushcfunction(state, Verbose);
lua_setfield(state, -2, "verbose");
lua_pushcfunction(state, Info);
lua_setfield(state, -2, "info");
lua_pushcfunction(state, Warn);
lua_setfield(state, -2, "warn");
lua_pushcfunction(state, Error);
lua_setfield(state, -2, "error");
lua_pushcfunction(state, Trace);
lua_setfield(state, -2, "trace");
SetFunction(state, Verbose, "verbose");
SetFunction(state, Info, "info");
SetFunction(state, Warn, "warn");
SetFunction(state, Error, "error");
SetFunction(state, Trace, "trace");
lua_setglobal(state, "log");
}
};
+5 -13
View File
@@ -1,5 +1,6 @@
#include "core/scripting/LuaLibrary.hpp"
#include "core/scripting/LuaScript.hpp"
#include "core/scripting/LuaUtils.hpp"
#include "core/util/Joaat.hpp"
namespace YimMenu::Lua
@@ -65,19 +66,10 @@ namespace YimMenu::Lua
virtual void Register(lua_State* state) override
{
lua_newtable(state);
lua_pushcfunction(state, RunInCallback);
lua_setfield(state, -2, "run_in_callback");
lua_pushcfunction(state, Yield);
lua_setfield(state, -2, "yield");
lua_pushcfunction(state, IsInsideCallback);
lua_setfield(state, -2, "is_inside_callback");
lua_pushcfunction(state, RegisterEventHandler);
lua_setfield(state, -2, "register_event_handler");
SetFunction(state, RunInCallback, "run_in_callback");
SetFunction(state, Yield, "yield");
SetFunction(state, IsInsideCallback, "is_inside_callback");
SetFunction(state, RegisterEventHandler, "register_event_handler");
lua_setglobal(state, "script");
}
};
+28
View File
@@ -0,0 +1,28 @@
#include "core/scripting/LuaLibrary.hpp"
#include "core/scripting/LuaScript.hpp"
#include "core/scripting/LuaUtils.hpp"
#include "core/util/Joaat.hpp"
namespace YimMenu::Lua
{
class Util : LuaLibrary
{
using LuaLibrary::LuaLibrary;
static int Joaat(lua_State* state)
{
const char* string = luaL_checkstring(state, 1);
lua_pushinteger(state, (int)YimMenu::Joaat(string));
return 1;
}
virtual void Register(lua_State* state) override
{
lua_newtable(state);
SetFunction(state, Joaat, "joaat");
lua_setglobal(state, "util");
}
};
Util _Util;
}
+43
View File
@@ -0,0 +1,43 @@
#include "core/scripting/LuaLibrary.hpp"
#include "core/scripting/LuaScript.hpp"
#include "core/scripting/LuaUtils.hpp"
#include "types/rage/vector.hpp"
namespace YimMenu::Lua
{
class Vector3 : LuaLibrary
{
using LuaLibrary::LuaLibrary;
static int New(lua_State* state)
{
auto args = lua_gettop(state);
if (args == 0)
CreateObject<rage::fvector3>(state);
else if (args == 3)
CreateObject<rage::fvector3>(state, luaL_checknumber(state, 1), luaL_checknumber(state, 2), luaL_checknumber(state, 3));
else
luaL_error(state, "Invalid amount of arguments passed to Vector3::New");
return 1;
}
virtual void Register(lua_State* state) override
{
luaL_newmetatable(state, "Vector3");
{
lua_newtable(state);
{
// TODO?
}
lua_setfield(state, -2, "__index"); // prototype
}
Metatable<rage::fvector3>::Register(state);
lua_newtable(state);
SetConstructor<New>(state);
lua_setglobal(state, "Vector3");
}
};
Vector3 _Vector3;
}
+135
View File
@@ -0,0 +1,135 @@
#include "core/scripting/LuaLibrary.hpp"
#include "core/scripting/LuaScript.hpp"
#include "core/scripting/LuaUtils.hpp"
#include "game/gta/Entity.hpp"
namespace YimMenu::Lua
{
// TODO: we need to automate this
class Entity : LuaLibrary
{
using LuaLibrary::LuaLibrary;
static int New(lua_State* state)
{
CreateObject<YimMenu::Entity>(state, luaL_checkinteger(state, 1));
return 1;
}
static int GetHandle(lua_State* state)
{
lua_pushinteger(state, GetObject<YimMenu::Entity>(state, 1).GetHandle());
return 1;
}
static int IsValid(lua_State* state)
{
lua_pushboolean(state, GetObject<YimMenu::Entity>(state, 1).IsValid());
return 1;
}
static int IsPed(lua_State* state)
{
lua_pushboolean(state, GetObject<YimMenu::Entity>(state, 1).IsPed());
return 1;
}
static int IsVehicle(lua_State* state)
{
lua_pushboolean(state, GetObject<YimMenu::Entity>(state, 1).IsVehicle());
return 1;
}
static int IsObject(lua_State* state)
{
lua_pushboolean(state, GetObject<YimMenu::Entity>(state, 1).IsObject());
return 1;
}
static int IsPlayer(lua_State* state)
{
lua_pushboolean(state, GetObject<YimMenu::Entity>(state, 1).IsPlayer());
return 1;
}
static int IsMissionEntity(lua_State* state)
{
lua_pushboolean(state, GetObject<YimMenu::Entity>(state, 1).IsMissionEntity());
return 1;
}
static int GetModel(lua_State* state)
{
lua_pushinteger(state, (int)GetObject<YimMenu::Entity>(state, 1).GetModel());
return 1;
}
static int GetPosition(lua_State* state)
{
CopyObject<rage::fvector3>(state, GetObject<YimMenu::Entity>(state, 1).GetPosition());
return 1;
}
static int GetRotation(lua_State* state)
{
CopyObject<rage::fvector3>(state, GetObject<YimMenu::Entity>(state, 1).GetRotation(lua_gettop(state) >= 2 ? luaL_checkinteger(state, 2) : 2));
return 1;
}
static int GetVelocity(lua_State* state)
{
CopyObject<rage::fvector3>(state, GetObject<YimMenu::Entity>(state, 1).GetVelocity());
return 1;
}
static int SetPosition(lua_State* state)
{
GetObject<YimMenu::Entity>(state, 1).SetPosition(GetObject<rage::fvector3>(state, 2));
return 0;
}
static int SetRotation(lua_State* state)
{
GetObject<YimMenu::Entity>(state, 1).SetRotation(GetObject<rage::fvector3>(state, 2), lua_gettop(state) >= 3 ? luaL_checkinteger(state, 3) : 2);
return 0;
}
static int SetVelocity(lua_State* state)
{
GetObject<YimMenu::Entity>(state, 1).SetVelocity(GetObject<rage::fvector3>(state, 2));
return 0;
}
virtual void Register(lua_State* state) override
{
luaL_newmetatable(state, "Entity");
{
lua_newtable(state);
{
SetFunction(state, GetHandle, "get_handle");
SetFunction(state, IsValid, "is_valid");
SetFunction(state, IsPed, "is_ped");
SetFunction(state, IsVehicle, "is_vehicle");
SetFunction(state, IsObject, "is_object");
SetFunction(state, IsPlayer, "is_player");
SetFunction(state, IsMissionEntity, "is_mission_entity");
SetFunction(state, GetModel, "get_model");
SetFunction(state, GetPosition, "get_position");
SetFunction(state, GetRotation, "get_rotation");
SetFunction(state, GetVelocity, "get_velocity");
SetFunction(state, SetPosition, "set_position");
SetFunction(state, SetRotation, "set_rotation");
SetFunction(state, SetVelocity, "set_velocity");
}
lua_setfield(state, -2, "__index"); // prototype
}
Metatable<YimMenu::Entity>::Register(state);
lua_newtable(state);
SetConstructor<New>(state);
lua_setglobal(state, "Entity");
}
};
Entity _Entity;
}
@@ -0,0 +1,99 @@
#include "core/scripting/LuaLibrary.hpp"
#include "core/scripting/LuaScript.hpp"
#include "core/scripting/LuaUtils.hpp"
#include "game/gta/ScriptGlobal.hpp"
namespace YimMenu::Lua
{
// TODO: we need to automate this
class ScriptGlobal : LuaLibrary
{
using LuaLibrary::LuaLibrary;
static int New(lua_State* state)
{
CreateObject<YimMenu::ScriptGlobal>(state, luaL_checkinteger(state, 1));
return 1;
}
static int At(lua_State* state)
{
auto num_args = lua_gettop(state) - 1; // first argument is self
auto& global = GetObject<YimMenu::ScriptGlobal>(state, 1);
auto size = num_args > 1 ? luaL_checkinteger(state, 3) : 0;
if (size != 0)
CopyObject<YimMenu::ScriptGlobal>(state, global.At(luaL_checkinteger(state, 2), size));
else
CopyObject<YimMenu::ScriptGlobal>(state, global.At(luaL_checkinteger(state, 2)));
return 1;
}
static int CanAccess(lua_State* state)
{
lua_pushboolean(state, GetObject<YimMenu::ScriptGlobal>(state, 1).CanAccess());
return 1;
}
static int GetInt(lua_State* state)
{
auto& global = GetObject<YimMenu::ScriptGlobal>(state, 1);
int value = 0;
if (global.CanAccess())
value = *global.As<int*>();
lua_pushinteger(state, value);
return 1;
}
static int GetFloat(lua_State* state)
{
auto& global = GetObject<YimMenu::ScriptGlobal>(state, 1);
float value = 0;
if (global.CanAccess())
value = *global.As<float*>();
lua_pushnumber(state, value);
return 1;
}
static int SetInt(lua_State* state)
{
auto& global = GetObject<YimMenu::ScriptGlobal>(state, 1);
if (global.CanAccess())
*global.As<int*>() = luaL_checkinteger(state, 2);
return 0;
}
static int SetFloat(lua_State* state)
{
auto& global = GetObject<YimMenu::ScriptGlobal>(state, 1);
if (global.CanAccess())
*global.As<float*>() = static_cast<float>(luaL_checknumber(state, 2));
return 0;
}
virtual void Register(lua_State* state) override
{
luaL_newmetatable(state, "ScriptGlobal");
{
lua_newtable(state);
{
SetFunction(state, At, "at");
SetFunction(state, CanAccess, "can_access");
SetFunction(state, GetInt, "get_int");
SetFunction(state, GetFloat, "get_float");
SetFunction(state, SetInt, "set_int");
SetFunction(state, SetFloat, "set_float");
}
lua_setfield(state, -2, "__index"); // prototype
}
Metatable<YimMenu::ScriptGlobal>::Register(state);
lua_newtable(state);
SetConstructor<New>(state);
lua_setglobal(state, "ScriptGlobal");
}
};
ScriptGlobal _ScriptGlobal;
}