2021-10-18 12:39:15 +02:00
|
|
|
#include "ClientLua.h"
|
|
|
|
|
#include "Logger.h"
|
|
|
|
|
#include "ClientDetours.h"
|
|
|
|
|
#include "FSRoot.h"
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
2021-10-18 13:31:32 +02:00
|
|
|
#include "luafiles.generated.h"
|
|
|
|
|
|
2021-11-26 15:10:53 +01:00
|
|
|
// new custom range
|
|
|
|
|
CLIENT_ADDRESS(void, CAVE_START, 0x7743d2)
|
|
|
|
|
constexpr int CAVE_SIZE = 0x26; // space for 7 functions
|
2021-10-18 12:39:15 +02:00
|
|
|
|
|
|
|
|
#define JMP_SIZE 5
|
|
|
|
|
#define NOP 0x90
|
|
|
|
|
#define JMP 0xe9
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
2021-10-23 12:09:38 +02:00
|
|
|
struct LuaFunction {
|
|
|
|
|
std::string const name;
|
|
|
|
|
lua_CFunction func;
|
|
|
|
|
|
|
|
|
|
std::string const file;
|
|
|
|
|
size_t line;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::vector<LuaFunction>& luaRegistry()
|
|
|
|
|
{
|
|
|
|
|
static std::vector<LuaFunction> _luaRegistry;
|
|
|
|
|
return _luaRegistry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t lastCave = 0;
|
|
|
|
|
|
2021-10-24 12:23:43 +02:00
|
|
|
CLIENT_ADDRESS(lua_State*, _state, 0x00d3f78c);
|
2021-10-23 12:09:38 +02:00
|
|
|
bool isInitialized = false;
|
|
|
|
|
|
2021-10-24 12:23:43 +02:00
|
|
|
CLIENT_FUNCTION(UnregisterGlobal,0x00817FD0, __cdecl,void,(char const* name))
|
|
|
|
|
CLIENT_FUNCTION(FrameScriptRegisterFunction
|
2021-10-23 12:09:38 +02:00
|
|
|
, 0x00817F90
|
2021-10-24 11:56:58 +02:00
|
|
|
, __cdecl
|
2021-10-23 12:09:38 +02:00
|
|
|
, void
|
|
|
|
|
, (char const* name, lua_CFunction fn)
|
|
|
|
|
)
|
2021-10-18 12:39:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace ClientLua {
|
2021-10-23 12:09:38 +02:00
|
|
|
lua_State* State()
|
|
|
|
|
{
|
|
|
|
|
return *_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RegisterLua(std::string const& lua, std::string const& filename, size_t line)
|
|
|
|
|
{
|
|
|
|
|
LUA_FILES.push_back({filename+":"+std::to_string(line),lua});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int AddFunction(char const* name, lua_CFunction fn, std::string const& file, size_t line)
|
|
|
|
|
{
|
|
|
|
|
luaRegistry().push_back({ name, fn, file, line });
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-24 12:23:43 +02:00
|
|
|
CLIENT_FUNCTION(_GetString, 0x0084E0E0, __cdecl, char const*, (lua_State* L, int32_t, int32_t))
|
|
|
|
|
CLIENT_FUNCTION(_GetNumber, 0x0084E030, __cdecl, double, (lua_State* L, int32_t))
|
2021-10-23 12:09:38 +02:00
|
|
|
|
|
|
|
|
std::string GetString(lua_State* L, int32_t offset, std::string const& defValue)
|
|
|
|
|
{
|
|
|
|
|
return IsString(L, offset) ? _GetString(L, offset, 0) : defValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double GetNumber(lua_State* L, int32_t offset, double defValue)
|
|
|
|
|
{
|
|
|
|
|
return IsNumber(L, offset) ? _GetNumber(L, offset) : defValue;
|
|
|
|
|
}
|
2021-10-19 12:47:32 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-25 11:08:39 +02:00
|
|
|
CLIENT_DETOUR(LoadScriptFunctions, 0x5120E0, __cdecl, int, ()) {
|
|
|
|
|
LOG_DEBUG << "Loading script functions";
|
2021-10-23 12:09:38 +02:00
|
|
|
DWORD old;
|
|
|
|
|
VirtualProtect((LPVOID)CAVE_START, JMP_SIZE * luaRegistry().size(), PAGE_EXECUTE_READWRITE, &old);
|
|
|
|
|
memset(CAVE_START, NOP, JMP_SIZE * luaRegistry().size());
|
2021-11-26 15:10:53 +01:00
|
|
|
|
|
|
|
|
// write a jmp
|
|
|
|
|
*((unsigned char*)CAVE_START ) = 0xed;
|
|
|
|
|
*((unsigned char*)CAVE_START + 1) = 0x26;
|
|
|
|
|
|
2021-10-23 12:09:38 +02:00
|
|
|
for (size_t i = 0; i < luaRegistry().size(); ++i)
|
|
|
|
|
{
|
2021-11-26 15:10:53 +01:00
|
|
|
size_t cur_cave = uint32_t(CAVE_START) + 2 + i * JMP_SIZE;
|
2021-10-23 12:09:38 +02:00
|
|
|
LuaFunction& fn = luaRegistry()[i];
|
|
|
|
|
LOG_DEBUG
|
|
|
|
|
<< "Registering Lua function: "
|
|
|
|
|
<< fn.name
|
|
|
|
|
<< "@"
|
|
|
|
|
<< fn.func
|
|
|
|
|
<< " -> "
|
|
|
|
|
<< relProjectPath(fn.file)
|
|
|
|
|
<< ":"
|
|
|
|
|
<< fn.line;
|
|
|
|
|
// write jmp
|
|
|
|
|
*(uint8_t*)cur_cave = JMP;
|
|
|
|
|
*(uint32_t*)(cur_cave + 1) = int32_t(fn.func) - ((int32_t)cur_cave) - JMP_SIZE;
|
|
|
|
|
FrameScriptRegisterFunction(fn.name.c_str(), (lua_CFunction)cur_cave);
|
|
|
|
|
}
|
|
|
|
|
DWORD dummy;
|
|
|
|
|
VirtualProtect((LPVOID)CAVE_START, JMP_SIZE * luaRegistry().size(), old, &dummy);
|
|
|
|
|
lastCave = luaRegistry().size();
|
|
|
|
|
|
2021-10-25 11:08:39 +02:00
|
|
|
// so we have them available in the scripts below
|
|
|
|
|
int funcs = LoadScriptFunctions();
|
|
|
|
|
|
2021-10-23 12:09:38 +02:00
|
|
|
for (auto const& pair : LUA_FILES)
|
|
|
|
|
{
|
|
|
|
|
LOG_DEBUG << "Running lua file " << pair.first;
|
|
|
|
|
ClientLua::DoString(pair.second.c_str(), *_state);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-25 11:08:39 +02:00
|
|
|
return funcs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CLIENT_DETOUR(UnloadScriptFunctions, 0x00512280, __cdecl, int, ()) {
|
|
|
|
|
if (lastCave > 0)
|
|
|
|
|
{
|
|
|
|
|
DWORD old;
|
|
|
|
|
VirtualProtect((LPVOID)CAVE_START, JMP_SIZE * lastCave, PAGE_EXECUTE_READWRITE, &old);
|
|
|
|
|
memset(CAVE_START, NOP, JMP_SIZE * lastCave);
|
|
|
|
|
DWORD dummy;
|
|
|
|
|
VirtualProtect((LPVOID)CAVE_START, JMP_SIZE * lastCave, old, &dummy);
|
|
|
|
|
}
|
|
|
|
|
return UnloadScriptFunctions();
|
2021-10-19 12:47:32 +02:00
|
|
|
}
|