Console changes
This commit is contained in:
parent
72e1cd331a
commit
6d6e79cc15
@ -625,7 +625,7 @@ namespace command
|
|||||||
if (dvar->type != game::dvar_type::string
|
if (dvar->type != game::dvar_type::string
|
||||||
&& dvar->type != game::dvar_type::enumeration)
|
&& dvar->type != game::dvar_type::enumeration)
|
||||||
{
|
{
|
||||||
console::info("%s is not a string-based dvar\n", dvar->hash);
|
console::info("%s is not a string-based dvar\n", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <utils/thread.hpp>
|
#include <utils/thread.hpp>
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
|
|
||||||
|
#define OUTPUT_HANDLE GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
|
|
||||||
namespace game_console
|
namespace game_console
|
||||||
{
|
{
|
||||||
void print(int type, const std::string& data);
|
void print(int type, const std::string& data);
|
||||||
@ -17,6 +19,9 @@ namespace console
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
utils::hook::detour printf_hook;
|
||||||
|
std::recursive_mutex print_mutex;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool kill;
|
bool kill;
|
||||||
@ -30,62 +35,145 @@ namespace console
|
|||||||
|
|
||||||
void set_cursor_pos(int x)
|
void set_cursor_pos(int x)
|
||||||
{
|
{
|
||||||
const auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO info{};
|
CONSOLE_SCREEN_BUFFER_INFO info{};
|
||||||
GetConsoleScreenBufferInfo(handle, &info);
|
GetConsoleScreenBufferInfo(OUTPUT_HANDLE, &info);
|
||||||
info.dwCursorPosition.X = static_cast<short>(x);
|
info.dwCursorPosition.X = static_cast<short>(x);
|
||||||
SetConsoleCursorPosition(handle, info.dwCursorPosition);
|
SetConsoleCursorPosition(OUTPUT_HANDLE, info.dwCursorPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_cursor(const bool show)
|
void show_cursor(const bool show)
|
||||||
{
|
{
|
||||||
const auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
CONSOLE_CURSOR_INFO info{};
|
CONSOLE_CURSOR_INFO info{};
|
||||||
GetConsoleCursorInfo(handle, &info);
|
GetConsoleCursorInfo(OUTPUT_HANDLE, &info);
|
||||||
info.bVisible = show;
|
info.bVisible = show;
|
||||||
SetConsoleCursorInfo(handle, &info);
|
SetConsoleCursorInfo(OUTPUT_HANDLE, &info);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
int invoke_printf(const char* fmt, Args&&... args)
|
||||||
|
{
|
||||||
|
return printf_hook.invoke<int>(fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string format(va_list* ap, const char* message)
|
||||||
|
{
|
||||||
|
static thread_local char buffer[0x1000];
|
||||||
|
|
||||||
|
const auto count = _vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer), message, *ap);
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {buffer, static_cast<size_t>(count)};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t get_attribute(const int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case con_type_info:
|
||||||
|
return 7; // white
|
||||||
|
case con_type_warning:
|
||||||
|
return 6; // yellow
|
||||||
|
case con_type_error:
|
||||||
|
return 4; // red
|
||||||
|
case con_type_debug:
|
||||||
|
return 3; // cyan
|
||||||
|
}
|
||||||
|
|
||||||
|
return 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
|
std::lock_guard _0(print_mutex);
|
||||||
|
|
||||||
show_cursor(false);
|
show_cursor(false);
|
||||||
set_cursor_pos(0);
|
set_cursor_pos(0);
|
||||||
|
invoke_printf("%s", con.buffer);
|
||||||
printf("%s", con.buffer);
|
|
||||||
|
|
||||||
set_cursor_pos(con.cursor);
|
set_cursor_pos(con.cursor);
|
||||||
show_cursor(true);
|
show_cursor(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_output()
|
void clear_output()
|
||||||
{
|
{
|
||||||
|
std::lock_guard _0(print_mutex);
|
||||||
|
|
||||||
show_cursor(false);
|
show_cursor(false);
|
||||||
set_cursor_pos(0);
|
set_cursor_pos(0);
|
||||||
|
|
||||||
for (auto i = 0; i < std::strlen(con.buffer); i++)
|
for (auto i = 0; i < std::strlen(con.buffer); i++)
|
||||||
{
|
{
|
||||||
printf(" ");
|
invoke_printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
set_cursor_pos(con.cursor);
|
set_cursor_pos(con.cursor);
|
||||||
show_cursor(true);
|
show_cursor(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dispatch_message(const int type, const std::string& message)
|
||||||
|
{
|
||||||
|
std::lock_guard _0(print_mutex);
|
||||||
|
|
||||||
|
clear_output();
|
||||||
|
set_cursor_pos(0);
|
||||||
|
|
||||||
|
SetConsoleTextAttribute(OUTPUT_HANDLE, get_attribute(type));
|
||||||
|
const auto res = invoke_printf("%s", message.data());
|
||||||
|
SetConsoleTextAttribute(OUTPUT_HANDLE, get_attribute(con_type_info));
|
||||||
|
|
||||||
|
game_console::print(type, message);
|
||||||
|
|
||||||
|
if (message.size() <= 0 || message[message.size() - 1] != '\n')
|
||||||
|
{
|
||||||
|
invoke_printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
std::lock_guard _0(print_mutex);
|
||||||
|
|
||||||
clear_output();
|
clear_output();
|
||||||
strncpy_s(con.buffer, "", sizeof(con.buffer));
|
strncpy_s(con.buffer, "", sizeof(con.buffer));
|
||||||
|
|
||||||
con.cursor = 0;
|
con.cursor = 0;
|
||||||
set_cursor_pos(0);
|
set_cursor_pos(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t get_max_input_length()
|
||||||
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info{};
|
||||||
|
GetConsoleScreenBufferInfo(OUTPUT_HANDLE, &info);
|
||||||
|
const auto columns = static_cast<size_t>(info.srWindow.Right - info.srWindow.Left - 1);
|
||||||
|
return std::max(size_t(0), std::min(columns, sizeof(con.buffer)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_resize()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void handle_input(const INPUT_RECORD record)
|
void handle_input(const INPUT_RECORD record)
|
||||||
{
|
{
|
||||||
|
if (record.EventType == WINDOW_BUFFER_SIZE_EVENT)
|
||||||
|
{
|
||||||
|
handle_resize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown)
|
if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard _0(print_mutex);
|
||||||
|
|
||||||
const auto key = record.Event.KeyEvent.wVirtualKeyCode;
|
const auto key = record.Event.KeyEvent.wVirtualKeyCode;
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
@ -102,9 +190,9 @@ namespace console
|
|||||||
{
|
{
|
||||||
strncpy_s(con.buffer, con.history.at(con.history_index).data(), sizeof(con.buffer));
|
strncpy_s(con.buffer, con.history.at(con.history_index).data(), sizeof(con.buffer));
|
||||||
con.cursor = static_cast<int>(strlen(con.buffer));
|
con.cursor = static_cast<int>(strlen(con.buffer));
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VK_DOWN:
|
case VK_DOWN:
|
||||||
@ -120,9 +208,9 @@ namespace console
|
|||||||
{
|
{
|
||||||
strncpy_s(con.buffer, con.history.at(con.history_index).data(), sizeof(con.buffer));
|
strncpy_s(con.buffer, con.history.at(con.history_index).data(), sizeof(con.buffer));
|
||||||
con.cursor = static_cast<int>(strlen(con.buffer));
|
con.cursor = static_cast<int>(strlen(con.buffer));
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VK_LEFT:
|
case VK_LEFT:
|
||||||
@ -157,7 +245,10 @@ namespace console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con.history.push_front(con.buffer);
|
if (con.buffer[0])
|
||||||
|
{
|
||||||
|
con.history.push_front(con.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (con.history.size() > 10)
|
if (con.history.size() > 10)
|
||||||
{
|
{
|
||||||
@ -168,14 +259,20 @@ namespace console
|
|||||||
|
|
||||||
game::Cbuf_AddText(0, 0, con.buffer);
|
game::Cbuf_AddText(0, 0, con.buffer);
|
||||||
|
|
||||||
strncpy_s(con.buffer, "", sizeof(con.buffer));
|
|
||||||
con.cursor = 0;
|
con.cursor = 0;
|
||||||
|
|
||||||
printf("\r\n");
|
clear_output();
|
||||||
|
invoke_printf("]%s\r\n", con.buffer);
|
||||||
|
strncpy_s(con.buffer, "", sizeof(con.buffer));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VK_BACK:
|
case VK_BACK:
|
||||||
{
|
{
|
||||||
|
if (con.cursor <= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
clear_output();
|
clear_output();
|
||||||
|
|
||||||
std::memmove(con.buffer + con.cursor - 1, con.buffer + con.cursor,
|
std::memmove(con.buffer + con.cursor - 1, con.buffer + con.cursor,
|
||||||
@ -183,7 +280,6 @@ namespace console
|
|||||||
con.cursor--;
|
con.cursor--;
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -194,7 +290,7 @@ namespace console
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::strlen(con.buffer) + 1 >= sizeof(con.buffer))
|
if (std::strlen(con.buffer) + 1 >= get_max_input_length())
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -203,51 +299,22 @@ namespace console
|
|||||||
con.buffer + con.cursor, std::strlen(con.buffer) + 1 - con.cursor);
|
con.buffer + con.cursor, std::strlen(con.buffer) + 1 - con.cursor);
|
||||||
con.buffer[con.cursor] = c;
|
con.buffer[con.cursor] = c;
|
||||||
con.cursor++;
|
con.cursor++;
|
||||||
|
|
||||||
update();
|
update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string format(va_list* ap, const char* message)
|
int __cdecl printf_stub(const char* fmt, ...)
|
||||||
{
|
|
||||||
static thread_local char buffer[0x1000];
|
|
||||||
|
|
||||||
const auto count = _vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer), message, *ap);
|
|
||||||
if (count < 0)
|
|
||||||
{
|
{
|
||||||
return {};
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
const auto result = format(&ap, fmt);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return dispatch_message(con_type_info, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {buffer, static_cast<size_t>(count)};
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t get_attribute(const int type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case con_type_info:
|
|
||||||
return 7; // white
|
|
||||||
case con_type_warning:
|
|
||||||
return 6; // yellow
|
|
||||||
case con_type_error:
|
|
||||||
return 4; // red
|
|
||||||
case con_type_debug:
|
|
||||||
return 3; // cyan
|
|
||||||
}
|
|
||||||
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispatch_message(const int type, const std::string& message)
|
|
||||||
{
|
|
||||||
const auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
SetConsoleTextAttribute(handle, get_attribute(type));
|
|
||||||
printf("%s", message.data());
|
|
||||||
SetConsoleTextAttribute(handle, get_attribute(con_type_info));
|
|
||||||
game_console::print(type, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(const int type, const char* fmt, ...)
|
void print(const int type, const char* fmt, ...)
|
||||||
@ -270,6 +337,8 @@ namespace console
|
|||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
|
printf_hook.create(printf, printf_stub);
|
||||||
|
|
||||||
ShowWindow(GetConsoleWindow(), SW_SHOW);
|
ShowWindow(GetConsoleWindow(), SW_SHOW);
|
||||||
SetConsoleTitle("H1-Mod");
|
SetConsoleTitle("H1-Mod");
|
||||||
|
|
||||||
|
@ -124,6 +124,9 @@ namespace logger
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lua print
|
||||||
|
utils::hook::jump(SELECT_VALUE(0x0E6E30_b, 0x1F6140_b), printf);
|
||||||
|
|
||||||
com_error_hook.create(game::Com_Error, com_error_stub);
|
com_error_hook.create(game::Com_Error, com_error_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -167,7 +167,7 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), const void* inData, bool includeOverride)>
|
WEAK symbol<void(XAssetType type, void(__cdecl* func)(XAssetHeader, void*), const void* inData, bool includeOverride)>
|
||||||
DB_EnumXAssets_Internal{0x1F0BF0, 0x394C60};
|
DB_EnumXAssets_Internal{0x1F0BF0, 0x394C60};
|
||||||
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x0, 0x366140};
|
WEAK symbol<const char*(const XAsset* asset)> DB_GetXAssetName{0x1BF890, 0x366140};
|
||||||
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{0x0, 0x0};
|
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{0x0, 0x0};
|
||||||
WEAK symbol<XAssetHeader(XAssetType type, const char* name,
|
WEAK symbol<XAssetHeader(XAssetType type, const char* name,
|
||||||
int createDefault)> DB_FindXAssetHeader{0x1F1120, 0x3950C0};
|
int createDefault)> DB_FindXAssetHeader{0x1F1120, 0x3950C0};
|
||||||
|
Loading…
Reference in New Issue
Block a user