feat(services): added hotkey_service (#634)

Co-authored-by: Yimura <24669514+Yimura@users.noreply.github.com>
This commit is contained in:
Aure7138
2022-11-27 01:29:14 +08:00
committed by GitHub
parent d927a58b1d
commit 2364bc5688
8 changed files with 195 additions and 3 deletions

View File

@ -0,0 +1,37 @@
#include "hotkey.hpp"
namespace big
{
hotkey::hotkey(rage::joaat_t name_hash, key_t key, hotkey_func func, std::optional<std::chrono::high_resolution_clock::duration> cooldown) :
m_name_hash(name_hash),
m_key(key),
m_func(func),
m_cooldown(cooldown),
m_wakeup()
{
}
bool hotkey::can_exec() const
{
return !m_cooldown.has_value() || std::chrono::high_resolution_clock::now() >= m_wakeup;
}
void hotkey::exec()
{
if (m_cooldown.has_value())
m_wakeup = std::chrono::high_resolution_clock::now() + m_cooldown.value();
m_func();
}
rage::joaat_t hotkey::name_hash() const
{
return m_name_hash;
}
void hotkey::set_key(key_t new_key)
{
m_key = new_key;
}
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "common.hpp"
#include "rage/joaat.hpp"
namespace big
{
using hotkey_func = std::function<void()>;
using key_t = unsigned int;
class hotkey final
{
public:
hotkey(rage::joaat_t name_hash, key_t key, hotkey_func func, std::optional<std::chrono::high_resolution_clock::duration> cooldown = std::nullopt);
virtual ~hotkey() = default;
bool can_exec() const;
void exec();
rage::joaat_t name_hash() const;
void set_key(key_t new_key);
private:
rage::joaat_t m_name_hash;
key_t m_key;
hotkey_func m_func;
std::optional<std::chrono::high_resolution_clock::duration> m_cooldown;
std::chrono::high_resolution_clock::time_point m_wakeup;
};
}

View File

@ -0,0 +1,67 @@
#include "hotkey_service.hpp"
#include "fiber_pool.hpp"
#include "util/teleport.hpp"
namespace big
{
hotkey_service::hotkey_service()
{
register_hotkey("waypoint", g->settings.hotkeys.teleport_waypoint, teleport::to_waypoint);
register_hotkey("objective", g->settings.hotkeys.teleport_objective, teleport::to_objective);
g_hotkey_service = this;
}
hotkey_service::~hotkey_service()
{
g_hotkey_service = nullptr;
}
void hotkey_service::register_hotkey(const std::string_view name, key_t key, hotkey_func func, eKeyState state, std::optional<std::chrono::high_resolution_clock::duration> cooldown)
{
m_hotkeys[state == eKeyState::RELEASE].emplace(key, hotkey(rage::joaat(name), key, func, cooldown));
}
bool hotkey_service::update_hotkey(const std::string_view name, const key_t key)
{
static auto update_hotkey_map = [key](hotkey_map& hotkey_map, rage::joaat_t name_hash) -> bool
{
if (const auto &it = std::find_if(hotkey_map.begin(), hotkey_map.end(), [name_hash](std::pair<key_t, hotkey> pair) -> bool
{
return pair.second.name_hash() == name_hash;
}); it != hotkey_map.end())
{
auto hotkey = it->second;
hotkey.set_key(key);
hotkey_map.emplace(key, hotkey);
hotkey_map.erase(it);
return true;
}
return false;
};
const auto name_hash = rage::joaat(name);
return update_hotkey_map(m_hotkeys[1], name_hash) // released
&& update_hotkey_map(m_hotkeys[0], name_hash); // down
}
void hotkey_service::wndproc(eKeyState state, key_t key)
{
if (state == eKeyState::RELEASE || state == eKeyState::DOWN)
{
auto &hotkey_map = m_hotkeys[state == eKeyState::RELEASE];
if (const auto &it = hotkey_map.find(key); it != hotkey_map.end())
{
if (auto &hotkey = it->second; hotkey.can_exec())
{
g_fiber_pool->queue_job([&hotkey]
{
hotkey.exec();
});
}
}
}
}
}

View File

@ -0,0 +1,42 @@
#pragma once
#include "common.hpp"
#include "hotkey.hpp"
namespace big
{
enum eKeyState : unsigned int
{
RELEASE = WM_KEYUP,
DOWN = WM_KEYDOWN
};
using hotkey_map = std::map<key_t, hotkey>;
class hotkey_service final
{
public:
hotkey_service();
virtual ~hotkey_service();
hotkey_service(const hotkey_service&) = delete;
hotkey_service(hotkey_service&&) noexcept = delete;
hotkey_service& operator=(const hotkey_service&) = delete;
hotkey_service& operator=(hotkey_service&&) noexcept = delete;
void register_hotkey(
const std::string_view name,
const key_t initial_key,
const hotkey_func func,
const eKeyState state = eKeyState::RELEASE,
std::optional<std::chrono::high_resolution_clock::duration> cooldown = std::nullopt);
bool update_hotkey(const std::string_view name, const key_t new_key);
void wndproc(eKeyState state, key_t key);
private:
// yes curse me
std::array<hotkey_map, 2> m_hotkeys;
};
inline hotkey_service* g_hotkey_service{};
}