Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions src/unrealsdk/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ namespace unrealsdk::commands {

namespace {

#ifndef UNREALSDK_IMPORTING

utils::StringViewMap<std::wstring, DLLSafeCallback*> commands{};
using DLLSafeCallback = utils::DLLSafeCallback<Callback>;

#ifndef UNREALSDK_IMPORTING
utils::StringViewMap<std::wstring, DLLSafeCallback> commands{};
#endif

} // namespace
Expand All @@ -18,25 +18,25 @@ utils::StringViewMap<std::wstring, DLLSafeCallback*> commands{};
const std::wstring NEXT_LINE{};

#ifdef UNREALSDK_SHARED
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback* callback);
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback&& callback);
#endif
#ifndef UNREALSDK_IMPORTING
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback* callback) {
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback&& callback) {
std::wstring lower_cmd(size, '\0');
std::transform(cmd, cmd + size, lower_cmd.begin(), &std::towlower);

if (commands.contains(lower_cmd)) {
return false;
}

commands.emplace(std::move(lower_cmd), callback);
commands.emplace(std::move(lower_cmd), std::move(callback));
return true;
}
#endif

bool add_command(std::wstring_view cmd, const Callback& callback) {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
return UNREALSDK_MANGLE(add_command)(cmd.data(), cmd.size(), new DLLSafeCallback(callback));
return UNREALSDK_MANGLE(add_command)(cmd.data(), cmd.size(), {callback});
}

#ifdef UNREALSDK_SHARED
Expand Down Expand Up @@ -67,9 +67,7 @@ UNREALSDK_CAPI(bool, remove_command, const wchar_t* cmd, size_t size) {
return false;
}

iter->second->destroy();
commands.erase(iter);

