@@ -0,0 +1,522 @@ | |||||
#include "BL3Lua.h" | |||||
#include "LuaUtility.h" | |||||
#include "include/patternscan.hpp" | |||||
int lua_exception_handler(lua_State* L, sol::optional<const std::exception&> maybe_exception, sol::string_view description) { | |||||
// L is the lua state, which you can wrap in a state_view if necessary | |||||
// maybe_exception will contain exception, if it exists | |||||
// description will either be the what() of the exception or a description saying that we hit the general-case catch(...) | |||||
std::cout << "An exception occurred in a function, here's what it says "; | |||||
if (maybe_exception) { | |||||
std::cout << "(straight from the exception): "; | |||||
const std::exception& ex = *maybe_exception; | |||||
std::cout << ex.what() << std::endl; | |||||
} | |||||
else { | |||||
std::cout << "(from the description parameter): "; | |||||
std::cout.write(description.data(), static_cast<std::streamsize>(description.size())); | |||||
std::cout << std::endl; | |||||
} | |||||
// you must push 1 element onto the stack to be | |||||
// transported through as the error object in Lua | |||||
// note that Lua -- and 99.5% of all Lua users and libraries -- expects a string | |||||
// so we push a single string (in our case, the description of the error) | |||||
return sol::stack::push(L, description); | |||||
} | |||||
inline void my_panic(sol::optional<std::string> maybe_msg) { | |||||
std::cerr << "Lua is in a panic state and will now abort() the application" << std::endl; | |||||
if (maybe_msg) { | |||||
const std::string& msg = maybe_msg.value(); | |||||
std::cerr << "\terror message: " << msg << std::endl; | |||||
} | |||||
// When this function exits, Lua will exhibit default behavior and abort() | |||||
} | |||||
BL3Lua::BL3Lua() | |||||
{ | |||||
InitializeCriticalSection(&luaCritSec); | |||||
/*InitializeCriticalSection(&procEventCritSec); | |||||
InitializeCriticalSection(&consoleCommandCritSec);*/ | |||||
lua = new sol::state(); | |||||
lua->open_libraries(); | |||||
lua->set_exception_handler(lua_exception_handler); | |||||
lua->set_panic(sol::c_call<decltype(&my_panic), &my_panic>); | |||||
registerBase(); | |||||
while (SDK::GEngine == nullptr) | |||||
{ | |||||
auto engineAddress = PatternScan::FindSignature(NULL, "48 8b 4c 24 50 48 89 05 ?? ?? ?? ?? 48 85 c9 74 05 e8"); | |||||
if (engineAddress != NULL) | |||||
{ | |||||
auto tmp = (engineAddress + 5); | |||||
auto tmp2 = tmp + 3; | |||||
SDK::GEngine = reinterpret_cast<SDK::UEngine**>((tmp + 7 + *(int*)(tmp2))); | |||||
} | |||||
} | |||||
consoleEnvironment = sol::environment(*lua, sol::create, lua->globals()); | |||||
} | |||||
BL3Lua::~BL3Lua() | |||||
{ | |||||
lua_close(lua->lua_state()); | |||||
DeleteCriticalSection(&luaCritSec); | |||||
} | |||||
bool BL3Lua::ExecuteScriptFile(const char* filePath, bool printInGame) | |||||
{ | |||||
bool result = false; | |||||
EnterCriticalSection(&luaCritSec); | |||||
int indexToDelete = -1; | |||||
for (int i = 0; i < loadedComponents.size(); i++) { | |||||
if (!strcmp(loadedComponents[i]->m_FileName.c_str(), filePath)) { | |||||
indexToDelete = i; | |||||
break; | |||||
} | |||||
} | |||||
// TODO: Properly delete references during iteration | |||||
// Implement iterator instead of loop | |||||
if (indexToDelete != -1) { | |||||
// Remove registered Hotkeys from this env | |||||
auto hkIT = registeredHotkeys.begin(); | |||||
while (hkIT != registeredHotkeys.end()) { | |||||
/*for (auto& r : hkIT) {*/ | |||||
sol::reference eRef = std::get<0>(*hkIT); | |||||
sol::environment env = sol::get_environment(eRef); | |||||
if (env == loadedComponents[indexToDelete]->m_Env) { | |||||
eRef.abandon(); | |||||
hkIT = registeredHotkeys.erase(hkIT); | |||||
//registeredHotkeys.erase(std::remove(registeredHotkeys.begin(), registeredHotkeys.end(), r), registeredHotkeys.end()); | |||||
} | |||||
if(hkIT != registeredHotkeys.end()) | |||||
++hkIT; | |||||
} | |||||
auto procEventIT = procEventHooks.begin(); | |||||
// Remove procEventHooks from this env | |||||
//for (auto& r : procEventHooks) { | |||||
while(procEventIT != procEventHooks.end()){ | |||||
bool didErase = false; | |||||
for (auto& p : procEventIT->second) { | |||||
sol::reference eRef = std::get<0>(p); | |||||
sol::environment env = sol::get_environment(eRef); | |||||
if (env == loadedComponents[indexToDelete]->m_Env) { | |||||
eRef.abandon(); | |||||
//r.second.erase(std::remove(r.second.begin(), r.second.end(), p), r.second.end()); | |||||
didErase = true; | |||||
} | |||||
} | |||||
if (didErase) { | |||||
procEventIT = procEventHooks.erase(procEventIT); | |||||
if (procEventIT != procEventHooks.end()) | |||||
++procEventIT; | |||||
} | |||||
} | |||||
// Remove consoleCommands from this env | |||||
auto ccIT = consoleCommands.begin(); | |||||
//for (auto& r : consoleCommands) { | |||||
while(ccIT != consoleCommands.end()){ | |||||
sol::reference eRef = std::get<0>(ccIT->second); | |||||
sol::environment env = sol::get_environment(eRef); | |||||
if (env == loadedComponents[indexToDelete]->m_Env) { | |||||
eRef.abandon(); | |||||
ccIT = consoleCommands.erase(ccIT); | |||||
//consoleCommands.erase(r.first); | |||||
} | |||||
if (ccIT != consoleCommands.end()) | |||||
++ccIT; | |||||
} | |||||
delete loadedComponents[indexToDelete]; | |||||
loadedComponents.erase(loadedComponents.begin() + indexToDelete); | |||||
} | |||||
lua->collect_garbage(); | |||||
LuaComponent* nComp = new LuaComponent(filePath, lua); | |||||
nComp->Init(); | |||||
loadedComponents.push_back(nComp); | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
return nComp->m_Env != sol::lua_nil; | |||||
} | |||||
bool BL3Lua::ExecuteScriptString(const char* scriptCode, bool printInGame) | |||||
{ | |||||
bool result = false; | |||||
EnterCriticalSection(&luaCritSec); | |||||
try { | |||||
auto func_result = lua->safe_script(scriptCode, consoleEnvironment); | |||||
if (!func_result.valid()) { | |||||
sol::error err = func_result; | |||||
std::cout << "[LUA] failed with error: " << err.what() << std::endl; | |||||
if (printInGame) { | |||||
sol::protected_function printFunc = (*(lua))["PrintGameConsole"]; | |||||
if (printFunc.valid()) { | |||||
std::string errorMessage = std::string("[LUA] failed with error: ").append(err.what()); | |||||
printFunc(errorMessage); | |||||
} | |||||
} | |||||
} | |||||
else { | |||||
result = true; | |||||
} | |||||
} | |||||
catch (...) { | |||||
} | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
return result; | |||||
} | |||||
void BL3Lua::RunCallbacks(const char* callbackName, sol::object data) | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
try{ | |||||
sol::protected_function runCallbackFunc = (*lua)["RunCallbacks"]; | |||||
if (runCallbackFunc.valid()){ | |||||
sol::protected_function_result result = runCallbackFunc(callbackName, data); | |||||
if (!result.valid()) { | |||||
sol::error err = result; | |||||
std::cout << "Error during callbacks: " << err.what() << std::endl; | |||||
} | |||||
} | |||||
} | |||||
catch(...){} | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::TDump(sol::object tableToDump) | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
try { | |||||
sol::protected_function tdumpFunc = (*lua)["internalTDump"]; | |||||
if (tdumpFunc.valid()) { | |||||
sol::protected_function_result result = tdumpFunc(tableToDump); | |||||
if (!result.valid()) { | |||||
sol::error err = result; | |||||
std::cout << "Error during tdump: " << err.what() << std::endl; | |||||
} | |||||
} | |||||
} | |||||
catch (...) {} | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::ClearCallbacks() | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
while (callbacks && !callbacks.empty()) { | |||||
callbacks.clear(); | |||||
} | |||||
callbacks = lua->create_named_table("Callbacks"); | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::ValidateHotkeys() | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
std::vector<int> toDelete; | |||||
std::vector<std::tuple<sol::reference, lua_State*, std::string, std::string, std::string>> tmp; | |||||
bool needsFixup = false; | |||||
for (int i = 0; i < registeredHotkeys.size(); ++i) { | |||||
if (!std::get<0>(registeredHotkeys[i]).valid()) | |||||
{ | |||||
needsFixup = true; | |||||
} | |||||
else { | |||||
tmp.push_back(registeredHotkeys[i]); | |||||
} | |||||
} | |||||
if (needsFixup) { | |||||
registeredHotkeys = tmp; | |||||
} | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
// Registering works | |||||
uint32_t BL3Lua::RegisterHotkey(sol::this_state s, sol::this_environment e, sol::variadic_args va) { | |||||
bool anyError = false; | |||||
ValidateHotkeys(); | |||||
EnterCriticalSection(&luaCritSec); | |||||
std::vector<std::string> hotkeys; | |||||
sol::function func; | |||||
for (auto v : va) { | |||||
if (v.is<std::string_view>()) { | |||||
std::string hk = v.as<std::string>(); | |||||
if (!LuaUtility::ContainsKey(hk)) | |||||
{ | |||||
anyError = true; | |||||
sol::protected_function printFunc = (*(lua))["PrintGameConsole"]; | |||||
if (printFunc.valid()) { | |||||
char buffer[1024]; | |||||
sprintf_s(buffer, sizeof(buffer), "\"%s\" is not a valid keybind!", hk.c_str()); | |||||
std::string errorMessage = std::string(buffer); | |||||
printFunc(errorMessage); | |||||
} | |||||
} | |||||
else { | |||||
hotkeys.push_back(hk); | |||||
} | |||||
} | |||||
else if (v.is<sol::function>()) { | |||||
func = v.as<sol::function>(); | |||||
} | |||||
} | |||||
//std::vector<std::string> hotkeys = hotkeyTable.as<std::vector<std::string>>(); | |||||
if (hotkeys.size() >= 1 && hotkeys.size() <= 3 && func.valid()) { | |||||
for (auto& hk : hotkeys) { | |||||
if (!LuaUtility::ContainsKey(hk)) | |||||
{ | |||||
anyError = true; | |||||
sol::protected_function printFunc = (*(lua))["PrintGameConsole"]; | |||||
if (printFunc.valid()) { | |||||
char buffer[1024]; | |||||
sprintf_s(buffer, sizeof(buffer), "\"%s\" is not a valid keybind!", hk.c_str()); | |||||
std::string errorMessage = std::string(buffer); | |||||
printFunc(errorMessage); | |||||
} | |||||
} | |||||
} | |||||
if (anyError) { | |||||
LeaveCriticalSection(&luaCritSec); | |||||
return 0; | |||||
} | |||||
int index = -1; | |||||
for (int i = 0; i < registeredHotkeys.size(); ++i) { | |||||
sol::function testFunc = std::get<0>(registeredHotkeys[i]); | |||||
if (std::get<0>(registeredHotkeys[i]) == func) { | |||||
index = i; | |||||
break; | |||||
} | |||||
} | |||||
switch (hotkeys.size()) | |||||
{ | |||||
case 1: | |||||
if (index != -1) { | |||||
registeredHotkeys[index] = std::make_tuple(func, s.L, hotkeys.at(0), "", ""); | |||||
} | |||||
else { | |||||
registeredHotkeys.push_back(std::make_tuple(func, s.L, hotkeys.at(0), "", "")); | |||||
} | |||||
break; | |||||
case 2: | |||||
if (index != -1) { | |||||
registeredHotkeys[index] = std::make_tuple(func, s.L, hotkeys.at(0), "", ""); | |||||
} | |||||
else { | |||||
registeredHotkeys.push_back(std::make_tuple(func, s.L, hotkeys.at(0), hotkeys.at(1), "")); | |||||
} | |||||
break; | |||||
case 3: | |||||
if (index != -1) { | |||||
registeredHotkeys[index] = std::make_tuple(func, s.L, hotkeys.at(0), "", ""); | |||||
} | |||||
else { | |||||
registeredHotkeys.push_back(std::make_tuple(func, s.L, hotkeys.at(0), hotkeys.at(1), hotkeys.at(2))); | |||||
} | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
LeaveCriticalSection(&luaCritSec); | |||||
return 0; | |||||
} | |||||
void BL3Lua::RemoveHotkey(sol::this_state s, sol::this_environment e, uint32_t, sol::function func) { | |||||
lua->collect_garbage(); | |||||
} | |||||
void BL3Lua::RemoveAllHotkeys() { | |||||
EnterCriticalSection(&luaCritSec); | |||||
registeredHotkeys.clear(); | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::AddHook(sol::this_state s, sol::this_environment e, const std::string& hookName, sol::function func, bool preHook) | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
procEventHooks[hookName].push_back(std::make_tuple(func, s.L, preHook)); | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::RemoveAllHooks() | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
if (procEventHooks.size() > 0) { | |||||
procEventHooks.clear(); | |||||
} | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::RemoveHook(sol::this_state s, sol::this_environment e, const std::string& hookName, sol::function func) | |||||
{ | |||||
int index = -1; | |||||
EnterCriticalSection(&luaCritSec); | |||||
for (int i = 0; i < procEventHooks[hookName].size(); ++i) { | |||||
if (std::get<0>(procEventHooks[hookName][i]).registry_index() == func.registry_index()) { | |||||
index = i; | |||||
break; | |||||
} | |||||
} | |||||
if (index != -1) | |||||
procEventHooks[hookName].erase(procEventHooks[hookName].begin(), procEventHooks[hookName].begin() + index); | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::AddConsoleCommand(sol::this_state s, sol::this_environment e, const std::string& command, sol::function func) | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
consoleCommands[command] = std::make_tuple(func, s.L, command.size()); | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::RemoveAllConsoleCommands() | |||||
{ | |||||
EnterCriticalSection(&luaCritSec); | |||||
if (consoleCommands.size() > 0) { | |||||
consoleCommands.clear(); | |||||
} | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::RemoveConsoleCommand(sol::this_state s, sol::this_environment e, const std::string& command, sol::function func) | |||||
{ | |||||
int index = -1; | |||||
EnterCriticalSection(&luaCritSec); | |||||
for (int i = 0; i < consoleCommands.size(); ++i) { | |||||
if (std::get<0>(consoleCommands[command]) == func) { | |||||
index = i; | |||||
break; | |||||
} | |||||
} | |||||
if (index != -1){ | |||||
consoleCommands.erase(command); | |||||
} | |||||
lua->collect_garbage(); | |||||
LeaveCriticalSection(&luaCritSec); | |||||
} | |||||
void BL3Lua::registerBase() | |||||
{ | |||||
lua->set_function("IsKeyPressed", sol::overload( | |||||
[](std::string keyName) { return LuaUtility::IsKeyPressed(keyName); }, | |||||
[](std::string keyName, std::string keyName2) {return LuaUtility::IsKeyPressed(keyName, keyName2); }, | |||||
[](std::string keyName, std::string keyName2, std::string keyName3) {return LuaUtility::IsKeyPressed(keyName, keyName2, keyName3); | |||||
})); | |||||
lua->set_function("FindObject", [](std::string name) { | |||||
auto tmp = SDK::UObject::FindObject<SDK::UObject>(name); | |||||
return tmp; | |||||
}); | |||||
lua->set_function("StaticFindObject", [](SDK::UClass* pClass, const std::wstring_view name) | |||||
{ | |||||
return StaticFindObject(pClass, reinterpret_cast<SDK::UObject*>(-1), &name.data()[0], false); | |||||
}); | |||||
lua->set_function("RegisterHotkey", [&](sol::this_state s, sol::this_environment e, sol::variadic_args va) { | |||||
RegisterHotkey(s, e, va); | |||||
}); | |||||
lua->set_function("ClearHotkeys", [&]() {RemoveAllHotkeys(); }); | |||||
sol::protected_function_result result = lua->safe_script(R"( | |||||
function RegisterCallback(onEventName, lCallback) | |||||
while true do | |||||
if Callbacks then | |||||
break | |||||
end | |||||
end | |||||
if Callbacks then | |||||
Callbacks[lCallback] = onEventName | |||||
else | |||||
print("Callback-Table does not exist!") | |||||
end | |||||
end | |||||
function RunCallbacks(eventName, data) | |||||
for key, value in pairs(Callbacks) do | |||||
key(data) | |||||
end | |||||
end | |||||
function internalTDump(object) | |||||
if object == nil then | |||||
return | |||||
end | |||||
for key, value in pairs(getmetatable(object)) do | |||||
if not string.find(key, "_") and key ~= "new" then | |||||
-- if type(value) == "function" then | |||||
-- print("[Function] " .. tostring(key)) | |||||
-- else | |||||
-- print(tostring(key)) | |||||
-- end | |||||
print(tostring(key)) | |||||
end | |||||
end | |||||
end | |||||
defPrint = print | |||||
print = function(...) | |||||
for i,v in ipairs{...} do | |||||
if PrintGameConsole then | |||||
PrintGameConsole(tostring(v)) | |||||
end | |||||
end | |||||
defPrint(...) | |||||
end | |||||
)"); | |||||
if (!result.valid()) { | |||||
sol::error err = result; | |||||
std::cout << err.what() << std::endl; | |||||
} | |||||
SDK::UObject::SetupLuaBind(lua); | |||||
loadlibs(); | |||||
adjustRequirePath(); | |||||
removeAbusableFuncs(); | |||||
callbacks = lua->create_named_table("Callbacks"); | |||||
} | |||||
void BL3Lua::loadlibs() | |||||
{ | |||||
const char* jsonlua = | |||||
#include "include/json.lua" | |||||
; | |||||
const char* splitlua = | |||||
#include "include/split.lua" | |||||
; | |||||
lua->require_script("json", jsonlua); | |||||
lua->require_script("split", splitlua); | |||||
} | |||||
void BL3Lua::adjustRequirePath() { | |||||
const std::string defaultPath = (*lua)["package"]["path"]; | |||||
wchar_t pBuffer[MAX_PATH]; | |||||
GetCurrentDirectory(sizeof(pBuffer), pBuffer); | |||||
std::wstring widePath(pBuffer); | |||||
std::string path(widePath.begin(), widePath.end()); | |||||
path.append("\\lua\\Modules\\?.lua"); | |||||
(*lua)["package"]["path"] = defaultPath + ";" + path; | |||||
} | |||||
void BL3Lua::removeAbusableFuncs() { | |||||
sol::table global = lua->globals(); | |||||
if (global.valid()) { | |||||
global["os"]["remove"] = sol::lua_nil; | |||||
} | |||||
} |
@@ -0,0 +1,61 @@ | |||||
#pragma once | |||||
#define SOL_EXCEPTIONS_SAFE_PROPAGATION 1 | |||||
#define SOL_ALL_SAFETIES_ON 1 | |||||
//#include "SOL/sol.hpp" | |||||
#include "F:/Programmieren/Lua/sol2/single/single/include/sol/sol.hpp" | |||||
#include <iostream> | |||||
#include <unordered_map> | |||||
#include <vector> | |||||
#include <tuple> | |||||
//#include "C:/SDK_GEN/BL3/SDK/BL3_Basic.hpp" | |||||
//#include "C:/SDK_GEN/BL3/SDK/BL3_CoreUObject_classes.hpp" | |||||
#include "C:/SDK_GEN/BL3-2021-4-9/SDK.hpp" | |||||
#include <Windows.h> | |||||
#include "LuaComponent.h" | |||||
class BL3Lua | |||||
{ | |||||
public: | |||||
BL3Lua(); | |||||
~BL3Lua(); | |||||
bool ExecuteScriptFile(const char* filePath, bool printInGame = false); | |||||
bool ExecuteScriptString(const char* scriptCode, bool printInGame = false); | |||||
void RunCallbacks(const char* callbackName, sol::object data); | |||||
void TDump(sol::object tableToDump); | |||||
void ClearCallbacks(); | |||||
void AddHook(sol::this_state s, sol::this_environment e, const std::string& hookName, sol::function func, bool preHook); | |||||
void RemoveHook(sol::this_state s, sol::this_environment e, const std::string& hookName, sol::function func); | |||||
void RemoveAllHooks(); | |||||
void AddConsoleCommand(sol::this_state s, sol::this_environment e, const std::string& command, sol::function func); | |||||
void RemoveConsoleCommand(sol::this_state s, sol::this_environment e, const std::string& command, sol::function func); | |||||
void RemoveAllConsoleCommands(); | |||||
uint32_t RegisterHotkey(sol::this_state s, sol::this_environment e, sol::variadic_args va); | |||||
void RemoveHotkey(sol::this_state s, sol::this_environment e, uint32_t, sol::function func); | |||||
void RemoveAllHotkeys(); | |||||
void ValidateHotkeys(); | |||||
//std::vector<sol::protected_function> GetHooks(const char* hookName); | |||||
//void RegisterUtility(); | |||||
private: | |||||
void registerBase(); | |||||
void loadlibs(); | |||||
void adjustRequirePath(); | |||||
void removeAbusableFuncs(); | |||||
public: | |||||
sol::state* lua; | |||||
CRITICAL_SECTION luaCritSec; | |||||
std::unordered_map<std::string, std::vector<std::tuple<sol::reference, lua_State*, bool>>> procEventHooks; | |||||
std::unordered_map<std::string, std::tuple<sol::reference, lua_State*, size_t>> consoleCommands; | |||||
std::vector<std::tuple<sol::reference, lua_State*, std::string, std::string, std::string>> registeredHotkeys; | |||||
std::vector<LuaComponent*> loadedComponents; | |||||
private: | |||||
sol::table callbacks; | |||||
sol::environment consoleEnvironment; | |||||
}; | |||||
@@ -0,0 +1,188 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
<ItemGroup Label="ProjectConfigurations"> | |||||
<ProjectConfiguration Include="Debug-JIT|x64"> | |||||
<Configuration>Debug-JIT</Configuration> | |||||
<Platform>x64</Platform> | |||||
</ProjectConfiguration> | |||||
<ProjectConfiguration Include="Debug|x64"> | |||||
<Configuration>Debug</Configuration> | |||||
<Platform>x64</Platform> | |||||
</ProjectConfiguration> | |||||
<ProjectConfiguration Include="Release|x64"> | |||||
<Configuration>Release</Configuration> | |||||
<Platform>x64</Platform> | |||||
</ProjectConfiguration> | |||||
</ItemGroup> | |||||
<PropertyGroup Label="Globals"> | |||||
<VCProjectVersion>16.0</VCProjectVersion> | |||||
<Keyword>Win32Proj</Keyword> | |||||
<ProjectGuid>{df0b7199-3ed8-49dc-9544-46b6315d4390}</ProjectGuid> | |||||
<RootNamespace>BL3Lua</RootNamespace> | |||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> | |||||
<ProjectName>BLua</ProjectName> | |||||
</PropertyGroup> | |||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | |||||
<ConfigurationType>DynamicLibrary</ConfigurationType> | |||||
<UseDebugLibraries>true</UseDebugLibraries> | |||||
<PlatformToolset>ClangCL</PlatformToolset> | |||||
<CharacterSet>Unicode</CharacterSet> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug-JIT|x64'" Label="Configuration"> | |||||
<ConfigurationType>DynamicLibrary</ConfigurationType> | |||||
<UseDebugLibraries>true</UseDebugLibraries> | |||||
<PlatformToolset>ClangCL</PlatformToolset> | |||||
<CharacterSet>Unicode</CharacterSet> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | |||||
<ConfigurationType>DynamicLibrary</ConfigurationType> | |||||
<UseDebugLibraries>false</UseDebugLibraries> | |||||
<PlatformToolset>ClangCL</PlatformToolset> | |||||
<WholeProgramOptimization>true</WholeProgramOptimization> | |||||
<CharacterSet>Unicode</CharacterSet> | |||||
</PropertyGroup> | |||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | |||||
<ImportGroup Label="ExtensionSettings"> | |||||
</ImportGroup> | |||||
<ImportGroup Label="Shared"> | |||||
</ImportGroup> | |||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||||
</ImportGroup> | |||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug-JIT|x64'" Label="PropertySheets"> | |||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||||
</ImportGroup> | |||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||||
</ImportGroup> | |||||
<PropertyGroup Label="UserMacros" /> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||||
<LinkIncremental>true</LinkIncremental> | |||||
<IncludePath>C:\SDK_GEN\BL3-2021-4-9\SDK;F:\Programmieren\Lua\sol2\single\single\include;F:\Programmieren\Lua\lua-5.4.2_Win64_vc16_lib\include;F:\Programmieren\Lua;F:\Programmieren\C++\BL3\BL3Lua\include;$(IncludePath)</IncludePath> | |||||
<LibraryPath>F:\Programmieren\C++\BL3\BL3Lua\lib;$(LibraryPath)</LibraryPath> | |||||
<SourcePath>$(SourcePath)</SourcePath> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug-JIT|x64'"> | |||||
<LinkIncremental>true</LinkIncremental> | |||||
<IncludePath>C:\SDK_GEN\BL3-2021-4-9\SDK;F:\Programmieren\Lua\sol2\single\single\include;F:\Programmieren\Lua\lua-5.4.2_Win64_vc16_lib\include;F:\Programmieren\Lua;F:\Programmieren\C++\BL3\BL3Lua\include;$(IncludePath)</IncludePath> | |||||
<LibraryPath>F:\Programmieren\C++\BL3\BL3Lua\lib;$(LibraryPath)</LibraryPath> | |||||
<SourcePath>$(SourcePath)</SourcePath> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||||
<LinkIncremental>false</LinkIncremental> | |||||
<IncludePath>C:\SDK_GEN\BL3-2021-4-9\SDK;F:\Programmieren\Lua\sol2\single\single\include;F:\Programmieren\Lua\lua-5.4.2_Win64_vc16_lib\include;F:\Programmieren\Lua;F:\Programmieren\C++\BL3\BL3Lua\include;$(IncludePath)</IncludePath> | |||||
<LibraryPath>F:\Programmieren\C++\BL3\BL3Lua\lib;$(LibraryPath)</LibraryPath> | |||||
<SourcePath>$(SourcePath)</SourcePath> | |||||
</PropertyGroup> | |||||
<PropertyGroup Label="Vcpkg"> | |||||
<VcpkgAutoLink>false</VcpkgAutoLink> | |||||
</PropertyGroup> | |||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||||
<ClCompile> | |||||
<WarningLevel>Level3</WarningLevel> | |||||
<SDLCheck>true</SDLCheck> | |||||
<PreprocessorDefinitions>_DEBUG;BL3LUA_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
<ConformanceMode>true</ConformanceMode> | |||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> | |||||
<PrecompiledHeaderFile> | |||||
</PrecompiledHeaderFile> | |||||
<LanguageStandard>stdcpp17</LanguageStandard> | |||||
<LanguageStandard_C>stdc17</LanguageStandard_C> | |||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> | |||||
<OmitFramePointers>true</OmitFramePointers> | |||||
<BufferSecurityCheck>false</BufferSecurityCheck> | |||||
<ExceptionHandling>Async</ExceptionHandling> | |||||
<RuntimeTypeInfo>false</RuntimeTypeInfo> | |||||
</ClCompile> | |||||
<Link> | |||||
<SubSystem>Windows</SubSystem> | |||||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||||
<EnableUAC>false</EnableUAC> | |||||
<AdditionalDependencies>lua5.4.2-static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> | |||||
</Link> | |||||
</ItemDefinitionGroup> | |||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug-JIT|x64'"> | |||||
<ClCompile> | |||||
<WarningLevel>Level3</WarningLevel> | |||||
<SDLCheck>true</SDLCheck> | |||||
<PreprocessorDefinitions>_DEBUG;BL3LUA_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
<ConformanceMode>true</ConformanceMode> | |||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> | |||||
<PrecompiledHeaderFile> | |||||
</PrecompiledHeaderFile> | |||||
<LanguageStandard>stdcpp17</LanguageStandard> | |||||
<LanguageStandard_C>stdc17</LanguageStandard_C> | |||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> | |||||
<OmitFramePointers>true</OmitFramePointers> | |||||
<BufferSecurityCheck>false</BufferSecurityCheck> | |||||
<ExceptionHandling>Async</ExceptionHandling> | |||||
<RuntimeTypeInfo>false</RuntimeTypeInfo> | |||||
</ClCompile> | |||||
<Link> | |||||
<SubSystem>Windows</SubSystem> | |||||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||||
<EnableUAC>false</EnableUAC> | |||||
<AdditionalDependencies>lua5.4.2-static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> | |||||
</Link> | |||||
</ItemDefinitionGroup> | |||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||||
<ClCompile> | |||||
<WarningLevel>Level3</WarningLevel> | |||||
<FunctionLevelLinking>true</FunctionLevelLinking> | |||||
<IntrinsicFunctions>true</IntrinsicFunctions> | |||||
<SDLCheck>true</SDLCheck> | |||||
<PreprocessorDefinitions>NDEBUG;BL3LUA_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
<ConformanceMode>true</ConformanceMode> | |||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> | |||||
<PrecompiledHeaderFile> | |||||
</PrecompiledHeaderFile> | |||||
<LanguageStandard>stdcpp17</LanguageStandard> | |||||
<LanguageStandard_C>stdc17</LanguageStandard_C> | |||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> | |||||
<OmitFramePointers>true</OmitFramePointers> | |||||
<ExceptionHandling>Async</ExceptionHandling> | |||||
<BufferSecurityCheck>false</BufferSecurityCheck> | |||||
<AdditionalOptions>-m64 /GR- %(AdditionalOptions)</AdditionalOptions> | |||||
<RuntimeTypeInfo>false</RuntimeTypeInfo> | |||||
</ClCompile> | |||||
<Link> | |||||
<SubSystem>Windows</SubSystem> | |||||
<EnableCOMDATFolding>true</EnableCOMDATFolding> | |||||
<OptimizeReferences>true</OptimizeReferences> | |||||
<GenerateDebugInformation>true</GenerateDebugInformation> | |||||
<EnableUAC>false</EnableUAC> | |||||
<AdditionalDependencies>lua5.4.2-static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> | |||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> | |||||
</Link> | |||||
</ItemDefinitionGroup> | |||||
<ItemGroup> | |||||
<ClCompile Include="BL3Lua.cpp" /> | |||||
<ClCompile Include="BL3LuaDLL.cpp" /> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_Basic.cpp" /> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_CoreUObject_functions.cpp" /> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_Engine_functions.cpp" /> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_GbxUI_functions.cpp" /> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_OakGame_functions.cpp" /> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_ScaleformUI_functions.cpp" /> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_UMG_functions.cpp" /> | |||||
<ClCompile Include="LuaComponent.cpp" /> | |||||
<ClCompile Include="LuaUtility.cpp" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ClInclude Include="BitFields.hpp" /> | |||||
<ClInclude Include="BL3Lua.h" /> | |||||
<ClInclude Include="Helper.hpp" /> | |||||
<ClInclude Include="include\LuaComponent.h" /> | |||||
<ClInclude Include="include\Patterns.h" /> | |||||
<ClInclude Include="include\Utility.hpp" /> | |||||
<ClInclude Include="LuaUtility.h" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<None Include="include\json.lua" /> | |||||
<None Include="split.lua" /> | |||||
</ItemGroup> | |||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||||
<ImportGroup Label="ExtensionTargets"> | |||||
</ImportGroup> | |||||
</Project> |
@@ -0,0 +1,86 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
<ItemGroup> | |||||
<Filter Include="Source Files"> | |||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> | |||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> | |||||
</Filter> | |||||
<Filter Include="Header Files"> | |||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> | |||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> | |||||
</Filter> | |||||
<Filter Include="Resource Files"> | |||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> | |||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> | |||||
</Filter> | |||||
<Filter Include="SDK-CPP"> | |||||
<UniqueIdentifier>{f40848c6-786f-425a-aeb2-8f803968ded9}</UniqueIdentifier> | |||||
</Filter> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ClCompile Include="BL3LuaDLL.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="BL3Lua.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="LuaUtility.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="LuaComponent.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_CoreUObject_functions.cpp"> | |||||
<Filter>SDK-CPP</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_Basic.cpp"> | |||||
<Filter>SDK-CPP</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_OakGame_functions.cpp"> | |||||
<Filter>SDK-CPP</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_Engine_functions.cpp"> | |||||
<Filter>SDK-CPP</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_GbxUI_functions.cpp"> | |||||
<Filter>SDK-CPP</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_ScaleformUI_functions.cpp"> | |||||
<Filter>SDK-CPP</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="C:\SDK_GEN\BL3-2021-4-9\SDK\BL3_UMG_functions.cpp"> | |||||
<Filter>SDK-CPP</Filter> | |||||
</ClCompile> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ClInclude Include="BitFields.hpp"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="BL3Lua.h"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="Helper.hpp"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="LuaUtility.h"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="include\LuaComponent.h"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="include\Patterns.h"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="include\Utility.hpp"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<None Include="include\json.lua"> | |||||
<Filter>Resource Files</Filter> | |||||
</None> | |||||
<None Include="split.lua"> | |||||
<Filter>Resource Files</Filter> | |||||
</None> | |||||
</ItemGroup> | |||||
</Project> |
@@ -0,0 +1,18 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | |||||
<LocalDebuggerCommand>E:\SteamLibrary\steamapps\common\Borderlands 3\OakGame\Binaries\Win64\Borderlands3.exe</LocalDebuggerCommand> | |||||
<LocalDebuggerAttach>true</LocalDebuggerAttach> | |||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug-JIT|x64'"> | |||||
<LocalDebuggerCommand>E:\SteamLibrary\steamapps\common\Borderlands 3\OakGame\Binaries\Win64\Borderlands3.exe</LocalDebuggerCommand> | |||||
<LocalDebuggerAttach>true</LocalDebuggerAttach> | |||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||||
<LocalDebuggerCommand>E:\SteamLibrary\steamapps\common\Borderlands 3\OakGame\Binaries\Win64\Borderlands3.exe</LocalDebuggerCommand> | |||||
<LocalDebuggerAttach>true</LocalDebuggerAttach> | |||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> | |||||
</PropertyGroup> | |||||
</Project> |
@@ -0,0 +1,88 @@ | |||||
#pragma once | |||||
#include <cstddef> | |||||
#include <cstdint> | |||||
#include <climits> | |||||
#include <type_traits> | |||||
// https://stackoverflow.com/a/263738 | |||||
/* a=target variable, b=bit number to act upon 0-n */ | |||||
#define BIT_SET(a,b) ((a) |= (1ULL<<(b))) | |||||
#define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b))) | |||||
#define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b))) | |||||
#define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b)))) // '!!' to make sure this returns 0 or 1 | |||||
/* x=target variable, y=mask */ | |||||
#define BITMASK_SET(x,y) ((x) |= (y)) | |||||
#define BITMASK_CLEAR(x,y) ((x) &= (~(y))) | |||||
#define BITMASK_FLIP(x,y) ((x) ^= (y)) | |||||
#define BITMASK_CHECK_ALL(x,y) (!(~(x) & (y))) | |||||
#define BITMASK_CHECK_ANY(x,y) ((x) & (y)) | |||||
namespace itsy_bitsy { | |||||
template <std::size_t sz, typename C = void> | |||||
struct bit_type { | |||||
typedef uint64_t type; | |||||
}; | |||||
template <std::size_t sz> | |||||
struct bit_type<sz, std::enable_if_t<(sz <= 1)>> { | |||||
typedef bool type; | |||||
}; | |||||
template <std::size_t sz> | |||||
struct bit_type<sz, std::enable_if_t<(sz > 2 && sz <= 16)>> { | |||||
typedef uint16_t type; | |||||
}; | |||||
template <std::size_t sz> | |||||
struct bit_type<sz, std::enable_if_t<(sz > 16 && sz <= 32)>> { | |||||
typedef uint32_t type; | |||||
}; | |||||
template <std::size_t sz> | |||||
struct bit_type<sz, std::enable_if_t<(sz > 32 && sz <= 64)>> { | |||||
typedef uint64_t type; | |||||
}; | |||||
template <std::size_t sz> | |||||
using bit_type_t = typename bit_type<sz>::type; | |||||
template <typename T, typename V> | |||||
bool vcxx_warning_crap(std::true_type, V val) { | |||||
return val != 0; | |||||
} | |||||
template <typename T, typename V> | |||||
T vcxx_warning_crap(std::false_type, V val) { | |||||
return static_cast<T>(val); | |||||
} | |||||
template <typename T, typename V> | |||||
auto vcxx_warning_crap(V val) { | |||||
return vcxx_warning_crap<T>(std::is_same<bool, T>(), val); | |||||
} | |||||
template <typename Base, std::size_t baseOffset = 0x0, std::size_t bit_target = 0x0, std::size_t size = 0x1> | |||||
void write(Base& b, bit_type_t<size> bits) { | |||||
uintptr_t baseAddr = reinterpret_cast<uintptr_t>(&b); | |||||
uintptr_t offs = baseOffset; | |||||
unsigned char* byt = reinterpret_cast<unsigned char*>(baseAddr + offs); | |||||
char testb = *byt & (1 << bit_target); | |||||
if (bits) | |||||
BIT_SET(*byt, bit_target); | |||||
else | |||||
BIT_CLEAR(*byt, bit_target); | |||||
} | |||||
template <typename Base, std::size_t baseOffset = 0x0, std::size_t bit_target = 0x0, std::size_t size = 0x1> | |||||
bit_type_t<size> read(Base& b) { | |||||
uintptr_t baseAddr = reinterpret_cast<uintptr_t>(&b); | |||||
uintptr_t offs = baseOffset; | |||||
unsigned char* byt = reinterpret_cast<unsigned char*>(baseAddr + offs); | |||||
char test = *byt & (1 << bit_target); | |||||
if (test) | |||||
return true; | |||||
return false; | |||||
} | |||||
} |
@@ -0,0 +1,78 @@ | |||||
#pragma once | |||||
#include <windows.h> | |||||
/* | |||||
A safer replacement for the obsolete IsBadReadPtr() and IsBadWritePtr() WinAPI functions | |||||
on top of VirtualQuery() which respects Windows guard pages. It does not use SEH | |||||
and is designed to be compatible with the above-mentioned functions. | |||||
The calls to the IsBadReadPtr() and IsBadWritePtr() can be replaced with the calls to | |||||
the IsBadMemPtr() as follows: | |||||
- IsBadReadPtr(...) => IsBadMemPtr(FALSE, ...) | |||||
- IsBadWritePtr(...) => IsBadMemPtr(TRUE, ...) | |||||
*/ | |||||
BOOL IsBadMemPtr(/*BOOL write, */void* ptr, size_t size) | |||||
{ | |||||
MEMORY_BASIC_INFORMATION mbi; | |||||
BOOL ok; | |||||
DWORD mask; | |||||
BYTE* p = (BYTE*)ptr; | |||||
BYTE* maxp = p + size; | |||||
BYTE* regend = NULL; | |||||
if (size == 0) | |||||
{ | |||||
return FALSE; | |||||
} | |||||
if (p == NULL) | |||||
{ | |||||
return TRUE; | |||||
} | |||||
/*if (write == FALSE) | |||||
{ | |||||
mask = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; | |||||
} | |||||
else | |||||
{*/ | |||||
mask = PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; | |||||
/*}*/ | |||||
do | |||||
{ | |||||
if (p == ptr || p == regend) | |||||
{ | |||||
if (VirtualQuery((LPCVOID)p, &mbi, sizeof(mbi)) == 0) | |||||
{ | |||||
return TRUE; | |||||
} | |||||
else | |||||
{ | |||||
regend = ((BYTE*)mbi.BaseAddress + mbi.RegionSize); | |||||
} | |||||
} | |||||
ok = (mbi.Protect & mask) != 0; | |||||
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) | |||||
{ | |||||
ok = FALSE; | |||||
} | |||||
if (!ok) | |||||
{ | |||||
return TRUE; | |||||
} | |||||
if (maxp <= regend) /* the whole address range is inside the current memory region */ | |||||
{ | |||||
return FALSE; | |||||
} | |||||
else if (maxp > regend) /* this region is a part of (or overlaps with) the address range we are checking */ | |||||
{ | |||||
p = regend; /* lets move to the next memory region */ | |||||
} | |||||
} while (p < maxp); | |||||
return FALSE; | |||||
} |
@@ -0,0 +1,61 @@ | |||||
#include "LuaComponent.h" | |||||
LuaComponent::LuaComponent() { | |||||
this->m_Env = nullptr; | |||||
this->m_FileName = ""; | |||||
} | |||||
LuaComponent::LuaComponent(const std::string& fileName, sol::state* state) { | |||||
this->m_FileName = fileName; | |||||
this->state = state; | |||||
} | |||||
LuaComponent::~LuaComponent() { | |||||
if (m_Env) { | |||||
sol::protected_function releaseFunc = m_Env["OnRelease"]; | |||||
if (releaseFunc.valid()) { | |||||
releaseFunc.call(); | |||||
} | |||||
m_Env.clear(); | |||||
m_Env = sol::lua_nil; | |||||
} | |||||
} | |||||
void LuaComponent::Init() { | |||||
LoadScript(m_FileName); | |||||
OnInit(); | |||||
} | |||||
void LuaComponent::OnInit() { | |||||
if (m_Env) { | |||||
sol::protected_function initFunc = m_Env["OnInit"]; | |||||
if (initFunc.valid()) { | |||||
initFunc.call(); | |||||
} | |||||
} | |||||
} | |||||
void LuaComponent::LoadScript(const std::string& fileName) { | |||||
m_FileName = fileName; | |||||
//m_Env = std::make_unique<sol::environment>(sol::environment(*state, sol::create, state->globals())).get(); | |||||
m_Env = sol::environment(*state, sol::create, state->globals()); | |||||
sol::load_result error = state->load_file(fileName); | |||||
if (error.status() == sol::load_status::ok) { | |||||
try { | |||||
auto func_result = state->safe_script_file(fileName, m_Env); | |||||
if (!func_result.valid()) { | |||||
sol::error err = error; | |||||
std::cout << "[LUA] lua_dofile failed with error: " << err.what() << std::endl; | |||||
sol::protected_function printFunc = (*(state))["PrintGameConsole"]; | |||||
if (printFunc.valid()) { | |||||
std::string errorMessage = std::string("[LUA] failed with error: ").append(err.what()); | |||||
printFunc(errorMessage); | |||||
} | |||||
} | |||||
} | |||||
catch (...) { | |||||
} | |||||
} | |||||
state->collect_garbage(); | |||||
} |
@@ -0,0 +1,151 @@ | |||||
#include "LuaUtility.h" | |||||
#include <windows.h> | |||||
#include <WinUser.h> | |||||
#include <string> | |||||
static std::unordered_map<std::string, uint8_t> keyMap; | |||||
LuaUtility::LuaUtility() | |||||
{ | |||||
keyMap = GetKeyMap(); | |||||
} | |||||
bool LuaUtility::IsKeyPressed(std::string keyName) | |||||
{ | |||||
if (keyName.length() > 1) { | |||||
std::transform(keyName.begin(), keyName.end(), keyName.begin(), [](unsigned char c) {return std::tolower(c); }); | |||||
auto keycode = GetKeyMap()[keyName]; | |||||
return (GetAsyncKeyState(GetKeyMap()[keyName]) & 0x8000) != 0; | |||||
} | |||||
else { | |||||
std::transform(keyName.begin(), keyName.end(), keyName.begin(), [](unsigned char c) {return std::toupper(c); }); | |||||
return (GetAsyncKeyState(keyName.c_str()[0]) & 0x8000) != 0; | |||||
} | |||||
return false; | |||||
} | |||||
bool LuaUtility::IsKeyPressed(std::string keyName, std::string keyName2) | |||||
{ | |||||
std::vector<uint8_t> keys; | |||||
std::string current = keyName; | |||||
for (int i = 0; i < 2; i++) { | |||||
if (current.length() > 1) { | |||||
std::transform(current.begin(), current.end(), current.begin(), [](unsigned char c) {return std::tolower(c); }); | |||||
keys.push_back(GetKeyMap()[current]); | |||||
} | |||||
else { | |||||
std::transform(current.begin(), current.end(), current.begin(), [](unsigned char c) {return std::toupper(c); }); | |||||
keys.push_back(current.c_str()[0]); | |||||
} | |||||
current = keyName2; | |||||
} | |||||
return ((GetAsyncKeyState(keys[0]) & 0x8000) && GetAsyncKeyState(keys[1]) & 0x8000) != 0; | |||||
} | |||||
bool LuaUtility::IsKeyPressed(std::string keyName, std::string keyName2, std::string keyName3) | |||||
{ | |||||
std::vector<uint8_t> keys; | |||||
std::string current = keyName; | |||||
for (int i = 0; i < 3; i++) { | |||||
if (current.length() > 1) { | |||||
std::transform(current.begin(), current.end(), current.begin(), [](unsigned char c) {return std::tolower(c); }); | |||||
keys.push_back(GetKeyMap()[current]); | |||||
} | |||||
else { | |||||
std::transform(current.begin(), current.end(), current.begin(), [](unsigned char c) {return std::toupper(c); }); | |||||
keys.push_back(current.c_str()[0]); | |||||
} | |||||
if (i == 0) | |||||
current = keyName2; | |||||
else | |||||
current = keyName3; | |||||
} | |||||
return ((GetAsyncKeyState(keys[0]) & 0x8000) && GetAsyncKeyState(keys[1] & 0x8000) && GetAsyncKeyState(keys[2]) & 0x8000) != 0; | |||||
} | |||||
bool LuaUtility::ContainsKey(std::string keyName) { | |||||
if (keyMap.size() == 0) | |||||
keyMap = GetKeyMap(); | |||||
std::transform(keyName.begin(), keyName.end(), keyName.begin(), [](unsigned char c) {return std::tolower(c); }); | |||||
return keyMap.find(keyName) != keyMap.end(); | |||||
} | |||||
std::unordered_map<std::string, uint8_t> LuaUtility::GetKeyMap() | |||||
{ | |||||
if (!keyMap.size()) { | |||||
keyMap.insert(std::pair<std::string, uint8_t>("backspace", VK_BACK)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("tab", VK_TAB)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("clear", VK_CLEAR)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("return", VK_RETURN)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("enter", VK_RETURN)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("shift", VK_SHIFT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("ctrl", VK_CONTROL)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("alt", VK_MENU)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("pause", VK_PAUSE)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("capslock", VK_CAPITAL)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("escape", VK_ESCAPE)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("space", VK_SPACE)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("pageup", VK_PRIOR)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("pagedown", VK_NEXT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("end", VK_END)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("home", VK_HOME)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("left", VK_LEFT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("up", VK_UP)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("right", VK_RIGHT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("down", VK_DOWN)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("printscr", VK_SNAPSHOT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("insert", VK_INSERT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("delete", VK_DELETE)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f1", VK_F1)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f2", VK_F2)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f3", VK_F3)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f4", VK_F4)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f5", VK_F5)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f6", VK_F6)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f7", VK_F7)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f8", VK_F8)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f9", VK_F9)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f10", VK_F10)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f11", VK_F11)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("f12", VK_F12)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad0", VK_NUMPAD0)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad1", VK_NUMPAD1)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad2", VK_NUMPAD2)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad3", VK_NUMPAD3)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad4", VK_NUMPAD4)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad5", VK_NUMPAD5)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad6", VK_NUMPAD6)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad7", VK_NUMPAD7)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad8", VK_NUMPAD8)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numpad9", VK_NUMPAD9)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("multiply", VK_MULTIPLY)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("add", VK_ADD)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("subtract", VK_SUBTRACT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("decimal", VK_DECIMAL)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("divide", VK_DIVIDE)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("numlock", VK_NUMLOCK)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("0", 0x30)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("1", 0x31)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("2", 0x32)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("3", 0x33)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("4", 0x34)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("5", 0x35)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("6", 0x36)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("7", 0x37)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("8", 0x38)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("9", 0x39)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("scrollock", VK_SCROLL)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("lshift", VK_LSHIFT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("rshift", VK_RSHIFT)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("lctrl", VK_LCONTROL)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("rctrl", VK_RCONTROL)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("lalt", VK_LMENU)); | |||||
keyMap.insert(std::pair<std::string, uint8_t>("ralt", VK_RMENU)); | |||||
} | |||||
return keyMap; | |||||
} |
@@ -0,0 +1,18 @@ | |||||
#pragma once | |||||
#include <algorithm> | |||||
#include <vector> | |||||
#include <unordered_map> | |||||
class LuaUtility | |||||
{ | |||||
public: | |||||
LuaUtility(); | |||||
static bool IsKeyPressed(std::string keyName); | |||||
static bool IsKeyPressed(std::string keyName, std::string keyName2); | |||||
static bool IsKeyPressed(std::string keyName, std::string keyName2, std::string keyName3); | |||||
static bool ContainsKey(std::string keyName); | |||||
private: | |||||
static std::unordered_map<std::string, uint8_t> GetKeyMap(); | |||||
}; |
@@ -0,0 +1,21 @@ | |||||
#pragma once | |||||
#include "F:/Programmieren/Lua/sol2/single/single/include/sol/sol.hpp" | |||||
#include <iostream> | |||||
class LuaComponent | |||||
{ | |||||
public: | |||||
LuaComponent(); | |||||
LuaComponent(const std::string& fileName, sol::state* state); | |||||
~LuaComponent(); | |||||
void Init(); | |||||
void OnInit(); | |||||
void LoadScript(const std::string& fileName); | |||||
public: | |||||
std::string m_FileName; | |||||
sol::environment m_Env; | |||||
sol::state* state; | |||||
}; | |||||
@@ -0,0 +1,73 @@ | |||||
#pragma once | |||||
#include "F:/Programmieren/C++/xorstr-master/include/xorstr.hpp" | |||||
auto gObjPattern = xorstr("44 8b 54 24 50 48 8d 05 ?? ?? ?? ?? ?? f6 48 89 01 48 89 71 10"); | |||||
auto gNamesPattern = xorstr("48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 85 C0 75 5F B9 08 04 ?? ?? 48 89 5C 24 20 E8"); | |||||
auto processEventPattern = xorstr("40 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8D ?? ?? ?? 48 89 9D ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C5 48 89 85 ?? ?? ?? ?? 8B 41"); | |||||
auto getTransientPackagePattern = xorstr("48 8b 4c 24 50 48 89 05 ?? ?? ?? ?? 48 85 c9 74 05 e8"); | |||||
auto mallocPattern = xorstr("48 89 5C 24 ?? 57 48 83 EC 20 48 8B F9 8B DA 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 0C E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01 44 8B C3 48 8B D7 48 8B 5C 24 ?? 48 83 C4 20 5F 48 FF 60 10"); | |||||
auto reallocPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F1 41 8B D8 48 8B 0D ?? ?? ?? ?? 48 8B FA 48 85 C9 75 0C E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01 44 8B CB 4C 8B C7 48 8B D6 48 8B 5C 24 ?? 48 8B 74 24 ?? 48 83 C4 20 5F 48 FF 60 18"); | |||||
auto fnamectorPattern = xorstr("40 53 48 83 EC 30 C7 44 24"); | |||||
auto ufunctionBindPattern = xorstr("40 ?? 48 83 EC ?? 48 8B ?? E8 ?? ?? ?? ?? F7 83 88 00 00 00"); | |||||
auto ftextfromstringPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 30 48 63 7A ?? 33 C0 48 8B 32 48 8B D9 48 89 44 24 ?? 89 7C 24 ?? 85 FF 75 ?? 89 44 24 ?? EB ?? 45 33 C0 48 8D 4C 24 ?? 8B D7 E8 ?? ?? ?? ?? 48 8B"); | |||||
auto getWorldFromContextObjectPattern = xorstr("48 89 5c 24 18 56 48 83 ec 40 41 8b d8 48 8b f2 48 85 d2 75 2a 83 fb 01 75 18 33 c0 48 8d"); | |||||
auto isValidLowLevelPattern = xorstr("4C 8B C1 48 85 C9 74 4F"); | |||||
auto staticConstructObjectPattern = xorstr("48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 44 8B A5"); | |||||
auto staticDuplicateObjectPattern = xorstr("4C 89 44 24 ?? 55 53 56 57 41 54 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05"); | |||||
auto newObjectPattern = xorstr("48 89 5c 24 18 55 56 57 41 54 41 55 41 56 41 57 48 8d ac 24 40 ff ff ff 48 81 ec c0 01 00 00 48 8b 05 ?? ?? ?? ?? 48 33 c4 48 89 85 b0 00 00 00 44 8b a5 20 01 00 00"); | |||||
auto getWorldPattern = xorstr("40 53 48 83 EC 20 8B 41 ?? 48 8B D9 C1 E8 04 A8 01 75 ?? 48 8B 49"); | |||||
auto spawnActorPattern = xorstr("40 53 56 57 48 83 EC 70 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 ?? 0F 28 1D"); | |||||
auto getMapNamePattern = xorstr("48 89 5C 24 ?? 56 48 83 EC 30 33 F6 48 8B D9 48 89 31 44 8B C6"); | |||||
auto functionInvokePattern = xorstr("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 20 8B 41 08 4D 8B F1"); | |||||
auto callFuncPattern = xorstr("48 89 ?? ?? ?? 48 89 ?? ?? ?? 57 48 83 EC ?? 48 8B ?? ?? 48 8B ?? 49 8B ?? 48 8B ?? F2 0F"); | |||||
auto staticExecPattern = xorstr("4C 89 ?? ?? ?? 55 53 56 41 ?? 41 ?? 48 8B"); | |||||
auto getGlobalLogSingletonPattern = xorstr("48 83 EC 28 65 48 8B 04 25 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8B 0C C8 8B 04 0A 39 05 ?? ?? ?? ?? 7F 0C 48 8D 05 ?? ?? ?? ?? 48 83 C4 28 C3 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 3D ?? ?? ?? ?? ?? 75 DF 48 8D 05 ?? ?? ?? ?? 66 C7 05"); | |||||
auto consoleOutputDeviceShowPattern = xorstr("40 55 53 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 2F 48 8B 41 20"); | |||||
auto addOutputDevicePattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 54 24 ?? 57 48 83 EC 20 48 8B F1 48 8B FA 48 83 C1 48"); | |||||
auto createConsoleOutputDevice = xorstr("48 83 EC 28 B9 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 C9 48 85 C0 74 25 66 C7 40"); | |||||
auto consoleOutputTextPattern = xorstr("48 8B C4 55 56 48 8D 68 A1 48 81 EC ?? ?? ?? ?? 48 89 58 08 48 63 5A 08"); | |||||
auto consoleClearOutputPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B 59 50 48 8D 71 50"); | |||||
auto addToViewportPattern = xorstr("48 8B 01 44 8B C2 33 D2"); | |||||
auto registerFunctionAPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 49 8B F0 48 8B D9 41 B8"); | |||||
auto registerFunctionOtherPattern = xorstr("45 85 C0 0F 84 ?? ?? ?? ?? 4C 8B DC 41 56"); | |||||
auto staticLoadObjectPattern = xorstr("40 ?? 53 56 57 41 ?? 41 ?? 41 ?? 41 ?? 48 8D ?? ?? ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B ?? ?? ?? ?? ?? 48 33 ?? 48 89 ?? ?? ?? ?? ?? 0F B6 ?? ?? ?? ?? ?? 49 8B ?? 4C 8B ?? ?? ?? ?? ?? 33 DB"); | |||||
auto staticFindObjectPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 55 57 41 54 41 56 41 57 48 8B EC 48 83 EC 60 80 3D"); | |||||
auto dumpObjectToStringPattern = xorstr("4C 8B ?? 53 48 81 EC ?? ?? ?? ?? 48 8B ?? ?? ?? ?? ?? 48 33 ?? 48 89 ?? ?? ?? ?? ?? ?? 49 89 ?? ?? B9"); | |||||
auto FOakPlayerManager__DoSparkAuthenticationPattern = xorstr("48 8B ?? 55 53 56 48 8D ?? ?? 48 81 EC ?? ?? ?? ?? 48 89 ?? ?? 33 FF"); | |||||
auto FOakStartupProcess__PerformStepPattern = xorstr("40 ?? 53 56 57 48 8D ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B ?? ?? 48 8B ?? 48 89"); | |||||
auto FGbxSparkModuleGetPattern = xorstr("48 83 EC ?? 48 8B ?? ?? ?? ?? ?? 48 85 ?? 75 ?? 44 8D ?? ?? 48 89 ?? ?? ?? 48 8D ?? ?? ?? ?? ?? 48 8D ?? ?? ?? E8 ?? ?? ?? ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B ?? ?? ?? ?? ?? 48 8B ?? ?? ?? 48 83 C4 ?? C3 CC CC 48 89 ?? ?? ?? 57"); | |||||
auto FSparkInitProcessStartProcessPattern = xorstr("40 57 48 83 EC 20 48 83 3D ?? ?? ?? ?? ?? 48 8B F9 75 34"); | |||||
auto FSparkInitProcessReadDiscoveryPattern = xorstr("48 8B ?? 55 48 8D ?? ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 89 ?? ?? 48 89 ?? ?? 0F B6"); | |||||
auto oakGameInstanceProcessPendingMicropatchesPattern = xorstr("4C 8B ?? 55 56 41 ?? 49 8D ?? ?? 48 81 EC ?? ?? ?? ?? 4C 8D"); | |||||
auto oakGameStateRefreshMicropatchSwitchesPattern = xorstr("40 ?? 48 83 EC ?? 48 8B ?? ?? ?? ?? ?? 48 33 ?? 48 89 ?? ?? ?? 80 B9 28 01 00 00"); | |||||
auto buildMainMenuPattern = xorstr("40 ?? 56 41 ?? 48 8D ?? ?? ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B ?? ?? ?? ?? ?? 48 33 ?? 48 89 ?? ?? ?? ?? ?? 45 33"); | |||||
auto buildPauseMenuPattern = xorstr("48 8B ?? 55 53 57 48 8D ?? ?? 48 81 EC ?? ?? ?? ?? 48 89 ?? ?? 48 8B ?? 4C 89 ?? ?? 4C 89 ?? ?? 4C 89"); | |||||
auto buildOptionsMenuPattern = xorstr("48 8B C4 55 56 48 8D 68 A1 48 81 EC ?? ?? ?? ?? 48 83 B9 ?? ?? ?? ?? ?? 48 8B F1 0F 84 ?? ?? ?? ?? 80 B9 ?? ?? ?? ?? ?? 48 89 58 E8"); | |||||
auto mainAndPauseMenuAddMenuItemPattern = xorstr("48 89 54 24 ?? 48 89 4C 24 ?? 55 53 56 57 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 83 B9"); | |||||
auto mainAndPauseMenuRemoveAllItemsPattern = xorstr("40 ?? 48 83 EC ?? 48 8B ?? 48 81 C1 ?? ?? ?? ?? 83 79 0C ?? C7 41 08 ?? ?? ?? ?? 74 ?? 33 D2 E8 ?? ?? ?? ?? 48 8B ?? ?? ?? ?? ?? 48 85"); | |||||
auto mainAndPauseMenuStartMenuTransitionPattern = xorstr("48 89 5C 24 ?? 55 57 41 56 48 81 EC ?? ?? ?? ?? 83 B9"); | |||||
auto scrollingListInsertListItemPattern = xorstr("48 8B ?? 4C 89 ?? ?? 55 48 8D ?? ?? 48 81 EC ?? ?? ?? ?? 48 89 ?? ?? 4C 8B"); | |||||
auto listItemNumberInitializeItemPattern = xorstr("40 ?? 48 83 EC ?? 0F 29 ?? ?? ?? 48 8B ?? 48 8B ?? ?? ?? ?? ?? 0F 28 ?? 0F 29 ?? ?? ?? 0F 28 ?? 48 85 ?? 74 ?? 48 8B ?? 45 33"); | |||||
auto optionBaseCreateContentPanelPattern = xorstr("40 ?? 48 83 EC ?? 48 8B ?? ?? ?? 48 8B ?? 48 89 ?? ?? 48 8B"); | |||||
auto optionBaseCreateContentPanelItemPattern = xorstr("48 85 ?? 0F 84 ?? ?? ?? ?? 56 57 48 83 EC ?? 48 8B ?? 48 8B ?? E8 ?? ?? ?? ?? 84 C0"); | |||||
auto optionBaseMenuLoadBaseOptionsMenuPattern = xorstr("40 ?? 41 ?? 48 8B ?? 48 83 EC ?? 4C 8B ?? E8 ?? ?? ?? ?? 49 83 BE 10 06 00 00"); | |||||
auto gfxOptionsMenuCreateOptionPanelPattern = xorstr("89 54 ?? ?? 55 56 41 ?? 48 8D ?? ?? ?? ?? ?? ?? 48 81 EC"); | |||||
auto gfxOptionsMenuOnGFxMenuIsInitedAndStartedBeginPattern = xorstr("40 ?? 48 83 EC ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B ?? E8 ?? ?? ?? ?? 8B 15"); | |||||
auto optionBaseSetupSpinnerItemPattern = xorstr("48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 57 48 83 EC ?? 49 8B ?? 41 8B ?? 48 8B ?? 48 8B ?? 48 85 ?? 0F 84 ?? ?? ?? ?? 48 8D ?? ?? ?? 48 8B ?? E8 ?? ?? ?? ?? 4C 8D ?? ?? ?? ?? ?? 48 89 ?? ?? ?? 44 8B ?? 48 8D ?? ?? ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B ?? 48 85 ?? 74 ?? 48 8B ?? 48 8B ?? E8 ?? ?? ?? ?? 48 83 7F 70"); | |||||
auto optionBaseSetupSpinnerItemAsBooleanPattern = xorstr("48 8B ?? 48 89 ?? ?? 55 57 41 ?? 48 81 EC ?? ?? ?? ?? 49 8B ?? 41 0F"); | |||||
auto optionBaseSetupSpinnerItemWithTextPattern = xorstr("48 89 ?? ?? ?? 56 57 41 ?? 48 83 EC ?? 48 83 B9 80 00 00 00 ?? 41 8B"); | |||||
auto optionBaseSetupTitleItemPattern = xorstr("4C 8B ?? 55 53 57 49 8D ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B ?? ?? ?? ?? ?? 48 33 ?? 48 89 ?? ?? 48 83 B9 80 00 00 00"); | |||||
auto optionBaseSetupButtonItemPattern = xorstr("48 89 ?? ?? ?? 48 89 ?? ?? ?? 41 ?? 48 83 EC ?? 49 8B ?? 48 8B ?? 4C 8B ?? 48 85 ?? 0F 84"); | |||||
auto optionBaseSetupSliderItemPattern = xorstr("48 8B ?? 55 56 41 ?? 48 81 EC ?? ?? ?? ?? 0F 29 ?? ?? 0F 28 ?? 4D 8B"); | |||||
auto optionBaseSetupDropdownListItemPattern = xorstr("48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 57 48 83 EC ?? 41 8B ?? 49 8B ?? 48 8B ?? 48 8B ?? 48 85 ?? 0F 84 ?? ?? ?? ?? 48 8D ?? ?? ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B ?? ?? ?? ?? ?? ?? 48 8D ?? ?? ?? 44 8B ?? 48 89 ?? ?? ?? 4C 8B ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B ?? 48 85 ?? 74 ?? 48 8B ?? 48 8B ?? E8 ?? ?? ?? ?? 48 83 7F 70 ?? 74 ?? 80 BB 17 01 00 00 ?? 74 ?? 48 8B ?? ?? 48 85 ?? 74 ?? E8 ?? ?? ?? ?? 84 C0 74 ?? B2 ?? EB ?? 32 D2 48 8D ?? ?? ?? ?? ?? 48 8B ?? FF 50 ?? 48 8B"); | |||||
auto optionBaseSetupControlsItemPattern = xorstr("48 8B ?? 57 41 ?? 41 ?? 41 ?? 48 83 EC ?? 4D 8B"); | |||||
auto listItemSpinnerSetDefaultValuePattern = xorstr("48 8B ?? 89 91 ?? ?? ?? ?? C6 81 3C 03 00 00"); | |||||
auto listItemNumberGetCurrentValuePattern = xorstr("48 89 ?? ?? ?? 57 48 83 EC ?? 48 8B ?? 48 8B ?? 48 8B ?? ?? ?? ?? ?? 48 85 ?? 74 ?? E8 ?? ?? ?? ?? 48 85 ?? 74 ?? 48 8B ?? E8 ?? ?? ?? ?? F3 0F ?? ?? ?? ?? ?? ?? 65 48 ?? ?? ?? ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8B ?? ?? 8B 04 ?? 39 05 ?? ?? ?? ?? 0F 8F ?? ?? ?? ?? F3 0F ?? ?? ?? ?? ?? ?? 48 8D ?? ?? ?? ?? ?? F3 0F"); | |||||
auto listItemNumberSetDefaultValuePattern = xorstr("40 ?? 48 83 EC ?? F3 0F ?? ?? ?? ?? ?? ?? 48 8B ?? C6 81 84 03 00 00"); | |||||
auto listItemComboBoxSetDefaultValuePattern = xorstr("48 8B ?? ?? ?? ?? ?? 89 91 ?? ?? ?? ?? C6 81 2C 03 00 00"); | |||||
auto listItemComboBoxGetSelectedIndexPattern = xorstr("48 8B ?? ?? ?? ?? ?? 48 85 ?? 74 ?? 48 8B ?? ?? ?? ?? ?? 8B 80 ?? ?? ?? ?? C3"); | |||||
auto listItemSpinnerGetCurrentSelectionIndexPattern = xorstr("48 8B ?? ?? ?? ?? ?? 48 85 ?? 0F 85 ?? ?? ?? ?? B8 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC CC CC 48 8B"); |
@@ -0,0 +1,14 @@ | |||||
#pragma once | |||||
std::string Replace(std::string str, const std::string& strToFind, const std::string& replaceWith) { | |||||
size_t index = 0; | |||||
std::string result = str; | |||||
while (true) { | |||||
index = result.find(strToFind, index); | |||||
if (index == std::string::npos) | |||||
break; | |||||
result.replace(index, strToFind.size(), replaceWith); | |||||
index += replaceWith.size(); | |||||
} | |||||
return result; | |||||
} |
@@ -0,0 +1,390 @@ | |||||
R"( | |||||
-- | |||||
-- json.lua | |||||
-- | |||||
-- Copyright (c) 2020 rxi | |||||
-- | |||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of | |||||
-- this software and associated documentation files (the "Software"), to deal in | |||||
-- the Software without restriction, including without limitation the rights to | |||||
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |||||
-- of the Software, and to permit persons to whom the Software is furnished to do | |||||
-- so, subject to the following conditions: | |||||
-- | |||||
-- The above copyright notice and this permission notice shall be included in all | |||||
-- copies or substantial portions of the Software. | |||||
-- | |||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
-- SOFTWARE. | |||||
-- | |||||
local json = { _version = "0.1.2" } | |||||
------------------------------------------------------------------------------- | |||||
-- Encode | |||||
------------------------------------------------------------------------------- | |||||
local encode | |||||
local escape_char_map = { | |||||
[ "\\" ] = "\\", | |||||
[ "\"" ] = "\"", | |||||
[ "\b" ] = "b", | |||||
[ "\f" ] = "f", | |||||
[ "\n" ] = "n", | |||||
[ "\r" ] = "r", | |||||
[ "\t" ] = "t", | |||||
} | |||||
local escape_char_map_inv = { [ "/" ] = "/" } | |||||
for k, v in pairs(escape_char_map) do | |||||
escape_char_map_inv[v] = k | |||||
end | |||||
local function escape_char(c) | |||||
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte())) | |||||
end | |||||
local function encode_nil(val) | |||||
return "null" | |||||
end | |||||
local function encode_table(val, stack) | |||||
local res = {} | |||||
stack = stack or {} | |||||
-- Circular reference? | |||||
if stack[val] then error("circular reference") end | |||||
stack[val] = true | |||||
if rawget(val, 1) ~= nil or next(val) == nil then | |||||
-- Treat as array -- check keys are valid and it is not sparse | |||||
local n = 0 | |||||
for k in pairs(val) do | |||||
if type(k) ~= "number" then | |||||
error("invalid table: mixed or invalid key types") | |||||
end | |||||
n = n + 1 | |||||
end | |||||
if n ~= #val then | |||||
error("invalid table: sparse array") | |||||
end | |||||
-- Encode | |||||
for i, v in ipairs(val) do | |||||
table.insert(res, encode(v, stack)) | |||||
end | |||||
stack[val] = nil | |||||
return "[" .. table.concat(res, ",") .. "]" | |||||
else | |||||
-- Treat as an object | |||||
for k, v in pairs(val) do | |||||
if type(k) ~= "string" then | |||||
error("invalid table: mixed or invalid key types") | |||||
end | |||||
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) | |||||
end | |||||
stack[val] = nil | |||||
return "{" .. table.concat(res, ",") .. "}" | |||||
end | |||||
end | |||||
local function encode_string(val) | |||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' | |||||
end | |||||
local function encode_number(val) | |||||
-- Check for NaN, -inf and inf | |||||
if val ~= val or val <= -math.huge or val >= math.huge then | |||||
error("unexpected number value '" .. tostring(val) .. "'") | |||||
end | |||||
return string.format("%.14g", val) | |||||
end | |||||
local type_func_map = { | |||||
[ "nil" ] = encode_nil, | |||||
[ "table" ] = encode_table, | |||||
[ "string" ] = encode_string, | |||||
[ "number" ] = encode_number, | |||||
[ "boolean" ] = tostring, | |||||
} | |||||
encode = function(val, stack) | |||||
local t = type(val) | |||||
local f = type_func_map[t] | |||||
if f then | |||||
return f(val, stack) | |||||
end | |||||
error("unexpected type '" .. t .. "'") | |||||
end | |||||
function json.encode(val) | |||||
return ( encode(val) ) | |||||
end | |||||
------------------------------------------------------------------------------- | |||||
-- Decode | |||||
------------------------------------------------------------------------------- | |||||
local parse | |||||
local function create_set(...) | |||||
local res = {} | |||||
for i = 1, select("#", ...) do | |||||
res[ select(i, ...) ] = true | |||||
end | |||||
return res | |||||
end | |||||
local space_chars = create_set(" ", "\t", "\r", "\n") | |||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") | |||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") | |||||
local literals = create_set("true", "false", "null") | |||||
local literal_map = { | |||||
[ "true" ] = true, | |||||
[ "false" ] = false, | |||||
[ "null" ] = nil, | |||||
} | |||||
local function next_char(str, idx, set, negate) | |||||
for i = idx, #str do | |||||
if set[str:sub(i, i)] ~= negate then | |||||
return i | |||||
end | |||||
end | |||||
return #str + 1 | |||||
end | |||||
local function decode_error(str, idx, msg) | |||||
local line_count = 1 | |||||
local col_count = 1 | |||||
for i = 1, idx - 1 do | |||||
col_count = col_count + 1 | |||||
if str:sub(i, i) == "\n" then | |||||
line_count = line_count + 1 | |||||
col_count = 1 | |||||
end | |||||
end | |||||
error( string.format("%s at line %d col %d", msg, line_count, col_count) ) | |||||
end | |||||
local function codepoint_to_utf8(n) | |||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa | |||||
local f = math.floor | |||||
if n <= 0x7f then | |||||
return string.char(n) | |||||
elseif n <= 0x7ff then | |||||
return string.char(f(n / 64) + 192, n % 64 + 128) | |||||
elseif n <= 0xffff then | |||||
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) | |||||
elseif n <= 0x10ffff then | |||||
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, | |||||
f(n % 4096 / 64) + 128, n % 64 + 128) | |||||
end | |||||
error( string.format("invalid unicode codepoint '%x'", n) ) | |||||
end | |||||
local function parse_unicode_escape(s) | |||||
local n1 = tonumber( s:sub(1, 4), 16 ) | |||||
local n2 = tonumber( s:sub(7, 10), 16 ) | |||||
-- Surrogate pair? | |||||
if n2 then | |||||
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) | |||||
else | |||||
return codepoint_to_utf8(n1) | |||||
end | |||||
end | |||||
local function parse_string(str, i) | |||||
local res = "" | |||||
local j = i + 1 | |||||
local k = j | |||||
while j <= #str do | |||||
local x = str:byte(j) | |||||
if x < 32 then | |||||
decode_error(str, j, "control character in string") | |||||
elseif x == 92 then -- `\`: Escape | |||||
res = res .. str:sub(k, j - 1) | |||||
j = j + 1 | |||||
local c = str:sub(j, j) | |||||
if c == "u" then | |||||
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) | |||||
or str:match("^%x%x%x%x", j + 1) | |||||
or decode_error(str, j - 1, "invalid unicode escape in string") | |||||
res = res .. parse_unicode_escape(hex) | |||||
j = j + #hex | |||||
else | |||||
if not escape_chars[c] then | |||||
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string") | |||||
end | |||||
res = res .. escape_char_map_inv[c] | |||||
end | |||||
k = j + 1 | |||||
elseif x == 34 then -- `"`: End of string | |||||
res = res .. str:sub(k, j - 1) | |||||
return res, j + 1 | |||||
end | |||||
j = j + 1 | |||||
end | |||||
decode_error(str, i, "expected closing quote for string") | |||||
end | |||||
local function parse_number(str, i) | |||||
local x = next_char(str, i, delim_chars) | |||||
local s = str:sub(i, x - 1) | |||||
local n = tonumber(s) | |||||
if not n then | |||||
decode_error(str, i, "invalid number '" .. s .. "'") | |||||
end | |||||
return n, x | |||||
end | |||||
local function parse_literal(str, i) | |||||
local x = next_char(str, i, delim_chars) | |||||
local word = str:sub(i, x - 1) | |||||
if not literals[word] then | |||||
decode_error(str, i, "invalid literal '" .. word .. "'") | |||||
end | |||||
return literal_map[word], x | |||||
end | |||||
local function parse_array(str, i) | |||||
local res = {} | |||||
local n = 1 | |||||
i = i + 1 | |||||
while 1 do | |||||
local x | |||||
i = next_char(str, i, space_chars, true) | |||||
-- Empty / end of array? | |||||
if str:sub(i, i) == "]" then | |||||
i = i + 1 | |||||
break | |||||
end | |||||
-- Read token | |||||
x, i = parse(str, i) | |||||
res[n] = x | |||||
n = n + 1 | |||||
-- Next token | |||||
i = next_char(str, i, space_chars, true) | |||||
local chr = str:sub(i, i) | |||||
i = i + 1 | |||||
if chr == "]" then break end | |||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end | |||||
end | |||||
return res, i | |||||
end | |||||
local function parse_object(str, i) | |||||
local res = {} | |||||
i = i + 1 | |||||
while 1 do | |||||
local key, val | |||||
i = next_char(str, i, space_chars, true) | |||||
-- Empty / end of object? | |||||
if str:sub(i, i) == "}" then | |||||
i = i + 1 | |||||
break | |||||
end | |||||
-- Read key | |||||
if str:sub(i, i) ~= '"' then | |||||
decode_error(str, i, "expected string for key") | |||||
end | |||||
key, i = parse(str, i) | |||||
-- Read ':' delimiter | |||||
i = next_char(str, i, space_chars, true) | |||||
if str:sub(i, i) ~= ":" then | |||||
decode_error(str, i, "expected ':' after key") | |||||
end | |||||
i = next_char(str, i + 1, space_chars, true) | |||||
-- Read value | |||||
val, i = parse(str, i) | |||||
-- Set | |||||
res[key] = val | |||||
-- Next token | |||||
i = next_char(str, i, space_chars, true) | |||||
local chr = str:sub(i, i) | |||||
i = i + 1 | |||||
if chr == "}" then break end | |||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end | |||||
end | |||||
return res, i | |||||
end | |||||
local char_func_map = { | |||||
[ '"' ] = parse_string, | |||||
[ "0" ] = parse_number, | |||||
[ "1" ] = parse_number, | |||||
[ "2" ] = parse_number, | |||||
[ "3" ] = parse_number, | |||||
[ "4" ] = parse_number, | |||||
[ "5" ] = parse_number, | |||||
[ "6" ] = parse_number, | |||||
[ "7" ] = parse_number, | |||||
[ "8" ] = parse_number, | |||||
[ "9" ] = parse_number, | |||||
[ "-" ] = parse_number, | |||||
[ "t" ] = parse_literal, | |||||
[ "f" ] = parse_literal, | |||||
[ "n" ] = parse_literal, | |||||
[ "[" ] = parse_array, | |||||
[ "{" ] = parse_object, | |||||
} | |||||
parse = function(str, idx) | |||||
local chr = str:sub(idx, idx) | |||||
local f = char_func_map[chr] | |||||
if f then | |||||
return f(str, idx) | |||||
end | |||||
decode_error(str, idx, "unexpected character '" .. chr .. "'") | |||||
end | |||||
function json.decode(str) | |||||
if type(str) ~= "string" then | |||||
error("expected argument of type string, got " .. type(str)) | |||||
end | |||||
local res, idx = parse(str, next_char(str, 1, space_chars, true)) | |||||
idx = next_char(str, idx, space_chars, true) | |||||
if idx <= #str then | |||||
decode_error(str, idx, "trailing garbage") | |||||
end | |||||
return res | |||||
end | |||||
return json | |||||
)" |
@@ -0,0 +1,129 @@ | |||||
R"( | |||||
------------------------------------------------------------------ | |||||
-- | |||||
-- Author: Alexey Melnichuk <alexeymelnichuck@gmail.com> | |||||
-- | |||||
-- Copyright (C) 2016 Alexey Melnichuk <alexeymelnichuck@gmail.com> | |||||
-- | |||||
-- Licensed according to the included 'LICENSE' document | |||||
-- | |||||
-- This file is part of lua-split library. | |||||
-- | |||||
------------------------------------------------------------------ | |||||
--- | |||||
-- @usage | |||||
-- split = require "split" | |||||
-- lines = split(str, '\r?\n') | |||||
-- key, val = split.first(str, '=', true) | |||||
-- a,b,c,d = split.unpack(str, ':', true) | |||||
local unpack = unpack or table.unpack | |||||
local function is_match_empty(pat, plain) | |||||
return not not string.find('', pat, nil, plain) | |||||
end | |||||
local function split(str, sep, plain) | |||||
local b, res = 0, {} | |||||
sep = sep or '%s+' | |||||
assert(type(sep) == 'string') | |||||
assert(type(str) == 'string') | |||||
if #sep == 0 then | |||||
for i = 1, #str do | |||||
res[#res + 1] = string.sub(str, i, i) | |||||
end | |||||
return res | |||||
end | |||||
assert(not is_match_empty(sep, plain), 'delimiter can not match empty string') | |||||
while b <= #str do | |||||
local e, e2 = string.find(str, sep, b, plain) | |||||
if e then | |||||
res[#res + 1] = string.sub(str, b, e-1) | |||||
b = e2 + 1 | |||||
if b > #str then res[#res + 1] = "" end | |||||
else | |||||
res[#res + 1] = string.sub(str, b) | |||||
break | |||||
end | |||||
end | |||||
return res | |||||
end | |||||
local function split_iter(str, sep, plain) | |||||
sep = sep or '%s+' | |||||
assert(type(sep) == 'string') | |||||
assert(type(str) == 'string') | |||||
if #sep == 0 then | |||||
local i = 0 | |||||
return function() | |||||
i = i + 1 | |||||
if i > #str then return end | |||||
return (string.sub(str, i, i)) | |||||
end | |||||
end | |||||
assert(not is_match_empty(sep, plain), 'delimiter can not match empty string') | |||||
local b, eol = 0 | |||||
return function() | |||||
if b > #str then | |||||
if eol then | |||||
eol = nil | |||||
return "" | |||||
end | |||||
return | |||||
end | |||||
local e, e2 = string.find(str, sep, b, plain) | |||||
if e then | |||||
local s = string.sub(str, b, e-1) | |||||
b = e2 + 1 | |||||
if b > #str then eol = true end | |||||
return s | |||||
end | |||||
local s = string.sub(str, b) | |||||
b = #str + 1 | |||||
return s | |||||
end | |||||
end | |||||
local function usplit(...) return unpack(split(...)) end | |||||
local function split_first(str, sep, plain) | |||||
sep = sep or '%s+' | |||||
assert(type(sep) == 'string') | |||||
assert(type(str) == 'string') | |||||
if #sep == 0 then | |||||
return string.sub(str, 1, 1), string.sub(str, 2) | |||||
end | |||||
assert(not is_match_empty(sep, plain), 'delimiter can not match empty string') | |||||
local e, e2 = string.find(str, sep, nil, plain) | |||||
if e then | |||||
return string.sub(str, 1, e - 1), string.sub(str, e2 + 1) | |||||
end | |||||
return str | |||||
end | |||||
return setmetatable({ | |||||
split = split; | |||||
unpack = usplit; | |||||
first = split_first; | |||||
each = split_iter; | |||||
},{ | |||||
__call = function(_, ...) | |||||
return split(...) | |||||
end | |||||
}) | |||||
)" |