mirror of
https://github.com/XLabsProject/s1x-client.git
synced 2023-08-02 15:02:12 +02:00
commit
5f36ccb877
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -44,3 +44,6 @@
|
||||
[submodule "deps/stb"]
|
||||
path = deps/stb
|
||||
url = https://github.com/nothings/stb.git
|
||||
[submodule "deps/gsc-tool"]
|
||||
path = deps/gsc-tool
|
||||
url = https://github.com/xensik/gsc-tool.git
|
||||
|
2
deps/GSL
vendored
2
deps/GSL
vendored
@ -1 +1 @@
|
||||
Subproject commit 10df83d292bf5bbdc487e57dc8c2dc8c7a01f4d1
|
||||
Subproject commit 991fa6682e819590c695f00c6b880548e55fa914
|
2
deps/asmjit
vendored
2
deps/asmjit
vendored
@ -1 +1 @@
|
||||
Subproject commit 5c469e3f7c307da939d38d72e09f08db7ca076ef
|
||||
Subproject commit 15a603661871b86c048e697f0e6cd17374dcecc0
|
28
deps/extra/gsc-tool/interface.cpp
vendored
Normal file
28
deps/extra/gsc-tool/interface.cpp
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
#include <stdafx.hpp>
|
||||
#include <xsk/s1.hpp>
|
||||
#include "interface.hpp"
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
std::unique_ptr<xsk::gsc::compiler> compiler()
|
||||
{
|
||||
auto compiler = std::make_unique<xsk::gsc::s1::compiler>();
|
||||
compiler->mode(xsk::gsc::build::prod);
|
||||
return compiler;
|
||||
}
|
||||
|
||||
std::unique_ptr<xsk::gsc::decompiler> decompiler()
|
||||
{
|
||||
return std::make_unique<xsk::gsc::s1::decompiler>();
|
||||
}
|
||||
|
||||
std::unique_ptr<xsk::gsc::assembler> assembler()
|
||||
{
|
||||
return std::make_unique<xsk::gsc::s1::assembler>();
|
||||
}
|
||||
|
||||
std::unique_ptr<xsk::gsc::disassembler> disassembler()
|
||||
{
|
||||
return std::make_unique<xsk::gsc::s1::disassembler>();
|
||||
}
|
||||
}
|
9
deps/extra/gsc-tool/interface.hpp
vendored
Normal file
9
deps/extra/gsc-tool/interface.hpp
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
std::unique_ptr<xsk::gsc::compiler> compiler();
|
||||
std::unique_ptr<xsk::gsc::decompiler> decompiler();
|
||||
std::unique_ptr<xsk::gsc::assembler> assembler();
|
||||
std::unique_ptr<xsk::gsc::disassembler> disassembler();
|
||||
}
|
1
deps/gsc-tool
vendored
Submodule
1
deps/gsc-tool
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e5d6196da194457ba01cc94674a83da802b769ca
|
2
deps/libtomcrypt
vendored
2
deps/libtomcrypt
vendored
@ -1 +1 @@
|
||||
Subproject commit ddfe2e8aa7c4239463a8a1d26724aef123333549
|
||||
Subproject commit 3474ca37124c6fe78f5461876542e226a25b5f1f
|
2
deps/libtommath
vendored
2
deps/libtommath
vendored
@ -1 +1 @@
|
||||
Subproject commit 4b47368501321c795d5b54d87a5bab35a21a7940
|
||||
Subproject commit 96f9edf9aaf145c6ecf5225eea3f5e86a0f26935
|
2
deps/lua
vendored
2
deps/lua
vendored
@ -1 +1 @@
|
||||
Subproject commit 997f11f54322883c3181225f29d101a597f31730
|
||||
Subproject commit 26be27459b11feabed52cf40aaa76f86c7edc977
|
2
deps/minhook
vendored
2
deps/minhook
vendored
@ -1 +1 @@
|
||||
Subproject commit 4a455528f61b5a375b1f9d44e7d296d47f18bb18
|
||||
Subproject commit 426cb6880035ee3cceed05384bb3f2db01a20a15
|
63
deps/premake/gsc-tool.lua
vendored
Normal file
63
deps/premake/gsc-tool.lua
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
gsc_tool = {
|
||||
source = path.join(dependencies.basePath, "gsc-tool/src"),
|
||||
}
|
||||
|
||||
function gsc_tool.import()
|
||||
links { "xsk-gsc-s1", "xsk-gsc-utils" }
|
||||
gsc_tool.includes()
|
||||
end
|
||||
|
||||
function gsc_tool.includes()
|
||||
includedirs {
|
||||
path.join(gsc_tool.source, "s1"),
|
||||
path.join(gsc_tool.source, "utils"),
|
||||
path.join(dependencies.basePath, "extra/gsc-tool"),
|
||||
}
|
||||
end
|
||||
|
||||
function gsc_tool.project()
|
||||
project "xsk-gsc-utils"
|
||||
kind "StaticLib"
|
||||
language "C++"
|
||||
|
||||
pchheader "stdafx.hpp"
|
||||
pchsource (path.join(gsc_tool.source, "utils/stdafx.cpp"))
|
||||
|
||||
files {
|
||||
path.join(gsc_tool.source, "utils/**.hpp"),
|
||||
path.join(gsc_tool.source, "utils/**.cpp"),
|
||||
}
|
||||
|
||||
includedirs {
|
||||
path.join(gsc_tool.source, "utils"),
|
||||
gsc_tool.source,
|
||||
}
|
||||
|
||||
zlib.includes()
|
||||
|
||||
project "xsk-gsc-s1"
|
||||
kind "StaticLib"
|
||||
language "C++"
|
||||
|
||||
filter "action:vs*"
|
||||
buildoptions "/bigobj"
|
||||
buildoptions "/Zc:__cplusplus"
|
||||
filter {}
|
||||
|
||||
pchheader "stdafx.hpp"
|
||||
pchsource (path.join(gsc_tool.source, "s1/stdafx.cpp"))
|
||||
|
||||
files {
|
||||
path.join(gsc_tool.source, "s1/**.hpp"),
|
||||
path.join(gsc_tool.source, "s1/**.cpp"),
|
||||
path.join(dependencies.basePath, "extra/gsc-tool/interface.cpp"),
|
||||
}
|
||||
|
||||
includedirs {
|
||||
path.join(gsc_tool.source, "s1"),
|
||||
gsc_tool.source,
|
||||
path.join(dependencies.basePath, "extra/gsc-tool"),
|
||||
}
|
||||
end
|
||||
|
||||
table.insert(dependencies, gsc_tool)
|
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
||||
Subproject commit fb6f8da08b60b6beb5bb360d79dd3feda0147da7
|
||||
Subproject commit 57786d126249b5ed4f42b579047941805e742949
|
2
deps/sol2
vendored
2
deps/sol2
vendored
@ -1 +1 @@
|
||||
Subproject commit 4de99c5b41b64b7e654bf8e48b177e8414a756b7
|
||||
Subproject commit 0386513a2d59fefe448f4fc8742455ce1fc152ab
|
2
deps/stb
vendored
2
deps/stb
vendored
@ -1 +1 @@
|
||||
Subproject commit af1a5bc352164740c1cc1354942b1c6b72eacb8a
|
||||
Subproject commit 8b5f1f37b5b75829fc72d38e7b5d4bcbf8a26d55
|
2
deps/zlib
vendored
2
deps/zlib
vendored
@ -1 +1 @@
|
||||
Subproject commit 5752b171fd4cc96b8d1f9526ec1940199c6e9740
|
||||
Subproject commit 04f42ceca40f73e2978b50e93806c2a18c1281fc
|
@ -17,6 +17,8 @@ namespace dedicated
|
||||
utils::hook::detour gscr_set_dynamic_dvar_hook;
|
||||
utils::hook::detour com_quit_f_hook;
|
||||
|
||||
const game::dvar_t* sv_lanOnly;
|
||||
|
||||
void init_dedicated_server()
|
||||
{
|
||||
static bool initialized = false;
|
||||
@ -29,8 +31,7 @@ namespace dedicated
|
||||
|
||||
void send_heartbeat()
|
||||
{
|
||||
auto* const dvar = game::Dvar_FindVar("sv_lanOnly");
|
||||
if (dvar && dvar->current.enabled)
|
||||
if (sv_lanOnly->current.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -107,16 +108,16 @@ namespace dedicated
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
game::dvar_t* gscr_set_dynamic_dvar()
|
||||
void gscr_set_dynamic_dvar()
|
||||
{
|
||||
auto s = game::Scr_GetString(0);
|
||||
auto* dvar = game::Dvar_FindVar(s);
|
||||
if (dvar && !strncmp("scr_", dvar->name, 4))
|
||||
if (dvar && !std::strncmp("scr_", dvar->name, 4))
|
||||
{
|
||||
return dvar;
|
||||
return;
|
||||
}
|
||||
|
||||
return gscr_set_dynamic_dvar_hook.invoke<game::dvar_t*>();
|
||||
gscr_set_dynamic_dvar_hook.invoke<void>();
|
||||
}
|
||||
|
||||
void kill_server()
|
||||
@ -135,12 +136,12 @@ namespace dedicated
|
||||
|
||||
void sys_error_stub(const char* msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
char buffer[2048]{};
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
vsnprintf_s(buffer, _TRUNCATE, msg, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
@ -175,11 +176,9 @@ namespace dedicated
|
||||
return;
|
||||
}
|
||||
|
||||
// Register dedicated dvar
|
||||
game::Dvar_RegisterBool("dedicated", true, game::DVAR_FLAG_READ, "Dedicated server");
|
||||
|
||||
// Add lanonly mode
|
||||
game::Dvar_RegisterBool("sv_lanOnly", false, game::DVAR_FLAG_NONE, "Don't send heartbeat");
|
||||
sv_lanOnly = game::Dvar_RegisterBool("sv_lanOnly", false, game::DVAR_FLAG_NONE, "Don't send heartbeat");
|
||||
|
||||
// Disable VirtualLobby
|
||||
dvars::override::Dvar_RegisterBool("virtualLobbyEnabled", false, game::DVAR_FLAG_NONE | game::DVAR_FLAG_READ);
|
||||
|
@ -342,9 +342,8 @@ namespace demonware
|
||||
|
||||
void bd_logger_stub(const char* const function, const char* const msg, ...)
|
||||
{
|
||||
static auto* enabled =
|
||||
game::Dvar_RegisterBool("bd_logger_enabled", false, game::DVAR_FLAG_SAVED, "bdLogger");
|
||||
if (!enabled->current.enabled)
|
||||
static const auto* bd_logger_enabled = game::Dvar_RegisterBool("bd_logger_enabled", false, game::DVAR_FLAG_NONE, "Enable bdLogger");
|
||||
if (!bd_logger_enabled->current.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "fastfiles.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include "fastfiles.hpp"
|
||||
#include "command.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
namespace fastfiles
|
||||
@ -15,6 +17,7 @@ namespace fastfiles
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour db_try_load_x_file_internal_hook;
|
||||
utils::hook::detour db_find_x_asset_header_hook;
|
||||
|
||||
void db_try_load_x_file_internal(const char* zone_name, const int flags)
|
||||
{
|
||||
@ -25,15 +28,60 @@ namespace fastfiles
|
||||
});
|
||||
return db_try_load_x_file_internal_hook.invoke<void>(zone_name, flags);
|
||||
}
|
||||
|
||||
void dump_gsc_script(const std::string& name, game::XAssetHeader header)
|
||||
{
|
||||
if (!dvars::g_dump_scripts->current.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string buffer;
|
||||
buffer.append(header.scriptfile->name, std::strlen(header.scriptfile->name) + 1);
|
||||
buffer.append(reinterpret_cast<char*>(&header.scriptfile->compressedLen), 4);
|
||||
buffer.append(reinterpret_cast<char*>(&header.scriptfile->len), 4);
|
||||
buffer.append(reinterpret_cast<char*>(&header.scriptfile->bytecodeLen), 4);
|
||||
buffer.append(header.scriptfile->buffer, header.scriptfile->compressedLen);
|
||||
buffer.append(reinterpret_cast<char*>(header.scriptfile->bytecode), header.scriptfile->bytecodeLen);
|
||||
|
||||
const auto out_name = std::format("gsc_dump/{}.gscbin", name);
|
||||
utils::io::write_file(out_name, buffer);
|
||||
|
||||
console::info("Dumped %s\n", out_name.data());
|
||||
}
|
||||
|
||||
game::XAssetHeader db_find_x_asset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
|
||||
{
|
||||
const auto start = game::Sys_Milliseconds();
|
||||
const auto result = db_find_x_asset_header_hook.invoke<game::XAssetHeader>(type, name, allow_create_default);
|
||||
const auto diff = game::Sys_Milliseconds() - start;
|
||||
|
||||
if (type == game::ASSET_TYPE_SCRIPTFILE)
|
||||
{
|
||||
dump_gsc_script(name, result);
|
||||
}
|
||||
|
||||
if (diff > 100)
|
||||
{
|
||||
console::print(
|
||||
result.data == nullptr ? console::con_type_error : console::con_type_warning, "Waited %i msec for asset '%s' of type '%s'.\n",
|
||||
diff,
|
||||
name,
|
||||
game::g_assetNames[type]
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_current_fastfile()
|
||||
{
|
||||
std::string fastfile_copy;
|
||||
current_fastfile.access([&](std::string& fastfile)
|
||||
auto fastfile_copy = current_fastfile.access<std::string>([&](std::string& fastfile)
|
||||
{
|
||||
fastfile_copy = fastfile;
|
||||
return fastfile;
|
||||
});
|
||||
|
||||
return fastfile_copy;
|
||||
}
|
||||
|
||||
@ -70,6 +118,15 @@ namespace fastfiles
|
||||
return new_pool;
|
||||
}
|
||||
|
||||
void enum_assets(const game::XAssetType type, const std::function<void(game::XAssetHeader)>& callback, const bool include_override)
|
||||
{
|
||||
game::DB_EnumXAssets_Internal(type, static_cast<void(*)(game::XAssetHeader, void*)>([](game::XAssetHeader header, void* data)
|
||||
{
|
||||
const auto& cb = *static_cast<const std::function<void(game::XAssetHeader)>*>(data);
|
||||
cb(header);
|
||||
}), &callback, include_override);
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
@ -78,6 +135,9 @@ namespace fastfiles
|
||||
db_try_load_x_file_internal_hook.create(
|
||||
SELECT_VALUE(0x1401816F0, 0x1402741C0), &db_try_load_x_file_internal);
|
||||
|
||||
db_find_x_asset_header_hook.create(game::DB_FindXAssetHeader, db_find_x_asset_header_stub);
|
||||
dvars::g_dump_scripts = game::Dvar_RegisterBool("g_dumpScripts", false, game::DVAR_FLAG_NONE, "Dump GSC scripts to binary format");
|
||||
|
||||
command::add("loadzone", [](const command::params& params)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
|
@ -5,4 +5,6 @@
|
||||
namespace fastfiles
|
||||
{
|
||||
std::string get_current_fastfile();
|
||||
|
||||
void enum_assets(game::XAssetType type, const std::function<void(game::XAssetHeader)>& callback, bool include_override);
|
||||
}
|
||||
|
@ -1,20 +1,31 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "filesystem.hpp"
|
||||
#include "game_module.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "dvars.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/io.hpp>
|
||||
|
||||
namespace filesystem
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool initialized = false;
|
||||
|
||||
bool custom_path_registered = false;
|
||||
|
||||
std::deque<std::filesystem::path>& get_search_paths_internal()
|
||||
{
|
||||
static std::deque<std::filesystem::path> search_paths{};
|
||||
return search_paths;
|
||||
}
|
||||
|
||||
std::string get_binary_directory()
|
||||
{
|
||||
const auto dir = game_module::get_host_module().get_folder();
|
||||
@ -36,9 +47,43 @@ namespace filesystem
|
||||
|
||||
void fs_startup_stub(const char* gamename)
|
||||
{
|
||||
console::info("[FS] Startup\n");
|
||||
|
||||
initialized = true;
|
||||
custom_path_registered = false;
|
||||
|
||||
register_path(get_binary_directory() + "\\data");
|
||||
register_path(".");
|
||||
register_path("s1x");
|
||||
|
||||
game::FS_Startup(gamename);
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> get_paths(const std::filesystem::path& path)
|
||||
{
|
||||
std::vector<std::filesystem::path> paths{};
|
||||
|
||||
const auto code = game::SEH_GetCurrentLanguageName();
|
||||
|
||||
paths.push_back(path);
|
||||
|
||||
paths.push_back(path / code);
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
bool can_insert_path(const std::filesystem::path& path)
|
||||
{
|
||||
for (const auto& path_ : get_search_paths_internal())
|
||||
{
|
||||
if (path_ == path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
file::file(std::string name)
|
||||
@ -70,6 +115,137 @@ namespace filesystem
|
||||
return this->name_;
|
||||
}
|
||||
|
||||
std::string read_file(const std::string& path)
|
||||
{
|
||||
for (const auto& search_path : get_search_paths_internal())
|
||||
{
|
||||
const auto path_ = search_path / path;
|
||||
if (utils::io::file_exists(path_.generic_string()))
|
||||
{
|
||||
return utils::io::read_file(path_.generic_string());
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool read_file(const std::string& path, std::string* data, std::string* real_path)
|
||||
{
|
||||
for (const auto& search_path : get_search_paths_internal())
|
||||
{
|
||||
const auto path_ = search_path / path;
|
||||
if (utils::io::read_file(path_.generic_string(), data))
|
||||
{
|
||||
if (real_path != nullptr)
|
||||
{
|
||||
*real_path = path_.generic_string();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool find_file(const std::string& path, std::string* real_path)
|
||||
{
|
||||
for (const auto& search_path : get_search_paths_internal())
|
||||
{
|
||||
const auto path_ = search_path / path;
|
||||
if (utils::io::file_exists(path_.generic_string()))
|
||||
{
|
||||
*real_path = path_.generic_string();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exists(const std::string& path)
|
||||
{
|
||||
for (const auto& search_path : get_search_paths_internal())
|
||||
{
|
||||
const auto path_ = search_path / path;
|
||||
if (utils::io::file_exists(path_.generic_string()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void register_path(const std::filesystem::path& path)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto paths = get_paths(path);
|
||||
for (const auto& path_ : paths)
|
||||
{
|
||||
if (can_insert_path(path_))
|
||||
{
|
||||
console::info("[FS] Registering path '%s'\n", path_.generic_string().data());
|
||||
get_search_paths_internal().push_front(path_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unregister_path(const std::filesystem::path& path)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto paths = get_paths(path);
|
||||
for (const auto& path_ : paths)
|
||||
{
|
||||
auto& search_paths = get_search_paths_internal();
|
||||
for (auto i = search_paths.begin(); i != search_paths.end();)
|
||||
{
|
||||
if (*i == path_)
|
||||
{
|
||||
console::info("[FS] Unregistering path '%s'\n", path_.generic_string().data());
|
||||
i = search_paths.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> get_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths{};
|
||||
|
||||
for (const auto& path : get_search_paths_internal())
|
||||
{
|
||||
paths.push_back(path.generic_string());
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
std::vector<std::string> get_search_paths_rev()
|
||||
{
|
||||
std::vector<std::string> paths{};
|
||||
const auto& search_paths = get_search_paths_internal();
|
||||
|
||||
for (auto i = search_paths.rbegin(); i != search_paths.rend(); ++i)
|
||||
{
|
||||
paths.push_back(i->generic_string());
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
|
@ -7,13 +7,24 @@ namespace filesystem
|
||||
public:
|
||||
file(std::string name);
|
||||
|
||||
bool exists() const;
|
||||
const std::string& get_buffer() const;
|
||||
const std::string& get_name() const;
|
||||
[[nodiscard]] bool exists() const;
|
||||
[[nodiscard]] const std::string& get_buffer() const;
|
||||
[[nodiscard]] const std::string& get_name() const;
|
||||
|
||||
private:
|
||||
bool valid_ = false;
|
||||
std::string name_;
|
||||
std::string buffer_;
|
||||
};
|
||||
|
||||
std::string read_file(const std::string& path);
|
||||
bool read_file(const std::string& path, std::string* data, std::string* real_path = nullptr);
|
||||
bool find_file(const std::string& path, std::string* real_path);
|
||||
bool exists(const std::string& path);
|
||||
|
||||
void register_path(const std::filesystem::path& path);
|
||||
void unregister_path(const std::filesystem::path& path);
|
||||
|
||||
std::vector<std::string> get_search_paths();
|
||||
std::vector<std::string> get_search_paths_rev();
|
||||
}
|
||||
|
69
src/client/component/gsc/script_extension.cpp
Normal file
69
src/client/component/gsc/script_extension.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
#include "component/console.hpp"
|
||||
|
||||
#include <xsk/gsc/types.hpp>
|
||||
#include <xsk/resolver.hpp>
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
namespace
|
||||
{
|
||||
typedef void(*builtin_function)();
|
||||
std::unordered_map<std::uint32_t, builtin_function> builtin_funcs_overrides;
|
||||
|
||||
utils::hook::detour scr_register_function_hook;
|
||||
|
||||
void override_function(const std::string& name, builtin_function func)
|
||||
{
|
||||
const auto id = xsk::gsc::s1::resolver::function_id(name);
|
||||
builtin_funcs_overrides.emplace(id, func);
|
||||
}
|
||||
|
||||
void scr_register_function_stub(void* func, int type, unsigned int name)
|
||||
{
|
||||
if (const auto got = builtin_funcs_overrides.find(name); got != builtin_funcs_overrides.end())
|
||||
{
|
||||
func = got->second;
|
||||
}
|
||||
|
||||
scr_register_function_hook.invoke<void>(func, type, name);
|
||||
}
|
||||
|
||||
void scr_print()
|
||||
{
|
||||
for (auto i = 0u; i < game::Scr_GetNumParam(); ++i)
|
||||
{
|
||||
console::info("%s", game::Scr_GetString(i));
|
||||
}
|
||||
}
|
||||
|
||||
void scr_print_ln()
|
||||
{
|
||||
for (auto i = 0u; i < game::Scr_GetNumParam(); ++i)
|
||||
{
|
||||
console::info("%s", game::Scr_GetString(i));
|
||||
}
|
||||
|
||||
console::info("\n");
|
||||
}
|
||||
}
|
||||
|
||||
class extension final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
scr_register_function_hook.create(game::Scr_RegisterFunction, &scr_register_function_stub);
|
||||
|
||||
override_function("print", &scr_print);
|
||||
override_function("println", &scr_print_ln);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(gsc::extension)
|
366
src/client/component/gsc/script_loading.cpp
Normal file
366
src/client/component/gsc/script_loading.cpp
Normal file
@ -0,0 +1,366 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
#include "component/filesystem.hpp"
|
||||
#include "component/console.hpp"
|
||||
#include "component/scripting.hpp"
|
||||
#include "component/fastfiles.hpp"
|
||||
|
||||
#include <xsk/gsc/types.hpp>
|
||||
#include <xsk/gsc/interfaces/compiler.hpp>
|
||||
#include <xsk/gsc/interfaces/decompiler.hpp>
|
||||
#include <xsk/gsc/interfaces/assembler.hpp>
|
||||
#include <xsk/gsc/interfaces/disassembler.hpp>
|
||||
#include <xsk/utils/compression.hpp>
|
||||
#include <xsk/resolver.hpp>
|
||||
#include <interface.hpp>
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
namespace
|
||||
{
|
||||
auto compiler = ::gsc::compiler();
|
||||
auto decompiler = ::gsc::decompiler();
|
||||
auto assembler = ::gsc::assembler();
|
||||
auto disassembler = ::gsc::disassembler();
|
||||
|
||||
std::unordered_map<std::string, unsigned int> main_handles;
|
||||
std::unordered_map<std::string, unsigned int> init_handles;
|
||||
|
||||
std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
||||
|
||||
void clear()
|
||||
{
|
||||
main_handles.clear();
|
||||
init_handles.clear();
|
||||
loaded_scripts.clear();
|
||||
}
|
||||
|
||||
bool read_script_file(const std::string& name, std::string* data)
|
||||
{
|
||||
if (filesystem::read_file(name, data))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto* name_str = name.data();
|
||||
if (game::DB_XAssetExists(game::ASSET_TYPE_RAWFILE, name_str) &&
|
||||
!game::DB_IsXAssetDefault(game::ASSET_TYPE_RAWFILE, name_str))
|
||||
{
|
||||
const auto asset = game::DB_FindXAssetHeader(game::ASSET_TYPE_RAWFILE, name.data(), false);
|
||||
const auto len = game::DB_GetRawFileLen(asset.rawfile);
|
||||
data->resize(len);
|
||||
game::DB_GetRawBuffer(asset.rawfile, data->data(), len);
|
||||
if (len > 0)
|
||||
{
|
||||
data->pop_back();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
game::ScriptFile* load_custom_script(const char* file_name, const std::string& real_name)
|
||||
{
|
||||
if (const auto got = loaded_scripts.find(real_name); got != loaded_scripts.end())
|
||||
{
|
||||
return got->second;
|
||||
}
|
||||
|
||||
std::string source_buffer{};
|
||||
if (!read_script_file(real_name + ".gsc", &source_buffer))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> data;
|
||||
data.assign(source_buffer.begin(), source_buffer.end());
|
||||
|
||||
try
|
||||
{
|
||||
compiler->compile(real_name, data);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
console::error("*********** script compile error *************\n");
|
||||
console::error("failed to compile '%s':\n%s", real_name.data(), ex.what());
|
||||
console::error("**********************************************\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto assembly = compiler->output();
|
||||
|
||||
try
|
||||
{
|
||||
assembler->assemble(real_name, assembly);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
console::error("*********** script compile error *************\n");
|
||||
console::error("failed to assemble '%s':\n%s", real_name.data(), ex.what());
|
||||
console::error("**********************************************\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto script_file_ptr = static_cast<game::ScriptFile*>(game::PMem_AllocFromSource_NoDebug(sizeof(game::ScriptFile), 4, 1, 5));
|
||||
script_file_ptr->name = file_name;
|
||||
|
||||
const auto stack = assembler->output_stack();
|
||||
script_file_ptr->len = static_cast<int>(stack.size());
|
||||
|
||||
const auto script = assembler->output_script();
|
||||
script_file_ptr->bytecodeLen = static_cast<int>(script.size());
|
||||
|
||||
const auto script_size = script.size();
|
||||
// Use PMem for both stack and byte code
|
||||
const auto buffer_size = script_size + stack.size() + 2;
|
||||
|
||||
const auto buffer = static_cast<std::uint8_t*>(game::PMem_AllocFromSource_NoDebug(static_cast<std::uint32_t>(buffer_size), 4, 1, 5));
|
||||
std::memcpy(buffer, script.data(), script_size);
|
||||
std::memcpy(&buffer[script_size], stack.data(), stack.size());
|
||||
|
||||
script_file_ptr->bytecode = &buffer[0];
|
||||
script_file_ptr->buffer = reinterpret_cast<char*>(&buffer[script.size()]);
|
||||
script_file_ptr->compressedLen = 0;
|
||||
|
||||
loaded_scripts[real_name] = script_file_ptr;
|
||||
|
||||
return script_file_ptr;
|
||||
}
|
||||
|
||||
std::string get_script_file_name(const std::string& name)
|
||||
{
|
||||
const auto id = xsk::gsc::s1::resolver::token_id(name);
|
||||
if (!id)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
return std::to_string(id);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> decompile_script_file(const std::string& name, const std::string& real_name)
|
||||
{
|
||||
const auto* script_file = game::DB_FindXAssetHeader(game::ASSET_TYPE_SCRIPTFILE, name.data(), false).scriptfile;
|
||||
if (!script_file)
|
||||
{
|
||||
throw std::runtime_error(std::format("Could not load scriptfile '{}'", real_name));
|
||||
}
|
||||
|
||||
console::info("Decompiling scriptfile '%s'\n", real_name.data());
|
||||
|
||||
std::vector<std::uint8_t> stack{script_file->buffer, script_file->buffer + script_file->len};
|
||||
std::vector<std::uint8_t> bytecode{script_file->bytecode, script_file->bytecode + script_file->bytecodeLen};
|
||||
|
||||
auto decompressed_stack = xsk::utils::zlib::decompress(stack, static_cast<std::uint32_t>(stack.size()));
|
||||
|
||||
disassembler->disassemble(name, bytecode, decompressed_stack);
|
||||
auto output = disassembler->output();
|
||||
|
||||
decompiler->decompile(name, output);
|
||||
|
||||
return decompiler->output();
|
||||
}
|
||||
|
||||
void load_script(const std::string& name)
|
||||
{
|
||||
if (!game::Scr_LoadScript(name.data()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto main_handle = game::Scr_GetFunctionHandle(name.data(), xsk::gsc::s1::resolver::token_id("main"));
|
||||
const auto init_handle = game::Scr_GetFunctionHandle(name.data(), xsk::gsc::s1::resolver::token_id("init"));
|
||||
|
||||
if (main_handle)
|
||||
{
|
||||
console::info("Loaded '%s::main'\n", name.data());
|
||||
main_handles[name] = main_handle;
|
||||
}
|
||||
|
||||
if (init_handle)
|
||||
{
|
||||
console::info("Loaded '%s::init'\n", name.data());
|
||||
init_handles[name] = init_handle;
|
||||
}
|
||||
}
|
||||
|
||||
void load_scripts(const std::filesystem::path& root_dir)
|
||||
{
|
||||
const std::filesystem::path script_dir = root_dir / "scripts";
|
||||
if (!utils::io::directory_exists(script_dir.generic_string()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto scripts = utils::io::list_files(script_dir.generic_string());
|
||||
for (const auto& script : scripts)
|
||||
{
|
||||
if (!script.ends_with(".gsc"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::filesystem::path path(script);
|
||||
const auto relative = path.lexically_relative(root_dir).generic_string();
|
||||
const auto base_name = relative.substr(0, relative.size() - 4);
|
||||
|
||||
load_script(base_name);
|
||||
}
|
||||
}
|
||||
|
||||
game::ScriptFile* find_script(game::XAssetType /*type*/, const char* name, int /*allow_create_default*/)
|
||||
{
|
||||
std::string real_name = name;
|
||||
const auto id = static_cast<std::uint16_t>(std::atoi(name));
|
||||
if (id)
|
||||
{
|
||||
real_name = xsk::gsc::s1::resolver::token_name(id);
|
||||
}
|
||||
|
||||
auto* script = load_custom_script(name, real_name);
|
||||
if (script)
|
||||
{
|
||||
return script;
|
||||
}
|
||||
|
||||
return game::DB_FindXAssetHeader(game::ASSET_TYPE_SCRIPTFILE, name, 1).scriptfile;
|
||||
}
|
||||
|
||||
int db_is_x_asset_default(game::XAssetType type, const char* name)
|
||||
{
|
||||
if (loaded_scripts.contains(name))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return game::DB_IsXAssetDefault(type, name);
|
||||
}
|
||||
|
||||
void gscr_load_game_type_script_stub()
|
||||
{
|
||||
utils::hook::invoke<void>(0x140330490);
|
||||
|
||||
clear();
|
||||
|
||||
fastfiles::enum_assets(game::ASSET_TYPE_RAWFILE, [](const game::XAssetHeader header)
|
||||
{
|
||||
const std::string name = header.rawfile->name;
|
||||
|
||||
if (name.ends_with(".gsc") && name.starts_with("scripts/"))
|
||||
{
|
||||
// Remove .gsc from the file name as it will be re-added by the game later
|
||||
const auto base_name = name.substr(0, name.size() - 4);
|
||||
load_script(base_name);
|
||||
}
|
||||
}, true);
|
||||
|
||||
for (const auto& path : filesystem::get_search_paths())
|
||||
{
|
||||
load_scripts(path);
|
||||
}
|
||||
}
|
||||
|
||||
void db_get_raw_buffer_stub(const game::RawFile* rawfile, char* buf, const int size)
|
||||
{
|
||||
if (rawfile->len > 0 && rawfile->compressedLen == 0)
|
||||
{
|
||||
std::memset(buf, 0, size);
|
||||
std::memcpy(buf, rawfile->buffer, std::min(rawfile->len, size));
|
||||
return;
|
||||
}
|
||||
|
||||
game::DB_GetRawBuffer(rawfile, buf, size);
|
||||
}
|
||||
|
||||
void g_load_structs_stub()
|
||||
{
|
||||
for (auto& function_handle : main_handles)
|
||||
{
|
||||
console::info("Executing '%s::main'\n", function_handle.first.data());
|
||||
const auto thread = game::Scr_ExecThread(function_handle.second, 0);
|
||||
game::RemoveRefToObject(thread);
|
||||
}
|
||||
|
||||
utils::hook::invoke<void>(0x1403380D0);
|
||||
}
|
||||
|
||||
void scr_load_level_stub()
|
||||
{
|
||||
utils::hook::invoke<void>(0x140325B90);
|
||||
|
||||
for (auto& function_handle : init_handles)
|
||||
{
|
||||
console::info("Executing '%s::init'\n", function_handle.first.data());
|
||||
const auto thread = game::Scr_ExecThread(function_handle.second, 0);
|
||||
game::RemoveRefToObject(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class loading final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow custom scripts to include other custom scripts
|
||||
xsk::gsc::s1::resolver::init([](const auto& include_name) -> std::vector<std::uint8_t>
|
||||
{
|
||||
const auto real_name = include_name + ".gsc";
|
||||
|
||||
std::string file_buffer;
|
||||
if (!read_script_file(real_name, &file_buffer) || file_buffer.empty())
|
||||
{
|
||||
const auto name = get_script_file_name(include_name);
|
||||
if (game::DB_XAssetExists(game::ASSET_TYPE_SCRIPTFILE, name.data()))
|
||||
{
|
||||
return decompile_script_file(name, real_name);
|
||||
}
|
||||
|
||||
throw std::runtime_error(std::format("Could not load gsc file '{}'", real_name));
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> result;
|
||||
result.assign(file_buffer.begin(), file_buffer.end());
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
// ProcessScript
|
||||
utils::hook::call(0x1403F7317, find_script);
|
||||
utils::hook::call(0x1403F7327, db_is_x_asset_default);
|
||||
|
||||
// GScr_LoadScripts
|
||||
utils::hook::call(0x140330B19, gscr_load_game_type_script_stub);
|
||||
|
||||
// Load our scripts with an uncompressed stack
|
||||
utils::hook::call(0x1403F7380, db_get_raw_buffer_stub);
|
||||
|
||||
// Exec script handles
|
||||
utils::hook::call(0x1402F71AE, g_load_structs_stub);
|
||||
utils::hook::call(0x1402F71C7, scr_load_level_stub);
|
||||
|
||||
scripting::on_shutdown([](int free_scripts)
|
||||
{
|
||||
if (free_scripts)
|
||||
{
|
||||
xsk::gsc::s1::resolver::cleanup();
|
||||
clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(gsc::loading)
|
@ -1,8 +1,8 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "party.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
@ -13,48 +13,42 @@ namespace logger
|
||||
{
|
||||
utils::hook::detour com_error_hook;
|
||||
|
||||
game::dvar_t* logger_dev = nullptr;
|
||||
|
||||
void print_error(const char* msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
char buffer[2048]{};
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
|
||||
vsnprintf_s(buffer, _TRUNCATE, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
console::error(buffer);
|
||||
console::error("%s", buffer);
|
||||
}
|
||||
|
||||
void print_com_error(int, const char* msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
char buffer[2048]{};
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
|
||||
vsnprintf_s(buffer, _TRUNCATE, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
console::error(buffer);
|
||||
console::error("%s", buffer);
|
||||
}
|
||||
|
||||
void com_error_stub(const int error, const char* msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
char buffer[2048]{};
|
||||
va_list ap;
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
va_start(ap, msg);
|
||||
vsnprintf_s(buffer, _TRUNCATE, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
console::error("Error: %s\n", buffer);
|
||||
}
|
||||
console::error("Error: %s\n", buffer);
|
||||
|
||||
party::clear_sv_motd(); // clear sv_motd on error if it exists
|
||||
|
||||
@ -63,51 +57,43 @@ namespace logger
|
||||
|
||||
void print_warning(const char* msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
char buffer[2048]{};
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
|
||||
vsnprintf_s(buffer, _TRUNCATE, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
console::warn(buffer);
|
||||
console::warn("%s", buffer);
|
||||
}
|
||||
|
||||
void print(const char* msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
char buffer[2048]{};
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
|
||||
vsnprintf_s(buffer, _TRUNCATE, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
console::info(buffer);
|
||||
console::info("%s", buffer);
|
||||
}
|
||||
|
||||
void print_dev(const char* msg, ...)
|
||||
{
|
||||
static auto* enabled =
|
||||
game::Dvar_RegisterBool("logger_dev", false, game::DVAR_FLAG_SAVED, "Print dev stuff");
|
||||
if (!enabled->current.enabled)
|
||||
if (!logger_dev->current.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
|
||||
char buffer[2048]{};
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
|
||||
vsnprintf_s(buffer, _TRUNCATE, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
console::info(buffer);
|
||||
console::info("%s", buffer);
|
||||
}
|
||||
|
||||
// nullsub_56
|
||||
@ -166,6 +152,9 @@ namespace logger
|
||||
{
|
||||
nullsub_56();
|
||||
sub_1400E7420();
|
||||
|
||||
// Make havok script's print function actually print
|
||||
utils::hook::jump(0x140701A1C, print);
|
||||
}
|
||||
|
||||
if (!game::environment::is_sp())
|
||||
@ -175,8 +164,7 @@ namespace logger
|
||||
|
||||
com_error_hook.create(game::Com_Error, com_error_stub);
|
||||
|
||||
// Make havok script's print function actually print
|
||||
utils::hook::jump(0x140701A1C, print);
|
||||
logger_dev = game::Dvar_RegisterBool("logger_dev", false, game::DVAR_FLAG_SAVED, "Print dev stuff");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ namespace scripting
|
||||
|
||||
std::string current_file;
|
||||
|
||||
std::vector<std::function<void(int)>> shutdown_callbacks;
|
||||
|
||||
void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value,
|
||||
game::VariableValue* top)
|
||||
{
|
||||
@ -69,6 +71,12 @@ namespace scripting
|
||||
void g_shutdown_game_stub(const int free_scripts)
|
||||
{
|
||||
lua::engine::stop();
|
||||
|
||||
for (const auto& callback : shutdown_callbacks)
|
||||
{
|
||||
callback(free_scripts);
|
||||
}
|
||||
|
||||
return g_shutdown_game_hook.invoke<void>(free_scripts);
|
||||
}
|
||||
|
||||
@ -95,6 +103,11 @@ namespace scripting
|
||||
}
|
||||
}
|
||||
|
||||
void on_shutdown(const std::function<void(int)>& callback)
|
||||
{
|
||||
shutdown_callbacks.push_back(callback);
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
|
@ -3,4 +3,6 @@
|
||||
namespace scripting
|
||||
{
|
||||
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
|
||||
|
||||
void on_shutdown(const std::function<void(int)>& callback);
|
||||
}
|
||||
|
@ -31,16 +31,10 @@ namespace ui_scripting
|
||||
utils::hook::detour hks_shutdown_hook;
|
||||
utils::hook::detour hks_package_require_hook;
|
||||
|
||||
struct script
|
||||
{
|
||||
std::string name;
|
||||
std::string root;
|
||||
};
|
||||
|
||||
struct globals_t
|
||||
{
|
||||
std::string in_require_script;
|
||||
std::vector<script> loaded_scripts;
|
||||
std::unordered_map<std::string, std::string> loaded_scripts;
|
||||
bool load_raw_script{};
|
||||
std::string raw_script_name{};
|
||||
};
|
||||
@ -49,28 +43,13 @@ namespace ui_scripting
|
||||
|
||||
bool is_loaded_script(const std::string& name)
|
||||
{
|
||||
for (auto i = globals.loaded_scripts.begin(); i != globals.loaded_scripts.end(); ++i)
|
||||
{
|
||||
if (i->name == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return globals.loaded_scripts.contains(name);
|
||||
}
|
||||
|
||||
std::string get_root_script(const std::string& name)
|
||||
{
|
||||
for (auto i = globals.loaded_scripts.begin(); i != globals.loaded_scripts.end(); ++i)
|
||||
{
|
||||
if (i->name == name)
|
||||
{
|
||||
return i->root;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
const auto itr = globals.loaded_scripts.find(name);
|
||||
return itr == globals.loaded_scripts.end() ? std::string() : itr->second;
|
||||
}
|
||||
|
||||
table get_globals()
|
||||
@ -116,7 +95,7 @@ namespace ui_scripting
|
||||
|
||||
void load_script(const std::string& name, const std::string& data)
|
||||
{
|
||||
globals.loaded_scripts.push_back({name, name});
|
||||
globals.loaded_scripts[name] = name;
|
||||
|
||||
const auto lua = get_globals();
|
||||
const auto load_results = lua["loadstring"](data, name);
|
||||
@ -266,8 +245,10 @@ namespace ui_scripting
|
||||
return hks_package_require_hook.invoke<void*>(state);
|
||||
}
|
||||
|
||||
game::XAssetHeader db_find_xasset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
|
||||
game::XAssetHeader db_find_x_asset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
|
||||
{
|
||||
game::XAssetHeader header{.luaFile = nullptr};
|
||||
|
||||
if (!is_loaded_script(globals.in_require_script))
|
||||
{
|
||||
return game::DB_FindXAssetHeader(type, name, allow_create_default);
|
||||
@ -281,14 +262,14 @@ namespace ui_scripting
|
||||
{
|
||||
globals.load_raw_script = true;
|
||||
globals.raw_script_name = target_script;
|
||||
return static_cast<game::XAssetHeader>(reinterpret_cast<game::LuaFile*>(1));
|
||||
header.luaFile = reinterpret_cast<game::LuaFile*>(1);
|
||||
}
|
||||
else if (name_.starts_with("ui/LUI/"))
|
||||
{
|
||||
return game::DB_FindXAssetHeader(type, name, allow_create_default);
|
||||
}
|
||||
|
||||
return static_cast<game::XAssetHeader>(nullptr);
|
||||
return header;
|
||||
}
|
||||
|
||||
int hks_load_stub(game::hks::lua_State* state, void* compiler_options,
|
||||
@ -297,14 +278,11 @@ namespace ui_scripting
|
||||
if (globals.load_raw_script)
|
||||
{
|
||||
globals.load_raw_script = false;
|
||||
globals.loaded_scripts.push_back({globals.raw_script_name, globals.in_require_script});
|
||||
globals.loaded_scripts[globals.raw_script_name] = globals.in_require_script;
|
||||
return load_buffer(globals.raw_script_name, utils::io::read_file(globals.raw_script_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
return utils::hook::invoke<int>(0x14009CA10, state, compiler_options, reader,
|
||||
reader_data, chunk_name);
|
||||
}
|
||||
|
||||
return utils::hook::invoke<int>(0x14009CA10, state, compiler_options, reader, reader_data, chunk_name);
|
||||
}
|
||||
|
||||
int main_handler(game::hks::lua_State* state)
|
||||
@ -316,7 +294,7 @@ namespace ui_scripting
|
||||
}
|
||||
|
||||
const auto closure = value.v.cClosure;
|
||||
if (converted_functions.find(closure) == converted_functions.end())
|
||||
if (!converted_functions.contains(closure))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -364,15 +342,15 @@ namespace ui_scripting
|
||||
return;
|
||||
}
|
||||
|
||||
utils::hook::call(0x1400CB68B, db_find_xasset_header_stub);
|
||||
utils::hook::call(0x1400CB7D6, db_find_xasset_header_stub);
|
||||
utils::hook::call(0x1400CB68B, db_find_x_asset_header_stub);
|
||||
utils::hook::call(0x1400CB7D6, db_find_x_asset_header_stub);
|
||||
utils::hook::call(0x1400CB861, hks_load_stub);
|
||||
|
||||
hks_package_require_hook.create(0x1400781D0, hks_package_require_stub);
|
||||
hks_start_hook.create(0x1400E4E40, hks_start_stub);
|
||||
hks_shutdown_hook.create(0x1400DB9A0, hks_shutdown_stub);
|
||||
|
||||
command::add("lui_restart", []()
|
||||
command::add("lui_restart", []
|
||||
{
|
||||
utils::hook::invoke<void>(0x1400DB9A0);
|
||||
utils::hook::invoke<void>(0x1400E6730);
|
||||
|
@ -21,6 +21,7 @@ namespace dvars
|
||||
game::dvar_t* g_playerCollision = nullptr;
|
||||
|
||||
game::dvar_t* pm_bouncing = nullptr;
|
||||
game::dvar_t* g_dump_scripts = nullptr;
|
||||
game::dvar_t* g_gravity = nullptr;
|
||||
game::dvar_t* g_speed = nullptr;
|
||||
game::dvar_t* g_elevators = nullptr;
|
||||
|
@ -20,6 +20,7 @@ namespace dvars
|
||||
extern game::dvar_t* g_playerEjection;
|
||||
|
||||
extern game::dvar_t* pm_bouncing;
|
||||
extern game::dvar_t* g_dump_scripts;
|
||||
extern game::dvar_t* g_gravity;
|
||||
extern game::dvar_t* g_speed;
|
||||
extern game::dvar_t* g_elevators;
|
||||
|
@ -1202,7 +1202,7 @@ namespace game
|
||||
int len;
|
||||
int bytecodeLen;
|
||||
const char* buffer;
|
||||
char* bytecode;
|
||||
unsigned char* bytecode;
|
||||
};
|
||||
|
||||
struct StringTableCell
|
||||
|
@ -46,23 +46,19 @@ namespace game
|
||||
WEAK symbol<bool()> CL_IsCgameInitialized{0x140136560, 0x1401FD510};
|
||||
|
||||
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{0x1400EE500, 0x1401A3050};
|
||||
WEAK symbol<void(int localClientNum, /*mp::cg_s**/void* cg, const char* dvar, const char* value)>
|
||||
CG_SetClientDvarFromServer
|
||||
{0, 0x1401BF0A0};
|
||||
WEAK symbol<void(int localClientNum, /*mp::cg_s**/void* cg, const char* dvar, const char* value)> CG_SetClientDvarFromServer{0, 0x1401BF0A0};
|
||||
|
||||
WEAK symbol<void(XAssetType type, void (__cdecl* func)(XAssetHeader, void*), void* inData, bool includeOverride)>
|
||||
DB_EnumXAssets_FastFile{0x14017D7C0, 0x14026EC10};
|
||||
WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), const void* inData, bool includeOverride)>
|
||||
DB_EnumXAssets_Internal{0x14017D830, 0x14026EC80};
|
||||
WEAK symbol<XAssetEntry(XAssetType type, const char* name)>
|
||||
DB_FindXAssetEntry{0x14017D830, 0x14026F020};
|
||||
WEAK symbol<XAssetHeader(XAssetType type, const char *name, int allowCreateDefault)>
|
||||
DB_FindXAssetHeader{0x14017DCA0, 0x14026F0F0};
|
||||
WEAK symbol<void(XAssetType type, void (__cdecl* func)(XAssetHeader, void*), void* inData, bool includeOverride)> DB_EnumXAssets_FastFile{0x14017D7C0, 0x14026EC10};
|
||||
WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), const void* inData, bool includeOverride)> DB_EnumXAssets_Internal{0x14017D830, 0x14026EC80};
|
||||
WEAK symbol<XAssetEntry(XAssetType type, const char* name)> DB_FindXAssetEntry{0x14017D830, 0x14026F020};
|
||||
WEAK symbol<XAssetHeader(XAssetType type, const char *name, int allowCreateDefault)> DB_FindXAssetHeader{0x14017DCA0, 0x14026F0F0};
|
||||
WEAK symbol<const char* (const XAsset* asset)> DB_GetXAssetName{0x140151C00, 0x140240DD0};
|
||||
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{0x140151C20, 0x140240DF0};
|
||||
WEAK symbol<void(XZoneInfo* zoneInfo, unsigned int zoneCount, DBSyncMode syncMode)> DB_LoadXAssets{
|
||||
0x1402F8B50, 0x140270F30
|
||||
};
|
||||
WEAK symbol<void(XZoneInfo* zoneInfo, unsigned int zoneCount, DBSyncMode syncMode)> DB_LoadXAssets{0x1402F8B50, 0x140270F30};
|
||||
WEAK symbol<int(XAssetType type, const char* name)> DB_XAssetExists{0x0, 0x1402750F0};
|
||||
WEAK symbol<int(XAssetType type, const char* name)> DB_IsXAssetDefault{0x0, 0x140270320};
|
||||
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x0, 0x14026FCC0};
|
||||
WEAK symbol<void(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x0, 0x14026FB90};
|
||||
|
||||
WEAK symbol<dvar_t*(const char* name)> Dvar_FindVar{0x140370860, 0x1404BF8B0};
|
||||
WEAK symbol<void(const dvar_t* dvar)> Dvar_ClearModified{0x140370700, 0x1404BF690};
|
||||
@ -130,30 +126,25 @@ namespace game
|
||||
|
||||
WEAK symbol<unsigned int(int)> Live_SyncOnlineDataFlags{0x1404459A0, 0x140562830};
|
||||
|
||||
WEAK symbol<void(int clientNum, const char* menu, int a3, int a4, unsigned int a5)> LUI_OpenMenu{0, 0x14048E450};
|
||||
WEAK symbol<void(int localClientNum, const char* menuName, int isPopup, int isModal, unsigned int isExclusive)> LUI_OpenMenu{0, 0x14048E450};
|
||||
WEAK symbol<void()> LUI_EnterCriticalSection{0, 0x1400D2B10};
|
||||
WEAK symbol<void()> LUI_LeaveCriticalSection{0, 0x1400D7620};
|
||||
|
||||
WEAK symbol<bool(int clientNum, const char* menu)> Menu_IsMenuOpenAndVisible{0, 0x140488570};
|
||||
WEAK symbol<bool(int localClientNum, const char* menuName)> Menu_IsMenuOpenAndVisible{0, 0x140488570};
|
||||
|
||||
WEAK symbol<Material*(const char* material)> Material_RegisterHandle{0x1404919D0, 0x1405AFBE0};
|
||||
|
||||
WEAK symbol<void(netadr_s*, sockaddr*)> NetadrToSockadr{0, 0x1404B6F10};
|
||||
|
||||
WEAK symbol<void(netsrc_t, netadr_s*, const char*)> NET_OutOfBandPrint{0, 0x1403DADC0};
|
||||
WEAK symbol<void(netsrc_t sock, int length, const void* data, const netadr_s* to)> NET_SendLoopPacket{
|
||||
0, 0x1403DAF80
|
||||
};
|
||||
WEAK symbol<void(netsrc_t sock, int length, const void* data, const netadr_s* to)> NET_SendLoopPacket{0, 0x1403DAF80};
|
||||
WEAK symbol<bool(const char* s, netadr_s* a)> NET_StringToAdr{0, 0x1403DB070};
|
||||
|
||||
WEAK symbol<void(float x, float y, float width, float height, float s0, float t0, float s1, float t1,
|
||||
float* color, Material* material)> R_AddCmdDrawStretchPic{0x1404A2580, 0x1405C0CB0};
|
||||
WEAK symbol<void(const char*, int, Font_s*, float, float, float, float, float, float*, int)> R_AddCmdDrawText{
|
||||
0x1404A2BF0, 0x1405C1320
|
||||
};
|
||||
WEAK symbol<void(const char*, int, Font_s*, float, float, float, float, float, float*, int)> R_AddCmdDrawText{0x1404A2BF0, 0x1405C1320};
|
||||
|
||||
WEAK symbol<void(const char*, int, Font_s*, float, float, float, float, float, const float*, int, int, char)>
|
||||
R_AddCmdDrawTextWithCursor{0x1404A35E0, 0x1405C1D10};
|
||||
WEAK symbol<void(const char*, int, Font_s*, float, float, float, float, float, const float*, int, int, char)> R_AddCmdDrawTextWithCursor{0x1404A35E0, 0x1405C1D10};
|
||||
WEAK symbol<Font_s*(const char* font)> R_RegisterFont{0x140481F90, 0x14059F3C0};
|
||||
WEAK symbol<void()> R_SyncRenderThread{0x1404A4D60, 0x1405C34F0};
|
||||
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x140482270, 0x14059F6B0};
|
||||
@ -162,16 +153,19 @@ namespace game
|
||||
|
||||
WEAK symbol<unsigned int()> Scr_AllocArray{0x140317C50, 0x1403F4280};
|
||||
WEAK symbol<const float*(const float* v)> Scr_AllocVector{0x140317D10, 0x1403F4370};
|
||||
WEAK symbol<const char*(int index)> Scr_GetString{0x14031C570, 0x1403F8C50};
|
||||
WEAK symbol<unsigned int()> Scr_GetInt{0x14031C1F0, 0x1403F88D0};
|
||||
WEAK symbol<float(int index)> Scr_GetFloat{0x14031C090, 0x1403F8820};
|
||||
WEAK symbol<int()> Scr_GetNumParam{0x14031C2A0, 0x1403F8980};
|
||||
WEAK symbol<const char*(unsigned int index)> Scr_GetString{0x14031C570, 0x1403F8C50};
|
||||
WEAK symbol<int(unsigned int index)> Scr_GetInt{0x14031C1F0, 0x1403F88D0};
|
||||
WEAK symbol<float(unsigned int index)> Scr_GetFloat{0x14031C090, 0x1403F8820};
|
||||
WEAK symbol<unsigned int()> Scr_GetNumParam{0x14031C2A0, 0x1403F8980};
|
||||
WEAK symbol<void()> Scr_ClearOutParams{0x14031B7C0, 0x1403F8040};
|
||||
WEAK symbol<scr_entref_t(unsigned int entId)> Scr_GetEntityIdRef{0x14031A0D0, 0x1403F68A0};
|
||||
WEAK symbol<int(unsigned int classnum, int entnum, int offset)> Scr_SetObjectField{0x14026B620, 0x140339450};
|
||||
WEAK symbol<void(unsigned int id, scr_string_t stringValue, unsigned int paramcount)> Scr_NotifyId{
|
||||
0x14031CB80, 0x1403F92D0
|
||||
};
|
||||
WEAK symbol<void(unsigned int id, scr_string_t stringValue, unsigned int paramcount)> Scr_NotifyId{0x14031CB80, 0x1403F92D0};
|
||||
|
||||
WEAK symbol<unsigned __int16(int handle, unsigned int paramcount)> Scr_ExecThread{0x0, 0x1403F8120};
|
||||
WEAK symbol<unsigned int(const char* name)> Scr_LoadScript{0x0, 0x1403EE250};
|
||||
WEAK symbol<unsigned int(const char* script, unsigned int name)> Scr_GetFunctionHandle{0x0, 0x1403EE0D0};
|
||||
WEAK symbol<unsigned int(void* func, int type, unsigned int name)> Scr_RegisterFunction{0x1403115B0, 0x1403EDAE0};
|
||||
|
||||
WEAK symbol<unsigned int(unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x0, 0x1403F9E40};
|
||||
|
||||
@ -196,9 +190,7 @@ namespace game
|
||||
WEAK symbol<void(mp::client_t* client)> SV_DropClient{0, 0x140438A30};
|
||||
WEAK symbol<void(mp::client_t*, const char*, int)> SV_ExecuteClientCommand{0, 0x15121D8E6};
|
||||
WEAK symbol<void(int localClientNum)> SV_FastRestart{0, 0x1404374E0};
|
||||
WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{
|
||||
0x1403F3A70, 0x14043E120
|
||||
};
|
||||
WEAK symbol<void(int clientNum, svscmd_type type, const char* text)> SV_GameSendServerCommand{0x1403F3A70, 0x14043E120};
|
||||
WEAK symbol<const char*(int clientNum)> SV_GetGuid{0, 0x14043E1E0};
|
||||
WEAK symbol<int(int clientNum)> SV_GetClientPing{0, 0x14043E1C0};
|
||||
WEAK symbol<playerState_s*(int num)> SV_GetPlayerstateForClientNum{0x1403F3AB0, 0x14043E260};
|
||||
@ -206,9 +198,7 @@ namespace game
|
||||
WEAK symbol<bool()> SV_Loaded{0x1403F42C0, 0x14043FA50};
|
||||
WEAK symbol<bool(const char* map)> SV_MapExists{0, 0x140437800};
|
||||
WEAK symbol<void(int localClientNum, const char* map, bool mapIsPreloaded)> SV_StartMap{0, 0x140438320};
|
||||
WEAK symbol<void(int localClientNum, const char* map, bool mapIsPreloaded, bool migrate)> SV_StartMapForParty{
|
||||
0, 0x140438490
|
||||
};
|
||||
WEAK symbol<void(int localClientNum, const char* map, bool mapIsPreloaded, bool migrate)> SV_StartMapForParty{0, 0x140438490};
|
||||
|
||||
WEAK symbol<void(int index, const char* string)> SV_SetConfigstring{0, 0x14043FCA0};
|
||||
|
||||
@ -229,6 +219,11 @@ namespace game
|
||||
WEAK symbol<void(unsigned int localClientNum, const char** args)> UI_RunMenuScript{0, 0x140490060};
|
||||
WEAK symbol<int(const char* text, int maxChars, Font_s* font, float scale)> UI_TextWidth{0, 0x140492380};
|
||||
|
||||
WEAK symbol<const char*()> SEH_GetCurrentLanguageName{0x140339300, 0x1404745C0};
|
||||
|
||||
WEAK symbol<void*(unsigned int size, unsigned int alignment, unsigned int type, int source)> PMem_AllocFromSource_NoDebug{0x0, 0x1404C7BA0};
|
||||
WEAK symbol<void*(unsigned int size)> Hunk_AllocateTempMemoryHighInternal{0x0, 0x1404B68B0};
|
||||
|
||||
WEAK symbol<void*(jmp_buf* Buf, int Value)> longjmp{0x14059C5C0, 0x1406FD930};
|
||||
WEAK symbol<int(jmp_buf* Buf)> _setjmp{0x14059CD00, 0x1406FE070};
|
||||
|
||||
@ -301,15 +296,13 @@ namespace game
|
||||
WEAK symbol<HksObject* (HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_gettable{0, 0x14009D800};
|
||||
WEAK symbol<void(lua_State* s, int nargs, int nresults, const unsigned int* pc)> vm_call_internal{0, 0x1400C9EC0};
|
||||
WEAK symbol<HashTable*(lua_State* s, unsigned int arraySize, unsigned int hashSize)> Hashtable_Create{0, 0x14008AAE0};
|
||||
WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues,
|
||||
int internal_, int profilerTreatClosureAsFunc)> cclosure_Create{0, 0x14008AD00};
|
||||
WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues, int internal_, int profilerTreatClosureAsFunc)> cclosure_Create{0, 0x14008AD00};
|
||||
WEAK symbol<int(lua_State* s, int t)> hksi_luaL_ref{0, 0x1400A7D60};
|
||||
WEAK symbol<void(lua_State* s, int t, int ref)> hksi_luaL_unref{0, 0x1400A0660};
|
||||
WEAK symbol<int(lua_State* s, const HksCompilerSettings* options, const char* buff,
|
||||
unsigned __int64 sz, const char* name)> hksi_hksL_loadbuffer{0, 0x14009ECA0};
|
||||
WEAK symbol<int(lua_State* s, const HksCompilerSettings* options, const char* buff, unsigned __int64 sz, const char* name)> hksi_hksL_loadbuffer{0, 0x14009ECA0};
|
||||
WEAK symbol<int(lua_State* s, const char* what, lua_Debug* ar)> hksi_lua_getinfo{0, 0x1400A0C00};
|
||||
WEAK symbol<int(lua_State* s, int level, lua_Debug* ar)> hksi_lua_getstack{0, 0x1400A0EC0};
|
||||
WEAK symbol<void(lua_State* s, const char* fmt, ...)> hksi_luaL_error{0, 0x1400A03D0};
|
||||
WEAK symbol<const char*> typenames{0, 0x1409AB270};
|
||||
WEAK symbol<const char*> s_compilerTypeName{0, 0x1409AB270};
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ namespace ui_scripting
|
||||
values.push_back(v);
|
||||
}
|
||||
|
||||
if (values.size() == 0)
|
||||
if (values.empty())
|
||||
{
|
||||
values.push_back({});
|
||||
}
|
||||
@ -90,7 +90,7 @@ namespace ui_scripting
|
||||
values.push_back(v);
|
||||
}
|
||||
|
||||
if (values.size() == 0)
|
||||
if (values.empty())
|
||||
{
|
||||
values.push_back({});
|
||||
}
|
||||
|
@ -13,53 +13,50 @@ namespace ui_scripting
|
||||
class function;
|
||||
class script_value;
|
||||
|
||||
namespace
|
||||
template <typename T>
|
||||
std::string get_typename()
|
||||
{
|
||||
template <typename T>
|
||||
std::string get_typename()
|
||||
auto& info = typeid(T);
|
||||
|
||||
if (info == typeid(std::string) ||
|
||||
info == typeid(const char*))
|
||||
{
|
||||
auto& info = typeid(T);
|
||||
|
||||
if (info == typeid(std::string) ||
|
||||
info == typeid(const char*))
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
|
||||
if (info == typeid(lightuserdata))
|
||||
{
|
||||
return "lightuserdata";
|
||||
}
|
||||
|
||||
if (info == typeid(userdata))
|
||||
{
|
||||
return "userdata";
|
||||
}
|
||||
|
||||
if (info == typeid(table))
|
||||
{
|
||||
return "table";
|
||||
}
|
||||
|
||||
if (info == typeid(function))
|
||||
{
|
||||
return "function";
|
||||
}
|
||||
|
||||
if (info == typeid(int) ||
|
||||
info == typeid(float) ||
|
||||
info == typeid(unsigned int))
|
||||
{
|
||||
return "number";
|
||||
}
|
||||
|
||||
if (info == typeid(bool))
|
||||
{
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
return info.name();
|
||||
return "string";
|
||||
}
|
||||
|
||||
if (info == typeid(lightuserdata))
|
||||
{
|
||||
return "lightuserdata";
|
||||
}
|
||||
|
||||
if (info == typeid(userdata))
|
||||
{
|
||||
return "userdata";
|
||||
}
|
||||
|
||||
if (info == typeid(table))
|
||||
{
|
||||
return "table";
|
||||
}
|
||||
|
||||
if (info == typeid(function))
|
||||
{
|
||||
return "function";
|
||||
}
|
||||
|
||||
if (info == typeid(int) ||
|
||||
info == typeid(float) ||
|
||||
info == typeid(unsigned int))
|
||||
{
|
||||
return "number";
|
||||
}
|
||||
|
||||
if (info == typeid(bool))
|
||||
{
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
return info.name();
|
||||
}
|
||||
|
||||
class hks_object
|
||||
@ -167,7 +164,7 @@ namespace ui_scripting
|
||||
{
|
||||
if (!this->is<T>())
|
||||
{
|
||||
const auto hks_typename = game::hks::typenames[this->get_raw().t + 2];
|
||||
const auto hks_typename = game::hks::s_compilerTypeName[this->get_raw().t + 2];
|
||||
const auto typename_ = get_typename<T>();
|
||||
|
||||
throw std::runtime_error(utils::string::va("%s expected, got %s",
|
||||
|
@ -1,355 +1,354 @@
|
||||
#include <std_include.hpp>
|
||||
#include "types.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "../../component/ui_scripting.hpp"
|
||||
|
||||
namespace ui_scripting
|
||||
{
|
||||
/***************************************************************
|
||||
* Lightuserdata
|
||||
**************************************************************/
|
||||
/***************************************************************
|
||||
* Lightuserdata
|
||||
**************************************************************/
|
||||
|
||||
lightuserdata::lightuserdata(void* ptr_)
|
||||
: ptr(ptr_)
|
||||
{
|
||||
}
|
||||
lightuserdata::lightuserdata(void* ptr_)
|
||||
: ptr(ptr_)
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Userdata
|
||||
**************************************************************/
|
||||
/***************************************************************
|
||||
* Userdata
|
||||
**************************************************************/
|
||||
|
||||
userdata::userdata(void* ptr_)
|
||||
: ptr(ptr_)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
userdata::userdata(void* ptr_)
|
||||
: ptr(ptr_)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
|
||||
userdata::userdata(const userdata& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
userdata::userdata(const userdata& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
|
||||
userdata::userdata(userdata&& other) noexcept
|
||||
{
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
userdata::userdata(userdata&& other) noexcept
|
||||
{
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
|
||||
userdata::~userdata()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
userdata::~userdata()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
|
||||
userdata& userdata::operator=(const userdata& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
this->add();
|
||||
}
|
||||
userdata& userdata::operator=(const userdata& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
this->add();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
userdata& userdata::operator=(userdata&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
userdata& userdata::operator=(userdata&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void userdata::add()
|
||||
{
|
||||
game::hks::HksObject value{};
|
||||
value.v.ptr = this->ptr;
|
||||
value.t = game::hks::TUSERDATA;
|
||||
void userdata::add()
|
||||
{
|
||||
game::hks::HksObject value{};
|
||||
value.v.ptr = this->ptr;
|
||||
value.t = game::hks::TUSERDATA;
|
||||
|
||||
const auto state = *game::hks::lua_state;
|
||||
const auto top = state->m_apistack.top;
|
||||
const auto state = *game::hks::lua_state;
|
||||
const auto top = state->m_apistack.top;
|
||||
|
||||
push_value(value);
|
||||
push_value(value);
|
||||
|
||||
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
|
||||
state->m_apistack.top = top;
|
||||
}
|
||||
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
|
||||
state->m_apistack.top = top;
|
||||
}
|
||||
|
||||
void userdata::release()
|
||||
{
|
||||
if (this->ref)
|
||||
{
|
||||
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
|
||||
}
|
||||
}
|
||||
void userdata::release()
|
||||
{
|
||||
if (this->ref)
|
||||
{
|
||||
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
|
||||
}
|
||||
}
|
||||
|
||||
void userdata::set(const script_value& key, const script_value& value) const
|
||||
{
|
||||
set_field(*this, key, value);
|
||||
}
|
||||
void userdata::set(const script_value& key, const script_value& value) const
|
||||
{
|
||||
set_field(*this, key, value);
|
||||
}
|
||||
|
||||
script_value userdata::get(const script_value& key) const
|
||||
{
|
||||
return get_field(*this, key);
|
||||
}
|
||||
script_value userdata::get(const script_value& key) const
|
||||
{
|
||||
return get_field(*this, key);
|
||||
}
|
||||
|
||||
userdata_value userdata::operator[](const script_value& key) const
|
||||
{
|
||||
return {*this, key};
|
||||
}
|
||||
userdata_value userdata::operator[](const script_value& key) const
|
||||
{
|
||||
return {*this, key};
|
||||
}
|
||||
|
||||
userdata_value::userdata_value(const userdata& table, const script_value& key)
|
||||
: userdata_(table)
|
||||
, key_(key)
|
||||
{
|
||||
this->value_ = this->userdata_.get(key).get_raw();
|
||||
}
|
||||
userdata_value::userdata_value(const userdata& table, const script_value& key)
|
||||
: userdata_(table)
|
||||
, key_(key)
|
||||
{
|
||||
this->value_ = this->userdata_.get(key).get_raw();
|
||||
}
|
||||
|
||||
void userdata_value::operator=(const script_value& value)
|
||||
{
|
||||
this->userdata_.set(this->key_, value);
|
||||
this->value_ = value.get_raw();
|
||||
}
|
||||
void userdata_value::operator=(const script_value& value)
|
||||
{
|
||||
this->userdata_.set(this->key_, value);
|
||||
this->value_ = value.get_raw();
|
||||
}
|
||||
|
||||
bool userdata_value::operator==(const script_value& value)
|
||||
{
|
||||
return this->userdata_.get(this->key_) == value;
|
||||
}
|
||||
bool userdata_value::operator==(const script_value& value)
|
||||
{
|
||||
return this->userdata_.get(this->key_) == value;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Table
|
||||
**************************************************************/
|
||||
/***************************************************************
|
||||
* Table
|
||||
**************************************************************/
|
||||
|
||||
table::table()
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
this->ptr = game::hks::Hashtable_Create(state, 0, 0);
|
||||
this->add();
|
||||
}
|
||||
table::table()
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
this->ptr = game::hks::Hashtable_Create(state, 0, 0);
|
||||
this->add();
|
||||
}
|
||||
|
||||
table::table(game::hks::HashTable* ptr_)
|
||||
: ptr(ptr_)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
table::table(game::hks::HashTable* ptr_)
|
||||
: ptr(ptr_)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
|
||||
table::table(const table& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
table::table(const table& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
|
||||
table::table(table&& other) noexcept
|
||||
{
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
table::table(table&& other) noexcept
|
||||
{
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
|
||||
table::~table()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
table::~table()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
|
||||
table& table::operator=(const table& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
this->add();
|
||||
}
|
||||
table& table::operator=(const table& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
this->add();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
table& table::operator=(table&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
table& table::operator=(table&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void table::add()
|
||||
{
|
||||
game::hks::HksObject value{};
|
||||
value.v.table = this->ptr;
|
||||
value.t = game::hks::TTABLE;
|
||||
void table::add()
|
||||
{
|
||||
game::hks::HksObject value{};
|
||||
value.v.table = this->ptr;
|
||||
value.t = game::hks::TTABLE;
|
||||
|
||||
const auto state = *game::hks::lua_state;
|
||||
const auto top = state->m_apistack.top;
|
||||
const auto state = *game::hks::lua_state;
|
||||
const auto top = state->m_apistack.top;
|
||||
|
||||
push_value(value);
|
||||
push_value(value);
|
||||
|
||||
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
|
||||
state->m_apistack.top = top;
|
||||
}
|
||||
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
|
||||
state->m_apistack.top = top;
|
||||
}
|
||||
|
||||
void table::release()
|
||||
{
|
||||
if (this->ref)
|
||||
{
|
||||
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
|
||||
}
|
||||
}
|
||||
void table::release()
|
||||
{
|
||||
if (this->ref)
|
||||
{
|
||||
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
|
||||
}
|
||||
}
|
||||
|
||||
void table::set(const script_value& key, const script_value& value) const
|
||||
{
|
||||
set_field(*this, key, value);
|
||||
}
|
||||
void table::set(const script_value& key, const script_value& value) const
|
||||
{
|
||||
set_field(*this, key, value);
|
||||
}
|
||||
|
||||
table_value table::operator[](const script_value& key) const
|
||||
{
|
||||
return {*this, key};
|
||||
}
|
||||
table_value table::operator[](const script_value& key) const
|
||||
{
|
||||
return {*this, key};
|
||||
}
|
||||
|
||||
script_value table::get(const script_value& key) const
|
||||
{
|
||||
return get_field(*this, key);
|
||||
}
|
||||
script_value table::get(const script_value& key) const
|
||||
{
|
||||
return get_field(*this, key);
|
||||
}
|
||||
|
||||
table_value::table_value(const table& table, const script_value& key)
|
||||
: table_(table)
|
||||
, key_(key)
|
||||
{
|
||||
this->value_ = this->table_.get(key).get_raw();
|
||||
}
|
||||
table_value::table_value(const table& table, const script_value& key)
|
||||
: table_(table)
|
||||
, key_(key)
|
||||
{
|
||||
this->value_ = this->table_.get(key).get_raw();
|
||||
}
|
||||
|
||||
void table_value::operator=(const script_value& value)
|
||||
{
|
||||
this->table_.set(this->key_, value);
|
||||
this->value_ = value.get_raw();
|
||||
}
|
||||
void table_value::operator=(const script_value& value)
|
||||
{
|
||||
this->table_.set(this->key_, value);
|
||||
this->value_ = value.get_raw();
|
||||
}
|
||||
|
||||
void table_value::operator=(const table_value& value)
|
||||
{
|
||||
this->table_.set(this->key_, value);
|
||||
this->value_ = value.get_raw();
|
||||
}
|
||||
void table_value::operator=(const table_value& value)
|
||||
{
|
||||
this->table_.set(this->key_, value);
|
||||
this->value_ = value.get_raw();
|
||||
}
|
||||
|
||||
bool table_value::operator==(const script_value& value)
|
||||
{
|
||||
return this->table_.get(this->key_) == value;
|
||||
}
|
||||
bool table_value::operator==(const script_value& value)
|
||||
{
|
||||
return this->table_.get(this->key_) == value;
|
||||
}
|
||||
|
||||
bool table_value::operator==(const table_value& value)
|
||||
{
|
||||
return this->table_.get(this->key_) == value;
|
||||
}
|
||||
bool table_value::operator==(const table_value& value)
|
||||
{
|
||||
return this->table_.get(this->key_) == value;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Function
|
||||
**************************************************************/
|
||||
/***************************************************************
|
||||
* Function
|
||||
**************************************************************/
|
||||
|
||||
function::function(game::hks::lua_function func)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
this->ptr = game::hks::cclosure_Create(state, func, 0, 0, 0);
|
||||
this->type = game::hks::HksObjectType::TCFUNCTION;
|
||||
this->add();
|
||||
}
|
||||
function::function(game::hks::lua_function func)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
this->ptr = game::hks::cclosure_Create(state, func, 0, 0, 0);
|
||||
this->type = game::hks::HksObjectType::TCFUNCTION;
|
||||
this->add();
|
||||
}
|
||||
|
||||
function::function(game::hks::cclosure* ptr_, game::hks::HksObjectType type_)
|
||||
: ptr(ptr_)
|
||||
, type(type_)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
function::function(game::hks::cclosure* ptr_, game::hks::HksObjectType type_)
|
||||
: ptr(ptr_)
|
||||
, type(type_)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
|
||||
function::function(const function& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
function::function(const function& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
|
||||
function::function(function&& other) noexcept
|
||||
{
|
||||
this->ptr = other.ptr;
|
||||
this->type = other.type;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
function::function(function&& other) noexcept
|
||||
{
|
||||
this->ptr = other.ptr;
|
||||
this->type = other.type;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
|
||||
function::~function()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
function::~function()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
|
||||
function& function::operator=(const function& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->type = other.type;
|
||||
this->ref = other.ref;
|
||||
this->add();
|
||||
}
|
||||
function& function::operator=(const function& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->type = other.type;
|
||||
this->ref = other.ref;
|
||||
this->add();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
function& function::operator=(function&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->type = other.type;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
function& function::operator=(function&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->ptr = other.ptr;
|
||||
this->type = other.type;
|
||||
this->ref = other.ref;
|
||||
other.ref = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void function::add()
|
||||
{
|
||||
game::hks::HksObject value{};
|
||||
value.v.cClosure = this->ptr;
|
||||
value.t = this->type;
|
||||
void function::add()
|
||||
{
|
||||
game::hks::HksObject value{};
|
||||
value.v.cClosure = this->ptr;
|
||||
value.t = this->type;
|
||||
|
||||
const auto state = *game::hks::lua_state;
|
||||
const auto top = state->m_apistack.top;
|
||||
const auto state = *game::hks::lua_state;
|
||||
const auto top = state->m_apistack.top;
|
||||
|
||||
push_value(value);
|
||||
push_value(value);
|
||||
|
||||
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
|
||||
state->m_apistack.top = top;
|
||||
}
|
||||
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
|
||||
state->m_apistack.top = top;
|
||||
}
|
||||
|
||||
void function::release()
|
||||
{
|
||||
if (this->ref)
|
||||
{
|
||||
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
|
||||
}
|
||||
}
|
||||
void function::release()
|
||||
{
|
||||
if (this->ref)
|
||||
{
|
||||
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
|
||||
}
|
||||
}
|
||||
|
||||
arguments function::call(const arguments& arguments) const
|
||||
{
|
||||
return call_script_function(*this, arguments);
|
||||
}
|
||||
arguments function::call(const arguments& arguments) const
|
||||
{
|
||||
return call_script_function(*this, arguments);
|
||||
}
|
||||
|
||||
arguments function::operator()(const arguments& arguments) const
|
||||
{
|
||||
return this->call(arguments);
|
||||
}
|
||||
arguments function::operator()(const arguments& arguments) const
|
||||
{
|
||||
return this->call(arguments);
|
||||
}
|
||||
|
||||
arguments function::operator()() const
|
||||
{
|
||||
return this->call({});
|
||||
}
|
||||
arguments function::operator()() const
|
||||
{
|
||||
return this->call({});
|
||||
}
|
||||
}
|
||||
|
@ -1,140 +1,140 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
#include "script_value.hpp"
|
||||
#include "../../component/ui_scripting.hpp"
|
||||
#include "component/ui_scripting.hpp"
|
||||
|
||||
namespace ui_scripting
|
||||
{
|
||||
class lightuserdata
|
||||
{
|
||||
public:
|
||||
lightuserdata(void*);
|
||||
void* ptr;
|
||||
};
|
||||
class lightuserdata
|
||||
{
|
||||
public:
|
||||
lightuserdata(void*);
|
||||
void* ptr;
|
||||
};
|
||||
|
||||
class userdata_value;
|
||||
class userdata_value;
|
||||
|
||||
class userdata
|
||||
{
|
||||
public:
|
||||
userdata(void*);
|
||||
class userdata
|
||||
{
|
||||
public:
|
||||
userdata(void*);
|
||||
|
||||
userdata(const userdata& other);
|
||||
userdata(userdata&& other) noexcept;
|
||||
userdata(const userdata& other);
|
||||
userdata(userdata&& other) noexcept;
|
||||
|
||||
~userdata();
|
||||
~userdata();
|
||||
|
||||
userdata& operator=(const userdata& other);
|
||||
userdata& operator=(userdata&& other) noexcept;
|
||||
userdata& operator=(const userdata& other);
|
||||
userdata& operator=(userdata&& other) noexcept;
|
||||
|
||||
script_value get(const script_value& key) const;
|
||||
void set(const script_value& key, const script_value& value) const;
|
||||
script_value get(const script_value& key) const;
|
||||
void set(const script_value& key, const script_value& value) const;
|
||||
|
||||
userdata_value operator[](const script_value& key) const;
|
||||
userdata_value operator[](const script_value& key) const;
|
||||
|
||||
void* ptr;
|
||||
void* ptr;
|
||||
|
||||
private:
|
||||
void add();
|
||||
void release();
|
||||
private:
|
||||
void add();
|
||||
void release();
|
||||
|
||||
int ref{};
|
||||
};
|
||||
int ref{};
|
||||
};
|
||||
|
||||
class userdata_value : public script_value
|
||||
{
|
||||
public:
|
||||
userdata_value(const userdata& table, const script_value& key);
|
||||
void operator=(const script_value& value);
|
||||
bool operator==(const script_value& value);
|
||||
private:
|
||||
userdata userdata_;
|
||||
script_value key_;
|
||||
};
|
||||
class userdata_value : public script_value
|
||||
{
|
||||
public:
|
||||
userdata_value(const userdata& table, const script_value& key);
|
||||
void operator=(const script_value& value);
|
||||
bool operator==(const script_value& value);
|
||||
private:
|
||||
userdata userdata_;
|
||||
script_value key_;
|
||||
};
|
||||
|
||||
class table_value;
|
||||
class table_value;
|
||||
|
||||
class table
|
||||
{
|
||||
public:
|
||||
table();
|
||||
table(game::hks::HashTable* ptr_);
|
||||
class table
|
||||
{
|
||||
public:
|
||||
table();
|
||||
table(game::hks::HashTable* ptr_);
|
||||
|
||||
table(const table& other);
|
||||
table(table&& other) noexcept;
|
||||
table(const table& other);
|
||||
table(table&& other) noexcept;
|
||||
|
||||
~table();
|
||||
~table();
|
||||
|
||||
table& operator=(const table& other);
|
||||
table& operator=(table&& other) noexcept;
|
||||
table& operator=(const table& other);
|
||||
table& operator=(table&& other) noexcept;
|
||||
|
||||
script_value get(const script_value& key) const;
|
||||
void set(const script_value& key, const script_value& value) const;
|
||||
script_value get(const script_value& key) const;
|
||||
void set(const script_value& key, const script_value& value) const;
|
||||
|
||||
table_value operator[](const script_value& key) const;
|
||||
table_value operator[](const script_value& key) const;
|
||||
|
||||
game::hks::HashTable* ptr;
|
||||
game::hks::HashTable* ptr;
|
||||
|
||||
private:
|
||||
void add();
|
||||
void release();
|
||||
private:
|
||||
void add();
|
||||
void release();
|
||||
|
||||
int ref{};
|
||||
};
|
||||
int ref{};
|
||||
};
|
||||
|
||||
class table_value : public script_value
|
||||
{
|
||||
public:
|
||||
table_value(const table& table, const script_value& key);
|
||||
void operator=(const script_value& value);
|
||||
void operator=(const table_value& value);
|
||||
bool operator==(const script_value& value);
|
||||
bool operator==(const table_value& value);
|
||||
private:
|
||||
table table_;
|
||||
script_value key_;
|
||||
};
|
||||
class table_value : public script_value
|
||||
{
|
||||
public:
|
||||
table_value(const table& table, const script_value& key);
|
||||
void operator=(const script_value& value);
|
||||
void operator=(const table_value& value);
|
||||
bool operator==(const script_value& value);
|
||||
bool operator==(const table_value& value);
|
||||
private:
|
||||
table table_;
|
||||
script_value key_;
|
||||
};
|
||||
|
||||
class function
|
||||
{
|
||||
public:
|
||||
function(game::hks::lua_function);
|
||||
function(game::hks::cclosure*, game::hks::HksObjectType);
|
||||
class function
|
||||
{
|
||||
public:
|
||||
function(game::hks::lua_function);
|
||||
function(game::hks::cclosure*, game::hks::HksObjectType);
|
||||
|
||||
template <typename F>
|
||||
function(F f)
|
||||
{
|
||||
this->ptr = ui_scripting::convert_function(f);
|
||||
this->type = game::hks::TCFUNCTION;
|
||||
}
|
||||
template <typename F>
|
||||
function(F f)
|
||||
{
|
||||
this->ptr = ui_scripting::convert_function(f);
|
||||
this->type = game::hks::TCFUNCTION;
|
||||
}
|
||||
|
||||
function(const function& other);
|
||||
function(function&& other) noexcept;
|
||||
function(const function& other);
|
||||
function(function&& other) noexcept;
|
||||
|
||||
~function();
|
||||
~function();
|
||||
|
||||
function& operator=(const function& other);
|
||||
function& operator=(function&& other) noexcept;
|
||||
function& operator=(const function& other);
|
||||
function& operator=(function&& other) noexcept;
|
||||
|
||||
arguments call(const arguments& arguments) const;
|
||||
arguments call(const arguments& arguments) const;
|
||||
|
||||
arguments operator()(const arguments& arguments) const;
|
||||
arguments operator()(const arguments& arguments) const;
|
||||
|
||||
template<class ...T>
|
||||
arguments operator()(T... arguments) const
|
||||
{
|
||||
return this->call({arguments...});
|
||||
}
|
||||
template<class ...T>
|
||||
arguments operator()(T... arguments) const
|
||||
{
|
||||
return this->call({arguments...});
|
||||
}
|
||||
|
||||
arguments operator()() const;
|
||||
arguments operator()() const;
|
||||
|
||||
game::hks::cclosure* ptr;
|
||||
game::hks::HksObjectType type;
|
||||
game::hks::cclosure* ptr;
|
||||
game::hks::HksObjectType type;
|
||||
|
||||
private:
|
||||
void add();
|
||||
void release();
|
||||
private:
|
||||
void add();
|
||||
void release();
|
||||
|
||||
int ref{};
|
||||
};
|
||||
int ref{};
|
||||
};
|
||||
}
|
||||
|
Binary file not shown.
BIN
tools/protoc.exe
BIN
tools/protoc.exe
Binary file not shown.
Loading…
Reference in New Issue
Block a user