Skip to content

Commit

Permalink
Plugins: Add FName and further reflection functions
Browse files Browse the repository at this point in the history
Added FName::to_string, FField::get_fname and get_class
ADded UObject::get_fname
  • Loading branch information
praydog committed Feb 18, 2024
1 parent 81e7774 commit d1e0e26
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 16 deletions.
34 changes: 34 additions & 0 deletions examples/example_plugin/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ SOFTWARE.
#include <sstream>
#include <mutex>
#include <memory>
#include <locale>
#include <codecvt>

#include <Windows.h>

Expand Down Expand Up @@ -179,6 +181,38 @@ class ExamplePlugin : public uevr::Plugin {
API::get()->log_info("Running once on pre engine tick");
API::get()->execute_command(L"stat fps");

// Log the UEngine name.
const auto uengine_fname = engine->get_fname();
const auto uengine_name = uengine_fname->to_string();

// Convert from wide to narrow string (we do not have utility::narrow in this context).
std::string uengine_name_narrow{std::wstring_convert<std::codecvt_utf8<wchar_t>>{}.to_bytes(uengine_name)};

API::get()->log_info("Engine name: %s", uengine_name_narrow.c_str());

// Go through all of engine's fields and log their names.
const auto engine_class_ours = (API::UStruct*)engine->get_class();
for (auto super = engine_class_ours; super != nullptr; super = super->get_super()) {
for (auto field = super->get_child_properties(); field != nullptr; field = field->get_next()) {
const auto field_fname = field->get_fname();
const auto field_name = field_fname->to_string();
const auto field_class = field->get_class();

std::wstring prepend{};

if (field_class != nullptr) {
const auto field_class_fname = field_class->get_fname();
const auto field_class_name = field_class_fname->to_string();

prepend = field_class_name + L" ";
}

// Convert from wide to narrow string (we do not have utility::narrow in this context).
std::string field_name_narrow{std::wstring_convert<std::codecvt_utf8<wchar_t>>{}.to_bytes(prepend + field_name)};
API::get()->log_info(" Field name: %s", field_name_narrow.c_str());
}
}

// Check if we can find the GameInstance and call is_a() on it.
const auto game_instance = engine->get_property<API::UObject*>(L"GameInstance");

Expand Down
18 changes: 17 additions & 1 deletion include/uevr/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ SOFTWARE.
#define UEVR_OUT

#define UEVR_PLUGIN_VERSION_MAJOR 2
#define UEVR_PLUGIN_VERSION_MINOR 6
#define UEVR_PLUGIN_VERSION_MINOR 7
#define UEVR_PLUGIN_VERSION_PATCH 0

#define UEVR_RENDERER_D3D11 0
Expand Down Expand Up @@ -66,6 +66,8 @@ DECLARE_UEVR_HANDLE(UEVR_FPropertyHandle);
DECLARE_UEVR_HANDLE(UEVR_UStructHandle);
DECLARE_UEVR_HANDLE(UEVR_UClassHandle);
DECLARE_UEVR_HANDLE(UEVR_UFunctionHandle);
DECLARE_UEVR_HANDLE(UEVR_FNameHandle);
DECLARE_UEVR_HANDLE(UEVR_FFieldClassHandle);

// OpenXR stuff
DECLARE_UEVR_HANDLE(UEVR_XrInstance);
Expand Down Expand Up @@ -233,6 +235,8 @@ typedef struct {

typedef struct {
UEVR_FFieldHandle (*get_next)(UEVR_FFieldHandle field);
UEVR_FFieldClassHandle (*get_class)(UEVR_FFieldHandle field);
UEVR_FNameHandle (*get_fname)(UEVR_FFieldHandle field);
} UEVR_FFieldFunctions;

typedef struct {
Expand Down Expand Up @@ -263,6 +267,8 @@ typedef struct {

void (*process_event)(UEVR_UObjectHandle object, UEVR_UFunctionHandle function, void* params);
void (*call_function)(UEVR_UObjectHandle object, const wchar_t* name, void* params);

UEVR_FNameHandle (*get_fname)(UEVR_UObjectHandle object);
} UEVR_UObjectFunctions;

typedef struct {
Expand All @@ -278,6 +284,14 @@ typedef struct {
UEVR_UObjectHandle (*get_first_object_by_class_name)(const wchar_t* class_name, bool allow_default);
} UEVR_UObjectHookFunctions;

typedef struct {
UEVR_FNameHandle (*get_fname)(UEVR_FFieldClassHandle field_class);
} UEVR_FFieldClassFunctions;

typedef struct {
unsigned int (*to_string)(UEVR_FNameHandle name, wchar_t* buffer, unsigned int buffer_size);
} UEVR_FNameFunctions;

typedef struct {
const UEVR_SDKFunctions* functions;
const UEVR_SDKCallbacks* callbacks;
Expand All @@ -289,6 +303,8 @@ typedef struct {
const UEVR_UClassFunctions* uclass;
const UEVR_UFunctionFunctions* ufunction;
const UEVR_UObjectHookFunctions* uobject_hook;
const UEVR_FFieldClassFunctions* ffield_class;
const UEVR_FNameFunctions* fname;
} UEVR_SDKData;

DECLARE_UEVR_HANDLE(UEVR_IVRSystem);
Expand Down
55 changes: 45 additions & 10 deletions include/uevr/API.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class API {
struct FProperty;
struct FFieldClass;
struct FUObjectArray;
struct FName;

template<typename T = UObject>
T* find_uobject(std::wstring_view name) {
Expand Down Expand Up @@ -144,6 +145,33 @@ class API {
return (FUObjectArray*)fn();
}

struct FName {
inline UEVR_FNameHandle to_handle() { return (UEVR_FNameHandle)this; }
inline UEVR_FNameHandle to_handle() const { return (UEVR_FNameHandle)this; }

std::wstring to_string() const {
static const auto fn = initialize()->to_string;
const auto size = fn(to_handle(), nullptr, 0);
if (size == 0) {
return L"";
}

std::wstring result(size, L'\0');
fn(to_handle(), result.data(), size + 1);
return result;
}

private:
static inline const UEVR_FNameFunctions* s_functions{nullptr};
static inline const UEVR_FNameFunctions* initialize() {
if (s_functions == nullptr) {
s_functions = API::get()->sdk()->fname;
}

return s_functions;
}
};

struct UObject {
inline UEVR_UObjectHandle to_handle() { return (UEVR_UObjectHandle)this; }
inline UEVR_UObjectHandle to_handle() const { return (UEVR_UObjectHandle)this; }
Expand Down Expand Up @@ -202,6 +230,11 @@ class API {
return *get_property_data<T>(name);
}

FName* get_fname() const {
static const auto fn = initialize()->get_fname;
return (FName*)fn(to_handle());
}

private:
static inline const UEVR_UObjectFunctions* s_functions{nullptr};
inline static const UEVR_UObjectFunctions* initialize() {
Expand Down Expand Up @@ -355,17 +388,16 @@ class API {
static const auto fn = initialize()->get_next;
return (FField*)fn(to_handle());
}

// TODO: stubbed out for now
/*
inline std::wstring get_name() const {
FName* get_fname() const {
static const auto fn = initialize()->get_fname;
return (FName*)fn(to_handle());
}

FFieldClass* get_class() const {
static const auto fn = initialize()->get_class;
return (FFieldClass*)fn(to_handle());
}
*/

private:
static inline const UEVR_FFieldFunctions* s_functions{nullptr};
Expand Down Expand Up @@ -401,24 +433,27 @@ class API {

struct FFieldClass {
// TODO: stubbed out for now
/*inline UEVR_FFieldClassHandle to_handle() { return (UEVR_FFieldClassHandle)this; }
inline UEVR_FFieldClassHandle to_handle() { return (UEVR_FFieldClassHandle)this; }
inline UEVR_FFieldClassHandle to_handle() const { return (UEVR_FFieldClassHandle)this; }

FName* get_fname() const {
static const auto fn = initialize()->get_fname;
return (FName*)fn(to_handle());
}

std::wstring get_name() const {
static const auto fn = initialize()->get_name;
return fn(to_handle());
return get_fname()->to_string();
}

private:
static inline const UEVR_FFieldClassFunctions* s_functions{nullptr};
static inline const UEVR_FFieldClassFunctions* initialize() {
if (s_functions == nullptr) {
s_functions = API::get()->sdk()->ffieldclass;
s_functions = API::get()->sdk()->ffield_class;
}

return s_functions;
}
*/
};

// TODO
Expand Down
2 changes: 1 addition & 1 deletion src/CommitHash.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#define UEVR_COMMIT_HASH "efd4c133d1ab679f1b72cea18d17f53e91869821"
#define UEVR_COMMIT_HASH "81e77749037bd11ab11d84c9598901fc36e6b9b7"
#define UEVR_BUILD_DATE "17.02.2024"
#define UEVR_BUILD_TIME "00:00"
51 changes: 47 additions & 4 deletions src/mods/PluginLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ UEVR_UObjectFunctions g_uobject_functions {
[](UEVR_UObjectHandle obj, const wchar_t* name, void* params) {
UOBJECT(obj)->call_function(name, params);
},
// get_fname
[](UEVR_UObjectHandle obj) {
return (UEVR_FNameHandle)&UOBJECT(obj)->get_fname();
},
};

UEVR_UObjectArrayFunctions g_uobject_array_functions {
Expand All @@ -355,6 +359,14 @@ UEVR_FFieldFunctions g_ffield_functions {
[](UEVR_FFieldHandle field) {
return (UEVR_FFieldHandle)FFIELD(field)->get_next();
},
// get_class
[](UEVR_FFieldHandle field) {
return (UEVR_FFieldClassHandle)FFIELD(field)->get_class();
},
// get_fname
[](UEVR_FFieldHandle field) {
return (UEVR_FNameHandle)&FFIELD(field)->get_field_name();
},
};

#define FPROPERTY(x) ((sdk::FProperty*)x)
Expand Down Expand Up @@ -489,6 +501,35 @@ UEVR_UObjectHookFunctions g_uobjecthook_functions {
uevr::uobjecthook::get_first_object_by_class_name
};

#define FFIELDCLASS(x) ((sdk::FFieldClass*)x)

UEVR_FFieldClassFunctions g_ffield_class_functions {
// get_fname
[](UEVR_FFieldClassHandle field) {
return (UEVR_FNameHandle)&FFIELDCLASS(field)->get_name();
},
};

#define FNAME(x) ((sdk::FName*)x)

UEVR_FNameFunctions g_fname_functions {
// to_string
[](UEVR_FNameHandle name, wchar_t* buffer, unsigned int buffer_size) -> unsigned int {
const auto result = FNAME(name)->to_string();

if (buffer == nullptr || buffer_size == 0) {
return (unsigned int)result.size();
}

const auto size = std::min<size_t>(result.size(), (size_t)buffer_size - 1);

memcpy(buffer, result.c_str(), size * sizeof(wchar_t));
buffer[size] = L'\0';

return (unsigned int)size;
},
};

UEVR_SDKData g_sdk_data {
&g_sdk_functions,
&g_sdk_callbacks,
Expand All @@ -499,7 +540,9 @@ UEVR_SDKData g_sdk_data {
&g_ustruct_functions,
&g_uclass_functions,
&g_ufunction_functions,
&g_uobjecthook_functions
&g_uobjecthook_functions,
&g_ffield_class_functions,
&g_fname_functions,
};

namespace uevr {
Expand Down Expand Up @@ -922,11 +965,11 @@ void PluginLoader::early_init() try {
namespace fs = std::filesystem;

std::scoped_lock _{m_mux};
std::string module_path{};
std::wstring module_path{};

module_path.resize(1024, 0);
module_path.resize(GetModuleFileName(nullptr, module_path.data(), module_path.size()));
spdlog::info("[PluginLoader] Module path {}", module_path);
module_path.resize(GetModuleFileNameW(nullptr, module_path.data(), module_path.size()));
spdlog::info("[PluginLoader] Module path {}", utility::narrow(module_path));

const auto plugin_path = Framework::get_persistent_dir() / "plugins";

Expand Down

0 comments on commit d1e0e26

Please sign in to comment.