return true;
}
#endif
Expand Down Expand Up @@ -101,12 +99,10 @@ bool is_command_valid(std::wstring_view line, bool direct_user_input) {
void run_command(std::wstring_view line) {
auto iter = commands.find(NEXT_LINE);
if (iter != commands.end()) {
auto callback = iter->second;
auto callback = std::move(iter->second);
commands.erase(iter);

callback->operator()(line.data(), line.size(), 0);

callback->destroy();
callback(line.data(), line.size(), 0);
return;
}

Expand All @@ -122,7 +118,7 @@ void run_command(std::wstring_view line) {
std::wstring cmd(cmd_end - non_space, '\0');
std::transform(non_space, cmd_end, cmd.begin(), &std::towlower);

commands.at(cmd)->operator()(line.data(), line.size(), cmd_end - line.begin());
commands.at(cmd)(line.data(), line.size(), cmd_end - line.begin());
}

#endif
Expand Down
3 changes: 1 addition & 2 deletions src/unrealsdk/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ extern const std::wstring NEXT_LINE;
* points to the first whitespace char after the command (or off the end of the
* string if there was none). 0 in the case of a `NEXT_LINE` match.
*/
using DLLSafeCallback = utils::DLLSafeCallback<void, const wchar_t*, size_t, size_t>;
using Callback = DLLSafeCallback::InnerFunc;
using Callback = std::function<void(const wchar_t*, size_t, size_t)>;

/**
* @brief Adds a custom console command.
Expand Down
51 changes: 24 additions & 27 deletions src/unrealsdk/hook_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@

using namespace unrealsdk::unreal;

namespace unrealsdk::hook_manager {

using DLLSafeCallback = utils::DLLSafeCallback<Callback>;

#pragma region Implementation
#ifndef UNREALSDK_IMPORTING
namespace unrealsdk::hook_manager::impl {
namespace impl {

/*
The fact that hooks run arbitrary user provided callbacks means our data structure can get modified
Expand Down Expand Up @@ -81,7 +85,7 @@ struct Node {
std::wstring full_name;
Type type;
std::wstring identifier;
DLLSafeCallback* callback;
DLLSafeCallback callback;

// Using shared pointers because it's easy
// Since we use std::make_shared, we're not really wasting allocations, but as a future
Expand All @@ -96,22 +100,12 @@ struct Node {
std::wstring_view full_name,
Type type,
std::wstring_view identifier,
DLLSafeCallback* callback)
DLLSafeCallback&& callback)
: fname(fname),
full_name(full_name),
type(type),
identifier(identifier),
callback(callback) {}
Node(const Node&) = default;
Node(Node&&) noexcept = default;
Node& operator=(const Node&) = default;
Node& operator=(Node&&) noexcept = default;
~Node() {
if (this->callback != nullptr) {
this->callback->destroy();
this->callback = nullptr;
}
}
callback(std::move(callback)) {}
};

namespace {
Expand Down Expand Up @@ -181,23 +175,24 @@ FName extract_func_obj_name(std::wstring_view func) {
bool add_hook(std::wstring_view func,
Type type,
std::wstring_view identifier,
DLLSafeCallback* callback) {
DLLSafeCallback&& callback) {
auto fname = extract_func_obj_name(func);

auto hash_idx = get_table_index(fname);
auto node = hooks_hash_table.at(hash_idx);
if (node == nullptr) {
// This function isn't in the hash table, can just add directly.
hooks_hash_table.at(hash_idx) =
std::make_shared<Node>(fname, func, type, identifier, callback);
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
return true;
}

// Look through hash collisions
while (node->fname != fname) {
if (node->next_collision == nullptr) {
// We found a collision, but nothing matched our name, so add it to the end
node->next_collision = std::make_shared<Node>(fname, func, type, identifier, callback);
node->next_collision =
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
return true;
}
node = node->next_collision;
Expand All @@ -207,7 +202,8 @@ bool add_hook(std::wstring_view func,
while (node->full_name != func) {
if (node->next_function == nullptr) {
// We found another function with the same fname, but nothing matches the full name
node->next_function = std::make_shared<Node>(fname, func, type, identifier, callback);
node->next_function =
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
return true;
}
node = node->next_function;
Expand All @@ -217,7 +213,8 @@ bool add_hook(std::wstring_view func,
while (node->type != type) {
if (node->next_type == nullptr) {
// We found the right function, but it doesn't have any hooks of this type yet
node->next_type = std::make_shared<Node>(fname, func, type, identifier, callback);
node->next_type =
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
return true;
}
node = node->next_type;
Expand All @@ -228,7 +225,7 @@ bool add_hook(std::wstring_view func,
if (node->next_in_collection == nullptr) {
// Didn't find a matching identifier, add our new hook at the end
node->next_in_collection =
std::make_shared<Node>(fname, func, type, identifier, callback);
std::make_shared<Node>(fname, func, type, identifier, std::move(callback));
}
node = node->next_in_collection;
}
Expand Down Expand Up @@ -503,7 +500,7 @@ bool run_hooks_of_type(std::shared_ptr<Node> node, Type type, Details& hook) {
bool ret = false;
for (; node != nullptr; node = node->next_in_collection) {
try {
ret |= node->callback->operator()(hook);
ret |= node->callback(hook);
} catch (const std::exception& ex) {
LOG(ERROR, "An exception occurred during hook processing");
LOG(ERROR, L"Function: {}", hook.func.func->get_path_name());
Expand All @@ -514,14 +511,13 @@ bool run_hooks_of_type(std::shared_ptr<Node> node, Type type, Details& hook) {
return ret;
}

} // namespace unrealsdk::hook_manager::impl
} // namespace impl
#endif
#pragma endregion

// =================================================================================================

#pragma region Public Interface
namespace unrealsdk::hook_manager {

#ifdef UNREALSDK_SHARED
UNREALSDK_CAPI(void, log_all_calls, bool should_log);
Expand Down Expand Up @@ -555,7 +551,7 @@ UNREALSDK_CAPI(bool,
Type type,
const wchar_t* identifier,
size_t identifier_size,
DLLSafeCallback* callback);
DLLSafeCallback&& callback);
#endif
#ifndef UNREALSDK_IMPORTING
UNREALSDK_CAPI(bool,
Expand All @@ -565,8 +561,9 @@ UNREALSDK_CAPI(bool,
Type type,
const wchar_t* identifier,
size_t identifier_size,
DLLSafeCallback* callback) {
return impl::add_hook({func, func_size}, type, {identifier, identifier_size}, callback);
DLLSafeCallback&& callback) {
return impl::add_hook({func, func_size}, type, {identifier, identifier_size},
std::move(callback));
}
#endif

Expand All @@ -576,7 +573,7 @@ bool add_hook(std::wstring_view func,
const Callback& callback) {
// NOLINTBEGIN(cppcoreguidelines-owning-memory)
return UNREALSDK_MANGLE(add_hook)(func.data(), func.size(), type, identifier.data(),
identifier.size(), new DLLSafeCallback(callback));
identifier.size(), {callback});
// NOLINTEND(cppcoreguidelines-owning-memory)
}

Expand Down
3 changes: 1 addition & 2 deletions src/unrealsdk/hook_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ struct Details {
* will not be run.
* In post-hooks: ignored.
*/
using DLLSafeCallback = utils::DLLSafeCallback<bool, Details&>;
using Callback = DLLSafeCallback::InnerFunc;
using Callback = std::function<bool(Details&)>;

/**
* @brief Toggles logging all unreal function calls. Best used in short bursts for debugging.
Expand Down
Loading