diff --git a/src/game/game.cpp b/src/game/game.cpp index 09230c3..fcb3d77 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -5,9 +5,15 @@ namespace game { namespace native { + Cmd_AddCommand_t Cmd_AddCommand; + Conbuf_AppendText_t Conbuf_AppendText; Sys_ShowConsole_t Sys_ShowConsole; + + int* cmd_args; + int* cmd_argc; + const char*** cmd_argv; } @@ -32,8 +38,14 @@ namespace game { mode = _mode; + native::Cmd_AddCommand = native::Cmd_AddCommand_t(SELECT_VALUE(0x558820, 0x545DF0, 0)); + native::Conbuf_AppendText = native::Conbuf_AppendText_t(SELECT_VALUE(0x4C84E0, 0x5CF610, 0x53C790)); native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0)); + + native::cmd_args = reinterpret_cast(SELECT_VALUE(0x1750750, 0x1C978D0, 0x1B455F8)); + native::cmd_argc = reinterpret_cast(SELECT_VALUE(0x1750794, 0x1C97914, 0x1B4563C)); + native::cmd_argv = reinterpret_cast(SELECT_VALUE(0x17507B4, 0x1C97934, 0x1B4565C)); } } diff --git a/src/game/game.hpp b/src/game/game.hpp index a940900..a635bac 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -9,11 +9,18 @@ namespace game { namespace native { + typedef void (*Cmd_AddCommand_t)(const char* cmdName, void(*function)(), cmd_function_t* allocedCmd); + extern Cmd_AddCommand_t Cmd_AddCommand; + typedef void (*Conbuf_AppendText_t)(const char* message); extern Conbuf_AppendText_t Conbuf_AppendText; typedef void (*Sys_ShowConsole_t)(); extern Sys_ShowConsole_t Sys_ShowConsole; + + extern int* cmd_args; + extern int* cmd_argc; + extern const char*** cmd_argv; } bool is_mp(); diff --git a/src/game/structs.hpp b/src/game/structs.hpp index ac3a7d0..8df2f05 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -368,5 +368,15 @@ namespace game char m_hash[4]; }; #pragma pack(pop) + + typedef struct cmd_function_s + { + cmd_function_s* next; + const char* name; + const char* autoCompleteDir; + const char* autoCompleteExt; + void (__cdecl *function)(); + int flags; + } cmd_function_t; } } diff --git a/src/module/command.cpp b/src/module/command.cpp new file mode 100644 index 0000000..c40447a --- /dev/null +++ b/src/module/command.cpp @@ -0,0 +1,47 @@ +#include +#include "command.hpp" +#include "utils/string.hpp" +#include "game/structs.hpp" +#include "game/game.hpp" +#include "scheduler.hpp" + +utils::memory::allocator command::allocator_; +std::mutex command::mutex_; +std::unordered_map&)>> command::callbacks_; + +void command::add(const std::string& name, const std::function&)>& callback) +{ + std::lock_guard _(mutex_); + callbacks_[utils::string::to_lower(name)] = callback; + + const auto cmd_name = allocator_.duplicate_string(name); + const auto cmd_function = allocator_.allocate(); + + game::native::Cmd_AddCommand(cmd_name, dispatcher, cmd_function); +} + +void command::pre_destroy() +{ + std::lock_guard _(mutex_); + callbacks_.clear(); +} + +void command::dispatcher() +{ + if (game::native::cmd_argc[*game::native::cmd_args] < 1) return; + + const auto command = utils::string::to_lower(game::native::cmd_argv[*game::native::cmd_args][0]); + const auto handler = callbacks_.find(command); + if (handler == callbacks_.end()) return; + + std::vector arguments; + + for (auto i = 0; i < game::native::cmd_argc[*game::native::cmd_args]; ++i) + { + arguments.emplace_back(game::native::cmd_argv[*game::native::cmd_args][i]); + } + + handler->second(arguments); +} + +REGISTER_MODULE(command); diff --git a/src/module/command.hpp b/src/module/command.hpp new file mode 100644 index 0000000..c264c7e --- /dev/null +++ b/src/module/command.hpp @@ -0,0 +1,18 @@ +#pragma once +#include "loader/module_loader.hpp" +#include "utils/memory.hpp" + +class command final : public module +{ +public: + static void add(const std::string& name, const std::function&)>& callback); + + void pre_destroy() override; + +private: + static utils::memory::allocator allocator_; + static std::mutex mutex_; + static std::unordered_map&)>> callbacks_; + + static void dispatcher(); +}; diff --git a/src/module/scheduler.cpp b/src/module/scheduler.cpp index b5192fc..a5b1ee3 100644 --- a/src/module/scheduler.cpp +++ b/src/module/scheduler.cpp @@ -3,6 +3,7 @@ std::mutex scheduler::mutex_; std::vector> scheduler::callbacks_; +std::vector> scheduler::single_callbacks_; void scheduler::on_frame(const std::function& callback) { @@ -10,25 +11,40 @@ void scheduler::on_frame(const std::function& callback) callbacks_.push_back(callback); } +void scheduler::once(const std::function& callback) +{ + std::lock_guard _(mutex_); + single_callbacks_.push_back(callback); +} + void scheduler::execute() { std::vector> callbacks_copy; + std::vector> single_callbacks_copy; { std::lock_guard _(mutex_); callbacks_copy = callbacks_; + single_callbacks_copy = single_callbacks_; + single_callbacks_.clear(); } for (const auto& callback : callbacks_copy) { callback(); } + + for (const auto& callback : single_callbacks_copy) + { + callback(); + } } void scheduler::pre_destroy() { std::lock_guard _(mutex_); callbacks_.clear(); + single_callbacks_.clear(); } REGISTER_MODULE(scheduler); diff --git a/src/module/scheduler.hpp b/src/module/scheduler.hpp index 1c80a4c..0024548 100644 --- a/src/module/scheduler.hpp +++ b/src/module/scheduler.hpp @@ -5,6 +5,7 @@ class scheduler final : public module { public: static void on_frame(const std::function& callback); + static void once(const std::function& callback); static void execute(); void pre_destroy() override; @@ -12,4 +13,5 @@ public: private: static std::mutex mutex_; static std::vector> callbacks_; + static std::vector> single_callbacks_; }; diff --git a/src/utils/string.cpp b/src/utils/string.cpp index faad6f4..9a4da47 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -18,6 +18,26 @@ namespace utils return result; } + std::string to_lower(std::string text) + { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) + { + return CHAR(tolower(input)); + }); + + return text; + } + + std::string to_upper(std::string text) + { + std::transform(text.begin(), text.end(), text.begin(), [](const char input) + { + return CHAR(toupper(input)); + }); + + return text; + } + std::string dump_hex(const std::string& data, const std::string& separator) { std::string result; diff --git a/src/utils/string.hpp b/src/utils/string.hpp index a3f7b10..9c6d829 100644 --- a/src/utils/string.hpp +++ b/src/utils/string.hpp @@ -76,6 +76,9 @@ namespace utils const char* va(const char* fmt, ...); + std::string to_lower(std::string text); + std::string to_upper(std::string text); + std::string dump_hex(const std::string& data, const std::string& separator = " "); } }