Extend ui scripting to support loading from appdata
This commit is contained in:
parent
e4b54a2dae
commit
228f943983
@ -16,7 +16,8 @@ namespace ui_scripting
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::unordered_map<game::hks::cclosure*, std::function<arguments(const function_arguments& args)>> converted_functions;
|
std::unordered_map<game::hks::cclosure*, std::function<arguments(const function_arguments& args)>>
|
||||||
|
converted_functions;
|
||||||
|
|
||||||
utils::hook::detour ui_cod_init_hook;
|
utils::hook::detour ui_cod_init_hook;
|
||||||
utils::hook::detour ui_cod_lobbyui_init_hook;
|
utils::hook::detour ui_cod_lobbyui_init_hook;
|
||||||
@ -87,9 +88,9 @@ namespace ui_scripting
|
|||||||
state->m_global->m_bytecodeSharingMode = game::hks::HKS_BYTECODE_SHARING_ON;
|
state->m_global->m_bytecodeSharingMode = game::hks::HKS_BYTECODE_SHARING_ON;
|
||||||
|
|
||||||
const auto _0 = utils::finally([&]
|
const auto _0 = utils::finally([&]
|
||||||
{
|
{
|
||||||
state->m_global->m_bytecodeSharingMode = sharing_mode;
|
state->m_global->m_bytecodeSharingMode = sharing_mode;
|
||||||
});
|
});
|
||||||
|
|
||||||
game::hks::HksCompilerSettings compiler_settings{};
|
game::hks::HksCompilerSettings compiler_settings{};
|
||||||
return game::hks::hksi_hksL_loadbuffer(state, &compiler_settings, data.data(), data.size(), name.data());
|
return game::hks::hksi_hksL_loadbuffer(state, &compiler_settings, data.data(), data.size(), name.data());
|
||||||
@ -130,14 +131,16 @@ namespace ui_scripting
|
|||||||
|
|
||||||
for (const auto& script : scripts)
|
for (const auto& script : scripts)
|
||||||
{
|
{
|
||||||
|
const auto script_file = script.generic_string();
|
||||||
|
|
||||||
if (std::filesystem::is_regular_file(script))
|
if (std::filesystem::is_regular_file(script))
|
||||||
{
|
{
|
||||||
const std::string file_path = script.substr(script.find("ui_scripts") + 11);
|
const std::string file_path = script_file.substr(script_file.find("ui_scripts") + 11);
|
||||||
globals.local_scripts[file_path.c_str()] = script;
|
globals.local_scripts[file_path] = script_file;
|
||||||
}
|
}
|
||||||
else if (std::filesystem::is_directory(script))
|
else if (std::filesystem::is_directory(script))
|
||||||
{
|
{
|
||||||
load_local_script_files(script);
|
load_local_script_files(script_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,11 +159,11 @@ namespace ui_scripting
|
|||||||
for (const auto& script : scripts)
|
for (const auto& script : scripts)
|
||||||
{
|
{
|
||||||
std::string data;
|
std::string data;
|
||||||
|
const auto script_file = script.generic_string();
|
||||||
if (std::filesystem::is_directory(script) && utils::io::read_file(script + "/__init__.lua", &data))
|
if (std::filesystem::is_directory(script) && utils::io::read_file(script_file + "/__init__.lua", &data))
|
||||||
{
|
{
|
||||||
print_loading_script(script);
|
print_loading_script(script_file);
|
||||||
load_script(script + "/__init__.lua", data);
|
load_script(script_file + "/__init__.lua", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,9 +208,8 @@ namespace ui_scripting
|
|||||||
lua["luiglobals"] = lua;
|
lua["luiglobals"] = lua;
|
||||||
|
|
||||||
utils::nt::library host{};
|
utils::nt::library host{};
|
||||||
load_scripts(host.get_folder().append("/data/ui_scripts/").string());
|
load_scripts((game::get_appdata_path() / "data/ui_scripts/").string());
|
||||||
load_scripts("boiii/ui_scripts/");
|
load_scripts((host.get_folder() / "boiii/ui_scripts/").string());
|
||||||
load_scripts("data/ui_scripts/");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void try_start()
|
void try_start()
|
||||||
@ -231,9 +233,8 @@ namespace ui_scripting
|
|||||||
// Fetch the names of the local files so file overrides are already handled
|
// Fetch the names of the local files so file overrides are already handled
|
||||||
globals = {};
|
globals = {};
|
||||||
utils::nt::library host{};
|
utils::nt::library host{};
|
||||||
load_local_script_files(host.get_folder().append("/data/ui_scripts/").string());
|
load_local_script_files((game::get_appdata_path() / "data/ui_scripts/").string());
|
||||||
load_local_script_files("boiii/ui_scripts/");
|
load_local_script_files((host.get_folder() / "boiii/ui_scripts/").string());
|
||||||
load_local_script_files("data/ui_scripts/");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto _0 = utils::finally(&try_start);
|
const auto _0 = utils::finally(&try_start);
|
||||||
@ -260,7 +261,8 @@ namespace ui_scripting
|
|||||||
return hks_package_require_hook.invoke<void*>(state);
|
return hks_package_require_hook.invoke<void*>(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hks_load_stub(game::hks::lua_State* state, void* compiler_options, void* reader, void* reader_data, void* debug_reader, void* debug_reader_data, const char* chunk_name)
|
int hks_load_stub(game::hks::lua_State* state, void* compiler_options, void* reader, void* reader_data,
|
||||||
|
void* debug_reader, void* debug_reader_data, const char* chunk_name)
|
||||||
{
|
{
|
||||||
if (globals.load_raw_script)
|
if (globals.load_raw_script)
|
||||||
{
|
{
|
||||||
@ -269,12 +271,13 @@ namespace ui_scripting
|
|||||||
return load_buffer(globals.raw_script_name, utils::io::read_file(globals.raw_script_name));
|
return load_buffer(globals.raw_script_name, utils::io::read_file(globals.raw_script_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::hook::invoke<int>(0x141D3AFB0_g, state, compiler_options, reader, reader_data, debug_reader, debug_reader_data, chunk_name);
|
return utils::hook::invoke<int>(0x141D3AFB0_g, state, compiler_options, reader, reader_data, debug_reader,
|
||||||
|
debug_reader_data, chunk_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
game::XAssetHeader lua_cod_getrawfile_stub(char* filename)
|
game::XAssetHeader lua_cod_getrawfile_stub(char* filename)
|
||||||
{
|
{
|
||||||
game::XAssetHeader header{ .luaFile = nullptr };
|
game::XAssetHeader header{.luaFile = nullptr};
|
||||||
|
|
||||||
if (!is_loaded_script(globals.in_require_script) && !is_local_script(filename))
|
if (!is_loaded_script(globals.in_require_script) && !is_local_script(filename))
|
||||||
{
|
{
|
||||||
@ -316,7 +319,10 @@ namespace ui_scripting
|
|||||||
{
|
{
|
||||||
auto state = get_globals();
|
auto state = get_globals();
|
||||||
// TODO: Is it possible to do this with a confirm dialog? Doing this in LUI seems unsafe to me because mods will be able to change this aswell
|
// TODO: Is it possible to do this with a confirm dialog? Doing this in LUI seems unsafe to me because mods will be able to change this aswell
|
||||||
state["LuaUtils"]["ShowMessageDialog"](0, 0, "The map/mod you are playing tried to run code that can be unsafe. This can include writing or reading files on your system, accessing environment variables, running system commands or loading a dll. These are usually used for storing data across games, integrating third party software like Discord or fetching data from a server to make the gameplay for dynamic.\nThis can also cause a lot of harm by the wrong people.\n\nIf you trust this map/mod and want to enable these features, open the following file in your Black Ops 3 installation: players/user/config.cfg.\nIn this file change 'set cg_enable_unsafe_lua_functions 0' to 'set cg_enable_unsafe_lua_functions 1' and restart Black Ops 3.", "Unsafe lua function called");
|
state["LuaUtils"]["ShowMessageDialog"](
|
||||||
|
0, 0,
|
||||||
|
"The map/mod you are playing tried to run code that can be unsafe. This can include writing or reading files on your system, accessing environment variables, running system commands or loading a dll. These are usually used for storing data across games, integrating third party software like Discord or fetching data from a server to make the gameplay for dynamic.\nThis can also cause a lot of harm by the wrong people.\n\nIf you trust this map/mod and want to enable these features, open the following file in your Black Ops 3 installation: players/user/config.cfg.\nIn this file change 'set cg_enable_unsafe_lua_functions 0' to 'set cg_enable_unsafe_lua_functions 1' and restart Black Ops 3.",
|
||||||
|
"Unsafe lua function called");
|
||||||
unsafe_function_called_message_shown = true;
|
unsafe_function_called_message_shown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,13 +388,16 @@ namespace ui_scripting
|
|||||||
ui_shutdown_hook.create(0x14270E9C0_g, ui_shutdown_stub);
|
ui_shutdown_hook.create(0x14270E9C0_g, ui_shutdown_stub);
|
||||||
lua_cod_getrawfile_hook.create(0x141F0F880_g, lua_cod_getrawfile_stub);
|
lua_cod_getrawfile_hook.create(0x141F0F880_g, lua_cod_getrawfile_stub);
|
||||||
|
|
||||||
dvar_cg_enable_unsafe_lua_functions = game::Dvar_RegisterBool(game::Dvar_GenerateHash("cg_enable_unsafe_lua_functions"), "cg_enable_unsafe_lua_functions", false, (game::dvarFlags_e)0x1000, "Enables the use of unsafe lua functions");
|
dvar_cg_enable_unsafe_lua_functions = game::Dvar_RegisterBool(
|
||||||
|
game::Dvar_GenerateHash("cg_enable_unsafe_lua_functions"), "cg_enable_unsafe_lua_functions", false,
|
||||||
|
(game::dvarFlags_e)0x1000, "Enables the use of unsafe lua functions");
|
||||||
dvar_cg_enable_unsafe_lua_functions->debugName = "cg_enable_unsafe_lua_functions";
|
dvar_cg_enable_unsafe_lua_functions->debugName = "cg_enable_unsafe_lua_functions";
|
||||||
|
|
||||||
scheduler::once([]() {
|
scheduler::once([]()
|
||||||
|
{
|
||||||
game::dvar_t* dvar_callstack_ship = game::Dvar_FindVar("ui_error_callstack_ship");
|
game::dvar_t* dvar_callstack_ship = game::Dvar_FindVar("ui_error_callstack_ship");
|
||||||
dvar_callstack_ship->flags = (game::dvarFlags_e)0;
|
dvar_callstack_ship->flags = (game::dvarFlags_e)0;
|
||||||
game::dvar_t* dvar_report_delay= game::Dvar_FindVar("ui_error_report_delay");
|
game::dvar_t* dvar_report_delay = game::Dvar_FindVar("ui_error_report_delay");
|
||||||
dvar_report_delay->flags = (game::dvarFlags_e)0;
|
dvar_report_delay->flags = (game::dvarFlags_e)0;
|
||||||
|
|
||||||
game::Dvar_SetFromStringByName("ui_error_callstack_ship", "1", true);
|
game::Dvar_SetFromStringByName("ui_error_callstack_ship", "1", true);
|
||||||
@ -396,33 +405,34 @@ namespace ui_scripting
|
|||||||
}, scheduler::pipeline::renderer);
|
}, scheduler::pipeline::renderer);
|
||||||
|
|
||||||
command::add("luiReload", [](auto& params)
|
command::add("luiReload", [](auto& params)
|
||||||
|
{
|
||||||
|
auto frontend = game::Com_IsRunningUILevel();
|
||||||
|
|
||||||
|
if (frontend)
|
||||||
{
|
{
|
||||||
auto frontend = game::Com_IsRunningUILevel();
|
converted_functions.clear();
|
||||||
|
|
||||||
if (frontend)
|
globals.loaded_scripts.clear();
|
||||||
{
|
globals.local_scripts.clear();
|
||||||
converted_functions.clear();
|
|
||||||
|
|
||||||
globals.loaded_scripts.clear();
|
game::UI_CoD_Shutdown();
|
||||||
globals.local_scripts.clear();
|
game::UI_CoD_Init(true);
|
||||||
|
|
||||||
game::UI_CoD_Shutdown();
|
// Com_LoadFrontEnd stripped
|
||||||
game::UI_CoD_Init(true);
|
game::Lua_CoD_LoadLuaFile(*game::hks::lua_state, "ui_mp.T6.main");
|
||||||
|
game::UI_AddMenu(game::UI_CoD_GetRootNameForController(0), "main", -1, *game::hks::lua_state);
|
||||||
|
|
||||||
// Com_LoadFrontEnd stripped
|
game::UI_CoD_LobbyUI_Init();
|
||||||
game::Lua_CoD_LoadLuaFile(*game::hks::lua_state, "ui_mp.T6.main");
|
}
|
||||||
game::UI_AddMenu(game::UI_CoD_GetRootNameForController(0), "main", -1, *game::hks::lua_state);
|
else
|
||||||
|
{
|
||||||
|
// TODO: Find a way to do a full shutdown & restart like in frontend, that opens up the loading screen that can't be easily closed
|
||||||
|
game::CG_LUIHUDRestart(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
game::UI_CoD_LobbyUI_Init();
|
scheduler::once([]()
|
||||||
}
|
{
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Find a way to do a full shutdown & restart like in frontend, that opens up the loading screen that can't be easily closed
|
|
||||||
game::CG_LUIHUDRestart(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
scheduler::once([]() {
|
|
||||||
if (!dvar_cg_enable_unsafe_lua_functions->current.enabled)
|
if (!dvar_cg_enable_unsafe_lua_functions->current.enabled)
|
||||||
{
|
{
|
||||||
// Do not allow the HKS vm to open LUA's libraries
|
// Do not allow the HKS vm to open LUA's libraries
|
||||||
|
Loading…
Reference in New Issue
Block a user