diff --git a/src/client/component/gsc/script_extension.cpp b/src/client/component/gsc/script_extension.cpp index 5b0e3a2..c45f4fb 100644 --- a/src/client/component/gsc/script_extension.cpp +++ b/src/client/component/gsc/script_extension.cpp @@ -1,6 +1,8 @@ #include #include "loader/component_loader.hpp" #include "game/game.hpp" +#include "game/dvars.hpp" + #include "game/scripting/functions.hpp" #include @@ -19,8 +21,6 @@ namespace gsc std::uint16_t function_id_start = 0x2DF; void* func_table[0x1000]; - const game::dvar_t* developer_script = nullptr; - namespace { #define RVA(ptr) static_cast(reinterpret_cast(ptr) - 0x140000000) @@ -135,7 +135,7 @@ namespace gsc void vm_error_stub(int mark_pos) { - if (!developer_script->current.enabled && !force_error_print) + if (!dvars::com_developer_script->current.enabled && !force_error_print) { utils::hook::invoke(0x1404B6790, mark_pos); return; @@ -263,8 +263,6 @@ namespace gsc return; } - developer_script = game::Dvar_RegisterBool("developer_script", false, game::DVAR_FLAG_NONE, "Enable developer script comments"); - utils::hook::nop(0x1403FB7F7 + 5, 2); utils::hook::call(0x1403FB7F7, vm_call_builtin_function); diff --git a/src/client/component/gsc/script_extension.hpp b/src/client/component/gsc/script_extension.hpp index bdd44ff..9fab151 100644 --- a/src/client/component/gsc/script_extension.hpp +++ b/src/client/component/gsc/script_extension.hpp @@ -4,8 +4,6 @@ namespace gsc { extern void* func_table[0x1000]; - extern const game::dvar_t* developer_script; - void scr_error(const char* error); void override_function(const std::string& name, game::BuiltinFunction func); void add_function(const std::string& name, game::BuiltinFunction function); diff --git a/src/client/component/gsc/script_loading.cpp b/src/client/component/gsc/script_loading.cpp index 5f3bd65..1010774 100644 --- a/src/client/component/gsc/script_loading.cpp +++ b/src/client/component/gsc/script_loading.cpp @@ -1,6 +1,7 @@ #include #include "loader/component_loader.hpp" #include "game/game.hpp" +#include "game/dvars.hpp" #include #include @@ -10,7 +11,6 @@ #include "component/filesystem.hpp" #include "component/console.hpp" #include "component/scripting.hpp" -#include "component/fastfiles.hpp" #include "script_loading.hpp" @@ -26,8 +26,6 @@ namespace gsc std::unordered_map loaded_scripts; utils::memory::allocator script_allocator; - const game::dvar_t* developer_script; - void clear() { main_handles.clear(); @@ -228,18 +226,6 @@ namespace gsc 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); @@ -292,11 +278,19 @@ namespace gsc void scr_begin_load_scripts_stub() { - const auto comp_mode = developer_script->current.enabled ? - xsk::gsc::build::dev : - xsk::gsc::build::prod; + auto build = xsk::gsc::build::prod; - gsc_ctx->init(comp_mode, []([[maybe_unused]] auto const* ctx, const auto& included_path) -> std::pair> + if (dvars::com_developer && dvars::com_developer->current.integer > 0) + { + build = static_cast(static_cast(build) | static_cast(xsk::gsc::build::dev_maps)); + } + + if (dvars::com_developer_script && dvars::com_developer_script->current.enabled) + { + build = static_cast(static_cast(build) | static_cast(xsk::gsc::build::dev_blocks)); + } + + gsc_ctx->init(build, []([[maybe_unused]] auto const* ctx, const auto& included_path) -> std::pair> { const auto script_name = std::filesystem::path(included_path).replace_extension().string(); @@ -364,7 +358,8 @@ namespace gsc utils::hook::call(SELECT_VALUE(0x1403309E9, 0x1403309E9), scr_begin_load_scripts_stub); // GScr_LoadScripts utils::hook::call(SELECT_VALUE(0x14023DA84, 0x140330B9C), scr_end_load_scripts_stub); // GScr_LoadScripts - developer_script = game::Dvar_RegisterBool("developer_script", false, game::DVAR_FLAG_NONE, "Enable developer script comments"); + dvars::com_developer = game::Dvar_RegisterInt("developer", 0, 0, 2, game::DVAR_FLAG_NONE, "Enable development options"); + dvars::com_developer_script = game::Dvar_RegisterBool("developer_script", false, game::DVAR_FLAG_NONE, "Enable developer script comments"); if (game::environment::is_sp()) { diff --git a/src/client/component/network.cpp b/src/client/component/network.cpp index e813a1d..a895d9b 100644 --- a/src/client/component/network.cpp +++ b/src/client/component/network.cpp @@ -3,9 +3,9 @@ #include "game/game.hpp" #include "command.hpp" -#include "network.hpp" #include "console.hpp" #include "dvars.hpp" +#include "network.hpp" #include #include @@ -273,12 +273,8 @@ namespace network utils::hook::set(0x1403DAD14, max_packet_size); utils::hook::set(0x1403DAD35, max_packet_size); - // ignore built in "print" oob command and add in our own + // ignore built in "print" oob command for security reasons utils::hook::set(0x14020A723, 0xEB); - on("print", [](const game::netadr_s&, const std::string& data) - { - console::info("%s", data.data()); - }); } } }; diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index 6408da2..fed15d4 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -35,6 +35,7 @@ namespace patches { return; } + return sv_kick_client_num_hook.invoke(client_num, reason); } @@ -100,7 +101,7 @@ namespace patches } else { - char command[0x1000] = {0}; + char command[0x1000]{}; game::Dvar_GetCombinedString(command, 1); game::Dvar_SetCommand(args.get(0), command); } @@ -226,10 +227,6 @@ namespace patches SetThreadExecutionState(ES_DISPLAY_REQUIRED); }, scheduler::pipeline::main); - // Allow kbam input when gamepad is enabled - utils::hook::nop(SELECT_VALUE(0x14013EF83, 0x140206DB3), 2); - utils::hook::nop(SELECT_VALUE(0x14013CBAC, 0x140204710), 6); - if (game::environment::is_sp()) { patch_sp(); diff --git a/src/client/component/rcon.cpp b/src/client/component/rcon.cpp index a9216e4..e1901b3 100644 --- a/src/client/component/rcon.cpp +++ b/src/client/component/rcon.cpp @@ -79,7 +79,7 @@ namespace rcon strncpy_s(clean_name, client->name, _TRUNCATE); game::I_CleanStr(clean_name); - if (client->header.state >= 1) + if (client->header.state > game::CA_DISCONNECTED) { buffer.append(utils::string::va("%3i %5i %3s %s %32s %16s %21s %5i\n", i, @@ -136,12 +136,13 @@ namespace rcon return; } - console::info("%s", build_status_buffer().data()); + const auto status = build_status_buffer(); + console::info("%s", status.data()); }); if (!game::environment::is_dedi()) { - command::add("rcon", [&](const command::params& params) + command::add("rcon", [](const command::params& params) { static std::string rcon_password{}; @@ -178,9 +179,8 @@ namespace rcon const auto password = message.substr(0, pos); const auto command = message.substr(pos + 1); - const auto rcon_password = game::Dvar_FindVar("rcon_password"); - if (command.empty() || !rcon_password || !rcon_password->current.string || !strlen( - rcon_password->current.string)) + const auto* rcon_password = game::Dvar_FindVar("rcon_password"); + if (command.empty() || !rcon_password || !*rcon_password->current.string) { return; } diff --git a/src/client/component/stats.cpp b/src/client/component/stats.cpp index 2450b63..90d167c 100644 --- a/src/client/component/stats.cpp +++ b/src/client/component/stats.cpp @@ -12,8 +12,8 @@ namespace stats { namespace { - game::dvar_t* cg_unlock_all_items; - game::dvar_t* cg_unlock_all_loot; + const game::dvar_t* cg_unlock_all_items; + const game::dvar_t* cg_unlock_all_loot; utils::hook::detour is_item_locked_hook1; utils::hook::detour is_item_locked_hook2; @@ -74,17 +74,17 @@ namespace stats } else { - // unlock all - cg_unlock_all_items = game::Dvar_RegisterBool("cg_unlockall_items", false, game::DVAR_FLAG_SAVED, "Unlock items that are level-locked by the player's stats."); + // unlock all + cg_unlock_all_items = game::Dvar_RegisterBool("cg_unlockall_items", false, game::DVAR_FLAG_SAVED, "Unlock items that are level-locked by the player's stats."); cg_unlock_all_loot = game::Dvar_RegisterBool("cg_unlockall_loot", false, game::DVAR_FLAG_SAVED, "Unlock supply drop loot."); - game::Dvar_RegisterBool("cg_unlockall_classes", false, game::DVAR_FLAG_SAVED, "Unlock extra class slots."); + game::Dvar_RegisterBool("cg_unlockall_classes", false, game::DVAR_FLAG_SAVED, "Unlock extra class slots."); - is_item_locked_hook1.create(0x1403BD790, is_item_locked_stub1); // LiveStorage_IsItemUnlockedFromTable_LocalClient - is_item_locked_hook2.create(0x1403BD290, is_item_locked_stub2); // LiveStorage_IsItemUnlockedFromTable - is_item_locked_hook3.create(0x1403BAF60, is_loot_locked_stub); // unlocks supply drop loot - } + is_item_locked_hook1.create(0x1403BD790, is_item_locked_stub1); // LiveStorage_IsItemUnlockedFromTable_LocalClient + is_item_locked_hook2.create(0x1403BD290, is_item_locked_stub2); // LiveStorage_IsItemUnlockedFromTable + is_item_locked_hook3.create(0x1403BAF60, is_loot_locked_stub); // unlocks supply drop loot + } - command::add("setPlayerDataInt", [](const command::params& params) + command::add("setPlayerDataInt", [](const command::params& params) { if (params.size() < 2) { diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index 7423c2f..d80d00b 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -40,6 +40,9 @@ namespace dvars game::dvar_t* sv_cheats = nullptr; + game::dvar_t* com_developer = nullptr; + game::dvar_t* com_developer_script = nullptr; + std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain) { if (domain.vector.min == -FLT_MAX) diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index fe3e7aa..40bbe82 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -39,6 +39,9 @@ namespace dvars extern game::dvar_t* sv_cheats; - std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain); - std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain); + extern game::dvar_t* com_developer; + extern game::dvar_t* com_developer_script; + + std::string dvar_get_vector_domain(int components, const game::dvar_limits& domain); + std::string dvar_get_domain(game::dvar_type type, const game::dvar_limits& domain); } diff --git a/src/client/main.cpp b/src/client/main.cpp index 2f06702..c0ad37d 100644 --- a/src/client/main.cpp +++ b/src/client/main.cpp @@ -12,6 +12,21 @@ #include +const char* get_current_date() +{ + auto now = std::chrono::system_clock::now(); + auto current_time = std::chrono::system_clock::to_time_t(now); + std::tm local_time{}; + + (void)localtime_s(&local_time, ¤t_time); + + std::stringstream ss; + ss << std::put_time(&local_time, "%Y%m%d_%H%M%S"); + + const auto result = ss.str(); + return utils::string::va("%s", result.data()); +} + LONG WINAPI exception_handler(PEXCEPTION_POINTERS exception_info) { if (exception_info->ExceptionRecord->ExceptionCode == 0x406D1388) @@ -38,7 +53,7 @@ LONG WINAPI exception_handler(PEXCEPTION_POINTERS exception_info) | MiniDumpWithThreadInfo; CreateDirectoryA("minidumps", nullptr); - const auto* file_name = utils::string::va("minidumps\\s1-mod_%s_%u.dmp", SHORTVERSION, static_cast(std::time(nullptr))); + const auto* file_name = utils::string::va("minidumps\\s1-mod_%s_%s.dmp", SHORTVERSION, get_current_date()); constexpr auto file_share = FILE_SHARE_READ | FILE_SHARE_WRITE; const auto file_handle = CreateFileA(file_name, GENERIC_WRITE | GENERIC_READ, file_share, nullptr, @@ -166,7 +181,11 @@ FARPROC load_binary(const launcher::mode mode) binary.data())); } +#ifdef INJECT_HOST_AS_LIB return loader.load_library(binary); +#else + return loader.load(self, data); +#endif } void remove_crash_file() diff --git a/src/client/std_include.hpp b/src/client/std_include.hpp index 4ba2eb3..0ab229c 100644 --- a/src/client/std_include.hpp +++ b/src/client/std_include.hpp @@ -32,6 +32,8 @@ #include #include +#define INJECT_HOST_AS_LIB + // min and max is required by gdi, therefore NOMINMAX won't work #ifdef max #undef max