Functionality Improvements
+ Added 'keycatchers' as an standalone component + Improvement to logger with output division + Improvements to game console
This commit is contained in:
parent
b66a191aff
commit
84facee97e
@ -159,7 +159,7 @@ namespace command
|
|||||||
add(command, [f = std::move(function)](const params&)
|
add(command, [f = std::move(function)](const params&)
|
||||||
{
|
{
|
||||||
f();
|
f();
|
||||||
});
|
}, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(const std::string& command, command_param_function function, const char* desc)
|
void add(const std::string& command, command_param_function function, const char* desc)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "component/dvars.hpp"
|
#include "component/dvars.hpp"
|
||||||
#include "component/scheduler.hpp"
|
#include "component/scheduler.hpp"
|
||||||
|
#include "component/keycatchers.hpp"
|
||||||
|
|
||||||
#include <utilities/hook.hpp>
|
#include <utilities/hook.hpp>
|
||||||
#include <utilities/string.hpp>
|
#include <utilities/string.hpp>
|
||||||
@ -437,8 +438,7 @@ namespace game_console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool console_char_event(const int local_client_num, const int key, const bool is_repeated)
|
||||||
bool console_char_event(const int local_client_num, const int key)
|
|
||||||
{
|
{
|
||||||
if (key == game::keyNum_t::K_GRAVE ||
|
if (key == game::keyNum_t::K_GRAVE ||
|
||||||
key == game::keyNum_t::K_TILDE ||
|
key == game::keyNum_t::K_TILDE ||
|
||||||
@ -490,7 +490,7 @@ namespace game_console
|
|||||||
|
|
||||||
for (size_t i = 0; i < clipboard.length(); i++)
|
for (size_t i = 0; i < clipboard.length(); i++)
|
||||||
{
|
{
|
||||||
console_char_event(local_client_num, clipboard[i]);
|
console_char_event(local_client_num, clipboard[i], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -546,7 +546,7 @@ namespace game_console
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool console_key_event(const int local_client_num, const int key, const int down)
|
bool console_key_event(const int local_client_num, const int key, const bool down, const unsigned int time)
|
||||||
{
|
{
|
||||||
if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE)
|
if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE)
|
||||||
{
|
{
|
||||||
@ -650,10 +650,8 @@ namespace game_console
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == game::keyNum_t::K_ENTER)
|
if (key == game::keyNum_t::K_ENTER && !utilities::string::is_truely_empty(con.buffer))
|
||||||
{
|
{
|
||||||
//game::Cbuf_AddText(0, utilities::string::va("%s \n", fixed_input.data()));
|
|
||||||
|
|
||||||
if (history_index != -1)
|
if (history_index != -1)
|
||||||
{
|
{
|
||||||
const auto itr = history.begin() + history_index;
|
const auto itr = history.begin() + history_index;
|
||||||
@ -684,29 +682,6 @@ namespace game_console
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities::hook::detour cl_key_event_hook;
|
|
||||||
void cl_key_event_stub(int localClientNum, int key, bool down, unsigned int time)
|
|
||||||
{
|
|
||||||
if (!game_console::console_key_event(localClientNum, key, down))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl_key_event_hook.invoke<void>(localClientNum, key, down, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
utilities::hook::detour cl_char_event_hook;
|
|
||||||
void cl_char_event_stub(const int localClientNum, const int key, bool isRepeated)
|
|
||||||
{
|
|
||||||
if (!game_console::console_char_event(localClientNum, key))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl_char_event_hook.invoke<void>(localClientNum, key, isRepeated);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -714,9 +689,8 @@ namespace game_console
|
|||||||
{
|
{
|
||||||
scheduler::loop(draw_console, scheduler::renderer);
|
scheduler::loop(draw_console, scheduler::renderer);
|
||||||
|
|
||||||
cl_key_event_hook.create(0x142839250_g, cl_key_event_stub);
|
keycatchers::add_key_event(console_key_event);
|
||||||
cl_char_event_hook.create(0x142836F80_g, cl_char_event_stub);
|
keycatchers::add_char_event(console_char_event);
|
||||||
|
|
||||||
|
|
||||||
// initialize our structs
|
// initialize our structs
|
||||||
con.cursor = 0;
|
con.cursor = 0;
|
||||||
|
71
source/proxy-dll/component/keycatchers.cpp
Normal file
71
source/proxy-dll/component/keycatchers.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "keycatchers.hpp"
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include <utilities/hook.hpp>
|
||||||
|
#include <utilities/concurrency.hpp>
|
||||||
|
|
||||||
|
namespace keycatchers
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
utilities::concurrency::container<std::vector<ke_typedef>, std::recursive_mutex> key_event_callbacks;
|
||||||
|
utilities::concurrency::container<std::vector<ch_typedef>, std::recursive_mutex> char_event_callbacks;
|
||||||
|
|
||||||
|
utilities::hook::detour cl_key_event_hook;
|
||||||
|
void cl_key_event_stub(const int localClientNum, const int key, bool down, const unsigned int time)
|
||||||
|
{
|
||||||
|
key_event_callbacks.access([&](std::vector<ke_typedef>& callbacks)
|
||||||
|
{
|
||||||
|
for (auto& func : callbacks) {
|
||||||
|
if (!func(localClientNum, key, down, time))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cl_key_event_hook.invoke<void>(localClientNum, key, down, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
utilities::hook::detour cl_char_event_hook;
|
||||||
|
void cl_char_event_stub(const int localClientNum, const int key, bool isRepeated)
|
||||||
|
{
|
||||||
|
char_event_callbacks.access([&](std::vector<ch_typedef>& callbacks)
|
||||||
|
{
|
||||||
|
for (auto& func : callbacks) {
|
||||||
|
if (!func(localClientNum, key, isRepeated))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cl_char_event_hook.invoke<void>(localClientNum, key, isRepeated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_key_event(ke_typedef&& func)
|
||||||
|
{
|
||||||
|
key_event_callbacks.access([&func](std::vector<ke_typedef>& callbacks)
|
||||||
|
{
|
||||||
|
callbacks.push_back(std::move(func));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_char_event(ch_typedef&& func)
|
||||||
|
{
|
||||||
|
char_event_callbacks.access([&func](std::vector<ch_typedef>& callbacks)
|
||||||
|
{
|
||||||
|
callbacks.push_back(std::move(func));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
cl_key_event_hook.create(0x142839250_g, cl_key_event_stub);
|
||||||
|
cl_char_event_hook.create(0x142836F80_g, cl_char_event_stub);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(keycatchers::component)
|
10
source/proxy-dll/component/keycatchers.hpp
Normal file
10
source/proxy-dll/component/keycatchers.hpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace keycatchers
|
||||||
|
{
|
||||||
|
using ke_typedef = std::function<bool(int, int, bool, unsigned int)>;
|
||||||
|
using ch_typedef = std::function<bool(int, int, bool)>;
|
||||||
|
|
||||||
|
void add_key_event(ke_typedef&& func);
|
||||||
|
void add_char_event(ch_typedef&& func);
|
||||||
|
}
|
@ -5,9 +5,6 @@
|
|||||||
|
|
||||||
#include <utilities/nt.hpp>
|
#include <utilities/nt.hpp>
|
||||||
|
|
||||||
#define OUTPUT_DEBUG_API
|
|
||||||
#define OUTPUT_GAME_CONSOLE
|
|
||||||
|
|
||||||
namespace logger
|
namespace logger
|
||||||
{
|
{
|
||||||
const char* LogTypeNames[] =
|
const char* LogTypeNames[] =
|
||||||
@ -15,7 +12,8 @@ namespace logger
|
|||||||
"DEBUG",
|
"DEBUG",
|
||||||
"INFO",
|
"INFO",
|
||||||
"WARN",
|
"WARN",
|
||||||
"ERROR"
|
"ERROR",
|
||||||
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
void write(const int type, std::string str)
|
void write(const int type, std::string str)
|
||||||
@ -24,15 +22,14 @@ namespace logger
|
|||||||
if (type == LOG_TYPE_DEBUG) return;
|
if (type == LOG_TYPE_DEBUG) return;
|
||||||
#endif // _DEBUG
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
game_console::print(str);
|
||||||
|
if (type == type::LOG_TYPE_CONSOLE) return;
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "[ " << LogTypeNames[type] << " ] " << str << std::endl;
|
ss << "[ " << LogTypeNames[type] << " ] " << str << std::endl;
|
||||||
|
|
||||||
std::string text = ss.str();
|
std::string text = ss.str();
|
||||||
|
|
||||||
#ifdef OUTPUT_GAME_CONSOLE
|
|
||||||
game_console::print(text);
|
|
||||||
#endif // OUTPUT_GAME_CONSOLE
|
|
||||||
|
|
||||||
#ifdef OUTPUT_DEBUG_API
|
#ifdef OUTPUT_DEBUG_API
|
||||||
OutputDebugStringA(text.c_str());
|
OutputDebugStringA(text.c_str());
|
||||||
#endif // OUTPUT_DEBUG_API
|
#endif // OUTPUT_DEBUG_API
|
||||||
|
@ -7,7 +7,8 @@ namespace logger
|
|||||||
LOG_TYPE_DEBUG = 0,
|
LOG_TYPE_DEBUG = 0,
|
||||||
LOG_TYPE_INFO = 1,
|
LOG_TYPE_INFO = 1,
|
||||||
LOG_TYPE_WARN = 2,
|
LOG_TYPE_WARN = 2,
|
||||||
LOG_TYPE_ERROR = 3
|
LOG_TYPE_ERROR = 3,
|
||||||
|
LOG_TYPE_CONSOLE = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
void write(const int type, std::string str);
|
void write(const int type, std::string str);
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "dvars.hpp"
|
#include "dvars.hpp"
|
||||||
#include "hashes.hpp"
|
#include "hashes.hpp"
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "game_console.hpp"
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "definitions/xassets.hpp"
|
#include "definitions/xassets.hpp"
|
||||||
@ -1099,17 +1098,17 @@ namespace mods {
|
|||||||
if (!game::Com_IsRunningUILevel())
|
if (!game::Com_IsRunningUILevel())
|
||||||
{
|
{
|
||||||
// avoid gsc issues, but if a script is loaded in the frontend, it will still crash
|
// avoid gsc issues, but if a script is loaded in the frontend, it will still crash
|
||||||
game_console::print("can't load mods while in-game!");
|
logger::write(logger::LOG_TYPE_CONSOLE, "can't load mods while in-game!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!storage.load_mods())
|
if (!storage.load_mods())
|
||||||
{
|
{
|
||||||
game_console::print("mods reloaded.");
|
logger::write(logger::LOG_TYPE_CONSOLE, "mods reloaded.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
game_console::print("mods reloaded with errors, see logs.");
|
logger::write(logger::LOG_TYPE_CONSOLE, "mods reloaded with errors, see logs.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,30 @@ namespace utilities::string
|
|||||||
}
|
}
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
void copy(char* dest, const size_t max_size, const char* src)
|
||||||
|
{
|
||||||
|
if (!max_size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0;; ++i)
|
||||||
|
{
|
||||||
|
if (i + 1 == max_size)
|
||||||
|
{
|
||||||
|
dest[i] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest[i] = src[i];
|
||||||
|
|
||||||
|
if (!src[i])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string replace(std::string str, const std::string& from, const std::string& to)
|
std::string replace(std::string str, const std::string& from, const std::string& to)
|
||||||
{
|
{
|
||||||
if (from.empty())
|
if (from.empty())
|
||||||
@ -198,6 +222,46 @@ namespace utilities::string
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string& ltrim(std::string& str)
|
||||||
|
{
|
||||||
|
str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](const unsigned char input)
|
||||||
|
{
|
||||||
|
return !std::isspace(input);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string& rtrim(std::string& str)
|
||||||
|
{
|
||||||
|
str.erase(std::find_if(str.rbegin(), str.rend(), [](const unsigned char input)
|
||||||
|
{
|
||||||
|
return !std::isspace(input);
|
||||||
|
}).base(), str.end());
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string& trim(std::string& str)
|
||||||
|
{
|
||||||
|
return ltrim(rtrim(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_truely_empty(std::string str)
|
||||||
|
{
|
||||||
|
return trim(str).size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringMatch compare(const std::string& s1, const std::string& s2)
|
||||||
|
{
|
||||||
|
if (s1 == s2)
|
||||||
|
return StringMatch::Identical;
|
||||||
|
else if (to_lower(s1) == to_lower(s2))
|
||||||
|
return StringMatch::CaseVariant;
|
||||||
|
else
|
||||||
|
return StringMatch::Mismatch;
|
||||||
|
}
|
||||||
|
|
||||||
double match(const std::string& input, const std::string& text)
|
double match(const std::string& input, const std::string& text)
|
||||||
{
|
{
|
||||||
if (text == input) return 1.00; // identical
|
if (text == input) return 1.00; // identical
|
||||||
@ -211,13 +275,6 @@ namespace utilities::string
|
|||||||
return ((double)match_percent / 100);
|
return ((double)match_percent / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compare(const std::string& s1, const std::string& s2, bool sensetive)
|
|
||||||
{
|
|
||||||
if (sensetive && (s1 == s2)) return true;
|
|
||||||
if (!sensetive && (to_lower(s1) == to_lower(s2))) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool contains(std::string text, std::string substr, bool sensetive)
|
bool contains(std::string text, std::string substr, bool sensetive)
|
||||||
{
|
{
|
||||||
if (!sensetive) {
|
if (!sensetive) {
|
||||||
|
@ -100,9 +100,28 @@ namespace utilities::string
|
|||||||
std::string convert(const std::wstring& wstr);
|
std::string convert(const std::wstring& wstr);
|
||||||
std::wstring convert(const std::string& str);
|
std::wstring convert(const std::string& str);
|
||||||
|
|
||||||
|
void copy(char* dest, size_t max_size, const char* src);
|
||||||
|
|
||||||
|
template <size_t Size>
|
||||||
|
void copy(char(&dest)[Size], const char* src)
|
||||||
|
{
|
||||||
|
copy(dest, Size, src);
|
||||||
|
}
|
||||||
|
|
||||||
std::string replace(std::string str, const std::string& from, const std::string& to);
|
std::string replace(std::string str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
|
std::string& trim(std::string& str);
|
||||||
|
|
||||||
|
bool is_truely_empty(std::string str);
|
||||||
|
|
||||||
|
enum StringMatch
|
||||||
|
{
|
||||||
|
Mismatch = 0,
|
||||||
|
Identical = 1,
|
||||||
|
CaseVariant = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
StringMatch compare(const std::string& s1, const std::string& s2);
|
||||||
double match(const std::string& input, const std::string& text);
|
double match(const std::string& input, const std::string& text);
|
||||||
bool compare(const std::string& s1, const std::string& s2, bool sensetive = false);
|
|
||||||
bool contains(std::string text, std::string substr, bool sensetive = false);
|
bool contains(std::string text, std::string substr, bool sensetive = false);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user