From 24823da3405e3cc18a172eaf8518c56bd1c07c3b Mon Sep 17 00:00:00 2001 From: Diavolo Date: Fri, 30 Dec 2022 12:06:32 +0100 Subject: [PATCH] console: migrate to iw6x code --- src/module/command.cpp | 13 +-- src/module/console.cpp | 194 ++++++++++++++++++++++----------------- src/module/console.hpp | 54 +++++++++++ src/module/fastfiles.cpp | 6 +- src/module/game_log.cpp | 15 +-- src/module/log_file.cpp | 4 +- 6 files changed, 185 insertions(+), 101 deletions(-) create mode 100644 src/module/console.hpp diff --git a/src/module/command.cpp b/src/module/command.cpp index 5690be1..6e949a3 100644 --- a/src/module/command.cpp +++ b/src/module/command.cpp @@ -6,6 +6,7 @@ #include #include "command.hpp" +#include "console.hpp" static utils::memory::allocator allocator; @@ -231,7 +232,7 @@ void command::add_sp_commands() ent->client->flags ^= 1; const auto* msg = (ent->client->flags & 1) ? "GAME_NOCLIPON" : "GAME_NOCLIPOFF"; - printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "noclip print", game::native::LOCMSG_SAFE)); + console::info("%s\n", game::native::SEH_LocalizeTextMessage(msg, "noclip print", game::native::LOCMSG_SAFE)); }); add("ufo", [] @@ -248,7 +249,7 @@ void command::add_sp_commands() ent->client->flags ^= 2; const auto* msg = (ent->client->flags & 2) ? "GAME_UFOON" : "GAME_UFOOFF"; - printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "ufo print", game::native::LOCMSG_SAFE)); + console::info("%s\n", game::native::SEH_LocalizeTextMessage(msg, "ufo print", game::native::LOCMSG_SAFE)); }); add("god", [] @@ -265,7 +266,7 @@ void command::add_sp_commands() ent->flags ^= game::native::FL_GODMODE; const auto* msg = (ent->flags & game::native::FL_GODMODE) ? "GAME_GODMODE_ON" : "GAME_GODMODE_OFF"; - printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "god print", game::native::LOCMSG_SAFE)); + console::info("%s\n", game::native::SEH_LocalizeTextMessage(msg, "god print", game::native::LOCMSG_SAFE)); }); add("demigod", [] @@ -282,7 +283,7 @@ void command::add_sp_commands() ent->flags ^= game::native::FL_DEMI_GODMODE; const auto* msg = (ent->flags & game::native::FL_DEMI_GODMODE) ? "GAME_DEMI_GODMODE_ON" : "GAME_DEMI_GODMODE_OFF"; - printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "demigod print", game::native::LOCMSG_SAFE)); + console::info("%s\n", game::native::SEH_LocalizeTextMessage(msg, "demigod print", game::native::LOCMSG_SAFE)); }); add("notarget", [] @@ -299,7 +300,7 @@ void command::add_sp_commands() ent->flags ^= game::native::FL_NOTARGET; const auto* msg = (ent->flags & game::native::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF"; - printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "notarget print", game::native::LOCMSG_SAFE)); + console::info("%s\n", game::native::SEH_LocalizeTextMessage(msg, "notarget print", game::native::LOCMSG_SAFE)); }); add("setviewpos", [](const params& params) @@ -318,7 +319,7 @@ void command::add_sp_commands() if (params.size() < 4 || params.size() > 6) { - printf("setviewpos x y z [yaw] [pitch]\n"); + console::info("setviewpos x y z [yaw] [pitch]\n"); return; } diff --git a/src/module/console.cpp b/src/module/console.cpp index 1349884..7fc1a51 100644 --- a/src/module/console.cpp +++ b/src/module/console.cpp @@ -2,111 +2,137 @@ #include #include "game/game.hpp" +#include + +#include "console.hpp" #include "scheduler.hpp" -class console final : public module +namespace { -public: - console() + using message_queue = std::queue; + utils::concurrency::container message_queue_; +} + +console::console() +{ + ShowWindow(GetConsoleWindow(), SW_HIDE); + + (void)_pipe(this->handles_, 1024, _O_TEXT); + (void)_dup2(this->handles_[1], 1); + (void)_dup2(this->handles_[1], 2); +} + +void console::post_start() +{ + scheduler::loop(std::bind(&console::log_messages, this), scheduler::pipeline::main); + + this->console_runner_ = std::thread(std::bind(&console::runner, this)); +} + +void console::post_load() +{ + game::native::Sys_ShowConsole(); + + message_queue_.access([this]([[maybe_unused]] message_queue& queue) { - ShowWindow(GetConsoleWindow(), SW_HIDE); - - (void)_pipe(this->handles_, 1024, _O_TEXT); - (void)_dup2(this->handles_[1], 1); - (void)_dup2(this->handles_[1], 2); - } - - void post_start() override - { - scheduler::loop(std::bind(&console::log_messages, this), scheduler::pipeline::main); - - this->console_runner_ = std::thread(std::bind(&console::runner, this)); - } - - void pre_destroy() override - { - this->terminate_runner_ = true; - - printf("\r\n"); - _flushall(); - - _close(this->handles_[0]); - _close(this->handles_[1]); - - if (this->console_runner_.joinable()) - { - this->console_runner_.join(); - } - } - - void post_load() override - { - game::native::Sys_ShowConsole(); - - std::lock_guard _(this->mutex_); this->console_initialized_ = true; - } + }); +} -private: - bool console_initialized_ = false; - bool terminate_runner_ = false; +void console::pre_destroy() +{ + this->terminate_runner_ = true; - std::mutex mutex_; - std::thread console_runner_; - std::queue message_queue_; + printf("\r\n"); + _flushall(); - int handles_[2]{}; + _close(this->handles_[0]); + _close(this->handles_[1]); - void log_messages() + if (this->console_runner_.joinable()) { - while (this->console_initialized_ && !this->message_queue_.empty()) + this->console_runner_.join(); + } +} + +void console::print(const int type, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + const auto result = format(&ap, fmt); + va_end(ap); + + dispatch_message(type, result); +} + +void console::log_messages() const +{ + while (this->console_initialized_ && !message_queue_.get_raw().empty()) + { + std::queue message_queue_copy; + { - std::queue message_queue_copy; - + message_queue_.access([&](message_queue& queue) { - std::lock_guard _(this->mutex_); - message_queue_copy = this->message_queue_; - this->message_queue_ = {}; - } - - while (!message_queue_copy.empty()) - { - log_message(message_queue_copy.front()); - message_queue_copy.pop(); - } + message_queue_copy = std::move(queue); + queue = std::queue(); + }); } - fflush(stdout); - fflush(stderr); + while (!message_queue_copy.empty()) + { + log_message(message_queue_copy.front()); + message_queue_copy.pop(); + } } - static void log_message(const std::string& message) - { + fflush(stdout); + fflush(stderr); +} + +void console::log_message(const std::string& message) +{ #ifdef _DEBUG - OutputDebugStringA(message.data()); + OutputDebugStringA(message.data()); #endif - game::native::Conbuf_AppendText(message.data()); - } + game::native::Conbuf_AppendText(message.data()); +} - void runner() +void console::dispatch_message([[maybe_unused]] const int type, const std::string& message) +{ + message_queue_.access([&message](message_queue& queue) { - while (!this->terminate_runner_ && this->handles_[0]) - { - char buffer[1024]; - const auto len = _read(this->handles_[0], buffer, sizeof(buffer)); - if (len > 0) - { - std::lock_guard _(this->mutex_); - this->message_queue_.push(std::string(buffer, len)); - } - else - { - std::this_thread::sleep_for(10ms); - } - } + queue.emplace(message); + }); +} - std::this_thread::yield(); +void console::runner() const +{ + while (!this->terminate_runner_ && this->handles_[0]) + { + char buffer[1024]; + const auto len = _read(this->handles_[0], buffer, sizeof(buffer)); + if (len > 0) + { + dispatch_message(con_type_info, std::string(buffer, len)); + } + else + { + std::this_thread::sleep_for(10ms); + } } -}; + + std::this_thread::yield(); +} + +std::string console::format(va_list* ap, const char* message) +{ + static thread_local char buffer[0x1000]; + + const auto count = vsnprintf_s(buffer, _TRUNCATE, message, *ap); + + if (count < 0) return {}; + return {buffer, static_cast(count)}; +} REGISTER_MODULE(console) diff --git a/src/module/console.hpp b/src/module/console.hpp new file mode 100644 index 0000000..19215f6 --- /dev/null +++ b/src/module/console.hpp @@ -0,0 +1,54 @@ +#pragma once + +class console final : public module +{ +public: + enum + { + con_type_error = 1, + con_type_warning = 3, + con_type_info = 7, + }; + + console(); + + void post_start() override; + void post_load() override; + void pre_destroy() override; + + static void print(int type, const char* fmt, ...); + + template + static void error(const char* fmt, Args&&... args) + { + print(con_type_error, fmt, std::forward(args)...); + } + + template + static void warn(const char* fmt, Args&&... args) + { + print(con_type_warning, fmt, std::forward(args)...); + } + + template + static void info(const char* fmt, Args&&... args) + { + print(con_type_info, fmt, std::forward(args)...); + } + +private: + bool console_initialized_ = false; + bool terminate_runner_ = false; + + std::thread console_runner_; + + int handles_[2]{}; + + void log_messages() const; + static void log_message(const std::string& message); + static void dispatch_message(const int type, const std::string& message); + + void runner() const; + + static std::string format(va_list* ap, const char* message); +}; diff --git a/src/module/fastfiles.cpp b/src/module/fastfiles.cpp index 2b17bc7..b8e1566 100644 --- a/src/module/fastfiles.cpp +++ b/src/module/fastfiles.cpp @@ -2,6 +2,8 @@ #include #include "game/game.hpp" +#include "console.hpp" + #include static __declspec(naked) void db_load_stub_client(game::native::XZoneInfo*, unsigned int, int) @@ -14,7 +16,7 @@ static __declspec(naked) void db_load_stub_client(game::native::XZoneInfo*, unsi mov ecx, game::native::DB_LoadXAssets add ecx, 7h push ecx - retn + ret } } @@ -33,7 +35,7 @@ private: { if (zone_info[i].name) { - printf("Loading FastFile: %s (0x%X | 0x%X)\n", zone_info[i].name, zone_info[i].allocFlags, zone_info[i].freeFlags); + console::info("Loading FastFile: %s (0x%X | 0x%X)\n", zone_info[i].name, zone_info[i].allocFlags, zone_info[i].freeFlags); } } diff --git a/src/module/game_log.cpp b/src/module/game_log.cpp index 3c81190..c627cbf 100644 --- a/src/module/game_log.cpp +++ b/src/module/game_log.cpp @@ -8,6 +8,7 @@ #include "scheduler.hpp" #include "file_system.hpp" #include "scripting.hpp" +#include "console.hpp" const game::native::dvar_t* game_log::g_log; const game::native::dvar_t* game_log::g_logSync; @@ -60,15 +61,15 @@ void game_log::gscr_log_print() void game_log::g_init_game_stub() { - printf("------- Game Initialization -------\n"); - printf("gamename: %s\n", reinterpret_cast(0x7FFC68)); - printf("gamedate: %s\n", __DATE__); + console::info("------- Game Initialization -------\n"); + console::info("gamename: %s\n", reinterpret_cast(0x7FFC68)); + console::info("gamedate: %s\n", __DATE__); const auto* log = g_log->current.string; if (*log == '\0') { - printf("Not logging to disk.\n"); + console::info("Not logging to disk.\n"); } else { @@ -76,11 +77,11 @@ void game_log::g_init_game_stub() if (!log_file) { - printf("WARNING: Couldn't open logfile: %s\n", log); + console::info("WARNING: Couldn't open logfile: %s\n", log); } else { - printf("Logging to disk: '%s'.\n", log); + console::info("Logging to disk: '%s'.\n", log); g_log_printf("------------------------------------------------------------\n"); g_log_printf("InitGame\n"); } @@ -91,7 +92,7 @@ void game_log::g_init_game_stub() void game_log::g_shutdown_game_stub(int free_scripts) { - printf("==== ShutdownGame (%d) ====\n", free_scripts); + console::info("==== ShutdownGame (%d) ====\n", free_scripts); if (log_file) { diff --git a/src/module/log_file.cpp b/src/module/log_file.cpp index 20b1307..101cbaf 100644 --- a/src/module/log_file.cpp +++ b/src/module/log_file.cpp @@ -1,11 +1,11 @@ #include #include - #include "game/game.hpp" #include "game/engine/scoped_critical_section.hpp" #include "log_file.hpp" #include "file_system.hpp" +#include "console.hpp" const char* log_file::log_file_name; @@ -80,7 +80,7 @@ void log_file::info(const char* fmt, ...) com_log_print_message(msg); } - printf("%s", msg); + console::info("%s", msg); } void log_file::post_load()