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&)
|
||||
{
|
||||
f();
|
||||
});
|
||||
}, desc);
|
||||
}
|
||||
|
||||
void add(const std::string& command, command_param_function function, const char* desc)
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "component/dvars.hpp"
|
||||
#include "component/scheduler.hpp"
|
||||
#include "component/keycatchers.hpp"
|
||||
|
||||
#include <utilities/hook.hpp>
|
||||
#include <utilities/string.hpp>
|
||||
@ -437,8 +438,7 @@ namespace game_console
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool console_char_event(const int local_client_num, const int key)
|
||||
bool console_char_event(const int local_client_num, const int key, const bool is_repeated)
|
||||
{
|
||||
if (key == game::keyNum_t::K_GRAVE ||
|
||||
key == game::keyNum_t::K_TILDE ||
|
||||
@ -490,7 +490,7 @@ namespace game_console
|
||||
|
||||
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;
|
||||
@ -546,7 +546,7 @@ namespace game_console
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
const auto itr = history.begin() + history_index;
|
||||
@ -684,29 +682,6 @@ namespace game_console
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -714,9 +689,8 @@ namespace game_console
|
||||
{
|
||||
scheduler::loop(draw_console, scheduler::renderer);
|
||||
|
||||
cl_key_event_hook.create(0x142839250_g, cl_key_event_stub);
|
||||
cl_char_event_hook.create(0x142836F80_g, cl_char_event_stub);
|
||||
|
||||
keycatchers::add_key_event(console_key_event);
|
||||
keycatchers::add_char_event(console_char_event);
|
||||
|
||||
// initialize our structs
|
||||
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>
|
||||
|
||||
#define OUTPUT_DEBUG_API
|
||||
#define OUTPUT_GAME_CONSOLE
|
||||
|
||||
namespace logger
|
||||
{
|
||||
const char* LogTypeNames[] =
|
||||
@ -15,7 +12,8 @@ namespace logger
|
||||
"DEBUG",
|
||||
"INFO",
|
||||
"WARN",
|
||||
"ERROR"
|
||||
"ERROR",
|
||||
""
|
||||
};
|
||||
|
||||
void write(const int type, std::string str)
|
||||
@ -24,15 +22,14 @@ namespace logger
|
||||
if (type == LOG_TYPE_DEBUG) return;
|
||||
#endif // _DEBUG
|
||||
|
||||
game_console::print(str);
|
||||
if (type == type::LOG_TYPE_CONSOLE) return;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "[ " << LogTypeNames[type] << " ] " << str << std::endl;
|
||||
|
||||
std::string text = ss.str();
|
||||
|
||||
#ifdef OUTPUT_GAME_CONSOLE
|
||||
game_console::print(text);
|
||||
#endif // OUTPUT_GAME_CONSOLE
|
||||
|
||||
#ifdef OUTPUT_DEBUG_API
|
||||
OutputDebugStringA(text.c_str());
|
||||
#endif // OUTPUT_DEBUG_API
|
||||
|
@ -7,7 +7,8 @@ namespace logger
|
||||
LOG_TYPE_DEBUG = 0,
|
||||
LOG_TYPE_INFO = 1,
|
||||
LOG_TYPE_WARN = 2,
|
||||
LOG_TYPE_ERROR = 3
|
||||
LOG_TYPE_ERROR = 3,
|
||||
LOG_TYPE_CONSOLE = 4
|
||||
};
|
||||
|
||||
void write(const int type, std::string str);
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "dvars.hpp"
|
||||
#include "hashes.hpp"
|
||||
#include "command.hpp"
|
||||
#include "game_console.hpp"
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "definitions/xassets.hpp"
|
||||
@ -1099,17 +1098,17 @@ namespace mods {
|
||||
if (!game::Com_IsRunningUILevel())
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (!storage.load_mods())
|
||||
{
|
||||
game_console::print("mods reloaded.");
|
||||
logger::write(logger::LOG_TYPE_CONSOLE, "mods reloaded.");
|
||||
}
|
||||
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)
|
||||
|
||||
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)
|
||||
{
|
||||
if (from.empty())
|
||||
@ -198,6 +222,46 @@ namespace utilities::string
|
||||
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)
|
||||
{
|
||||
if (text == input) return 1.00; // identical
|
||||
@ -211,13 +275,6 @@ namespace utilities::string
|
||||
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)
|
||||
{
|
||||
if (!sensetive) {
|
||||
|
@ -100,9 +100,28 @@ namespace utilities::string
|
||||
std::string convert(const std::wstring& wstr);
|
||||
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& 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);
|
||||
bool compare(const std::string& s1, const std::string& s2, bool sensetive = false);
|
||||
bool contains(std::string text, std::string substr, bool sensetive = false);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user