Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added 'RegisterHookFromBP' and 'UnregisterHookFromBP' for BP Mods #421

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 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
4 changes: 4 additions & 0 deletions UE4SS/include/LuaType/LuaUFunction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <LuaMadeSimple/LuaMadeSimple.hpp>
#include <LuaType/LuaUObject.hpp>
#include <LuaType/LuaUStruct.hpp>

namespace RC::Unreal
{
Expand Down Expand Up @@ -45,6 +46,9 @@ namespace RC::LuaType
};
class UFunction : public UObjectBase<Unreal::UFunction, UFunctionName>
{
public:
using Super = UStruct;

private:
// This is the 'this' pointer for this UFunction
Unreal::UObject* m_base{};
Expand Down
39 changes: 39 additions & 0 deletions UE4SS/include/LuaType/LuaXNumericProperty.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <LuaType/LuaXProperty.hpp>

namespace RC::Unreal
{
class FNumericProperty;
}

namespace RC::LuaType
{
struct FNumericPropertyName
{
constexpr static const char* ToString()
{
return "NumericProperty";
}
};
class XNumericProperty : public RemoteObjectBase<Unreal::FNumericProperty, FNumericPropertyName>
{
public:
using Super = XProperty;

private:
explicit XNumericProperty(Unreal::FNumericProperty* object);

public:
XNumericProperty() = delete;
auto static construct(const LuaMadeSimple::Lua&, Unreal::FNumericProperty*) -> const LuaMadeSimple::Lua::Table;
auto static construct(const LuaMadeSimple::Lua&, BaseObject&) -> const LuaMadeSimple::Lua::Table;

private:
auto static setup_metamethods(BaseObject&) -> void;

private:
template <LuaMadeSimple::Type::IsFinal is_final>
auto static setup_member_functions(const LuaMadeSimple::Lua::Table&) -> void;
};
} // namespace RC::LuaType
2 changes: 2 additions & 0 deletions UE4SS/src/LuaType/LuaUFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ namespace RC::LuaType
template <LuaMadeSimple::Type::IsFinal is_final>
auto UFunction::setup_member_functions(const LuaMadeSimple::Lua::Table& table) -> void
{
Super::setup_member_functions<LuaMadeSimple::Type::IsFinal::No>(table);

table.add_pair("GetFunctionFlags", [](const LuaMadeSimple::Lua& lua) -> int {
const auto& lua_object = lua.get_userdata<LuaType::UFunction>();
lua.set_integer(lua_object.get_remote_cpp_object()->GetFunctionFlags());
Expand Down
76 changes: 76 additions & 0 deletions UE4SS/src/LuaType/LuaXNumericProperty.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <LuaType/LuaUClass.hpp>
#include <LuaType/LuaUObject.hpp>
#include <LuaType/LuaXNumericProperty.hpp>
#pragma warning(disable : 4005)
#include <Unreal/Property/FNumericProperty.hpp>
#pragma warning(default : 4005)

namespace RC::LuaType
{
XNumericProperty::XNumericProperty(Unreal::FNumericProperty* object) : RemoteObjectBase<Unreal::FNumericProperty, FNumericPropertyName>(object)
{
}

auto XNumericProperty::construct(const LuaMadeSimple::Lua& lua, Unreal::FNumericProperty* unreal_object) -> const LuaMadeSimple::Lua::Table
{
LuaType::XNumericProperty lua_object{unreal_object};

auto metatable_name = ClassName::ToString();

LuaMadeSimple::Lua::Table table = lua.get_metatable(metatable_name);
if (lua.is_nil(-1))
{
lua.discard_value(-1);
LuaMadeSimple::Type::RemoteObject<Unreal::FNumericProperty>::construct(lua, lua_object);
setup_metamethods(lua_object);
setup_member_functions<LuaMadeSimple::Type::IsFinal::Yes>(table);
lua.new_metatable<LuaType::XNumericProperty>(metatable_name, lua_object.get_metamethods());
}

// Create object & surrender ownership to Lua
lua.transfer_stack_object(std::move(lua_object), metatable_name, lua_object.get_metamethods());

return table;
}

auto XNumericProperty::construct(const LuaMadeSimple::Lua& lua, BaseObject& construct_to) -> const LuaMadeSimple::Lua::Table
{
LuaMadeSimple::Lua::Table table = LuaMadeSimple::Type::RemoteObject<Unreal::FNumericProperty>::construct(lua, construct_to);

setup_member_functions<LuaMadeSimple::Type::IsFinal::No>(table);

setup_metamethods(construct_to);

return table;
}

auto XNumericProperty::setup_metamethods([[maybe_unused]] BaseObject& base_object) -> void
{
// XNumericProperty has no metamethods
}

template <LuaMadeSimple::Type::IsFinal is_final>
auto XNumericProperty::setup_member_functions(const LuaMadeSimple::Lua::Table& table) -> void
{
Super::setup_member_functions<LuaMadeSimple::Type::IsFinal::No>(table);

table.add_pair("IsFloatingPoint", [](const LuaMadeSimple::Lua& lua) -> int {
const auto& lua_object = lua.get_userdata<XNumericProperty>();
lua.set_bool(lua_object.get_remote_cpp_object()->IsFloatingPoint());
return 1;
});


if constexpr (is_final == LuaMadeSimple::Type::IsFinal::Yes)
{
table.add_pair("type", [](const LuaMadeSimple::Lua& lua) -> int {
lua.set_string(ClassName::ToString());
return 1;
});

// If this is the final object then we also want to finalize creating the table
// If not then it's the responsibility of the overriding object to call 'make_global()'
// table.make_global(ClassName::ToString());
}
}
} // namespace RC::LuaType
48 changes: 48 additions & 0 deletions UE4SS/src/LuaType/LuaXProperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
#include <LuaType/LuaXObjectProperty.hpp>
#include <LuaType/LuaXProperty.hpp>
#include <LuaType/LuaXStructProperty.hpp>
#include <LuaType/LuaXNumericProperty.hpp>
#pragma warning(disable : 4005)
#include <Unreal/FProperty.hpp>
#include <Unreal/Property/FArrayProperty.hpp>
#include <Unreal/Property/FBoolProperty.hpp>
#include <Unreal/Property/FEnumProperty.hpp>
#include <Unreal/Property/FObjectProperty.hpp>
#include <Unreal/Property/FStructProperty.hpp>
#include <Unreal/Property/FNumericProperty.hpp>
#pragma warning(default : 4005)

namespace RC::LuaType
Expand Down Expand Up @@ -45,6 +47,10 @@ namespace RC::LuaType
{
XArrayProperty::construct(lua, as_array_property);
}
else if (auto* as_numeric_property = Unreal::CastField<Unreal::FNumericProperty>(property); as_numeric_property)
{
XNumericProperty::construct(lua, as_numeric_property);
}
else
{
XProperty::construct(lua, property);
Expand Down Expand Up @@ -137,6 +143,42 @@ namespace RC::LuaType
return 1;
});

table.add_pair("HasAnyPropertyFlags", [](const LuaMadeSimple::Lua& lua) -> int {
std::string error_overload_not_found{R"(
No overload found for function 'Property.HasAnyPropertyFlags'.
Overloads:
#1: HasAnyPropertyFlags(EPropertyFlags PropertyFlags))"};

const auto& lua_object = lua.get_userdata<SelfType>();

if (!lua.is_integer())
{
lua.throw_error(error_overload_not_found);
}

Unreal::EPropertyFlags object_flags = static_cast<Unreal::EPropertyFlags>(lua.get_integer());
lua.set_bool(lua_object.get_remote_cpp_object()->HasAnyPropertyFlags(object_flags));
return 1;
});

table.add_pair("HasAllPropertyFlags", [](const LuaMadeSimple::Lua& lua) -> int {
std::string error_overload_not_found{R"(
No overload found for function 'Property.HasAllPropertyFlags'.
Overloads:
#1: HasAllPropertyFlags(EPropertyFlags PropertyFlags))"};

const auto& lua_object = lua.get_userdata<SelfType>();

if (!lua.is_integer())
{
lua.throw_error(error_overload_not_found);
}

Unreal::EPropertyFlags object_flags = static_cast<Unreal::EPropertyFlags>(lua.get_integer());
lua.set_bool(lua_object.get_remote_cpp_object()->HasAllPropertyFlags(object_flags));
return 1;
});

table.add_pair("IsA", [](const LuaMadeSimple::Lua& lua) -> int {
std::string error_overload_not_found{R"(
No overload found for function 'IsA'.
Expand Down Expand Up @@ -178,6 +220,12 @@ No overload found for function 'IsA'.
}
return 1;
}
else if (lua.is_userdata()) // FFieldClass, returned from Property:GetClass()
{
auto ffield_class = lua.get_userdata<LuaType::XFieldClass>();
lua.set_bool(lua_object.get_remote_cpp_object()->IsA(ffield_class.get_local_cpp_object()));
return 1;
}
else
{
lua.throw_error(error_overload_not_found);
Expand Down
82 changes: 82 additions & 0 deletions UE4SS/src/Mod/LuaMod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,86 @@ namespace RC
object_internal_flags_table.make_global("EInternalObjectFlags");
}

static auto register_property_flags(const LuaMadeSimple::Lua& lua) -> void
{
LuaMadeSimple::Lua::Table property_flags_table = lua.prepare_new_table();
property_flags_table.add_pair("CPF_None", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_None));
property_flags_table.add_pair("CPF_Edit", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Edit));
property_flags_table.add_pair("CPF_ConstParm", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_ConstParm));
property_flags_table.add_pair("CPF_BlueprintVisible",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_BlueprintVisible));
property_flags_table.add_pair("CPF_ExportObject", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_ExportObject));
property_flags_table.add_pair("CPF_BlueprintReadOnly",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_BlueprintReadOnly));
property_flags_table.add_pair("CPF_Net", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Net));
property_flags_table.add_pair("CPF_EditFixedSize", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_EditFixedSize));
property_flags_table.add_pair("CPF_Parm", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Parm));
property_flags_table.add_pair("CPF_OutParm", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_OutParm));
property_flags_table.add_pair("CPF_ZeroConstructor",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_ZeroConstructor));
property_flags_table.add_pair("CPF_ReturnParm", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_ReturnParm));
property_flags_table.add_pair("CPF_DisableEditOnTemplate",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_DisableEditOnTemplate));
property_flags_table.add_pair("CPF_Transient", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Transient));
property_flags_table.add_pair("CPF_Config", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Config));
property_flags_table.add_pair("CPF_DisableEditOnInstance",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_DisableEditOnInstance));
property_flags_table.add_pair("CPF_EditConst", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_EditConst));
property_flags_table.add_pair("CPF_GlobalConfig", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_GlobalConfig));
property_flags_table.add_pair("CPF_InstancedReference",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_InstancedReference));
property_flags_table.add_pair("CPF_DuplicateTransient",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_DuplicateTransient));
property_flags_table.add_pair("CPF_SaveGame", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_SaveGame));
property_flags_table.add_pair("CPF_NoClear", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_NoClear));
property_flags_table.add_pair("CPF_ReferenceParm", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_ReferenceParm));
property_flags_table.add_pair("CPF_BlueprintAssignable",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_BlueprintAssignable));
property_flags_table.add_pair("CPF_Deprecated", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Deprecated));
property_flags_table.add_pair("CPF_IsPlainOldData",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_IsPlainOldData));
property_flags_table.add_pair("CPF_RepSkip", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_RepSkip));
property_flags_table.add_pair("CPF_RepNotify", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_RepNotify));
property_flags_table.add_pair("CPF_Interp", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Interp));
property_flags_table.add_pair("CPF_NonTransactional",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_NonTransactional));
property_flags_table.add_pair("CPF_EditorOnly", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_EditorOnly));
property_flags_table.add_pair("CPF_NoDestructor", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_NoDestructor));
property_flags_table.add_pair("CPF_AutoWeak", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_AutoWeak));
property_flags_table.add_pair("CPF_ContainsInstancedReference",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_ContainsInstancedReference));
property_flags_table.add_pair("CPF_AssetRegistrySearchable",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_AssetRegistrySearchable));
property_flags_table.add_pair("CPF_SimpleDisplay", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_SimpleDisplay));
property_flags_table.add_pair("CPF_AdvancedDisplay",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_AdvancedDisplay));
property_flags_table.add_pair("CPF_Protected", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_Protected));
property_flags_table.add_pair("CPF_BlueprintCallable",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_BlueprintCallable));
property_flags_table.add_pair("CPF_BlueprintAuthorityOnly",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_BlueprintAuthorityOnly));
property_flags_table.add_pair("CPF_TextExportTransient",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_TextExportTransient));
property_flags_table.add_pair("CPF_NonPIEDuplicateTransient",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_NonPIEDuplicateTransient));
property_flags_table.add_pair("CPF_ExposeOnSpawn", static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_ExposeOnSpawn));
property_flags_table.add_pair("CPF_PersistentInstance",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_PersistentInstance));
property_flags_table.add_pair("CPF_UObjectWrapper",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_UObjectWrapper));
property_flags_table.add_pair("CPF_HasGetValueTypeHash",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_HasGetValueTypeHash));
property_flags_table.add_pair("CPF_NativeAccessSpecifierPublic",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_NativeAccessSpecifierPublic));
property_flags_table.add_pair("CPF_NativeAccessSpecifierProtected",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_NativeAccessSpecifierProtected));
property_flags_table.add_pair("CPF_NativeAccessSpecifierPrivate",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_NativeAccessSpecifierPrivate));
property_flags_table.add_pair("CPF_SkipSerialization",
static_cast<std::underlying_type_t<Unreal::EPropertyFlags>>(Unreal::EPropertyFlags::CPF_SkipSerialization));
property_flags_table.make_global("EPropertyFlags");
}

static auto register_efindname(const LuaMadeSimple::Lua& lua) -> void
{
LuaMadeSimple::Lua::Table efindname_table = lua.prepare_new_table();
Expand Down Expand Up @@ -3300,6 +3380,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'.

register_all_property_types(lua);
register_object_flags(lua);
register_property_flags(lua);
register_efindname(lua);

lua.set_nil();
Expand Down Expand Up @@ -3449,6 +3530,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'.
register_input_globals(*LuaStatics::console_executor);
register_all_property_types(*LuaStatics::console_executor);
register_object_flags(*LuaStatics::console_executor);
register_property_flags(*LuaStatics::console_executor);
LuaStatics::console_executor_enabled = true;
};

Expand Down
3 changes: 3 additions & 0 deletions assets/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ TBD
### UHT Dumper

### Lua API
Implemented `NumericProperty`, and its `IsFloatingPoint` member function.

Implemented member functions `HasAnyPropertyFlags` and `HasAllPropertyFlags` for Property.

### C++ API

Expand Down
Loading