From ae2a969985fce10cd4c20f3273135e7432854926 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 5 Feb 2024 14:06:10 -0600 Subject: [PATCH 001/213] port to linux, build only --- .vscode/settings.json | 107 ++ UE4SS/generated_include/MacroSetter.hpp | 908 ++++----- UE4SS/include/Common.hpp | 11 + UE4SS/include/ExceptionHandling.hpp | 2 +- UE4SS/include/LuaCustomMemberFunctions.hpp | 7 +- UE4SS/include/LuaType/LuaCustomProperty.hpp | 10 +- UE4SS/include/LuaType/LuaUObject.hpp | 18 +- UE4SS/include/Mod/CppMod.hpp | 19 +- UE4SS/include/Mod/CppUserModBase.hpp | 33 +- UE4SS/include/Mod/LuaMod.hpp | 10 +- UE4SS/include/Mod/Mod.hpp | 8 +- UE4SS/include/ObjectDumper/ObjectToString.hpp | 44 +- UE4SS/include/Platform.hpp | 5 + UE4SS/include/SDKGenerator/Common.hpp | 18 +- UE4SS/include/SDKGenerator/JSONDumper.hpp | 2 +- .../include/SDKGenerator/TMapOverrideGen.hpp | 4 +- .../SDKGenerator/UEHeaderGenerator.hpp | 187 +- UE4SS/include/SettingsManager.hpp | 6 + UE4SS/include/Signatures.hpp | 2 +- UE4SS/include/UE4SSProgram.hpp | 110 +- UE4SS/include/USMapGenerator/writer.h | 6 +- UE4SS/src/EntryLinux.cpp | 69 + ...ain_ue4ss_rewritten.cpp => EntryWin32.cpp} | 17 +- UE4SS/src/GUI/BPMods.cpp | 2 +- UE4SS/src/GUI/Console.cpp | 4 +- UE4SS/src/GUI/Dumpers.cpp | 34 +- UE4SS/src/GUI/GUI.cpp | 2 +- UE4SS/src/GUI/LiveView.cpp | 61 +- UE4SS/src/GUI/SearcherWidget.cpp | 4 +- UE4SS/src/GUI/UFunctionCallerWidget.cpp | 20 +- UE4SS/src/LuaLibrary.cpp | 88 +- UE4SS/src/LuaType/LuaCustomProperty.cpp | 6 +- UE4SS/src/LuaType/LuaFName.cpp | 6 +- UE4SS/src/LuaType/LuaFOutputDevice.cpp | 2 +- UE4SS/src/LuaType/LuaFString.cpp | 2 +- UE4SS/src/LuaType/LuaFText.cpp | 6 +- UE4SS/src/LuaType/LuaTArray.cpp | 2 +- UE4SS/src/LuaType/LuaUClass.cpp | 2 +- UE4SS/src/LuaType/LuaUEnum.cpp | 11 +- UE4SS/src/LuaType/LuaUObject.cpp | 8 +- UE4SS/src/LuaType/LuaUScriptStruct.cpp | 2 +- UE4SS/src/LuaType/LuaUWorld.cpp | 4 +- UE4SS/src/LuaType/LuaXProperty.cpp | 10 +- UE4SS/src/Mod/CppMod.cpp | 38 +- UE4SS/src/Mod/CppUserModBase.cpp | 6 +- UE4SS/src/Mod/LuaMod.cpp | 261 +-- UE4SS/src/Mod/Mod.cpp | 4 +- UE4SS/src/ObjectDumper/ObjectToString.cpp | 94 +- UE4SS/src/SDKGenerator/Common.cpp | 311 +-- UE4SS/src/SDKGenerator/Generator.cpp | 220 +-- UE4SS/src/SDKGenerator/JSONDumper.cpp | 80 +- UE4SS/src/SDKGenerator/TMapOverrideGen.cpp | 24 +- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 1663 +++++++++-------- UE4SS/src/SettingsManager.cpp | 41 +- UE4SS/src/Signatures.cpp | 38 +- UE4SS/src/UE4SSProgram.cpp | 543 +++--- UE4SS/src/USMapGenerator/Generator.cpp | 12 +- UVTD/include/UVTD/ExceptionHandling.hpp | 2 +- UVTD/include/UVTD/Symbols.hpp | 6 +- UVTD/src/MemberVarsDumper.cpp | 12 +- UVTD/src/MemberVarsWrapperGenerator.cpp | 10 +- UVTD/src/SolBindingsGenerator.cpp | 4 +- UVTD/src/Symbols.cpp | 4 +- UVTD/src/UVTD.cpp | 6 +- UVTD/src/UnrealVirtualGenerator.cpp | 8 +- UVTD/src/VTableDumper.cpp | 16 +- UVTD/src/main.cpp | 24 +- cmake/Findzydis.cmake | 1 + .../ASMHelper/include/ASMHelper/Common.hpp | 10 + deps/first/ASMHelper/src/ASMHelper.cpp | 12 +- .../include/Constructs/Annotated.hpp | 2 +- .../include/Constructs/Generator.hpp | 2 +- .../include/DynamicOutput/Common.hpp | 10 + .../DynamicOutput/DebugConsoleDevice.hpp | 3 +- .../include/DynamicOutput/Output.hpp | 12 +- .../include/DynamicOutput/TestDevice.hpp | 4 +- .../DynamicOutput/src/DebugConsoleDevice.cpp | 9 +- deps/first/DynamicOutput/src/OutputDevice.cpp | 4 +- deps/first/File/include/File/Common.hpp | 10 + deps/first/File/include/File/FileDef.hpp | 15 +- deps/first/File/include/File/FileType/All.hpp | 5 +- .../File/include/File/FileType/StdFile.hpp | 87 + deps/first/File/include/File/Macros.hpp | 63 +- deps/first/File/src/FileType/StdFile.cpp | 516 +++++ .../first/Helpers/include/Helpers/Casting.hpp | 43 + deps/first/Helpers/include/Helpers/Format.hpp | 34 + deps/first/Helpers/include/Helpers/String.hpp | 114 +- .../IniParser/include/IniParser/Common.hpp | 10 + .../include/IniParser/Experimental.hpp | 48 +- .../first/IniParser/include/IniParser/Ini.hpp | 30 +- .../IniParser/include/IniParser/JSON.hpp | 50 +- .../IniParser/include/IniParser/Section.hpp | 6 +- .../include/IniParser/TokenParser.hpp | 14 +- .../IniParser/include/IniParser/Value.hpp | 10 +- deps/first/IniParser/src/Experimental.cpp | 104 +- deps/first/IniParser/src/Ini.cpp | 46 +- deps/first/IniParser/src/JSON.cpp | 46 +- deps/first/IniParser/src/TokenParser.cpp | 75 +- deps/first/IniParser/src/Value.cpp | 8 +- deps/first/JSON/include/JSON/Array.hpp | 4 +- deps/first/JSON/include/JSON/Bool.hpp | 2 +- deps/first/JSON/include/JSON/Common.hpp | 14 +- deps/first/JSON/include/JSON/KeyValuePair.hpp | 20 +- deps/first/JSON/include/JSON/Null.hpp | 2 +- deps/first/JSON/include/JSON/Number.hpp | 2 +- deps/first/JSON/include/JSON/Object.hpp | 30 +- .../first/JSON/include/JSON/Parser/Parser.hpp | 2 +- .../JSON/include/JSON/Parser/TokenParser.hpp | 6 +- deps/first/JSON/include/JSON/String.hpp | 10 +- deps/first/JSON/include/JSON/Value.hpp | 2 +- deps/first/JSON/src/Array.cpp | 20 +- deps/first/JSON/src/Bool.cpp | 4 +- deps/first/JSON/src/Null.cpp | 4 +- deps/first/JSON/src/Number.cpp | 2 +- deps/first/JSON/src/Object.cpp | 36 +- deps/first/JSON/src/Parser/Parser.cpp | 14 +- deps/first/JSON/src/Parser/TokenParser.cpp | 10 +- deps/first/JSON/src/String.cpp | 6 +- .../include/LuaMadeSimple/Common.hpp | 11 + .../include/LuaMadeSimple/LuaMadeSimple.hpp | 20 +- .../first/LuaMadeSimple/src/LuaMadeSimple.cpp | 6 +- deps/first/LuaRaw/src/luauser.c | 36 +- deps/first/MProgram/include/ErrorObject.hpp | 6 + .../ParserBase/include/ParserBase/Common.hpp | 10 + .../ParserBase/include/ParserBase/Token.hpp | 26 +- .../include/ParserBase/TokenParser.hpp | 6 +- .../include/ParserBase/Tokenizer.hpp | 2 +- deps/first/ParserBase/src/Token.cpp | 8 +- deps/first/ParserBase/src/TokenParser.cpp | 4 +- deps/first/ParserBase/src/Tokenizer.cpp | 16 +- .../include/SigScanner/Common.hpp | 11 + .../include/SigScanner/Linux/DLData.hpp | 26 + .../SigScanner/SinglePassSigScanner.hpp | 346 +--- .../SigScanner/SinglePassSigScannerLinux.hpp | 336 ++++ .../SigScanner/SinglePassSigScannerWin32.hpp | 352 ++++ .../src/SinglePassSigScannerLinux.cpp | 820 ++++++++ ...nner.cpp => SinglePassSigScannerWin32.cpp} | 19 +- deps/first/Unreal | 2 +- deps/first/patternsleuth | 2 +- deps/first/patternsleuth_bind/Cargo.lock | 40 + .../packages/p/polyhook_2/CMakeLists.txt | 33 - deps/third/DynoHook/00-compilebugs.patch | 61 + 142 files changed, 5883 insertions(+), 3215 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 UE4SS/include/Platform.hpp create mode 100644 UE4SS/src/EntryLinux.cpp rename UE4SS/src/{main_ue4ss_rewritten.cpp => EntryWin32.cpp} (89%) create mode 100644 cmake/Findzydis.cmake create mode 100644 deps/first/File/include/File/FileType/StdFile.hpp create mode 100644 deps/first/File/src/FileType/StdFile.cpp create mode 100644 deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp create mode 100644 deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp create mode 100644 deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp create mode 100644 deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp rename deps/first/SinglePassSigScanner/src/{SinglePassSigScanner.cpp => SinglePassSigScannerWin32.cpp} (99%) delete mode 100644 deps/third-repo/packages/p/polyhook_2/CMakeLists.txt create mode 100644 deps/third/DynoHook/00-compilebugs.patch diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..3fdcaf704 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,107 @@ +{ + "files.associations": { + "*.S": "gas", + "tuple": "cpp", + "compare": "cpp", + "cstdint": "cpp", + "*.tcc": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "optional": "cpp", + "variant": "cpp", + "array": "cpp", + "chrono": "cpp", + "string": "cpp", + "string_view": "cpp", + "format": "cpp", + "initializer_list": "cpp", + "ranges": "cpp", + "span": "cpp", + "regex": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "cinttypes": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "coroutine": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "map": "cpp", + "set": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "ratio": "cpp", + "source_location": "cpp", + "system_error": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "typeinfo": "cpp", + "any": "cpp", + "cfenv": "cpp", + "expected": "cpp", + "*.inc": "cpp", + "complex": "cpp", + "forward_list": "cpp", + "valarray": "cpp", + "__bit_reference": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__node_handle": "cpp", + "__split_buffer": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__verbose_abort": "cpp", + "execution": "cpp", + "ios": "cpp", + "locale": "cpp", + "print": "cpp", + "queue": "cpp", + "stack": "cpp", + "typeindex": "cpp" + }, + "C_Cpp.default.compileCommands": "build/compile_commands.json", + "cmake.buildTask": true, + "rust-analyzer.linkedProjects": [ + "/home/yangff/Project/RE-UE4SS/deps/first/patternsleuth/Cargo.toml" + ], + "cmake.generator": "Ninja" +} \ No newline at end of file diff --git a/UE4SS/generated_include/MacroSetter.hpp b/UE4SS/generated_include/MacroSetter.hpp index c776ad2ec..d041d9aaf 100644 --- a/UE4SS/generated_include/MacroSetter.hpp +++ b/UE4SS/generated_include/MacroSetter.hpp @@ -1,892 +1,892 @@ -if (auto val = parser.get_int64(STR("UObjectBase"), STR("Class"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("Class"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("Class"), static_cast(val)); -if (auto val = parser.get_int64(STR("UObjectBase"), STR("ClassPrivate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("ClassPrivate"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("ClassPrivate"), static_cast(val)); -if (auto val = parser.get_int64(STR("UObjectBase"), STR("InternalIndex"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("InternalIndex"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("InternalIndex"), static_cast(val)); -if (auto val = parser.get_int64(STR("UObjectBase"), STR("Name"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("Name"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("Name"), static_cast(val)); -if (auto val = parser.get_int64(STR("UObjectBase"), STR("NamePrivate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("NamePrivate"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("NamePrivate"), static_cast(val)); -if (auto val = parser.get_int64(STR("UObjectBase"), STR("ObjectFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("ObjectFlags"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("ObjectFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("UObjectBase"), STR("Outer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("Outer"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("Outer"), static_cast(val)); -if (auto val = parser.get_int64(STR("UObjectBase"), STR("OuterPrivate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UObjectBase"), SYSSTR("OuterPrivate"), -1); val != -1) Unreal::UObjectBase::MemberOffsets.emplace(STR("OuterPrivate"), static_cast(val)); -if (auto val = parser.get_int64(STR("UScriptStruct::ICppStructOps"), STR("Alignment"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UScriptStruct::ICppStructOps"), SYSSTR("Alignment"), -1); val != -1) Unreal::UScriptStruct::ICppStructOps::MemberOffsets.emplace(STR("Alignment"), static_cast(val)); -if (auto val = parser.get_int64(STR("UScriptStruct::ICppStructOps"), STR("Size"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UScriptStruct::ICppStructOps"), SYSSTR("Size"), -1); val != -1) Unreal::UScriptStruct::ICppStructOps::MemberOffsets.emplace(STR("Size"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("ArrayDim"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("ArrayDim"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("ArrayDim"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("DestructorLinkNext"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("DestructorLinkNext"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("DestructorLinkNext"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("ElementSize"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("ElementSize"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("ElementSize"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("NextRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("NextRef"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("NextRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("Offset_Internal"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("Offset_Internal"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("Offset_Internal"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("PostConstructLinkNext"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("PostConstructLinkNext"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("PostConstructLinkNext"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("PropertyFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("PropertyFlags"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("PropertyFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("PropertyLinkNext"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("PropertyLinkNext"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("PropertyLinkNext"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("RepIndex"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("RepIndex"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("RepIndex"), static_cast(val)); -if (auto val = parser.get_int64(STR("FProperty"), STR("RepNotifyFunc"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FProperty"), SYSSTR("RepNotifyFunc"), -1); val != -1) Unreal::FProperty::MemberOffsets.emplace(STR("RepNotifyFunc"), static_cast(val)); -if (auto val = parser.get_int64(STR("FSoftClassProperty"), STR("MetaClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FSoftClassProperty"), SYSSTR("MetaClass"), -1); val != -1) Unreal::FSoftClassProperty::MemberOffsets.emplace(STR("MetaClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("DefaultPlayerName"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("DefaultPlayerName"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("DefaultPlayerName"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("GameSession"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("GameSession"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("GameSession"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("GameSessionClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("GameSessionClass"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("GameSessionClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("HUDClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("HUDClass"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("HUDClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("OptionsString"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("OptionsString"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("OptionsString"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("PlayerStateClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("PlayerStateClass"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("PlayerStateClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("ServerStatReplicator"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("ServerStatReplicator"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("ServerStatReplicator"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("ServerStatReplicatorClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("ServerStatReplicatorClass"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("ServerStatReplicatorClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("SpectatorClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("SpectatorClass"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("SpectatorClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("bPauseable"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("bPauseable"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("bPauseable"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("bStartPlayersAsSpectators"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("bStartPlayersAsSpectators"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("bStartPlayersAsSpectators"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameModeBase"), STR("bUseSeamlessTravel"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameModeBase"), SYSSTR("bUseSeamlessTravel"), -1); val != -1) Unreal::AGameModeBase::MemberOffsets.emplace(STR("bUseSeamlessTravel"), static_cast(val)); -if (auto val = parser.get_int64(STR("FOutputDevice"), STR("bAutoEmitLineTerminator"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FOutputDevice"), SYSSTR("bAutoEmitLineTerminator"), -1); val != -1) Unreal::FOutputDevice::MemberOffsets.emplace(STR("bAutoEmitLineTerminator"), static_cast(val)); -if (auto val = parser.get_int64(STR("FOutputDevice"), STR("bSuppressEventTag"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FOutputDevice"), SYSSTR("bSuppressEventTag"), -1); val != -1) Unreal::FOutputDevice::MemberOffsets.emplace(STR("bSuppressEventTag"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("EventGraphCallOffset"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("EventGraphCallOffset"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("EventGraphCallOffset"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("EventGraphFunction"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("EventGraphFunction"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("EventGraphFunction"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("FirstPropertyToInit"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("FirstPropertyToInit"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("FirstPropertyToInit"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("Func"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("Func"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("FunctionFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("Func"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("Func"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("FunctionFlags"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("FunctionFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("NumParms"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("NumParms"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("NumParms"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("ParmsSize"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("ParmsSize"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("ParmsSize"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("RPCId"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("RPCId"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("RPCId"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("RPCResponseId"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("RPCResponseId"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("RPCResponseId"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("RepOffset"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("RepOffset"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("RepOffset"), static_cast(val)); -if (auto val = parser.get_int64(STR("UFunction"), STR("ReturnValueOffset"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("ReturnValueOffset"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("ReturnValueOffset"), static_cast(val)); -if (auto val = parser.get_int64(STR("UField"), STR("Next"), -1); val != -1) Unreal::UField::MemberOffsets.emplace(STR("Next"), static_cast(val)); -if (auto val = parser.get_int64(STR("FEnumProperty"), STR("Enum"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UField"), SYSSTR("Next"), -1); val != -1) Unreal::UField::MemberOffsets.emplace(STR("Next"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("FEnumProperty"), SYSSTR("Enum"), -1); val != -1) Unreal::FEnumProperty::MemberOffsets.emplace(STR("Enum"), static_cast(val)); -if (auto val = parser.get_int64(STR("FEnumProperty"), STR("UnderlyingProp"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FEnumProperty"), SYSSTR("UnderlyingProp"), -1); val != -1) Unreal::FEnumProperty::MemberOffsets.emplace(STR("UnderlyingProp"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("ChildProperties"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("ChildProperties"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("ChildProperties"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("Children"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("Children"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("Children"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("DestructorLink"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("DestructorLink"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("DestructorLink"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("MinAlignment"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("MinAlignment"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("MinAlignment"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("PostConstructLink"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("PostConstructLink"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("PostConstructLink"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("PropertiesSize"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("PropertiesSize"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("PropertiesSize"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("PropertyLink"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("PropertyLink"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("PropertyLink"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("RefLink"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("RefLink"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("RefLink"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("Script"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("Script"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("ScriptAndPropertyObjectReferences"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("Script"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("Script"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("ScriptAndPropertyObjectReferences"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("ScriptAndPropertyObjectReferences"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("ScriptObjectReferences"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("ScriptObjectReferences"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("ScriptObjectReferences"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("SuperStruct"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("SuperStruct"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("SuperStruct"), static_cast(val)); -if (auto val = parser.get_int64(STR("UStruct"), STR("UnresolvedScriptProperties"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("UnresolvedScriptProperties"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("UnresolvedScriptProperties"), static_cast(val)); -if (auto val = parser.get_int64(STR("FDelegateProperty"), STR("SignatureFunction"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FDelegateProperty"), SYSSTR("SignatureFunction"), -1); val != -1) Unreal::FDelegateProperty::MemberOffsets.emplace(STR("SignatureFunction"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("ActiveSplitscreenType"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("ActiveSplitscreenType"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("ActiveSplitscreenType"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("AudioDeviceHandle"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("AudioDeviceHandle"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("AudioDeviceHandle"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("CurrentBufferVisualizationMode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("CurrentBufferVisualizationMode"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("CurrentBufferVisualizationMode"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("CurrentLumenVisualizationMode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("CurrentLumenVisualizationMode"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("CurrentLumenVisualizationMode"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("CurrentNaniteVisualizationMode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("CurrentNaniteVisualizationMode"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("CurrentNaniteVisualizationMode"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("CurrentVirtualShadowMapVisualizationMode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("CurrentVirtualShadowMapVisualizationMode"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("CurrentVirtualShadowMapVisualizationMode"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("DebugProperties"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("DebugProperties"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("DebugProperties"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("EngineShowFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("EngineShowFlags"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("EngineShowFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("GameLayerManagerPtr"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("GameLayerManagerPtr"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("GameLayerManagerPtr"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("HighResScreenshotDialog"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("HighResScreenshotDialog"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("HighResScreenshotDialog"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("MaxSplitscreenPlayers"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("MaxSplitscreenPlayers"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("MaxSplitscreenPlayers"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("MouseCaptureMode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("MouseCaptureMode"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("MouseCaptureMode"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("MouseLockMode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("MouseLockMode"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("MouseLockMode"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("SplitscreenInfo"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("SplitscreenInfo"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("SplitscreenInfo"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("StatHitchesData"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("StatHitchesData"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("StatHitchesData"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("StatUnitData"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("StatUnitData"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("StatUnitData"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("TitleSafeZone"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("TitleSafeZone"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("TitleSafeZone"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("ViewModeIndex"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("ViewModeIndex"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("ViewModeIndex"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("Viewport"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("Viewport"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("Viewport"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("ViewportConsole"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("ViewportConsole"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("ViewportConsole"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("ViewportFrame"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("ViewportFrame"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("ViewportFrame"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("ViewportOverlayWidget"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("ViewportOverlayWidget"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("ViewportOverlayWidget"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("Window"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("Window"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("Window"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("World"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("World"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("World"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bDisableSplitScreenOverride"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bDisableSplitScreenOverride"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bDisableSplitScreenOverride"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bDisableWorldRendering"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bDisableWorldRendering"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bDisableWorldRendering"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bHasAudioFocus"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bHasAudioFocus"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bHasAudioFocus"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bHideCursorDuringCapture"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bHideCursorDuringCapture"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bHideCursorDuringCapture"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bIgnoreInput"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bIgnoreInput"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bIgnoreInput"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bIsMouseOverClient"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bIsMouseOverClient"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bIsMouseOverClient"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bIsPlayInEditorViewport"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bIsPlayInEditorViewport"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bIsPlayInEditorViewport"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bLockDuringCapture"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bLockDuringCapture"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bLockDuringCapture"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bShowTitleSafeZone"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bShowTitleSafeZone"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bShowTitleSafeZone"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bSuppressTransitionMessage"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bSuppressTransitionMessage"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bSuppressTransitionMessage"), static_cast(val)); -if (auto val = parser.get_int64(STR("UGameViewportClient"), STR("bUseSoftwareCursorWidgets"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UGameViewportClient"), SYSSTR("bUseSoftwareCursorWidgets"), -1); val != -1) Unreal::UGameViewportClient::MemberOffsets.emplace(STR("bUseSoftwareCursorWidgets"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArAllowLazyLoading"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArAllowLazyLoading"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArAllowLazyLoading"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArContainsCode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArContainsCode"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArContainsCode"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArContainsMap"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArContainsMap"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArContainsMap"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArCustomPropertyList"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArCustomPropertyList"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArCustomPropertyList"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArEngineNetVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArEngineNetVer"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArEngineNetVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArEngineVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArEngineVer"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArEngineVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArForceByteSwapping"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArForceByteSwapping"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArForceByteSwapping"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArForceUnicode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArForceUnicode"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArForceUnicode"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArGameNetVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArGameNetVer"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArGameNetVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIgnoreArchetypeRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIgnoreArchetypeRef"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIgnoreArchetypeRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIgnoreClassGeneratedByRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIgnoreClassGeneratedByRef"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIgnoreClassGeneratedByRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIgnoreClassRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIgnoreClassRef"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIgnoreClassRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIgnoreOuterRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIgnoreOuterRef"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIgnoreOuterRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsCountingMemory"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsCountingMemory"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsCountingMemory"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsCriticalError"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsCriticalError"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsCriticalError"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsError"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsError"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsError"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsFilterEditorOnly"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsFilterEditorOnly"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsFilterEditorOnly"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsLoading"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsLoading"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsLoading"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsModifyingWeakAndStrongReferences"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsModifyingWeakAndStrongReferences"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsModifyingWeakAndStrongReferences"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsNetArchive"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsNetArchive"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsNetArchive"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsObjectReferenceCollector"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsObjectReferenceCollector"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsObjectReferenceCollector"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsPersistent"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsPersistent"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsPersistent"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsSaveGame"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsSaveGame"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsSaveGame"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsSaving"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsSaving"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsSaving"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsTextFormat"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsTextFormat"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsTextFormat"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArIsTransacting"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArIsTransacting"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArIsTransacting"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArLicenseeUE4Ver"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArLicenseeUE4Ver"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArLicenseeUE4Ver"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArMaxSerializeSize"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArMaxSerializeSize"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArMaxSerializeSize"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArNetVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArNetVer"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArNetVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArNoDelta"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArNoDelta"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArNoDelta"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArNoIntraPropertyDelta"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArNoIntraPropertyDelta"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArNoIntraPropertyDelta"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArPortFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArPortFlags"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArPortFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArRequiresLocalizationGather"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArRequiresLocalizationGather"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArRequiresLocalizationGather"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArSerializingDefaults"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArSerializingDefaults"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArSerializingDefaults"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArShouldSkipBulkData"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArShouldSkipBulkData"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArShouldSkipBulkData"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArUE4Ver"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArUE4Ver"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArUE4Ver"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArUseCustomPropertyList"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArUseCustomPropertyList"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArUseCustomPropertyList"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("ArWantBinaryPropertySerialization"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("ArWantBinaryPropertySerialization"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("ArWantBinaryPropertySerialization"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("CookingTargetPlatform"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("CookingTargetPlatform"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("CookingTargetPlatform"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("CustomVersionContainer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("CustomVersionContainer"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("CustomVersionContainer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("SerializedProperty"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("SerializedProperty"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("SerializedProperty"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchive"), STR("bCustomVersionsAreReset"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchive"), SYSSTR("bCustomVersionsAreReset"), -1); val != -1) Unreal::FArchive::MemberOffsets.emplace(STR("bCustomVersionsAreReset"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("CurrentID"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("CurrentID"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("CurrentID"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("DefaultPlayerName"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("DefaultPlayerName"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("DefaultPlayerName"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("EngineMessageClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("EngineMessageClass"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("EngineMessageClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("GameModeClassAliases"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("GameModeClassAliases"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("GameModeClassAliases"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("GameSession"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("GameSession"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("GameSession"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("HUDClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("HUDClass"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("HUDClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("InactivePlayerArray"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("InactivePlayerArray"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("InactivePlayerArray"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("InactivePlayerStateLifeSpan"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("InactivePlayerStateLifeSpan"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("InactivePlayerStateLifeSpan"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("MatchState"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("MatchState"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("MatchState"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("MaxInactivePlayers"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("MaxInactivePlayers"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("MaxInactivePlayers"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("MinRespawnDelay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("MinRespawnDelay"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("MinRespawnDelay"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("NumBots"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("NumBots"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("NumBots"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("NumPlayers"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("NumPlayers"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("NumPlayers"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("NumSpectators"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("NumSpectators"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("NumSpectators"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("NumTravellingPlayers"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("NumTravellingPlayers"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("NumTravellingPlayers"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("OptionsString"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("OptionsString"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("OptionsString"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("PlayerStateClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("PlayerStateClass"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("PlayerStateClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("SpectatorClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("SpectatorClass"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("SpectatorClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("bDelayedStart"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("bDelayedStart"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("bDelayedStart"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("bHandleDedicatedServerReplays"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("bHandleDedicatedServerReplays"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("bHandleDedicatedServerReplays"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("bPauseable"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("bPauseable"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("bPauseable"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("bStartPlayersAsSpectators"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("bStartPlayersAsSpectators"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("bStartPlayersAsSpectators"), static_cast(val)); -if (auto val = parser.get_int64(STR("AGameMode"), STR("bUseSeamlessTravel"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AGameMode"), SYSSTR("bUseSeamlessTravel"), -1); val != -1) Unreal::AGameMode::MemberOffsets.emplace(STR("bUseSeamlessTravel"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("AttachmentReplication"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("AttachmentReplication"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("AttachmentReplication"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("AutoReceiveInput"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("AutoReceiveInput"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("AutoReceiveInput"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("CachedLastRenderTime"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("CachedLastRenderTime"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("CachedLastRenderTime"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("ControllingMatineeActors"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("ControllingMatineeActors"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("ControllingMatineeActors"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("CreationTime"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("CreationTime"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("CreationTime"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("CustomTimeDilation"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("CustomTimeDilation"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("CustomTimeDilation"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("DefaultUpdateOverlapsMethodDuringLevelStreaming"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("DefaultUpdateOverlapsMethodDuringLevelStreaming"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("DefaultUpdateOverlapsMethodDuringLevelStreaming"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("DetachFence"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("DetachFence"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("DetachFence"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("HiddenEditorViews"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("HiddenEditorViews"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("HiddenEditorViews"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("InitialLifeSpan"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("InitialLifeSpan"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("InitialLifeSpan"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("InputComponent"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("InputComponent"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("InputComponent"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("InputConsumeOption_DEPRECATED"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("InputConsumeOption_DEPRECATED"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("InputConsumeOption_DEPRECATED"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("InputPriority"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("InputPriority"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("InputPriority"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("LastNetUpdateTime"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("LastNetUpdateTime"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("LastNetUpdateTime"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("LastRenderTime"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("LastRenderTime"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("LastRenderTime"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("Layers"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("Layers"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("MinNetUpdateFrequency"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("Layers"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("Layers"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("MinNetUpdateFrequency"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("MinNetUpdateFrequency"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("NetCullDistanceSquared"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetCullDistanceSquared"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetCullDistanceSquared"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("NetDormancy"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetDormancy"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetDormancy"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("NetDriverName"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetDriverName"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetDriverName"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("NetPriority"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetPriority"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetPriority"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("NetTag"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetTag"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("NetUpdateFrequency"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetTag"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetTag"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetUpdateFrequency"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetUpdateFrequency"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("NetUpdateTime"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetUpdateTime"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetUpdateTime"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnActorBeginOverlap"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnActorBeginOverlap"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnActorBeginOverlap"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnActorEndOverlap"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnActorEndOverlap"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnActorEndOverlap"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnActorHit"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnActorHit"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnActorHit"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnBeginCursorOver"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnBeginCursorOver"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnBeginCursorOver"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnClicked"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnClicked"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnClicked"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnDestroyed"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnDestroyed"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnDestroyed"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnEndCursorOver"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnEndCursorOver"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnEndCursorOver"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnEndPlay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnEndPlay"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnEndPlay"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnInputTouchBegin"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnInputTouchBegin"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnInputTouchBegin"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnInputTouchEnd"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnInputTouchEnd"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnInputTouchEnd"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnInputTouchEnter"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnInputTouchEnter"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnInputTouchEnter"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnInputTouchLeave"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnInputTouchLeave"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnInputTouchLeave"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnReleased"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnReleased"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnReleased"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnTakeAnyDamage"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnTakeAnyDamage"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnTakeAnyDamage"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnTakePointDamage"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnTakePointDamage"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnTakePointDamage"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("OnTakeRadialDamage"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("OnTakeRadialDamage"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("OnTakeRadialDamage"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("ParentComponent"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("ParentComponent"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("ParentComponent"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("PrimaryActorTick"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("PrimaryActorTick"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("PrimaryActorTick"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("RayTracingGroupId"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("RayTracingGroupId"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("RayTracingGroupId"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("RemoteRole"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("RemoteRole"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("RemoteRole"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("ReplicatedComponentsInfo"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("ReplicatedComponentsInfo"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("ReplicatedComponentsInfo"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("ReplicatedMovement"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("ReplicatedMovement"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("ReplicatedMovement"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("ReplicatedSubObjects"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("ReplicatedSubObjects"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("ReplicatedSubObjects"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("Role"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("Role"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("RootComponent"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("Role"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("Role"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("RootComponent"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("RootComponent"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("SpawnCollisionHandlingMethod"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("SpawnCollisionHandlingMethod"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("SpawnCollisionHandlingMethod"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("Tags"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("Tags"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("TimerHandle_LifeSpanExpired"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("Tags"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("Tags"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("TimerHandle_LifeSpanExpired"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("TimerHandle_LifeSpanExpired"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("UpdateOverlapsMethodDuringLevelStreaming"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("UpdateOverlapsMethodDuringLevelStreaming"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("UpdateOverlapsMethodDuringLevelStreaming"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bActorBeginningPlayFromLevelStreaming"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bActorBeginningPlayFromLevelStreaming"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bActorBeginningPlayFromLevelStreaming"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bActorEnableCollision"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bActorEnableCollision"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bActorEnableCollision"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bActorInitialized"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bActorInitialized"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bActorInitialized"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bActorIsBeingConstructed"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bActorIsBeingConstructed"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bActorIsBeingConstructed"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bActorIsBeingDestroyed"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bActorIsBeingDestroyed"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bActorIsBeingDestroyed"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bActorSeamlessTraveled"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bActorSeamlessTraveled"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bActorSeamlessTraveled"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bActorWantsDestroyDuringBeginPlay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bActorWantsDestroyDuringBeginPlay"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bActorWantsDestroyDuringBeginPlay"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bAllowReceiveTickEventOnDedicatedServer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bAllowReceiveTickEventOnDedicatedServer"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bAllowReceiveTickEventOnDedicatedServer"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bAllowTickBeforeBeginPlay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bAllowTickBeforeBeginPlay"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bAllowTickBeforeBeginPlay"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bAlwaysRelevant"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bAlwaysRelevant"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bAlwaysRelevant"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bAsyncPhysicsTickEnabled"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bAsyncPhysicsTickEnabled"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bAsyncPhysicsTickEnabled"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bAutoDestroyWhenFinished"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bAutoDestroyWhenFinished"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bAutoDestroyWhenFinished"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bBlockInput"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bBlockInput"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bBlockInput"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bCallPreReplication"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bCallPreReplication"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bCallPreReplication"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bCallPreReplicationForReplay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bCallPreReplicationForReplay"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bCallPreReplicationForReplay"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bCanBeDamaged"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bCanBeDamaged"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bCanBeDamaged"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bCanBeInCluster"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bCanBeInCluster"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bCanBeInCluster"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bCollideWhenPlacing"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bCollideWhenPlacing"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bCollideWhenPlacing"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bEnableAutoLODGeneration"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bEnableAutoLODGeneration"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bEnableAutoLODGeneration"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bExchangedRoles"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bExchangedRoles"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bExchangedRoles"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bFindCameraComponentWhenViewTarget"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bFindCameraComponentWhenViewTarget"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bFindCameraComponentWhenViewTarget"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bForceNetAddressable"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bForceNetAddressable"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bForceNetAddressable"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bGenerateOverlapEventsDuringLevelStreaming"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bGenerateOverlapEventsDuringLevelStreaming"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bGenerateOverlapEventsDuringLevelStreaming"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bHasDeferredComponentRegistration"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHasDeferredComponentRegistration"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bHasDeferredComponentRegistration"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bHasFinishedSpawning"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHasFinishedSpawning"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bHasFinishedSpawning"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bHasRegisteredAllComponents"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHasRegisteredAllComponents"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bHasRegisteredAllComponents"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bHidden"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bHidden"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bIgnoresOriginShifting"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHidden"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bHidden"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bIgnoresOriginShifting"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bIgnoresOriginShifting"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bIsEditorOnlyActor"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bIsEditorOnlyActor"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bIsEditorOnlyActor"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bNetCheckedInitialPhysicsState"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bNetCheckedInitialPhysicsState"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bNetCheckedInitialPhysicsState"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bNetLoadOnClient"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bNetLoadOnClient"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bNetLoadOnClient"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bNetStartup"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bNetStartup"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bNetStartup"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bNetTemporary"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bNetTemporary"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bNetTemporary"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bNetUseOwnerRelevancy"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bNetUseOwnerRelevancy"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bNetUseOwnerRelevancy"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bOnlyRelevantToOwner"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bOnlyRelevantToOwner"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bOnlyRelevantToOwner"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bPendingNetUpdate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bPendingNetUpdate"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bPendingNetUpdate"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bRelevantForLevelBounds"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bRelevantForLevelBounds"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bRelevantForLevelBounds"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bRelevantForNetworkReplays"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bRelevantForNetworkReplays"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bRelevantForNetworkReplays"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bReplayRewindable"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bReplayRewindable"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bReplayRewindable"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bReplicateMovement"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bReplicateMovement"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bReplicateMovement"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bReplicateUsingRegisteredSubObjectList"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bReplicateUsingRegisteredSubObjectList"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bReplicateUsingRegisteredSubObjectList"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bReplicates"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bReplicates"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bReplicates"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bRunningUserConstructionScript"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bRunningUserConstructionScript"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bRunningUserConstructionScript"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bTearOff"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bTearOff"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bTearOff"), static_cast(val)); -if (auto val = parser.get_int64(STR("AActor"), STR("bTickFunctionsRegistered"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bTickFunctionsRegistered"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bTickFunctionsRegistered"), static_cast(val)); -if (auto val = parser.get_int64(STR("UPlayer"), STR("ConfiguredInternetSpeed"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UPlayer"), SYSSTR("ConfiguredInternetSpeed"), -1); val != -1) Unreal::UPlayer::MemberOffsets.emplace(STR("ConfiguredInternetSpeed"), static_cast(val)); -if (auto val = parser.get_int64(STR("UPlayer"), STR("ConfiguredLanSpeed"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UPlayer"), SYSSTR("ConfiguredLanSpeed"), -1); val != -1) Unreal::UPlayer::MemberOffsets.emplace(STR("ConfiguredLanSpeed"), static_cast(val)); -if (auto val = parser.get_int64(STR("UPlayer"), STR("CurrentNetSpeed"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UPlayer"), SYSSTR("CurrentNetSpeed"), -1); val != -1) Unreal::UPlayer::MemberOffsets.emplace(STR("CurrentNetSpeed"), static_cast(val)); -if (auto val = parser.get_int64(STR("FByteProperty"), STR("Enum"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FByteProperty"), SYSSTR("Enum"), -1); val != -1) Unreal::FByteProperty::MemberOffsets.emplace(STR("Enum"), static_cast(val)); -if (auto val = parser.get_int64(STR("ULocalPlayer"), STR("AspectRatioAxisConstraint"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("ULocalPlayer"), SYSSTR("AspectRatioAxisConstraint"), -1); val != -1) Unreal::ULocalPlayer::MemberOffsets.emplace(STR("AspectRatioAxisConstraint"), static_cast(val)); -if (auto val = parser.get_int64(STR("ULocalPlayer"), STR("ControllerId"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("ULocalPlayer"), SYSSTR("ControllerId"), -1); val != -1) Unreal::ULocalPlayer::MemberOffsets.emplace(STR("ControllerId"), static_cast(val)); -if (auto val = parser.get_int64(STR("ULocalPlayer"), STR("LastViewLocation"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("ULocalPlayer"), SYSSTR("LastViewLocation"), -1); val != -1) Unreal::ULocalPlayer::MemberOffsets.emplace(STR("LastViewLocation"), static_cast(val)); -if (auto val = parser.get_int64(STR("ULocalPlayer"), STR("ViewportClient"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("ULocalPlayer"), SYSSTR("ViewportClient"), -1); val != -1) Unreal::ULocalPlayer::MemberOffsets.emplace(STR("ViewportClient"), static_cast(val)); -if (auto val = parser.get_int64(STR("ULocalPlayer"), STR("bSentSplitJoin"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("ULocalPlayer"), SYSSTR("bSentSplitJoin"), -1); val != -1) Unreal::ULocalPlayer::MemberOffsets.emplace(STR("bSentSplitJoin"), static_cast(val)); -if (auto val = parser.get_int64(STR("FMulticastDelegateProperty"), STR("SignatureFunction"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FMulticastDelegateProperty"), SYSSTR("SignatureFunction"), -1); val != -1) Unreal::FMulticastDelegateProperty::MemberOffsets.emplace(STR("SignatureFunction"), static_cast(val)); -if (auto val = parser.get_int64(STR("FObjectPropertyBase"), STR("PropertyClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FObjectPropertyBase"), SYSSTR("PropertyClass"), -1); val != -1) Unreal::FObjectPropertyBase::MemberOffsets.emplace(STR("PropertyClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArAllowLazyLoading"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArAllowLazyLoading"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArAllowLazyLoading"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArContainsCode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArContainsCode"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArContainsCode"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArContainsMap"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArContainsMap"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArContainsMap"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArCustomPropertyList"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArCustomPropertyList"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArCustomPropertyList"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArEngineNetVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArEngineNetVer"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArEngineNetVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArEngineVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArEngineVer"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArEngineVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArForceByteSwapping"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArForceByteSwapping"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArForceByteSwapping"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArForceUnicode"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArForceUnicode"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArForceUnicode"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArGameNetVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArGameNetVer"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArGameNetVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIgnoreArchetypeRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIgnoreArchetypeRef"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIgnoreArchetypeRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIgnoreClassGeneratedByRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIgnoreClassGeneratedByRef"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIgnoreClassGeneratedByRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIgnoreClassRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIgnoreClassRef"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIgnoreClassRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIgnoreOuterRef"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIgnoreOuterRef"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIgnoreOuterRef"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsCountingMemory"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsCountingMemory"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsCountingMemory"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsCriticalError"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsCriticalError"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsCriticalError"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsError"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsError"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsError"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsFilterEditorOnly"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsFilterEditorOnly"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsFilterEditorOnly"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsLoading"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsLoading"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsLoading"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsLoadingFromCookedPackage"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsLoadingFromCookedPackage"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsLoadingFromCookedPackage"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsModifyingWeakAndStrongReferences"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsModifyingWeakAndStrongReferences"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsModifyingWeakAndStrongReferences"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsNetArchive"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsNetArchive"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsNetArchive"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsObjectReferenceCollector"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsObjectReferenceCollector"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsObjectReferenceCollector"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsPersistent"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsPersistent"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsPersistent"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsSaveGame"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsSaveGame"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsSaveGame"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsSaving"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsSaving"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsSaving"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsTextFormat"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsTextFormat"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsTextFormat"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArIsTransacting"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArIsTransacting"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArIsTransacting"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArLicenseeUE4Ver"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArLicenseeUE4Ver"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArLicenseeUE4Ver"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArLicenseeUEVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArLicenseeUEVer"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArLicenseeUEVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArMaxSerializeSize"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArMaxSerializeSize"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArMaxSerializeSize"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArNoDelta"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArNoDelta"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArNoDelta"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArNoIntraPropertyDelta"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArNoIntraPropertyDelta"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArNoIntraPropertyDelta"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArPortFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArPortFlags"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArPortFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArRequiresLocalizationGather"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArRequiresLocalizationGather"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArRequiresLocalizationGather"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArSerializingDefaults"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArSerializingDefaults"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArSerializingDefaults"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArShouldSkipBulkData"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArShouldSkipBulkData"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArShouldSkipBulkData"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArShouldSkipCompilingAssets"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArShouldSkipCompilingAssets"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArShouldSkipCompilingAssets"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArUE4Ver"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArUE4Ver"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArUE4Ver"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArUEVer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArUEVer"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArUEVer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArUseCustomPropertyList"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArUseCustomPropertyList"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArUseCustomPropertyList"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArUseUnversionedPropertySerialization"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArUseUnversionedPropertySerialization"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArUseUnversionedPropertySerialization"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("ArWantBinaryPropertySerialization"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("ArWantBinaryPropertySerialization"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("ArWantBinaryPropertySerialization"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("CookingTargetPlatform"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("CookingTargetPlatform"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("CookingTargetPlatform"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("CustomVersionContainer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("CustomVersionContainer"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("CustomVersionContainer"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("SerializedProperty"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("SerializedProperty"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("SerializedProperty"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArchiveState"), STR("bCustomVersionsAreReset"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArchiveState"), SYSSTR("bCustomVersionsAreReset"), -1); val != -1) Unreal::FArchiveState::MemberOffsets.emplace(STR("bCustomVersionsAreReset"), static_cast(val)); -if (auto val = parser.get_int64(STR("FField"), STR("ClassPrivate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("ClassPrivate"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("ClassPrivate"), static_cast(val)); -if (auto val = parser.get_int64(STR("FField"), STR("FlagsPrivate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("FlagsPrivate"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("FlagsPrivate"), static_cast(val)); -if (auto val = parser.get_int64(STR("FField"), STR("NamePrivate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("NamePrivate"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("NamePrivate"), static_cast(val)); -if (auto val = parser.get_int64(STR("FField"), STR("Next"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("Next"), static_cast(val)); -if (auto val = parser.get_int64(STR("FField"), STR("Owner"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("Owner"), static_cast(val)); -if (auto val = parser.get_int64(STR("FClassProperty"), STR("MetaClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("Next"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("Next"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("Owner"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("Owner"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("FClassProperty"), SYSSTR("MetaClass"), -1); val != -1) Unreal::FClassProperty::MemberOffsets.emplace(STR("MetaClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("FBoolProperty"), STR("ByteMask"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FBoolProperty"), SYSSTR("ByteMask"), -1); val != -1) Unreal::FBoolProperty::MemberOffsets.emplace(STR("ByteMask"), static_cast(val)); -if (auto val = parser.get_int64(STR("FBoolProperty"), STR("ByteOffset"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FBoolProperty"), SYSSTR("ByteOffset"), -1); val != -1) Unreal::FBoolProperty::MemberOffsets.emplace(STR("ByteOffset"), static_cast(val)); -if (auto val = parser.get_int64(STR("FBoolProperty"), STR("FieldMask"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FBoolProperty"), SYSSTR("FieldMask"), -1); val != -1) Unreal::FBoolProperty::MemberOffsets.emplace(STR("FieldMask"), static_cast(val)); -if (auto val = parser.get_int64(STR("FBoolProperty"), STR("FieldSize"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FBoolProperty"), SYSSTR("FieldSize"), -1); val != -1) Unreal::FBoolProperty::MemberOffsets.emplace(STR("FieldSize"), static_cast(val)); -if (auto val = parser.get_int64(STR("UScriptStruct"), STR("CppStructOps"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UScriptStruct"), SYSSTR("CppStructOps"), -1); val != -1) Unreal::UScriptStruct::MemberOffsets.emplace(STR("CppStructOps"), static_cast(val)); -if (auto val = parser.get_int64(STR("UScriptStruct"), STR("StructFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UScriptStruct"), SYSSTR("StructFlags"), -1); val != -1) Unreal::UScriptStruct::MemberOffsets.emplace(STR("StructFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("UScriptStruct"), STR("bCppStructOpsFromBaseClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UScriptStruct"), SYSSTR("bCppStructOpsFromBaseClass"), -1); val != -1) Unreal::UScriptStruct::MemberOffsets.emplace(STR("bCppStructOpsFromBaseClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("UScriptStruct"), STR("bPrepareCppStructOpsCompleted"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UScriptStruct"), SYSSTR("bPrepareCppStructOpsCompleted"), -1); val != -1) Unreal::UScriptStruct::MemberOffsets.emplace(STR("bPrepareCppStructOpsCompleted"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("ActiveLevelCollectionIndex"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("ActiveLevelCollectionIndex"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("ActiveLevelCollectionIndex"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("AudioDeviceHandle"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("AudioDeviceHandle"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("AudioDeviceHandle"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("AudioTimeSeconds"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("AudioTimeSeconds"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("AudioTimeSeconds"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("BlockTillLevelStreamingCompletedEpoch"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("BlockTillLevelStreamingCompletedEpoch"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("BlockTillLevelStreamingCompletedEpoch"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("BuildStreamingDataTimer"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("BuildStreamingDataTimer"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("BuildStreamingDataTimer"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("CachedViewInfoRenderedLastFrame"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("CachedViewInfoRenderedLastFrame"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("CachedViewInfoRenderedLastFrame"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("CleanupWorldTag"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("CleanupWorldTag"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("CleanupWorldTag"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("CommittedPersistentLevelName"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("CommittedPersistentLevelName"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("CommittedPersistentLevelName"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("ContentBundleManager"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("ContentBundleManager"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("ContentBundleManager"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("DebugDrawTraceTag"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("DebugDrawTraceTag"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("DebugDrawTraceTag"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("DeltaRealTimeSeconds"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("DeltaRealTimeSeconds"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("DeltaRealTimeSeconds"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("DeltaTimeSeconds"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("DeltaTimeSeconds"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("DeltaTimeSeconds"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("ExtraReferencedObjects"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("ExtraReferencedObjects"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("ExtraReferencedObjects"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("FullPurgeTriggered"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("FullPurgeTriggered"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("FullPurgeTriggered"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("IsInBlockTillLevelStreamingCompleted"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("IsInBlockTillLevelStreamingCompleted"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("IsInBlockTillLevelStreamingCompleted"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("LWILastAssignedUID"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("LWILastAssignedUID"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("LWILastAssignedUID"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("LastRenderTime"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("LastRenderTime"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("LastRenderTime"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("LastTimeUnbuiltLightingWasEncountered"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("LastTimeUnbuiltLightingWasEncountered"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("LastTimeUnbuiltLightingWasEncountered"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("LevelSequenceActors"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("LevelSequenceActors"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("LevelSequenceActors"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NextSwitchCountdown"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NextSwitchCountdown"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NextSwitchCountdown"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NextURL"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NextURL"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NumInvalidReflectionCaptureComponents"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NextURL"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NextURL"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumInvalidReflectionCaptureComponents"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NumInvalidReflectionCaptureComponents"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NumLightingUnbuiltObjects"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumLightingUnbuiltObjects"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NumLightingUnbuiltObjects"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NumStreamingLevelsBeingLoaded"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumStreamingLevelsBeingLoaded"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NumStreamingLevelsBeingLoaded"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NumTextureStreamingDirtyResources"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumTextureStreamingDirtyResources"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NumTextureStreamingDirtyResources"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NumTextureStreamingUnbuiltComponents"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumTextureStreamingUnbuiltComponents"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NumTextureStreamingUnbuiltComponents"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("NumUnbuiltReflectionCaptures"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumUnbuiltReflectionCaptures"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NumUnbuiltReflectionCaptures"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("OnWorldPartitionInitializedEvent"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("OnWorldPartitionInitializedEvent"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("OnWorldPartitionInitializedEvent"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("OnWorldPartitionUninitializedEvent"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("OnWorldPartitionUninitializedEvent"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("OnWorldPartitionUninitializedEvent"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("OriginLocation"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("OriginLocation"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("OriginLocation"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("OriginOffsetThisFrame"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("OriginOffsetThisFrame"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("OriginOffsetThisFrame"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("PauseDelay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("PauseDelay"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("PauseDelay"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("PerModuleDataObjects"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("PerModuleDataObjects"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("PerModuleDataObjects"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("PlayerNum"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("PlayerNum"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("PlayerNum"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("PreparingLevelNames"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("PreparingLevelNames"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("PreparingLevelNames"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("RealTimeSeconds"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("RealTimeSeconds"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("RealTimeSeconds"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("RequestedOriginLocation"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("RequestedOriginLocation"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("RequestedOriginLocation"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("ServerStreamingLevelsVisibility"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("ServerStreamingLevelsVisibility"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("ServerStreamingLevelsVisibility"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("StreamingLevelsPrefix"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("StreamingLevelsPrefix"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("StreamingLevelsPrefix"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("StreamingVolumeUpdateDelay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("StreamingVolumeUpdateDelay"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("StreamingVolumeUpdateDelay"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("TimeSeconds"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("TimeSeconds"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("TimeSeconds"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("TimeSinceLastPendingKillPurge"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("TimeSinceLastPendingKillPurge"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("TimeSinceLastPendingKillPurge"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("UnpausedTimeSeconds"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("UnpausedTimeSeconds"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("UnpausedTimeSeconds"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("ViewLocationsRenderedLastFrame"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("ViewLocationsRenderedLastFrame"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("ViewLocationsRenderedLastFrame"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bActorsInitialized"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bActorsInitialized"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bActorsInitialized"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bAggressiveLOD"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bAggressiveLOD"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bAggressiveLOD"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bAllowAudioPlayback"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bAllowAudioPlayback"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bAllowAudioPlayback"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bAllowDeferredPhysicsStateCreation"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bAllowDeferredPhysicsStateCreation"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bAllowDeferredPhysicsStateCreation"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bAreConstraintsDirty"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bAreConstraintsDirty"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bAreConstraintsDirty"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bBegunPlay"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bBegunPlay"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bBegunPlay"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bCleanedUpWorld"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bCleanedUpWorld"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bCleanedUpWorld"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bCreateRenderStateForHiddenComponents"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bCreateRenderStateForHiddenComponents"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bCreateRenderStateForHiddenComponents"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bDebugDrawAllTraceTags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bDebugDrawAllTraceTags"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bDebugDrawAllTraceTags"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bDebugFrameStepExecution"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bDebugFrameStepExecution"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bDebugFrameStepExecution"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bDebugPauseExecution"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bDebugPauseExecution"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bDebugPauseExecution"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bDoDelayedUpdateCullDistanceVolumes"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bDoDelayedUpdateCullDistanceVolumes"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bDoDelayedUpdateCullDistanceVolumes"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bDropDetail"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bDropDetail"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bDropDetail"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bHack_Force_UsesGameHiddenFlags_True"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bHack_Force_UsesGameHiddenFlags_True"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bHack_Force_UsesGameHiddenFlags_True"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bHasEverBeenInitialized"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bHasEverBeenInitialized"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bHasEverBeenInitialized"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bInTick"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bInTick"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bInitializedAndNeedsCleanup"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bInTick"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bInTick"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bInitializedAndNeedsCleanup"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bInitializedAndNeedsCleanup"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bIsBuilt"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsBuilt"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bIsBuilt"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bIsCameraMoveableWhenPaused"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsCameraMoveableWhenPaused"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bIsCameraMoveableWhenPaused"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bIsDefaultLevel"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsDefaultLevel"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bIsDefaultLevel"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bIsLevelStreamingFrozen"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsLevelStreamingFrozen"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bIsLevelStreamingFrozen"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bIsRunningConstructionScript"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsRunningConstructionScript"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bIsRunningConstructionScript"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bIsTearingDown"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsTearingDown"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bIsTearingDown"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bIsWorldInitialized"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsWorldInitialized"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bIsWorldInitialized"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bKismetScriptError"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bKismetScriptError"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bKismetScriptError"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bMarkedObjectsPendingKill"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bMarkedObjectsPendingKill"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bMarkedObjectsPendingKill"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bMatchStarted"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bMatchStarted"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bMatchStarted"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bMaterialParameterCollectionInstanceNeedsDeferredUpdate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bMaterialParameterCollectionInstanceNeedsDeferredUpdate"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bMaterialParameterCollectionInstanceNeedsDeferredUpdate"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bOriginOffsetThisFrame"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bOriginOffsetThisFrame"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bOriginOffsetThisFrame"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bPlayersOnly"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bPlayersOnly"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bPlayersOnly"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bPlayersOnlyPending"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bPlayersOnlyPending"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bPlayersOnlyPending"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bPostTickComponentUpdate"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bPostTickComponentUpdate"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bPostTickComponentUpdate"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bRequestedBlockOnAsyncLoading"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bRequestedBlockOnAsyncLoading"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bRequestedBlockOnAsyncLoading"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bRequiresHitProxies"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bRequiresHitProxies"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bRequiresHitProxies"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bShouldDelayGarbageCollect"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bShouldDelayGarbageCollect"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bShouldDelayGarbageCollect"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bShouldForceUnloadStreamingLevels"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bShouldForceUnloadStreamingLevels"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bShouldForceUnloadStreamingLevels"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bShouldForceVisibleStreamingLevels"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bShouldForceVisibleStreamingLevels"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bShouldForceVisibleStreamingLevels"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bShouldSimulatePhysics"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bShouldSimulatePhysics"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bShouldSimulatePhysics"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bShouldTick"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bShouldTick"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bShouldTick"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bStartup"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bStartup"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bStartup"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bStreamingDataDirty"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bStreamingDataDirty"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bStreamingDataDirty"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bSupportsMakingInvisibleTransactionRequests"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bSupportsMakingInvisibleTransactionRequests"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bSupportsMakingInvisibleTransactionRequests"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bSupportsMakingVisibleTransactionRequests"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bSupportsMakingVisibleTransactionRequests"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bSupportsMakingVisibleTransactionRequests"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bTickNewlySpawned"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bTickNewlySpawned"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bTickNewlySpawned"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bTriggerPostLoadMap"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bTriggerPostLoadMap"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bTriggerPostLoadMap"), static_cast(val)); -if (auto val = parser.get_int64(STR("UWorld"), STR("bWorldWasLoadedThisTick"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bWorldWasLoadedThisTick"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bWorldWasLoadedThisTick"), static_cast(val)); -if (auto val = parser.get_int64(STR("FSetProperty"), STR("ElementProp"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FSetProperty"), SYSSTR("ElementProp"), -1); val != -1) Unreal::FSetProperty::MemberOffsets.emplace(STR("ElementProp"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassAddReferencedObjects"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassAddReferencedObjects"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassAddReferencedObjects"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassCastFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassCastFlags"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassCastFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassConfigName"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassConfigName"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassConfigName"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassConstructor"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassConstructor"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassConstructor"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassDefaultObject"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassDefaultObject"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassDefaultObject"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassFlags"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassFlags"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassFlags"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassGeneratedBy"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassGeneratedBy"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassGeneratedBy"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassUnique"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassUnique"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassUnique"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassVTableHelperCtorCaller"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassVTableHelperCtorCaller"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassVTableHelperCtorCaller"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("ClassWithin"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("ClassWithin"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("ClassWithin"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("CppClassStaticFunctions"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("CppClassStaticFunctions"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("CppClassStaticFunctions"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("FirstOwnedClassRep"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("FirstOwnedClassRep"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("FirstOwnedClassRep"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("Interfaces"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("Interfaces"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("Interfaces"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("NetFields"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("NetFields"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("NetFields"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("SparseClassData"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("SparseClassData"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("SparseClassData"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("SparseClassDataStruct"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("SparseClassDataStruct"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("SparseClassDataStruct"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("UberGraphFramePointerProperty"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("UberGraphFramePointerProperty"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("UberGraphFramePointerProperty"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("bCooked"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("bCooked"), static_cast(val)); -if (auto val = parser.get_int64(STR("UClass"), STR("bLayoutChanging"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("bCooked"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("bCooked"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("bLayoutChanging"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("bLayoutChanging"), static_cast(val)); -if (auto val = parser.get_int64(STR("UEnum"), STR("CppForm"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("CppForm"), static_cast(val)); -if (auto val = parser.get_int64(STR("UEnum"), STR("CppType"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("CppType"), static_cast(val)); -if (auto val = parser.get_int64(STR("UEnum"), STR("EnumDisplayNameFn"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("CppForm"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("CppForm"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("CppType"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("CppType"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("EnumDisplayNameFn"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("EnumDisplayNameFn"), static_cast(val)); -if (auto val = parser.get_int64(STR("UEnum"), STR("EnumFlags_Internal"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("EnumFlags_Internal"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("EnumFlags_Internal"), static_cast(val)); -if (auto val = parser.get_int64(STR("UEnum"), STR("EnumPackage"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("EnumPackage"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("EnumPackage"), static_cast(val)); -if (auto val = parser.get_int64(STR("UEnum"), STR("Names"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("Names"), static_cast(val)); -if (auto val = parser.get_int64(STR("FMapProperty"), STR("KeyProp"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("Names"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("Names"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("FMapProperty"), SYSSTR("KeyProp"), -1); val != -1) Unreal::FMapProperty::MemberOffsets.emplace(STR("KeyProp"), static_cast(val)); -if (auto val = parser.get_int64(STR("FMapProperty"), STR("ValueProp"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FMapProperty"), SYSSTR("ValueProp"), -1); val != -1) Unreal::FMapProperty::MemberOffsets.emplace(STR("ValueProp"), static_cast(val)); -if (auto val = parser.get_int64(STR("FStructProperty"), STR("Struct"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FStructProperty"), SYSSTR("Struct"), -1); val != -1) Unreal::FStructProperty::MemberOffsets.emplace(STR("Struct"), static_cast(val)); -if (auto val = parser.get_int64(STR("FArrayProperty"), STR("Inner"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FArrayProperty"), SYSSTR("Inner"), -1); val != -1) Unreal::FArrayProperty::MemberOffsets.emplace(STR("Inner"), static_cast(val)); -if (auto val = parser.get_int64(STR("FInterfaceProperty"), STR("InterfaceClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FInterfaceProperty"), SYSSTR("InterfaceClass"), -1); val != -1) Unreal::FInterfaceProperty::MemberOffsets.emplace(STR("InterfaceClass"), static_cast(val)); -if (auto val = parser.get_int64(STR("FFieldPathProperty"), STR("PropertyClass"), -1); val != -1) +if (auto val = parser.get_int64(SYSSTR("FFieldPathProperty"), SYSSTR("PropertyClass"), -1); val != -1) Unreal::FFieldPathProperty::MemberOffsets.emplace(STR("PropertyClass"), static_cast(val)); diff --git a/UE4SS/include/Common.hpp b/UE4SS/include/Common.hpp index 53368ad82..5aaf184f8 100644 --- a/UE4SS/include/Common.hpp +++ b/UE4SS/include/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_UE4SS_EXPORTS #ifndef RC_UE4SS_API #define RC_UE4SS_API __declspec(dllimport) @@ -9,3 +11,12 @@ #define RC_UE4SS_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_UE4SS_API +#define RC_UE4SS_API +#endif + + +#endif diff --git a/UE4SS/include/ExceptionHandling.hpp b/UE4SS/include/ExceptionHandling.hpp index c6745b158..6ab016086 100644 --- a/UE4SS/include/ExceptionHandling.hpp +++ b/UE4SS/include/ExceptionHandling.hpp @@ -8,7 +8,7 @@ #define UE4SS_ERROR_OUTPUTTER() \ if (!Output::has_internal_error()) \ { \ - Output::send(STR("Error: {}\n"), to_wstring(e.what())); \ + Output::send(SYSSTR("Error: {}\n"), to_generic_string(e.what())); \ } \ else \ { \ diff --git a/UE4SS/include/LuaCustomMemberFunctions.hpp b/UE4SS/include/LuaCustomMemberFunctions.hpp index d3f8c5b3f..f770ad44f 100644 --- a/UE4SS/include/LuaCustomMemberFunctions.hpp +++ b/UE4SS/include/LuaCustomMemberFunctions.hpp @@ -49,9 +49,9 @@ namespace RC::LuaBackCompat // Backwards compatibility with UE4SS 1.3. - auto StaticFindObject(UClass* ObjectClass, UObject* InObjectPackage, const wchar_t* OrigInName, bool bExactClass = false) -> UObject*; - auto StaticFindObject(const wchar_t* OrigInName) -> UObject*; - auto NotifyOnNewObject(const wchar_t* class_name, std::function& callable) -> void; + auto StaticFindObject(UClass* ObjectClass, UObject* InObjectPackage, const UECharType* OrigInName, bool bExactClass = false) -> UObject*; + auto StaticFindObject(const UECharType* OrigInName) -> UObject*; + auto NotifyOnNewObject(const UECharType* class_name, std::function& callable) -> void; auto lua_RegisterHook_wrapper(lua_State*) -> int; auto lua_UObjectBase_IsA_wrapper(lua_State*) -> int; @@ -140,6 +140,7 @@ namespace RC::UnrealRuntimeTypes using TypeHandlerMap = std::unordered_map; TypeHandlerMap TypeHandlers{ {"Pointer", &Array_Type_Handler_Ptr}, + // TODO: should I change this to something? {"wchar_t", &Array_Type_Handler_WChar_T}, }; diff --git a/UE4SS/include/LuaType/LuaCustomProperty.hpp b/UE4SS/include/LuaType/LuaCustomProperty.hpp index b19edc7e2..c69903742 100644 --- a/UE4SS/include/LuaType/LuaCustomProperty.hpp +++ b/UE4SS/include/LuaType/LuaCustomProperty.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace RC::Unreal { class UObject; @@ -17,11 +19,11 @@ namespace RC::LuaType class LuaCustomProperty { public: - std::wstring m_name{}; + SystemStringType m_name{}; std::unique_ptr m_property; public: - LuaCustomProperty(std::wstring name, std::unique_ptr property); + LuaCustomProperty(SystemStringType name, std::unique_ptr property); private: class PropertyList @@ -30,9 +32,9 @@ namespace RC::LuaType std::vector properties; public: - auto add(std::wstring property_name, std::unique_ptr) -> void; + auto add(SystemStringType property_name, std::unique_ptr) -> void; auto clear() -> void; - auto find_or_nullptr(Unreal::UObject* base, std::wstring property_name) -> Unreal::FProperty*; + auto find_or_nullptr(Unreal::UObject* base, SystemStringType property_name) -> Unreal::FProperty*; }; public: diff --git a/UE4SS/include/LuaType/LuaUObject.hpp b/UE4SS/include/LuaType/LuaUObject.hpp index ea81196a3..e92605091 100644 --- a/UE4SS/include/LuaType/LuaUObject.hpp +++ b/UE4SS/include/LuaType/LuaUObject.hpp @@ -462,7 +462,7 @@ namespace RC::LuaType { lua.throw_error("Function 'GetProperty' requires a string as the first parameter"); } - std::wstring property_name = to_wstring(lua.get_string(2)); + SystemStringType property_name = to_generic_string(lua.get_string(2)); auto reflection_table = lua.get_table(); const auto& reflected_object = reflection_table.get_userdata_field("ReflectedObject").get_remote_cpp_object(); @@ -478,7 +478,7 @@ namespace RC::LuaType { obj_as_struct = reflected_object->GetClassPrivate(); } - auto* property = obj_as_struct->FindProperty(Unreal::FName(property_name)); + auto* property = obj_as_struct->FindProperty(Unreal::FName(SystemStringToUEString(property_name))); construct_xproperty(lua, property); return 1; @@ -586,7 +586,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. { lua.throw_error(error_overload_not_found); } - auto cmd = to_wstring(lua.get_string()); + auto cmd = to_generic_string(lua.get_string()); if (lua.get_stack_size() < 2) { @@ -601,7 +601,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. auto executor = lua.get_userdata(); auto ar = Unreal::FOutputDevice{}; - auto return_value = lua_object.get_remote_cpp_object()->ProcessConsoleExec(cmd.c_str(), ar, executor.get_remote_cpp_object()); + auto return_value = lua_object.get_remote_cpp_object()->ProcessConsoleExec(SystemStringToUEString(cmd).c_str(), ar, executor.get_remote_cpp_object()); lua.set_bool(return_value); return 1; @@ -641,7 +641,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. { auto& lua_object = lua.get_userdata(); - const std::wstring& member_name = to_const_wstring(lua.get_string()); + const SystemStringType& member_name = to_generic_string(lua.get_string()); // If nullptr then we assume the UObject wasn't found so lets return an invalid UObject to Lua // This allows the safe chaining of "__index" as long as the Lua script checks ":IsValid()" before using the object @@ -656,17 +656,17 @@ No overload found for function 'UObject.ProcessConsoleExec'. SelfType::construct(lua, static_cast(nullptr)); break; case Operation::Set: - Output::send(STR("[Lua][Error] Tried setting member variable '{}' but UObject instance is nullptr\n"), member_name); + Output::send(SYSSTR("[Lua][Error] Tried setting member variable '{}' but UObject instance is nullptr\n"), member_name); break; default: - Output::send(STR("[Lua][Error] The UObject instance is nullptr & operation type was invalid\n")); + Output::send(SYSSTR("[Lua][Error] The UObject instance is nullptr & operation type was invalid\n")); break; } return; } - Unreal::FName property_name = Unreal::FName(member_name); + Unreal::FName property_name = Unreal::FName(SystemStringToUEString(member_name)); Unreal::FField* field = LuaCustomProperty::StaticStorage::property_list.find_or_nullptr(lua_object.get_remote_cpp_object(), member_name); if (!field) @@ -777,7 +777,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. { // We can either throw an error and kill the execution /**/ - std::wstring property_type_name = property_type.ToString(); + SystemStringType property_type_name = UEStringToSystemString(property_type.ToString()); lua.throw_error(std::format( "[LocalUnrealParam::prepare_to_handle] Tried accessing unreal property without a registered handler. Property type '{}' not supported.", to_string(property_type_name))); diff --git a/UE4SS/include/Mod/CppMod.hpp b/UE4SS/include/Mod/CppMod.hpp index 92d90e147..18466a457 100644 --- a/UE4SS/include/Mod/CppMod.hpp +++ b/UE4SS/include/Mod/CppMod.hpp @@ -2,12 +2,18 @@ #include +#ifdef WIN32 #define NOMINMAX #include +#else +#include +#endif #include #include +#include + namespace RC { namespace LuaMadeSimple @@ -22,17 +28,18 @@ namespace RC typedef void (*uninstall_type)(CppUserModBase*); private: - std::wstring m_dlls_path; - + SystemStringType m_dlls_path; +#ifdef WIN32 HMODULE m_main_dll_module = NULL; DLL_DIRECTORY_COOKIE m_dlls_path_cookie = NULL; +#endif start_type m_start_mod_func = nullptr; uninstall_type m_uninstall_mod_func = nullptr; CppUserModBase* m_mod = nullptr; public: - CppMod(UE4SSProgram&, std::wstring&& mod_name, std::wstring&& mod_path); + CppMod(UE4SSProgram&, SystemStringType&& mod_name, SystemStringType&& mod_path); CppMod(CppMod&) = delete; CppMod(CppMod&&) = delete; ~CppMod() override; @@ -41,7 +48,7 @@ namespace RC auto start_mod() -> void override; auto uninstall() -> void override; - auto fire_on_lua_start(StringViewType mod_name, + auto fire_on_lua_start(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -50,7 +57,7 @@ namespace RC auto fire_on_lua_start(LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, std::vector& hook_luas) -> void; - auto fire_on_lua_stop(StringViewType mod_name, + auto fire_on_lua_stop(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -63,6 +70,6 @@ namespace RC auto fire_ui_init() -> void override; auto fire_program_start() -> void override; auto fire_update() -> void override; - auto fire_dll_load(std::wstring_view dll_name) -> void; + auto fire_dll_load(SystemStringViewType dll_name) -> void; }; } // namespace RC diff --git a/UE4SS/include/Mod/CppUserModBase.hpp b/UE4SS/include/Mod/CppUserModBase.hpp index 710f17210..76d48ed41 100644 --- a/UE4SS/include/Mod/CppUserModBase.hpp +++ b/UE4SS/include/Mod/CppUserModBase.hpp @@ -5,18 +5,20 @@ #include #include +#ifdef HAS_GUI #include #include +#endif namespace RC { struct ModMetadata { - const StringType ModName{}; - const StringType ModVersion{}; - const StringType ModDescription{}; - const StringType ModAuthors{}; - const StringType ModIntendedSDKVersion{}; + const SystemStringType ModName{}; + const SystemStringType ModVersion{}; + const SystemStringType ModDescription{}; + const SystemStringType ModAuthors{}; + const SystemStringType ModIntendedSDKVersion{}; }; namespace LuaMadeSimple @@ -29,14 +31,15 @@ namespace RC class CppUserModBase { protected: + #ifdef HAS_GUI std::vector> GUITabs{}; - + #endif public: - StringType ModName{}; - StringType ModVersion{}; - StringType ModDescription{}; - StringType ModAuthors{}; - StringType ModIntendedSDKVersion{}; + SystemStringType ModName{}; + SystemStringType ModVersion{}; + SystemStringType ModDescription{}; + SystemStringType ModAuthors{}; + SystemStringType ModIntendedSDKVersion{}; public: RC_UE4SS_API CppUserModBase(); @@ -72,7 +75,7 @@ namespace RC * @param async_lua This is the Lua instance for asynchronous things like ExecuteAsync and ExecuteWithDelay. * @param hook_luas This is a container of Lua instances that are used for game-thread hooks like ExecuteInGameThread. */ - RC_UE4SS_API virtual auto on_lua_start(StringViewType mod_name, + RC_UE4SS_API virtual auto on_lua_start(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -103,7 +106,7 @@ namespace RC * @param async_lua This is the Lua instance for asynchronous things like ExecuteAsync and ExecuteWithDelay. * @param hook_luas This is a container of Lua instances that are used for game-thread hooks like ExecuteInGameThread. */ - RC_UE4SS_API virtual auto on_lua_stop(StringViewType mod_name, + RC_UE4SS_API virtual auto on_lua_stop(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -125,10 +128,11 @@ namespace RC { } - RC_UE4SS_API virtual auto on_dll_load(std::wstring_view dll_name) -> void + RC_UE4SS_API virtual auto on_dll_load(SystemStringType dll_name) -> void { } +#ifdef HAS_GUI RC_UE4SS_API virtual auto render_tab() -> void{}; protected: @@ -136,5 +140,6 @@ namespace RC RC_UE4SS_API auto register_keydown_event(Input::Key, const Input::EventCallbackCallable&, uint8_t custom_data = 0) -> void; RC_UE4SS_API auto register_keydown_event(Input::Key, const Input::Handler::ModifierKeyArray&, const Input::EventCallbackCallable&, uint8_t custom_data = 0) -> void; +#endif }; } // namespace RC diff --git a/UE4SS/include/Mod/LuaMod.hpp b/UE4SS/include/Mod/LuaMod.hpp index 31ad8435c..861acdb72 100644 --- a/UE4SS/include/Mod/LuaMod.hpp +++ b/UE4SS/include/Mod/LuaMod.hpp @@ -26,7 +26,7 @@ namespace RC class LuaMod : public Mod { private: - std::wstring m_scripts_path; + SystemStringType m_scripts_path; LuaMadeSimple::Lua& m_lua; public: @@ -97,8 +97,8 @@ namespace RC static inline std::vector m_call_function_by_name_with_arguments_post_callbacks; static inline std::vector m_local_player_exec_pre_callbacks; static inline std::vector m_local_player_exec_post_callbacks; - static inline std::unordered_map m_global_command_lua_callbacks; - static inline std::unordered_map m_custom_command_lua_pre_callbacks; + static inline std::unordered_map m_global_command_lua_callbacks; + static inline std::unordered_map m_custom_command_lua_pre_callbacks; static inline std::vector m_game_thread_actions{}; // This is storage that persists through hot-reloads. static inline std::unordered_map m_shared_lua_variables{}; @@ -109,7 +109,7 @@ namespace RC static inline std::vector m_init_game_state_post_callbacks{}; static inline std::vector m_begin_play_pre_callbacks{}; static inline std::vector m_begin_play_post_callbacks{}; - static inline std::unordered_map m_script_hook_callbacks{}; + static inline std::unordered_map m_script_hook_callbacks{}; static inline std::unordered_map m_generic_hook_id_to_native_hook_id{}; // Generic hook ids are generated incrementally so the first one is 0 and the next one is always +1 from the last id. static inline int32_t m_last_generic_hook_id{}; @@ -124,7 +124,7 @@ namespace RC std::mutex m_actions_lock{}; public: - LuaMod(UE4SSProgram&, std::wstring&& mod_name, std::wstring&& mod_path); + LuaMod(UE4SSProgram&, SystemStringType&& mod_name, SystemStringType&& mod_path); ~LuaMod() override = default; private: diff --git a/UE4SS/include/Mod/Mod.hpp b/UE4SS/include/Mod/Mod.hpp index 0f22559b4..7fca91ca7 100644 --- a/UE4SS/include/Mod/Mod.hpp +++ b/UE4SS/include/Mod/Mod.hpp @@ -26,8 +26,8 @@ namespace RC protected: #pragma warning(disable : 4251) - std::wstring m_mod_name; - std::wstring m_mod_path; + SystemStringType m_mod_name; + SystemStringType m_mod_path; #pragma warning(default : 4251) protected: @@ -45,11 +45,11 @@ namespace RC }; public: - Mod(UE4SSProgram&, std::wstring&& mod_name, std::wstring&& mod_path); + Mod(UE4SSProgram&, SystemStringType&& mod_name, SystemStringType&& mod_path); virtual ~Mod() = default; public: - auto get_name() const -> std::wstring_view; + auto get_name() const -> SystemStringViewType; virtual auto start_mod() -> void = 0; virtual auto uninstall() -> void = 0; diff --git a/UE4SS/include/ObjectDumper/ObjectToString.hpp b/UE4SS/include/ObjectDumper/ObjectToString.hpp index 0b0525a2b..3cbf96a8d 100644 --- a/UE4SS/include/ObjectDumper/ObjectToString.hpp +++ b/UE4SS/include/ObjectDumper/ObjectToString.hpp @@ -8,7 +8,7 @@ namespace RC::ObjectDumper { using ToStringHash = size_t; - using ObjectToStringDecl = std::function; + using ObjectToStringDecl = std::function; extern std::unordered_map object_to_string_functions; using ObjectToStringComplexDeclCallable = const std::function&; @@ -20,33 +20,33 @@ namespace RC::ObjectDumper auto to_string_exists(size_t hash) -> bool; auto to_string_complex_exists(size_t hash) -> bool; - auto object_trivial_dump_to_string(void* p_this, std::wstring& out_line, const wchar_t* post_delimiter = L".") -> void; - auto object_to_string(void* p_this, std::wstring& out_line) -> void; + auto object_trivial_dump_to_string(void* p_this, SystemStringType& out_line, const SystemCharType* post_delimiter = SYSSTR(".")) -> void; + auto object_to_string(void* p_this, SystemStringType& out_line) -> void; - auto property_trivial_dump_to_string(void* p_this, std::wstring& out_line) -> void; - auto property_to_string(void* p_this, std::wstring& out_line) -> void; + auto property_trivial_dump_to_string(void* p_this, SystemStringType& out_line) -> void; + auto property_to_string(void* p_this, SystemStringType& out_line) -> void; - auto arrayproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto arrayproperty_to_string_complex(void* p_this, std::wstring& out_line, ObjectToStringComplexDeclCallable callable) -> void; + auto arrayproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto arrayproperty_to_string_complex(void* p_this, SystemStringType& out_line, ObjectToStringComplexDeclCallable callable) -> void; - auto mapproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto mapproperty_to_string_complex(void* p_this, std::wstring& out_line, ObjectToStringComplexDeclCallable callable) -> void; + auto mapproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto mapproperty_to_string_complex(void* p_this, SystemStringType& out_line, ObjectToStringComplexDeclCallable callable) -> void; - auto classproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto delegateproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto fieldpathproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto interfaceproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto multicastdelegateproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto objectproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto structproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto enumproperty_to_string(void* p_this, std::wstring& out_line) -> void; - auto boolproperty_to_string(void* p_this, std::wstring& out_line) -> void; + auto classproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto delegateproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto fieldpathproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto interfaceproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto multicastdelegateproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto objectproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto structproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto enumproperty_to_string(void* p_this, SystemStringType& out_line) -> void; + auto boolproperty_to_string(void* p_this, SystemStringType& out_line) -> void; - auto enum_to_string(void* p_this, std::wstring& out_line) -> void; - auto struct_to_string(void* p_this, std::wstring& out_line) -> void; - auto function_to_string(void* p_this, std::wstring& out_line) -> void; + auto enum_to_string(void* p_this, SystemStringType& out_line) -> void; + auto struct_to_string(void* p_this, SystemStringType& out_line) -> void; + auto function_to_string(void* p_this, SystemStringType& out_line) -> void; - auto scriptstruct_to_string_complex(void* p_this, std::wstring& out_line, ObjectToStringComplexDeclCallable callable) -> void; + auto scriptstruct_to_string_complex(void* p_this, SystemStringType& out_line, ObjectToStringComplexDeclCallable callable) -> void; auto init() -> void; } // namespace RC::ObjectDumper diff --git a/UE4SS/include/Platform.hpp b/UE4SS/include/Platform.hpp new file mode 100644 index 000000000..3f3dc91f1 --- /dev/null +++ b/UE4SS/include/Platform.hpp @@ -0,0 +1,5 @@ +#pragma once +#include + +std::filesystem::path get_executable_path(); +void add_dlsearch_folder(std::filesystem::path &path); diff --git a/UE4SS/include/SDKGenerator/Common.hpp b/UE4SS/include/SDKGenerator/Common.hpp index ce5793824..5280e7d88 100644 --- a/UE4SS/include/SDKGenerator/Common.hpp +++ b/UE4SS/include/SDKGenerator/Common.hpp @@ -31,19 +31,19 @@ namespace RC }; auto is_integral_type(Unreal::FProperty* property) -> bool; - auto get_native_enum_name(Unreal::UEnum* uenum, bool include_type = true) -> File::StringType; + auto get_native_enum_name(Unreal::UEnum* uenum, bool include_type = true) -> SystemStringType; auto generate_property_cxx_name(Unreal::FProperty* property, bool is_top_level_declaration, Unreal::UObject* class_context, - EnableForwardDeclarations = EnableForwardDeclarations::No) -> File::StringType; - auto generate_property_lua_name(Unreal::FProperty* property, bool is_top_level_declaration, Unreal::UObject* class_context) -> File::StringType; - auto sanitize_property_name(const File::StringType& property_name) -> File::StringType; - auto generate_delegate_name(Unreal::FProperty* property, const File::StringType& context_name) -> File::StringType; - auto get_native_class_name(Unreal::UClass* uclass, bool interface_name = false) -> File::StringType; - auto get_native_struct_name(Unreal::UScriptStruct* script_struct) -> File::StringType; + EnableForwardDeclarations = EnableForwardDeclarations::No) -> SystemStringType; + auto generate_property_lua_name(Unreal::FProperty* property, bool is_top_level_declaration, Unreal::UObject* class_context) -> SystemStringType; + auto sanitize_property_name(const SystemStringType& property_name) -> SystemStringType; + auto generate_delegate_name(Unreal::FProperty* property, const SystemStringType& context_name) -> SystemStringType; + auto get_native_class_name(Unreal::UClass* uclass, bool interface_name = false) -> SystemStringType; + auto get_native_struct_name(Unreal::UScriptStruct* script_struct) -> SystemStringType; auto get_native_delegate_type_name(Unreal::UFunction* signature_function, Unreal::UClass* current_class = nullptr, bool strip_outer_name = false) - -> File::StringType; + -> SystemStringType; auto is_delegate_signature_function(Unreal::UFunction* signature_function) -> bool; - auto strip_delegate_signature_postfix(Unreal::UFunction* signature_function) -> File::StringType; + auto strip_delegate_signature_postfix(Unreal::UFunction* signature_function) -> SystemStringType; } // namespace UEGenerator } // namespace RC diff --git a/UE4SS/include/SDKGenerator/JSONDumper.hpp b/UE4SS/include/SDKGenerator/JSONDumper.hpp index fea36c867..1a117118c 100644 --- a/UE4SS/include/SDKGenerator/JSONDumper.hpp +++ b/UE4SS/include/SDKGenerator/JSONDumper.hpp @@ -9,5 +9,5 @@ namespace RC namespace RC::UEGenerator::JSONDumper { - auto dump_to_json(File::StringViewType file_name) -> void; + auto dump_to_json(SystemStringType file_name) -> void; } diff --git a/UE4SS/include/SDKGenerator/TMapOverrideGen.hpp b/UE4SS/include/SDKGenerator/TMapOverrideGen.hpp index 31e76d6c5..6a93735a1 100644 --- a/UE4SS/include/SDKGenerator/TMapOverrideGen.hpp +++ b/UE4SS/include/SDKGenerator/TMapOverrideGen.hpp @@ -7,12 +7,12 @@ namespace RC::UEGenerator { - using RC::Unreal::FName; + using ::RC::Unreal::FName; class TMapOverrideGenerator { public: - static std::unordered_set MapProperties; + static ::std::unordered_set MapProperties; static auto generate_tmapoverride() -> void; }; } // namespace RC::UEGenerator diff --git a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp index 59cf49670..a3822f3ed 100644 --- a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp +++ b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include @@ -26,15 +28,15 @@ namespace RC::Unreal namespace RC::UEGenerator { - using FFilePath = std::filesystem::path; - using UObject = RC::Unreal::UObject; - using UStruct = RC::Unreal::UStruct; - using UClass = RC::Unreal::UClass; - using FProperty = RC::Unreal::FProperty; - using FField = RC::Unreal::FField; - using UEnum = RC::Unreal::UEnum; - using UScriptStruct = RC::Unreal::UScriptStruct; - using UFunction = RC::Unreal::UFunction; + using FFilePath = ::std::filesystem::path; + using UObject = ::RC::Unreal::UObject; + using UStruct = ::RC::Unreal::UStruct; + using UClass = ::RC::Unreal::UClass; + using FProperty = ::RC::Unreal::FProperty; + using FField = ::RC::Unreal::FField; + using UEnum = ::RC::Unreal::UEnum; + using UScriptStruct = ::RC::Unreal::UScriptStruct; + using UFunction = ::RC::Unreal::UFunction; enum class DependencyLevel { @@ -65,14 +67,14 @@ namespace RC::UEGenerator struct PropertyTypeDeclarationContext { - std::wstring context_name; + SystemStringType context_name; class GeneratedSourceFile* source_file; bool is_top_level_declaration; bool* out_is_bitmask_bool; - PropertyTypeDeclarationContext(const std::wstring& context_name, + PropertyTypeDeclarationContext(const SystemStringType& context_name, GeneratedSourceFile* source_file = NULL, bool is_top_level_declaration = false, bool* out_is_bitmask_bool = NULL) @@ -91,21 +93,26 @@ namespace RC::UEGenerator struct StringInsensitiveCompare { - auto operator()(const std::wstring& a, const std::wstring& b) const -> bool + auto operator()(const SystemStringType& a, const SystemStringType& b) const -> bool { + #ifdef LINUX + return strcasecmp(a.c_str(), b.c_str()) < 0; + + #else return _wcsicmp(a.c_str(), b.c_str()) < 0; + #endif } }; - using CaseInsensitiveSet = std::set; + using CaseInsensitiveSet = ::std::set; class GeneratedFile { protected: - std::wstring m_file_base_name; + SystemStringType m_file_base_name; FFilePath m_full_file_path; - std::wstring m_file_contents_buffer; + SystemStringType m_file_contents_buffer; int32_t m_current_indent_count; public: @@ -117,34 +124,52 @@ namespace RC::UEGenerator GeneratedFile(GeneratedFile&&) = default; auto operator=(const GeneratedFile&) -> void = delete; - auto append_line(const std::wstring& line) -> void; - auto append_line_no_indent(const std::wstring& line) -> void; + auto append_line(const SystemStringType& line) -> void; + auto append_line_no_indent(const SystemStringType& line) -> void; auto begin_indent_level() -> void; auto end_indent_level() -> void; auto serialize_file_content_to_disk() -> bool; virtual auto has_content_to_save() const -> bool; - virtual auto generate_file_contents() -> std::wstring; + virtual auto generate_file_contents() -> SystemStringType; }; class GeneratedSourceFile : public GeneratedFile { private: - std::wstring m_file_module_name; - std::map m_dependencies; - std::set m_extra_includes; - mutable std::set m_dependency_module_names; + SystemStringType m_file_module_name; + ::std::map m_dependencies; + ::std::set m_extra_includes; + mutable ::std::set m_dependency_module_names; UObject* m_object; GeneratedSourceFile* m_header_file; bool m_is_implementation_file; bool m_needs_get_type_hash; public: - std::wstring m_implementation_constructor; - std::unordered_set parent_property_names{}; - std::map> attachments{}; - - GeneratedSourceFile(const FFilePath& file_path, const std::wstring& file_module_name, bool is_implementation_file, UObject* object); + // workaround for clang tuple bug + // https://github.com/llvm/llvm-project/issues/17042 + struct attachment_data { + SystemStringType property_type; // <0> + SystemStringType attach_string; // <1> + bool access_type; // <2> + + attachment_data(const SystemStringType& property_type, const SystemStringType& attach_string, bool access_type) + : property_type(property_type), attach_string(attach_string), access_type(access_type) + { + } + + attachment_data(const attachment_data& other) = default; + attachment_data(attachment_data&& other) = default; + auto operator=(const attachment_data&) -> attachment_data& = default; + auto operator=(attachment_data&&) -> attachment_data& = default; + + }; + SystemStringType m_implementation_constructor; + ::std::unordered_set parent_property_names{}; + ::std::map attachments{}; + + GeneratedSourceFile(const FFilePath& file_path, const SystemStringType& file_module_name, bool is_implementation_file, UObject* object); // Delete copy and move constructors and assignment operator GeneratedSourceFile(const GeneratedSourceFile&) = delete; @@ -153,9 +178,9 @@ namespace RC::UEGenerator auto set_header_file(GeneratedSourceFile* header_file) -> void; auto add_dependency_object(UObject* object, DependencyLevel dependency_level) -> void; - auto add_extra_include(const std::wstring& included_file_name) -> void; + auto add_extra_include(const SystemStringType& included_file_name) -> void; - auto get_header_module_name() const -> const std::wstring& + auto get_header_module_name() const -> const SystemStringType& { return m_file_module_name; } @@ -179,30 +204,30 @@ namespace RC::UEGenerator virtual auto has_content_to_save() const -> bool override; - auto copy_dependency_module_names(std::set& out_dependency_module_names) const -> void + auto copy_dependency_module_names(::std::set& out_dependency_module_names) const -> void { out_dependency_module_names.insert(m_dependency_module_names.begin(), m_dependency_module_names.end()); } auto static create_source_file(const FFilePath& root_dir, - const std::wstring& module_name, - const std::wstring& base_name, + const SystemStringType& module_name, + const SystemStringType& base_name, bool is_implementation_file, UObject* object) -> GeneratedSourceFile; - virtual auto generate_file_contents() -> std::wstring override; + virtual auto generate_file_contents() -> SystemStringType override; protected: auto has_dependency(UObject* object, DependencyLevel dependency_level) -> bool; - auto generate_pre_declarations_string() const -> std::wstring; - auto generate_includes_string() const -> std::wstring; + auto generate_pre_declarations_string() const -> SystemStringType; + auto generate_includes_string() const -> SystemStringType; }; struct UniqueName { static constexpr int32_t HAS_NO_DUPLICATES = 1; - File::StringType name{}; + SystemStringType name{}; int32_t usable_id{HAS_NO_DUPLICATES}; }; @@ -210,26 +235,26 @@ namespace RC::UEGenerator { private: FFilePath m_root_directory; - std::wstring m_primary_module_name; + SystemStringType m_primary_module_name; - std::set m_forced_module_dependencies; - std::set m_ignored_module_names; - std::set m_classes_with_object_initializer; + ::std::set m_forced_module_dependencies; + ::std::set m_ignored_module_names; + ::std::set m_classes_with_object_initializer; - std::unordered_map m_underlying_enum_types; - std::set m_blueprint_visible_enums; - std::set m_blueprint_visible_structs; - std::map>> m_module_dependencies; + ::std::unordered_map m_underlying_enum_types; + ::std::set m_blueprint_visible_enums; + ::std::set m_blueprint_visible_structs; + ::std::map>> m_module_dependencies; - std::vector m_header_files; - std::unordered_set m_structs_that_need_get_type_hash; + ::std::vector m_header_files; + ::std::unordered_set m_structs_that_need_get_type_hash; // Storage to ensure that we don't have duplicate file names - static std::map m_used_file_names; - static std::map m_dependency_object_to_unique_id; + static ::std::map m_used_file_names; + static ::std::map m_dependency_object_to_unique_id; // Storage for class defaultsubojects when populating property initializers - std::unordered_map m_class_subobjects; + ::std::unordered_map m_class_subobjects; public: UEHeaderGenerator(const FFilePath& root_directory); @@ -243,8 +268,8 @@ namespace RC::UEGenerator auto dump_native_packages() -> void; auto generate_object_description_file(UObject* object) -> bool; - auto generate_module_build_file(const std::wstring& module_name) -> void; - auto generate_module_implementation_file(const std::wstring& module_name) -> void; + auto generate_module_build_file(const SystemStringType& module_name) -> void; + auto generate_module_implementation_file(const SystemStringType& module_name) -> void; private: auto generate_interface_definition(UClass* function, GeneratedSourceFile& header_data) -> void; @@ -264,7 +289,7 @@ namespace RC::UEGenerator const CaseInsensitiveSet& blacklisted_property_names, bool generate_as_override = false) -> void; - auto generate_property_value(UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const std::wstring& property_scope) + auto generate_property_value(UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const SystemStringType& property_scope) -> void; auto generate_function_implementation(UClass* uclass, UFunction* function, @@ -272,49 +297,49 @@ namespace RC::UEGenerator bool is_generating_interface, const CaseInsensitiveSet& blacklisted_property_names) -> void; - auto generate_interface_flags(UClass* uinterface) const -> std::wstring; - auto generate_class_flags(UClass* uclass) const -> std::wstring; - auto generate_struct_flags(UScriptStruct* script_struct) const -> std::wstring; - auto generate_enum_flags(UEnum* uenum) const -> std::wstring; - auto generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> std::wstring; - auto generate_property_flags(FProperty* property) const -> std::wstring; - auto generate_function_argument_flags(FProperty* property) const -> std::wstring; - auto generate_function_flags(UFunction* function, bool is_function_pure_virtual = false) const -> std::wstring; + auto generate_interface_flags(UClass* uinterface) const -> SystemStringType; + auto generate_class_flags(UClass* uclass) const -> SystemStringType; + auto generate_struct_flags(UScriptStruct* script_struct) const -> SystemStringType; + auto generate_enum_flags(UEnum* uenum) const -> SystemStringType; + auto generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> SystemStringType; + auto generate_property_flags(FProperty* property) const -> SystemStringType; + auto generate_function_argument_flags(FProperty* property) const -> SystemStringType; + auto generate_function_flags(UFunction* function, bool is_function_pure_virtual = false) const -> SystemStringType; auto generate_function_parameter_list(UClass* property, UFunction* function, GeneratedSourceFile& header_data, bool generate_comma_before_name, - const std::wstring& context_name, + const SystemStringType& context_name, const CaseInsensitiveSet& blacklisted_property_names, - int32_t* out_num_params = NULL) -> std::wstring; - auto generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const std::wstring& ContextName) -> std::wstring; + int32_t* out_num_params = NULL) -> SystemStringType; + auto generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType; - auto generate_enum_value(UEnum* uenum, int64_t enum_value) -> std::wstring; + auto generate_enum_value(UEnum* uenum, int64_t enum_value) -> SystemStringType; auto generate_simple_assignment_expression(FProperty* property, - const std::wstring& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const std::wstring& property_scope, - const std::wstring& operator_type = STR(" = ")) -> void; + const SystemStringType& property_scope, + const SystemStringType& operator_type = SYSSTR(" = ")) -> void; auto generate_advanced_assignment_expression(FProperty* property, - const std::wstring& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const std::wstring& property_scope, - const std::wstring& property_type, - const std::wstring& operator_type = STR(" = ")) -> void; + const SystemStringType& property_scope, + const SystemStringType& property_type, + const SystemStringType& operator_type = SYSSTR(" = ")) -> void; - auto static generate_parameter_count_string(int32_t parameter_count) -> std::wstring; - auto static determine_primary_game_module_name() -> std::wstring; + auto static generate_parameter_count_string(int32_t parameter_count) -> SystemStringType; + auto static determine_primary_game_module_name() -> SystemStringType; public: - auto add_module_and_sub_module_dependencies(std::set& out_module_dependencies, const std::wstring& module_name, bool add_self_module = true) + auto add_module_and_sub_module_dependencies(::std::set& out_module_dependencies, const SystemStringType& module_name, bool add_self_module = true) -> void; auto static collect_blacklisted_property_names(UObject* property) -> CaseInsensitiveSet; - auto static generate_object_pre_declaration(UObject* object) -> std::vector>; + auto static generate_object_pre_declaration(UObject* object) -> ::std::vector<::std::vector>; - auto static convert_module_name_to_api_name(const std::wstring& module_name) -> std::wstring; - auto static get_module_name_for_package(UObject* package) -> std::wstring; - auto static sanitize_enumeration_name(const std::wstring& enumeration_name) -> std::wstring; + auto static convert_module_name_to_api_name(const SystemStringType& module_name) -> SystemStringType; + auto static get_module_name_for_package(UObject* package) -> SystemStringType; + auto static sanitize_enumeration_name(const SystemStringType& enumeration_name) -> SystemStringType; auto static get_highest_enum(UEnum* uenum) -> int64_t; auto static get_lowest_enum(UEnum* uenum) -> int64_t; @@ -325,8 +350,8 @@ namespace RC::UEGenerator auto static append_access_modifier(GeneratedSourceFile& header_data, AccessModifier needed_access, AccessModifier& current_access) -> void; auto static get_property_access_modifier(FProperty* property) -> AccessModifier; auto static get_function_access_modifier(UFunction* function) -> AccessModifier; - auto static create_string_literal(const std::wstring& string) -> std::wstring; - auto static get_header_name_for_object(UObject* object, bool get_existing_header = false) -> std::wstring; - auto static generate_cross_module_include(UObject* object, const std::wstring& module_name, const std::wstring& fallback_name) -> std::wstring; + auto static create_string_literal(const SystemStringType& string) -> SystemStringType; + auto static get_header_name_for_object(UObject* object, bool get_existing_header = false) -> SystemStringType; + auto static generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) -> SystemStringType; }; } // namespace RC::UEGenerator diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index 321497282..a2186e21c 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -5,7 +5,10 @@ #include #include + +#ifdef HAS_GUI #include +#endif namespace RC { @@ -61,7 +64,10 @@ namespace RC bool DebugConsoleEnabled{true}; bool DebugConsoleVisible{true}; float DebugGUIFontScaling{1.0}; + #ifdef HAS_GUI GUI::GfxBackend GraphicsAPI{GUI::GfxBackend::GLFW3_OpenGL3}; + #endif + int64_t LiveViewObjectsPerGroup{64 * 1024 / 2}; } Debug; struct SectionCrashDump diff --git a/UE4SS/include/Signatures.hpp b/UE4SS/include/Signatures.hpp index f2951bc79..e5e7f2174 100644 --- a/UE4SS/include/Signatures.hpp +++ b/UE4SS/include/Signatures.hpp @@ -21,7 +21,7 @@ namespace RC using LuaScriptMatchFoundFunc = const std::function; using LuaScriptScanCompleteFunc = const std::function; - auto scan_from_lua_script(std::wstring& script_file_path_and_name, + auto scan_from_lua_script(SystemStringType& script_file_path_and_name, std::vector&, LuaScriptMatchFoundFunc& match_found_func, LuaScriptScanCompleteFunc& scan_complete_func = &scan_complete_default_func) -> void; diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index 672e92ec6..5493df83b 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -7,14 +7,25 @@ #include #include +#ifdef WIN32 #include +#endif #include + +#ifdef HAS_GUI #include #include +#endif + +#ifdef HAS_INPUT #include +#endif + #include #include +#ifdef HAS_CPPMOD #include +#endif #include #include #include @@ -80,13 +91,12 @@ namespace RC class UE4SSProgram : public MProgram { - public: friend class CppUserModBase; // m_input_handler public: - constexpr static wchar_t m_settings_file_name[] = L"UE4SS-settings.ini"; - constexpr static wchar_t m_log_file_name[] = L"UE4SS.log"; - constexpr static wchar_t m_object_dumper_file_name[] = L"UE4SS_ObjectDump.txt"; + constexpr static SystemCharType m_settings_file_name[] = SYSSTR("UE4SS-settings.ini"); + constexpr static SystemCharType m_log_file_name[] = SYSSTR("UE4SS.log"); + constexpr static SystemCharType m_object_dumper_file_name[] = SYSSTR("UE4SS_ObjectDump.txt"); public: RC_UE4SS_API static SettingsManager settings_manager; @@ -96,21 +106,30 @@ namespace RC bool m_is_program_started; protected: - Input::Handler m_input_handler{L"ConsoleWindowClass", L"UnrealWindow"}; +#ifdef HAS_INPUT + Input::Handler m_input_handler{SYSSTR("ConsoleWindowClass"), SYSSTR("UnrealWindow")}; +#endif std::jthread m_event_loop; public: +#ifdef HAS_GUI std::jthread m_render_thread; - +#endif private: +#ifdef WIN32 CrashDumper m_crash_dumper{}; - +#endif private: std::filesystem::path m_game_path_and_exe_name; std::filesystem::path m_root_directory; std::filesystem::path m_module_file_path; std::filesystem::path m_working_directory; std::filesystem::path m_mods_directory; + + SystemStringType m_module_file_path_str; + SystemStringType m_working_directory_str; + SystemStringType m_mods_directory_str; + std::filesystem::path m_game_executable_directory; std::filesystem::path m_log_directory; std::filesystem::path m_object_dumper_output_directory; @@ -119,7 +138,10 @@ namespace RC std::filesystem::path m_legacy_root_directory; Output::DebugConsoleDevice* m_debug_console_device{}; Output::ConsoleDevice* m_console_device{}; + +#ifdef HAS_GUI GUI::DebuggingGUI m_debugging_gui{}; +#endif using EventCallable = void (*)(void* data); struct Event @@ -131,6 +153,7 @@ namespace RC std::mutex m_event_queue_mutex{}; private: +#ifdef WIN32 std::unique_ptr m_load_library_a_hook; uint64_t m_hook_trampoline_load_library_a; @@ -142,6 +165,7 @@ namespace RC std::unique_ptr m_load_library_ex_w_hook; uint64_t m_hook_trampoline_load_library_ex_w; +#endif public: static inline std::vector> m_mods; @@ -168,19 +192,19 @@ namespace RC }; public: - UE4SSProgram(const std::wstring& ModuleFilePath, std::initializer_list options); + UE4SSProgram(const SystemStringType& ModuleFilePath, std::initializer_list options); ~UE4SSProgram(); UE4SSProgram(const UE4SSProgram&) = delete; UE4SSProgram(UE4SSProgram&&) = delete; private: - auto setup_paths(const std::wstring& moduleFilePath) -> void; + auto setup_paths(const SystemStringType& moduleFilePath) -> void; enum class FunctionStatus { Success, Failure, }; - auto create_emergency_console_for_early_error(File::StringViewType error_message) -> void; + auto create_emergency_console_for_early_error(SystemStringViewType error_message) -> void; auto setup_mod_directory_path() -> void; auto create_simple_console() -> void; auto setup_unreal() -> void; @@ -204,21 +228,21 @@ namespace RC auto fire_unreal_init_for_cpp_mods() -> void; auto fire_ui_init_for_cpp_mods() -> void; auto fire_program_start_for_cpp_mods() -> void; - auto fire_dll_load_for_cpp_mods(std::wstring_view dll_name) -> void; + auto fire_dll_load_for_cpp_mods(SystemStringViewType dll_name) -> void; public: auto init() -> void; auto is_program_started() -> bool; auto reinstall_mods() -> void; - auto get_object_dumper_output_directory() -> const File::StringType; - RC_UE4SS_API auto get_module_directory() -> File::StringViewType; - RC_UE4SS_API auto get_game_executable_directory() -> File::StringViewType; - RC_UE4SS_API auto get_working_directory() -> File::StringViewType; - RC_UE4SS_API auto get_mods_directory() -> File::StringViewType; - RC_UE4SS_API auto get_legacy_root_directory() -> File::StringViewType; + auto get_object_dumper_output_directory() -> const SystemStringType; + RC_UE4SS_API auto get_module_directory() -> SystemStringViewType; + RC_UE4SS_API auto get_working_directory() -> SystemStringViewType; + RC_UE4SS_API auto get_mods_directory() -> SystemStringViewType; + RC_UE4SS_API auto get_legacy_root_directory() -> SystemStringViewType; RC_UE4SS_API auto generate_uht_compatible_headers() -> void; RC_UE4SS_API auto generate_cxx_headers(const std::filesystem::path& output_dir) -> void; RC_UE4SS_API auto generate_lua_types(const std::filesystem::path& output_dir) -> void; +#ifdef HAS_GUI auto get_debugging_ui() -> GUI::DebuggingGUI& { return m_debugging_gui; @@ -234,6 +258,7 @@ namespace RC { return ImGui::GetAllocatorFunctions(alloc_func, free_func, user_data); } +#endif RC_UE4SS_API auto queue_event(EventCallable callable, void* data) -> void; RC_UE4SS_API auto is_queue_empty() -> bool; RC_UE4SS_API auto can_process_events() -> bool @@ -242,6 +267,7 @@ namespace RC } public: +#ifdef HAS_INPUT // API pass-through for use outside the private scope of UE4SSProgram RC_UE4SS_API auto register_keydown_event(Input::Key, const Input::EventCallbackCallable&, uint8_t custom_data = 0, void* custom_data2 = nullptr) -> void; RC_UE4SS_API auto register_keydown_event(Input::Key, @@ -251,60 +277,40 @@ namespace RC void* custom_data2 = nullptr) -> void; RC_UE4SS_API auto is_keydown_event_registered(Input::Key) -> bool; RC_UE4SS_API auto is_keydown_event_registered(Input::Key, const Input::Handler::ModifierKeyArray&) -> bool; +#endif private: static auto install_cpp_mods() -> void; static auto install_lua_mods() -> void; using FMBNI_ExtraPredicate = std::function; - static auto find_mod_by_name_internal(std::wstring_view mod_name, + static auto find_mod_by_name_internal(SystemStringViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No, FMBNI_ExtraPredicate extra_predicate = {}) -> Mod*; public: - RC_UE4SS_API static auto dump_uobject(Unreal::UObject* object, std::unordered_set* dumped_fields, StringType& out_line, bool is_below_425) + RC_UE4SS_API static auto dump_uobject(Unreal::UObject* object, std::unordered_set* dumped_fields, SystemStringType& out_line, bool is_below_425) -> void; - RC_UE4SS_API static auto dump_xproperty(Unreal::FProperty* property, StringType& out_line) -> void; - RC_UE4SS_API static auto dump_all_objects_and_properties(const File::StringType& output_path_and_file_name) -> void; + RC_UE4SS_API static auto dump_xproperty(Unreal::FProperty* property, SystemStringType& out_line) -> void; + RC_UE4SS_API static auto dump_all_objects_and_properties(const SystemStringType& output_path_and_file_name) -> void; template - static auto find_mod_by_name(std::wstring_view mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> T* + static auto find_mod_by_name(SystemStringType mod_name, IsInstalled is_installed = IsInstalled::No, IsStarted is_started = IsStarted::No) -> T* { - std::abort(); + return static_cast(find_mod_by_name_internal(mod_name, is_installed, is_started, [](auto elem) -> bool { + return dynamic_cast(elem); + })); }; + template - static auto find_mod_by_name(std::string_view mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> T* + static auto find_mod_by_name(SystemStringViewType mod_name, IsInstalled is_installed = IsInstalled::No, IsStarted is_started = IsStarted::No) -> T* { - std::abort(); + return find_mod_by_name(to_generic_string(mod_name), is_installed, is_started); }; - template <> - auto find_mod_by_name(std::wstring_view mod_name, IsInstalled is_installed, IsStarted is_started) -> LuaMod* - { - return static_cast(find_mod_by_name_internal(mod_name, is_installed, is_started, [](auto elem) -> bool { - return dynamic_cast(elem); - })); - } - template <> - auto find_mod_by_name(std::wstring_view mod_name, IsInstalled is_installed, IsStarted is_started) -> CppMod* - { - return static_cast(find_mod_by_name_internal(mod_name, is_installed, is_started, [](auto elem) -> bool { - return dynamic_cast(elem); - })); - } - template <> - auto find_mod_by_name(std::string_view mod_name, IsInstalled is_installed, IsStarted is_started) -> LuaMod* - { - return find_mod_by_name(to_wstring(mod_name), is_installed, is_started); - } - template <> - auto find_mod_by_name(std::string_view mod_name, IsInstalled is_installed, IsStarted is_started) -> CppMod* - { - return find_mod_by_name(to_wstring(mod_name), is_installed, is_started); - } - RC_UE4SS_API static auto find_lua_mod_by_name(std::wstring_view mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; - RC_UE4SS_API static auto find_lua_mod_by_name(std::string_view mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; + RC_UE4SS_API static auto find_lua_mod_by_name(UEViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; + RC_UE4SS_API static auto find_lua_mod_by_name(SystemStringViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; static auto static_cleanup() -> void; RC_UE4SS_API static auto get_program() -> UE4SSProgram& { @@ -312,9 +318,11 @@ namespace RC } private: +#ifdef WIN32 friend void* HookedLoadLibraryA(const char* dll_name); friend void* HookedLoadLibraryExA(const char* dll_name, void* file, int32_t flags); friend void* HookedLoadLibraryW(const wchar_t* dll_name); friend void* HookedLoadLibraryExW(const wchar_t* dll_name, void* file, int32_t flags); +#endif }; } // namespace RC diff --git a/UE4SS/include/USMapGenerator/writer.h b/UE4SS/include/USMapGenerator/writer.h index 3ded027cd..83c1515a2 100644 --- a/UE4SS/include/USMapGenerator/writer.h +++ b/UE4SS/include/USMapGenerator/writer.h @@ -5,6 +5,10 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-variable" +#ifdef LINUX +#define fopen_s(pFile, filename, mode) ((*(pFile)) = fopen((filename), (mode))) == NULL +#endif + class IBufferWriter { public: @@ -49,7 +53,7 @@ class StreamWriter : IBufferWriter FORCEINLINE void Seek(int Pos, int Origin = SEEK_CUR) override { - m_Stream.seekp(Pos, Origin); + m_Stream.seekp((std::streamoff) Pos, (std::ios_base::seekdir) Origin); } uint32_t Size() override diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp new file mode 100644 index 000000000..8c0e417bb --- /dev/null +++ b/UE4SS/src/EntryLinux.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include "UE4SSProgram.hpp" +#include "Platform.hpp" + +#include +#include +#include +#include + +using namespace RC; + +pthread_t ue4ss_mainthread; + +// constrcutor +void __attribute__((constructor)) UE4SS_Start() +{ + // find libUE4SS.so path using dlfcn + Dl_info dl_info; + if (dladdr((void *)UE4SS_Start, &dl_info) == 0) + { + std::cerr << "Failed to find libUE4SS.so path" << std::endl; + return; + } + + SystemStringType ue4sspath = to_generic_string(dl_info.dli_fname); + auto program = new UE4SSProgram(ue4sspath, {}); + // use pthread here + pthread_create(&ue4ss_mainthread, nullptr, [](void *arg) -> void * { + auto program = (UE4SSProgram *)arg; + program->init(); + + if (auto e = program->get_error_object(); e->has_error()) + { + // If the output system errored out then use printf_s as a fallback + // Logging will only happen to the debug console but it's something at least + if (!Output::has_internal_error()) + { + Output::send(SYSSTR("Fatal Error: {}\n"), to_generic_string(e->get_message())); + } + else + { + printf("Error: %s\n", e->get_message()); + } + } + return nullptr; + }, program); +} + +// destructor +void __attribute__((destructor)) UE4SS_End() +{ + UE4SSProgram::static_cleanup(); +} + +std::filesystem::path get_executable_path() { + // get executable path on Linux + char result[1024]; + ssize_t count = readlink("/proc/self/exe", result, 1023); + return std::filesystem::path(std::string(result, (count > 0) ? count : 0)); +} + +void add_dlsearch_folder(std::filesystem::path &path) { + // not implemented +} diff --git a/UE4SS/src/main_ue4ss_rewritten.cpp b/UE4SS/src/EntryWin32.cpp similarity index 89% rename from UE4SS/src/main_ue4ss_rewritten.cpp rename to UE4SS/src/EntryWin32.cpp index a6b836933..1673a7914 100644 --- a/UE4SS/src/main_ue4ss_rewritten.cpp +++ b/UE4SS/src/EntryWin32.cpp @@ -7,6 +7,8 @@ #include #include "UE4SSProgram.hpp" +#include "Platform.hpp" + #include #include @@ -131,4 +133,17 @@ auto WIN_API_FUNCTION_NAME(HMODULE hModule, DWORD ul_reason_for_call, [[maybe_un break; } return TRUE; -} \ No newline at end of file +} + +std::filesystem::path get_executable_path() { + wchar_t exe_path_buffer[1024]; + GetModuleFileNameW(GetModuleHandle(nullptr), exe_path_buffer, 1023); + return std::filesystem::path(buffer); +} + + +void add_dlsearch_folder(std::filesystem::path &path) { + SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + // Make sure game directory DLLs are also included + AddDllDirectory(path.c_str()); +} diff --git a/UE4SS/src/GUI/BPMods.cpp b/UE4SS/src/GUI/BPMods.cpp index b5507c6ba..77061995f 100644 --- a/UE4SS/src/GUI/BPMods.cpp +++ b/UE4SS/src/GUI/BPMods.cpp @@ -113,7 +113,7 @@ namespace RC::GUI::BPMods const auto& mod_button = mod_info.ModButtons[i2]; if (ImGui::Button(std::format("{}", mod_button).c_str())) { - Output::send(STR("Mod button {} hit.\n"), to_wstring(mod_button)); + Output::send(SYSSTR("Mod button {} hit.\n"), to_generic_string(mod_button)); mod_info.ModActor->ModMenuButtonPressed(static_cast(i2)); } } diff --git a/UE4SS/src/GUI/Console.cpp b/UE4SS/src/GUI/Console.cpp index b0150c9a5..aa781d920 100644 --- a/UE4SS/src/GUI/Console.cpp +++ b/UE4SS/src/GUI/Console.cpp @@ -107,14 +107,14 @@ namespace RC::GUI bool reclaim_focus{}; ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; auto text_edit_callback_wrapper = [](ImGuiInputTextCallbackData* data) -> int { Console* console = - static_cast(data->UserData); Output::send(STR("text_edit_callback_wrapper\n")); + static_cast(data->UserData); Output::send(SYSSTR("text_edit_callback_wrapper\n")); //return console->text_edit_callback(data); return 0; }; ImGui::PushItemWidth(-12.0f); if (ImGui::InputText("##console_input_buffer", m_input_buffer, IM_ARRAYSIZE(m_input_buffer), input_text_flags, text_edit_callback_wrapper, this)) { - Output::send(STR("ConsoleInput\n")); + Output::send(SYSSTR("ConsoleInput\n")); reclaim_focus = true; } ImGui::PopItemWidth(); diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index a2ddc0028..460a4923f 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -90,17 +90,17 @@ namespace RC::GUI::Dumpers auto location = root_component->GetValuePtrByPropertyNameInChain(STR("RelativeLocation")); FString location_string{}; location_property->ExportTextItem(location_string, location, nullptr, nullptr, 0); - root_actor_buffer.append(std::format(STR("\"{}\","), location_string.GetCharArray())); + root_actor_buffer.append(std::format(SYSSTR("\"{}\","), location_string.GetCharArray())); auto rotation = root_component->GetValuePtrByPropertyNameInChain(STR("RelativeRotation")); FString rotation_string{}; rotation_property->ExportTextItem(rotation_string, rotation, nullptr, nullptr, 0); - root_actor_buffer.append(std::format(STR("\"{}\","), rotation_string.GetCharArray())); + root_actor_buffer.append(std::format(SYSSTR("\"{}\","), rotation_string.GetCharArray())); auto scale = root_component->GetValuePtrByPropertyNameInChain(STR("RelativeScale3D")); FString scale_string{}; scale_property->ExportTextItem(scale_string, scale, nullptr, nullptr, 0); - root_actor_buffer.append(std::format(STR("\"{}\","), scale_string.GetCharArray())); + root_actor_buffer.append(std::format(SYSSTR("\"{}\","), scale_string.GetCharArray())); return root_actor_buffer; } @@ -128,13 +128,13 @@ namespace RC::GUI::Dumpers StringType actor_buffer{}; - actor_buffer.append(std::format(STR("Row_{},"), actor_count)); + actor_buffer.append(std::format(SYSSTR("Row_{},"), actor_count)); static auto game_mode_base = UObjectGlobals::FindFirstOf(STR("GameModeBase")); static auto class_property = game_mode_base->GetPropertyByNameInChain(STR("GameStateClass")); FString actor_class_string{}; class_property->ExportTextItem(actor_class_string, &actor->GetClassPrivate(), nullptr, nullptr, 0); - actor_buffer.append(std::format(STR("{},"), actor_class_string.GetCharArray())); + actor_buffer.append(std::format(SYSSTR("{},"), actor_class_string.GetCharArray())); // TODO: build system to handle other types of components - possibly including a way to specify which components to dump and which properties are important via a config file actor_buffer.append(generate_root_component_csv(*root_component)); @@ -157,7 +157,7 @@ namespace RC::GUI::Dumpers static auto mesh_property = static_mesh_component_ptr->GetPropertyByNameInChain(STR("StaticMesh")); FString mesh_string{}; mesh_property->ExportTextItem(mesh_string, &mesh, nullptr, nullptr, 0); - actor_buffer.append(std::format(STR("(StaticMesh={}',"), mesh_string.GetCharArray())); + actor_buffer.append(std::format(SYSSTR("(StaticMesh={}',"), mesh_string.GetCharArray())); auto materials_for_each_body = [&](const UObject* material_interface) { if (material_interface) @@ -178,8 +178,8 @@ namespace RC::GUI::Dumpers auto material_typeless_name = StringViewType{material_full_name.begin() + static_cast(material_type_space_location) + 1, material_full_name.end()}; - actor_buffer.append(std::format(STR("{}'"), material_interface->GetClassPrivate()->GetName())); - actor_buffer.append(std::format(STR("\"\"{}"), material_typeless_name)); + actor_buffer.append(std::format(SYSSTR("{}'"), material_interface->GetClassPrivate()->GetName())); + actor_buffer.append(std::format(SYSSTR("\"\"{}"), material_typeless_name)); actor_buffer.append(STR("\"\"'")); } }; @@ -264,19 +264,19 @@ namespace RC::GUI::Dumpers auto& actor_json_object = global_json_array.new_object(); - actor_json_object.new_string(STR("Name"), std::format(STR("Row_{}"), actor_count)); + actor_json_object.new_string(STR("Name"), std::format(SYSSTR("Row_{}"), actor_count)); static auto game_mode_base = UObjectGlobals::FindFirstOf(STR("GameModeBase")); static auto class_property = game_mode_base->GetPropertyByNameInChain(STR("GameStateClass")); FString actor_class_string{}; class_property->ExportTextItem(actor_class_string, &actor->GetClassPrivate(), nullptr, nullptr, 0); - actor_json_object.new_string(STR("Actor"), std::format(STR("{}"), StringViewType{actor_class_string.GetCharArray()})); + actor_json_object.new_string(STR("Actor"), std::format(SYSSTR("{}"), StringViewType{actor_class_string.GetCharArray()})); auto& root_component_json_object = actor_json_object.new_object(STR("RootComponent")); FString root_component_class_string{}; class_property->ExportTextItem(root_component_class_string, &(*root_component)->GetClassPrivate(), nullptr, nullptr, 0); - root_component_json_object.new_string(STR("SceneComponentClass"), std::format(STR("{}"), StringViewType{root_component_class_string.GetCharArray()})); + root_component_json_object.new_string(STR("SceneComponentClass"), std::format(SYSSTR("{}"), StringViewType{root_component_class_string.GetCharArray()})); auto& location_json_object = root_component_json_object.new_object(STR("Location")); auto location = (*root_component)->GetValuePtrByPropertyNameInChain(STR("RelativeLocation")); @@ -308,30 +308,30 @@ namespace RC::GUI::Dumpers void call_generate_static_mesh_file() { - Output::send(STR("Dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); + Output::send(SYSSTR("Dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); static auto dump_actor_class = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.StaticMeshActor")); std::wstring file_buffer{}; file_buffer.append(generate_actors_csv_file(dump_actor_class)); auto file = - File::open(std::format(STR("{}\\{}-ue4ss_static_mesh_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), + File::open(std::format(SYSSTR("{}\\{}-ue4ss_static_mesh_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); file.write_string_to_file(file_buffer); - Output::send(STR("Finished dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); + Output::send(SYSSTR("Finished dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); } void call_generate_all_actor_file() { - Output::send(STR("Dumping CSV of all loaded actor types, positions and mesh properties\n")); + Output::send(SYSSTR("Dumping CSV of all loaded actor types, positions and mesh properties\n")); std::wstring file_buffer{}; file_buffer.append(generate_actors_csv_file(AActor::StaticClass())); - auto file = File::open(std::format(STR("{}\\{}-ue4ss_actor_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), + auto file = File::open(std::format(SYSSTR("{}\\{}-ue4ss_actor_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); file.write_string_to_file(file_buffer); - Output::send(STR("Finished dumping CSV of all loaded actor types, positions and mesh properties\n")); + Output::send(SYSSTR("Finished dumping CSV of all loaded actor types, positions and mesh properties\n")); } auto render() -> void diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index e770705c0..577a58ad3 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -333,7 +333,7 @@ namespace RC::GUI { if (!Output::has_internal_error()) { - Output::send(STR("Error: {}\n"), to_wstring(e.what())); + Output::send(SYSSTR("Error: {}\n"), to_generic_string(e.what())); } else { diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 70cbaec79..5623f651d 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -578,13 +578,12 @@ namespace RC::GUI static auto internal_load_watches_from_disk() -> void { - auto working_directory_path = StringType{UE4SSProgram::get_program().get_working_directory()} + std::format(STR("\\watches\\watches.meta.json")); - auto legacy_root_directory_path = StringType{UE4SSProgram::get_program().get_legacy_root_directory()} + std::format(STR("\\watches\\watches.meta.json")); + auto working_directory_path = SystemStringType{UE4SSProgram::get_program().get_working_directory()} + std::format(SYSSTR("\\watches\\watches.meta.json")); + auto legacy_root_directory_path = SystemStringType{UE4SSProgram::get_program().get_legacy_root_directory()} + std::format(SYSSTR("\\watches\\watches.meta.json")); - StringType json_file_contents; bool is_legacy = !std::filesystem::exists(working_directory_path) && std::filesystem::exists(legacy_root_directory_path); auto json_file = File::open(is_legacy ? legacy_root_directory_path : working_directory_path, File::OpenFor::Reading, File::OverwriteExistingFile::No, File::CreateIfNonExistent::Yes); - + auto json_file_contents = json_file.read_all(); if (json_file_contents.empty()) { return; @@ -673,7 +672,7 @@ namespace RC::GUI } } - auto json_file = File::open(StringType{UE4SSProgram::get_program().get_working_directory()} + std::format(STR("\\watches\\watches.meta.json")), + auto json_file = File::open(StringType{UE4SSProgram::get_program().get_working_directory()} + std::format(SYSSTR("\\watches\\watches.meta.json")), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); @@ -714,10 +713,10 @@ namespace RC::GUI { auto& file_device = output.get_device(); file_device.set_file_name_and_path(StringType{UE4SSProgram::get_program().get_working_directory()} + - std::format(STR("\\watches\\ue4ss_watch_{}_{}.txt"), object_name, property_name)); + std::format(SYSSTR("\\watches\\ue4ss_watch_{}_{}.txt"), object_name, property_name)); file_device.set_formatter([](File::StringViewType string) -> File::StringType { - const auto when_as_string = std::format(STR("{:%Y-%m-%d %H:%M:%S}"), std::chrono::system_clock::now()); - return std::format(STR("[{}] {}"), when_as_string, string); + const auto when_as_string = std::format(SYSSTR("{:%Y-%m-%d %H:%M:%S}"), std::chrono::system_clock::now()); + return std::format(SYSSTR("[{}] {}"), when_as_string, string); }); } @@ -1531,7 +1530,7 @@ namespace RC::GUI auto LiveView::search_by_name() -> void { - Output::send(STR("Searching by name...\n")); + Output::send(SYSSTR("Searching by name...\n")); s_name_search_results.clear(); s_name_search_results_set.clear(); UObjectGlobals::ForEachUObject([&](UObject* object, ...) { @@ -1685,14 +1684,14 @@ namespace RC::GUI } } - Output::send(STR("{}\n"), uclass->GetFullName()); + Output::send(SYSSTR("{}\n"), uclass->GetFullName()); ImGui::Text("Properties"); for (FProperty* property : uclass->ForEachProperty()) { if (ImGui::TreeNode(to_string(property->GetFullName()).c_str())) { - Output::send(STR("Show property: {}\n"), property->GetFullName()); + Output::send(SYSSTR("Show property: {}\n"), property->GetFullName()); } } } @@ -1987,7 +1986,7 @@ namespace RC::GUI { parent_name = obj ? obj->GetName() : STR("None"); } - auto edit_property_value_modal_name = to_string(std::format(STR("Edit value of property: {}->{}"), parent_name, property->GetName())); + auto edit_property_value_modal_name = to_string(std::format(SYSSTR("Edit value of property: {}->{}"), parent_name, property->GetName())); if (open_edit_value_popup) { @@ -2077,7 +2076,7 @@ namespace RC::GUI ImGui::TableNextColumn(); ImGui::Text("%S", enum_name.c_str()); - if (ImGui::BeginPopupContextItem(to_string(std::format(STR("context-menu-{}"), enum_name)).c_str())) + if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("context-menu-{}"), enum_name)).c_str())) { if (ImGui::MenuItem("Copy name")) { @@ -2096,7 +2095,7 @@ namespace RC::GUI ImGui::TableNextColumn(); ImGui::Text("%lld", name.Value); - if (ImGui::BeginPopupContextItem(to_string(std::format(STR("context-menu-{}-{}"), enum_name, name.Value)).c_str())) + if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("context-menu-{}-{}"), enum_name, name.Value)).c_str())) { if (ImGui::MenuItem("Copy value")) { @@ -2111,7 +2110,7 @@ namespace RC::GUI } ImGui::TableNextColumn(); - ImGui::PushID(to_string(std::format(STR("button_add_{}"), enum_name)).c_str()); + ImGui::PushID(to_string(std::format(SYSSTR("button_add_{}"), enum_name)).c_str()); if (ImGui::Button("+")) { open_add_name_popup = true; @@ -2119,18 +2118,18 @@ namespace RC::GUI } ImGui::PopID(); ImGui::SameLine(); - ImGui::PushID(to_string(std::format(STR("button_remove_{}"), enum_name)).c_str()); + ImGui::PushID(to_string(std::format(SYSSTR("button_remove_{}"), enum_name)).c_str()); if (ImGui::Button("-")) { uenum->RemoveFromNamesAt(index, 1); } ImGui::PopID(); - std::string edit_enum_name_modal_name = to_string(std::format(STR("Edit enum name for: {}"), name.Key.ToString())); + std::string edit_enum_name_modal_name = to_string(std::format(SYSSTR("Edit enum name for: {}"), name.Key.ToString())); - std::string edit_enum_value_modal_name = to_string(std::format(STR("Edit enum value for: {}"), name.Key.ToString())); + std::string edit_enum_value_modal_name = to_string(std::format(SYSSTR("Edit enum value for: {}"), name.Key.ToString())); - std::string add_enum_name_modal_name = to_string(std::format(STR("Enter new enum name after: {}"), name.Key.ToString())); + std::string add_enum_name_modal_name = to_string(std::format(SYSSTR("Enter new enum name after: {}"), name.Key.ToString())); if (open_edit_name_popup) { @@ -2907,7 +2906,7 @@ namespace RC::GUI watch.property_value = std::move(live_value_string); - const auto when_as_string = std::format(STR("{:%H:%M:%S}"), std::chrono::system_clock::now()); + const auto when_as_string = std::format(SYSSTR("{:%H:%M:%S}"), std::chrono::system_clock::now()); watch.history.append(to_string(when_as_string + STR(" ") + watch.property_value + STR("\n"))); if (watch.write_to_file) @@ -2943,10 +2942,10 @@ namespace RC::GUI auto num_params = function->GetNumParms(); - const auto when_as_string = std::format(STR("{:%H:%M:%S}"), std::chrono::system_clock::now()); - StringType buffer{std::format(STR("Received call @ {}.\n"), when_as_string)}; + const auto when_as_string = std::format(SYSSTR("{:%H:%M:%S}"), std::chrono::system_clock::now()); + StringType buffer{std::format(SYSSTR("Received call @ {}.\n"), when_as_string)}; - buffer.append(std::format(STR(" Context:\n {}\n"), context.Context->GetFullName())); + buffer.append(std::format(SYSSTR(" Context:\n {}\n"), context.Context->GetFullName())); buffer.append(STR(" Locals:\n")); bool has_local_params{}; @@ -2960,7 +2959,7 @@ namespace RC::GUI FString param_text{}; auto container_ptr = param->ContainerPtrToValuePtr(context.TheStack.Locals()); param->ExportTextItem(param_text, container_ptr, container_ptr, std::bit_cast(function), NULL); - buffer.append(std::format(STR(" {} = {}\n"), param->GetName(), param_text.GetCharArray())); + buffer.append(std::format(SYSSTR(" {} = {}\n"), param->GetName(), param_text.GetCharArray())); } if (!has_local_params) { @@ -2983,7 +2982,7 @@ namespace RC::GUI FString param_text{}; auto container_ptr = FindOutParamValueAddress(context.TheStack, param); param->ExportTextItem(param_text, container_ptr, container_ptr, std::bit_cast(function), NULL); - buffer.append(std::format(STR(" {} = {}\n"), param->GetName(), param_text.GetCharArray())); + buffer.append(std::format(SYSSTR(" {} = {}\n"), param->GetName(), param_text.GetCharArray())); } if (!has_out_params) { @@ -2997,7 +2996,7 @@ namespace RC::GUI FString return_property_text{}; auto container_ptr = context.RESULT_DECL; return_property->ExportTextItem(return_property_text, container_ptr, container_ptr, std::bit_cast(function), NULL); - buffer.append(std::format(STR(" {}"), return_property_text.GetCharArray())); + buffer.append(std::format(SYSSTR(" {}"), return_property_text.GetCharArray())); } else { @@ -3446,7 +3445,7 @@ namespace RC::GUI { if (ImGui::MenuItem(ICON_FA_COPY " Copy Full Name")) { - Output::send(STR("Copy Full Name: {}\n"), object->GetFullName()); + Output::send(SYSSTR("Copy Full Name: {}\n"), object->GetFullName()); ImGui::SetClipboardText(tree_node_name.c_str()); } if (object->IsA()) @@ -3584,7 +3583,7 @@ namespace RC::GUI auto& watch = *watch_ptr; ImGui::TableNextRow(); ImGui::TableNextColumn(); - if (ImGui::Checkbox(to_string(std::format(STR("##watch-on-off-{}"), watch.hash)).c_str(), &watch.enabled)) + if (ImGui::Checkbox(to_string(std::format(SYSSTR("##watch-on-off-{}"), watch.hash)).c_str(), &watch.enabled)) { if (watch.container->IsA()) { @@ -3598,7 +3597,7 @@ namespace RC::GUI ImGui::EndTooltip(); } ImGui::SameLine(0.0f, 2.0f); - ImGui::Checkbox(to_string(std::format(STR("##watch-write-to-file-{}"), watch.hash)).c_str(), &watch.write_to_file); + ImGui::Checkbox(to_string(std::format(SYSSTR("##watch-write-to-file-{}"), watch.hash)).c_str(), &watch.write_to_file); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -3625,12 +3624,12 @@ namespace RC::GUI ImGui::PopID(); } ImGui::TableNextColumn(); - if (ImGui::Checkbox(to_string(std::format(STR("##watch-from-disk-{}"), watch.hash)).c_str(), &watch.load_on_startup)) + if (ImGui::Checkbox(to_string(std::format(SYSSTR("##watch-from-disk-{}"), watch.hash)).c_str(), &watch.load_on_startup)) { save_watches_to_disk(); } ImGui::SetNextWindowSize({690.0f, 0.0f}); - if (ImGui::BeginPopupContextItem(to_string(std::format(STR("##watch-from-disk-settings-popup-{}"), watch.hash)).c_str())) + if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("##watch-from-disk-settings-popup-{}"), watch.hash)).c_str())) { ImGui::Text("Acquisition Method"); ImGui::Text("This determines how the watch will be reacquired."); diff --git a/UE4SS/src/GUI/SearcherWidget.cpp b/UE4SS/src/GUI/SearcherWidget.cpp index 2cb338cc8..214a68a92 100644 --- a/UE4SS/src/GUI/SearcherWidget.cpp +++ b/UE4SS/src/GUI/SearcherWidget.cpp @@ -55,7 +55,7 @@ namespace RC::GUI std::string search_buffer{m_search_by_name_buffer}; if (search_buffer.empty()) { - // Output::send(STR("Search all functions\n")); + // Output::send(SYSSTR("Search all functions\n")); m_name_to_search_by.clear(); m_current_iterator = m_all_iterator; m_is_searching_by_name = false; @@ -63,7 +63,7 @@ namespace RC::GUI } else { - // Output::send(STR("Search for: {}\n"), search_buffer.empty() ? STR("") : to_wstring(search_buffer)); + // Output::send(SYSSTR("Search for: {}\n"), search_buffer.empty() ? STR("") : to_wstring(search_buffer)); m_name_to_search_by = search_buffer; m_current_iterator = m_search_iterator; m_is_searching_by_name = true; diff --git a/UE4SS/src/GUI/UFunctionCallerWidget.cpp b/UE4SS/src/GUI/UFunctionCallerWidget.cpp index e072e6332..a0528ea79 100644 --- a/UE4SS/src/GUI/UFunctionCallerWidget.cpp +++ b/UE4SS/src/GUI/UFunctionCallerWidget.cpp @@ -150,9 +150,9 @@ namespace RC::GUI s_do_call = false; auto& function_flags = s_function->GetFunctionFlags(); function_flags |= FUNC_Exec; - Output::send(STR("Processing command: {}\n"), s_cmd); + Output::send(SYSSTR("Processing command: {}\n"), s_cmd); bool call_succeeded = s_instance->ProcessConsoleExec(s_cmd.c_str(), s_ar, s_executor); - Output::send(STR("call_succeeded: {}\n"), call_succeeded); + Output::send(SYSSTR("call_succeeded: {}\n"), call_succeeded); function_flags &= ~FUNC_Exec; } } @@ -164,13 +164,13 @@ namespace RC::GUI } auto function = m_currently_selected_function->function; - auto cmd = std::format(STR("{}"), function->GetName()); + auto cmd = std::format(SYSSTR("{}"), UEStringToSystemString(function->GetName())); for (const auto& param : m_params_for_selected_function) { - cmd.append(std::format(STR(" {}"), to_wstring(param.value_from_ui))); + cmd.append(std::format(SYSSTR(" {}"), to_wstring(param.value_from_ui))); } - Output::send(STR("Queueing command: {}\n"), cmd); + Output::send(SYSSTR("Queueing command: {}\n"), cmd); s_cmd = cmd; s_instance = instance; @@ -245,19 +245,19 @@ namespace RC::GUI static auto get_typeless_object_name(UObject* object) -> std::string { - auto object_name = to_string(object->GetFullName()); + auto object_name = UEStringToSystemString(object->GetFullName()); auto object_name_type_space_location = object_name.find(" "); if (object_name_type_space_location == object_name.npos) { - Output::send(STR("Could not copy name of PlayerController, was unable to find space in full PlayerController name: '{}'."), - to_wstring(object_name)); + Output::send(SYSSTR("Could not copy name of PlayerController, was unable to find space in full PlayerController name: '{}'."), + object_name); return {}; } else { if (object_name_type_space_location > static_cast(std::numeric_limits::max())) { - Output::send(STR("integer overflow when converting pc_name_type_space_location to signed")); + Output::send(SYSSTR("integer overflow when converting pc_name_type_space_location to signed")); return {}; } else @@ -313,7 +313,7 @@ namespace RC::GUI { m_prev_instance = instance; - auto popup_modal_id = to_string(std::format(STR("##functions-for-{}"), instance->HashObject())); + auto popup_modal_id = to_string(std::format(SYSSTR("##functions-for-{}"), instance->HashObject())); auto& is_open = is_widget_open(); if (is_open) { diff --git a/UE4SS/src/LuaLibrary.cpp b/UE4SS/src/LuaLibrary.cpp index 2d5e608e2..ec312704e 100644 --- a/UE4SS/src/LuaLibrary.cpp +++ b/UE4SS/src/LuaLibrary.cpp @@ -9,6 +9,12 @@ #include #include +#ifdef WIN32 +#include +#else +#include +#endif + namespace RC::LuaLibrary { auto get_outputdevice_ref(const LuaMadeSimple::Lua& lua) -> const Unreal::FOutputDevice* @@ -33,13 +39,13 @@ namespace RC::LuaLibrary { auto* output_device = get_outputdevice_ref(lua); - StringType formatted_string = STR("[Lua] "); - StringType outdevice_string; + SystemStringType formatted_string = SYSSTR("[Lua] "); + SystemStringType outdevice_string; if (output_device) { // Remove stack item from get_outputdevice_ref's lua_getglobal lua.discard_value(-1); - outdevice_string = STR("[Lua] "); + outdevice_string = SYSSTR("[Lua] "); } int32_t stack_size = lua.get_stack_size(); @@ -47,13 +53,13 @@ namespace RC::LuaLibrary { // lua_tostring (macro of lua_tolstring) is NOT the same as luaL_tolstring // luaL_tolstring provides tostring()-ish conversion for any value - auto lua_str = to_generic_string(luaL_tolstring(lua.get_lua_state(), i, nullptr)); + auto lua_str = to_system(luaL_tolstring(lua.get_lua_state(), i, nullptr)); if (i > 1) { // Use double tab, as single tab might make the spacing too thin in the console - formatted_string.append(STR("\t\t")); - if (output_device) outdevice_string.append(STR(" ")); + formatted_string.append(SYSSTR("\t\t")); + if (output_device) outdevice_string.append(SYSSTR(" ")); } formatted_string.append(lua_str); if (output_device) outdevice_string.append(lua_str); @@ -66,24 +72,22 @@ namespace RC::LuaLibrary if (output_device) output_device->Log(outdevice_string.c_str()); - return 0; - } - - auto deref_to_int32(const LuaMadeSimple::Lua& lua) -> int - { - if (lua.get_stack_size() != 1 || !lua.is_integer()) - { - Output::send(STR("[Fatal] Lua function 'DerefToInt32' must have only 1 parameter and it must be of type 'int'.\n")); + Output::send(SYSSTR("[Fatal] Lua function 'DerefToInt32' must have only 1 parameter and it must be of type 'int'.\n")); lua.set_nil(); return 1; } int32_t* int32_ptr = reinterpret_cast(lua.get_integer()); - int32_t int32_val = Helper::Casting::offset_deref_safe(int32_ptr, 0, GetCurrentProcess()); + #ifdef WIN32 + auto self = GetCurrentProcess(); + #else + auto self = getpid(); + #endif + int32_t int32_val = Helper::Casting::offset_deref_safe(int32_ptr, 0, self); if (int32_val == 0) { - Output::send(STR("[Fatal] Address passed to Lua function 'DerefToInt32' was not a valid pointer.\n")); + Output::send(SYSSTR("[Fatal] Address passed to Lua function 'DerefToInt32' was not a valid pointer.\n")); lua.set_nil(); return 1; } @@ -98,7 +102,7 @@ namespace RC::LuaLibrary // Logging will only happen to the debug console but it's something at least if (!Output::has_internal_error()) { - Output::send(STR("Error: {}\n"), to_wstring(e)); + Output::send(SYSSTR("Error: {}\n"), to_generic_string(e)); } else { @@ -106,31 +110,31 @@ namespace RC::LuaLibrary } } - static auto exported_function_status_to_string(ExportedFunctionStatus status) -> std::wstring_view + static auto exported_function_status_to_string(ExportedFunctionStatus status) -> SystemStringViewType { switch (status) { case ExportedFunctionStatus::NO_ERROR_TO_EXPORT: - return L"NO_ERROR_TO_EXPORT | 0"; + return SYSSTR("NO_ERROR_TO_EXPORT | 0"); case ExportedFunctionStatus::UNKNOWN_ERROR: - return L"UNKNOWN_ERROR | 7"; + return SYSSTR("UNKNOWN_ERROR | 7"); case ExportedFunctionStatus::SUCCESS: - return L"SUCCESS | 1"; + return SYSSTR("SUCCESS | 1"); case ExportedFunctionStatus::VARIABLE_NOT_FOUND: - return L"VARIABLE_NOT_FOUND | 2"; + return SYSSTR("VARIABLE_NOT_FOUND | 2"); case ExportedFunctionStatus::MOD_IS_NULLPTR: - return L"MOD_IS_NULLPTR | 3"; + return SYSSTR("MOD_IS_NULLPTR | 3"); case ExportedFunctionStatus::SCRIPT_FUNCTION_RETURNED_FALSE: - return L"SCRIPT_FUNCTION_RETURNED_FALSE | 4"; + return SYSSTR("SCRIPT_FUNCTION_RETURNED_FALSE | 4"); case ExportedFunctionStatus::UNABLE_TO_CALL_SCRIPT_FUNCTION: - return L"UNABLE_TO_CALL_SCRIPT_FUNCTION | 5"; + return SYSSTR("UNABLE_TO_CALL_SCRIPT_FUNCTION | 5"); case ExportedFunctionStatus::SCRIPT_FUNCTION_NOT_FOUND: - return L"SCRIPT_FUNCTION_NOT_FOUND | 6"; + return SYSSTR("SCRIPT_FUNCTION_NOT_FOUND | 6"); case ExportedFunctionStatus::UE4SS_NOT_INITIALIZED: - return L"UE4SS_NOT_INITIALIZED | 8"; + return SYSSTR("UE4SS_NOT_INITIALIZED | 8"); } - return L"Missed switch case"; + return SYSSTR("Missed switch case"); } auto get_lua_state_by_mod_name(const char* mod_name) -> lua_State* @@ -184,7 +188,7 @@ namespace RC::LuaLibrary if (!Unreal::UnrealInitializer::StaticStorage::bIsInitialized) { return_struct.status = ExportedFunctionStatus::UE4SS_NOT_INITIALIZED; - Output::send(STR("set_script_variable_int32 | UE4SS is not initialized\n")); + Output::send(SYSSTR("set_script_variable_int32 | UE4SS is not initialized\n")); return; } @@ -194,14 +198,14 @@ namespace RC::LuaLibrary const std::wstring variable_name_wide = std::wstring(tmp_var_name.begin(), tmp_var_name.end()); const std::string tmp_mod_name = mod_name; const std::wstring mod_name_wide = std::wstring(tmp_mod_name.begin(), tmp_mod_name.end()); - Output::send(STR("Setting variable '{}' in mod '{}' to {}\n"), variable_name_wide, mod_name_wide, new_value); + Output::send(SYSSTR("Setting variable '{}' in mod '{}' to {}\n"), variable_name_wide, mod_name_wide, new_value); //*/ auto mod = UE4SSProgram::find_lua_mod_by_name(mod_name, UE4SSProgram::IsInstalled::Yes, UE4SSProgram::IsStarted::Yes); if (!mod) { return_struct.status = ExportedFunctionStatus::MOD_IS_NULLPTR; - Output::send(STR("set_script_variable_int32 | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); + Output::send(SYSSTR("set_script_variable_int32 | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); return; } @@ -213,7 +217,7 @@ namespace RC::LuaLibrary if (type == LUA_TNIL) { return_struct.status = ExportedFunctionStatus::VARIABLE_NOT_FOUND; - Output::send(STR("set_script_variable_int32 | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); + Output::send(SYSSTR("set_script_variable_int32 | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); return; } @@ -221,7 +225,7 @@ namespace RC::LuaLibrary lua_setglobal(lua.get_lua_state(), variable_name); return_struct.status = ExportedFunctionStatus::SUCCESS; - Output::send(STR("set_script_variable_int32 | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); + Output::send(SYSSTR("set_script_variable_int32 | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); } catch (std::runtime_error& e) { @@ -240,7 +244,7 @@ namespace RC::LuaLibrary if (!Unreal::UnrealInitializer::StaticStorage::bIsInitialized) { return_struct.status = ExportedFunctionStatus::UE4SS_NOT_INITIALIZED; - Output::send(STR("set_script_variable_default_data | UE4SS is not initialized\n")); + Output::send(SYSSTR("set_script_variable_default_data | UE4SS is not initialized\n")); return; } @@ -257,11 +261,11 @@ namespace RC::LuaLibrary { const std::string tmp_data1_value_ansi = external_data.data1.as_string; const std::wstring data1_value_wide = std::wstring(tmp_data1_value_ansi.begin(), tmp_data1_value_ansi.end()); - Output::send(STR("Setting '{}.data1' as string to '{}' in mod '{}'"), variable_name_wide, data1_value_wide, mod_name_wide); + Output::send(SYSSTR("Setting '{}.data1' as string to '{}' in mod '{}'"), variable_name_wide, data1_value_wide, mod_name_wide); break; } case DefaultDataType::Float: - Output::send(STR("Setting '{}.data1' as float to '{}' in mod '{}'"), variable_name_wide, external_data.data1.as_float, mod_name_wide); + Output::send(SYSSTR("Setting '{}.data1' as float to '{}' in mod '{}'"), variable_name_wide, external_data.data1.as_float, mod_name_wide); break; } //*/ @@ -270,7 +274,7 @@ namespace RC::LuaLibrary if (!mod) { return_struct.status = ExportedFunctionStatus::MOD_IS_NULLPTR; - Output::send(STR("set_script_variable_default_data | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); + Output::send(SYSSTR("set_script_variable_default_data | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); return; } @@ -347,7 +351,7 @@ namespace RC::LuaLibrary if (!Unreal::UnrealInitializer::StaticStorage::bIsInitialized) { return_struct.status = ExportedFunctionStatus::UE4SS_NOT_INITIALIZED; - Output::send(STR("call_script_function | UE4SS is not initialized\n")); + Output::send(SYSSTR("call_script_function | UE4SS is not initialized\n")); return; } @@ -357,14 +361,14 @@ namespace RC::LuaLibrary const std::wstring func_name_wide = std::wstring(tmp_func_name.begin(), tmp_func_name.end()); const std::string tmp_mod_name = mod_name; const std::wstring mod_name_wide = std::wstring(tmp_mod_name.begin(), tmp_mod_name.end()); - Output::send(STR("Calling script function '{}' in mod '{}'\n"), func_name_wide, mod_name_wide); + Output::send(SYSSTR("Calling script function '{}' in mod '{}'\n"), func_name_wide, mod_name_wide); //*/ auto mod = UE4SSProgram::find_lua_mod_by_name(mod_name, UE4SSProgram::IsInstalled::Yes, UE4SSProgram::IsStarted::Yes); if (!mod) { return_struct.status = ExportedFunctionStatus::MOD_IS_NULLPTR; - Output::send(STR("call_script_function | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); + Output::send(SYSSTR("call_script_function | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); return; } @@ -377,7 +381,7 @@ namespace RC::LuaLibrary catch (std::runtime_error&) { return_struct.status = ExportedFunctionStatus::SCRIPT_FUNCTION_NOT_FOUND; - Output::send(STR("call_script_function | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); + Output::send(SYSSTR("call_script_function | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); return; } @@ -414,7 +418,7 @@ namespace RC::LuaLibrary return_struct.status = ExportedFunctionStatus::SUCCESS; } - Output::send(STR("call_script_function | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); + Output::send(SYSSTR("call_script_function | return_struct.status: {}\n"), exported_function_status_to_string(return_struct.status)); } catch (std::runtime_error& e) { diff --git a/UE4SS/src/LuaType/LuaCustomProperty.cpp b/UE4SS/src/LuaType/LuaCustomProperty.cpp index 90b4be840..26ba59068 100644 --- a/UE4SS/src/LuaType/LuaCustomProperty.cpp +++ b/UE4SS/src/LuaType/LuaCustomProperty.cpp @@ -12,11 +12,11 @@ namespace RC::LuaType { LuaCustomProperty::PropertyList LuaCustomProperty::StaticStorage::property_list; - LuaCustomProperty::LuaCustomProperty(std::wstring name, std::unique_ptr property) : m_name(name), m_property(std::move(property)) + LuaCustomProperty::LuaCustomProperty(SystemStringType name, std::unique_ptr property) : m_name(name), m_property(std::move(property)) { } - auto LuaCustomProperty::PropertyList::add(std::wstring property_name, std::unique_ptr property) -> void + auto LuaCustomProperty::PropertyList::add(SystemStringType property_name, std::unique_ptr property) -> void { (void)properties.emplace_back(LuaCustomProperty{property_name, std::move(property)}).m_property.get(); } @@ -26,7 +26,7 @@ namespace RC::LuaType properties.clear(); } - auto LuaCustomProperty::PropertyList::find_or_nullptr(Unreal::UObject* base, std::wstring property_name) -> Unreal::FProperty* + auto LuaCustomProperty::PropertyList::find_or_nullptr(Unreal::UObject* base, SystemStringType property_name) -> Unreal::FProperty* { Unreal::FProperty* custom_property_found{}; diff --git a/UE4SS/src/LuaType/LuaFName.cpp b/UE4SS/src/LuaType/LuaFName.cpp index 207ecc3e8..cc9db044d 100644 --- a/UE4SS/src/LuaType/LuaFName.cpp +++ b/UE4SS/src/LuaType/LuaFName.cpp @@ -60,11 +60,11 @@ No overload found for function 'FName'. } int64_t name_comparison_index{}; - StringType name_string{}; + SystemStringType name_string{}; Unreal::EFindName find_type{Unreal::EFindName::FNAME_Add}; if (lua.is_string()) { - name_string = to_wstring(lua.get_string()); + name_string = to_generic_string(lua.get_string()); } else if (lua.is_integer()) { @@ -94,7 +94,7 @@ No overload found for function 'FName'. } else { - LuaType::FName::construct(lua, Unreal::FName(name_string, find_type)); + LuaType::FName::construct(lua, Unreal::FName(SystemStringToUEString(name_string), find_type)); } return 1; diff --git a/UE4SS/src/LuaType/LuaFOutputDevice.cpp b/UE4SS/src/LuaType/LuaFOutputDevice.cpp index 105c59ce2..32f711ac3 100644 --- a/UE4SS/src/LuaType/LuaFOutputDevice.cpp +++ b/UE4SS/src/LuaType/LuaFOutputDevice.cpp @@ -65,7 +65,7 @@ No overload found for function 'Log'. } auto message = lua.get_string(); - lua_object.get_remote_cpp_object()->Log(to_wstring(message).c_str()); + lua_object.get_remote_cpp_object()->Log(SystemStringToUEString(to_generic_string(message)).c_str()); return 0; }); diff --git a/UE4SS/src/LuaType/LuaFString.cpp b/UE4SS/src/LuaType/LuaFString.cpp index ad412aa01..36b9bc153 100644 --- a/UE4SS/src/LuaType/LuaFString.cpp +++ b/UE4SS/src/LuaType/LuaFString.cpp @@ -57,7 +57,7 @@ namespace RC::LuaType const wchar_t* string_data = lua_object.get_local_cpp_object().GetCharArray(); if (string_data) { - lua.set_string(to_string(string_data)); + lua.set_string(to_string(UEStringType(string_data))); } else { diff --git a/UE4SS/src/LuaType/LuaFText.cpp b/UE4SS/src/LuaType/LuaFText.cpp index d28a91ef6..9883b02fb 100644 --- a/UE4SS/src/LuaType/LuaFText.cpp +++ b/UE4SS/src/LuaType/LuaFText.cpp @@ -58,17 +58,17 @@ No overload found for function 'FText'. lua.discard_value(); } - StringType text_string{}; + SystemStringType text_string{}; if (lua.is_string()) { - text_string = to_wstring(lua.get_string()); + text_string = to_generic_string(lua.get_string()); } else { lua.throw_error(error_overload_not_found); } - LuaType::FText::construct(lua, Unreal::FText(text_string)); + LuaType::FText::construct(lua, Unreal::FText(SystemStringToUEString(text_string))); return 1; }); diff --git a/UE4SS/src/LuaType/LuaTArray.cpp b/UE4SS/src/LuaType/LuaTArray.cpp index af33b8553..07329d388 100644 --- a/UE4SS/src/LuaType/LuaTArray.cpp +++ b/UE4SS/src/LuaType/LuaTArray.cpp @@ -23,7 +23,7 @@ namespace RC::LuaType if (!lua_object.m_inner_property) { - Output::send(STR("TArray::construct: m_inner_property is nullptr for {}"), lua_object.m_property->GetFullName()); + Output::send(SYSSTR("TArray::construct: m_inner_property is nullptr for {}"), UEStringToSystemString(lua_object.m_property->GetFullName())); } auto metatable_name = ClassName::ToString(); diff --git a/UE4SS/src/LuaType/LuaUClass.cpp b/UE4SS/src/LuaType/LuaUClass.cpp index 21ece9996..f4046201b 100644 --- a/UE4SS/src/LuaType/LuaUClass.cpp +++ b/UE4SS/src/LuaType/LuaUClass.cpp @@ -63,7 +63,7 @@ namespace RC::LuaType if (!lua_object.get_remote_cpp_object()) { LuaType::UObject::construct(lua, nullptr); - Output::send(STR("[Lua][Error] Tried getting the CDO but the UClass instance is nullptr\n")); + Output::send(SYSSTR("[Lua][Error] Tried getting the CDO but the UClass instance is nullptr\n")); } else { diff --git a/UE4SS/src/LuaType/LuaUEnum.cpp b/UE4SS/src/LuaType/LuaUEnum.cpp index f25a8a15d..e02b10b65 100644 --- a/UE4SS/src/LuaType/LuaUEnum.cpp +++ b/UE4SS/src/LuaType/LuaUEnum.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace RC::LuaType { @@ -153,7 +154,7 @@ No overload found for function 'UEnum.InsertIntoNames'. lua.throw_error("Function 'UEnum.InsertIntoNames' cannot be called with 0 parameters."); } - StringType param_name{}; + SystemStringType param_name{}; int64_t param_value = 0; int32_t param_index = 0; bool param_shift = false; @@ -161,7 +162,7 @@ No overload found for function 'UEnum.InsertIntoNames'. // P1 (Name), string if (lua.is_string()) { - param_name = to_wstring(lua.get_string()); + param_name = to_generic_string(lua.get_string()); } else { @@ -194,8 +195,8 @@ No overload found for function 'UEnum.InsertIntoNames'. param_shift = lua.get_bool(); } - const Unreal::FName key{param_name, Unreal::FNAME_Add}; - const auto pair = Unreal::TPair{key, param_value}; + const Unreal::FName key{SystemStringToUEString(param_name), Unreal::FNAME_Add}; + const auto pair = Unreal::TPair{key, param_value}; lua_object.get_remote_cpp_object()->InsertIntoNames(pair, param_index, param_shift); return 1; @@ -242,7 +243,7 @@ No overload found for function 'UEnum.EditNameAt'. lua.throw_error("'UEnum.EditNameAt' could not load parameter for \"NewName\""); } - Unreal::FName new_key = Unreal::FName(to_wstring(param_new_name), Unreal::FNAME_Add); + Unreal::FName new_key = Unreal::FName(SystemStringToUEString(to_generic_string(param_new_name)), Unreal::FNAME_Add); lua_object.get_remote_cpp_object()->EditNameAt(param_index, new_key); return 0; diff --git a/UE4SS/src/LuaType/LuaUObject.cpp b/UE4SS/src/LuaType/LuaUObject.cpp index 03d588ebe..a6de573d5 100644 --- a/UE4SS/src/LuaType/LuaUObject.cpp +++ b/UE4SS/src/LuaType/LuaUObject.cpp @@ -755,7 +755,7 @@ namespace RC::LuaType { array = new unsigned char[array_property->GetElementSize() * table_length]; - params.lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { + params.lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { // Skip this table entry if the key wasn't numerical, who knows what the user put in their script if (!table.key.is_integer()) { @@ -1016,7 +1016,7 @@ namespace RC::LuaType } case Operation::Set: // For now, doing nothing just to get past the error - Output::send(STR("[push_weakobjectproperty] Operation::Set is not supported\n")); + Output::send(SYSSTR("[push_weakobjectproperty] Operation::Set is not supported\n")); return; case Operation::GetParam: params.lua.throw_error("[push_weakobjectproperty] Operation::GetParam is not supported"); @@ -1107,7 +1107,7 @@ namespace RC::LuaType if (params.lua.is_string()) { auto lua_string = params.lua.get_string(); - auto fstring = Unreal::FString{to_wstring(lua_string).c_str()}; + auto fstring = Unreal::FString{ SystemStringToUEString(to_generic_string(lua_string)).c_str() }; *string = fstring; } else if (params.lua.is_userdata()) @@ -1233,7 +1233,7 @@ No overload found for function 'IsA'. } else if (lua.is_string()) { - auto* object_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_wstring(lua.get_string())); + auto* object_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(to_generic_string(lua.get_string()))); lua.set_bool(is_a_internal(lua, object, object_class)); } else diff --git a/UE4SS/src/LuaType/LuaUScriptStruct.cpp b/UE4SS/src/LuaType/LuaUScriptStruct.cpp index b0474fe7d..0fac2b871 100644 --- a/UE4SS/src/LuaType/LuaUScriptStruct.cpp +++ b/UE4SS/src/LuaType/LuaUScriptStruct.cpp @@ -196,7 +196,7 @@ namespace RC::LuaType { auto& lua_object = lua.get_userdata(); - Unreal::FName property_name = Unreal::FName(to_wstring(lua.get_string())); + Unreal::FName property_name = Unreal::FName(SystemStringToUEString(to_generic_string(lua.get_string()))); // Check if property_name is 'NONE' if (property_name.GetComparisonIndex() == 0) diff --git a/UE4SS/src/LuaType/LuaUWorld.cpp b/UE4SS/src/LuaType/LuaUWorld.cpp index 887db969b..a2c515a7f 100644 --- a/UE4SS/src/LuaType/LuaUWorld.cpp +++ b/UE4SS/src/LuaType/LuaUWorld.cpp @@ -82,7 +82,7 @@ No overload found for function 'SpawnActor'. } else if (lua.is_table()) { - lua.for_each_in_table([&](const LuaMadeSimple::LuaTableReference& table) { + lua.for_each_in_table([&](const LuaMadeSimple::LuaTableReference& table) { if (table.key.is_string() && table.key.get_string() == "X" && table.value.is_number()) { location.SetX(table.value.get_number()); @@ -113,7 +113,7 @@ No overload found for function 'SpawnActor'. } else if (lua.is_table()) { - lua.for_each_in_table([&](const LuaMadeSimple::LuaTableReference& table) { + lua.for_each_in_table([&](const LuaMadeSimple::LuaTableReference& table) { if (table.key.is_string() && table.key.get_string() == "Yaw" && table.value.is_number()) { rotation.SetYaw(table.value.get_number()); diff --git a/UE4SS/src/LuaType/LuaXProperty.cpp b/UE4SS/src/LuaType/LuaXProperty.cpp index dc9944626..9412b0a60 100644 --- a/UE4SS/src/LuaType/LuaXProperty.cpp +++ b/UE4SS/src/LuaType/LuaXProperty.cpp @@ -114,7 +114,7 @@ namespace RC::LuaType if (lua_object.get_remote_cpp_object()) { // Set the return value to the ansi version of the full name - lua.set_string(to_string(lua_object.get_remote_cpp_object()->GetFullName()).c_str()); + lua.set_string(UEStringToSystemString(lua_object.get_remote_cpp_object()->GetFullName()).c_str()); } else { @@ -147,7 +147,7 @@ No overload found for function 'IsA'. if (lua.is_table()) { int64_t ffield_class_pointer{}; - lua.for_each_in_table([&](const LuaMadeSimple::LuaTableReference& table) { + lua.for_each_in_table([&](const LuaMadeSimple::LuaTableReference& table) { if (table.key.is_string() && table.key.get_string() == "FFieldClassPointer") { if (!table.value.is_integer()) @@ -224,10 +224,10 @@ No overload found for function 'ImportText'. const auto& lua_object = lua.get_userdata(); - File::StringType buffer; + SystemStringType buffer; if (lua.is_string()) { - buffer = to_wstring(lua.get_string()); + buffer = to_generic_string(lua.get_string()); } else { @@ -261,7 +261,7 @@ No overload found for function 'ImportText'. } auto* owner_object = lua.get_userdata().get_remote_cpp_object(); - lua_object.get_remote_cpp_object()->ImportText(buffer.c_str(), data, port_flags, owner_object, nullptr); + lua_object.get_remote_cpp_object()->ImportText(SystemStringToUEString(buffer).c_str(), data, port_flags, owner_object, nullptr); return 0; }); diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index b8a7b4904..aaad18a72 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -6,27 +6,36 @@ #include #include +#ifdef LINUX +#define printf_s printf +#endif + namespace RC { - CppMod::CppMod(UE4SSProgram& program, std::wstring&& mod_name, std::wstring&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) + CppMod::CppMod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) { - m_dlls_path = m_mod_path + L"\\dlls"; + std::filesystem::path m_dlls_path = m_mod_path; + + m_dlls_path = m_dlls_path / SYSSTR("dlls"); if (!std::filesystem::exists(m_dlls_path)) { - Output::send(STR("Could not find the dlls folder for mod {}\n"), m_mod_name); + Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), to_generic_string(m_mod_name)); set_installable(false); return; } - auto dll_path = m_dlls_path + L"\\main.dll"; +#define STRINGIFY(x) #x +#define CONCATENATE_WIDE_STRING(name, ext) SYSSTR(name) STRINGIFY(ext) + auto dll_path = m_dlls_path / CONCATENATE_WIDE_STRING("main", DLLEXT); +#ifdef WIN32 // Add mods dlls directory to search path for dynamic/shared linked libraries in mods m_dlls_path_cookie = AddDllDirectory(m_dlls_path.c_str()); m_main_dll_module = LoadLibraryExW(dll_path.c_str(), NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); if (!m_main_dll_module) { - Output::send(STR("Failed to load dll <{}> for mod {}, error code: 0x{:x}\n"), dll_path, m_mod_name, GetLastError()); + Output::send(SYSSTR("Failed to load dll <{}> for mod {}, error code: 0x{:x}\n"), dll_path, m_mod_name, GetLastError()); set_installable(false); return; } @@ -36,7 +45,7 @@ namespace RC if (!m_start_mod_func || !m_uninstall_mod_func) { - Output::send(STR("Failed to find exported mod lifecycle functions for mod {}\n"), m_mod_name); + Output::send(SYSSTR("Failed to find exported mod lifecycle functions for mod {}\n"), m_mod_name); FreeLibrary(m_main_dll_module); m_main_dll_module = NULL; @@ -44,6 +53,7 @@ namespace RC set_installable(false); return; } +#endif } auto CppMod::start_mod() -> void @@ -57,10 +67,10 @@ namespace RC { if (!Output::has_internal_error()) { - Output::send(STR("Failed to load dll <{}> for mod {}, because: {}\n"), - m_dlls_path + L"\\main.dll\n", + Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), + (std::filesystem::path {m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)).generic_string() + "\n", m_mod_name, - to_wstring(e.what())); + to_generic_string(e.what())); } else { @@ -71,14 +81,14 @@ namespace RC auto CppMod::uninstall() -> void { - Output::send(STR("Stopping C++ mod '{}' for uninstall\n"), m_mod_name); + Output::send(SYSSTR("Stopping C++ mod '{}' for uninstall\n"), m_mod_name); if (m_mod && m_uninstall_mod_func) { m_uninstall_mod_func(m_mod); } } - auto CppMod::fire_on_lua_start(StringViewType mod_name, + auto CppMod::fire_on_lua_start(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -99,7 +109,7 @@ namespace RC } } - auto CppMod::fire_on_lua_stop(StringViewType mod_name, + auto CppMod::fire_on_lua_stop(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -152,7 +162,7 @@ namespace RC } } - auto CppMod::fire_dll_load(std::wstring_view dll_name) -> void + auto CppMod::fire_dll_load(SystemStringViewType dll_name) -> void { if (m_mod) { @@ -162,10 +172,12 @@ namespace RC CppMod::~CppMod() { + #ifdef WIN32 if (m_main_dll_module) { FreeLibrary(m_main_dll_module); RemoveDllDirectory(m_dlls_path_cookie); } + #endif } } // namespace RC \ No newline at end of file diff --git a/UE4SS/src/Mod/CppUserModBase.cpp b/UE4SS/src/Mod/CppUserModBase.cpp index 8d93279d4..b56699b1a 100644 --- a/UE4SS/src/Mod/CppUserModBase.cpp +++ b/UE4SS/src/Mod/CppUserModBase.cpp @@ -8,12 +8,13 @@ namespace RC { if (ModIntendedSDKVersion.empty()) { - ModIntendedSDKVersion = std::format(STR("{}.{}.{}"), UE4SS_LIB_VERSION_MAJOR, UE4SS_LIB_VERSION_MINOR, UE4SS_LIB_VERSION_HOTFIX); + ModIntendedSDKVersion = std::format(SYSSTR("{}.{}.{}"), UE4SS_LIB_VERSION_MAJOR, UE4SS_LIB_VERSION_MINOR, UE4SS_LIB_VERSION_HOTFIX); } } CppUserModBase::~CppUserModBase() { + #ifdef HAS_GUI for (const auto& tab : GUITabs) { if (tab) @@ -47,8 +48,10 @@ namespace RC return were_all_events_registered_from_this_mod; }); + #endif } +#ifdef HAS_GUI auto CppUserModBase::register_tab(std::wstring_view tab_name, GUI::GUITab::RenderFunctionType render_function) -> void { auto& tab = GUITabs.emplace_back(std::make_shared(tab_name, render_function, this)); @@ -67,4 +70,5 @@ namespace RC { UE4SSProgram::get_program().register_keydown_event(key, callback, modifier_keys, 2, new KeyDownEventData{custom_data, this}); } +#endif } // namespace RC diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index b3bb5ed3b..7e92a65b9 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -11,7 +11,11 @@ #include #include #include + +#ifdef HAS_INPUT #include +#endif + #include #include #include @@ -22,8 +26,12 @@ #include #include #include + +#ifdef HAS_CPPMOD #include #include +#endif + #include #pragma warning(disable : 4005) #include @@ -254,11 +262,11 @@ namespace RC // If the type wasn't supported then we simply clean the Lua stack, output a warning and then do nothing lua_data.lua.discard_value(); - std::wstring parameter_type_name = property_type_name.ToString(); - std::wstring parameter_name = lua_data.return_property->GetName(); + auto parameter_type_name = UEStringToSystemString(property_type_name.ToString()); + auto parameter_name = UEStringToSystemString(lua_data.return_property->GetName()); Output::send( - STR("Tried altering return value of a hooked UFunction without a registered handler for return type Return property '{}' of type " + SYSSTR("Tried altering return value of a hooked UFunction without a registered handler for return type Return property '{}' of type " "'{}' not supported."), parameter_name, parameter_type_name); @@ -629,12 +637,13 @@ namespace RC efindname_table.make_global("EFindName"); } - LuaMod::LuaMod(UE4SSProgram& program, std::wstring&& mod_name, std::wstring&& mod_path) + LuaMod::LuaMod(UE4SSProgram& program, SystemStringType && mod_name, SystemStringType && mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)), m_lua(LuaMadeSimple::new_state()) { // Verify that there's a 'Scripts' directory // Give the full path to the 'Scripts' directory to the mod container - m_scripts_path = m_mod_path + L"\\scripts"; + std::filesystem::path mod_path_fs = m_mod_path; + m_scripts_path = (mod_path_fs / SYSSTR("scripts")).generic_string(); // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod if (!std::filesystem::exists(m_scripts_path)) @@ -812,6 +821,7 @@ namespace RC auto LuaMod::setup_lua_require_paths(const LuaMadeSimple::Lua& lua) const -> void { + // TODO: use correct \/ for linux auto* lua_state = m_lua.get_lua_state(); lua_getglobal(lua_state, "package"); @@ -859,7 +869,7 @@ No overload found for function 'StaticFindObject'. // Ignores any params after P1 if (lua.is_string()) { - Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_wstring(lua.get_string())); + Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(to_generic_string(lua.get_string()))); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe @@ -883,7 +893,7 @@ No overload found for function 'StaticFindObject'. Unreal::UClass* param_class{}; Unreal::UObject* param_in_outer{}; - std::wstring param_name{}; + SystemStringType param_name{}; bool param_exact_class{}; // P1 (Class), userdata @@ -919,7 +929,7 @@ No overload found for function 'StaticFindObject'. // P3 (Name), string if (lua.is_string()) { - param_name = to_wstring(lua.get_string()); + param_name = to_generic_string(lua.get_string()); } else { @@ -933,7 +943,7 @@ No overload found for function 'StaticFindObject'. } // There's no error if P4 isn't a bool, simply ignore all parameters after P3 - Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(param_class, param_in_outer, param_name, param_exact_class); + Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(param_class, param_in_outer, SystemStringToUEString(param_name), param_exact_class); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe @@ -961,7 +971,7 @@ No overload found for function 'FindFirstOf'. // Ignores any params after P1 if (lua.is_string()) { - Unreal::UObject* object = Unreal::UObjectGlobals::FindFirstOf(to_wstring(lua.get_string())); + Unreal::UObject* object = Unreal::UObjectGlobals::FindFirstOf(SystemStringToUEString(to_generic_string(lua.get_string()))); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe @@ -1042,9 +1052,10 @@ No overload found for function 'FindAllOf'. lua.set_nil(); return 1; }); - + if (is_true_mod == Mod::IsTrueMod::Yes) { +#ifdef HAS_INPUT lua.register_function("IsKeyBindRegistered", [](const LuaMadeSimple::Lua& lua) -> int { std::string error_overload_not_found{R"( No overload found for function 'IsKeyBindRegistered'. @@ -1071,7 +1082,7 @@ No overload found for function 'IsKeyBindRegistered'. Input::Handler::ModifierKeyArray modifier_keys{}; uint8_t table_counter{}; - lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { + lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { if (!table.value.is_integer()) { lua.throw_error( @@ -1089,7 +1100,6 @@ No overload found for function 'IsKeyBindRegistered'. return false; }); - if (table_counter > 0) { lua.set_bool(mod->m_program.is_keydown_event_registered(key_to_check, modifier_keys)); @@ -1098,6 +1108,7 @@ No overload found for function 'IsKeyBindRegistered'. { lua.set_bool(mod->m_program.is_keydown_event_registered(key_to_check)); } + } else { @@ -1137,7 +1148,7 @@ No overload found for function 'RegisterKeyBindAsync'. } catch (std::runtime_error& e) { - Output::send(STR("{}\n"), to_wstring(lua.handle_error(e.what()))); + Output::send(SYSSTR("{}\n"), to_generic_string(lua.handle_error(e.what()))); } }; @@ -1172,7 +1183,7 @@ No overload found for function 'RegisterKeyBindAsync'. Input::Handler::ModifierKeyArray modifier_keys{}; uint8_t table_counter{}; - lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { + lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { if (!table.value.is_integer()) { lua.throw_error( @@ -1256,7 +1267,7 @@ No overload found for function 'RegisterKeyBind'. } catch (std::runtime_error& e) { - Output::send(STR("{}\n"), to_wstring(lua.handle_error(e.what()))); + Output::send(SYSSTR("{}\n"), to_generic_string(lua.handle_error(e.what()))); } }; @@ -1291,7 +1302,7 @@ No overload found for function 'RegisterKeyBind'. Input::Handler::ModifierKeyArray modifier_keys{}; uint8_t table_counter{}; - lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { + lua.for_each_in_table([&](LuaMadeSimple::LuaTableReference table) -> bool { if (!table.value.is_integer()) { lua.throw_error("Lua function 'RegisterKeyBind', overload #2, requires a table of 1-byte large integers as the second parameter"); @@ -1342,6 +1353,7 @@ No overload found for function 'RegisterKeyBind'. return 0; }); +#endif lua.register_function("UnregisterHook", [](const LuaMadeSimple::Lua& lua) -> int { std::lock_guard guard{LuaMod::m_thread_actions_mutex}; @@ -1355,8 +1367,8 @@ No overload found for function 'UnregisterHook'. lua.throw_error(error_overload_not_found); } - std::wstring function_name = to_wstring(lua.get_string()); - std::wstring function_name_no_prefix = function_name.substr(function_name.find_first_of(L" ") + 1, function_name.size()); + UEStringType function_name = to_u16string(lua.get_string()); + UEStringType function_name_no_prefix = function_name.substr(function_name.find_first_of(STR(" ")) + 1, function_name.size()); Unreal::UFunction* unreal_function = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, function_name_no_prefix); if (!unreal_function) @@ -1392,9 +1404,9 @@ No overload found for function 'UnregisterHook'. if (native_hook_pre_id_it != LuaMod::m_generic_hook_id_to_native_hook_id.end() && native_hook_post_id_it != LuaMod::m_generic_hook_id_to_native_hook_id.end()) { - Output::send(STR("Unregistering native hook with pre-id: {}\n"), native_hook_pre_id_it->first); + Output::send(SYSSTR("Unregistering native hook with pre-id: {}\n"), native_hook_pre_id_it->first); unreal_function->UnregisterHook(static_cast(native_hook_pre_id_it->second)); - Output::send(STR("Unregistering native hook with post-id: {}\n"), native_hook_post_id_it->first); + Output::send(SYSSTR("Unregistering native hook with post-id: {}\n"), native_hook_post_id_it->first); unreal_function->UnregisterHook(static_cast(native_hook_post_id_it->second)); // LuaUnrealScriptFunctionData contains the hook's lua registry references, captured in RegisterHook in two different lua states. @@ -1417,10 +1429,10 @@ No overload found for function 'UnregisterHook'. } else { - if (auto callback_data_it = LuaMod::m_script_hook_callbacks.find(unreal_function->GetFullName()); + if (auto callback_data_it = LuaMod::m_script_hook_callbacks.find(UEStringToSystemString(unreal_function->GetFullName())); callback_data_it != LuaMod::m_script_hook_callbacks.end()) { - Output::send(STR("Unregistering script hook with id: {}\n"), post_id); + Output::send(SYSSTR("Unregistering script hook with id: {}\n"), post_id); auto& registry_indexes = callback_data_it->second.registry_indexes; std::erase_if(registry_indexes, [&](const auto& pair) -> bool { return post_id == pair.second.identifier; @@ -1437,15 +1449,15 @@ No overload found for function 'UnregisterHook'. { lua.throw_error("Could not dump objects and properties because the pointer to 'Mod' was nullptr"); } - UE4SSProgram::dump_all_objects_and_properties(mod->m_program.get_object_dumper_output_directory() + STR("\\") + - UE4SSProgram::m_object_dumper_file_name); + UE4SSProgram::dump_all_objects_and_properties((std::filesystem::path{mod->m_program.get_object_dumper_output_directory()} / + UE4SSProgram::m_object_dumper_file_name).generic_string()); return 0; }); lua.register_function("GenerateSDK", []([[maybe_unused]] const LuaMadeSimple::Lua& lua) -> int { const Mod* mod = get_mod_ref(lua); - File::StringType working_dir{mod->m_program.get_working_directory()}; - mod->m_program.generate_cxx_headers(working_dir + STR("\\CXXHeaderDump")); + std::filesystem::path working_dir{mod->m_program.get_working_directory()}; + mod->m_program.generate_cxx_headers(working_dir / SYSSTR("CXXHeaderDump")); return 0; }); @@ -1617,9 +1629,9 @@ No overload found for function 'RegisterCustomProperty'. struct PropertyInfo { - std::wstring name{}; + SystemStringType name{}; PropertyTypeInfo type{}; // Figure out what to do here, it shouldn't be just a string - std::wstring belongs_to_class{}; + SystemStringType belongs_to_class{}; int32_t offset_internal{-1}; int32_t element_size{-1}; // Is this required for trivial types like integers and floats ? @@ -1718,12 +1730,12 @@ No overload found for function 'RegisterCustomProperty'. }; // Always required, for all property types - property_info.name = to_wstring(lua_table.get_string_field("Name")); + property_info.name = to_generic_string(lua_table.get_string_field("Name")); property_info.type.name = lua_table.get_table_field("Type").get_string_field("Name"); property_info.type.size = verify_and_convert_int64_to_int32("Type", "Size"); property_info.type.ffieldclass_pointer = reinterpret_cast(lua_table.get_table_field("Type").get_int_field("FFieldClassPointer")); property_info.type.static_pointer = reinterpret_cast(lua_table.get_table_field("Type").get_int_field("StaticPointer")); - property_info.belongs_to_class = to_wstring(lua_table.get_string_field("BelongsToClass")); + property_info.belongs_to_class = to_generic_string(lua_table.get_string_field("BelongsToClass")); std::string oi_property_name; int32_t oi_relative_offset{}; @@ -1766,7 +1778,7 @@ No overload found for function 'RegisterCustomProperty'. lua.throw_error("Parameter #1 for function 'RegisterCustomProperty'. The table is missing required fields."); } - Unreal::UClass* belongs_to_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, property_info.belongs_to_class); + Unreal::UClass* belongs_to_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(property_info.belongs_to_class)); if (!belongs_to_class) { lua.throw_error("Tried to 'RegisterCustomProperty' but 'BelongsToClass' could not be found"); @@ -1774,7 +1786,7 @@ No overload found for function 'RegisterCustomProperty'. if (property_info.offset_internal_is_table) { - auto name = Unreal::FName(to_wstring(oi_property_name)); + auto name = Unreal::FName(SystemStringToUEString(oi_property_name)); Unreal::FProperty* oi_property = belongs_to_class->FindProperty(name); if (!oi_property) { @@ -1811,14 +1823,14 @@ No overload found for function 'RegisterCustomProperty'. printf_s("Registered Custom Property\n"); printf_s("PropertyInfo {\n"); - printf_s("\tName: %S\n", property_info.name.c_str()); + printf_s("\tName: " SystemStringPrint "\n", property_info.name.c_str()); printf_s("\tType {\n"); printf_s("\t\tName: %s\n", property_info.type.name.data()); printf_s("\t\tSize: 0x%X\n", property_info.type.size); printf_s("\t\tFFieldClassPointer: 0x%p\n", property_info.type.ffieldclass_pointer); printf_s("\t\tStaticPointer: 0x%p\n", property_info.type.static_pointer); printf_s("\t}\n"); - printf_s("\tBelongsToClass: %S\n", property_info.belongs_to_class.c_str()); + printf_s("\tBelongsToClass: " SystemStringPrint "\n", property_info.belongs_to_class.c_str()); printf_s("\tOffsetInternal: 0x%X\n", property_info.offset_internal); if (property_info.is_array_property) @@ -1870,7 +1882,7 @@ No overload found for function 'NotifyOnNewObject'. lua.throw_error(error_overload_not_found); } - std::wstring class_name = to_wstring(lua.get_string()); + SystemStringType class_name = to_generic_string(lua.get_string()); if (!lua.is_function()) { @@ -1888,7 +1900,7 @@ No overload found for function 'NotifyOnNewObject'. const auto func_ref = hook_lua->registry().make_ref(); const auto thread_ref = mod->lua().registry().make_ref(); - Unreal::UClass* instance_of_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, class_name); + Unreal::UClass* instance_of_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(class_name)); LuaMod::m_static_construct_object_lua_callbacks.emplace_back(LuaMod::LuaCancellableCallbackData{hook_lua, instance_of_class, func_ref, thread_ref}); @@ -1906,7 +1918,7 @@ No overload found for function 'RegisterCustomEvent'. lua.throw_error(error_overload_not_found); } - std::wstring event_name = to_wstring(lua.get_string()); + SystemStringType event_name = to_generic_string(lua.get_string()); if (!lua.is_function()) { @@ -1942,7 +1954,7 @@ No overload found for function 'UnregisterCustomEvent'. { lua.throw_error(error_overload_not_found); } - auto custom_event_name = to_wstring(lua.get_string()); + auto custom_event_name = to_generic_string(lua.get_string()); LuaMod::m_custom_event_callbacks.erase(custom_event_name); @@ -2125,7 +2137,7 @@ No overload found for function 'IterateGameDirectories'. auto game_content_dir = game_executable_directory.parent_path().parent_path() / "Content"; if (!std::filesystem::exists(game_content_dir)) { - Output::send(STR("IterateGameDirectories: Could not locate the root directory because the directory structure is unknown " + Output::send(SYSSTR("IterateGameDirectories: Could not locate the root directory because the directory structure is unknown " "(not /Game/Binaries/Win64)\n")); lua.set_nil(); return 1; @@ -2248,19 +2260,19 @@ No overload found for function 'CreateLogicModsDirectory'. if (std::filesystem::exists(logic_mods_dir)) { Output::send( - STR("CreateLogicModsDirectory: \"LogicMods\" directory already exists. Cancelling creation of new directory.\n")); + SYSSTR("CreateLogicModsDirectory: \"LogicMods\" directory already exists. Cancelling creation of new directory.\n")); lua.set_bool(false); return 1; } - Output::send(STR("CreateLogicModsDirectory: LogicMods directory not found. Creating LogicMods directory.\n")); + Output::send(SYSSTR("CreateLogicModsDirectory: LogicMods directory not found. Creating LogicMods directory.\n")); auto new_logic_mods_dir = std::filesystem::create_directory(logic_mods_dir); if (!new_logic_mods_dir) { lua.throw_error("CreateLogicModsDirectory: Unable to create \"LogicMods\" directory. Try creating manually.\n"); } - Output::send(STR("CreateLogicModsDirectory: LogicMods directory created.\n")); + Output::send(SYSSTR("CreateLogicModsDirectory: LogicMods directory created.\n")); lua.set_bool(true); return 1; @@ -2486,7 +2498,7 @@ No overload found for function 'RegisterConsoleCommandGlobalHandler'. { throw std::runtime_error{error_overload_not_found}; } - auto command_name = to_wstring(lua.get_string()); + auto command_name = to_generic_string(lua.get_string()); if (!lua.is_function()) { @@ -2521,7 +2533,7 @@ No overload found for function 'RegisterConsoleCommandHandler'. { throw std::runtime_error{error_overload_not_found}; } - auto command_name = to_wstring(lua.get_string()); + auto command_name = to_generic_string(lua.get_string()); if (!lua.is_function()) { @@ -2561,7 +2573,7 @@ No overload found for function 'LoadAsset'. { throw std::runtime_error{error_overload_not_found}; } - auto asset_path_and_name = Unreal::FName(to_wstring(lua.get_string()), Unreal::FNAME_Add); + auto asset_path_and_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); auto* asset_registry = static_cast(Unreal::UAssetRegistryHelpers::GetAssetRegistry().ObjectPointer); if (!asset_registry) @@ -2580,11 +2592,11 @@ No overload found for function 'LoadAsset'. if (loaded_asset) { did_asset_load = true; - Output::send(STR("Asset loaded\n")); + Output::send(SYSSTR("Asset loaded\n")); } else { - Output::send(STR("Asset was found but not loaded, could be a package\n")); + Output::send(SYSSTR("Asset was found but not loaded, could be a package\n")); } } @@ -2612,7 +2624,7 @@ No overload found for function 'FindObject'. bool could_be_in_class{}; if (lua.is_string()) { - object_class_name = Unreal::FName(to_wstring(lua.get_string()), Unreal::FNAME_Add); + object_class_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); } else if (lua.is_userdata()) { @@ -2655,7 +2667,7 @@ No overload found for function 'FindObject'. bool could_be_object_short_name{}; if (lua.is_string()) { - object_short_name = Unreal::FName(to_wstring(lua.get_string()), Unreal::FNAME_Add); + object_short_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); could_be_object_short_name = true; } else if (lua.is_userdata()) @@ -2739,7 +2751,7 @@ No overload found for function 'FindObject'. if (could_be_in_class && could_be_in_outer && could_be_in_name) { - LuaType::auto_construct_object(lua, Unreal::UObjectGlobals::FindObject(in_class, in_outer, to_wstring(in_name), exact_class)); + LuaType::auto_construct_object(lua, Unreal::UObjectGlobals::FindObject(in_class, in_outer, to_u16string(in_name), exact_class)); } else { @@ -2786,7 +2798,7 @@ No overload found for function 'FindObjects'. bool object_class_name_supplied{true}; if (lua.is_string()) { - object_class_name = Unreal::FName(to_wstring(lua.get_string()), Unreal::FNAME_Add); + object_class_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); } else if (lua.is_userdata()) { @@ -2824,7 +2836,7 @@ No overload found for function 'FindObjects'. Unreal::FName object_short_name{}; if (lua.is_string()) { - object_short_name = Unreal::FName(to_wstring(lua.get_string()), Unreal::FNAME_Add); + object_short_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); } else if (lua.is_userdata()) { @@ -2966,8 +2978,8 @@ No overload found for function 'RegisterHook'. lua.throw_error(error_overload_not_found); } - std::wstring function_name = to_wstring(lua.get_string()); - std::wstring function_name_no_prefix = function_name.substr(function_name.find_first_of(L"/"), function_name.size()); + SystemStringType function_name = to_generic_string(lua.get_string()); + SystemStringType function_name_no_prefix = function_name.substr(function_name.find_first_of(SYSSTR("/")), function_name.size()); if (!lua.is_function()) { @@ -2997,7 +3009,7 @@ No overload found for function 'RegisterHook'. has_post_callback = true; } - Unreal::UFunction* unreal_function = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, function_name_no_prefix); + Unreal::UFunction* unreal_function = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(function_name_no_prefix)); if (!unreal_function) { lua.throw_error("Tried to register a hook with Lua function 'RegisterHook' but no UFunction with the specified name was found."); @@ -3020,24 +3032,23 @@ No overload found for function 'RegisterHook'. generic_pre_id = m_last_generic_hook_id; m_generic_hook_id_to_native_hook_id.emplace(++m_last_generic_hook_id, post_id); generic_post_id = m_last_generic_hook_id; - Output::send(STR("[RegisterHook] Registered native hook ({}, {}) for {}\n"), + Output::send(SYSSTR("[RegisterHook] Registered native hook ({}, {}) for {}\n"), generic_pre_id, generic_post_id, - unreal_function->GetFullName()); + UEStringToSystemString(unreal_function->GetFullName())); } else if (func_ptr && func_ptr == Unreal::UObject::ProcessInternalInternal.get_function_address() && !unreal_function->HasAnyFunctionFlags(Unreal::EFunctionFlags::FUNC_Native)) { ++m_last_generic_hook_id; - auto [callback_data, _] = LuaMod::m_script_hook_callbacks.emplace(unreal_function->GetFullName(), LuaCallbackData{*hook_lua, nullptr, {}}); - callback_data->second.registry_indexes.emplace_back(hook_lua, - LuaMod::LuaCallbackData::RegistryIndex{lua_callback_registry_index, m_last_generic_hook_id}); + auto [callback_data, _] = LuaMod::m_script_hook_callbacks.emplace(UEStringToSystemString(unreal_function->GetFullName()), LuaCallbackData{lua, nullptr, {}}); + callback_data->second.registry_indexes.emplace_back(LuaMod::LuaCallbackData::RegistryIndex{lua_callback_registry_index, m_last_generic_hook_id}); generic_pre_id = m_last_generic_hook_id; generic_post_id = m_last_generic_hook_id; - Output::send(STR("[RegisterHook] Registered script hook ({}, {}) for {}\n"), + Output::send(SYSSTR("[RegisterHook] Registered script hook ({}, {}) for {}\n"), generic_pre_id, generic_post_id, - unreal_function->GetFullName()); + UEStringToSystemString(unreal_function->GetFullName())); } else { @@ -3249,8 +3260,8 @@ No overload found for function 'FPackageName:IsShortPackageName'. { lua.throw_error(error_overload_not_found); } - - File::StringType PossiblyLongName = to_wstring(lua.get_string()); + auto local_str = SystemStringToUEString(to_generic_string(lua.get_string())); + UEViewType PossiblyLongName = local_str; lua.set_bool(Unreal::FPackageName::IsShortPackageName(PossiblyLongName)); return 1; @@ -3266,8 +3277,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. { lua.throw_error(error_overload_not_found); } - - File::StringType InLongPackageName = to_wstring(lua.get_string()); + auto local_str = SystemStringToUEString(to_generic_string(lua.get_string())); + UEViewType InLongPackageName = local_str; lua.set_bool(Unreal::FPackageName::IsValidLongPackageName(InLongPackageName)); return 1; @@ -3307,6 +3318,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. lua_setglobal(lua.get_lua_state(), "__OriginalReturnValue"); } +#ifdef HAS_CPPMOD auto LuaMod::fire_on_lua_start_for_cpp_mods() -> void { if (!is_started()) @@ -3346,6 +3358,15 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } } } +#else + auto LuaMod::fire_on_lua_start_for_cpp_mods() -> void + { + } + + auto LuaMod::fire_on_lua_stop_for_cpp_mods() -> void + { + } +#endif auto LuaMod::start_mod() -> void { @@ -3364,11 +3385,11 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. // Don't crash on syntax errors. try { - main_lua()->execute_file(m_scripts_path + L"\\main.lua"); + main_lua()->execute_file((std::filesystem::path {m_scripts_path} / SYSSTR("main.lua")).generic_string()); } catch (std::runtime_error& e) { - Output::send(STR("{}\n"), to_wstring(e.what())); + Output::send(SYSSTR("{}\n"), to_generic_string(e.what())); } } @@ -3377,7 +3398,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. // ProcessEvent hook may try to run, and the lua state will not be valid std::lock_guard guard{LuaMod::m_thread_actions_mutex}; - Output::send(STR("Stopping mod '{}' for uninstall\n"), m_mod_name); + Output::send(SYSSTR("Stopping mod '{}' for uninstall\n"), m_mod_name); fire_on_lua_stop_for_cpp_mods(); @@ -3408,8 +3429,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. std::erase_if(g_hooked_script_function_data, [&](std::unique_ptr& item) -> bool { if (item->mod == this) { - Output::send(STR("\tUnregistering hook by id '{}#{}' for mod {}\n"), item->unreal_function->GetName(), item->pre_callback_id, item->mod->get_name()); - Output::send(STR("\tUnregistering hook by id '{}#{}' for mod {}\n"), item->unreal_function->GetName(), item->post_callback_id, item->mod->get_name()); + Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), UEStringToSystemString(item->unreal_function->GetName()), item->pre_callback_id, item->mod->get_name()); + Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), UEStringToSystemString(item->unreal_function->GetName()), item->post_callback_id, item->mod->get_name()); item->unreal_function->UnregisterHook(item->pre_callback_id); item->unreal_function->UnregisterHook(item->post_callback_id); return true; @@ -3465,12 +3486,12 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. { std::lock_guard guard{LuaMod::m_thread_actions_mutex}; - auto execute_hook = [&](std::unordered_map& callback_container, bool precise_name_match) { + auto execute_hook = [&](std::unordered_map& callback_container, bool precise_name_match) { if (callback_container.empty()) { return; } - if (auto it = callback_container.find(precise_name_match ? Stack.Node()->GetFullName() : Stack.Node()->GetName()); it != callback_container.end()) + if (auto it = callback_container.find(precise_name_match ? UEStringToSystemString(Stack.Node()->GetFullName()) : UEStringToSystemString(Stack.Node()->GetName())); it != callback_container.end()) { const auto& callback_data = it->second; for (const auto& [lua_ptr, registry_index] : callback_data.registry_indexes) @@ -3564,10 +3585,10 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } else { - std::wstring return_property_type_name = return_property_type.ToString(); - std::wstring return_property_name = return_property->GetName(); + SystemStringType return_property_type_name = UEStringToSystemString(return_property_type.ToString()); + SystemStringType return_property_name = UEStringToSystemString(return_property->GetName()); - Output::send(STR("Tried altering return value of a custom BP function without a registered handler for return type Return " + Output::send(SYSSTR("Tried altering return value of a custom BP function without a registered handler for return type Return " "property '{}' of type '{}' not supported."), return_property_name, return_property_type_name); @@ -3779,7 +3800,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - Output::send(STR("{}\n"), to_wstring(e.what())); + Output::send(SYSSTR("{}\n"), to_generic_string(e.what())); } if (cancel) @@ -3798,7 +3819,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. return constructed_object; }); - Unreal::Hook::RegisterULocalPlayerExecPreCallback([](Unreal::ULocalPlayer* context, Unreal::UWorld* in_world, const TCHAR* cmd, Unreal::FOutputDevice& ar) + Unreal::Hook::RegisterULocalPlayerExecPreCallback([](Unreal::ULocalPlayer* context, Unreal::UWorld* in_world, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar) -> Unreal::Hook::ULocalPlayerExecCallbackReturnValue { return TRY([&] { for (const auto& callback_data : m_local_player_exec_pre_callbacks) @@ -3814,7 +3835,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. static auto s_object_property_name = Unreal::FName(STR("ObjectProperty")); LuaType::RemoteUnrealParam::construct(callback_data.lua, &context, s_object_property_name); LuaType::RemoteUnrealParam::construct(callback_data.lua, &in_world, s_object_property_name); - callback_data.lua.set_string(to_string(cmd)); + callback_data.lua.set_string(to_string((UECharType*)cmd)); LuaType::FOutputDevice::construct(callback_data.lua, &ar); callback_data.lua.call_function(4, 2); @@ -3858,7 +3879,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); }); - Unreal::Hook::RegisterULocalPlayerExecPostCallback([](Unreal::ULocalPlayer* context, Unreal::UWorld* in_world, const TCHAR* cmd, Unreal::FOutputDevice& ar) + Unreal::Hook::RegisterULocalPlayerExecPostCallback([](Unreal::ULocalPlayer* context, Unreal::UWorld* in_world, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar) -> Unreal::Hook::ULocalPlayerExecCallbackReturnValue { return TRY([&] { for (const auto& callback_data : m_local_player_exec_post_callbacks) @@ -3874,7 +3895,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. static auto s_object_property_name = Unreal::FName(STR("ObjectProperty")); LuaType::RemoteUnrealParam::construct(callback_data.lua, &context, s_object_property_name); LuaType::RemoteUnrealParam::construct(callback_data.lua, &in_world, s_object_property_name); - callback_data.lua.set_string(to_string(cmd)); + callback_data.lua.set_string(to_string((UECharType*)cmd)); LuaType::FOutputDevice::construct(callback_data.lua, &ar); callback_data.lua.call_function(4, 2); @@ -3919,7 +3940,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); Unreal::Hook::RegisterCallFunctionByNameWithArgumentsPreCallback( - [](Unreal::UObject* context, const TCHAR* str, Unreal::FOutputDevice& ar, Unreal::UObject* executor, bool b_force_call_with_non_exec) + [](Unreal::UObject* context, const RC::Unreal::TCHAR* str, Unreal::FOutputDevice& ar, Unreal::UObject* executor, bool b_force_call_with_non_exec) -> std::pair { return TRY([&] { for (const auto& callback_data : m_call_function_by_name_with_arguments_pre_callbacks) @@ -3934,7 +3955,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. static auto s_object_property_name = Unreal::FName(STR("ObjectProperty")); LuaType::RemoteUnrealParam::construct(callback_data.lua, &context, s_object_property_name); - callback_data.lua.set_string(to_string(str)); + callback_data.lua.set_string(to_string((UECharType*)str)); LuaType::FOutputDevice::construct(callback_data.lua, &ar); LuaType::RemoteUnrealParam::construct(callback_data.lua, &executor, s_object_property_name); callback_data.lua.set_bool(b_force_call_with_non_exec); @@ -3967,7 +3988,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); Unreal::Hook::RegisterCallFunctionByNameWithArgumentsPostCallback( - [](Unreal::UObject* context, const TCHAR* str, Unreal::FOutputDevice& ar, Unreal::UObject* executor, bool b_force_call_with_non_exec) + [](Unreal::UObject* context, const RC::Unreal::TCHAR* str, Unreal::FOutputDevice& ar, Unreal::UObject* executor, bool b_force_call_with_non_exec) -> std::pair { return TRY([&] { for (const auto& callback_data : m_call_function_by_name_with_arguments_post_callbacks) @@ -3982,7 +4003,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. static auto s_object_property_name = Unreal::FName(STR("ObjectProperty")); LuaType::RemoteUnrealParam::construct(callback_data.lua, &context, s_object_property_name); - callback_data.lua.set_string(to_string(str)); + callback_data.lua.set_string(to_string((UECharType*)str)); LuaType::FOutputDevice::construct(callback_data.lua, &ar); LuaType::RemoteUnrealParam::construct(callback_data.lua, &executor, s_object_property_name); callback_data.lua.set_bool(b_force_call_with_non_exec); @@ -4015,32 +4036,32 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); // Lua from the in-game console. - Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { - auto logln = [&ar](const File::StringType& log_message) { - Output::send(std::format(STR("{}\n"), log_message)); - ar.Log(log_message.c_str()); + Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { + auto logln = [&ar](const SystemStringType& log_message) { + Output::send(std::format(SYSSTR("{}\n"), log_message)); + ar.Log((const RC::Unreal::TCHAR*) log_message.c_str()); }; - if (!LuaStatics::console_executor_enabled && String::iequal(File::StringViewType{cmd}, STR("luastart"))) + if (!LuaStatics::console_executor_enabled && String::iequal(UEViewType{(UECharType*)cmd}, STR("luastart"))) { start_console_lua_executor(); - logln(STR("Console Lua executor started")); + logln(SYSSTR("Console Lua executor started")); return true; } - else if (LuaStatics::console_executor_enabled && String::iequal(File::StringViewType{cmd}, STR("luastop"))) + else if (LuaStatics::console_executor_enabled && String::iequal(UEViewType{(UECharType*)cmd}, STR("luastop"))) { stop_console_lua_executor(); - logln(STR("Console Lua executor stopped")); + logln(SYSSTR("Console Lua executor stopped")); return true; } - else if (LuaStatics::console_executor_enabled && String::iequal(File::StringViewType{cmd}, STR("luarestart"))) + else if (LuaStatics::console_executor_enabled && String::iequal(UEViewType{(UECharType*)cmd}, STR("luarestart"))) { stop_console_lua_executor(); start_console_lua_executor(); - logln(STR("Console Lua executor restarted")); + logln(SYSSTR("Console Lua executor restarted")); return true; } - else if (String::iequal(File::StringViewType{cmd}, STR("clear"))) + else if (String::iequal(UEViewType{(UECharType*)cmd}, STR("clear"))) { // TODO: Replace with proper implementation when we have UGameViewportClient and UConsole. // This should be fairly cross-game & cross-engine-version compatible even without the proper implementation. @@ -4058,17 +4079,17 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. { if (!LuaStatics::console_executor) { - logln(STR("Console Lua executor is enabled but the Lua instance is nullptr. Please try run RC_LUA_START again.")); + logln(SYSSTR("Console Lua executor is enabled but the Lua instance is nullptr. Please try run RC_LUA_START again.")); return true; } LuaLibrary::set_outputdevice_ref(*LuaStatics::console_executor, &ar); - // logln(std::format(STR("Executing '{}' as Lua"), cmd)); + // logln(std::format(SYSSTR("Executing '{}' as Lua"), cmd)); try { - if (int status = luaL_loadstring(LuaStatics::console_executor->get_lua_state(), to_string(cmd).c_str()); status != LUA_OK) + if (int status = luaL_loadstring(LuaStatics::console_executor->get_lua_state(), to_string((UECharType*)cmd).c_str()); status != LUA_OK) { LuaStatics::console_executor->throw_error( std::format("luaL_loadstring returned {}", LuaStatics::console_executor->resolve_status_message(status, true))); @@ -4082,7 +4103,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - logln(to_wstring(e.what())); + logln(to_generic_string(e.what())); } // We always return true when the console Lua executor is enabled in order to suppress other handlers @@ -4096,10 +4117,10 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. // RegisterProcessConsoleExecPreHook Unreal::Hook::RegisterProcessConsoleExecGlobalPreCallback( - [](Unreal::UObject* context, const TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { + [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { return TRY([&] { - auto command = File::StringViewType{cmd}; - auto command_parts = explode_by_occurrence(cmd, ' '); + auto command = UEViewType{(const UECharType*) cmd}; + auto command_parts = explode_by_occurrence((const UECharType*) cmd, ' '); for (const auto& callback_data : m_process_console_exec_pre_callbacks) { @@ -4152,10 +4173,10 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. // RegisterProcessConsoleExecPostHook Unreal::Hook::RegisterProcessConsoleExecGlobalPostCallback( - [](Unreal::UObject* context, const TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { + [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { return TRY([&] { - auto command = File::StringViewType{cmd}; - auto command_parts = explode_by_occurrence(cmd, ' '); + auto command = UEViewType {(const UECharType*) cmd}; + auto command_parts = explode_by_occurrence((const UECharType*)cmd, ' '); for (const auto& callback_data : m_process_console_exec_post_callbacks) { @@ -4207,7 +4228,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); // RegisterConsoleCommandHandler - Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { + Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { (void)executor; if (!Unreal::Cast(context)) @@ -4216,9 +4237,9 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } return TRY([&] { - auto command = File::StringViewType{cmd}; - auto command_parts = explode_by_occurrence(cmd, ' '); - File::StringType command_name; + auto command = UEStringToSystemString(cmd); + auto command_parts = explode_by_occurrence(command, ' '); + SystemStringType command_name; if (command_parts.size() > 1) { command_name = command_parts[0]; @@ -4271,14 +4292,14 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); // RegisterConsoleCommandGlobalHandler - Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { + Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { (void)context; (void)executor; return TRY([&] { - auto command = File::StringViewType{cmd}; - auto command_parts = explode_by_occurrence(cmd, ' '); - File::StringType command_name; + auto command = UEStringToSystemString(cmd); + auto command_parts = explode_by_occurrence(command, ' '); + SystemStringType command_name; if (command_parts.size() > 1) { command_name = command_parts[0]; @@ -4333,12 +4354,12 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. if (Unreal::UObject::ProcessLocalScriptFunctionInternal.is_ready() && Unreal::Version::IsAtLeast(4, 22)) { - Output::send(STR("Enabling custom events\n")); + Output::send(SYSSTR("Enabling custom events\n")); Unreal::Hook::RegisterProcessLocalScriptFunctionPostCallback(script_hook); } else if (Unreal::UObject::ProcessInternalInternal.is_ready() && Unreal::Version::IsBelow(4, 22)) { - Output::send(STR("Enabling custom events\n")); + Output::send(SYSSTR("Enabling custom events\n")); Unreal::Hook::RegisterProcessInternalPostCallback(script_hook); } } @@ -4395,9 +4416,9 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - Output::send(STR("[{}] {}\n"), - to_wstring(action.type == LuaMod::ActionType::Loop ? "LoopAsync" : "DelayedAction"), - to_wstring(e.what())); + Output::send(SYSSTR("[{}] {}\n"), + to_generic_string(action.type == LuaMod::ActionType::Loop ? SYSSTR("LoopAsync") : SYSSTR("DelayedAction")), + to_generic_string(e.what())); } return result; diff --git a/UE4SS/src/Mod/Mod.cpp b/UE4SS/src/Mod/Mod.cpp index 65550fa71..b0cab8e7e 100644 --- a/UE4SS/src/Mod/Mod.cpp +++ b/UE4SS/src/Mod/Mod.cpp @@ -52,11 +52,11 @@ namespace RC { - Mod::Mod(UE4SSProgram& program, std::wstring&& mod_name, std::wstring&& mod_path) : m_program(program), m_mod_name(mod_name), m_mod_path(mod_path) + Mod::Mod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : m_program(program), m_mod_name(mod_name), m_mod_path(mod_path) { } - auto Mod::get_name() const -> std::wstring_view + auto Mod::get_name() const -> SystemStringViewType { return m_mod_name; } diff --git a/UE4SS/src/ObjectDumper/ObjectToString.cpp b/UE4SS/src/ObjectDumper/ObjectToString.cpp index 22784d9e3..3d0ff774d 100644 --- a/UE4SS/src/ObjectDumper/ObjectToString.cpp +++ b/UE4SS/src/ObjectDumper/ObjectToString.cpp @@ -56,54 +56,54 @@ namespace RC::ObjectDumper return object_to_string_complex_functions.contains(hash); } - auto object_trivial_dump_to_string(void* p_this, std::wstring& out_line, const wchar_t* post_delimiter) -> void + auto object_trivial_dump_to_string(void* p_this, SystemStringType& out_line, const SystemCharType* post_delimiter) -> void { UObject* p_typed_this = static_cast(p_this); - out_line.append(std::format(L"[{:016X}] ", reinterpret_cast(p_this))); - out_line.append(p_typed_this->GetFullName()); - out_line.append(std::format(L" [n: {:X}] [c: {:016X}] [or: {:016X}]", + out_line.append(std::format(SYSSTR("[{:016X}] "), reinterpret_cast(p_this))); + out_line.append(UEStringToSystemString(p_typed_this->GetFullName())); + out_line.append(std::format(SYSSTR(" [n: {:X}] [c: {:016X}] [or: {:016X}]"), p_typed_this->GetNamePrivate().GetComparisonIndex(), reinterpret_cast(p_typed_this->GetClassPrivate()), reinterpret_cast(p_typed_this->GetOuterPrivate()))); } - auto object_to_string(void* p_this, std::wstring& out_line) -> void + auto object_to_string(void* p_this, SystemStringType& out_line) -> void { object_trivial_dump_to_string(p_this, out_line); } - auto property_trivial_dump_to_string(void* p_this, std::wstring& out_line) -> void + auto property_trivial_dump_to_string(void* p_this, SystemStringType& out_line) -> void { FProperty* p_typed_this = static_cast(p_this); - out_line.append(std::format(L"[{:016X}] ", reinterpret_cast(p_this))); - out_line.append(p_typed_this->GetFullName()); - out_line.append(std::format(L" [o: {:X}] ", p_typed_this->GetOffset_Internal())); + out_line.append(std::format(SYSSTR("[{:016X}] "), reinterpret_cast(p_this))); + out_line.append(UEStringToSystemString(p_typed_this->GetFullName())); + out_line.append(std::format(SYSSTR(" [o: {:X}] "), p_typed_this->GetOffset_Internal())); auto property_class = p_typed_this->GetClass(); - out_line.append(std::format(L"[n: {:X}] [c: {:016X}]", p_typed_this->GetFName().GetComparisonIndex(), property_class.HashObject())); + out_line.append(std::format(SYSSTR("[n: {:X}] [c: {:016X}]"), p_typed_this->GetFName().GetComparisonIndex(), property_class.HashObject())); if (Version::IsAtLeast(4, 25)) { - out_line.append(std::format(L" [owr: {:016X}]", p_typed_this->GetOwnerVariant().HashObject())); + out_line.append(std::format(SYSSTR(" [owr: {:016X}]"), p_typed_this->GetOwnerVariant().HashObject())); } } - auto property_to_string(void* p_this, std::wstring& out_line) -> void + auto property_to_string(void* p_this, SystemStringType& out_line) -> void { property_trivial_dump_to_string(p_this, out_line); } - auto arrayproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto arrayproperty_to_string(void* p_this, SystemStringType& out_line) -> void { property_trivial_dump_to_string(p_this, out_line); FArrayProperty* p_typed_this = static_cast(p_this); - out_line.append(std::format(L" [ai: {:016X}]", reinterpret_cast(p_typed_this->GetInner()))); + out_line.append(std::format(SYSSTR(" [ai: {:016X}]"), reinterpret_cast(p_typed_this->GetInner()))); } - auto arrayproperty_to_string_complex(void* p_this, std::wstring& out_line, ObjectToStringComplexDeclCallable callable) -> void + auto arrayproperty_to_string_complex(void* p_this, SystemStringType& out_line, ObjectToStringComplexDeclCallable callable) -> void { FProperty* array_inner = static_cast(p_this)->GetInner(); auto array_inner_class = array_inner->GetClass().HashObject(); @@ -116,7 +116,7 @@ namespace RC::ObjectDumper { // If this code is executed then we'll be having another line before we return to the dumper, so we need to explicitly add a new line // If this code is not executed then we'll not be having another line and the dumper will add the new line - out_line.append(L"\n"); + out_line.append(SYSSTR("\n")); get_to_string_complex(array_inner_class)(array_inner, out_line, [&]([[maybe_unused]] void* prop) { // It's possible that a new line is supposed to be appended here @@ -127,22 +127,22 @@ namespace RC::ObjectDumper } else { - out_line.append(array_inner->GetFullName()); + out_line.append(UEStringToSystemString(array_inner->GetFullName())); callable(array_inner); } } - auto mapproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto mapproperty_to_string(void* p_this, SystemStringType& out_line) -> void { property_trivial_dump_to_string(p_this, out_line); FMapProperty* typed_this = static_cast(p_this); FProperty* key_property = typed_this->GetKeyProp(); FProperty* value_property = typed_this->GetValueProp(); - out_line.append(std::format(L" [kp: {:016X}] [vp: {:016X}]", reinterpret_cast(key_property), reinterpret_cast(value_property))); + out_line.append(std::format(SYSSTR(" [kp: {:016X}] [vp: {:016X}]"), reinterpret_cast(key_property), reinterpret_cast(value_property))); } - auto mapproperty_to_string_complex(void* p_this, std::wstring& out_line, ObjectToStringComplexDeclCallable callable) -> void + auto mapproperty_to_string_complex(void* p_this, SystemStringType& out_line, ObjectToStringComplexDeclCallable callable) -> void { FMapProperty* typed_this = static_cast(p_this); FProperty* key_property = typed_this->GetKeyProp(); @@ -159,7 +159,7 @@ namespace RC::ObjectDumper { // If this code is executed then we'll be having another line before we return to the dumper, so we need to explicitly add a new line // If this code is not executed then we'll not be having another line and the dumper will add the new line - out_line.append(L"\n"); + out_line.append(SYSSTR("\n")); get_to_string_complex(property_class)(property, out_line, [&]([[maybe_unused]] void* prop) {}); } @@ -168,7 +168,7 @@ namespace RC::ObjectDumper } else { - out_line.append(property->GetFullName()); + out_line.append(UEStringToSystemString(property->GetFullName())); callable(property); } }; @@ -177,83 +177,83 @@ namespace RC::ObjectDumper dump_property(value_property, value_property_class); } - auto classproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto classproperty_to_string(void* p_this, SystemStringType& out_line) -> void { FClassProperty* typed_this = static_cast(p_this); property_trivial_dump_to_string(p_this, out_line); // mc = MetaClass - out_line.append(std::format(L" [mc: {:016X}]", reinterpret_cast(typed_this->GetMetaClass()))); + out_line.append(std::format(SYSSTR(" [mc: {:016X}]"), reinterpret_cast(typed_this->GetMetaClass()))); } - auto delegateproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto delegateproperty_to_string(void* p_this, SystemStringType& out_line) -> void { property_trivial_dump_to_string(p_this, out_line); FDelegateProperty* p_typed_this = static_cast(p_this); - out_line.append(std::format(L" [df: {:016X}]", reinterpret_cast(p_typed_this->GetSignatureFunction()))); + out_line.append(std::format(SYSSTR(" [df: {:016X}]"), reinterpret_cast(p_typed_this->GetSignatureFunction()))); } - auto fieldpathproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto fieldpathproperty_to_string(void* p_this, SystemStringType& out_line) -> void { FFieldPathProperty* typed_this = static_cast(p_this); property_trivial_dump_to_string(p_this, out_line); - out_line.append(std::format(L" [pc: {:016X}]", reinterpret_cast(typed_this->GetPropertyClass()))); + out_line.append(std::format(SYSSTR(" [pc: {:016X}]"), reinterpret_cast(typed_this->GetPropertyClass()))); } - auto interfaceproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto interfaceproperty_to_string(void* p_this, SystemStringType& out_line) -> void { FInterfaceProperty* typed_this = static_cast(p_this); property_trivial_dump_to_string(p_this, out_line); - out_line.append(std::format(L" [ic: {:016X}]", reinterpret_cast(typed_this->GetInterfaceClass()))); + out_line.append(std::format(SYSSTR(" [ic: {:016X}]"), reinterpret_cast(typed_this->GetInterfaceClass()))); } - auto multicastdelegateproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto multicastdelegateproperty_to_string(void* p_this, SystemStringType& out_line) -> void { property_trivial_dump_to_string(p_this, out_line); FMulticastDelegateProperty* p_typed_this = static_cast(p_this); - out_line.append(std::format(L" [df: {:016X}]", reinterpret_cast(p_typed_this->GetSignatureFunction()))); + out_line.append(std::format(SYSSTR(" [df: {:016X}]"), reinterpret_cast(p_typed_this->GetSignatureFunction()))); } - auto objectproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto objectproperty_to_string(void* p_this, SystemStringType& out_line) -> void { FObjectProperty* typed_this = static_cast(p_this); property_trivial_dump_to_string(p_this, out_line); - out_line.append(std::format(L" [pc: {:016X}]", reinterpret_cast(typed_this->GetPropertyClass()))); + out_line.append(std::format(SYSSTR(" [pc: {:016X}]"), reinterpret_cast(typed_this->GetPropertyClass()))); } - auto structproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto structproperty_to_string(void* p_this, SystemStringType& out_line) -> void { FStructProperty* typed_this = static_cast(p_this); property_trivial_dump_to_string(p_this, out_line); - out_line.append(std::format(L" [ss: {:016X}]", reinterpret_cast(typed_this->GetStruct()))); + out_line.append(std::format(SYSSTR(" [ss: {:016X}]"), reinterpret_cast(typed_this->GetStruct()))); } - auto enumproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto enumproperty_to_string(void* p_this, SystemStringType& out_line) -> void { property_trivial_dump_to_string(p_this, out_line); auto* typed_this = static_cast(p_this); - out_line.append(std::format(L" [em: {:016X}]", reinterpret_cast(typed_this->GetEnum()))); + out_line.append(std::format(SYSSTR(" [em: {:016X}]"), reinterpret_cast(typed_this->GetEnum()))); } - auto boolproperty_to_string(void* p_this, std::wstring& out_line) -> void + auto boolproperty_to_string(void* p_this, SystemStringType& out_line) -> void { property_trivial_dump_to_string(p_this, out_line); auto* typed_this = static_cast(p_this); if (typed_this->GetFieldMask() != 255) { - out_line.append(std::format(L" [fm: {:X}] [bm: {:X}]", typed_this->GetFieldMask(), typed_this->GetByteMask())); + out_line.append(std::format(SYSSTR(" [fm: {:X}] [bm: {:X}]"), typed_this->GetFieldMask(), typed_this->GetByteMask())); } } - auto enum_to_string(void* p_this, std::wstring& out_line) -> void + auto enum_to_string(void* p_this, SystemStringType& out_line) -> void { object_trivial_dump_to_string(p_this, out_line); @@ -261,24 +261,24 @@ namespace RC::ObjectDumper for (auto& Elem : typed_this->ForEachName()) { - out_line.append(std::format(L"\n[{:016X}] {} [n: {:X}] [v: {}]", 0, Elem.Key.ToString(), Elem.Key.GetComparisonIndex(), Elem.Value)); + out_line.append(std::format(SYSSTR("\n[{:016X}] {} [n: {:X}] [v: {}]"), 0, UEStringToSystemString(Elem.Key.ToString()), Elem.Key.GetComparisonIndex(), Elem.Value)); } } - auto struct_to_string(void* p_this, std::wstring& out_line) -> void + auto struct_to_string(void* p_this, SystemStringType& out_line) -> void { UStruct* typed_this = static_cast(p_this); object_trivial_dump_to_string(p_this, out_line); - out_line.append(std::format(L" [sps: {:016X}]", reinterpret_cast(typed_this->GetSuperStruct()))); + out_line.append(std::format(SYSSTR(" [sps: {:016X}]"), reinterpret_cast(typed_this->GetSuperStruct()))); } - auto function_to_string(void* p_this, std::wstring& out_line) -> void + auto function_to_string(void* p_this, SystemStringType& out_line) -> void { - object_trivial_dump_to_string(p_this, out_line, L":"); + object_trivial_dump_to_string(p_this, out_line, SYSSTR(":")); } - auto scriptstruct_to_string_complex(void* p_this, std::wstring& out_line, ObjectToStringComplexDeclCallable callable) -> void + auto scriptstruct_to_string_complex(void* p_this, SystemStringType& out_line, ObjectToStringComplexDeclCallable callable) -> void { UScriptStruct* script_struct = static_cast(p_this); diff --git a/UE4SS/src/SDKGenerator/Common.cpp b/UE4SS/src/SDKGenerator/Common.cpp index 3948dbf5d..38c26affb 100644 --- a/UE4SS/src/SDKGenerator/Common.cpp +++ b/UE4SS/src/SDKGenerator/Common.cpp @@ -30,6 +30,7 @@ #pragma warning(default : 4005) #define DELEGATE_SIGNATURE_POSTFIX STR("__DelegateSignature") +#define DELEGATE_SIGNATURE_POSTFIX_SYS SYSSTR("__DelegateSignature") namespace RC::UEGenerator { @@ -41,22 +42,22 @@ namespace RC::UEGenerator if (interface_name) { - result_string.append(STR("I")); + result_string.append(SYSSTR("I")); } else if (uclass->IsChildOf()) { - result_string.append(STR("A")); + result_string.append(SYSSTR("A")); } else { - result_string.append(STR("U")); + result_string.append(SYSSTR("U")); } if ((uclass->GetClassFlags() & Unreal::CLASS_Deprecated) != 0) { - result_string.append(STR("DEPRECATED_")); + result_string.append(SYSSTR("DEPRECATED_")); } - result_string.append(uclass->GetName()); + result_string.append(UEStringToSystemString(uclass->GetName())); return result_string; } @@ -74,33 +75,33 @@ namespace RC::UEGenerator auto get_native_enum_name(UEnum* uenum, bool include_type) -> File::StringType { - std::wstring result_string; + SystemStringType result_string; // Seems to be not needed, because enum objects, unlike classes or structs, retain their normal E prefix - // ResultString.append(STR("E")); - result_string.append(uenum->GetName()); + // ResultString.append(SYSSTR("E")); + result_string.append(UEStringToSystemString(uenum->GetName())); // Namespaced enums need to have ::Type appended for the type if (uenum->GetCppForm() == UEnum::ECppForm::Namespaced && include_type) { - result_string.append(STR("::Type")); + result_string.append(SYSSTR("::Type")); } return result_string; } auto get_native_struct_name(UScriptStruct* script_struct) -> File::StringType { - std::wstring result_string; + SystemStringType result_string; - result_string.append(STR("F")); - result_string.append(script_struct->GetName()); + result_string.append(SYSSTR("F")); + result_string.append(UEStringToSystemString(script_struct->GetName())); return result_string; } auto sanitize_property_name(const File::StringType& property_name) -> File::StringType { - std::wstring resulting_name = property_name; + SystemStringType resulting_name = property_name; // Remove heading underscore, used by private variables in some games if (resulting_name.length() >= 2 && resulting_name[0] == '_') @@ -123,14 +124,14 @@ namespace RC::UEGenerator auto generate_delegate_name(FProperty* property, const File::StringType& context_name) -> File::StringType { - const std::wstring property_name = sanitize_property_name(property->GetName()); - return std::format(STR("F{}{}"), context_name, property_name); + const SystemStringType property_name = sanitize_property_name(UEStringToSystemString(property->GetName())); + return std::format(SYSSTR("F{}{}"), context_name, property_name); } auto generate_property_cxx_name(FProperty* property, bool is_top_level_declaration, UObject* class_context, EnableForwardDeclarations enable_forward_declarations) -> File::StringType { - const std::wstring field_class_name = property->GetClass().GetName(); + const SystemStringType field_class_name = UEStringToSystemString(property->GetClass().GetName()); // Byte Property if (property->IsA()) @@ -141,10 +142,10 @@ namespace RC::UEGenerator if (enum_value != NULL) { // Non-EnumClass enumerations should be wrapped into TEnumAsByte according to UHT - const std::wstring enum_type_name = get_native_enum_name(enum_value); - return std::format(STR("TEnumAsByte<{}>"), enum_type_name); + const SystemStringType enum_type_name = get_native_enum_name(enum_value); + return std::format(SYSSTR("TEnumAsByte<{}>"), enum_type_name); } - return STR("uint8"); + return SYSSTR("uint8"); } // Enum Property @@ -158,7 +159,7 @@ namespace RC::UEGenerator throw std::runtime_error(RC::fmt("EnumProperty %S does not have a valid Enum value", property->GetName().c_str())); } - const std::wstring enum_type_name = get_native_enum_name(uenum); + const SystemStringType enum_type_name = get_native_enum_name(uenum); return enum_type_name; } @@ -168,47 +169,47 @@ namespace RC::UEGenerator FBoolProperty* bool_property = static_cast(property); if (is_top_level_declaration && bool_property->GetFieldMask() != 255) { - return STR("uint8"); + return SYSSTR("uint8"); } - return STR("bool"); + return SYSSTR("bool"); } // Standard Numeric Properties if (property->IsA()) { - return STR("int8"); + return SYSSTR("int8"); } else if (property->IsA()) { - return STR("int16"); + return SYSSTR("int16"); } else if (property->IsA()) { - return STR("int32"); + return SYSSTR("int32"); } else if (property->IsA()) { - return STR("int64"); + return SYSSTR("int64"); } else if (property->IsA()) { - return STR("uint16"); + return SYSSTR("uint16"); } else if (property->IsA()) { - return STR("uint32"); + return SYSSTR("uint32"); } else if (property->IsA()) { - return STR("uint64"); + return SYSSTR("uint64"); } else if (property->IsA()) { - return STR("float"); + return SYSSTR("float"); } else if (property->IsA()) { - return STR("double"); + return SYSSTR("double"); } // Class Properties @@ -219,22 +220,22 @@ namespace RC::UEGenerator if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return STR("UClass*"); + return SYSSTR("UClass*"); } File::StringType meta_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { - meta_class_name = STR("class "); + meta_class_name = SYSSTR("class "); } meta_class_name.append(get_native_class_name(meta_class, false)); - return std::format(STR("TSubclassOf<{}>"), meta_class_name); + return std::format(SYSSTR("TSubclassOf<{}>"), meta_class_name); } if (auto* class_property = CastField(property); class_property) { // TODO: Confirm that this is accurate - return STR("TObjectPtr"); + return SYSSTR("TObjectPtr"); } if (property->IsA()) @@ -244,15 +245,15 @@ namespace RC::UEGenerator if (meta_class == NULL) { - return STR("TSoftClassPtr"); + return SYSSTR("TSoftClassPtr"); } else if (meta_class == UObject::StaticClass()) { - return STR("TSoftClassPtr"); + return SYSSTR("TSoftClassPtr"); } - const std::wstring meta_class_name = get_native_class_name(meta_class, false); - return std::format(STR("TSoftClassPtr<{}>"), meta_class_name); + const SystemStringType meta_class_name = get_native_class_name(meta_class, false); + return std::format(SYSSTR("TSoftClassPtr<{}>"), meta_class_name); } // Object Properties @@ -265,11 +266,11 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("UObject*"); + return SYSSTR("UObject*"); } - const std::wstring property_class_name = get_native_class_name(property_class, false); - return std::format(STR("{}*"), property_class_name); + const SystemStringType property_class_name = get_native_class_name(property_class, false); + return std::format(SYSSTR("{}*"), property_class_name); } if (auto* object_property = CastField(property); object_property) @@ -278,12 +279,12 @@ namespace RC::UEGenerator if (!property_class) { - return STR("TObjectPtr"); + return SYSSTR("TObjectPtr"); } else { const auto property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TObjectPtr<{}>"), property_class_name); } } @@ -294,16 +295,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TWeakObjectPtr"); + return SYSSTR("TWeakObjectPtr"); } File::StringType property_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { - property_class_name = std::format(STR("class ")); + property_class_name = std::format(SYSSTR("class ")); } property_class_name.append(get_native_class_name(property_class, false)); - return std::format(STR("TWeakObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TWeakObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -313,16 +314,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TLazyObjectPtr"); + return SYSSTR("TLazyObjectPtr"); } File::StringType property_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { - property_class_name = STR("class "); + property_class_name = SYSSTR("class "); } property_class_name.append(get_native_class_name(property_class, false)); - return std::format(STR("TLazyObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TLazyObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -332,11 +333,11 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TSoftObjectPtr"); + return SYSSTR("TSoftObjectPtr"); } - const std::wstring property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TSoftObjectPtr<{}>"), property_class_name); + const SystemStringType property_class_name = get_native_class_name(property_class, false); + return std::format(SYSSTR("TSoftObjectPtr<{}>"), property_class_name); } // Interface Property @@ -347,16 +348,16 @@ namespace RC::UEGenerator if (interface_class == NULL || interface_class == UInterface::StaticClass()) { - return STR("FScriptInterface"); + return SYSSTR("FScriptInterface"); } File::StringType interface_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { - interface_class_name = STR("class "); + interface_class_name = SYSSTR("class "); } interface_class_name.append(get_native_class_name(interface_class, true)); - return std::format(STR("TScriptInterface<{}>"), interface_class_name); + return std::format(SYSSTR("TScriptInterface<{}>"), interface_class_name); } // Struct Property @@ -370,7 +371,7 @@ namespace RC::UEGenerator throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); } - const std::wstring native_struct_name = get_native_struct_name(script_struct); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); return native_struct_name; } @@ -379,7 +380,7 @@ namespace RC::UEGenerator { FDelegateProperty* delegate_property = static_cast(property); - const std::wstring delegate_type_name = generate_delegate_name(delegate_property, class_context->GetName()); + const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); return delegate_type_name; } @@ -389,7 +390,7 @@ namespace RC::UEGenerator { FMulticastInlineDelegateProperty* delegate_property = static_cast(property); - const std::wstring delegate_type_name = generate_delegate_name(delegate_property, class_context->GetName()); + const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); return delegate_type_name; } @@ -397,7 +398,7 @@ namespace RC::UEGenerator { FMulticastSparseDelegateProperty* delegate_property = static_cast(property); - const std::wstring delegate_type_name = generate_delegate_name(delegate_property, class_context->GetName()); + const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); return delegate_type_name; } @@ -405,8 +406,8 @@ namespace RC::UEGenerator if (property->IsA()) { FFieldPathProperty* field_path_property = static_cast(property); - const std::wstring property_class_name = field_path_property->GetPropertyClass()->GetName(); - return std::format(STR("TFieldPath"), property_class_name); + const SystemStringType property_class_name = UEStringToSystemString(field_path_property->GetPropertyClass()->GetName()); + return std::format(SYSSTR("TFieldPath"), property_class_name); } // Collection and Map Properties @@ -421,11 +422,11 @@ namespace RC::UEGenerator { if (inner_property->IsA()) { - inner_property_type = STR("class "); + inner_property_type = SYSSTR("class "); } } inner_property_type.append(generate_property_cxx_name(inner_property, is_top_level_declaration, class_context)); - return std::format(STR("TArray<{}>"), inner_property_type); + return std::format(SYSSTR("TArray<{}>"), inner_property_type); } if (property->IsA()) @@ -433,8 +434,8 @@ namespace RC::UEGenerator FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const std::wstring element_property_type = generate_property_cxx_name(element_prop, is_top_level_declaration, class_context); - return std::format(STR("TSet<{}>"), element_property_type); + const SystemStringType element_property_type = generate_property_cxx_name(element_prop, is_top_level_declaration, class_context); + return std::format(SYSSTR("TSet<{}>"), element_property_type); } // TODO: This is missing support for freeze image map properties because XMapProperty is incomplete. (low priority) @@ -450,42 +451,42 @@ namespace RC::UEGenerator { if (!key_property->IsA()) { - key_type = STR("class "); + key_type = SYSSTR("class "); } if (!value_property->IsA()) { - value_type = STR("class "); + value_type = SYSSTR("class "); } } key_type.append(generate_property_cxx_name(key_property, is_top_level_declaration, class_context)); value_type.append(generate_property_cxx_name(value_property, is_top_level_declaration, class_context)); - return std::format(STR("TMap<{}, {}>"), key_type, value_type); + return std::format(SYSSTR("TMap<{}, {}>"), key_type, value_type); } // Standard properties that do not have any special attributes if (property->IsA()) { - return STR("FName"); + return SYSSTR("FName"); } else if (property->IsA()) { - return STR("FString"); + return SYSSTR("FString"); } else if (property->IsA()) { - return STR("FText"); + return SYSSTR("FText"); } - throw std::runtime_error(RC::fmt("Unsupported property class %S", field_class_name.c_str())); + throw std::runtime_error(RC::fmt("Unsupported property class " SystemStringPrint, field_class_name.c_str())); } auto generate_property_lua_name(FProperty* property, bool is_top_level_declaration, UObject* class_context) -> File::StringType { - const std::wstring field_class_name = property->GetClass().GetName(); + const SystemStringType field_class_name = UEStringToSystemString(property->GetClass().GetName()); // Byte Property - if (field_class_name == STR("ByteProperty")) + if (field_class_name == SYSSTR("ByteProperty")) { FByteProperty* byte_property = static_cast(property); UEnum* enum_value = byte_property->GetEnum(); @@ -493,14 +494,14 @@ namespace RC::UEGenerator if (enum_value != NULL) { // Non-EnumClass enumerations should be wrapped into TEnumAsByte according to UHT - const std::wstring enum_type_name = get_native_enum_name(enum_value); - return std::format(STR("{}"), enum_type_name); + const SystemStringType enum_type_name = get_native_enum_name(enum_value); + return std::format(SYSSTR("{}"), enum_type_name); } - return STR("uint8"); + return SYSSTR("uint8"); } // Enum Property - if (field_class_name == STR("EnumProperty")) + if (field_class_name == SYSSTR("EnumProperty")) { FEnumProperty* enum_property = static_cast(property); UEnum* uenum = enum_property->GetEnum(); @@ -510,69 +511,69 @@ namespace RC::UEGenerator throw std::runtime_error(RC::fmt("EnumProperty %S does not have a valid Enum value", property->GetName().c_str())); } - const std::wstring enum_type_name = get_native_enum_name(uenum); + const SystemStringType enum_type_name = get_native_enum_name(uenum); return enum_type_name; } // Bool Property - if (field_class_name == STR("BoolProperty")) + if (field_class_name == SYSSTR("BoolProperty")) { - return STR("boolean"); + return SYSSTR("boolean"); } // Standard Numeric Properties - if (field_class_name == STR("Int8Property")) + if (field_class_name == SYSSTR("Int8Property")) { - return STR("int8"); + return SYSSTR("int8"); } - else if (field_class_name == STR("Int16Property")) + else if (field_class_name == SYSSTR("Int16Property")) { - return STR("int16"); + return SYSSTR("int16"); } - else if (field_class_name == STR("IntProperty")) + else if (field_class_name == SYSSTR("IntProperty")) { - return STR("int32"); + return SYSSTR("int32"); } - else if (field_class_name == STR("Int64Property")) + else if (field_class_name == SYSSTR("Int64Property")) { - return STR("int64"); + return SYSSTR("int64"); } - else if (field_class_name == STR("UInt16Property")) + else if (field_class_name == SYSSTR("UInt16Property")) { - return STR("uint16"); + return SYSSTR("uint16"); } - else if (field_class_name == STR("UInt32Property")) + else if (field_class_name == SYSSTR("UInt32Property")) { - return STR("uint32"); + return SYSSTR("uint32"); } - else if (field_class_name == STR("UInt64Property")) + else if (field_class_name == SYSSTR("UInt64Property")) { - return STR("uint64"); + return SYSSTR("uint64"); } - else if (field_class_name == STR("FloatProperty")) + else if (field_class_name == SYSSTR("FloatProperty")) { - return STR("float"); + return SYSSTR("float"); } - else if (field_class_name == STR("DoubleProperty")) + else if (field_class_name == SYSSTR("DoubleProperty")) { - return STR("double"); + return SYSSTR("double"); } // Object Properties // TODO: Verify that the syntax for 'AssetObjectProperty' is the same as for 'ObjectProperty'. // If it's not, then add another branch here after you figure out what the syntax should be. - if (field_class_name == STR("ObjectProperty") || field_class_name == STR("AssetObjectProperty")) + if (field_class_name == SYSSTR("ObjectProperty") || field_class_name == SYSSTR("AssetObjectProperty")) { FObjectProperty* object_property = static_cast(property); UClass* property_class = object_property->GetPropertyClass(); if (property_class == NULL) { - return STR("UObject"); + return SYSSTR("UObject"); } - const std::wstring property_class_name = get_native_class_name(property_class, false); - return std::format(STR("{}"), property_class_name); + const SystemStringType property_class_name = get_native_class_name(property_class, false); + return std::format(SYSSTR("{}"), property_class_name); } if (auto* object_property = CastField(property); object_property) @@ -581,113 +582,113 @@ namespace RC::UEGenerator if (!property_class) { - return STR("TObjectPtr"); + return SYSSTR("TObjectPtr"); } else { const auto property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TObjectPtr<{}>"), property_class_name); } } - if (field_class_name == STR("WeakObjectProperty")) + if (field_class_name == SYSSTR("WeakObjectProperty")) { FWeakObjectProperty* weak_object_property = static_cast(property); UClass* property_class = weak_object_property->GetPropertyClass(); if (property_class == NULL) { - return STR("TWeakObjectPtr"); + return SYSSTR("TWeakObjectPtr"); } File::StringType property_class_name{}; property_class_name.append(get_native_class_name(property_class, false)); - return std::format(STR("TWeakObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TWeakObjectPtr<{}>"), property_class_name); } - if (field_class_name == STR("LazyObjectProperty")) + if (field_class_name == SYSSTR("LazyObjectProperty")) { FLazyObjectProperty* lazy_object_property = static_cast(property); UClass* property_class = lazy_object_property->GetPropertyClass(); if (property_class == NULL) { - return STR("TLazyObjectPtr"); + return SYSSTR("TLazyObjectPtr"); } File::StringType property_class_name{}; property_class_name.append(get_native_class_name(property_class, false)); - return std::format(STR("TLazyObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TLazyObjectPtr<{}>"), property_class_name); } - if (field_class_name == STR("SoftObjectProperty")) + if (field_class_name == SYSSTR("SoftObjectProperty")) { FSoftObjectProperty* soft_object_property = static_cast(property); UClass* property_class = soft_object_property->GetPropertyClass(); if (property_class == NULL) { - return STR("TSoftObjectPtr"); + return SYSSTR("TSoftObjectPtr"); } - const std::wstring property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TSoftObjectPtr<{}>"), property_class_name); + const SystemStringType property_class_name = get_native_class_name(property_class, false); + return std::format(SYSSTR("TSoftObjectPtr<{}>"), property_class_name); } // Class Properties - if (field_class_name == STR("ClassProperty") || field_class_name == STR("AssetClassProperty")) + if (field_class_name == SYSSTR("ClassProperty") || field_class_name == SYSSTR("AssetClassProperty")) { FClassProperty* class_property = static_cast(property); UClass* meta_class = class_property->GetMetaClass(); if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return STR("UClass"); + return SYSSTR("UClass"); } File::StringType meta_class_name{}; meta_class_name.append(get_native_class_name(meta_class, false)); - return std::format(STR("TSubclassOf<{}>"), meta_class_name); + return std::format(SYSSTR("TSubclassOf<{}>"), meta_class_name); } if (auto* class_property = CastField(property); class_property) { // TODO: Confirm that this is accurate - return STR("TObjectPtr"); + return SYSSTR("TObjectPtr"); } - if (field_class_name == STR("SoftClassProperty")) + if (field_class_name == SYSSTR("SoftClassProperty")) { FSoftClassProperty* soft_class_property = static_cast(property); UClass* meta_class = soft_class_property->GetMetaClass(); if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return STR("TSoftClassPtr"); + return SYSSTR("TSoftClassPtr"); } - const std::wstring meta_class_name = get_native_class_name(meta_class, false); - return std::format(STR("TSoftClassPtr<{}>"), meta_class_name); + const SystemStringType meta_class_name = get_native_class_name(meta_class, false); + return std::format(SYSSTR("TSoftClassPtr<{}>"), meta_class_name); } // Interface Property - if (field_class_name == STR("InterfaceProperty")) + if (field_class_name == SYSSTR("InterfaceProperty")) { FInterfaceProperty* interface_property = static_cast(property); UClass* interface_class = interface_property->GetInterfaceClass(); if (interface_class == NULL || interface_class == UInterface::StaticClass()) { - return STR("FScriptInterface"); + return SYSSTR("FScriptInterface"); } File::StringType interface_class_name{}; interface_class_name.append(get_native_class_name(interface_class, true)); - return std::format(STR("TScriptInterface<{}>"), interface_class_name); + return std::format(SYSSTR("TScriptInterface<{}>"), interface_class_name); } // Struct Property - if (field_class_name == STR("StructProperty")) + if (field_class_name == SYSSTR("StructProperty")) { FStructProperty* struct_property = static_cast(property); UScriptStruct* script_struct = struct_property->GetStruct(); @@ -697,68 +698,68 @@ namespace RC::UEGenerator throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); } - const std::wstring native_struct_name = get_native_struct_name(script_struct); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); return native_struct_name; } // Delegate Properties - if (field_class_name == STR("DelegateProperty")) + if (field_class_name == SYSSTR("DelegateProperty")) { FDelegateProperty* delegate_property = static_cast(property); - const std::wstring delegate_type_name = generate_delegate_name(delegate_property, class_context->GetName()); + const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); return delegate_type_name; } // In 4.23, they replaced 'MulticastDelegateProperty' with 'Inline' & 'Sparse' variants // It looks like the delegate macro might be the same as the 'Inline' variant in later versions, so we'll use the same branch here - if (field_class_name == STR("MulticastInlineDelegateProperty") || field_class_name == STR("MulticastDelegateProperty")) + if (field_class_name == SYSSTR("MulticastInlineDelegateProperty") || field_class_name == SYSSTR("MulticastDelegateProperty")) { FMulticastInlineDelegateProperty* delegate_property = static_cast(property); - const std::wstring delegate_type_name = generate_delegate_name(delegate_property, class_context->GetName()); + const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); return delegate_type_name; } - if (field_class_name == STR("MulticastSparseDelegateProperty")) + if (field_class_name == SYSSTR("MulticastSparseDelegateProperty")) { FMulticastSparseDelegateProperty* delegate_property = static_cast(property); - const std::wstring delegate_type_name = generate_delegate_name(delegate_property, class_context->GetName()); + const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); return delegate_type_name; } // Field path property - if (field_class_name == STR("FieldPathProperty")) + if (field_class_name == SYSSTR("FieldPathProperty")) { FFieldPathProperty* field_path_property = static_cast(property); - const std::wstring property_class_name = field_path_property->GetPropertyClass()->GetName(); - return std::format(STR("TFieldPath"), property_class_name); + const SystemStringType property_class_name = UEStringToSystemString(field_path_property->GetPropertyClass()->GetName()); + return std::format(SYSSTR("TFieldPath"), property_class_name); } // Collection and Map Properties // TODO: This is missing support for freeze image array properties because XArrayProperty is incomplete. (low priority) - if (field_class_name == STR("ArrayProperty")) + if (field_class_name == SYSSTR("ArrayProperty")) { FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); File::StringType inner_property_type{}; inner_property_type.append(generate_property_lua_name(inner_property, is_top_level_declaration, class_context)); - return std::format(STR("TArray<{}>"), inner_property_type); + return std::format(SYSSTR("TArray<{}>"), inner_property_type); } - if (field_class_name == STR("SetProperty")) + if (field_class_name == SYSSTR("SetProperty")) { FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const std::wstring element_property_type = generate_property_lua_name(element_prop, is_top_level_declaration, class_context); - return std::format(STR("TSet<{}>"), element_property_type); + const SystemStringType element_property_type = generate_property_lua_name(element_prop, is_top_level_declaration, class_context); + return std::format(SYSSTR("TSet<{}>"), element_property_type); } // TODO: This is missing support for freeze image map properties because XMapProperty is incomplete. (low priority) - if (field_class_name == STR("MapProperty")) + if (field_class_name == SYSSTR("MapProperty")) { FMapProperty* map_property = static_cast(property); FProperty* key_property = map_property->GetKeyProp(); @@ -769,21 +770,21 @@ namespace RC::UEGenerator key_type.append(generate_property_lua_name(key_property, is_top_level_declaration, class_context)); value_type.append(generate_property_lua_name(value_property, is_top_level_declaration, class_context)); - return std::format(STR("TMap<{}, {}>"), key_type, value_type); + return std::format(SYSSTR("TMap<{}, {}>"), key_type, value_type); } // Standard properties that do not have any special attributes - if (field_class_name == STR("NameProperty")) + if (field_class_name == SYSSTR("NameProperty")) { - return STR("FName"); + return SYSSTR("FName"); } - else if (field_class_name == STR("StrProperty")) + else if (field_class_name == SYSSTR("StrProperty")) { - return STR("FString"); + return SYSSTR("FString"); } - else if (field_class_name == STR("TextProperty")) + else if (field_class_name == SYSSTR("TextProperty")) { - return STR("FText"); + return SYSSTR("FText"); } throw std::runtime_error(RC::fmt("Unsupported property class %S", field_class_name.c_str())); } @@ -797,7 +798,7 @@ namespace RC::UEGenerator // Delegate names always start with F and have __DelegateSignature postfix File::StringType delegate_type_name = strip_delegate_signature_postfix(signature_function); - delegate_type_name.insert(0, STR("F")); + delegate_type_name.insert(0, SYSSTR("F")); // Return the delegate name without the outer name if we have been requested to strip it if (strip_outer_name) @@ -818,7 +819,7 @@ namespace RC::UEGenerator bool is_class_interface = delegate_outer_class->IsChildOf(); const File::StringType outer_class_name = get_native_class_name(delegate_outer_class, is_class_interface); - delegate_type_name.insert(0, STR("::")); + delegate_type_name.insert(0, SYSSTR("::")); delegate_type_name.insert(0, outer_class_name); } } @@ -843,9 +844,9 @@ namespace RC::UEGenerator } // Delegate names always start with F and have __DelegateSignature postfix - const File::StringType delegate_signature_postfix = DELEGATE_SIGNATURE_POSTFIX; + const SystemStringType delegate_signature_postfix = DELEGATE_SIGNATURE_POSTFIX_SYS; - File::StringType delegate_name = signature_function->GetName(); + SystemStringType delegate_name = UEStringToSystemString (signature_function->GetName()); delegate_name.erase(delegate_name.length() - delegate_signature_postfix.length()); return delegate_name; } diff --git a/UE4SS/src/SDKGenerator/Generator.cpp b/UE4SS/src/SDKGenerator/Generator.cpp index 6980cd161..b2ddff5c6 100644 --- a/UE4SS/src/SDKGenerator/Generator.cpp +++ b/UE4SS/src/SDKGenerator/Generator.cpp @@ -85,7 +85,7 @@ namespace RC::UEGenerator File::StringType tab_storage{}; for (size_t i = 0; i < num_tabs; ++i) { - tab_storage += STR(" "); + tab_storage += SYSSTR(" "); } return tab_storage; @@ -95,11 +95,11 @@ namespace RC::UEGenerator UClass* obj_class = obj->GetClassPrivate(); if (obj_class->IsChildOf()) { - return STR("struct"); + return SYSSTR("struct"); } else { - return STR("class"); + return SYSSTR("class"); } } auto generate_class_name(UStruct* class_to_generate) -> File::StringType @@ -146,7 +146,7 @@ namespace RC::UEGenerator auto create_all_files() -> void { - Output::send(STR("Creating all files...\n")); + Output::send(SYSSTR("Creating all files...\n")); for (auto& [comparison_index, generated_file] : m_files) { if (!generated_file.ordered_primary_file_contents.empty()) @@ -166,7 +166,7 @@ namespace RC::UEGenerator if (combined_file_contents.empty()) { - Output::send(STR("Empty primary file contents in '{}'\n"), generated_file.package_name); + Output::send(SYSSTR("Empty primary file contents in '{}'\n"), generated_file.package_name); } else { @@ -193,7 +193,7 @@ namespace RC::UEGenerator if (combined_file_contents.empty()) { - Output::send(STR("Empty secondary file contents in '{}'\n"), generated_file.package_name); + Output::send(SYSSTR("Empty secondary file contents in '{}'\n"), generated_file.package_name); } else { @@ -212,11 +212,11 @@ namespace RC::UEGenerator std::vector other_content; for (auto& line : content) { - if (line.starts_with(STR("struct"))) + if (line.starts_with(SYSSTR("struct"))) { struct_content.push_back(line); } - else if (line.starts_with(STR("class"))) + else if (line.starts_with(SYSSTR("class"))) { class_content.push_back(line); } @@ -246,16 +246,16 @@ namespace RC::UEGenerator }); } - auto get_class_name(const auto& x) -> std::wstring + auto get_class_name(const auto& x) -> SystemStringType { // Using this method instead of regex because it is extremely slow - auto class_name = x.substr(x.find(STR(' ')) + 1); - class_name = class_name.substr(0, class_name.find(STR(' '))); - if (class_name == STR("class")) + auto class_name = x.substr(x.find(SYSSTR(' ')) + 1); + class_name = class_name.substr(0, class_name.find(SYSSTR(' '))); + if (class_name == SYSSTR("class")) { // Case for enum class - class_name = x.substr(x.find(STR(' ')) + 7); - class_name = class_name.substr(0, class_name.find(STR(' '))); + class_name = x.substr(x.find(SYSSTR(' ')) + 7); + class_name = class_name.substr(0, class_name.find(SYSSTR(' '))); } return class_name; } @@ -269,7 +269,7 @@ namespace RC::UEGenerator { if (UE4SSProgram::settings_manager.CXXHeaderGenerator.DumpOffsetsAndSizes) { - return std::format(STR("{:85} // 0x{:04X} (size: 0x{:X})"), line, property->GetOffset_Internal(), property->GetSize()); + return std::format(SYSSTR("{:85} // 0x{:04X} (size: 0x{:X})"), line, property->GetOffset_Internal(), property->GetSize()); } else { @@ -342,14 +342,14 @@ namespace RC::UEGenerator return return_property_info.has_value() ? return_property_info.value().property : nullptr; }(); - File::StringType function_name{function_info.function->GetName()}; + File::StringType function_name{UEStringToSystemString(function_info.function->GetName())}; if (is_delegate_function == IsDelegateFunction::Yes) { // Remove the last 19 characters, which is always '__DelegateSignature' for delegates function_name.erase(function_name.size() - 19, 19); } - StringType current_class_content{}; + SystemStringType current_class_content{}; specification.generate_function_declaration(this, current_class_content, owner, function_info, function_name, return_property, return_property_info); // Commenting out this code because all network replicated functions are events @@ -357,10 +357,10 @@ namespace RC::UEGenerator /* if ((function->get_function_flags() & Unreal::EFunctionFlags::FUNC_Event) != 0) { - current_class_content.append(STR(" // EVENT")); + current_class_content.append(SYSSTR(" // EVENT")); } //*/ - current_class_content.append(STR("\n")); + current_class_content.append(SYSSTR("\n")); out_current_class_content.append(current_class_content); } @@ -488,12 +488,12 @@ namespace RC::UEGenerator size_t colon_pos = enum_value_full_name.rfind(STR(":")); auto enum_value_name = colon_pos == enum_value_full_name.npos ? enum_value_full_name : enum_value_full_name.substr(colon_pos + 1); - specification.generate_enum_member(content_buffer, uenum, enum_value_name, elem); + specification.generate_enum_member(content_buffer, uenum, UEStringToSystemString(enum_value_name), elem); } specification.generate_enum_end(content_buffer, uenum); - content_buffer.append(STR("\n\n")); + content_buffer.append(SYSSTR("\n\n")); generated_file.ordered_secondary_file_contents.push_back(content_buffer); } @@ -538,8 +538,8 @@ namespace RC::UEGenerator else { // Get rid of everything before the last slash + the last slash, leaving only the actual name - File::StringType package_name = package->GetNamePrivate().ToString(); - package_name = package_name.substr(package_name.rfind(STR("/")) + 1); + File::StringType package_name = UEStringToSystemString(package->GetNamePrivate().ToString()); + package_name = package_name.substr(package_name.rfind(SYSSTR("/")) + 1); File::StringType package_name_all_lower = package_name; std::transform(package_name_all_lower.begin(), package_name_all_lower.end(), package_name_all_lower.begin(), [](File::CharType c) { return std::towlower(c); @@ -549,8 +549,8 @@ namespace RC::UEGenerator { // File name collision auto& file_name = m_file_names[package_name_all_lower]; - package_name.append(std::format(STR("_DUPL_{}"), ++file_name.num_collisions)); - Output::send(STR("File name collision, renamed to '{}'\n"), package_name); + package_name.append(std::format(SYSSTR("_DUPL_{}"), ++file_name.num_collisions)); + Output::send(SYSSTR("File name collision, renamed to '{}'\n"), package_name); } else { @@ -558,8 +558,12 @@ namespace RC::UEGenerator } // The '\\?\' at the beginning of the string unlocks path size restriction from MAX_PATH to 32k + #ifdef WIN32 std::filesystem::path directory_to_generate_in = std::filesystem::path("\\\\?\\"); directory_to_generate_in += (m_directory_to_generate_in); + #else + std::filesystem::path directory_to_generate_in = (m_directory_to_generate_in); + #endif File::StringType ext = specification.get_file_extension(); std::filesystem::path primary_file_path_and_name = directory_to_generate_in; @@ -567,7 +571,7 @@ namespace RC::UEGenerator primary_file_path_and_name.replace_extension(ext); std::filesystem::path secondary_file_path_and_name = directory_to_generate_in; - secondary_file_path_and_name.append(package_name + STR("_enums")); + secondary_file_path_and_name.append(package_name + SYSSTR("_enums")); secondary_file_path_and_name.replace_extension(ext); GeneratedFile generated_file{ @@ -612,9 +616,9 @@ namespace RC::UEGenerator public: auto generate() -> void { - Output::send(STR("Cleaning up old SDK files...\n")); + Output::send(SYSSTR("Cleaning up old SDK files...\n")); cleanup_old_sdk(); - Output::send(STR("Generating SDK...\n")); + Output::send(SYSSTR("Generating SDK...\n")); // 400k should be enough for most games, and it's highly unlikely to cause more than one reallocation even if the game is huge m_classes_dumped.reserve(400000); @@ -669,54 +673,54 @@ namespace RC::UEGenerator public: auto get_file_extension() -> File::StringType { - return STR(".hpp"); + return SYSSTR(".hpp"); } auto generate_file_header(GeneratedFile& generated_file) -> void { generated_file.primary_file.write_string_to_file( - std::format(STR("#ifndef UE4SS_SDK_{}_HPP\n#define UE4SS_SDK_{}_HPP\n\n"), generated_file.package_name, generated_file.package_name)); + std::format(SYSSTR("#ifndef UE4SS_SDK_{}_HPP\n#define UE4SS_SDK_{}_HPP\n\n"), generated_file.package_name, generated_file.package_name)); if (!generated_file.secondary_file_has_no_contents) { - generated_file.primary_file.write_string_to_file(std::format(STR("#include \"{}\"\n\n"), generated_file.secondary_file_name.filename().c_str())); + generated_file.primary_file.write_string_to_file(std::format(SYSSTR("#include \"{}\"\n\n"), generated_file.secondary_file_name.filename().c_str())); } } auto generate_file_footer(GeneratedFile& generated_file) -> void { - generated_file.primary_file.write_string_to_file(std::format(STR("#endif\n"))); + generated_file.primary_file.write_string_to_file(std::format(SYSSTR("#endif\n"))); } auto generate_enum_declaration(File::StringType& content_buffer, UEnum* uenum) -> void { const auto cpp_form = uenum->GetCppForm(); if (cpp_form == UEnum::ECppForm::Regular) { - content_buffer.append(std::format(STR("enum {} {{\n"), get_native_enum_name(uenum, false))); + content_buffer.append(std::format(SYSSTR("enum {} {{\n"), get_native_enum_name(uenum, false))); } else if (cpp_form == UEnum::ECppForm::Namespaced) { - content_buffer.append(std::format(STR("namespace {} {{\n{}enum Type {{\n"), get_native_enum_name(uenum, false), generate_tab())); + content_buffer.append(std::format(SYSSTR("namespace {} {{\n{}enum Type {{\n"), get_native_enum_name(uenum, false), generate_tab())); } else if (cpp_form == UEnum::ECppForm::EnumClass) { - content_buffer.append(std::format(STR("enum class {} {{\n"), get_native_enum_name(uenum, false))); + content_buffer.append(std::format(SYSSTR("enum class {} {{\n"), get_native_enum_name(uenum, false))); } } auto generate_enum_member(File::StringType& content_buffer, UEnum* uenum, const File::StringType& enum_value_name, const Unreal::FEnumNamePair& elem) -> void { - content_buffer.append(std::format(STR("{}{}{} = {},\n"), + content_buffer.append(std::format(SYSSTR("{}{}{} = {},\n"), generate_tab(), - uenum->GetCppForm() == UEnum::ECppForm::Namespaced ? generate_tab() : STR(""), + uenum->GetCppForm() == UEnum::ECppForm::Namespaced ? generate_tab() : SYSSTR(""), enum_value_name, elem.Value)); } auto generate_enum_end(File::StringType& content_buffer, UEnum* uenum) -> void { const auto cpp_form = uenum->GetCppForm(); - content_buffer.append(std::format(STR("{}}};"), cpp_form == UEnum::ECppForm::Namespaced ? generate_tab() : STR(""))); + content_buffer.append(std::format(SYSSTR("{}}};"), cpp_form == UEnum::ECppForm::Namespaced ? generate_tab() : SYSSTR(""))); if (cpp_form == UEnum::ECppForm::Namespaced) { - content_buffer.append(STR("\n}")); + content_buffer.append(SYSSTR("\n}")); } } auto should_generate_class(UStruct* native_class) @@ -772,22 +776,22 @@ namespace RC::UEGenerator int32_t current_property_offset = property->GetOffset_Internal(); int32_t current_property_size = property->GetSize(); - StringType part_one{}; + SystemStringType part_one{}; try { - part_one = std::format(STR("{}{}{} {};"), + part_one = std::format(SYSSTR("{}{}{} {};"), generate_tab(), - property_info.should_forward_declare ? STR("class ") : STR(""), + property_info.should_forward_declare ? SYSSTR("class ") : SYSSTR(""), generate_property_cxx_name(property, true, native_class, EnableForwardDeclarations::Yes), - property->GetName()); + UEStringToSystemString(property->GetName())); } catch (std::exception& e) { - Output::send(STR("Could not generate property '{}' because: {}\n"), property->GetFullName(), to_wstring(e.what())); + Output::send(SYSSTR("Could not generate property '{}' because: {}\n"),UEStringToSystemString(property->GetFullName()), to_generic_string(e.what())); continue; } - content_buffer.append(std::format(STR("{}\n"), generator->generate_offset_comment(property, part_one))); + content_buffer.append(std::format(SYSSTR("{}\n"), generator->generate_offset_comment(property, part_one))); if (property->IsA()) { @@ -839,12 +843,12 @@ namespace RC::UEGenerator int32_t padding_property_offset = current_property_end_location; int32_t padding_property_size = next_property_offset - padding_property_offset; - auto padding_part_one = std::format(STR("{}char {}[0x{:X}];"), + auto padding_part_one = std::format(SYSSTR("{}char {}[0x{:X}];"), generate_tab(), - std::format(STR("padding_{}"), num_padding_elements++), + std::format(SYSSTR("padding_{}"), num_padding_elements++), padding_property_size); content_buffer.append( - std::format(STR("{:85} // 0x{:04X} (size: 0x{:X})\n"), padding_part_one, padding_property_offset, padding_property_size)); + std::format(SYSSTR("{:85} // 0x{:04X} (size: 0x{:X})\n"), padding_part_one, padding_property_offset, padding_property_size)); } } } @@ -858,7 +862,7 @@ namespace RC::UEGenerator // Functions if (native_class->HasChildren()) { - content_buffer.append(STR("\n")); + content_buffer.append(SYSSTR("\n")); for (const auto& function_info : functions_to_generate) { generator->generate_function_declaration(object_info, function_info, generated_file, content_buffer); @@ -867,7 +871,7 @@ namespace RC::UEGenerator generate_class_end(content_buffer, class_size); - content_buffer.append(STR("\n\n")); + content_buffer.append(SYSSTR("\n\n")); current_class_content.append(content_buffer); } @@ -878,11 +882,11 @@ namespace RC::UEGenerator if (inherits_from_class) { content_buffer.append( - std::format(STR("{} {} : public {}\n{{\n"), generate_prefix(native_class), class_name, generate_class_name(inherits_from_class))); + std::format(SYSSTR("{} {} : public {}\n{{\n"), generate_prefix(native_class), class_name, generate_class_name(inherits_from_class))); } else { - content_buffer.append(std::format(STR("{} {}\n{{\n"), generate_prefix(native_class), class_name)); + content_buffer.append(std::format(SYSSTR("{} {}\n{{\n"), generate_prefix(native_class), class_name)); } } auto generate_class_struct_end(File::StringType& content_buffer, @@ -912,8 +916,8 @@ namespace RC::UEGenerator printf_s("last_property_offset: %X\n", last_property_offset); printf_s("first_property_offset: %X\n", first_property_offset); - auto padding_part_one = std::format(STR("{}char {}[0x{:X}];"), generate_tab(), std::format(STR("padding_{}"), num_padding_elements), padding_size); - out.append(std::format(STR("{:85} // 0x{:04X} (size: 0x{:X})\n"), padding_part_one, last_property_offset + last_property_size, padding_size)); + auto padding_part_one = std::format(SYSSTR("{}char {}[0x{:X}];"), generate_tab(), std::format(SYSSTR("padding_{}"), num_padding_elements), padding_size); + out.append(std::format(SYSSTR("{:85} // 0x{:04X} (size: 0x{:X})\n"), padding_part_one, last_property_offset + last_property_size, padding_size)); } } //*/ @@ -923,8 +927,8 @@ namespace RC::UEGenerator // No reflected member variables exist but there are non-reflected member variables // Add padding for non-reflected member variables, for alignment purposes auto padding_part_one = - std::format(STR("{}char {}[0x{:X}];"), generate_tab(), std::format(STR("padding_{}"), num_padding_elements), class_size); - content_buffer.append(std::format(STR("{:85} // 0x0000 (size: 0x{:X})\n"), padding_part_one, 0x0)); + std::format(SYSSTR("{}char {}[0x{:X}];"), generate_tab(), std::format(SYSSTR("padding_{}"), num_padding_elements), class_size); + content_buffer.append(std::format(SYSSTR("{:85} // 0x0000 (size: 0x{:X})\n"), padding_part_one, 0x0)); } } } @@ -932,11 +936,11 @@ namespace RC::UEGenerator { if (UE4SSProgram::settings_manager.CXXHeaderGenerator.DumpOffsetsAndSizes) { - content_buffer.append(std::format(STR("}}; // Size: 0x{:X}"), class_size)); + content_buffer.append(std::format(SYSSTR("}}; // Size: 0x{:X}"), class_size)); } else { - content_buffer.append(STR("};")); + content_buffer.append(SYSSTR("};")); } } @@ -957,23 +961,23 @@ namespace RC::UEGenerator } catch (std::exception& e) { - Output::send(STR("Could not generate function '{}' because: {}\n"), - function_info.function->GetFullName(), - to_wstring(e.what())); + Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), + UEStringToSystemString(function_info.function->GetFullName()), + to_generic_string(e.what())); return; } if (return_property_info.value().should_forward_declare && !generator->check_ignore_forward_declaration(owner, return_property)) { - function_type_name.insert(0, STR("class ")); + function_type_name.insert(0, SYSSTR("class ")); } } else { - function_type_name = STR("void"); + function_type_name = SYSSTR("void"); } - current_class_content.append(std::format(STR("{}{} {}("), generate_tab(), function_type_name, function_name)); + current_class_content.append(std::format(SYSSTR("{}{} {}("), generate_tab(), function_type_name, function_name)); for (size_t i = 0; i < function_info.params.size(); ++i) { @@ -983,18 +987,18 @@ namespace RC::UEGenerator try { current_class_content.append( - std::format(STR("{}{}{}{} {}"), - param_info.property->HasAnyPropertyFlags(Unreal::CPF_ConstParm) ? STR("const ") : STR(""), - param_info.should_forward_declare ? STR("class ") : STR(""), + std::format(SYSSTR("{}{}{}{} {}"), + param_info.property->HasAnyPropertyFlags(Unreal::CPF_ConstParm) ? SYSSTR("const ") : SYSSTR(""), + param_info.should_forward_declare ? SYSSTR("class ") : SYSSTR(""), generate_property_cxx_name(param_info.property, true, function_info.function, EnableForwardDeclarations::Yes), - param_info.property->HasAnyPropertyFlags(Unreal::CPF_ReferenceParm | Unreal::CPF_OutParm) ? STR("&") : STR(""), - param_info.property->GetName())); + param_info.property->HasAnyPropertyFlags(Unreal::CPF_ReferenceParm | Unreal::CPF_OutParm) ? SYSSTR("&") : SYSSTR(""), + UEStringToSystemString(param_info.property->GetName()))); } catch (std::exception& e) { - Output::send(STR("Could not generate function '{}' because: {}\n"), - function_info.function->GetFullName(), - to_wstring(e.what())); + Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), + UEStringToSystemString(function_info.function->GetFullName()), + to_generic_string(e.what())); return; } @@ -1003,12 +1007,12 @@ namespace RC::UEGenerator auto* next_param = function_info.params[i + 1].property; if (next_param && (!next_param->HasAnyPropertyFlags(Unreal::CPF_ReturnParm) || i + 2 < function_info.params.size())) { - current_class_content.append(STR(", ")); + current_class_content.append(SYSSTR(", ")); } } } } - current_class_content.append(STR(");")); + current_class_content.append(SYSSTR(");")); } }; @@ -1017,10 +1021,10 @@ namespace RC::UEGenerator private: auto is_valid_lua_symbol(const File::StringType& str) -> bool { - static const std::set keywords = {STR("and"), STR("break"), STR("do"), STR("else"), STR("elseif"), STR("end"), - STR("false"), STR("for"), STR("function"), STR("if"), STR("in"), STR("local"), - STR("nil"), STR("not"), STR("or"), STR("repeat"), STR("return"), STR("then"), - STR("true"), STR("until"), STR("while")}; + static const std::set keywords = {SYSSTR("and"), SYSSTR("break"), SYSSTR("do"), SYSSTR("else"), SYSSTR("elseif"), SYSSTR("end"), + SYSSTR("false"), SYSSTR("for"), SYSSTR("function"), SYSSTR("if"), SYSSTR("in"), SYSSTR("local"), + SYSSTR("nil"), SYSSTR("not"), SYSSTR("or"), SYSSTR("repeat"), SYSSTR("return"), SYSSTR("then"), + SYSSTR("true"), SYSSTR("until"), SYSSTR("while")}; if (keywords.contains(str)) { return false; @@ -1079,27 +1083,27 @@ namespace RC::UEGenerator public: auto get_file_extension() -> File::StringType { - return STR(".lua"); + return SYSSTR(".lua"); } auto generate_file_header(GeneratedFile& generated_file) -> void { - generated_file.primary_file.write_string_to_file(STR("---@meta\n\n")); + generated_file.primary_file.write_string_to_file(SYSSTR("---@meta\n\n")); } auto generate_file_footer(GeneratedFile& generated_file) -> void { } auto generate_enum_declaration(File::StringType& content_buffer, UEnum* uenum) -> void { - auto enum_name = uenum->GetName(); - content_buffer.append(std::format(STR("---@enum {}\n{} = {{\n"), enum_name, enum_name)); + auto enum_name = UEStringToSystemString(uenum->GetName()); + content_buffer.append(std::format(SYSSTR("---@enum {}\n{} = {{\n"), enum_name, enum_name)); } auto generate_enum_member(File::StringType& content_buffer, UEnum* uenum, const File::StringType& enum_value_name, const Unreal::FEnumNamePair& elem) -> void { - content_buffer.append(std::format(STR("{}{} = {},\n"), generate_tab(), enum_value_name, elem.Value)); + content_buffer.append(std::format(SYSSTR("{}{} = {},\n"), generate_tab(), enum_value_name, elem.Value)); } auto generate_enum_end(File::StringType& content_buffer, UEnum* uenum) -> void { - content_buffer.append(STR("}")); + content_buffer.append(SYSSTR("}")); } auto should_generate_class(UStruct* native_class) @@ -1158,20 +1162,20 @@ namespace RC::UEGenerator try { - const auto& property_name = property->GetName(); + const auto& property_name = UEStringToSystemString(property->GetName()); if (is_valid_lua_symbol(property_name)) { - content_buffer.append(std::format(STR("---@field {} {}\n"), property_name, generate_property_lua_name(property, true, native_class))); + content_buffer.append(std::format(SYSSTR("---@field {} {}\n"), property_name, generate_property_lua_name(property, true, native_class))); } else { content_buffer.append( - std::format(STR("---@field [{}] {}\n"), quote_lua_symbol(property_name), generate_property_lua_name(property, true, native_class))); + std::format(SYSSTR("---@field [{}] {}\n"), quote_lua_symbol(property_name), generate_property_lua_name(property, true, native_class))); } } catch (std::exception& e) { - Output::send(STR("Could not generate property '{}' because: {}\n"), property->GetFullName(), to_wstring(e.what())); + Output::send(SYSSTR("Could not generate property '{}' because: {}\n"), UEStringToSystemString(property->GetFullName()), to_generic_string(e.what())); continue; } @@ -1186,7 +1190,7 @@ namespace RC::UEGenerator // Functions if (native_class->HasChildren()) { - content_buffer.append(STR("\n")); + content_buffer.append(SYSSTR("\n")); for (const auto& function_info : functions_to_generate) { generator->generate_function_declaration(object_info, function_info, generated_file, content_buffer); @@ -1195,7 +1199,7 @@ namespace RC::UEGenerator generate_class_end(content_buffer, class_size); - content_buffer.append(STR("\n\n")); + content_buffer.append(SYSSTR("\n\n")); current_class_content.append(content_buffer); } @@ -1204,11 +1208,11 @@ namespace RC::UEGenerator auto class_name = generate_class_name(native_class); if (inherits_from_class) { - content_buffer.append(std::format(STR("---@class {} : {}\n"), class_name, generate_class_name(inherits_from_class))); + content_buffer.append(std::format(SYSSTR("---@class {} : {}\n"), class_name, generate_class_name(inherits_from_class))); } else { - content_buffer.append(std::format(STR("---@class {}\n"), class_name)); + content_buffer.append(std::format(SYSSTR("---@class {}\n"), class_name)); } } auto generate_class_struct_end(File::StringType& content_buffer, @@ -1217,7 +1221,7 @@ namespace RC::UEGenerator int32_t num_padding_elements, XProperty* last_property_in_this_class) -> void { - content_buffer.append(std::format(STR("{} = {{}}\n"), class_name)); + content_buffer.append(std::format(SYSSTR("{} = {{}}\n"), class_name)); } auto generate_class_end(File::StringType& content_buffer, size_t class_size) -> void { @@ -1238,17 +1242,17 @@ namespace RC::UEGenerator { try { - auto param_name = param_info.property->GetName(); + auto param_name = UEStringToSystemString(param_info.property->GetName()); // TODO disambiguate param renames - current_class_content.append(std::format(STR("---@param {} {}\n"), + current_class_content.append(std::format(SYSSTR("---@param {} {}\n"), make_valid_symbol(param_name), generate_property_lua_name(param_info.property, true, function_info.function))); } catch (std::exception& e) { - Output::send(STR("Could not generate function '{}' because: {}\n"), - function_info.function->GetFullName(), - to_wstring(e.what())); + Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), + UEStringToSystemString( function_info.function->GetFullName()), + to_generic_string(e.what())); return; } } @@ -1258,13 +1262,13 @@ namespace RC::UEGenerator { try { - current_class_content.append(std::format(STR("---@return {}\n"), generate_property_lua_name(return_property, true, function_info.function))); + current_class_content.append(std::format(SYSSTR("---@return {}\n"), generate_property_lua_name(return_property, true, function_info.function))); } catch (std::exception& e) { - Output::send(STR("Could not generate function '{}' because: {}\n"), - function_info.function->GetFullName(), - to_wstring(e.what())); + Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), + UEStringToSystemString(function_info.function->GetFullName()), + to_generic_string(e.what())); return; } } @@ -1273,11 +1277,11 @@ namespace RC::UEGenerator if (is_valid_lua_symbol(function_name)) { - current_class_content.append(std::format(STR("function {}:{}("), class_name, function_name)); + current_class_content.append(std::format(SYSSTR("function {}:{}("), class_name, function_name)); } else { - current_class_content.append(std::format(STR("{}[{}] = function("), class_name, quote_lua_symbol(function_name))); + current_class_content.append(std::format(SYSSTR("{}[{}] = function("), class_name, quote_lua_symbol(function_name))); } for (size_t i = 0; i < function_info.params.size(); ++i) @@ -1285,21 +1289,21 @@ namespace RC::UEGenerator const auto& param_info = function_info.params[i]; if (!param_info.property->HasAnyPropertyFlags(Unreal::CPF_ReturnParm)) { - auto param_name = param_info.property->GetName(); + auto param_name = UEStringToSystemString(param_info.property->GetName()); // TODO disambiguate param renames - current_class_content.append(std::format(STR("{}"), make_valid_symbol(param_name))); + current_class_content.append(std::format(SYSSTR("{}"), make_valid_symbol(param_name))); if (i + 1 < function_info.params.size()) { auto* next_param = function_info.params[i + 1].property; if (next_param && (!next_param->HasAnyPropertyFlags(Unreal::CPF_ReturnParm) || i + 2 < function_info.params.size())) { - current_class_content.append(STR(", ")); + current_class_content.append(SYSSTR(", ")); } } } } - current_class_content.append(STR(") end")); + current_class_content.append(SYSSTR(") end")); } }; diff --git a/UE4SS/src/SDKGenerator/JSONDumper.cpp b/UE4SS/src/SDKGenerator/JSONDumper.cpp index a8163d063..e2e58895b 100644 --- a/UE4SS/src/SDKGenerator/JSONDumper.cpp +++ b/UE4SS/src/SDKGenerator/JSONDumper.cpp @@ -41,31 +41,31 @@ namespace RC::UEGenerator::JSONDumper return false; } - if (class_name.find(STR("BP_")) != class_name.npos) + if (class_name.find(SYSSTR("BP_")) != class_name.npos) { return true; } - if (class_name.find(STR("ENE_")) != class_name.npos) + if (class_name.find(SYSSTR("ENE_")) != class_name.npos) { return true; } - if (class_name.find(STR("BPL_")) != class_name.npos) + if (class_name.find(SYSSTR("BPL_")) != class_name.npos) { return true; } - if (class_name.find(STR("OBJ_")) != class_name.npos) + if (class_name.find(SYSSTR("OBJ_")) != class_name.npos) { return true; } - if (class_name.find(STR("LIB_")) != class_name.npos) + if (class_name.find(SYSSTR("LIB_")) != class_name.npos) { return true; } - if (class_name.find(STR("PRJ_")) != class_name.npos) + if (class_name.find(SYSSTR("PRJ_")) != class_name.npos) { return true; } - if (class_name.find(STR("WPN_")) != class_name.npos) + if (class_name.find(SYSSTR("WPN_")) != class_name.npos) { return true; } @@ -179,7 +179,7 @@ namespace RC::UEGenerator::JSONDumper auto static should_skip_event(File::StringViewType event_name) -> bool { - if (event_name.find(STR("BndEvt")) != event_name.npos) + if (event_name.find(SYSSTR("BndEvt")) != event_name.npos) { return true; } @@ -188,10 +188,10 @@ namespace RC::UEGenerator::JSONDumper auto dump_to_json(File::StringViewType file_name) -> void { - Output::send(STR("Loading all assets...\n")); + Output::send(SYSSTR("Loading all assets...\n")); UAssetRegistry::LoadAllAssets(); - Output::send(STR("Dumping to JSON file\n")); + Output::send(SYSSTR("Dumping to JSON file\n")); auto json = JSON::Array{}; UObjectGlobals::ForEachUObject([&](void* raw_object, int32_t chunk_index, int32_t object_index) { @@ -201,7 +201,7 @@ namespace RC::UEGenerator::JSONDumper } UObject* object = static_cast(raw_object); - auto object_name = object->GetName(); + auto object_name = UEStringToSystemString(object->GetName()); if (!is_valid_class_to_dump(object_name, object)) { return LoopAction::Continue; @@ -211,17 +211,17 @@ namespace RC::UEGenerator::JSONDumper object_name.erase(object_name.size() - 2, 2); auto& bp_class = json.new_object(); - bp_class.new_string(STR("bp_class"), object_name); + bp_class.new_string(SYSSTR("bp_class"), object_name); if (auto* super_struct = object_as_class->GetSuperStruct(); super_struct) { - bp_class.new_string(STR("inherits"), super_struct->GetName()); + bp_class.new_string(SYSSTR("inherits"), UEStringToSystemString(super_struct->GetName())); } else { - bp_class.new_null(STR("inherits")); + bp_class.new_null(SYSSTR("inherits")); } - auto& events = bp_class.new_array(STR("events")); + auto& events = bp_class.new_array(SYSSTR("events")); for (UFunction* event_function : object_as_class->ForEachFunction()) { if (should_skip_general_function(event_function)) @@ -233,16 +233,16 @@ namespace RC::UEGenerator::JSONDumper continue; } - auto event_name = event_function->GetName(); + auto event_name = UEStringToSystemString(event_function->GetName()); if (should_skip_event(event_name)) { continue; } auto& bp_events = events.new_object(); - bp_events.new_string(STR("name"), event_name); + bp_events.new_string(SYSSTR("name"), event_name); - auto& bp_event_args = bp_events.new_array(STR("args")); + auto& bp_event_args = bp_events.new_array(SYSSTR("args")); for (FProperty* param : event_function->ForEachProperty()) { if (should_skip_property(param)) @@ -251,15 +251,15 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_event_arg = bp_event_args.new_object(); - bp_event_arg.new_string(STR("name"), param->GetName()); - bp_event_arg.new_string(STR("type"), generate_property_cxx_name(param, true, event_function)); + bp_event_arg.new_string(SYSSTR("name"), UEStringToSystemString(param->GetName())); + bp_event_arg.new_string(SYSSTR("type"), generate_property_cxx_name(param, true, event_function)); bool is_out = param->HasAnyPropertyFlags(EPropertyFlags::CPF_OutParm) && !param->HasAnyPropertyFlags(EPropertyFlags::CPF_ConstParm); - bp_event_arg.new_bool(STR("is_out"), is_out); - bp_event_arg.new_bool(STR("is_return"), param->HasAnyPropertyFlags(Unreal::EPropertyFlags::CPF_ReturnParm)); + bp_event_arg.new_bool(SYSSTR("is_out"), is_out); + bp_event_arg.new_bool(SYSSTR("is_return"), param->HasAnyPropertyFlags(Unreal::EPropertyFlags::CPF_ReturnParm)); } } - auto& functions = bp_class.new_array(STR("functions")); + auto& functions = bp_class.new_array(SYSSTR("functions")); for (UFunction* function : object_as_class->ForEachFunction()) { if (should_skip_function(function)) @@ -268,9 +268,9 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_function = functions.new_object(); - bp_function.new_string(STR("name"), function->GetName()); + bp_function.new_string(SYSSTR("name"), UEStringToSystemString(function->GetName())); - auto& bp_function_args = bp_function.new_array(STR("args")); + auto& bp_function_args = bp_function.new_array(SYSSTR("args")); for (FProperty* param : function->ForEachProperty()) { if (should_skip_property(param)) @@ -279,15 +279,15 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_function_arg = bp_function_args.new_object(); - bp_function_arg.new_string(STR("name"), param->GetName()); - bp_function_arg.new_string(STR("type"), generate_property_cxx_name(param, true, function)); + bp_function_arg.new_string(SYSSTR("name"), UEStringToSystemString(param->GetName())); + bp_function_arg.new_string(SYSSTR("type"), generate_property_cxx_name(param, true, function)); bool is_out = param->HasAnyPropertyFlags(EPropertyFlags::CPF_OutParm) && !param->HasAnyPropertyFlags(EPropertyFlags::CPF_ConstParm); - bp_function_arg.new_bool(STR("is_out"), is_out); - bp_function_arg.new_bool(STR("is_return"), param->HasAnyPropertyFlags(Unreal::EPropertyFlags::CPF_ReturnParm)); + bp_function_arg.new_bool(SYSSTR("is_out"), is_out); + bp_function_arg.new_bool(SYSSTR("is_return"), param->HasAnyPropertyFlags(Unreal::EPropertyFlags::CPF_ReturnParm)); } } - auto& properties = bp_class.new_array(STR("properties")); + auto& properties = bp_class.new_array(SYSSTR("properties")); for (FProperty* property : object_as_class->ForEachProperty()) { if (should_skip_property(property)) @@ -296,11 +296,11 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_property = properties.new_object(); - bp_property.new_string(STR("name"), property->GetName()); - bp_property.new_string(STR("type"), generate_property_cxx_name(property, true, object_as_class)); + bp_property.new_string(SYSSTR("name"),UEStringToSystemString(property->GetName())); + bp_property.new_string(SYSSTR("type"), generate_property_cxx_name(property, true, object_as_class)); } - auto& delegates = bp_class.new_array(STR("delegates")); + auto& delegates = bp_class.new_array(SYSSTR("delegates")); for (UFunction* delegate_function : object_as_class->ForEachFunction()) { if (should_skip_general_function(delegate_function)) @@ -313,9 +313,9 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_delegate = delegates.new_object(); - bp_delegate.new_string(STR("name"), delegate_function->GetName()); + bp_delegate.new_string(SYSSTR("name"), UEStringToSystemString(delegate_function->GetName())); - auto& bp_delegate_args = bp_delegate.new_array(STR("args")); + auto& bp_delegate_args = bp_delegate.new_array(SYSSTR("args")); for (FProperty* param : delegate_function->ForEachProperty()) { if (should_skip_property(param)) @@ -324,11 +324,11 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_delegate_arg = bp_delegate_args.new_object(); - bp_delegate_arg.new_string(STR("name"), param->GetName()); - bp_delegate_arg.new_string(STR("type"), generate_property_cxx_name(param, true, delegate_function)); + bp_delegate_arg.new_string(SYSSTR("name"), UEStringToSystemString(param->GetName())); + bp_delegate_arg.new_string(SYSSTR("type"), generate_property_cxx_name(param, true, delegate_function)); bool is_out = param->HasAnyPropertyFlags(EPropertyFlags::CPF_OutParm) && !param->HasAnyPropertyFlags(EPropertyFlags::CPF_ConstParm); - bp_delegate_arg.new_bool(STR("is_out"), is_out); - bp_delegate_arg.new_bool(STR("is_return"), param->HasAnyPropertyFlags(Unreal::EPropertyFlags::CPF_ReturnParm)); + bp_delegate_arg.new_bool(SYSSTR("is_out"), is_out); + bp_delegate_arg.new_bool(SYSSTR("is_return"), param->HasAnyPropertyFlags(Unreal::EPropertyFlags::CPF_ReturnParm)); } } @@ -340,7 +340,7 @@ namespace RC::UEGenerator::JSONDumper json_file.write_string_to_file(json.serialize(JSON::ShouldFormat::Yes, &indent_level)); json_file.close(); - Output::send(STR("Unloading all forcefully loaded assets\n")); + Output::send(SYSSTR("Unloading all forcefully loaded assets\n")); UAssetRegistry::FreeAllForcefullyLoadedAssets(); } } // namespace RC::UEGenerator::JSONDumper diff --git a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp index 5b9440038..0e8605001 100644 --- a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp +++ b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp @@ -25,7 +25,7 @@ namespace RC::UEGenerator auto TMapOverrideGenerator::generate_tmapoverride() -> void { - Output::send(STR("Dumping TMap Property Overrides\n")); + Output::send(SYSSTR("Dumping TMap Property Overrides\n")); auto fm_object = JSON::Object{}; auto uaapi_object = JSON::Object{}; @@ -53,7 +53,7 @@ namespace RC::UEGenerator MapProperties.insert(property->GetFName()); - auto property_name = property->GetFName().ToString(); + auto property_name = UEStringToSystemString(property->GetFName().ToString()); auto key_as_struct_property = CastField(static_cast(property)->GetKeyProp()); auto key_struct_type = key_as_struct_property ? key_as_struct_property->GetStruct() : nullptr; @@ -67,32 +67,32 @@ namespace RC::UEGenerator { continue; } - Output::send(STR("Found Relevant TMap Property: {} in Class: {}\n"), property_name, object->GetName()); + Output::send(SYSSTR("Found Relevant TMap Property: {} in Class: {}\n"), property_name, UEStringToSystemString(object->GetName())); auto& fm_json_object = fm_object.new_object(property_name); auto& uaapi_array = uaapi_object.new_array(property_name); if (is_key_valid) { - auto key_name = key_as_struct_property->GetStruct()->GetName(); - fm_json_object.new_string(STR("Key"), key_name); + auto key_name = UEStringToSystemString(key_as_struct_property->GetStruct()->GetName()); + fm_json_object.new_string(SYSSTR("Key"), key_name); uaapi_array.new_string(key_name); } else { - fm_json_object.new_string(STR("Key"), STR("")); + fm_json_object.new_string(SYSSTR("Key"), SYSSTR("")); uaapi_array.new_null(); } if (is_value_valid) { - auto value_name = value_as_struct_property->GetStruct()->GetName(); - fm_json_object.new_string(STR("Value"), value_name); + auto value_name = UEStringToSystemString(value_as_struct_property->GetStruct()->GetName()); + fm_json_object.new_string(SYSSTR("Value"), value_name); uaapi_array.new_string(value_name); } else { - fm_json_object.new_string(STR("Value"), STR("")); + fm_json_object.new_string(SYSSTR("Value"), SYSSTR("")); uaapi_array.new_null(); } @@ -110,17 +110,17 @@ namespace RC::UEGenerator // Retrieve JSON as a string. int32_t indent_level{}; - auto uaapifile = open(StringType{UE4SSProgram::get_program().get_working_directory()} + STR("\\UAssetAPITMapOverrides.json"), + auto uaapifile = open(SystemStringType{UE4SSProgram::get_program().get_working_directory()} + SYSSTR("\\UAssetAPITMapOverrides.json"), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); - auto fmodelfile = open(StringType{UE4SSProgram::get_program().get_working_directory()} + STR("\\FModelTMapOverrides.json"), + auto fmodelfile = open(SystemStringType{UE4SSProgram::get_program().get_working_directory()} + SYSSTR("\\FModelTMapOverrides.json"), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); uaapifile.write_string_to_file(uaapi_object.serialize(JSON::ShouldFormat::Yes, &indent_level)); fmodelfile.write_string_to_file(fm_object.serialize(JSON::ShouldFormat::Yes, &indent_level)); - Output::send(STR("Finished Dumping {} TMap Properties\n"), num_objects_generated); + Output::send(SYSSTR("Finished Dumping {} TMap Properties\n"), num_objects_generated); MapProperties.clear(); } } // namespace RC::UEGenerator \ No newline at end of file diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index 4c1cb29b1..d6e901df6 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -1,8 +1,11 @@ +#ifdef WIN32 + #define NOMINMAX #include #ifdef TEXT #undef TEXT #endif +#endif #include #include @@ -132,7 +135,7 @@ namespace RC::UEGenerator } } - auto string_to_uppercase(std::wstring s) -> std::wstring + auto string_to_uppercase(SystemStringType s) -> SystemStringType { std::transform(s.begin(), s.end(), s.begin(), [](wchar_t c) { return towupper(c); @@ -142,8 +145,8 @@ namespace RC::UEGenerator class FlagFormatHelper { - std::set m_switches; - std::map> m_parameters; + std::set m_switches; + std::map> m_parameters; std::shared_ptr m_meta_helper; FlagFormatHelper(bool is_root_helper) @@ -159,14 +162,14 @@ namespace RC::UEGenerator { } - auto add_switch(const std::wstring& switch_name) -> void + auto add_switch(const SystemStringType& switch_name) -> void { m_switches.insert(switch_name); } - auto add_parameter(const std::wstring& parameter_name, const std::wstring& parameter_value) -> void + auto add_parameter(const SystemStringType& parameter_name, const SystemStringType& parameter_value) -> void { - if (parameter_name == STR("meta")) + if (parameter_name == SYSSTR("meta")) { throw std::invalid_argument("Use get_meta() to add metadata to the flag declaration"); } @@ -187,54 +190,54 @@ namespace RC::UEGenerator return m_meta_helper.get(); } - auto build_flag_string() const -> std::wstring + auto build_flag_string() const -> SystemStringType { - std::wstring resulting_string; + SystemStringType resulting_string; - for (const std::wstring& switch_name : m_switches) + for (const SystemStringType& switch_name : m_switches) { resulting_string.append(switch_name); - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(", ")); } for (const auto& parameter_pair : m_parameters) { resulting_string.append(parameter_pair.first); - resulting_string.append(STR("=")); - const std::set& parameter_values = parameter_pair.second; + resulting_string.append(SYSSTR("=")); + const std::set& parameter_values = parameter_pair.second; if (parameter_values.size() != 1) { - resulting_string.append(STR("(")); + resulting_string.append(SYSSTR("(")); - for (const std::wstring& parameter_value : parameter_values) + for (const SystemStringType& parameter_value : parameter_values) { resulting_string.append(parameter_value); - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(", ")); } if (parameter_values.size() != 0) { resulting_string.erase(resulting_string.size() - 1, 1); } - resulting_string.append(STR(")")); + resulting_string.append(SYSSTR(")")); } else { resulting_string.append(*parameter_values.begin()); } - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(", ")); } if (m_meta_helper) { - const std::wstring meta_flag_string = m_meta_helper->build_flag_string(); + const SystemStringType meta_flag_string = m_meta_helper->build_flag_string(); if (!meta_flag_string.empty()) { - resulting_string.append(STR("meta=(")); + resulting_string.append(SYSSTR("meta=(")); resulting_string.append(meta_flag_string); - resulting_string.append(STR(")")); - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(")")); + resulting_string.append(SYSSTR(", ")); } } @@ -246,69 +249,69 @@ namespace RC::UEGenerator } }; - auto UEHeaderGenerator::generate_module_build_file(const std::wstring& module_name) -> void + auto UEHeaderGenerator::generate_module_build_file(const SystemStringType& module_name) -> void { - const FFilePath module_file_path = m_root_directory / module_name / std::format(STR("{}.Build.cs"), module_name); + const FFilePath module_file_path = m_root_directory / module_name / std::format(SYSSTR("{}.Build.cs"), module_name); GeneratedFile module_build_file = GeneratedFile(module_file_path); - module_build_file.append_line(STR("using UnrealBuildTool;")); - module_build_file.append_line(STR("")); + module_build_file.append_line(SYSSTR("using UnrealBuildTool;")); + module_build_file.append_line(SYSSTR("")); - module_build_file.append_line(std::format(STR("public class {} : ModuleRules {{"), module_name)); + module_build_file.append_line(std::format(SYSSTR("public class {} : ModuleRules {{"), module_name)); module_build_file.begin_indent_level(); - module_build_file.append_line(std::format(STR("public {}(ReadOnlyTargetRules Target) : base(Target) {{"), module_name)); + module_build_file.append_line(std::format(SYSSTR("public {}(ReadOnlyTargetRules Target) : base(Target) {{"), module_name)); module_build_file.begin_indent_level(); - module_build_file.append_line(STR("PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;")); + module_build_file.append_line(SYSSTR("PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;")); if (Version::IsAtLeast(4, 24)) { - module_build_file.append_line(STR("bLegacyPublicIncludePaths = false;")); - module_build_file.append_line(STR("ShadowVariableWarningLevel = WarningLevel.Warning;")); + module_build_file.append_line(SYSSTR("bLegacyPublicIncludePaths = false;")); + module_build_file.append_line(SYSSTR("ShadowVariableWarningLevel = WarningLevel.Warning;")); } - module_build_file.append_line(STR("")); - module_build_file.append_line(STR("PublicDependencyModuleNames.AddRange(new string[] {")); + module_build_file.append_line(SYSSTR("")); + module_build_file.append_line(SYSSTR("PublicDependencyModuleNames.AddRange(new string[] {")); module_build_file.begin_indent_level(); - std::set all_module_dependencies = this->m_forced_module_dependencies; - std::set clean_module_dependencies{}; + std::set all_module_dependencies = this->m_forced_module_dependencies; + std::set clean_module_dependencies{}; add_module_and_sub_module_dependencies(clean_module_dependencies, module_name, false); all_module_dependencies.insert(clean_module_dependencies.begin(), clean_module_dependencies.end()); - for (const std::wstring& other_module_name : all_module_dependencies) + for (const SystemStringType& other_module_name : all_module_dependencies) { - module_build_file.append_line(std::format(STR("\"{}\","), other_module_name)); + module_build_file.append_line(std::format(SYSSTR("\"{}\","), other_module_name)); } module_build_file.end_indent_level(); - module_build_file.append_line(STR("});")); + module_build_file.append_line(SYSSTR("});")); module_build_file.end_indent_level(); - module_build_file.append_line(STR("}")); + module_build_file.append_line(SYSSTR("}")); module_build_file.end_indent_level(); - module_build_file.append_line(STR("}")); + module_build_file.append_line(SYSSTR("}")); module_build_file.serialize_file_content_to_disk(); } - auto UEHeaderGenerator::generate_module_implementation_file(const std::wstring& module_name) -> void + auto UEHeaderGenerator::generate_module_implementation_file(const SystemStringType& module_name) -> void { - const FFilePath module_file_path = m_root_directory / module_name / STR("Private") / std::format(STR("{}Module.cpp"), module_name); + const FFilePath module_file_path = m_root_directory / module_name / SYSSTR("Private") / std::format(SYSSTR("{}Module.cpp"), module_name); GeneratedFile module_impl_file = GeneratedFile(module_file_path); - module_impl_file.append_line(STR("#include \"Modules/ModuleManager.h\"")); - module_impl_file.append_line(STR("")); + module_impl_file.append_line(SYSSTR("#include \"Modules/ModuleManager.h\"")); + module_impl_file.append_line(SYSSTR("")); if (module_name != m_primary_module_name) { - module_impl_file.append_line(std::format(STR("IMPLEMENT_MODULE(FDefaultGameModuleImpl, {});"), module_name)); + module_impl_file.append_line(std::format(SYSSTR("IMPLEMENT_MODULE(FDefaultGameModuleImpl, {});"), module_name)); } else { - module_impl_file.append_line(std::format(STR("IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, {}, {});"), module_name, module_name)); + module_impl_file.append_line(std::format(SYSSTR("IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, {}, {});"), module_name, module_name)); } module_impl_file.serialize_file_content_to_disk(); @@ -316,40 +319,40 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_interface_definition(UClass* uclass, GeneratedSourceFile& header_data) -> void { - const std::wstring interface_class_native_name = get_native_class_name(uclass); - const std::wstring interface_flags_string = generate_interface_flags(uclass); + const SystemStringType interface_class_native_name = get_native_class_name(uclass); + const SystemStringType interface_flags_string = generate_interface_flags(uclass); - std::wstring maybe_api_name; + SystemStringType maybe_api_name; if ((uclass->GetClassFlags() & CLASS_RequiredAPI) != 0) { maybe_api_name.append(convert_module_name_to_api_name(header_data.get_header_module_name())); - maybe_api_name.append(STR(" ")); + maybe_api_name.append(SYSSTR(" ")); } UClass* super_class = uclass->GetSuperClass(); header_data.add_dependency_object(super_class, DependencyLevel::Include); - std::wstring parent_interface_class_name = get_native_class_name(super_class); + SystemStringType parent_interface_class_name = get_native_class_name(super_class); // Generate interface UCLASS declaration - header_data.append_line(std::format(STR("UINTERFACE({})"), interface_flags_string)); - header_data.append_line(std::format(STR("class {}{} : public {} {{"), maybe_api_name, interface_class_native_name, parent_interface_class_name)); + header_data.append_line(std::format(SYSSTR("UINTERFACE({})"), interface_flags_string)); + header_data.append_line(std::format(SYSSTR("class {}{} : public {} {{"), maybe_api_name, interface_class_native_name, parent_interface_class_name)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); header_data.end_indent_level(); - header_data.append_line(STR("};")); - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("};")); + header_data.append_line(SYSSTR("")); // Generate interface real class declaration - const std::wstring interface_native_name = get_native_class_name(uclass, true); - const std::wstring parent_interface_name = get_native_class_name(super_class, true); + const SystemStringType interface_native_name = get_native_class_name(uclass, true); + const SystemStringType parent_interface_name = get_native_class_name(super_class, true); - header_data.append_line(std::format(STR("class {}{} : public {} {{"), maybe_api_name, interface_native_name, parent_interface_name)); + header_data.append_line(std::format(SYSSTR("class {}{} : public {} {{"), maybe_api_name, interface_native_name, parent_interface_name)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -366,7 +369,7 @@ namespace RC::UEGenerator } if (NumDelegatesGenerated) { - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("")); } // Generate interface functions @@ -380,30 +383,30 @@ namespace RC::UEGenerator } header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); } auto UEHeaderGenerator::generate_object_definition(UClass* uclass, GeneratedSourceFile& header_data) -> void { - const std::wstring class_native_name = get_native_class_name(uclass); - const std::wstring class_flags_string = generate_class_flags(uclass); + const SystemStringType class_native_name = get_native_class_name(uclass); + const SystemStringType class_flags_string = generate_class_flags(uclass); - std::wstring maybe_api_name; + SystemStringType maybe_api_name; if ((uclass->GetClassFlags() & CLASS_RequiredAPI) != 0) { maybe_api_name.append(convert_module_name_to_api_name(header_data.get_header_module_name())); - maybe_api_name.append(STR(" ")); + maybe_api_name.append(SYSSTR(" ")); } UClass* super_class = uclass->GetSuperClass(); - std::wstring parent_class_name; + SystemStringType parent_class_name; if (super_class) { parent_class_name = get_native_class_name(super_class); } else { - parent_class_name = STR("UObjectBaseUtility"); + parent_class_name = SYSSTR("UObjectBaseUtility"); } if (super_class) @@ -411,23 +414,23 @@ namespace RC::UEGenerator header_data.add_dependency_object(super_class, DependencyLevel::Include); } - std::wstring interface_list_string; + SystemStringType interface_list_string; auto implemented_interfaces = uclass->GetInterfaces(); for (const RC::Unreal::FImplementedInterface& uinterface : implemented_interfaces) { header_data.add_dependency_object(uinterface.Class, DependencyLevel::Include); - const std::wstring interface_name = get_native_class_name(uinterface.Class, true); + const SystemStringType interface_name = get_native_class_name(uinterface.Class, true); - interface_list_string.append(STR(", public ")); + interface_list_string.append(SYSSTR(", public ")); interface_list_string.append(interface_name); } - header_data.append_line(std::format(STR("UCLASS({})"), class_flags_string)); - header_data.append_line(std::format(STR("class {}{} : public {}{} {{"), maybe_api_name, class_native_name, parent_class_name, interface_list_string)); + header_data.append_line(std::format(SYSSTR("UCLASS({})"), class_flags_string)); + header_data.append_line(std::format(SYSSTR("class {}{} : public {}{} {{"), maybe_api_name, class_native_name, parent_class_name, interface_list_string)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -447,7 +450,7 @@ namespace RC::UEGenerator } if (NumDelegatesGenerated) { - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("")); } // Generate properties @@ -471,19 +474,19 @@ namespace RC::UEGenerator append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); // Generate constructor - std::wstring constructor_string; + SystemStringType constructor_string; if (uclass->IsChildOf() || uclass->IsChildOf()) { - constructor_string.append(STR("const FObjectInitializer& ObjectInitializer")); + constructor_string.append(SYSSTR("const FObjectInitializer& ObjectInitializer")); } - header_data.append_line(std::format(STR("{}({});"), class_native_name, constructor_string)); - header_data.append_line_no_indent(STR("")); + header_data.append_line(std::format(SYSSTR("{}({});"), class_native_name, constructor_string)); + header_data.append_line_no_indent(SYSSTR("")); // Generate GetLifetimeReplicatedProps override if we have encountered replicated properties if (encountered_replicated_properties) { - header_data.append_line(STR("virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;")); - header_data.append_line_no_indent(STR("")); + header_data.append_line(SYSSTR("virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;")); + header_data.append_line_no_indent(SYSSTR("")); } // Generate functions @@ -501,8 +504,8 @@ namespace RC::UEGenerator // Generate overrides for all inherited virtual functions if (implemented_interfaces.Num() > 0) { - header_data.append_line_no_indent(STR("")); - header_data.append_line(STR("// Fix for true pure virtual functions not being implemented")); + header_data.append_line_no_indent(SYSSTR("")); + header_data.append_line(SYSSTR("// Fix for true pure virtual functions not being implemented")); } for (const RC::Unreal::FImplementedInterface& uinterface : implemented_interfaces) { @@ -519,33 +522,33 @@ namespace RC::UEGenerator } header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); } auto UEHeaderGenerator::generate_struct_definition(UScriptStruct* script_struct, GeneratedSourceFile& header_data) -> void { - const std::wstring struct_native_name = get_native_struct_name(script_struct); - const std::wstring struct_flags_string = generate_struct_flags(script_struct); + const SystemStringType struct_native_name = get_native_struct_name(script_struct); + const SystemStringType struct_flags_string = generate_struct_flags(script_struct); - std::wstring api_macro_name = convert_module_name_to_api_name(header_data.get_header_module_name()); - api_macro_name.append(STR(" ")); + SystemStringType api_macro_name = convert_module_name_to_api_name(header_data.get_header_module_name()); + api_macro_name.append(SYSSTR(" ")); bool is_struct_exported = (script_struct->GetStructFlags() & STRUCT_RequiredAPI) != 0; UScriptStruct* super_struct = script_struct->GetSuperScriptStruct(); - std::wstring parent_struct_declaration; + SystemStringType parent_struct_declaration; if (super_struct) { header_data.add_dependency_object(super_struct, DependencyLevel::Include); - const std::wstring super_struct_native_name = get_native_struct_name(super_struct); - parent_struct_declaration.append(std::format(STR(" : public {}"), super_struct_native_name)); + const SystemStringType super_struct_native_name = get_native_struct_name(super_struct); + parent_struct_declaration.append(std::format(SYSSTR(" : public {}"), super_struct_native_name)); } - header_data.append_line(std::format(STR("USTRUCT({})"), struct_flags_string)); - header_data.append_line(std::format(STR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : STR(""), struct_native_name, parent_struct_declaration)); + header_data.append_line(std::format(SYSSTR("USTRUCT({})"), struct_flags_string)); + header_data.append_line(std::format(SYSSTR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name, parent_struct_declaration)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -568,34 +571,34 @@ namespace RC::UEGenerator // Generate constructor and make sure it's public append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); - header_data.append_line(std::format(STR("{}{}();"), !is_struct_exported ? api_macro_name : STR(""), struct_native_name)); + header_data.append_line(std::format(SYSSTR("{}{}();"), !is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name)); header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); } auto UEHeaderGenerator::generate_enum_definition(UEnum* uenum, GeneratedSourceFile& header_data) -> void { - const StringType native_enum_name = get_native_enum_name(uenum, false); + const SystemStringType native_enum_name = get_native_enum_name(uenum, false); const int64 highest_enum_value = get_highest_enum(uenum); const bool can_use_uint8_override = (highest_enum_value <= 255 && get_lowest_enum(uenum) >= 0); - const StringType enum_flags_string = generate_enum_flags(uenum); + const SystemStringType enum_flags_string = generate_enum_flags(uenum); const auto underlying_type = m_underlying_enum_types.find(native_enum_name); const bool has_known_underlying_type = underlying_type != m_underlying_enum_types.end(); UEnum::ECppForm cpp_form = uenum->GetCppForm(); bool enum_is_uint8{false}; - header_data.append_line(std::format(STR("UENUM({})"), enum_flags_string)); + header_data.append_line(std::format(SYSSTR("UENUM({})"), enum_flags_string)); if (cpp_form == UEnum::ECppForm::Namespaced) { - header_data.append_line(std::format(STR("namespace {} {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("namespace {} {{"), native_enum_name)); header_data.begin_indent_level(); - header_data.append_line(STR("enum Type {")); + header_data.append_line(SYSSTR("enum Type {")); } else if (cpp_form == UEnum::ECppForm::Regular) { - header_data.append_line(std::format(STR("enum {} {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("enum {} {{"), native_enum_name)); } else if (cpp_form == UEnum::ECppForm::EnumClass) { @@ -603,34 +606,34 @@ namespace RC::UEGenerator { if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeEnumClassesBlueprintType && can_use_uint8_override) { - header_data.append_line(std::format(STR("enum class {} : uint8 {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("enum class {} : uint8 {{"), native_enum_name)); enum_is_uint8 = true; } else { // Enum has never been used in any native classes or structures, go with implicit type - header_data.append_line(std::format(STR("enum class {} {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("enum class {} {{"), native_enum_name)); } } else { - std::wstring underlying_type_string = underlying_type->second; + SystemStringType underlying_type_string = underlying_type->second; - header_data.append_line(std::format(STR("enum class {} : {} {{"), native_enum_name, underlying_type_string)); + header_data.append_line(std::format(SYSSTR("enum class {} : {} {{"), native_enum_name, underlying_type_string)); } } header_data.begin_indent_level(); - StringType enum_prefix = uenum->GenerateEnumPrefix(); + UEStringType enum_prefix = uenum->GenerateEnumPrefix(); int64 expected_next_enum_value = 0; bool last_value_was_negative_one{false}; - std::set enum_name_set{}; + std::set enum_name_set{}; for (auto [Name, Value] : uenum->ForEachName()) { - StringType enum_name = Name.ToString(); - StringType result_enumeration_line = sanitize_enumeration_name(enum_name); - StringType pre_append_result_line = result_enumeration_line; + UEStringType enum_name = Name.ToString(); + SystemStringType result_enumeration_line = sanitize_enumeration_name(UEStringToSystemString(enum_name)); + SystemStringType pre_append_result_line = result_enumeration_line; // If an enum name is listed in the array twice, that likely means it is used as the value for another enum. Long story short, don't print it. if (enum_name_set.contains(enum_name)) @@ -644,26 +647,26 @@ namespace RC::UEGenerator // Taking advantage of GetNameByValue returning the first result for the value to determine if there are any enumerator names that // reference an already declared value/name. - StringType first_name_with_value = uenum->GetNameByValue(Value).ToString(); + UEStringType first_name_with_value = uenum->GetNameByValue(Value).ToString(); if (first_name_with_value != Name.ToString()) { - result_enumeration_line.append(std::format(STR(" = {}"), sanitize_enumeration_name(first_name_with_value))); + result_enumeration_line.append(std::format(SYSSTR(" = {}"), sanitize_enumeration_name(UEStringToSystemString(first_name_with_value)))); } else if (Value != expected_next_enum_value || last_value_was_negative_one) { - const StringType CastString = (enum_is_uint8 && Value < 0) ? STR("(uint8)") : STR(""); - const StringType MinusSign = Value < 0 ? STR("-") : STR(""); - result_enumeration_line.append(std::format(STR(" = {}{}{}"), CastString, MinusSign, std::abs(Value))); + const SystemStringType CastString = (enum_is_uint8 && Value < 0) ? SYSSTR("(uint8)") : SYSSTR(""); + const SystemStringType MinusSign = Value < 0 ? SYSSTR("-") : SYSSTR(""); + result_enumeration_line.append(std::format(SYSSTR(" = {}{}{}"), CastString, MinusSign, Value < 0 ? -Value : Value)); } expected_next_enum_value = Value + 1; last_value_was_negative_one = (Value == -1); - StringType pre_append_result_line_lower = pre_append_result_line; + SystemStringType pre_append_result_line_lower = pre_append_result_line; std::transform(pre_append_result_line_lower.begin(), pre_append_result_line_lower.end(), pre_append_result_line_lower.begin(), ::towlower); - if (pre_append_result_line_lower.ends_with(STR("_max"))) + if (pre_append_result_line_lower.ends_with(SYSSTR("_max"))) { - const StringType expected_full_constant_name = std::format(STR("{}_MAX"), enum_prefix); - StringType expected_full_constant_name_lower = expected_full_constant_name; + const SystemStringType expected_full_constant_name = std::format(SYSSTR("{}_MAX"), UEStringToSystemString(enum_prefix)); + SystemStringType expected_full_constant_name_lower = expected_full_constant_name; std::transform(expected_full_constant_name_lower.begin(), expected_full_constant_name_lower.end(), expected_full_constant_name_lower.begin(), ::towlower); int64_t expected_max_value = highest_enum_value + 1; @@ -675,33 +678,33 @@ namespace RC::UEGenerator continue; } // Otherwise, just make sure it's hidden and not visible to the end user - result_enumeration_line.append(STR(" UMETA(Hidden)")); + result_enumeration_line.append(SYSSTR(" UMETA(Hidden)")); } - result_enumeration_line.append(STR(",")); + result_enumeration_line.append(SYSSTR(",")); header_data.append_line(result_enumeration_line); } header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); if (cpp_form == UEnum::ECppForm::Namespaced) { header_data.end_indent_level(); - header_data.append_line(STR("}")); + header_data.append_line(SYSSTR("}")); } } auto UEHeaderGenerator::generate_delegate_type_declaration(UFunction* signature_function, UClass* delegate_class, GeneratedSourceFile& header_data) -> void { - std::wstring owning_class; + SystemStringType owning_class; if (delegate_class == nullptr) { - owning_class = STR("UObject*"); + owning_class = SYSSTR("UObject*"); } else { - owning_class = delegate_class->GetNamePrivate().ToString(); + owning_class = UEStringToSystemString(delegate_class->GetNamePrivate().ToString()); } auto function_flags = signature_function->GetFunctionFlags(); @@ -716,52 +719,52 @@ namespace RC::UEGenerator const bool is_multicast = (function_flags & Unreal::FUNC_MulticastDelegate) != 0; const bool declared_const = (function_flags & FUNC_Const) != 0; - const std::wstring delegate_type_name = get_native_delegate_type_name(signature_function, nullptr, true); + const SystemStringType delegate_type_name = get_native_delegate_type_name(signature_function, nullptr, true); FProperty* return_value_property = signature_function->GetReturnProperty(); - std::wstring delegate_macro_string; + SystemStringType delegate_macro_string; // Delegate macro declaration is only allowed on the top level delegates, class-based types are limited to being implicit if (signature_function->GetOuterPrivate()->IsA()) { - delegate_macro_string.append(STR("UDELEGATE(")); + delegate_macro_string.append(SYSSTR("UDELEGATE(")); delegate_macro_string.append(generate_function_flags(signature_function)); - delegate_macro_string.append(STR(") ")); + delegate_macro_string.append(SYSSTR(") ")); } PropertyTypeDeclarationContext context(delegate_type_name, &header_data); int32_t num_delegate_parameters = 0; - std::wstring delegate_parameter_list = + SystemStringType delegate_parameter_list = generate_function_parameter_list(nullptr, signature_function, header_data, true, context.context_name, {}, &num_delegate_parameters); if (num_delegate_parameters > 0) { - delegate_parameter_list.insert(0, STR(", ")); + delegate_parameter_list.insert(0, SYSSTR(", ")); } if (num_delegate_parameters > 9) { - Output::send(STR("Invalid delegate parameter count in Delegate: {}. Using _TooMany\n"), delegate_type_name); + Output::send(SYSSTR("Invalid delegate parameter count in Delegate: {}. Using _TooMany\n"), delegate_type_name); } - std::wstring return_value_declaration; + SystemStringType return_value_declaration; if (return_value_property != NULL) { return_value_declaration = generate_property_type_declaration(return_value_property, context); - return_value_declaration.append(STR(", ")); + return_value_declaration.append(SYSSTR(", ")); } - std::wstring delegate_declaration_string = std::format(STR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), + SystemStringType delegate_declaration_string = std::format(SYSSTR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), delegate_macro_string, - is_multicast ? STR("_MULTICAST") : STR(""), - is_sparse ? STR("_SPARSE") : STR(""), - return_value_property ? STR("_RetVal") : STR(""), + is_multicast ? SYSSTR("_MULTICAST") : SYSSTR(""), + is_sparse ? SYSSTR("_SPARSE") : SYSSTR(""), + return_value_property ? SYSSTR("_RetVal") : SYSSTR(""), generate_parameter_count_string(num_delegate_parameters), - declared_const ? STR("_Const") : STR(""), + declared_const ? SYSSTR("_Const") : SYSSTR(""), return_value_declaration, delegate_type_name, // TODO: Actually get delegate property name. - is_sparse ? std::format(STR("{}, {}"), owning_class, STR("EnterPropertyName")) : STR(""), + is_sparse ? std::format(SYSSTR("{}, {}"), owning_class, SYSSTR("EnterPropertyName")) : SYSSTR(""), delegate_parameter_list); header_data.append_line(delegate_declaration_string); @@ -769,32 +772,32 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_object_implementation(UClass* uclass, GeneratedSourceFile& implementation_file) -> void { - const std::wstring class_native_name = get_native_class_name(uclass); + const SystemStringType class_native_name = get_native_class_name(uclass); - std::wstring constructor_content_string; - std::wstring constructor_postfix_string; + SystemStringType constructor_content_string; + SystemStringType constructor_postfix_string; UClass* super_class = uclass->GetSuperClass(); - const std::wstring native_parent_class_name = super_class ? get_native_class_name(super_class) : STR("UObjectUtility"); + const SystemStringType native_parent_class_name = super_class ? get_native_class_name(super_class) : SYSSTR("UObjectUtility"); // Generate constructor implementation except for overrides. // If class is a child of AActor we add the UObjectInitializer constructor. // This may not be required in all cases, but is necessary to override subcomponents and does not hurt anything. - std::wstring object_initializer_overrides; + SystemStringType object_initializer_overrides; if (uclass->IsChildOf() || uclass->IsChildOf()) { - constructor_content_string.append(STR("const FObjectInitializer& ObjectInitializer")); - constructor_postfix_string.append(std::format(STR(") : Super(ObjectInitializer{}"), object_initializer_overrides)); + constructor_content_string.append(SYSSTR("const FObjectInitializer& ObjectInitializer")); + constructor_postfix_string.append(std::format(SYSSTR(") : Super(ObjectInitializer{}"), object_initializer_overrides)); } // If parent class contains the UObjectInitializer constructor without default value, // we need to create the explicit call to such constructor and pass UObjectInitializer::Get() as the argument. else if (m_classes_with_object_initializer.contains(native_parent_class_name)) { - constructor_postfix_string.append(std::format(STR(") : {}(FObjectInitializer::Get()"), native_parent_class_name)); + constructor_postfix_string.append(std::format(SYSSTR(") : {}(FObjectInitializer::Get()"), native_parent_class_name)); } implementation_file.m_implementation_constructor.append( - std::format(STR("{}::{}({}{}"), class_native_name, class_native_name, constructor_content_string, constructor_postfix_string)); + std::format(SYSSTR("{}::{}({}{}"), class_native_name, class_native_name, constructor_content_string, constructor_postfix_string)); implementation_file.begin_indent_level(); @@ -805,34 +808,34 @@ namespace RC::UEGenerator { for (FProperty* property : uclass->OrderedForEachPropertyInChain()) { - generate_property_value(uclass, property, class_default_object, implementation_file, STR("this->")); + generate_property_value(uclass, property, class_default_object, implementation_file, SYSSTR("this->")); } } else { - implementation_file.append_line(STR("// Null default object.")); + implementation_file.append_line(SYSSTR("// Null default object.")); } m_class_subobjects.clear(); // Generate component attachments for (auto attachment : implementation_file.attachments) { - if (get<2>(attachment.second) == false) + if ((attachment.second).access_type == false) { - generate_simple_assignment_expression(attachment.first, get<1>(attachment.second), implementation_file, STR("this->"), STR("->")); + generate_simple_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, SYSSTR("this->"), SYSSTR("->")); } else { - generate_advanced_assignment_expression(attachment.first, get<1>(attachment.second), implementation_file, STR("this->"), get<0>(attachment.second), STR("->")); + generate_advanced_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, SYSSTR("this->"), (attachment.second).property_type, SYSSTR("->")); } } implementation_file.end_indent_level(); - implementation_file.append_line(STR("}\n")); + implementation_file.append_line(SYSSTR("}\n")); // Finalize constructor. We do this after the property generation because we need information from the properties // to determine the required overrides within the constructor. - implementation_file.m_implementation_constructor.append(STR(") {")); + implementation_file.m_implementation_constructor.append(SYSSTR(") {")); CaseInsensitiveSet blacklisted_property_names = collect_blacklisted_property_names(uclass); @@ -842,7 +845,7 @@ namespace RC::UEGenerator if (!is_delegate_signature_function(function)) { generate_function_implementation(uclass, function, implementation_file, false, blacklisted_property_names); - implementation_file.append_line(STR("")); + implementation_file.append_line(SYSSTR("")); } } @@ -856,35 +859,35 @@ namespace RC::UEGenerator // Generate replicated properties implementation if we really need it if (encountered_replicated_properties) { - implementation_file.add_extra_include(STR("Net/UnrealNetwork.h")); + implementation_file.add_extra_include(SYSSTR("Net/UnrealNetwork.h")); implementation_file.append_line( - std::format(STR("void {}::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const {{"), class_native_name)); + std::format(SYSSTR("void {}::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const {{"), class_native_name)); implementation_file.begin_indent_level(); - implementation_file.append_line(STR("Super::GetLifetimeReplicatedProps(OutLifetimeProps);")); - implementation_file.append_line(STR("")); + implementation_file.append_line(SYSSTR("Super::GetLifetimeReplicatedProps(OutLifetimeProps);")); + implementation_file.append_line(SYSSTR("")); for (FProperty* property : uclass->ForEachProperty()) { if ((property->GetPropertyFlags() & CPF_Net) != 0) { - implementation_file.append_line(std::format(STR("DOREPLIFETIME({}, {});"), class_native_name, property->GetName())); + implementation_file.append_line(std::format(SYSSTR("DOREPLIFETIME({}, {});"), class_native_name, UEStringToSystemString(property->GetName()))); } } implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); - implementation_file.append_line(STR("")); + implementation_file.append_line(SYSSTR("}")); + implementation_file.append_line(SYSSTR("")); } } auto UEHeaderGenerator::generate_struct_implementation(UScriptStruct* script_struct, GeneratedSourceFile& implementation_file) -> void { - const std::wstring struct_native_name = get_native_struct_name(script_struct); + const SystemStringType struct_native_name = get_native_struct_name(script_struct); // Generate constructor implementation and initialize properties inside - implementation_file.m_implementation_constructor.append(std::format(STR("{}::{}() {{"), struct_native_name, struct_native_name)); + implementation_file.m_implementation_constructor.append(std::format(SYSSTR("{}::{}() {{"), struct_native_name, struct_native_name)); implementation_file.begin_indent_level(); // Generate properties @@ -895,26 +898,26 @@ namespace RC::UEGenerator for (FProperty* property : script_struct->OrderedForEachPropertyInChain()) { - generate_property_value(script_struct, property, struct_default_object, implementation_file, STR("this->")); + generate_property_value(script_struct, property, struct_default_object, implementation_file, SYSSTR("this->")); } // TODO: ScriptStruct->DestroyStruct(StructDefaultObject); free(struct_default_object); implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); + implementation_file.append_line(SYSSTR("}")); } auto UEHeaderGenerator::generate_property(UObject* uclass, FProperty* property, GeneratedSourceFile& header_data) -> void { - const std::wstring property_flags_string = generate_property_flags(property); + const SystemStringType property_flags_string = generate_property_flags(property); bool is_bitmask_bool = false; - PropertyTypeDeclarationContext Context(uclass->GetName(), &header_data, true, &is_bitmask_bool); + PropertyTypeDeclarationContext Context(UEStringToSystemString(uclass->GetName()), &header_data, true, &is_bitmask_bool); - std::wstring property_type_string{}; + SystemStringType property_type_string{}; bool type_is_valid = true; - std::wstring error_string{}; + SystemStringType error_string{}; try { property_type_string = generate_property_type_declaration(property, Context); @@ -922,34 +925,34 @@ namespace RC::UEGenerator catch (std::exception& e) { type_is_valid = false; - error_string = to_wstring(e.what()); + error_string = to_generic_string(std::string(e.what())); } if (!type_is_valid) { - Output::send(STR("Warning: {}\n"), error_string); - header_data.append_line(std::format(STR("// UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(STR("// Missed Property: {}"), property->GetName())); - header_data.append_line(std::format(STR("// {}"), error_string)); - header_data.append_line(STR("")); + Output::send(SYSSTR("Warning: {}\n"), error_string); + header_data.append_line(std::format(SYSSTR("// UPROPERTY({})"), property_flags_string)); + header_data.append_line(std::format(SYSSTR("// Missed Property: {}"), UEStringToSystemString(property->GetName()))); + header_data.append_line(std::format(SYSSTR("// {}"), error_string)); + header_data.append_line(SYSSTR("")); return; } - std::wstring property_extra_declaration; + SystemStringType property_extra_declaration; if (property->GetArrayDim() != 1) { - property_extra_declaration.append(STR("[")); - property_extra_declaration.append(std::to_wstring(property->GetArrayDim())); - property_extra_declaration.append(STR("]")); + property_extra_declaration.append(SYSSTR("[")); + property_extra_declaration.append(to_generic_string(std::to_string(property->GetArrayDim()))); + property_extra_declaration.append(SYSSTR("]")); } else if (is_bitmask_bool) { - property_extra_declaration.append(STR(": 1")); + property_extra_declaration.append(SYSSTR(": 1")); } - header_data.append_line(std::format(STR("UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(STR("{} {}{};"), property_type_string, property->GetName(), property_extra_declaration)); - header_data.append_line(STR("")); + header_data.append_line(std::format(SYSSTR("UPROPERTY({})"), property_flags_string)); + header_data.append_line(std::format(SYSSTR("{} {}{};"), property_type_string, UEStringToSystemString(property->GetName()), property_extra_declaration)); + header_data.append_line(SYSSTR("")); } // TODO FUNC_Final is not properly handled (should be always set except some weird cases) @@ -961,90 +964,90 @@ namespace RC::UEGenerator bool generate_as_override) -> void { auto function_flags = function->GetFunctionFlags(); - const std::wstring context_name = uclass->GetName(); + const UEStringType context_name = uclass->GetName(); bool is_function_pure_virtual = generate_as_override; - std::wstring function_modifier_string; + SystemStringType function_modifier_string; if ((function_flags & FUNC_Static) != 0) { - function_modifier_string.append(STR("static ")); + function_modifier_string.append(SYSSTR("static ")); } else if ((function_flags & FUNC_BlueprintEvent) == 0 && is_generating_interface) { // When we have a blueprint function that is not blueprint event inside the interface, // it means we are dealing with the native interface that cannot be implemented via blueprints // and uses pure virtual functions implemented through native code - function_modifier_string.append(STR("virtual ")); + function_modifier_string.append(SYSSTR("virtual ")); is_function_pure_virtual = true; } FProperty* return_property = function->GetReturnProperty(); - std::wstring return_property_string; + SystemStringType return_property_string; if (return_property != NULL) { - PropertyTypeDeclarationContext context(uclass->GetName(), &header_data); + PropertyTypeDeclarationContext context(UEStringToSystemString(uclass->GetName()), &header_data); return_property_string = generate_property_type_declaration(return_property, context); } else { - return_property_string = STR("void"); + return_property_string = SYSSTR("void"); } - std::wstring function_extra_postfix_string; + SystemStringType function_extra_postfix_string; if ((function_flags & FUNC_Const) != 0) { - function_extra_postfix_string.append(STR(" const")); + function_extra_postfix_string.append(SYSSTR(" const")); } if (is_function_pure_virtual) { - std::wstring return_statement_string; + SystemStringType return_statement_string; if (return_property != NULL) { - const std::wstring default_property_value = generate_default_property_value(return_property, header_data, context_name); - return_statement_string = std::format(STR(" return {};"), default_property_value); + const SystemStringType default_property_value = generate_default_property_value(return_property, header_data, UEStringToSystemString(context_name)); + return_statement_string = std::format(SYSSTR(" return {};"), default_property_value); } if (generate_as_override) { - function_extra_postfix_string.append(STR(" override")); + function_extra_postfix_string.append(SYSSTR(" override")); } - function_extra_postfix_string.append(std::format(STR(" PURE_VIRTUAL({},{})"), function->GetName(), return_statement_string)); + function_extra_postfix_string.append(std::format(SYSSTR(" PURE_VIRTUAL({},{})"), UEStringToSystemString(function->GetName()), return_statement_string)); } - std::wstring function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, context_name, blacklisted_property_names); + SystemStringType function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, UEStringToSystemString(context_name), blacklisted_property_names); - const std::wstring function_flags_string = generate_function_flags(function, is_function_pure_virtual); - header_data.append_line(std::format(STR("UFUNCTION({})"), function_flags_string)); + const SystemStringType function_flags_string = generate_function_flags(function, is_function_pure_virtual); + header_data.append_line(std::format(SYSSTR("UFUNCTION({})"), function_flags_string)); // Format for virtual functions // virtual () PURE_VIRTUAL(, ) - header_data.append_line(std::format(STR("{}{} {}({}){};"), + header_data.append_line(std::format(SYSSTR("{}{} {}({}){};"), function_modifier_string, return_property_string, - function->GetName(), + UEStringToSystemString(function->GetName()), function_argument_list, function_extra_postfix_string)); - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("")); } - auto UEHeaderGenerator::generate_enum_value(UEnum* uenum, int64_t enum_value) -> std::wstring + auto UEHeaderGenerator::generate_enum_value(UEnum* uenum, int64_t enum_value) -> SystemStringType { UEnum::ECppForm cpp_form = uenum->GetCppForm(); - const std::wstring enum_native_name = get_native_enum_name(uenum, false); + const SystemStringType enum_native_name = get_native_enum_name(uenum, false); - std::wstring enum_constant_name; + SystemStringType enum_constant_name; for (auto [Name, Value] : uenum->ForEachName()) { if (Value == enum_value) { - enum_constant_name = sanitize_enumeration_name(Name.ToString()); + enum_constant_name = sanitize_enumeration_name(UEStringToSystemString(Name.ToString())); } } if (enum_constant_name.empty()) { - Output::send(STR("Warning: Invalid value for enum '{}', casting instead of using enum name. Value '{}' will be cast to the enum.\n"), + Output::send(SYSSTR("Warning: Invalid value for enum '{}', casting instead of using enum name. Value '{}' will be cast to the enum.\n"), enum_native_name, enum_value); - return std::format(STR("({}){}"), enum_native_name, enum_value); + return std::format(SYSSTR("({}){}"), enum_native_name, enum_value); } else { @@ -1053,57 +1056,57 @@ namespace RC::UEGenerator { return enum_constant_name; } - return std::format(STR("{}::{}"), enum_native_name, enum_constant_name); + return std::format(SYSSTR("{}::{}"), enum_native_name, enum_constant_name); } } auto UEHeaderGenerator::generate_simple_assignment_expression(FProperty* property, - const std::wstring& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const std::wstring& property_scope, - const std::wstring& operator_type) -> void + const SystemStringType& property_scope, + const SystemStringType& operator_type) -> void { - const std::wstring field_class_name = property->GetName(); + const SystemStringType field_class_name = UEStringToSystemString(property->GetName()); if (property->GetArrayDim() == 1) { - implementation_file.append_line(std::format(STR("{}{}{}{};"), property_scope, field_class_name, operator_type, value)); + implementation_file.append_line(std::format(SYSSTR("{}{}{}{};"), property_scope, field_class_name, operator_type, value)); } else { for (int32_t i = 0; i < property->GetArrayDim(); i++) { - implementation_file.append_line(std::format(STR("{}{}[{}]{}{};"), property_scope, field_class_name, i, operator_type, value)); + implementation_file.append_line(std::format(SYSSTR("{}{}[{}]{}{};"), property_scope, field_class_name, i, operator_type, value)); } } } auto UEHeaderGenerator::generate_advanced_assignment_expression(FProperty* property, - const std::wstring& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const std::wstring& property_scope, - const std::wstring& property_type, - const std::wstring& operator_type) -> void + const SystemStringType& property_scope, + const SystemStringType& property_type, + const SystemStringType& operator_type) -> void { - const std::wstring field_class_name = property->GetName(); - implementation_file.append_line(std::format(STR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); + const SystemStringType field_class_name = UEStringToSystemString(property->GetName()); + implementation_file.append_line(std::format(SYSSTR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); if (property->GetArrayDim() == 1) { - implementation_file.append_line(std::format(STR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); + implementation_file.append_line(std::format(SYSSTR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); } else { for (int32_t i = 0; i < property->GetArrayDim(); i++) { implementation_file.append_line( - std::format(STR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), field_class_name, property_scope, field_class_name, i, operator_type, value)); + std::format(SYSSTR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), field_class_name, property_scope, field_class_name, i, operator_type, value)); } } } auto UEHeaderGenerator::generate_property_value( - UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const std::wstring& property_scope) -> void + UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const SystemStringType& property_scope) -> void { - const std::wstring property_name = property->GetName(); + const UEStringType property_name = property->GetName(); if (property_name == STR("NativeClass") || property_name == STR("hudClass")) { return; } const bool private_access_modifier = get_property_access_modifier(property) == AccessModifier::Private; bool super_and_no_access = false; @@ -1111,7 +1114,7 @@ namespace RC::UEGenerator UStruct* super; void* super_object = nullptr; FProperty* super_property = nullptr; - const std::wstring property_type = generate_property_cxx_name(property, true, ustruct); + const SystemStringType property_type = generate_property_cxx_name(property, true, ustruct); auto as_class = Cast(ustruct); if (as_class) { @@ -1152,15 +1155,19 @@ namespace RC::UEGenerator } UEnum* uenum = byte_property->GetEnum(); - std::wstring result_property_value; + SystemStringType result_property_value; if (uenum != NULL) { - const std::wstring enum_type_name = get_native_enum_name(uenum); + const SystemStringType enum_type_name = get_native_enum_name(uenum); result_property_value = generate_enum_value(uenum, *byte_property_value); } else { + #ifdef WIN32 result_property_value = std::to_wstring(*byte_property_value); + #else + result_property_value = std::to_string(*byte_property_value); + #endif } if (!super_and_no_access) @@ -1200,7 +1207,7 @@ namespace RC::UEGenerator } implementation_file.add_dependency_object(uenum, DependencyLevel::Include); - std::wstring result_property_value = generate_enum_value(uenum, value); + SystemStringType result_property_value = generate_enum_value(uenum, value); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1242,7 +1249,7 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - const std::wstring result_property_value = result_bool_value ? STR("true") : STR("false"); + const SystemStringType result_property_value = result_bool_value ? SYSSTR("true") : SYSSTR("false"); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1260,13 +1267,13 @@ namespace RC::UEGenerator if (property->IsA()) { FName* name_value = property->ContainerPtrToValuePtr(object); - const std::wstring name_value_string = name_value->ToString(); + const SystemStringType name_value_string = UEStringToSystemString(name_value->ToString()); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FName* super_name_value = super_property->ContainerPtrToValuePtr(super_object); - const std::wstring super_name_value_string = super_name_value->ToString(); + const SystemStringType super_name_value_string = UEStringToSystemString(super_name_value->ToString()); if (name_value_string == super_name_value_string) { return; @@ -1274,9 +1281,9 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - if (name_value_string != STR("None")) + if (name_value_string != SYSSTR("None")) { - const std::wstring result_property_value = std::format(STR("TEXT(\"{}\")"), name_value_string); + const SystemStringType result_property_value = std::format(SYSSTR("TEXT(\"{}\")"), name_value_string); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1293,13 +1300,13 @@ namespace RC::UEGenerator if (property->IsA()) { FString* string_value = property->ContainerPtrToValuePtr(object); - const std::wstring string_value_string = string_value->GetCharArray(); + const SystemStringType string_value_string = UEStringToSystemString(UEStringType (string_value->GetCharArray())); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FString* super_string_value = super_property->ContainerPtrToValuePtr(super_object); - const std::wstring super_string_value_string = super_string_value->GetCharArray(); + const SystemStringType super_string_value_string = UEStringToSystemString(UEStringType (super_string_value->GetCharArray())); if (string_value_string == super_string_value_string) { return; @@ -1307,9 +1314,9 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - if (string_value_string != STR("")) + if (string_value_string != SYSSTR("")) { - const std::wstring result_value = create_string_literal(string_value_string); + const SystemStringType result_value = create_string_literal(string_value_string); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_value, implementation_file, property_scope); @@ -1342,7 +1349,7 @@ namespace RC::UEGenerator if (text_value_string != STR("")) { - const std::wstring result_property_value = std::format(STR("FText::FromString({})"), create_string_literal(text_value_string)); + const SystemStringType result_property_value = std::format(SYSSTR("FText::FromString({})"), create_string_literal(UEStringToSystemString(text_value_string))); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1378,11 +1385,11 @@ namespace RC::UEGenerator // If class value is NULL, generate a simple NULL assignment if (!super_and_no_access) { - generate_simple_assignment_expression(property, STR("NULL"), implementation_file, property_scope); + generate_simple_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope); } else { - generate_advanced_assignment_expression(property, STR("NULL"), implementation_file, property_scope, property_type); + generate_advanced_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope, property_type); } } else if ((class_value->GetClassFlags() & CLASS_Native) != 0) @@ -1390,8 +1397,8 @@ namespace RC::UEGenerator implementation_file.add_dependency_object(class_value, DependencyLevel::Include); // Otherwise, generate StaticClass call, assuming the class is native - const std::wstring object_class_name = get_native_class_name(class_value); - const std::wstring initializer = std::format(STR("{}::StaticClass()"), object_class_name); + const SystemStringType object_class_name = get_native_class_name(class_value); + const SystemStringType initializer = std::format(SYSSTR("{}::StaticClass()"), object_class_name); if (!super_and_no_access) { @@ -1405,7 +1412,7 @@ namespace RC::UEGenerator else { // Unhandled case, reference to the non-native blueprint class potentially? - Output::send(STR("Unhandled default value of the FClassProperty {}: {}\n"), property->GetFullName(), class_value->GetFullName()); + Output::send(SYSSTR("Unhandled default value of the FClassProperty {}: {}\n"), UEStringToSystemString(property->GetFullName()), UEStringToSystemString(class_value->GetFullName())); } return; } @@ -1436,11 +1443,11 @@ namespace RC::UEGenerator // TODO: Needs additional checks to see if the class is abstract to potentially change this to a default object init if (!super_and_no_access) { - generate_simple_assignment_expression(property, STR("NULL"), implementation_file, property_scope); + generate_simple_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope); } else { - generate_advanced_assignment_expression(property, STR("NULL"), implementation_file, property_scope, property_type); + generate_advanced_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope, property_type); } return; } @@ -1448,14 +1455,14 @@ namespace RC::UEGenerator if (sub_object_value->HasAnyFlags(EObjectFlags::RF_DefaultSubObject)) { UClass* object_class_type = sub_object_value->GetClassPrivate(); - const std::wstring object_name = sub_object_value->GetName(); + const SystemStringType object_name = UEStringToSystemString(sub_object_value->GetName()); UClass* super_object_class_type{}; // Additional checks to ensure this property needs to be initialized in the current class if (super_sub_object_value) { super_object_class_type = super_sub_object_value->GetClassPrivate(); - const std::wstring super_object_name = super_sub_object_value->GetName(); + const SystemStringType super_object_name = UEStringToSystemString(super_sub_object_value->GetName()); if ((object_class_type == super_object_class_type) && (object_name == super_object_name)) { return; @@ -1464,7 +1471,7 @@ namespace RC::UEGenerator } bool parent_component_found = false; - std::wstring prior_property_variable{}; + SystemStringType prior_property_variable{}; // Check to see if any other property in the super initialized a component with the same name to ensure // we are not creating the subobject in a child class unnecessarily. @@ -1478,7 +1485,7 @@ namespace RC::UEGenerator UObject* check_super_sub_object_value = *check_super_object_property->ContainerPtrToValuePtr(super_object); if (check_super_sub_object_value) { - std::wstring check_super_object_name = check_super_sub_object_value->GetName(); + SystemStringType check_super_object_name = UEStringToSystemString(check_super_sub_object_value->GetName()); if (check_super_object_name == object_name) { parent_component_found = true; @@ -1491,33 +1498,33 @@ namespace RC::UEGenerator // Generate an initializer by either setting this property to a pre-existing property // overriding the object class of an existing component, or creating a new default subobject - std::wstring initializer{}; + SystemStringType initializer{}; if (auto it = m_class_subobjects.find(object_name); it != m_class_subobjects.end()) { // Set property to equal previous property referencing the same object initializer = it->second; - FProperty* prior_property = ustruct->GetPropertyByNameInChain(initializer.c_str()); + FProperty* prior_property = ustruct->GetPropertyByNameInChain(SystemStringToUEString(initializer).c_str()); bool prior_private = get_property_access_modifier(prior_property) == AccessModifier::Private; if (prior_private) { UObject* check_sub_object_value = *prior_property->ContainerPtrToValuePtr(object); - std::wstring prior_prop_class_name = STR("NULL"); + SystemStringType prior_prop_class_name = SYSSTR("NULL"); if (check_sub_object_value->GetClassPrivate() != nullptr) { prior_prop_class_name = get_native_class_name(check_sub_object_value->GetClassPrivate()); } implementation_file.append_line( - std::format(STR("FProperty* p_{}_Prior = GetClass()->FindPropertyByName(\"{}\");"), initializer, initializer)); - initializer = std::format(STR("*p_{}_Prior->ContainerPtrToValuePtr<{}*>(this)"), initializer, prior_prop_class_name); + std::format(SYSSTR("FProperty* p_{}_Prior = GetClass()->FindPropertyByName(\"{}\");"), initializer, initializer)); + initializer = std::format(SYSSTR("*p_{}_Prior->ContainerPtrToValuePtr<{}*>(this)"), initializer, prior_prop_class_name); } if (!super_and_no_access) { - initializer = std::format(STR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); + initializer = std::format(SYSSTR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); } else { - initializer = std::format(STR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); + initializer = std::format(SYSSTR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); generate_advanced_assignment_expression(property, initializer, implementation_file, property_scope, property_type); } } @@ -1526,16 +1533,16 @@ namespace RC::UEGenerator // Add an objectinitializer default subobject class override to the constructor implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); implementation_file.m_implementation_constructor.append( - std::format(STR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), object_name)); - m_class_subobjects.try_emplace(object_name, property->GetName()); + std::format(SYSSTR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), object_name)); + m_class_subobjects.try_emplace(object_name, UEStringToSystemString(property->GetName())); } else { // Generate a CreateDefaultSubobject function call implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); - const std::wstring object_class_name = get_native_class_name(object_class_type); - initializer = std::format(STR("CreateDefaultSubobject<{}>(TEXT(\"{}\"))"), object_class_name, object_name); - m_class_subobjects.try_emplace(object_name, property->GetName()); + const SystemStringType object_class_name = get_native_class_name(object_class_type); + initializer = std::format(SYSSTR("CreateDefaultSubobject<{}>(TEXT(\"{}\"))"), object_class_name, object_name); + m_class_subobjects.try_emplace(object_name, UEStringToSystemString(property->GetName())); if (!super_and_no_access) { generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); @@ -1554,14 +1561,14 @@ namespace RC::UEGenerator } if (attach_parent_object_value != NULL) { - const std::wstring attach_parent_object_name = attach_parent_object_value->GetName(); - const std::wstring operator_type = STR("->"); + const SystemStringType attach_parent_object_name = UEStringToSystemString (attach_parent_object_value->GetName()); + const SystemStringType operator_type = SYSSTR("->"); bool parent_found = false; - std::wstring attach_string; + SystemStringType attach_string; if (auto it = m_class_subobjects.find(attach_parent_object_name); it != m_class_subobjects.end()) { // Set property to equal previous property referencing the same object - attach_string = std::format(STR("SetupAttachment({})"), it->second); + attach_string = std::format(SYSSTR("SetupAttachment({})"), it->second); parent_found = true; } else if (as_class) @@ -1574,25 +1581,25 @@ namespace RC::UEGenerator UObject* check_sub_object_value = *check_object_property->ContainerPtrToValuePtr(object); if (check_sub_object_value) { - std::wstring check_object_name = check_sub_object_value->GetName(); + SystemStringType check_object_name = UEStringToSystemString(check_sub_object_value->GetName()); if (check_object_name == attach_parent_object_name) { if (get_property_access_modifier(check_object_property) != AccessModifier::Private) { - attach_string = std::format(STR("SetupAttachment({})"), check_property->GetName()); + attach_string = std::format(SYSSTR("SetupAttachment({})"), UEStringToSystemString(check_property->GetName())); } else { - StringType parent_property_name = std::format(STR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), - check_property->GetName(), - check_property->GetName()); + SystemStringType parent_property_name = std::format(SYSSTR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), + UEStringToSystemString(check_property->GetName()), + UEStringToSystemString(check_property->GetName())); if (!implementation_file.parent_property_names.contains(parent_property_name)) { implementation_file.parent_property_names.emplace(parent_property_name); implementation_file.append_line(parent_property_name); } - attach_string = std::format(STR("SetupAttachment(p_{}_Parent->ContainerPtrToValuePtr<{}>(this))"), - check_property->GetName(), + attach_string = std::format(SYSSTR("SetupAttachment(p_{}_Parent->ContainerPtrToValuePtr<{}>(this))"), + UEStringToSystemString(check_property->GetName()), get_native_class_name(check_sub_object_value->GetClassPrivate())); implementation_file.add_dependency_object(check_sub_object_value->GetClassPrivate(), DependencyLevel::Include); } @@ -1607,11 +1614,11 @@ namespace RC::UEGenerator { if (!super_and_no_access) { - implementation_file.attachments.try_emplace(property, std::tuple{property_type, attach_string, false}); + implementation_file.attachments.try_emplace(property, GeneratedSourceFile::attachment_data {property_type, attach_string, false}); } else { - implementation_file.attachments.try_emplace(property, std::tuple{property_type, attach_string, true}); + implementation_file.attachments.try_emplace(property, GeneratedSourceFile::attachment_data {property_type, attach_string, true}); } } } @@ -1634,8 +1641,8 @@ namespace RC::UEGenerator // Generate a ::StaticClass call if this object represents a class implementation_file.add_dependency_object(sub_object_as_class, DependencyLevel::Include); - const std::wstring object_class_name = get_native_class_name(sub_object_as_class); - const std::wstring initializer = std::format(STR("{}::StaticClass()"), object_class_name); + const SystemStringType object_class_name = get_native_class_name(sub_object_as_class); + const SystemStringType initializer = std::format(SYSSTR("{}::StaticClass()"), object_class_name); if (!super_and_no_access) { generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); @@ -1648,14 +1655,14 @@ namespace RC::UEGenerator } // Unhandled case, might be some external object reference - Output::send(STR("Unhandled default value of the FObjectProperty {}: {}\n"), property->GetFullName(), sub_object_value->GetFullName()); + Output::send(SYSSTR("Unhandled default value of the FObjectProperty {}: {}\n"), UEStringToSystemString(property->GetFullName()), UEStringToSystemString(sub_object_value->GetFullName())); return; } // Struct properties are serialization as normal struct constructors with custom scope // TODO there are a lot of issues with that regarding member access, unnecessary assignments and so on - /*if (FieldClassName == STR("StructProperty")) { + /*if (FieldClassName == SYSSTR("StructProperty")) { XStructProperty* StructProperty = static_cast(Property); UScriptStruct* ScriptStruct = StructProperty->get_script_struct(); @@ -1664,7 +1671,7 @@ namespace RC::UEGenerator } void* StructDataPointer = StructProperty->container_ptr_to_value_ptr(Object); - const std::wstring NewPropertyScope = std::format(STR("{}{}."), PropertyScope, StructProperty->GetName()); + const SystemStringType NewPropertyScope = std::format(SYSSTR("{}{}."), PropertyScope, StructProperty->GetName()); //Generate values for each struct property //TODO we do not really need to generate assignments for each struct member, we only really need members that are different from the constructor set @@ -1694,7 +1701,7 @@ namespace RC::UEGenerator { if (!super_and_no_access) { - implementation_file.append_line(std::format(STR("{}{}.AddDefaulted({});"), property_scope, property->GetName(), property_value->Num())); + implementation_file.append_line(std::format(SYSSTR("{}{}.AddDefaulted({});"), property_scope, UEStringToSystemString(property->GetName()), (int32_t)property_value->Num())); } else { @@ -1729,16 +1736,16 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - std::wstring number_constant_string; + SystemStringType number_constant_string; if (!numeric_property->IsFloatingPoint()) { int64 value = numeric_property->GetSignedIntPropertyValue(numeric_property->ContainerPtrToValuePtr(object)); - number_constant_string = std::to_wstring(value); + number_constant_string = to_generic_string( std::to_string(value)); } else { double value = numeric_property->GetFloatingPointPropertyValue(numeric_property->ContainerPtrToValuePtr(object)); - number_constant_string = std::format(STR("{:.2f}f"), value); + number_constant_string = std::format(SYSSTR("{:.2f}f"), value); } if (!super_and_no_access) { @@ -1758,24 +1765,24 @@ namespace RC::UEGenerator bool is_generating_interface, const CaseInsensitiveSet& blacklisted_property_names) -> void { - const std::wstring class_native_name = get_native_class_name(uclass, is_generating_interface); - const std::wstring raw_function_name = function->GetName(); + const SystemStringType class_native_name = get_native_class_name(uclass, is_generating_interface); + const SystemStringType raw_function_name = UEStringToSystemString(function->GetName()); auto function_flags = function->GetFunctionFlags(); - PropertyTypeDeclarationContext context(uclass->GetName(), &implementation_file); + PropertyTypeDeclarationContext context(UEStringToSystemString(uclass->GetName()), &implementation_file); - std::wstring function_implementation_name; - std::wstring net_validate_function_name; + SystemStringType function_implementation_name; + SystemStringType net_validate_function_name; bool is_input_function_const = ((function_flags)&FUNC_Const) != 0; if ((function_flags & FUNC_Net) != 0) { // Network functions always have the implementation inside the _Implementation function - function_implementation_name = std::format(STR("{}::{}_Implementation"), class_native_name, raw_function_name); + function_implementation_name = std::format(SYSSTR("{}::{}_Implementation"), class_native_name, raw_function_name); // Validated network functions by default have their validation function name set to _Validate if ((function_flags & FUNC_NetValidate) != 0) { - net_validate_function_name = std::format(STR("{}::{}_Validate"), class_native_name, raw_function_name); + net_validate_function_name = std::format(SYSSTR("{}::{}_Validate"), class_native_name, raw_function_name); } } else if ((function_flags & FUNC_BlueprintEvent) != 0) @@ -1784,16 +1791,16 @@ namespace RC::UEGenerator // BlueprintImplementableEvents do not have any native functions at all, they're just thunks if ((function_flags & FUNC_Native) != 0) { - function_implementation_name = std::format(STR("{}::{}_Implementation"), class_native_name, raw_function_name); + function_implementation_name = std::format(SYSSTR("{}::{}_Implementation"), class_native_name, raw_function_name); } } else { // Otherwise, normal UFunctions get a standard name matching the function in question - function_implementation_name = std::format(STR("{}::{}"), class_native_name, raw_function_name); + function_implementation_name = std::format(SYSSTR("{}::{}"), class_native_name, raw_function_name); } - std::wstring function_parameter_list; + SystemStringType function_parameter_list; if (!function_implementation_name.empty() || !net_validate_function_name.empty()) { function_parameter_list = @@ -1804,63 +1811,63 @@ namespace RC::UEGenerator { FProperty* return_value_property = function->GetReturnProperty(); - const std::wstring return_value_type = return_value_property ? generate_property_type_declaration(return_value_property, context) : STR("void"); + const SystemStringType return_value_type = return_value_property ? generate_property_type_declaration(return_value_property, context) : SYSSTR("void"); - implementation_file.append_line(std::format(STR("{} {}({}){} {{"), + implementation_file.append_line(std::format(SYSSTR("{} {}({}){} {{"), return_value_type, function_implementation_name, function_parameter_list, - is_input_function_const ? STR(" const") : STR(""))); + is_input_function_const ? SYSSTR(" const") : SYSSTR(""))); implementation_file.begin_indent_level(); if (return_value_property != NULL) { - const std::wstring default_value = generate_default_property_value(return_value_property, implementation_file, context.context_name); - implementation_file.append_line(std::format(STR("return {};"), default_value)); + const SystemStringType default_value = generate_default_property_value(return_value_property, implementation_file, context.context_name); + implementation_file.append_line(std::format(SYSSTR("return {};"), default_value)); } implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); + implementation_file.append_line(SYSSTR("}")); } if (!net_validate_function_name.empty()) { - implementation_file.append_line(std::format(STR("bool {}({}) {{"), net_validate_function_name, function_parameter_list)); + implementation_file.append_line(std::format(SYSSTR("bool {}({}) {{"), net_validate_function_name, function_parameter_list)); implementation_file.begin_indent_level(); - implementation_file.append_line(STR("return true;")); + implementation_file.append_line(SYSSTR("return true;")); implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); + implementation_file.append_line(SYSSTR("}")); } } - auto UEHeaderGenerator::generate_parameter_count_string(int32_t parameter_count) -> std::wstring + auto UEHeaderGenerator::generate_parameter_count_string(int32_t parameter_count) -> SystemStringType { switch (parameter_count) { case 0: - return STR(""); + return SYSSTR(""); case 1: - return STR("_OneParam"); + return SYSSTR("_OneParam"); case 2: - return STR("_TwoParams"); + return SYSSTR("_TwoParams"); case 3: - return STR("_ThreeParams"); + return SYSSTR("_ThreeParams"); case 4: - return STR("_FourParams"); + return SYSSTR("_FourParams"); case 5: - return STR("_FiveParams"); + return SYSSTR("_FiveParams"); case 6: - return STR("_SixParams"); + return SYSSTR("_SixParams"); case 7: - return STR("_SevenParams"); + return SYSSTR("_SevenParams"); case 8: - return STR("_EightParams"); + return SYSSTR("_EightParams"); case 9: - return STR("_NineParams"); + return SYSSTR("_NineParams"); default: - return STR("_TooMany"); + return SYSSTR("_TooMany"); } } @@ -1872,15 +1879,15 @@ namespace RC::UEGenerator if (needed_access == AccessModifier::Public) { - header_data.append_line_no_indent(STR("public:")); + header_data.append_line_no_indent(SYSSTR("public:")); } else if (needed_access == AccessModifier::Protected) { - header_data.append_line_no_indent(STR("protected:")); + header_data.append_line_no_indent(SYSSTR("protected:")); } else if (needed_access == AccessModifier::Private) { - header_data.append_line_no_indent(STR("private:")); + header_data.append_line_no_indent(SYSSTR("private:")); } } } @@ -1923,40 +1930,40 @@ namespace RC::UEGenerator return AccessModifier::Public; } - auto UEHeaderGenerator::create_string_literal(const std::wstring& string) -> std::wstring + auto UEHeaderGenerator::create_string_literal(const SystemStringType& string) -> SystemStringType { - std::wstring result; - result.append(STR("TEXT(\"")); + SystemStringType result; + result.append(SYSSTR("TEXT(\"")); bool previous_character_was_hex = false; - const wchar_t* ptr = string.c_str(); - while (wchar_t ch = *ptr++) + const SystemCharType* ptr = string.c_str(); + while (SystemCharType ch = *ptr++) { switch (ch) { - case STR('\r'): { + case SYSSTR('\r'): { continue; } - case STR('\n'): { - result.append(STR("\\n")); + case SYSSTR('\n'): { + result.append(SYSSTR("\\n")); previous_character_was_hex = false; break; } - case STR('\\'): { - result.append(STR("\\\\")); + case SYSSTR('\\'): { + result.append(SYSSTR("\\\\")); previous_character_was_hex = false; break; } - case STR('\"'): { - result.append(STR("\\\"")); + case SYSSTR('\"'): { + result.append(SYSSTR("\\\"")); previous_character_was_hex = false; break; } default: { - if (ch < 31 || ch >= 128) + if ((unsigned char)ch < 31 || (unsigned char)ch >= 128) { - result.append(std::format(STR("\\x{:04X}"), ch)); + result.append(std::format(SYSSTR("\\x{:04X}"), ch)); previous_character_was_hex = true; } else @@ -1965,7 +1972,7 @@ namespace RC::UEGenerator // appended to the hex sequence, causing a different number if (previous_character_was_hex && iswxdigit(ch) != 0) { - result.append(STR("\")TEXT(\"")); + result.append(SYSSTR("\")TEXT(\"")); } previous_character_was_hex = false; result.push_back(ch); @@ -1974,19 +1981,19 @@ namespace RC::UEGenerator } } } - result.append(STR("\")")); + result.append(SYSSTR("\")")); return result; } - auto UEHeaderGenerator::convert_module_name_to_api_name(const std::wstring& module_name) -> std::wstring + auto UEHeaderGenerator::convert_module_name_to_api_name(const SystemStringType& module_name) -> SystemStringType { - std::wstring uppercase_string = string_to_uppercase(module_name); - uppercase_string.append(STR("_API")); + SystemStringType uppercase_string = string_to_uppercase(module_name); + uppercase_string.append(SYSSTR("_API")); return uppercase_string; } - auto UEHeaderGenerator::add_module_and_sub_module_dependencies(std::set& out_module_dependencies, - const std::wstring& module_name, + auto UEHeaderGenerator::add_module_and_sub_module_dependencies(std::set& out_module_dependencies, + const SystemStringType& module_name, bool add_self_module) -> void { // Prevent infinite recursion @@ -2002,7 +2009,7 @@ namespace RC::UEGenerator const auto iterator = m_module_dependencies.find(module_name); if (iterator != m_module_dependencies.end()) { - for (const std::wstring& DependencyModuleName : *iterator->second) + for (const SystemStringType& DependencyModuleName : *iterator->second) { out_module_dependencies.insert(DependencyModuleName); } @@ -2019,12 +2026,12 @@ namespace RC::UEGenerator for (FProperty* property : class_object->ForEachProperty()) { - result_set.insert(property->GetName()); + result_set.insert(UEStringToSystemString(property->GetName())); } for (UFunction* function : class_object->ForEachFunction()) { - result_set.insert(function->GetName()); + result_set.insert(UEStringToSystemString(function->GetName())); } } else if (uclass->GetClassPrivate()->IsChildOf(UScriptStruct::StaticClass())) @@ -2033,7 +2040,7 @@ namespace RC::UEGenerator for (FProperty* property : script_struct->ForEachProperty()) { - result_set.insert(property->GetName()); + result_set.insert(UEStringToSystemString(property->GetName())); } } return result_set; @@ -2041,7 +2048,7 @@ namespace RC::UEGenerator // TODO CannotImplementInterfaceInBlueprint is not exactly right, // TODO you can have interface with no implementable blueprint methods but that you can still implement in blueprint - auto UEHeaderGenerator::generate_interface_flags(UClass* uinterface) const -> std::wstring + auto UEHeaderGenerator::generate_interface_flags(UClass* uinterface) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2053,7 +2060,7 @@ namespace RC::UEGenerator if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(STR("MinimalAPI")); + flag_format_helper.add_switch(SYSSTR("MinimalAPI")); } ClassBlueprintInfo blueprint_info = get_class_blueprint_info(uinterface); @@ -2063,22 +2070,22 @@ namespace RC::UEGenerator { if (!parent_blueprint_info.is_blueprintable) { - flag_format_helper.add_switch(STR("Blueprintable")); + flag_format_helper.add_switch(SYSSTR("Blueprintable")); } } else if (blueprint_info.is_blueprint_type) { if (!parent_blueprint_info.is_blueprint_type) { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } - flag_format_helper.get_meta()->add_switch(STR("CannotImplementInterfaceInBlueprint")); + flag_format_helper.get_meta()->add_switch(SYSSTR("CannotImplementInterfaceInBlueprint")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_class_flags(UClass* uclass) const -> std::wstring + auto UEHeaderGenerator::generate_class_flags(UClass* uclass) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2090,7 +2097,7 @@ namespace RC::UEGenerator if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(STR("MinimalAPI")); + flag_format_helper.add_switch(SYSSTR("MinimalAPI")); } ClassBlueprintInfo blueprint_info = get_class_blueprint_info(uclass); @@ -2102,7 +2109,7 @@ namespace RC::UEGenerator if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(STR("Blueprintable")); + flag_format_helper.add_switch(SYSSTR("Blueprintable")); } else { @@ -2110,97 +2117,97 @@ namespace RC::UEGenerator { if (!parent_blueprint_info.is_blueprintable) { - flag_format_helper.add_switch(STR("Blueprintable")); + flag_format_helper.add_switch(SYSSTR("Blueprintable")); } } else if (blueprint_info.is_blueprint_type) { if (!parent_blueprint_info.is_blueprint_type) { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } } } if ((class_own_flags & CLASS_Deprecated) != 0) { - flag_format_helper.add_switch(STR("Deprecated")); + flag_format_helper.add_switch(SYSSTR("Deprecated")); } if ((class_own_flags & CLASS_Abstract) != 0) { - flag_format_helper.add_switch(STR("Abstract")); + flag_format_helper.add_switch(SYSSTR("Abstract")); } if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(STR("MinimalAPI")); + flag_format_helper.add_switch(SYSSTR("MinimalAPI")); } if ((class_own_flags & CLASS_NoExport) != 0) { - flag_format_helper.add_switch(STR("NoExport")); + flag_format_helper.add_switch(SYSSTR("NoExport")); } // TODO not quite the case, because UHT boilerplate implicitly marks every native class as CLASS_Intrinsic // if ((ClassOwnFlags & CLASS_Intrinsic) != 0) { - // FlagFormatHelper.AddSwitch(STR("Intrinsic")); + // FlagFormatHelper.AddSwitch(SYSSTR("Intrinsic")); // } if ((class_own_flags & CLASS_Const) != 0) { - flag_format_helper.add_switch(STR("Const")); + flag_format_helper.add_switch(SYSSTR("Const")); } if ((class_own_flags & CLASS_DefaultToInstanced) != 0) { - flag_format_helper.add_switch(STR("DefaultToInstanced")); + flag_format_helper.add_switch(SYSSTR("DefaultToInstanced")); } UClass* class_within = uclass->GetClassWithin(); if (class_within != NULL && class_within != UObject::StaticClass() && (super_class == NULL || class_within != super_class->GetClassWithin())) { - flag_format_helper.add_parameter(STR("Within"), class_within->GetName()); + flag_format_helper.add_parameter(SYSSTR("Within"), UEStringToSystemString(class_within->GetName())); } if ((class_own_flags & CLASS_Transient) != 0) { - flag_format_helper.add_switch(STR("Transient")); + flag_format_helper.add_switch(SYSSTR("Transient")); } else if ((parent_class_flags & CLASS_Transient) != 0) { - flag_format_helper.add_switch(STR("NonTransient")); + flag_format_helper.add_switch(SYSSTR("NonTransient")); } if ((class_own_flags & CLASS_EditInlineNew) != 0) { - flag_format_helper.add_switch(STR("EditInlineNew")); + flag_format_helper.add_switch(SYSSTR("EditInlineNew")); } else if ((class_flags & CLASS_EditInlineNew) == 0 && (parent_class_flags & CLASS_EditInlineNew) != 0) { - flag_format_helper.add_switch(STR("NotEditInlineNew")); + flag_format_helper.add_switch(SYSSTR("NotEditInlineNew")); } if ((class_own_flags & CLASS_NotPlaceable) != 0) { - flag_format_helper.add_switch(STR("NotPlaceable")); + flag_format_helper.add_switch(SYSSTR("NotPlaceable")); } else if ((class_flags & CLASS_NotPlaceable) == 0 && (parent_class_flags & CLASS_NotPlaceable) != 0) { - flag_format_helper.add_switch(STR("Placeable")); + flag_format_helper.add_switch(SYSSTR("Placeable")); } bool add_config_name{false}; if ((class_own_flags & CLASS_DefaultConfig) != 0) { - flag_format_helper.add_switch(STR("DefaultConfig")); + flag_format_helper.add_switch(SYSSTR("DefaultConfig")); add_config_name = true; } if ((class_own_flags & CLASS_GlobalUserConfig) != 0) { - flag_format_helper.add_switch(STR("GlobalUserConfig")); + flag_format_helper.add_switch(SYSSTR("GlobalUserConfig")); add_config_name = true; } if ((class_own_flags & CLASS_ProjectUserConfig) != 0) { - flag_format_helper.add_switch(STR("ProjectUserConfig")); + flag_format_helper.add_switch(SYSSTR("ProjectUserConfig")); add_config_name = true; } @@ -2212,58 +2219,58 @@ namespace RC::UEGenerator } } - const std::wstring class_config_name = uclass->GetClassConfigName().ToString(); + const UEStringType class_config_name = uclass->GetClassConfigName().ToString(); if (super_class == NULL || class_config_name != super_class->GetClassConfigName().ToString()) { - flag_format_helper.add_parameter(STR("Config"), class_config_name); + flag_format_helper.add_parameter(SYSSTR("Config"), UEStringToSystemString(class_config_name)); // Don't add our override config if we add the real one here add_config_name = false; } if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllConfigsEngineConfig && add_config_name) { - flag_format_helper.add_parameter(STR("Config"), STR("Engine")); + flag_format_helper.add_parameter(SYSSTR("Config"), SYSSTR("Engine")); } if ((class_own_flags & CLASS_PerObjectConfig) != 0) { - flag_format_helper.add_switch(STR("PerObjectConfig")); + flag_format_helper.add_switch(SYSSTR("PerObjectConfig")); } if ((class_own_flags & CLASS_ConfigDoNotCheckDefaults) != 0) { - flag_format_helper.add_switch(STR("ConfigDoNotCheckDefaults")); + flag_format_helper.add_switch(SYSSTR("ConfigDoNotCheckDefaults")); } if ((class_own_flags & CLASS_HideDropDown) != 0) { - flag_format_helper.add_switch(STR("HideDropdown")); + flag_format_helper.add_switch(SYSSTR("HideDropdown")); } if ((class_own_flags & CLASS_CollapseCategories) != 0) { - flag_format_helper.add_switch(STR("CollapseCategories")); + flag_format_helper.add_switch(SYSSTR("CollapseCategories")); } else if ((parent_class_flags & CLASS_CollapseCategories) != 0) { - flag_format_helper.add_switch(STR("DontCollapseCategories")); + flag_format_helper.add_switch(SYSSTR("DontCollapseCategories")); } // Mark all UActorComponent derived classes as BlueprintSpawnableComponent by default // This will allow using them inside the Simple Construction Script of the blueprint assets if (uclass->IsChildOf()) { - flag_format_helper.get_meta()->add_switch(STR("BlueprintSpawnableComponent")); - flag_format_helper.add_parameter(STR("ClassGroup"), STR("Custom")); + flag_format_helper.get_meta()->add_switch(SYSSTR("BlueprintSpawnableComponent")); + flag_format_helper.add_parameter(SYSSTR("ClassGroup"), SYSSTR("Custom")); } return flag_format_helper.build_flag_string(); } /**/ - auto UEHeaderGenerator::generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> std::wstring + auto UEHeaderGenerator::generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> SystemStringType { UClass* current_class = Unreal::Cast(property->GetOutermostOwner()); - const std::wstring field_class_name = property->GetClass().GetName(); + const UEStringType field_class_name = property->GetClass().GetName(); // Byte Property if (property->IsA()) @@ -2278,7 +2285,7 @@ namespace RC::UEGenerator context.source_file->add_dependency_object(enum_value, DependencyLevel::Include); } - const std::wstring enum_type_name = get_native_enum_name(enum_value); + const SystemStringType enum_type_name = get_native_enum_name(enum_value); if ((property->GetPropertyFlags() & CPF_BlueprintVisible) != 0) { @@ -2286,9 +2293,9 @@ namespace RC::UEGenerator } // Non-EnumClass enumerations should be wrapped into TEnumAsByte according to UHT, but implicit uint8s should not use TEnumAsByte - return std::format(STR("TEnumAsByte<{}>"), enum_type_name); + return std::format(SYSSTR("TEnumAsByte<{}>"), enum_type_name); } - return STR("uint8"); + return SYSSTR("uint8"); } // Enum Property @@ -2305,14 +2312,14 @@ namespace RC::UEGenerator { context.source_file->add_dependency_object(uenum, DependencyLevel::Include); } - const std::wstring enum_type_name = get_native_enum_name(uenum); + const SystemStringType enum_type_name = get_native_enum_name(uenum); if ((property->GetPropertyFlags() & CPF_BlueprintVisible) != 0) { this->m_blueprint_visible_enums.insert(enum_type_name); } - const std::wstring underlying_enum_type = generate_property_type_declaration(underlying_property, context); + const SystemStringType underlying_enum_type = generate_property_type_declaration(underlying_property, context); this->m_underlying_enum_types.insert({enum_type_name, underlying_enum_type}); return enum_type_name; } @@ -2326,48 +2333,48 @@ namespace RC::UEGenerator if (bool_property->GetFieldMask() != 255) { *context.out_is_bitmask_bool = true; - return STR("uint8"); + return SYSSTR("uint8"); } } - return STR("bool"); + return SYSSTR("bool"); } // Standard Numeric Properties if (property->IsA()) { - return STR("int8"); + return SYSSTR("int8"); } else if (property->IsA()) { - return STR("int16"); + return SYSSTR("int16"); } else if (property->IsA()) { - return STR("int32"); + return SYSSTR("int32"); } else if (property->IsA()) { - return STR("int64"); + return SYSSTR("int64"); } else if (property->IsA()) { - return STR("uint16"); + return SYSSTR("uint16"); } else if (property->IsA()) { - return STR("uint32"); + return SYSSTR("uint32"); } else if (property->IsA()) { - return STR("uint64"); + return SYSSTR("uint64"); } else if (property->IsA()) { - return STR("float"); + return SYSSTR("float"); } else if (property->IsA()) { - return STR("double"); + return SYSSTR("double"); } // Class Properties @@ -2378,23 +2385,23 @@ namespace RC::UEGenerator if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return STR("UClass*"); + return SYSSTR("UClass*"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(meta_class, DependencyLevel::PreDeclaration); - context.source_file->add_extra_include(STR("Templates/SubclassOf.h")); + context.source_file->add_extra_include(SYSSTR("Templates/SubclassOf.h")); } - const std::wstring meta_class_name = get_native_class_name(meta_class, false); + const SystemStringType meta_class_name = get_native_class_name(meta_class, false); - return std::format(STR("TSubclassOf<{}>"), meta_class_name); + return std::format(SYSSTR("TSubclassOf<{}>"), meta_class_name); } if (auto* class_property = CastField(property); class_property) { // TODO: Confirm that this is accurate - return STR("TClassPtr"); + return SYSSTR("TClassPtr"); } if (property->IsA()) @@ -2404,16 +2411,16 @@ namespace RC::UEGenerator if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return STR("TSoftClassPtr"); + return SYSSTR("TSoftClassPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(meta_class, DependencyLevel::PreDeclaration); } - const std::wstring meta_class_name = get_native_class_name(meta_class, false); + const SystemStringType meta_class_name = get_native_class_name(meta_class, false); - return std::format(STR("TSoftClassPtr<{}>"), meta_class_name); + return std::format(SYSSTR("TSoftClassPtr<{}>"), meta_class_name); } // Object Properties @@ -2426,15 +2433,15 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("UObject*"); + return SYSSTR("UObject*"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const std::wstring property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("{}*"), property_class_name); + return std::format(SYSSTR("{}*"), property_class_name); } if (auto* object_property = CastField(property); object_property) @@ -2443,7 +2450,7 @@ namespace RC::UEGenerator if (!property_class) { - return STR("TObjectPtr"); + return SYSSTR("TObjectPtr"); } else { @@ -2453,7 +2460,7 @@ namespace RC::UEGenerator } const auto property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TObjectPtr<{}>"), property_class_name); } } @@ -2464,16 +2471,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TWeakObjectPtr"); + return SYSSTR("TWeakObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const std::wstring property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TWeakObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TWeakObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -2483,16 +2490,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TLazyObjectPtr"); + return SYSSTR("TLazyObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const std::wstring property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TLazyObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TLazyObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -2502,16 +2509,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TSoftObjectPtr"); + return SYSSTR("TSoftObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const std::wstring property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TSoftObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TSoftObjectPtr<{}>"), property_class_name); } // Interface Property @@ -2522,16 +2529,16 @@ namespace RC::UEGenerator if (interface_class == NULL || interface_class == UInterface::StaticClass()) { - return STR("FScriptInterface"); + return SYSSTR("FScriptInterface"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(interface_class, DependencyLevel::PreDeclaration); } - const std::wstring interface_class_name = get_native_class_name(interface_class, true); + const SystemStringType interface_class_name = get_native_class_name(interface_class, true); - return std::format(STR("TScriptInterface<{}>"), interface_class_name); + return std::format(SYSSTR("TScriptInterface<{}>"), interface_class_name); } // Struct Property @@ -2544,7 +2551,7 @@ namespace RC::UEGenerator { throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); } - const std::wstring native_struct_name = get_native_struct_name(script_struct); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); if (context.source_file != NULL) { @@ -2613,8 +2620,8 @@ namespace RC::UEGenerator if (property->IsA()) { FFieldPathProperty* field_path_property = static_cast(property); - const std::wstring property_class_name = field_path_property->GetPropertyClass()->GetName(); - return std::format(STR("TFieldPath"), property_class_name); + const SystemStringType property_class_name = UEStringToSystemString(field_path_property->GetPropertyClass()->GetName()); + return std::format(SYSSTR("TFieldPath"), property_class_name); } // Collection and Map Properties @@ -2624,8 +2631,8 @@ namespace RC::UEGenerator FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - const std::wstring inner_property_type = generate_property_type_declaration(inner_property, context.inner_context()); - return std::format(STR("TArray<{}>"), inner_property_type); + const SystemStringType inner_property_type = generate_property_type_declaration(inner_property, context.inner_context()); + return std::format(SYSSTR("TArray<{}>"), inner_property_type); } if (property->IsA()) @@ -2633,8 +2640,8 @@ namespace RC::UEGenerator FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const std::wstring element_property_type = generate_property_type_declaration(element_prop, context.inner_context()); - return std::format(STR("TSet<{}>"), element_property_type); + const SystemStringType element_property_type = generate_property_type_declaration(element_prop, context.inner_context()); + return std::format(SYSSTR("TSet<{}>"), element_property_type); } // TODO: This is missing support for freeze image map properties because XMapProperty is incomplete. (low priority) @@ -2644,24 +2651,24 @@ namespace RC::UEGenerator FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - const std::wstring key_type = generate_property_type_declaration(key_property, context.inner_context()); - const std::wstring value_type = generate_property_type_declaration(value_property, context.inner_context()); + const SystemStringType key_type = generate_property_type_declaration(key_property, context.inner_context()); + const SystemStringType value_type = generate_property_type_declaration(value_property, context.inner_context()); - return std::format(STR("TMap<{}, {}>"), key_type, value_type); + return std::format(SYSSTR("TMap<{}, {}>"), key_type, value_type); } // Standard properties that do not have any special attributes if (property->IsA()) { - return STR("FName"); + return SYSSTR("FName"); } else if (property->IsA()) { - return STR("FString"); + return SYSSTR("FString"); } else if (property->IsA()) { - return STR("FText"); + return SYSSTR("FText"); } throw std::runtime_error(RC::fmt("[generate_property_type_declaration] Unsupported property class '%S', full name: '%S'", field_class_name.c_str(), @@ -2669,38 +2676,38 @@ namespace RC::UEGenerator } //*/ - auto UEHeaderGenerator::generate_function_argument_flags(FProperty* property) const -> std::wstring + auto UEHeaderGenerator::generate_function_argument_flags(FProperty* property) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; auto property_flags = property->GetPropertyFlags(); // CPF_ConstParm is handled explicitly in the parameter list generator, it will generate const before parameter // if ((PropertyFlags & CPF_ConstParm) != 0) { - // FlagFormatHelper.AddSwitch(STR("Const")); + // FlagFormatHelper.AddSwitch(SYSSTR("Const")); // } // We only want to add UPARAM(Ref) when parameter is marked as reference AND output, // while not being marked as constant, because if it's marked as constant, it might be a parameter passed by const reference if ((property_flags & CPF_ReferenceParm) != 0 && (property_flags & CPF_OutParm) != 0 && (property_flags & CPF_ConstParm) == 0) { - flag_format_helper.add_switch(STR("Ref")); + flag_format_helper.add_switch(SYSSTR("Ref")); } if ((property_flags & CPF_RepSkip) != 0) { - flag_format_helper.add_switch(STR("NotReplicated")); + flag_format_helper.add_switch(SYSSTR("NotReplicated")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_property_flags(FProperty* property) const -> std::wstring + auto UEHeaderGenerator::generate_property_flags(FProperty* property) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; auto property_flags = property->GetPropertyFlags(); if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(STR("EditAnywhere")); + flag_format_helper.add_switch(SYSSTR("EditAnywhere")); } else if ((property_flags & CPF_Edit) != 0) { @@ -2708,97 +2715,97 @@ namespace RC::UEGenerator { if ((property_flags & CPF_DisableEditOnTemplate) != 0) { - flag_format_helper.add_switch(STR("VisibleInstanceOnly")); + flag_format_helper.add_switch(SYSSTR("VisibleInstanceOnly")); } else if ((property_flags & CPF_DisableEditOnInstance) != 0) { - flag_format_helper.add_switch(STR("VisibleDefaultsOnly")); + flag_format_helper.add_switch(SYSSTR("VisibleDefaultsOnly")); } else { - flag_format_helper.add_switch(STR("VisibleAnywhere")); + flag_format_helper.add_switch(SYSSTR("VisibleAnywhere")); } } else { if ((property_flags & CPF_DisableEditOnTemplate) != 0) { - flag_format_helper.add_switch(STR("EditInstanceOnly")); + flag_format_helper.add_switch(SYSSTR("EditInstanceOnly")); } else if ((property_flags & CPF_DisableEditOnInstance) != 0) { - flag_format_helper.add_switch(STR("EditDefaultsOnly")); + flag_format_helper.add_switch(SYSSTR("EditDefaultsOnly")); } else { - flag_format_helper.add_switch(STR("EditAnywhere")); + flag_format_helper.add_switch(SYSSTR("EditAnywhere")); } } } if ((property_flags & CPF_NoClear) != 0) { - flag_format_helper.add_switch(STR("NoClear")); + flag_format_helper.add_switch(SYSSTR("NoClear")); } if ((property_flags & CPF_EditFixedSize) != 0) { - flag_format_helper.add_switch(STR("EditFixedSize")); + flag_format_helper.add_switch(SYSSTR("EditFixedSize")); } if ((property_flags & CPF_SimpleDisplay) != 0) { - flag_format_helper.add_switch(STR("SimpleDisplay")); + flag_format_helper.add_switch(SYSSTR("SimpleDisplay")); } if ((property_flags & CPF_AdvancedDisplay) != 0) { - flag_format_helper.add_switch(STR("AdvancedDisplay")); + flag_format_helper.add_switch(SYSSTR("AdvancedDisplay")); } if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { if (property->GetArrayDim() == 1 && is_subtype_valid(property)) { - flag_format_helper.add_switch(STR("BlueprintReadWrite")); + flag_format_helper.add_switch(SYSSTR("BlueprintReadWrite")); } - flag_format_helper.get_meta()->add_parameter(STR("AllowPrivateAccess"), STR("true")); + flag_format_helper.get_meta()->add_parameter(SYSSTR("AllowPrivateAccess"), SYSSTR("true")); } else if ((property_flags & CPF_BlueprintVisible) != 0) { if ((property_flags & CPF_BlueprintReadOnly) != 0) { - flag_format_helper.add_switch(STR("BlueprintReadOnly")); + flag_format_helper.add_switch(SYSSTR("BlueprintReadOnly")); } else { - flag_format_helper.add_switch(STR("BlueprintReadWrite")); + flag_format_helper.add_switch(SYSSTR("BlueprintReadWrite")); } if ((property_flags & CPF_NativeAccessSpecifierPrivate) != 0) { - flag_format_helper.get_meta()->add_parameter(STR("AllowPrivateAccess"), STR("true")); + flag_format_helper.get_meta()->add_parameter(SYSSTR("AllowPrivateAccess"), SYSSTR("true")); } } if ((property_flags & CPF_BlueprintAssignable) != 0) { - flag_format_helper.add_switch(STR("BlueprintAssignable")); + flag_format_helper.add_switch(SYSSTR("BlueprintAssignable")); } if ((property_flags & CPF_BlueprintCallable) != 0) { - flag_format_helper.add_switch(STR("BlueprintCallable")); + flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); } if ((property_flags & CPF_BlueprintAuthorityOnly) != 0) { - flag_format_helper.add_switch(STR("BlueprintAuthorityOnly")); + flag_format_helper.add_switch(SYSSTR("BlueprintAuthorityOnly")); } if ((property_flags & CPF_Config) != 0) { if ((property_flags & CPF_GlobalConfig) != 0) { - flag_format_helper.add_switch(STR("GlobalConfig")); + flag_format_helper.add_switch(SYSSTR("GlobalConfig")); } else { - flag_format_helper.add_switch(STR("Config")); + flag_format_helper.add_switch(SYSSTR("Config")); } } @@ -2806,55 +2813,55 @@ namespace RC::UEGenerator { if ((property_flags & CPF_RepNotify) != 0) { - const std::wstring rep_notify_func_name = property->GetRepNotifyFunc().ToString(); - flag_format_helper.add_parameter(STR("ReplicatedUsing"), rep_notify_func_name); + const SystemStringType rep_notify_func_name = UEStringToSystemString(property->GetRepNotifyFunc().ToString()); + flag_format_helper.add_parameter(SYSSTR("ReplicatedUsing"), rep_notify_func_name); } else { - flag_format_helper.add_switch(STR("Replicated")); + flag_format_helper.add_switch(SYSSTR("Replicated")); } } if ((property_flags & CPF_RepSkip) != 0) { - flag_format_helper.add_switch(STR("NotReplicated")); + flag_format_helper.add_switch(SYSSTR("NotReplicated")); } if ((property_flags & CPF_AssetRegistrySearchable) != 0) { - flag_format_helper.add_switch(STR("AssetRegistrySearchable")); + flag_format_helper.add_switch(SYSSTR("AssetRegistrySearchable")); } if ((property_flags & CPF_Interp) != 0) { - flag_format_helper.add_switch(STR("Interp")); + flag_format_helper.add_switch(SYSSTR("Interp")); } if ((property_flags & CPF_SaveGame) != 0) { - flag_format_helper.add_switch(STR("SaveGame")); + flag_format_helper.add_switch(SYSSTR("SaveGame")); } if ((property_flags & CPF_NonTransactional) != 0) { - flag_format_helper.add_switch(STR("NonTransactional")); + flag_format_helper.add_switch(SYSSTR("NonTransactional")); } if ((property_flags & CPF_Transient) != 0) { - flag_format_helper.add_switch(STR("Transient")); + flag_format_helper.add_switch(SYSSTR("Transient")); } if ((property_flags & CPF_DuplicateTransient) != 0) { - flag_format_helper.add_switch(STR("DuplicateTransient")); + flag_format_helper.add_switch(SYSSTR("DuplicateTransient")); } if ((property_flags & CPF_TextExportTransient) != 0) { - flag_format_helper.add_switch(STR("TextExportTransient")); + flag_format_helper.add_switch(SYSSTR("TextExportTransient")); } if ((property_flags & CPF_NonPIEDuplicateTransient) != 0) { - flag_format_helper.add_switch(STR("NonPIEDuplicateTransient")); + flag_format_helper.add_switch(SYSSTR("NonPIEDuplicateTransient")); } if ((property_flags & CPF_SkipSerialization) != 0) { - flag_format_helper.add_switch(STR("SkipSerialization")); + flag_format_helper.add_switch(SYSSTR("SkipSerialization")); } // Need to have all of these flags, otherwise we might accidentally get Instanced of delegate properties; CPF_ExportObject is not set for delegate properties @@ -2867,16 +2874,16 @@ namespace RC::UEGenerator (property->IsA() || (property->IsA() && static_cast(property)->GetInner()->IsA()) || (property->IsA() && static_cast(property)->GetValueProp()->IsA()))) { - flag_format_helper.add_switch(STR("Instanced")); + flag_format_helper.add_switch(SYSSTR("Instanced")); } else if ((property_flags & CPF_ExportObject) != 0) { - flag_format_helper.add_switch(STR("Export")); + flag_format_helper.add_switch(SYSSTR("Export")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_struct_flags(UScriptStruct* script_struct) const -> std::wstring + auto UEHeaderGenerator::generate_struct_flags(UScriptStruct* script_struct) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2886,29 +2893,29 @@ namespace RC::UEGenerator EStructFlags struct_own_flags = (EStructFlags)(struct_flags & (~(parent_struct_flags & STRUCT_Inherit))); - const std::wstring native_struct_name = get_native_struct_name(script_struct); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); if (is_struct_blueprint_type(script_struct) || m_blueprint_visible_structs.contains(native_struct_name) || UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } if ((struct_own_flags & STRUCT_NoExport) != 0) { - flag_format_helper.add_switch(STR("NoExport")); + flag_format_helper.add_switch(SYSSTR("NoExport")); } if ((struct_own_flags & STRUCT_Atomic) != 0) { - flag_format_helper.add_switch(STR("Atomic")); + flag_format_helper.add_switch(SYSSTR("Atomic")); } if ((struct_own_flags & STRUCT_Immutable) != 0) { - flag_format_helper.add_switch(STR("Immutable")); + flag_format_helper.add_switch(SYSSTR("Immutable")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_enum_flags(UEnum* uenum) const -> std::wstring + auto UEHeaderGenerator::generate_enum_flags(UEnum* uenum) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2917,9 +2924,9 @@ namespace RC::UEGenerator if ((((int32_t)enum_flags) & ((int32_t)EEnumFlags::Flags)) != 0) { - flag_format_helper.add_switch(STR("Flags")); + flag_format_helper.add_switch(SYSSTR("Flags")); } - const std::wstring enum_native_name = get_native_enum_name(uenum); + const SystemStringType enum_native_name = get_native_enum_name(uenum); if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeEnumClassesBlueprintType) { @@ -2927,30 +2934,30 @@ namespace RC::UEGenerator if (cpp_form == UEnum::ECppForm::EnumClass) { const auto underlying_type = m_underlying_enum_types.find(enum_native_name); - if (underlying_type->second == STR("uint8") || + if (underlying_type->second == SYSSTR("uint8") || (underlying_type == m_underlying_enum_types.end() && (get_highest_enum(uenum) <= 255 && get_lowest_enum(uenum) >= 0))) { // Underlying type is implicit or explicitly uint8. - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } } else { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::sanitize_enumeration_name(const std::wstring& enumeration_name) -> std::wstring + auto UEHeaderGenerator::sanitize_enumeration_name(const SystemStringType& enumeration_name) -> SystemStringType { - std::wstring result_enum_name = enumeration_name; + SystemStringType result_enum_name = enumeration_name; // Remove enumeration name from the string - size_t enum_name_string_split = enumeration_name.find(STR("::")); - if (enum_name_string_split != std::wstring::npos) + size_t enum_name_string_split = enumeration_name.find(SYSSTR("::")); + if (enum_name_string_split != SystemStringType::npos) { result_enum_name.erase(0, enum_name_string_split + 2); } @@ -2965,15 +2972,15 @@ namespace RC::UEGenerator } int64 highest_enum_value = 0; - const StringType enum_prefix = uenum->GenerateEnumPrefix(); - const StringType expected_max_name = std::format(STR("{}_MAX"), enum_prefix); - StringType expected_max_name_lower = expected_max_name; + const SystemStringType enum_prefix = UEStringToSystemString(uenum->GenerateEnumPrefix()); + const SystemStringType expected_max_name = std::format(SYSSTR("{}_MAX"), enum_prefix); + SystemStringType expected_max_name_lower = expected_max_name; std::transform(expected_max_name_lower.begin(), expected_max_name_lower.end(), expected_max_name_lower.begin(), ::towlower); for (auto [Name, Value] : uenum->ForEachName()) { - StringType enum_name = sanitize_enumeration_name(Name.ToString()); - StringType enum_name_lower = enum_name; + SystemStringType enum_name = sanitize_enumeration_name(UEStringToSystemString(Name.ToString())); + SystemStringType enum_name_lower = enum_name; std::transform(enum_name_lower.begin(), enum_name_lower.end(), enum_name_lower.begin(), ::towlower); if ((enum_name_lower != expected_max_name_lower && enum_name_lower != sanitize_enumeration_name(expected_max_name_lower)) && Value > highest_enum_value) { @@ -3001,7 +3008,7 @@ namespace RC::UEGenerator return lowest_enum_value; } - auto UEHeaderGenerator::generate_function_flags(UFunction* function, bool is_function_pure_virtual) const -> std::wstring + auto UEHeaderGenerator::generate_function_flags(UFunction* function, bool is_function_pure_virtual) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -3022,7 +3029,7 @@ namespace RC::UEGenerator // Interface functions cannot be BlueprintPure if ((function_flags & FUNC_BlueprintPure) != 0 && !is_interface_function) { - flag_format_helper.add_switch(STR("BlueprintPure")); + flag_format_helper.add_switch(SYSSTR("BlueprintPure")); } else { @@ -3030,9 +3037,9 @@ namespace RC::UEGenerator // it has been explicitly marked as blueprint impure, and we need to preserve this behavior if ((function_flags & FUNC_Const) != 0 && !is_interface_function) { - flag_format_helper.add_parameter(STR("BlueprintPure"), STR("false")); + flag_format_helper.add_parameter(SYSSTR("BlueprintPure"), SYSSTR("false")); } - flag_format_helper.add_switch(STR("BlueprintCallable")); + flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); blueprint_callable_added = true; } } @@ -3050,7 +3057,7 @@ namespace RC::UEGenerator if (!has_invalid_param) { - flag_format_helper.add_switch(STR("BlueprintCallable")); + flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); } } @@ -3058,11 +3065,11 @@ namespace RC::UEGenerator { if ((function_flags & FUNC_Native) != 0) { - flag_format_helper.add_switch(STR("BlueprintNativeEvent")); + flag_format_helper.add_switch(SYSSTR("BlueprintNativeEvent")); } else { - flag_format_helper.add_switch(STR("BlueprintImplementableEvent")); + flag_format_helper.add_switch(SYSSTR("BlueprintImplementableEvent")); } } @@ -3070,50 +3077,50 @@ namespace RC::UEGenerator { if ((function_flags & FUNC_NetServer) != 0) { - flag_format_helper.add_switch(STR("Server")); + flag_format_helper.add_switch(SYSSTR("Server")); } else if ((function_flags & FUNC_NetClient) != 0) { - flag_format_helper.add_switch(STR("Client")); + flag_format_helper.add_switch(SYSSTR("Client")); } else if ((function_flags & FUNC_NetMulticast) != 0) { - flag_format_helper.add_switch(STR("NetMulticast")); + flag_format_helper.add_switch(SYSSTR("NetMulticast")); } else if ((function_flags & FUNC_NetRequest) != 0) { - flag_format_helper.add_switch(STR("ServiceRequest")); + flag_format_helper.add_switch(SYSSTR("ServiceRequest")); } else if ((function_flags & FUNC_NetResponse) != 0) { - flag_format_helper.add_switch(STR("ServiceResponse")); + flag_format_helper.add_switch(SYSSTR("ServiceResponse")); } if ((function_flags & FUNC_NetReliable) != 0) { - flag_format_helper.add_switch(STR("Reliable")); + flag_format_helper.add_switch(SYSSTR("Reliable")); } else { - flag_format_helper.add_switch(STR("Unreliable")); + flag_format_helper.add_switch(SYSSTR("Unreliable")); } if ((function_flags & FUNC_NetValidate) != 0) { - flag_format_helper.add_switch(STR("WithValidation")); + flag_format_helper.add_switch(SYSSTR("WithValidation")); } } if ((function_flags & FUNC_Exec) != 0) { - flag_format_helper.add_switch(STR("Exec")); + flag_format_helper.add_switch(SYSSTR("Exec")); } if ((function_flags & FUNC_BlueprintAuthorityOnly) != 0) { - flag_format_helper.add_switch(STR("BlueprintAuthorityOnly")); + flag_format_helper.add_switch(SYSSTR("BlueprintAuthorityOnly")); } if ((function_flags & FUNC_BlueprintCosmetic) != 0) { - flag_format_helper.add_switch(STR("BlueprintCosmetic")); + flag_format_helper.add_switch(SYSSTR("BlueprintCosmetic")); } static auto latent_action_info = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.LatentActionInfo")); @@ -3121,11 +3128,11 @@ namespace RC::UEGenerator bool bLAFound = false; for (FProperty* param : function->ForEachProperty()) { - auto param_name = param->GetName(); + auto param_name = UEStringToSystemString(param->GetName()); auto param_uc_name = string_to_uppercase(param_name); - if (param_uc_name.find(STR("WORLDCONTEXT")) != param_uc_name.npos) + if (param_uc_name.find(SYSSTR("WORLDCONTEXT")) != param_uc_name.npos) { - flag_format_helper.get_meta()->add_parameter(STR("WorldContext"), std::format(STR("\"{}\""), param_name)); + flag_format_helper.get_meta()->add_parameter(SYSSTR("WorldContext"), std::format(SYSSTR("\"{}\""), param_name)); bWCFound = true; } if (auto as_struct_property = CastField(param); as_struct_property) @@ -3133,8 +3140,8 @@ namespace RC::UEGenerator // We now know this is a StructProperty. if (as_struct_property->GetStruct()->IsChildOf(latent_action_info)) { - flag_format_helper.get_meta()->add_parameter(STR("LatentInfo"), std::format(STR("\"{}\""), param_name)); - flag_format_helper.get_meta()->add_switch(STR("Latent")); + flag_format_helper.get_meta()->add_parameter(SYSSTR("LatentInfo"), std::format(SYSSTR("\"{}\""), param_name)); + flag_format_helper.get_meta()->add_switch(SYSSTR("Latent")); bLAFound = true; } } @@ -3151,28 +3158,28 @@ namespace RC::UEGenerator UFunction* function, GeneratedSourceFile& header_data, bool generate_comma_before_name, - const std::wstring& context_name, + const SystemStringType& context_name, const CaseInsensitiveSet& blacklisted_property_names, - int32_t* out_num_params) -> std::wstring + int32_t* out_num_params) -> SystemStringType { - std::wstring function_arguments_string; + SystemStringType function_arguments_string; for (FProperty* property : function->ForEachProperty()) { auto property_flags = property->GetPropertyFlags(); if ((property_flags & CPF_Parm) != 0 && (property_flags & CPF_ReturnParm) == 0) { - std::wstring param_declaration; + SystemStringType param_declaration; // We only generate UPARAM declarations if we are not generating the implementation file if (!header_data.is_implementation_file()) { - const std::wstring parameter_flags_string = generate_function_argument_flags(property); + const SystemStringType parameter_flags_string = generate_function_argument_flags(property); if (!parameter_flags_string.empty()) { - param_declaration.append(STR("UPARAM(")); + param_declaration.append(SYSSTR("UPARAM(")); param_declaration.append(parameter_flags_string); - param_declaration.append(STR(") ")); + param_declaration.append(SYSSTR(") ")); } } @@ -3184,7 +3191,7 @@ namespace RC::UEGenerator // Append const keyword to the parameter declaration if it is marked as const parameter if ((property_flags & CPF_ConstParm) != 0 || should_force_const_ref) { - param_declaration.append(STR("const ")); + param_declaration.append(SYSSTR("const ")); } PropertyTypeDeclarationContext context(context_name, &header_data); @@ -3194,27 +3201,27 @@ namespace RC::UEGenerator // which would also be always set for output parameters if ((property_flags & (CPF_ReferenceParm | CPF_OutParm)) != 0 || should_force_const_ref) { - param_declaration.append(STR("&")); + param_declaration.append(SYSSTR("&")); } if (generate_comma_before_name) { - param_declaration.append(STR(",")); + param_declaration.append(SYSSTR(",")); } - param_declaration.append(STR(" ")); + param_declaration.append(SYSSTR(" ")); - std::wstring property_name = property->GetName(); + SystemStringType property_name = UEStringToSystemString(property->GetName()); // If property name is blacklisted, capitalize first letter and prepend New if ((uclass && is_function_parameter_shadowing(uclass, property)) || blacklisted_property_names.contains(property_name)) { property_name[0] = towupper(property_name[0]); - property_name.insert(0, STR("New")); + property_name.insert(0, SYSSTR("New")); } param_declaration.append(property_name); function_arguments_string.append(param_declaration); - function_arguments_string.append(STR(", ")); + function_arguments_string.append(SYSSTR(", ")); if (out_num_params) { (*out_num_params)++; @@ -3230,13 +3237,13 @@ namespace RC::UEGenerator return function_arguments_string; } - auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const std::wstring& ContextName) -> std::wstring + auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType { - const std::wstring field_class_name = property->GetClass().GetName(); + const SystemStringType field_class_name = UEStringToSystemString(property->GetClass().GetName()); PropertyTypeDeclarationContext context(ContextName, &header_data); // Byte Property - if (field_class_name == STR("ByteProperty")) + if (field_class_name == SYSSTR("ByteProperty")) { FByteProperty* byte_property = static_cast(property); UEnum* Enum = byte_property->GetEnum(); @@ -3246,11 +3253,11 @@ namespace RC::UEGenerator const int64_t first_enum_constant_value = Enum->GetEnumNameByIndex(0).Value; return generate_enum_value(Enum, first_enum_constant_value); } - return STR("0"); + return SYSSTR("0"); } // Enum Property - if (field_class_name == STR("EnumProperty")) + if (field_class_name == SYSSTR("EnumProperty")) { FEnumProperty* enum_property = static_cast(property); UEnum* uenum = enum_property->GetEnum(); @@ -3264,42 +3271,42 @@ namespace RC::UEGenerator } // Bool Property - if (field_class_name == STR("BoolProperty")) + if (field_class_name == SYSSTR("BoolProperty")) { - return STR("false"); + return SYSSTR("false"); } // Standard Numeric Properties - if (field_class_name == STR("Int8Property") || field_class_name == STR("Int16Property") || field_class_name == STR("IntProperty") || - field_class_name == STR("Int64Property") || field_class_name == STR("UInt16Property") || field_class_name == STR("UInt32Property") || - field_class_name == STR("UInt64Property")) + if (field_class_name == SYSSTR("Int8Property") || field_class_name == SYSSTR("Int16Property") || field_class_name == SYSSTR("IntProperty") || + field_class_name == SYSSTR("Int64Property") || field_class_name == SYSSTR("UInt16Property") || field_class_name == SYSSTR("UInt32Property") || + field_class_name == SYSSTR("UInt64Property")) { - return STR("0"); + return SYSSTR("0"); } - if (field_class_name == STR("FloatProperty")) + if (field_class_name == SYSSTR("FloatProperty")) { - return STR("0.0f"); + return SYSSTR("0.0f"); } - if (field_class_name == STR("DoubleProperty")) + if (field_class_name == SYSSTR("DoubleProperty")) { - return STR("0.0"); + return SYSSTR("0.0"); } // Object Properties - if (field_class_name == STR("ObjectProperty") || field_class_name == STR("WeakObjectProperty") || field_class_name == STR("LazyObjectProperty") || - field_class_name == STR("SoftObjectProperty") || field_class_name == STR("AssetObjectProperty") || property->IsA()) + if (field_class_name == SYSSTR("ObjectProperty") || field_class_name == SYSSTR("WeakObjectProperty") || field_class_name == SYSSTR("LazyObjectProperty") || + field_class_name == SYSSTR("SoftObjectProperty") || field_class_name == SYSSTR("AssetObjectProperty") || property->IsA()) { - return STR("NULL"); + return SYSSTR("NULL"); } // Class Properties - if (field_class_name == STR("ClassProperty") || field_class_name == STR("SoftClassProperty") || field_class_name == STR("InterfaceProperty") || - field_class_name == STR("AssetClassProperty") || property->IsA()) + if (field_class_name == SYSSTR("ClassProperty") || field_class_name == SYSSTR("SoftClassProperty") || field_class_name == SYSSTR("InterfaceProperty") || + field_class_name == SYSSTR("AssetClassProperty") || property->IsA()) { - return STR("NULL"); + return SYSSTR("NULL"); } // Struct Property - if (field_class_name == STR("StructProperty")) + if (field_class_name == SYSSTR("StructProperty")) { FStructProperty* struct_property = static_cast(property); UScriptStruct* script_struct = struct_property->GetStruct(); @@ -3308,67 +3315,67 @@ namespace RC::UEGenerator { throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); } - const std::wstring native_struct_name = get_native_struct_name(script_struct); - return std::format(STR("{}{{}}"), native_struct_name); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); + return std::format(SYSSTR("{}{{}}"), native_struct_name); } // Delegate Properties - if (field_class_name == STR("DelegateProperty") || field_class_name == STR("MulticastInlineDelegateProperty") || - field_class_name == STR("MulticastSparseDelegateProperty")) + if (field_class_name == SYSSTR("DelegateProperty") || field_class_name == SYSSTR("MulticastInlineDelegateProperty") || + field_class_name == SYSSTR("MulticastSparseDelegateProperty")) { - const std::wstring delegate_type_name = generate_delegate_name(property, context.context_name); - return std::format(STR("{}()"), delegate_type_name); + const SystemStringType delegate_type_name = generate_delegate_name(property, context.context_name); + return std::format(SYSSTR("{}()"), delegate_type_name); } // Field path property - if (field_class_name == STR("FieldPathProperty")) + if (field_class_name == SYSSTR("FieldPathProperty")) { - return STR("FFieldPath()"); + return SYSSTR("FFieldPath()"); } // Collection and Map Properties - if (field_class_name == STR("ArrayProperty")) + if (field_class_name == SYSSTR("ArrayProperty")) { FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - const std::wstring inner_property_type = generate_property_type_declaration(inner_property, context); - return std::format(STR("TArray<{}>()"), inner_property_type); + const SystemStringType inner_property_type = generate_property_type_declaration(inner_property, context); + return std::format(SYSSTR("TArray<{}>()"), inner_property_type); } - if (field_class_name == STR("SetProperty")) + if (field_class_name == SYSSTR("SetProperty")) { FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const std::wstring element_property_type = generate_property_type_declaration(element_prop, context); - return std::format(STR("TSet<{}>()"), element_property_type); + const SystemStringType element_property_type = generate_property_type_declaration(element_prop, context); + return std::format(SYSSTR("TSet<{}>()"), element_property_type); } - if (field_class_name == STR("MapProperty")) + if (field_class_name == SYSSTR("MapProperty")) { FMapProperty* map_property = static_cast(property); FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - const std::wstring key_type = generate_property_type_declaration(key_property, context); - const std::wstring value_type = generate_property_type_declaration(value_property, context); + const SystemStringType key_type = generate_property_type_declaration(key_property, context); + const SystemStringType value_type = generate_property_type_declaration(value_property, context); - return std::format(STR("TMap<{}, {}>()"), key_type, value_type); + return std::format(SYSSTR("TMap<{}, {}>()"), key_type, value_type); } // Various string, name and text properties - if (field_class_name == STR("NameProperty")) + if (field_class_name == SYSSTR("NameProperty")) { - return STR("NAME_None"); + return SYSSTR("NAME_None"); } - if (field_class_name == STR("StrProperty")) + if (field_class_name == SYSSTR("StrProperty")) { - return STR("TEXT(\"\")"); + return SYSSTR("TEXT(\"\")"); } - if (field_class_name == STR("TextProperty")) + if (field_class_name == SYSSTR("TextProperty")) { - return STR("FText::GetEmpty()"); + return SYSSTR("FText::GetEmpty()"); } throw std::runtime_error(RC::fmt("[generate_default_property_value] Unsupported property class '%S', full name: '%S'", field_class_name.c_str(), @@ -3462,18 +3469,18 @@ namespace RC::UEGenerator return is_shadowing; } - auto UEHeaderGenerator::get_module_name_for_package(UObject* package) -> std::wstring + auto UEHeaderGenerator::get_module_name_for_package(UObject* package) -> SystemStringType { if (package->GetOuterPrivate() != NULL) { throw std::invalid_argument("Encountered a package with an outer object set"); } - std::wstring package_name = package->GetName(); - if (!package_name.starts_with(STR("/Script/"))) + SystemStringType package_name = UEStringToSystemString(package->GetName()); + if (!package_name.starts_with(SYSSTR("/Script/"))) { - return STR(""); + return SYSSTR(""); } - package_name.erase(0, wcslen(STR("/Script/"))); + package_name.erase(0, SystemStringType(SYSSTR("/Script/")).length()); return package_name; } @@ -3483,22 +3490,22 @@ namespace RC::UEGenerator this->m_primary_module_name = determine_primary_game_module_name(); // Force inclusion of Core and CoreUObject into all the generated module build files - this->m_forced_module_dependencies.insert(STR("Core")); - this->m_forced_module_dependencies.insert(STR("CoreUObject")); + this->m_forced_module_dependencies.insert(SYSSTR("Core")); + this->m_forced_module_dependencies.insert(SYSSTR("CoreUObject")); // TODO not optimal, but still needed for the majority of the cases - this->m_forced_module_dependencies.insert(STR("Engine")); + this->m_forced_module_dependencies.insert(SYSSTR("Engine")); // Add few classes that require explicit UObjectInitializer constructor call, excluding classes inheriting from AActor. - this->m_classes_with_object_initializer.insert(STR("UUserWidget")); - this->m_classes_with_object_initializer.insert(STR("UListView")); - this->m_classes_with_object_initializer.insert(STR("UMovieSceneTrack")); - this->m_classes_with_object_initializer.insert(STR("USoundWaveProcedural")); - this->m_classes_with_object_initializer.insert(STR("URichTextBlock")); - this->m_classes_with_object_initializer.insert(STR("URichTextBlockImageDecorator")); - this->m_classes_with_object_initializer.insert(STR("URichTextBlockDecorator")); - this->m_classes_with_object_initializer.insert(STR("USkeletalMeshComponentBudgeted")); - this->m_classes_with_object_initializer.insert(STR("UIpNetDriver")); - this->m_classes_with_object_initializer.insert(STR("UAITask")); + this->m_classes_with_object_initializer.insert(SYSSTR("UUserWidget")); + this->m_classes_with_object_initializer.insert(SYSSTR("UListView")); + this->m_classes_with_object_initializer.insert(SYSSTR("UMovieSceneTrack")); + this->m_classes_with_object_initializer.insert(SYSSTR("USoundWaveProcedural")); + this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlock")); + this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlockImageDecorator")); + this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlockDecorator")); + this->m_classes_with_object_initializer.insert(SYSSTR("USkeletalMeshComponentBudgeted")); + this->m_classes_with_object_initializer.insert(SYSSTR("UIpNetDriver")); + this->m_classes_with_object_initializer.insert(SYSSTR("UAITask")); } auto UEHeaderGenerator::ignore_selected_modules() -> void @@ -3510,144 +3517,144 @@ namespace RC::UEGenerator if (UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreEngineAndCoreUObject || UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreAllCoreEngineModules) { - this->m_ignored_module_names.insert(STR("Engine")); - this->m_ignored_module_names.insert(STR("CoreUObject")); + this->m_ignored_module_names.insert(SYSSTR("Engine")); + this->m_ignored_module_names.insert(SYSSTR("CoreUObject")); } // Skip all core engine packages if requested if (UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreAllCoreEngineModules) { - this->m_ignored_module_names.insert(STR("ActorLayerUtilities")); - this->m_ignored_module_names.insert(STR("ActorSequence")); - this->m_ignored_module_names.insert(STR("AIModule")); - this->m_ignored_module_names.insert(STR("AndroidPermission")); - this->m_ignored_module_names.insert(STR("AnimationCore")); - this->m_ignored_module_names.insert(STR("AnimationSharing")); - this->m_ignored_module_names.insert(STR("AnimGraphRuntime")); - this->m_ignored_module_names.insert(STR("AppleImageUtils")); - this->m_ignored_module_names.insert(STR("ArchVisCharacter")); - this->m_ignored_module_names.insert(STR("AssetRegistry")); - this->m_ignored_module_names.insert(STR("AssetTags")); - this->m_ignored_module_names.insert(STR("AudioAnalyzer")); - this->m_ignored_module_names.insert(STR("AudioCapture")); - this->m_ignored_module_names.insert(STR("AudioExtensions")); - this->m_ignored_module_names.insert(STR("AudioMixer")); - this->m_ignored_module_names.insert(STR("AudioPlatformConfiguration")); - this->m_ignored_module_names.insert(STR("AudioSynesthesia")); - this->m_ignored_module_names.insert(STR("AugmentedReality")); - this->m_ignored_module_names.insert(STR("AutomationUtils")); - this->m_ignored_module_names.insert(STR("AvfMediaFactory")); - this->m_ignored_module_names.insert(STR("BuildPatchServices")); - this->m_ignored_module_names.insert(STR("CableComponent")); - this->m_ignored_module_names.insert(STR("Chaos")); - this->m_ignored_module_names.insert(STR("ChaosCloth")); - this->m_ignored_module_names.insert(STR("ChaosNiagara")); - this->m_ignored_module_names.insert(STR("ChaosSolvers")); - this->m_ignored_module_names.insert(STR("ChaosSolverEngine")); - this->m_ignored_module_names.insert(STR("CinematicCamera")); - this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeCommon")); - this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeInterface")); - this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeNv")); - this->m_ignored_module_names.insert(STR("CustomMeshComponent")); - this->m_ignored_module_names.insert(STR("DatasmithContent")); - this->m_ignored_module_names.insert(STR("DeveloperSettings")); - this->m_ignored_module_names.insert(STR("EditableMesh")); - this->m_ignored_module_names.insert(STR("EngineMessages")); - this->m_ignored_module_names.insert(STR("EngineSettings")); - this->m_ignored_module_names.insert(STR("EyeTracker")); - this->m_ignored_module_names.insert(STR("FacialAnimation")); - this->m_ignored_module_names.insert(STR("FieldSystemCore")); - this->m_ignored_module_names.insert(STR("FieldSystemEngine")); - this->m_ignored_module_names.insert(STR("Foliage")); - this->m_ignored_module_names.insert(STR("GameplayTags")); - this->m_ignored_module_names.insert(STR("GameplayTasks")); - this->m_ignored_module_names.insert(STR("GeometryCache")); - this->m_ignored_module_names.insert(STR("GeometryCacheTracks")); - this->m_ignored_module_names.insert(STR("GeometryCollectionCore")); - this->m_ignored_module_names.insert(STR("GeometryCollectionSimulationCore")); - this->m_ignored_module_names.insert(STR("GeometryCollectionEngine")); - this->m_ignored_module_names.insert(STR("GeometryCollectionTracks")); - this->m_ignored_module_names.insert(STR("GooglePAD")); - this->m_ignored_module_names.insert(STR("HeadMountedDisplay")); - this->m_ignored_module_names.insert(STR("ImageWrapper")); - this->m_ignored_module_names.insert(STR("ImageWriteQueue")); - this->m_ignored_module_names.insert(STR("ImgMedia")); - this->m_ignored_module_names.insert(STR("ImgMediaFactory")); - this->m_ignored_module_names.insert(STR("InputCore")); - this->m_ignored_module_names.insert(STR("InteractiveToolsFramework")); - this->m_ignored_module_names.insert(STR("JsonUtilities")); - this->m_ignored_module_names.insert(STR("Landscape")); - this->m_ignored_module_names.insert(STR("LevelSequence")); - this->m_ignored_module_names.insert(STR("LightPropagationVolumeRuntime")); - this->m_ignored_module_names.insert(STR("LiveLinkInterface")); - this->m_ignored_module_names.insert(STR("LocationServicesBPLibrary")); - this->m_ignored_module_names.insert(STR("LuminRuntimeSettings")); - this->m_ignored_module_names.insert(STR("MagicLeap")); - this->m_ignored_module_names.insert(STR("MagicLeapAR")); - this->m_ignored_module_names.insert(STR("MagicLeapARPin")); - this->m_ignored_module_names.insert(STR("MagicLeapAudio")); - this->m_ignored_module_names.insert(STR("MagicLeapController")); - this->m_ignored_module_names.insert(STR("MagicLeapEyeTracker")); - this->m_ignored_module_names.insert(STR("MagicLeapHandMeshing")); - this->m_ignored_module_names.insert(STR("MagicLeapHandTracking")); - this->m_ignored_module_names.insert(STR("MagicLeapIdentity")); - this->m_ignored_module_names.insert(STR("MagicLeapImageTracker")); - this->m_ignored_module_names.insert(STR("MagicLeapLightEstimation")); - this->m_ignored_module_names.insert(STR("MagicLeapPlanes")); - this->m_ignored_module_names.insert(STR("MagicLeapPrivileges")); - this->m_ignored_module_names.insert(STR("MagicLeapSecureStorage")); - this->m_ignored_module_names.insert(STR("MagicLeapSharedWorld")); - this->m_ignored_module_names.insert(STR("MaterialShaderQualitySettings")); - this->m_ignored_module_names.insert(STR("MediaAssets")); - this->m_ignored_module_names.insert(STR("MediaCompositing")); - this->m_ignored_module_names.insert(STR("MediaUtils")); - this->m_ignored_module_names.insert(STR("MeshDescription")); - this->m_ignored_module_names.insert(STR("MobilePatchingUtils")); - this->m_ignored_module_names.insert(STR("MotoSynth")); - this->m_ignored_module_names.insert(STR("MoviePlayer")); - this->m_ignored_module_names.insert(STR("MovieScene")); - this->m_ignored_module_names.insert(STR("MovieSceneCapture")); - this->m_ignored_module_names.insert(STR("MovieSceneTracks")); - this->m_ignored_module_names.insert(STR("MRMesh")); - this->m_ignored_module_names.insert(STR("NavigationSystem")); - this->m_ignored_module_names.insert(STR("NetCore")); - this->m_ignored_module_names.insert(STR("Niagara")); - this->m_ignored_module_names.insert(STR("NiagaraAnimNotifies")); - this->m_ignored_module_names.insert(STR("NiagaraCore")); - this->m_ignored_module_names.insert(STR("NiagaraShader")); - this->m_ignored_module_names.insert(STR("OculusHMD")); - this->m_ignored_module_names.insert(STR("OculusInput")); - this->m_ignored_module_names.insert(STR("OculusMR")); - this->m_ignored_module_names.insert(STR("OnlineSubsystem")); - this->m_ignored_module_names.insert(STR("OnlineSubsystemUtils")); - this->m_ignored_module_names.insert(STR("Overlay")); - this->m_ignored_module_names.insert(STR("PacketHandler")); - this->m_ignored_module_names.insert(STR("Paper2D")); - this->m_ignored_module_names.insert(STR("PhysicsCore")); - this->m_ignored_module_names.insert(STR("PhysXVehicles")); - this->m_ignored_module_names.insert(STR("ProceduralMeshComponent")); - this->m_ignored_module_names.insert(STR("PropertyAccess")); - this->m_ignored_module_names.insert(STR("PropertyPath")); - this->m_ignored_module_names.insert(STR("Renderer")); - this->m_ignored_module_names.insert(STR("Serialization")); - this->m_ignored_module_names.insert(STR("SessionMessages")); - this->m_ignored_module_names.insert(STR("SignificanceManager")); - this->m_ignored_module_names.insert(STR("Slate")); - this->m_ignored_module_names.insert(STR("SlateCore")); - this->m_ignored_module_names.insert(STR("SoundFields")); - this->m_ignored_module_names.insert(STR("StaticMeshDescription")); - this->m_ignored_module_names.insert(STR("SteamVR")); - this->m_ignored_module_names.insert(STR("SteamVRInputDevice")); - this->m_ignored_module_names.insert(STR("Synthesis")); - this->m_ignored_module_names.insert(STR("TcpMessaging")); - this->m_ignored_module_names.insert(STR("TemplateSequence")); - this->m_ignored_module_names.insert(STR("TimeManagement")); - this->m_ignored_module_names.insert(STR("UdpMessaging")); - this->m_ignored_module_names.insert(STR("UMG")); - this->m_ignored_module_names.insert(STR("UObjectPlugin")); - this->m_ignored_module_names.insert(STR("VariantManagerContent")); - this->m_ignored_module_names.insert(STR("VectorVM")); - this->m_ignored_module_names.insert(STR("WmfMediaFactory")); + this->m_ignored_module_names.insert(SYSSTR("ActorLayerUtilities")); + this->m_ignored_module_names.insert(SYSSTR("ActorSequence")); + this->m_ignored_module_names.insert(SYSSTR("AIModule")); + this->m_ignored_module_names.insert(SYSSTR("AndroidPermission")); + this->m_ignored_module_names.insert(SYSSTR("AnimationCore")); + this->m_ignored_module_names.insert(SYSSTR("AnimationSharing")); + this->m_ignored_module_names.insert(SYSSTR("AnimGraphRuntime")); + this->m_ignored_module_names.insert(SYSSTR("AppleImageUtils")); + this->m_ignored_module_names.insert(SYSSTR("ArchVisCharacter")); + this->m_ignored_module_names.insert(SYSSTR("AssetRegistry")); + this->m_ignored_module_names.insert(SYSSTR("AssetTags")); + this->m_ignored_module_names.insert(SYSSTR("AudioAnalyzer")); + this->m_ignored_module_names.insert(SYSSTR("AudioCapture")); + this->m_ignored_module_names.insert(SYSSTR("AudioExtensions")); + this->m_ignored_module_names.insert(SYSSTR("AudioMixer")); + this->m_ignored_module_names.insert(SYSSTR("AudioPlatformConfiguration")); + this->m_ignored_module_names.insert(SYSSTR("AudioSynesthesia")); + this->m_ignored_module_names.insert(SYSSTR("AugmentedReality")); + this->m_ignored_module_names.insert(SYSSTR("AutomationUtils")); + this->m_ignored_module_names.insert(SYSSTR("AvfMediaFactory")); + this->m_ignored_module_names.insert(SYSSTR("BuildPatchServices")); + this->m_ignored_module_names.insert(SYSSTR("CableComponent")); + this->m_ignored_module_names.insert(SYSSTR("Chaos")); + this->m_ignored_module_names.insert(SYSSTR("ChaosCloth")); + this->m_ignored_module_names.insert(SYSSTR("ChaosNiagara")); + this->m_ignored_module_names.insert(SYSSTR("ChaosSolvers")); + this->m_ignored_module_names.insert(SYSSTR("ChaosSolverEngine")); + this->m_ignored_module_names.insert(SYSSTR("CinematicCamera")); + this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeCommon")); + this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeInterface")); + this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeNv")); + this->m_ignored_module_names.insert(SYSSTR("CustomMeshComponent")); + this->m_ignored_module_names.insert(SYSSTR("DatasmithContent")); + this->m_ignored_module_names.insert(SYSSTR("DeveloperSettings")); + this->m_ignored_module_names.insert(SYSSTR("EditableMesh")); + this->m_ignored_module_names.insert(SYSSTR("EngineMessages")); + this->m_ignored_module_names.insert(SYSSTR("EngineSettings")); + this->m_ignored_module_names.insert(SYSSTR("EyeTracker")); + this->m_ignored_module_names.insert(SYSSTR("FacialAnimation")); + this->m_ignored_module_names.insert(SYSSTR("FieldSystemCore")); + this->m_ignored_module_names.insert(SYSSTR("FieldSystemEngine")); + this->m_ignored_module_names.insert(SYSSTR("Foliage")); + this->m_ignored_module_names.insert(SYSSTR("GameplayTags")); + this->m_ignored_module_names.insert(SYSSTR("GameplayTasks")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCache")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCacheTracks")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionCore")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionSimulationCore")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionEngine")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionTracks")); + this->m_ignored_module_names.insert(SYSSTR("GooglePAD")); + this->m_ignored_module_names.insert(SYSSTR("HeadMountedDisplay")); + this->m_ignored_module_names.insert(SYSSTR("ImageWrapper")); + this->m_ignored_module_names.insert(SYSSTR("ImageWriteQueue")); + this->m_ignored_module_names.insert(SYSSTR("ImgMedia")); + this->m_ignored_module_names.insert(SYSSTR("ImgMediaFactory")); + this->m_ignored_module_names.insert(SYSSTR("InputCore")); + this->m_ignored_module_names.insert(SYSSTR("InteractiveToolsFramework")); + this->m_ignored_module_names.insert(SYSSTR("JsonUtilities")); + this->m_ignored_module_names.insert(SYSSTR("Landscape")); + this->m_ignored_module_names.insert(SYSSTR("LevelSequence")); + this->m_ignored_module_names.insert(SYSSTR("LightPropagationVolumeRuntime")); + this->m_ignored_module_names.insert(SYSSTR("LiveLinkInterface")); + this->m_ignored_module_names.insert(SYSSTR("LocationServicesBPLibrary")); + this->m_ignored_module_names.insert(SYSSTR("LuminRuntimeSettings")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeap")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapAR")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapARPin")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapAudio")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapController")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapEyeTracker")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapHandMeshing")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapHandTracking")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapIdentity")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapImageTracker")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapLightEstimation")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapPlanes")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapPrivileges")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapSecureStorage")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapSharedWorld")); + this->m_ignored_module_names.insert(SYSSTR("MaterialShaderQualitySettings")); + this->m_ignored_module_names.insert(SYSSTR("MediaAssets")); + this->m_ignored_module_names.insert(SYSSTR("MediaCompositing")); + this->m_ignored_module_names.insert(SYSSTR("MediaUtils")); + this->m_ignored_module_names.insert(SYSSTR("MeshDescription")); + this->m_ignored_module_names.insert(SYSSTR("MobilePatchingUtils")); + this->m_ignored_module_names.insert(SYSSTR("MotoSynth")); + this->m_ignored_module_names.insert(SYSSTR("MoviePlayer")); + this->m_ignored_module_names.insert(SYSSTR("MovieScene")); + this->m_ignored_module_names.insert(SYSSTR("MovieSceneCapture")); + this->m_ignored_module_names.insert(SYSSTR("MovieSceneTracks")); + this->m_ignored_module_names.insert(SYSSTR("MRMesh")); + this->m_ignored_module_names.insert(SYSSTR("NavigationSystem")); + this->m_ignored_module_names.insert(SYSSTR("NetCore")); + this->m_ignored_module_names.insert(SYSSTR("Niagara")); + this->m_ignored_module_names.insert(SYSSTR("NiagaraAnimNotifies")); + this->m_ignored_module_names.insert(SYSSTR("NiagaraCore")); + this->m_ignored_module_names.insert(SYSSTR("NiagaraShader")); + this->m_ignored_module_names.insert(SYSSTR("OculusHMD")); + this->m_ignored_module_names.insert(SYSSTR("OculusInput")); + this->m_ignored_module_names.insert(SYSSTR("OculusMR")); + this->m_ignored_module_names.insert(SYSSTR("OnlineSubsystem")); + this->m_ignored_module_names.insert(SYSSTR("OnlineSubsystemUtils")); + this->m_ignored_module_names.insert(SYSSTR("Overlay")); + this->m_ignored_module_names.insert(SYSSTR("PacketHandler")); + this->m_ignored_module_names.insert(SYSSTR("Paper2D")); + this->m_ignored_module_names.insert(SYSSTR("PhysicsCore")); + this->m_ignored_module_names.insert(SYSSTR("PhysXVehicles")); + this->m_ignored_module_names.insert(SYSSTR("ProceduralMeshComponent")); + this->m_ignored_module_names.insert(SYSSTR("PropertyAccess")); + this->m_ignored_module_names.insert(SYSSTR("PropertyPath")); + this->m_ignored_module_names.insert(SYSSTR("Renderer")); + this->m_ignored_module_names.insert(SYSSTR("Serialization")); + this->m_ignored_module_names.insert(SYSSTR("SessionMessages")); + this->m_ignored_module_names.insert(SYSSTR("SignificanceManager")); + this->m_ignored_module_names.insert(SYSSTR("Slate")); + this->m_ignored_module_names.insert(SYSSTR("SlateCore")); + this->m_ignored_module_names.insert(SYSSTR("SoundFields")); + this->m_ignored_module_names.insert(SYSSTR("StaticMeshDescription")); + this->m_ignored_module_names.insert(SYSSTR("SteamVR")); + this->m_ignored_module_names.insert(SYSSTR("SteamVRInputDevice")); + this->m_ignored_module_names.insert(SYSSTR("Synthesis")); + this->m_ignored_module_names.insert(SYSSTR("TcpMessaging")); + this->m_ignored_module_names.insert(SYSSTR("TemplateSequence")); + this->m_ignored_module_names.insert(SYSSTR("TimeManagement")); + this->m_ignored_module_names.insert(SYSSTR("UdpMessaging")); + this->m_ignored_module_names.insert(SYSSTR("UMG")); + this->m_ignored_module_names.insert(SYSSTR("UObjectPlugin")); + this->m_ignored_module_names.insert(SYSSTR("VariantManagerContent")); + this->m_ignored_module_names.insert(SYSSTR("VectorVM")); + this->m_ignored_module_names.insert(SYSSTR("WmfMediaFactory")); } } @@ -3655,20 +3662,20 @@ namespace RC::UEGenerator { ignore_selected_modules(); - Output::send(STR("Cleaning up previously generated SDK (if one exists)\n")); + Output::send(SYSSTR("Cleaning up previously generated SDK (if one exists)\n")); if (std::filesystem::exists(m_root_directory)) { std::filesystem::remove_all(m_root_directory); } - Output::send(STR("Initializing native packages dump\n")); + Output::send(SYSSTR("Initializing native packages dump\n")); std::vector native_classes_to_dump; std::vector native_structs_to_dump; std::vector native_enums_to_dump; std::vector native_delegates_to_dump; - Output::send(STR("Gathering native objects for dumping\n")); + Output::send(SYSSTR("Gathering native objects for dumping\n")); UObjectGlobals::ForEachUObject([&](void* raw_object, int32_t chunk_index, int32_t object_index) { UObject* typed_object = static_cast(raw_object); @@ -3713,37 +3720,37 @@ namespace RC::UEGenerator return RC::LoopAction::Continue; }); - Output::send(STR("Attempting to dump {} native classes\n"), native_classes_to_dump.size()); + Output::send(SYSSTR("Attempting to dump {} native classes\n"), native_classes_to_dump.size()); for (UFunction* delegate_signature_function : native_delegates_to_dump) { - // Output::send(STR("Dumping native delegate type {}\n"), global_delegate_signature->GetName()); + // Output::send(SYSSTR("Dumping native delegate type {}\n"), global_delegate_signature->GetName()); generate_object_description_file(delegate_signature_function); } for (UClass* class_to_dump : native_classes_to_dump) { - // Output::send(STR("Dumping native class {}\n"), class_to_dump->GetName()); + // Output::send(SYSSTR("Dumping native class {}\n"), class_to_dump->GetName()); generate_object_description_file(class_to_dump); } - Output::send(STR("Attempting to dump {} native structs\n"), native_structs_to_dump.size()); + Output::send(SYSSTR("Attempting to dump {} native structs\n"), native_structs_to_dump.size()); for (UScriptStruct* struct_to_dump : native_structs_to_dump) { - // Output::send(STR("Dumping native struct {}\n"), struct_to_dump->GetName()); + // Output::send(SYSSTR("Dumping native struct {}\n"), struct_to_dump->GetName()); generate_object_description_file(struct_to_dump); } - Output::send(STR("Attempting to dump {} native enums\n"), native_enums_to_dump.size()); + Output::send(SYSSTR("Attempting to dump {} native enums\n"), native_enums_to_dump.size()); for (UEnum* enum_to_dump : native_enums_to_dump) { - // Output::send(STR("Dumping native enum {}\n"), enum_to_dump->GetName()); + // Output::send(SYSSTR("Dumping native enum {}\n"), enum_to_dump->GetName()); generate_object_description_file(enum_to_dump); } - Output::send(STR("Writing stub module build files for {} modules\n"), m_module_dependencies.size()); + Output::send(SYSSTR("Writing stub module build files for {} modules\n"), m_module_dependencies.size()); for (const auto& module_pair : m_module_dependencies) { generate_module_implementation_file(module_pair.first); @@ -3767,7 +3774,7 @@ namespace RC::UEGenerator { name = get_native_struct_name(std::bit_cast(object)); } - header_file.append_line(std::format(STR("FORCEINLINE uint32 GetTypeHash(const {}) {{ return 0; }}"), name)); + header_file.append_line(std::format(SYSSTR("FORCEINLINE uint32 GetTypeHash(const {}) {{ return 0; }}"), name)); } // Case for FTickFunction struct @@ -3777,32 +3784,32 @@ namespace RC::UEGenerator auto super_struct = struct_object->GetSuperScriptStruct(); if (super_struct) { - if (get_native_struct_name(super_struct) == STR("FTickFunction")) + if (get_native_struct_name(super_struct) == SYSSTR("FTickFunction")) { File::StringType name{}; name = get_native_struct_name(struct_object); - header_file.append_line(STR("")); - header_file.append_line(STR("template<>")); - header_file.append_line(std::format(STR("struct TStructOpsTypeTraits<{}> : public TStructOpsTypeTraitsBase2<{}>"), name, name)); - header_file.append_line(STR("{")); - header_file.append_line(STR(" enum")); - header_file.append_line(STR(" {")); - header_file.append_line(STR(" WithCopy = false")); - header_file.append_line(STR(" };")); - header_file.append_line(STR("};")); + header_file.append_line(SYSSTR("")); + header_file.append_line(SYSSTR("template<>")); + header_file.append_line(std::format(SYSSTR("struct TStructOpsTypeTraits<{}> : public TStructOpsTypeTraitsBase2<{}>"), name, name)); + header_file.append_line(SYSSTR("{")); + header_file.append_line(SYSSTR(" enum")); + header_file.append_line(SYSSTR(" {")); + header_file.append_line(SYSSTR(" WithCopy = false")); + header_file.append_line(SYSSTR(" };")); + header_file.append_line(SYSSTR("};")); } } } header_file.serialize_file_content_to_disk(); } - Output::send(STR("Done!\n")); + Output::send(SYSSTR("Done!\n")); } auto UEHeaderGenerator::generate_object_description_file(UObject* object) -> bool { - const std::wstring module_name = get_module_name_for_package(object->GetOutermost()); - const std::wstring file_base_name = get_header_name_for_object(object); + const SystemStringType module_name = get_module_name_for_package(object->GetOutermost()); + const SystemStringType file_base_name = get_header_name_for_object(object); if (module_name.empty()) { @@ -3860,7 +3867,7 @@ namespace RC::UEGenerator auto iterator = this->m_module_dependencies.find(module_name); if (iterator == this->m_module_dependencies.end()) { - iterator = this->m_module_dependencies.insert({module_name, std::make_shared>()}).first; + iterator = this->m_module_dependencies.insert({module_name, std::make_shared>()}).first; } if (!header_file.has_content_to_save()) @@ -3875,16 +3882,16 @@ namespace RC::UEGenerator header_file.generate_file_contents(); // Record module names used in the headers - std::shared_ptr> out_dependency_module_names = iterator->second; + std::shared_ptr> out_dependency_module_names = iterator->second; header_file.copy_dependency_module_names(*out_dependency_module_names); implementation_file.copy_dependency_module_names(*out_dependency_module_names); return true; } - auto UEHeaderGenerator::generate_object_pre_declaration(UObject* object) -> std::vector> + auto UEHeaderGenerator::generate_object_pre_declaration(UObject* object) -> std::vector> { - std::vector> pre_declarations; + std::vector> pre_declarations; UClass* object_class = object->GetClassPrivate(); @@ -3894,15 +3901,15 @@ namespace RC::UEGenerator if (uclass->IsChildOf(UInterface::StaticClass())) { - pre_declarations.push_back({STR("class "), get_native_class_name(uclass, true), STR(";\n")}); + pre_declarations.push_back({SYSSTR("class "), get_native_class_name(uclass, true), SYSSTR(";\n")}); } - pre_declarations.push_back({STR("class "), get_native_class_name(uclass, false), STR(";\n")}); + pre_declarations.push_back({SYSSTR("class "), get_native_class_name(uclass, false), SYSSTR(";\n")}); } else if (object_class->IsChildOf(UScriptStruct::StaticClass())) { UScriptStruct* script_struct = static_cast(object); - pre_declarations.push_back({STR("struct "), get_native_struct_name(script_struct), STR(";\n")}); + pre_declarations.push_back({SYSSTR("struct "), get_native_struct_name(script_struct), SYSSTR(";\n")}); } else if (object_class->IsChildOf(UEnum::StaticClass())) { @@ -3917,7 +3924,7 @@ namespace RC::UEGenerator return pre_declarations; } - auto UEHeaderGenerator::get_header_name_for_object(UObject* object, bool get_existing_header) -> std::wstring + auto UEHeaderGenerator::get_header_name_for_object(UObject* object, bool get_existing_header) -> SystemStringType { File::StringType header_name{}; UObject* final_object{}; @@ -3925,14 +3932,14 @@ namespace RC::UEGenerator if (object->IsA() || object->IsA()) { // Class and struct headers follow the relevant object name - header_name = object->GetName(); + header_name = UEStringToSystemString(object->GetName()); final_object = object; } else if (object->IsA()) { // Enumeration usually have the E prefix which will be present in the header names // We do not strip it because there are some broken headers that do not follow that convention (e.g. funny Wwise) - header_name = object->GetName(); + header_name = UEStringToSystemString(object->GetName()); final_object = object; } else @@ -3952,8 +3959,8 @@ namespace RC::UEGenerator { // Otherwise, remove the postfix and use the function name as the header name // Also append the delegate postfix because apparently there can be conflicts - std::wstring DelegateName = strip_delegate_signature_postfix(signature_function); - DelegateName.append(STR("Delegate")); + SystemStringType DelegateName = strip_delegate_signature_postfix(signature_function); + DelegateName.append(SYSSTR("Delegate")); header_name = DelegateName; final_object = object; } @@ -3970,14 +3977,14 @@ namespace RC::UEGenerator { if (auto it2 = m_dependency_object_to_unique_id.find(final_object); it2 != m_dependency_object_to_unique_id.end()) { - header_name.append(std::format(STR("{}"), it2->second)); + header_name.append(std::format(SYSSTR("{}"), it2->second)); } } else { if (auto it = m_used_file_names.find(header_name); it != m_used_file_names.end()) { - header_name.append(std::format(STR("{}"), ++it->second.usable_id)); + header_name.append(std::format(SYSSTR("{}"), ++it->second.usable_id)); m_dependency_object_to_unique_id.emplace(final_object, it->second.usable_id); } else @@ -3994,26 +4001,29 @@ namespace RC::UEGenerator generate_delegate_type_declaration(signature_function, delegate_class, header_data); } - auto UEHeaderGenerator::determine_primary_game_module_name() -> std::wstring + auto UEHeaderGenerator::determine_primary_game_module_name() -> SystemStringType { + /* HMODULE primary_executable_module = GetModuleHandleW(NULL); wchar_t module_name_buffer[1024]{'\0'}; GetModuleFileNameW(primary_executable_module, module_name_buffer, ARRAYSIZE(module_name_buffer)); // Retrieve the filename from the full path, strip down the extension - FFilePath root_executable_path((std::wstring(module_name_buffer))); - std::wstring filename = root_executable_path.filename().replace_extension().wstring(); + FFilePath root_executable_path((SystemStringType(module_name_buffer))); + SystemStringType filename = root_executable_path.filename().replace_extension().wstring(); // Remove the shipping file postfix - std::wstring shipping_postfix = STR("-Win64-Shipping"); + SystemStringType shipping_postfix = SYSSTR("-Win64-Shipping"); if (filename.ends_with(shipping_postfix)) { filename.erase(filename.length() - shipping_postfix.length()); } return filename; + */ + return "Main"; } - auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const std::wstring& module_name, const std::wstring& fallback_name) -> std::wstring + auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) -> SystemStringType { // Retrieve the most top level object located inside the native package UObject* top_level_object = object; @@ -4023,31 +4033,31 @@ namespace RC::UEGenerator top_level_object = top_level_object->GetOuterPrivate(); } - const std::wstring object_name = top_level_object->GetName(); - return std::format(STR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), module_name, object_name, fallback_name); + const SystemStringType object_name = UEStringToSystemString(top_level_object->GetName()); + return std::format(SYSSTR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), module_name, object_name, fallback_name); } GeneratedFile::GeneratedFile(const FFilePath& full_file_path) { this->m_full_file_path = full_file_path; - this->m_file_base_name = full_file_path.filename().replace_extension().wstring(); + this->m_file_base_name = full_file_path.filename().replace_extension().generic_string(); this->m_current_indent_count = 0; } - auto GeneratedFile::append_line(const std::wstring& line) -> void + auto GeneratedFile::append_line(const SystemStringType& line) -> void { for (int32_t i = 0; i < m_current_indent_count; i++) { - m_file_contents_buffer.append(STR(" ")); + m_file_contents_buffer.append(SYSSTR(" ")); } m_file_contents_buffer.append(line); - m_file_contents_buffer.append(STR("\n")); + m_file_contents_buffer.append(SYSSTR("\n")); } - auto GeneratedFile::append_line_no_indent(const std::wstring& line) -> void + auto GeneratedFile::append_line_no_indent(const SystemStringType& line) -> void { m_file_contents_buffer.append(line); - m_file_contents_buffer.append(STR("\n")); + m_file_contents_buffer.append(SYSSTR("\n")); } auto GeneratedFile::begin_indent_level() -> void @@ -4073,18 +4083,19 @@ namespace RC::UEGenerator // TODO might be slow, maybe move it out into the header generator? std::filesystem::create_directories(this->m_full_file_path.parent_path()); - std::wofstream file_output_stream; + SystemStreamType file_output_stream; file_output_stream.open(m_full_file_path); if (!file_output_stream.is_open()) { throw std::invalid_argument("Failed to open the header file"); } - file_output_stream << generate_file_contents(); + // TODO: FIX STREAM +// file_output_stream << generate_file_contents().c_str(); file_output_stream.close(); return true; } - auto GeneratedFile::generate_file_contents() -> std::wstring + auto GeneratedFile::generate_file_contents() -> SystemStringType { return m_file_contents_buffer; } @@ -4095,24 +4106,24 @@ namespace RC::UEGenerator } auto GeneratedSourceFile::create_source_file(const FFilePath& root_dir, - const std::wstring& module_name, - const std::wstring& base_name, + const SystemStringType& module_name, + const SystemStringType& base_name, bool is_implementation_file, UObject* object) -> GeneratedSourceFile { FFilePath full_file_path; if (is_implementation_file) { - full_file_path = root_dir / module_name / STR("Private") / (base_name + STR(".cpp")); + full_file_path = root_dir / module_name / SYSSTR("Private") / (base_name + SYSSTR(".cpp")); } else { - full_file_path = root_dir / module_name / STR("Public") / (base_name + STR(".h")); + full_file_path = root_dir / module_name / SYSSTR("Public") / (base_name + SYSSTR(".h")); } return GeneratedSourceFile(full_file_path, module_name, is_implementation_file, object); } - GeneratedSourceFile::GeneratedSourceFile(const FFilePath& file_path, const std::wstring& file_module_name, bool is_implementation_file, UObject* object) + GeneratedSourceFile::GeneratedSourceFile(const FFilePath& file_path, const SystemStringType& file_module_name, bool is_implementation_file, UObject* object) : GeneratedFile(file_path) { this->m_file_module_name = file_module_name; @@ -4125,7 +4136,7 @@ namespace RC::UEGenerator this->m_header_file = header_file; } - auto GeneratedSourceFile::add_extra_include(const std::wstring& included_file_name) -> void + auto GeneratedSourceFile::add_extra_include(const SystemStringType& included_file_name) -> void { this->m_extra_includes.insert(included_file_name); } @@ -4141,44 +4152,44 @@ namespace RC::UEGenerator } } - auto GeneratedSourceFile::generate_file_contents() -> std::wstring + auto GeneratedSourceFile::generate_file_contents() -> SystemStringType { - std::wstring result_header_contents; + SystemStringType result_header_contents; result_header_contents.append(generate_includes_string()); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); - std::wstring pre_declarations_string = generate_pre_declarations_string(); + SystemStringType pre_declarations_string = generate_pre_declarations_string(); if (!pre_declarations_string.empty()) { result_header_contents.append(pre_declarations_string); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); } if (!m_implementation_constructor.empty()) { result_header_contents.append(m_implementation_constructor); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); } if (!m_file_contents_buffer.empty()) { result_header_contents.append(m_file_contents_buffer); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); } return result_header_contents; } - auto GeneratedSourceFile::generate_includes_string() const -> std::wstring + auto GeneratedSourceFile::generate_includes_string() const -> SystemStringType { - std::wstring result_include_string; - std::vector> include_lines; - std::vector cross_module_includes; + SystemStringType result_include_string; + std::vector> include_lines; + std::vector cross_module_includes; // For the header file, we generate the pragma and minimal core includes if (!m_is_implementation_file) { - result_include_string.append(STR("#pragma once\n")); - result_include_string.append(STR("#include \"CoreMinimal.h\"\n")); + result_include_string.append(SYSSTR("#pragma once\n")); + result_include_string.append(SYSSTR("#include \"CoreMinimal.h\"\n")); } // For CPP implementation file, we need to generate the header include if (m_is_implementation_file) @@ -4186,19 +4197,19 @@ namespace RC::UEGenerator if (m_header_file != NULL) { // Generate it if we have the correct header file set - result_include_string.append(std::format(STR("#include \"{}.h\"\n"), m_header_file->m_file_base_name)); + result_include_string.append(std::format(SYSSTR("#include \"{}.h\"\n"), m_header_file->m_file_base_name)); } else { // Otherwise, we generate a simple minimal core include - result_include_string.append(STR("#include \"CoreMinimal.h\"\n")); + result_include_string.append(SYSSTR("#include \"CoreMinimal.h\"\n")); } } // Generate extra includes we might need that do not represent objects - for (const std::wstring& extra_included_file : m_extra_includes) + for (const SystemStringType& extra_included_file : m_extra_includes) { - include_lines.push_back({STR("#include \""), extra_included_file, STR("\"\n")}); + include_lines.push_back({SYSSTR("#include \""), extra_included_file, SYSSTR("\"\n")}); } // Generate includes for the relevant object files @@ -4212,7 +4223,7 @@ namespace RC::UEGenerator continue; } - const std::wstring object_header_name = UEHeaderGenerator::get_header_name_for_object(dependency_object, true); + const SystemStringType object_header_name = UEHeaderGenerator::get_header_name_for_object(dependency_object, true); // Definitely skip include if object in question is placed into this header if (object_header_name == m_file_base_name) @@ -4229,7 +4240,7 @@ namespace RC::UEGenerator } } UObject* package = dependency_object->GetOutermost(); - std::wstring native_module_name = UEHeaderGenerator::get_module_name_for_package(package); + SystemStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); if (!native_module_name.empty()) { @@ -4237,7 +4248,7 @@ namespace RC::UEGenerator // since generated headers are always located in the module root and follow one file per object convention if (m_file_module_name == native_module_name) { - include_lines.push_back({STR("#include \""), object_header_name, STR(".h\"\n")}); + include_lines.push_back({SYSSTR("#include \""), object_header_name, SYSSTR(".h\"\n")}); } else { @@ -4254,13 +4265,13 @@ namespace RC::UEGenerator // Remove duplicates - there are sometimes multiple instances of the same cross module include cross_module_includes.erase(std::unique(cross_module_includes.begin(), cross_module_includes.end()), cross_module_includes.end()); - for (const std::wstring& cross_module_include : cross_module_includes) + for (const SystemStringType& cross_module_include : cross_module_includes) { result_include_string.append(cross_module_include); } // Sort the includes by module name, since we want to make sure that they are always in the same order - std::sort(include_lines.begin(), include_lines.end(), [](const std::vector& a, const std::vector& b) { + std::sort(include_lines.begin(), include_lines.end(), [](const std::vector& a, const std::vector& b) { return a[1] < b[1]; }); @@ -4275,15 +4286,15 @@ namespace RC::UEGenerator // Last include of the header file should always be a generated one if (!m_is_implementation_file) { - result_include_string.append(std::format(STR("#include \"{}.generated.h\"\n"), m_file_base_name)); + result_include_string.append(std::format(SYSSTR("#include \"{}.generated.h\"\n"), m_file_base_name)); } return result_include_string; } - auto GeneratedSourceFile::generate_pre_declarations_string() const -> std::wstring + auto GeneratedSourceFile::generate_pre_declarations_string() const -> SystemStringType { - std::wstring result_declarations; - std::vector>> pre_declarations; + SystemStringType result_declarations; + std::vector>> pre_declarations; // Generate pre-declarations for the relevant object files for (const auto& dependency_pair : m_dependencies) @@ -4298,7 +4309,7 @@ namespace RC::UEGenerator // We still need to reference the object's owner module UObject* package = dependency_object->GetOutermost(); - std::wstring native_module_name = UEHeaderGenerator::get_module_name_for_package(package); + SystemStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); if (!native_module_name.empty() && m_file_module_name != native_module_name) { @@ -4311,7 +4322,7 @@ namespace RC::UEGenerator // Sort the entries alphabetically by the class name std::sort(pre_declarations.begin(), pre_declarations.end(), - [](const std::vector>& a, const std::vector>& b) { + [](const std::vector>& a, const std::vector>& b) { return a[0][1] < b[0][1]; }); diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index 56557f7d4..fc3491dea 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -5,7 +5,7 @@ #define REGISTER_STRING_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_string(section_name, STR(#key)); \ + (member_var) = parser.get_string(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -14,7 +14,7 @@ #define REGISTER_INT64_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_int64(section_name, STR(#key)); \ + (member_var) = parser.get_int64(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -23,7 +23,7 @@ #define REGISTER_BOOL_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_bool(section_name, STR(#key)); \ + (member_var) = parser.get_bool(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -32,7 +32,7 @@ #define REGISTER_FLOAT_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_float(section_name, STR(#key)); \ + (member_var) = parser.get_float(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -47,10 +47,10 @@ namespace RC parser.parse(file); file.close(); - constexpr static File::CharType section_overrides[] = STR("Overrides"); + constexpr static File::CharType section_overrides[] = SYSSTR("Overrides"); REGISTER_STRING_SETTING(Overrides.ModsFolderPath, section_overrides, ModsFolderPath) - constexpr static File::CharType section_general[] = STR("General"); + constexpr static File::CharType section_general[] = SYSSTR("General"); REGISTER_BOOL_SETTING(General.EnableHotReloadSystem, section_general, EnableHotReloadSystem) REGISTER_BOOL_SETTING(General.UseCache, section_general, UseCache) REGISTER_BOOL_SETTING(General.InvalidateCacheIfDLLDiffers, section_general, InvalidateCacheIfDLLDiffers) @@ -58,19 +58,19 @@ namespace RC REGISTER_INT64_SETTING(General.SecondsToScanBeforeGivingUp, section_general, SecondsToScanBeforeGivingUp) REGISTER_BOOL_SETTING(General.UseUObjectArrayCache, section_general, bUseUObjectArrayCache) - constexpr static File::CharType section_engine_version_override[] = STR("EngineVersionOverride"); + constexpr static File::CharType section_engine_version_override[] = SYSSTR("EngineVersionOverride"); REGISTER_INT64_SETTING(EngineVersionOverride.MajorVersion, section_engine_version_override, MajorVersion) REGISTER_INT64_SETTING(EngineVersionOverride.MinorVersion, section_engine_version_override, MinorVersion) - constexpr static File::CharType section_object_dumper[] = STR("ObjectDumper"); + constexpr static File::CharType section_object_dumper[] = SYSSTR("ObjectDumper"); REGISTER_BOOL_SETTING(ObjectDumper.LoadAllAssetsBeforeDumpingObjects, section_object_dumper, LoadAllAssetsBeforeDumpingObjects) - constexpr static File::CharType section_cxx_header_generator[] = STR("CXXHeaderGenerator"); + constexpr static File::CharType section_cxx_header_generator[] = SYSSTR("CXXHeaderGenerator"); REGISTER_BOOL_SETTING(CXXHeaderGenerator.DumpOffsetsAndSizes, section_cxx_header_generator, DumpOffsetsAndSizes) REGISTER_BOOL_SETTING(CXXHeaderGenerator.KeepMemoryLayout, section_cxx_header_generator, KeepMemoryLayout) REGISTER_BOOL_SETTING(CXXHeaderGenerator.LoadAllAssetsBeforeGeneratingCXXHeaders, section_cxx_header_generator, LoadAllAssetsBeforeGeneratingCXXHeaders) - constexpr static File::CharType section_uht_header_generator[] = STR("UHTHeaderGenerator"); + constexpr static File::CharType section_uht_header_generator[] = SYSSTR("UHTHeaderGenerator"); REGISTER_BOOL_SETTING(UHTHeaderGenerator.IgnoreAllCoreEngineModules, section_uht_header_generator, IgnoreAllCoreEngineModules) REGISTER_BOOL_SETTING(UHTHeaderGenerator.IgnoreEngineAndCoreUObject, section_uht_header_generator, IgnoreEngineAndCoreUObject) REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeAllFunctionsBlueprintCallable, section_uht_header_generator, MakeAllFunctionsBlueprintCallable) @@ -78,34 +78,37 @@ namespace RC REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeEnumClassesBlueprintType, section_uht_header_generator, MakeEnumClassesBlueprintType) REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeAllConfigsEngineConfig, section_uht_header_generator, MakeAllConfigsEngineConfig) - constexpr static File::CharType section_debug[] = STR("Debug"); + constexpr static File::CharType section_debug[] = SYSSTR("Debug"); REGISTER_BOOL_SETTING(Debug.SimpleConsoleEnabled, section_debug, ConsoleEnabled) REGISTER_BOOL_SETTING(Debug.DebugConsoleEnabled, section_debug, GuiConsoleEnabled) REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) REGISTER_FLOAT_SETTING(Debug.DebugGUIFontScaling, section_debug, GuiConsoleFontScaling) - StringType graphics_api_string{}; + #ifdef HAS_GUI + SystemStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) - if (String::iequal(graphics_api_string, STR("DX11")) || String::iequal(graphics_api_string, STR("D3D11"))) + if (String::iequal(graphics_api_string, SYSSTR("DX11")) || String::iequal(graphics_api_string, SYSSTR("D3D11"))) { Debug.GraphicsAPI = GUI::GfxBackend::DX11; } - else if (String::iequal(graphics_api_string, STR("OpenGL"))) + else if (String::iequal(graphics_api_string, SYSSTR("OpenGL"))) { Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; } + #endif + REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); - constexpr static File::CharType section_crash_dump[] = STR("CrashDump"); + constexpr static File::CharType section_crash_dump[] = SYSSTR("CrashDump"); REGISTER_BOOL_SETTING(CrashDump.EnableDumping, section_crash_dump, EnableDumping); REGISTER_BOOL_SETTING(CrashDump.FullMemoryDump, section_crash_dump, FullMemoryDump); - constexpr static File::CharType section_threads[] = STR("Threads"); + constexpr static File::CharType section_threads[] = SYSSTR("Threads"); REGISTER_INT64_SETTING(Threads.SigScannerNumThreads, section_threads, SigScannerNumThreads) REGISTER_INT64_SETTING(Threads.SigScannerMultithreadingModuleSizeThreshold, section_threads, SigScannerMultithreadingModuleSizeThreshold) - constexpr static File::CharType section_memory[] = STR("Memory"); + constexpr static File::CharType section_memory[] = SYSSTR("Memory"); REGISTER_INT64_SETTING(Memory.MaxMemoryUsageDuringAssetLoading, section_memory, MaxMemoryUsageDuringAssetLoading) - constexpr static File::CharType section_hooks[] = STR("Hooks"); + constexpr static File::CharType section_hooks[] = SYSSTR("Hooks"); REGISTER_BOOL_SETTING(Hooks.HookProcessInternal, section_hooks, HookProcessInternal) REGISTER_BOOL_SETTING(Hooks.HookProcessLocalScriptFunction, section_hooks, HookProcessLocalScriptFunction) REGISTER_BOOL_SETTING(Hooks.HookLoadMap, section_hooks, HookLoadMap) @@ -116,7 +119,7 @@ namespace RC REGISTER_BOOL_SETTING(Hooks.HookAActorTick, section_hooks, HookAActorTick) REGISTER_INT64_SETTING(Hooks.FExecVTableOffsetInLocalPlayer, section_hooks, FExecVTableOffsetInLocalPlayer) - constexpr static File::CharType section_experimental_features[] = STR("ExperimentalFeatures"); + constexpr static File::CharType section_experimental_features[] = SYSSTR("ExperimentalFeatures"); REGISTER_BOOL_SETTING(Experimental.GUIUFunctionCaller, section_experimental_features, GUIUFunctionCaller) } } // namespace RC diff --git a/UE4SS/src/Signatures.cpp b/UE4SS/src/Signatures.cpp index 147feec75..fe275b454 100644 --- a/UE4SS/src/Signatures.cpp +++ b/UE4SS/src/Signatures.cpp @@ -18,7 +18,7 @@ namespace RC { } - auto scan_from_lua_script(std::wstring& script_file_path_and_name, + auto scan_from_lua_script(SystemStringType& script_file_path_and_name, std::vector& signature_containers, LuaScriptMatchFoundFunc& match_found_func, LuaScriptScanCompleteFunc& scan_complete_func) -> void @@ -38,7 +38,7 @@ namespace RC if (!lua.is_global_function(global_register_func_name) || !lua.is_global_function(global_on_match_found_func_name)) { - Output::send(STR("Lua functions 'Register' and 'OnMatchFound' must be present in {}\n"), script_file_path_and_name); + Output::send(SYSSTR("Lua functions 'Register' and 'OnMatchFound' must be present in {}\n"), script_file_path_and_name); throw std::runtime_error{"See error message above"}; } @@ -91,7 +91,7 @@ namespace RC auto setup_lua_scan_overrides(std::filesystem::path& working_directory, Unreal::UnrealInitializer::Config& config) -> void { - std::wstring lua_guobjectarray_scan_script = working_directory / "UE4SS_Signatures/GUObjectArray.lua"; + SystemStringType lua_guobjectarray_scan_script = (working_directory / "UE4SS_Signatures/GUObjectArray.lua").generic_string(); if (std::filesystem::exists(lua_guobjectarray_scan_script)) { config.ScanOverrides.guobjectarray = [lua_guobjectarray_scan_script](std::vector& signature_containers, @@ -100,7 +100,7 @@ namespace RC lua_guobjectarray_scan_script, signature_containers, [](void* address) { - Output::send(STR("GUObjectArray address: {} <- Lua Script\n"), address); + Output::send(SYSSTR("GUObjectArray address: {} <- Lua Script\n"), address); Unreal::UObjectArray::SetupGUObjectArrayAddress(address); return DidLuaScanSucceed::Yes; }, @@ -113,7 +113,7 @@ namespace RC }; } - std::wstring lua_fts_scan_script = working_directory / "UE4SS_Signatures/FName_ToString.lua"; + SystemStringType lua_fts_scan_script = (working_directory / "UE4SS_Signatures/FName_ToString.lua").generic_string(); if (std::filesystem::exists(lua_fts_scan_script)) { config.ScanOverrides.fname_to_string = [lua_fts_scan_script](std::vector& signature_containers, @@ -122,7 +122,7 @@ namespace RC lua_fts_scan_script, signature_containers, [](void* address) { - Output::send(STR("FName::ToString address: {} <- Lua Script\n"), address); + Output::send(SYSSTR("FName::ToString address: {} <- Lua Script\n"), address); Unreal::FName::ToStringInternal.assign_address(address); return DidLuaScanSucceed::Yes; }, @@ -135,7 +135,7 @@ namespace RC }; } - std::wstring lua_fnc_scan_script = working_directory / "UE4SS_Signatures/FName_Constructor.lua"; + SystemStringType lua_fnc_scan_script = (working_directory / "UE4SS_Signatures/FName_Constructor.lua").generic_string(); if (std::filesystem::exists(lua_fnc_scan_script)) { config.ScanOverrides.fname_constructor = [lua_fnc_scan_script](std::vector& signature_containers, @@ -144,11 +144,11 @@ namespace RC lua_fnc_scan_script, signature_containers, [&scan_result](void* address) { - Unreal::FName name = Unreal::FName(L"bCanBeDamaged", Unreal::FNAME_Find, address); + Unreal::FName name = Unreal::FName(STR("bCanBeDamaged"), Unreal::FNAME_Find, address); - if (name == L"bCanBeDamaged") + if (name == STR("bCanBeDamaged")) { - Output::send(STR("FName::FName address: {} <- Lua Script\n"), address); + Output::send(SYSSTR("FName::FName address: {} <- Lua Script\n"), address); Unreal::FName::ConstructorInternal.assign_address(address); return DidLuaScanSucceed::Yes; } @@ -168,8 +168,8 @@ namespace RC } // For compatibility, we look for 'FMemory_Free.lua' if 'GMalloc.lua' doesn't exist. - std::wstring lua_ffree_scan_script_new = working_directory / "UE4SS_Signatures/GMalloc.lua"; - std::wstring lua_ffree_scan_script_compat = working_directory / "UE4SS_Signatures/FMemory_Free.lua"; + SystemStringType lua_ffree_scan_script_new = (working_directory / "UE4SS_Signatures/GMalloc.lua").generic_string(); + SystemStringType lua_ffree_scan_script_compat = (working_directory / "UE4SS_Signatures/FMemory_Free.lua").generic_string(); auto lua_ffree_scan_script = std::filesystem::exists(lua_ffree_scan_script_new) ? lua_ffree_scan_script_new : lua_ffree_scan_script_compat; if (std::filesystem::exists(lua_ffree_scan_script)) { @@ -179,7 +179,7 @@ namespace RC lua_ffree_scan_script, signature_containers, [](void* address) { - Output::send(STR("GMalloc address: {} <- Lua Script\n"), address); + Output::send(SYSSTR("GMalloc address: {} <- Lua Script\n"), address); Unreal::FMalloc::UnrealStaticGMalloc = static_cast(address); Unreal::GMalloc = *Unreal::FMalloc::UnrealStaticGMalloc; return DidLuaScanSucceed::Yes; @@ -193,7 +193,7 @@ namespace RC }; } - std::wstring lua_sco_scan_script = working_directory / "UE4SS_Signatures/StaticConstructObject.lua"; + SystemStringType lua_sco_scan_script = (working_directory / "UE4SS_Signatures/StaticConstructObject.lua").generic_string(); if (std::filesystem::exists(lua_sco_scan_script)) { config.ScanOverrides.static_construct_object = [lua_sco_scan_script](std::vector& signature_containers, @@ -202,7 +202,7 @@ namespace RC lua_sco_scan_script, signature_containers, [](void* address) { - Output::send(STR("StaticConstructObject_Internal address: {} <- Lua Script\n"), address); + Output::send(SYSSTR("StaticConstructObject_Internal address: {} <- Lua Script\n"), address); Unreal::UObjectGlobals::SetupStaticConstructObjectInternalAddress(address); return DidLuaScanSucceed::Yes; }, @@ -215,7 +215,7 @@ namespace RC }; } - std::wstring lua_ftc_scan_script = working_directory / "UE4SS_Signatures/FText_Constructor.lua"; + SystemStringType lua_ftc_scan_script = (working_directory / "UE4SS_Signatures/FText_Constructor.lua").generic_string(); if (std::filesystem::exists(lua_ftc_scan_script)) { config.ScanOverrides.ftext_constructor = [lua_ftc_scan_script](std::vector& signature_containers, @@ -224,11 +224,11 @@ namespace RC lua_ftc_scan_script, signature_containers, [&scan_result](void* address) { - Unreal::FText text = Unreal::FText(L"bCanBeDamaged", address); + Unreal::FText text = Unreal::FText(STR("bCanBeDamaged"), address); - if (text == L"bCanBeDamaged") + if (text == STR("bCanBeDamaged")) { - Output::send(STR("FText::FText address: {} <- Lua Script\n"), address); + Output::send(SYSSTR("FText::FText address: {} <- Lua Script\n"), address); Unreal::FText::ConstructorInternal.assign_address(address); return DidLuaScanSucceed::Yes; } diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index e753c31d3..bbb79f4f5 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1,6 +1,7 @@ +#ifdef WIN32 #define NOMINMAX - #include +#endif #ifdef TEXT #undef TEXT @@ -16,9 +17,11 @@ #include #include #include +#ifdef HAS_GUI #include #include #include +#endif #include #include #include @@ -27,7 +30,9 @@ #include #include #include +#ifdef HAS_CPPMOD #include +#endif #include #include #include @@ -56,6 +61,7 @@ #include #include +#include namespace RC { @@ -94,12 +100,12 @@ namespace RC #define OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(StructName) \ for (const auto& [name, offset] : Unreal::StructName::MemberOffsets) \ { \ - Output::send(STR(#StructName "::{} = 0x{:X}\n"), name, offset); \ + Output::send(SYSSTR(#StructName "::{} = 0x{:X}\n"), UEStringToSystemString(name), offset); \ } auto output_all_member_offsets() -> void { - Output::send(STR("\n##### MEMBER OFFSETS START #####\n\n")); + Output::send(SYSSTR("\n##### MEMBER OFFSETS START #####\n\n")); OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(UObjectBase); OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(UScriptStruct); OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(UScriptStruct::ICppStructOps); @@ -126,14 +132,15 @@ namespace RC OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(FSoftClassProperty); OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(FInterfaceProperty); OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(FFieldPathProperty); - Output::send(STR("\n##### MEMBER OFFSETS END #####\n\n")); + Output::send(SYSSTR("\n##### MEMBER OFFSETS END #####\n\n")); } +#ifdef WIN32 void* HookedLoadLibraryA(const char* dll_name) { UE4SSProgram& program = UE4SSProgram::get_program(); HMODULE lib = PLH::FnCast(program.m_hook_trampoline_load_library_a, &LoadLibraryA)(dll_name); - program.fire_dll_load_for_cpp_mods(to_wstring(dll_name)); + program.fire_dll_load_for_cpp_mods(to_generic_string(dll_name)); return lib; } @@ -141,7 +148,7 @@ namespace RC { UE4SSProgram& program = UE4SSProgram::get_program(); HMODULE lib = PLH::FnCast(program.m_hook_trampoline_load_library_ex_a, &LoadLibraryExA)(dll_name, file, flags); - program.fire_dll_load_for_cpp_mods(to_wstring(dll_name)); + program.fire_dll_load_for_cpp_mods(to_generic_string(dll_name)); return lib; } @@ -160,8 +167,9 @@ namespace RC program.fire_dll_load_for_cpp_mods(dll_name); return lib; } +#endif - UE4SSProgram::UE4SSProgram(const std::wstring& moduleFilePath, std::initializer_list options) : MProgram(options) + UE4SSProgram::UE4SSProgram(const SystemStringType& moduleFilePath, std::initializer_list options) : MProgram(options) { ProfilerScope(); s_program = this; @@ -176,92 +184,97 @@ namespace RC } catch (std::exception& e) { - create_emergency_console_for_early_error(std::format(STR("The IniParser failed to parse: {}"), to_wstring(e.what()))); + create_emergency_console_for_early_error(std::format(SYSSTR("The IniParser failed to parse: {}"), to_generic_string(e.what()))); return; } +#ifdef WIN32 if (settings_manager.CrashDump.EnableDumping) { m_crash_dumper.enable(); } m_crash_dumper.set_full_memory_dump(settings_manager.CrashDump.FullMemoryDump); +#endif +#ifdef HAS_GUI m_debugging_gui.set_gfx_backend(settings_manager.Debug.GraphicsAPI); +#endif // Setup the log file auto& file_device = Output::set_default_devices(); - file_device.set_file_name_and_path(m_log_directory / m_log_file_name); + file_device.set_file_name_and_path((m_log_directory / m_log_file_name).generic_string()); create_simple_console(); +#ifdef HAS_GUI if (settings_manager.Debug.DebugConsoleEnabled) { m_console_device = &Output::set_default_devices(); m_console_device->set_formatter([](File::StringViewType string) -> File::StringType { - return std::format(STR("[{}] {}"), std::format(STR("{:%X}"), std::chrono::system_clock::now()), string); + return std::format(SYSSTR("[{}] {}"), std::format(SYSSTR("{:%X}"), std::chrono::system_clock::now()), string); }); if (settings_manager.Debug.DebugConsoleVisible) { m_render_thread = std::jthread{&GUI::gui_thread, &m_debugging_gui}; } } - +#endif // This is experimental code that's here only for future reference /* Unreal::UnrealInitializer::SetupUnrealModules(); constexpr const wchar_t* str_to_find = STR("Allocator: %s"); void* string_address = SinglePassScanner::string_scan(str_to_find, ScanTarget::Core); - Output::send(STR("\n\nFound string '{}' at {}\n\n"), std::wstring_view{str_to_find}, string_address); + Output::send(SYSSTR("\n\nFound string '{}' at {}\n\n"), SystemStringViewType{str_to_find}, string_address); //*/ - Output::send(STR("Console created\n")); - Output::send(STR("UE4SS - v{}.{}.{}{}{} - Git SHA #{}\n"), + Output::send(SYSSTR("Console created\n")); + Output::send(SYSSTR("UE4SS - v{}.{}.{}{}{} - Git SHA #{}\n"), UE4SS_LIB_VERSION_MAJOR, UE4SS_LIB_VERSION_MINOR, UE4SS_LIB_VERSION_HOTFIX, - std::format(L"{}", UE4SS_LIB_VERSION_PRERELEASE == 0 ? L"" : std::format(L" PreRelease #{}", UE4SS_LIB_VERSION_PRERELEASE)), - std::format(L"{}", - UE4SS_LIB_BETA_STARTED == 0 ? L"" : (UE4SS_LIB_IS_BETA == 0 ? L" Beta #?" : std::format(L" Beta #{}", UE4SS_LIB_VERSION_BETA))), - to_wstring(UE4SS_LIB_BUILD_GITSHA)); + std::format(SYSSTR("{}"), UE4SS_LIB_VERSION_PRERELEASE == 0 ? SYSSTR("") : std::format(SYSSTR(" PreRelease #{}"), UE4SS_LIB_VERSION_PRERELEASE)), + std::format(SYSSTR("{}"), + UE4SS_LIB_BETA_STARTED == 0 ? SYSSTR("") : (UE4SS_LIB_IS_BETA == 0 ? SYSSTR(" Beta #?") : std::format(SYSSTR(" Beta #{}"), UE4SS_LIB_VERSION_BETA))), + SYSSTR(UE4SS_LIB_BUILD_GITSHA)); #ifdef __clang__ -#define UE4SS_COMPILER L"Clang" +#define UE4SS_COMPILER SYSSTR("Clang") #else -#define UE4SS_COMPILER L"MSVC" +#define UE4SS_COMPILER SYSSTR("MSVC") #endif - Output::send(STR("UE4SS Build Configuration: {} ({})\n"), to_wstring(UE4SS_CONFIGURATION), UE4SS_COMPILER); - + Output::send(SYSSTR("UE4SS Build Configuration: {} ({})\n"), SYSSTR(UE4SS_CONFIGURATION), UE4SS_COMPILER); +#ifdef WIN32 m_load_library_a_hook = std::make_unique("kernel32.dll", "LoadLibraryA", std::bit_cast(&HookedLoadLibraryA), &m_hook_trampoline_load_library_a, - L""); + SYSSTR("")); m_load_library_a_hook->hook(); m_load_library_ex_a_hook = std::make_unique("kernel32.dll", "LoadLibraryExA", std::bit_cast(&HookedLoadLibraryExA), &m_hook_trampoline_load_library_ex_a, - L""); + SYSSTR("")); m_load_library_ex_a_hook->hook(); m_load_library_w_hook = std::make_unique("kernel32.dll", "LoadLibraryW", std::bit_cast(&HookedLoadLibraryW), &m_hook_trampoline_load_library_w, - L""); + SYSSTR("")); m_load_library_w_hook->hook(); m_load_library_ex_w_hook = std::make_unique("kernel32.dll", "LoadLibraryExW", std::bit_cast(&HookedLoadLibraryExW), &m_hook_trampoline_load_library_ex_w, - L""); + SYSSTR("")); m_load_library_ex_w_hook->hook(); - +#endif Unreal::UnrealInitializer::SetupUnrealModules(); setup_mods(); @@ -272,21 +285,21 @@ namespace RC if (m_has_game_specific_config) { - Output::send(STR("Found configuration for game: {}\n"), m_mods_directory.parent_path().filename().c_str()); + Output::send(SYSSTR("Found configuration for game: {}\n"), m_mods_directory.parent_path().filename().c_str()); } else { - Output::send(STR("No specific game configuration found, using default configuration file\n")); + Output::send(SYSSTR("No specific game configuration found, using default configuration file\n")); } - Output::send(STR("Config: {}\n\n"), m_settings_path_and_file.c_str()); - Output::send(STR("root directory: {}\n"), m_root_directory.c_str()); - Output::send(STR("working directory: {}\n"), m_working_directory.c_str()); - Output::send(STR("game executable directory: {}\n"), m_game_executable_directory.c_str()); - Output::send(STR("game executable: {} ({} bytes)\n\n\n"), m_game_path_and_exe_name.c_str(), std::filesystem::file_size(m_game_path_and_exe_name)); - Output::send(STR("mods directory: {}\n"), m_mods_directory.c_str()); - Output::send(STR("log directory: {}\n"), m_log_directory.c_str()); - Output::send(STR("object dumper directory: {}\n\n\n"), m_object_dumper_output_directory.c_str()); + Output::send(SYSSTR("Config: {}\n\n"), m_settings_path_and_file.c_str()); + Output::send(SYSSTR("root directory: {}\n"), m_root_directory.c_str()); + Output::send(SYSSTR("working directory: {}\n"), m_working_directory.c_str()); + Output::send(SYSSTR("game executable directory: {}\n"), m_game_executable_directory.c_str()); + Output::send(SYSSTR("game executable: {} ({} bytes)\n\n\n"), m_game_path_and_exe_name.c_str(), std::filesystem::file_size(m_game_path_and_exe_name)); + Output::send(SYSSTR("mods directory: {}\n"), m_mods_directory.c_str()); + Output::send(SYSSTR("log directory: {}\n"), m_log_directory.c_str()); + Output::send(SYSSTR("object dumper directory: {}\n\n\n"), m_object_dumper_output_directory.c_str()); } catch (std::runtime_error& e) { @@ -321,7 +334,8 @@ namespace RC { setup_unreal(); - Output::send(STR("Unreal Engine modules ({}):\n"), SigScannerStaticData::m_is_modular ? STR("modular") : STR("non-modular")); + Output::send(SYSSTR("Unreal Engine modules ({}):\n"), SigScannerStaticData::m_is_modular ? SYSSTR("modular") : SYSSTR("non-modular")); +#ifdef WIN32 auto& main_exe_ptr = SigScannerStaticData::m_modules_info.array[static_cast(ScanTarget::MainExe)].lpBaseOfDll; for (size_t i = 0; i < static_cast(ScanTarget::Max); ++i) { @@ -329,11 +343,26 @@ namespace RC // only log modules with unique addresses (non-modular builds have everything in MainExe) if (i == static_cast(ScanTarget::MainExe) || main_exe_ptr != module.lpBaseOfDll) { - auto module_name = to_wstring(ScanTargetToString(i)); - Output::send(STR("{} @ {} size={:#x}\n"), module_name.c_str(), module.lpBaseOfDll, module.SizeOfImage); + auto module_name = to_generic_string(ScanTargetToString(i)); + Output::send(SYSSTR("{} @ {} size={:#x}\n"), module_name.c_str(), module.lpBaseOfDll, module.SizeOfImage); } } +#elif defined(LINUX) + auto& main_exe_ptr = SigScannerStaticData::m_modules_info.array[static_cast(ScanTarget::MainExe)].base_address; + for (size_t i = 0; i < static_cast(ScanTarget::Max); ++i) + { + auto& module = SigScannerStaticData::m_modules_info.array[i]; + // only log modules with unique addresses (non-modular builds have everything in MainExe) + if (i == static_cast(ScanTarget::MainExe) || main_exe_ptr != module.base_address) + { + auto module_name = to_generic_string(ScanTargetToString(i)); + // FIXME: FIX Why this won't WORK? + // Output::send(SYSSTR("{} @ {} size={:#x}\n"), module_name, module.base_address, module.size); + } + } +#else +#endif fire_unreal_init_for_cpp_mods(); setup_unreal_properties(); UAssetRegistry::SetMaxMemoryUsageDuringAssetLoading(settings_manager.Memory.MaxMemoryUsageDuringAssetLoading); @@ -367,21 +396,22 @@ namespace RC } } - auto UE4SSProgram::setup_paths(const std::wstring& moduleFilePathString) -> void + auto UE4SSProgram::setup_paths(const SystemStringType& moduleFilePathString) -> void { ProfilerScope(); const std::filesystem::path moduleFilePath = std::filesystem::path(moduleFilePathString); - m_root_directory = moduleFilePath.parent_path().wstring(); - m_module_file_path = moduleFilePath.wstring(); + m_root_directory = moduleFilePath.parent_path().generic_string(); + m_module_file_path = moduleFilePath.generic_string(); // The default working directory is the root directory // Can be changed by creating a directory in the root directory // At that point, the working directory will be "root/" m_working_directory = m_root_directory; - wchar_t exe_path_buffer[1024]; - GetModuleFileNameW(GetModuleHandle(nullptr), exe_path_buffer, 1023); - std::filesystem::path game_exe_path = exe_path_buffer; + // Default file to open if there is no game specific config + m_default_settings_path_and_file = m_root_directory / m_settings_file_name; + + std::filesystem::path game_exe_path = get_executable_path(); std::filesystem::path game_directory_path = game_exe_path.parent_path(); m_legacy_root_directory = game_directory_path; @@ -392,8 +422,8 @@ namespace RC m_game_path_and_exe_name = game_exe_path; m_object_dumper_output_directory = m_working_directory; - // Allow loading of DLLs from the game directory - AddDllDirectory(game_exe_path.c_str()); + // Allow loading of DLLs from mod folders + add_dlsearch_folder(game_exe_path); for (const auto& item : std::filesystem::directory_iterator(m_root_directory)) { @@ -406,7 +436,7 @@ namespace RC { m_has_game_specific_config = true; m_working_directory = item.path(); - m_mods_directory = item.path().wstring() + L"\\Mods"; + m_mods_directory = item.path() / SYSSTR("Mods"); m_settings_path_and_file = std::move(item.path()); m_log_directory = m_working_directory; m_object_dumper_output_directory = m_working_directory; @@ -433,7 +463,7 @@ namespace RC { settings_manager.Debug.SimpleConsoleEnabled = true; create_simple_console(); - printf_s("%S\n", error_message.data()); + printf_s( SystemStringPrint "\n", error_message.data()); } auto UE4SSProgram::setup_mod_directory_path() -> void @@ -457,9 +487,9 @@ namespace RC m_debug_console_device = &Output::set_default_devices(); Output::set_default_log_level(); m_debug_console_device->set_formatter([](File::StringViewType string) -> File::StringType { - return std::format(STR("[{}] {}"), std::format(STR("{:%X}"), std::chrono::system_clock::now()), string); + return std::format(SYSSTR("[{}] {}"), std::format(SYSSTR("{:%X}"), std::chrono::system_clock::now()), string); }); - +#ifdef WIN32 if (AllocConsole()) { FILE* stdin_filename; @@ -469,6 +499,7 @@ namespace RC freopen_s(&stdout_filename, "CONOUT$", "w", stdout); freopen_s(&stderr_filename, "CONOUT$", "w", stderr); } +#endif } } @@ -494,7 +525,7 @@ namespace RC { ProfilerScope(); // Retrieve offsets from the config file - const std::wstring offset_overrides_section{L"OffsetOverrides"}; + const SystemStringType offset_overrides_section{SYSSTR("OffsetOverrides")}; load_unreal_offsets_from_file(); @@ -562,7 +593,7 @@ namespace RC // Virtual function offset overrides TRY([&]() { ProfilerScopeNamed("loading virtual function offset overrides"); - static File::StringType virtual_function_offset_override_file{(m_working_directory / STR("VTableLayout.ini")).wstring()}; + static File::StringType virtual_function_offset_override_file{(m_working_directory / SYSSTR("VTableLayout.ini")).generic_string()}; if (std::filesystem::exists(virtual_function_offset_override_file)) { auto file = @@ -570,72 +601,80 @@ namespace RC Ini::Parser parser; parser.parse(file); - Output::send(STR("Getting ordered lists from ini file\n")); + Output::send(SYSSTR("Getting ordered lists from ini file\n")); auto calculate_virtual_function_offset = [](uint32_t current_index, BaseSizes... base_sizes) -> uint32_t { return current_index == 0 ? 0 : (current_index + (base_sizes + ...)) * 8; }; - auto retrieve_vtable_layout_from_ini = [&](const File::StringType& section_name, auto callable) -> uint32_t { + auto retrieve_vtable_layout_from_ini = [&](const SystemStringType& section_name, auto callable) -> uint32_t { auto list = parser.get_ordered_list(section_name); uint32_t vtable_size = list.size() - 1; - list.for_each([&](uint32_t index, File::StringType& item) { - callable(index, item); + list.for_each([&](uint32_t index, SystemStringType& item) { + auto ue_str = SystemStringToUEString(item); + callable(index, item, ue_str); }); return vtable_size; }; - Output::send(STR("UObjectBase\n")); - uint32_t uobjectbase_size = retrieve_vtable_layout_from_ini(STR("UObjectBase"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UObjectBase\n")); + uint32_t uobjectbase_size = retrieve_vtable_layout_from_ini(SYSSTR("UObjectBase"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, 0); - Output::send(STR("UObjectBase::{} = 0x{:X}\n"), item, offset); - Unreal::UObjectBase::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UObjectBase::{} = 0x{:X}\n"), item, offset); + Unreal::UObjectBase::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("UObjectBaseUtility\n")); - uint32_t uobjectbaseutility_size = retrieve_vtable_layout_from_ini(STR("UObjectBaseUtility"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UObjectBaseUtility\n")); + uint32_t uobjectbaseutility_size = retrieve_vtable_layout_from_ini(SYSSTR("UObjectBaseUtility"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size); - Output::send(STR("UObjectBaseUtility::{} = 0x{:X}\n"), item, offset); - Unreal::UObjectBaseUtility::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UObjectBaseUtility::{} = 0x{:X}\n"), item, offset); + Unreal::UObjectBaseUtility::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("UObject\n")); - uint32_t uobject_size = retrieve_vtable_layout_from_ini(STR("UObject"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UObject\n")); + uint32_t uobject_size = retrieve_vtable_layout_from_ini(SYSSTR("UObject"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size); - Output::send(STR("UObject::{} = 0x{:X}\n"), item, offset); - Unreal::UObject::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UObject::{} = 0x{:X}\n"), item, offset); + Unreal::UObject::VTableLayoutMap.emplace(item_ue, offset); + }); + + Output::send(SYSSTR("UField\n")); + uint32_t ufield_size = retrieve_vtable_layout_from_ini(SYSSTR("UField"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { + uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size); + Output::send(SYSSTR("UField::{} = 0x{:X}\n"), item, offset); + Unreal::UField::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("UField\n")); - uint32_t ufield_size = retrieve_vtable_layout_from_ini(STR("UField"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UEngine\n")); + uint32_t uengine_size = retrieve_vtable_layout_from_ini(SYSSTR("UEngine"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size); - Output::send(STR("UField::{} = 0x{:X}\n"), item, offset); - Unreal::UField::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UEngine::{} = 0x{:X}\n"), item, offset); + Unreal::UEngine::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("UEngine\n")); - uint32_t uengine_size = retrieve_vtable_layout_from_ini(STR("UEngine"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UEngine\n")); + uint32_t uengine_size = retrieve_vtable_layout_from_ini(SYSSTR("UEngine"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size); - Output::send(STR("UEngine::{} = 0x{:X}\n"), item, offset); - Unreal::UEngine::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UEngine::{} = 0x{:X}\n"), item, offset); + Unreal::UEngine::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("UScriptStruct::ICppStructOps\n")); - retrieve_vtable_layout_from_ini(STR("UScriptStruct::ICppStructOps"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UScriptStruct::ICppStructOps\n")); + retrieve_vtable_layout_from_ini(SYSSTR("UScriptStruct::ICppStructOps"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, 0); - Output::send(STR("UScriptStruct::ICppStructOps::{} = 0x{:X}\n"), item, offset); - Unreal::UScriptStruct::ICppStructOps::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UScriptStruct::ICppStructOps::{} = 0x{:X}\n"), item, offset); + Unreal::UScriptStruct::ICppStructOps::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("FField\n")); - uint32_t ffield_size = retrieve_vtable_layout_from_ini(STR("FField"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("FField\n")); + uint32_t ffield_size = retrieve_vtable_layout_from_ini(SYSSTR("FField"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, 0); - Output::send(STR("FField::{} = 0x{:X}\n"), item, offset); - Unreal::FField::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("FField::{} = 0x{:X}\n"), item, offset); + Unreal::FField::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("FProperty\n")); - uint32_t fproperty_size = retrieve_vtable_layout_from_ini(STR("FProperty"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("FProperty\n")); + uint32_t fproperty_size = retrieve_vtable_layout_from_ini(SYSSTR("FProperty"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset{}; if (Unreal::Version::IsBelow(4, 25)) { @@ -645,8 +684,8 @@ namespace RC { offset = calculate_virtual_function_offset(index, ffield_size); } - Output::send(STR("FProperty::{} = 0x{:X}\n"), item, offset); - Unreal::FProperty::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("FProperty::{} = 0x{:X}\n"), item, offset); + Unreal::FProperty::VTableLayoutMap.emplace(item_ue, offset); }); // If the engine version is <4.25 then the inheritance is different and we must take that into consideration. @@ -659,66 +698,66 @@ namespace RC fproperty_size = ffield_size + fproperty_size; } - Output::send(STR("FNumericProperty\n")); - retrieve_vtable_layout_from_ini(STR("FNumericProperty"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("FNumericProperty\n")); + retrieve_vtable_layout_from_ini(SYSSTR("FNumericProperty"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, fproperty_size); - Output::send(STR("FNumericProperty::{} = 0x{:X}\n"), item, offset); - Unreal::FNumericProperty::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("FNumericProperty::{} = 0x{:X}\n"), item, offset); + Unreal::FNumericProperty::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("FMulticastDelegateProperty\n")); - retrieve_vtable_layout_from_ini(STR("FMulticastDelegateProperty"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("FMulticastDelegateProperty\n")); + retrieve_vtable_layout_from_ini(SYSSTR("FMulticastDelegateProperty"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, fproperty_size); - Output::send(STR("FMulticastDelegateProperty::{} = 0x{:X}\n"), item, offset); - Unreal::FMulticastDelegateProperty::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("FMulticastDelegateProperty::{} = 0x{:X}\n"), item, offset); + Unreal::FMulticastDelegateProperty::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("FObjectPropertyBase\n")); - retrieve_vtable_layout_from_ini(STR("FObjectPropertyBase"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("FObjectPropertyBase\n")); + retrieve_vtable_layout_from_ini(SYSSTR("FObjectPropertyBase"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, fproperty_size); - Output::send(STR("FObjectPropertyBase::{} = 0x{:X}\n"), item, offset); - Unreal::FObjectPropertyBase::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("FObjectPropertyBase::{} = 0x{:X}\n"), item, offset); + Unreal::FObjectPropertyBase::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("UStruct\n")); - retrieve_vtable_layout_from_ini(STR("UStruct"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UStruct\n")); + retrieve_vtable_layout_from_ini(SYSSTR("UStruct"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size, ufield_size); - Output::send(STR("UStruct::{} = 0x{:X}\n"), item, offset); - Unreal::UStruct::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UStruct::{} = 0x{:X}\n"), item, offset); + Unreal::UStruct::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("FOutputDevice\n")); - retrieve_vtable_layout_from_ini(STR("FOutputDevice"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("FOutputDevice\n")); + retrieve_vtable_layout_from_ini(SYSSTR("FOutputDevice"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, 0); - Output::send(STR("FOutputDevice::{} = 0x{:X}\n"), item, offset); - Unreal::FOutputDevice::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("FOutputDevice::{} = 0x{:X}\n"), item, offset); + Unreal::FOutputDevice::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("FMalloc\n")); - retrieve_vtable_layout_from_ini(STR("FMalloc"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("FMalloc\n")); + retrieve_vtable_layout_from_ini(SYSSTR("FMalloc"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { // We don't support FExec, so we're manually telling it the size. static constexpr uint32_t fexec_size = 1; uint32_t offset = calculate_virtual_function_offset(index, fexec_size); - Output::send(STR("FMalloc::{} = 0x{:X}\n"), item, offset); - Unreal::FMalloc::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("FMalloc::{} = 0x{:X}\n"), item, offset); + Unreal::FMalloc::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("AActor\n")); - uint32_t aactor_size = retrieve_vtable_layout_from_ini(STR("AActor"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("AActor\n")); + uint32_t aactor_size = retrieve_vtable_layout_from_ini(SYSSTR("AActor"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size); - Output::send(STR("AActor::{} = 0x{:X}\n"), item, offset); - Unreal::AActor::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("AActor::{} = 0x{:X}\n"), item, offset); + Unreal::AActor::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("AGameModeBase\n")); - uint32_t agamemodebase_size = retrieve_vtable_layout_from_ini(STR("AGameModeBase"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("AGameModeBase\n")); + uint32_t agamemodebase_size = retrieve_vtable_layout_from_ini(SYSSTR("AGameModeBase"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size, aactor_size); - Output::send(STR("AGameModeBase::{} = 0x{:X}\n"), item, offset); - Unreal::AGameModeBase::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("AGameModeBase::{} = 0x{:X}\n"), item, offset); + Unreal::AGameModeBase::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("AGameMode\n")); - retrieve_vtable_layout_from_ini(STR("AGameMode"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("AGameMode\n")); + retrieve_vtable_layout_from_ini(SYSSTR("AGameMode"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, Unreal::Version::IsAtLeast(4, 14) ? uobjectbase_size, @@ -730,22 +769,22 @@ namespace RC uobjectbaseutility_size, uobject_size, aactor_size); - Output::send(STR("AGameMode::{} = 0x{:X}\n"), item, offset); - Unreal::AGameMode::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("AGameMode::{} = 0x{:X}\n"), item, offset); + Unreal::AGameMode::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("UPlayer\n")); - uint32_t uplayer_size = retrieve_vtable_layout_from_ini(STR("UPlayer"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("UPlayer\n")); + uint32_t uplayer_size = retrieve_vtable_layout_from_ini(SYSSTR("UPlayer"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size); - Output::send(STR("UPlayer::{} = 0x{:X}\n"), item, offset); - Unreal::UPlayer::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("UPlayer::{} = 0x{:X}\n"), item, offset); + Unreal::UPlayer::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(STR("ULocalPlayer\n")); - retrieve_vtable_layout_from_ini(STR("ULocalPlayer"), [&](uint32_t index, File::StringType& item) { + Output::send(SYSSTR("ULocalPlayer\n")); + retrieve_vtable_layout_from_ini(SYSSTR("ULocalPlayer"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size, uplayer_size); - Output::send(STR("ULocalPlayer::{} = 0x{:X}\n"), item, offset); - Unreal::ULocalPlayer::VTableLayoutMap.emplace(item, offset); + Output::send(SYSSTR("ULocalPlayer::{} = 0x{:X}\n"), item, offset); + Unreal::ULocalPlayer::VTableLayoutMap.emplace(item_ue, offset); }); file.close(); @@ -768,16 +807,16 @@ namespace RC if (!UObject::ProcessLocalScriptFunctionInternal.is_ready() && Unreal::Version::IsAtLeast(4, 22)) { can_create_custom_events = false; - Output::send(STR("ProcessLocalScriptFunction is not available, the following features will be unavailable:\n")); + Output::send(SYSSTR("ProcessLocalScriptFunction is not available, the following features will be unavailable:\n")); } else if (!UObject::ProcessInternalInternal.is_ready() && Unreal::Version::IsBelow(4, 22)) { can_create_custom_events = false; - Output::send(STR("ProcessInternal is not available, the following features will be unavailable:\n")); + Output::send(SYSSTR("ProcessInternal is not available, the following features will be unavailable:\n")); } if (!can_create_custom_events) { - Output::send(STR("\n")); + Output::send(SYSSTR("\n")); } } @@ -787,7 +826,7 @@ namespace RC m_shared_functions.set_script_variable_default_data_function = &LuaLibrary::set_script_variable_default_data; m_shared_functions.call_script_function_function = &LuaLibrary::call_script_function; m_shared_functions.is_ue4ss_initialized_function = &LuaLibrary::is_ue4ss_initialized; - Output::send(STR("m_shared_functions: {}\n"), static_cast(&m_shared_functions)); + Output::send(SYSSTR("m_shared_functions: {}\n"), static_cast(&m_shared_functions)); } auto UE4SSProgram::on_program_start() -> void @@ -799,7 +838,7 @@ namespace RC /* UObjectArray::AddUObjectCreateListener(&FUEDeathListener::UEDeathListener); //*/ - +#ifdef HAS_GUI if (settings_manager.Debug.DebugConsoleEnabled) { if (settings_manager.General.UseUObjectArrayCache) @@ -823,6 +862,7 @@ namespace RC }); }); } +#endif #ifdef TIME_FUNCTION_MACRO_ENABLED m_input_handler.register_keydown_event(Input::Key::Y, {Input::ModifierKey::CONTROL}, [&]() { @@ -830,19 +870,19 @@ namespace RC { FunctionTimerFrame::stop_profiling(); FunctionTimerFrame::dump_profile(); - Output::send(STR("Profiler stopped & dumped\n")); + Output::send(SYSSTR("Profiler stopped & dumped\n")); } else { FunctionTimerFrame::start_profiling(); - Output::send(STR("Profiler started\n")); + Output::send(SYSSTR("Profiler started\n")); } }); #endif TRY([&] { ObjectDumper::init(); - +#ifdef HAS_INPUT if (settings_manager.General.EnableHotReloadSystem) { m_input_handler.register_keydown_event(Input::Key::R, {Input::ModifierKey::CONTROL}, [&]() { @@ -851,12 +891,12 @@ namespace RC }); }); } - +#endif if ((settings_manager.ObjectDumper.LoadAllAssetsBeforeDumpingObjects || settings_manager.CXXHeaderGenerator.LoadAllAssetsBeforeGeneratingCXXHeaders) && Unreal::Version::IsBelow(4, 17)) { Output::send( - STR("FAssetData not available in <4.17, ignoring 'LoadAllAssetsBeforeDumpingObjects' & 'LoadAllAssetsBeforeGeneratingCXXHeaders'.")); + SYSSTR("FAssetData not available in <4.17, ignoring 'LoadAllAssetsBeforeDumpingObjects' & 'LoadAllAssetsBeforeGeneratingCXXHeaders'.")); } install_lua_mods(); @@ -865,12 +905,14 @@ namespace RC start_lua_mods(); }); +#ifdef HAS_INPUT if (settings_manager.General.EnableDebugKeyBindings) { m_input_handler.register_keydown_event(Input::Key::NUM_NINE, {Input::ModifierKey::CONTROL}, [&]() { generate_uht_compatible_headers(); }); } +#endif } auto UE4SSProgram::update() -> void @@ -879,7 +921,7 @@ namespace RC on_program_start(); - Output::send(STR("Event loop start\n")); + Output::send(SYSSTR("Event loop start\n")); for (m_processing_events = true; m_processing_events;) { if (m_pause_events_processing || UE4SSProgram::unreal_is_shutting_down) @@ -929,9 +971,9 @@ namespace RC } } //*/ - +#ifdef HAS_INPUT m_input_handler.process_event(); - +#endif { ProfilerScopeNamed("mod update processing"); @@ -947,40 +989,40 @@ namespace RC std::this_thread::sleep_for(std::chrono::milliseconds(5)); ProfilerFrameMark(); } - Output::send(STR("Event loop end\n")); + Output::send(SYSSTR("Event loop end\n")); } auto UE4SSProgram::setup_unreal_properties() -> void { - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"ObjectProperty").GetComparisonIndex(), &LuaType::push_objectproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"ClassProperty").GetComparisonIndex(), &LuaType::push_classproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"Int8Property").GetComparisonIndex(), &LuaType::push_int8property); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"Int16Property").GetComparisonIndex(), &LuaType::push_int16property); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"IntProperty").GetComparisonIndex(), &LuaType::push_intproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"Int64Property").GetComparisonIndex(), &LuaType::push_int64property); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"ByteProperty").GetComparisonIndex(), &LuaType::push_byteproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"UInt16Property").GetComparisonIndex(), &LuaType::push_uint16property); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"UInt32Property").GetComparisonIndex(), &LuaType::push_uint32property); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"UInt64Property").GetComparisonIndex(), &LuaType::push_uint64property); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"StructProperty").GetComparisonIndex(), &LuaType::push_structproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"ArrayProperty").GetComparisonIndex(), &LuaType::push_arrayproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"FloatProperty").GetComparisonIndex(), &LuaType::push_floatproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"DoubleProperty").GetComparisonIndex(), &LuaType::push_doubleproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"BoolProperty").GetComparisonIndex(), &LuaType::push_boolproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"EnumProperty").GetComparisonIndex(), &LuaType::push_enumproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"WeakObjectProperty").GetComparisonIndex(), &LuaType::push_weakobjectproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"NameProperty").GetComparisonIndex(), &LuaType::push_nameproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"TextProperty").GetComparisonIndex(), &LuaType::push_textproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"StrProperty").GetComparisonIndex(), &LuaType::push_strproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"SoftClassProperty").GetComparisonIndex(), &LuaType::push_softclassproperty); - LuaType::StaticState::m_property_value_pushers.emplace(FName(L"InterfaceProperty").GetComparisonIndex(), &LuaType::push_interfaceproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("ObjectProperty")).GetComparisonIndex(), &LuaType::push_objectproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("ClassProperty")).GetComparisonIndex(), &LuaType::push_classproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("Int8Property")).GetComparisonIndex(), &LuaType::push_int8property); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("Int16Property")).GetComparisonIndex(), &LuaType::push_int16property); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("IntProperty")).GetComparisonIndex(), &LuaType::push_intproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("Int64Property")).GetComparisonIndex(), &LuaType::push_int64property); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("ByteProperty")).GetComparisonIndex(), &LuaType::push_byteproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("UInt16Property")).GetComparisonIndex(), &LuaType::push_uint16property); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("UInt32Property")).GetComparisonIndex(), &LuaType::push_uint32property); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("UInt64Property")).GetComparisonIndex(), &LuaType::push_uint64property); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("StructProperty")).GetComparisonIndex(), &LuaType::push_structproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("ArrayProperty")).GetComparisonIndex(), &LuaType::push_arrayproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("FloatProperty")).GetComparisonIndex(), &LuaType::push_floatproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("DoubleProperty")).GetComparisonIndex(), &LuaType::push_doubleproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("BoolProperty")).GetComparisonIndex(), &LuaType::push_boolproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("EnumProperty")).GetComparisonIndex(), &LuaType::push_enumproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("WeakObjectProperty")).GetComparisonIndex(), &LuaType::push_weakobjectproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("NameProperty")).GetComparisonIndex(), &LuaType::push_nameproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("TextProperty")).GetComparisonIndex(), &LuaType::push_textproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("StrProperty")).GetComparisonIndex(), &LuaType::push_strproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("SoftClassProperty")).GetComparisonIndex(), &LuaType::push_softclassproperty); + LuaType::StaticState::m_property_value_pushers.emplace(FName(STR("InterfaceProperty")).GetComparisonIndex(), &LuaType::push_interfaceproperty); } auto UE4SSProgram::setup_mods() -> void { ProfilerScope(); - Output::send(STR("Setting up mods...\n")); + Output::send(SYSSTR("Setting up mods...\n")); if (!std::filesystem::exists(m_mods_directory)) { @@ -1001,10 +1043,10 @@ namespace RC set_error("is_directory ran into error %d", ec.value()); } - std::wstring directory_lowercase = sub_directory.path().stem().wstring(); + SystemStringType directory_lowercase = sub_directory.path().stem().generic_string(); std::transform(directory_lowercase.begin(), directory_lowercase.end(), directory_lowercase.begin(), std::towlower); - if (directory_lowercase == L"shared") + if (directory_lowercase == SYSSTR("shared")) { // Do stuff when shared libraries have been implemented } @@ -1012,9 +1054,11 @@ namespace RC { // Create the mod but don't install it yet if (std::filesystem::exists(sub_directory.path() / "scripts")) - m_mods.emplace_back(std::make_unique(*this, sub_directory.path().stem().wstring(), sub_directory.path().wstring())); + m_mods.emplace_back(std::make_unique(*this, sub_directory.path().stem().generic_string(), sub_directory.path().generic_string())); +#ifdef HAS_CPPMOD if (std::filesystem::exists(sub_directory.path() / "dlls")) - m_mods.emplace_back(std::make_unique(*this, sub_directory.path().stem().wstring(), sub_directory.path().wstring())); + m_mods.emplace_back(std::make_unique(*this, sub_directory.path().stem().generic_string(), sub_directory.path().generic_string())); +#endif } } } @@ -1037,19 +1081,19 @@ namespace RC if (mod_name_is_taken) { mod->set_installable(false); - Output::send(STR("Mod name '{}' is already in use.\n"), mod->get_name()); + Output::send(SYSSTR("Mod name '{}' is already in use.\n"), mod->get_name()); continue; } if (mod->is_installed()) { - Output::send(STR("Tried to install a mod that was already installed, Mod: '{}'\n"), mod->get_name()); + Output::send(SYSSTR("Tried to install a mod that was already installed, Mod: '{}'\n"), mod->get_name()); continue; } if (!mod->is_installable()) { - Output::send(STR("Was unable to install mod '{}' for unknown reasons. Mod is not installable.\n"), mod->get_name()); + Output::send(SYSSTR("Was unable to install mod '{}' for unknown reasons. Mod is not installable.\n"), mod->get_name()); continue; } @@ -1059,7 +1103,9 @@ namespace RC auto UE4SSProgram::install_cpp_mods() -> void { + #ifdef HAS_CPPMOD install_mods(m_mods); + #endif } auto UE4SSProgram::install_lua_mods() -> void @@ -1072,10 +1118,12 @@ namespace RC ProfilerScope(); for (const auto& mod : m_mods) { + #ifdef HAS_CPPMOD if (!dynamic_cast(mod.get())) { continue; } + #endif mod->fire_unreal_init(); } } @@ -1098,22 +1146,26 @@ namespace RC ProfilerScope(); for (const auto& mod : m_mods) { + #ifdef HAS_CPPMOD if (!dynamic_cast(mod.get())) { continue; } + #endif mod->fire_program_start(); } } - auto UE4SSProgram::fire_dll_load_for_cpp_mods(std::wstring_view dll_name) -> void + auto UE4SSProgram::fire_dll_load_for_cpp_mods(SystemStringViewType dll_name) -> void { for (const auto& mod : m_mods) { + #ifdef HAS_CPPMOD if (auto cpp_mod = dynamic_cast(mod.get()); cpp_mod) { cpp_mod->fire_dll_load(dll_name); } + #endif } } @@ -1122,24 +1174,24 @@ namespace RC { ProfilerScope(); // Part #1: Start all mods that are enabled in mods.txt. - Output::send(STR("Starting mods (from mods.txt load order)...\n")); + Output::send(SYSSTR("Starting mods (from mods.txt load order)...\n")); std::filesystem::path mods_directory = UE4SSProgram::get_program().get_mods_directory(); - std::wstring enabled_mods_file{mods_directory / "mods.txt"}; + SystemStringType enabled_mods_file{mods_directory / "mods.txt"}; if (!std::filesystem::exists(enabled_mods_file)) { - Output::send(STR("No mods.txt file found...\n")); + Output::send(SYSSTR("No mods.txt file found...\n")); } else { // 'mods.txt' exists, lets parse it - std::wifstream mods_stream{enabled_mods_file}; + SystemStreamType mods_stream{enabled_mods_file}; - std::wstring current_line; + SystemStringType current_line; while (std::getline(mods_stream, current_line)) { // Don't parse any lines with ';' - if (current_line.find(L";") != current_line.npos) + if (current_line.find(SYSSTR(";")) != current_line.npos) { continue; } @@ -1151,12 +1203,12 @@ namespace RC } // Remove all spaces - auto end = std::remove(current_line.begin(), current_line.end(), L' '); + auto end = std::remove(current_line.begin(), current_line.end(), SYSSTR(' ')); current_line.erase(end, current_line.end()); // Parse the line into something that can be converted into proper data - std::wstring mod_name = explode_by_occurrence(current_line, L':', 1); - std::wstring mod_enabled = explode_by_occurrence(current_line, L':', ExplodeType::FromEnd); + SystemStringType mod_name = explode_by_occurrence(current_line, SYSSTR(':'), 1); + SystemStringType mod_enabled = explode_by_occurrence(current_line, SYSSTR(':'), ExplodeType::FromEnd); auto mod = UE4SSProgram::find_mod_by_name(mod_name, UE4SSProgram::IsInstalled::Yes); if (!mod || !dynamic_cast(mod)) @@ -1164,20 +1216,20 @@ namespace RC continue; } - if (!mod_enabled.empty() && mod_enabled[0] == L'1') + if (!mod_enabled.empty() && mod_enabled[0] == SYSSTR('1')) { - Output::send(STR("Starting {} mod '{}'\n"), std::is_same_v ? STR("Lua") : STR("C++"), mod->get_name().data()); + Output::send(SYSSTR("Starting {} mod '{}'\n"), std::is_same_v ? SYSSTR("Lua") : SYSSTR("C++"), mod->get_name().data()); mod->start_mod(); } else { - Output::send(STR("Mod '{}' disabled in mods.txt.\n"), mod_name); + Output::send(SYSSTR("Mod '{}' disabled in mods.txt.\n"), mod_name); } } } // Part #2: Start all mods that have enabled.txt present in the mod directory. - Output::send(STR("Starting mods (from enabled.txt, no defined load order)...\n")); + Output::send(SYSSTR("Starting mods (from enabled.txt, no defined load order)...\n")); for (const auto& mod_directory : std::filesystem::directory_iterator(mods_directory)) { @@ -1201,14 +1253,14 @@ namespace RC return std::format("exists ran into error {}", ec.value()); } - auto mod = UE4SSProgram::find_mod_by_name(mod_directory.path().stem().c_str(), UE4SSProgram::IsInstalled::Yes); + auto mod = UE4SSProgram::find_mod_by_name(mod_directory.path().stem().generic_string(), UE4SSProgram::IsInstalled::Yes); if (!dynamic_cast(mod)) { continue; } if (!mod) { - Output::send(STR("Found a mod with enabled.txt but mod has not been installed properly.\n")); + Output::send(SYSSTR("Found a mod with enabled.txt but mod has not been installed properly.\n")); continue; } @@ -1217,7 +1269,7 @@ namespace RC continue; } - Output::send(STR("Mod '{}' has enabled.txt, starting mod.\n"), mod->get_name().data()); + Output::send(SYSSTR("Mod '{}' has enabled.txt, starting mod.\n"), mod->get_name().data()); mod->start_mod(); } @@ -1236,6 +1288,7 @@ namespace RC auto UE4SSProgram::start_cpp_mods(IsInitialStartup is_initial_startup) -> void { + #ifdef HAS_CPPMOD ProfilerScope(); auto error_message = start_mods(); if (!error_message.empty()) @@ -1250,20 +1303,27 @@ namespace RC { fire_ui_init_for_cpp_mods(); } + #endif } auto UE4SSProgram::uninstall_mods() -> void { ProfilerScope(); + +#ifdef HAS_CPPMOD std::vector cpp_mods{}; +#endif std::vector lua_mods{}; for (auto& mod : m_mods) { +#ifdef HAS_CPPMOD if (auto cpp_mod = dynamic_cast(mod.get()); cpp_mod) { cpp_mods.emplace_back(cpp_mod); } - else if (auto lua_mod = dynamic_cast(mod.get()); lua_mod) + else +#endif + if (auto lua_mod = dynamic_cast(mod.get()); lua_mod) { lua_mods.emplace_back(lua_mod); } @@ -1275,11 +1335,12 @@ namespace RC mod->uninstall(); } +#ifdef HAS_CPPMOD for (auto& mod : cpp_mods) { mod->uninstall(); } - +#endif m_mods.clear(); LuaMod::global_uninstall(); } @@ -1292,7 +1353,7 @@ namespace RC auto UE4SSProgram::reinstall_mods() -> void { ProfilerScope(); - Output::send(STR("Re-installing all mods\n")); + Output::send(SYSSTR("Re-installing all mods\n")); // Stop processing events while stuff isn't properly setup m_pause_events_processing = true; @@ -1300,6 +1361,7 @@ namespace RC uninstall_mods(); // Remove key binds that were set from Lua scripts + #ifdef HAS_INPUT auto& key_events = m_input_handler.get_events(); std::erase_if(key_events, [](Input::KeySet& input_event) -> bool { bool were_all_events_registered_from_lua = true; @@ -1322,6 +1384,7 @@ namespace RC return were_all_events_registered_from_lua; }); + #endif // Remove all custom properties // Uncomment when custom properties are working @@ -1348,12 +1411,13 @@ namespace RC fire_program_start_for_cpp_mods(); } - Output::send(STR("All mods re-installed\n")); + Output::send(SYSSTR("All mods re-installed\n")); } auto UE4SSProgram::get_module_directory() -> File::StringViewType { - return m_module_file_path.c_str(); + m_module_file_path_str = m_module_file_path.generic_string(); + return m_module_file_path_str; } auto UE4SSProgram::get_game_executable_directory() -> File::StringViewType @@ -1363,12 +1427,14 @@ namespace RC auto UE4SSProgram::get_working_directory() -> File::StringViewType { - return m_working_directory.c_str(); + m_working_directory_str = m_working_directory.generic_string(); + return m_working_directory_str; } auto UE4SSProgram::get_mods_directory() -> File::StringViewType { - return m_mods_directory.c_str(); + m_mods_directory_str = m_mods_directory.generic_string(); + return m_mods_directory_str; } auto UE4SSProgram::get_legacy_root_directory() -> File::StringViewType @@ -1379,7 +1445,7 @@ namespace RC auto UE4SSProgram::generate_uht_compatible_headers() -> void { ProfilerScope(); - Output::send(STR("Generating UHT compatible headers...\n")); + Output::send(SYSSTR("Generating UHT compatible headers...\n")); double generator_duration{}; { @@ -1390,7 +1456,7 @@ namespace RC HeaderGenerator.dump_native_packages(); } - Output::send(STR("Generating UHT compatible headers took {} seconds\n"), generator_duration); + Output::send(SYSSTR("Generating UHT compatible headers took {} seconds\n"), generator_duration); } auto UE4SSProgram::generate_cxx_headers(const std::filesystem::path& output_dir) -> void @@ -1398,7 +1464,7 @@ namespace RC ProfilerScope(); if (settings_manager.CXXHeaderGenerator.LoadAllAssetsBeforeGeneratingCXXHeaders) { - Output::send(STR("Loading all assets...\n")); + Output::send(SYSSTR("Loading all assets...\n")); double asset_loading_duration{}; { ProfilerScopeNamed("loading all assets"); @@ -1406,7 +1472,7 @@ namespace RC UAssetRegistry::LoadAllAssets(); } - Output::send(STR("Loading all assets took {} seconds\n"), asset_loading_duration); + Output::send(SYSSTR("Loading all assets took {} seconds\n"), asset_loading_duration); } double generator_duration; @@ -1416,11 +1482,11 @@ namespace RC UEGenerator::generate_cxx_headers(output_dir); - Output::send(STR("Unloading all forcefully loaded assets\n")); + Output::send(SYSSTR("Unloading all forcefully loaded assets\n")); } UAssetRegistry::FreeAllForcefullyLoadedAssets(); - Output::send(STR("SDK generated in {} seconds.\n"), generator_duration); + Output::send(SYSSTR("SDK generated in {} seconds.\n"), generator_duration); } auto UE4SSProgram::generate_lua_types(const std::filesystem::path& output_dir) -> void @@ -1428,7 +1494,7 @@ namespace RC ProfilerScope(); if (settings_manager.CXXHeaderGenerator.LoadAllAssetsBeforeGeneratingCXXHeaders) { - Output::send(STR("Loading all assets...\n")); + Output::send(SYSSTR("Loading all assets...\n")); double asset_loading_duration{}; { ProfilerScopeNamed("loading all assets"); @@ -1436,7 +1502,7 @@ namespace RC UAssetRegistry::LoadAllAssets(); } - Output::send(STR("Loading all assets took {} seconds\n"), asset_loading_duration); + Output::send(SYSSTR("Loading all assets took {} seconds\n"), asset_loading_duration); } double generator_duration; @@ -1446,13 +1512,13 @@ namespace RC UEGenerator::generate_lua_types(output_dir); - Output::send(STR("Unloading all forcefully loaded assets\n")); + Output::send(SYSSTR("Unloading all forcefully loaded assets\n")); } UAssetRegistry::FreeAllForcefullyLoadedAssets(); - Output::send(STR("SDK generated in {} seconds.\n"), generator_duration); + Output::send(SYSSTR("SDK generated in {} seconds.\n"), generator_duration); } - +#ifdef HAS_GUI auto UE4SSProgram::stop_render_thread() -> void { if (m_render_thread.joinable()) @@ -1471,6 +1537,7 @@ namespace RC { m_debugging_gui.remove_tab(tab); } +#endif auto UE4SSProgram::queue_event(EventCallable callable, void* data) -> void { @@ -1488,6 +1555,7 @@ namespace RC return m_queued_events.empty(); } +#ifdef HAS_INPUT auto UE4SSProgram::register_keydown_event(Input::Key key, const Input::EventCallbackCallable& callback, uint8_t custom_data, void* custom_data2) -> void { m_input_handler.register_keydown_event(key, callback, custom_data, custom_data2); @@ -1511,8 +1579,8 @@ namespace RC { return m_input_handler.is_keydown_event_registered(key, modifier_keys); } - - auto UE4SSProgram::find_mod_by_name_internal(std::wstring_view mod_name, IsInstalled is_installed, IsStarted is_started, FMBNI_ExtraPredicate extra_predicate) +#endif + auto UE4SSProgram::find_mod_by_name_internal(SystemStringViewType mod_name, IsInstalled is_installed, IsStarted is_started, FMBNI_ExtraPredicate extra_predicate) -> Mod* { auto mod_exists_with_name = std::find_if(m_mods.begin(), m_mods.end(), [&](auto& elem) -> bool { @@ -1550,22 +1618,23 @@ namespace RC } } - auto UE4SSProgram::find_lua_mod_by_name(std::string_view mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* + auto UE4SSProgram::find_lua_mod_by_name(SystemStringViewType mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* { return static_cast(find_mod_by_name(mod_name, installed_only, is_started)); } - auto UE4SSProgram::find_lua_mod_by_name(std::wstring_view mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* + auto UE4SSProgram::find_lua_mod_by_name(UEViewType mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* { - return static_cast(find_mod_by_name(mod_name, installed_only, is_started)); + auto sysstr = UEStringToSystemString(UEStringType{mod_name}); + return static_cast(find_mod_by_name(sysstr, installed_only, is_started)); } auto UE4SSProgram::get_object_dumper_output_directory() -> const File::StringType { - return m_object_dumper_output_directory.c_str(); + return m_object_dumper_output_directory.generic_string(); } - auto UE4SSProgram::dump_uobject(UObject* object, std::unordered_set* in_dumped_fields, StringType& out_line, bool is_below_425) -> void + auto UE4SSProgram::dump_uobject(UObject* object, std::unordered_set* in_dumped_fields, SystemStringType& out_line, bool is_below_425) -> void { bool owns_dumped_fields{}; auto dumped_fields_ptr = [&] { @@ -1599,7 +1668,7 @@ namespace RC // Dump UObject ObjectDumper::get_to_string(typed_class)(object, out_line); - out_line.append(L"\n"); + out_line.append(SYSSTR("\n")); if (!is_below_425 && ObjectDumper::to_string_complex_exists(typed_class)) { @@ -1620,7 +1689,7 @@ namespace RC { // A type-specific implementation does not exist so lets call the default implementation for UObjects instead ObjectDumper::object_to_string(object, out_line); - out_line.append(L"\n"); + out_line.append(SYSSTR("\n")); } // If the UClass of the UObject has any properties then dump them @@ -1649,50 +1718,50 @@ namespace RC } } - auto UE4SSProgram::dump_xproperty(FProperty* property, StringType& out_line) -> void + auto UE4SSProgram::dump_xproperty(FProperty* property, SystemStringType& out_line) -> void { auto typed_prop_class = property->GetClass().HashObject(); if (ObjectDumper::to_string_exists(typed_prop_class)) { ObjectDumper::get_to_string(typed_prop_class)(property, out_line); - out_line.append(L"\n"); + out_line.append(SYSSTR("\n")); if (ObjectDumper::to_string_complex_exists(typed_prop_class)) { ObjectDumper::get_to_string_complex(typed_prop_class)(property, out_line, [&]([[maybe_unused]] void* prop) { - out_line.append(L"\n"); + out_line.append(SYSSTR("\n")); }); } } else { ObjectDumper::property_to_string(property, out_line); - out_line.append(L"\n"); + out_line.append(SYSSTR("\n")); } } auto UE4SSProgram::dump_all_objects_and_properties(const File::StringType& output_path_and_file_name) -> void { /* - Output::send(STR("Test msg with no fmt args, and no optional arg\n")); - Output::send(STR("Test msg with no fmt args, and one optional arg [Normal]\n"), LogLevel::Normal); - Output::send(STR("Test msg with no fmt args, and one optional arg [Verbose]\n"), LogLevel::Verbose); - Output::send(STR("Test msg with one fmt arg [{}], and one optional arg [Warning]\n"), LogLevel::Warning, 33); - Output::send(STR("Test msg with two fmt args [{}, {}], and one optional arg [Error]\n"), LogLevel::Error, 33, 44); + Output::send(SYSSTR("Test msg with no fmt args, and no optional arg\n")); + Output::send(SYSSTR("Test msg with no fmt args, and one optional arg [Normal]\n"), LogLevel::Normal); + Output::send(SYSSTR("Test msg with no fmt args, and one optional arg [Verbose]\n"), LogLevel::Verbose); + Output::send(SYSSTR("Test msg with one fmt arg [{}], and one optional arg [Warning]\n"), LogLevel::Warning, 33); + Output::send(SYSSTR("Test msg with two fmt args [{}, {}], and one optional arg [Error]\n"), LogLevel::Error, 33, 44); //*/ // Object & Property Dumper -> START if (settings_manager.ObjectDumper.LoadAllAssetsBeforeDumpingObjects) { - Output::send(STR("Loading all assets...\n")); + Output::send(SYSSTR("Loading all assets...\n")); double asset_loading_duration{}; { ScopedTimer loading_timer{&asset_loading_duration}; UAssetRegistry::LoadAllAssets(); } - Output::send(STR("Loading all assets took {} seconds\n"), asset_loading_duration); + Output::send(SYSSTR("Loading all assets took {} seconds\n"), asset_loading_duration); } double dumper_duration{}; @@ -1724,10 +1793,10 @@ namespace RC // Make string & reserve massive amounts of space to hopefully not reach the end of the string and require more // dynamic allocations - std::wstring out_line; + SystemStringType out_line; out_line.reserve(200000000); - Output::send(STR("Dumping all objects & properties in GUObjectArray\n")); + Output::send(SYSSTR("Dumping all objects & properties in GUObjectArray\n")); UObjectGlobals::ForEachUObject([&](void* object, [[maybe_unused]] int32_t chunk_index, [[maybe_unused]] int32_t object_index) { dump_uobject(static_cast(object), &dumped_fields, out_line, is_below_425); return LoopAction::Continue; @@ -1738,11 +1807,11 @@ namespace RC // Reset the dumped_fields set, otherwise no fields will be dumped in subsequent dumps dumped_fields.clear(); - Output::send(STR("Done iterating GUObjectArray\n")); + Output::send(SYSSTR("Done iterating GUObjectArray\n")); } UAssetRegistry::FreeAllForcefullyLoadedAssets(); - Output::send(STR("Dumping GUObjectArray took {} seconds\n"), dumper_duration); + Output::send(SYSSTR("Dumping GUObjectArray took {} seconds\n"), dumper_duration); // Object & Property Dumper -> END } diff --git a/UE4SS/src/USMapGenerator/Generator.cpp b/UE4SS/src/USMapGenerator/Generator.cpp index 78d5517c8..7701078c2 100644 --- a/UE4SS/src/USMapGenerator/Generator.cpp +++ b/UE4SS/src/USMapGenerator/Generator.cpp @@ -200,7 +200,7 @@ namespace RC::OutTheShade auto generate_usmap() -> void { - Output::send(STR("Mappings Generator by OutTheShade\nAttempting to dump mappings...\nPort of https://github.com/OutTheShade/UnrealMappingsDumper " + Output::send(SYSSTR("Mappings Generator by OutTheShade\nAttempting to dump mappings...\nPort of https://github.com/OutTheShade/UnrealMappingsDumper " "Commit SHA 4da8c66\n")); StreamWriter Buffer; @@ -299,11 +299,11 @@ namespace RC::OutTheShade if (Object->GetClassPrivate() == UClass::StaticClass() || Object->GetClassPrivate() == UScriptStruct::StaticClass() || Object->GetClassPrivate() == UEnum::StaticClass()) { - std::wstring RawPathName = Object->GetPathName(); - std::wstring::size_type PathNameStart = + UEStringType RawPathName = Object->GetPathName(); + UEStringType::size_type PathNameStart = 0; // include first bit (Script/Game) to avoid ambiguity; to drop it, replace with RawPathName.find_first_of('/', 1) + 1; - std::wstring::size_type PathNameLength = RawPathName.find_last_of('.') - PathNameStart; - std::wstring FinalPathStr = RawPathName.substr(PathNameStart, PathNameLength); + UEStringType::size_type PathNameLength = RawPathName.find_last_of('.') - PathNameStart; + UEStringType FinalPathStr = RawPathName.substr(PathNameStart, PathNameLength); FName FinalPathName = FName(FinalPathStr); NameMap.insert_or_assign(FinalPathName, 0); @@ -518,6 +518,6 @@ namespace RC::OutTheShade FileOutput.Write(UsmapData.data(), UsmapData.size()); - Output::send(STR("Mappings Generation Completed Successfully!\n")); + Output::send(SYSSTR("Mappings Generation Completed Successfully!\n")); } } // namespace RC::OutTheShade diff --git a/UVTD/include/UVTD/ExceptionHandling.hpp b/UVTD/include/UVTD/ExceptionHandling.hpp index ed3c0747f..a691a453d 100644 --- a/UVTD/include/UVTD/ExceptionHandling.hpp +++ b/UVTD/include/UVTD/ExceptionHandling.hpp @@ -21,7 +21,7 @@ namespace RC { if (!Output::has_internal_error()) { - Output::send(STR("Error: {}\n"), to_wstring(e.what())); + Output::send(SYSSTR("Error: {}\n"), to_wstring(e.what())); } else { diff --git a/UVTD/include/UVTD/Symbols.hpp b/UVTD/include/UVTD/Symbols.hpp index dfcf8f577..bc34b0f0b 100644 --- a/UVTD/include/UVTD/Symbols.hpp +++ b/UVTD/include/UVTD/Symbols.hpp @@ -56,7 +56,7 @@ namespace RC::UVTD auto to_string() const -> File::StringType { - return std::format(STR("{}"), type); + return std::format(SYSSTR("{}"), type); } }; @@ -74,10 +74,10 @@ namespace RC::UVTD for (size_t i = 0; i < params.size(); i++) { bool should_add_comma = i < params.size() - 1; - params_string.append(std::format(STR("{}{}"), params[i].to_string(), should_add_comma ? STR(", ") : STR(""))); + params_string.append(std::format(SYSSTR("{}{}"), params[i].to_string(), should_add_comma ? STR(", ") : STR(""))); } - return std::format(STR("{} {}({}){};"), return_type, name, params_string, const_qualifier ? STR("const") : STR("")); + return std::format(SYSSTR("{} {}({}){};"), return_type, name, params_string, const_qualifier ? STR("const") : STR("")); } }; diff --git a/UVTD/src/MemberVarsDumper.cpp b/UVTD/src/MemberVarsDumper.cpp index 5e6c8ab5f..4070394de 100644 --- a/UVTD/src/MemberVarsDumper.cpp +++ b/UVTD/src/MemberVarsDumper.cpp @@ -158,7 +158,7 @@ namespace RC::UVTD auto MemberVarsDumper::dump_member_variable_layouts(std::unordered_map& names) -> void { - Output::send(STR("Dumping {} symbols for {}\n"), names.size(), symbols.pdb_file_path.filename().stem().wstring()); + Output::send(SYSSTR("Dumping {} symbols for {}\n"), names.size(), symbols.pdb_file_path.filename().stem().wstring()); const PDB::TPIStream tpi_stream = PDB::CreateTPIStream(symbols.pdb_file); @@ -201,7 +201,7 @@ namespace RC::UVTD auto default_template_file = std::filesystem::path{STR("MemberVariableLayout.ini")}; - Output::send(STR("Generating file '{}'\n"), default_template_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), default_template_file.wstring()); Output::Targets default_ini_dumper; auto& default_ini_file_device = default_ini_dumper.get_device(); @@ -210,9 +210,9 @@ namespace RC::UVTD return File::StringType{string}; }); - auto template_file = std::format(STR("MemberVariableLayout_{}_Template.ini"), pdb_name); + auto template_file = std::format(SYSSTR("MemberVariableLayout_{}_Template.ini"), pdb_name); - Output::send(STR("Generating file '{}'\n"), template_file); + Output::send(SYSSTR("Generating file '{}'\n"), template_file); Output::Targets ini_dumper; auto& ini_file_device = ini_dumper.get_device(); @@ -232,9 +232,9 @@ namespace RC::UVTD } auto default_setter_src_file = member_variable_layouts_gen_function_bodies_path / - std::format(STR("{}_MemberVariableLayout_DefaultSetter_{}.cpp"), pdb_name, class_entry.class_name_clean); + std::format(SYSSTR("{}_MemberVariableLayout_DefaultSetter_{}.cpp"), pdb_name, class_entry.class_name_clean); - Output::send(STR("Generating file '{}'\n"), default_setter_src_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), default_setter_src_file.wstring()); Output::Targets default_setter_src_dumper; auto& default_setter_src_file_device = default_setter_src_dumper.get_device(); diff --git a/UVTD/src/MemberVarsWrapperGenerator.cpp b/UVTD/src/MemberVarsWrapperGenerator.cpp index a408c9c6e..e276f3975 100644 --- a/UVTD/src/MemberVarsWrapperGenerator.cpp +++ b/UVTD/src/MemberVarsWrapperGenerator.cpp @@ -10,7 +10,7 @@ namespace RC::UVTD { auto macro_setter_file = std::filesystem::path{STR("MacroSetter.hpp")}; - Output::send(STR("Generating file '{}'\n"), macro_setter_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), macro_setter_file.wstring()); Output::Targets macro_setter_dumper; auto& macro_setter_file_device = macro_setter_dumper.get_device(); @@ -27,9 +27,9 @@ namespace RC::UVTD } auto wrapper_header_file = member_variable_layouts_gen_output_include_path / - std::format(STR("MemberVariableLayout_HeaderWrapper_{}.hpp"), class_entry.class_name_clean); + std::format(SYSSTR("MemberVariableLayout_HeaderWrapper_{}.hpp"), class_entry.class_name_clean); - Output::send(STR("Generating file '{}'\n"), wrapper_header_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), wrapper_header_file.wstring()); Output::Targets header_wrapper_dumper; auto& wrapper_header_file_device = header_wrapper_dumper.get_device(); @@ -39,9 +39,9 @@ namespace RC::UVTD }); auto wrapper_src_file = - member_variable_layouts_gen_output_include_path / std::format(STR("MemberVariableLayout_SrcWrapper_{}.hpp"), class_entry.class_name_clean); + member_variable_layouts_gen_output_include_path / std::format(SYSSTR("MemberVariableLayout_SrcWrapper_{}.hpp"), class_entry.class_name_clean); - Output::send(STR("Generating file '{}'\n"), wrapper_src_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), wrapper_src_file.wstring()); Output::Targets wrapper_src_dumper; auto& wrapper_src_file_device = wrapper_src_dumper.get_device(); diff --git a/UVTD/src/SolBindingsGenerator.cpp b/UVTD/src/SolBindingsGenerator.cpp index 45e7f2206..d869a091f 100644 --- a/UVTD/src/SolBindingsGenerator.cpp +++ b/UVTD/src/SolBindingsGenerator.cpp @@ -26,9 +26,9 @@ namespace RC::UVTD auto final_class_name = class_name; - auto wrapper_header_file = sol_bindings_output_path / std::format(STR("SolBindings_{}.hpp"), final_class_name_clean); + auto wrapper_header_file = sol_bindings_output_path / std::format(SYSSTR("SolBindings_{}.hpp"), final_class_name_clean); - Output::send(STR("Generating file '{}'\n"), wrapper_header_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), wrapper_header_file.wstring()); Output::Targets header_wrapper_dumper; diff --git a/UVTD/src/Symbols.cpp b/UVTD/src/Symbols.cpp index 59e43c2da..67b6a3722 100644 --- a/UVTD/src/Symbols.cpp +++ b/UVTD/src/Symbols.cpp @@ -246,7 +246,7 @@ namespace RC::UVTD case PDB::CodeView::TPI::TypeRecordKind::LF_PROCEDURE: { File::StringType return_type = get_type_name(tpi_stream, record->data.LF_PROCEDURE.rvtype, true); File::StringType args = get_type_name(tpi_stream, record->data.LF_PROCEDURE.arglist, check_valid); - return std::format(STR("std::function<{}({})>"), return_type, args); + return std::format(SYSSTR("std::function<{}({})>"), return_type, args); } case PDB::CodeView::TPI::TypeRecordKind::LF_ARGLIST: { File::StringType args{}; @@ -254,7 +254,7 @@ namespace RC::UVTD for (size_t i = 0; i < record->data.LF_ARGLIST.count; i++) { bool should_add_comma = i < record->data.LF_ARGLIST.count - 1; - args.append(std::format(STR("{}{}"), get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true), should_add_comma ? STR(", ") : STR(""))); + args.append(std::format(SYSSTR("{}{}"), get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true), should_add_comma ? STR(", ") : STR(""))); } return args; diff --git a/UVTD/src/UVTD.cpp b/UVTD/src/UVTD.cpp index b65488a5e..e53c5fe78 100644 --- a/UVTD/src/UVTD.cpp +++ b/UVTD/src/UVTD.cpp @@ -117,7 +117,7 @@ namespace RC::UVTD shared_container.join(run_container); - Output::send(STR("Code generated.\n")); + Output::send(SYSSTR("Code generated.\n")); } }); } @@ -128,9 +128,9 @@ namespace RC::UVTD MemberVarsWrapperGenerator wrapper_generator{std::move(shared_container)}; wrapper_generator.generate_files(); - Output::send(STR("Code generated.\n")); + Output::send(SYSSTR("Code generated.\n")); } - Output::send(STR("All done.\n")); + Output::send(SYSSTR("All done.\n")); } } // namespace RC::UVTD diff --git a/UVTD/src/UnrealVirtualGenerator.cpp b/UVTD/src/UnrealVirtualGenerator.cpp index f3ab28c48..979c45eab 100644 --- a/UVTD/src/UnrealVirtualGenerator.cpp +++ b/UVTD/src/UnrealVirtualGenerator.cpp @@ -10,9 +10,9 @@ namespace RC::UVTD auto pdb_name_no_underscore = pdb_name; pdb_name_no_underscore.replace(pdb_name_no_underscore.find(STR('_')), 1, STR("")); - auto virtual_header_file = virtual_gen_output_include_path / std::format(STR("UnrealVirtual{}.hpp"), pdb_name_no_underscore); + auto virtual_header_file = virtual_gen_output_include_path / std::format(SYSSTR("UnrealVirtual{}.hpp"), pdb_name_no_underscore); - Output::send(STR("Generating file '{}'\n"), virtual_header_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), virtual_header_file.wstring()); Output::Targets virtual_header_dumper; auto& virtual_header_file_device = virtual_header_dumper.get_device(); @@ -21,9 +21,9 @@ namespace RC::UVTD return File::StringType{string}; }); - auto virtual_src_file = virtual_gen_function_bodies_path / std::format(STR("UnrealVirtual{}.cpp"), pdb_name_no_underscore); + auto virtual_src_file = virtual_gen_function_bodies_path / std::format(SYSSTR("UnrealVirtual{}.cpp"), pdb_name_no_underscore); - Output::send(STR("Generating file '{}'\n"), virtual_src_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), virtual_src_file.wstring()); Output::Targets virtual_src_dumper; auto& virtual_src_file_device = virtual_src_dumper.get_device(); diff --git a/UVTD/src/VTableDumper.cpp b/UVTD/src/VTableDumper.cpp index 485c547cc..0cdc54cf0 100644 --- a/UVTD/src/VTableDumper.cpp +++ b/UVTD/src/VTableDumper.cpp @@ -90,7 +90,7 @@ namespace RC::UVTD File::StringType overload_name = method_name_clean; if (overload_index != 0) { - overload_name += std::format(STR("_{}"), overload_index); + overload_name += std::format(SYSSTR("_{}"), overload_index); } overload_index++; @@ -120,12 +120,12 @@ namespace RC::UVTD { if (auto it2 = it->second.find(method_name); it2 != it->second.end()) { - method_name.append(std::format(STR("_{}"), ++it2->second)); + method_name.append(std::format(SYSSTR("_{}"), ++it2->second)); is_overload = true; } } - Output::send(STR(" method {} offset {}\n"), method_name, vtable_offset); + Output::send(SYSSTR(" method {} offset {}\n"), method_name, vtable_offset); File::StringType method_name_clean = Symbols::clean_name(method_name); @@ -139,7 +139,7 @@ namespace RC::UVTD auto VTableDumper::dump_vtable_for_symbol(std::unordered_map& names) -> void { - Output::send(STR("Dumping {} struct symbols for {}\n"), names.size(), symbols.pdb_file_path.filename().stem().wstring()); + Output::send(SYSSTR("Dumping {} struct symbols for {}\n"), names.size(), symbols.pdb_file_path.filename().stem().wstring()); const PDB::TPIStream tpi_stream = PDB::CreateTPIStream(symbols.pdb_file); @@ -181,11 +181,11 @@ namespace RC::UVTD for (const auto& [class_name, class_entry] : type_container.get_class_entries()) { - Output::send(STR("Generating file '{}_VTableOffsets_{}_FunctionBody.cpp'\n"), pdb_name, class_entry.class_name_clean); + Output::send(SYSSTR("Generating file '{}_VTableOffsets_{}_FunctionBody.cpp'\n"), pdb_name, class_entry.class_name_clean); Output::Targets function_body_dumper; auto& function_body_file_device = function_body_dumper.get_device(); function_body_file_device.set_file_name_and_path(vtable_gen_output_function_bodies_path / - std::format(STR("{}_VTableOffsets_{}_FunctionBody.cpp"), pdb_name, class_name)); + std::format(SYSSTR("{}_VTableOffsets_{}_FunctionBody.cpp"), pdb_name, class_name)); function_body_file_device.set_formatter([](File::StringViewType string) { return File::StringType{string}; }); @@ -208,8 +208,8 @@ namespace RC::UVTD } } - auto template_file = std::format(STR("VTableLayout_{}_Template.ini"), pdb_name); - Output::send(STR("Generating file '{}'\n"), template_file); + auto template_file = std::format(SYSSTR("VTableLayout_{}_Template.ini"), pdb_name); + Output::send(SYSSTR("Generating file '{}'\n"), template_file); Output::Targets ini_dumper; auto& ini_file_device = ini_dumper.get_device(); ini_file_device.set_file_name_and_path(vtable_templates_output_path / template_file); diff --git a/UVTD/src/main.cpp b/UVTD/src/main.cpp index 1a63c13c8..3d7cf8ebf 100644 --- a/UVTD/src/main.cpp +++ b/UVTD/src/main.cpp @@ -12,12 +12,12 @@ using namespace RC; auto static get_user_selection() -> int32_t { - Output::send(STR("What would you like to do ?\n")); - Output::send(STR("1. Generate VTable layouts\n")); - Output::send(STR("2. Generate class/struct member variable layouts\n")); - Output::send(STR("3. Generate sol bindings\n")); - Output::send(STR("4. Everything\n")); - Output::send(STR("0. Exit\n")); + Output::send(SYSSTR("What would you like to do ?\n")); + Output::send(SYSSTR("1. Generate VTable layouts\n")); + Output::send(SYSSTR("2. Generate class/struct member variable layouts\n")); + Output::send(SYSSTR("3. Generate sol bindings\n")); + Output::send(SYSSTR("4. Everything\n")); + Output::send(SYSSTR("0. Exit\n")); int32_t selection{}; std::cin >> selection; @@ -53,7 +53,7 @@ auto thread_dll_start([[maybe_unused]] LPVOID thread_param) -> unsigned long try { - Output::send(STR("Unreal Virtual Table Dumper -> START\n")); + Output::send(SYSSTR("Unreal Virtual Table Dumper -> START\n")); for (int32_t selection = get_user_selection(); selection != 1337; selection = get_user_selection()) { @@ -64,22 +64,22 @@ auto thread_dll_start([[maybe_unused]] LPVOID thread_param) -> unsigned long } else if (selection == 1) { - Output::send(STR("Generating VTable layouts...\n")); + Output::send(SYSSTR("Generating VTable layouts...\n")); settings.should_dump_vtable = true; } else if (selection == 2) { - Output::send(STR("Generating class/struct member variable layouts...\n")); + Output::send(SYSSTR("Generating class/struct member variable layouts...\n")); settings.should_dump_member_vars = true; } else if (selection == 3) { - Output::send(STR("Generating sol bindings...\n")); + Output::send(SYSSTR("Generating sol bindings...\n")); settings.should_dump_sol_bindings = true; } else if (selection == 4) { - Output::send(STR("Generating VTable layouts and class/struct member variable layouts...\n")); + Output::send(SYSSTR("Generating VTable layouts and class/struct member variable layouts...\n")); settings.should_dump_vtable = true; settings.should_dump_member_vars = true; } @@ -89,7 +89,7 @@ auto thread_dll_start([[maybe_unused]] LPVOID thread_param) -> unsigned long } catch (std::exception& e) { - Output::send(STR("Exception caught: {}\n"), to_wstring(e.what())); + Output::send(SYSSTR("Exception caught: {}\n"), to_wstring(e.what())); } return 0; diff --git a/cmake/Findzydis.cmake b/cmake/Findzydis.cmake new file mode 100644 index 000000000..be830bd8c --- /dev/null +++ b/cmake/Findzydis.cmake @@ -0,0 +1 @@ +# nothing to do diff --git a/deps/first/ASMHelper/include/ASMHelper/Common.hpp b/deps/first/ASMHelper/include/ASMHelper/Common.hpp index 1cf9fedad..58638eef5 100644 --- a/deps/first/ASMHelper/include/ASMHelper/Common.hpp +++ b/deps/first/ASMHelper/include/ASMHelper/Common.hpp @@ -1,5 +1,6 @@ #pragma once +#ifdef WIN32 #ifndef RC_ASM_HELPER_EXPORTS #ifndef RC_ASM_HELPER_BUILD_STATIC #ifndef RC_ASM_API @@ -15,3 +16,12 @@ #define RC_ASM_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_ASM_API +#define RC_ASM_API +#endif + +#endif + diff --git a/deps/first/ASMHelper/src/ASMHelper.cpp b/deps/first/ASMHelper/src/ASMHelper.cpp index bf59ba5cd..2f1a3a6b2 100644 --- a/deps/first/ASMHelper/src/ASMHelper.cpp +++ b/deps/first/ASMHelper/src/ASMHelper.cpp @@ -4,9 +4,11 @@ #include #include +#include + namespace RC::ASM { - auto get_first_instruction_at_address(void* in_instruction_ptr) -> Instruction + auto get_first_instruction_at_address(void* in_instruction_ptr) -> std::pair> { auto instruction_ptr = static_cast(in_instruction_ptr); ZydisDecoder decoder{}; @@ -23,9 +25,9 @@ namespace RC::ASM auto resolve_absolute_address(void* in_instruction_ptr) -> void* { - auto instruction = get_first_instruction_at_address(in_instruction_ptr); + auto [instruction, operands] = get_first_instruction_at_address(in_instruction_ptr); ZyanU64 resolved_address{}; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&instruction.raw, &instruction.operands[0], std::bit_cast(in_instruction_ptr), &resolved_address))) + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&instruction.raw, &operands[0], std::bit_cast(in_instruction_ptr), &resolved_address))) { return std::bit_cast(resolved_address); } @@ -47,7 +49,7 @@ namespace RC::ASM auto resolve_function_address_from_potential_jmp(void* function_ptr) -> void* { - auto instruction = get_first_instruction_at_address(function_ptr); + auto [instruction, _] = get_first_instruction_at_address(function_ptr); if (instruction.raw.mnemonic == ZYDIS_MNEMONIC_JMP || instruction.raw.mnemonic == ZYDIS_MNEMONIC_CALL) { if (auto resolved_address = resolve_jmp(instruction.address); resolved_address) @@ -56,7 +58,7 @@ namespace RC::ASM } else { - Output::send(STR("Was unable to resolve JMP instruction @ {}\n"), instruction.address); + Output::send(SYSSTR("Was unable to resolve JMP instruction @ {}\n"), instruction.address); return nullptr; } } diff --git a/deps/first/Constructs/include/Constructs/Annotated.hpp b/deps/first/Constructs/include/Constructs/Annotated.hpp index c22380ebb..53ee07a4b 100644 --- a/deps/first/Constructs/include/Constructs/Annotated.hpp +++ b/deps/first/Constructs/include/Constructs/Annotated.hpp @@ -24,7 +24,7 @@ namespace RC * Annotated, int> annotated_integer(123); * * for (const auto& comment : comments) { - * Output::send(STR("{}\n"), comment); + * Output::send(SYSSTR("{}\n"), comment); * } * @endcode */ diff --git a/deps/first/Constructs/include/Constructs/Generator.hpp b/deps/first/Constructs/include/Constructs/Generator.hpp index 6edae7e5d..f3f7196dd 100644 --- a/deps/first/Constructs/include/Constructs/Generator.hpp +++ b/deps/first/Constructs/include/Constructs/Generator.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +// #include #include namespace RC diff --git a/deps/first/DynamicOutput/include/DynamicOutput/Common.hpp b/deps/first/DynamicOutput/include/DynamicOutput/Common.hpp index 173e00f16..1f8302b5c 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/Common.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_DYNAMIC_OUTPUT_EXPORTS #ifndef RC_DYNAMIC_OUTPUT_BUILD_STATIC #ifndef RC_DYNOUT_API @@ -15,3 +17,11 @@ #define RC_DYNOUT_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_DYNOUT_API +#define RC_DYNOUT_API +#endif + +#endif \ No newline at end of file diff --git a/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp index b62cdf320..ff5c57191 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp @@ -14,8 +14,9 @@ namespace RC::Output mutable bool m_windows_console_mode_set{}; private: +#ifdef WIN32 auto set_windows_console_out_mode_if_needed() const -> void; - +#endif public: public: #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE diff --git a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp index ee2e0c087..0182d3f83 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp @@ -19,7 +19,11 @@ #if RC_IS_ANSI == 1 #define RC_STD_MAKE_FORMAT_ARGS std::make_format_args #else +#ifdef WIN32 #define RC_STD_MAKE_FORMAT_ARGS std::make_wformat_args +#else +#define RC_STD_MAKE_FORMAT_ARGS std::make_format_args +#endif #endif namespace RC::Output @@ -122,11 +126,11 @@ namespace RC::Output if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat(content), RC_STD_MAKE_FORMAT_ARGS(static_cast(optional_arg))); + device->receive_with_optional_arg(content, 0); } else { - device->receive(std::vformat(content)); + device->receive(content); } } } @@ -343,11 +347,11 @@ namespace RC::Output if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...)), optional_arg); + device->receive_with_optional_arg(std::vformat((std::string)content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...)), optional_arg); } else { - device->receive(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); + device->receive(std::vformat((std::string)content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); } } } diff --git a/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp index f8b8b371e..48c6249cf 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp @@ -63,9 +63,9 @@ namespace RC::Output } #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE - printf_s("TestDevice received: %S", fmt.c_str()); + printf_s("TestDevice received: "SystemStringPrint, fmt.c_str()); #else - printf_s("%S", fmt.data()); + printf_s(SystemStringPrint, fmt.data()); #endif } }; diff --git a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp index 71ef287d6..fc897c241 100644 --- a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp +++ b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp @@ -4,8 +4,11 @@ #include #include +#ifdef WIN32 #define NOMINMAX #include +#endif + #ifdef TEXT #undef TEXT #endif @@ -36,6 +39,7 @@ namespace RC::Output return "\033[0;0m"; } + #ifdef WIN32 auto DebugConsoleDevice::set_windows_console_out_mode_if_needed() const -> void { if (m_windows_console_mode_set) @@ -51,6 +55,7 @@ namespace RC::Output } m_windows_console_mode_set = true; } + #endif auto DebugConsoleDevice::has_optional_arg() const -> bool { @@ -64,12 +69,14 @@ namespace RC::Output auto DebugConsoleDevice::receive_with_optional_arg(File::StringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void { + #ifdef WIN32 set_windows_console_out_mode_if_needed(); + #endif #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE printf_s("DebugConsoleDevice received: %S", m_formatter(fmt).c_str()); #else - printf_s("%s%S\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); + printf_s("%s" SystemStringPrint"\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); #endif } } // namespace RC::Output diff --git a/deps/first/DynamicOutput/src/OutputDevice.cpp b/deps/first/DynamicOutput/src/OutputDevice.cpp index 7f20019d3..e7bae076e 100644 --- a/deps/first/DynamicOutput/src/OutputDevice.cpp +++ b/deps/first/DynamicOutput/src/OutputDevice.cpp @@ -25,12 +25,12 @@ namespace RC::Output auto OutputDevice::get_now_as_string() -> const File::StringType { auto now = std::chrono::system_clock::now(); - const File::StringType when_as_string = std::format(STR("{:%Y-%m-%d %X}"), now); + const File::StringType when_as_string = std::format(SYSSTR("{:%Y-%m-%d %X}"), now); return when_as_string; } auto OutputDevice::default_format_string(File::StringViewType string_to_format) -> File::StringType { - return std::format(STR("[{}] {}"), get_now_as_string(), string_to_format); + return std::format(SYSSTR("[{}] {}"), get_now_as_string(), string_to_format); } } // namespace RC::Output diff --git a/deps/first/File/include/File/Common.hpp b/deps/first/File/include/File/Common.hpp index 0aaf2cec5..caad17e9c 100644 --- a/deps/first/File/include/File/Common.hpp +++ b/deps/first/File/include/File/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_FILE_EXPORTS #ifndef RC_FILE_BUILD_STATIC #ifndef RC_FILE_API @@ -15,3 +17,11 @@ #define RC_FILE_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_FILE_API +#define RC_FILE_API +#endif + +#endif \ No newline at end of file diff --git a/deps/first/File/include/File/FileDef.hpp b/deps/first/File/include/File/FileDef.hpp index 19efd9129..6d5d4204b 100644 --- a/deps/first/File/include/File/FileDef.hpp +++ b/deps/first/File/include/File/FileDef.hpp @@ -3,16 +3,27 @@ namespace RC::File { #ifndef RC_DETECTED_OS +#ifdef WIN32 #ifdef _WIN32 #define RC_DETECTED_OS _WIN32 #else static_assert(false, "Could not setup the 'Handle' typedef because a supported OS was not detected."); #endif + +#else + +#ifdef LINUX +#define RC_DETECTED_OS LINUX +#else + static_assert(false, "Could not setup the 'Handle' typedef because a supported OS was not detected."); +#endif + +#endif #endif -#if RC_DETECTED_OS == _WIN32 +#if RC_DETECTED_OS == LINUX #ifndef RC_OS_FILE_TYPE_INCLUDE_FILE -#define RC_OS_FILE_TYPE_INCLUDE_FILE +#define RC_OS_FILE_TYPE_INCLUDE_FILE #else static_assert(false, "Could not setup the 'RC_OS_FILE_TYPE_INCLUDE_FILE' macro because a supported OS was not detected."); #endif diff --git a/deps/first/File/include/File/FileType/All.hpp b/deps/first/File/include/File/FileType/All.hpp index 4c9ce44db..a9d5f52e2 100644 --- a/deps/first/File/include/File/FileType/All.hpp +++ b/deps/first/File/include/File/FileType/All.hpp @@ -1,3 +1,6 @@ #pragma once - +#ifdef WIN32 #include +#else +#include +#endif \ No newline at end of file diff --git a/deps/first/File/include/File/FileType/StdFile.hpp b/deps/first/File/include/File/FileType/StdFile.hpp new file mode 100644 index 000000000..a4282998d --- /dev/null +++ b/deps/first/File/include/File/FileType/StdFile.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace RC::File +{ + class StdFile : public FileInterface + { + private: + using HANDLE = FILE*; + + struct IdentifyingProperties + { + struct stat file_stat{}; + }; + + private: + HANDLE m_file{}; + uint8_t* m_memory_map{}; + size_t m_memory_map_size{}; + OpenProperties m_open_properties{}; + std::filesystem::path m_file_path_and_name{}; + std::filesystem::path m_serialization_file_path_and_name{}; + IdentifyingProperties m_identifying_properties{}; + constexpr static inline size_t cache_size = 0x500; + unsigned char m_cache[cache_size]{}; + size_t m_offset_to_next_serialized_item{}; + bool m_has_cache_in_memory{}; + bool m_has_cached_identifying_properties{}; + bool m_is_file_open{}; + + public: + ~StdFile() override = default; + + private: + auto static create_all_directories(const std::filesystem::path& file_name_and_path) -> void; + + private: + auto close_file() -> void; + + public: + [[nodiscard]] auto is_file_open() const -> bool; + + public: + RC_FILE_API auto set_file(HANDLE new_file) -> void; + RC_FILE_API auto set_is_file_open(bool new_is_open) -> void; + RC_FILE_API auto get_file() -> HANDLE; + RC_FILE_API auto serialization_file_exists() -> bool; + + // File Interface -> START + RC_FILE_API auto is_valid() noexcept -> bool override; + RC_FILE_API auto invalidate_file() noexcept -> void override; + RC_FILE_API auto static delete_file(const std::filesystem::path&) -> void; + RC_FILE_API auto delete_file() -> void override; + RC_FILE_API auto get_raw_handle() noexcept -> void* override; + [[nodiscard]] RC_FILE_API auto get_file_path() const noexcept -> const std::filesystem::path& override; + RC_FILE_API auto set_serialization_output_file(const std::filesystem::path& output_file) noexcept -> void override; + RC_FILE_API auto serialize_identifying_properties() -> void override; + RC_FILE_API auto deserialize_identifying_properties() -> void override; + RC_FILE_API auto is_deserialized_and_live_equal() -> bool override; + RC_FILE_API auto invalidate_serialization() -> void override; + RC_FILE_API auto serialize_item(const GenericItemData& data, bool is_internal_item = false) -> void override; + RC_FILE_API auto get_serialized_item(size_t data_size, bool is_internal_item = false) -> void* override; + RC_FILE_API auto close_current_file() -> void override; + RC_FILE_API auto write_string_to_file(StringViewType string_to_write) -> void override; + RC_FILE_API auto is_same_as(StdFile& other_file) -> bool override; + [[nodiscard]] RC_FILE_API auto read_all() const -> StringType override; + [[nodiscard]] RC_FILE_API auto memory_map() -> std::span override; + [[nodiscard]] RC_FILE_API auto static open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> StdFile; + // File Interface -> END + }; + + // This file is automatically included ONLY if Windows is detected + // Therefore, it's not necessary to do any checks here + template + class HandleTemplate; + using Handle = HandleTemplate; +} // namespace RC::File diff --git a/deps/first/File/include/File/Macros.hpp b/deps/first/File/include/File/Macros.hpp index fb27b48a3..d35bfd989 100644 --- a/deps/first/File/include/File/Macros.hpp +++ b/deps/first/File/include/File/Macros.hpp @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include + // Set this to 1 to use ANSI (char*) instead of wide strings (wchar_t*) #ifndef RC_IS_ANSI #define RC_IS_ANSI 0 @@ -7,8 +11,21 @@ #if RC_IS_ANSI == 1 #define STR(str) u##str +#define SYSSTR(str) str +#else +#ifdef LINUX +#define STR(str) u##str +#define SYSSTR(str) str #else #define STR(str) L##str +#define SYSSTR(str) L##str +#endif +#endif + +#ifdef S +static_assert(false, "UE4SS define 'S' is already defined, please solve this"); +#else +//#define S(str) STR(str) #endif #define THROW_INTERNAL_FILE_ERROR(msg) \ @@ -33,29 +50,63 @@ namespace RC::File using StringViewType = std::string_view; using CharType = char; using StreamType = std::ifstream; - using ToString = std::tostring; + // using ToString = std::tostring; constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { return std::to_string(std::forward(numeric_value)); }; #else +#ifdef WIN32 using StringType = std::wstring; using StringViewType = std::wstring_view; using CharType = wchar_t; using StreamType = std::wifstream; - constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { return std::to_wstring(std::forward(numeric_value)); }; +#else +// on linux, use utf8 + using StringType = std::string; + using StringViewType = std::string_view; + using CharType = char; + using StreamType = std::ifstream; + + constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_string(std::forward(numeric_value)); + }; +#endif #endif } // namespace RC::File namespace RC { - using StringType = File::StringType; - using StringViewType = File::StringViewType; - using CharType = File::CharType; - using StreamType = File::StreamType; + using SystemStringType = File::StringType; + using SystemStringViewType = File::StringViewType; + using SystemCharType = File::CharType; + using SystemStreamType = File::StreamType; + +#ifdef WIN32 + using UEStringType = File::StringType; + using UEViewType = File::StringViewType; + using UECharType = File::CharType; + #define SystemStringPrint "%S" + #define UEStringPrint "%S" + static auto SystemStringToUEString = [](const SystemStringType& str) -> UEStringType { return str; }; + static auto UEStringToSystemString = [](const UEStringType& str) -> SystemStringType { return str; }; +#else + using UEStringType = std::u16string; + using UEViewType = std::u16string_view; + using UECharType = char16_t; + #define SystemStringPrint "%s" + #define UEStringPrint "%S" + static auto SystemStringToUEString = [](const SystemStringType& str) -> UEStringType { + static std::wstring_convert, char16_t> converter{}; + return converter.from_bytes((std::string)str); + }; + static auto UEStringToSystemString = [](const UEStringType& str) -> SystemStringType { + return std::wstring_convert, char16_t>{}.to_bytes((std::u16string)str); + }; +#endif constexpr auto ToString = File::ToString; } // namespace RC diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp new file mode 100644 index 000000000..830d479f9 --- /dev/null +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -0,0 +1,516 @@ +#include +#include + +#include +#include +#include + +#include + +namespace RC::File +{ + auto StdFile::is_valid() noexcept -> bool + { + return m_file != nullptr; + } + + auto StdFile::invalidate_file() noexcept -> void { + m_file = nullptr; + } + + auto StdFile::delete_file(const std::filesystem::path& file_path_and_name) -> void + { + std::filesystem::remove(file_path_and_name); + } + + auto StdFile::delete_file() -> void + { + if (m_is_file_open) + { + close_file(); + } + + delete_file(m_file_path_and_name); + } + + auto StdFile::set_file(HANDLE new_file) -> void + { + m_file = new_file; + } + + + auto StdFile::get_file() -> HANDLE + { + return m_file; + } + + auto StdFile::set_is_file_open(bool new_is_open) -> void + { + m_is_file_open = new_is_open; + } + + auto StdFile::get_raw_handle() noexcept -> void* + { + return static_cast(m_file); + } + + auto StdFile::get_file_path() const noexcept -> const std::filesystem::path& + { + return m_file_path_and_name; + } + + auto StdFile::set_serialization_output_file(const std::filesystem::path& output_file) noexcept -> void + { + m_serialization_file_path_and_name = output_file; + } + + auto StdFile::serialization_file_exists() -> bool + { + return std::filesystem::exists(m_serialization_file_path_and_name); + } + + template + auto write_to_file(StdFile& file, DataType* data, size_t num_bytes_to_write) -> void + { + if (!file.is_file_open()) + { + THROW_INTERNAL_FILE_ERROR("[StdFile::write_to_file] Tried writing to file but the file is not open") + } + + size_t bytes_written = fwrite(data, sizeof(DataType), num_bytes_to_write, file.get_file()); + if (bytes_written < 0) { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::write_to_file] Tried writing to file but was unable to complete operation. Error: {}", bytes_written)); + } + } + + auto StdFile::serialize_identifying_properties() -> void + { + if (m_serialization_file_path_and_name.empty()) + { + THROW_INTERNAL_FILE_ERROR("[StdFile::serialize_identifying_properties]: Path & file name for serialization file is empty, please call " + "'set_serialization_output_file'") + } + + struct stat file_info{}; + fstat(fileno(m_file), &file_info); + + serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_dev}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_ino}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_mode}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_nlink}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_uid}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_gid}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_rdev}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::SignedLong, .data_long = file_info.st_size}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::SignedLong, .data_long = file_info.st_atime}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::SignedLong, .data_long = file_info.st_mtime}, true); + serialize_item(GenericItemData{.data_type = GenericDataType::SignedLong, .data_long = file_info.st_ctime}, true); + + } + + auto StdFile::deserialize_identifying_properties() -> void + { + m_identifying_properties.file_stat.st_dev = *static_cast(get_serialized_item(sizeof(unsigned long), true)); + m_identifying_properties.file_stat.st_ino = *static_cast(get_serialized_item(sizeof(unsigned long), true)); + m_identifying_properties.file_stat.st_mode = *static_cast(get_serialized_item(sizeof(unsigned long), true)); + m_identifying_properties.file_stat.st_nlink = *static_cast(get_serialized_item(sizeof(unsigned long), true)); + m_identifying_properties.file_stat.st_uid = *static_cast(get_serialized_item(sizeof(unsigned long), true)); + m_identifying_properties.file_stat.st_gid = *static_cast(get_serialized_item(sizeof(unsigned long), true)); + m_identifying_properties.file_stat.st_rdev = *static_cast(get_serialized_item(sizeof(unsigned long), true)); + m_identifying_properties.file_stat.st_size = *static_cast(get_serialized_item(sizeof(signed long), true)); + m_identifying_properties.file_stat.st_atime = *static_cast(get_serialized_item(sizeof(signed long), true)); + m_identifying_properties.file_stat.st_mtime = *static_cast(get_serialized_item(sizeof(signed long), true)); + m_identifying_properties.file_stat.st_ctime = *static_cast(get_serialized_item(sizeof(signed long), true)); + m_offset_to_next_serialized_item = 11*8; + + m_has_cached_identifying_properties = true; + + } + + auto StdFile::is_deserialized_and_live_equal() -> bool { + if (!m_has_cached_identifying_properties) + { + if (!std::filesystem::exists(m_serialization_file_path_and_name)) + { + return false; + } + else + { + deserialize_identifying_properties(); + } + } + + return true; + } + + auto StdFile::invalidate_serialization() -> void + { + if (m_serialization_file_path_and_name.empty()) + { + THROW_INTERNAL_FILE_ERROR("[StdFile::invalidate_serialization] Could not invalidate serialization file because " + "'m_serialization_file_path_and_name' was empty, please call 'set_serialization_output_file'") + } + + if (std::filesystem::exists(m_serialization_file_path_and_name)) + { + delete_file(m_serialization_file_path_and_name); + } + } + + template + auto serialize_typed_item(DataType data, Handle& output_file) -> void + { + write_to_file(output_file.get_underlying_type(), &data, sizeof(DataType)); + } + + + auto StdFile::serialize_item(const GenericItemData& data, bool is_internal_item) -> void + { + if (m_serialization_file_path_and_name.empty()) + { + THROW_INTERNAL_FILE_ERROR( + "[StdFile::serialize_item]: Path & file name for serialization file is empty, please call 'set_serialization_output_file'") + } + + if (!serialization_file_exists() && !is_internal_item) + { + // If the serialization cache file doesn't exist & this is not an identifying property item, + // then we need to serialize the identifying properties before continuing + serialize_identifying_properties(); + } + + Handle serialization_file = open(m_serialization_file_path_and_name, OpenFor::Appending, OverwriteExistingFile::No, CreateIfNonExistent::Yes); + + switch (data.data_type) + { + case GenericDataType::UnsignedLong: + serialize_typed_item(data.data_ulong, serialization_file); + serialization_file.get_underlying_type().m_offset_to_next_serialized_item += sizeof(unsigned long); + break; + case GenericDataType::SignedLong: + serialize_typed_item(data.data_long, serialization_file); + serialization_file.get_underlying_type().m_offset_to_next_serialized_item += sizeof(signed long); + break; + case GenericDataType::UnsignedLongLong: + serialize_typed_item(data.data_ulonglong, serialization_file); + serialization_file.get_underlying_type().m_offset_to_next_serialized_item += sizeof(unsigned long long); + break; + case GenericDataType::SignedLongLong: + serialize_typed_item(data.data_longlong, serialization_file); + serialization_file.get_underlying_type().m_offset_to_next_serialized_item += sizeof(signed long long); + break; + } + + serialization_file.close(); + } + + + auto StdFile::get_serialized_item(size_t data_size, bool is_internal_item) -> void* + { + if (!m_has_cache_in_memory) + { + if (m_serialization_file_path_and_name.empty()) + { + THROW_INTERNAL_FILE_ERROR( + "[StdFile::get_serialized_item]: Path & file name for serialization file is empty, please call 'set_serialization_output_file'") + } + + Handle cache_file = open(m_serialization_file_path_and_name); + auto bytes_read = fread(&m_cache, cache_size, 1, (HANDLE) cache_file.get_raw_handle()); + if (bytes_read < 0) + { + THROW_INTERNAL_FILE_ERROR( + std::format("[StdFile::get_serialized_item] Tried deserializing file but was unable to complete operation. Error: {}", bytes_read)) + } + + cache_file.close(); + + m_has_cache_in_memory = true; + } + + if (!m_has_cached_identifying_properties && !is_internal_item) + { + deserialize_identifying_properties(); + } + + void* data_ptr = &m_cache[m_offset_to_next_serialized_item]; + m_offset_to_next_serialized_item += data_size; + return data_ptr; + } + + auto StdFile::close_current_file() -> void + { + close_file(); + } + + auto StdFile::create_all_directories(const std::filesystem::path& file_name_and_path) -> void + { + if (file_name_and_path.parent_path().empty()) + { + return; + } + + try + { + std::filesystem::create_directories(file_name_and_path.parent_path()); + } + catch (const std::filesystem::filesystem_error& e) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::create_all_directories] Tried creating directories '{}' but encountered an error. Error: {}", + file_name_and_path.string(), + e.what())) + } + } + + + auto StdFile::close_file() -> void + { + if (m_memory_map) + { + size_t aligned_size = m_memory_map_size & ~(sysconf(_SC_PAGE_SIZE) - 1); + if (munmap(m_memory_map, aligned_size) != 0) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::close_file] Was unable to unmap file, error: {}", errno)) + } + else + { + m_memory_map = nullptr; + m_memory_map_size = 0; + } + } + + if (!is_valid() || !is_file_open()) + { + return; + } + + if (fclose(m_file) == 0) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::close_file] Was unable to close file, error: {}", errno)) + } + else + { + set_is_file_open(false); + } + } + + auto StdFile::is_file_open() const -> bool + { + return m_is_file_open; + } + + auto StdFile::write_string_to_file(StringViewType string_to_write) -> void + { + try { + write_to_file(*this, string_to_write.data(), string_to_write.size()); + } catch (const std::exception& e) { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::write_string_to_file] Tried writing string to file but could not convert to utf-8. Error: {}", e.what())) + } + } + + auto StdFile::is_same_as(StdFile& other_file) -> bool + { + struct stat file_info{}; + if (fstat(fileno(m_file), &file_info) != 0) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::is_same_as] Tried retrieving file information by handle. Error: {}", errno)) + } + + struct stat other_file_info{}; + if (fstat(fileno(other_file.get_file()), &other_file_info) != 0) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::is_same_as] Tried retrieving file information by handle. Error: {}", errno)) + } + + if (file_info.st_dev != other_file_info.st_dev) + { + return false; + } + + if (file_info.st_ino != other_file_info.st_ino) + { + return false; + } + + if (file_info.st_mode != other_file_info.st_mode) + { + return false; + } + + if (file_info.st_nlink != other_file_info.st_nlink) + { + return false; + } + + if (file_info.st_uid != other_file_info.st_uid) + { + return false; + } + + if (file_info.st_gid != other_file_info.st_gid) + { + return false; + } + + if (file_info.st_rdev != other_file_info.st_rdev) + { + return false; + } + + if (file_info.st_size != other_file_info.st_size) + { + return false; + } + + if (file_info.st_mtime != other_file_info.st_mtime) + { + return false; + } + + if (file_info.st_ctime != other_file_info.st_ctime) + { + return false; + } + + return true; + } + + auto StdFile::read_all() const -> StringType + { + StreamType stream{get_file_path(), std::ios::in | std::ios::binary}; + if (!stream) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::read_all] Tried to read entire file but returned error {}", errno)) + } + else + { + // Strip the BOM if it exists + File::StreamType::off_type start{}; + File::CharType bom[3]{}; + stream.read(bom, 3); + if ((unsigned char)bom[0] == 0xEF && (unsigned char)bom[1] == 0xBB && (unsigned char)bom[2] == 0xBF) + { + // BOM: UTF-8 + start = 3; + } + + StringType file_contents; + stream.seekg(0, std::ios::end); + auto size = stream.tellg(); + if (size == -1) + { + return {}; + } + file_contents.resize(size); + stream.seekg(start, std::ios::beg); + stream.read(&file_contents[0], file_contents.size()); + stream.close(); + return file_contents; + } + } + + + auto StdFile::memory_map() -> std::span + { + int flags = PROT_NONE; + switch (m_open_properties.open_for) + { + case OpenFor::Writing: + case OpenFor::Appending: + flags |= PROT_WRITE; + case OpenFor::Reading: + flags |= PROT_READ; + break; + default: + THROW_INTERNAL_FILE_ERROR("[StdFile::memory_map] Tried to memory map file but 'm_open_properties' contains invalid data.") + } + + // seek to get size to map while keep original file position + auto original_position = ftell(m_file); + fseek(m_file, 0, SEEK_END); + auto file_size = ftell(m_file); + fseek(m_file, original_position, SEEK_SET); + + + auto res = mmap(nullptr, file_size, flags, MAP_SHARED, fileno(m_file), 0); + if (res == (void*) -1) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::memory_map] Tried to memory map file but 'mmap' returned error: {}", errno)) + } + + m_memory_map = (uint8_t*) res; + m_memory_map_size = file_size; + + return std::span(m_memory_map, file_size); + } + + + auto StdFile::open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> StdFile + { + // Reminder: std::filesystem::canonical() will get the full path & file name on the drive + // It only works if the directory already exists so check that first + // Should CreateFile take the canonical path ? + + if (file_name_and_path.empty()) + { + THROW_INTERNAL_FILE_ERROR("[StdFile::open_file] Tried to open file but file_name_and_path was empty.") + } + const char* modes; + switch (open_properties.open_for) + { + case OpenFor::Writing: + if (open_properties.overwrite_existing_file == OverwriteExistingFile::Yes) { + modes = "wb+"; + } else { + modes = "wb"; + } + break; + case OpenFor::Appending: + modes = "ab"; + break; + case OpenFor::Reading: + modes = "rb"; + break; + default: + THROW_INTERNAL_FILE_ERROR("[StdFile::open_file] Tried to open file but received invalid data for the 'OpenFor' parameter.") + } + + if (open_properties.overwrite_existing_file == OverwriteExistingFile::Yes) { + create_all_directories(file_name_and_path); + } + else if (open_properties.create_if_non_existent == CreateIfNonExistent::Yes) + { + create_all_directories(file_name_and_path); + } + else + { + if (!std::filesystem::exists(file_name_and_path)) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::open_file] Tried opening file but file does not exist: {}", file_name_and_path.string())) + } + } + + StdFile file{}; + + // This very badly named API may create a new file or it may not but it will always open a file (unless there's an error) + file.set_file(fopen(file_name_and_path.string().c_str(), modes)); + + if (file.get_file() == NULL) + { + std::string_view open_type = open_properties.open_for == OpenFor::Writing || open_properties.open_for == OpenFor::Appending ? "writing" : "reading"; + + int error = errno; + THROW_INTERNAL_FILE_ERROR( + std::format("[StdFile::open_file] Tried opening file for {} but encountered an error. Path & File: {} | errno = {}\n", + open_type, + file_name_and_path.string(), + error)) + } + + file.m_file_path_and_name = file_name_and_path; + file.set_is_file_open(true); + file.m_open_properties = open_properties; + + return file; + } +} diff --git a/deps/first/Helpers/include/Helpers/Casting.hpp b/deps/first/Helpers/include/Helpers/Casting.hpp index 176b37aee..05d5cf8df 100644 --- a/deps/first/Helpers/include/Helpers/Casting.hpp +++ b/deps/first/Helpers/include/Helpers/Casting.hpp @@ -3,12 +3,19 @@ #include #include +#ifdef WIN32 #ifdef _WIN32 #define WINDOWS #define NOMINMAX #include "Windows.h" #endif +#else + +#include + +#endif + namespace RC::Helper::Casting { template @@ -67,5 +74,41 @@ namespace RC::Helper::Casting { return ptr_cast_deref_safe(base_ptr, offset, process_handle); } +#else +// use process_vm_readv + template + auto ptr_cast_deref_safe(From ptr, int32_t offset, pid_t process_handle) -> To + { + static_assert(std::is_pointer_v, "ptr_cast_deref_safe can only cast from pointer types"); + + // For this example, To == UObject* + // Therefore: To* == UObject** + To* data_ptr = std::bit_cast(std::bit_cast(ptr) + offset); + + size_t bytes_read; + uintptr_t is_valid_ptr_buffer; + struct iovec local[1]; + struct iovec remote[1]; + local[0].iov_base = &is_valid_ptr_buffer; + local[0].iov_len = sizeof(is_valid_ptr_buffer); + remote[0].iov_base = data_ptr; + remote[0].iov_len = sizeof(is_valid_ptr_buffer); + if (process_vm_readv(process_handle, local, 1, remote, 1, 0) < 0) + { + return 0; + } + else + { + return *data_ptr; + } + + } + + // Compatibility with older code from before 'ptr_cast' existed + template + static auto offset_deref_safe(From* base_ptr, int32_t offset, pid_t process_handle) -> To + { + return ptr_cast_deref_safe(base_ptr, offset, process_handle); + } #endif } // namespace RC::Helper::Casting diff --git a/deps/first/Helpers/include/Helpers/Format.hpp b/deps/first/Helpers/include/Helpers/Format.hpp index 329f91292..ea825c228 100644 --- a/deps/first/Helpers/include/Helpers/Format.hpp +++ b/deps/first/Helpers/include/Helpers/Format.hpp @@ -1,6 +1,13 @@ #pragma once #include +#include +#include + +#ifdef LINUX +#define swprintf_s swprintf +#define sprintf_s snprintf +#endif namespace RC { @@ -53,4 +60,31 @@ namespace RC return out_string; } + +/* + template + auto static fmt(const char16_t* fmt, Args... args) -> std::wstring + { + constexpr size_t out_string_length = 1000; + char16_t out_string[out_string_length]; + + size_t msg_len = wcslen(fmt); + + // Attempt to give a hint if the buffer is too small + if (msg_len > out_string_length) + { + fmt = L"An error occurred but the message was too long for the buffer."; + msg_len = wcslen(fmt); + } + + // If the buffer is too small for the hint message then I guess we do nothing + // The default message will be used which can't be too small since it's calculated at compile-time + if (msg_len < out_string_length) + { + swprintf_s(out_string, out_string_length, fmt, args...); + } + + return out_string; + } +*/ } // namespace RC diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index e8f964060..c681742a1 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -44,6 +45,23 @@ namespace RC return return_value; } + auto inline explode_by_occurrence(const std::u16string& in_str_wide, const char16_t delimiter, ExplodeType start_or_end) -> std::u16string + { + size_t occurrence = (start_or_end == ExplodeType::FromStart ? in_str_wide.find_first_of(delimiter) : in_str_wide.find_last_of(delimiter)); + + std::u16string return_value; + if (occurrence != std::wstring::npos) + { + return_value = start_or_end == ExplodeType::FromEnd ? in_str_wide.substr(occurrence + 1, std::u16string::npos) : in_str_wide.substr(0, occurrence); + } + else + { + return_value = in_str_wide; + } + + return return_value; + } + auto inline explode_by_occurrence(const std::string& in_str, const char delimiter, ExplodeType start_or_end) -> std::string { size_t occurrence = (start_or_end == ExplodeType::FromStart ? in_str.find_first_of(delimiter) : in_str.find_last_of(delimiter)); @@ -131,6 +149,33 @@ namespace RC return result; } + auto inline explode_by_occurrence(const std::u16string& in_str_wide, const char16_t delimiter) -> std::vector + { + std::vector result; + + size_t counter{}; + size_t start_offset{}; + + for (const char16_t* current_char = in_str_wide.c_str(); *current_char; ++current_char) + { + if (*current_char == delimiter || counter == in_str_wide.length() - 1) + { + std::u16string sub_str = in_str_wide.substr(start_offset, counter - start_offset + (counter == in_str_wide.length() - 1 ? 1 : 0)); + if (start_offset > 0) + { + sub_str.erase(0, 1); + } + result.emplace_back(sub_str); + + start_offset = counter; + } + + ++counter; + } + + return result; + } + auto inline explode_by_occurrence(const std::wstring& in_str, const wchar_t delimiter, const int32_t occurrence) -> std::wstring { size_t found_occurrence{}; @@ -148,6 +193,23 @@ namespace RC } /* explode_by_occurrence -> END */ + auto inline explode_by_occurrence(const std::u16string& in_str, const char16_t delimiter, const int32_t occurrence) -> std::u16string + { + size_t found_occurrence{}; + for (int64_t i = 0; i < std::count(in_str.begin(), in_str.end(), delimiter); i++) + { + found_occurrence = in_str.find(delimiter, found_occurrence + 1); + if (i + 1 == occurrence) + { + return in_str.substr(0, found_occurrence); + } + } + + // No occurrence was found, returning empty string for now + return {}; + } + /* explode_by_occurrence -> END */ + auto inline to_wstring(std::string& input) -> std::wstring { #pragma warning(disable : 4996) @@ -203,12 +265,33 @@ namespace RC #pragma warning(default : 4996) } + auto inline to_string(std::u16string& input) -> std::string + { + return std::wstring_convert, char16_t>{}.to_bytes(input); + } + auto inline to_string(std::wstring_view input) -> std::string { auto temp_input = std::wstring{input}; return to_string(temp_input); } + auto inline to_string(std::u16string_view input) -> std::string + { + auto temp_input = std::u16string{input}; + return to_string(temp_input); + } + + auto inline to_string(std::string_view input) -> std::string + { + return std::string{input}; + } + + auto inline to_string(std::string input) -> std::string + { + return std::string{input}; + } + auto inline to_u16string(std::wstring& input) -> std::u16string { return {input.begin(), input.end()}; @@ -231,14 +314,14 @@ namespace RC return to_u16string(temp_input); } - auto inline to_generic_string(const auto& input) -> StringType + auto inline to_generic_string(const auto& input) -> SystemStringType { - if constexpr (std::is_same_v>>, StringViewType>) + if constexpr (std::is_same_v>>, SystemStringViewType>) { - return StringType{input}; + return SystemStringType{input}; } - else if constexpr (std::is_same_v>>, StringType> || - std::is_same_v>>, CharType>) + else if constexpr (std::is_same_v>>, SystemStringType> || + std::is_same_v>>, SystemCharType>) { return input; } @@ -247,7 +330,11 @@ namespace RC #if RC_IS_ANSI == 1 return to_string(input); #else +#ifdef WIN32 return to_wstring(input); +#else + return to_string(input); +#endif #endif } } @@ -261,16 +348,33 @@ namespace RC }); } + auto inline iequal(std::u16string_view a, std::u16string_view b) + { + return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), [](const char16_t a_char, const char16_t b_char) { + return std::towlower(a_char) == std::towlower(b_char); + }); + } + auto inline iequal(std::wstring& a, const wchar_t* b) { return iequal(a, std::wstring_view{b}); } + auto inline iequal(std::u16string& a, const char16_t* b) + { + return iequal(a, std::u16string_view{b}); + } + auto inline iequal(const wchar_t* a, std::wstring& b) { return iequal(std::wstring_view{a}, b); } + auto inline iequal(const char16_t* a, std::u16string& b) + { + return iequal(std::u16string_view{a}, b); + } + auto inline iequal(std::string_view a, std::string_view b) { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), [](const char a_char, const char b_char) { diff --git a/deps/first/IniParser/include/IniParser/Common.hpp b/deps/first/IniParser/include/IniParser/Common.hpp index 5077118ed..3196c27b4 100644 --- a/deps/first/IniParser/include/IniParser/Common.hpp +++ b/deps/first/IniParser/include/IniParser/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_INI_PARSER_EXPORTS #ifndef RC_INI_PARSER_BUILD_STATIC #ifndef RC_INI_PARSER_API @@ -15,3 +17,11 @@ #define RC_INI_PARSER_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_INI_PARSER_API +#define RC_INI_PARSER_API +#endif + +#endif diff --git a/deps/first/IniParser/include/IniParser/Experimental.hpp b/deps/first/IniParser/include/IniParser/Experimental.hpp index 38c8039eb..370640b7c 100644 --- a/deps/first/IniParser/include/IniParser/Experimental.hpp +++ b/deps/first/IniParser/include/IniParser/Experimental.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace RC::Parser::Experimental { enum TokenType : int @@ -24,47 +26,47 @@ namespace RC::Parser::Experimental class RuleOne : public Parser::TokenRule { public: - [[nodiscard]] auto to_string() const -> std::wstring override + [[nodiscard]] auto to_string() const -> SystemCharType override { - return L"RuleOne"; + return SYSSTR("RuleOne"); } }; class TokenMustEndWithOppositeToken : public Parser::TokenRule { public: - TokenMustEndWithOppositeToken() : TokenRule(L"TokenMustEndWithOppositeToken") + TokenMustEndWithOppositeToken() : TokenRule(SYSSTR("TokenMustEndWithOppositeToken")) { } - auto exec(const Parser::Token& token, const wchar_t* start_of_token, size_t current_cursor_location, Tokenizer& tokenizer) -> int override + auto exec(const Parser::Token& token, const SystemCharType* start_of_token, size_t current_cursor_location, Tokenizer& tokenizer) -> int override { - printf_s("TokenMustEndWithOppositeToken::exec [%S]\n", token.to_string().c_str()); + printf_s("TokenMustEndWithOppositeToken::exec [" SystemStringPrint "]\n", token.to_string().c_str()); return 0; } - [[nodiscard]] auto to_string() const -> std::wstring override + [[nodiscard]] auto to_string() const -> SystemStringType override { - return L"TokenMustEndWithOppositeToken"; + return SYSSTR("TokenMustEndWithOppositeToken"); } }; class TokenMustHaveCharsBeforeEnd : public Parser::TokenRule { public: - TokenMustHaveCharsBeforeEnd() : TokenRule(L"TokenMustHaveCharsBeforeEnd") + TokenMustHaveCharsBeforeEnd() : TokenRule(SYSSTR("TokenMustHaveCharsBeforeEnd")) { } - auto exec(const Parser::Token& token, const wchar_t* start_of_token, size_t current_cursor_location, Tokenizer& tokenizer) -> int override + auto exec(const Parser::Token& token, const SystemCharType* start_of_token, size_t current_cursor_location, Tokenizer& tokenizer) -> int override { - printf_s("TokenMustHaveCharsBeforeEnd::exec [%S]\n", token.to_string().c_str()); + printf_s("TokenMustHaveCharsBeforeEnd::exec [" SystemStringPrint "]\n", token.to_string().c_str()); return 0; } - [[nodiscard]] auto to_string() const -> std::wstring override + [[nodiscard]] auto to_string() const -> SystemStringType override { - return L"TokenMustHaveCharsBeforeEnd"; + return SYSSTR("TokenMustHaveCharsBeforeEnd"); } }; @@ -76,35 +78,35 @@ namespace RC::Parser::Experimental // Always use "ref->value" instead of "value" // That way it returns properly if this value is a refernece to another variable // The "ref->value" member is set to self if it doesn't refer to another variable - std::wstring value{}; + SystemStringType value{}; const Value* ref{}; }; struct Section { - std::unordered_map key_value_pairs{}; + std::unordered_map key_value_pairs{}; }; private: - using SectionContainer = std::unordered_map; + using SectionContainer = std::unordered_map; SectionContainer& m_output; Section* m_current_section{}; Value* m_variable_to_assign_to{}; - std::wstring m_temporary{}; + SystemStringType m_temporary{}; public: - ExperimentalTokenParser(const Parser::Tokenizer& tokenizer, std::wstring input, std::unordered_map& output) + ExperimentalTokenParser(const Parser::Tokenizer& tokenizer, SystemStringType input, std::unordered_map& output) : TokenParser(tokenizer, input), m_output(output) { } public: - auto static find_variable_by_name(Section* section, const std::wstring& name) -> std::optional>; - auto static find_variable_by_name(SectionContainer& sections, const std::wstring& name) -> std::optional>; + auto static find_variable_by_name(Section* section, const SystemStringType& name) -> std::optional>; + auto static find_variable_by_name(SectionContainer& sections, const SystemStringType& name) -> std::optional>; private: - auto find_variable_by_name(const std::wstring& name) -> std::optional>; + auto find_variable_by_name(const SystemStringType& name) -> std::optional>; auto try_set_section_value(Value& pair_value, const Parser::Token& token, bool is_space_valid = true) -> void; auto handle_operator_equals(const Parser::Token& token) -> void; auto handle_operator_plus(const Parser::Token& token) -> void; @@ -120,16 +122,16 @@ namespace RC::Parser::Experimental class ExperimentalParser { private: - std::unordered_map m_sections; + std::unordered_map m_sections; public: - ExperimentalParser(const std::wstring& input); + ExperimentalParser(const SystemStringType& input); private: auto create_available_tokens_for_tokenizer() -> Parser::TokenContainer; public: - auto get_string(const std::wstring& section, const std::wstring& key, const std::wstring& default_value) -> std::wstring; + auto get_string(const SystemStringType& section, const SystemStringType& key, const SystemStringType& default_value) -> SystemStringType; }; auto test() -> void; diff --git a/deps/first/IniParser/include/IniParser/Ini.hpp b/deps/first/IniParser/include/IniParser/Ini.hpp index fd9034aea..acfafbeae 100644 --- a/deps/first/IniParser/include/IniParser/Ini.hpp +++ b/deps/first/IniParser/include/IniParser/Ini.hpp @@ -23,32 +23,32 @@ namespace RC::Ini }; private: - std::unordered_map m_sections; + std::unordered_map m_sections; bool m_parsing_is_complete{false}; public: Parser() = default; private: - RC_INI_PARSER_API auto parse_internal(File::StringType& input) -> void; + RC_INI_PARSER_API auto parse_internal(SystemStringType& input) -> void; RC_INI_PARSER_API auto create_available_tokens_for_tokenizer() -> ParserBase::TokenContainer; - RC_INI_PARSER_API auto get_value(const File::StringType& section, const File::StringType& key, CanThrow = CanThrow::Yes) const + RC_INI_PARSER_API auto get_value(const SystemStringType& section, const SystemStringType& key, CanThrow = CanThrow::Yes) const -> std::optional>; public: - RC_INI_PARSER_API auto parse(File::StringType& input) -> void; + RC_INI_PARSER_API auto parse(SystemStringType& input) -> void; RC_INI_PARSER_API auto parse(const File::Handle&) -> void; - RC_INI_PARSER_API auto get_list(const File::StringType& section) -> List; - RC_INI_PARSER_API auto get_ordered_list(const File::StringType& section) -> List; - RC_INI_PARSER_API auto get_string(const File::StringType& section, const File::StringType& key, const File::StringType& default_value) const noexcept - -> const File::StringType&; - RC_INI_PARSER_API auto get_string(const File::StringType& section, const File::StringType& key) const -> const File::StringType&; + RC_INI_PARSER_API auto get_list(const SystemStringType& section) -> List; + RC_INI_PARSER_API auto get_ordered_list(const SystemStringType& section) -> List; + RC_INI_PARSER_API auto get_string(const SystemStringType& section, const SystemStringType& key, const SystemStringType& default_value) const noexcept + -> const SystemStringType&; + RC_INI_PARSER_API auto get_string(const SystemStringType& section, const SystemStringType& key) const -> const SystemStringType&; // Should there be more integer getters ? They'd confirm size and convert explicitly (or throw?), no implicit conversions. - RC_INI_PARSER_API auto get_int64(const File::StringType& section, const File::StringType& key, int64_t default_value) const noexcept -> int64_t; - RC_INI_PARSER_API auto get_int64(const File::StringType& section, const File::StringType& key) const -> int64_t; - RC_INI_PARSER_API auto get_float(const File::StringType& section, const File::StringType& key, float default_value) const noexcept -> float; - RC_INI_PARSER_API auto get_float(const File::StringType& section, const File::StringType& key) const -> float; - RC_INI_PARSER_API auto get_bool(const File::StringType& section, const File::StringType& key, bool default_value) const noexcept -> bool; - RC_INI_PARSER_API auto get_bool(const File::StringType& section, const File::StringType& key) const -> bool; + RC_INI_PARSER_API auto get_int64(const SystemStringType& section, const SystemStringType& key, int64_t default_value) const noexcept -> int64_t; + RC_INI_PARSER_API auto get_int64(const SystemStringType& section, const SystemStringType& key) const -> int64_t; + RC_INI_PARSER_API auto get_float(const SystemStringType& section, const SystemStringType& key, float default_value) const noexcept -> float; + RC_INI_PARSER_API auto get_float(const SystemStringType& section, const SystemStringType& key) const -> float; + RC_INI_PARSER_API auto get_bool(const SystemStringType& section, const SystemStringType& key, bool default_value) const noexcept -> bool; + RC_INI_PARSER_API auto get_bool(const SystemStringType& section, const SystemStringType& key) const -> bool; }; } // namespace RC::Ini diff --git a/deps/first/IniParser/include/IniParser/JSON.hpp b/deps/first/IniParser/include/IniParser/JSON.hpp index fc6d763bc..1b6e9b602 100644 --- a/deps/first/IniParser/include/IniParser/JSON.hpp +++ b/deps/first/IniParser/include/IniParser/JSON.hpp @@ -6,6 +6,8 @@ #include #include +#include + namespace RC::Parser { namespace JSONInternal @@ -24,31 +26,31 @@ namespace RC::Parser EndOfFile, }; - auto static token_type_to_string(const TokenType token_type) -> File::StringType + auto static token_type_to_string(const TokenType token_type) -> SystemStringType { switch (token_type) { case Default: - return STR("Default"); + return SYSSTR("Default"); case OpenCurlyBrace: - return STR("OpenCurlyBrace"); + return SYSSTR("OpenCurlyBrace"); case CloseCurlyBrace: - return STR("CloseCurlyBrace"); + return SYSSTR("CloseCurlyBrace"); case OpenSquareBracket: - return STR("OpenSquareBracket"); + return SYSSTR("OpenSquareBracket"); case CloseSquareBracket: - return STR("CloseSquareBracket"); + return SYSSTR("CloseSquareBracket"); case Colon: - return STR("Colon"); + return SYSSTR("Colon"); case Comma: - return STR("Comma"); + return SYSSTR("Comma"); break; case DoubleQuote: - return STR("DoubleQuote"); + return SYSSTR("DoubleQuote"); case Characters: - return STR("Characters"); + return SYSSTR("Characters"); case EndOfFile: - return STR("EndOfFile"); + return SYSSTR("EndOfFile"); } } @@ -63,29 +65,29 @@ namespace RC::Parser class ItemBase { public: - File::StringType m_name{STR("--UNNAMED-ITEM--")}; + SystemStringType m_name{SYSSTR("--UNNAMED-ITEM--")}; bool m_is_global_scope{false}; public: - auto get_name() -> File::StringViewType; + auto get_name() -> SystemStringType; virtual ~ItemBase() = default; - virtual auto to_string() -> File::StringType = 0; + virtual auto to_string() -> SystemStringType = 0; virtual auto get_type() -> ItemType = 0; }; class StringItem : public ItemBase { public: - File::StringType m_value{}; + SystemStringType m_value{}; public: StringItem() = default; - StringItem(const File::StringType& value) : m_value(value) + StringItem(const SystemStringType& value) : m_value(value) { } - auto to_string() -> File::StringType override; + auto to_string() -> SystemStringType override; auto get_type() -> ItemType override { return ItemType::String; @@ -100,7 +102,7 @@ namespace RC::Parser size_t m_previous_column_without_comma{}; public: - auto to_string() -> File::StringType override; + auto to_string() -> SystemStringType override; auto get_type() -> ItemType override { return ItemType::Object; @@ -113,7 +115,7 @@ namespace RC::Parser std::vector> m_members{}; public: - auto to_string() -> File::StringType override; + auto to_string() -> SystemStringType override; auto get_type() -> ItemType override { return ItemType::Array; @@ -160,18 +162,18 @@ namespace RC::Parser ItemType m_next_item_expected{}; TokenType m_next_token_expected{TokenType::Default}; TokenTypeStack m_processed_token_types{}; - File::StringType m_string_value_buffer{}; + SystemStringType m_string_value_buffer{}; bool m_double_quote_opened{false}; bool m_double_quote_successfully_closed{false}; public: - TokenParser(const Parser::Tokenizer& tokenizer, File::StringType& input) : Parser::TokenParser(tokenizer, input) + TokenParser(const Parser::Tokenizer& tokenizer, SystemStringType& input) : Parser::TokenParser(tokenizer, input) { } private: - auto token_to_string(const Token& token) -> File::StringType; + auto token_to_string(const Token& token) -> SystemStringType; auto skip_all_spaces() -> void; auto parse_open_curly_brace(const Token& token) -> void; @@ -198,10 +200,10 @@ namespace RC::Parser JSON() = default; private: - auto parse_internal(File::StringType& input) -> void; + auto parse_internal(SystemStringType& input) -> void; public: - auto parse(File::StringType& input) -> void; + auto parse(SystemStringType& input) -> void; auto parse(File::Handle&) -> void; auto release_contents() -> std::vector>; diff --git a/deps/first/IniParser/include/IniParser/Section.hpp b/deps/first/IniParser/include/IniParser/Section.hpp index b6d9797ff..18e7b170c 100644 --- a/deps/first/IniParser/include/IniParser/Section.hpp +++ b/deps/first/IniParser/include/IniParser/Section.hpp @@ -9,13 +9,13 @@ namespace RC::Ini { struct Section { - std::unordered_map key_value_pairs{}; - std::vector ordered_list{}; + std::unordered_map key_value_pairs{}; + std::vector ordered_list{}; bool is_ordered_list{}; }; template - concept CallableWithKeyValuePair = std::invocable; + concept CallableWithKeyValuePair = std::invocable; class List { diff --git a/deps/first/IniParser/include/IniParser/TokenParser.hpp b/deps/first/IniParser/include/IniParser/TokenParser.hpp index a7192852a..930377540 100644 --- a/deps/first/IniParser/include/IniParser/TokenParser.hpp +++ b/deps/first/IniParser/include/IniParser/TokenParser.hpp @@ -22,30 +22,30 @@ namespace RC::Ini SetSectionValue, }; - auto state_to_string(State) -> File::StringType; + auto state_to_string(State) -> SystemStringType; class TokenParser : public ParserBase::TokenParser { private: - using SectionContainer = std::unordered_map; + using SectionContainer = std::unordered_map; SectionContainer& m_output; Section* m_current_section{}; Value* m_current_value{}; - File::StringType m_current_character_data{}; + SystemStringType m_current_character_data{}; State m_current_state{State::StartOfFile}; public: - TokenParser(const ParserBase::Tokenizer& tokenizer, File::StringType& input, std::unordered_map& output) + TokenParser(const ParserBase::Tokenizer& tokenizer, SystemStringType& input, std::unordered_map& output) : ParserBase::TokenParser(tokenizer, input), m_output(output) { } public: - RC_INI_PARSER_API auto static find_variable_by_name(Section* section, const File::StringType& name) -> std::optional>; + RC_INI_PARSER_API auto static find_variable_by_name(Section* section, const SystemStringType& name) -> std::optional>; private: - RC_INI_PARSER_API auto find_variable_by_name(const File::StringType& name) -> std::optional>; - RC_INI_PARSER_API auto characters_to_string(const ParserBase::Token& characters_token) -> File::StringType; + RC_INI_PARSER_API auto find_variable_by_name(const SystemStringType& name) -> std::optional>; + RC_INI_PARSER_API auto characters_to_string(const ParserBase::Token& characters_token) -> SystemStringType; RC_INI_PARSER_API auto handle_opening_square_bracket_token(const ParserBase::Token& token) -> void; RC_INI_PARSER_API auto handle_closing_square_bracket_token(const ParserBase::Token& token) -> void; RC_INI_PARSER_API auto handle_space_token(const ParserBase::Token& token) -> void; diff --git a/deps/first/IniParser/include/IniParser/Value.hpp b/deps/first/IniParser/include/IniParser/Value.hpp index 9c302619c..dcd36b54b 100644 --- a/deps/first/IniParser/include/IniParser/Value.hpp +++ b/deps/first/IniParser/include/IniParser/Value.hpp @@ -26,7 +26,7 @@ namespace RC::Ini // Always use "m_ref->value" instead of "value" // That way it returns properly if this value is a reference to another variable // The "m_ref->value" member is set to self if it doesn't refer to another variable - File::StringType m_string_value; + SystemStringType m_string_value; int64_t m_int64_value{}; float m_float_value{}; bool m_bool_value{}; @@ -57,14 +57,14 @@ namespace RC::Ini return is_valid_type(); } - RC_INI_PARSER_API auto get_string_value() const -> const File::StringType&; + RC_INI_PARSER_API auto get_string_value() const -> const SystemStringType&; RC_INI_PARSER_API auto get_int64_value() const -> int64_t; RC_INI_PARSER_API auto get_float_value() const -> float; RC_INI_PARSER_API auto get_bool_value() const -> bool; - RC_INI_PARSER_API auto add_string_value(File::StringViewType data) -> void; - RC_INI_PARSER_API auto add_int64_value(const File::StringType& data, int base = 10) -> void; - RC_INI_PARSER_API auto add_float_value(const File::StringType& data) -> void; + RC_INI_PARSER_API auto add_string_value(SystemStringViewType data) -> void; + RC_INI_PARSER_API auto add_int64_value(const SystemStringType& data, int base = 10) -> void; + RC_INI_PARSER_API auto add_float_value(const SystemStringType& data) -> void; RC_INI_PARSER_API auto add_bool_value(bool data) -> void; private: diff --git a/deps/first/IniParser/src/Experimental.cpp b/deps/first/IniParser/src/Experimental.cpp index 9e143cb02..8a5f01fcd 100644 --- a/deps/first/IniParser/src/Experimental.cpp +++ b/deps/first/IniParser/src/Experimental.cpp @@ -2,7 +2,7 @@ namespace RC::Parser::Experimental { - auto ExperimentalTokenParser::find_variable_by_name(Section* section, const std::wstring& name) -> std::optional> + auto ExperimentalTokenParser::find_variable_by_name(Section* section, const SystemStringType& name) -> std::optional> { auto const& var = section->key_value_pairs.find(name); if (var != section->key_value_pairs.end()) @@ -15,7 +15,7 @@ namespace RC::Parser::Experimental } } - auto ExperimentalTokenParser::find_variable_by_name(SectionContainer& sections, const std::wstring& name) -> std::optional> + auto ExperimentalTokenParser::find_variable_by_name(SectionContainer& sections, const SystemStringType& name) -> std::optional> { std::optional> value_found = [&]() -> std::optional> { for (auto& [_, section] : sections) @@ -33,7 +33,7 @@ namespace RC::Parser::Experimental return value_found; } - auto ExperimentalTokenParser::find_variable_by_name(const std::wstring& name) -> std::optional> + auto ExperimentalTokenParser::find_variable_by_name(const SystemStringType& name) -> std::optional> { size_t occurrence_of_dot = name.find_first_of(L'.'); if (occurrence_of_dot == name.npos || occurrence_of_dot + 1 > name.size()) @@ -49,7 +49,7 @@ namespace RC::Parser::Experimental } else { - const std::wstring requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); + const SystemStringType requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); return find_variable_by_name(&requested_section->second, requested_variable_name); } } @@ -60,12 +60,12 @@ namespace RC::Parser::Experimental const auto token_type = token.get_type(); if (token_type == TokenType::EndOfFile || token_type == TokenType::NewLine) { - pair_value.value = L""; + pair_value.value = SYSSTR(""); pair_value.ref = &pair_value; } else if (token_type == TokenType::Characters) { - std::wstring value_data{}; + SystemStringType value_data{}; consume_continually([&](const Parser::Token& token) { const auto token_type = token.get_type(); if (token_type == TokenType::EndOfFile || token_type == TokenType::NewLine) @@ -85,7 +85,7 @@ namespace RC::Parser::Experimental else if (token_type == TokenType::Space) { // Append space - value_data.append(L" "); + value_data.append(SYSSTR(" ")); // Consume another token return false; @@ -161,7 +161,7 @@ namespace RC::Parser::Experimental } else if (previous_token.get_type() == TokenType::Characters) { - std::wstring key_name = get_data(previous_token); + SystemStringType key_name = get_data(previous_token); const auto& key_value_pair_iter = m_current_section->key_value_pairs.find(key_name); if (key_value_pair_iter == m_current_section->key_value_pairs.end()) { @@ -188,7 +188,7 @@ namespace RC::Parser::Experimental } else if (characters_token.get_type() == TokenType::Characters) { - const std::wstring key_name = get_data(characters_token); + const SystemStringType key_name = get_data(characters_token); const auto& maybe_variable = find_variable_by_name(key_name); if (maybe_variable.has_value()) { @@ -250,7 +250,7 @@ namespace RC::Parser::Experimental // May be a variable or a temporary (Characters token) bool lhs_is_variable{}; bool lhs_is_temporary{}; - std::wstring lhs = [&]() { + SystemStringType lhs = [&]() { if (!m_temporary.empty()) { lhs_is_temporary = true; @@ -265,7 +265,7 @@ namespace RC::Parser::Experimental } else { - const std::wstring lhs_data = get_data(lhs_token); + const SystemStringType lhs_data = get_data(lhs_token); auto maybe_variable = find_variable_by_name(lhs_data); if (maybe_variable.has_value()) { @@ -306,8 +306,8 @@ namespace RC::Parser::Experimental // } // Find rhs - std::wstring rhs = [&]() { - std::wstring rhs_temporary{}; + SystemStringType rhs = [&]() { + SystemStringType rhs_temporary{}; const auto& next_token = peek(); if (next_token.get_type() == TokenType::EndOfFile) @@ -332,7 +332,7 @@ namespace RC::Parser::Experimental } else if (next_token.get_type() == TokenType::Space) { - rhs_temporary += L" "; + rhs_temporary += SYSSTR(" "); consume(); // Consume the first Space consume_until(TokenType::Characters, [&](const Parser::Token& token) { @@ -346,7 +346,7 @@ namespace RC::Parser::Experimental } else { - rhs_temporary += L" "; + rhs_temporary += SYSSTR(" "); return false; } } @@ -476,7 +476,7 @@ namespace RC::Parser::Experimental } }(); - std::wstring section_name = get_data(section_name_token); + SystemStringType section_name = get_data(section_name_token); if (auto section = m_output.find(section_name); section != m_output.end()) { m_current_section = §ion->second; @@ -515,7 +515,7 @@ namespace RC::Parser::Experimental } } - ExperimentalParser::ExperimentalParser(const std::wstring& input) + ExperimentalParser::ExperimentalParser(const SystemStringType& input) { // Tokenize -> START Parser::Tokenizer tokenizer; @@ -533,28 +533,28 @@ namespace RC::Parser::Experimental { Parser::TokenContainer tc; - tc.add(Parser::Token::create(TokenType::CarriageReturn, L"CarriageReturn", L"\r")); - tc.add(Parser::Token::create(TokenType::NewLine, L"NewLine", L"\n")); - tc.add(Parser::Token::create(TokenType::Space, L"Space", L" ")); + tc.add(Parser::Token::create(TokenType::CarriageReturn, SYSSTR("CarriageReturn"), SYSSTR("\r"))); + tc.add(Parser::Token::create(TokenType::NewLine, SYSSTR("NewLine"), SYSSTR("\n"))); + tc.add(Parser::Token::create(TokenType::Space, SYSSTR("Space"), SYSSTR(" "))); tc.add(Parser::Token::create(TokenType::Characters, - L"Characters", - L"", + SYSSTR("Characters"), + SYSSTR(""), Parser::Token::HasData::Yes)); // Empty identifier will match everything that no other token identifier matches - tc.add(Parser::Token::create(TokenType::Equals, L"Equals", L"=")); - // tc.add(Parser::Token::create(IniFileToken::Plus, L"Plus", L"+")); + tc.add(Parser::Token::create(TokenType::Equals, SYSSTR("Equals"), SYSSTR("="))); + // tc.add(Parser::Token::create(IniFileToken::Plus, SYSSTR("Plus"), SYSSTR("+"))); - auto close_square_bracket_token = tc.add(Parser::Token::create(TokenType::ClosingSquareBracket, L"CloseSquareBracket", L"]")); + auto close_square_bracket_token = tc.add(Parser::Token::create(TokenType::ClosingSquareBracket, SYSSTR("CloseSquareBracket"), SYSSTR("]"))); auto token = - Parser::Token::create(TokenType::OpeningSquareBracket, L"OpenSquareBracket", L"["); + Parser::Token::create(TokenType::OpeningSquareBracket, SYSSTR("OpenSquareBracket"), SYSSTR("[")); tc.add(std::move(token)); - tc.add(Parser::Token::create(TokenType::SemiColon, L"SemiColon", L";")); + tc.add(Parser::Token::create(TokenType::SemiColon, SYSSTR("SemiColon"), SYSSTR(";"))); return tc; } - auto ExperimentalParser::get_string(const std::wstring& section, const std::wstring& key, const std::wstring& default_value) -> std::wstring + auto ExperimentalParser::get_string(const SystemStringType& section, const SystemStringType& key, const SystemStringType& default_value) -> SystemStringType { auto section_iter = m_sections.find(section); if (section_iter == m_sections.end()) @@ -590,7 +590,7 @@ var6 = hello + + world var7 = 1 + 2 + 3 + 4 */ - std::wstring config_str = LR"( + SystemStringType config_str = R"( [ SectionOne] ; This is a comment and as such should be ignored by the parser var1 = 2 @@ -624,30 +624,30 @@ var5 = a string with spaces printf_s("Creating experimental parser\n"); ExperimentalParser parser{config_str}; - constexpr wchar_t default_value[] = L""; - printf_s("SectionOne.var1 = %S\n", parser.get_string(L"SectionOne", L"var1", default_value).c_str()); - printf_s("SectionOne.var2 = %S\n", parser.get_string(L"SectionOne", L"var2", default_value).c_str()); - printf_s("SectionOne.var3 = %S\n", parser.get_string(L"SectionOne", L"var3", default_value).c_str()); - printf_s("SectionOne.var4 = %S\n", parser.get_string(L"SectionOne", L"var4", default_value).c_str()); - printf_s("SectionOne.var5 = %S\n", parser.get_string(L"SectionOne", L"var5", default_value).c_str()); - printf_s("SectionOne.var6 = %S\n", parser.get_string(L"SectionOne", L"var6", default_value).c_str()); - printf_s("SectionOne.var7 = %S\n", parser.get_string(L"SectionOne", L"var7", default_value).c_str()); + constexpr char16_t default_value[] = SYSSTR(""); + printf_s("SectionOne.var1 = %S\n", parser.get_string(SYSSTR("SectionOne"), SYSSTR("var1"), default_value).c_str()); + printf_s("SectionOne.var2 = %S\n", parser.get_string(SYSSTR("SectionOne"), SYSSTR("var2"), default_value).c_str()); + printf_s("SectionOne.var3 = %S\n", parser.get_string(SYSSTR("SectionOne"), SYSSTR("var3"), default_value).c_str()); + printf_s("SectionOne.var4 = %S\n", parser.get_string(SYSSTR("SectionOne"), SYSSTR("var4"), default_value).c_str()); + printf_s("SectionOne.var5 = %S\n", parser.get_string(SYSSTR("SectionOne"), SYSSTR("var5"), default_value).c_str()); + printf_s("SectionOne.var6 = %S\n", parser.get_string(SYSSTR("SectionOne"), SYSSTR("var6"), default_value).c_str()); + printf_s("SectionOne.var7 = %S\n", parser.get_string(SYSSTR("SectionOne"), SYSSTR("var7"), default_value).c_str()); printf_s("\n"); - printf_s("SectionTwo.var1 = %S\n", parser.get_string(L"SectionTwo", L"var1", default_value).c_str()); - printf_s("SectionTwo.var2 = %S\n", parser.get_string(L"SectionTwo", L"var2", default_value).c_str()); - printf_s("SectionTwo.var3 = %S\n", parser.get_string(L"SectionTwo", L"var3", default_value).c_str()); - printf_s("SectionTwo.var4 = %S\n", parser.get_string(L"SectionTwo", L"var4", default_value).c_str()); - printf_s("SectionTwo.var5 = %S\n", parser.get_string(L"SectionTwo", L"var5", default_value).c_str()); - printf_s("SectionTwo.var6 = %S\n", parser.get_string(L"SectionTwo", L"var6", default_value).c_str()); - printf_s("SectionTwo.var7 = %S\n", parser.get_string(L"SectionTwo", L"var7", default_value).c_str()); - printf_s("SectionTwo.var8 = %S\n", parser.get_string(L"SectionTwo", L"var8", default_value).c_str()); - printf_s("SectionTwo.var9 = %S\n", parser.get_string(L"SectionTwo", L"var9", default_value).c_str()); - printf_s("SectionTwo.var10 = %S\n", parser.get_string(L"SectionTwo", L"var10", default_value).c_str()); + printf_s("SectionTwo.var1 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var1"), default_value).c_str()); + printf_s("SectionTwo.var2 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var2"), default_value).c_str()); + printf_s("SectionTwo.var3 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var3"), default_value).c_str()); + printf_s("SectionTwo.var4 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var4"), default_value).c_str()); + printf_s("SectionTwo.var5 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var5"), default_value).c_str()); + printf_s("SectionTwo.var6 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var6"), default_value).c_str()); + printf_s("SectionTwo.var7 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var7"), default_value).c_str()); + printf_s("SectionTwo.var8 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var8"), default_value).c_str()); + printf_s("SectionTwo.var9 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var9"), default_value).c_str()); + printf_s("SectionTwo.var10 = %S\n", parser.get_string(SYSSTR("SectionTwo"), SYSSTR("var10"), default_value).c_str()); printf_s("\n"); - printf_s("AnotherSection.var1 = %S\n", parser.get_string(L"AnotherSection", L"var1", default_value).c_str()); - printf_s("AnotherSection.var2 = %S\n", parser.get_string(L"AnotherSection", L"var2", default_value).c_str()); - printf_s("AnotherSection.var3 = %S\n", parser.get_string(L"AnotherSection", L"var3", default_value).c_str()); - printf_s("AnotherSection.var4 = %S\n", parser.get_string(L"AnotherSection", L"var4", default_value).c_str()); - printf_s("AnotherSection.var5 = %S\n", parser.get_string(L"AnotherSection", L"var5", default_value).c_str()); + printf_s("AnotherSection.var1 = %S\n", parser.get_string(SYSSTR("AnotherSection"), SYSSTR("var1"), default_value).c_str()); + printf_s("AnotherSection.var2 = %S\n", parser.get_string(SYSSTR("AnotherSection"), SYSSTR("var2"), default_value).c_str()); + printf_s("AnotherSection.var3 = %S\n", parser.get_string(SYSSTR("AnotherSection"), SYSSTR("var3"), default_value).c_str()); + printf_s("AnotherSection.var4 = %S\n", parser.get_string(SYSSTR("AnotherSection"), SYSSTR("var4"), default_value).c_str()); + printf_s("AnotherSection.var5 = %S\n", parser.get_string(SYSSTR("AnotherSection"), SYSSTR("var5"), default_value).c_str()); } } // namespace RC::Parser::Experimental diff --git a/deps/first/IniParser/src/Ini.cpp b/deps/first/IniParser/src/Ini.cpp index 20670ccab..f2bd072cc 100644 --- a/deps/first/IniParser/src/Ini.cpp +++ b/deps/first/IniParser/src/Ini.cpp @@ -4,7 +4,7 @@ namespace RC::Ini { - auto Parser::parse_internal(File::StringType& input) -> void + auto Parser::parse_internal(SystemStringType& input) -> void { // Tokenize -> START ParserBase::Tokenizer tokenizer; @@ -24,24 +24,24 @@ namespace RC::Ini { ParserBase::TokenContainer tc; - tc.add(ParserBase::Token::create(IniTokenType::CarriageReturn, STR("CarriageReturn"), STR("\r"))); - tc.add(ParserBase::Token::create(IniTokenType::NewLine, STR("NewLine"), STR("\n"))); - tc.add(ParserBase::Token::create(IniTokenType::Space, STR("Space"), STR(" "))); + tc.add(ParserBase::Token::create(IniTokenType::CarriageReturn, SYSSTR("CarriageReturn"), SYSSTR("\r"))); + tc.add(ParserBase::Token::create(IniTokenType::NewLine, SYSSTR("NewLine"), SYSSTR("\n"))); + tc.add(ParserBase::Token::create(IniTokenType::Space, SYSSTR("Space"), SYSSTR(" "))); tc.add(ParserBase::Token::create(IniTokenType::Characters, - STR("Characters"), - STR(""), + SYSSTR("Characters"), + SYSSTR(""), ParserBase::Token::HasData::Yes)); // Empty identifier will match everything that no other token identifier matches - tc.add(ParserBase::Token::create /**/ (IniTokenType::Equals, STR("Equals"), STR("="))); - tc.add(ParserBase::Token::create(IniTokenType::ClosingSquareBracket, STR("CloseSquareBracket"), STR("]"))); - tc.add(ParserBase::Token::create(IniTokenType::OpeningSquareBracket, STR("OpenSquareBracket"), STR("["))); - tc.add(ParserBase::Token::create(IniTokenType::SemiColon, STR("SemiColon"), STR(";"))); + tc.add(ParserBase::Token::create /**/ (IniTokenType::Equals, SYSSTR("Equals"), SYSSTR("="))); + tc.add(ParserBase::Token::create(IniTokenType::ClosingSquareBracket, SYSSTR("CloseSquareBracket"), SYSSTR("]"))); + tc.add(ParserBase::Token::create(IniTokenType::OpeningSquareBracket, SYSSTR("OpenSquareBracket"), SYSSTR("["))); + tc.add(ParserBase::Token::create(IniTokenType::SemiColon, SYSSTR("SemiColon"), SYSSTR(";"))); tc.set_eof_token(IniTokenType::EndOfFile); return tc; } - auto Parser::get_value(const File::StringType& section, const File::StringType& key, CanThrow can_throw) const + auto Parser::get_value(const SystemStringType& section, const SystemStringType& key, CanThrow can_throw) const -> std::optional> { if (!m_parsing_is_complete) @@ -76,7 +76,7 @@ namespace RC::Ini } } - auto Parser::parse(File::StringType& input) -> void + auto Parser::parse(SystemStringType& input) -> void { parse_internal(input); } @@ -87,7 +87,7 @@ namespace RC::Ini parse_internal(input); } - auto Parser::get_list(const File::StringType& section) -> List + auto Parser::get_list(const SystemStringType& section) -> List { const auto& section_iter = m_sections.find(section); @@ -101,13 +101,13 @@ namespace RC::Ini } } - auto Parser::get_ordered_list(const File::StringType& section) -> List + auto Parser::get_ordered_list(const SystemStringType& section) -> List { return get_list(section); } - auto Parser::get_string(const File::StringType& section, const File::StringType& key, const File::StringType& default_value) const noexcept - -> const File::StringType& + auto Parser::get_string(const SystemStringType& section, const SystemStringType& key, const SystemStringType& default_value) const noexcept + -> const SystemStringType& { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -128,7 +128,7 @@ namespace RC::Ini } } - auto Parser::get_string(const File::StringType& section, const File::StringType& key) const -> const File::StringType& + auto Parser::get_string(const SystemStringType& section, const SystemStringType& key) const -> const SystemStringType& { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -149,7 +149,7 @@ namespace RC::Ini } } - auto Parser::get_int64(const File::StringType& section, const File::StringType& key, int64_t default_value) const noexcept -> int64_t + auto Parser::get_int64(const SystemStringType& section, const SystemStringType& key, int64_t default_value) const noexcept -> int64_t { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -170,7 +170,7 @@ namespace RC::Ini } } - auto Parser::get_int64(const File::StringType& section, const File::StringType& key) const -> int64_t + auto Parser::get_int64(const SystemStringType& section, const SystemStringType& key) const -> int64_t { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -191,7 +191,7 @@ namespace RC::Ini } } - auto Parser::get_float(const File::StringType& section, const File::StringType& key, float default_value) const noexcept -> float + auto Parser::get_float(const SystemStringType& section, const SystemStringType& key, float default_value) const noexcept -> float { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -212,7 +212,7 @@ namespace RC::Ini } } - auto Parser::get_float(const File::StringType& section, const File::StringType& key) const -> float + auto Parser::get_float(const SystemStringType& section, const SystemStringType& key) const -> float { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -233,7 +233,7 @@ namespace RC::Ini } } - auto Parser::get_bool(const File::StringType& section, const File::StringType& key, bool default_value) const noexcept -> bool + auto Parser::get_bool(const SystemStringType& section, const SystemStringType& key, bool default_value) const noexcept -> bool { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -254,7 +254,7 @@ namespace RC::Ini } } - auto Parser::get_bool(const File::StringType& section, const File::StringType& key) const -> bool + auto Parser::get_bool(const SystemStringType& section, const SystemStringType& key) const -> bool { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) diff --git a/deps/first/IniParser/src/JSON.cpp b/deps/first/IniParser/src/JSON.cpp index a0a71f85d..b84c2659c 100644 --- a/deps/first/IniParser/src/JSON.cpp +++ b/deps/first/IniParser/src/JSON.cpp @@ -11,7 +11,7 @@ namespace RC::Parser return std::string{in.begin(), in.end()}; } - static auto has_only_spaces(const File::StringType& data) -> bool + static auto has_only_spaces(const SystemStringType& data) -> bool { if (std::all_of(data.begin(), data.end(), [](File::CharType c) { return std::isspace(c) || c == '\n'; @@ -27,11 +27,11 @@ namespace RC::Parser } } - auto JSONInternal::ItemBase::get_name() -> File::StringViewType + auto JSONInternal::ItemBase::get_name() -> SystemStringViewType { if (m_is_global_scope) { - return STR("-- IS ANONYMOUS GLOBAL --"); + return SYSSTR("-- IS ANONYMOUS GLOBAL --"); } else { @@ -39,31 +39,31 @@ namespace RC::Parser } } - auto JSONInternal::StringItem::to_string() -> File::StringType + auto JSONInternal::StringItem::to_string() -> SystemStringType { - return std::format(STR("String = \"{}\""), m_value); + return std::format(SYSSTR("String = \"{}\""), m_value); } - auto JSONInternal::ObjectScope::to_string() -> File::StringType + auto JSONInternal::ObjectScope::to_string() -> SystemStringType { - File::StringType str = std::format(STR("Object = \"{}\""), get_name()); + SystemStringType str = std::format(SYSSTR("Object = \"{}\""), get_name()); for (const auto& member : m_members) { - str.append(std::format(STR("\n\"{}\" = {}"), member->get_name(), member->to_string())); + str.append(std::format(SYSSTR("\n\"{}\" = {}"), member->get_name(), member->to_string())); } return str; } - auto JSONInternal::ArrayScope::to_string() -> File::StringType + auto JSONInternal::ArrayScope::to_string() -> SystemStringType { - return std::format(STR("Array = \"{}\""), get_name()); + return std::format(SYSSTR("Array = \"{}\""), get_name()); } - auto JSONInternal::TokenParser::token_to_string(const Token& token) -> File::StringType + auto JSONInternal::TokenParser::token_to_string(const Token& token) -> SystemStringType { - File::StringType string{}; + SystemStringType string{}; // TODO: Support manual escaping of double quotes with '\' while (peek().get_type() != TokenType::DoubleQuote) @@ -342,18 +342,18 @@ namespace RC::Parser } } - auto JSON::parse_internal(File::StringType& input) -> void + auto JSON::parse_internal(SystemStringType& input) -> void { Tokenizer tokenizer; TokenContainer tc; - tc.add(Token::create(JSONInternal::TokenType::OpenCurlyBrace, STR("OpenCurlyBrace"), STR("{"))); - tc.add(Token::create(JSONInternal::TokenType::CloseCurlyBrace, STR("CloseCurlyBrace"), STR("}"))); - tc.add(Token::create(JSONInternal::TokenType::OpenSquareBracket, STR("OpenSquareBracket"), STR("["))); - tc.add(Token::create(JSONInternal::TokenType::CloseSquareBracket, STR("CloseSquareBracket"), STR("]"))); - tc.add(Token::create(JSONInternal::TokenType::Colon, STR("Colon"), STR(":"))); - tc.add(Token::create(JSONInternal::TokenType::Comma, STR("Comma"), STR(","))); - tc.add(Token::create(JSONInternal::TokenType::DoubleQuote, STR("DoubleQuote"), STR("\""))); - tc.add(Token::create(JSONInternal::TokenType::Characters, STR("Characters"), STR(""), Token::HasData::Yes)); + tc.add(Token::create(JSONInternal::TokenType::OpenCurlyBrace, SYSSTR("OpenCurlyBrace"), SYSSTR("{"))); + tc.add(Token::create(JSONInternal::TokenType::CloseCurlyBrace, SYSSTR("CloseCurlyBrace"), SYSSTR("}"))); + tc.add(Token::create(JSONInternal::TokenType::OpenSquareBracket, SYSSTR("OpenSquareBracket"), SYSSTR("["))); + tc.add(Token::create(JSONInternal::TokenType::CloseSquareBracket, SYSSTR("CloseSquareBracket"), SYSSTR("]"))); + tc.add(Token::create(JSONInternal::TokenType::Colon, SYSSTR("Colon"), SYSSTR(":"))); + tc.add(Token::create(JSONInternal::TokenType::Comma, SYSSTR("Comma"), SYSSTR(","))); + tc.add(Token::create(JSONInternal::TokenType::DoubleQuote, SYSSTR("DoubleQuote"), SYSSTR("\""))); + tc.add(Token::create(JSONInternal::TokenType::Characters, SYSSTR("Characters"), SYSSTR(""), Token::HasData::Yes)); tc.set_eof_token(JSONInternal::TokenType::EndOfFile); tokenizer.set_available_tokens(std::move(tc)); tokenizer.tokenize(input); @@ -362,7 +362,7 @@ namespace RC::Parser m_token_parser->parse(); } - auto JSON::parse(File::StringType& input) -> void + auto JSON::parse(SystemStringType& input) -> void { parse_internal(input); } @@ -391,7 +391,7 @@ namespace RC::Parser */ /**/ - File::StringType input = LR"( + SystemStringType input = LR"( { "my key": "my string, value", "my second key": "my other string value", diff --git a/deps/first/IniParser/src/TokenParser.cpp b/deps/first/IniParser/src/TokenParser.cpp index dd633366e..7ce0adff1 100644 --- a/deps/first/IniParser/src/TokenParser.cpp +++ b/deps/first/IniParser/src/TokenParser.cpp @@ -28,10 +28,10 @@ namespace RC::Ini bool is_bool{false}; }; - auto static is_int(File::StringViewType data) -> Int + auto static is_int(SystemStringType data) -> Int { bool has_0x_prefix = [&]() { - return (data.size() > 2 && data[0] == L'0' && (data[1] == L'x' || data[1] == L'X')); + return (data.size() > 2 && data[0] == SYSSTR('0') && (data[1] == SYSSTR('x') || data[1] == SYSSTR('X'))); }(); if (!has_0x_prefix && data[0] != L'-' && std::iswdigit(data[0]) == 0) @@ -40,10 +40,10 @@ namespace RC::Ini } else { - File::StringViewType string = has_0x_prefix ? File::StringViewType{data.begin() + 2, data.end()} : data; - if (!has_0x_prefix && data[0] == STR('-')) + SystemStringType string = has_0x_prefix ? SystemStringType{data.begin() + 2, data.end()} : data; + if (!has_0x_prefix && data[0] == SYSSTR('-')) { - string = File::StringViewType{string.begin() + 1, string.end()}; + string = SystemStringType{string.begin() + 1, string.end()}; } bool is_int = std::ranges::all_of(string.begin(), string.end(), [&](const File::CharType c) { if constexpr (std::is_same_v) @@ -60,10 +60,10 @@ namespace RC::Ini } } - auto static is_float(File::StringViewType data) -> Float + auto static is_float(SystemStringType data) -> Float { bool has_decimal_or_negative_prefix = [&]() { - return data.size() > 1 && data[0] == L'.' || data[0] == L'-'; + return data.size() > 1 && data[0] == SYSSTR('.') || data[0] == SYSSTR('-'); }(); if (!has_decimal_or_negative_prefix && std::iswdigit(data[0]) == 0) @@ -72,19 +72,19 @@ namespace RC::Ini } else { - File::StringViewType string = data.ends_with(STR('f')) ? File::StringViewType{data.begin(), data.end() - 1} : data; + SystemStringType string = data.ends_with(SYSSTR('f')) ? SystemStringType{data.begin(), data.end() - 1} : data; if (has_decimal_or_negative_prefix) { - string = File::StringViewType{string.begin() + 1, string.end()}; + string = SystemStringType{string.begin() + 1, string.end()}; } bool is_float = std::ranges::all_of(string.begin(), string.end(), [&](const File::CharType c) { if constexpr (std::is_same_v) { - return has_decimal_or_negative_prefix ? std::iswxdigit(c) : std::iswdigit(c) != 0 || c == STR('.'); + return has_decimal_or_negative_prefix ? std::iswxdigit(c) : std::iswdigit(c) != 0 || c == SYSSTR('.'); } else { - return has_decimal_or_negative_prefix ? std::isxdigit(c) : std::isdigit(c) != 0 || c == STR('.'); + return has_decimal_or_negative_prefix ? std::isxdigit(c) : std::isdigit(c) != 0 || c == SYSSTR('.'); } }); @@ -92,20 +92,17 @@ namespace RC::Ini } } - auto static is_bool(const File::StringType& data) -> Bool + auto static is_bool(const SystemStringType& data) -> Bool { - File::StringType all_lower_string_data = data; - // TODO: This to_lower implementation is not string-type agnostic - // A code change would be required if 'File::StringType' is defined as a char instead of a wchar_t - // Solution: Make two overloads in the string helper library, one for 'std::string' and one for 'std::wstring' - std::transform(all_lower_string_data.begin(), all_lower_string_data.end(), all_lower_string_data.begin(), [](wchar_t c) { + SystemStringType all_lower_string_data = data; + std::transform(all_lower_string_data.begin(), all_lower_string_data.end(), all_lower_string_data.begin(), [](SystemCharType c) { return std::towlower(c); }); - if (all_lower_string_data == STR("true") || all_lower_string_data == STR("1")) + if (all_lower_string_data == SYSSTR("true") || all_lower_string_data == SYSSTR("1")) { return Bool{.value = true, .is_bool = true}; } - else if (all_lower_string_data == STR("false") || all_lower_string_data == STR("0")) + else if (all_lower_string_data == SYSSTR("false") || all_lower_string_data == SYSSTR("0")) { return Bool{.value = false, .is_bool = true}; } @@ -115,7 +112,7 @@ namespace RC::Ini } } - auto TokenParser::find_variable_by_name(Section* section, const RC::StringType& name) -> std::optional> + auto TokenParser::find_variable_by_name(Section* section, const RC::SystemStringType& name) -> std::optional> { auto const& var = section->key_value_pairs.find(name); if (var != section->key_value_pairs.end()) @@ -128,7 +125,7 @@ namespace RC::Ini } } - auto TokenParser::find_variable_by_name(const StringType& name) -> std::optional> + auto TokenParser::find_variable_by_name(const SystemStringType& name) -> std::optional> { size_t occurrence_of_dot = name.find_first_of(L'.'); if (occurrence_of_dot == name.npos || occurrence_of_dot + 1 > name.size()) @@ -144,38 +141,38 @@ namespace RC::Ini } else { - const File::StringType requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); + const SystemStringType requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); return find_variable_by_name(&requested_section->second, requested_variable_name); } } } - auto state_to_string(State state) -> File::StringType + auto state_to_string(State state) -> SystemStringType { switch (state) { case State::StartOfFile: - return STR("StartOfFile"); + return SYSSTR("StartOfFile"); case State::SetSectionValue: - return STR("SetSectionValue"); + return SYSSTR("SetSectionValue"); case State::NewLineStarted: - return STR("NewLineStarted"); + return SYSSTR("NewLineStarted"); case State::CreateNewOrSetCurrentSection: - return STR("CreateNewOrSetCurrentSection"); + return SYSSTR("CreateNewOrSetCurrentSection"); case State::CreateSectionKey: - return STR("CreateSectionKey"); + return SYSSTR("CreateSectionKey"); case State::StoreSectionKey: - return STR("StoreSectionKey"); + return SYSSTR("StoreSectionKey"); } - return STR("UnknownState"); + return SYSSTR("UnknownState"); } - auto TokenParser::characters_to_string(const ParserBase::Token& characters_token) -> File::StringType + auto TokenParser::characters_to_string(const ParserBase::Token& characters_token) -> SystemStringType { auto* current_token = &characters_token; - File::StringType full_value{}; + SystemStringType full_value{}; while (true) { const auto token_type = current_token->get_type(); @@ -185,7 +182,7 @@ namespace RC::Ini } else if (token_type == IniTokenType::Space) { - full_value.append(STR(" ")); + full_value.append(SYSSTR(" ")); } else if (token_type == IniTokenType::Characters) { @@ -193,7 +190,7 @@ namespace RC::Ini } else if (token_type == IniTokenType::Equals) { - full_value.append(STR("=")); + full_value.append(SYSSTR("=")); } else if (token_type == IniTokenType::ClosingSquareBracket) { @@ -204,15 +201,15 @@ namespace RC::Ini // The next token is the last token on this line and since it's ] we don't want to include it in the string break; } - full_value.append(STR("]")); + full_value.append(SYSSTR("]")); } else if (token_type == IniTokenType::OpeningSquareBracket) { - full_value.append(STR("[")); + full_value.append(SYSSTR("[")); } else if (token_type == IniTokenType::SemiColon) { - full_value.append(STR(";")); + full_value.append(SYSSTR(";")); } // Exit early and let the state machine deal with the new line @@ -293,7 +290,7 @@ namespace RC::Ini { if (m_current_state == State::CreateNewOrSetCurrentSection) { - m_current_character_data.append(STR(" ")); + m_current_character_data.append(SYSSTR(" ")); } } @@ -384,7 +381,7 @@ namespace RC::Ini // Create the value with the correct key and an empty value and store a pointer to it so that the value can be set later m_current_value = &m_current_section->key_value_pairs.emplace(m_current_character_data, Value{}).first->second; - m_current_value->add_string_value(STR("")); + m_current_value->add_string_value(SYSSTR("")); m_current_value->set_ref(m_current_value); m_current_character_data.clear(); diff --git a/deps/first/IniParser/src/Value.cpp b/deps/first/IniParser/src/Value.cpp index 05e79ee57..36a23fa59 100644 --- a/deps/first/IniParser/src/Value.cpp +++ b/deps/first/IniParser/src/Value.cpp @@ -20,7 +20,7 @@ namespace RC::Ini m_ref = new_ref; } - auto Value::get_string_value() const -> const File::StringType& + auto Value::get_string_value() const -> const SystemStringType& { return m_string_value; } @@ -40,7 +40,7 @@ namespace RC::Ini return m_bool_value; } - auto Value::add_string_value(File::StringViewType data) -> void + auto Value::add_string_value(SystemStringViewType data) -> void { m_string_value = data; @@ -52,7 +52,7 @@ namespace RC::Ini add_type(); } - auto Value::add_int64_value(const StringType& data, int base) -> void + auto Value::add_int64_value(const SystemStringType& data, int base) -> void { m_int64_value = std::stoi(data, nullptr, base); @@ -64,7 +64,7 @@ namespace RC::Ini add_type(); } - auto Value::add_float_value(const StringType& data) -> void + auto Value::add_float_value(const SystemStringType& data) -> void { m_float_value = std::stof(data, nullptr); diff --git a/deps/first/JSON/include/JSON/Array.hpp b/deps/first/JSON/include/JSON/Array.hpp index 979b31aab..e4cd241b8 100644 --- a/deps/first/JSON/include/JSON/Array.hpp +++ b/deps/first/JSON/include/JSON/Array.hpp @@ -41,7 +41,7 @@ namespace RC::JSON public: auto new_object() -> class Object&; auto new_array() -> class Array&; - auto new_string(const StringType& value) -> void; + auto new_string(const SystemStringType& value) -> void; auto new_null() -> void; auto new_bool(bool value) -> void; @@ -87,7 +87,7 @@ namespace RC::JSON } public: - auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> StringType override; + auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Array; diff --git a/deps/first/JSON/include/JSON/Bool.hpp b/deps/first/JSON/include/JSON/Bool.hpp index 31dcfa978..ac4c44fc0 100644 --- a/deps/first/JSON/include/JSON/Bool.hpp +++ b/deps/first/JSON/include/JSON/Bool.hpp @@ -23,7 +23,7 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> StringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Bool; diff --git a/deps/first/JSON/include/JSON/Common.hpp b/deps/first/JSON/include/JSON/Common.hpp index f0aaf684f..99dc44be8 100644 --- a/deps/first/JSON/include/JSON/Common.hpp +++ b/deps/first/JSON/include/JSON/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_JSON_EXPORTS #ifndef RC_JSON_BUILD_STATIC #ifndef RC_JSON_API @@ -16,6 +18,14 @@ #endif #endif +#else + +#ifndef RC_JSON_API +#define RC_JSON_API +#endif + +#endif + #include #include @@ -29,7 +39,7 @@ namespace RC::JSON class ScopeStack; } - auto inline indent(int32_t* indent_level, File::StringType& string) -> void + auto inline indent(int32_t* indent_level, SystemStringType& string) -> void { if (!indent_level) { @@ -38,7 +48,7 @@ namespace RC::JSON for (int32_t i = 0; i < *indent_level; ++i) { - string.append(STR(" ")); + string.append(SYSSTR(" ")); } } } // namespace RC::JSON diff --git a/deps/first/JSON/include/JSON/KeyValuePair.hpp b/deps/first/JSON/include/JSON/KeyValuePair.hpp index 208901e75..8c665ab32 100644 --- a/deps/first/JSON/include/JSON/KeyValuePair.hpp +++ b/deps/first/JSON/include/JSON/KeyValuePair.hpp @@ -5,13 +5,13 @@ namespace RC::JSON template struct TypedKeyValuePair { - const StringType& key; + const SystemStringType& key; T* value{}; }; struct KeyValuePair { - StringType key{}; + SystemStringType key{}; std::unique_ptr value{}; template @@ -126,13 +126,13 @@ type_to_string(get_type()), type_to_string(JSONElementType::static_type()))}; template struct JSONTypedKeyValuePair { - const StringType& key; + const SystemStringType& key; T* value{}; }; struct JSONKeyValuePair { - StringType key{}; + SystemStringType key{}; std::unique_ptr value{}; template @@ -191,7 +191,7 @@ type_to_string(get_type()), type_to_string(JSONElementType::static_type()))}; auto get(StringViewType key) const -> ValueType& { auto value = find_value_by_key(key); - if (!value) { throw std::runtime_error{to_string(std::format(STR("No key in JSON object with name {}"), key))}; } + if (!value) { throw std::runtime_error{to_string(std::format(SYSSTR("No key in JSON object with name {}"), key))}; } return *static_cast(value); } @@ -199,7 +199,7 @@ type_to_string(get_type()), type_to_string(JSONElementType::static_type()))}; auto get(StringViewType key) -> ValueType& { auto value = find_value_by_key(key); - if (!value) { throw std::runtime_error{to_string(std::format(STR("No key in JSON object with name {}"), key))}; } + if (!value) { throw std::runtime_error{to_string(std::format(SYSSTR("No key in JSON object with name {}"), key))}; } return *static_cast(value); } }; @@ -222,16 +222,16 @@ type_to_string(get_type()), type_to_string(JSONElementType::static_type()))}; struct JSONString : JSONElementBase { private: - StringType value{}; + SystemStringType value{}; public: JSONString() = default; - JSONString(StringType value) : value(std::move(value)) { } + JSONString(SystemStringType value) : value(std::move(value)) { } public: constexpr static auto static_type() -> JSONElementType { return JSONElementType::String; } - auto get() -> StringType& { return value; } - auto get() const -> const StringType& { return value; } + auto get() -> SystemStringType& { return value; } + auto get() const -> const SystemStringType& { return value; } auto get_view() -> StringViewType { return value; } auto get_view() const -> StringViewType { return value; } auto get_type() const -> JSONElementType override { return JSONElementType::String; } diff --git a/deps/first/JSON/include/JSON/Null.hpp b/deps/first/JSON/include/JSON/Null.hpp index 17943bf1f..27aeab023 100644 --- a/deps/first/JSON/include/JSON/Null.hpp +++ b/deps/first/JSON/include/JSON/Null.hpp @@ -13,7 +13,7 @@ namespace RC::JSON ~Null() override = default; public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> StringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Null; diff --git a/deps/first/JSON/include/JSON/Number.hpp b/deps/first/JSON/include/JSON/Number.hpp index 897b60e99..9fc269624 100644 --- a/deps/first/JSON/include/JSON/Number.hpp +++ b/deps/first/JSON/include/JSON/Number.hpp @@ -167,7 +167,7 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> StringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> JSON::Type override { return JSON::Type::Number; diff --git a/deps/first/JSON/include/JSON/Object.hpp b/deps/first/JSON/include/JSON/Object.hpp index f3f5dd609..207225cc9 100644 --- a/deps/first/JSON/include/JSON/Object.hpp +++ b/deps/first/JSON/include/JSON/Object.hpp @@ -30,7 +30,7 @@ namespace RC::JSON #pragma warning(disable : 4251) private: - std::unordered_map> m_members{}; + std::unordered_map> m_members{}; IsGlobalObject m_is_global_object{IsGlobalObject::No}; #pragma warning(default : 4251) @@ -44,17 +44,17 @@ namespace RC::JSON auto operator=(const Object&) -> Object& = delete; private: - auto find_value_by_key(const StringType& key) const -> Value*; - auto find_value_by_key(const StringType& key) -> Value*; + auto find_value_by_key(const SystemStringType& key) const -> Value*; + auto find_value_by_key(const SystemStringType& key) -> Value*; public: - auto new_object(StringType name) -> Object&; - auto new_array(StringType name) -> class Array&; - auto new_string(StringType name, const StringType& value) -> void; - auto new_null(StringType name) -> void; - auto new_bool(StringType name, bool value) -> void; + auto new_object(SystemStringType name) -> Object&; + auto new_array(SystemStringType name) -> class Array&; + auto new_string(SystemStringType name, const SystemStringType& value) -> void; + auto new_null(SystemStringType name) -> void; + auto new_bool(SystemStringType name, bool value) -> void; - auto add_object(StringType name, std::unique_ptr) -> void; + auto add_object(SystemStringType name, std::unique_ptr) -> void; auto get() -> decltype(m_members)& { @@ -66,34 +66,34 @@ namespace RC::JSON }; template - auto get(const StringType& key) const -> ValueType& + auto get(const SystemStringType& key) const -> ValueType& { auto value = find_value_by_key(key); if (!value) { - throw std::runtime_error{to_string(std::format(STR("No key in JSON object with name {}"), key))}; + throw std::runtime_error{to_string(std::format(SYSSTR("No key in JSON object with name {}"), key))}; } return *static_cast(value); } template - auto get(const StringType& key) -> ValueType& + auto get(const SystemStringType& key) -> ValueType& { auto value = find_value_by_key(key); if (!value) { - throw std::runtime_error{to_string(std::format(STR("No key in JSON object with name {}"), key))}; + throw std::runtime_error{to_string(std::format(SYSSTR("No key in JSON object with name {}"), key))}; } return *static_cast(value); } template - auto new_number(StringType name, number_type value) -> void + auto new_number(SystemStringType name, number_type value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> StringType override; + auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Object; diff --git a/deps/first/JSON/include/JSON/Parser/Parser.hpp b/deps/first/JSON/include/JSON/Parser/Parser.hpp index a3324df5d..252c7d02a 100644 --- a/deps/first/JSON/include/JSON/Parser/Parser.hpp +++ b/deps/first/JSON/include/JSON/Parser/Parser.hpp @@ -10,6 +10,6 @@ namespace RC::JSON::Parser { - RC_JSON_API auto parse(StringType& input) -> std::unique_ptr; + RC_JSON_API auto parse(SystemStringType& input) -> std::unique_ptr; RC_JSON_API auto parse(const File::Handle&) -> std::unique_ptr; } // namespace RC::JSON::Parser diff --git a/deps/first/JSON/include/JSON/Parser/TokenParser.hpp b/deps/first/JSON/include/JSON/Parser/TokenParser.hpp index b28cdc9d4..35e003afa 100644 --- a/deps/first/JSON/include/JSON/Parser/TokenParser.hpp +++ b/deps/first/JSON/include/JSON/Parser/TokenParser.hpp @@ -79,7 +79,7 @@ namespace RC::JSON::Parser } } template - auto add_element_to_top(StringType key, std::unique_ptr value) -> ValueType* + auto add_element_to_top(SystemStringType key, std::unique_ptr value) -> ValueType* { auto& top = peek_top(); if (top.is()) @@ -107,7 +107,7 @@ namespace RC::JSON::Parser private: std::unique_ptr m_global_object; ScopeStack m_scope_stack{}; - StringType m_last_key{}; + SystemStringType m_last_key{}; std::unique_ptr m_last_value{}; State m_current_state{State::StartOfFile}; TokenType m_expected_token{}; @@ -115,7 +115,7 @@ namespace RC::JSON::Parser bool m_defer_element_creation{}; public: - TokenParser(const ParserBase::Tokenizer& tokenizer, File::StringType& input) : ParserBase::TokenParser(tokenizer, input) + TokenParser(const ParserBase::Tokenizer& tokenizer, SystemStringType& input) : ParserBase::TokenParser(tokenizer, input) { } virtual ~TokenParser() = default; diff --git a/deps/first/JSON/include/JSON/String.hpp b/deps/first/JSON/include/JSON/String.hpp index c3edc1fd9..f62602ddf 100644 --- a/deps/first/JSON/include/JSON/String.hpp +++ b/deps/first/JSON/include/JSON/String.hpp @@ -14,25 +14,25 @@ namespace RC::JSON RC_JSON_API constexpr static Type static_type = Type::String; private: - StringType m_data{}; + SystemStringType m_data{}; public: RC_JSON_API String() = default; - RC_JSON_API explicit String(StringViewType string); + RC_JSON_API explicit String(SystemStringViewType string); RC_JSON_API ~String() override = default; public: - RC_JSON_API auto get() -> StringType& + RC_JSON_API auto get() -> SystemStringType& { return m_data; } - RC_JSON_API auto get_view() const -> StringViewType + RC_JSON_API auto get_view() const -> SystemStringViewType { return m_data; } public: - RC_JSON_API auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> StringType override; + RC_JSON_API auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; RC_JSON_API auto get_type() const -> Type override { return Type::String; diff --git a/deps/first/JSON/include/JSON/Value.hpp b/deps/first/JSON/include/JSON/Value.hpp index 5914d163f..e7fa78b18 100644 --- a/deps/first/JSON/include/JSON/Value.hpp +++ b/deps/first/JSON/include/JSON/Value.hpp @@ -50,7 +50,7 @@ namespace RC::JSON virtual ~Value() = default; public: - virtual auto serialize(ShouldFormat, int32_t* indent_level) -> StringType = 0; + virtual auto serialize(ShouldFormat, int32_t* indent_level) -> SystemStringType = 0; virtual auto get_type() const -> Type = 0; public: diff --git a/deps/first/JSON/src/Array.cpp b/deps/first/JSON/src/Array.cpp index 0f02e46f9..413d103f8 100644 --- a/deps/first/JSON/src/Array.cpp +++ b/deps/first/JSON/src/Array.cpp @@ -16,7 +16,7 @@ namespace RC::JSON return static_cast(*m_members.emplace_back(std::make_unique())); } - auto Array::new_string(const StringType& value) -> void + auto Array::new_string(const SystemStringType& value) -> void { m_members.emplace_back(std::make_unique(value)); } @@ -36,22 +36,22 @@ namespace RC::JSON m_members.emplace_back(std::move(object)); } - auto Array::serialize(ShouldFormat should_format, int32_t* indent_level) -> StringType + auto Array::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { if (!indent_level) { throw std::runtime_error{"Must supply an indent_level pointer"}; }; - StringType array_as_string{}; + SystemStringType array_as_string{}; if (should_format == ShouldFormat::Yes && !m_members.empty()) { - array_as_string.append(STR("[\n")); + array_as_string.append(SYSSTR("[\n")); } else { - array_as_string.append(STR("[")); + array_as_string.append(SYSSTR("[")); } ++(*indent_level); @@ -70,11 +70,11 @@ namespace RC::JSON { if (should_format == ShouldFormat::Yes) { - array_as_string.append(STR(",\n")); + array_as_string.append(SYSSTR(",\n")); } else { - array_as_string.append(STR(",")); + array_as_string.append(SYSSTR(",")); } } @@ -85,13 +85,13 @@ namespace RC::JSON if (should_format == ShouldFormat::Yes && !m_members.empty()) { - array_as_string.append(STR("\n")); + array_as_string.append(SYSSTR("\n")); indent(indent_level, array_as_string); - array_as_string.append(STR("]")); + array_as_string.append(SYSSTR("]")); } else { - array_as_string.append(STR("]")); + array_as_string.append(SYSSTR("]")); } if (!m_members.empty()) diff --git a/deps/first/JSON/src/Bool.cpp b/deps/first/JSON/src/Bool.cpp index 79ff91871..62b894131 100644 --- a/deps/first/JSON/src/Bool.cpp +++ b/deps/first/JSON/src/Bool.cpp @@ -6,10 +6,10 @@ namespace RC::JSON { } - auto Bool::serialize(ShouldFormat should_format, int32_t* indent_level) -> StringType + auto Bool::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { (void)should_format; (void)indent_level; - return m_underlying_value ? STR("true") : STR("false"); + return m_underlying_value ? SYSSTR("true") : SYSSTR("false"); } } // namespace RC::JSON diff --git a/deps/first/JSON/src/Null.cpp b/deps/first/JSON/src/Null.cpp index 867dd612c..0cbda75f9 100644 --- a/deps/first/JSON/src/Null.cpp +++ b/deps/first/JSON/src/Null.cpp @@ -2,10 +2,10 @@ namespace RC::JSON { - auto Null::serialize(ShouldFormat should_format, int32_t* indent_level) -> StringType + auto Null::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { (void)should_format; (void)indent_level; - return STR("null"); + return SYSSTR("null"); } } // namespace RC::JSON diff --git a/deps/first/JSON/src/Number.cpp b/deps/first/JSON/src/Number.cpp index 4628a8948..eb97ade3b 100644 --- a/deps/first/JSON/src/Number.cpp +++ b/deps/first/JSON/src/Number.cpp @@ -42,7 +42,7 @@ namespace RC::JSON m_stored_type = Type::Double; } - auto Number::serialize(ShouldFormat should_format, int32_t* indent_level) -> StringType + auto Number::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { (void)should_format; (void)indent_level; diff --git a/deps/first/JSON/src/Object.cpp b/deps/first/JSON/src/Object.cpp index e4c1c265b..172ed07cd 100644 --- a/deps/first/JSON/src/Object.cpp +++ b/deps/first/JSON/src/Object.cpp @@ -6,7 +6,7 @@ namespace RC::JSON { - auto Object::find_value_by_key(const StringType& look_for_key) const -> Value* + auto Object::find_value_by_key(const SystemStringType& look_for_key) const -> Value* { if (auto it = m_members.find(look_for_key); it != m_members.end()) { @@ -17,7 +17,7 @@ namespace RC::JSON return nullptr; } } - auto Object::find_value_by_key(const StringType& look_for_key) -> Value* + auto Object::find_value_by_key(const SystemStringType& look_for_key) -> Value* { if (auto it = m_members.find(look_for_key); it != m_members.end()) { @@ -29,52 +29,52 @@ namespace RC::JSON } } - auto Object::new_object(StringType name) -> Object& + auto Object::new_object(SystemStringType name) -> Object& { return *static_cast(m_members.emplace(std::move(name), std::make_unique()).first->second.get()); } - auto Object::new_array(StringType name) -> Array& + auto Object::new_array(SystemStringType name) -> Array& { return *static_cast(m_members.emplace(std::move(name), std::make_unique()).first->second.get()); } - auto Object::new_string(StringType name, const StringType& value) -> void + auto Object::new_string(SystemStringType name, const SystemStringType& value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto Object::new_null(StringType name) -> void + auto Object::new_null(SystemStringType name) -> void { m_members.emplace(std::move(name), std::make_unique()); } - auto Object::new_bool(StringType name, bool value) -> void + auto Object::new_bool(SystemStringType name, bool value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto Object::add_object(StringType name, std::unique_ptr object) -> void + auto Object::add_object(SystemStringType name, std::unique_ptr object) -> void { m_members.emplace(std::move(name), std::move(object)); } - auto Object::serialize(ShouldFormat should_format, int32_t* indent_level) -> StringType + auto Object::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { if (!indent_level) { throw std::runtime_error{"Must supply an indent_level pointer"}; }; - StringType object_as_string{}; + SystemStringType object_as_string{}; if (should_format == ShouldFormat::Yes && !m_members.empty()) { - object_as_string.append(STR("{\n")); + object_as_string.append(SYSSTR("{\n")); } else { - object_as_string.append(STR("{")); + object_as_string.append(SYSSTR("{")); } ++(*indent_level); @@ -87,18 +87,18 @@ namespace RC::JSON indent(indent_level, object_as_string); } - object_as_string.append(std::format(STR("\"{}\":"), key)); + object_as_string.append(std::format(SYSSTR("\"{}\":"), key)); object_as_string.append(value->serialize(should_format, indent_level)); if (member_count + 1 < m_members.size()) { if (should_format == ShouldFormat::Yes) { - object_as_string.append(STR(",\n")); + object_as_string.append(SYSSTR(",\n")); } else { - object_as_string.append(STR(",")); + object_as_string.append(SYSSTR(",")); } } @@ -109,13 +109,13 @@ namespace RC::JSON if (should_format == ShouldFormat::Yes && !m_members.empty()) { - object_as_string.append(STR("\n")); + object_as_string.append(SYSSTR("\n")); indent(indent_level, object_as_string); - object_as_string.append(STR("}")); + object_as_string.append(SYSSTR("}")); } else { - object_as_string.append(STR("}")); + object_as_string.append(SYSSTR("}")); } if (!m_members.empty() || m_is_global_object == IsGlobalObject::Yes) diff --git a/deps/first/JSON/src/Parser/Parser.cpp b/deps/first/JSON/src/Parser/Parser.cpp index 4dbc3beff..7d2cc80ca 100644 --- a/deps/first/JSON/src/Parser/Parser.cpp +++ b/deps/first/JSON/src/Parser/Parser.cpp @@ -11,12 +11,12 @@ namespace RC::JSON::Parser { ParserBase::TokenContainer tc; - tc.add(ParserBase::Token::create(TokenType::CarriageReturn, STR("CarriageReturn"), STR("\r"))); - tc.add(ParserBase::Token::create(TokenType::NewLine, STR("NewLine"), STR("\n"))); - tc.add(ParserBase::Token::create(TokenType::DoubleQuote, STR("DoubleQuote"), STR("\""))); + tc.add(ParserBase::Token::create(TokenType::CarriageReturn, SYSSTR("CarriageReturn"), SYSSTR("\r"))); + tc.add(ParserBase::Token::create(TokenType::NewLine, SYSSTR("NewLine"), SYSSTR("\n"))); + tc.add(ParserBase::Token::create(TokenType::DoubleQuote, SYSSTR("DoubleQuote"), SYSSTR("\""))); tc.add(ParserBase::Token::create(TokenType::Characters, - STR("Characters"), - STR(""), + SYSSTR("Characters"), + SYSSTR(""), ParserBase::Token::HasData::Yes)); // Empty identifier will match everything that no other token identifier matches tc.add(ParserBase::Token::create(TokenType::ClosingCurlyBrace, STR("ClosingCurlyBrace"), STR("}"))); tc.add(ParserBase::Token::create(TokenType::OpeningCurlyBrace, STR("OpeningCurlyBrace"), STR("{"))); @@ -32,7 +32,7 @@ namespace RC::JSON::Parser return tc; } - static auto parse_internal(File::StringType& input) -> std::unique_ptr + static auto parse_internal(SystemStringType& input) -> std::unique_ptr { // Tokenize -> START ParserBase::Tokenizer tokenizer; @@ -54,7 +54,7 @@ namespace RC::JSON::Parser } } // namespace Internal - auto parse(File::StringType& input) -> std::unique_ptr + auto parse(SystemStringType& input) -> std::unique_ptr { return Internal::parse_internal(input); } diff --git a/deps/first/JSON/src/Parser/TokenParser.cpp b/deps/first/JSON/src/Parser/TokenParser.cpp index df0b83912..6c91cb483 100644 --- a/deps/first/JSON/src/Parser/TokenParser.cpp +++ b/deps/first/JSON/src/Parser/TokenParser.cpp @@ -32,9 +32,9 @@ namespace RC::JSON::Parser throw std::runtime_error{e}; \ } - static auto is_number(StringViewType data) -> bool + static auto is_number(SystemStringViewType data) -> bool { - return std::ranges::all_of(data.begin(), data.end(), [&](const CharType c) { + return std::ranges::all_of(data.begin(), data.end(), [&](const SystemCharType c) { if constexpr (std::is_same_v) { return std::iswdigit(c) != 0; @@ -71,7 +71,7 @@ namespace RC::JSON::Parser return m_storage.back(); } - static auto has_only_spaces(const File::StringType& data) -> bool + static auto has_only_spaces(const SystemStringType& data) -> bool { return std::all_of(data.begin(), data.end(), [](File::CharType c) { return std::isspace(c) || c == '\n'; @@ -171,7 +171,7 @@ namespace RC::JSON::Parser else if (m_current_state == State::ReadValue) { auto data_raw = get_data(token); - StringType data_no_spaces = data_raw; + SystemStringType data_no_spaces = data_raw; data_no_spaces.erase(std::remove_if(data_no_spaces.begin(), data_no_spaces.end(), [](wchar_t c) { @@ -185,7 +185,7 @@ namespace RC::JSON::Parser { do_comma_verification(); - m_last_value = std::make_unique(std::stoll(data_no_spaces, nullptr)); + m_last_value = std::make_unique((uint64_t)std::stoll(data_no_spaces, nullptr)); } else if (!m_string_started) { diff --git a/deps/first/JSON/src/String.cpp b/deps/first/JSON/src/String.cpp index 5001c7c2c..6a89d1165 100644 --- a/deps/first/JSON/src/String.cpp +++ b/deps/first/JSON/src/String.cpp @@ -2,12 +2,12 @@ namespace RC::JSON { - String::String(StringViewType string) : m_data(string) + String::String(SystemStringViewType string) : m_data(string) { } - auto String::serialize([[maybe_unused]] ShouldFormat should_format, [[maybe_unused]] int32_t* indent_level) -> StringType + auto String::serialize([[maybe_unused]] ShouldFormat should_format, [[maybe_unused]] int32_t* indent_level) -> SystemStringType { - return std::format(STR("\"{}\""), m_data); + return std::format(SYSSTR("\"{}\""), m_data); } } // namespace RC::JSON diff --git a/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp b/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp index 466233e24..9a197a847 100644 --- a/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp +++ b/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_LUA_MADE_SIMPLE_EXPORTS #ifndef RC_LUA_MADE_SIMPLE_BUILD_STATIC #ifndef RC_LMS_API @@ -15,3 +17,12 @@ #define RC_LMS_API __declspec(dllexport) #endif #endif + +#else + + +#ifndef RC_LMS_API +#define RC_LMS_API +#endif + +#endif \ No newline at end of file diff --git a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp index a4ca10f2f..31a88779a 100644 --- a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp +++ b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include @@ -26,10 +28,10 @@ namespace RC::LuaMadeSimple /** * @tparam StackIndex Valid values are -1 for table key and -2 for table value */ - template + template struct RC_LMS_API LuaTableData { - const class Lua* lua{}; + const LuaT* lua{}; [[nodiscard]] auto is_nil() -> bool { @@ -85,12 +87,14 @@ namespace RC::LuaMadeSimple /** * Helper for dealing with Lua tables passed from Lua to C++ */ + template struct RC_LMS_API LuaTableReference { - LuaTableData<-1> key; - LuaTableData<-2> value; + LuaTableData<-1, LuaT> key; + LuaTableData<-2, LuaT> value; }; + class Lua; using PostFunctionProcessCallback = void (*)(const Lua&); /** @@ -292,7 +296,7 @@ namespace RC::LuaMadeSimple { lua_pushboolean(get_lua_instance().get_lua_state(), value); } - else if constexpr (std::is_same_v || std::is_same_v) + else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) { lua_pushinteger(get_lua_instance().get_lua_state(), value); } @@ -517,9 +521,9 @@ namespace RC::LuaMadeSimple } RC_LMS_API auto execute_file(std::string_view) const -> void; - RC_LMS_API auto execute_file(std::wstring_view) const -> void; + RC_LMS_API auto execute_file(std::u16string_view) const -> void; RC_LMS_API auto execute_string(std::string_view) const -> void; - RC_LMS_API auto execute_string(std::wstring_view) const -> void; + RC_LMS_API auto execute_string(std::u16string_view) const -> void; RC_LMS_API auto open_all_libs() const -> void; RC_LMS_API auto set_hook(lua_Hook, int32_t mask, int32_t count) const -> void; @@ -571,7 +575,7 @@ namespace RC::LuaMadeSimple [[nodiscard]] RC_LMS_API auto is_table(int32_t force_index = 1) const -> bool; [[nodiscard]] RC_LMS_API auto get_table() const -> Table; - using ForEachInTableCallable = std::function; + using ForEachInTableCallable = std::function)>; // If you use a lambda then make absolutely sure to capture the 'LuaMadeSimple::Lua' object by reference // If you don't then it will be improperly copied and things, including nested for_each calls, will break diff --git a/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp b/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp index 411ddfe7d..71da33188 100644 --- a/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp +++ b/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp @@ -434,7 +434,7 @@ namespace RC::LuaMadeSimple } } - auto Lua::execute_file(std::wstring_view file_name_and_path) const -> void + auto Lua::execute_file(std::u16string_view file_name_and_path) const -> void { #pragma warning(disable : 4244) std::string file_name_and_path_ansi = std::string(file_name_and_path.begin(), file_name_and_path.end()); @@ -455,7 +455,7 @@ namespace RC::LuaMadeSimple } } - auto Lua::execute_string(std::wstring_view code) const -> void + auto Lua::execute_string(std::u16string_view code) const -> void { #pragma warning(disable : 4244) std::string code_ansi = std::string(code.begin(), code.end()); @@ -662,7 +662,7 @@ namespace RC::LuaMadeSimple // It's up to the 'callable' to fetch the key/value from the stack // This makes dealing with different types easier // TODO: Make it so you don't need to pass the 'this' pointer to both the key & value struct - LuaTableReference table{.key = {this}, .value = {this}}; + LuaTableReference table{.key = {this}, .value = {this}}; if (callable(table)) { lua_pop(get_lua_state(), 3); diff --git a/deps/first/LuaRaw/src/luauser.c b/deps/first/LuaRaw/src/luauser.c index 889de0178..813e29364 100644 --- a/deps/first/LuaRaw/src/luauser.c +++ b/deps/first/LuaRaw/src/luauser.c @@ -1,3 +1,4 @@ +#ifdef WIN32 #include #include "lua.h" @@ -37,4 +38,37 @@ void LuaUnlock(lua_State* L) { /* Release control of mutex */ LeaveCriticalSection(&Gl.LockSct); -} \ No newline at end of file +} +#else +#include +#include +#include "lua.h" + +static struct { + pthread_mutex_t mutex; + bool init; +} lua_lock_mutex; + +void LuaLock(lua_State * L){ + pthread_mutex_lock(&lua_lock_mutex.mutex); +} + +void LuaUnlock(lua_State * L){ + pthread_mutex_unlock(&lua_lock_mutex.mutex); +} + +void LuaLockInitial(lua_State * L){ + if (!lua_lock_mutex.init){ + pthread_mutex_init(&lua_lock_mutex.mutex, NULL); + lua_lock_mutex.init = true; + } +} + +void LuaLockFinal(lua_State * L){ + if (lua_lock_mutex.init){ + pthread_mutex_destroy(&lua_lock_mutex.mutex); + lua_lock_mutex.init = false; + } +} + +#endif \ No newline at end of file diff --git a/deps/first/MProgram/include/ErrorObject.hpp b/deps/first/MProgram/include/ErrorObject.hpp index 8e8702956..d6204045e 100644 --- a/deps/first/MProgram/include/ErrorObject.hpp +++ b/deps/first/MProgram/include/ErrorObject.hpp @@ -1,6 +1,12 @@ #pragma once #include +#include + +#ifdef LINUX +#define sprintf_s snprintf +#define strncpy_s strncpy +#endif namespace RC { diff --git a/deps/first/ParserBase/include/ParserBase/Common.hpp b/deps/first/ParserBase/include/ParserBase/Common.hpp index fe00aac44..42daab5ea 100644 --- a/deps/first/ParserBase/include/ParserBase/Common.hpp +++ b/deps/first/ParserBase/include/ParserBase/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_PARSER_BASE_EXPORTS #ifndef RC_PARSER_BASE_BUILD_STATIC #ifndef RC_PB_API @@ -15,3 +17,11 @@ #define RC_PB_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_PB_API +#define RC_PB_API +#endif + +#endif \ No newline at end of file diff --git a/deps/first/ParserBase/include/ParserBase/Token.hpp b/deps/first/ParserBase/include/ParserBase/Token.hpp index 35c12ccd8..39c31c25b 100644 --- a/deps/first/ParserBase/include/ParserBase/Token.hpp +++ b/deps/first/ParserBase/include/ParserBase/Token.hpp @@ -12,20 +12,20 @@ namespace RC::ParserBase class TokenRule { private: - File::StringType m_debug_name; + SystemStringType m_debug_name; public: - explicit TokenRule(File::StringViewType rule_name) : m_debug_name(rule_name) + explicit TokenRule(SystemStringViewType rule_name) : m_debug_name(rule_name) { } virtual ~TokenRule() = default; public: - RC_PB_API virtual auto exec(const class Token& token, const File::CharType* start_of_token, size_t current_cursor_location, class Tokenizer&) -> int = 0; + RC_PB_API virtual auto exec(const class Token& token, const SystemCharType* start_of_token, size_t current_cursor_location, class Tokenizer&) -> int = 0; - [[nodiscard]] RC_PB_API virtual auto to_string() const -> File::StringType + [[nodiscard]] RC_PB_API virtual auto to_string() const -> SystemStringType { - return STR("BaseTokenRule (invalid)"); + return SYSSTR("BaseTokenRule (invalid)"); } }; @@ -42,8 +42,8 @@ namespace RC::ParserBase }; private: - File::StringType m_debug_name; - File::StringType m_identifier; + SystemStringType m_debug_name; + SystemStringType m_identifier; std::vector> m_rules; int m_type; // To be cast to an enum before use. This is to avoid using a template which forces everything to be in the header file. mutable size_t m_start{}; @@ -53,7 +53,7 @@ namespace RC::ParserBase HasData m_has_data; public: - RC_PB_API Token(int type, File::StringViewType name, File::StringViewType identifier, HasData has_data = HasData::No); + RC_PB_API Token(int type, SystemStringViewType name, SystemStringViewType identifier, HasData has_data = HasData::No); public: RC_PB_API auto get_type() const -> int; @@ -63,7 +63,7 @@ namespace RC::ParserBase RC_PB_API auto get_start() const -> size_t; RC_PB_API auto set_end(size_t) -> void; RC_PB_API auto get_end() const -> size_t; - RC_PB_API auto get_identifier() const -> File::StringViewType; + RC_PB_API auto get_identifier() const -> SystemStringViewType; RC_PB_API auto get_line() const -> size_t; RC_PB_API auto get_column() const -> size_t; @@ -74,7 +74,7 @@ namespace RC::ParserBase } RC_PB_API auto get_rules() const -> const std::vector>&; - [[nodiscard]] RC_PB_API auto to_string() const -> File::StringType; + [[nodiscard]] RC_PB_API auto to_string() const -> SystemStringType; public: template @@ -92,10 +92,10 @@ namespace RC::ParserBase create_internal(token); } - RC_PB_API auto static create(int type, File::StringViewType name, File::StringViewType identifier, HasData = HasData::No) -> Token; + RC_PB_API auto static create(int type, SystemStringViewType name, SystemStringViewType identifier, HasData = HasData::No) -> Token; template - auto static create(int type, File::StringViewType name, File::StringViewType identifier, HasData has_data = HasData::No) -> Token + auto static create(int type, SystemStringViewType name, SystemStringViewType identifier, HasData has_data = HasData::No) -> Token { Token token{type, name, identifier, has_data}; create_internal(token); @@ -103,7 +103,7 @@ namespace RC::ParserBase } template - auto static create(int type, File::StringViewType name, File::StringViewType identifier, HasData has_data = HasData::No) -> Token + auto static create(int type, SystemStringViewType name, SystemStringViewType identifier, HasData has_data = HasData::No) -> Token { Token token{type, name, identifier, has_data}; create_internal(token); diff --git a/deps/first/ParserBase/include/ParserBase/TokenParser.hpp b/deps/first/ParserBase/include/ParserBase/TokenParser.hpp index 708d4a743..2bd3a306b 100644 --- a/deps/first/ParserBase/include/ParserBase/TokenParser.hpp +++ b/deps/first/ParserBase/include/ParserBase/TokenParser.hpp @@ -34,7 +34,7 @@ namespace RC::ParserBase private: const class Tokenizer& m_tokenizer; - mutable File::StringType m_data; + mutable SystemStringType m_data; protected: mutable size_t m_current_token_index_being_parsed{0}; @@ -42,7 +42,7 @@ namespace RC::ParserBase public: // Investigate whether I want to std::move the input here - RC_PB_API TokenParser(const class Tokenizer&, File::StringType& input); + RC_PB_API TokenParser(const class Tokenizer&, SystemStringType& input); RC_PB_API virtual ~TokenParser() = default; protected: @@ -61,7 +61,7 @@ namespace RC::ParserBase protected: RC_PB_API auto get_token(size_t index) const -> const class Token&; - RC_PB_API auto get_data(const class Token&) const -> const File::StringType; + RC_PB_API auto get_data(const class Token&) const -> const SystemStringType; // auto find_token_with_data(int token_type, File::StringViewType data) const -> std::optional>; diff --git a/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp b/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp index 1ea87a5f7..8812f1ddb 100644 --- a/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp +++ b/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp @@ -43,7 +43,7 @@ namespace RC::ParserBase public: RC_PB_API auto set_available_tokens(TokenContainer&&) -> void; // TODO: Maybe the constructor should take the input instead of 'tokenize' - RC_PB_API auto tokenize(const File::StringType& input) -> void; + RC_PB_API auto tokenize(const SystemStringType& input) -> void; [[nodiscard]] RC_PB_API auto get_tokens() const -> const std::vector&; [[nodiscard]] RC_PB_API auto get_last_token() const -> const Token&; }; diff --git a/deps/first/ParserBase/src/Token.cpp b/deps/first/ParserBase/src/Token.cpp index 1a11b8d12..386816ec8 100644 --- a/deps/first/ParserBase/src/Token.cpp +++ b/deps/first/ParserBase/src/Token.cpp @@ -2,7 +2,7 @@ namespace RC::ParserBase { - Token::Token(int type, File::StringViewType name, File::StringViewType identifier, Token::HasData has_data) + Token::Token(int type, SystemStringViewType name, SystemStringViewType identifier, Token::HasData has_data) : m_debug_name(name), m_identifier(identifier), m_type(type), m_has_data(has_data) { } @@ -42,7 +42,7 @@ namespace RC::ParserBase return m_end; } - auto Token::get_identifier() const -> File::StringViewType + auto Token::get_identifier() const -> SystemStringViewType { return m_identifier; } @@ -62,12 +62,12 @@ namespace RC::ParserBase return m_rules; } - auto Token::to_string() const -> File::StringType + auto Token::to_string() const -> SystemStringType { return m_debug_name; } - auto Token::create(int type, File::StringViewType name, File::StringViewType identifier, HasData has_data) -> Token + auto Token::create(int type, SystemStringViewType name, SystemStringViewType identifier, HasData has_data) -> Token { Token token{type, name, identifier, has_data}; return token; diff --git a/deps/first/ParserBase/src/TokenParser.cpp b/deps/first/ParserBase/src/TokenParser.cpp index 5e75b9d19..a01c448be 100644 --- a/deps/first/ParserBase/src/TokenParser.cpp +++ b/deps/first/ParserBase/src/TokenParser.cpp @@ -4,7 +4,7 @@ namespace RC::ParserBase { - TokenParser::TokenParser(const Tokenizer& tokenizer, File::StringType& input) : m_tokenizer(tokenizer), m_data(input) + TokenParser::TokenParser(const Tokenizer& tokenizer, SystemStringType& input) : m_tokenizer(tokenizer), m_data(input) { } @@ -13,7 +13,7 @@ namespace RC::ParserBase return m_tokenizer.get_tokens()[index]; } - auto TokenParser::get_data(const Token& token) const -> const File::StringType + auto TokenParser::get_data(const Token& token) const -> const SystemStringType { if (!token.has_data()) { diff --git a/deps/first/ParserBase/src/Tokenizer.cpp b/deps/first/ParserBase/src/Tokenizer.cpp index 40e57bfec..37a9e28a9 100644 --- a/deps/first/ParserBase/src/Tokenizer.cpp +++ b/deps/first/ParserBase/src/Tokenizer.cpp @@ -41,7 +41,7 @@ namespace RC::ParserBase m_token_container = std::move(token_container); } - auto Tokenizer::tokenize(const File::StringType& input) -> void + auto Tokenizer::tokenize(const SystemStringType& input) -> void { // printf_s("Tokenizer::tokenize()\n\n"); @@ -75,12 +75,12 @@ namespace RC::ParserBase throw std::runtime_error{"[Tokenizer::tokenize] Input was empty"}; } - File::StringType a; + SystemStringType a; const File::CharType* input_array = input.c_str(); size_t global_cursor{}; - auto peek = [&](File::StringType& out_str, const File::CharType* character, size_t num_chars) -> void { + auto peek = [&](SystemStringType& out_str, const File::CharType* character, size_t num_chars) -> void { if (global_cursor + num_chars <= input.size()) { for (size_t i = 0; i < num_chars; ++i) @@ -97,8 +97,8 @@ namespace RC::ParserBase bool matched_anything{false}; }; - File::StringType current_empty_token{}; - File::StringType empty_token_data{}; + SystemStringType current_empty_token{}; + SystemStringType empty_token_data{}; TokenFoundWrapper empty_token{}; size_t start_of_empty_token{}; bool start_of_empty_token_set{}; @@ -137,8 +137,8 @@ namespace RC::ParserBase int advance_cursor_by{-1}; bool all_rules_obeyed{true}; - File::StringViewType identifier_to_find = token.get_identifier(); - File::StringType compare_to; + SystemStringViewType identifier_to_find = token.get_identifier(); + SystemStringType compare_to; size_t identifier_size = identifier_to_find.size(); peek(compare_to, c, identifier_size); bool identifier_should_match_all = identifier_to_find.empty(); @@ -213,7 +213,7 @@ namespace RC::ParserBase // This is required because the loop above stops at end-of-file without processing it deal_with_possible_empty_token(); - m_tokens_in_input.emplace_back(Token{m_token_container.m_eof_token_type, STR("EndOfFile"), STR("--EOF-DO-NOT-PARSE--")}); + m_tokens_in_input.emplace_back(Token{m_token_container.m_eof_token_type, SYSSTR("EndOfFile"), SYSSTR("--EOF-DO-NOT-PARSE--")}); } auto Tokenizer::get_tokens() const -> const std::vector& diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp index c06dffd05..eff4e6fc9 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef WIN32 + #ifndef RC_SINGLE_PASS_SIG_SCANNER_EXPORTS #ifndef RC_SINGLE_PASS_SIG_SCANNER_BUILD_STATIC #ifndef RC_SPSS_API @@ -15,3 +17,12 @@ #define RC_SPSS_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_SPSS_API +#define RC_SPSS_API +#endif + +#endif + diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp new file mode 100644 index 000000000..cd39a1938 --- /dev/null +++ b/deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include +#include + +struct DLData +{ + std::string libname; + uint8_t* base_address; + uint64_t map_start, map_end; + size_t size; + // sorted by start address + std::set> phdrs; + std::tuple find_phdr(uint8_t* addr) { + for (auto& phdr : phdrs) { + // use end address to find the phdr + if (std::get<0>(phdr) + std::get<1>(phdr) > addr) { + return phdr; + } + } + return std::make_tuple(nullptr, 0, 0); + } +}; diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp index 9cd281a16..bdd83425f 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp @@ -1,343 +1,7 @@ #pragma once -#include -#include -#include -#include - -#include - -#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) -#define LO_NIBBLE(b) ((b)&0x0F) - -// Windows.h forward declarations -struct _SYSTEM_INFO; -typedef _SYSTEM_INFO SYSTEM_INFO; -struct _MODULEINFO; -typedef _MODULEINFO MODULEINFO; - -namespace RC -{ - // Windows structs, to prevent the need to include Windows.h in this header - struct WIN_MODULEINFO - { - void* lpBaseOfDll; - unsigned long SizeOfImage; - void* EntryPoint; - - RC_SPSS_API auto operator=(MODULEINFO) -> WIN_MODULEINFO&; - }; - - enum class ScanTarget - { - MainExe, - - AIModule, - Analytics, - AnalyticsET, - AnimationCore, - AnimGraphRuntime, - AppFramework, - ApplicationCore, - AssetRegistry, - AudioCaptureCore, - AudioCaptureRtAudio, - AudioExtensions, - AudioMixer, - AudioMixerCore, - AudioMixerXAudio2, - AudioPlatformConfiguration, - AugmentedReality, - AVEncoder, - AVIWriter, - BuildPatchServices, - BuildSettings, - Cbor, - CEF3Utils, - Chaos, - ChaosCore, - ChaosSolverEngine, - ChaosSolvers, - CinematicCamera, - ClothingSystemRuntimeCommon, - ClothingSystemRuntimeInterface, - ClothingSystemRuntimeNv, - Core, - CoreUObject, - CrunchCompression, - D3D11RHI, - D3D12RHI, - Engine, - EngineMessages, - EngineSettings, - EyeTracker, - FieldSystemCore, - FieldSystemEngine, - FieldSystemSimulationCore, - Foliage, - GameplayMediaEncoder, - GameplayTags, - GameplayTasks, - GeometryCollectionCore, - GeometryCollectionEngine, - GeometryCollectionSimulationCore, - HeadMountedDisplay, - HTTP, - HttpNetworkReplayStreaming, - HTTPServer, - Icmp, - ImageCore, - ImageWrapper, - ImageWriteQueue, - InputCore, - InputDevice, - InstallBundleManager, - InstancedSplines, - InteractiveToolsFramework, - Json, - JsonUtilities, - Landscape, - LauncherCheck, - LauncherPlatform, - LevelSequence, - LocalFileNetworkReplayStreaming, - MaterialShaderQualitySettings, - Media, - MediaAssets, - MediaUtils, - MeshDescription, - MeshUtilitiesCommon, - Messaging, - MessagingCommon, - MoviePlayer, - MovieScene, - MovieSceneCapture, - MovieSceneTracks, - MRMesh, - NavigationSystem, - Navmesh, - NetCore, - Networking, - NetworkReplayStreaming, - NonRealtimeAudioRenderer, - NullDrv, - NullNetworkReplayStreaming, - OpenGLDrv, - Overlay, - PacketHandler, - PakFile, - PerfCounters, - PhysicsCore, - PhysicsSQ, - PhysXCooking, - PreLoadScreen, - Projects, - PropertyPath, - RawMesh, - ReliabilityHandlerComponent, - RenderCore, - Renderer, - RHI, - RSA, - SandboxFile, - Serialization, - SessionMessages, - SessionServices, - SignalProcessing, - Slate, - SlateCore, - SlateNullRenderer, - SlateRHIRenderer, - Sockets, - SoundFieldRendering, - SSL, - StaticMeshDescription, - StreamingPauseRendering, - SynthBenchmark, - TimeManagement, - TraceLog, - UELibSampleRate, - UMG, - VectorVM, - Voice, - Voronoi, - VulkanRHI, - WebBrowser, - WindowsPlatformFeatures, - XAudio2, - - Max, - }; - - auto RC_SPSS_API ScanTargetToString(ScanTarget scan_target) -> std::string; - auto RC_SPSS_API ScanTargetToString(size_t scan_target) -> std::string; - - class RC_SPSS_API ScanTargetArray - { - public: - std::array(ScanTarget::Max)> array{}; - - auto operator[](ScanTarget index) -> MODULEINFO&; - }; - - // Static storage to be used across all sig scanner types - // At the moment the only scanner type that exists is SinglePassScanner - // In the future there might be a multi-threaded version of SinglePassScanner - class RC_SPSS_API SigScannerStaticData - { - public: - // Store all of the MODULEINFO structs for all of the scan targets - // Can a vector of something non-windows be stored here and then a static MODULEINFO can be created in the cpp file ? - static ScanTargetArray m_modules_info; - static bool m_is_modular; - }; - - struct RC_SPSS_API SignatureContainerLight - { - // The scanner will set this to whichever signature a match was found for - size_t index_into_signatures{}; - - // The scanner will set this to the address of the current match (if a match was found) - // This is guaranteed to be non-null when 'callable' is called - uint8_t* match_address{}; - }; - - struct RC_SPSS_API SignatureData - { - std::string signature{}; - - // TODO: Add 'ScanTarget' in here and remove 'ScanTarget' from the 'start_scan' function - - // The user-code can cast the custom data to their own enum type before using - // It will be zero-defaulted in the event of no custom data being supplied - int32_t custom_data{}; - - // A mask that's used for the StdFind scanning method. - std::string mask{}; - }; - - class SignatureContainer - { - private: - // Member variables in this class shouldn't be mutable outside of the scanner internals - // They cannot simply be private because this class isn't part of the scanner - // They cannot be const because they need to be mutated by the scanner - // The solution is to make everything private and give the scanner access by using the 'friend' keyword - friend class SinglePassScanner; - - private: - std::vector signatures; - const std::function on_match_found; - const std::function on_scan_finished; - - // Whether to store the results and pass them to on_scan_completed - const bool store_results{}; - - // The scanner will store results in here if 'store_results' is true - std::vector result_store{}; - - // True if the scan was successful, otherwise false - bool did_succeed{false}; - - // The scanner will use this to cancel all future calls to 'callable' if the 'callable' signaled - bool ignore{}; - - // The scanner will set this to whichever signature a match was found for - size_t index_into_signatures{}; - - // The scanner will set this to the address of the current match (if a match was found) - // This is guaranteed to be non-null when 'callable' is called - uint8_t* match_address{}; - - // The scanner will set this to the size of the signature that was matched - size_t match_signature_size{}; - - public: - template - SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param) - : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param) - { - } - - template - SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param, bool store_results_param) - : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param), store_results(store_results_param) - { - } - - public: - [[nodiscard]] auto get_match_address() const -> uint8_t* - { - return match_address; - } - [[nodiscard]] auto get_index_into_signatures() const -> size_t - { - return index_into_signatures; - } - [[nodiscard]] auto get_did_succeed() -> bool& - { - return did_succeed; - } - [[nodiscard]] auto get_did_succeed() const -> bool - { - return did_succeed; - } - [[nodiscard]] auto get_signatures() const -> const std::vector& - { - return signatures; - } - [[nodiscard]] auto get_result_store() const -> const std::vector& - { - return result_store; - } - [[nodiscard]] auto get_match_signature_size() const -> size_t - { - return match_signature_size; - } - }; - - class SinglePassScanner - { - private: - static std::mutex m_scanner_mutex; - - public: - enum class ScanMethod - { - Scalar, - StdFind, - }; - - public: - RC_SPSS_API static uint32_t m_num_threads; - RC_SPSS_API static ScanMethod m_scan_method; - - // The minimum size a module has to be for multi-threading to be enabled - // Smaller modules might increase the cost of scanning due to the cost of creating threads - RC_SPSS_API static uint32_t m_multithreading_module_size_threshold; - - private: - RC_SPSS_API auto static string_to_vector(std::string_view signature) -> std::vector; - RC_SPSS_API auto static string_to_vector(const std::vector& signatures) -> std::vector>; - RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; - - public: - RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, - uint8_t* end_address, - SYSTEM_INFO& info, - std::vector& signature_containers) -> void; - RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, - uint8_t* end_address, - SYSTEM_INFO& info, - std::vector& signature_containers) -> void; - RC_SPSS_API auto static scanner_work_thread_stdfind(uint8_t* start_address, - uint8_t* end_address, - SYSTEM_INFO& info, - std::vector& signature_containers) -> void; - - using SignatureContainerMap = std::unordered_map>; - RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; - - RC_SPSS_API auto static string_scan(std::wstring_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; - }; -} // namespace RC +#ifdef WIN32 +#include "SinglePassSigScannerWin32.hpp" +#else +#include "SinglePassSigScannerLinux.hpp" +#endif \ No newline at end of file diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp new file mode 100644 index 000000000..c50f68f09 --- /dev/null +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp @@ -0,0 +1,336 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include + +#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) +#define LO_NIBBLE(b) ((b)&0x0F) + +namespace RC +{ + enum class ScanTarget + { + MainExe, + + AIModule, + Analytics, + AnalyticsET, + AnimationCore, + AnimGraphRuntime, + AppFramework, + ApplicationCore, + AssetRegistry, + AudioCaptureCore, + AudioCaptureRtAudio, + AudioExtensions, + AudioMixer, + AudioMixerCore, + AudioMixerXAudio2, + AudioPlatformConfiguration, + AugmentedReality, + AVEncoder, + AVIWriter, + BuildPatchServices, + BuildSettings, + Cbor, + CEF3Utils, + Chaos, + ChaosCore, + ChaosSolverEngine, + ChaosSolvers, + CinematicCamera, + ClothingSystemRuntimeCommon, + ClothingSystemRuntimeInterface, + ClothingSystemRuntimeNv, + Core, + CoreUObject, + CrunchCompression, + D3D11RHI, + D3D12RHI, + Engine, + EngineMessages, + EngineSettings, + EyeTracker, + FieldSystemCore, + FieldSystemEngine, + FieldSystemSimulationCore, + Foliage, + GameplayMediaEncoder, + GameplayTags, + GameplayTasks, + GeometryCollectionCore, + GeometryCollectionEngine, + GeometryCollectionSimulationCore, + HeadMountedDisplay, + HTTP, + HttpNetworkReplayStreaming, + HTTPServer, + Icmp, + ImageCore, + ImageWrapper, + ImageWriteQueue, + InputCore, + InputDevice, + InstallBundleManager, + InstancedSplines, + InteractiveToolsFramework, + Json, + JsonUtilities, + Landscape, + LauncherCheck, + LauncherPlatform, + LevelSequence, + LocalFileNetworkReplayStreaming, + MaterialShaderQualitySettings, + Media, + MediaAssets, + MediaUtils, + MeshDescription, + MeshUtilitiesCommon, + Messaging, + MessagingCommon, + MoviePlayer, + MovieScene, + MovieSceneCapture, + MovieSceneTracks, + MRMesh, + NavigationSystem, + Navmesh, + NetCore, + Networking, + NetworkReplayStreaming, + NonRealtimeAudioRenderer, + NullDrv, + NullNetworkReplayStreaming, + OpenGLDrv, + Overlay, + PacketHandler, + PakFile, + PerfCounters, + PhysicsCore, + PhysicsSQ, + PhysXCooking, + PreLoadScreen, + Projects, + PropertyPath, + RawMesh, + ReliabilityHandlerComponent, + RenderCore, + Renderer, + RHI, + RSA, + SandboxFile, + Serialization, + SessionMessages, + SessionServices, + SignalProcessing, + Slate, + SlateCore, + SlateNullRenderer, + SlateRHIRenderer, + Sockets, + SoundFieldRendering, + SSL, + StaticMeshDescription, + StreamingPauseRendering, + SynthBenchmark, + TimeManagement, + TraceLog, + UELibSampleRate, + UMG, + VectorVM, + Voice, + Voronoi, + VulkanRHI, + WebBrowser, + WindowsPlatformFeatures, + XAudio2, + + Max, + }; + + auto RC_SPSS_API ScanTargetToString(ScanTarget scan_target) -> std::string; + auto RC_SPSS_API ScanTargetToString(size_t scan_target) -> std::string; + +#ifdef WIN32 + class RC_SPSS_API ScanTargetArray + { + public: + std::array(ScanTarget::Max)> array{}; + + auto operator[](ScanTarget index) -> MODULEINFO&; + }; +#else + class RC_SPSS_API ScanTargetArray + { + public: + std::array(ScanTarget::Max)> array{}; + + auto operator[](ScanTarget index) -> DLData&; + }; +#endif + // Static storage to be used across all sig scanner types + // At the moment the only scanner type that exists is SinglePassScanner + // In the future there might be a multi-threaded version of SinglePassScanner + class RC_SPSS_API SigScannerStaticData + { + public: + // Store all of the MODULEINFO structs for all of the scan targets + // Can a vector of something non-windows be stored here and then a static MODULEINFO can be created in the cpp file ? + static ScanTargetArray m_modules_info; + static bool m_is_modular; + }; + + struct RC_SPSS_API SignatureContainerLight + { + // The scanner will set this to whichever signature a match was found for + size_t index_into_signatures{}; + + // The scanner will set this to the address of the current match (if a match was found) + // This is guaranteed to be non-null when 'callable' is called + uint8_t* match_address{}; + }; + + struct RC_SPSS_API SignatureData + { + std::string signature{}; + + // TODO: Add 'ScanTarget' in here and remove 'ScanTarget' from the 'start_scan' function + + // The user-code can cast the custom data to their own enum type before using + // It will be zero-defaulted in the event of no custom data being supplied + int32_t custom_data{}; + + // A mask that's used for the StdFind scanning method. + std::string mask{}; + }; + + class SignatureContainer + { + private: + // Member variables in this class shouldn't be mutable outside of the scanner internals + // They cannot simply be private because this class isn't part of the scanner + // They cannot be const because they need to be mutated by the scanner + // The solution is to make everything private and give the scanner access by using the 'friend' keyword + friend class SinglePassScanner; + + private: + std::vector signatures; + const std::function on_match_found; + const std::function on_scan_finished; + + // Whether to store the results and pass them to on_scan_completed + const bool store_results{}; + + // The scanner will store results in here if 'store_results' is true + std::vector result_store{}; + + // True if the scan was successful, otherwise false + bool did_succeed{false}; + + // The scanner will use this to cancel all future calls to 'callable' if the 'callable' signaled + bool ignore{}; + + // The scanner will set this to whichever signature a match was found for + size_t index_into_signatures{}; + + // The scanner will set this to the address of the current match (if a match was found) + // This is guaranteed to be non-null when 'callable' is called + uint8_t* match_address{}; + + // The scanner will set this to the size of the signature that was matched + size_t match_signature_size{}; + + public: + template + SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param) + : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param) + { + } + + template + SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param, bool store_results_param) + : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param), store_results(store_results_param) + { + } + + public: + [[nodiscard]] auto get_match_address() const -> uint8_t* + { + return match_address; + } + [[nodiscard]] auto get_index_into_signatures() const -> size_t + { + return index_into_signatures; + } + [[nodiscard]] auto get_did_succeed() -> bool& + { + return did_succeed; + } + [[nodiscard]] auto get_did_succeed() const -> bool + { + return did_succeed; + } + [[nodiscard]] auto get_signatures() const -> const std::vector& + { + return signatures; + } + [[nodiscard]] auto get_result_store() const -> const std::vector& + { + return result_store; + } + [[nodiscard]] auto get_match_signature_size() const -> size_t + { + return match_signature_size; + } + }; + + class SinglePassScanner + { + private: + static std::mutex m_scanner_mutex; + + public: + enum class ScanMethod + { + Scalar, + StdFind, + }; + + public: + RC_SPSS_API static uint32_t m_num_threads; + RC_SPSS_API static ScanMethod m_scan_method; + + // The minimum size a module has to be for multi-threading to be enabled + // Smaller modules might increase the cost of scanning due to the cost of creating threads + RC_SPSS_API static uint32_t m_multithreading_module_size_threshold; + + private: + RC_SPSS_API auto static string_to_vector(std::string_view signature) -> std::vector; + RC_SPSS_API auto static string_to_vector(const std::vector& signatures) -> std::vector>; + RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; + + public: + RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, + uint8_t* end_address, + DLData& info, + std::vector& signature_containers) -> void; + RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, + uint8_t* end_address, + DLData& info, + std::vector& signature_containers) -> void; + RC_SPSS_API auto static scanner_work_thread_stdfind(uint8_t* start_address, + uint8_t* end_address, + DLData& info, + std::vector& signature_containers) -> void; + + using SignatureContainerMap = std::unordered_map>; + RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; + }; +} // namespace RC diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp new file mode 100644 index 000000000..a8afd086f --- /dev/null +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp @@ -0,0 +1,352 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) +#define LO_NIBBLE(b) ((b)&0x0F) + +// Windows.h forward declarations +struct _SYSTEM_INFO; +typedef _SYSTEM_INFO SYSTEM_INFO; +struct _MODULEINFO; +typedef _MODULEINFO MODULEINFO; + +namespace RC +{ + // Windows structs, to prevent the need to include Windows.h in this header + struct WIN_MODULEINFO + { + void* lpBaseOfDll; + unsigned long SizeOfImage; + void* EntryPoint; + RC_SPSS_API auto operator=(MODULEINFO) -> WIN_MODULEINFO&; + }; + + enum class ScanTarget + { + MainExe, + + AIModule, + Analytics, + AnalyticsET, + AnimationCore, + AnimGraphRuntime, + AppFramework, + ApplicationCore, + AssetRegistry, + AudioCaptureCore, + AudioCaptureRtAudio, + AudioExtensions, + AudioMixer, + AudioMixerCore, + AudioMixerXAudio2, + AudioPlatformConfiguration, + AugmentedReality, + AVEncoder, + AVIWriter, + BuildPatchServices, + BuildSettings, + Cbor, + CEF3Utils, + Chaos, + ChaosCore, + ChaosSolverEngine, + ChaosSolvers, + CinematicCamera, + ClothingSystemRuntimeCommon, + ClothingSystemRuntimeInterface, + ClothingSystemRuntimeNv, + Core, + CoreUObject, + CrunchCompression, + D3D11RHI, + D3D12RHI, + Engine, + EngineMessages, + EngineSettings, + EyeTracker, + FieldSystemCore, + FieldSystemEngine, + FieldSystemSimulationCore, + Foliage, + GameplayMediaEncoder, + GameplayTags, + GameplayTasks, + GeometryCollectionCore, + GeometryCollectionEngine, + GeometryCollectionSimulationCore, + HeadMountedDisplay, + HTTP, + HttpNetworkReplayStreaming, + HTTPServer, + Icmp, + ImageCore, + ImageWrapper, + ImageWriteQueue, + InputCore, + InputDevice, + InstallBundleManager, + InstancedSplines, + InteractiveToolsFramework, + Json, + JsonUtilities, + Landscape, + LauncherCheck, + LauncherPlatform, + LevelSequence, + LocalFileNetworkReplayStreaming, + MaterialShaderQualitySettings, + Media, + MediaAssets, + MediaUtils, + MeshDescription, + MeshUtilitiesCommon, + Messaging, + MessagingCommon, + MoviePlayer, + MovieScene, + MovieSceneCapture, + MovieSceneTracks, + MRMesh, + NavigationSystem, + Navmesh, + NetCore, + Networking, + NetworkReplayStreaming, + NonRealtimeAudioRenderer, + NullDrv, + NullNetworkReplayStreaming, + OpenGLDrv, + Overlay, + PacketHandler, + PakFile, + PerfCounters, + PhysicsCore, + PhysicsSQ, + PhysXCooking, + PreLoadScreen, + Projects, + PropertyPath, + RawMesh, + ReliabilityHandlerComponent, + RenderCore, + Renderer, + RHI, + RSA, + SandboxFile, + Serialization, + SessionMessages, + SessionServices, + SignalProcessing, + Slate, + SlateCore, + SlateNullRenderer, + SlateRHIRenderer, + Sockets, + SoundFieldRendering, + SSL, + StaticMeshDescription, + StreamingPauseRendering, + SynthBenchmark, + TimeManagement, + TraceLog, + UELibSampleRate, + UMG, + VectorVM, + Voice, + Voronoi, + VulkanRHI, + WebBrowser, + WindowsPlatformFeatures, + XAudio2, + + Max, + }; + + auto RC_SPSS_API ScanTargetToString(ScanTarget scan_target) -> std::string; + auto RC_SPSS_API ScanTargetToString(size_t scan_target) -> std::string; + +#ifdef WIN32 + class RC_SPSS_API ScanTargetArray + { + public: + std::array(ScanTarget::Max)> array{}; + + auto operator[](ScanTarget index) -> MODULEINFO&; + }; +#else + class RC_SPSS_API ScanTargetArray + { + public: + std::array(ScanTarget::Max)> array{}; + + auto operator[](ScanTarget index) -> DLData&; + }; +#endif + // Static storage to be used across all sig scanner types + // At the moment the only scanner type that exists is SinglePassScanner + // In the future there might be a multi-threaded version of SinglePassScanner + class RC_SPSS_API SigScannerStaticData + { + public: + // Store all of the MODULEINFO structs for all of the scan targets + // Can a vector of something non-windows be stored here and then a static MODULEINFO can be created in the cpp file ? + static ScanTargetArray m_modules_info; + static bool m_is_modular; + }; + + struct RC_SPSS_API SignatureContainerLight + { + // The scanner will set this to whichever signature a match was found for + size_t index_into_signatures{}; + + // The scanner will set this to the address of the current match (if a match was found) + // This is guaranteed to be non-null when 'callable' is called + uint8_t* match_address{}; + }; + + struct RC_SPSS_API SignatureData + { + std::string signature{}; + + // TODO: Add 'ScanTarget' in here and remove 'ScanTarget' from the 'start_scan' function + + // The user-code can cast the custom data to their own enum type before using + // It will be zero-defaulted in the event of no custom data being supplied + int32_t custom_data{}; + + // A mask that's used for the StdFind scanning method. + std::string mask{}; + }; + + class SignatureContainer + { + private: + // Member variables in this class shouldn't be mutable outside of the scanner internals + // They cannot simply be private because this class isn't part of the scanner + // They cannot be const because they need to be mutated by the scanner + // The solution is to make everything private and give the scanner access by using the 'friend' keyword + friend class SinglePassScanner; + + private: + std::vector signatures; + const std::function on_match_found; + const std::function on_scan_finished; + + // Whether to store the results and pass them to on_scan_completed + const bool store_results{}; + + // The scanner will store results in here if 'store_results' is true + std::vector result_store{}; + + // True if the scan was successful, otherwise false + bool did_succeed{false}; + + // The scanner will use this to cancel all future calls to 'callable' if the 'callable' signaled + bool ignore{}; + + // The scanner will set this to whichever signature a match was found for + size_t index_into_signatures{}; + + // The scanner will set this to the address of the current match (if a match was found) + // This is guaranteed to be non-null when 'callable' is called + uint8_t* match_address{}; + + // The scanner will set this to the size of the signature that was matched + size_t match_signature_size{}; + + public: + template + SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param) + : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param) + { + } + + template + SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param, bool store_results_param) + : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param), store_results(store_results_param) + { + } + + public: + [[nodiscard]] auto get_match_address() const -> uint8_t* + { + return match_address; + } + [[nodiscard]] auto get_index_into_signatures() const -> size_t + { + return index_into_signatures; + } + [[nodiscard]] auto get_did_succeed() -> bool& + { + return did_succeed; + } + [[nodiscard]] auto get_did_succeed() const -> bool + { + return did_succeed; + } + [[nodiscard]] auto get_signatures() const -> const std::vector& + { + return signatures; + } + [[nodiscard]] auto get_result_store() const -> const std::vector& + { + return result_store; + } + [[nodiscard]] auto get_match_signature_size() const -> size_t + { + return match_signature_size; + } + }; + + class SinglePassScanner + { + private: + static std::mutex m_scanner_mutex; + + public: + enum class ScanMethod + { + Scalar, + StdFind, + }; + + public: + RC_SPSS_API static uint32_t m_num_threads; + RC_SPSS_API static ScanMethod m_scan_method; + + // The minimum size a module has to be for multi-threading to be enabled + // Smaller modules might increase the cost of scanning due to the cost of creating threads + RC_SPSS_API static uint32_t m_multithreading_module_size_threshold; + + private: + RC_SPSS_API auto static string_to_vector(std::string_view signature) -> std::vector; + RC_SPSS_API auto static string_to_vector(const std::vector& signatures) -> std::vector>; + RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; + + public: + RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, + uint8_t* end_address, + SYSTEM_INFO& info, + std::vector& signature_containers) -> void; + RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, + uint8_t* end_address, + SYSTEM_INFO& info, + std::vector& signature_containers) -> void; + RC_SPSS_API auto static scanner_work_thread_stdfind(uint8_t* start_address, + uint8_t* end_address, + SYSTEM_INFO& info, + std::vector& signature_containers) -> void; + + using SignatureContainerMap = std::unordered_map>; + RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; +#ifdef WIN32 + RC_SPSS_API auto static string_scan(std::wstring_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; +#endif + }; +} // namespace RC diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp new file mode 100644 index 000000000..f9839a185 --- /dev/null +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp @@ -0,0 +1,820 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#define byte uint8_t + +namespace RC +{ + ScanTargetArray SigScannerStaticData::m_modules_info; + bool SigScannerStaticData::m_is_modular; + + uint32_t SinglePassScanner::m_num_threads = 8; + SinglePassScanner::ScanMethod SinglePassScanner::m_scan_method = ScanMethod::Scalar; + uint32_t SinglePassScanner::m_multithreading_module_size_threshold = 0x1000000; + std::mutex SinglePassScanner::m_scanner_mutex{}; + + auto ScanTargetArray::operator[](ScanTarget index) -> DLData& + { + return array[static_cast(index)]; + } + + + auto ScanTargetToString(ScanTarget scan_target) -> std::string + { + switch (scan_target) + { + case ScanTarget::MainExe: + return {"MainExe"}; + case ScanTarget::AIModule: + return {"AIModule"}; + case ScanTarget::Analytics: + return {"Analytics"}; + case ScanTarget::AnalyticsET: + return {"AnalyticsET"}; + case ScanTarget::AnimationCore: + return {"AnimationCore"}; + case ScanTarget::AnimGraphRuntime: + return {"AnimGraphRuntime"}; + case ScanTarget::AppFramework: + return {"AppFramework"}; + case ScanTarget::ApplicationCore: + return {"ApplicationCore"}; + case ScanTarget::AssetRegistry: + return {"AssetRegistry"}; + case ScanTarget::AudioCaptureCore: + return {"AudioCaptureCore"}; + case ScanTarget::AudioCaptureRtAudio: + return {"AudioCaptureRtAudio"}; + case ScanTarget::AudioExtensions: + return {"AudioExtensions"}; + case ScanTarget::AudioMixer: + return {"AudioMixer"}; + case ScanTarget::AudioMixerCore: + return {"AudioMixerCore"}; + case ScanTarget::AudioMixerXAudio2: + return {"AudioMixerXAudio2"}; + case ScanTarget::AudioPlatformConfiguration: + return {"AudioPlatformConfiguration"}; + case ScanTarget::AugmentedReality: + return {"AugmentedReality"}; + case ScanTarget::AVEncoder: + return {"AVEncoder"}; + case ScanTarget::AVIWriter: + return {"AVIWriter"}; + case ScanTarget::BuildPatchServices: + return {"BuildPatchServices"}; + case ScanTarget::BuildSettings: + return {"BuildSettings"}; + case ScanTarget::Cbor: + return {"Cbor"}; + case ScanTarget::CEF3Utils: + return {"CEF3Utils"}; + case ScanTarget::Chaos: + return {"Chaos"}; + case ScanTarget::ChaosCore: + return {"ChaosCore"}; + case ScanTarget::ChaosSolverEngine: + return {"ChaosSolverEngine"}; + case ScanTarget::ChaosSolvers: + return {"ChaosSolvers"}; + case ScanTarget::CinematicCamera: + return {"CinematicCamera"}; + case ScanTarget::ClothingSystemRuntimeCommon: + return {"ClothingSystemRuntimeCommon"}; + case ScanTarget::ClothingSystemRuntimeInterface: + return {"ClothingSystemRuntimeInterface"}; + case ScanTarget::ClothingSystemRuntimeNv: + return {"ClothingSystemRuntimeNv"}; + case ScanTarget::Core: + return {"Core"}; + case ScanTarget::CoreUObject: + return {"CoreUObject"}; + case ScanTarget::CrunchCompression: + return {"CrunchCompression"}; + case ScanTarget::D3D11RHI: + return {"D3D11RHI"}; + case ScanTarget::D3D12RHI: + return {"D3D12RHI"}; + case ScanTarget::Engine: + return {"Engine"}; + case ScanTarget::EngineMessages: + return {"EngineMessages"}; + case ScanTarget::EngineSettings: + return {"EngineSettings"}; + case ScanTarget::EyeTracker: + return {"EyeTracker"}; + case ScanTarget::FieldSystemCore: + return {"FieldSystemCore"}; + case ScanTarget::FieldSystemEngine: + return {"FieldSystemEngine"}; + case ScanTarget::FieldSystemSimulationCore: + return {"FieldSystemSimulationCore"}; + case ScanTarget::Foliage: + return {"Foliage"}; + case ScanTarget::GameplayMediaEncoder: + return {"GameplayMediaEncoder"}; + case ScanTarget::GameplayTags: + return {"GameplayTags"}; + case ScanTarget::GameplayTasks: + return {"GameplayTasks"}; + case ScanTarget::GeometryCollectionCore: + return {"GeometryCollectionCore"}; + case ScanTarget::GeometryCollectionEngine: + return {"GeometryCollectionEngine"}; + case ScanTarget::GeometryCollectionSimulationCore: + return {"GeometryCollectionSimulationCore"}; + case ScanTarget::HeadMountedDisplay: + return {"HeadMountedDisplay"}; + case ScanTarget::HTTP: + return {"HTTP"}; + case ScanTarget::HttpNetworkReplayStreaming: + return {"HttpNetworkReplayStreaming"}; + case ScanTarget::HTTPServer: + return {"HTTPServer"}; + case ScanTarget::Icmp: + return {"Icmp"}; + case ScanTarget::ImageCore: + return {"ImageCore"}; + case ScanTarget::ImageWrapper: + return {"ImageWrapper"}; + case ScanTarget::ImageWriteQueue: + return {"ImageWriteQueue"}; + case ScanTarget::InputCore: + return {"InputCore"}; + case ScanTarget::InputDevice: + return {"InputDevice"}; + case ScanTarget::InstallBundleManager: + return {"InstallBundleManager"}; + case ScanTarget::InstancedSplines: + return {"InstancedSplines"}; + case ScanTarget::InteractiveToolsFramework: + return {"InteractiveToolsFramework"}; + case ScanTarget::Json: + return {"Json"}; + case ScanTarget::JsonUtilities: + return {"JsonUtilities"}; + case ScanTarget::Landscape: + return {"Landscape"}; + case ScanTarget::LauncherCheck: + return {"LauncherCheck"}; + case ScanTarget::LauncherPlatform: + return {"LauncherPlatform"}; + case ScanTarget::LevelSequence: + return {"LevelSequence"}; + case ScanTarget::LocalFileNetworkReplayStreaming: + return {"LocalFileNetworkReplayStreaming"}; + case ScanTarget::MaterialShaderQualitySettings: + return {"MaterialShaderQualitySettings"}; + case ScanTarget::Media: + return {"Media"}; + case ScanTarget::MediaAssets: + return {"MediaAssets"}; + case ScanTarget::MediaUtils: + return {"MediaUtils"}; + case ScanTarget::MeshDescription: + return {"MeshDescription"}; + case ScanTarget::MeshUtilitiesCommon: + return {"MeshUtilitiesCommon"}; + case ScanTarget::Messaging: + return {"Messaging"}; + case ScanTarget::MessagingCommon: + return {"MessagingCommon"}; + case ScanTarget::MoviePlayer: + return {"MoviePlayer"}; + case ScanTarget::MovieScene: + return {"MovieScene"}; + case ScanTarget::MovieSceneCapture: + return {"MovieSceneCapture"}; + case ScanTarget::MovieSceneTracks: + return {"MovieSceneTracks"}; + case ScanTarget::MRMesh: + return {"MRMesh"}; + case ScanTarget::NavigationSystem: + return {"NavigationSystem"}; + case ScanTarget::Navmesh: + return {"Navmesh"}; + case ScanTarget::NetCore: + return {"NetCore"}; + case ScanTarget::Networking: + return {"Networking"}; + case ScanTarget::NetworkReplayStreaming: + return {"NetworkReplayStreaming"}; + case ScanTarget::NonRealtimeAudioRenderer: + return {"NonRealtimeAudioRenderer"}; + case ScanTarget::NullDrv: + return {"NullDrv"}; + case ScanTarget::NullNetworkReplayStreaming: + return {"NullNetworkReplayStreaming"}; + case ScanTarget::OpenGLDrv: + return {"OpenGLDrv"}; + case ScanTarget::Overlay: + return {"Overlay"}; + case ScanTarget::PacketHandler: + return {"PacketHandler"}; + case ScanTarget::PakFile: + return {"PakFile"}; + case ScanTarget::PerfCounters: + return {"PerfCounters"}; + case ScanTarget::PhysicsCore: + return {"PhysicsCore"}; + case ScanTarget::PhysicsSQ: + return {"PhysicsSQ"}; + case ScanTarget::PhysXCooking: + return {"PhysXCooking"}; + case ScanTarget::PreLoadScreen: + return {"PreLoadScreen"}; + case ScanTarget::Projects: + return {"Projects"}; + case ScanTarget::PropertyPath: + return {"PropertyPath"}; + case ScanTarget::RawMesh: + return {"RawMesh"}; + case ScanTarget::ReliabilityHandlerComponent: + return {"ReliabilityHandlerComponent"}; + case ScanTarget::RenderCore: + return {"RenderCore"}; + case ScanTarget::Renderer: + return {"Renderer"}; + case ScanTarget::RHI: + return {"RHI"}; + case ScanTarget::RSA: + return {"RSA"}; + case ScanTarget::SandboxFile: + return {"SandboxFile"}; + case ScanTarget::Serialization: + return {"Serialization"}; + case ScanTarget::SessionMessages: + return {"SessionMessages"}; + case ScanTarget::SessionServices: + return {"SessionServices"}; + case ScanTarget::SignalProcessing: + return {"SignalProcessing"}; + case ScanTarget::Slate: + return {"Slate"}; + case ScanTarget::SlateCore: + return {"SlateCore"}; + case ScanTarget::SlateNullRenderer: + return {"SlateNullRenderer"}; + case ScanTarget::SlateRHIRenderer: + return {"SlateRHIRenderer"}; + case ScanTarget::Sockets: + return {"Sockets"}; + case ScanTarget::SoundFieldRendering: + return {"SoundFieldRendering"}; + case ScanTarget::SSL: + return {"SSL"}; + case ScanTarget::StaticMeshDescription: + return {"StaticMeshDescription"}; + case ScanTarget::StreamingPauseRendering: + return {"StreamingPauseRendering"}; + case ScanTarget::SynthBenchmark: + return {"SynthBenchmark"}; + case ScanTarget::TimeManagement: + return {"TimeManagement"}; + case ScanTarget::TraceLog: + return {"TraceLog"}; + case ScanTarget::UELibSampleRate: + return {"UELibSampleRate"}; + case ScanTarget::UMG: + return {"UMG"}; + case ScanTarget::VectorVM: + return {"VectorVM"}; + case ScanTarget::Voice: + return {"Voice"}; + case ScanTarget::Voronoi: + return {"Voronoi"}; + case ScanTarget::VulkanRHI: + return {"VulkanRHI"}; + case ScanTarget::WebBrowser: + return {"WebBrowser"}; + case ScanTarget::WindowsPlatformFeatures: + return {"WindowsPlatformFeatures"}; + case ScanTarget::XAudio2: + return {"XAudio2"}; + case ScanTarget::Max: + return {"Max"}; + } + + throw std::runtime_error{std::format("Invalid param for ScanTargetToString, param: {}", static_cast(scan_target))}; + } + + auto ScanTargetToString(size_t scan_target) -> std::string + { + return ScanTargetToString(static_cast(scan_target)); + } + + static auto ConvertHexCharToInt(char ch) -> int + { + if (ch >= '0' && ch <= '9') return ch - '0'; + if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; + if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; + return -1; + } + + auto SinglePassScanner::string_to_vector(std::string_view signature) -> std::vector + { + std::vector bytes; + char* const start = const_cast(signature.data()); + char* const end = const_cast(signature.data()) + strlen(signature.data()); + + for (char* current = start; current < end; current++) + { + if (*current == '?') + { + bytes.push_back(-1); + } + else if (std::isxdigit(*current)) + { + bytes.push_back(ConvertHexCharToInt(*current)); + } + } + + return bytes; + } + + auto SinglePassScanner::string_to_vector(const std::vector& signatures) -> std::vector> + { + std::vector> vector_of_signatures; + vector_of_signatures.reserve(signatures.size()); + + for (const auto& signature_data : signatures) + { + vector_of_signatures.emplace_back(string_to_vector(signature_data.signature)); + } + + return vector_of_signatures; + } + + struct PatternData + { + std::vector pattern{}; + std::vector mask{}; + SignatureContainer* signature_container{}; + }; + + static auto CharToByte(char symbol) -> uint8_t + { + if (symbol >= 'a' && symbol <= 'z') + { + return symbol - 'a' + 0xA; + } + else if (symbol >= 'A' && symbol <= 'Z') + { + return symbol - 'A' + 0xA; + } + else if (symbol >= '0' && symbol <= '9') + { + return symbol - '0'; + } + else + { + return 0; + } + } + + static auto make_mask(std::string_view pattern, SignatureContainer& signature_container, const size_t data_size) -> PatternData + { + PatternData pattern_data{}; + + if (pattern.length() < 1 || pattern[0] == '?') + { + throw std::runtime_error{std::format("[make_mask] A pattern cannot start with a wildcard.\nPattern: {}", pattern)}; + } + + for (size_t i = 0; i < pattern.length(); i++) + { + char symbol = pattern[i]; + char next_symbol = ((i + 1) < pattern.length()) ? pattern[i + 1] : 0; + if (symbol == ' ') + { + continue; + } + + if (symbol == '?') + { + pattern_data.pattern.push_back(0x00); + pattern_data.mask.push_back(0x00); + + if (next_symbol == '?') + { + ++i; + } + continue; + } + + uint8_t byte = CharToByte(symbol) << 4 | CharToByte(next_symbol); + + pattern_data.pattern.push_back(byte); + pattern_data.mask.push_back(0xff); + + ++i; + } + + static constexpr size_t Alignment = 32; + size_t count = (size_t)std::ceil((float)data_size / Alignment); + size_t padding_size = count * Alignment - data_size; + + for (size_t i = 0; i < padding_size; i++) + { + pattern_data.pattern.push_back(0x00); + pattern_data.mask.push_back(0x00); + } + + pattern_data.signature_container = &signature_container; + return pattern_data; + } + + auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, DLData& info, std::vector& signature_containers) + -> void + { + ProfilerSetThreadName("UE4SS-ScannerWorkThread"); + ProfilerScope(); + + switch (m_scan_method) + { + case ScanMethod::Scalar: + scanner_work_thread_scalar(start_address, end_address, info, signature_containers); + break; + case ScanMethod::StdFind: + scanner_work_thread_stdfind(start_address, end_address, info, signature_containers); + break; + } + } + + auto SinglePassScanner::scanner_work_thread_scalar(uint8_t* start_address, + uint8_t* end_address, + DLData& info, + std::vector& signature_containers) -> void + { + ProfilerScope(); + if (!start_address) + { + start_address = static_cast(info.base_address); + } + if (!end_address) + { + end_address = static_cast(info.base_address + info.size); + } + + // TODO: Nasty nasty nasty. Come up with a better solution... wtf + // It should ideally be able to work with the char* directly instead of converting to to vectors of ints + // The reason why working directly with the char* is a problem is that it's expensive to convert a hex char to an int + // Also look at the comments below + std::vector>> vector_of_sigs; + + // const std::regex signature_validity_regex(R"(^([0-9A-F\?] )([0-9A-F\?]\/[0-9A-F\?] )*([0-9A-F\?])$)"); + + // Making a vector here to be identical to the SignatureContainer vector + // The difference is that it stores the sigs converted from char* to std::vector + // This makes it easier to work with even if it's wasteful + // This should not be done in the nested loops below because this operation is very slow + vector_of_sigs.reserve(signature_containers.size()); + for (const auto& container : signature_containers) + { + // Only continue if the signature is properly formatted + // Bring this code back when both: + // A. The regex has been updated to take into consideration. + // B. The threads have been synced before the scan to verify that all threads are scanning for valid signatures. + // for (const auto& signature_data : container.signatures) + //{ + // if (!std::regex_search(signature_data.signature, signature_validity_regex)) + // { + // throw std::runtime_error{std::format("[SinglePassSigScanner::start_scan] A signature is improperly formatted. Signature: {}", signature_data.signature)}; + // } + //} + + // Signatures for this container + vector_of_sigs.emplace_back(string_to_vector(container.signatures)); + } + + // Loop everything + for (uint8_t* i = start_address; i < end_address; ++i) + { + auto addr = info.find_phdr(i); + if (addr == std::make_tuple(nullptr, 0, 0)) + { + continue; + } + if (std::get<0>(addr) > i) { + i = std::get<0>(addr); + } + uint8_t* region_end = static_cast(std::get<0>(addr)) + std::get<1>(addr); + if ((std::get<2>(addr) & PF_R) == 0) { + i = region_end; + continue; + } + + uint8_t* scan_end = std::min(end_address, region_end); + for (uint8_t* region_start = std::get<0>(addr); region_start < scan_end; ++region_start) + { + bool skip_to_next_container{}; + + for (size_t container_index = 0; const auto& int_container : vector_of_sigs) + { + for (size_t signature_index = 0; const auto& sig : int_container) + { + // If the container is refusing more calls then skip to the next container + if (signature_containers[container_index].ignore) + { + break; + } + + // Skip if we're about to dereference uninitialized memory + if (region_start + sig.size() > region_end) + { + break; + } + + for (size_t sig_i = 0; sig_i < sig.size(); sig_i += 2) + { + if (sig.at(sig_i) != -1 && sig.at(sig_i) != HI_NIBBLE(*(byte*)(region_start + (sig_i / 2))) || + sig.at(sig_i + 1) != -1 && sig.at(sig_i + 1) != LO_NIBBLE(*(byte*)(region_start + (sig_i / 2)))) + { + break; + } + + if (sig_i + 2 == sig.size()) + { + { + std::lock_guard safe_scope(m_scanner_mutex); + + // Checking for the second time if the container is refusing more calls + // This is required when multi-threading is enabled + if (signature_containers[container_index].ignore) + { + skip_to_next_container = true; + break; + } + + // One of the signatures have found a full match so lets forward the details to the callable + signature_containers[container_index].index_into_signatures = signature_index; + signature_containers[container_index].match_address = region_start; + signature_containers[container_index].match_signature_size = sig.size() / 2; + + skip_to_next_container = signature_containers[container_index].on_match_found(signature_containers[container_index]); + signature_containers[container_index].ignore = skip_to_next_container; + + // Store results if the container at the containers request + if (signature_containers[container_index].store_results) + { + signature_containers[container_index].result_store.emplace_back( + SignatureContainerLight{.index_into_signatures = signature_index, .match_address = region_start}); + } + } + + break; + } + } + + if (skip_to_next_container) + { + // A match was found and signaled to skip to the next container + break; + } + + ++signature_index; + } + + ++container_index; + } + } + + i = scan_end; + + } + } + + static auto format_aob_string(std::string& str) -> void + { + if (str.size() < 4) + { + return; + } + if (str[3] != '/') + { + return; + } + + std::erase_if(str, [&](const char c) { + return c == ' '; + }); + + std::ranges::transform(str, str.begin(), [&str](const char c) { + return c == '/' ? ' ' : c; + }); + } + + auto SinglePassScanner::format_aob_strings(std::vector& signature_containers) -> void + { + std::lock_guard safe_scope(m_scanner_mutex); + for (auto& signature_container : signature_containers) + { + for (auto& signature : signature_container.signatures) + { + format_aob_string(signature.signature); + } + } + } + + auto SinglePassScanner::scanner_work_thread_stdfind(uint8_t* start_address, + uint8_t* end_address, + DLData& info, + std::vector& signature_containers) -> void + { + ProfilerScope(); + + if (!start_address) + { + start_address = static_cast(info.base_address); + } + if (!end_address) + { + end_address = static_cast(info.base_address + info.size); + } + + format_aob_strings(signature_containers); + + std::vector> pattern_datas{}; + for (auto& signature_container : signature_containers) + { + auto& pattern_data = pattern_datas.emplace_back(); + for (auto& signature : signature_container.signatures) + { + pattern_data.emplace_back(make_mask(signature.signature, signature_container, end_address - start_address)); + } + } + + // Loop everything + for (size_t container_index = 0; const auto& patterns : pattern_datas) + { + for (size_t signature_index = 0; const auto& pattern_data : patterns) + { + // If the container is refusing more calls then skip to the next container + if (pattern_data.signature_container->ignore) + { + break; + } + + auto it = start_address; + auto end = it + (end_address - start_address) - (pattern_data.pattern.size()) + 1; + uint8_t needle = pattern_data.pattern[0]; + + bool skip_to_next_container{}; + while (end != (it = std::find(it, end, needle))) + { + bool found = true; + for (size_t pattern_offset = 0; pattern_offset < pattern_data.pattern.size(); ++pattern_offset) + { + if ((it[pattern_offset] & pattern_data.mask[pattern_offset]) != pattern_data.pattern[pattern_offset]) + { + found = false; + break; + } + } + + if (found) + { + { + std::lock_guard safe_scope(m_scanner_mutex); + + // Checking for the second time if the container is refusing more calls + // This is required when multi-threading is enabled + if (pattern_data.signature_container->ignore) + { + skip_to_next_container = true; + break; + } + + // One of the signatures have found a full match so lets forward the details to the callable + pattern_data.signature_container->index_into_signatures = signature_index; + pattern_data.signature_container->match_address = it; + pattern_data.signature_container->match_signature_size = pattern_data.pattern.size(); + + skip_to_next_container = pattern_data.signature_container->on_match_found(*pattern_data.signature_container); + pattern_data.signature_container->ignore = skip_to_next_container; + + // Store results if the container at the containers request + if (pattern_data.signature_container->store_results) + { + pattern_data.signature_container->result_store.emplace_back( + SignatureContainerLight{.index_into_signatures = signature_index, .match_address = it}); + } + } + } + + it++; + } + + if (skip_to_next_container) + { + // A match was found and signaled to skip to the next container + break; + } + + ++signature_index; + } + ++container_index; + } + } + + auto SinglePassScanner::start_scan(SignatureContainerMap& signature_containers) -> void + { + //DLData info = SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; + + // If not modular then the containers get merged into one scan target + // That way there are no extra scans + // If modular then loop the containers and retrieve the scan target for each and pass everything to the do_scan() lambda + + if (!SigScannerStaticData::m_is_modular) + { + DLData merged_module_info{}; + std::vector merged_containers; + + for (const auto& [scan_target, outer_container] : signature_containers) + { + merged_module_info = *std::bit_cast(&SigScannerStaticData::m_modules_info[scan_target]); + for (const auto& signature_container : outer_container) + { + merged_containers.emplace_back(signature_container); + } + } + + if (merged_containers.empty()) + { + throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " + "an internal error."}; + } + + uint8_t* module_start_address = static_cast(merged_module_info.base_address); + + if (merged_module_info.size >= m_multithreading_module_size_threshold) + { + // Module is large enough to make it overall faster to scan with multiple threads + std::vector> scan_threads; + + // Higher values are better for debugging + // You will get a bigger diminishing returns the faster your computer is (especially in release mode) + uint32_t range = merged_module_info.size / m_num_threads; + + // Calculating the ranges for each thread to scan and starting the scan + uint32_t last_range{}; + for (uint32_t thread_id = 0; thread_id < m_num_threads; ++thread_id) + { + scan_threads.emplace_back(std::async(std::launch::async, + &scanner_work_thread, + module_start_address + last_range, + module_start_address + last_range + range, + std::ref(merged_module_info), + std::ref(merged_containers))); + + last_range += range; + } + + for (const auto& scan_thread : scan_threads) + { + scan_thread.wait(); + } + } + else + { + // Module is too small to make it overall faster to scan with multiple threads + uint8_t* module_end_address = static_cast(module_start_address + merged_module_info.size); + scanner_work_thread(module_start_address, module_end_address, merged_module_info, merged_containers); + } + + for (auto& container : merged_containers) + { + container.on_scan_finished(container); + } + } + else + { + // This ranged for loop is performing a copy of unordered_map> + // Is this required ? Would it be worth trying to avoid copying here ? + // Right now it can't be auto& or const auto& because the do_scan function takes a non-const since it needs to mutate the values inside the vector + auto info = SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; + for (auto& [scan_target, signature_container] : signature_containers) + { + uint8_t* module_start_address = static_cast(SigScannerStaticData::m_modules_info[scan_target].base_address); + uint8_t* module_end_address = static_cast(module_start_address + SigScannerStaticData::m_modules_info[scan_target].size); + + scanner_work_thread(module_start_address, module_end_address, info, signature_container); + + for (auto& container : signature_container) + { + container.on_scan_finished(container); + } + } + } + } +} // namespace RC \ No newline at end of file diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp similarity index 99% rename from deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp rename to deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp index ca8e76830..4d2c4ab8a 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp @@ -2,13 +2,23 @@ #include #include +#include + +#ifdef WIN32 #define NOMINMAX #include #include +#endif + #include #include +#ifdef LINUX +#include +#define byte uint8_t +#endif + namespace RC { ScanTargetArray SigScannerStaticData::m_modules_info; @@ -18,7 +28,7 @@ namespace RC SinglePassScanner::ScanMethod SinglePassScanner::m_scan_method = ScanMethod::Scalar; uint32_t SinglePassScanner::m_multithreading_module_size_threshold = 0x1000000; std::mutex SinglePassScanner::m_scanner_mutex{}; - +#ifdef WIN32 auto WIN_MODULEINFO::operator=(MODULEINFO other) -> WIN_MODULEINFO& { lpBaseOfDll = other.lpBaseOfDll; @@ -31,6 +41,13 @@ namespace RC { return *std::bit_cast(&array[static_cast(index)]); } +#else + auto ScanTargetArray::operator[](ScanTarget index) -> DLData& + { + return array[static_cast(index)]; + } +#endif + auto ScanTargetToString(ScanTarget scan_target) -> std::string { diff --git a/deps/first/Unreal b/deps/first/Unreal index ebfddd128..8bbf04eb3 160000 --- a/deps/first/Unreal +++ b/deps/first/Unreal @@ -1 +1 @@ -Subproject commit ebfddd128dc9e4b1ef76108348d70e57e1639b88 +Subproject commit 8bbf04eb3cb30c2c6815f3cf1f025e2d78b11d47 diff --git a/deps/first/patternsleuth b/deps/first/patternsleuth index 33e731e99..625b6125b 160000 --- a/deps/first/patternsleuth +++ b/deps/first/patternsleuth @@ -1 +1 @@ -Subproject commit 33e731e99f2a6bb7f65a8e95e89fd1c06ce9d1d2 +Subproject commit 625b6125b5518759c4fae81f4c19aa630fd0d33f diff --git a/deps/first/patternsleuth_bind/Cargo.lock b/deps/first/patternsleuth_bind/Cargo.lock index dd07ac157..f2e2e9568 100644 --- a/deps/first/patternsleuth_bind/Cargo.lock +++ b/deps/first/patternsleuth_bind/Cargo.lock @@ -119,6 +119,18 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + [[package]] name = "flate2" version = "1.0.28" @@ -230,6 +242,17 @@ dependencies = [ "slab", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -251,6 +274,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "indexmap" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "inventory" version = "0.3.14" @@ -349,6 +382,7 @@ dependencies = [ "anyhow", "futures", "futures-scopes", + "gimli", "iced-x86", "inventory", "itertools", @@ -494,6 +528,12 @@ version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" diff --git a/deps/third-repo/packages/p/polyhook_2/CMakeLists.txt b/deps/third-repo/packages/p/polyhook_2/CMakeLists.txt deleted file mode 100644 index f502acff3..000000000 --- a/deps/third-repo/packages/p/polyhook_2/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -cmake_minimum_required(VERSION 3.27) - -include(FetchContent) - -set(FETCHCONTENT_QUIET OFF) - -FetchContent_Declare(PolyHook2 - GIT_REPOSITORY https://github.com/stevemk14ebr/PolyHook_2_0.git - GIT_TAG fd2a88f09c8ae89440858fc52573656141013c7f - GIT_PROGRESS ON) - -if (${UE4SS_PolyHook_BUILD_SHARED}) - set(MAKE_POLYHOOK_DEPENDENCIES_SHARED ON) - set(MAKE_POLYHOOK_DEPENDENCIES_STATIC OFF) -else () - set(MAKE_POLYHOOK_DEPENDENCIES_SHARED OFF) - set(MAKE_POLYHOOK_DEPENDENCIES_STATIC ON) -endif () - -set(POLYHOOK_BUILD_DLL ON CACHE BOOL "Build dll & lib instead of tests" FORCE) -set(POLYHOOK_BUILD_SHARED_LIB ${MAKE_POLYHOOK_DEPENDENCIES_SHARED} CACHE BOOL "Build polyhook2 as shared libary" FORCE) -set(POLYHOOK_USE_EXTERNAL_ZYDIS ON CACHE BOOL "Use external zydis libary" FORCE) -set(ASMJIT_STATIC ${MAKE_POLYHOOK_DEPENDENCIES_STATIC} CACHE BOOL "Build 'asmjit' library as static" FORCE) -set(POLYHOOK_BUILD_STATIC_RUNTIME OFF CACHE BOOL "Use static runtime" FORCE) - -# prevent PolyHook from setting MSVC_RUNTIME_LIBRARY to "MultiThreaded$<$:Debug>DLL" by unsetting 'MSVC' var -set(TMP_MSVC ${MSVC}) -unset(MSVC) - -FetchContent_MakeAvailable(PolyHook2) - -# re-enable 'install' and reset 'MSVC' since we're done adding PolyHook -set(MSVC ${TMP_MSVC}) diff --git a/deps/third/DynoHook/00-compilebugs.patch b/deps/third/DynoHook/00-compilebugs.patch new file mode 100644 index 000000000..0df69e274 --- /dev/null +++ b/deps/third/DynoHook/00-compilebugs.patch @@ -0,0 +1,61 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 1633c1e..f215704 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -256,7 +256,7 @@ endif() + #Zydis + if(DYNOHOOK_USE_EXTERNAL_ZYDIS) + find_package(zydis REQUIRED) +- target_link_libraries(${PROJECT_NAME} PUBLIC Zydis::Zydis) ++ target_link_libraries(${PROJECT_NAME} PUBLIC Zydis) + else() + target_link_libraries(${PROJECT_NAME} PUBLIC $) + target_include_directories(${PROJECT_NAME} PUBLIC $) +diff --git a/src/detours/x64_detour.cpp b/src/detours/x64_detour.cpp +index 9e309dd..355119d 100644 +--- a/src/detours/x64_detour.cpp ++++ b/src/detours/x64_detour.cpp +@@ -3,6 +3,8 @@ + #include + #include + ++#include ++ + using namespace std::string_literals; + + using namespace dyno; +diff --git a/src/mem_accessor.cpp b/src/mem_accessor.cpp +index c3b6795..1d0b071 100644 +--- a/src/mem_accessor.cpp ++++ b/src/mem_accessor.cpp +@@ -2,6 +2,8 @@ + #include + #include + ++#include ++ + using namespace dyno; + + #if DYNO_PLATFORM_WINDOWS +@@ -74,7 +76,7 @@ static region_t get_region_from_addr(uintptr_t addr) { + res.prot = res.prot | ProtFlag::X; + + if (res.prot == ProtFlag::UNSET) +- res.prot = ProtFlag::NONE; ++ res.prot = ProtFlag::UNSET; + + break; + } +diff --git a/src/x64_hook.cpp b/src/x64_hook.cpp +index b419a45..32c51cc 100644 +--- a/src/x64_hook.cpp ++++ b/src/x64_hook.cpp +@@ -161,7 +161,7 @@ void x64Hook::writeModifyReturnAddress(Assembler& a) { + a.lea(rdx, qword_ptr(rsp, pushed)); + a.mov(rsi, qword_ptr(rsp, pushed)); + a.mov(rdi, this); +- a.sub(rsp, space); ++ a.sub(rsp, reserved); + a.call((void*&) setReturnAddress); // stack should be aligned by 16 bytes, call adds +8 + a.add(rsp, reserved); + #endif From b1728696e3f5a27bc94ec49d65e1d9a295b225db Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 8 Feb 2024 00:58:10 -0600 Subject: [PATCH 002/213] frpintf for output --- deps/first/DynamicOutput/src/DebugConsoleDevice.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp index fc897c241..a7864f557 100644 --- a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp +++ b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp @@ -76,7 +76,12 @@ namespace RC::Output #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE printf_s("DebugConsoleDevice received: %S", m_formatter(fmt).c_str()); #else +#ifdef WIN32 printf_s("%s" SystemStringPrint"\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); +#else + fprintf(stderr, "%s" SystemStringPrint"\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); + +#endif #endif } } // namespace RC::Output From 6056888885edeef25f25fbb8fa1c734f52a560a1 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 8 Feb 2024 00:58:25 -0600 Subject: [PATCH 003/213] should be != --- deps/first/File/src/FileType/StdFile.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index 830d479f9..e15bd4ccb 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -284,7 +284,7 @@ namespace RC::File return; } - if (fclose(m_file) == 0) + if (fclose(m_file) != 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::close_file] Was unable to close file, error: {}", errno)) } @@ -472,6 +472,7 @@ namespace RC::File modes = "rb"; break; default: + printf("open_for: %d\n", open_properties.open_for); THROW_INTERNAL_FILE_ERROR("[StdFile::open_file] Tried to open file but received invalid data for the 'OpenFor' parameter.") } @@ -486,6 +487,7 @@ namespace RC::File { if (!std::filesystem::exists(file_name_and_path)) { + printf("file_name_and_path: %s not exists\n", file_name_and_path.string().c_str()); THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::open_file] Tried opening file but file does not exist: {}", file_name_and_path.string())) } } @@ -500,6 +502,7 @@ namespace RC::File std::string_view open_type = open_properties.open_for == OpenFor::Writing || open_properties.open_for == OpenFor::Appending ? "writing" : "reading"; int error = errno; + printf("open file %s failed, error: %d\n", file_name_and_path.string().c_str(), error); THROW_INTERNAL_FILE_ERROR( std::format("[StdFile::open_file] Tried opening file for {} but encountered an error. Path & File: {} | errno = {}\n", open_type, From b47204894b88a37de6042a91d87305ee241d58a8 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 8 Feb 2024 00:58:42 -0600 Subject: [PATCH 004/213] some testing --- UE4SS/src/EntryLinux.cpp | 86 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 8c0e417bb..5f438c614 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -7,17 +7,19 @@ #include "UE4SSProgram.hpp" #include "Platform.hpp" +#define _GNU_SOURCE #include #include +#include #include #include +#include using namespace RC; pthread_t ue4ss_mainthread; -// constrcutor -void __attribute__((constructor)) UE4SS_Start() +void UE4SS_Start() { // find libUE4SS.so path using dlfcn Dl_info dl_info; @@ -26,14 +28,22 @@ void __attribute__((constructor)) UE4SS_Start() std::cerr << "Failed to find libUE4SS.so path" << std::endl; return; } - + #define EARLY_THROW_TEST + #ifdef EARLY_THROW_TEST + try { + throw std::runtime_error{"Hello from Here!"}; + } catch (std::exception& e) { + fprintf(stderr, "%s\n", e.what()); + } + #endif SystemStringType ue4sspath = to_generic_string(dl_info.dli_fname); auto program = new UE4SSProgram(ue4sspath, {}); + // use pthread here pthread_create(&ue4ss_mainthread, nullptr, [](void *arg) -> void * { auto program = (UE4SSProgram *)arg; program->init(); - + fprintf(stderr, "inited in thread\n"); if (auto e = program->get_error_object(); e->has_error()) { // If the output system errored out then use printf_s as a fallback @@ -51,10 +61,76 @@ void __attribute__((constructor)) UE4SS_Start() }, program); } +static bool UE4SSInited = false; + +/* +void __attribute__((constructor)) UE4SS_Init() { + // It may not init in correct order.. + if (!UE4SSInited) { + printf("UE4SS_Init Called\n"); + // UE4SS_Start(); + printf("UE4SS_Start Returned\n"); + UE4SSInited = true; + } +} +*/ + +static int (*next_main)(int, char **, char **); +static bool inited = false; +int hooked_main(int argc, char **argv, char **envp) { + // delay the hook to make sure all objects are constructed + fprintf(stderr, "Running hooked main before actual main my pid = %d\n", getpid()); + if (!inited) { + fprintf(stderr, "Do another hook?\n"); + UE4SS_Start(); + inited = true; + } else { + fprintf(stderr, "UE4SS already inited? \n"); + } + return next_main(argc, argv, envp); +} + +#define ALIGN_UP_PAGE(x) (( ((unsigned long)(x)) + 0xFFF) & ~0xFFF) +#define ALIGN_DOWN_PAGE(x) (((unsigned long)(x)) & ~0xFFF) + +extern "C" { +int __libc_start_main( + int (*main)(int, char **, char **), + int argc, + char **argv, + int (*init)(int, char **, char **), + void (*fini)(void), + void (*rtld_fini)(void), + void *stack_end) +{ + next_main = main; + typeof(&__libc_start_main) orig = (typeof(&__libc_start_main))dlsym(RTLD_NEXT, "__libc_start_main"); + // gxx fix + void *current___gxx_personality_v0 = dlsym(RTLD_NEXT, "__gxx_personality_v0"); + Dl_info dl_info; + Elf64_Sym *sym; + dladdr1(current___gxx_personality_v0, &dl_info, (void**) &sym, RTLD_DL_SYMENT); + fprintf(stderr, "__gxx_personality_v0 found in %s @ %p\n", dl_info.dli_fname, current___gxx_personality_v0); + if (strstr(dl_info.dli_fname, "libsteam_api.so") != nullptr) { + fprintf(stderr, "libsteam_api shit detected\n"); + mprotect((void*)ALIGN_DOWN_PAGE(sym), ALIGN_UP_PAGE(sym + 1) - ALIGN_DOWN_PAGE(sym), PROT_READ | PROT_WRITE); + sym->st_info = ELF64_ST_INFO(STB_LOCAL, ELF64_ST_TYPE(sym->st_info)); + sym->st_other = STV_INTERNAL; + } + current___gxx_personality_v0 = dlsym(RTLD_DEFAULT, "__gxx_personality_v0"); + fprintf(stderr, "Now the current___gxx_personality_v0 is %p\n", current___gxx_personality_v0); + + return orig(hooked_main, argc, argv, init, fini, rtld_fini, stack_end); +} +} + // destructor void __attribute__((destructor)) UE4SS_End() { - UE4SSProgram::static_cleanup(); + if (UE4SSInited) { + // UE4SSProgram::static_cleanup(); + UE4SSInited = false; + } } std::filesystem::path get_executable_path() { From f4de0ad7bc8b5425626f89eebc329ae09b754ab6 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 8 Feb 2024 00:59:07 -0600 Subject: [PATCH 005/213] no crash dump yet, comment out for now --- UE4SS/src/SettingsManager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index fc3491dea..e9419c0fb 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -46,7 +46,6 @@ namespace RC Ini::Parser parser; parser.parse(file); file.close(); - constexpr static File::CharType section_overrides[] = SYSSTR("Overrides"); REGISTER_STRING_SETTING(Overrides.ModsFolderPath, section_overrides, ModsFolderPath) @@ -97,9 +96,9 @@ namespace RC #endif REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); - constexpr static File::CharType section_crash_dump[] = SYSSTR("CrashDump"); - REGISTER_BOOL_SETTING(CrashDump.EnableDumping, section_crash_dump, EnableDumping); - REGISTER_BOOL_SETTING(CrashDump.FullMemoryDump, section_crash_dump, FullMemoryDump); + ///constexpr static File::CharType section_crash_dump[] = SYSSTR("CrashDump"); + ///REGISTER_BOOL_SETTING(CrashDump.EnableDumping, section_crash_dump, EnableDumping); + ///REGISTER_BOOL_SETTING(CrashDump.FullMemoryDump, section_crash_dump, FullMemoryDump); constexpr static File::CharType section_threads[] = SYSSTR("Threads"); REGISTER_INT64_SETTING(Threads.SigScannerNumThreads, section_threads, SigScannerNumThreads) From 6c4cadbd4db287edd0341991ce1eccb468058211 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 8 Feb 2024 00:59:17 -0600 Subject: [PATCH 006/213] debugs --- UE4SS/src/UE4SSProgram.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index bbb79f4f5..4eb1cb358 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -593,6 +593,7 @@ namespace RC // Virtual function offset overrides TRY([&]() { ProfilerScopeNamed("loading virtual function offset overrides"); + fprintf(stderr, "Loading offset\n"); static File::StringType virtual_function_offset_override_file{(m_working_directory / SYSSTR("VTableLayout.ini")).generic_string()}; if (std::filesystem::exists(virtual_function_offset_override_file)) { @@ -789,8 +790,11 @@ namespace RC file.close(); } + + fprintf(stderr, "Loading offset done\n"); }); + fprintf(stderr, "Setting hooks\n"); config.bHookProcessInternal = settings_manager.Hooks.HookProcessInternal; config.bHookProcessLocalScriptFunction = settings_manager.Hooks.HookProcessLocalScriptFunction; config.bHookLoadMap = settings_manager.Hooks.HookLoadMap; @@ -800,7 +804,7 @@ namespace RC config.bHookLocalPlayerExec = settings_manager.Hooks.HookLocalPlayerExec; config.bHookAActorTick = settings_manager.Hooks.HookAActorTick; config.FExecVTableOffsetInLocalPlayer = settings_manager.Hooks.FExecVTableOffsetInLocalPlayer; - + fprintf(stderr, "Before UnrealInitializer::Initialize\n"); Unreal::UnrealInitializer::Initialize(config); bool can_create_custom_events{true}; From cfa20dfa3957bd39a47e6b2c54b5764261a7b0fb Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 8 Feb 2024 01:02:27 -0600 Subject: [PATCH 007/213] update deps --- deps/first/patternsleuth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/patternsleuth b/deps/first/patternsleuth index 625b6125b..a26ec954d 160000 --- a/deps/first/patternsleuth +++ b/deps/first/patternsleuth @@ -1 +1 @@ -Subproject commit 625b6125b5518759c4fae81f4c19aa630fd0d33f +Subproject commit a26ec954d63adc70660f962f27586cf5fc5972e5 From 40b193aff7eea4c7ac1df8961ac255dd48451458 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 03:47:54 -0600 Subject: [PATCH 008/213] haeder generator for Linux + DWARF --- scripts/HeaderGen.py | 250 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100755 scripts/HeaderGen.py diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py new file mode 100755 index 000000000..320a30098 --- /dev/null +++ b/scripts/HeaderGen.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python3 +# generate header file for C++, using DRAWF information from .debug files + +import os +import sys + +DEFAULT_FILENAME = "./UnrealGame-Linux-Shipping.debug" +DEFAULT_SEARCH_DIR = "../deps/first/Unreal/generated_include" +DEFAULT_GENERATED_DIR = "../generated" + +FUNCTION_TEMPLATE = """if (auto it = {ClassName}::VTableLayoutMap.find(STR("{FunctionName}")); it == {ClassName}::VTableLayoutMap.end()) +{{ + {ClassName}::VTableLayoutMap.emplace(STR("{FunctionName}"), 0x{FunctionOffset:02x}); +}} +""" + +MEMBER_TEMPLATE = """if (auto it = {ClassName}::MemberOffsets.find(STR("{MemberName}")); it == {ClassName}::MemberOffsets.end()) +{{ + UWorld::MemberOffsets.emplace(STR("{MemberName}"), 0x{MemberOffset:02x}); +}} +""" + +class CMember: + def __init__(self, name, offset): + self.name = name + self.offset = offset + + def GenerateMember(self, className, count = None): + if count and count != 0: + return MEMBER_TEMPLATE.format(ClassName = className, MemberName = f"{self.name}_{count}", MemberOffset = self.offset) + else: + return MEMBER_TEMPLATE.format(ClassName = className, MemberName = self.name, MemberOffset = self.offset) + +class CVFunc: + def __init__(self, mangledname, name, slotoffset): + self.mangledname = mangledname + self.name = name + self.slotoffset = slotoffset + + def GenerateVFunc(self, className, count = None): + if count and count != 0: + return FUNCTION_TEMPLATE.format(ClassName = className, FunctionName = f"{self.name}_{count}", FunctionOffset = self.slotoffset) + else: + return FUNCTION_TEMPLATE.format(ClassName = className, FunctionName = self.name, FunctionOffset = self.slotoffset) + +class CClass: + def __init__(self, name): + self.name = name + self.members = {} + self.vfuncs = {} + + def AddMember(self, member, offset): + if member not in self.members: + self.members[member] = CMember(member, offset) + + def AddVFunc(self, mangledname, vfunc, offset): + if mangledname not in self.vfuncs: + self.vfuncs[mangledname] = CVFunc(mangledname, vfunc, offset) + + def GenerateMember(self): + vals = list(self.members.values()) + vals.sort(key = lambda x: x.offset) + return "\n".join([member.GenerateMember(self.name) for member in vals]) + + def GenerateVTable(self): + generatedName = {} + results = [] + vals = list(self.vfuncs.values()) + vals.sort(key = lambda x: x.slotoffset) + for vfunc in vals: + if vfunc.name in generatedName: + generatedName[vfunc.name] += 1 + else: + generatedName[vfunc.name] = 0 + results.append(vfunc.GenerateVFunc(self.name, generatedName[vfunc.name])) + return "\n".join(results) + +class Database: + def __init__(self): + self.classes = {} + + def GetClass(self, name): + if name not in self.classes: + self.classes[name] = CClass(name) + return self.classes[name] + + def GenerateMember(self): + return { name: cls.GenerateMember() for name, cls in self.classes.items() } + + def GenerateVTable(self): + return { name: cls.GenerateVTable() for name, cls in self.classes.items() } + +def GetClassNames(search_dir = DEFAULT_SEARCH_DIR): + # glob all file with pattern "MemberVariableLayout_HeaderWrapper_{ClassName}.hpp" + # return list of class names + """ + import glob, re + return [re.search(r"MemberVariableLayout_HeaderWrapper_(.*).hpp", file).group(1) for file in glob.glob(f"{search_dir}/MemberVariableLayout_HeaderWrapper_*.hpp")] + """ + return ['UGameViewportClient', + 'UEnum', + 'UConsole', + 'UDataTable', + 'FClassProperty', + 'FByteProperty', + 'FDelegateProperty', + 'UFunction', + 'FEnumProperty', + 'FSetProperty', + 'FInterfaceProperty', + 'FFieldPathProperty', + 'AGameMode', + 'UObjectBase', + 'FObjectPropertyBase', + 'AActor', + 'FBoolProperty', + 'UScriptStruct__ICppStructOps', + 'FMulticastDelegateProperty', + 'UPlayer', + 'FOutputDevice', + 'UField', + 'FMapProperty', + 'FArchive', + 'FSoftClassProperty', + 'FStructProperty', + 'ULocalPlayer', + 'UWorld', + 'AGameModeBase', + 'FConsoleVariableBase', + 'FConsoleCommandBase', + 'FArchiveState', + 'UScriptStruct', + 'FConsoleManager', + 'UStruct', + 'FProperty', + 'FArrayProperty', + 'UClass', + 'FField'] + +from elftools.dwarf.die import DIE +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + +def ScanCU(database, classes, cu): + for ch in cu.get_top_DIE().iter_children(): + if ch.tag == 'DW_TAG_class_type': + if ch.attributes.get('DW_AT_name'): + name = ch.attributes['DW_AT_name'].value.decode('utf-8') + if name in classes: + print(name) + klass = database.GetClass(name) + for m in ch.iter_children(): + name_m = m.attributes.get('DW_AT_name') + if not name_m: + continue + name_m = name_m.value.decode('utf-8') + if m.tag == 'DW_TAG_member': + if m.attributes.get('DW_AT_data_member_location'): + print(f" member: {name_m} @ {m.attributes['DW_AT_data_member_location'].value}") + klass.AddMember(name_m, m.attributes['DW_AT_data_member_location'].value) + if m.tag == "DW_TAG_subprogram": + # check if DW_AT_vtable_elem_location exists + if m.attributes.get('DW_AT_vtable_elem_location'): + # is a virtual function + link_name = m.attributes.get('DW_AT_linkage_name') + if link_name: + link_name = link_name.value.decode('utf-8') + else: + link_name = name_m + + print(f" vfunc: {name_m} aka {link_name} @ {m.attributes['DW_AT_vtable_elem_location'].value[1] * 8}") + klass.AddVFunc(link_name, name_m, m.attributes['DW_AT_vtable_elem_location'].value[1] * 8) + print() + +def ProcessFile(filename = DEFAULT_FILENAME, target_dir = DEFAULT_GENERATED_DIR, target_class = GetClassNames()): + with open(filename, 'rb') as f: + elffile = ELFFile(f) + dwarfinfo = elffile.get_dwarf_info() + + # if database_.pkl exists, load it and resume from last progress + started = True + if os.path.exists("database_.pkl"): + with open("database_.pkl", "rb") as f: + import pickle + database = pickle.load(f) + progress = pickle.load(f) + started = False + else: + database = Database() + + for cu in dwarfinfo.iter_CUs(): + if cu.get_top_DIE().attributes.get('DW_AT_name').value.decode('utf-8') == progress: + started = True + continue + if not started: + continue + + ScanCU(database, target_class, cu) + # pickle dump + with open("database_.pkl", "wb") as f: + import pickle + pickle.dump(database, f) + pickle.dump(cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8'), f) # dump progress + print(f"{cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8')} done...") + + # generate header files + path = DEFAULT_GENERATED_DIR + VFunc = "Linux_5_11_VTableOffsets_{ClassName}_FunctionBody.cpp" + Member = "Linux_5_11_MemberVariableLayout_DefaultSetter_{ClassName}.cpp" + for c in database.classes.values(): + with open(path + VFunc.format(ClassName=c.name), "w") as f: + f.write(c.GenerateVTable()) + with open(path + Member.format(ClassName=c.name), "w") as f: + f.write(c.GenerateMember()) + +def resolve_path(path): + return os.path.abspath(os.path.expanduser(path)) + +if __name__ == "__main__": + # get optional arguments + if len(sys.argv) > 1: + filename = sys.argv[1] + else: + filename = DEFAULT_FILENAME + if len(sys.argv) > 2: + target_dir = sys.argv[2] + else: + target_dir = "generated" + if len(sys.argv) > 3: + target_class = sys.argv[3:] + else: + target_class = GetClassNames() + + # check validity of arguments + if filename == '-h' or filename == '--help': + print(f"Usage: {sys.argv[0]} [filename] [target_dir] [target_class...]") + print(f" Default filename: {resolve_path(DEFAULT_FILENAME)}") + print(f" Default target_dir: {resolve_path(DEFAULT_GENERATED_DIR)}") + print(f" Default target_class: {' '.join(GetClassNames())}") + sys.exit(0) + + if not os.path.exists(filename): + print(f"File {filename} not found") + sys.exit(1) + + if not os.path.exists(target_dir): + print(f"Directory {target_dir} not found") + sys.exit(1) + + rocessFile(filename, target_dir, target_class) From f163d1efa7cffa9720edf617c5bf0c8f0967dda5 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 03:49:03 -0600 Subject: [PATCH 009/213] fix path and add results --- scripts/HeaderGen.py | 11 +++++------ scripts/database_.pkl | Bin 0 -> 119580 bytes 2 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 scripts/database_.pkl diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 320a30098..06f40a3c4 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -179,8 +179,8 @@ def ProcessFile(filename = DEFAULT_FILENAME, target_dir = DEFAULT_GENERATED_DIR, # if database_.pkl exists, load it and resume from last progress started = True - if os.path.exists("database_.pkl"): - with open("database_.pkl", "rb") as f: + if os.path.exists("database.pkl"): + with open("database.pkl", "rb") as f: import pickle database = pickle.load(f) progress = pickle.load(f) @@ -197,20 +197,19 @@ def ProcessFile(filename = DEFAULT_FILENAME, target_dir = DEFAULT_GENERATED_DIR, ScanCU(database, target_class, cu) # pickle dump - with open("database_.pkl", "wb") as f: + with open("database.pkl", "wb") as f: import pickle pickle.dump(database, f) pickle.dump(cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8'), f) # dump progress print(f"{cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8')} done...") # generate header files - path = DEFAULT_GENERATED_DIR VFunc = "Linux_5_11_VTableOffsets_{ClassName}_FunctionBody.cpp" Member = "Linux_5_11_MemberVariableLayout_DefaultSetter_{ClassName}.cpp" for c in database.classes.values(): - with open(path + VFunc.format(ClassName=c.name), "w") as f: + with open(target_dir + VFunc.format(ClassName=c.name), "w") as f: f.write(c.GenerateVTable()) - with open(path + Member.format(ClassName=c.name), "w") as f: + with open(target_dir + Member.format(ClassName=c.name), "w") as f: f.write(c.GenerateMember()) def resolve_path(path): diff --git a/scripts/database_.pkl b/scripts/database_.pkl new file mode 100644 index 0000000000000000000000000000000000000000..af0e14c5c5fd4076a1470da208ac56eb79314de5 GIT binary patch literal 119580 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 literal 0 HcmV?d00001 From 8056bef4a0c9978759100cc2ccbd4513255038ed Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 13:54:45 -0600 Subject: [PATCH 010/213] use argparse, not tested --- scripts/HeaderGen.py | 84 ++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 06f40a3c4..52a02d93e 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -172,15 +172,15 @@ def ScanCU(database, classes, cu): klass.AddVFunc(link_name, name_m, m.attributes['DW_AT_vtable_elem_location'].value[1] * 8) print() -def ProcessFile(filename = DEFAULT_FILENAME, target_dir = DEFAULT_GENERATED_DIR, target_class = GetClassNames()): +def ProcessFile(filename = DEFAULT_FILENAME, outfile= "database.pkl", target_class = GetClassNames()): with open(filename, 'rb') as f: elffile = ELFFile(f) dwarfinfo = elffile.get_dwarf_info() # if database_.pkl exists, load it and resume from last progress started = True - if os.path.exists("database.pkl"): - with open("database.pkl", "rb") as f: + if os.path.exists(outfile): + with open(outfile, "rb") as f: import pickle database = pickle.load(f) progress = pickle.load(f) @@ -197,53 +197,69 @@ def ProcessFile(filename = DEFAULT_FILENAME, target_dir = DEFAULT_GENERATED_DIR, ScanCU(database, target_class, cu) # pickle dump - with open("database.pkl", "wb") as f: + with open(outfile, "wb") as f: import pickle pickle.dump(database, f) pickle.dump(cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8'), f) # dump progress print(f"{cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8')} done...") + + print("CU scan done") + + return database +def GenerateHeaderFile(target_dir = DEFAULT_GENERATED_DIR, database = "database.pkl"): + print("Generating header files...") + if isinstance(database, str): + with open(database, "rb") as f: + import pickle + database = pickle.load(f) # generate header files VFunc = "Linux_5_11_VTableOffsets_{ClassName}_FunctionBody.cpp" Member = "Linux_5_11_MemberVariableLayout_DefaultSetter_{ClassName}.cpp" for c in database.classes.values(): + print(f"Generating {c.name}...") with open(target_dir + VFunc.format(ClassName=c.name), "w") as f: f.write(c.GenerateVTable()) with open(target_dir + Member.format(ClassName=c.name), "w") as f: f.write(c.GenerateMember()) + def resolve_path(path): return os.path.abspath(os.path.expanduser(path)) if __name__ == "__main__": - # get optional arguments - if len(sys.argv) > 1: - filename = sys.argv[1] - else: - filename = DEFAULT_FILENAME - if len(sys.argv) > 2: - target_dir = sys.argv[2] - else: - target_dir = "generated" - if len(sys.argv) > 3: - target_class = sys.argv[3:] + # -help/--help for usage + # -s in scan mode, args are [scan debug file] -o for output file -c for target class, can have a -g for generate header file + # -g for generate header mode, args are [database.pkl] -t for target directory + import argparse + parser = argparse.ArgumentParser(description="Generate header file for C++, using DRAWF information from .debug files") + parser.add_argument("-s", "--scan", help="Scan mode", action="store_true") + parser.add_argument("-g", "--generate", help="Generate header file", action="store_true") + + parser.add_argument("-o", "--output", help="Output file", nargs="?", default="database.pkl") + parser.add_argument("-c", "--class", help="Target class", nargs="+", metavar="class_", default=GetClassNames()) + parser.add_argument("-t", "--target", help="Target directory", nargs="?", default=DEFAULT_GENERATED_DIR) + parser.add_argument("filename", help="Filename", nargs="?", default=DEFAULT_FILENAME) + args = parser.parse_args() + + if args.scan: + if not args.output: + print("Output file not specified") + sys.exit(1) + if not args.class_: + print("Target class not specified") + sys.exit(1) + if args.generate: + if not args.target: + print("Target directory not specified") + database = ProcessFile(args.filename, args.output, args.class_) + if args.generate: + GenerateHeaderFile(args.target, database) else: - target_class = GetClassNames() - - # check validity of arguments - if filename == '-h' or filename == '--help': - print(f"Usage: {sys.argv[0]} [filename] [target_dir] [target_class...]") - print(f" Default filename: {resolve_path(DEFAULT_FILENAME)}") - print(f" Default target_dir: {resolve_path(DEFAULT_GENERATED_DIR)}") - print(f" Default target_class: {' '.join(GetClassNames())}") - sys.exit(0) - - if not os.path.exists(filename): - print(f"File {filename} not found") - sys.exit(1) - - if not os.path.exists(target_dir): - print(f"Directory {target_dir} not found") - sys.exit(1) - - rocessFile(filename, target_dir, target_class) + if args.generate: + if not args.target: + print("Target directory not specified") + fn = args.filename + if fn == DEFAULT_FILENAME: + fn = "database.pkl" + GenerateHeaderFile(args.target, args.filename) From 9f88547ed964baaa0507998506cb6d83cebbe7d9 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 14:16:21 -0600 Subject: [PATCH 011/213] should be 501 --- scripts/HeaderGen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 52a02d93e..894ce77fa 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -214,8 +214,8 @@ def GenerateHeaderFile(target_dir = DEFAULT_GENERATED_DIR, database = "database. import pickle database = pickle.load(f) # generate header files - VFunc = "Linux_5_11_VTableOffsets_{ClassName}_FunctionBody.cpp" - Member = "Linux_5_11_MemberVariableLayout_DefaultSetter_{ClassName}.cpp" + VFunc = "Linux_5_01_VTableOffsets_{ClassName}_FunctionBody.cpp" + Member = "Linux_5_01_MemberVariableLayout_DefaultSetter_{ClassName}.cpp" for c in database.classes.values(): print(f"Generating {c.name}...") with open(target_dir + VFunc.format(ClassName=c.name), "w") as f: From d9c8610bf346c3f3c7854909714ffa492903cf35 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 16:42:18 -0600 Subject: [PATCH 012/213] new class list --- scripts/HeaderGen.py | 68 ++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 43 deletions(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 894ce77fa..f3c4dbfaa 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -3,6 +3,8 @@ import os import sys +import re +import pickle DEFAULT_FILENAME = "./UnrealGame-Linux-Shipping.debug" DEFAULT_SEARCH_DIR = "../deps/first/Unreal/generated_include" @@ -20,6 +22,8 @@ }} """ +Version = "5_01" + class CMember: def __init__(self, name, offset): self.name = name @@ -94,48 +98,13 @@ def GetClassNames(search_dir = DEFAULT_SEARCH_DIR): # glob all file with pattern "MemberVariableLayout_HeaderWrapper_{ClassName}.hpp" # return list of class names """ - import glob, re - return [re.search(r"MemberVariableLayout_HeaderWrapper_(.*).hpp", file).group(1) for file in glob.glob(f"{search_dir}/MemberVariableLayout_HeaderWrapper_*.hpp")] + import glob + tabA = [re.search(rf"{Version}_VTableOffsets_(.*)_FunctionBody\.cpp", file).group(1) for file in glob.glob(f"{search_dir}/FunctionBodies/{Version}_VTableOffsets_*.cpp")] + tabB = [re.search(rf"{Version}_MemberVariableLayout_DefaultSetter_(.*)\.cpp", file).group(1) for file in glob.glob(f"{search_dir}/FunctionBodies/{Version}_MemberVariableLayout_DefaultSetter_*.cpp")] + return list(dict.fromkeys(tabA + tabB)) """ - return ['UGameViewportClient', - 'UEnum', - 'UConsole', - 'UDataTable', - 'FClassProperty', - 'FByteProperty', - 'FDelegateProperty', - 'UFunction', - 'FEnumProperty', - 'FSetProperty', - 'FInterfaceProperty', - 'FFieldPathProperty', - 'AGameMode', - 'UObjectBase', - 'FObjectPropertyBase', - 'AActor', - 'FBoolProperty', - 'UScriptStruct__ICppStructOps', - 'FMulticastDelegateProperty', - 'UPlayer', - 'FOutputDevice', - 'UField', - 'FMapProperty', - 'FArchive', - 'FSoftClassProperty', - 'FStructProperty', - 'ULocalPlayer', - 'UWorld', - 'AGameModeBase', - 'FConsoleVariableBase', - 'FConsoleCommandBase', - 'FArchiveState', - 'UScriptStruct', - 'FConsoleManager', - 'UStruct', - 'FProperty', - 'FArrayProperty', - 'UClass', - 'FField'] + + return ['FArchiveState', 'UDataTable', 'FConsoleManager', 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct__ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] from elftools.dwarf.die import DIE from elftools.elf.elffile import ELFFile @@ -181,7 +150,6 @@ def ProcessFile(filename = DEFAULT_FILENAME, outfile= "database.pkl", target_cla started = True if os.path.exists(outfile): with open(outfile, "rb") as f: - import pickle database = pickle.load(f) progress = pickle.load(f) started = False @@ -198,7 +166,6 @@ def ProcessFile(filename = DEFAULT_FILENAME, outfile= "database.pkl", target_cla ScanCU(database, target_class, cu) # pickle dump with open(outfile, "wb") as f: - import pickle pickle.dump(database, f) pickle.dump(cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8'), f) # dump progress print(f"{cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8')} done...") @@ -235,6 +202,8 @@ def resolve_path(path): parser = argparse.ArgumentParser(description="Generate header file for C++, using DRAWF information from .debug files") parser.add_argument("-s", "--scan", help="Scan mode", action="store_true") parser.add_argument("-g", "--generate", help="Generate header file", action="store_true") + parser.add_argument("-i", "--info", help="Print infos", action="store_true") + parser.add_argument("-v", "--version", help="Set version", nargs="?", default=Version) parser.add_argument("-o", "--output", help="Output file", nargs="?", default="database.pkl") parser.add_argument("-c", "--class", help="Target class", nargs="+", metavar="class_", default=GetClassNames()) @@ -242,6 +211,19 @@ def resolve_path(path): parser.add_argument("filename", help="Filename", nargs="?", default=DEFAULT_FILENAME) args = parser.parse_args() + if args.version: + # valid version = "\d_\d\d" + if not re.match(r"\d_\d\d", args.version): + print("Invalid version") + sys.exit(1) + Version = args.version + + if args.info: + print(" Class names: ", GetClassNames()) + print(" Default search dir: ", resolve_path(DEFAULT_SEARCH_DIR)) + print(" Default generated dir: ", resolve_path(DEFAULT_GENERATED_DIR)) + sys.exit(0) + if args.scan: if not args.output: print("Output file not specified") From 282f1a3f7b056fea00ffd19b7d71962f91561e0c Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 18:35:54 -0600 Subject: [PATCH 013/213] support subclass --- scripts/HeaderGen.py | 135 +++++++++++++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 36 deletions(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index f3c4dbfaa..9f9174599 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # generate header file for C++, using DRAWF information from .debug files - +# e.g., ./HeaderGen.py -s -g -t ../deps/first/Unreal/generated_include/FunctionBodies /mnt/d/Projects/palworld/UnrealGame-Linux-Shipping.debug import os import sys import re @@ -79,6 +79,12 @@ def GenerateVTable(self): results.append(vfunc.GenerateVFunc(self.name, generatedName[vfunc.name])) return "\n".join(results) + def HasMember(self): + return len(self.members) > 0 + + def HasVFunc(self): + return len(self.vfuncs) > 0 + class Database: def __init__(self): self.classes = {} @@ -101,23 +107,40 @@ def GetClassNames(search_dir = DEFAULT_SEARCH_DIR): import glob tabA = [re.search(rf"{Version}_VTableOffsets_(.*)_FunctionBody\.cpp", file).group(1) for file in glob.glob(f"{search_dir}/FunctionBodies/{Version}_VTableOffsets_*.cpp")] tabB = [re.search(rf"{Version}_MemberVariableLayout_DefaultSetter_(.*)\.cpp", file).group(1) for file in glob.glob(f"{search_dir}/FunctionBodies/{Version}_MemberVariableLayout_DefaultSetter_*.cpp")] - return list(dict.fromkeys(tabA + tabB)) + l = list(dict.fromkeys(tabA + tabB)) + # replace _ to : + return [x.replace("_", ":") for x in l] """ + return ['FArchiveState', 'UDataTable', 'FConsoleManager', 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct::ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] - return ['FArchiveState', 'UDataTable', 'FConsoleManager', 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct__ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] +AdditonalClasses = ['FUObjectArray'] from elftools.dwarf.die import DIE from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection -def ScanCU(database, classes, cu): - for ch in cu.get_top_DIE().iter_children(): - if ch.tag == 'DW_TAG_class_type': +def SubClassMatch(name, classes): + newclasses = [] + for i in classes: + if i.startswith(name + "::"): + # remove i:: + newclasses.append(i[len(name) + 2:]) + if len(newclasses) == 0: + return None + return newclasses + +# test +# print(SubClassMatch("UScriptStruct", GetClassNames())) + +def ScanCU(database, classes, citer, prefix = []): + for ch in citer: + if ch.tag == 'DW_TAG_class_type' or ch.tag == 'DW_TAG_structure_type' or ch.tag == 'DW_TAG_union_type': if ch.attributes.get('DW_AT_name'): name = ch.attributes['DW_AT_name'].value.decode('utf-8') if name in classes: - print(name) - klass = database.GetClass(name) + longname = "::".join(prefix + [name]) + print(longname) + klass = database.GetClass(longname) for m in ch.iter_children(): name_m = m.attributes.get('DW_AT_name') if not name_m: @@ -140,55 +163,94 @@ def ScanCU(database, classes, cu): print(f" vfunc: {name_m} aka {link_name} @ {m.attributes['DW_AT_vtable_elem_location'].value[1] * 8}") klass.AddVFunc(link_name, name_m, m.attributes['DW_AT_vtable_elem_location'].value[1] * 8) print() + if (subclasses := SubClassMatch(name, classes)) is not None: + ScanCU(database, subclasses, ch.iter_children(), prefix + [name]) -def ProcessFile(filename = DEFAULT_FILENAME, outfile= "database.pkl", target_class = GetClassNames()): - with open(filename, 'rb') as f: - elffile = ELFFile(f) - dwarfinfo = elffile.get_dwarf_info() - +def RunSingle(conn, dwarfinfo, outfile, cus, idx, target_class): # if database_.pkl exists, load it and resume from last progress started = True if os.path.exists(outfile): with open(outfile, "rb") as f: database = pickle.load(f) progress = pickle.load(f) - started = False else: database = Database() - - for cu in dwarfinfo.iter_CUs(): - if cu.get_top_DIE().attributes.get('DW_AT_name').value.decode('utf-8') == progress: - started = True + progress = 0 + + # iter from idx + for i, cu in enumerate(cus): + if i < progress: continue - if not started: + if i < idx: continue - - ScanCU(database, target_class, cu) + print(f"Scanning {cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8')} ...") + ScanCU(database, target_class, cu.get_top_DIE().iter_children()) + print(f"{cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8')} done...") # pickle dump with open(outfile, "wb") as f: pickle.dump(database, f) - pickle.dump(cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8'), f) # dump progress - print(f"{cu.get_top_DIE().attributes['DW_AT_name'].value.decode('utf-8')} done...") + pickle.dump(i + 1, f) + conn.send(i + 1) + conn.close() + return + conn.send(i + 1) + conn.close() - print("CU scan done") - return database +from multiprocessing import Process, Pipe -def GenerateHeaderFile(target_dir = DEFAULT_GENERATED_DIR, database = "database.pkl"): +def ProcessFile(filename = DEFAULT_FILENAME, outfile= "database.pkl", target_class = GetClassNames()): + with open(filename, 'rb') as f: + elffile = ELFFile(f) + dwarfinfo = elffile.get_dwarf_info() + + target_class += AdditonalClasses + + cus = list(dwarfinfo.iter_CUs()) + idx = 0 + while idx < len(cus): + parent_conn, child_conn = Pipe() + p = Process(target=RunSingle, args=(child_conn, dwarfinfo, outfile, cus, idx, target_class)) + p.start() + idx = parent_conn.recv() + p.join() + + print("CU scan done") + +def GenerateHeaderFile(target_dir = DEFAULT_GENERATED_DIR, database = "database.pkl", target_class = GetClassNames()): print("Generating header files...") if isinstance(database, str): with open(database, "rb") as f: import pickle database = pickle.load(f) # generate header files - VFunc = "Linux_5_01_VTableOffsets_{ClassName}_FunctionBody.cpp" - Member = "Linux_5_01_MemberVariableLayout_DefaultSetter_{ClassName}.cpp" + VFunc = "Linux_{Version}_VTableOffsets_{ClassName}_FunctionBody.cpp" + Member = "Linux_{Version}_MemberVariableLayout_DefaultSetter_{ClassName}.cpp" + GeneratedVFuncs = set() + GeneratedMembers = set() + TargetClasses = set(target_class) for c in database.classes.values(): + if c.name not in TargetClasses: + continue print(f"Generating {c.name}...") - with open(target_dir + VFunc.format(ClassName=c.name), "w") as f: - f.write(c.GenerateVTable()) - with open(target_dir + Member.format(ClassName=c.name), "w") as f: - f.write(c.GenerateMember()) + if c.HasVFunc(): + with open(target_dir + "/" + VFunc.format(ClassName=c.name.replace(':', "_"), Version=Version), "w") as f: + f.write(c.GenerateVTable()) + GeneratedVFuncs.add(c.name) + print(f" {VFunc.format(ClassName=c.name, Version=Version)} done") + if c.HasMember(): + with open(target_dir + "/" + Member.format(ClassName=c.name.replace(':', "_"), Version=Version), "w") as f: + f.write(c.GenerateMember()) + print(f" {Member.format(ClassName=c.name, Version=Version)} done") + GeneratedMembers.add(c.name) + print("Header files gerenation done.") + print("Summary:") + print(" Generated VFuncs: ", len(GeneratedVFuncs)) + print(" Generated Members: ", len(GeneratedMembers)) + # print classes not generated + print("Classes not generated:") + print(" VFuncs: ", TargetClasses - GeneratedVFuncs) + print(" Members: ", TargetClasses - GeneratedMembers) def resolve_path(path): @@ -204,9 +266,10 @@ def resolve_path(path): parser.add_argument("-g", "--generate", help="Generate header file", action="store_true") parser.add_argument("-i", "--info", help="Print infos", action="store_true") parser.add_argument("-v", "--version", help="Set version", nargs="?", default=Version) + parser.add_argument("-a", "--addition", help="Add additional classes for scan", nargs="+", default=AdditonalClasses) parser.add_argument("-o", "--output", help="Output file", nargs="?", default="database.pkl") - parser.add_argument("-c", "--class", help="Target class", nargs="+", metavar="class_", default=GetClassNames()) + parser.add_argument("-c", "--class", help="Target class", nargs="+", dest="class_", default=GetClassNames()) parser.add_argument("-t", "--target", help="Target directory", nargs="?", default=DEFAULT_GENERATED_DIR) parser.add_argument("filename", help="Filename", nargs="?", default=DEFAULT_FILENAME) args = parser.parse_args() @@ -234,9 +297,9 @@ def resolve_path(path): if args.generate: if not args.target: print("Target directory not specified") - database = ProcessFile(args.filename, args.output, args.class_) + ProcessFile(args.filename, args.output, args.class_) if args.generate: - GenerateHeaderFile(args.target, database) + GenerateHeaderFile(args.target, args.output, args.class_) else: if args.generate: if not args.target: @@ -244,4 +307,4 @@ def resolve_path(path): fn = args.filename if fn == DEFAULT_FILENAME: fn = "database.pkl" - GenerateHeaderFile(args.target, args.filename) + GenerateHeaderFile(args.target, args.filename, args.class_) From b956e95227b29a7a64d463fd84654238e1f6a4df Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 19:05:28 -0600 Subject: [PATCH 014/213] add print function --- scripts/HeaderGen.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 9f9174599..5c3a1170c 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -79,6 +79,16 @@ def GenerateVTable(self): results.append(vfunc.GenerateVFunc(self.name, generatedName[vfunc.name])) return "\n".join(results) + def __str__(self): + return "\n".join([ + f"Class {self.name}{{", + "\t// Members", + "\n".join([f"\t{member.name} @ 0x{member.offset:02x}" for member in self.members.values()]), + "\t// VFuncs", + "\n".join([f"\t{vfunc.name} @ 0x{vfunc.slotoffset:02x} // {vunfc.mangledname}" for vfunc in self.vfuncs.values()]), + "}" + ]) + def HasMember(self): return len(self.members) > 0 @@ -264,6 +274,9 @@ def resolve_path(path): parser = argparse.ArgumentParser(description="Generate header file for C++, using DRAWF information from .debug files") parser.add_argument("-s", "--scan", help="Scan mode", action="store_true") parser.add_argument("-g", "--generate", help="Generate header file", action="store_true") + # -p only one class + parser.add_argument("-p", "--print", help="Print definition for class", nargs="?", default=None) + parser.add_argument("-i", "--info", help="Print infos", action="store_true") parser.add_argument("-v", "--version", help="Set version", nargs="?", default=Version) parser.add_argument("-a", "--addition", help="Add additional classes for scan", nargs="+", default=AdditonalClasses) @@ -287,6 +300,20 @@ def resolve_path(path): print(" Default generated dir: ", resolve_path(DEFAULT_GENERATED_DIR)) sys.exit(0) + if args.print: + fn = args.filename + if fn == DEFAULT_FILENAME: + fn = "database.pkl" + if not os.path.exists(fn): + print("Database file not found") + sys.exit(1) + with open(fn, "rb") as f: + database = pickle.load(f) + if args.print not in database.classes: + print(f"Class {args.print} not found") + sys.exit(1) + print(str(database.classes[args.print])) + sys.exit(0) if args.scan: if not args.output: print("Output file not specified") @@ -307,4 +334,7 @@ def resolve_path(path): fn = args.filename if fn == DEFAULT_FILENAME: fn = "database.pkl" + if not os.path.exists(fn): + print("Database file not found") + sys.exit(1) GenerateHeaderFile(args.target, args.filename, args.class_) From 85cb57bfceb196661d2b6508ac46a58b8f9f4f98 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 12 Feb 2024 19:57:40 -0600 Subject: [PATCH 015/213] no need for add --- scripts/HeaderGen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 5c3a1170c..bd2bf6e6d 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -123,7 +123,7 @@ def GetClassNames(search_dir = DEFAULT_SEARCH_DIR): """ return ['FArchiveState', 'UDataTable', 'FConsoleManager', 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct::ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] -AdditonalClasses = ['FUObjectArray'] +AdditonalClasses = [] from elftools.dwarf.die import DIE from elftools.elf.elffile import ELFFile From 6118ca109bb5728dc42844993ce3040eaa2c92e5 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 13 Feb 2024 00:37:31 -0600 Subject: [PATCH 016/213] remove test flag --- UE4SS/src/EntryLinux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 5f438c614..7ec7c92f0 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -28,7 +28,7 @@ void UE4SS_Start() std::cerr << "Failed to find libUE4SS.so path" << std::endl; return; } - #define EARLY_THROW_TEST + //#define EARLY_THROW_TEST #ifdef EARLY_THROW_TEST try { throw std::runtime_error{"Hello from Here!"}; From f6c29bb2add083eda431adadc07a7eaa0936f6ca Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 13 Feb 2024 01:21:34 -0600 Subject: [PATCH 017/213] remove UE4SS from its child process --- UE4SS/src/EntryLinux.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 7ec7c92f0..6892334f5 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -93,6 +93,8 @@ int hooked_main(int argc, char **argv, char **envp) { #define ALIGN_UP_PAGE(x) (( ((unsigned long)(x)) + 0xFFF) & ~0xFFF) #define ALIGN_DOWN_PAGE(x) (((unsigned long)(x)) & ~0xFFF) +extern char **environ; + extern "C" { int __libc_start_main( int (*main)(int, char **, char **), @@ -120,8 +122,22 @@ int __libc_start_main( current___gxx_personality_v0 = dlsym(RTLD_DEFAULT, "__gxx_personality_v0"); fprintf(stderr, "Now the current___gxx_personality_v0 is %p\n", current___gxx_personality_v0); + // remove LD_PRELOAD from environ + int nenv = 0; + for (int i = 0; environ[i]; i++) + nenv ++; + for (int i = 0; i < nenv; i++) { + if (strncmp(environ[i], "LD_PRELOAD=", 11) == 0) { + fprintf(stderr, "Found LD_PRELOAD @%d %s\n", i, environ[i]); + environ[i] = environ[nenv - 1]; + nenv --; + } + } + environ[nenv] = NULL; + return orig(hooked_main, argc, argv, init, fini, rtld_fini, stack_end); } + } // destructor From 060e14abbd525ed33fdd4127f2942205d5ee06b4 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 13 Feb 2024 01:39:42 -0600 Subject: [PATCH 018/213] do not throw --- .../src/SinglePassSigScannerLinux.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp index f9839a185..b29b3aa9b 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp @@ -734,7 +734,7 @@ namespace RC // If not modular then the containers get merged into one scan target // That way there are no extra scans // If modular then loop the containers and retrieve the scan target for each and pass everything to the do_scan() lambda - + fprintf(stderr, "signature_containers.size() = %d\n", signature_containers.size()); if (!SigScannerStaticData::m_is_modular) { DLData merged_module_info{}; @@ -743,6 +743,7 @@ namespace RC for (const auto& [scan_target, outer_container] : signature_containers) { merged_module_info = *std::bit_cast(&SigScannerStaticData::m_modules_info[scan_target]); + fprintf(stderr, "outer_container len = %d\n", outer_container.size()); for (const auto& signature_container : outer_container) { merged_containers.emplace_back(signature_container); @@ -751,8 +752,10 @@ namespace RC if (merged_containers.empty()) { - throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " - "an internal error."}; + fprintf(stderr, "No containers to merge\n"); + return ; + //throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " + // "an internal error."}; } uint8_t* module_start_address = static_cast(merged_module_info.base_address); From 49fbb8e27ae8ff61d3b8d4141abdc59126b7e40a Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 13 Feb 2024 02:33:27 -0600 Subject: [PATCH 019/213] fixed throw problem!! --- UE4SS/src/EntryLinux.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 6892334f5..7bb0771bc 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -108,20 +108,20 @@ int __libc_start_main( next_main = main; typeof(&__libc_start_main) orig = (typeof(&__libc_start_main))dlsym(RTLD_NEXT, "__libc_start_main"); // gxx fix - void *current___gxx_personality_v0 = dlsym(RTLD_NEXT, "__gxx_personality_v0"); Dl_info dl_info; Elf64_Sym *sym; - dladdr1(current___gxx_personality_v0, &dl_info, (void**) &sym, RTLD_DL_SYMENT); - fprintf(stderr, "__gxx_personality_v0 found in %s @ %p\n", dl_info.dli_fname, current___gxx_personality_v0); - if (strstr(dl_info.dli_fname, "libsteam_api.so") != nullptr) { - fprintf(stderr, "libsteam_api shit detected\n"); + // libsteam_api is okay, the UE engine is causing problem + + void *current___cxa_throw = dlsym(RTLD_DEFAULT, "__cxa_throw"); + dladdr1(current___cxa_throw, &dl_info, (void**) &sym, RTLD_DL_SYMENT); + fprintf(stderr, "__cxa_throw found in %s @ %p\n", dl_info.dli_fname, current___cxa_throw); + if ((unsigned long)current___cxa_throw < 0x7fffffff) { + fprintf(stderr, "maybe UE, patched\n"); mprotect((void*)ALIGN_DOWN_PAGE(sym), ALIGN_UP_PAGE(sym + 1) - ALIGN_DOWN_PAGE(sym), PROT_READ | PROT_WRITE); sym->st_info = ELF64_ST_INFO(STB_LOCAL, ELF64_ST_TYPE(sym->st_info)); sym->st_other = STV_INTERNAL; + // assume this is UE5's address range and remove this symbol } - current___gxx_personality_v0 = dlsym(RTLD_DEFAULT, "__gxx_personality_v0"); - fprintf(stderr, "Now the current___gxx_personality_v0 is %p\n", current___gxx_personality_v0); - // remove LD_PRELOAD from environ int nenv = 0; for (int i = 0; environ[i]; i++) From 58ec512c0116877507529745bbbda873a1537801 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 13 Feb 2024 02:56:12 -0600 Subject: [PATCH 020/213] fix classname --- scripts/HeaderGen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index bd2bf6e6d..4169ec22b 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -18,7 +18,7 @@ MEMBER_TEMPLATE = """if (auto it = {ClassName}::MemberOffsets.find(STR("{MemberName}")); it == {ClassName}::MemberOffsets.end()) {{ - UWorld::MemberOffsets.emplace(STR("{MemberName}"), 0x{MemberOffset:02x}); + {ClassName}::MemberOffsets.emplace(STR("{MemberName}"), 0x{MemberOffset:02x}); }} """ From a3a0c4610f5c74a8ec053028aa3a22dd680cffc4 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 14 Feb 2024 01:33:26 -0600 Subject: [PATCH 021/213] exoprt get_game_directory() --- UE4SS/include/UE4SSProgram.hpp | 2 ++ UE4SS/src/UE4SSProgram.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index 5493df83b..d200cc265 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -128,6 +128,7 @@ namespace RC SystemStringType m_module_file_path_str; SystemStringType m_working_directory_str; + SystemStringType m_game_executable_str; SystemStringType m_mods_directory_str; std::filesystem::path m_game_executable_directory; @@ -239,6 +240,7 @@ namespace RC RC_UE4SS_API auto get_working_directory() -> SystemStringViewType; RC_UE4SS_API auto get_mods_directory() -> SystemStringViewType; RC_UE4SS_API auto get_legacy_root_directory() -> SystemStringViewType; + RC_UE4SS_API auto UE4SSProgram::get_game_directory() -> SystemStringViewType; RC_UE4SS_API auto generate_uht_compatible_headers() -> void; RC_UE4SS_API auto generate_cxx_headers(const std::filesystem::path& output_dir) -> void; RC_UE4SS_API auto generate_lua_types(const std::filesystem::path& output_dir) -> void; diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 4eb1cb358..2e47dcabb 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1445,6 +1445,12 @@ namespace RC { return m_legacy_root_directory.c_str(); } + + auto UE4SSProgram::get_game_directory() -> File::StringViewType + { + m_game_executable_str = m_game_executable_directory.generic_string(); + return m_game_executable_str; + } auto UE4SSProgram::generate_uht_compatible_headers() -> void { From 43feb29eed9e0d7e368875ff6beea7611e838e05 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 14 Feb 2024 01:33:33 -0600 Subject: [PATCH 022/213] use path relative to get_game_directory() --- UE4SS/src/Mod/LuaMod.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 7e92a65b9..ba322b525 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -70,6 +70,8 @@ #include #pragma warning(default : 4005) +#include + namespace RC { LuaMadeSimple::Lua* LuaStatics::console_executor{}; @@ -827,17 +829,17 @@ namespace RC lua_getfield(lua_state, -1, "path"); std::string current_paths = lua_tostring(lua_state, -1); - current_paths.append(std::format(";{}\\{}\\Scripts\\?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); - current_paths.append(std::format(";{}\\shared\\?.lua", to_string(m_program.get_mods_directory()).c_str())); - current_paths.append(std::format(";{}\\shared\\?\\?.lua", to_string(m_program.get_mods_directory()).c_str())); + current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); + current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); lua_pop(lua_state, 1); lua_pushstring(lua_state, current_paths.c_str()); lua_setfield(lua_state, -2, "path"); lua_getfield(lua_state, -1, "cpath"); std::string current_cpaths = lua_tostring(lua_state, -1); - current_cpaths.append(std::format(";{}\\{}\\Scripts\\?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); - current_cpaths.append(std::format(";{}\\{}\\?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); lua_pop(lua_state, 1); lua_pushstring(lua_state, current_cpaths.c_str()); lua_setfield(lua_state, -2, "cpath"); @@ -2133,8 +2135,8 @@ No overload found for function 'IterateGameDirectories'. Overloads: #1: IterateGameDirectories()"}; - std::filesystem::path game_executable_directory = UE4SSProgram::get_program().get_game_executable_directory(); - auto game_content_dir = game_executable_directory.parent_path().parent_path() / "Content"; + std::filesystem::path game_exe_directory = UE4SSProgram::get_program().get_game_directory(); + auto game_content_dir = game_exe_directory.parent_path().parent_path() / "Content"; if (!std::filesystem::exists(game_content_dir)) { Output::send(SYSSTR("IterateGameDirectories: Could not locate the root directory because the directory structure is unknown " @@ -2143,8 +2145,8 @@ No overload found for function 'IterateGameDirectories'. return 1; } - auto game_name = game_executable_directory.parent_path().parent_path().stem(); - auto game_root_directory = game_executable_directory.parent_path().parent_path().parent_path(); + auto game_name = game_exe_directory.parent_path().parent_path().stem(); + auto game_root_directory = game_exe_directory.parent_path().parent_path().parent_path(); auto directories_table = lua.prepare_new_table(); std::function iterate_directory = @@ -2249,8 +2251,8 @@ No overload found for function 'CreateLogicModsDirectory'. Overloads: #1: CreateLogicModsDirectory()"}; - std::filesystem::path game_executable_directory = UE4SSProgram::get_program().get_game_executable_directory(); - auto game_content_dir = game_executable_directory.parent_path().parent_path() / "Content"; + std::filesystem::path game_exe_directory = UE4SSProgram::get_program().get_game_directory(); + auto game_content_dir = game_exe_directory.parent_path().parent_path() / "Content"; if (!std::filesystem::exists(game_content_dir)) { lua.throw_error("CreateLogicModsDirectory: Could not locate the \"Content\" directory because the directory structure is unknown (not " From dd255c0a24736f1272c1f167afaf06a5ddc76c7e Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 14 Feb 2024 04:06:04 -0600 Subject: [PATCH 023/213] make both people happy (for now) --- UE4SS/src/Mod/LuaMod.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index ba322b525..36cc54491 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -830,6 +830,7 @@ namespace RC lua_getfield(lua_state, -1, "path"); std::string current_paths = lua_tostring(lua_state, -1); current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); lua_pop(lua_state, 1); @@ -839,6 +840,7 @@ namespace RC lua_getfield(lua_state, -1, "cpath"); std::string current_cpaths = lua_tostring(lua_state, -1); current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); lua_pop(lua_state, 1); lua_pushstring(lua_state, current_cpaths.c_str()); From 79cca148b8ca99a4fd5fb7bc2605a513056ee254 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 01:40:30 -0600 Subject: [PATCH 024/213] add github CI --- .github/package.sh | 4 ++ .github/workflows/UpdateUESubmodule.yml | 55 ------------------- .github/workflows/experimental.yml | 72 ------------------------- .github/workflows/linux-test.yml | 41 ++++++++++++++ .github/workflows/pushdocs.yml | 52 ------------------ .github/workflows/release.yml | 72 ------------------------- 6 files changed, 45 insertions(+), 251 deletions(-) create mode 100755 .github/package.sh delete mode 100644 .github/workflows/UpdateUESubmodule.yml delete mode 100644 .github/workflows/experimental.yml create mode 100644 .github/workflows/linux-test.yml delete mode 100644 .github/workflows/pushdocs.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/package.sh b/.github/package.sh new file mode 100755 index 000000000..6c97beebf --- /dev/null +++ b/.github/package.sh @@ -0,0 +1,4 @@ +#!/bin/bash +mkdir package +cp build/Output/Game__Shipping__Linux/libUE4SS.so package +cp assets/UE4SS-settings.ini package diff --git a/.github/workflows/UpdateUESubmodule.yml b/.github/workflows/UpdateUESubmodule.yml deleted file mode 100644 index f210c1e5e..000000000 --- a/.github/workflows/UpdateUESubmodule.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Update UE Submodule and PR - -on: - workflow_dispatch: - -env: - COMMITS_BODY: '' - -jobs: - update-submodule: - permissions: write-all - runs-on: ubuntu-latest - - steps: - - name: Setup github SSH for UEPseudo - uses: shimataro/ssh-key-action@v2 - with: - key: ${{ secrets.UEPSEUDO_SSH_KEY }} - known_hosts: unnecessary - - - name: Checkout - uses: actions/checkout@v4 - - - name: Initialize submodule - run: | - git submodule update --init --recursive - - - name: Get commits between HEAD and main in the submodule - id: submodule-commits - run: | - cd ./deps/first/Unreal - git fetch origin main - git log HEAD..main --pretty="tformat:* %s (**%an**) _%h_" >> submodule-commits.txt - body=$(cat submodule-commits.txt) - body="${body//'%'/'%25'}" - body="${body//$'\n'/'%0A'}" - body="${body//$'\r'/'%0D'}" - echo "COMMITS_BODY=$body" >> $GITHUB_ENV - - - name: Update submodule to latest commit on main branch - run: | - cd ./deps/first/Unreal - git checkout main - git pull origin main - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 - with: - commit-message: Update UE Submodule - committer: GitHub - author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> - title: Update UE Submodule - body: ${{ env.COMMITS_BODY }} - branch: update-ue-submodule - base: main \ No newline at end of file diff --git a/.github/workflows/experimental.yml b/.github/workflows/experimental.yml deleted file mode 100644 index e1f735122..000000000 --- a/.github/workflows/experimental.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Make Experimental Release - -on: - workflow_dispatch: - push: - branches: [ "main" ] - paths: - - "UE4SS/src/**" - - "UE4SS/include/**" - - "UE4SS/generated_src/**" - - "UE4SS/generated_include/**" - - "deps/**" - - "UE4SS/proxy_generator/**" - -permissions: - contents: read - -jobs: - make-release: - permissions: write-all - runs-on: windows-2022 - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 # needed to get commits since last tag - token: ${{ secrets.UEPSEUDO_PAT }} - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Setup MSVC - uses: ilammy/msvc-dev-cmd@v1 - - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - - - name: Cache - uses: actions/cache@v4 - with: - path: | - .xmake - Binaries - Intermediates - C:/Users/runneradmin/AppData/Local/.xmake - key: ${{ runner.os }}-xmake-${{ hashFiles('**/xmake.lua') }} - - - name: Build - run: | - xmake f -m "Game__Shipping__Win64" -y - xmake build - - - name: Package - run: python tools/buildscripts/build.py package -e - - - name: Release - uses: softprops/action-gh-release@v1 - with: - prerelease: true - tag_name: experimental - body_path: release/release_notes.md - files: | - release/UE4SS_v*.zip - release/zDEV-UE4SS_v*.zip - release/zCustomGameConfigs.zip - release/zMapGenBP.zip diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml new file mode 100644 index 000000000..4f4a3f53d --- /dev/null +++ b/.github/workflows/linux-test.yml @@ -0,0 +1,41 @@ +name: Linux Test Build + +on: + workflow_dispatch: + push: + branches: [ "linux-port" ] + paths: + - "UE4SS/src/**" + - "UE4SS/include/**" + - "UE4SS/generated_src/**" + - "UE4SS/generated_include/**" + - "deps/**" + - "UE4SS/proxy_generator/**" + +permissions: + contents: read + +jobs: + make-release: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 # needed to get commits since last tag + + - name: Setup Ninja + uses: seanmiddleditch/gha-setup-ninja@v3 + + - name: Build + run: | + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 + cmake --build build + - name: Package + run: .github/package.sh + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: Linux-Release + path: package/ diff --git a/.github/workflows/pushdocs.yml b/.github/workflows/pushdocs.yml deleted file mode 100644 index 93a2f66a1..000000000 --- a/.github/workflows/pushdocs.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Deploy docs - -on: - workflow_dispatch: - push: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Setup mdBook - run: | - mkdir mdbook - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.14/mdbook-v0.4.14-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook - echo `pwd`/mdbook >> $GITHUB_PATH - - - name: Build - run: | - python docs-export/export.py - python docs-repo/build.py - - - uses: actions/upload-pages-artifact@v1 - with: - path: docs-repo/docs - deploy: - needs: build - - permissions: - pages: write - id-token: write - - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - - runs-on: ubuntu-latest - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 52b74a758..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Make Release -on: workflow_dispatch - -permissions: - contents: read - -jobs: - make-release: - permissions: write-all - runs-on: windows-2022 - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 # needed to get commits since last tag - token: ${{ secrets.UEPSEUDO_PAT }} - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Setup MSVC - uses: ilammy/msvc-dev-cmd@v1 - - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - - - name: Release Commit - id: release_commit - run: python build.py release_commit ${{ github.actor }} - working-directory: ./tools/buildscripts - - - name: Cache - uses: actions/cache@v4 - with: - path: | - .xmake - Binaries - Intermediates - C:/Users/runneradmin/AppData/Local/.xmake - key: ${{ runner.os }}-xmake-${{ hashFiles('**/xmake.lua') }} - - - name: Build - run: | - xmake f -m "Game__Shipping__Win64" -y - xmake build - - - name: Package - run: python tools/buildscripts/build.py package - - - name: Push changes - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: ${{ github.ref }} - tags: true - - - name: Release - uses: softprops/action-gh-release@v1 - with: - tag_name: ${{ steps.release_commit.outputs.release_tag }} - body_path: release/release_notes.md - files: | - release/UE4SS_v*.zip - release/zDEV-UE4SS_v*.zip - release/zCustomGameConfigs.zip - release/zMapGenBP.zip From 03ab5113baa109f66186a4afb62a5afae8f337fe Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 01:43:40 -0600 Subject: [PATCH 025/213] fix indent --- .github/workflows/linux-test.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 4f4a3f53d..76b1486ed 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -24,17 +24,15 @@ jobs: with: submodules: recursive fetch-depth: 0 # needed to get commits since last tag - - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@v3 - - name: Build run: | cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 cmake --build build - - name: Package + - name: Package run: .github/package.sh - - name: Upload Artifacts + - name: Upload Artifacts uses: actions/upload-artifact@v3 with: name: Linux-Release From 4e72e8777cb004bc758028b36c243901b7d84ff1 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 01:45:38 -0600 Subject: [PATCH 026/213] trigger it --- .github/workflows/linux-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 76b1486ed..1cd0182c6 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -11,6 +11,7 @@ on: - "UE4SS/generated_include/**" - "deps/**" - "UE4SS/proxy_generator/**" + - ".github/**" permissions: contents: read From 12b68b54d2d1c2eaf2400443653d2821a4de8cd8 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 01:47:32 -0600 Subject: [PATCH 027/213] change remote to allow ci build(?) --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index ce01d3b56..027e91abf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "deps/first/Unreal"] path = deps/first/Unreal - url = git@github.com:Re-UE4SS/UEPseudo.git + url = git@github.com:Yangff/UEPseudo.git [submodule "deps/first/patternsleuth"] path = deps/first/patternsleuth - url = git@github.com:trumank/patternsleuth.git + url = git@github.com:Yangff/patternsleuth.git From e8b842936b2918d061714afad3183f0293224256 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 01:55:49 -0600 Subject: [PATCH 028/213] use ssh key --- .github/workflows/linux-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 1cd0182c6..c7f2e8a7a 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -23,6 +23,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: + key: ${{ secrets.SSHKEY }} submodules: recursive fetch-depth: 0 # needed to get commits since last tag - name: Setup Ninja From 45f28bb0d227377f7e016b32b25ffee7caa03922 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 01:57:03 -0600 Subject: [PATCH 029/213] ty fix checkout --- .github/workflows/linux-test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index c7f2e8a7a..ba60eaf77 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -20,10 +20,14 @@ jobs: make-release: runs-on: ubuntu-22.04 steps: + - name: Setup github SSH + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSHKEY }} + known_hosts: unnecessary - name: Checkout uses: actions/checkout@v4 with: - key: ${{ secrets.SSHKEY }} submodules: recursive fetch-depth: 0 # needed to get commits since last tag - name: Setup Ninja From 90cab979ef8663f8a4d9702c0936c8704012118f Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 01:57:41 -0600 Subject: [PATCH 030/213] key again? --- .github/workflows/linux-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index ba60eaf77..eed8645f4 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -30,6 +30,7 @@ jobs: with: submodules: recursive fetch-depth: 0 # needed to get commits since last tag + ssh-key: ${{ secrets.SSHKEY }} - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@v3 - name: Build From c339371a09407e71dd301e450aad3031a23b3859 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 02:06:17 -0600 Subject: [PATCH 031/213] setup clang and rust --- .github/workflows/linux-test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index eed8645f4..0ca44ae9c 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -33,6 +33,12 @@ jobs: ssh-key: ${{ secrets.SSHKEY }} - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@v3 + - name: Set up Clang + uses: egor-tensin/setup-clang@v1 + with: + version: 15 + platform: x64 + - uses: dtolnay/rust-toolchain@1.77.0 - name: Build run: | cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 From 040eed6fe04e630c05141bbfc79fa6811bc35219 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 02:10:18 -0600 Subject: [PATCH 032/213] modify ver --- .github/workflows/linux-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 0ca44ae9c..a5a24cc14 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -38,7 +38,7 @@ jobs: with: version: 15 platform: x64 - - uses: dtolnay/rust-toolchain@1.77.0 + - uses: dtolnay/rust-toolchain@1.76.0 - name: Build run: | cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 From aedb6075095dac323fb4a5a0f9ef9f0e893c0e30 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 02:11:38 -0600 Subject: [PATCH 033/213] should be Game__Shipping__Linux --- .github/workflows/linux-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index a5a24cc14..0fa73f880 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -41,7 +41,7 @@ jobs: - uses: dtolnay/rust-toolchain@1.76.0 - name: Build run: | - cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Linux cmake --build build - name: Package run: .github/package.sh From 7ec574ed628970902404df484286be3cae7630e8 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 02:18:10 -0600 Subject: [PATCH 034/213] can we get clang 16? --- .github/workflows/linux-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 0fa73f880..d46480b1b 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -34,9 +34,9 @@ jobs: - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@v3 - name: Set up Clang - uses: egor-tensin/setup-clang@v1 + uses: Totto16/setup-clang@v1 with: - version: 15 + version: 16 platform: x64 - uses: dtolnay/rust-toolchain@1.76.0 - name: Build From 98746cc45889f89045c3bfb052cc72f19329ed20 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 02:22:57 -0600 Subject: [PATCH 035/213] try this action? --- .github/workflows/linux-test.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index d46480b1b..e9be588e6 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -34,10 +34,12 @@ jobs: - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@v3 - name: Set up Clang - uses: Totto16/setup-clang@v1 + uses: KyleMayes/install-llvm-action@v1 with: - version: 16 + version: "16.0" platform: x64 + env: true + ubuntu-version: 22.04 - uses: dtolnay/rust-toolchain@1.76.0 - name: Build run: | From 00a066da9388cd4903f42388034bc50d7f002663 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 03:00:04 -0600 Subject: [PATCH 036/213] trg ci --- .github/workflows/linux-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index e9be588e6..ec140005b 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -12,6 +12,7 @@ on: - "deps/**" - "UE4SS/proxy_generator/**" - ".github/**" + - "CMakeLists.txt" permissions: contents: read From 2f21e1379bc7ac5e5037187056eaed547596b730 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 16 Feb 2024 03:12:04 -0600 Subject: [PATCH 037/213] fix path --- .github/package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/package.sh b/.github/package.sh index 6c97beebf..45915b638 100755 --- a/.github/package.sh +++ b/.github/package.sh @@ -1,4 +1,4 @@ #!/bin/bash mkdir package -cp build/Output/Game__Shipping__Linux/libUE4SS.so package +cp build/Output/Game__Shipping__Linux/UE4SS/bin/libUE4SS.so package cp assets/UE4SS-settings.ini package From 34f1c1bb4e198c5be5b6539ce8b98e4255abe8e4 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 17 Feb 2024 01:22:41 -0600 Subject: [PATCH 038/213] setup sccache --- .github/workflows/linux-test.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index ec140005b..e5e98c5dc 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -41,11 +41,17 @@ jobs: platform: x64 env: true ubuntu-version: 22.04 - - uses: dtolnay/rust-toolchain@1.76.0 + - name: Setup Rust + uses: dtolnay/rust-toolchain@1.76.0 + - name: Run sccache-cache + uses: mozilla-actions/sccache-action@v0.0.3 - name: Build run: | - cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Linux + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Linux -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache cmake --build build + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" - name: Package run: .github/package.sh - name: Upload Artifacts From 51d0b9b8c116d6fee98054f82b57e9932e8b5291 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 17 Feb 2024 04:42:06 -0600 Subject: [PATCH 039/213] make m_mods a member variable --- UE4SS/include/UE4SSProgram.hpp | 4 ++-- UE4SS/src/UE4SSProgram.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index d200cc265..40e1ae320 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -169,9 +169,9 @@ namespace RC #endif public: - static inline std::vector> m_mods; + std::vector> m_mods; - static inline RecognizableStruct m_shared_functions{}; + RecognizableStruct m_shared_functions{}; static inline UE4SSProgram* s_program{}; diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 2e47dcabb..4a3dc264b 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1108,13 +1108,13 @@ namespace RC auto UE4SSProgram::install_cpp_mods() -> void { #ifdef HAS_CPPMOD - install_mods(m_mods); + install_mods(get_program().m_mods); #endif } auto UE4SSProgram::install_lua_mods() -> void { - install_mods(m_mods); + install_mods(get_program().m_mods); } auto UE4SSProgram::fire_unreal_init_for_cpp_mods() -> void @@ -1593,7 +1593,7 @@ namespace RC auto UE4SSProgram::find_mod_by_name_internal(SystemStringViewType mod_name, IsInstalled is_installed, IsStarted is_started, FMBNI_ExtraPredicate extra_predicate) -> Mod* { - auto mod_exists_with_name = std::find_if(m_mods.begin(), m_mods.end(), [&](auto& elem) -> bool { + auto mod_exists_with_name = std::find_if(get_program().m_mods.begin(), get_program().m_mods.end(), [&](auto& elem) -> bool { bool found = true; if (!extra_predicate(elem.get())) @@ -1617,7 +1617,7 @@ namespace RC }); // clang-format off - if (mod_exists_with_name == m_mods.end()) + if (mod_exists_with_name == get_program().m_mods.end()) { return nullptr; } From c2ce4f942985e82547f26adcc72dd3c3d62645fe Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 17 Feb 2024 18:47:35 -0600 Subject: [PATCH 040/213] fix headergen --- scripts/HeaderGen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 4169ec22b..8a8835a8b 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -16,9 +16,9 @@ }} """ -MEMBER_TEMPLATE = """if (auto it = {ClassName}::MemberOffsets.find(STR("{MemberName}")); it == {ClassName}::MemberOffsets.end()) +MEMBER_TEMPLATE = """if (auto it = {ClassName}::MemberOffsets.find(SYSSTR("{MemberName}")); it == {ClassName}::MemberOffsets.end()) {{ - {ClassName}::MemberOffsets.emplace(STR("{MemberName}"), 0x{MemberOffset:02x}); + {ClassName}::MemberOffsets.emplace(SYSSTR("{MemberName}"), 0x{MemberOffset:02x}); }} """ From 978d25472325307c6937255b72f77714155e25fe Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 18 Feb 2024 16:42:49 -0600 Subject: [PATCH 041/213] more fix on cxa_throw --- UE4SS/src/EntryLinux.cpp | 111 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 7bb0771bc..0d9def9fb 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -96,6 +96,18 @@ int hooked_main(int argc, char **argv, char **envp) { extern char **environ; extern "C" { + +struct link_map_private { + Elf64_Addr l_addr; + char *l_name; + Elf64_Dyn *l_ld; + struct link_map_private *l_next, *l_prev; + struct link_map_private *l_real; + Lmid_t l_ns; + struct libname_list *l_libname; + Elf64_Dyn *l_info[DT_NUM + 0 + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM]; +}; + int __libc_start_main( int (*main)(int, char **, char **), int argc, @@ -111,7 +123,6 @@ int __libc_start_main( Dl_info dl_info; Elf64_Sym *sym; // libsteam_api is okay, the UE engine is causing problem - void *current___cxa_throw = dlsym(RTLD_DEFAULT, "__cxa_throw"); dladdr1(current___cxa_throw, &dl_info, (void**) &sym, RTLD_DL_SYMENT); fprintf(stderr, "__cxa_throw found in %s @ %p\n", dl_info.dli_fname, current___cxa_throw); @@ -121,7 +132,105 @@ int __libc_start_main( sym->st_info = ELF64_ST_INFO(STB_LOCAL, ELF64_ST_TYPE(sym->st_info)); sym->st_other = STV_INTERNAL; // assume this is UE5's address range and remove this symbol + void *working___cxa_throw = dlsym(RTLD_DEFAULT, "__cxa_throw"); + struct link_map_private* map1; + dladdr1(working___cxa_throw, &dl_info, (void**) &map1, RTLD_DL_SYMENT); + fprintf(stderr, "now we're using __cxa_throw from %s @ %p\n", dl_info.dli_fname, working___cxa_throw); + + struct data_encap { + void *working___cxa_throw; + void *current___cxa_throw; + } data = {working___cxa_throw, current___cxa_throw}; + dl_iterate_phdr([](struct dl_phdr_info *info, size_t size, void *data) -> int { + auto working___cxa_throw = ((struct data_encap*)data)->working___cxa_throw; + auto current___cxa_throw = ((struct data_encap*)data)->current___cxa_throw; + fprintf(stderr, "Examing %s @ %p... \n", info->dlpi_name, info->dlpi_addr); + // skip vdso + if (strstr(info->dlpi_name, "vdso") != nullptr) { + fprintf(stderr, " Skipping %s\n", info->dlpi_name); + return 0; + } + // get dynamic + Elf64_Dyn *dyn = nullptr; + for (int i = 0; i < info->dlpi_phnum; i++) { + if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) { + dyn = (Elf64_Dyn *)(info->dlpi_phdr[i].p_vaddr + info->dlpi_addr); + } + } + + // iterate dynamic, find .plt.got + struct RELA_INFOS { + Elf64_Rela *rela; + ssize_t sz; + } rela_infos[2] = {}; + // symbol table + Elf64_Sym *sym = nullptr; + // string table + char *strtab = nullptr; + for (int i = 0; dyn[i].d_tag != DT_NULL; i++) { + // DT_JMPREL + if (dyn[i].d_tag == DT_JMPREL) { + rela_infos[0].rela = (Elf64_Rela *)(dyn[i].d_un.d_ptr); + } + if (dyn[i].d_tag == DT_RELA) { + rela_infos[1].rela = (Elf64_Rela *)(dyn[i].d_un.d_ptr); + } + // DT_SYMTAB + if (dyn[i].d_tag == DT_SYMTAB) { + sym = (Elf64_Sym *)(dyn[i].d_un.d_ptr); + } + // DT_STRTAB + if (dyn[i].d_tag == DT_STRTAB) { + strtab = (char *)(dyn[i].d_un.d_ptr); + } + // DT_PLTRELSZ + if (dyn[i].d_tag == DT_PLTRELSZ) { + rela_infos[0].sz = dyn[i].d_un.d_val; + } + // DT_RELASZ + if (dyn[i].d_tag == DT_RELASZ) { + rela_infos[1].sz = dyn[i].d_un.d_val; + } + } + if (sym == nullptr || strtab == nullptr) { + fprintf(stderr, " No sym or strtab found %p %p\n", sym, strtab); + return 0; + } + if ((rela_infos[0].rela == nullptr) && (rela_infos[1].rela == nullptr)) { + fprintf(stderr, " No rela found %p %p\n", rela_infos[0].rela, rela_infos[1].rela); + return 0; + } + auto process_rela = [&] (Elf64_Rela *rela, ssize_t sz, Elf64_Sym *sym, char *strtab) { + fprintf(stderr, " Found rela @ %p, sym @ %p, strtab @ %p\n", rela, sym, strtab); + for (int i = 0; i < sz / sizeof(Elf64_Rela); i++) { + if (sym[ELF64_R_SYM(rela[i].r_info)].st_name != 0) { + char *name = strtab + sym[ELF64_R_SYM(rela[i].r_info)].st_name; + if (strncmp(name, "__cxa_throw", 11) == 0) { + fprintf(stderr, " Found __cxa_throw symbol @ %p\n", rela[i].r_offset); + } else { + continue; + } + // got table address + unsigned long* address = (unsigned long *)(rela[i].r_offset + info->dlpi_addr); + if (*address == (unsigned long)current___cxa_throw) { + fprintf(stderr, " Found __cxa_throw in .plt.got @ %p, offset = %d\n", address, rela[i].r_offset); + mprotect((void*)ALIGN_DOWN_PAGE(address), ALIGN_UP_PAGE(address + 1) - ALIGN_DOWN_PAGE(address), PROT_READ | PROT_WRITE); + *address = (unsigned long)working___cxa_throw; + fprintf(stderr, " Patched __cxa_throw to @ %p\n", working___cxa_throw); + } + } + } + }; + for (int i = 0; i < 2; i++) { + if (rela_infos[i].rela != nullptr) { + process_rela(rela_infos[i].rela, rela_infos[i].sz, sym, strtab); + } + } + return 0; + }, &data); + } + // remove LD_PRELOAD from environ int nenv = 0; for (int i = 0; environ[i]; i++) From 791929f5ae802941896fde382276ee53d416c731 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 18 Feb 2024 16:43:32 -0600 Subject: [PATCH 042/213] fix comment --- UE4SS/src/EntryLinux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 0d9def9fb..15cdce759 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -158,7 +158,7 @@ int __libc_start_main( } } - // iterate dynamic, find .plt.got + // iterate dynamic, find relocation to __cxa_throw struct RELA_INFOS { Elf64_Rela *rela; ssize_t sz; From 21229976b5c829a2c2c60f9d7951a72551ad7acf Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 18 Feb 2024 19:37:18 -0600 Subject: [PATCH 043/213] fixup rebase --- UE4SS/include/Mod/LuaMod.hpp | 4 ++-- UE4SS/src/Mod/LuaMod.cpp | 4 +++- deps/first/ASMHelper/src/ASMHelper.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/UE4SS/include/Mod/LuaMod.hpp b/UE4SS/include/Mod/LuaMod.hpp index 861acdb72..029e94987 100644 --- a/UE4SS/include/Mod/LuaMod.hpp +++ b/UE4SS/include/Mod/LuaMod.hpp @@ -101,8 +101,8 @@ namespace RC static inline std::unordered_map m_custom_command_lua_pre_callbacks; static inline std::vector m_game_thread_actions{}; // This is storage that persists through hot-reloads. - static inline std::unordered_map m_shared_lua_variables{}; - static inline std::unordered_map m_custom_event_callbacks{}; + static inline std::unordered_map m_shared_lua_variables{}; + static inline std::unordered_map m_custom_event_callbacks{}; static inline std::vector m_load_map_pre_callbacks{}; static inline std::vector m_load_map_post_callbacks{}; static inline std::vector m_init_game_state_pre_callbacks{}; diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 36cc54491..df0906a44 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -26,12 +26,14 @@ #include #include #include +#include + #ifdef HAS_CPPMOD -#include #include #endif + #include #pragma warning(disable : 4005) #include diff --git a/deps/first/ASMHelper/src/ASMHelper.cpp b/deps/first/ASMHelper/src/ASMHelper.cpp index 2f1a3a6b2..8633dec55 100644 --- a/deps/first/ASMHelper/src/ASMHelper.cpp +++ b/deps/first/ASMHelper/src/ASMHelper.cpp @@ -8,7 +8,7 @@ namespace RC::ASM { - auto get_first_instruction_at_address(void* in_instruction_ptr) -> std::pair> + auto get_first_instruction_at_address(void* in_instruction_ptr) -> Instruction { auto instruction_ptr = static_cast(in_instruction_ptr); ZydisDecoder decoder{}; @@ -25,9 +25,9 @@ namespace RC::ASM auto resolve_absolute_address(void* in_instruction_ptr) -> void* { - auto [instruction, operands] = get_first_instruction_at_address(in_instruction_ptr); + auto instruction = get_first_instruction_at_address(in_instruction_ptr); ZyanU64 resolved_address{}; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&instruction.raw, &operands[0], std::bit_cast(in_instruction_ptr), &resolved_address))) + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&instruction.raw, &instruction.operands[0], std::bit_cast(in_instruction_ptr), &resolved_address))) { return std::bit_cast(resolved_address); } @@ -49,7 +49,7 @@ namespace RC::ASM auto resolve_function_address_from_potential_jmp(void* function_ptr) -> void* { - auto [instruction, _] = get_first_instruction_at_address(function_ptr); + auto instruction = get_first_instruction_at_address(function_ptr); if (instruction.raw.mnemonic == ZYDIS_MNEMONIC_JMP || instruction.raw.mnemonic == ZYDIS_MNEMONIC_CALL) { if (auto resolved_address = resolve_jmp(instruction.address); resolved_address) From 22757df3d566760f48e9134c9c0ac5c240f6d6b4 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 18 Feb 2024 19:47:06 -0600 Subject: [PATCH 044/213] resolved more conflicts --- UE4SS/src/Mod/LuaMod.cpp | 3 ++- UE4SS/src/UE4SSProgram.cpp | 7 ------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index df0906a44..33715b244 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -3048,7 +3048,8 @@ No overload found for function 'RegisterHook'. { ++m_last_generic_hook_id; auto [callback_data, _] = LuaMod::m_script_hook_callbacks.emplace(UEStringToSystemString(unreal_function->GetFullName()), LuaCallbackData{lua, nullptr, {}}); - callback_data->second.registry_indexes.emplace_back(LuaMod::LuaCallbackData::RegistryIndex{lua_callback_registry_index, m_last_generic_hook_id}); + callback_data->second.registry_indexes.emplace_back(hook_lua, + LuaMod::LuaCallbackData::RegistryIndex{lua_callback_registry_index, m_last_generic_hook_id}); generic_pre_id = m_last_generic_hook_id; generic_post_id = m_last_generic_hook_id; Output::send(SYSSTR("[RegisterHook] Registered script hook ({}, {}) for {}\n"), diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 4a3dc264b..9bab1e791 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -653,13 +653,6 @@ namespace RC Unreal::UEngine::VTableLayoutMap.emplace(item_ue, offset); }); - Output::send(SYSSTR("UEngine\n")); - uint32_t uengine_size = retrieve_vtable_layout_from_ini(SYSSTR("UEngine"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { - uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size); - Output::send(SYSSTR("UEngine::{} = 0x{:X}\n"), item, offset); - Unreal::UEngine::VTableLayoutMap.emplace(item_ue, offset); - }); - Output::send(SYSSTR("UScriptStruct::ICppStructOps\n")); retrieve_vtable_layout_from_ini(SYSSTR("UScriptStruct::ICppStructOps"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { uint32_t offset = calculate_virtual_function_offset(index, 0); From 7f4dd82c0540b8a23cc3167dadfe8cc310ef2a21 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 18 Feb 2024 21:15:19 -0600 Subject: [PATCH 045/213] avoid appending on existing file --- deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp index a212e4080..28b2d3bb2 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp @@ -57,7 +57,7 @@ namespace RC::Output { if (m_always_create_file) { - m_file = File::open(m_file_name_and_path, File::OpenFor::Appending, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); + m_file = File::open(m_file_name_and_path, File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); } else { From 6f6d38f2da2fe8119515a768af0436ba6029d90b Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 19 Feb 2024 04:31:17 -0600 Subject: [PATCH 046/213] new string handling and ... maybe no need for fmt? --- UE4SS/include/ExceptionHandling.hpp | 2 +- UE4SS/include/LuaType/LuaUObject.hpp | 16 +- UE4SS/include/UE4SSProgram.hpp | 4 +- UE4SS/src/EntryLinux.cpp | 4 +- UE4SS/src/GUI/BPMods.cpp | 2 +- UE4SS/src/GUI/GUI.cpp | 2 +- UE4SS/src/GUI/UFunctionCallerWidget.cpp | 4 +- UE4SS/src/LuaLibrary.cpp | 2 +- UE4SS/src/LuaType/LuaFName.cpp | 4 +- UE4SS/src/LuaType/LuaFOutputDevice.cpp | 2 +- UE4SS/src/LuaType/LuaFText.cpp | 4 +- UE4SS/src/LuaType/LuaTArray.cpp | 2 +- UE4SS/src/LuaType/LuaUEnum.cpp | 6 +- UE4SS/src/LuaType/LuaUObject.cpp | 4 +- UE4SS/src/LuaType/LuaUScriptStruct.cpp | 2 +- UE4SS/src/LuaType/LuaXProperty.cpp | 6 +- UE4SS/src/Mod/CppMod.cpp | 4 +- UE4SS/src/Mod/LuaMod.cpp | 102 ++++--- UE4SS/src/Mod/Mod.cpp | 1 - UE4SS/src/ObjectDumper/ObjectToString.cpp | 10 +- UE4SS/src/SDKGenerator/Common.cpp | 49 ++-- UE4SS/src/SDKGenerator/Generator.cpp | 38 +-- UE4SS/src/SDKGenerator/JSONDumper.cpp | 18 +- UE4SS/src/SDKGenerator/TMapOverrideGen.cpp | 8 +- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 167 ++++++------ UE4SS/src/UE4SSProgram.cpp | 19 +- .../include/DynamicOutput/Output.hpp | 56 ++-- deps/first/File/include/File/Macros.hpp | 126 +++++---- deps/first/File/src/FileType/WinFile.cpp | 2 +- deps/first/Helpers/include/Helpers/Format.hpp | 87 +----- deps/first/Helpers/include/Helpers/String.hpp | 255 ++++++++++++++++-- .../SigScanner/SinglePassSigScannerWin32.hpp | 2 +- .../src/SinglePassSigScannerWin32.cpp | 4 +- 33 files changed, 591 insertions(+), 423 deletions(-) diff --git a/UE4SS/include/ExceptionHandling.hpp b/UE4SS/include/ExceptionHandling.hpp index 6ab016086..5b9315866 100644 --- a/UE4SS/include/ExceptionHandling.hpp +++ b/UE4SS/include/ExceptionHandling.hpp @@ -8,7 +8,7 @@ #define UE4SS_ERROR_OUTPUTTER() \ if (!Output::has_internal_error()) \ { \ - Output::send(SYSSTR("Error: {}\n"), to_generic_string(e.what())); \ + Output::send(SYSSTR("Error: {}\n"), to_system(e.what())); \ } \ else \ { \ diff --git a/UE4SS/include/LuaType/LuaUObject.hpp b/UE4SS/include/LuaType/LuaUObject.hpp index e92605091..4fcc724c9 100644 --- a/UE4SS/include/LuaType/LuaUObject.hpp +++ b/UE4SS/include/LuaType/LuaUObject.hpp @@ -462,7 +462,7 @@ namespace RC::LuaType { lua.throw_error("Function 'GetProperty' requires a string as the first parameter"); } - SystemStringType property_name = to_generic_string(lua.get_string(2)); + auto property_name = to_system(lua.get_string(2)); auto reflection_table = lua.get_table(); const auto& reflected_object = reflection_table.get_userdata_field("ReflectedObject").get_remote_cpp_object(); @@ -478,7 +478,7 @@ namespace RC::LuaType { obj_as_struct = reflected_object->GetClassPrivate(); } - auto* property = obj_as_struct->FindProperty(Unreal::FName(SystemStringToUEString(property_name))); + auto* property = obj_as_struct->FindProperty(Unreal::FName(to_ue(property_name))); construct_xproperty(lua, property); return 1; @@ -586,7 +586,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. { lua.throw_error(error_overload_not_found); } - auto cmd = to_generic_string(lua.get_string()); + auto cmd = to_system(lua.get_string()); if (lua.get_stack_size() < 2) { @@ -601,7 +601,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. auto executor = lua.get_userdata(); auto ar = Unreal::FOutputDevice{}; - auto return_value = lua_object.get_remote_cpp_object()->ProcessConsoleExec(SystemStringToUEString(cmd).c_str(), ar, executor.get_remote_cpp_object()); + auto return_value = lua_object.get_remote_cpp_object()->ProcessConsoleExec(to_ue_string(cmd).c_str(), ar, executor.get_remote_cpp_object()); lua.set_bool(return_value); return 1; @@ -641,7 +641,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. { auto& lua_object = lua.get_userdata(); - const SystemStringType& member_name = to_generic_string(lua.get_string()); + auto member_name = to_system_string(lua.get_string()); // If nullptr then we assume the UObject wasn't found so lets return an invalid UObject to Lua // This allows the safe chaining of "__index" as long as the Lua script checks ":IsValid()" before using the object @@ -666,7 +666,7 @@ No overload found for function 'UObject.ProcessConsoleExec'. return; } - Unreal::FName property_name = Unreal::FName(SystemStringToUEString(member_name)); + Unreal::FName property_name = Unreal::FName(to_ue(member_name)); Unreal::FField* field = LuaCustomProperty::StaticStorage::property_list.find_or_nullptr(lua_object.get_remote_cpp_object(), member_name); if (!field) @@ -777,10 +777,10 @@ No overload found for function 'UObject.ProcessConsoleExec'. { // We can either throw an error and kill the execution /**/ - SystemStringType property_type_name = UEStringToSystemString(property_type.ToString()); + auto property_type_name = to_string(property_type.ToString()); lua.throw_error(std::format( "[LocalUnrealParam::prepare_to_handle] Tried accessing unreal property without a registered handler. Property type '{}' not supported.", - to_string(property_type_name))); + property_type_name)); //*/ // Or we can treat unhandled property types as some sort of generic type diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index 40e1ae320..60a33b255 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -308,10 +308,10 @@ namespace RC template static auto find_mod_by_name(SystemStringViewType mod_name, IsInstalled is_installed = IsInstalled::No, IsStarted is_started = IsStarted::No) -> T* { - return find_mod_by_name(to_generic_string(mod_name), is_installed, is_started); + return find_mod_by_name(to_system(mod_name), is_installed, is_started); }; - RC_UE4SS_API static auto find_lua_mod_by_name(UEViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; + RC_UE4SS_API static auto find_lua_mod_by_name(UEStringViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; RC_UE4SS_API static auto find_lua_mod_by_name(SystemStringViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; static auto static_cleanup() -> void; RC_UE4SS_API static auto get_program() -> UE4SSProgram& diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 15cdce759..349affc86 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -36,7 +36,7 @@ void UE4SS_Start() fprintf(stderr, "%s\n", e.what()); } #endif - SystemStringType ue4sspath = to_generic_string(dl_info.dli_fname); + auto ue4sspath = to_system_string(dl_info.dli_fname); auto program = new UE4SSProgram(ue4sspath, {}); // use pthread here @@ -50,7 +50,7 @@ void UE4SS_Start() // Logging will only happen to the debug console but it's something at least if (!Output::has_internal_error()) { - Output::send(SYSSTR("Fatal Error: {}\n"), to_generic_string(e->get_message())); + Output::send(SYSSTR("Fatal Error: {}\n"), e->get_message()); } else { diff --git a/UE4SS/src/GUI/BPMods.cpp b/UE4SS/src/GUI/BPMods.cpp index 77061995f..58d13bb3f 100644 --- a/UE4SS/src/GUI/BPMods.cpp +++ b/UE4SS/src/GUI/BPMods.cpp @@ -113,7 +113,7 @@ namespace RC::GUI::BPMods const auto& mod_button = mod_info.ModButtons[i2]; if (ImGui::Button(std::format("{}", mod_button).c_str())) { - Output::send(SYSSTR("Mod button {} hit.\n"), to_generic_string(mod_button)); + Output::send(SYSSTR("Mod button {} hit.\n"), to_system(mod_button)); mod_info.ModActor->ModMenuButtonPressed(static_cast(i2)); } } diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 577a58ad3..f0021d9f2 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -333,7 +333,7 @@ namespace RC::GUI { if (!Output::has_internal_error()) { - Output::send(SYSSTR("Error: {}\n"), to_generic_string(e.what())); + Output::send(SYSSTR("Error: {}\n"), to_system(e.what())); } else { diff --git a/UE4SS/src/GUI/UFunctionCallerWidget.cpp b/UE4SS/src/GUI/UFunctionCallerWidget.cpp index a0528ea79..c2521cadd 100644 --- a/UE4SS/src/GUI/UFunctionCallerWidget.cpp +++ b/UE4SS/src/GUI/UFunctionCallerWidget.cpp @@ -164,7 +164,7 @@ namespace RC::GUI } auto function = m_currently_selected_function->function; - auto cmd = std::format(SYSSTR("{}"), UEStringToSystemString(function->GetName())); + auto cmd = std::format(SYSSTR("{}"), to_system(function->GetName())); for (const auto& param : m_params_for_selected_function) { cmd.append(std::format(SYSSTR(" {}"), to_wstring(param.value_from_ui))); @@ -245,7 +245,7 @@ namespace RC::GUI static auto get_typeless_object_name(UObject* object) -> std::string { - auto object_name = UEStringToSystemString(object->GetFullName()); + auto object_name = to_system(object->GetFullName()); auto object_name_type_space_location = object_name.find(" "); if (object_name_type_space_location == object_name.npos) { diff --git a/UE4SS/src/LuaLibrary.cpp b/UE4SS/src/LuaLibrary.cpp index ec312704e..db8846e4f 100644 --- a/UE4SS/src/LuaLibrary.cpp +++ b/UE4SS/src/LuaLibrary.cpp @@ -102,7 +102,7 @@ namespace RC::LuaLibrary // Logging will only happen to the debug console but it's something at least if (!Output::has_internal_error()) { - Output::send(SYSSTR("Error: {}\n"), to_generic_string(e)); + Output::send(SYSSTR("Error: {}\n"), to_system(e)); } else { diff --git a/UE4SS/src/LuaType/LuaFName.cpp b/UE4SS/src/LuaType/LuaFName.cpp index cc9db044d..9353a175c 100644 --- a/UE4SS/src/LuaType/LuaFName.cpp +++ b/UE4SS/src/LuaType/LuaFName.cpp @@ -64,7 +64,7 @@ No overload found for function 'FName'. Unreal::EFindName find_type{Unreal::EFindName::FNAME_Add}; if (lua.is_string()) { - name_string = to_generic_string(lua.get_string()); + name_string = to_system(lua.get_string()); } else if (lua.is_integer()) { @@ -94,7 +94,7 @@ No overload found for function 'FName'. } else { - LuaType::FName::construct(lua, Unreal::FName(SystemStringToUEString(name_string), find_type)); + LuaType::FName::construct(lua, Unreal::FName(to_ue(name_string), find_type)); } return 1; diff --git a/UE4SS/src/LuaType/LuaFOutputDevice.cpp b/UE4SS/src/LuaType/LuaFOutputDevice.cpp index 32f711ac3..7c8566c17 100644 --- a/UE4SS/src/LuaType/LuaFOutputDevice.cpp +++ b/UE4SS/src/LuaType/LuaFOutputDevice.cpp @@ -65,7 +65,7 @@ No overload found for function 'Log'. } auto message = lua.get_string(); - lua_object.get_remote_cpp_object()->Log(SystemStringToUEString(to_generic_string(message)).c_str()); + lua_object.get_remote_cpp_object()->Log(to_ue(to_system(message)).c_str()); return 0; }); diff --git a/UE4SS/src/LuaType/LuaFText.cpp b/UE4SS/src/LuaType/LuaFText.cpp index 9883b02fb..48a94bb07 100644 --- a/UE4SS/src/LuaType/LuaFText.cpp +++ b/UE4SS/src/LuaType/LuaFText.cpp @@ -61,14 +61,14 @@ No overload found for function 'FText'. SystemStringType text_string{}; if (lua.is_string()) { - text_string = to_generic_string(lua.get_string()); + text_string = to_system(lua.get_string()); } else { lua.throw_error(error_overload_not_found); } - LuaType::FText::construct(lua, Unreal::FText(SystemStringToUEString(text_string))); + LuaType::FText::construct(lua, Unreal::FText(to_ue(text_string))); return 1; }); diff --git a/UE4SS/src/LuaType/LuaTArray.cpp b/UE4SS/src/LuaType/LuaTArray.cpp index 07329d388..2003507e9 100644 --- a/UE4SS/src/LuaType/LuaTArray.cpp +++ b/UE4SS/src/LuaType/LuaTArray.cpp @@ -23,7 +23,7 @@ namespace RC::LuaType if (!lua_object.m_inner_property) { - Output::send(SYSSTR("TArray::construct: m_inner_property is nullptr for {}"), UEStringToSystemString(lua_object.m_property->GetFullName())); + Output::send(SYSSTR("TArray::construct: m_inner_property is nullptr for {}"), to_system(lua_object.m_property->GetFullName())); } auto metatable_name = ClassName::ToString(); diff --git a/UE4SS/src/LuaType/LuaUEnum.cpp b/UE4SS/src/LuaType/LuaUEnum.cpp index e02b10b65..ebe3480b6 100644 --- a/UE4SS/src/LuaType/LuaUEnum.cpp +++ b/UE4SS/src/LuaType/LuaUEnum.cpp @@ -162,7 +162,7 @@ No overload found for function 'UEnum.InsertIntoNames'. // P1 (Name), string if (lua.is_string()) { - param_name = to_generic_string(lua.get_string()); + param_name = to_system(lua.get_string()); } else { @@ -195,7 +195,7 @@ No overload found for function 'UEnum.InsertIntoNames'. param_shift = lua.get_bool(); } - const Unreal::FName key{SystemStringToUEString(param_name), Unreal::FNAME_Add}; + const Unreal::FName key{to_ue(param_name), Unreal::FNAME_Add}; const auto pair = Unreal::TPair{key, param_value}; lua_object.get_remote_cpp_object()->InsertIntoNames(pair, param_index, param_shift); @@ -243,7 +243,7 @@ No overload found for function 'UEnum.EditNameAt'. lua.throw_error("'UEnum.EditNameAt' could not load parameter for \"NewName\""); } - Unreal::FName new_key = Unreal::FName(SystemStringToUEString(to_generic_string(param_new_name)), Unreal::FNAME_Add); + Unreal::FName new_key = Unreal::FName(to_ue(to_system(param_new_name)), Unreal::FNAME_Add); lua_object.get_remote_cpp_object()->EditNameAt(param_index, new_key); return 0; diff --git a/UE4SS/src/LuaType/LuaUObject.cpp b/UE4SS/src/LuaType/LuaUObject.cpp index a6de573d5..71d8ef7e3 100644 --- a/UE4SS/src/LuaType/LuaUObject.cpp +++ b/UE4SS/src/LuaType/LuaUObject.cpp @@ -1107,7 +1107,7 @@ namespace RC::LuaType if (params.lua.is_string()) { auto lua_string = params.lua.get_string(); - auto fstring = Unreal::FString{ SystemStringToUEString(to_generic_string(lua_string)).c_str() }; + auto fstring = Unreal::FString{ to_ue(to_system(lua_string)).c_str() }; *string = fstring; } else if (params.lua.is_userdata()) @@ -1233,7 +1233,7 @@ No overload found for function 'IsA'. } else if (lua.is_string()) { - auto* object_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(to_generic_string(lua.get_string()))); + auto* object_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue(to_system(lua.get_string()))); lua.set_bool(is_a_internal(lua, object, object_class)); } else diff --git a/UE4SS/src/LuaType/LuaUScriptStruct.cpp b/UE4SS/src/LuaType/LuaUScriptStruct.cpp index 0fac2b871..4959d58bb 100644 --- a/UE4SS/src/LuaType/LuaUScriptStruct.cpp +++ b/UE4SS/src/LuaType/LuaUScriptStruct.cpp @@ -196,7 +196,7 @@ namespace RC::LuaType { auto& lua_object = lua.get_userdata(); - Unreal::FName property_name = Unreal::FName(SystemStringToUEString(to_generic_string(lua.get_string()))); + Unreal::FName property_name = Unreal::FName(to_ue(to_system(lua.get_string()))); // Check if property_name is 'NONE' if (property_name.GetComparisonIndex() == 0) diff --git a/UE4SS/src/LuaType/LuaXProperty.cpp b/UE4SS/src/LuaType/LuaXProperty.cpp index 9412b0a60..eb02eacf9 100644 --- a/UE4SS/src/LuaType/LuaXProperty.cpp +++ b/UE4SS/src/LuaType/LuaXProperty.cpp @@ -114,7 +114,7 @@ namespace RC::LuaType if (lua_object.get_remote_cpp_object()) { // Set the return value to the ansi version of the full name - lua.set_string(UEStringToSystemString(lua_object.get_remote_cpp_object()->GetFullName()).c_str()); + lua.set_string(to_system(lua_object.get_remote_cpp_object()->GetFullName()).c_str()); } else { @@ -227,7 +227,7 @@ No overload found for function 'ImportText'. SystemStringType buffer; if (lua.is_string()) { - buffer = to_generic_string(lua.get_string()); + buffer = to_system(lua.get_string()); } else { @@ -261,7 +261,7 @@ No overload found for function 'ImportText'. } auto* owner_object = lua.get_userdata().get_remote_cpp_object(); - lua_object.get_remote_cpp_object()->ImportText(SystemStringToUEString(buffer).c_str(), data, port_flags, owner_object, nullptr); + lua_object.get_remote_cpp_object()->ImportText(to_ue(buffer).c_str(), data, port_flags, owner_object, nullptr); return 0; }); diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index aaad18a72..16f32f508 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -20,7 +20,7 @@ namespace RC if (!std::filesystem::exists(m_dlls_path)) { - Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), to_generic_string(m_mod_name)); + Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), to_system(m_mod_name)); set_installable(false); return; } @@ -70,7 +70,7 @@ namespace RC Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), (std::filesystem::path {m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)).generic_string() + "\n", m_mod_name, - to_generic_string(e.what())); + to_system(e.what())); } else { diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 33715b244..33d81d521 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #ifdef HAS_INPUT @@ -266,8 +265,8 @@ namespace RC // If the type wasn't supported then we simply clean the Lua stack, output a warning and then do nothing lua_data.lua.discard_value(); - auto parameter_type_name = UEStringToSystemString(property_type_name.ToString()); - auto parameter_name = UEStringToSystemString(lua_data.return_property->GetName()); + auto parameter_type_name = to_system(property_type_name.ToString()); + auto parameter_name = to_system(lua_data.return_property->GetName()); Output::send( SYSSTR("Tried altering return value of a hooked UFunction without a registered handler for return type Return property '{}' of type " @@ -875,7 +874,7 @@ No overload found for function 'StaticFindObject'. // Ignores any params after P1 if (lua.is_string()) { - Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(to_generic_string(lua.get_string()))); + Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue(to_system(lua.get_string()))); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe @@ -935,7 +934,7 @@ No overload found for function 'StaticFindObject'. // P3 (Name), string if (lua.is_string()) { - param_name = to_generic_string(lua.get_string()); + param_name = to_system(lua.get_string()); } else { @@ -949,7 +948,7 @@ No overload found for function 'StaticFindObject'. } // There's no error if P4 isn't a bool, simply ignore all parameters after P3 - Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(param_class, param_in_outer, SystemStringToUEString(param_name), param_exact_class); + Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(param_class, param_in_outer, to_ue(param_name), param_exact_class); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe @@ -977,7 +976,7 @@ No overload found for function 'FindFirstOf'. // Ignores any params after P1 if (lua.is_string()) { - Unreal::UObject* object = Unreal::UObjectGlobals::FindFirstOf(SystemStringToUEString(to_generic_string(lua.get_string()))); + Unreal::UObject* object = Unreal::UObjectGlobals::FindFirstOf(to_ue(to_system(lua.get_string()))); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe @@ -1154,7 +1153,7 @@ No overload found for function 'RegisterKeyBindAsync'. } catch (std::runtime_error& e) { - Output::send(SYSSTR("{}\n"), to_generic_string(lua.handle_error(e.what()))); + Output::send(SYSSTR("{}\n"), to_system(lua.handle_error(e.what()))); } }; @@ -1273,7 +1272,7 @@ No overload found for function 'RegisterKeyBind'. } catch (std::runtime_error& e) { - Output::send(SYSSTR("{}\n"), to_generic_string(lua.handle_error(e.what()))); + Output::send(SYSSTR("{}\n"), to_system(lua.handle_error(e.what()))); } }; @@ -1373,8 +1372,8 @@ No overload found for function 'UnregisterHook'. lua.throw_error(error_overload_not_found); } - UEStringType function_name = to_u16string(lua.get_string()); - UEStringType function_name_no_prefix = function_name.substr(function_name.find_first_of(STR(" ")) + 1, function_name.size()); + auto function_name = to_u16string(lua.get_string()); + auto function_name_no_prefix = function_name.substr(function_name.find_first_of(STR(" ")) + 1, function_name.size()); Unreal::UFunction* unreal_function = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, function_name_no_prefix); if (!unreal_function) @@ -1435,7 +1434,7 @@ No overload found for function 'UnregisterHook'. } else { - if (auto callback_data_it = LuaMod::m_script_hook_callbacks.find(UEStringToSystemString(unreal_function->GetFullName())); + if (auto callback_data_it = LuaMod::m_script_hook_callbacks.find(to_system(unreal_function->GetFullName())); callback_data_it != LuaMod::m_script_hook_callbacks.end()) { Output::send(SYSSTR("Unregistering script hook with id: {}\n"), post_id); @@ -1736,12 +1735,12 @@ No overload found for function 'RegisterCustomProperty'. }; // Always required, for all property types - property_info.name = to_generic_string(lua_table.get_string_field("Name")); + property_info.name = to_system(lua_table.get_string_field("Name")); property_info.type.name = lua_table.get_table_field("Type").get_string_field("Name"); property_info.type.size = verify_and_convert_int64_to_int32("Type", "Size"); property_info.type.ffieldclass_pointer = reinterpret_cast(lua_table.get_table_field("Type").get_int_field("FFieldClassPointer")); property_info.type.static_pointer = reinterpret_cast(lua_table.get_table_field("Type").get_int_field("StaticPointer")); - property_info.belongs_to_class = to_generic_string(lua_table.get_string_field("BelongsToClass")); + property_info.belongs_to_class = to_system(lua_table.get_string_field("BelongsToClass")); std::string oi_property_name; int32_t oi_relative_offset{}; @@ -1784,7 +1783,7 @@ No overload found for function 'RegisterCustomProperty'. lua.throw_error("Parameter #1 for function 'RegisterCustomProperty'. The table is missing required fields."); } - Unreal::UClass* belongs_to_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(property_info.belongs_to_class)); + Unreal::UClass* belongs_to_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue(property_info.belongs_to_class)); if (!belongs_to_class) { lua.throw_error("Tried to 'RegisterCustomProperty' but 'BelongsToClass' could not be found"); @@ -1792,7 +1791,7 @@ No overload found for function 'RegisterCustomProperty'. if (property_info.offset_internal_is_table) { - auto name = Unreal::FName(SystemStringToUEString(oi_property_name)); + auto name = Unreal::FName(to_ue(oi_property_name)); Unreal::FProperty* oi_property = belongs_to_class->FindProperty(name); if (!oi_property) { @@ -1888,7 +1887,7 @@ No overload found for function 'NotifyOnNewObject'. lua.throw_error(error_overload_not_found); } - SystemStringType class_name = to_generic_string(lua.get_string()); + auto class_name = to_system(lua.get_string()); if (!lua.is_function()) { @@ -1906,7 +1905,7 @@ No overload found for function 'NotifyOnNewObject'. const auto func_ref = hook_lua->registry().make_ref(); const auto thread_ref = mod->lua().registry().make_ref(); - Unreal::UClass* instance_of_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(class_name)); + Unreal::UClass* instance_of_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue(class_name)); LuaMod::m_static_construct_object_lua_callbacks.emplace_back(LuaMod::LuaCancellableCallbackData{hook_lua, instance_of_class, func_ref, thread_ref}); @@ -1924,7 +1923,7 @@ No overload found for function 'RegisterCustomEvent'. lua.throw_error(error_overload_not_found); } - SystemStringType event_name = to_generic_string(lua.get_string()); + auto event_name = to_system(lua.get_string()); if (!lua.is_function()) { @@ -1960,7 +1959,7 @@ No overload found for function 'UnregisterCustomEvent'. { lua.throw_error(error_overload_not_found); } - auto custom_event_name = to_generic_string(lua.get_string()); + auto custom_event_name = to_system_string(lua.get_string()); LuaMod::m_custom_event_callbacks.erase(custom_event_name); @@ -2504,7 +2503,7 @@ No overload found for function 'RegisterConsoleCommandGlobalHandler'. { throw std::runtime_error{error_overload_not_found}; } - auto command_name = to_generic_string(lua.get_string()); + auto command_name = to_system_string(lua.get_string()); if (!lua.is_function()) { @@ -2539,7 +2538,7 @@ No overload found for function 'RegisterConsoleCommandHandler'. { throw std::runtime_error{error_overload_not_found}; } - auto command_name = to_generic_string(lua.get_string()); + auto command_name = to_system_string(lua.get_string()); if (!lua.is_function()) { @@ -2984,8 +2983,8 @@ No overload found for function 'RegisterHook'. lua.throw_error(error_overload_not_found); } - SystemStringType function_name = to_generic_string(lua.get_string()); - SystemStringType function_name_no_prefix = function_name.substr(function_name.find_first_of(SYSSTR("/")), function_name.size()); + auto function_name = to_system(lua.get_string()); + auto function_name_no_prefix = function_name.substr(function_name.find_first_of(SYSSTR("/")), function_name.size()); if (!lua.is_function()) { @@ -3015,7 +3014,7 @@ No overload found for function 'RegisterHook'. has_post_callback = true; } - Unreal::UFunction* unreal_function = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, SystemStringToUEString(function_name_no_prefix)); + Unreal::UFunction* unreal_function = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue(function_name_no_prefix)); if (!unreal_function) { lua.throw_error("Tried to register a hook with Lua function 'RegisterHook' but no UFunction with the specified name was found."); @@ -3041,13 +3040,13 @@ No overload found for function 'RegisterHook'. Output::send(SYSSTR("[RegisterHook] Registered native hook ({}, {}) for {}\n"), generic_pre_id, generic_post_id, - UEStringToSystemString(unreal_function->GetFullName())); + to_system(unreal_function->GetFullName())); } else if (func_ptr && func_ptr == Unreal::UObject::ProcessInternalInternal.get_function_address() && !unreal_function->HasAnyFunctionFlags(Unreal::EFunctionFlags::FUNC_Native)) { ++m_last_generic_hook_id; - auto [callback_data, _] = LuaMod::m_script_hook_callbacks.emplace(UEStringToSystemString(unreal_function->GetFullName()), LuaCallbackData{lua, nullptr, {}}); + auto [callback_data, _] = LuaMod::m_script_hook_callbacks.emplace(to_system(unreal_function->GetFullName()), LuaCallbackData{lua, nullptr, {}}); callback_data->second.registry_indexes.emplace_back(hook_lua, LuaMod::LuaCallbackData::RegistryIndex{lua_callback_registry_index, m_last_generic_hook_id}); generic_pre_id = m_last_generic_hook_id; @@ -3055,7 +3054,7 @@ No overload found for function 'RegisterHook'. Output::send(SYSSTR("[RegisterHook] Registered script hook ({}, {}) for {}\n"), generic_pre_id, generic_post_id, - UEStringToSystemString(unreal_function->GetFullName())); + to_system(unreal_function->GetFullName())); } else { @@ -3267,8 +3266,8 @@ No overload found for function 'FPackageName:IsShortPackageName'. { lua.throw_error(error_overload_not_found); } - auto local_str = SystemStringToUEString(to_generic_string(lua.get_string())); - UEViewType PossiblyLongName = local_str; + auto local_str = to_ue(lua.get_string()); + UEStringViewType PossiblyLongName = local_str; lua.set_bool(Unreal::FPackageName::IsShortPackageName(PossiblyLongName)); return 1; @@ -3284,8 +3283,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. { lua.throw_error(error_overload_not_found); } - auto local_str = SystemStringToUEString(to_generic_string(lua.get_string())); - UEViewType InLongPackageName = local_str; + auto local_str = to_ue(lua.get_string()); + UEStringViewType InLongPackageName = local_str; lua.set_bool(Unreal::FPackageName::IsValidLongPackageName(InLongPackageName)); return 1; @@ -3396,7 +3395,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - Output::send(SYSSTR("{}\n"), to_generic_string(e.what())); + Output::send(SYSSTR("{}\n"), to_system(e.what())); } } @@ -3436,8 +3435,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. std::erase_if(g_hooked_script_function_data, [&](std::unique_ptr& item) -> bool { if (item->mod == this) { - Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), UEStringToSystemString(item->unreal_function->GetName()), item->pre_callback_id, item->mod->get_name()); - Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), UEStringToSystemString(item->unreal_function->GetName()), item->post_callback_id, item->mod->get_name()); + Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), to_system(item->unreal_function->GetName()), item->pre_callback_id, item->mod->get_name()); + Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), to_system(item->unreal_function->GetName()), item->post_callback_id, item->mod->get_name()); item->unreal_function->UnregisterHook(item->pre_callback_id); item->unreal_function->UnregisterHook(item->post_callback_id); return true; @@ -3498,7 +3497,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. { return; } - if (auto it = callback_container.find(precise_name_match ? UEStringToSystemString(Stack.Node()->GetFullName()) : UEStringToSystemString(Stack.Node()->GetName())); it != callback_container.end()) + if (auto it = callback_container.find(precise_name_match ? to_system(Stack.Node()->GetFullName()) : to_system(Stack.Node()->GetName())); it != callback_container.end()) { const auto& callback_data = it->second; for (const auto& [lua_ptr, registry_index] : callback_data.registry_indexes) @@ -3592,13 +3591,10 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } else { - SystemStringType return_property_type_name = UEStringToSystemString(return_property_type.ToString()); - SystemStringType return_property_name = UEStringToSystemString(return_property->GetName()); - Output::send(SYSSTR("Tried altering return value of a custom BP function without a registered handler for return type Return " "property '{}' of type '{}' not supported."), - return_property_name, - return_property_type_name); + return_property->GetName(), + return_property_type.ToString()); } } } @@ -3807,7 +3803,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - Output::send(SYSSTR("{}\n"), to_generic_string(e.what())); + Output::send(SYSSTR("{}\n"), to_system(e.what())); } if (cancel) @@ -4049,26 +4045,26 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. ar.Log((const RC::Unreal::TCHAR*) log_message.c_str()); }; - if (!LuaStatics::console_executor_enabled && String::iequal(UEViewType{(UECharType*)cmd}, STR("luastart"))) + if (!LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luastart"))) { start_console_lua_executor(); logln(SYSSTR("Console Lua executor started")); return true; } - else if (LuaStatics::console_executor_enabled && String::iequal(UEViewType{(UECharType*)cmd}, STR("luastop"))) + else if (LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luastop"))) { stop_console_lua_executor(); logln(SYSSTR("Console Lua executor stopped")); return true; } - else if (LuaStatics::console_executor_enabled && String::iequal(UEViewType{(UECharType*)cmd}, STR("luarestart"))) + else if (LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luarestart"))) { stop_console_lua_executor(); start_console_lua_executor(); logln(SYSSTR("Console Lua executor restarted")); return true; } - else if (String::iequal(UEViewType{(UECharType*)cmd}, STR("clear"))) + else if (String::iequal(UEStringViewType{(UECharType*)cmd}, STR("clear"))) { // TODO: Replace with proper implementation when we have UGameViewportClient and UConsole. // This should be fairly cross-game & cross-engine-version compatible even without the proper implementation. @@ -4110,7 +4106,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - logln(to_generic_string(e.what())); + logln(to_system(e.what())); } // We always return true when the console Lua executor is enabled in order to suppress other handlers @@ -4126,7 +4122,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. Unreal::Hook::RegisterProcessConsoleExecGlobalPreCallback( [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { return TRY([&] { - auto command = UEViewType{(const UECharType*) cmd}; + auto command = UEStringViewType{(const UECharType*) cmd}; auto command_parts = explode_by_occurrence((const UECharType*) cmd, ' '); for (const auto& callback_data : m_process_console_exec_pre_callbacks) @@ -4182,7 +4178,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. Unreal::Hook::RegisterProcessConsoleExecGlobalPostCallback( [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { return TRY([&] { - auto command = UEViewType {(const UECharType*) cmd}; + auto command = UEStringViewType {(const UECharType*) cmd}; auto command_parts = explode_by_occurrence((const UECharType*)cmd, ' '); for (const auto& callback_data : m_process_console_exec_post_callbacks) @@ -4244,7 +4240,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } return TRY([&] { - auto command = UEStringToSystemString(cmd); + auto command = to_system(cmd); auto command_parts = explode_by_occurrence(command, ' '); SystemStringType command_name; if (command_parts.size() > 1) @@ -4304,7 +4300,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. (void)executor; return TRY([&] { - auto command = UEStringToSystemString(cmd); + auto command = to_system(cmd); auto command_parts = explode_by_occurrence(command, ' '); SystemStringType command_name; if (command_parts.size() > 1) @@ -4424,8 +4420,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. catch (std::runtime_error& e) { Output::send(SYSSTR("[{}] {}\n"), - to_generic_string(action.type == LuaMod::ActionType::Loop ? SYSSTR("LoopAsync") : SYSSTR("DelayedAction")), - to_generic_string(e.what())); + to_system(action.type == LuaMod::ActionType::Loop ? SYSSTR("LoopAsync") : SYSSTR("DelayedAction")), + to_system(e.what())); } return result; diff --git a/UE4SS/src/Mod/Mod.cpp b/UE4SS/src/Mod/Mod.cpp index b0cab8e7e..933c04107 100644 --- a/UE4SS/src/Mod/Mod.cpp +++ b/UE4SS/src/Mod/Mod.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include diff --git a/UE4SS/src/ObjectDumper/ObjectToString.cpp b/UE4SS/src/ObjectDumper/ObjectToString.cpp index 3d0ff774d..687e1da67 100644 --- a/UE4SS/src/ObjectDumper/ObjectToString.cpp +++ b/UE4SS/src/ObjectDumper/ObjectToString.cpp @@ -61,7 +61,7 @@ namespace RC::ObjectDumper UObject* p_typed_this = static_cast(p_this); out_line.append(std::format(SYSSTR("[{:016X}] "), reinterpret_cast(p_this))); - out_line.append(UEStringToSystemString(p_typed_this->GetFullName())); + out_line.append(to_system(p_typed_this->GetFullName())); out_line.append(std::format(SYSSTR(" [n: {:X}] [c: {:016X}] [or: {:016X}]"), p_typed_this->GetNamePrivate().GetComparisonIndex(), reinterpret_cast(p_typed_this->GetClassPrivate()), @@ -78,7 +78,7 @@ namespace RC::ObjectDumper FProperty* p_typed_this = static_cast(p_this); out_line.append(std::format(SYSSTR("[{:016X}] "), reinterpret_cast(p_this))); - out_line.append(UEStringToSystemString(p_typed_this->GetFullName())); + out_line.append(to_system(p_typed_this->GetFullName())); out_line.append(std::format(SYSSTR(" [o: {:X}] "), p_typed_this->GetOffset_Internal())); auto property_class = p_typed_this->GetClass(); @@ -127,7 +127,7 @@ namespace RC::ObjectDumper } else { - out_line.append(UEStringToSystemString(array_inner->GetFullName())); + out_line.append(to_system(array_inner->GetFullName())); callable(array_inner); } } @@ -168,7 +168,7 @@ namespace RC::ObjectDumper } else { - out_line.append(UEStringToSystemString(property->GetFullName())); + out_line.append(to_system(property->GetFullName())); callable(property); } }; @@ -261,7 +261,7 @@ namespace RC::ObjectDumper for (auto& Elem : typed_this->ForEachName()) { - out_line.append(std::format(SYSSTR("\n[{:016X}] {} [n: {:X}] [v: {}]"), 0, UEStringToSystemString(Elem.Key.ToString()), Elem.Key.GetComparisonIndex(), Elem.Value)); + out_line.append(std::format(SYSSTR("\n[{:016X}] {} [n: {:X}] [v: {}]"), 0, to_system(Elem.Key.ToString()), Elem.Key.GetComparisonIndex(), Elem.Value)); } } diff --git a/UE4SS/src/SDKGenerator/Common.cpp b/UE4SS/src/SDKGenerator/Common.cpp index 38c26affb..47321eb3c 100644 --- a/UE4SS/src/SDKGenerator/Common.cpp +++ b/UE4SS/src/SDKGenerator/Common.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #pragma warning(default : 4005) #define DELEGATE_SIGNATURE_POSTFIX STR("__DelegateSignature") @@ -57,7 +58,7 @@ namespace RC::UEGenerator result_string.append(SYSSTR("DEPRECATED_")); } - result_string.append(UEStringToSystemString(uclass->GetName())); + result_string.append(to_system(uclass->GetName())); return result_string; } @@ -79,7 +80,7 @@ namespace RC::UEGenerator // Seems to be not needed, because enum objects, unlike classes or structs, retain their normal E prefix // ResultString.append(SYSSTR("E")); - result_string.append(UEStringToSystemString(uenum->GetName())); + result_string.append(to_system(uenum->GetName())); // Namespaced enums need to have ::Type appended for the type if (uenum->GetCppForm() == UEnum::ECppForm::Namespaced && include_type) @@ -94,7 +95,7 @@ namespace RC::UEGenerator SystemStringType result_string; result_string.append(SYSSTR("F")); - result_string.append(UEStringToSystemString(script_struct->GetName())); + result_string.append(to_system(script_struct->GetName())); return result_string; } @@ -124,14 +125,14 @@ namespace RC::UEGenerator auto generate_delegate_name(FProperty* property, const File::StringType& context_name) -> File::StringType { - const SystemStringType property_name = sanitize_property_name(UEStringToSystemString(property->GetName())); + const auto property_name = sanitize_property_name(to_system_string(property->GetName())); return std::format(SYSSTR("F{}{}"), context_name, property_name); } auto generate_property_cxx_name(FProperty* property, bool is_top_level_declaration, UObject* class_context, EnableForwardDeclarations enable_forward_declarations) -> File::StringType { - const SystemStringType field_class_name = UEStringToSystemString(property->GetClass().GetName()); + const auto field_class_name = to_system(property->GetClass().GetName()); // Byte Property if (property->IsA()) @@ -156,7 +157,7 @@ namespace RC::UEGenerator if (uenum == NULL) { - throw std::runtime_error(RC::fmt("EnumProperty %S does not have a valid Enum value", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("EnumProperty {} does not have a valid Enum value", property->GetName())); } const SystemStringType enum_type_name = get_native_enum_name(uenum); @@ -368,7 +369,7 @@ namespace RC::UEGenerator if (script_struct == NULL) { - throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } const SystemStringType native_struct_name = get_native_struct_name(script_struct); @@ -380,7 +381,7 @@ namespace RC::UEGenerator { FDelegateProperty* delegate_property = static_cast(property); - const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); + const auto delegate_type_name = generate_delegate_name(delegate_property, to_system(class_context->GetName())); return delegate_type_name; } @@ -390,7 +391,7 @@ namespace RC::UEGenerator { FMulticastInlineDelegateProperty* delegate_property = static_cast(property); - const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); + const auto delegate_type_name = generate_delegate_name(delegate_property, to_system(class_context->GetName())); return delegate_type_name; } @@ -398,7 +399,7 @@ namespace RC::UEGenerator { FMulticastSparseDelegateProperty* delegate_property = static_cast(property); - const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); + const auto delegate_type_name = generate_delegate_name(delegate_property, to_system(class_context->GetName())); return delegate_type_name; } @@ -406,7 +407,7 @@ namespace RC::UEGenerator if (property->IsA()) { FFieldPathProperty* field_path_property = static_cast(property); - const SystemStringType property_class_name = UEStringToSystemString(field_path_property->GetPropertyClass()->GetName()); + const auto property_class_name = to_system(field_path_property->GetPropertyClass()->GetName()); return std::format(SYSSTR("TFieldPath"), property_class_name); } @@ -478,12 +479,12 @@ namespace RC::UEGenerator { return SYSSTR("FText"); } - throw std::runtime_error(RC::fmt("Unsupported property class " SystemStringPrint, field_class_name.c_str())); + throw std::runtime_error(RC::fmt("Unsupported property class " SystemStringPrint, field_class_name)); } auto generate_property_lua_name(FProperty* property, bool is_top_level_declaration, UObject* class_context) -> File::StringType { - const SystemStringType field_class_name = UEStringToSystemString(property->GetClass().GetName()); + const auto field_class_name = to_system(property->GetClass().GetName()); // Byte Property if (field_class_name == SYSSTR("ByteProperty")) @@ -508,7 +509,7 @@ namespace RC::UEGenerator if (uenum == NULL) { - throw std::runtime_error(RC::fmt("EnumProperty %S does not have a valid Enum value", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("EnumProperty {} does not have a valid Enum value", property->GetName())); } const SystemStringType enum_type_name = get_native_enum_name(uenum); @@ -695,7 +696,7 @@ namespace RC::UEGenerator if (script_struct == NULL) { - throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } const SystemStringType native_struct_name = get_native_struct_name(script_struct); @@ -707,7 +708,7 @@ namespace RC::UEGenerator { FDelegateProperty* delegate_property = static_cast(property); - const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); + const auto delegate_type_name = generate_delegate_name(delegate_property, to_system(class_context->GetName())); return delegate_type_name; } @@ -717,7 +718,7 @@ namespace RC::UEGenerator { FMulticastInlineDelegateProperty* delegate_property = static_cast(property); - const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); + const auto delegate_type_name = generate_delegate_name(delegate_property, to_system(class_context->GetName())); return delegate_type_name; } @@ -725,7 +726,7 @@ namespace RC::UEGenerator { FMulticastSparseDelegateProperty* delegate_property = static_cast(property); - const SystemStringType delegate_type_name = generate_delegate_name(delegate_property, UEStringToSystemString(class_context->GetName())); + const auto delegate_type_name = generate_delegate_name(delegate_property, to_system(class_context->GetName())); return delegate_type_name; } @@ -733,7 +734,7 @@ namespace RC::UEGenerator if (field_class_name == SYSSTR("FieldPathProperty")) { FFieldPathProperty* field_path_property = static_cast(property); - const SystemStringType property_class_name = UEStringToSystemString(field_path_property->GetPropertyClass()->GetName()); + const auto property_class_name = to_system(field_path_property->GetPropertyClass()->GetName()); return std::format(SYSSTR("TFieldPath"), property_class_name); } @@ -786,14 +787,14 @@ namespace RC::UEGenerator { return SYSSTR("FText"); } - throw std::runtime_error(RC::fmt("Unsupported property class %S", field_class_name.c_str())); + throw std::runtime_error(RC::fmt("Unsupported property class {}", field_class_name)); } auto get_native_delegate_type_name(Unreal::UFunction* signature_function, Unreal::UClass* current_class, bool strip_outer_name) -> File::StringType { if (!is_delegate_signature_function(signature_function)) { - throw std::runtime_error(RC::fmt("Function %S is not a delegate signature function", signature_function->GetName().c_str())); + throw std::runtime_error(RC::fmt("Function {} is not a delegate signature function", signature_function->GetName())); } // Delegate names always start with F and have __DelegateSignature postfix @@ -826,7 +827,7 @@ namespace RC::UEGenerator else if (!delegate_outer->IsA()) { // Delegate signature functions should never exist outside the UPackage or UClass - throw std::runtime_error(RC::fmt("Delegate signature function %S does not have class or package as outer", delegate_outer->GetName().c_str())); + throw std::runtime_error(RC::fmt("Delegate signature function {} does not have class or package as outer", delegate_outer->GetName())); } return delegate_type_name; } @@ -840,13 +841,13 @@ namespace RC::UEGenerator { if (!is_delegate_signature_function(signature_function)) { - throw std::runtime_error(RC::fmt("Function %S is not a delegate signature function", signature_function->GetName().c_str())); + throw std::runtime_error(RC::fmt("Function {} is not a delegate signature function", signature_function->GetName())); } // Delegate names always start with F and have __DelegateSignature postfix const SystemStringType delegate_signature_postfix = DELEGATE_SIGNATURE_POSTFIX_SYS; - SystemStringType delegate_name = UEStringToSystemString (signature_function->GetName()); + auto delegate_name = to_system(signature_function->GetName()); delegate_name.erase(delegate_name.length() - delegate_signature_postfix.length()); return delegate_name; } diff --git a/UE4SS/src/SDKGenerator/Generator.cpp b/UE4SS/src/SDKGenerator/Generator.cpp index b2ddff5c6..eb9f931dc 100644 --- a/UE4SS/src/SDKGenerator/Generator.cpp +++ b/UE4SS/src/SDKGenerator/Generator.cpp @@ -342,7 +342,7 @@ namespace RC::UEGenerator return return_property_info.has_value() ? return_property_info.value().property : nullptr; }(); - File::StringType function_name{UEStringToSystemString(function_info.function->GetName())}; + File::StringType function_name{to_system(function_info.function->GetName())}; if (is_delegate_function == IsDelegateFunction::Yes) { // Remove the last 19 characters, which is always '__DelegateSignature' for delegates @@ -488,7 +488,7 @@ namespace RC::UEGenerator size_t colon_pos = enum_value_full_name.rfind(STR(":")); auto enum_value_name = colon_pos == enum_value_full_name.npos ? enum_value_full_name : enum_value_full_name.substr(colon_pos + 1); - specification.generate_enum_member(content_buffer, uenum, UEStringToSystemString(enum_value_name), elem); + specification.generate_enum_member(content_buffer, uenum, to_system(enum_value_name), elem); } specification.generate_enum_end(content_buffer, uenum); @@ -538,7 +538,7 @@ namespace RC::UEGenerator else { // Get rid of everything before the last slash + the last slash, leaving only the actual name - File::StringType package_name = UEStringToSystemString(package->GetNamePrivate().ToString()); + File::StringType package_name = to_system(package->GetNamePrivate().ToString()); package_name = package_name.substr(package_name.rfind(SYSSTR("/")) + 1); File::StringType package_name_all_lower = package_name; std::transform(package_name_all_lower.begin(), package_name_all_lower.end(), package_name_all_lower.begin(), [](File::CharType c) { @@ -783,11 +783,11 @@ namespace RC::UEGenerator generate_tab(), property_info.should_forward_declare ? SYSSTR("class ") : SYSSTR(""), generate_property_cxx_name(property, true, native_class, EnableForwardDeclarations::Yes), - UEStringToSystemString(property->GetName())); + to_system(property->GetName())); } catch (std::exception& e) { - Output::send(SYSSTR("Could not generate property '{}' because: {}\n"),UEStringToSystemString(property->GetFullName()), to_generic_string(e.what())); + Output::send(SYSSTR("Could not generate property '{}' because: {}\n"),to_system(property->GetFullName()), to_system(e.what())); continue; } @@ -962,8 +962,8 @@ namespace RC::UEGenerator catch (std::exception& e) { Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), - UEStringToSystemString(function_info.function->GetFullName()), - to_generic_string(e.what())); + to_system(function_info.function->GetFullName()), + to_system(e.what())); return; } @@ -992,13 +992,13 @@ namespace RC::UEGenerator param_info.should_forward_declare ? SYSSTR("class ") : SYSSTR(""), generate_property_cxx_name(param_info.property, true, function_info.function, EnableForwardDeclarations::Yes), param_info.property->HasAnyPropertyFlags(Unreal::CPF_ReferenceParm | Unreal::CPF_OutParm) ? SYSSTR("&") : SYSSTR(""), - UEStringToSystemString(param_info.property->GetName()))); + to_system(param_info.property->GetName()))); } catch (std::exception& e) { Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), - UEStringToSystemString(function_info.function->GetFullName()), - to_generic_string(e.what())); + to_system(function_info.function->GetFullName()), + to_system(e.what())); return; } @@ -1094,7 +1094,7 @@ namespace RC::UEGenerator } auto generate_enum_declaration(File::StringType& content_buffer, UEnum* uenum) -> void { - auto enum_name = UEStringToSystemString(uenum->GetName()); + auto enum_name = to_system(uenum->GetName()); content_buffer.append(std::format(SYSSTR("---@enum {}\n{} = {{\n"), enum_name, enum_name)); } auto generate_enum_member(File::StringType& content_buffer, UEnum* uenum, const File::StringType& enum_value_name, const Unreal::FEnumNamePair& elem) -> void @@ -1162,7 +1162,7 @@ namespace RC::UEGenerator try { - const auto& property_name = UEStringToSystemString(property->GetName()); + const auto& property_name = to_system(property->GetName()); if (is_valid_lua_symbol(property_name)) { content_buffer.append(std::format(SYSSTR("---@field {} {}\n"), property_name, generate_property_lua_name(property, true, native_class))); @@ -1175,7 +1175,7 @@ namespace RC::UEGenerator } catch (std::exception& e) { - Output::send(SYSSTR("Could not generate property '{}' because: {}\n"), UEStringToSystemString(property->GetFullName()), to_generic_string(e.what())); + Output::send(SYSSTR("Could not generate property '{}' because: {}\n"), to_system(property->GetFullName()), to_system(e.what())); continue; } @@ -1242,7 +1242,7 @@ namespace RC::UEGenerator { try { - auto param_name = UEStringToSystemString(param_info.property->GetName()); + auto param_name = to_system(param_info.property->GetName()); // TODO disambiguate param renames current_class_content.append(std::format(SYSSTR("---@param {} {}\n"), make_valid_symbol(param_name), @@ -1251,8 +1251,8 @@ namespace RC::UEGenerator catch (std::exception& e) { Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), - UEStringToSystemString( function_info.function->GetFullName()), - to_generic_string(e.what())); + to_system( function_info.function->GetFullName()), + to_system(e.what())); return; } } @@ -1267,8 +1267,8 @@ namespace RC::UEGenerator catch (std::exception& e) { Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), - UEStringToSystemString(function_info.function->GetFullName()), - to_generic_string(e.what())); + to_system(function_info.function->GetFullName()), + to_system(e.what())); return; } } @@ -1289,7 +1289,7 @@ namespace RC::UEGenerator const auto& param_info = function_info.params[i]; if (!param_info.property->HasAnyPropertyFlags(Unreal::CPF_ReturnParm)) { - auto param_name = UEStringToSystemString(param_info.property->GetName()); + auto param_name = to_system(param_info.property->GetName()); // TODO disambiguate param renames current_class_content.append(std::format(SYSSTR("{}"), make_valid_symbol(param_name))); diff --git a/UE4SS/src/SDKGenerator/JSONDumper.cpp b/UE4SS/src/SDKGenerator/JSONDumper.cpp index e2e58895b..5920f4f0c 100644 --- a/UE4SS/src/SDKGenerator/JSONDumper.cpp +++ b/UE4SS/src/SDKGenerator/JSONDumper.cpp @@ -201,7 +201,7 @@ namespace RC::UEGenerator::JSONDumper } UObject* object = static_cast(raw_object); - auto object_name = UEStringToSystemString(object->GetName()); + auto object_name = to_system(object->GetName()); if (!is_valid_class_to_dump(object_name, object)) { return LoopAction::Continue; @@ -214,7 +214,7 @@ namespace RC::UEGenerator::JSONDumper bp_class.new_string(SYSSTR("bp_class"), object_name); if (auto* super_struct = object_as_class->GetSuperStruct(); super_struct) { - bp_class.new_string(SYSSTR("inherits"), UEStringToSystemString(super_struct->GetName())); + bp_class.new_string(SYSSTR("inherits"), to_system(super_struct->GetName())); } else { @@ -233,7 +233,7 @@ namespace RC::UEGenerator::JSONDumper continue; } - auto event_name = UEStringToSystemString(event_function->GetName()); + auto event_name = to_system(event_function->GetName()); if (should_skip_event(event_name)) { continue; @@ -251,7 +251,7 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_event_arg = bp_event_args.new_object(); - bp_event_arg.new_string(SYSSTR("name"), UEStringToSystemString(param->GetName())); + bp_event_arg.new_string(SYSSTR("name"), to_system(param->GetName())); bp_event_arg.new_string(SYSSTR("type"), generate_property_cxx_name(param, true, event_function)); bool is_out = param->HasAnyPropertyFlags(EPropertyFlags::CPF_OutParm) && !param->HasAnyPropertyFlags(EPropertyFlags::CPF_ConstParm); bp_event_arg.new_bool(SYSSTR("is_out"), is_out); @@ -268,7 +268,7 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_function = functions.new_object(); - bp_function.new_string(SYSSTR("name"), UEStringToSystemString(function->GetName())); + bp_function.new_string(SYSSTR("name"), to_system(function->GetName())); auto& bp_function_args = bp_function.new_array(SYSSTR("args")); for (FProperty* param : function->ForEachProperty()) @@ -279,7 +279,7 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_function_arg = bp_function_args.new_object(); - bp_function_arg.new_string(SYSSTR("name"), UEStringToSystemString(param->GetName())); + bp_function_arg.new_string(SYSSTR("name"), to_system(param->GetName())); bp_function_arg.new_string(SYSSTR("type"), generate_property_cxx_name(param, true, function)); bool is_out = param->HasAnyPropertyFlags(EPropertyFlags::CPF_OutParm) && !param->HasAnyPropertyFlags(EPropertyFlags::CPF_ConstParm); bp_function_arg.new_bool(SYSSTR("is_out"), is_out); @@ -296,7 +296,7 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_property = properties.new_object(); - bp_property.new_string(SYSSTR("name"),UEStringToSystemString(property->GetName())); + bp_property.new_string(SYSSTR("name"),to_system(property->GetName())); bp_property.new_string(SYSSTR("type"), generate_property_cxx_name(property, true, object_as_class)); } @@ -313,7 +313,7 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_delegate = delegates.new_object(); - bp_delegate.new_string(SYSSTR("name"), UEStringToSystemString(delegate_function->GetName())); + bp_delegate.new_string(SYSSTR("name"), to_system(delegate_function->GetName())); auto& bp_delegate_args = bp_delegate.new_array(SYSSTR("args")); for (FProperty* param : delegate_function->ForEachProperty()) @@ -324,7 +324,7 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_delegate_arg = bp_delegate_args.new_object(); - bp_delegate_arg.new_string(SYSSTR("name"), UEStringToSystemString(param->GetName())); + bp_delegate_arg.new_string(SYSSTR("name"), to_system(param->GetName())); bp_delegate_arg.new_string(SYSSTR("type"), generate_property_cxx_name(param, true, delegate_function)); bool is_out = param->HasAnyPropertyFlags(EPropertyFlags::CPF_OutParm) && !param->HasAnyPropertyFlags(EPropertyFlags::CPF_ConstParm); bp_delegate_arg.new_bool(SYSSTR("is_out"), is_out); diff --git a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp index 0e8605001..68aca9a65 100644 --- a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp +++ b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp @@ -53,7 +53,7 @@ namespace RC::UEGenerator MapProperties.insert(property->GetFName()); - auto property_name = UEStringToSystemString(property->GetFName().ToString()); + auto property_name = to_system(property->GetFName().ToString()); auto key_as_struct_property = CastField(static_cast(property)->GetKeyProp()); auto key_struct_type = key_as_struct_property ? key_as_struct_property->GetStruct() : nullptr; @@ -67,14 +67,14 @@ namespace RC::UEGenerator { continue; } - Output::send(SYSSTR("Found Relevant TMap Property: {} in Class: {}\n"), property_name, UEStringToSystemString(object->GetName())); + Output::send(SYSSTR("Found Relevant TMap Property: {} in Class: {}\n"), property_name, to_system(object->GetName())); auto& fm_json_object = fm_object.new_object(property_name); auto& uaapi_array = uaapi_object.new_array(property_name); if (is_key_valid) { - auto key_name = UEStringToSystemString(key_as_struct_property->GetStruct()->GetName()); + auto key_name = to_system(key_as_struct_property->GetStruct()->GetName()); fm_json_object.new_string(SYSSTR("Key"), key_name); uaapi_array.new_string(key_name); } @@ -86,7 +86,7 @@ namespace RC::UEGenerator if (is_value_valid) { - auto value_name = UEStringToSystemString(value_as_struct_property->GetStruct()->GetName()); + auto value_name = to_system(value_as_struct_property->GetStruct()->GetName()); fm_json_object.new_string(SYSSTR("Value"), value_name); uaapi_array.new_string(value_name); } diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index d6e901df6..4e79d9dec 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #pragma warning(default : 4005) namespace RC::UEGenerator @@ -632,8 +633,8 @@ namespace RC::UEGenerator for (auto [Name, Value] : uenum->ForEachName()) { UEStringType enum_name = Name.ToString(); - SystemStringType result_enumeration_line = sanitize_enumeration_name(UEStringToSystemString(enum_name)); - SystemStringType pre_append_result_line = result_enumeration_line; + auto result_enumeration_line = sanitize_enumeration_name(to_system(enum_name)); + auto pre_append_result_line = result_enumeration_line; // If an enum name is listed in the array twice, that likely means it is used as the value for another enum. Long story short, don't print it. if (enum_name_set.contains(enum_name)) @@ -647,15 +648,15 @@ namespace RC::UEGenerator // Taking advantage of GetNameByValue returning the first result for the value to determine if there are any enumerator names that // reference an already declared value/name. - UEStringType first_name_with_value = uenum->GetNameByValue(Value).ToString(); + auto first_name_with_value = uenum->GetNameByValue(Value).ToString(); if (first_name_with_value != Name.ToString()) { - result_enumeration_line.append(std::format(SYSSTR(" = {}"), sanitize_enumeration_name(UEStringToSystemString(first_name_with_value)))); + result_enumeration_line.append(std::format(SYSSTR(" = {}"), sanitize_enumeration_name(to_system(first_name_with_value)))); } else if (Value != expected_next_enum_value || last_value_was_negative_one) { - const SystemStringType CastString = (enum_is_uint8 && Value < 0) ? SYSSTR("(uint8)") : SYSSTR(""); - const SystemStringType MinusSign = Value < 0 ? SYSSTR("-") : SYSSTR(""); + const auto CastString = (enum_is_uint8 && Value < 0) ? SYSSTR("(uint8)") : SYSSTR(""); + const auto MinusSign = Value < 0 ? SYSSTR("-") : SYSSTR(""); result_enumeration_line.append(std::format(SYSSTR(" = {}{}{}"), CastString, MinusSign, Value < 0 ? -Value : Value)); } expected_next_enum_value = Value + 1; @@ -665,7 +666,7 @@ namespace RC::UEGenerator std::transform(pre_append_result_line_lower.begin(), pre_append_result_line_lower.end(), pre_append_result_line_lower.begin(), ::towlower); if (pre_append_result_line_lower.ends_with(SYSSTR("_max"))) { - const SystemStringType expected_full_constant_name = std::format(SYSSTR("{}_MAX"), UEStringToSystemString(enum_prefix)); + const auto expected_full_constant_name = std::format(SYSSTR("{}_MAX"), to_system(enum_prefix)); SystemStringType expected_full_constant_name_lower = expected_full_constant_name; std::transform(expected_full_constant_name_lower.begin(), expected_full_constant_name_lower.end(), expected_full_constant_name_lower.begin(), ::towlower); @@ -704,13 +705,13 @@ namespace RC::UEGenerator } else { - owning_class = UEStringToSystemString(delegate_class->GetNamePrivate().ToString()); + owning_class = to_system(delegate_class->GetNamePrivate().ToString()); } auto function_flags = signature_function->GetFunctionFlags(); if ((function_flags & Unreal::FUNC_Delegate) == 0) { - throw std::runtime_error(RC::fmt("Delegate Signature function %S is missing FUNC_Delegate flag", signature_function->GetName().c_str())); + throw std::runtime_error(RC::fmt("Delegate Signature function {} is missing FUNC_Delegate flag", signature_function->GetName())); } // TODO not particularly nice or reliable, but will do for now @@ -872,7 +873,7 @@ namespace RC::UEGenerator { if ((property->GetPropertyFlags() & CPF_Net) != 0) { - implementation_file.append_line(std::format(SYSSTR("DOREPLIFETIME({}, {});"), class_native_name, UEStringToSystemString(property->GetName()))); + implementation_file.append_line(std::format(SYSSTR("DOREPLIFETIME({}, {});"), class_native_name, to_system(property->GetName()))); } } @@ -913,7 +914,7 @@ namespace RC::UEGenerator const SystemStringType property_flags_string = generate_property_flags(property); bool is_bitmask_bool = false; - PropertyTypeDeclarationContext Context(UEStringToSystemString(uclass->GetName()), &header_data, true, &is_bitmask_bool); + PropertyTypeDeclarationContext Context(to_system(uclass->GetName()), &header_data, true, &is_bitmask_bool); SystemStringType property_type_string{}; bool type_is_valid = true; @@ -925,14 +926,14 @@ namespace RC::UEGenerator catch (std::exception& e) { type_is_valid = false; - error_string = to_generic_string(std::string(e.what())); + error_string = to_system(std::string(e.what())); } if (!type_is_valid) { Output::send(SYSSTR("Warning: {}\n"), error_string); header_data.append_line(std::format(SYSSTR("// UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(SYSSTR("// Missed Property: {}"), UEStringToSystemString(property->GetName()))); + header_data.append_line(std::format(SYSSTR("// Missed Property: {}"), to_system(property->GetName()))); header_data.append_line(std::format(SYSSTR("// {}"), error_string)); header_data.append_line(SYSSTR("")); return; @@ -942,7 +943,7 @@ namespace RC::UEGenerator if (property->GetArrayDim() != 1) { property_extra_declaration.append(SYSSTR("[")); - property_extra_declaration.append(to_generic_string(std::to_string(property->GetArrayDim()))); + property_extra_declaration.append(to_system(std::to_string(property->GetArrayDim()))); property_extra_declaration.append(SYSSTR("]")); } else if (is_bitmask_bool) @@ -951,7 +952,7 @@ namespace RC::UEGenerator } header_data.append_line(std::format(SYSSTR("UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(SYSSTR("{} {}{};"), property_type_string, UEStringToSystemString(property->GetName()), property_extra_declaration)); + header_data.append_line(std::format(SYSSTR("{} {}{};"), property_type_string, to_system(property->GetName()), property_extra_declaration)); header_data.append_line(SYSSTR("")); } @@ -985,7 +986,7 @@ namespace RC::UEGenerator SystemStringType return_property_string; if (return_property != NULL) { - PropertyTypeDeclarationContext context(UEStringToSystemString(uclass->GetName()), &header_data); + PropertyTypeDeclarationContext context(to_system(uclass->GetName()), &header_data); return_property_string = generate_property_type_declaration(return_property, context); } else @@ -1003,7 +1004,7 @@ namespace RC::UEGenerator SystemStringType return_statement_string; if (return_property != NULL) { - const SystemStringType default_property_value = generate_default_property_value(return_property, header_data, UEStringToSystemString(context_name)); + const auto default_property_value = generate_default_property_value(return_property, header_data, to_system(context_name)); return_statement_string = std::format(SYSSTR(" return {};"), default_property_value); } @@ -1011,19 +1012,19 @@ namespace RC::UEGenerator { function_extra_postfix_string.append(SYSSTR(" override")); } - function_extra_postfix_string.append(std::format(SYSSTR(" PURE_VIRTUAL({},{})"), UEStringToSystemString(function->GetName()), return_statement_string)); + function_extra_postfix_string.append(std::format(SYSSTR(" PURE_VIRTUAL({},{})"), to_system(function->GetName()), return_statement_string)); } - SystemStringType function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, UEStringToSystemString(context_name), blacklisted_property_names); + auto function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, to_system(context_name), blacklisted_property_names); - const SystemStringType function_flags_string = generate_function_flags(function, is_function_pure_virtual); + const auto function_flags_string = generate_function_flags(function, is_function_pure_virtual); header_data.append_line(std::format(SYSSTR("UFUNCTION({})"), function_flags_string)); // Format for virtual functions // virtual () PURE_VIRTUAL(, ) header_data.append_line(std::format(SYSSTR("{}{} {}({}){};"), function_modifier_string, return_property_string, - UEStringToSystemString(function->GetName()), + to_system(function->GetName()), function_argument_list, function_extra_postfix_string)); header_data.append_line(SYSSTR("")); @@ -1039,7 +1040,7 @@ namespace RC::UEGenerator { if (Value == enum_value) { - enum_constant_name = sanitize_enumeration_name(UEStringToSystemString(Name.ToString())); + enum_constant_name = sanitize_enumeration_name(to_system(Name.ToString())); } } if (enum_constant_name.empty()) @@ -1066,7 +1067,7 @@ namespace RC::UEGenerator const SystemStringType& property_scope, const SystemStringType& operator_type) -> void { - const SystemStringType field_class_name = UEStringToSystemString(property->GetName()); + const auto field_class_name = to_system(property->GetName()); if (property->GetArrayDim() == 1) { implementation_file.append_line(std::format(SYSSTR("{}{}{}{};"), property_scope, field_class_name, operator_type, value)); @@ -1087,7 +1088,7 @@ namespace RC::UEGenerator const SystemStringType& property_type, const SystemStringType& operator_type) -> void { - const SystemStringType field_class_name = UEStringToSystemString(property->GetName()); + const auto field_class_name = to_system(property->GetName()); implementation_file.append_line(std::format(SYSSTR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); if (property->GetArrayDim() == 1) { @@ -1188,7 +1189,7 @@ namespace RC::UEGenerator UEnum* uenum = p_enum_property->GetEnum(); if (uenum == NULL) { - throw std::runtime_error(RC::fmt("EnumProperty %S does not have a valid Enum value", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("EnumProperty {} does not have a valid Enum value", property->GetName())); } FNumericProperty* underlying_property = p_enum_property->GetUnderlyingProperty(); @@ -1267,13 +1268,13 @@ namespace RC::UEGenerator if (property->IsA()) { FName* name_value = property->ContainerPtrToValuePtr(object); - const SystemStringType name_value_string = UEStringToSystemString(name_value->ToString()); + const auto name_value_string = to_system(name_value->ToString()); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FName* super_name_value = super_property->ContainerPtrToValuePtr(super_object); - const SystemStringType super_name_value_string = UEStringToSystemString(super_name_value->ToString()); + const auto super_name_value_string = to_system(super_name_value->ToString()); if (name_value_string == super_name_value_string) { return; @@ -1300,13 +1301,13 @@ namespace RC::UEGenerator if (property->IsA()) { FString* string_value = property->ContainerPtrToValuePtr(object); - const SystemStringType string_value_string = UEStringToSystemString(UEStringType (string_value->GetCharArray())); + const auto string_value_string = to_system(UEStringType (string_value->GetCharArray())); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FString* super_string_value = super_property->ContainerPtrToValuePtr(super_object); - const SystemStringType super_string_value_string = UEStringToSystemString(UEStringType (super_string_value->GetCharArray())); + const auto super_string_value_string = to_system(UEStringType (super_string_value->GetCharArray())); if (string_value_string == super_string_value_string) { return; @@ -1349,7 +1350,7 @@ namespace RC::UEGenerator if (text_value_string != STR("")) { - const SystemStringType result_property_value = std::format(SYSSTR("FText::FromString({})"), create_string_literal(UEStringToSystemString(text_value_string))); + const auto result_property_value = std::format(SYSSTR("FText::FromString({})"), create_string_literal(to_system(text_value_string))); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1412,7 +1413,7 @@ namespace RC::UEGenerator else { // Unhandled case, reference to the non-native blueprint class potentially? - Output::send(SYSSTR("Unhandled default value of the FClassProperty {}: {}\n"), UEStringToSystemString(property->GetFullName()), UEStringToSystemString(class_value->GetFullName())); + Output::send(SYSSTR("Unhandled default value of the FClassProperty {}: {}\n"), to_system(property->GetFullName()), to_system(class_value->GetFullName())); } return; } @@ -1455,14 +1456,14 @@ namespace RC::UEGenerator if (sub_object_value->HasAnyFlags(EObjectFlags::RF_DefaultSubObject)) { UClass* object_class_type = sub_object_value->GetClassPrivate(); - const SystemStringType object_name = UEStringToSystemString(sub_object_value->GetName()); + const auto object_name = to_system(sub_object_value->GetName()); UClass* super_object_class_type{}; // Additional checks to ensure this property needs to be initialized in the current class if (super_sub_object_value) { super_object_class_type = super_sub_object_value->GetClassPrivate(); - const SystemStringType super_object_name = UEStringToSystemString(super_sub_object_value->GetName()); + const auto super_object_name = to_system(super_sub_object_value->GetName()); if ((object_class_type == super_object_class_type) && (object_name == super_object_name)) { return; @@ -1485,7 +1486,7 @@ namespace RC::UEGenerator UObject* check_super_sub_object_value = *check_super_object_property->ContainerPtrToValuePtr(super_object); if (check_super_sub_object_value) { - SystemStringType check_super_object_name = UEStringToSystemString(check_super_sub_object_value->GetName()); + auto check_super_object_name = to_system(check_super_sub_object_value->GetName()); if (check_super_object_name == object_name) { parent_component_found = true; @@ -1503,7 +1504,7 @@ namespace RC::UEGenerator { // Set property to equal previous property referencing the same object initializer = it->second; - FProperty* prior_property = ustruct->GetPropertyByNameInChain(SystemStringToUEString(initializer).c_str()); + FProperty* prior_property = ustruct->GetPropertyByNameInChain(to_ue(initializer).c_str()); bool prior_private = get_property_access_modifier(prior_property) == AccessModifier::Private; if (prior_private) { @@ -1534,7 +1535,7 @@ namespace RC::UEGenerator implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); implementation_file.m_implementation_constructor.append( std::format(SYSSTR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), object_name)); - m_class_subobjects.try_emplace(object_name, UEStringToSystemString(property->GetName())); + m_class_subobjects.try_emplace(object_name, to_system(property->GetName())); } else { @@ -1542,7 +1543,7 @@ namespace RC::UEGenerator implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); const SystemStringType object_class_name = get_native_class_name(object_class_type); initializer = std::format(SYSSTR("CreateDefaultSubobject<{}>(TEXT(\"{}\"))"), object_class_name, object_name); - m_class_subobjects.try_emplace(object_name, UEStringToSystemString(property->GetName())); + m_class_subobjects.try_emplace(object_name, to_system(property->GetName())); if (!super_and_no_access) { generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); @@ -1561,7 +1562,7 @@ namespace RC::UEGenerator } if (attach_parent_object_value != NULL) { - const SystemStringType attach_parent_object_name = UEStringToSystemString (attach_parent_object_value->GetName()); + const auto attach_parent_object_name = to_system(attach_parent_object_value->GetName()); const SystemStringType operator_type = SYSSTR("->"); bool parent_found = false; SystemStringType attach_string; @@ -1581,25 +1582,25 @@ namespace RC::UEGenerator UObject* check_sub_object_value = *check_object_property->ContainerPtrToValuePtr(object); if (check_sub_object_value) { - SystemStringType check_object_name = UEStringToSystemString(check_sub_object_value->GetName()); + auto check_object_name = to_system(check_sub_object_value->GetName()); if (check_object_name == attach_parent_object_name) { if (get_property_access_modifier(check_object_property) != AccessModifier::Private) { - attach_string = std::format(SYSSTR("SetupAttachment({})"), UEStringToSystemString(check_property->GetName())); + attach_string = std::format(SYSSTR("SetupAttachment({})"), to_system(check_property->GetName())); } else { - SystemStringType parent_property_name = std::format(SYSSTR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), - UEStringToSystemString(check_property->GetName()), - UEStringToSystemString(check_property->GetName())); + auto parent_property_name = std::format(SYSSTR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), + to_system(check_property->GetName()), + to_system(check_property->GetName())); if (!implementation_file.parent_property_names.contains(parent_property_name)) { implementation_file.parent_property_names.emplace(parent_property_name); implementation_file.append_line(parent_property_name); } attach_string = std::format(SYSSTR("SetupAttachment(p_{}_Parent->ContainerPtrToValuePtr<{}>(this))"), - UEStringToSystemString(check_property->GetName()), + to_system(check_property->GetName()), get_native_class_name(check_sub_object_value->GetClassPrivate())); implementation_file.add_dependency_object(check_sub_object_value->GetClassPrivate(), DependencyLevel::Include); } @@ -1655,7 +1656,7 @@ namespace RC::UEGenerator } // Unhandled case, might be some external object reference - Output::send(SYSSTR("Unhandled default value of the FObjectProperty {}: {}\n"), UEStringToSystemString(property->GetFullName()), UEStringToSystemString(sub_object_value->GetFullName())); + Output::send(SYSSTR("Unhandled default value of the FObjectProperty {}: {}\n"), to_system(property->GetFullName()), to_system(sub_object_value->GetFullName())); return; } @@ -1701,7 +1702,7 @@ namespace RC::UEGenerator { if (!super_and_no_access) { - implementation_file.append_line(std::format(SYSSTR("{}{}.AddDefaulted({});"), property_scope, UEStringToSystemString(property->GetName()), (int32_t)property_value->Num())); + implementation_file.append_line(std::format(SYSSTR("{}{}.AddDefaulted({});"), property_scope, to_system(property->GetName()), (int32_t)property_value->Num())); } else { @@ -1740,7 +1741,7 @@ namespace RC::UEGenerator if (!numeric_property->IsFloatingPoint()) { int64 value = numeric_property->GetSignedIntPropertyValue(numeric_property->ContainerPtrToValuePtr(object)); - number_constant_string = to_generic_string( std::to_string(value)); + number_constant_string = to_system( std::to_string(value)); } else { @@ -1765,10 +1766,10 @@ namespace RC::UEGenerator bool is_generating_interface, const CaseInsensitiveSet& blacklisted_property_names) -> void { - const SystemStringType class_native_name = get_native_class_name(uclass, is_generating_interface); - const SystemStringType raw_function_name = UEStringToSystemString(function->GetName()); + const auto class_native_name = get_native_class_name(uclass, is_generating_interface); + const auto raw_function_name = to_system(function->GetName()); auto function_flags = function->GetFunctionFlags(); - PropertyTypeDeclarationContext context(UEStringToSystemString(uclass->GetName()), &implementation_file); + PropertyTypeDeclarationContext context(to_system(uclass->GetName()), &implementation_file); SystemStringType function_implementation_name; SystemStringType net_validate_function_name; @@ -2026,12 +2027,12 @@ namespace RC::UEGenerator for (FProperty* property : class_object->ForEachProperty()) { - result_set.insert(UEStringToSystemString(property->GetName())); + result_set.insert(to_system(property->GetName())); } for (UFunction* function : class_object->ForEachFunction()) { - result_set.insert(UEStringToSystemString(function->GetName())); + result_set.insert(to_system(function->GetName())); } } else if (uclass->GetClassPrivate()->IsChildOf(UScriptStruct::StaticClass())) @@ -2040,7 +2041,7 @@ namespace RC::UEGenerator for (FProperty* property : script_struct->ForEachProperty()) { - result_set.insert(UEStringToSystemString(property->GetName())); + result_set.insert(to_system(property->GetName())); } } return result_set; @@ -2163,7 +2164,7 @@ namespace RC::UEGenerator UClass* class_within = uclass->GetClassWithin(); if (class_within != NULL && class_within != UObject::StaticClass() && (super_class == NULL || class_within != super_class->GetClassWithin())) { - flag_format_helper.add_parameter(SYSSTR("Within"), UEStringToSystemString(class_within->GetName())); + flag_format_helper.add_parameter(SYSSTR("Within"), to_system(class_within->GetName())); } if ((class_own_flags & CLASS_Transient) != 0) @@ -2222,7 +2223,7 @@ namespace RC::UEGenerator const UEStringType class_config_name = uclass->GetClassConfigName().ToString(); if (super_class == NULL || class_config_name != super_class->GetClassConfigName().ToString()) { - flag_format_helper.add_parameter(SYSSTR("Config"), UEStringToSystemString(class_config_name)); + flag_format_helper.add_parameter(SYSSTR("Config"), to_system(class_config_name)); // Don't add our override config if we add the real one here add_config_name = false; } @@ -2306,7 +2307,7 @@ namespace RC::UEGenerator UEnum* uenum = enum_property->GetEnum(); if (uenum == NULL) { - throw std::runtime_error(RC::fmt("EnumProperty %S does not have a valid Enum value", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("EnumProperty {} does not have a valid Enum value", property->GetName())); } if (context.source_file != NULL) { @@ -2549,7 +2550,7 @@ namespace RC::UEGenerator if (script_struct == NULL) { - throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } const SystemStringType native_struct_name = get_native_struct_name(script_struct); @@ -2620,7 +2621,7 @@ namespace RC::UEGenerator if (property->IsA()) { FFieldPathProperty* field_path_property = static_cast(property); - const SystemStringType property_class_name = UEStringToSystemString(field_path_property->GetPropertyClass()->GetName()); + const auto property_class_name = to_system(field_path_property->GetPropertyClass()->GetName()); return std::format(SYSSTR("TFieldPath"), property_class_name); } @@ -2670,9 +2671,9 @@ namespace RC::UEGenerator { return SYSSTR("FText"); } - throw std::runtime_error(RC::fmt("[generate_property_type_declaration] Unsupported property class '%S', full name: '%S'", - field_class_name.c_str(), - property->GetFullName().c_str())); + throw std::runtime_error(RC::fmt("[generate_property_type_declaration] Unsupported property class '{}', full name: '{}'", + field_class_name, + property->GetFullName())); } //*/ @@ -2813,7 +2814,7 @@ namespace RC::UEGenerator { if ((property_flags & CPF_RepNotify) != 0) { - const SystemStringType rep_notify_func_name = UEStringToSystemString(property->GetRepNotifyFunc().ToString()); + const auto rep_notify_func_name = to_system(property->GetRepNotifyFunc().ToString()); flag_format_helper.add_parameter(SYSSTR("ReplicatedUsing"), rep_notify_func_name); } else @@ -2972,15 +2973,15 @@ namespace RC::UEGenerator } int64 highest_enum_value = 0; - const SystemStringType enum_prefix = UEStringToSystemString(uenum->GenerateEnumPrefix()); - const SystemStringType expected_max_name = std::format(SYSSTR("{}_MAX"), enum_prefix); - SystemStringType expected_max_name_lower = expected_max_name; + const auto enum_prefix = to_system(uenum->GenerateEnumPrefix()); + const auto expected_max_name = std::format(SYSSTR("{}_MAX"), enum_prefix); + auto expected_max_name_lower = expected_max_name; std::transform(expected_max_name_lower.begin(), expected_max_name_lower.end(), expected_max_name_lower.begin(), ::towlower); for (auto [Name, Value] : uenum->ForEachName()) { - SystemStringType enum_name = sanitize_enumeration_name(UEStringToSystemString(Name.ToString())); - SystemStringType enum_name_lower = enum_name; + auto enum_name = sanitize_enumeration_name(to_system(Name.ToString())); + auto enum_name_lower = enum_name; std::transform(enum_name_lower.begin(), enum_name_lower.end(), enum_name_lower.begin(), ::towlower); if ((enum_name_lower != expected_max_name_lower && enum_name_lower != sanitize_enumeration_name(expected_max_name_lower)) && Value > highest_enum_value) { @@ -3128,7 +3129,7 @@ namespace RC::UEGenerator bool bLAFound = false; for (FProperty* param : function->ForEachProperty()) { - auto param_name = UEStringToSystemString(param->GetName()); + auto param_name = to_system(param->GetName()); auto param_uc_name = string_to_uppercase(param_name); if (param_uc_name.find(SYSSTR("WORLDCONTEXT")) != param_uc_name.npos) { @@ -3210,7 +3211,7 @@ namespace RC::UEGenerator } param_declaration.append(SYSSTR(" ")); - SystemStringType property_name = UEStringToSystemString(property->GetName()); + auto property_name = to_system(property->GetName()); // If property name is blacklisted, capitalize first letter and prepend New if ((uclass && is_function_parameter_shadowing(uclass, property)) || blacklisted_property_names.contains(property_name)) @@ -3239,7 +3240,7 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType { - const SystemStringType field_class_name = UEStringToSystemString(property->GetClass().GetName()); + const auto field_class_name = to_system(property->GetClass().GetName()); PropertyTypeDeclarationContext context(ContextName, &header_data); // Byte Property @@ -3264,7 +3265,7 @@ namespace RC::UEGenerator if (uenum == NULL) { - throw std::runtime_error(RC::fmt("EnumProperty %S does not have a valid Enum value", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("EnumProperty {} does not have a valid Enum value", property->GetName())); } const int64_t first_enum_constant_value = uenum->GetEnumNameByIndex(0).Value; return generate_enum_value(uenum, first_enum_constant_value); @@ -3313,7 +3314,7 @@ namespace RC::UEGenerator if (script_struct == NULL) { - throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty %S", property->GetName().c_str())); + throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } const SystemStringType native_struct_name = get_native_struct_name(script_struct); return std::format(SYSSTR("{}{{}}"), native_struct_name); @@ -3377,9 +3378,9 @@ namespace RC::UEGenerator { return SYSSTR("FText::GetEmpty()"); } - throw std::runtime_error(RC::fmt("[generate_default_property_value] Unsupported property class '%S', full name: '%S'", - field_class_name.c_str(), - property->GetFullName().c_str())); + throw std::runtime_error(RC::fmt("[generate_default_property_value] Unsupported property class '{}', full name: '{}'", + field_class_name, + property->GetFullName())); } auto UEHeaderGenerator::get_class_blueprint_info(UClass* uclass) -> ClassBlueprintInfo @@ -3475,7 +3476,7 @@ namespace RC::UEGenerator { throw std::invalid_argument("Encountered a package with an outer object set"); } - SystemStringType package_name = UEStringToSystemString(package->GetName()); + auto package_name = to_system(package->GetName()); if (!package_name.starts_with(SYSSTR("/Script/"))) { return SYSSTR(""); @@ -3850,18 +3851,18 @@ namespace RC::UEGenerator { if (!is_delegate_signature_function(function)) { - throw std::runtime_error(RC::fmt("Function %S is not a delegate signature function", function->GetName().c_str())); + throw std::runtime_error(RC::fmt("Function {} is not a delegate signature function", function->GetName())); } if (!function->GetOuterPrivate()->IsA()) { - throw std::runtime_error(RC::fmt("Delegate Signature Function %S does not have a UPackage as it's owner", function->GetName().c_str())); + throw std::runtime_error(RC::fmt("Delegate Signature Function {} does not have a UPackage as it's owner", function->GetName())); } generate_global_delegate_declaration(function, NULL, header_file); } else { throw std::runtime_error( - RC::fmt("Provided object %S is not of a supported type: %S", object->GetName().c_str(), object->GetClassPrivate()->GetName().c_str())); + RC::fmt("Provided object {} is not of a supported type: {}", object->GetName(), object->GetClassPrivate()->GetName())); } auto iterator = this->m_module_dependencies.find(module_name); @@ -3932,14 +3933,14 @@ namespace RC::UEGenerator if (object->IsA() || object->IsA()) { // Class and struct headers follow the relevant object name - header_name = UEStringToSystemString(object->GetName()); + header_name = to_system(object->GetName()); final_object = object; } else if (object->IsA()) { // Enumeration usually have the E prefix which will be present in the header names // We do not strip it because there are some broken headers that do not follow that convention (e.g. funny Wwise) - header_name = UEStringToSystemString(object->GetName()); + header_name = to_system(object->GetName()); final_object = object; } else @@ -3970,7 +3971,7 @@ namespace RC::UEGenerator if (header_name.empty()) { // Unsupported dependency object type - throw std::runtime_error(RC::fmt("Unsupported dependency object type %S: %S", object->GetClassPrivate()->GetName().c_str(), object->GetName().c_str())); + throw std::runtime_error(RC::fmt("Unsupported dependency object type {}: {}", object->GetClassPrivate()->GetName(), object->GetName())); } if (get_existing_header) @@ -4033,7 +4034,7 @@ namespace RC::UEGenerator top_level_object = top_level_object->GetOuterPrivate(); } - const SystemStringType object_name = UEStringToSystemString(top_level_object->GetName()); + const auto object_name = to_system(top_level_object->GetName()); return std::format(SYSSTR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), module_name, object_name, fallback_name); } diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 9bab1e791..9aed1d28d 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -23,7 +23,6 @@ #include #endif #include -#include #include #include #include @@ -100,7 +99,7 @@ namespace RC #define OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(StructName) \ for (const auto& [name, offset] : Unreal::StructName::MemberOffsets) \ { \ - Output::send(SYSSTR(#StructName "::{} = 0x{:X}\n"), UEStringToSystemString(name), offset); \ + Output::send(SYSSTR(#StructName "::{} = 0x{:X}\n"), to_system(name), offset); \ } auto output_all_member_offsets() -> void @@ -140,7 +139,7 @@ namespace RC { UE4SSProgram& program = UE4SSProgram::get_program(); HMODULE lib = PLH::FnCast(program.m_hook_trampoline_load_library_a, &LoadLibraryA)(dll_name); - program.fire_dll_load_for_cpp_mods(to_generic_string(dll_name)); + program.fire_dll_load_for_cpp_mods(to_system(dll_name)); return lib; } @@ -148,7 +147,7 @@ namespace RC { UE4SSProgram& program = UE4SSProgram::get_program(); HMODULE lib = PLH::FnCast(program.m_hook_trampoline_load_library_ex_a, &LoadLibraryExA)(dll_name, file, flags); - program.fire_dll_load_for_cpp_mods(to_generic_string(dll_name)); + program.fire_dll_load_for_cpp_mods(to_system(dll_name)); return lib; } @@ -184,7 +183,7 @@ namespace RC } catch (std::exception& e) { - create_emergency_console_for_early_error(std::format(SYSSTR("The IniParser failed to parse: {}"), to_generic_string(e.what()))); + create_emergency_console_for_early_error(std::format(SYSSTR("The IniParser failed to parse: {}"), to_system(e.what()))); return; } @@ -343,7 +342,7 @@ namespace RC // only log modules with unique addresses (non-modular builds have everything in MainExe) if (i == static_cast(ScanTarget::MainExe) || main_exe_ptr != module.lpBaseOfDll) { - auto module_name = to_generic_string(ScanTargetToString(i)); + auto module_name = to_system(ScanTargetToString(i)); Output::send(SYSSTR("{} @ {} size={:#x}\n"), module_name.c_str(), module.lpBaseOfDll, module.SizeOfImage); } } @@ -355,7 +354,7 @@ namespace RC // only log modules with unique addresses (non-modular builds have everything in MainExe) if (i == static_cast(ScanTarget::MainExe) || main_exe_ptr != module.base_address) { - auto module_name = to_generic_string(ScanTargetToString(i)); + auto module_name = to_system(ScanTargetToString(i)); // FIXME: FIX Why this won't WORK? // Output::send(SYSSTR("{} @ {} size={:#x}\n"), module_name, module.base_address, module.size); } @@ -612,7 +611,7 @@ namespace RC auto list = parser.get_ordered_list(section_name); uint32_t vtable_size = list.size() - 1; list.for_each([&](uint32_t index, SystemStringType& item) { - auto ue_str = SystemStringToUEString(item); + auto ue_str = to_ue(item); callable(index, item, ue_str); }); return vtable_size; @@ -1626,9 +1625,9 @@ namespace RC return static_cast(find_mod_by_name(mod_name, installed_only, is_started)); } - auto UE4SSProgram::find_lua_mod_by_name(UEViewType mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* + auto UE4SSProgram::find_lua_mod_by_name(UEStringViewType mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* { - auto sysstr = UEStringToSystemString(UEStringType{mod_name}); + auto sysstr = to_system(UEStringType{mod_name}); return static_cast(find_mod_by_name(sysstr, installed_only, is_started)); } diff --git a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp index 0182d3f83..b3633fa30 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp @@ -2,19 +2,23 @@ #define UE4SS_REWRITTEN_OUTPUT_HPP #include -#include #include #include #include #include #include #include +#include #include #include #include #include #include +#include + +// #include +// #include #if RC_IS_ANSI == 1 #define RC_STD_MAKE_FORMAT_ARGS std::make_format_args @@ -26,6 +30,7 @@ #endif #endif + namespace RC::Output { template @@ -119,14 +124,14 @@ namespace RC::Output { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } - + for (const auto& device : m_opened_devices) { ASSERT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(content, 0); + device->receive_with_optional_arg(content, static_cast(optional_arg)); } else { @@ -136,46 +141,50 @@ namespace RC::Output } template - auto send(File::StringViewType content, FmtArgs... fmt_args) -> void + auto send(File::StringViewType&& content, FmtArgs&&... fmt_args) -> void { if (m_opened_devices.empty()) { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } + auto formated = std::vformat(std::forward(content), RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + for (const auto& device : m_opened_devices) { ASSERT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...)), 0); + device->receive_with_optional_arg(formated, 0); } else { - device->receive(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); + device->receive(formated); } } } template - auto send(File::StringViewType content, OptionalArg optional_arg, FmtArgs... fmt_args) -> void + auto send(File::StringViewType content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void { if (m_opened_devices.empty()) { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + for (const auto& device : m_opened_devices) { ASSERT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat(content, fmt_args...), RC_STD_MAKE_FORMAT_ARGS(static_cast(optional_arg))); + device->receive_with_optional_arg(formated, RC_STD_MAKE_FORMAT_ARGS(static_cast(optional_arg))); } else { - device->receive(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); + device->receive(formated); } } } @@ -203,23 +212,25 @@ namespace RC::Output } template - auto send(File::StringViewType content, FmtArg fmt_arg, FmtArgs... fmt_args) -> void + auto send(File::StringViewType content, FmtArg&& fmt_arg, FmtArgs&&... fmt_args) -> void { if (m_opened_devices.empty()) { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_arg), std::forward(fmt_args))...)); + for (const auto& device : m_opened_devices) { ASSERT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_arg, fmt_args...)), optional_arg); + device->receive_with_optional_arg(formated, optional_arg); } else { - device->receive(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); + device->receive(formated); } } } @@ -283,37 +294,39 @@ namespace RC::Output } template - auto send(File::StringViewType content, FmtArgs... fmt_args) -> void + auto send(File::StringViewType content, FmtArgs&&... fmt_args) -> void { + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...)), 0); + device->receive_with_optional_arg(formated, 0); } else { - device->receive(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); + device->receive(formated); } } } template - auto send(File::StringViewType content, OptionalArg optional_arg, FmtArgs... fmt_args) -> void + auto send(File::StringViewType content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void { + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...)), static_cast(optional_arg)); + device->receive_with_optional_arg(formated, static_cast(optional_arg)); } else { - device->receive(std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); + device->receive(formated); } } } @@ -339,19 +352,20 @@ namespace RC::Output } template - auto send(File::StringViewType content, FmtArgs... fmt_args) -> void + auto send(File::StringViewType content, FmtArgs&&... fmt_args) -> void { + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(std::vformat((std::string)content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...)), optional_arg); + device->receive_with_optional_arg(formated, optional_arg); } else { - device->receive(std::vformat((std::string)content, RC_STD_MAKE_FORMAT_ARGS(fmt_args...))); + device->receive(formated); } } } diff --git a/deps/first/File/include/File/Macros.hpp b/deps/first/File/include/File/Macros.hpp index d35bfd989..fa0e4aca1 100644 --- a/deps/first/File/include/File/Macros.hpp +++ b/deps/first/File/include/File/Macros.hpp @@ -9,17 +9,20 @@ #define RC_IS_ANSI 0 #endif -#if RC_IS_ANSI == 1 +// always use u16string #define STR(str) u##str -#define SYSSTR(str) str -#else + #ifdef LINUX -#define STR(str) u##str -#define SYSSTR(str) str + #define SYSSTR(str) str + #define IOSTR(str) str #else -#define STR(str) L##str -#define SYSSTR(str) L##str -#endif + #if RC_IS_ANSI == 0 + #define SYSSTR(str) u##str + #define IOSTR(str) u##str + #else + #define SYSSTR(str) str + #define IOSTR(str) str + #endif #endif #ifdef S @@ -45,68 +48,79 @@ construct a Targets object and supply your own devices.") \ namespace RC::File { + typedef std::basic_ofstream u16ofstream; + typedef std::basic_ifstream u16ifstream; + #if RC_IS_ANSI == 1 using StringType = std::string; using StringViewType = std::string_view; using CharType = char; using StreamType = std::ifstream; - // using ToString = std::tostring; - - constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return std::to_string(std::forward(numeric_value)); - }; #else -#ifdef WIN32 - using StringType = std::wstring; - using StringViewType = std::wstring_view; - using CharType = wchar_t; - using StreamType = std::wifstream; - constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return std::to_wstring(std::forward(numeric_value)); - }; -#else -// on linux, use utf8 - using StringType = std::string; - using StringViewType = std::string_view; - using CharType = char; - using StreamType = std::ifstream; + // System String Types + #ifdef WIN32 + using StringType = std::u16string; + using StringViewType = std::u16string_view; + using CharType = std::u16string::value_type; + using StreamType = u16ifstream; + #else + // on linux, use utf8 + using StringType = std::string; + using StringViewType = std::string_view; + using CharType = char; + using StreamType = std::ifstream; + #endif // WIN32 +#endif // RC_IS_ANSI - constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return std::to_string(std::forward(numeric_value)); - }; -#endif -#endif } // namespace RC::File namespace RC { - using SystemStringType = File::StringType; - using SystemStringViewType = File::StringViewType; - using SystemCharType = File::CharType; - using SystemStreamType = File::StreamType; + // Should find a better place for these definitions + // System = C++ String Types +#if RC_IS_ANSI == 1 + using SystemStringType = std::string; + using SystemStringViewType = std::string_view; + using SystemCharType = char; + using SystemStreamType = std::ifstream; + constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_string(std::forward(numeric_value)); + }; + #define SystemStringPrint "%s" +#else + // System String Types + #ifdef WIN32 + using SystemStringType = std::u16string; + using SystemStringViewType = std::u16string_view; + using SystemCharType = std::u16string::value_type; + using SystemStreamType = u16ifstream; + constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_u16string(std::forward(numeric_value)); + }; + #define SystemStringPrint "%S" + #else + // on linux, use utf8 + using SystemStringType = std::string; + using SystemStringViewType = std::string_view; + using SystemCharType = char; + using SystemStreamType = std::ifstream; + constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_string(std::forward(numeric_value)); + }; + #define SystemStringPrint "%s" + #endif // WIN32 +#endif -#ifdef WIN32 - using UEStringType = File::StringType; - using UEViewType = File::StringViewType; - using UECharType = File::CharType; - #define SystemStringPrint "%S" - #define UEStringPrint "%S" - static auto SystemStringToUEString = [](const SystemStringType& str) -> UEStringType { return str; }; - static auto UEStringToSystemString = [](const UEStringType& str) -> SystemStringType { return str; }; +#if RC_IS_ANSI == 1 + using UEStringType = std::string; + using UEStringViewType = std::string_view; + using UECharType = std::string::value_type; + #define UEStringPrint "%s" #else using UEStringType = std::u16string; - using UEViewType = std::u16string_view; - using UECharType = char16_t; - #define SystemStringPrint "%s" + using UEStringViewType = std::u16string_view; + using UECharType = std::u16string::value_type; #define UEStringPrint "%S" - static auto SystemStringToUEString = [](const SystemStringType& str) -> UEStringType { - static std::wstring_convert, char16_t> converter{}; - return converter.from_bytes((std::string)str); - }; - static auto UEStringToSystemString = [](const UEStringType& str) -> SystemStringType { - return std::wstring_convert, char16_t>{}.to_bytes((std::u16string)str); - }; -#endif +#endif // RC_IS_ANSI - constexpr auto ToString = File::ToString; } // namespace RC diff --git a/deps/first/File/src/FileType/WinFile.cpp b/deps/first/File/src/FileType/WinFile.cpp index 0cbfd2f84..4d75ad5a9 100644 --- a/deps/first/File/src/FileType/WinFile.cpp +++ b/deps/first/File/src/FileType/WinFile.cpp @@ -28,7 +28,7 @@ namespace RC::File { if constexpr (sizeof(CharType) > 1) { - if (DeleteFileW(file_path_and_name.wstring().c_str()) == 0) + if (DeleteFileW(file_path_and_name.u16string().c_str()) == 0) { THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::delete_file] Was unable to delete file, error: {}", GetLastError())) } diff --git a/deps/first/Helpers/include/Helpers/Format.hpp b/deps/first/Helpers/include/Helpers/Format.hpp index ea825c228..57ebaea46 100644 --- a/deps/first/Helpers/include/Helpers/Format.hpp +++ b/deps/first/Helpers/include/Helpers/Format.hpp @@ -1,90 +1,13 @@ #pragma once #include -#include -#include - -#ifdef LINUX -#define swprintf_s swprintf -#define sprintf_s snprintf -#endif +#include namespace RC { - template - auto static fmt(const char* fmt, Args... args) -> std::string - { - constexpr size_t out_string_length = 1000; - char out_string[out_string_length]; - - size_t msg_len = strlen(fmt); - - // Attempt to give a hint if the buffer is too small - if (msg_len > out_string_length) - { - fmt = "An error occurred but the message was too long for the buffer."; - msg_len = strlen(fmt); - } - - // If the buffer is too small for the hint message then I guess we do nothing - // The default message will be used which can't be too small since it's calculated at compile-time - if (msg_len < out_string_length) - { - sprintf_s(out_string, out_string_length, fmt, args...); - } - - return out_string; - } - - template - auto static fmt(const wchar_t* fmt, Args... args) -> std::wstring + template + auto static fmt(const std::string_view&& fmt, FmtArgs&&... fmt_args) -> std::string { - constexpr size_t out_string_length = 1000; - wchar_t out_string[out_string_length]; - - size_t msg_len = wcslen(fmt); - - // Attempt to give a hint if the buffer is too small - if (msg_len > out_string_length) - { - fmt = L"An error occurred but the message was too long for the buffer."; - msg_len = wcslen(fmt); - } - - // If the buffer is too small for the hint message then I guess we do nothing - // The default message will be used which can't be too small since it's calculated at compile-time - if (msg_len < out_string_length) - { - swprintf_s(out_string, out_string_length, fmt, args...); - } - - return out_string; - } - -/* - template - auto static fmt(const char16_t* fmt, Args... args) -> std::wstring - { - constexpr size_t out_string_length = 1000; - char16_t out_string[out_string_length]; - - size_t msg_len = wcslen(fmt); - - // Attempt to give a hint if the buffer is too small - if (msg_len > out_string_length) - { - fmt = L"An error occurred but the message was too long for the buffer."; - msg_len = wcslen(fmt); - } - - // If the buffer is too small for the hint message then I guess we do nothing - // The default message will be used which can't be too small since it's calculated at compile-time - if (msg_len < out_string_length) - { - swprintf_s(out_string, out_string_length, fmt, args...); - } - - return out_string; + return std::vformat(std::forward(fmt), RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); } -*/ -} // namespace RC +} \ No newline at end of file diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index c681742a1..631c1e957 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include @@ -212,10 +214,15 @@ namespace RC auto inline to_wstring(std::string& input) -> std::wstring { + #if WIN32 #pragma warning(disable : 4996) - static std::wstring_convert> converter{}; - return converter.from_bytes(input); + static std::wstring_convert> converter{}; + return converter.from_bytes(input); #pragma warning(default : 4996) + #else + static std::wstring_convert> converter{}; + return converter.from_bytes(input); + #endif } auto inline to_const_wstring(std::string_view input) -> const std::wstring& @@ -248,21 +255,39 @@ namespace RC auto inline to_wstring(std::u16string& input) -> std::wstring { +#ifdef WIN32 return {input.begin(), input.end()}; +#else + throw std::runtime_error{"There is no reason to use this function on non-Windows platforms"}; +#endif } auto inline to_wstring(std::u16string_view input) -> std::wstring { +#ifdef WIN32 auto temp_input = std::u16string{input}; return to_wstring(temp_input); +#else + return to_wstring(std::u16string{input}); +#endif + } + + auto inline to_wstring(std::filesystem::path& input) -> std::wstring + { + return input.wstring(); } auto inline to_string(std::wstring& input) -> std::string { +#ifdef WIN32 #pragma warning(disable : 4996) static std::wstring_convert> converter{}; return converter.to_bytes(input); #pragma warning(default : 4996) +#else + static std::wstring_convert> converter{}; + return converter.to_bytes(input); +#endif } auto inline to_string(std::u16string& input) -> std::string @@ -287,14 +312,23 @@ namespace RC return std::string{input}; } - auto inline to_string(std::string input) -> std::string + auto inline to_string(std::string& input) -> std::string { return std::string{input}; } + auto inline to_string(std::filesystem::path& input) -> std::string + { + return input.string(); + } + auto inline to_u16string(std::wstring& input) -> std::u16string { +#ifdef WIN32 return {input.begin(), input.end()}; +#else + throw std::runtime_error{"There is no reason to use this function on non-Windows platforms"}; +#endif } auto inline to_u16string(std::wstring_view input) -> std::u16string @@ -305,7 +339,10 @@ namespace RC auto inline to_u16string(std::string& input) -> std::u16string { - return {input.begin(), input.end()}; + // codecvt_utf8_utf16 + #pragma warning(disable : 4996) + return std::wstring_convert, char16_t>{}.from_bytes(input); + #pragma warning(default : 4996) } auto inline to_u16string(std::string_view input) -> std::u16string @@ -314,31 +351,215 @@ namespace RC return to_u16string(temp_input); } - auto inline to_generic_string(const auto& input) -> SystemStringType + auto inline to_u16string(std::u16string_view input) -> std::u16string + { + return std::u16string{input}; + } + + auto inline to_u16string(std::u16string& input) -> std::u16string + { + return std::u16string{input}; + } + + auto inline to_u16string(std::filesystem::path& input) -> std::u16string { - if constexpr (std::is_same_v>>, SystemStringViewType>) + return input.u16string(); + } + + // Type traits to check if T is a string type that needs conversion + template + struct is_string_like_t : std::false_type {}; + + // Specializations for the types that need conversion + template<> struct is_string_like_t : std::true_type {}; + template<> struct is_string_like_t : std::true_type {}; + template<> struct is_string_like_t : std::true_type {}; + template<> struct is_string_like_t : std::true_type {}; + template<> struct is_string_like_t : std::true_type {}; + template<> struct is_string_like_t : std::true_type {}; + + template + struct dependent_false : std::false_type {}; + + template + auto stringviewify(T&& tp) { + if constexpr (std::is_same_v, UECharType*> || std::is_same_v, const UECharType*>) { + return UEStringViewType{tp}; + } else if constexpr (std::is_same_v, SystemCharType*> || std::is_same_v, const SystemCharType*>) { + return SystemStringViewType{tp}; + } else if constexpr (std::is_same_v, File::CharType*> || std::is_same_v, const File::CharType*>) { + return File::StringViewType{tp}; + } else { + return std::forward(tp); + } + } + + template + struct _can_be_string_view_t : std::false_type {}; + template<> struct _can_be_string_view_t : std::true_type {}; + template<> struct _can_be_string_view_t : std::true_type {}; + template<> struct _can_be_string_view_t : std::true_type {}; + template<> struct _can_be_string_view_t : std::true_type {}; + template<> struct _can_be_string_view_t : std::true_type {}; + template<> struct _can_be_string_view_t : std::true_type {}; + + template + struct can_be_string_view_t : _can_be_string_view_t> {}; + + template + struct is_file_string_type : std::disjunction< + std::is_same, + std::is_same + > {}; + + template + struct not_file_string_like_t : std::conjunction>, std::negation>>> {}; + + template + auto inline to_file_string(T&& input) -> File::StringType { + if constexpr (std::is_same_v) + { + return to_string(input); + } + else if constexpr (std::is_same_v) { - return SystemStringType{input}; + return to_wstring(input); } - else if constexpr (std::is_same_v>>, SystemStringType> || - std::is_same_v>>, SystemCharType>) + else if constexpr (std::is_same_v) { - return input; + return to_u16string(input); + } else { + static_assert(dependent_false::value, "Unsupported SystemStringType."); } - else + } + + template + auto to_file(T&& arg) { + if constexpr (can_be_string_view_t::value) { + return to_file_string(stringviewify(std::forward(arg))); + } + else if constexpr (not_file_string_like_t>::value) + { + return to_file_string(std::forward(arg)); + } + else + { + return std::forward(arg); + } + } + + template + struct is_system_string_type : std::disjunction< + std::is_same, + std::is_same + > {}; + + template + struct not_system_string_like_t : std::conjunction>,std::negation>>> {}; + + template + auto inline to_system_string(T&& input) -> SystemStringType { + if constexpr (std::is_same_v) { -#if RC_IS_ANSI == 1 return to_string(input); -#else -#ifdef WIN32 + } + else if constexpr (std::is_same_v) + { return to_wstring(input); -#else + } + else if constexpr (std::is_same_v) + { + return to_u16string(input); + } + else + { + static_assert(dependent_false::value, "Unsupported SystemStringType."); + } + } + + template + auto to_system(T&& arg) { + if constexpr (can_be_string_view_t::value) { + return to_system_string(stringviewify(std::forward(arg))); + } + else if constexpr (not_system_string_like_t>::value) + { + return to_system_string(std::forward(arg)); + } + else + { + return std::forward(arg); + } + } + + template + struct is_ue_string_type : std::disjunction< + std::is_same, + std::is_same + > {}; + + template + struct not_ue_string_like_t : std::conjunction>, std::negation>>> {}; + + template + auto inline to_ue_string(T&& input) -> UEStringType { + if constexpr (std::is_same_v) + { return to_string(input); -#endif -#endif + } + else if constexpr (std::is_same_v) + { + return to_wstring(input); + } + else if constexpr (std::is_same_v) + { + return to_u16string(input); + } + else + { + static_assert(dependent_false::value, "Unsupported SystemStringType."); + } + } + + template + auto to_ue(T&& arg) { + if constexpr (can_be_string_view_t::value) + { + return to_ue_string(stringviewify(std::forward(arg))); + } + else if constexpr (not_ue_string_like_t>::value) + { + return to_ue_string(std::forward(arg)); + } + else + { + return std::forward(arg); } } + template + struct is_lua_string_type : std::disjunction< + std::is_same, + std::is_same + > {}; + + template + struct not_lua_string_like_t : std::negation>> {}; + + template + auto to_lua(T&& arg) { + if constexpr (can_be_string_view_t::value || not_lua_string_like_t>::value) + { + return to_string((arg)); + } + else + { + return std::forward(arg); + } + } + + #define csfor_lua(x) (to_lua((x)).c_str()) + namespace String { auto inline iequal(std::wstring_view a, std::wstring_view b) diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp index a8afd086f..77ad45442 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp @@ -346,7 +346,7 @@ namespace RC using SignatureContainerMap = std::unordered_map>; RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; #ifdef WIN32 - RC_SPSS_API auto static string_scan(std::wstring_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; + RC_SPSS_API auto static string_scan(std::u16string_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; #endif }; } // namespace RC diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp index 4d2c4ab8a..ea849dbd0 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp @@ -375,7 +375,7 @@ namespace RC return vector_of_signatures; } - auto SinglePassScanner::string_scan(std::wstring_view string_to_scan_for, ScanTarget scan_target) -> void* + auto SinglePassScanner::string_scan(std::u16string_view string_to_scan_for, ScanTarget scan_target) -> void* { auto module = SigScannerStaticData::m_modules_info[scan_target]; @@ -406,7 +406,7 @@ namespace RC break; } - std::wstring_view maybe_string = std::wstring_view((const wchar_t*)region_start, string_to_scan_for.size()); + std::u16string_view maybe_string = std::u16string_view((const wchar_t*)region_start, string_to_scan_for.size()); if (maybe_string == string_to_scan_for) { address_found = region_start; From a607d9bd202198b8d186cda009cae66deb152c2b Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 19 Feb 2024 04:38:36 -0600 Subject: [PATCH 047/213] remove useless cast --- UE4SS/src/GUI/BPMods.cpp | 2 +- UE4SS/src/LuaLibrary.cpp | 2 +- UE4SS/src/Mod/LuaMod.cpp | 6 +++--- UE4SS/src/SDKGenerator/TMapOverrideGen.cpp | 2 +- UE4SS/src/UE4SSProgram.cpp | 2 +- UVTD/src/main.cpp | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/UE4SS/src/GUI/BPMods.cpp b/UE4SS/src/GUI/BPMods.cpp index 58d13bb3f..9e41785fc 100644 --- a/UE4SS/src/GUI/BPMods.cpp +++ b/UE4SS/src/GUI/BPMods.cpp @@ -113,7 +113,7 @@ namespace RC::GUI::BPMods const auto& mod_button = mod_info.ModButtons[i2]; if (ImGui::Button(std::format("{}", mod_button).c_str())) { - Output::send(SYSSTR("Mod button {} hit.\n"), to_system(mod_button)); + Output::send(SYSSTR("Mod button {} hit.\n"), mod_button); mod_info.ModActor->ModMenuButtonPressed(static_cast(i2)); } } diff --git a/UE4SS/src/LuaLibrary.cpp b/UE4SS/src/LuaLibrary.cpp index db8846e4f..c02ff101f 100644 --- a/UE4SS/src/LuaLibrary.cpp +++ b/UE4SS/src/LuaLibrary.cpp @@ -102,7 +102,7 @@ namespace RC::LuaLibrary // Logging will only happen to the debug console but it's something at least if (!Output::has_internal_error()) { - Output::send(SYSSTR("Error: {}\n"), to_system(e)); + Output::send(SYSSTR("Error: {}\n"), e); } else { diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 33d81d521..5625392ad 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -1153,7 +1153,7 @@ No overload found for function 'RegisterKeyBindAsync'. } catch (std::runtime_error& e) { - Output::send(SYSSTR("{}\n"), to_system(lua.handle_error(e.what()))); + Output::send(SYSSTR("{}\n"), lua.handle_error(e.what())); } }; @@ -1272,7 +1272,7 @@ No overload found for function 'RegisterKeyBind'. } catch (std::runtime_error& e) { - Output::send(SYSSTR("{}\n"), to_system(lua.handle_error(e.what()))); + Output::send(SYSSTR("{}\n"), lua.handle_error(e.what())); } }; @@ -3803,7 +3803,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - Output::send(SYSSTR("{}\n"), to_system(e.what())); + Output::send(SYSSTR("{}\n"), e.what()); } if (cancel) diff --git a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp index 68aca9a65..25012e71e 100644 --- a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp +++ b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp @@ -67,7 +67,7 @@ namespace RC::UEGenerator { continue; } - Output::send(SYSSTR("Found Relevant TMap Property: {} in Class: {}\n"), property_name, to_system(object->GetName())); + Output::send(SYSSTR("Found Relevant TMap Property: {} in Class: {}\n"), property_name, object->GetName()); auto& fm_json_object = fm_object.new_object(property_name); auto& uaapi_array = uaapi_object.new_array(property_name); diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 9aed1d28d..4581763da 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -99,7 +99,7 @@ namespace RC #define OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(StructName) \ for (const auto& [name, offset] : Unreal::StructName::MemberOffsets) \ { \ - Output::send(SYSSTR(#StructName "::{} = 0x{:X}\n"), to_system(name), offset); \ + Output::send(SYSSTR(#StructName "::{} = 0x{:X}\n"), name, offset); \ } auto output_all_member_offsets() -> void diff --git a/UVTD/src/main.cpp b/UVTD/src/main.cpp index 3d7cf8ebf..f5d65895a 100644 --- a/UVTD/src/main.cpp +++ b/UVTD/src/main.cpp @@ -89,7 +89,7 @@ auto thread_dll_start([[maybe_unused]] LPVOID thread_param) -> unsigned long } catch (std::exception& e) { - Output::send(SYSSTR("Exception caught: {}\n"), to_wstring(e.what())); + Output::send(SYSSTR("Exception caught: {}\n"), e.what()); } return 0; From 79822c54c1611ac72f79df2cd6d78ca11996769b Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 19 Feb 2024 05:19:31 -0600 Subject: [PATCH 048/213] remove use of generic_string() --- UE4SS/src/Mod/CppMod.cpp | 4 +-- UE4SS/src/Mod/LuaMod.cpp | 13 +++---- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 2 +- UE4SS/src/Signatures.cpp | 14 ++++---- UE4SS/src/UE4SSProgram.cpp | 30 ++++++++-------- deps/first/Helpers/include/Helpers/String.hpp | 36 +++++++++++-------- 6 files changed, 53 insertions(+), 46 deletions(-) diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 16f32f508..52a216584 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -68,9 +68,9 @@ namespace RC if (!Output::has_internal_error()) { Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), - (std::filesystem::path {m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)).generic_string() + "\n", + to_system_string(std::filesystem::path {m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)) + "\n", m_mod_name, - to_system(e.what())); + e.what()); } else { diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 5625392ad..4267028fb 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -646,10 +646,11 @@ namespace RC // Verify that there's a 'Scripts' directory // Give the full path to the 'Scripts' directory to the mod container std::filesystem::path mod_path_fs = m_mod_path; - m_scripts_path = (mod_path_fs / SYSSTR("scripts")).generic_string(); - + auto path = (mod_path_fs / SYSSTR("scripts")); + m_scripts_path = to_system_string(path); + // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod - if (!std::filesystem::exists(m_scripts_path)) + if (!std::filesystem::exists(path)) { set_installable(false); return; @@ -1454,8 +1455,8 @@ No overload found for function 'UnregisterHook'. { lua.throw_error("Could not dump objects and properties because the pointer to 'Mod' was nullptr"); } - UE4SSProgram::dump_all_objects_and_properties((std::filesystem::path{mod->m_program.get_object_dumper_output_directory()} / - UE4SSProgram::m_object_dumper_file_name).generic_string()); + UE4SSProgram::dump_all_objects_and_properties(to_system_string(std::filesystem::path{mod->m_program.get_object_dumper_output_directory()} / + UE4SSProgram::m_object_dumper_file_name)); return 0; }); @@ -3391,7 +3392,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. // Don't crash on syntax errors. try { - main_lua()->execute_file((std::filesystem::path {m_scripts_path} / SYSSTR("main.lua")).generic_string()); + main_lua()->execute_file(to_system_string(std::filesystem::path {m_scripts_path} / SYSSTR("main.lua"))); } catch (std::runtime_error& e) { diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index 4e79d9dec..86d631d7c 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -4041,7 +4041,7 @@ namespace RC::UEGenerator GeneratedFile::GeneratedFile(const FFilePath& full_file_path) { this->m_full_file_path = full_file_path; - this->m_file_base_name = full_file_path.filename().replace_extension().generic_string(); + this->m_file_base_name = to_system_string(full_file_path.filename().replace_extension()); this->m_current_indent_count = 0; } diff --git a/UE4SS/src/Signatures.cpp b/UE4SS/src/Signatures.cpp index fe275b454..c33a61b65 100644 --- a/UE4SS/src/Signatures.cpp +++ b/UE4SS/src/Signatures.cpp @@ -91,7 +91,7 @@ namespace RC auto setup_lua_scan_overrides(std::filesystem::path& working_directory, Unreal::UnrealInitializer::Config& config) -> void { - SystemStringType lua_guobjectarray_scan_script = (working_directory / "UE4SS_Signatures/GUObjectArray.lua").generic_string(); + SystemStringType lua_guobjectarray_scan_script = to_system_string(working_directory / "UE4SS_Signatures/GUObjectArray.lua"); if (std::filesystem::exists(lua_guobjectarray_scan_script)) { config.ScanOverrides.guobjectarray = [lua_guobjectarray_scan_script](std::vector& signature_containers, @@ -113,7 +113,7 @@ namespace RC }; } - SystemStringType lua_fts_scan_script = (working_directory / "UE4SS_Signatures/FName_ToString.lua").generic_string(); + SystemStringType lua_fts_scan_script = to_system_string(working_directory / "UE4SS_Signatures/FName_ToString.lua"); if (std::filesystem::exists(lua_fts_scan_script)) { config.ScanOverrides.fname_to_string = [lua_fts_scan_script](std::vector& signature_containers, @@ -135,7 +135,7 @@ namespace RC }; } - SystemStringType lua_fnc_scan_script = (working_directory / "UE4SS_Signatures/FName_Constructor.lua").generic_string(); + SystemStringType lua_fnc_scan_script = to_system_string(working_directory / "UE4SS_Signatures/FName_Constructor.lua"); if (std::filesystem::exists(lua_fnc_scan_script)) { config.ScanOverrides.fname_constructor = [lua_fnc_scan_script](std::vector& signature_containers, @@ -168,8 +168,8 @@ namespace RC } // For compatibility, we look for 'FMemory_Free.lua' if 'GMalloc.lua' doesn't exist. - SystemStringType lua_ffree_scan_script_new = (working_directory / "UE4SS_Signatures/GMalloc.lua").generic_string(); - SystemStringType lua_ffree_scan_script_compat = (working_directory / "UE4SS_Signatures/FMemory_Free.lua").generic_string(); + SystemStringType lua_ffree_scan_script_new = to_system_string(working_directory / "UE4SS_Signatures/GMalloc.lua"); + SystemStringType lua_ffree_scan_script_compat = to_system_string(working_directory / "UE4SS_Signatures/FMemory_Free.lua"); auto lua_ffree_scan_script = std::filesystem::exists(lua_ffree_scan_script_new) ? lua_ffree_scan_script_new : lua_ffree_scan_script_compat; if (std::filesystem::exists(lua_ffree_scan_script)) { @@ -193,7 +193,7 @@ namespace RC }; } - SystemStringType lua_sco_scan_script = (working_directory / "UE4SS_Signatures/StaticConstructObject.lua").generic_string(); + SystemStringType lua_sco_scan_script = to_system_string(working_directory / "UE4SS_Signatures/StaticConstructObject.lua"); if (std::filesystem::exists(lua_sco_scan_script)) { config.ScanOverrides.static_construct_object = [lua_sco_scan_script](std::vector& signature_containers, @@ -215,7 +215,7 @@ namespace RC }; } - SystemStringType lua_ftc_scan_script = (working_directory / "UE4SS_Signatures/FText_Constructor.lua").generic_string(); + SystemStringType lua_ftc_scan_script = to_system_string(working_directory / "UE4SS_Signatures/FText_Constructor.lua"); if (std::filesystem::exists(lua_ftc_scan_script)) { config.ScanOverrides.ftext_constructor = [lua_ftc_scan_script](std::vector& signature_containers, diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 4581763da..60649e1db 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -202,7 +202,7 @@ namespace RC // Setup the log file auto& file_device = Output::set_default_devices(); - file_device.set_file_name_and_path((m_log_directory / m_log_file_name).generic_string()); + file_device.set_file_name_and_path(to_system_string(m_log_directory / m_log_file_name)); create_simple_console(); @@ -399,8 +399,8 @@ namespace RC { ProfilerScope(); const std::filesystem::path moduleFilePath = std::filesystem::path(moduleFilePathString); - m_root_directory = moduleFilePath.parent_path().generic_string(); - m_module_file_path = moduleFilePath.generic_string(); + m_root_directory = to_system_string(moduleFilePath.parent_path()); + m_module_file_path = to_system_string(moduleFilePath); // The default working directory is the root directory // Can be changed by creating a directory in the root directory @@ -593,7 +593,7 @@ namespace RC TRY([&]() { ProfilerScopeNamed("loading virtual function offset overrides"); fprintf(stderr, "Loading offset\n"); - static File::StringType virtual_function_offset_override_file{(m_working_directory / SYSSTR("VTableLayout.ini")).generic_string()}; + static auto virtual_function_offset_override_file{m_working_directory / SYSSTR("VTableLayout.ini")}; if (std::filesystem::exists(virtual_function_offset_override_file)) { auto file = @@ -1039,7 +1039,7 @@ namespace RC set_error("is_directory ran into error %d", ec.value()); } - SystemStringType directory_lowercase = sub_directory.path().stem().generic_string(); + SystemStringType directory_lowercase = to_system_string(sub_directory.path().stem()); std::transform(directory_lowercase.begin(), directory_lowercase.end(), directory_lowercase.begin(), std::towlower); if (directory_lowercase == SYSSTR("shared")) @@ -1050,10 +1050,10 @@ namespace RC { // Create the mod but don't install it yet if (std::filesystem::exists(sub_directory.path() / "scripts")) - m_mods.emplace_back(std::make_unique(*this, sub_directory.path().stem().generic_string(), sub_directory.path().generic_string())); + m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); #ifdef HAS_CPPMOD if (std::filesystem::exists(sub_directory.path() / "dlls")) - m_mods.emplace_back(std::make_unique(*this, sub_directory.path().stem().generic_string(), sub_directory.path().generic_string())); + m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); #endif } } @@ -1249,7 +1249,7 @@ namespace RC return std::format("exists ran into error {}", ec.value()); } - auto mod = UE4SSProgram::find_mod_by_name(mod_directory.path().stem().generic_string(), UE4SSProgram::IsInstalled::Yes); + auto mod = UE4SSProgram::find_mod_by_name(to_system_string(mod_directory.path().stem()), UE4SSProgram::IsInstalled::Yes); if (!dynamic_cast(mod)) { continue; @@ -1412,7 +1412,7 @@ namespace RC auto UE4SSProgram::get_module_directory() -> File::StringViewType { - m_module_file_path_str = m_module_file_path.generic_string(); + m_module_file_path_str = to_system_string(m_module_file_path); return m_module_file_path_str; } @@ -1423,13 +1423,13 @@ namespace RC auto UE4SSProgram::get_working_directory() -> File::StringViewType { - m_working_directory_str = m_working_directory.generic_string(); + m_working_directory_str = to_system_string(m_working_directory); return m_working_directory_str; } auto UE4SSProgram::get_mods_directory() -> File::StringViewType { - m_mods_directory_str = m_mods_directory.generic_string(); + m_mods_directory_str = to_system_string(m_mods_directory); return m_mods_directory_str; } @@ -1440,7 +1440,7 @@ namespace RC auto UE4SSProgram::get_game_directory() -> File::StringViewType { - m_game_executable_str = m_game_executable_directory.generic_string(); + m_game_executable_str = to_system_string(m_game_executable_directory); return m_game_executable_str; } @@ -1631,9 +1631,9 @@ namespace RC return static_cast(find_mod_by_name(sysstr, installed_only, is_started)); } - auto UE4SSProgram::get_object_dumper_output_directory() -> const File::StringType + auto UE4SSProgram::get_object_dumper_output_directory() -> const SystemStringType { - return m_object_dumper_output_directory.generic_string(); + return to_system_string(m_object_dumper_output_directory); } auto UE4SSProgram::dump_uobject(UObject* object, std::unordered_set* in_dumped_fields, SystemStringType& out_line, bool is_below_425) -> void @@ -1743,7 +1743,7 @@ namespace RC } } - auto UE4SSProgram::dump_all_objects_and_properties(const File::StringType& output_path_and_file_name) -> void + auto UE4SSProgram::dump_all_objects_and_properties(const SystemStringType& output_path_and_file_name) -> void { /* Output::send(SYSSTR("Test msg with no fmt args, and no optional arg\n")); diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index 631c1e957..71d36e2c7 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -272,11 +272,6 @@ namespace RC #endif } - auto inline to_wstring(std::filesystem::path& input) -> std::wstring - { - return input.wstring(); - } - auto inline to_string(std::wstring& input) -> std::string { #ifdef WIN32 @@ -317,11 +312,6 @@ namespace RC return std::string{input}; } - auto inline to_string(std::filesystem::path& input) -> std::string - { - return input.string(); - } - auto inline to_u16string(std::wstring& input) -> std::u16string { #ifdef WIN32 @@ -361,11 +351,6 @@ namespace RC return std::u16string{input}; } - auto inline to_u16string(std::filesystem::path& input) -> std::u16string - { - return input.u16string(); - } - // Type traits to check if T is a string type that needs conversion template struct is_string_like_t : std::false_type {}; @@ -459,6 +444,27 @@ namespace RC template auto inline to_system_string(T&& input) -> SystemStringType { + if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) { + // just a workaround here + auto hold = input; + if constexpr (std::is_same_v) + { + return input.string(); + } + else if constexpr (std::is_same_v) + { + return input.wstring(); + } + else if constexpr (std::is_same_v) + { + return input.u16string(); + } + else + { + static_assert(dependent_false::value, "Unsupported SystemStringType."); + } + } + else if constexpr (std::is_same_v) { return to_string(input); From 7387bbf4b491d1f47e1c1fd478e48026964965b3 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 19 Feb 2024 05:29:22 -0600 Subject: [PATCH 049/213] lua strings --- UE4SS/src/LuaType/LuaUObject.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/UE4SS/src/LuaType/LuaUObject.cpp b/UE4SS/src/LuaType/LuaUObject.cpp index 71d8ef7e3..7cacb19c6 100644 --- a/UE4SS/src/LuaType/LuaUObject.cpp +++ b/UE4SS/src/LuaType/LuaUObject.cpp @@ -216,8 +216,8 @@ namespace RC::LuaType } else { - std::string parameter_type_name = to_string(property_type_fname.ToString()); - std::string parameter_name = to_string(param_next->GetName()); + auto parameter_type_name = to_string(property_type_fname.ToString()); + auto parameter_name = to_string(param_next->GetName()); lua.throw_error( std::format("Tried calling UFunction without a registered handler for parameter. Parameter '{}' of type '{}' not supported.", parameter_name, @@ -249,7 +249,7 @@ namespace RC::LuaType auto reuse_same_table = param->IsA() || param->IsA(); if (!reuse_same_table) { - lua_table.add_key(to_string(param->GetName()).c_str()); + lua_table.add_key(to_lua(param->GetName()).c_str()); } Unreal::FName param_type_fname = param->GetClass().GetFName(); @@ -271,7 +271,7 @@ namespace RC::LuaType } else { - std::string param_type_name = to_string(param_type_fname.ToString()); + auto param_type_name = to_string(param_type_fname.ToString()); lua.throw_error(std::format("Tried calling UFunction without a registered handler 'Out' param. Type '{}' not supported.", param_type_name)); } @@ -537,7 +537,7 @@ namespace RC::LuaType // return LoopAction::Continue; //} - std::string field_name = to_string(field->GetName()); + auto field_name = to_lua(field->GetName()); Unreal::FName field_type = field->GetClass().GetFName(); int32_t name_comparison_index = field_type.GetComparisonIndex(); @@ -562,10 +562,10 @@ namespace RC::LuaType } else { - std::string field_type_name = to_string(field_type.ToString()); + auto field_type_name = to_string(field_type.ToString()); lua.throw_error(std::format("Tried getting without a registered handler. 'StructProperty'.'{}' not supported. Field: '{}'", field_type_name, - field_name)); + to_string(field_name))); } }; @@ -581,7 +581,7 @@ namespace RC::LuaType for (Unreal::FProperty* field : script_struct->ForEachPropertyInChain()) { Unreal::FName field_type_fname = field->GetClass().GetFName(); - const std::string field_name = to_string(field->GetName()); + const auto field_name = to_lua(field->GetName()); // At the top of the stack now: table that has struct data @@ -622,10 +622,10 @@ namespace RC::LuaType } else { - std::string field_type_name = to_string(field_type_fname.ToString()); + auto field_type_name = to_string(field_type_fname.ToString()); params.lua.throw_error(std::format("Tried pushing (Operation::Set) StructProperty without a registered handler for field '{} {}'.", field_type_name, - field_name)); + to_string(field_name))); } }; @@ -724,7 +724,7 @@ namespace RC::LuaType } else { - std::string property_type_name = to_string(property_type_fname.ToString()); + auto property_type_name = to_string(property_type_fname.ToString()); lua.throw_error( std::format("Tried interacting with an array but the inner property has no registered handler. Property type '{}' not supported.", property_type_name)); @@ -739,7 +739,7 @@ namespace RC::LuaType int32_t name_comparison_index = inner_type_fname.GetComparisonIndex(); if (!StaticState::m_property_value_pushers.contains(name_comparison_index)) { - std::string inner_type_name = to_string(inner_type_fname.ToString()); + auto inner_type_name = to_string(inner_type_fname.ToString()); params.lua.throw_error(std::format("Tried pushing (Operation::Set) ArrayProperty with unsupported inner type of '{}'", inner_type_name)); } @@ -958,11 +958,11 @@ namespace RC::LuaType // Make global table to store enum name/value pairs -> START auto table = params.lua.prepare_new_table(); - std::string prop_name = to_string(params.property->GetName()); + auto prop_name = to_lua(params.property->GetName()); for (const auto& elem : enum_ptr->ForEachName()) { - std::string elem_name = to_string(elem.Key.ToString()); + auto elem_name = to_lua(elem.Key.ToString()); table.add_pair(elem_name.c_str(), elem.Value); } @@ -1297,7 +1297,7 @@ No overload found for function 'IsA'. { // We can either throw an error and kill the execution /**/ - std::string property_type_name = to_string(property_type.ToString()); + auto property_type_name = to_string(property_type.ToString()); lua.throw_error(std::format( "[handle_unreal_property_value] Tried accessing unreal property without a registered handler. Property type '{}' not supported.", property_type_name)); @@ -1422,7 +1422,7 @@ No overload found for function 'IsA'. { // We can either throw an error and kill the execution /**/ - std::string property_type_name = to_string(lua_object.m_type.ToString()); + auto property_type_name = to_string(lua_object.m_type.ToString()); lua.throw_error(std::format( "[RemoteUnrealParam::prepare_to_handle] Tried accessing unreal property without a registered handler. Property type '{}' not supported.", property_type_name)); From d222725c1ec66b36cb52c6f88ab8b539571b2bbb Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 19 Feb 2024 05:31:43 -0600 Subject: [PATCH 050/213] unused cast --- UE4SS/src/LuaType/LuaUObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/LuaType/LuaUObject.cpp b/UE4SS/src/LuaType/LuaUObject.cpp index 7cacb19c6..e5fdc1a57 100644 --- a/UE4SS/src/LuaType/LuaUObject.cpp +++ b/UE4SS/src/LuaType/LuaUObject.cpp @@ -1107,7 +1107,7 @@ namespace RC::LuaType if (params.lua.is_string()) { auto lua_string = params.lua.get_string(); - auto fstring = Unreal::FString{ to_ue(to_system(lua_string)).c_str() }; + auto fstring = Unreal::FString{ to_ue(lua_string).c_str() }; *string = fstring; } else if (params.lua.is_userdata()) From c59bce406021dd406d7ac1ded62bb474102260fc Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Mon, 19 Feb 2024 15:55:09 -0600 Subject: [PATCH 051/213] win32 compat --- UE4SS/include/GUI/GUITab.hpp | 6 +- UE4SS/include/GUI/LiveView.hpp | 8 +- .../LiveView/Filter/DefaultObjectsOnly.hpp | 2 +- .../GUI/LiveView/Filter/ExcludeClassName.hpp | 29 + .../LiveView/Filter/FunctionParamFlags.hpp | 2 +- .../GUI/LiveView/Filter/HasProperty.hpp | 6 +- .../GUI/LiveView/Filter/HasPropertyType.hpp | 6 +- .../LiveView/Filter/IncludeDefaultObjects.hpp | 2 +- .../GUI/LiveView/Filter/InstancesOnly.hpp | 2 +- .../GUI/LiveView/Filter/NonInstancesOnly.hpp | 2 +- UE4SS/include/Mod/CppMod.hpp | 8 +- UE4SS/include/Mod/CppUserModBase.hpp | 26 +- UE4SS/include/Mod/Mod.hpp | 6 +- .../SDKGenerator/UEHeaderGenerator.hpp | 140 +- UE4SS/include/UE4SSProgram.hpp | 12 +- UE4SS/src/EntryWin32.cpp | 2 +- UE4SS/src/GUI/BPMods.cpp | 3 + UE4SS/src/GUI/Dumpers.cpp | 21 +- UE4SS/src/GUI/LiveView.cpp | 23 +- UE4SS/src/GUI/UFunctionCallerWidget.cpp | 9 +- UE4SS/src/GUI/Windows.cpp | 4 +- UE4SS/src/LuaType/LuaModRef.cpp | 4 +- UE4SS/src/LuaType/LuaXProperty.cpp | 2 +- UE4SS/src/Mod/CppMod.cpp | 12 +- UE4SS/src/Mod/CppUserModBase.cpp | 2 +- UE4SS/src/Mod/LuaMod.cpp | 18 +- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 1615 +++++++++-------- UE4SS/src/Signatures.cpp | 2 +- UE4SS/src/UE4SSProgram.cpp | 15 +- UE4SS/src/USMapGenerator/Generator.cpp | 2 + UVTD/include/UVTD/Helpers.hpp | 4 +- UVTD/src/Helpers.cpp | 6 +- deps/first/File/include/File/FileDef.hpp | 7 + deps/first/File/include/File/Macros.hpp | 113 +- deps/first/File/src/FileType/WinFile.cpp | 2 +- deps/first/Helpers/include/Helpers/Format.hpp | 2 +- deps/first/Helpers/include/Helpers/String.hpp | 46 + .../IniParser/include/IniParser/JSON.hpp | 24 +- deps/first/JSON/include/JSON/Array.hpp | 4 +- deps/first/JSON/include/JSON/Bool.hpp | 2 +- deps/first/JSON/include/JSON/Common.hpp | 4 +- deps/first/JSON/include/JSON/KeyValuePair.hpp | 4 +- deps/first/JSON/include/JSON/Null.hpp | 2 +- deps/first/JSON/include/JSON/Number.hpp | 2 +- deps/first/JSON/include/JSON/Object.hpp | 26 +- .../first/JSON/include/JSON/Parser/Parser.hpp | 2 +- .../JSON/include/JSON/Parser/TokenParser.hpp | 6 +- deps/first/JSON/include/JSON/String.hpp | 10 +- deps/first/JSON/src/Array.cpp | 18 +- deps/first/JSON/src/Bool.cpp | 4 +- deps/first/JSON/src/Null.cpp | 4 +- deps/first/JSON/src/Number.cpp | 2 +- deps/first/JSON/src/Object.cpp | 36 +- deps/first/JSON/src/Parser/Parser.cpp | 17 +- deps/first/JSON/src/Parser/TokenParser.cpp | 19 +- deps/first/JSON/src/String.cpp | 6 +- .../include/LuaMadeSimple/LuaMadeSimple.hpp | 4 +- .../first/LuaMadeSimple/src/LuaMadeSimple.cpp | 4 +- .../SigScanner/SinglePassSigScannerWin32.hpp | 4 +- .../src/SinglePassSigScannerWin32.cpp | 9 +- 60 files changed, 1238 insertions(+), 1146 deletions(-) create mode 100644 UE4SS/include/GUI/LiveView/Filter/ExcludeClassName.hpp diff --git a/UE4SS/include/GUI/GUITab.hpp b/UE4SS/include/GUI/GUITab.hpp index 455e22567..c6a87cbfd 100644 --- a/UE4SS/include/GUI/GUITab.hpp +++ b/UE4SS/include/GUI/GUITab.hpp @@ -22,12 +22,12 @@ namespace RC::GUI private: RenderFunctionType render_function{}; CppUserModBase* owner{}; - StringType tab_name{}; + UEStringType tab_name{}; public: GUITab() = delete; - GUITab(StringViewType name, RenderFunctionType render_function) : tab_name(name), render_function(render_function){}; - GUITab(StringViewType name, RenderFunctionType render_function, CppUserModBase* owner) + GUITab(UEStringViewType name, RenderFunctionType render_function) : tab_name(name), render_function(render_function){}; + GUITab(UEStringViewType name, RenderFunctionType render_function, CppUserModBase* owner) : tab_name(name), render_function(render_function), owner(owner){}; ~GUITab() = default; diff --git a/UE4SS/include/GUI/LiveView.hpp b/UE4SS/include/GUI/LiveView.hpp index 1929cf773..3ac0306c0 100644 --- a/UE4SS/include/GUI/LiveView.hpp +++ b/UE4SS/include/GUI/LiveView.hpp @@ -61,9 +61,9 @@ namespace RC::GUI Output::Targets output{}; FProperty* property{}; UObject* container{}; - StringType object_name{}; - StringType property_name{}; - StringType property_value{}; + UEStringType object_name{}; + UEStringType property_name{}; + UEStringType property_value{}; size_t hash{}; std::string history{}; float history_previous_max_scroll_y{}; @@ -77,7 +77,7 @@ namespace RC::GUI std::pair function_hook_ids{}; Watch() = delete; - Watch(StringType&& object_name, StringType&& property_name); + Watch(UEStringType&& object_name, UEStringType&& property_name); }; private: diff --git a/UE4SS/include/GUI/LiveView/Filter/DefaultObjectsOnly.hpp b/UE4SS/include/GUI/LiveView/Filter/DefaultObjectsOnly.hpp index 121d01312..b8bfd3123 100644 --- a/UE4SS/include/GUI/LiveView/Filter/DefaultObjectsOnly.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/DefaultObjectsOnly.hpp @@ -7,7 +7,7 @@ namespace RC::GUI::Filter class DefaultObjectsOnly { public: - static inline StringType s_debug_name{STR("DefaultObjectsOnly")}; + static inline UEStringType s_debug_name{STR("DefaultObjectsOnly")}; static inline bool s_enabled{}; static auto pre_eval(UObject* object) -> bool diff --git a/UE4SS/include/GUI/LiveView/Filter/ExcludeClassName.hpp b/UE4SS/include/GUI/LiveView/Filter/ExcludeClassName.hpp new file mode 100644 index 000000000..6bf97062e --- /dev/null +++ b/UE4SS/include/GUI/LiveView/Filter/ExcludeClassName.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +namespace RC::GUI::Filter +{ + class ExcludeClassName + { + public: + static inline UEStringType s_debug_name{STR("ExcludeClassName")}; + static inline UEStringType s_value{}; + static inline std::string s_internal_value{}; + + static auto post_eval(UObject* object) -> bool + { + if (!s_value.empty()) + { + auto class_name = object->GetClassPrivate()->GetName(); + auto pos = class_name.find(s_value); + return pos != class_name.npos; + } + else + { + return false; + } + } + }; +} // namespace RC::GUI::Filter diff --git a/UE4SS/include/GUI/LiveView/Filter/FunctionParamFlags.hpp b/UE4SS/include/GUI/LiveView/Filter/FunctionParamFlags.hpp index 3880d367a..be64a26aa 100644 --- a/UE4SS/include/GUI/LiveView/Filter/FunctionParamFlags.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/FunctionParamFlags.hpp @@ -9,7 +9,7 @@ namespace RC::GUI::Filter class FunctionParamFlags { public: - static inline StringType s_debug_name{STR("FunctionParamFlags")}; + static inline UEStringType s_debug_name{STR("FunctionParamFlags")}; static inline bool s_enabled{}; static inline std::array s_checkboxes{}; static inline EPropertyFlags s_value{}; diff --git a/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp b/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp index 3f2f6ce4a..9a390bd24 100644 --- a/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp @@ -8,9 +8,9 @@ namespace RC::GUI::Filter class HasProperty { public: - static inline StringType s_debug_name{STR("HasProperty")}; - static inline std::string s_internal_properties{}; - static inline std::vector list_properties{}; + static inline UEStringType s_debug_name{STR("HasProperty")}; + static inline UEStringType s_value{}; + static inline std::string s_internal_value{}; static auto post_eval(UObject* object) -> bool { diff --git a/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp b/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp index 97484ba7a..1d7203e44 100644 --- a/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp @@ -10,9 +10,9 @@ namespace RC::GUI::Filter class HasPropertyType { public: - static inline StringType s_debug_name{STR("HasPropertyType")}; - static inline std::string s_internal_property_types{}; - static inline std::vector list_property_types{}; + static inline UEStringType s_debug_name{STR("HasPropertyType")}; + static inline FName s_value{}; + static inline std::string s_internal_value{}; static auto post_eval(UObject* object) -> bool { diff --git a/UE4SS/include/GUI/LiveView/Filter/IncludeDefaultObjects.hpp b/UE4SS/include/GUI/LiveView/Filter/IncludeDefaultObjects.hpp index 2dc3f3b9a..655d870c5 100644 --- a/UE4SS/include/GUI/LiveView/Filter/IncludeDefaultObjects.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/IncludeDefaultObjects.hpp @@ -7,7 +7,7 @@ namespace RC::GUI::Filter class IncludeDefaultObjects { public: - static inline StringType s_debug_name{STR("IncludeDefaultObjects")}; + static inline UEStringType s_debug_name{STR("IncludeDefaultObjects")}; static inline bool s_enabled{true}; static auto pre_eval(UObject* object) -> bool diff --git a/UE4SS/include/GUI/LiveView/Filter/InstancesOnly.hpp b/UE4SS/include/GUI/LiveView/Filter/InstancesOnly.hpp index 298afae00..c36be7839 100644 --- a/UE4SS/include/GUI/LiveView/Filter/InstancesOnly.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/InstancesOnly.hpp @@ -7,7 +7,7 @@ namespace RC::GUI::Filter class InstancesOnly { public: - static inline StringType s_debug_name{STR("InstancesOnly")}; + static inline UEStringType s_debug_name{STR("InstancesOnly")}; static inline bool s_enabled{}; static auto pre_eval(UObject* object) -> bool { diff --git a/UE4SS/include/GUI/LiveView/Filter/NonInstancesOnly.hpp b/UE4SS/include/GUI/LiveView/Filter/NonInstancesOnly.hpp index 23bfb47ef..9716d8a2b 100644 --- a/UE4SS/include/GUI/LiveView/Filter/NonInstancesOnly.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/NonInstancesOnly.hpp @@ -8,7 +8,7 @@ namespace RC::GUI::Filter class NonInstancesOnly { public: - static inline StringType s_debug_name{STR("NonInstancesOnly")}; + static inline UEStringType s_debug_name{STR("NonInstancesOnly")}; static inline bool s_enabled{}; static auto pre_eval(UObject* object) -> bool diff --git a/UE4SS/include/Mod/CppMod.hpp b/UE4SS/include/Mod/CppMod.hpp index 18466a457..b12a60e2c 100644 --- a/UE4SS/include/Mod/CppMod.hpp +++ b/UE4SS/include/Mod/CppMod.hpp @@ -28,7 +28,7 @@ namespace RC typedef void (*uninstall_type)(CppUserModBase*); private: - SystemStringType m_dlls_path; + UEStringType m_dlls_path; #ifdef WIN32 HMODULE m_main_dll_module = NULL; DLL_DIRECTORY_COOKIE m_dlls_path_cookie = NULL; @@ -39,7 +39,7 @@ namespace RC CppUserModBase* m_mod = nullptr; public: - CppMod(UE4SSProgram&, SystemStringType&& mod_name, SystemStringType&& mod_path); + CppMod(UE4SSProgram&, UEStringType&& mod_name, UEStringType&& mod_path); CppMod(CppMod&) = delete; CppMod(CppMod&&) = delete; ~CppMod() override; @@ -57,7 +57,7 @@ namespace RC auto fire_on_lua_start(LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, std::vector& hook_luas) -> void; - auto fire_on_lua_stop(SystemStringViewType mod_name, + auto fire_on_lua_stop(UEStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -70,6 +70,6 @@ namespace RC auto fire_ui_init() -> void override; auto fire_program_start() -> void override; auto fire_update() -> void override; - auto fire_dll_load(SystemStringViewType dll_name) -> void; + auto fire_dll_load(UEStringViewType dll_name) -> void; }; } // namespace RC diff --git a/UE4SS/include/Mod/CppUserModBase.hpp b/UE4SS/include/Mod/CppUserModBase.hpp index 76d48ed41..cab82b4b6 100644 --- a/UE4SS/include/Mod/CppUserModBase.hpp +++ b/UE4SS/include/Mod/CppUserModBase.hpp @@ -14,11 +14,11 @@ namespace RC { struct ModMetadata { - const SystemStringType ModName{}; - const SystemStringType ModVersion{}; - const SystemStringType ModDescription{}; - const SystemStringType ModAuthors{}; - const SystemStringType ModIntendedSDKVersion{}; + const UEStringType ModName{}; + const UEStringType ModVersion{}; + const UEStringType ModDescription{}; + const UEStringType ModAuthors{}; + const UEStringType ModIntendedSDKVersion{}; }; namespace LuaMadeSimple @@ -35,11 +35,11 @@ namespace RC std::vector> GUITabs{}; #endif public: - SystemStringType ModName{}; - SystemStringType ModVersion{}; - SystemStringType ModDescription{}; - SystemStringType ModAuthors{}; - SystemStringType ModIntendedSDKVersion{}; + UEStringType ModName{}; + UEStringType ModVersion{}; + UEStringType ModDescription{}; + UEStringType ModAuthors{}; + UEStringType ModIntendedSDKVersion{}; public: RC_UE4SS_API CppUserModBase(); @@ -75,7 +75,7 @@ namespace RC * @param async_lua This is the Lua instance for asynchronous things like ExecuteAsync and ExecuteWithDelay. * @param hook_luas This is a container of Lua instances that are used for game-thread hooks like ExecuteInGameThread. */ - RC_UE4SS_API virtual auto on_lua_start(SystemStringViewType mod_name, + RC_UE4SS_API virtual auto on_lua_start(UEStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -106,7 +106,7 @@ namespace RC * @param async_lua This is the Lua instance for asynchronous things like ExecuteAsync and ExecuteWithDelay. * @param hook_luas This is a container of Lua instances that are used for game-thread hooks like ExecuteInGameThread. */ - RC_UE4SS_API virtual auto on_lua_stop(SystemStringViewType mod_name, + RC_UE4SS_API virtual auto on_lua_stop(UEStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -128,7 +128,7 @@ namespace RC { } - RC_UE4SS_API virtual auto on_dll_load(SystemStringType dll_name) -> void + RC_UE4SS_API virtual auto on_dll_load(UEStringViewType dll_name) -> void { } diff --git a/UE4SS/include/Mod/Mod.hpp b/UE4SS/include/Mod/Mod.hpp index 7fca91ca7..fd921777c 100644 --- a/UE4SS/include/Mod/Mod.hpp +++ b/UE4SS/include/Mod/Mod.hpp @@ -26,8 +26,8 @@ namespace RC protected: #pragma warning(disable : 4251) - SystemStringType m_mod_name; - SystemStringType m_mod_path; + UEStringType m_mod_name; + UEStringType m_mod_path; #pragma warning(default : 4251) protected: @@ -45,7 +45,7 @@ namespace RC }; public: - Mod(UE4SSProgram&, SystemStringType&& mod_name, SystemStringType&& mod_path); + Mod(UE4SSProgram&, UEStringType&& mod_name, UEStringType&& mod_path); virtual ~Mod() = default; public: diff --git a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp index a3822f3ed..3b4e21d1f 100644 --- a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp +++ b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp @@ -67,14 +67,14 @@ namespace RC::UEGenerator struct PropertyTypeDeclarationContext { - SystemStringType context_name; + UEStringType context_name; class GeneratedSourceFile* source_file; bool is_top_level_declaration; bool* out_is_bitmask_bool; - PropertyTypeDeclarationContext(const SystemStringType& context_name, + PropertyTypeDeclarationContext(const UEStringType& context_name, GeneratedSourceFile* source_file = NULL, bool is_top_level_declaration = false, bool* out_is_bitmask_bool = NULL) @@ -93,26 +93,26 @@ namespace RC::UEGenerator struct StringInsensitiveCompare { - auto operator()(const SystemStringType& a, const SystemStringType& b) const -> bool + auto operator()(const UEStringType& a, const UEStringType& b) const -> bool { #ifdef LINUX + // TODO: Create a case insensitive string compare for Linux return strcasecmp(a.c_str(), b.c_str()) < 0; - #else return _wcsicmp(a.c_str(), b.c_str()) < 0; #endif } }; - using CaseInsensitiveSet = ::std::set; + using CaseInsensitiveSet = ::std::set; class GeneratedFile { protected: - SystemStringType m_file_base_name; + UEStringType m_file_base_name; FFilePath m_full_file_path; - SystemStringType m_file_contents_buffer; + UEStringType m_file_contents_buffer; int32_t m_current_indent_count; public: @@ -124,23 +124,23 @@ namespace RC::UEGenerator GeneratedFile(GeneratedFile&&) = default; auto operator=(const GeneratedFile&) -> void = delete; - auto append_line(const SystemStringType& line) -> void; - auto append_line_no_indent(const SystemStringType& line) -> void; + auto append_line(const UEStringType& line) -> void; + auto append_line_no_indent(const UEStringType& line) -> void; auto begin_indent_level() -> void; auto end_indent_level() -> void; auto serialize_file_content_to_disk() -> bool; virtual auto has_content_to_save() const -> bool; - virtual auto generate_file_contents() -> SystemStringType; + virtual auto generate_file_contents() -> UEStringType; }; class GeneratedSourceFile : public GeneratedFile { private: - SystemStringType m_file_module_name; + UEStringType m_file_module_name; ::std::map m_dependencies; - ::std::set m_extra_includes; - mutable ::std::set m_dependency_module_names; + ::std::set m_extra_includes; + mutable ::std::set m_dependency_module_names; UObject* m_object; GeneratedSourceFile* m_header_file; bool m_is_implementation_file; @@ -150,11 +150,11 @@ namespace RC::UEGenerator // workaround for clang tuple bug // https://github.com/llvm/llvm-project/issues/17042 struct attachment_data { - SystemStringType property_type; // <0> - SystemStringType attach_string; // <1> + UEStringType property_type; // <0> + UEStringType attach_string; // <1> bool access_type; // <2> - attachment_data(const SystemStringType& property_type, const SystemStringType& attach_string, bool access_type) + attachment_data(const UEStringType& property_type, const UEStringType& attach_string, bool access_type) : property_type(property_type), attach_string(attach_string), access_type(access_type) { } @@ -165,11 +165,11 @@ namespace RC::UEGenerator auto operator=(attachment_data&&) -> attachment_data& = default; }; - SystemStringType m_implementation_constructor; - ::std::unordered_set parent_property_names{}; + UEStringType m_implementation_constructor; + ::std::unordered_set parent_property_names{}; ::std::map attachments{}; - GeneratedSourceFile(const FFilePath& file_path, const SystemStringType& file_module_name, bool is_implementation_file, UObject* object); + GeneratedSourceFile(const FFilePath& file_path, const UEStringType& file_module_name, bool is_implementation_file, UObject* object); // Delete copy and move constructors and assignment operator GeneratedSourceFile(const GeneratedSourceFile&) = delete; @@ -178,9 +178,9 @@ namespace RC::UEGenerator auto set_header_file(GeneratedSourceFile* header_file) -> void; auto add_dependency_object(UObject* object, DependencyLevel dependency_level) -> void; - auto add_extra_include(const SystemStringType& included_file_name) -> void; + auto add_extra_include(const UEStringType& included_file_name) -> void; - auto get_header_module_name() const -> const SystemStringType& + auto get_header_module_name() const -> const UEStringType& { return m_file_module_name; } @@ -204,30 +204,30 @@ namespace RC::UEGenerator virtual auto has_content_to_save() const -> bool override; - auto copy_dependency_module_names(::std::set& out_dependency_module_names) const -> void + auto copy_dependency_module_names(::std::set& out_dependency_module_names) const -> void { out_dependency_module_names.insert(m_dependency_module_names.begin(), m_dependency_module_names.end()); } auto static create_source_file(const FFilePath& root_dir, - const SystemStringType& module_name, - const SystemStringType& base_name, + const UEStringType& module_name, + const UEStringType& base_name, bool is_implementation_file, UObject* object) -> GeneratedSourceFile; - virtual auto generate_file_contents() -> SystemStringType override; + virtual auto generate_file_contents() -> UEStringType override; protected: auto has_dependency(UObject* object, DependencyLevel dependency_level) -> bool; - auto generate_pre_declarations_string() const -> SystemStringType; - auto generate_includes_string() const -> SystemStringType; + auto generate_pre_declarations_string() const -> UEStringType; + auto generate_includes_string() const -> UEStringType; }; struct UniqueName { static constexpr int32_t HAS_NO_DUPLICATES = 1; - SystemStringType name{}; + UEStringType name{}; int32_t usable_id{HAS_NO_DUPLICATES}; }; @@ -235,26 +235,26 @@ namespace RC::UEGenerator { private: FFilePath m_root_directory; - SystemStringType m_primary_module_name; + UEStringType m_primary_module_name; - ::std::set m_forced_module_dependencies; - ::std::set m_ignored_module_names; - ::std::set m_classes_with_object_initializer; + ::std::set m_forced_module_dependencies; + ::std::set m_ignored_module_names; + ::std::set m_classes_with_object_initializer; - ::std::unordered_map m_underlying_enum_types; - ::std::set m_blueprint_visible_enums; - ::std::set m_blueprint_visible_structs; - ::std::map>> m_module_dependencies; + ::std::unordered_map m_underlying_enum_types; + ::std::set m_blueprint_visible_enums; + ::std::set m_blueprint_visible_structs; + ::std::map>> m_module_dependencies; ::std::vector m_header_files; ::std::unordered_set m_structs_that_need_get_type_hash; // Storage to ensure that we don't have duplicate file names - static ::std::map m_used_file_names; + static ::std::map m_used_file_names; static ::std::map m_dependency_object_to_unique_id; // Storage for class defaultsubojects when populating property initializers - ::std::unordered_map m_class_subobjects; + ::std::unordered_map m_class_subobjects; public: UEHeaderGenerator(const FFilePath& root_directory); @@ -268,8 +268,8 @@ namespace RC::UEGenerator auto dump_native_packages() -> void; auto generate_object_description_file(UObject* object) -> bool; - auto generate_module_build_file(const SystemStringType& module_name) -> void; - auto generate_module_implementation_file(const SystemStringType& module_name) -> void; + auto generate_module_build_file(const UEStringType& module_name) -> void; + auto generate_module_implementation_file(const UEStringType& module_name) -> void; private: auto generate_interface_definition(UClass* function, GeneratedSourceFile& header_data) -> void; @@ -289,7 +289,7 @@ namespace RC::UEGenerator const CaseInsensitiveSet& blacklisted_property_names, bool generate_as_override = false) -> void; - auto generate_property_value(UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const SystemStringType& property_scope) + auto generate_property_value(UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const UEStringType& property_scope) -> void; auto generate_function_implementation(UClass* uclass, UFunction* function, @@ -297,49 +297,49 @@ namespace RC::UEGenerator bool is_generating_interface, const CaseInsensitiveSet& blacklisted_property_names) -> void; - auto generate_interface_flags(UClass* uinterface) const -> SystemStringType; - auto generate_class_flags(UClass* uclass) const -> SystemStringType; - auto generate_struct_flags(UScriptStruct* script_struct) const -> SystemStringType; - auto generate_enum_flags(UEnum* uenum) const -> SystemStringType; - auto generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> SystemStringType; - auto generate_property_flags(FProperty* property) const -> SystemStringType; - auto generate_function_argument_flags(FProperty* property) const -> SystemStringType; - auto generate_function_flags(UFunction* function, bool is_function_pure_virtual = false) const -> SystemStringType; + auto generate_interface_flags(UClass* uinterface) const -> UEStringType; + auto generate_class_flags(UClass* uclass) const -> UEStringType; + auto generate_struct_flags(UScriptStruct* script_struct) const -> UEStringType; + auto generate_enum_flags(UEnum* uenum) const -> UEStringType; + auto generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> UEStringType; + auto generate_property_flags(FProperty* property) const -> UEStringType; + auto generate_function_argument_flags(FProperty* property) const -> UEStringType; + auto generate_function_flags(UFunction* function, bool is_function_pure_virtual = false) const -> UEStringType; auto generate_function_parameter_list(UClass* property, UFunction* function, GeneratedSourceFile& header_data, bool generate_comma_before_name, - const SystemStringType& context_name, + const UEStringType& context_name, const CaseInsensitiveSet& blacklisted_property_names, - int32_t* out_num_params = NULL) -> SystemStringType; - auto generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType; + int32_t* out_num_params = NULL) -> UEStringType; + auto generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const UEStringType& ContextName) -> UEStringType; - auto generate_enum_value(UEnum* uenum, int64_t enum_value) -> SystemStringType; + auto generate_enum_value(UEnum* uenum, int64_t enum_value) -> UEStringType; auto generate_simple_assignment_expression(FProperty* property, - const SystemStringType& value, + const UEStringType& value, GeneratedSourceFile& implementation_file, - const SystemStringType& property_scope, - const SystemStringType& operator_type = SYSSTR(" = ")) -> void; + const UEStringType& property_scope, + const UEStringType& operator_type = SYSSTR(" = ")) -> void; auto generate_advanced_assignment_expression(FProperty* property, - const SystemStringType& value, + const UEStringType& value, GeneratedSourceFile& implementation_file, - const SystemStringType& property_scope, - const SystemStringType& property_type, - const SystemStringType& operator_type = SYSSTR(" = ")) -> void; + const UEStringType& property_scope, + const UEStringType& property_type, + const UEStringType& operator_type = SYSSTR(" = ")) -> void; - auto static generate_parameter_count_string(int32_t parameter_count) -> SystemStringType; - auto static determine_primary_game_module_name() -> SystemStringType; + auto static generate_parameter_count_string(int32_t parameter_count) -> UEStringType; + auto static determine_primary_game_module_name() -> UEStringType; public: - auto add_module_and_sub_module_dependencies(::std::set& out_module_dependencies, const SystemStringType& module_name, bool add_self_module = true) + auto add_module_and_sub_module_dependencies(::std::set& out_module_dependencies, const UEStringType& module_name, bool add_self_module = true) -> void; auto static collect_blacklisted_property_names(UObject* property) -> CaseInsensitiveSet; - auto static generate_object_pre_declaration(UObject* object) -> ::std::vector<::std::vector>; + auto static generate_object_pre_declaration(UObject* object) -> ::std::vector<::std::vector>; - auto static convert_module_name_to_api_name(const SystemStringType& module_name) -> SystemStringType; - auto static get_module_name_for_package(UObject* package) -> SystemStringType; - auto static sanitize_enumeration_name(const SystemStringType& enumeration_name) -> SystemStringType; + auto static convert_module_name_to_api_name(const UEStringType& module_name) -> UEStringType; + auto static get_module_name_for_package(UObject* package) -> UEStringType; + auto static sanitize_enumeration_name(const UEStringType& enumeration_name) -> UEStringType; auto static get_highest_enum(UEnum* uenum) -> int64_t; auto static get_lowest_enum(UEnum* uenum) -> int64_t; @@ -350,8 +350,8 @@ namespace RC::UEGenerator auto static append_access_modifier(GeneratedSourceFile& header_data, AccessModifier needed_access, AccessModifier& current_access) -> void; auto static get_property_access_modifier(FProperty* property) -> AccessModifier; auto static get_function_access_modifier(UFunction* function) -> AccessModifier; - auto static create_string_literal(const SystemStringType& string) -> SystemStringType; - auto static get_header_name_for_object(UObject* object, bool get_existing_header = false) -> SystemStringType; - auto static generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) -> SystemStringType; + auto static create_string_literal(const UEStringType& string) -> UEStringType; + auto static get_header_name_for_object(UObject* object, bool get_existing_header = false) -> UEStringType; + auto static generate_cross_module_include(UObject* object, const UEStringType& module_name, const UEStringType& fallback_name) -> UEStringType; }; } // namespace RC::UEGenerator diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index 60a33b255..c1f1ccfd4 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -240,7 +240,7 @@ namespace RC RC_UE4SS_API auto get_working_directory() -> SystemStringViewType; RC_UE4SS_API auto get_mods_directory() -> SystemStringViewType; RC_UE4SS_API auto get_legacy_root_directory() -> SystemStringViewType; - RC_UE4SS_API auto UE4SSProgram::get_game_directory() -> SystemStringViewType; + RC_UE4SS_API auto get_game_directory() -> SystemStringViewType; RC_UE4SS_API auto generate_uht_compatible_headers() -> void; RC_UE4SS_API auto generate_cxx_headers(const std::filesystem::path& output_dir) -> void; RC_UE4SS_API auto generate_lua_types(const std::filesystem::path& output_dir) -> void; @@ -308,11 +308,15 @@ namespace RC template static auto find_mod_by_name(SystemStringViewType mod_name, IsInstalled is_installed = IsInstalled::No, IsStarted is_started = IsStarted::No) -> T* { - return find_mod_by_name(to_system(mod_name), is_installed, is_started); + return find_mod_by_name(to_system_string(mod_name), is_installed, is_started); }; - RC_UE4SS_API static auto find_lua_mod_by_name(UEStringViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; - RC_UE4SS_API static auto find_lua_mod_by_name(SystemStringViewType mod_name, IsInstalled = IsInstalled::No, IsStarted = IsStarted::No) -> LuaMod*; + template + RC_UE4SS_API static auto find_lua_mod_by_name(S mod_name, IsInstalled is_installed = IsInstalled::No, IsStarted is_started = IsStarted::No) -> LuaMod* + { + auto mod_name_str = to_system_string(mod_name); + return static_cast(find_mod_by_name(mod_name_str, is_installed, is_started)); + } static auto static_cleanup() -> void; RC_UE4SS_API static auto get_program() -> UE4SSProgram& { diff --git a/UE4SS/src/EntryWin32.cpp b/UE4SS/src/EntryWin32.cpp index 1673a7914..31deff417 100644 --- a/UE4SS/src/EntryWin32.cpp +++ b/UE4SS/src/EntryWin32.cpp @@ -138,7 +138,7 @@ auto WIN_API_FUNCTION_NAME(HMODULE hModule, DWORD ul_reason_for_call, [[maybe_un std::filesystem::path get_executable_path() { wchar_t exe_path_buffer[1024]; GetModuleFileNameW(GetModuleHandle(nullptr), exe_path_buffer, 1023); - return std::filesystem::path(buffer); + return std::filesystem::path(exe_path_buffer); } diff --git a/UE4SS/src/GUI/BPMods.cpp b/UE4SS/src/GUI/BPMods.cpp index 9e41785fc..25428ae20 100644 --- a/UE4SS/src/GUI/BPMods.cpp +++ b/UE4SS/src/GUI/BPMods.cpp @@ -16,6 +16,9 @@ #include +#undef min +#undef max + namespace RC::GUI::BPMods { using namespace RC::Unreal; diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index 460a4923f..736f76460 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -25,6 +25,9 @@ #include #include +#undef min +#undef max + namespace RC::GUI::Dumpers { using namespace ::RC::Unreal; @@ -79,9 +82,9 @@ namespace RC::GUI::Dumpers FMeshUVChannelInfo UVChannelData; }; - auto generate_root_component_csv(UObject* root_component) -> StringType + auto generate_root_component_csv(UObject* root_component) -> UEStringType { - StringType root_actor_buffer{}; + UEStringType root_actor_buffer{}; static auto location_property = root_component->GetPropertyByNameInChain(STR("RelativeLocation")); static auto rotation_property = root_component->GetPropertyByNameInChain(STR("RelativeRotation")); @@ -105,9 +108,9 @@ namespace RC::GUI::Dumpers return root_actor_buffer; } - static auto generate_actors_csv_file(UClass* dump_actor_class) -> StringType + static auto generate_actors_csv_file(UClass* dump_actor_class) -> UEStringType { - StringType file_buffer{}; + UEStringType file_buffer{}; file_buffer.append(STR("---,Actor,Location,Rotation,Scale,Meshes\n")); @@ -126,7 +129,7 @@ namespace RC::GUI::Dumpers return LoopAction::Continue; } - StringType actor_buffer{}; + UEStringType actor_buffer{}; actor_buffer.append(std::format(SYSSTR("Row_{},"), actor_count)); @@ -175,7 +178,7 @@ namespace RC::GUI::Dumpers { throw std::runtime_error{"integer overflow when converting material_type_space_location signed\n"}; } - auto material_typeless_name = StringViewType{material_full_name.begin() + static_cast(material_type_space_location) + 1, + auto material_typeless_name = UEStringViewType{material_full_name.begin() + static_cast(material_type_space_location) + 1, material_full_name.end()}; actor_buffer.append(std::format(SYSSTR("{}'"), material_interface->GetClassPrivate()->GetName())); @@ -243,7 +246,7 @@ namespace RC::GUI::Dumpers return file_buffer; } - static auto generate_actors_json_file(UClass* class_to_dump) -> StringType + static auto generate_actors_json_file(UClass* class_to_dump) -> UEStringType { auto global_json_array = JSON::Array{}; @@ -270,13 +273,13 @@ namespace RC::GUI::Dumpers static auto class_property = game_mode_base->GetPropertyByNameInChain(STR("GameStateClass")); FString actor_class_string{}; class_property->ExportTextItem(actor_class_string, &actor->GetClassPrivate(), nullptr, nullptr, 0); - actor_json_object.new_string(STR("Actor"), std::format(SYSSTR("{}"), StringViewType{actor_class_string.GetCharArray()})); + actor_json_object.new_string(STR("Actor"), std::format(SYSSTR("{}"), UEStringViewType{actor_class_string.GetCharArray()})); auto& root_component_json_object = actor_json_object.new_object(STR("RootComponent")); FString root_component_class_string{}; class_property->ExportTextItem(root_component_class_string, &(*root_component)->GetClassPrivate(), nullptr, nullptr, 0); - root_component_json_object.new_string(STR("SceneComponentClass"), std::format(SYSSTR("{}"), StringViewType{root_component_class_string.GetCharArray()})); + root_component_json_object.new_string(STR("SceneComponentClass"), std::format(SYSSTR("{}"), UEStringViewType{root_component_class_string.GetCharArray()})); auto& location_json_object = root_component_json_object.new_object(STR("Location")); auto location = (*root_component)->GetValuePtrByPropertyNameInChain(STR("RelativeLocation")); diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 5623f651d..ded85b3dd 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -49,6 +49,9 @@ #include #include +#undef max +#undef min + namespace RC::GUI { using namespace Unreal; @@ -560,7 +563,7 @@ namespace RC::GUI case LiveView::Watch::AcquisitionMethod::StaticFindObject: { auto object_full_name = watch.container->GetFullName(); auto object_type_space_location = object_full_name.find(STR(" ")); - auto object_typeless_name = StringType{object_full_name.begin() + object_type_space_location + 1, object_full_name.end()}; + auto object_typeless_name = UEStringType{object_full_name.begin() + object_type_space_location + 1, object_full_name.end()}; json_object->new_string(STR("AcquisitionID"), object_typeless_name); break; } @@ -672,7 +675,7 @@ namespace RC::GUI } } - auto json_file = File::open(StringType{UE4SSProgram::get_program().get_working_directory()} + std::format(SYSSTR("\\watches\\watches.meta.json")), + auto json_file = File::open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / "watches" / "watches.meta.json", File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); @@ -709,10 +712,10 @@ namespace RC::GUI UObjectArray::RemoveUObjectDeleteListener(&FLiveViewDeleteListener::LiveViewDeleteListener); } - LiveView::Watch::Watch(StringType&& object_name, StringType&& property_name) : object_name(object_name), property_name(property_name) + LiveView::Watch::Watch(UEStringType&& object_name, UEStringType&& property_name) : object_name(object_name), property_name(property_name) { auto& file_device = output.get_device(); - file_device.set_file_name_and_path(StringType{UE4SSProgram::get_program().get_working_directory()} + + file_device.set_file_name_and_path(UEStringType{UE4SSProgram::get_program().get_working_directory()} + std::format(SYSSTR("\\watches\\ue4ss_watch_{}_{}.txt"), object_name, property_name)); file_device.set_formatter([](File::StringViewType string) -> File::StringType { const auto when_as_string = std::format(SYSSTR("{:%Y-%m-%d %H:%M:%S}"), std::chrono::system_clock::now()); @@ -1981,7 +1984,7 @@ namespace RC::GUI } auto obj = container_type == ContainerType::Array ? *static_cast(container) : static_cast(container); - StringType parent_name{}; + UEStringType parent_name{}; if (container_type == ContainerType::Object) { parent_name = obj ? obj->GetName() : STR("None"); @@ -2176,7 +2179,7 @@ namespace RC::GUI if (ImGui::Button("Apply")) { FOutputDevice placeholder_device{}; - StringType new_name = to_wstring(m_current_property_value_buffer); + UEStringType new_name = to_wstring(m_current_property_value_buffer); FName new_key = FName(new_name, FNAME_Add); uenum->EditNameAt(index, new_key); if (uenum->GetEnumNames()[index].Key.ToString() != new_name) @@ -2260,7 +2263,7 @@ namespace RC::GUI if (ImGui::Button("Apply")) { FOutputDevice placeholder_device{}; - StringType new_name = to_wstring(m_current_property_value_buffer); + UEStringType new_name = to_wstring(m_current_property_value_buffer); FName new_key = FName(new_name, FNAME_Add); int64 value = names[index].Value; @@ -2897,7 +2900,7 @@ namespace RC::GUI { FString live_value_fstring{}; watch.property->ExportTextItem(live_value_fstring, watch.property->ContainerPtrToValuePtr(watch.container), nullptr, nullptr, 0); - auto live_value_string = StringType{live_value_fstring.GetCharArray()}; + auto live_value_string = UEStringType{live_value_fstring.GetCharArray()}; if (watch.property_value == live_value_string) { @@ -2943,7 +2946,7 @@ namespace RC::GUI auto num_params = function->GetNumParms(); const auto when_as_string = std::format(SYSSTR("{:%H:%M:%S}"), std::chrono::system_clock::now()); - StringType buffer{std::format(SYSSTR("Received call @ {}.\n"), when_as_string)}; + UEStringType buffer{std::format(SYSSTR("Received call @ {}.\n"), when_as_string)}; buffer.append(std::format(SYSSTR(" Context:\n {}\n"), context.Context->GetFullName())); @@ -3414,7 +3417,7 @@ namespace RC::GUI // Remember to update text width calculations for the last ImGui::PushItemWidth call if this text gets updated. if (ImGui::Button(ICON_FA_COPY " Copy search result")) { - StringType result{}; + UEStringType result{}; auto is_below_425 = Version::IsBelow(4, 25); for (const auto& search_result : s_name_search_results) { diff --git a/UE4SS/src/GUI/UFunctionCallerWidget.cpp b/UE4SS/src/GUI/UFunctionCallerWidget.cpp index c2521cadd..4d1bef2ea 100644 --- a/UE4SS/src/GUI/UFunctionCallerWidget.cpp +++ b/UE4SS/src/GUI/UFunctionCallerWidget.cpp @@ -18,6 +18,9 @@ #include #include +#undef min +#undef max + namespace RC::GUI { UFunctionCallerWidget::UFunctionCallerWidget() = default; @@ -139,7 +142,7 @@ namespace RC::GUI static bool s_do_call{}; static UObject* s_instance{}; - static StringType s_cmd{}; + static UEStringType s_cmd{}; static FOutputDevice s_ar{}; static UFunction* s_function{}; static UObject* s_executor{}; @@ -246,7 +249,7 @@ namespace RC::GUI static auto get_typeless_object_name(UObject* object) -> std::string { auto object_name = to_system(object->GetFullName()); - auto object_name_type_space_location = object_name.find(" "); + auto object_name_type_space_location = object_name.find(SYSSTR(" ")); if (object_name_type_space_location == object_name.npos) { Output::send(SYSSTR("Could not copy name of PlayerController, was unable to find space in full PlayerController name: '{}'."), @@ -283,7 +286,7 @@ namespace RC::GUI return params.ReturnValue; } - static auto render_other_list(std::string_view menu_name, StringViewType class_name, UFunctionParam& param) -> void + static auto render_other_list(std::string_view menu_name, UEStringViewType class_name, UFunctionParam& param) -> void { if (ImGui::BeginMenu(menu_name.data())) { diff --git a/UE4SS/src/GUI/Windows.cpp b/UE4SS/src/GUI/Windows.cpp index 486654ef4..26cee4cdd 100644 --- a/UE4SS/src/GUI/Windows.cpp +++ b/UE4SS/src/GUI/Windows.cpp @@ -36,10 +36,10 @@ namespace RC::GUI auto Backend_Windows::create_window(int loc_x, int loc_y, int size_x, int size_y) -> void { - StringType title_bar_text{STR("UE4SS Debugging Tools")}; + SystemStringType title_bar_text{SYSSTR("UE4SS Debugging Tools")}; if (dynamic_cast(m_gfx_backend)) { - title_bar_text.append(STR(" (DX11)")); + title_bar_text.append(SYSSTR(" (DX11)")); } // ImGui_ImplWin32_EnableDpiAwareness() diff --git a/UE4SS/src/LuaType/LuaModRef.cpp b/UE4SS/src/LuaType/LuaModRef.cpp index ee9fa4b15..afa23cc94 100644 --- a/UE4SS/src/LuaType/LuaModRef.cpp +++ b/UE4SS/src/LuaType/LuaModRef.cpp @@ -50,7 +50,7 @@ No overload found for function 'SetSharedVariable'. { throw std::runtime_error{error_overload_not_found}; } - auto variable_name = std::string{lua.get_string()}; + auto variable_name = to_system(lua.get_string()); RC::LuaMod::SharedLuaVariable* currently_stored_value{}; if (auto it = RC::LuaMod::m_shared_lua_variables.find(variable_name); it != RC::LuaMod::m_shared_lua_variables.end()) @@ -159,7 +159,7 @@ No overload found for function 'GetSharedVariable'. { throw std::runtime_error{error_overload_not_found}; } - auto variable_name = std::string{lua.get_string()}; + auto variable_name = to_system(lua.get_string()); if (auto it = RC::LuaMod::m_shared_lua_variables.find(variable_name); it != RC::LuaMod::m_shared_lua_variables.end()) { diff --git a/UE4SS/src/LuaType/LuaXProperty.cpp b/UE4SS/src/LuaType/LuaXProperty.cpp index eb02eacf9..70332a8d1 100644 --- a/UE4SS/src/LuaType/LuaXProperty.cpp +++ b/UE4SS/src/LuaType/LuaXProperty.cpp @@ -114,7 +114,7 @@ namespace RC::LuaType if (lua_object.get_remote_cpp_object()) { // Set the return value to the ansi version of the full name - lua.set_string(to_system(lua_object.get_remote_cpp_object()->GetFullName()).c_str()); + lua.set_string(to_lua(lua_object.get_remote_cpp_object()->GetFullName()).c_str()); } else { diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 52a216584..46c12761c 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -12,7 +12,7 @@ namespace RC { - CppMod::CppMod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) + CppMod::CppMod(UE4SSProgram& program, UEStringType&& mod_name, UEStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) { std::filesystem::path m_dlls_path = m_mod_path; @@ -35,7 +35,7 @@ namespace RC if (!m_main_dll_module) { - Output::send(SYSSTR("Failed to load dll <{}> for mod {}, error code: 0x{:x}\n"), dll_path, m_mod_name, GetLastError()); + Output::send(SYSSTR("Failed to load dll <{}> for mod {}, error code: 0x{:x}\n"), to_system_string(dll_path), m_mod_name, GetLastError()); set_installable(false); return; } @@ -68,7 +68,7 @@ namespace RC if (!Output::has_internal_error()) { Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), - to_system_string(std::filesystem::path {m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)) + "\n", + to_system_string(std::filesystem::path{m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)) + SYSSTR("\n"), m_mod_name, e.what()); } @@ -88,7 +88,7 @@ namespace RC } } - auto CppMod::fire_on_lua_start(SystemStringViewType mod_name, + auto CppMod::fire_on_lua_start(UEStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -109,7 +109,7 @@ namespace RC } } - auto CppMod::fire_on_lua_stop(SystemStringViewType mod_name, + auto CppMod::fire_on_lua_stop(UEStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -162,7 +162,7 @@ namespace RC } } - auto CppMod::fire_dll_load(SystemStringViewType dll_name) -> void + auto CppMod::fire_dll_load(UEStringViewType dll_name) -> void { if (m_mod) { diff --git a/UE4SS/src/Mod/CppUserModBase.cpp b/UE4SS/src/Mod/CppUserModBase.cpp index b56699b1a..8d6efa925 100644 --- a/UE4SS/src/Mod/CppUserModBase.cpp +++ b/UE4SS/src/Mod/CppUserModBase.cpp @@ -52,7 +52,7 @@ namespace RC } #ifdef HAS_GUI - auto CppUserModBase::register_tab(std::wstring_view tab_name, GUI::GUITab::RenderFunctionType render_function) -> void + auto CppUserModBase::register_tab(UEStringViewType tab_name, GUI::GUITab::RenderFunctionType render_function) -> void { auto& tab = GUITabs.emplace_back(std::make_shared(tab_name, render_function, this)); UE4SSProgram::get_program().add_gui_tab(tab); diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 4267028fb..29bff6c4a 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -1373,7 +1373,7 @@ No overload found for function 'UnregisterHook'. lua.throw_error(error_overload_not_found); } - auto function_name = to_u16string(lua.get_string()); + auto function_name = to_ue(lua.get_string()); auto function_name_no_prefix = function_name.substr(function_name.find_first_of(STR(" ")) + 1, function_name.size()); Unreal::UFunction* unreal_function = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, function_name_no_prefix); @@ -2579,7 +2579,7 @@ No overload found for function 'LoadAsset'. { throw std::runtime_error{error_overload_not_found}; } - auto asset_path_and_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); + auto asset_path_and_name = Unreal::FName(to_ue(lua.get_string()), Unreal::FNAME_Add); auto* asset_registry = static_cast(Unreal::UAssetRegistryHelpers::GetAssetRegistry().ObjectPointer); if (!asset_registry) @@ -2630,7 +2630,7 @@ No overload found for function 'FindObject'. bool could_be_in_class{}; if (lua.is_string()) { - object_class_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); + object_class_name = Unreal::FName(to_ue(lua.get_string()), Unreal::FNAME_Add); } else if (lua.is_userdata()) { @@ -2673,7 +2673,7 @@ No overload found for function 'FindObject'. bool could_be_object_short_name{}; if (lua.is_string()) { - object_short_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); + object_short_name = Unreal::FName(to_ue(lua.get_string()), Unreal::FNAME_Add); could_be_object_short_name = true; } else if (lua.is_userdata()) @@ -2757,7 +2757,7 @@ No overload found for function 'FindObject'. if (could_be_in_class && could_be_in_outer && could_be_in_name) { - LuaType::auto_construct_object(lua, Unreal::UObjectGlobals::FindObject(in_class, in_outer, to_u16string(in_name), exact_class)); + LuaType::auto_construct_object(lua, Unreal::UObjectGlobals::FindObject(in_class, in_outer, to_ue(in_name), exact_class)); } else { @@ -2804,7 +2804,7 @@ No overload found for function 'FindObjects'. bool object_class_name_supplied{true}; if (lua.is_string()) { - object_class_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); + object_class_name = Unreal::FName(to_ue(lua.get_string()), Unreal::FNAME_Add); } else if (lua.is_userdata()) { @@ -2842,7 +2842,7 @@ No overload found for function 'FindObjects'. Unreal::FName object_short_name{}; if (lua.is_string()) { - object_short_name = Unreal::FName(to_u16string(lua.get_string()), Unreal::FNAME_Add); + object_short_name = Unreal::FName(to_ue(lua.get_string()), Unreal::FNAME_Add); } else if (lua.is_userdata()) { @@ -3333,7 +3333,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. return; } - for (const auto& mod : UE4SSProgram::m_mods) + for (const auto& mod : UE4SSProgram::get_program().m_mods) { if (auto cpp_mod = dynamic_cast(mod.get()); cpp_mod && mod->is_started()) { @@ -3353,7 +3353,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. return; } - for (const auto& mod : UE4SSProgram::m_mods) + for (const auto& mod : UE4SSProgram::get_program().m_mods) { if (auto cpp_mod = dynamic_cast(mod.get()); cpp_mod && mod->is_started()) { diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index 86d631d7c..f2e5c2942 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -136,7 +136,7 @@ namespace RC::UEGenerator } } - auto string_to_uppercase(SystemStringType s) -> SystemStringType + auto string_to_uppercase(UEStringType s) -> UEStringType { std::transform(s.begin(), s.end(), s.begin(), [](wchar_t c) { return towupper(c); @@ -146,8 +146,8 @@ namespace RC::UEGenerator class FlagFormatHelper { - std::set m_switches; - std::map> m_parameters; + std::set m_switches; + std::map> m_parameters; std::shared_ptr m_meta_helper; FlagFormatHelper(bool is_root_helper) @@ -163,14 +163,14 @@ namespace RC::UEGenerator { } - auto add_switch(const SystemStringType& switch_name) -> void + auto add_switch(const UEStringType& switch_name) -> void { m_switches.insert(switch_name); } - auto add_parameter(const SystemStringType& parameter_name, const SystemStringType& parameter_value) -> void + auto add_parameter(const UEStringType& parameter_name, const UEStringType& parameter_value) -> void { - if (parameter_name == SYSSTR("meta")) + if (parameter_name == STR("meta")) { throw std::invalid_argument("Use get_meta() to add metadata to the flag declaration"); } @@ -191,54 +191,54 @@ namespace RC::UEGenerator return m_meta_helper.get(); } - auto build_flag_string() const -> SystemStringType + auto build_flag_string() const -> UEStringType { - SystemStringType resulting_string; + UEStringType resulting_string; - for (const SystemStringType& switch_name : m_switches) + for (const UEStringType& switch_name : m_switches) { resulting_string.append(switch_name); - resulting_string.append(SYSSTR(", ")); + resulting_string.append(STR(", ")); } for (const auto& parameter_pair : m_parameters) { resulting_string.append(parameter_pair.first); - resulting_string.append(SYSSTR("=")); - const std::set& parameter_values = parameter_pair.second; + resulting_string.append(STR("=")); + const std::set& parameter_values = parameter_pair.second; if (parameter_values.size() != 1) { - resulting_string.append(SYSSTR("(")); + resulting_string.append(STR("(")); - for (const SystemStringType& parameter_value : parameter_values) + for (const UEStringType& parameter_value : parameter_values) { resulting_string.append(parameter_value); - resulting_string.append(SYSSTR(", ")); + resulting_string.append(STR(", ")); } if (parameter_values.size() != 0) { resulting_string.erase(resulting_string.size() - 1, 1); } - resulting_string.append(SYSSTR(")")); + resulting_string.append(STR(")")); } else { resulting_string.append(*parameter_values.begin()); } - resulting_string.append(SYSSTR(", ")); + resulting_string.append(STR(", ")); } if (m_meta_helper) { - const SystemStringType meta_flag_string = m_meta_helper->build_flag_string(); + const UEStringType meta_flag_string = m_meta_helper->build_flag_string(); if (!meta_flag_string.empty()) { - resulting_string.append(SYSSTR("meta=(")); + resulting_string.append(STR("meta=(")); resulting_string.append(meta_flag_string); - resulting_string.append(SYSSTR(")")); - resulting_string.append(SYSSTR(", ")); + resulting_string.append(STR(")")); + resulting_string.append(STR(", ")); } } @@ -250,69 +250,69 @@ namespace RC::UEGenerator } }; - auto UEHeaderGenerator::generate_module_build_file(const SystemStringType& module_name) -> void + auto UEHeaderGenerator::generate_module_build_file(const UEStringType& module_name) -> void { - const FFilePath module_file_path = m_root_directory / module_name / std::format(SYSSTR("{}.Build.cs"), module_name); + const FFilePath module_file_path = m_root_directory / module_name / std::format(STR("{}.Build.cs"), module_name); GeneratedFile module_build_file = GeneratedFile(module_file_path); - module_build_file.append_line(SYSSTR("using UnrealBuildTool;")); - module_build_file.append_line(SYSSTR("")); + module_build_file.append_line(STR("using UnrealBuildTool;")); + module_build_file.append_line(STR("")); - module_build_file.append_line(std::format(SYSSTR("public class {} : ModuleRules {{"), module_name)); + module_build_file.append_line(std::format(STR("public class {} : ModuleRules {{"), module_name)); module_build_file.begin_indent_level(); - module_build_file.append_line(std::format(SYSSTR("public {}(ReadOnlyTargetRules Target) : base(Target) {{"), module_name)); + module_build_file.append_line(std::format(STR("public {}(ReadOnlyTargetRules Target) : base(Target) {{"), module_name)); module_build_file.begin_indent_level(); - module_build_file.append_line(SYSSTR("PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;")); + module_build_file.append_line(STR("PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;")); if (Version::IsAtLeast(4, 24)) { - module_build_file.append_line(SYSSTR("bLegacyPublicIncludePaths = false;")); - module_build_file.append_line(SYSSTR("ShadowVariableWarningLevel = WarningLevel.Warning;")); + module_build_file.append_line(STR("bLegacyPublicIncludePaths = false;")); + module_build_file.append_line(STR("ShadowVariableWarningLevel = WarningLevel.Warning;")); } - module_build_file.append_line(SYSSTR("")); - module_build_file.append_line(SYSSTR("PublicDependencyModuleNames.AddRange(new string[] {")); + module_build_file.append_line(STR("")); + module_build_file.append_line(STR("PublicDependencyModuleNames.AddRange(new string[] {")); module_build_file.begin_indent_level(); - std::set all_module_dependencies = this->m_forced_module_dependencies; - std::set clean_module_dependencies{}; + std::set all_module_dependencies = this->m_forced_module_dependencies; + std::set clean_module_dependencies{}; add_module_and_sub_module_dependencies(clean_module_dependencies, module_name, false); all_module_dependencies.insert(clean_module_dependencies.begin(), clean_module_dependencies.end()); - for (const SystemStringType& other_module_name : all_module_dependencies) + for (const UEStringType& other_module_name : all_module_dependencies) { - module_build_file.append_line(std::format(SYSSTR("\"{}\","), other_module_name)); + module_build_file.append_line(std::format(STR("\"{}\","), other_module_name)); } module_build_file.end_indent_level(); - module_build_file.append_line(SYSSTR("});")); + module_build_file.append_line(STR("});")); module_build_file.end_indent_level(); - module_build_file.append_line(SYSSTR("}")); + module_build_file.append_line(STR("}")); module_build_file.end_indent_level(); - module_build_file.append_line(SYSSTR("}")); + module_build_file.append_line(STR("}")); module_build_file.serialize_file_content_to_disk(); } - auto UEHeaderGenerator::generate_module_implementation_file(const SystemStringType& module_name) -> void + auto UEHeaderGenerator::generate_module_implementation_file(const UEStringType& module_name) -> void { - const FFilePath module_file_path = m_root_directory / module_name / SYSSTR("Private") / std::format(SYSSTR("{}Module.cpp"), module_name); + const FFilePath module_file_path = m_root_directory / module_name / STR("Private") / std::format(STR("{}Module.cpp"), module_name); GeneratedFile module_impl_file = GeneratedFile(module_file_path); - module_impl_file.append_line(SYSSTR("#include \"Modules/ModuleManager.h\"")); - module_impl_file.append_line(SYSSTR("")); + module_impl_file.append_line(STR("#include \"Modules/ModuleManager.h\"")); + module_impl_file.append_line(STR("")); if (module_name != m_primary_module_name) { - module_impl_file.append_line(std::format(SYSSTR("IMPLEMENT_MODULE(FDefaultGameModuleImpl, {});"), module_name)); + module_impl_file.append_line(std::format(STR("IMPLEMENT_MODULE(FDefaultGameModuleImpl, {});"), module_name)); } else { - module_impl_file.append_line(std::format(SYSSTR("IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, {}, {});"), module_name, module_name)); + module_impl_file.append_line(std::format(STR("IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, {}, {});"), module_name, module_name)); } module_impl_file.serialize_file_content_to_disk(); @@ -320,40 +320,40 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_interface_definition(UClass* uclass, GeneratedSourceFile& header_data) -> void { - const SystemStringType interface_class_native_name = get_native_class_name(uclass); - const SystemStringType interface_flags_string = generate_interface_flags(uclass); + const UEStringType interface_class_native_name = get_native_class_name(uclass); + const UEStringType interface_flags_string = generate_interface_flags(uclass); - SystemStringType maybe_api_name; + UEStringType maybe_api_name; if ((uclass->GetClassFlags() & CLASS_RequiredAPI) != 0) { maybe_api_name.append(convert_module_name_to_api_name(header_data.get_header_module_name())); - maybe_api_name.append(SYSSTR(" ")); + maybe_api_name.append(STR(" ")); } UClass* super_class = uclass->GetSuperClass(); header_data.add_dependency_object(super_class, DependencyLevel::Include); - SystemStringType parent_interface_class_name = get_native_class_name(super_class); + UEStringType parent_interface_class_name = get_native_class_name(super_class); // Generate interface UCLASS declaration - header_data.append_line(std::format(SYSSTR("UINTERFACE({})"), interface_flags_string)); - header_data.append_line(std::format(SYSSTR("class {}{} : public {} {{"), maybe_api_name, interface_class_native_name, parent_interface_class_name)); + header_data.append_line(std::format(STR("UINTERFACE({})"), interface_flags_string)); + header_data.append_line(std::format(STR("class {}{} : public {} {{"), maybe_api_name, interface_class_native_name, parent_interface_class_name)); header_data.begin_indent_level(); - header_data.append_line(SYSSTR("GENERATED_BODY()")); + header_data.append_line(STR("GENERATED_BODY()")); header_data.end_indent_level(); - header_data.append_line(SYSSTR("};")); - header_data.append_line(SYSSTR("")); + header_data.append_line(STR("};")); + header_data.append_line(STR("")); // Generate interface real class declaration - const SystemStringType interface_native_name = get_native_class_name(uclass, true); - const SystemStringType parent_interface_name = get_native_class_name(super_class, true); + const UEStringType interface_native_name = get_native_class_name(uclass, true); + const UEStringType parent_interface_name = get_native_class_name(super_class, true); - header_data.append_line(std::format(SYSSTR("class {}{} : public {} {{"), maybe_api_name, interface_native_name, parent_interface_name)); + header_data.append_line(std::format(STR("class {}{} : public {} {{"), maybe_api_name, interface_native_name, parent_interface_name)); header_data.begin_indent_level(); - header_data.append_line(SYSSTR("GENERATED_BODY()")); + header_data.append_line(STR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -370,7 +370,7 @@ namespace RC::UEGenerator } if (NumDelegatesGenerated) { - header_data.append_line(SYSSTR("")); + header_data.append_line(STR("")); } // Generate interface functions @@ -384,30 +384,30 @@ namespace RC::UEGenerator } header_data.end_indent_level(); - header_data.append_line(SYSSTR("};")); + header_data.append_line(STR("};")); } auto UEHeaderGenerator::generate_object_definition(UClass* uclass, GeneratedSourceFile& header_data) -> void { - const SystemStringType class_native_name = get_native_class_name(uclass); - const SystemStringType class_flags_string = generate_class_flags(uclass); + const UEStringType class_native_name = get_native_class_name(uclass); + const UEStringType class_flags_string = generate_class_flags(uclass); - SystemStringType maybe_api_name; + UEStringType maybe_api_name; if ((uclass->GetClassFlags() & CLASS_RequiredAPI) != 0) { maybe_api_name.append(convert_module_name_to_api_name(header_data.get_header_module_name())); - maybe_api_name.append(SYSSTR(" ")); + maybe_api_name.append(STR(" ")); } UClass* super_class = uclass->GetSuperClass(); - SystemStringType parent_class_name; + UEStringType parent_class_name; if (super_class) { parent_class_name = get_native_class_name(super_class); } else { - parent_class_name = SYSSTR("UObjectBaseUtility"); + parent_class_name = STR("UObjectBaseUtility"); } if (super_class) @@ -415,23 +415,23 @@ namespace RC::UEGenerator header_data.add_dependency_object(super_class, DependencyLevel::Include); } - SystemStringType interface_list_string; + UEStringType interface_list_string; auto implemented_interfaces = uclass->GetInterfaces(); for (const RC::Unreal::FImplementedInterface& uinterface : implemented_interfaces) { header_data.add_dependency_object(uinterface.Class, DependencyLevel::Include); - const SystemStringType interface_name = get_native_class_name(uinterface.Class, true); + const UEStringType interface_name = get_native_class_name(uinterface.Class, true); - interface_list_string.append(SYSSTR(", public ")); + interface_list_string.append(STR(", public ")); interface_list_string.append(interface_name); } - header_data.append_line(std::format(SYSSTR("UCLASS({})"), class_flags_string)); - header_data.append_line(std::format(SYSSTR("class {}{} : public {}{} {{"), maybe_api_name, class_native_name, parent_class_name, interface_list_string)); + header_data.append_line(std::format(STR("UCLASS({})"), class_flags_string)); + header_data.append_line(std::format(STR("class {}{} : public {}{} {{"), maybe_api_name, class_native_name, parent_class_name, interface_list_string)); header_data.begin_indent_level(); - header_data.append_line(SYSSTR("GENERATED_BODY()")); + header_data.append_line(STR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -451,7 +451,7 @@ namespace RC::UEGenerator } if (NumDelegatesGenerated) { - header_data.append_line(SYSSTR("")); + header_data.append_line(STR("")); } // Generate properties @@ -475,19 +475,19 @@ namespace RC::UEGenerator append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); // Generate constructor - SystemStringType constructor_string; + UEStringType constructor_string; if (uclass->IsChildOf() || uclass->IsChildOf()) { - constructor_string.append(SYSSTR("const FObjectInitializer& ObjectInitializer")); + constructor_string.append(STR("const FObjectInitializer& ObjectInitializer")); } - header_data.append_line(std::format(SYSSTR("{}({});"), class_native_name, constructor_string)); - header_data.append_line_no_indent(SYSSTR("")); + header_data.append_line(std::format(STR("{}({});"), class_native_name, constructor_string)); + header_data.append_line_no_indent(STR("")); // Generate GetLifetimeReplicatedProps override if we have encountered replicated properties if (encountered_replicated_properties) { - header_data.append_line(SYSSTR("virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;")); - header_data.append_line_no_indent(SYSSTR("")); + header_data.append_line(STR("virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;")); + header_data.append_line_no_indent(STR("")); } // Generate functions @@ -505,8 +505,8 @@ namespace RC::UEGenerator // Generate overrides for all inherited virtual functions if (implemented_interfaces.Num() > 0) { - header_data.append_line_no_indent(SYSSTR("")); - header_data.append_line(SYSSTR("// Fix for true pure virtual functions not being implemented")); + header_data.append_line_no_indent(STR("")); + header_data.append_line(STR("// Fix for true pure virtual functions not being implemented")); } for (const RC::Unreal::FImplementedInterface& uinterface : implemented_interfaces) { @@ -523,33 +523,33 @@ namespace RC::UEGenerator } header_data.end_indent_level(); - header_data.append_line(SYSSTR("};")); + header_data.append_line(STR("};")); } auto UEHeaderGenerator::generate_struct_definition(UScriptStruct* script_struct, GeneratedSourceFile& header_data) -> void { - const SystemStringType struct_native_name = get_native_struct_name(script_struct); - const SystemStringType struct_flags_string = generate_struct_flags(script_struct); + const UEStringType struct_native_name = get_native_struct_name(script_struct); + const UEStringType struct_flags_string = generate_struct_flags(script_struct); - SystemStringType api_macro_name = convert_module_name_to_api_name(header_data.get_header_module_name()); - api_macro_name.append(SYSSTR(" ")); + UEStringType api_macro_name = convert_module_name_to_api_name(header_data.get_header_module_name()); + api_macro_name.append(STR(" ")); bool is_struct_exported = (script_struct->GetStructFlags() & STRUCT_RequiredAPI) != 0; UScriptStruct* super_struct = script_struct->GetSuperScriptStruct(); - SystemStringType parent_struct_declaration; + UEStringType parent_struct_declaration; if (super_struct) { header_data.add_dependency_object(super_struct, DependencyLevel::Include); - const SystemStringType super_struct_native_name = get_native_struct_name(super_struct); - parent_struct_declaration.append(std::format(SYSSTR(" : public {}"), super_struct_native_name)); + const UEStringType super_struct_native_name = get_native_struct_name(super_struct); + parent_struct_declaration.append(std::format(STR(" : public {}"), super_struct_native_name)); } - header_data.append_line(std::format(SYSSTR("USTRUCT({})"), struct_flags_string)); - header_data.append_line(std::format(SYSSTR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name, parent_struct_declaration)); + header_data.append_line(std::format(STR("USTRUCT({})"), struct_flags_string)); + header_data.append_line(std::format(STR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : STR(""), struct_native_name, parent_struct_declaration)); header_data.begin_indent_level(); - header_data.append_line(SYSSTR("GENERATED_BODY()")); + header_data.append_line(STR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -572,34 +572,34 @@ namespace RC::UEGenerator // Generate constructor and make sure it's public append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); - header_data.append_line(std::format(SYSSTR("{}{}();"), !is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name)); + header_data.append_line(std::format(STR("{}{}();"), !is_struct_exported ? api_macro_name : STR(""), struct_native_name)); header_data.end_indent_level(); - header_data.append_line(SYSSTR("};")); + header_data.append_line(STR("};")); } auto UEHeaderGenerator::generate_enum_definition(UEnum* uenum, GeneratedSourceFile& header_data) -> void { - const SystemStringType native_enum_name = get_native_enum_name(uenum, false); + const UEStringType native_enum_name = get_native_enum_name(uenum, false); const int64 highest_enum_value = get_highest_enum(uenum); const bool can_use_uint8_override = (highest_enum_value <= 255 && get_lowest_enum(uenum) >= 0); - const SystemStringType enum_flags_string = generate_enum_flags(uenum); + const UEStringType enum_flags_string = generate_enum_flags(uenum); const auto underlying_type = m_underlying_enum_types.find(native_enum_name); const bool has_known_underlying_type = underlying_type != m_underlying_enum_types.end(); UEnum::ECppForm cpp_form = uenum->GetCppForm(); bool enum_is_uint8{false}; - header_data.append_line(std::format(SYSSTR("UENUM({})"), enum_flags_string)); + header_data.append_line(std::format(STR("UENUM({})"), enum_flags_string)); if (cpp_form == UEnum::ECppForm::Namespaced) { - header_data.append_line(std::format(SYSSTR("namespace {} {{"), native_enum_name)); + header_data.append_line(std::format(STR("namespace {} {{"), native_enum_name)); header_data.begin_indent_level(); - header_data.append_line(SYSSTR("enum Type {")); + header_data.append_line(STR("enum Type {")); } else if (cpp_form == UEnum::ECppForm::Regular) { - header_data.append_line(std::format(SYSSTR("enum {} {{"), native_enum_name)); + header_data.append_line(std::format(STR("enum {} {{"), native_enum_name)); } else if (cpp_form == UEnum::ECppForm::EnumClass) { @@ -607,20 +607,20 @@ namespace RC::UEGenerator { if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeEnumClassesBlueprintType && can_use_uint8_override) { - header_data.append_line(std::format(SYSSTR("enum class {} : uint8 {{"), native_enum_name)); + header_data.append_line(std::format(STR("enum class {} : uint8 {{"), native_enum_name)); enum_is_uint8 = true; } else { // Enum has never been used in any native classes or structures, go with implicit type - header_data.append_line(std::format(SYSSTR("enum class {} {{"), native_enum_name)); + header_data.append_line(std::format(STR("enum class {} {{"), native_enum_name)); } } else { - SystemStringType underlying_type_string = underlying_type->second; + UEStringType underlying_type_string = underlying_type->second; - header_data.append_line(std::format(SYSSTR("enum class {} : {} {{"), native_enum_name, underlying_type_string)); + header_data.append_line(std::format(STR("enum class {} : {} {{"), native_enum_name, underlying_type_string)); } } @@ -633,7 +633,7 @@ namespace RC::UEGenerator for (auto [Name, Value] : uenum->ForEachName()) { UEStringType enum_name = Name.ToString(); - auto result_enumeration_line = sanitize_enumeration_name(to_system(enum_name)); + auto result_enumeration_line = sanitize_enumeration_name((enum_name)); auto pre_append_result_line = result_enumeration_line; // If an enum name is listed in the array twice, that likely means it is used as the value for another enum. Long story short, don't print it. @@ -651,23 +651,23 @@ namespace RC::UEGenerator auto first_name_with_value = uenum->GetNameByValue(Value).ToString(); if (first_name_with_value != Name.ToString()) { - result_enumeration_line.append(std::format(SYSSTR(" = {}"), sanitize_enumeration_name(to_system(first_name_with_value)))); + result_enumeration_line.append(std::format(STR(" = {}"), sanitize_enumeration_name((first_name_with_value)))); } else if (Value != expected_next_enum_value || last_value_was_negative_one) { - const auto CastString = (enum_is_uint8 && Value < 0) ? SYSSTR("(uint8)") : SYSSTR(""); - const auto MinusSign = Value < 0 ? SYSSTR("-") : SYSSTR(""); - result_enumeration_line.append(std::format(SYSSTR(" = {}{}{}"), CastString, MinusSign, Value < 0 ? -Value : Value)); + const auto CastString = (enum_is_uint8 && Value < 0) ? STR("(uint8)") : STR(""); + const auto MinusSign = Value < 0 ? STR("-") : STR(""); + result_enumeration_line.append(std::format(STR(" = {}{}{}"), CastString, MinusSign, Value < 0 ? -Value : Value)); } expected_next_enum_value = Value + 1; last_value_was_negative_one = (Value == -1); - SystemStringType pre_append_result_line_lower = pre_append_result_line; + UEStringType pre_append_result_line_lower = pre_append_result_line; std::transform(pre_append_result_line_lower.begin(), pre_append_result_line_lower.end(), pre_append_result_line_lower.begin(), ::towlower); - if (pre_append_result_line_lower.ends_with(SYSSTR("_max"))) + if (pre_append_result_line_lower.ends_with(STR("_max"))) { - const auto expected_full_constant_name = std::format(SYSSTR("{}_MAX"), to_system(enum_prefix)); - SystemStringType expected_full_constant_name_lower = expected_full_constant_name; + const auto expected_full_constant_name = std::format(STR("{}_MAX"), to_system(enum_prefix)); + UEStringType expected_full_constant_name_lower = expected_full_constant_name; std::transform(expected_full_constant_name_lower.begin(), expected_full_constant_name_lower.end(), expected_full_constant_name_lower.begin(), ::towlower); int64_t expected_max_value = highest_enum_value + 1; @@ -679,33 +679,33 @@ namespace RC::UEGenerator continue; } // Otherwise, just make sure it's hidden and not visible to the end user - result_enumeration_line.append(SYSSTR(" UMETA(Hidden)")); + result_enumeration_line.append(STR(" UMETA(Hidden)")); } - result_enumeration_line.append(SYSSTR(",")); + result_enumeration_line.append(STR(",")); header_data.append_line(result_enumeration_line); } header_data.end_indent_level(); - header_data.append_line(SYSSTR("};")); + header_data.append_line(STR("};")); if (cpp_form == UEnum::ECppForm::Namespaced) { header_data.end_indent_level(); - header_data.append_line(SYSSTR("}")); + header_data.append_line(STR("}")); } } auto UEHeaderGenerator::generate_delegate_type_declaration(UFunction* signature_function, UClass* delegate_class, GeneratedSourceFile& header_data) -> void { - SystemStringType owning_class; + UEStringType owning_class; if (delegate_class == nullptr) { - owning_class = SYSSTR("UObject*"); + owning_class = STR("UObject*"); } else { - owning_class = to_system(delegate_class->GetNamePrivate().ToString()); + owning_class = (delegate_class->GetNamePrivate().ToString()); } auto function_flags = signature_function->GetFunctionFlags(); @@ -720,52 +720,52 @@ namespace RC::UEGenerator const bool is_multicast = (function_flags & Unreal::FUNC_MulticastDelegate) != 0; const bool declared_const = (function_flags & FUNC_Const) != 0; - const SystemStringType delegate_type_name = get_native_delegate_type_name(signature_function, nullptr, true); + const UEStringType delegate_type_name = get_native_delegate_type_name(signature_function, nullptr, true); FProperty* return_value_property = signature_function->GetReturnProperty(); - SystemStringType delegate_macro_string; + UEStringType delegate_macro_string; // Delegate macro declaration is only allowed on the top level delegates, class-based types are limited to being implicit if (signature_function->GetOuterPrivate()->IsA()) { - delegate_macro_string.append(SYSSTR("UDELEGATE(")); + delegate_macro_string.append(STR("UDELEGATE(")); delegate_macro_string.append(generate_function_flags(signature_function)); - delegate_macro_string.append(SYSSTR(") ")); + delegate_macro_string.append(STR(") ")); } PropertyTypeDeclarationContext context(delegate_type_name, &header_data); int32_t num_delegate_parameters = 0; - SystemStringType delegate_parameter_list = + UEStringType delegate_parameter_list = generate_function_parameter_list(nullptr, signature_function, header_data, true, context.context_name, {}, &num_delegate_parameters); if (num_delegate_parameters > 0) { - delegate_parameter_list.insert(0, SYSSTR(", ")); + delegate_parameter_list.insert(0, STR(", ")); } if (num_delegate_parameters > 9) { - Output::send(SYSSTR("Invalid delegate parameter count in Delegate: {}. Using _TooMany\n"), delegate_type_name); + Output::send(STR("Invalid delegate parameter count in Delegate: {}. Using _TooMany\n"), delegate_type_name); } - SystemStringType return_value_declaration; + UEStringType return_value_declaration; if (return_value_property != NULL) { return_value_declaration = generate_property_type_declaration(return_value_property, context); - return_value_declaration.append(SYSSTR(", ")); + return_value_declaration.append(STR(", ")); } - SystemStringType delegate_declaration_string = std::format(SYSSTR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), + UEStringType delegate_declaration_string = std::format(STR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), delegate_macro_string, - is_multicast ? SYSSTR("_MULTICAST") : SYSSTR(""), - is_sparse ? SYSSTR("_SPARSE") : SYSSTR(""), - return_value_property ? SYSSTR("_RetVal") : SYSSTR(""), + is_multicast ? STR("_MULTICAST") : STR(""), + is_sparse ? STR("_SPARSE") : STR(""), + return_value_property ? STR("_RetVal") : STR(""), generate_parameter_count_string(num_delegate_parameters), - declared_const ? SYSSTR("_Const") : SYSSTR(""), + declared_const ? STR("_Const") : STR(""), return_value_declaration, delegate_type_name, // TODO: Actually get delegate property name. - is_sparse ? std::format(SYSSTR("{}, {}"), owning_class, SYSSTR("EnterPropertyName")) : SYSSTR(""), + is_sparse ? std::format(STR("{}, {}"), owning_class, STR("EnterPropertyName")) : STR(""), delegate_parameter_list); header_data.append_line(delegate_declaration_string); @@ -773,32 +773,32 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_object_implementation(UClass* uclass, GeneratedSourceFile& implementation_file) -> void { - const SystemStringType class_native_name = get_native_class_name(uclass); + const UEStringType class_native_name = get_native_class_name(uclass); - SystemStringType constructor_content_string; - SystemStringType constructor_postfix_string; + UEStringType constructor_content_string; + UEStringType constructor_postfix_string; UClass* super_class = uclass->GetSuperClass(); - const SystemStringType native_parent_class_name = super_class ? get_native_class_name(super_class) : SYSSTR("UObjectUtility"); + const UEStringType native_parent_class_name = super_class ? get_native_class_name(super_class) : STR("UObjectUtility"); // Generate constructor implementation except for overrides. // If class is a child of AActor we add the UObjectInitializer constructor. // This may not be required in all cases, but is necessary to override subcomponents and does not hurt anything. - SystemStringType object_initializer_overrides; + UEStringType object_initializer_overrides; if (uclass->IsChildOf() || uclass->IsChildOf()) { - constructor_content_string.append(SYSSTR("const FObjectInitializer& ObjectInitializer")); - constructor_postfix_string.append(std::format(SYSSTR(") : Super(ObjectInitializer{}"), object_initializer_overrides)); + constructor_content_string.append(STR("const FObjectInitializer& ObjectInitializer")); + constructor_postfix_string.append(std::format(STR(") : Super(ObjectInitializer{}"), object_initializer_overrides)); } // If parent class contains the UObjectInitializer constructor without default value, // we need to create the explicit call to such constructor and pass UObjectInitializer::Get() as the argument. else if (m_classes_with_object_initializer.contains(native_parent_class_name)) { - constructor_postfix_string.append(std::format(SYSSTR(") : {}(FObjectInitializer::Get()"), native_parent_class_name)); + constructor_postfix_string.append(std::format(STR(") : {}(FObjectInitializer::Get()"), native_parent_class_name)); } implementation_file.m_implementation_constructor.append( - std::format(SYSSTR("{}::{}({}{}"), class_native_name, class_native_name, constructor_content_string, constructor_postfix_string)); + std::format(STR("{}::{}({}{}"), class_native_name, class_native_name, constructor_content_string, constructor_postfix_string)); implementation_file.begin_indent_level(); @@ -809,12 +809,12 @@ namespace RC::UEGenerator { for (FProperty* property : uclass->OrderedForEachPropertyInChain()) { - generate_property_value(uclass, property, class_default_object, implementation_file, SYSSTR("this->")); + generate_property_value(uclass, property, class_default_object, implementation_file, STR("this->")); } } else { - implementation_file.append_line(SYSSTR("// Null default object.")); + implementation_file.append_line(STR("// Null default object.")); } m_class_subobjects.clear(); @@ -823,20 +823,20 @@ namespace RC::UEGenerator { if ((attachment.second).access_type == false) { - generate_simple_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, SYSSTR("this->"), SYSSTR("->")); + generate_simple_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, STR("this->"), STR("->")); } else { - generate_advanced_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, SYSSTR("this->"), (attachment.second).property_type, SYSSTR("->")); + generate_advanced_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, STR("this->"), (attachment.second).property_type, STR("->")); } } implementation_file.end_indent_level(); - implementation_file.append_line(SYSSTR("}\n")); + implementation_file.append_line(STR("}\n")); // Finalize constructor. We do this after the property generation because we need information from the properties // to determine the required overrides within the constructor. - implementation_file.m_implementation_constructor.append(SYSSTR(") {")); + implementation_file.m_implementation_constructor.append(STR(") {")); CaseInsensitiveSet blacklisted_property_names = collect_blacklisted_property_names(uclass); @@ -846,7 +846,7 @@ namespace RC::UEGenerator if (!is_delegate_signature_function(function)) { generate_function_implementation(uclass, function, implementation_file, false, blacklisted_property_names); - implementation_file.append_line(SYSSTR("")); + implementation_file.append_line(STR("")); } } @@ -860,35 +860,35 @@ namespace RC::UEGenerator // Generate replicated properties implementation if we really need it if (encountered_replicated_properties) { - implementation_file.add_extra_include(SYSSTR("Net/UnrealNetwork.h")); + implementation_file.add_extra_include(STR("Net/UnrealNetwork.h")); implementation_file.append_line( - std::format(SYSSTR("void {}::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const {{"), class_native_name)); + std::format(STR("void {}::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const {{"), class_native_name)); implementation_file.begin_indent_level(); - implementation_file.append_line(SYSSTR("Super::GetLifetimeReplicatedProps(OutLifetimeProps);")); - implementation_file.append_line(SYSSTR("")); + implementation_file.append_line(STR("Super::GetLifetimeReplicatedProps(OutLifetimeProps);")); + implementation_file.append_line(STR("")); for (FProperty* property : uclass->ForEachProperty()) { if ((property->GetPropertyFlags() & CPF_Net) != 0) { - implementation_file.append_line(std::format(SYSSTR("DOREPLIFETIME({}, {});"), class_native_name, to_system(property->GetName()))); + implementation_file.append_line(std::format(STR("DOREPLIFETIME({}, {});"), class_native_name, (property->GetName()))); } } implementation_file.end_indent_level(); - implementation_file.append_line(SYSSTR("}")); - implementation_file.append_line(SYSSTR("")); + implementation_file.append_line(STR("}")); + implementation_file.append_line(STR("")); } } auto UEHeaderGenerator::generate_struct_implementation(UScriptStruct* script_struct, GeneratedSourceFile& implementation_file) -> void { - const SystemStringType struct_native_name = get_native_struct_name(script_struct); + const UEStringType struct_native_name = get_native_struct_name(script_struct); // Generate constructor implementation and initialize properties inside - implementation_file.m_implementation_constructor.append(std::format(SYSSTR("{}::{}() {{"), struct_native_name, struct_native_name)); + implementation_file.m_implementation_constructor.append(std::format(STR("{}::{}() {{"), struct_native_name, struct_native_name)); implementation_file.begin_indent_level(); // Generate properties @@ -899,26 +899,26 @@ namespace RC::UEGenerator for (FProperty* property : script_struct->OrderedForEachPropertyInChain()) { - generate_property_value(script_struct, property, struct_default_object, implementation_file, SYSSTR("this->")); + generate_property_value(script_struct, property, struct_default_object, implementation_file, STR("this->")); } // TODO: ScriptStruct->DestroyStruct(StructDefaultObject); free(struct_default_object); implementation_file.end_indent_level(); - implementation_file.append_line(SYSSTR("}")); + implementation_file.append_line(STR("}")); } auto UEHeaderGenerator::generate_property(UObject* uclass, FProperty* property, GeneratedSourceFile& header_data) -> void { - const SystemStringType property_flags_string = generate_property_flags(property); + const UEStringType property_flags_string = generate_property_flags(property); bool is_bitmask_bool = false; - PropertyTypeDeclarationContext Context(to_system(uclass->GetName()), &header_data, true, &is_bitmask_bool); + PropertyTypeDeclarationContext Context((uclass->GetName()), &header_data, true, &is_bitmask_bool); - SystemStringType property_type_string{}; + UEStringType property_type_string{}; bool type_is_valid = true; - SystemStringType error_string{}; + UEStringType error_string{}; try { property_type_string = generate_property_type_declaration(property, Context); @@ -926,34 +926,34 @@ namespace RC::UEGenerator catch (std::exception& e) { type_is_valid = false; - error_string = to_system(std::string(e.what())); + error_string = to_system(e.what()); } if (!type_is_valid) { - Output::send(SYSSTR("Warning: {}\n"), error_string); - header_data.append_line(std::format(SYSSTR("// UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(SYSSTR("// Missed Property: {}"), to_system(property->GetName()))); - header_data.append_line(std::format(SYSSTR("// {}"), error_string)); - header_data.append_line(SYSSTR("")); + Output::send(STR("Warning: {}\n"), error_string); + header_data.append_line(std::format(STR("// UPROPERTY({})"), property_flags_string)); + header_data.append_line(std::format(STR("// Missed Property: {}"), (property->GetName()))); + header_data.append_line(std::format(STR("// {}"), error_string)); + header_data.append_line(STR("")); return; } - SystemStringType property_extra_declaration; + UEStringType property_extra_declaration; if (property->GetArrayDim() != 1) { - property_extra_declaration.append(SYSSTR("[")); - property_extra_declaration.append(to_system(std::to_string(property->GetArrayDim()))); - property_extra_declaration.append(SYSSTR("]")); + property_extra_declaration.append(STR("[")); + property_extra_declaration.append(to_ue(std::to_string(property->GetArrayDim()))); + property_extra_declaration.append(STR("]")); } else if (is_bitmask_bool) { - property_extra_declaration.append(SYSSTR(": 1")); + property_extra_declaration.append(STR(": 1")); } - header_data.append_line(std::format(SYSSTR("UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(SYSSTR("{} {}{};"), property_type_string, to_system(property->GetName()), property_extra_declaration)); - header_data.append_line(SYSSTR("")); + header_data.append_line(std::format(STR("UPROPERTY({})"), property_flags_string)); + header_data.append_line(std::format(STR("{} {}{};"), property_type_string, (property->GetName()), property_extra_declaration)); + header_data.append_line(STR("")); } // TODO FUNC_Final is not properly handled (should be always set except some weird cases) @@ -968,87 +968,87 @@ namespace RC::UEGenerator const UEStringType context_name = uclass->GetName(); bool is_function_pure_virtual = generate_as_override; - SystemStringType function_modifier_string; + UEStringType function_modifier_string; if ((function_flags & FUNC_Static) != 0) { - function_modifier_string.append(SYSSTR("static ")); + function_modifier_string.append(STR("static ")); } else if ((function_flags & FUNC_BlueprintEvent) == 0 && is_generating_interface) { // When we have a blueprint function that is not blueprint event inside the interface, // it means we are dealing with the native interface that cannot be implemented via blueprints // and uses pure virtual functions implemented through native code - function_modifier_string.append(SYSSTR("virtual ")); + function_modifier_string.append(STR("virtual ")); is_function_pure_virtual = true; } FProperty* return_property = function->GetReturnProperty(); - SystemStringType return_property_string; + UEStringType return_property_string; if (return_property != NULL) { - PropertyTypeDeclarationContext context(to_system(uclass->GetName()), &header_data); + PropertyTypeDeclarationContext context((uclass->GetName()), &header_data); return_property_string = generate_property_type_declaration(return_property, context); } else { - return_property_string = SYSSTR("void"); + return_property_string = STR("void"); } - SystemStringType function_extra_postfix_string; + UEStringType function_extra_postfix_string; if ((function_flags & FUNC_Const) != 0) { - function_extra_postfix_string.append(SYSSTR(" const")); + function_extra_postfix_string.append(STR(" const")); } if (is_function_pure_virtual) { - SystemStringType return_statement_string; + UEStringType return_statement_string; if (return_property != NULL) { - const auto default_property_value = generate_default_property_value(return_property, header_data, to_system(context_name)); - return_statement_string = std::format(SYSSTR(" return {};"), default_property_value); + const auto default_property_value = generate_default_property_value(return_property, header_data, (context_name)); + return_statement_string = std::format(STR(" return {};"), default_property_value); } if (generate_as_override) { - function_extra_postfix_string.append(SYSSTR(" override")); + function_extra_postfix_string.append(STR(" override")); } - function_extra_postfix_string.append(std::format(SYSSTR(" PURE_VIRTUAL({},{})"), to_system(function->GetName()), return_statement_string)); + function_extra_postfix_string.append(std::format(STR(" PURE_VIRTUAL({},{})"), (function->GetName()), return_statement_string)); } - auto function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, to_system(context_name), blacklisted_property_names); + auto function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, (context_name), blacklisted_property_names); const auto function_flags_string = generate_function_flags(function, is_function_pure_virtual); - header_data.append_line(std::format(SYSSTR("UFUNCTION({})"), function_flags_string)); + header_data.append_line(std::format(STR("UFUNCTION({})"), function_flags_string)); // Format for virtual functions // virtual () PURE_VIRTUAL(, ) - header_data.append_line(std::format(SYSSTR("{}{} {}({}){};"), + header_data.append_line(std::format(STR("{}{} {}({}){};"), function_modifier_string, return_property_string, - to_system(function->GetName()), + (function->GetName()), function_argument_list, function_extra_postfix_string)); - header_data.append_line(SYSSTR("")); + header_data.append_line(STR("")); } - auto UEHeaderGenerator::generate_enum_value(UEnum* uenum, int64_t enum_value) -> SystemStringType + auto UEHeaderGenerator::generate_enum_value(UEnum* uenum, int64_t enum_value) -> UEStringType { UEnum::ECppForm cpp_form = uenum->GetCppForm(); - const SystemStringType enum_native_name = get_native_enum_name(uenum, false); + const UEStringType enum_native_name = get_native_enum_name(uenum, false); - SystemStringType enum_constant_name; + UEStringType enum_constant_name; for (auto [Name, Value] : uenum->ForEachName()) { if (Value == enum_value) { - enum_constant_name = sanitize_enumeration_name(to_system(Name.ToString())); + enum_constant_name = sanitize_enumeration_name((Name.ToString())); } } if (enum_constant_name.empty()) { - Output::send(SYSSTR("Warning: Invalid value for enum '{}', casting instead of using enum name. Value '{}' will be cast to the enum.\n"), + Output::send(STR("Warning: Invalid value for enum '{}', casting instead of using enum name. Value '{}' will be cast to the enum.\n"), enum_native_name, enum_value); - return std::format(SYSSTR("({}){}"), enum_native_name, enum_value); + return std::format(STR("({}){}"), enum_native_name, enum_value); } else { @@ -1057,55 +1057,55 @@ namespace RC::UEGenerator { return enum_constant_name; } - return std::format(SYSSTR("{}::{}"), enum_native_name, enum_constant_name); + return std::format(STR("{}::{}"), enum_native_name, enum_constant_name); } } auto UEHeaderGenerator::generate_simple_assignment_expression(FProperty* property, - const SystemStringType& value, + const UEStringType& value, GeneratedSourceFile& implementation_file, - const SystemStringType& property_scope, - const SystemStringType& operator_type) -> void + const UEStringType& property_scope, + const UEStringType& operator_type) -> void { - const auto field_class_name = to_system(property->GetName()); + const auto field_class_name = (property->GetName()); if (property->GetArrayDim() == 1) { - implementation_file.append_line(std::format(SYSSTR("{}{}{}{};"), property_scope, field_class_name, operator_type, value)); + implementation_file.append_line(std::format(STR("{}{}{}{};"), property_scope, field_class_name, operator_type, value)); } else { for (int32_t i = 0; i < property->GetArrayDim(); i++) { - implementation_file.append_line(std::format(SYSSTR("{}{}[{}]{}{};"), property_scope, field_class_name, i, operator_type, value)); + implementation_file.append_line(std::format(STR("{}{}[{}]{}{};"), property_scope, field_class_name, i, operator_type, value)); } } } auto UEHeaderGenerator::generate_advanced_assignment_expression(FProperty* property, - const SystemStringType& value, + const UEStringType& value, GeneratedSourceFile& implementation_file, - const SystemStringType& property_scope, - const SystemStringType& property_type, - const SystemStringType& operator_type) -> void + const UEStringType& property_scope, + const UEStringType& property_type, + const UEStringType& operator_type) -> void { - const auto field_class_name = to_system(property->GetName()); - implementation_file.append_line(std::format(SYSSTR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); + const auto field_class_name = (property->GetName()); + implementation_file.append_line(std::format(STR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); if (property->GetArrayDim() == 1) { - implementation_file.append_line(std::format(SYSSTR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); + implementation_file.append_line(std::format(STR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); } else { for (int32_t i = 0; i < property->GetArrayDim(); i++) { implementation_file.append_line( - std::format(SYSSTR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), field_class_name, property_scope, field_class_name, i, operator_type, value)); + std::format(STR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), field_class_name, property_scope, field_class_name, i, operator_type, value)); } } } auto UEHeaderGenerator::generate_property_value( - UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const SystemStringType& property_scope) -> void + UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const UEStringType& property_scope) -> void { const UEStringType property_name = property->GetName(); if (property_name == STR("NativeClass") || property_name == STR("hudClass")) { return; } @@ -1115,7 +1115,7 @@ namespace RC::UEGenerator UStruct* super; void* super_object = nullptr; FProperty* super_property = nullptr; - const SystemStringType property_type = generate_property_cxx_name(property, true, ustruct); + const UEStringType property_type = generate_property_cxx_name(property, true, ustruct); auto as_class = Cast(ustruct); if (as_class) { @@ -1156,10 +1156,10 @@ namespace RC::UEGenerator } UEnum* uenum = byte_property->GetEnum(); - SystemStringType result_property_value; + UEStringType result_property_value; if (uenum != NULL) { - const SystemStringType enum_type_name = get_native_enum_name(uenum); + const UEStringType enum_type_name = get_native_enum_name(uenum); result_property_value = generate_enum_value(uenum, *byte_property_value); } else @@ -1167,7 +1167,7 @@ namespace RC::UEGenerator #ifdef WIN32 result_property_value = std::to_wstring(*byte_property_value); #else - result_property_value = std::to_string(*byte_property_value); + result_property_value = to_ue(std::to_string(*byte_property_value)); #endif } @@ -1208,7 +1208,7 @@ namespace RC::UEGenerator } implementation_file.add_dependency_object(uenum, DependencyLevel::Include); - SystemStringType result_property_value = generate_enum_value(uenum, value); + UEStringType result_property_value = generate_enum_value(uenum, value); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1250,7 +1250,7 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - const SystemStringType result_property_value = result_bool_value ? SYSSTR("true") : SYSSTR("false"); + const UEStringType result_property_value = result_bool_value ? STR("true") : STR("false"); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1268,13 +1268,13 @@ namespace RC::UEGenerator if (property->IsA()) { FName* name_value = property->ContainerPtrToValuePtr(object); - const auto name_value_string = to_system(name_value->ToString()); + const auto name_value_string = (name_value->ToString()); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FName* super_name_value = super_property->ContainerPtrToValuePtr(super_object); - const auto super_name_value_string = to_system(super_name_value->ToString()); + const auto super_name_value_string = (super_name_value->ToString()); if (name_value_string == super_name_value_string) { return; @@ -1282,9 +1282,9 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - if (name_value_string != SYSSTR("None")) + if (name_value_string != STR("None")) { - const SystemStringType result_property_value = std::format(SYSSTR("TEXT(\"{}\")"), name_value_string); + const UEStringType result_property_value = std::format(STR("TEXT(\"{}\")"), name_value_string); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1301,13 +1301,13 @@ namespace RC::UEGenerator if (property->IsA()) { FString* string_value = property->ContainerPtrToValuePtr(object); - const auto string_value_string = to_system(UEStringType (string_value->GetCharArray())); + const auto string_value_string = (UEStringType (string_value->GetCharArray())); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FString* super_string_value = super_property->ContainerPtrToValuePtr(super_object); - const auto super_string_value_string = to_system(UEStringType (super_string_value->GetCharArray())); + const auto super_string_value_string = (UEStringType (super_string_value->GetCharArray())); if (string_value_string == super_string_value_string) { return; @@ -1315,9 +1315,9 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - if (string_value_string != SYSSTR("")) + if (string_value_string != STR("")) { - const SystemStringType result_value = create_string_literal(string_value_string); + const UEStringType result_value = create_string_literal(string_value_string); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_value, implementation_file, property_scope); @@ -1350,7 +1350,7 @@ namespace RC::UEGenerator if (text_value_string != STR("")) { - const auto result_property_value = std::format(SYSSTR("FText::FromString({})"), create_string_literal(to_system(text_value_string))); + const auto result_property_value = std::format(STR("FText::FromString({})"), create_string_literal((text_value_string))); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1386,11 +1386,11 @@ namespace RC::UEGenerator // If class value is NULL, generate a simple NULL assignment if (!super_and_no_access) { - generate_simple_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope); + generate_simple_assignment_expression(property, STR("NULL"), implementation_file, property_scope); } else { - generate_advanced_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope, property_type); + generate_advanced_assignment_expression(property, STR("NULL"), implementation_file, property_scope, property_type); } } else if ((class_value->GetClassFlags() & CLASS_Native) != 0) @@ -1398,8 +1398,8 @@ namespace RC::UEGenerator implementation_file.add_dependency_object(class_value, DependencyLevel::Include); // Otherwise, generate StaticClass call, assuming the class is native - const SystemStringType object_class_name = get_native_class_name(class_value); - const SystemStringType initializer = std::format(SYSSTR("{}::StaticClass()"), object_class_name); + const UEStringType object_class_name = get_native_class_name(class_value); + const UEStringType initializer = std::format(STR("{}::StaticClass()"), object_class_name); if (!super_and_no_access) { @@ -1413,7 +1413,7 @@ namespace RC::UEGenerator else { // Unhandled case, reference to the non-native blueprint class potentially? - Output::send(SYSSTR("Unhandled default value of the FClassProperty {}: {}\n"), to_system(property->GetFullName()), to_system(class_value->GetFullName())); + Output::send(STR("Unhandled default value of the FClassProperty {}: {}\n"), (property->GetFullName()), (class_value->GetFullName())); } return; } @@ -1444,11 +1444,11 @@ namespace RC::UEGenerator // TODO: Needs additional checks to see if the class is abstract to potentially change this to a default object init if (!super_and_no_access) { - generate_simple_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope); + generate_simple_assignment_expression(property, STR("NULL"), implementation_file, property_scope); } else { - generate_advanced_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope, property_type); + generate_advanced_assignment_expression(property, STR("NULL"), implementation_file, property_scope, property_type); } return; } @@ -1456,14 +1456,14 @@ namespace RC::UEGenerator if (sub_object_value->HasAnyFlags(EObjectFlags::RF_DefaultSubObject)) { UClass* object_class_type = sub_object_value->GetClassPrivate(); - const auto object_name = to_system(sub_object_value->GetName()); + const auto object_name = (sub_object_value->GetName()); UClass* super_object_class_type{}; // Additional checks to ensure this property needs to be initialized in the current class if (super_sub_object_value) { super_object_class_type = super_sub_object_value->GetClassPrivate(); - const auto super_object_name = to_system(super_sub_object_value->GetName()); + const auto super_object_name = (super_sub_object_value->GetName()); if ((object_class_type == super_object_class_type) && (object_name == super_object_name)) { return; @@ -1472,7 +1472,7 @@ namespace RC::UEGenerator } bool parent_component_found = false; - SystemStringType prior_property_variable{}; + UEStringType prior_property_variable{}; // Check to see if any other property in the super initialized a component with the same name to ensure // we are not creating the subobject in a child class unnecessarily. @@ -1486,7 +1486,7 @@ namespace RC::UEGenerator UObject* check_super_sub_object_value = *check_super_object_property->ContainerPtrToValuePtr(super_object); if (check_super_sub_object_value) { - auto check_super_object_name = to_system(check_super_sub_object_value->GetName()); + auto check_super_object_name = (check_super_sub_object_value->GetName()); if (check_super_object_name == object_name) { parent_component_found = true; @@ -1499,7 +1499,7 @@ namespace RC::UEGenerator // Generate an initializer by either setting this property to a pre-existing property // overriding the object class of an existing component, or creating a new default subobject - SystemStringType initializer{}; + UEStringType initializer{}; if (auto it = m_class_subobjects.find(object_name); it != m_class_subobjects.end()) { // Set property to equal previous property referencing the same object @@ -1509,23 +1509,23 @@ namespace RC::UEGenerator if (prior_private) { UObject* check_sub_object_value = *prior_property->ContainerPtrToValuePtr(object); - SystemStringType prior_prop_class_name = SYSSTR("NULL"); + UEStringType prior_prop_class_name = STR("NULL"); if (check_sub_object_value->GetClassPrivate() != nullptr) { prior_prop_class_name = get_native_class_name(check_sub_object_value->GetClassPrivate()); } implementation_file.append_line( - std::format(SYSSTR("FProperty* p_{}_Prior = GetClass()->FindPropertyByName(\"{}\");"), initializer, initializer)); - initializer = std::format(SYSSTR("*p_{}_Prior->ContainerPtrToValuePtr<{}*>(this)"), initializer, prior_prop_class_name); + std::format(STR("FProperty* p_{}_Prior = GetClass()->FindPropertyByName(\"{}\");"), initializer, initializer)); + initializer = std::format(STR("*p_{}_Prior->ContainerPtrToValuePtr<{}*>(this)"), initializer, prior_prop_class_name); } if (!super_and_no_access) { - initializer = std::format(SYSSTR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); + initializer = std::format(STR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); } else { - initializer = std::format(SYSSTR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); + initializer = std::format(STR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); generate_advanced_assignment_expression(property, initializer, implementation_file, property_scope, property_type); } } @@ -1534,16 +1534,16 @@ namespace RC::UEGenerator // Add an objectinitializer default subobject class override to the constructor implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); implementation_file.m_implementation_constructor.append( - std::format(SYSSTR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), object_name)); - m_class_subobjects.try_emplace(object_name, to_system(property->GetName())); + std::format(STR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), object_name)); + m_class_subobjects.try_emplace(object_name, (property->GetName())); } else { // Generate a CreateDefaultSubobject function call implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); - const SystemStringType object_class_name = get_native_class_name(object_class_type); - initializer = std::format(SYSSTR("CreateDefaultSubobject<{}>(TEXT(\"{}\"))"), object_class_name, object_name); - m_class_subobjects.try_emplace(object_name, to_system(property->GetName())); + const UEStringType object_class_name = get_native_class_name(object_class_type); + initializer = std::format(STR("CreateDefaultSubobject<{}>(TEXT(\"{}\"))"), object_class_name, object_name); + m_class_subobjects.try_emplace(object_name, (property->GetName())); if (!super_and_no_access) { generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); @@ -1562,14 +1562,14 @@ namespace RC::UEGenerator } if (attach_parent_object_value != NULL) { - const auto attach_parent_object_name = to_system(attach_parent_object_value->GetName()); - const SystemStringType operator_type = SYSSTR("->"); + const auto attach_parent_object_name = (attach_parent_object_value->GetName()); + const UEStringType operator_type = STR("->"); bool parent_found = false; - SystemStringType attach_string; + UEStringType attach_string; if (auto it = m_class_subobjects.find(attach_parent_object_name); it != m_class_subobjects.end()) { // Set property to equal previous property referencing the same object - attach_string = std::format(SYSSTR("SetupAttachment({})"), it->second); + attach_string = std::format(STR("SetupAttachment({})"), it->second); parent_found = true; } else if (as_class) @@ -1582,25 +1582,25 @@ namespace RC::UEGenerator UObject* check_sub_object_value = *check_object_property->ContainerPtrToValuePtr(object); if (check_sub_object_value) { - auto check_object_name = to_system(check_sub_object_value->GetName()); + auto check_object_name = (check_sub_object_value->GetName()); if (check_object_name == attach_parent_object_name) { if (get_property_access_modifier(check_object_property) != AccessModifier::Private) { - attach_string = std::format(SYSSTR("SetupAttachment({})"), to_system(check_property->GetName())); + attach_string = std::format(STR("SetupAttachment({})"), (check_property->GetName())); } else { - auto parent_property_name = std::format(SYSSTR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), - to_system(check_property->GetName()), - to_system(check_property->GetName())); + auto parent_property_name = std::format(STR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), + (check_property->GetName()), + (check_property->GetName())); if (!implementation_file.parent_property_names.contains(parent_property_name)) { implementation_file.parent_property_names.emplace(parent_property_name); implementation_file.append_line(parent_property_name); } - attach_string = std::format(SYSSTR("SetupAttachment(p_{}_Parent->ContainerPtrToValuePtr<{}>(this))"), - to_system(check_property->GetName()), + attach_string = std::format(STR("SetupAttachment(p_{}_Parent->ContainerPtrToValuePtr<{}>(this))"), + (check_property->GetName()), get_native_class_name(check_sub_object_value->GetClassPrivate())); implementation_file.add_dependency_object(check_sub_object_value->GetClassPrivate(), DependencyLevel::Include); } @@ -1642,8 +1642,8 @@ namespace RC::UEGenerator // Generate a ::StaticClass call if this object represents a class implementation_file.add_dependency_object(sub_object_as_class, DependencyLevel::Include); - const SystemStringType object_class_name = get_native_class_name(sub_object_as_class); - const SystemStringType initializer = std::format(SYSSTR("{}::StaticClass()"), object_class_name); + const UEStringType object_class_name = get_native_class_name(sub_object_as_class); + const UEStringType initializer = std::format(STR("{}::StaticClass()"), object_class_name); if (!super_and_no_access) { generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); @@ -1656,14 +1656,14 @@ namespace RC::UEGenerator } // Unhandled case, might be some external object reference - Output::send(SYSSTR("Unhandled default value of the FObjectProperty {}: {}\n"), to_system(property->GetFullName()), to_system(sub_object_value->GetFullName())); + Output::send(STR("Unhandled default value of the FObjectProperty {}: {}\n"), (property->GetFullName()), (sub_object_value->GetFullName())); return; } // Struct properties are serialization as normal struct constructors with custom scope // TODO there are a lot of issues with that regarding member access, unnecessary assignments and so on - /*if (FieldClassName == SYSSTR("StructProperty")) { + /*if (FieldClassName == STR("StructProperty")) { XStructProperty* StructProperty = static_cast(Property); UScriptStruct* ScriptStruct = StructProperty->get_script_struct(); @@ -1672,7 +1672,7 @@ namespace RC::UEGenerator } void* StructDataPointer = StructProperty->container_ptr_to_value_ptr(Object); - const SystemStringType NewPropertyScope = std::format(SYSSTR("{}{}."), PropertyScope, StructProperty->GetName()); + const UEStringType NewPropertyScope = std::format(STR("{}{}."), PropertyScope, StructProperty->GetName()); //Generate values for each struct property //TODO we do not really need to generate assignments for each struct member, we only really need members that are different from the constructor set @@ -1702,7 +1702,7 @@ namespace RC::UEGenerator { if (!super_and_no_access) { - implementation_file.append_line(std::format(SYSSTR("{}{}.AddDefaulted({});"), property_scope, to_system(property->GetName()), (int32_t)property_value->Num())); + implementation_file.append_line(std::format(STR("{}{}.AddDefaulted({});"), property_scope, (property->GetName()), (int32_t)property_value->Num())); } else { @@ -1737,16 +1737,16 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - SystemStringType number_constant_string; + UEStringType number_constant_string; if (!numeric_property->IsFloatingPoint()) { int64 value = numeric_property->GetSignedIntPropertyValue(numeric_property->ContainerPtrToValuePtr(object)); - number_constant_string = to_system( std::to_string(value)); + number_constant_string = to_ue(ToString(value)); } else { double value = numeric_property->GetFloatingPointPropertyValue(numeric_property->ContainerPtrToValuePtr(object)); - number_constant_string = std::format(SYSSTR("{:.2f}f"), value); + number_constant_string = std::format(STR("{:.2f}f"), value); } if (!super_and_no_access) { @@ -1767,23 +1767,23 @@ namespace RC::UEGenerator const CaseInsensitiveSet& blacklisted_property_names) -> void { const auto class_native_name = get_native_class_name(uclass, is_generating_interface); - const auto raw_function_name = to_system(function->GetName()); + const auto raw_function_name = (function->GetName()); auto function_flags = function->GetFunctionFlags(); - PropertyTypeDeclarationContext context(to_system(uclass->GetName()), &implementation_file); + PropertyTypeDeclarationContext context((uclass->GetName()), &implementation_file); - SystemStringType function_implementation_name; - SystemStringType net_validate_function_name; + UEStringType function_implementation_name; + UEStringType net_validate_function_name; bool is_input_function_const = ((function_flags)&FUNC_Const) != 0; if ((function_flags & FUNC_Net) != 0) { // Network functions always have the implementation inside the _Implementation function - function_implementation_name = std::format(SYSSTR("{}::{}_Implementation"), class_native_name, raw_function_name); + function_implementation_name = std::format(STR("{}::{}_Implementation"), class_native_name, raw_function_name); // Validated network functions by default have their validation function name set to _Validate if ((function_flags & FUNC_NetValidate) != 0) { - net_validate_function_name = std::format(SYSSTR("{}::{}_Validate"), class_native_name, raw_function_name); + net_validate_function_name = std::format(STR("{}::{}_Validate"), class_native_name, raw_function_name); } } else if ((function_flags & FUNC_BlueprintEvent) != 0) @@ -1792,16 +1792,16 @@ namespace RC::UEGenerator // BlueprintImplementableEvents do not have any native functions at all, they're just thunks if ((function_flags & FUNC_Native) != 0) { - function_implementation_name = std::format(SYSSTR("{}::{}_Implementation"), class_native_name, raw_function_name); + function_implementation_name = std::format(STR("{}::{}_Implementation"), class_native_name, raw_function_name); } } else { // Otherwise, normal UFunctions get a standard name matching the function in question - function_implementation_name = std::format(SYSSTR("{}::{}"), class_native_name, raw_function_name); + function_implementation_name = std::format(STR("{}::{}"), class_native_name, raw_function_name); } - SystemStringType function_parameter_list; + UEStringType function_parameter_list; if (!function_implementation_name.empty() || !net_validate_function_name.empty()) { function_parameter_list = @@ -1812,63 +1812,63 @@ namespace RC::UEGenerator { FProperty* return_value_property = function->GetReturnProperty(); - const SystemStringType return_value_type = return_value_property ? generate_property_type_declaration(return_value_property, context) : SYSSTR("void"); + const UEStringType return_value_type = return_value_property ? generate_property_type_declaration(return_value_property, context) : STR("void"); - implementation_file.append_line(std::format(SYSSTR("{} {}({}){} {{"), + implementation_file.append_line(std::format(STR("{} {}({}){} {{"), return_value_type, function_implementation_name, function_parameter_list, - is_input_function_const ? SYSSTR(" const") : SYSSTR(""))); + is_input_function_const ? STR(" const") : STR(""))); implementation_file.begin_indent_level(); if (return_value_property != NULL) { - const SystemStringType default_value = generate_default_property_value(return_value_property, implementation_file, context.context_name); - implementation_file.append_line(std::format(SYSSTR("return {};"), default_value)); + const UEStringType default_value = generate_default_property_value(return_value_property, implementation_file, context.context_name); + implementation_file.append_line(std::format(STR("return {};"), default_value)); } implementation_file.end_indent_level(); - implementation_file.append_line(SYSSTR("}")); + implementation_file.append_line(STR("}")); } if (!net_validate_function_name.empty()) { - implementation_file.append_line(std::format(SYSSTR("bool {}({}) {{"), net_validate_function_name, function_parameter_list)); + implementation_file.append_line(std::format(STR("bool {}({}) {{"), net_validate_function_name, function_parameter_list)); implementation_file.begin_indent_level(); - implementation_file.append_line(SYSSTR("return true;")); + implementation_file.append_line(STR("return true;")); implementation_file.end_indent_level(); - implementation_file.append_line(SYSSTR("}")); + implementation_file.append_line(STR("}")); } } - auto UEHeaderGenerator::generate_parameter_count_string(int32_t parameter_count) -> SystemStringType + auto UEHeaderGenerator::generate_parameter_count_string(int32_t parameter_count) -> UEStringType { switch (parameter_count) { case 0: - return SYSSTR(""); + return STR(""); case 1: - return SYSSTR("_OneParam"); + return STR("_OneParam"); case 2: - return SYSSTR("_TwoParams"); + return STR("_TwoParams"); case 3: - return SYSSTR("_ThreeParams"); + return STR("_ThreeParams"); case 4: - return SYSSTR("_FourParams"); + return STR("_FourParams"); case 5: - return SYSSTR("_FiveParams"); + return STR("_FiveParams"); case 6: - return SYSSTR("_SixParams"); + return STR("_SixParams"); case 7: - return SYSSTR("_SevenParams"); + return STR("_SevenParams"); case 8: - return SYSSTR("_EightParams"); + return STR("_EightParams"); case 9: - return SYSSTR("_NineParams"); + return STR("_NineParams"); default: - return SYSSTR("_TooMany"); + return STR("_TooMany"); } } @@ -1880,15 +1880,15 @@ namespace RC::UEGenerator if (needed_access == AccessModifier::Public) { - header_data.append_line_no_indent(SYSSTR("public:")); + header_data.append_line_no_indent(STR("public:")); } else if (needed_access == AccessModifier::Protected) { - header_data.append_line_no_indent(SYSSTR("protected:")); + header_data.append_line_no_indent(STR("protected:")); } else if (needed_access == AccessModifier::Private) { - header_data.append_line_no_indent(SYSSTR("private:")); + header_data.append_line_no_indent(STR("private:")); } } } @@ -1931,10 +1931,10 @@ namespace RC::UEGenerator return AccessModifier::Public; } - auto UEHeaderGenerator::create_string_literal(const SystemStringType& string) -> SystemStringType + auto UEHeaderGenerator::create_string_literal(const UEStringType& string) -> UEStringType { - SystemStringType result; - result.append(SYSSTR("TEXT(\"")); + UEStringType result; + result.append(STR("TEXT(\"")); bool previous_character_was_hex = false; @@ -1943,28 +1943,28 @@ namespace RC::UEGenerator { switch (ch) { - case SYSSTR('\r'): { + case STR('\r'): { continue; } - case SYSSTR('\n'): { - result.append(SYSSTR("\\n")); + case STR('\n'): { + result.append(STR("\\n")); previous_character_was_hex = false; break; } - case SYSSTR('\\'): { - result.append(SYSSTR("\\\\")); + case STR('\\'): { + result.append(STR("\\\\")); previous_character_was_hex = false; break; } - case SYSSTR('\"'): { - result.append(SYSSTR("\\\"")); + case STR('\"'): { + result.append(STR("\\\"")); previous_character_was_hex = false; break; } default: { if ((unsigned char)ch < 31 || (unsigned char)ch >= 128) { - result.append(std::format(SYSSTR("\\x{:04X}"), ch)); + result.append(std::format(STR("\\x{:04X}"), ch)); previous_character_was_hex = true; } else @@ -1973,7 +1973,7 @@ namespace RC::UEGenerator // appended to the hex sequence, causing a different number if (previous_character_was_hex && iswxdigit(ch) != 0) { - result.append(SYSSTR("\")TEXT(\"")); + result.append(STR("\")TEXT(\"")); } previous_character_was_hex = false; result.push_back(ch); @@ -1982,19 +1982,19 @@ namespace RC::UEGenerator } } } - result.append(SYSSTR("\")")); + result.append(STR("\")")); return result; } - auto UEHeaderGenerator::convert_module_name_to_api_name(const SystemStringType& module_name) -> SystemStringType + auto UEHeaderGenerator::convert_module_name_to_api_name(const UEStringType& module_name) -> UEStringType { - SystemStringType uppercase_string = string_to_uppercase(module_name); - uppercase_string.append(SYSSTR("_API")); + UEStringType uppercase_string = string_to_uppercase(module_name); + uppercase_string.append(STR("_API")); return uppercase_string; } - auto UEHeaderGenerator::add_module_and_sub_module_dependencies(std::set& out_module_dependencies, - const SystemStringType& module_name, + auto UEHeaderGenerator::add_module_and_sub_module_dependencies(std::set& out_module_dependencies, + const UEStringType& module_name, bool add_self_module) -> void { // Prevent infinite recursion @@ -2010,7 +2010,7 @@ namespace RC::UEGenerator const auto iterator = m_module_dependencies.find(module_name); if (iterator != m_module_dependencies.end()) { - for (const SystemStringType& DependencyModuleName : *iterator->second) + for (const UEStringType& DependencyModuleName : *iterator->second) { out_module_dependencies.insert(DependencyModuleName); } @@ -2027,12 +2027,12 @@ namespace RC::UEGenerator for (FProperty* property : class_object->ForEachProperty()) { - result_set.insert(to_system(property->GetName())); + result_set.insert((property->GetName())); } for (UFunction* function : class_object->ForEachFunction()) { - result_set.insert(to_system(function->GetName())); + result_set.insert((function->GetName())); } } else if (uclass->GetClassPrivate()->IsChildOf(UScriptStruct::StaticClass())) @@ -2041,7 +2041,7 @@ namespace RC::UEGenerator for (FProperty* property : script_struct->ForEachProperty()) { - result_set.insert(to_system(property->GetName())); + result_set.insert((property->GetName())); } } return result_set; @@ -2049,7 +2049,7 @@ namespace RC::UEGenerator // TODO CannotImplementInterfaceInBlueprint is not exactly right, // TODO you can have interface with no implementable blueprint methods but that you can still implement in blueprint - auto UEHeaderGenerator::generate_interface_flags(UClass* uinterface) const -> SystemStringType + auto UEHeaderGenerator::generate_interface_flags(UClass* uinterface) const -> UEStringType { FlagFormatHelper flag_format_helper{}; @@ -2061,7 +2061,7 @@ namespace RC::UEGenerator if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(SYSSTR("MinimalAPI")); + flag_format_helper.add_switch(STR("MinimalAPI")); } ClassBlueprintInfo blueprint_info = get_class_blueprint_info(uinterface); @@ -2071,22 +2071,22 @@ namespace RC::UEGenerator { if (!parent_blueprint_info.is_blueprintable) { - flag_format_helper.add_switch(SYSSTR("Blueprintable")); + flag_format_helper.add_switch(STR("Blueprintable")); } } else if (blueprint_info.is_blueprint_type) { if (!parent_blueprint_info.is_blueprint_type) { - flag_format_helper.add_switch(SYSSTR("BlueprintType")); + flag_format_helper.add_switch(STR("BlueprintType")); } - flag_format_helper.get_meta()->add_switch(SYSSTR("CannotImplementInterfaceInBlueprint")); + flag_format_helper.get_meta()->add_switch(STR("CannotImplementInterfaceInBlueprint")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_class_flags(UClass* uclass) const -> SystemStringType + auto UEHeaderGenerator::generate_class_flags(UClass* uclass) const -> UEStringType { FlagFormatHelper flag_format_helper{}; @@ -2098,7 +2098,7 @@ namespace RC::UEGenerator if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(SYSSTR("MinimalAPI")); + flag_format_helper.add_switch(STR("MinimalAPI")); } ClassBlueprintInfo blueprint_info = get_class_blueprint_info(uclass); @@ -2110,7 +2110,7 @@ namespace RC::UEGenerator if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(SYSSTR("Blueprintable")); + flag_format_helper.add_switch(STR("Blueprintable")); } else { @@ -2118,97 +2118,97 @@ namespace RC::UEGenerator { if (!parent_blueprint_info.is_blueprintable) { - flag_format_helper.add_switch(SYSSTR("Blueprintable")); + flag_format_helper.add_switch(STR("Blueprintable")); } } else if (blueprint_info.is_blueprint_type) { if (!parent_blueprint_info.is_blueprint_type) { - flag_format_helper.add_switch(SYSSTR("BlueprintType")); + flag_format_helper.add_switch(STR("BlueprintType")); } } } if ((class_own_flags & CLASS_Deprecated) != 0) { - flag_format_helper.add_switch(SYSSTR("Deprecated")); + flag_format_helper.add_switch(STR("Deprecated")); } if ((class_own_flags & CLASS_Abstract) != 0) { - flag_format_helper.add_switch(SYSSTR("Abstract")); + flag_format_helper.add_switch(STR("Abstract")); } if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(SYSSTR("MinimalAPI")); + flag_format_helper.add_switch(STR("MinimalAPI")); } if ((class_own_flags & CLASS_NoExport) != 0) { - flag_format_helper.add_switch(SYSSTR("NoExport")); + flag_format_helper.add_switch(STR("NoExport")); } // TODO not quite the case, because UHT boilerplate implicitly marks every native class as CLASS_Intrinsic // if ((ClassOwnFlags & CLASS_Intrinsic) != 0) { - // FlagFormatHelper.AddSwitch(SYSSTR("Intrinsic")); + // FlagFormatHelper.AddSwitch(STR("Intrinsic")); // } if ((class_own_flags & CLASS_Const) != 0) { - flag_format_helper.add_switch(SYSSTR("Const")); + flag_format_helper.add_switch(STR("Const")); } if ((class_own_flags & CLASS_DefaultToInstanced) != 0) { - flag_format_helper.add_switch(SYSSTR("DefaultToInstanced")); + flag_format_helper.add_switch(STR("DefaultToInstanced")); } UClass* class_within = uclass->GetClassWithin(); if (class_within != NULL && class_within != UObject::StaticClass() && (super_class == NULL || class_within != super_class->GetClassWithin())) { - flag_format_helper.add_parameter(SYSSTR("Within"), to_system(class_within->GetName())); + flag_format_helper.add_parameter(STR("Within"), (class_within->GetName())); } if ((class_own_flags & CLASS_Transient) != 0) { - flag_format_helper.add_switch(SYSSTR("Transient")); + flag_format_helper.add_switch(STR("Transient")); } else if ((parent_class_flags & CLASS_Transient) != 0) { - flag_format_helper.add_switch(SYSSTR("NonTransient")); + flag_format_helper.add_switch(STR("NonTransient")); } if ((class_own_flags & CLASS_EditInlineNew) != 0) { - flag_format_helper.add_switch(SYSSTR("EditInlineNew")); + flag_format_helper.add_switch(STR("EditInlineNew")); } else if ((class_flags & CLASS_EditInlineNew) == 0 && (parent_class_flags & CLASS_EditInlineNew) != 0) { - flag_format_helper.add_switch(SYSSTR("NotEditInlineNew")); + flag_format_helper.add_switch(STR("NotEditInlineNew")); } if ((class_own_flags & CLASS_NotPlaceable) != 0) { - flag_format_helper.add_switch(SYSSTR("NotPlaceable")); + flag_format_helper.add_switch(STR("NotPlaceable")); } else if ((class_flags & CLASS_NotPlaceable) == 0 && (parent_class_flags & CLASS_NotPlaceable) != 0) { - flag_format_helper.add_switch(SYSSTR("Placeable")); + flag_format_helper.add_switch(STR("Placeable")); } bool add_config_name{false}; if ((class_own_flags & CLASS_DefaultConfig) != 0) { - flag_format_helper.add_switch(SYSSTR("DefaultConfig")); + flag_format_helper.add_switch(STR("DefaultConfig")); add_config_name = true; } if ((class_own_flags & CLASS_GlobalUserConfig) != 0) { - flag_format_helper.add_switch(SYSSTR("GlobalUserConfig")); + flag_format_helper.add_switch(STR("GlobalUserConfig")); add_config_name = true; } if ((class_own_flags & CLASS_ProjectUserConfig) != 0) { - flag_format_helper.add_switch(SYSSTR("ProjectUserConfig")); + flag_format_helper.add_switch(STR("ProjectUserConfig")); add_config_name = true; } @@ -2223,52 +2223,52 @@ namespace RC::UEGenerator const UEStringType class_config_name = uclass->GetClassConfigName().ToString(); if (super_class == NULL || class_config_name != super_class->GetClassConfigName().ToString()) { - flag_format_helper.add_parameter(SYSSTR("Config"), to_system(class_config_name)); + flag_format_helper.add_parameter(STR("Config"), (class_config_name)); // Don't add our override config if we add the real one here add_config_name = false; } if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllConfigsEngineConfig && add_config_name) { - flag_format_helper.add_parameter(SYSSTR("Config"), SYSSTR("Engine")); + flag_format_helper.add_parameter(STR("Config"), STR("Engine")); } if ((class_own_flags & CLASS_PerObjectConfig) != 0) { - flag_format_helper.add_switch(SYSSTR("PerObjectConfig")); + flag_format_helper.add_switch(STR("PerObjectConfig")); } if ((class_own_flags & CLASS_ConfigDoNotCheckDefaults) != 0) { - flag_format_helper.add_switch(SYSSTR("ConfigDoNotCheckDefaults")); + flag_format_helper.add_switch(STR("ConfigDoNotCheckDefaults")); } if ((class_own_flags & CLASS_HideDropDown) != 0) { - flag_format_helper.add_switch(SYSSTR("HideDropdown")); + flag_format_helper.add_switch(STR("HideDropdown")); } if ((class_own_flags & CLASS_CollapseCategories) != 0) { - flag_format_helper.add_switch(SYSSTR("CollapseCategories")); + flag_format_helper.add_switch(STR("CollapseCategories")); } else if ((parent_class_flags & CLASS_CollapseCategories) != 0) { - flag_format_helper.add_switch(SYSSTR("DontCollapseCategories")); + flag_format_helper.add_switch(STR("DontCollapseCategories")); } // Mark all UActorComponent derived classes as BlueprintSpawnableComponent by default // This will allow using them inside the Simple Construction Script of the blueprint assets if (uclass->IsChildOf()) { - flag_format_helper.get_meta()->add_switch(SYSSTR("BlueprintSpawnableComponent")); - flag_format_helper.add_parameter(SYSSTR("ClassGroup"), SYSSTR("Custom")); + flag_format_helper.get_meta()->add_switch(STR("BlueprintSpawnableComponent")); + flag_format_helper.add_parameter(STR("ClassGroup"), STR("Custom")); } return flag_format_helper.build_flag_string(); } /**/ - auto UEHeaderGenerator::generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> SystemStringType + auto UEHeaderGenerator::generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> UEStringType { UClass* current_class = Unreal::Cast(property->GetOutermostOwner()); const UEStringType field_class_name = property->GetClass().GetName(); @@ -2286,7 +2286,7 @@ namespace RC::UEGenerator context.source_file->add_dependency_object(enum_value, DependencyLevel::Include); } - const SystemStringType enum_type_name = get_native_enum_name(enum_value); + const UEStringType enum_type_name = get_native_enum_name(enum_value); if ((property->GetPropertyFlags() & CPF_BlueprintVisible) != 0) { @@ -2294,9 +2294,9 @@ namespace RC::UEGenerator } // Non-EnumClass enumerations should be wrapped into TEnumAsByte according to UHT, but implicit uint8s should not use TEnumAsByte - return std::format(SYSSTR("TEnumAsByte<{}>"), enum_type_name); + return std::format(STR("TEnumAsByte<{}>"), enum_type_name); } - return SYSSTR("uint8"); + return STR("uint8"); } // Enum Property @@ -2313,14 +2313,14 @@ namespace RC::UEGenerator { context.source_file->add_dependency_object(uenum, DependencyLevel::Include); } - const SystemStringType enum_type_name = get_native_enum_name(uenum); + const UEStringType enum_type_name = get_native_enum_name(uenum); if ((property->GetPropertyFlags() & CPF_BlueprintVisible) != 0) { this->m_blueprint_visible_enums.insert(enum_type_name); } - const SystemStringType underlying_enum_type = generate_property_type_declaration(underlying_property, context); + const UEStringType underlying_enum_type = generate_property_type_declaration(underlying_property, context); this->m_underlying_enum_types.insert({enum_type_name, underlying_enum_type}); return enum_type_name; } @@ -2334,48 +2334,48 @@ namespace RC::UEGenerator if (bool_property->GetFieldMask() != 255) { *context.out_is_bitmask_bool = true; - return SYSSTR("uint8"); + return STR("uint8"); } } - return SYSSTR("bool"); + return STR("bool"); } // Standard Numeric Properties if (property->IsA()) { - return SYSSTR("int8"); + return STR("int8"); } else if (property->IsA()) { - return SYSSTR("int16"); + return STR("int16"); } else if (property->IsA()) { - return SYSSTR("int32"); + return STR("int32"); } else if (property->IsA()) { - return SYSSTR("int64"); + return STR("int64"); } else if (property->IsA()) { - return SYSSTR("uint16"); + return STR("uint16"); } else if (property->IsA()) { - return SYSSTR("uint32"); + return STR("uint32"); } else if (property->IsA()) { - return SYSSTR("uint64"); + return STR("uint64"); } else if (property->IsA()) { - return SYSSTR("float"); + return STR("float"); } else if (property->IsA()) { - return SYSSTR("double"); + return STR("double"); } // Class Properties @@ -2386,23 +2386,23 @@ namespace RC::UEGenerator if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return SYSSTR("UClass*"); + return STR("UClass*"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(meta_class, DependencyLevel::PreDeclaration); - context.source_file->add_extra_include(SYSSTR("Templates/SubclassOf.h")); + context.source_file->add_extra_include(STR("Templates/SubclassOf.h")); } - const SystemStringType meta_class_name = get_native_class_name(meta_class, false); + const UEStringType meta_class_name = get_native_class_name(meta_class, false); - return std::format(SYSSTR("TSubclassOf<{}>"), meta_class_name); + return std::format(STR("TSubclassOf<{}>"), meta_class_name); } if (auto* class_property = CastField(property); class_property) { // TODO: Confirm that this is accurate - return SYSSTR("TClassPtr"); + return STR("TClassPtr"); } if (property->IsA()) @@ -2412,16 +2412,16 @@ namespace RC::UEGenerator if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return SYSSTR("TSoftClassPtr"); + return STR("TSoftClassPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(meta_class, DependencyLevel::PreDeclaration); } - const SystemStringType meta_class_name = get_native_class_name(meta_class, false); + const UEStringType meta_class_name = get_native_class_name(meta_class, false); - return std::format(SYSSTR("TSoftClassPtr<{}>"), meta_class_name); + return std::format(STR("TSoftClassPtr<{}>"), meta_class_name); } // Object Properties @@ -2434,15 +2434,15 @@ namespace RC::UEGenerator if (property_class == NULL) { - return SYSSTR("UObject*"); + return STR("UObject*"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const SystemStringType property_class_name = get_native_class_name(property_class, false); + const UEStringType property_class_name = get_native_class_name(property_class, false); - return std::format(SYSSTR("{}*"), property_class_name); + return std::format(STR("{}*"), property_class_name); } if (auto* object_property = CastField(property); object_property) @@ -2451,7 +2451,7 @@ namespace RC::UEGenerator if (!property_class) { - return SYSSTR("TObjectPtr"); + return STR("TObjectPtr"); } else { @@ -2461,7 +2461,7 @@ namespace RC::UEGenerator } const auto property_class_name = get_native_class_name(property_class, false); - return std::format(SYSSTR("TObjectPtr<{}>"), property_class_name); + return std::format(STR("TObjectPtr<{}>"), property_class_name); } } @@ -2472,16 +2472,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return SYSSTR("TWeakObjectPtr"); + return STR("TWeakObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const SystemStringType property_class_name = get_native_class_name(property_class, false); + const UEStringType property_class_name = get_native_class_name(property_class, false); - return std::format(SYSSTR("TWeakObjectPtr<{}>"), property_class_name); + return std::format(STR("TWeakObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -2491,16 +2491,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return SYSSTR("TLazyObjectPtr"); + return STR("TLazyObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const SystemStringType property_class_name = get_native_class_name(property_class, false); + const UEStringType property_class_name = get_native_class_name(property_class, false); - return std::format(SYSSTR("TLazyObjectPtr<{}>"), property_class_name); + return std::format(STR("TLazyObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -2510,16 +2510,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return SYSSTR("TSoftObjectPtr"); + return STR("TSoftObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const SystemStringType property_class_name = get_native_class_name(property_class, false); + const UEStringType property_class_name = get_native_class_name(property_class, false); - return std::format(SYSSTR("TSoftObjectPtr<{}>"), property_class_name); + return std::format(STR("TSoftObjectPtr<{}>"), property_class_name); } // Interface Property @@ -2530,16 +2530,16 @@ namespace RC::UEGenerator if (interface_class == NULL || interface_class == UInterface::StaticClass()) { - return SYSSTR("FScriptInterface"); + return STR("FScriptInterface"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(interface_class, DependencyLevel::PreDeclaration); } - const SystemStringType interface_class_name = get_native_class_name(interface_class, true); + const UEStringType interface_class_name = get_native_class_name(interface_class, true); - return std::format(SYSSTR("TScriptInterface<{}>"), interface_class_name); + return std::format(STR("TScriptInterface<{}>"), interface_class_name); } // Struct Property @@ -2552,7 +2552,7 @@ namespace RC::UEGenerator { throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } - const SystemStringType native_struct_name = get_native_struct_name(script_struct); + const UEStringType native_struct_name = get_native_struct_name(script_struct); if (context.source_file != NULL) { @@ -2621,8 +2621,8 @@ namespace RC::UEGenerator if (property->IsA()) { FFieldPathProperty* field_path_property = static_cast(property); - const auto property_class_name = to_system(field_path_property->GetPropertyClass()->GetName()); - return std::format(SYSSTR("TFieldPath"), property_class_name); + const auto property_class_name = (field_path_property->GetPropertyClass()->GetName()); + return std::format(STR("TFieldPath"), property_class_name); } // Collection and Map Properties @@ -2632,8 +2632,8 @@ namespace RC::UEGenerator FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - const SystemStringType inner_property_type = generate_property_type_declaration(inner_property, context.inner_context()); - return std::format(SYSSTR("TArray<{}>"), inner_property_type); + const UEStringType inner_property_type = generate_property_type_declaration(inner_property, context.inner_context()); + return std::format(STR("TArray<{}>"), inner_property_type); } if (property->IsA()) @@ -2641,8 +2641,8 @@ namespace RC::UEGenerator FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const SystemStringType element_property_type = generate_property_type_declaration(element_prop, context.inner_context()); - return std::format(SYSSTR("TSet<{}>"), element_property_type); + const UEStringType element_property_type = generate_property_type_declaration(element_prop, context.inner_context()); + return std::format(STR("TSet<{}>"), element_property_type); } // TODO: This is missing support for freeze image map properties because XMapProperty is incomplete. (low priority) @@ -2652,24 +2652,24 @@ namespace RC::UEGenerator FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - const SystemStringType key_type = generate_property_type_declaration(key_property, context.inner_context()); - const SystemStringType value_type = generate_property_type_declaration(value_property, context.inner_context()); + const UEStringType key_type = generate_property_type_declaration(key_property, context.inner_context()); + const UEStringType value_type = generate_property_type_declaration(value_property, context.inner_context()); - return std::format(SYSSTR("TMap<{}, {}>"), key_type, value_type); + return std::format(STR("TMap<{}, {}>"), key_type, value_type); } // Standard properties that do not have any special attributes if (property->IsA()) { - return SYSSTR("FName"); + return STR("FName"); } else if (property->IsA()) { - return SYSSTR("FString"); + return STR("FString"); } else if (property->IsA()) { - return SYSSTR("FText"); + return STR("FText"); } throw std::runtime_error(RC::fmt("[generate_property_type_declaration] Unsupported property class '{}', full name: '{}'", field_class_name, @@ -2677,38 +2677,38 @@ namespace RC::UEGenerator } //*/ - auto UEHeaderGenerator::generate_function_argument_flags(FProperty* property) const -> SystemStringType + auto UEHeaderGenerator::generate_function_argument_flags(FProperty* property) const -> UEStringType { FlagFormatHelper flag_format_helper{}; auto property_flags = property->GetPropertyFlags(); // CPF_ConstParm is handled explicitly in the parameter list generator, it will generate const before parameter // if ((PropertyFlags & CPF_ConstParm) != 0) { - // FlagFormatHelper.AddSwitch(SYSSTR("Const")); + // FlagFormatHelper.AddSwitch(STR("Const")); // } // We only want to add UPARAM(Ref) when parameter is marked as reference AND output, // while not being marked as constant, because if it's marked as constant, it might be a parameter passed by const reference if ((property_flags & CPF_ReferenceParm) != 0 && (property_flags & CPF_OutParm) != 0 && (property_flags & CPF_ConstParm) == 0) { - flag_format_helper.add_switch(SYSSTR("Ref")); + flag_format_helper.add_switch(STR("Ref")); } if ((property_flags & CPF_RepSkip) != 0) { - flag_format_helper.add_switch(SYSSTR("NotReplicated")); + flag_format_helper.add_switch(STR("NotReplicated")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_property_flags(FProperty* property) const -> SystemStringType + auto UEHeaderGenerator::generate_property_flags(FProperty* property) const -> UEStringType { FlagFormatHelper flag_format_helper{}; auto property_flags = property->GetPropertyFlags(); if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(SYSSTR("EditAnywhere")); + flag_format_helper.add_switch(STR("EditAnywhere")); } else if ((property_flags & CPF_Edit) != 0) { @@ -2716,97 +2716,97 @@ namespace RC::UEGenerator { if ((property_flags & CPF_DisableEditOnTemplate) != 0) { - flag_format_helper.add_switch(SYSSTR("VisibleInstanceOnly")); + flag_format_helper.add_switch(STR("VisibleInstanceOnly")); } else if ((property_flags & CPF_DisableEditOnInstance) != 0) { - flag_format_helper.add_switch(SYSSTR("VisibleDefaultsOnly")); + flag_format_helper.add_switch(STR("VisibleDefaultsOnly")); } else { - flag_format_helper.add_switch(SYSSTR("VisibleAnywhere")); + flag_format_helper.add_switch(STR("VisibleAnywhere")); } } else { if ((property_flags & CPF_DisableEditOnTemplate) != 0) { - flag_format_helper.add_switch(SYSSTR("EditInstanceOnly")); + flag_format_helper.add_switch(STR("EditInstanceOnly")); } else if ((property_flags & CPF_DisableEditOnInstance) != 0) { - flag_format_helper.add_switch(SYSSTR("EditDefaultsOnly")); + flag_format_helper.add_switch(STR("EditDefaultsOnly")); } else { - flag_format_helper.add_switch(SYSSTR("EditAnywhere")); + flag_format_helper.add_switch(STR("EditAnywhere")); } } } if ((property_flags & CPF_NoClear) != 0) { - flag_format_helper.add_switch(SYSSTR("NoClear")); + flag_format_helper.add_switch(STR("NoClear")); } if ((property_flags & CPF_EditFixedSize) != 0) { - flag_format_helper.add_switch(SYSSTR("EditFixedSize")); + flag_format_helper.add_switch(STR("EditFixedSize")); } if ((property_flags & CPF_SimpleDisplay) != 0) { - flag_format_helper.add_switch(SYSSTR("SimpleDisplay")); + flag_format_helper.add_switch(STR("SimpleDisplay")); } if ((property_flags & CPF_AdvancedDisplay) != 0) { - flag_format_helper.add_switch(SYSSTR("AdvancedDisplay")); + flag_format_helper.add_switch(STR("AdvancedDisplay")); } if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { if (property->GetArrayDim() == 1 && is_subtype_valid(property)) { - flag_format_helper.add_switch(SYSSTR("BlueprintReadWrite")); + flag_format_helper.add_switch(STR("BlueprintReadWrite")); } - flag_format_helper.get_meta()->add_parameter(SYSSTR("AllowPrivateAccess"), SYSSTR("true")); + flag_format_helper.get_meta()->add_parameter(STR("AllowPrivateAccess"), STR("true")); } else if ((property_flags & CPF_BlueprintVisible) != 0) { if ((property_flags & CPF_BlueprintReadOnly) != 0) { - flag_format_helper.add_switch(SYSSTR("BlueprintReadOnly")); + flag_format_helper.add_switch(STR("BlueprintReadOnly")); } else { - flag_format_helper.add_switch(SYSSTR("BlueprintReadWrite")); + flag_format_helper.add_switch(STR("BlueprintReadWrite")); } if ((property_flags & CPF_NativeAccessSpecifierPrivate) != 0) { - flag_format_helper.get_meta()->add_parameter(SYSSTR("AllowPrivateAccess"), SYSSTR("true")); + flag_format_helper.get_meta()->add_parameter(STR("AllowPrivateAccess"), STR("true")); } } if ((property_flags & CPF_BlueprintAssignable) != 0) { - flag_format_helper.add_switch(SYSSTR("BlueprintAssignable")); + flag_format_helper.add_switch(STR("BlueprintAssignable")); } if ((property_flags & CPF_BlueprintCallable) != 0) { - flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); + flag_format_helper.add_switch(STR("BlueprintCallable")); } if ((property_flags & CPF_BlueprintAuthorityOnly) != 0) { - flag_format_helper.add_switch(SYSSTR("BlueprintAuthorityOnly")); + flag_format_helper.add_switch(STR("BlueprintAuthorityOnly")); } if ((property_flags & CPF_Config) != 0) { if ((property_flags & CPF_GlobalConfig) != 0) { - flag_format_helper.add_switch(SYSSTR("GlobalConfig")); + flag_format_helper.add_switch(STR("GlobalConfig")); } else { - flag_format_helper.add_switch(SYSSTR("Config")); + flag_format_helper.add_switch(STR("Config")); } } @@ -2814,55 +2814,55 @@ namespace RC::UEGenerator { if ((property_flags & CPF_RepNotify) != 0) { - const auto rep_notify_func_name = to_system(property->GetRepNotifyFunc().ToString()); - flag_format_helper.add_parameter(SYSSTR("ReplicatedUsing"), rep_notify_func_name); + const auto rep_notify_func_name = (property->GetRepNotifyFunc().ToString()); + flag_format_helper.add_parameter(STR("ReplicatedUsing"), rep_notify_func_name); } else { - flag_format_helper.add_switch(SYSSTR("Replicated")); + flag_format_helper.add_switch(STR("Replicated")); } } if ((property_flags & CPF_RepSkip) != 0) { - flag_format_helper.add_switch(SYSSTR("NotReplicated")); + flag_format_helper.add_switch(STR("NotReplicated")); } if ((property_flags & CPF_AssetRegistrySearchable) != 0) { - flag_format_helper.add_switch(SYSSTR("AssetRegistrySearchable")); + flag_format_helper.add_switch(STR("AssetRegistrySearchable")); } if ((property_flags & CPF_Interp) != 0) { - flag_format_helper.add_switch(SYSSTR("Interp")); + flag_format_helper.add_switch(STR("Interp")); } if ((property_flags & CPF_SaveGame) != 0) { - flag_format_helper.add_switch(SYSSTR("SaveGame")); + flag_format_helper.add_switch(STR("SaveGame")); } if ((property_flags & CPF_NonTransactional) != 0) { - flag_format_helper.add_switch(SYSSTR("NonTransactional")); + flag_format_helper.add_switch(STR("NonTransactional")); } if ((property_flags & CPF_Transient) != 0) { - flag_format_helper.add_switch(SYSSTR("Transient")); + flag_format_helper.add_switch(STR("Transient")); } if ((property_flags & CPF_DuplicateTransient) != 0) { - flag_format_helper.add_switch(SYSSTR("DuplicateTransient")); + flag_format_helper.add_switch(STR("DuplicateTransient")); } if ((property_flags & CPF_TextExportTransient) != 0) { - flag_format_helper.add_switch(SYSSTR("TextExportTransient")); + flag_format_helper.add_switch(STR("TextExportTransient")); } if ((property_flags & CPF_NonPIEDuplicateTransient) != 0) { - flag_format_helper.add_switch(SYSSTR("NonPIEDuplicateTransient")); + flag_format_helper.add_switch(STR("NonPIEDuplicateTransient")); } if ((property_flags & CPF_SkipSerialization) != 0) { - flag_format_helper.add_switch(SYSSTR("SkipSerialization")); + flag_format_helper.add_switch(STR("SkipSerialization")); } // Need to have all of these flags, otherwise we might accidentally get Instanced of delegate properties; CPF_ExportObject is not set for delegate properties @@ -2875,16 +2875,16 @@ namespace RC::UEGenerator (property->IsA() || (property->IsA() && static_cast(property)->GetInner()->IsA()) || (property->IsA() && static_cast(property)->GetValueProp()->IsA()))) { - flag_format_helper.add_switch(SYSSTR("Instanced")); + flag_format_helper.add_switch(STR("Instanced")); } else if ((property_flags & CPF_ExportObject) != 0) { - flag_format_helper.add_switch(SYSSTR("Export")); + flag_format_helper.add_switch(STR("Export")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_struct_flags(UScriptStruct* script_struct) const -> SystemStringType + auto UEHeaderGenerator::generate_struct_flags(UScriptStruct* script_struct) const -> UEStringType { FlagFormatHelper flag_format_helper{}; @@ -2894,29 +2894,29 @@ namespace RC::UEGenerator EStructFlags struct_own_flags = (EStructFlags)(struct_flags & (~(parent_struct_flags & STRUCT_Inherit))); - const SystemStringType native_struct_name = get_native_struct_name(script_struct); + const UEStringType native_struct_name = get_native_struct_name(script_struct); if (is_struct_blueprint_type(script_struct) || m_blueprint_visible_structs.contains(native_struct_name) || UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(SYSSTR("BlueprintType")); + flag_format_helper.add_switch(STR("BlueprintType")); } if ((struct_own_flags & STRUCT_NoExport) != 0) { - flag_format_helper.add_switch(SYSSTR("NoExport")); + flag_format_helper.add_switch(STR("NoExport")); } if ((struct_own_flags & STRUCT_Atomic) != 0) { - flag_format_helper.add_switch(SYSSTR("Atomic")); + flag_format_helper.add_switch(STR("Atomic")); } if ((struct_own_flags & STRUCT_Immutable) != 0) { - flag_format_helper.add_switch(SYSSTR("Immutable")); + flag_format_helper.add_switch(STR("Immutable")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_enum_flags(UEnum* uenum) const -> SystemStringType + auto UEHeaderGenerator::generate_enum_flags(UEnum* uenum) const -> UEStringType { FlagFormatHelper flag_format_helper{}; @@ -2925,9 +2925,9 @@ namespace RC::UEGenerator if ((((int32_t)enum_flags) & ((int32_t)EEnumFlags::Flags)) != 0) { - flag_format_helper.add_switch(SYSSTR("Flags")); + flag_format_helper.add_switch(STR("Flags")); } - const SystemStringType enum_native_name = get_native_enum_name(uenum); + const UEStringType enum_native_name = get_native_enum_name(uenum); if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeEnumClassesBlueprintType) { @@ -2935,30 +2935,30 @@ namespace RC::UEGenerator if (cpp_form == UEnum::ECppForm::EnumClass) { const auto underlying_type = m_underlying_enum_types.find(enum_native_name); - if (underlying_type->second == SYSSTR("uint8") || + if (underlying_type->second == STR("uint8") || (underlying_type == m_underlying_enum_types.end() && (get_highest_enum(uenum) <= 255 && get_lowest_enum(uenum) >= 0))) { // Underlying type is implicit or explicitly uint8. - flag_format_helper.add_switch(SYSSTR("BlueprintType")); + flag_format_helper.add_switch(STR("BlueprintType")); } } else { - flag_format_helper.add_switch(SYSSTR("BlueprintType")); + flag_format_helper.add_switch(STR("BlueprintType")); } } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::sanitize_enumeration_name(const SystemStringType& enumeration_name) -> SystemStringType + auto UEHeaderGenerator::sanitize_enumeration_name(const UEStringType& enumeration_name) -> UEStringType { - SystemStringType result_enum_name = enumeration_name; + UEStringType result_enum_name = enumeration_name; // Remove enumeration name from the string - size_t enum_name_string_split = enumeration_name.find(SYSSTR("::")); - if (enum_name_string_split != SystemStringType::npos) + size_t enum_name_string_split = enumeration_name.find(STR("::")); + if (enum_name_string_split != UEStringType::npos) { result_enum_name.erase(0, enum_name_string_split + 2); } @@ -2973,14 +2973,14 @@ namespace RC::UEGenerator } int64 highest_enum_value = 0; - const auto enum_prefix = to_system(uenum->GenerateEnumPrefix()); - const auto expected_max_name = std::format(SYSSTR("{}_MAX"), enum_prefix); + const auto enum_prefix = (uenum->GenerateEnumPrefix()); + const auto expected_max_name = std::format(STR("{}_MAX"), enum_prefix); auto expected_max_name_lower = expected_max_name; std::transform(expected_max_name_lower.begin(), expected_max_name_lower.end(), expected_max_name_lower.begin(), ::towlower); for (auto [Name, Value] : uenum->ForEachName()) { - auto enum_name = sanitize_enumeration_name(to_system(Name.ToString())); + auto enum_name = sanitize_enumeration_name((Name.ToString())); auto enum_name_lower = enum_name; std::transform(enum_name_lower.begin(), enum_name_lower.end(), enum_name_lower.begin(), ::towlower); if ((enum_name_lower != expected_max_name_lower && enum_name_lower != sanitize_enumeration_name(expected_max_name_lower)) && Value > highest_enum_value) @@ -3009,7 +3009,7 @@ namespace RC::UEGenerator return lowest_enum_value; } - auto UEHeaderGenerator::generate_function_flags(UFunction* function, bool is_function_pure_virtual) const -> SystemStringType + auto UEHeaderGenerator::generate_function_flags(UFunction* function, bool is_function_pure_virtual) const -> UEStringType { FlagFormatHelper flag_format_helper{}; @@ -3030,7 +3030,7 @@ namespace RC::UEGenerator // Interface functions cannot be BlueprintPure if ((function_flags & FUNC_BlueprintPure) != 0 && !is_interface_function) { - flag_format_helper.add_switch(SYSSTR("BlueprintPure")); + flag_format_helper.add_switch(STR("BlueprintPure")); } else { @@ -3038,9 +3038,9 @@ namespace RC::UEGenerator // it has been explicitly marked as blueprint impure, and we need to preserve this behavior if ((function_flags & FUNC_Const) != 0 && !is_interface_function) { - flag_format_helper.add_parameter(SYSSTR("BlueprintPure"), SYSSTR("false")); + flag_format_helper.add_parameter(STR("BlueprintPure"), STR("false")); } - flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); + flag_format_helper.add_switch(STR("BlueprintCallable")); blueprint_callable_added = true; } } @@ -3058,7 +3058,7 @@ namespace RC::UEGenerator if (!has_invalid_param) { - flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); + flag_format_helper.add_switch(STR("BlueprintCallable")); } } @@ -3066,11 +3066,11 @@ namespace RC::UEGenerator { if ((function_flags & FUNC_Native) != 0) { - flag_format_helper.add_switch(SYSSTR("BlueprintNativeEvent")); + flag_format_helper.add_switch(STR("BlueprintNativeEvent")); } else { - flag_format_helper.add_switch(SYSSTR("BlueprintImplementableEvent")); + flag_format_helper.add_switch(STR("BlueprintImplementableEvent")); } } @@ -3078,50 +3078,50 @@ namespace RC::UEGenerator { if ((function_flags & FUNC_NetServer) != 0) { - flag_format_helper.add_switch(SYSSTR("Server")); + flag_format_helper.add_switch(STR("Server")); } else if ((function_flags & FUNC_NetClient) != 0) { - flag_format_helper.add_switch(SYSSTR("Client")); + flag_format_helper.add_switch(STR("Client")); } else if ((function_flags & FUNC_NetMulticast) != 0) { - flag_format_helper.add_switch(SYSSTR("NetMulticast")); + flag_format_helper.add_switch(STR("NetMulticast")); } else if ((function_flags & FUNC_NetRequest) != 0) { - flag_format_helper.add_switch(SYSSTR("ServiceRequest")); + flag_format_helper.add_switch(STR("ServiceRequest")); } else if ((function_flags & FUNC_NetResponse) != 0) { - flag_format_helper.add_switch(SYSSTR("ServiceResponse")); + flag_format_helper.add_switch(STR("ServiceResponse")); } if ((function_flags & FUNC_NetReliable) != 0) { - flag_format_helper.add_switch(SYSSTR("Reliable")); + flag_format_helper.add_switch(STR("Reliable")); } else { - flag_format_helper.add_switch(SYSSTR("Unreliable")); + flag_format_helper.add_switch(STR("Unreliable")); } if ((function_flags & FUNC_NetValidate) != 0) { - flag_format_helper.add_switch(SYSSTR("WithValidation")); + flag_format_helper.add_switch(STR("WithValidation")); } } if ((function_flags & FUNC_Exec) != 0) { - flag_format_helper.add_switch(SYSSTR("Exec")); + flag_format_helper.add_switch(STR("Exec")); } if ((function_flags & FUNC_BlueprintAuthorityOnly) != 0) { - flag_format_helper.add_switch(SYSSTR("BlueprintAuthorityOnly")); + flag_format_helper.add_switch(STR("BlueprintAuthorityOnly")); } if ((function_flags & FUNC_BlueprintCosmetic) != 0) { - flag_format_helper.add_switch(SYSSTR("BlueprintCosmetic")); + flag_format_helper.add_switch(STR("BlueprintCosmetic")); } static auto latent_action_info = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.LatentActionInfo")); @@ -3129,11 +3129,11 @@ namespace RC::UEGenerator bool bLAFound = false; for (FProperty* param : function->ForEachProperty()) { - auto param_name = to_system(param->GetName()); + auto param_name = (param->GetName()); auto param_uc_name = string_to_uppercase(param_name); - if (param_uc_name.find(SYSSTR("WORLDCONTEXT")) != param_uc_name.npos) + if (param_uc_name.find(STR("WORLDCONTEXT")) != param_uc_name.npos) { - flag_format_helper.get_meta()->add_parameter(SYSSTR("WorldContext"), std::format(SYSSTR("\"{}\""), param_name)); + flag_format_helper.get_meta()->add_parameter(STR("WorldContext"), std::format(STR("\"{}\""), param_name)); bWCFound = true; } if (auto as_struct_property = CastField(param); as_struct_property) @@ -3141,8 +3141,8 @@ namespace RC::UEGenerator // We now know this is a StructProperty. if (as_struct_property->GetStruct()->IsChildOf(latent_action_info)) { - flag_format_helper.get_meta()->add_parameter(SYSSTR("LatentInfo"), std::format(SYSSTR("\"{}\""), param_name)); - flag_format_helper.get_meta()->add_switch(SYSSTR("Latent")); + flag_format_helper.get_meta()->add_parameter(STR("LatentInfo"), std::format(STR("\"{}\""), param_name)); + flag_format_helper.get_meta()->add_switch(STR("Latent")); bLAFound = true; } } @@ -3159,28 +3159,28 @@ namespace RC::UEGenerator UFunction* function, GeneratedSourceFile& header_data, bool generate_comma_before_name, - const SystemStringType& context_name, + const UEStringType& context_name, const CaseInsensitiveSet& blacklisted_property_names, - int32_t* out_num_params) -> SystemStringType + int32_t* out_num_params) -> UEStringType { - SystemStringType function_arguments_string; + UEStringType function_arguments_string; for (FProperty* property : function->ForEachProperty()) { auto property_flags = property->GetPropertyFlags(); if ((property_flags & CPF_Parm) != 0 && (property_flags & CPF_ReturnParm) == 0) { - SystemStringType param_declaration; + UEStringType param_declaration; // We only generate UPARAM declarations if we are not generating the implementation file if (!header_data.is_implementation_file()) { - const SystemStringType parameter_flags_string = generate_function_argument_flags(property); + const UEStringType parameter_flags_string = generate_function_argument_flags(property); if (!parameter_flags_string.empty()) { - param_declaration.append(SYSSTR("UPARAM(")); + param_declaration.append(STR("UPARAM(")); param_declaration.append(parameter_flags_string); - param_declaration.append(SYSSTR(") ")); + param_declaration.append(STR(") ")); } } @@ -3192,7 +3192,7 @@ namespace RC::UEGenerator // Append const keyword to the parameter declaration if it is marked as const parameter if ((property_flags & CPF_ConstParm) != 0 || should_force_const_ref) { - param_declaration.append(SYSSTR("const ")); + param_declaration.append(STR("const ")); } PropertyTypeDeclarationContext context(context_name, &header_data); @@ -3202,27 +3202,27 @@ namespace RC::UEGenerator // which would also be always set for output parameters if ((property_flags & (CPF_ReferenceParm | CPF_OutParm)) != 0 || should_force_const_ref) { - param_declaration.append(SYSSTR("&")); + param_declaration.append(STR("&")); } if (generate_comma_before_name) { - param_declaration.append(SYSSTR(",")); + param_declaration.append(STR(",")); } - param_declaration.append(SYSSTR(" ")); + param_declaration.append(STR(" ")); - auto property_name = to_system(property->GetName()); + auto property_name = (property->GetName()); // If property name is blacklisted, capitalize first letter and prepend New if ((uclass && is_function_parameter_shadowing(uclass, property)) || blacklisted_property_names.contains(property_name)) { property_name[0] = towupper(property_name[0]); - property_name.insert(0, SYSSTR("New")); + property_name.insert(0, STR("New")); } param_declaration.append(property_name); function_arguments_string.append(param_declaration); - function_arguments_string.append(SYSSTR(", ")); + function_arguments_string.append(STR(", ")); if (out_num_params) { (*out_num_params)++; @@ -3238,13 +3238,13 @@ namespace RC::UEGenerator return function_arguments_string; } - auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType + auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const UEStringType& ContextName) -> UEStringType { - const auto field_class_name = to_system(property->GetClass().GetName()); + const auto field_class_name = (property->GetClass().GetName()); PropertyTypeDeclarationContext context(ContextName, &header_data); // Byte Property - if (field_class_name == SYSSTR("ByteProperty")) + if (field_class_name == STR("ByteProperty")) { FByteProperty* byte_property = static_cast(property); UEnum* Enum = byte_property->GetEnum(); @@ -3254,11 +3254,11 @@ namespace RC::UEGenerator const int64_t first_enum_constant_value = Enum->GetEnumNameByIndex(0).Value; return generate_enum_value(Enum, first_enum_constant_value); } - return SYSSTR("0"); + return STR("0"); } // Enum Property - if (field_class_name == SYSSTR("EnumProperty")) + if (field_class_name == STR("EnumProperty")) { FEnumProperty* enum_property = static_cast(property); UEnum* uenum = enum_property->GetEnum(); @@ -3272,42 +3272,42 @@ namespace RC::UEGenerator } // Bool Property - if (field_class_name == SYSSTR("BoolProperty")) + if (field_class_name == STR("BoolProperty")) { - return SYSSTR("false"); + return STR("false"); } // Standard Numeric Properties - if (field_class_name == SYSSTR("Int8Property") || field_class_name == SYSSTR("Int16Property") || field_class_name == SYSSTR("IntProperty") || - field_class_name == SYSSTR("Int64Property") || field_class_name == SYSSTR("UInt16Property") || field_class_name == SYSSTR("UInt32Property") || - field_class_name == SYSSTR("UInt64Property")) + if (field_class_name == STR("Int8Property") || field_class_name == STR("Int16Property") || field_class_name == STR("IntProperty") || + field_class_name == STR("Int64Property") || field_class_name == STR("UInt16Property") || field_class_name == STR("UInt32Property") || + field_class_name == STR("UInt64Property")) { - return SYSSTR("0"); + return STR("0"); } - if (field_class_name == SYSSTR("FloatProperty")) + if (field_class_name == STR("FloatProperty")) { - return SYSSTR("0.0f"); + return STR("0.0f"); } - if (field_class_name == SYSSTR("DoubleProperty")) + if (field_class_name == STR("DoubleProperty")) { - return SYSSTR("0.0"); + return STR("0.0"); } // Object Properties - if (field_class_name == SYSSTR("ObjectProperty") || field_class_name == SYSSTR("WeakObjectProperty") || field_class_name == SYSSTR("LazyObjectProperty") || - field_class_name == SYSSTR("SoftObjectProperty") || field_class_name == SYSSTR("AssetObjectProperty") || property->IsA()) + if (field_class_name == STR("ObjectProperty") || field_class_name == STR("WeakObjectProperty") || field_class_name == STR("LazyObjectProperty") || + field_class_name == STR("SoftObjectProperty") || field_class_name == STR("AssetObjectProperty") || property->IsA()) { - return SYSSTR("NULL"); + return STR("NULL"); } // Class Properties - if (field_class_name == SYSSTR("ClassProperty") || field_class_name == SYSSTR("SoftClassProperty") || field_class_name == SYSSTR("InterfaceProperty") || - field_class_name == SYSSTR("AssetClassProperty") || property->IsA()) + if (field_class_name == STR("ClassProperty") || field_class_name == STR("SoftClassProperty") || field_class_name == STR("InterfaceProperty") || + field_class_name == STR("AssetClassProperty") || property->IsA()) { - return SYSSTR("NULL"); + return STR("NULL"); } // Struct Property - if (field_class_name == SYSSTR("StructProperty")) + if (field_class_name == STR("StructProperty")) { FStructProperty* struct_property = static_cast(property); UScriptStruct* script_struct = struct_property->GetStruct(); @@ -3316,67 +3316,67 @@ namespace RC::UEGenerator { throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } - const SystemStringType native_struct_name = get_native_struct_name(script_struct); - return std::format(SYSSTR("{}{{}}"), native_struct_name); + const UEStringType native_struct_name = get_native_struct_name(script_struct); + return std::format(STR("{}{{}}"), native_struct_name); } // Delegate Properties - if (field_class_name == SYSSTR("DelegateProperty") || field_class_name == SYSSTR("MulticastInlineDelegateProperty") || - field_class_name == SYSSTR("MulticastSparseDelegateProperty")) + if (field_class_name == STR("DelegateProperty") || field_class_name == STR("MulticastInlineDelegateProperty") || + field_class_name == STR("MulticastSparseDelegateProperty")) { - const SystemStringType delegate_type_name = generate_delegate_name(property, context.context_name); - return std::format(SYSSTR("{}()"), delegate_type_name); + const UEStringType delegate_type_name = generate_delegate_name(property, context.context_name); + return std::format(STR("{}()"), delegate_type_name); } // Field path property - if (field_class_name == SYSSTR("FieldPathProperty")) + if (field_class_name == STR("FieldPathProperty")) { - return SYSSTR("FFieldPath()"); + return STR("FFieldPath()"); } // Collection and Map Properties - if (field_class_name == SYSSTR("ArrayProperty")) + if (field_class_name == STR("ArrayProperty")) { FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - const SystemStringType inner_property_type = generate_property_type_declaration(inner_property, context); - return std::format(SYSSTR("TArray<{}>()"), inner_property_type); + const UEStringType inner_property_type = generate_property_type_declaration(inner_property, context); + return std::format(STR("TArray<{}>()"), inner_property_type); } - if (field_class_name == SYSSTR("SetProperty")) + if (field_class_name == STR("SetProperty")) { FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const SystemStringType element_property_type = generate_property_type_declaration(element_prop, context); - return std::format(SYSSTR("TSet<{}>()"), element_property_type); + const UEStringType element_property_type = generate_property_type_declaration(element_prop, context); + return std::format(STR("TSet<{}>()"), element_property_type); } - if (field_class_name == SYSSTR("MapProperty")) + if (field_class_name == STR("MapProperty")) { FMapProperty* map_property = static_cast(property); FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - const SystemStringType key_type = generate_property_type_declaration(key_property, context); - const SystemStringType value_type = generate_property_type_declaration(value_property, context); + const UEStringType key_type = generate_property_type_declaration(key_property, context); + const UEStringType value_type = generate_property_type_declaration(value_property, context); - return std::format(SYSSTR("TMap<{}, {}>()"), key_type, value_type); + return std::format(STR("TMap<{}, {}>()"), key_type, value_type); } // Various string, name and text properties - if (field_class_name == SYSSTR("NameProperty")) + if (field_class_name == STR("NameProperty")) { - return SYSSTR("NAME_None"); + return STR("NAME_None"); } - if (field_class_name == SYSSTR("StrProperty")) + if (field_class_name == STR("StrProperty")) { - return SYSSTR("TEXT(\"\")"); + return STR("TEXT(\"\")"); } - if (field_class_name == SYSSTR("TextProperty")) + if (field_class_name == STR("TextProperty")) { - return SYSSTR("FText::GetEmpty()"); + return STR("FText::GetEmpty()"); } throw std::runtime_error(RC::fmt("[generate_default_property_value] Unsupported property class '{}', full name: '{}'", field_class_name, @@ -3470,18 +3470,18 @@ namespace RC::UEGenerator return is_shadowing; } - auto UEHeaderGenerator::get_module_name_for_package(UObject* package) -> SystemStringType + auto UEHeaderGenerator::get_module_name_for_package(UObject* package) -> UEStringType { if (package->GetOuterPrivate() != NULL) { throw std::invalid_argument("Encountered a package with an outer object set"); } - auto package_name = to_system(package->GetName()); - if (!package_name.starts_with(SYSSTR("/Script/"))) + auto package_name = (package->GetName()); + if (!package_name.starts_with(STR("/Script/"))) { - return SYSSTR(""); + return STR(""); } - package_name.erase(0, SystemStringType(SYSSTR("/Script/")).length()); + package_name.erase(0, UEStringType(STR("/Script/")).length()); return package_name; } @@ -3491,22 +3491,22 @@ namespace RC::UEGenerator this->m_primary_module_name = determine_primary_game_module_name(); // Force inclusion of Core and CoreUObject into all the generated module build files - this->m_forced_module_dependencies.insert(SYSSTR("Core")); - this->m_forced_module_dependencies.insert(SYSSTR("CoreUObject")); + this->m_forced_module_dependencies.insert(STR("Core")); + this->m_forced_module_dependencies.insert(STR("CoreUObject")); // TODO not optimal, but still needed for the majority of the cases - this->m_forced_module_dependencies.insert(SYSSTR("Engine")); + this->m_forced_module_dependencies.insert(STR("Engine")); // Add few classes that require explicit UObjectInitializer constructor call, excluding classes inheriting from AActor. - this->m_classes_with_object_initializer.insert(SYSSTR("UUserWidget")); - this->m_classes_with_object_initializer.insert(SYSSTR("UListView")); - this->m_classes_with_object_initializer.insert(SYSSTR("UMovieSceneTrack")); - this->m_classes_with_object_initializer.insert(SYSSTR("USoundWaveProcedural")); - this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlock")); - this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlockImageDecorator")); - this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlockDecorator")); - this->m_classes_with_object_initializer.insert(SYSSTR("USkeletalMeshComponentBudgeted")); - this->m_classes_with_object_initializer.insert(SYSSTR("UIpNetDriver")); - this->m_classes_with_object_initializer.insert(SYSSTR("UAITask")); + this->m_classes_with_object_initializer.insert(STR("UUserWidget")); + this->m_classes_with_object_initializer.insert(STR("UListView")); + this->m_classes_with_object_initializer.insert(STR("UMovieSceneTrack")); + this->m_classes_with_object_initializer.insert(STR("USoundWaveProcedural")); + this->m_classes_with_object_initializer.insert(STR("URichTextBlock")); + this->m_classes_with_object_initializer.insert(STR("URichTextBlockImageDecorator")); + this->m_classes_with_object_initializer.insert(STR("URichTextBlockDecorator")); + this->m_classes_with_object_initializer.insert(STR("USkeletalMeshComponentBudgeted")); + this->m_classes_with_object_initializer.insert(STR("UIpNetDriver")); + this->m_classes_with_object_initializer.insert(STR("UAITask")); } auto UEHeaderGenerator::ignore_selected_modules() -> void @@ -3518,144 +3518,144 @@ namespace RC::UEGenerator if (UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreEngineAndCoreUObject || UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreAllCoreEngineModules) { - this->m_ignored_module_names.insert(SYSSTR("Engine")); - this->m_ignored_module_names.insert(SYSSTR("CoreUObject")); + this->m_ignored_module_names.insert(STR("Engine")); + this->m_ignored_module_names.insert(STR("CoreUObject")); } // Skip all core engine packages if requested if (UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreAllCoreEngineModules) { - this->m_ignored_module_names.insert(SYSSTR("ActorLayerUtilities")); - this->m_ignored_module_names.insert(SYSSTR("ActorSequence")); - this->m_ignored_module_names.insert(SYSSTR("AIModule")); - this->m_ignored_module_names.insert(SYSSTR("AndroidPermission")); - this->m_ignored_module_names.insert(SYSSTR("AnimationCore")); - this->m_ignored_module_names.insert(SYSSTR("AnimationSharing")); - this->m_ignored_module_names.insert(SYSSTR("AnimGraphRuntime")); - this->m_ignored_module_names.insert(SYSSTR("AppleImageUtils")); - this->m_ignored_module_names.insert(SYSSTR("ArchVisCharacter")); - this->m_ignored_module_names.insert(SYSSTR("AssetRegistry")); - this->m_ignored_module_names.insert(SYSSTR("AssetTags")); - this->m_ignored_module_names.insert(SYSSTR("AudioAnalyzer")); - this->m_ignored_module_names.insert(SYSSTR("AudioCapture")); - this->m_ignored_module_names.insert(SYSSTR("AudioExtensions")); - this->m_ignored_module_names.insert(SYSSTR("AudioMixer")); - this->m_ignored_module_names.insert(SYSSTR("AudioPlatformConfiguration")); - this->m_ignored_module_names.insert(SYSSTR("AudioSynesthesia")); - this->m_ignored_module_names.insert(SYSSTR("AugmentedReality")); - this->m_ignored_module_names.insert(SYSSTR("AutomationUtils")); - this->m_ignored_module_names.insert(SYSSTR("AvfMediaFactory")); - this->m_ignored_module_names.insert(SYSSTR("BuildPatchServices")); - this->m_ignored_module_names.insert(SYSSTR("CableComponent")); - this->m_ignored_module_names.insert(SYSSTR("Chaos")); - this->m_ignored_module_names.insert(SYSSTR("ChaosCloth")); - this->m_ignored_module_names.insert(SYSSTR("ChaosNiagara")); - this->m_ignored_module_names.insert(SYSSTR("ChaosSolvers")); - this->m_ignored_module_names.insert(SYSSTR("ChaosSolverEngine")); - this->m_ignored_module_names.insert(SYSSTR("CinematicCamera")); - this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeCommon")); - this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeInterface")); - this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeNv")); - this->m_ignored_module_names.insert(SYSSTR("CustomMeshComponent")); - this->m_ignored_module_names.insert(SYSSTR("DatasmithContent")); - this->m_ignored_module_names.insert(SYSSTR("DeveloperSettings")); - this->m_ignored_module_names.insert(SYSSTR("EditableMesh")); - this->m_ignored_module_names.insert(SYSSTR("EngineMessages")); - this->m_ignored_module_names.insert(SYSSTR("EngineSettings")); - this->m_ignored_module_names.insert(SYSSTR("EyeTracker")); - this->m_ignored_module_names.insert(SYSSTR("FacialAnimation")); - this->m_ignored_module_names.insert(SYSSTR("FieldSystemCore")); - this->m_ignored_module_names.insert(SYSSTR("FieldSystemEngine")); - this->m_ignored_module_names.insert(SYSSTR("Foliage")); - this->m_ignored_module_names.insert(SYSSTR("GameplayTags")); - this->m_ignored_module_names.insert(SYSSTR("GameplayTasks")); - this->m_ignored_module_names.insert(SYSSTR("GeometryCache")); - this->m_ignored_module_names.insert(SYSSTR("GeometryCacheTracks")); - this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionCore")); - this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionSimulationCore")); - this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionEngine")); - this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionTracks")); - this->m_ignored_module_names.insert(SYSSTR("GooglePAD")); - this->m_ignored_module_names.insert(SYSSTR("HeadMountedDisplay")); - this->m_ignored_module_names.insert(SYSSTR("ImageWrapper")); - this->m_ignored_module_names.insert(SYSSTR("ImageWriteQueue")); - this->m_ignored_module_names.insert(SYSSTR("ImgMedia")); - this->m_ignored_module_names.insert(SYSSTR("ImgMediaFactory")); - this->m_ignored_module_names.insert(SYSSTR("InputCore")); - this->m_ignored_module_names.insert(SYSSTR("InteractiveToolsFramework")); - this->m_ignored_module_names.insert(SYSSTR("JsonUtilities")); - this->m_ignored_module_names.insert(SYSSTR("Landscape")); - this->m_ignored_module_names.insert(SYSSTR("LevelSequence")); - this->m_ignored_module_names.insert(SYSSTR("LightPropagationVolumeRuntime")); - this->m_ignored_module_names.insert(SYSSTR("LiveLinkInterface")); - this->m_ignored_module_names.insert(SYSSTR("LocationServicesBPLibrary")); - this->m_ignored_module_names.insert(SYSSTR("LuminRuntimeSettings")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeap")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapAR")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapARPin")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapAudio")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapController")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapEyeTracker")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapHandMeshing")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapHandTracking")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapIdentity")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapImageTracker")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapLightEstimation")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapPlanes")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapPrivileges")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapSecureStorage")); - this->m_ignored_module_names.insert(SYSSTR("MagicLeapSharedWorld")); - this->m_ignored_module_names.insert(SYSSTR("MaterialShaderQualitySettings")); - this->m_ignored_module_names.insert(SYSSTR("MediaAssets")); - this->m_ignored_module_names.insert(SYSSTR("MediaCompositing")); - this->m_ignored_module_names.insert(SYSSTR("MediaUtils")); - this->m_ignored_module_names.insert(SYSSTR("MeshDescription")); - this->m_ignored_module_names.insert(SYSSTR("MobilePatchingUtils")); - this->m_ignored_module_names.insert(SYSSTR("MotoSynth")); - this->m_ignored_module_names.insert(SYSSTR("MoviePlayer")); - this->m_ignored_module_names.insert(SYSSTR("MovieScene")); - this->m_ignored_module_names.insert(SYSSTR("MovieSceneCapture")); - this->m_ignored_module_names.insert(SYSSTR("MovieSceneTracks")); - this->m_ignored_module_names.insert(SYSSTR("MRMesh")); - this->m_ignored_module_names.insert(SYSSTR("NavigationSystem")); - this->m_ignored_module_names.insert(SYSSTR("NetCore")); - this->m_ignored_module_names.insert(SYSSTR("Niagara")); - this->m_ignored_module_names.insert(SYSSTR("NiagaraAnimNotifies")); - this->m_ignored_module_names.insert(SYSSTR("NiagaraCore")); - this->m_ignored_module_names.insert(SYSSTR("NiagaraShader")); - this->m_ignored_module_names.insert(SYSSTR("OculusHMD")); - this->m_ignored_module_names.insert(SYSSTR("OculusInput")); - this->m_ignored_module_names.insert(SYSSTR("OculusMR")); - this->m_ignored_module_names.insert(SYSSTR("OnlineSubsystem")); - this->m_ignored_module_names.insert(SYSSTR("OnlineSubsystemUtils")); - this->m_ignored_module_names.insert(SYSSTR("Overlay")); - this->m_ignored_module_names.insert(SYSSTR("PacketHandler")); - this->m_ignored_module_names.insert(SYSSTR("Paper2D")); - this->m_ignored_module_names.insert(SYSSTR("PhysicsCore")); - this->m_ignored_module_names.insert(SYSSTR("PhysXVehicles")); - this->m_ignored_module_names.insert(SYSSTR("ProceduralMeshComponent")); - this->m_ignored_module_names.insert(SYSSTR("PropertyAccess")); - this->m_ignored_module_names.insert(SYSSTR("PropertyPath")); - this->m_ignored_module_names.insert(SYSSTR("Renderer")); - this->m_ignored_module_names.insert(SYSSTR("Serialization")); - this->m_ignored_module_names.insert(SYSSTR("SessionMessages")); - this->m_ignored_module_names.insert(SYSSTR("SignificanceManager")); - this->m_ignored_module_names.insert(SYSSTR("Slate")); - this->m_ignored_module_names.insert(SYSSTR("SlateCore")); - this->m_ignored_module_names.insert(SYSSTR("SoundFields")); - this->m_ignored_module_names.insert(SYSSTR("StaticMeshDescription")); - this->m_ignored_module_names.insert(SYSSTR("SteamVR")); - this->m_ignored_module_names.insert(SYSSTR("SteamVRInputDevice")); - this->m_ignored_module_names.insert(SYSSTR("Synthesis")); - this->m_ignored_module_names.insert(SYSSTR("TcpMessaging")); - this->m_ignored_module_names.insert(SYSSTR("TemplateSequence")); - this->m_ignored_module_names.insert(SYSSTR("TimeManagement")); - this->m_ignored_module_names.insert(SYSSTR("UdpMessaging")); - this->m_ignored_module_names.insert(SYSSTR("UMG")); - this->m_ignored_module_names.insert(SYSSTR("UObjectPlugin")); - this->m_ignored_module_names.insert(SYSSTR("VariantManagerContent")); - this->m_ignored_module_names.insert(SYSSTR("VectorVM")); - this->m_ignored_module_names.insert(SYSSTR("WmfMediaFactory")); + this->m_ignored_module_names.insert(STR("ActorLayerUtilities")); + this->m_ignored_module_names.insert(STR("ActorSequence")); + this->m_ignored_module_names.insert(STR("AIModule")); + this->m_ignored_module_names.insert(STR("AndroidPermission")); + this->m_ignored_module_names.insert(STR("AnimationCore")); + this->m_ignored_module_names.insert(STR("AnimationSharing")); + this->m_ignored_module_names.insert(STR("AnimGraphRuntime")); + this->m_ignored_module_names.insert(STR("AppleImageUtils")); + this->m_ignored_module_names.insert(STR("ArchVisCharacter")); + this->m_ignored_module_names.insert(STR("AssetRegistry")); + this->m_ignored_module_names.insert(STR("AssetTags")); + this->m_ignored_module_names.insert(STR("AudioAnalyzer")); + this->m_ignored_module_names.insert(STR("AudioCapture")); + this->m_ignored_module_names.insert(STR("AudioExtensions")); + this->m_ignored_module_names.insert(STR("AudioMixer")); + this->m_ignored_module_names.insert(STR("AudioPlatformConfiguration")); + this->m_ignored_module_names.insert(STR("AudioSynesthesia")); + this->m_ignored_module_names.insert(STR("AugmentedReality")); + this->m_ignored_module_names.insert(STR("AutomationUtils")); + this->m_ignored_module_names.insert(STR("AvfMediaFactory")); + this->m_ignored_module_names.insert(STR("BuildPatchServices")); + this->m_ignored_module_names.insert(STR("CableComponent")); + this->m_ignored_module_names.insert(STR("Chaos")); + this->m_ignored_module_names.insert(STR("ChaosCloth")); + this->m_ignored_module_names.insert(STR("ChaosNiagara")); + this->m_ignored_module_names.insert(STR("ChaosSolvers")); + this->m_ignored_module_names.insert(STR("ChaosSolverEngine")); + this->m_ignored_module_names.insert(STR("CinematicCamera")); + this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeCommon")); + this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeInterface")); + this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeNv")); + this->m_ignored_module_names.insert(STR("CustomMeshComponent")); + this->m_ignored_module_names.insert(STR("DatasmithContent")); + this->m_ignored_module_names.insert(STR("DeveloperSettings")); + this->m_ignored_module_names.insert(STR("EditableMesh")); + this->m_ignored_module_names.insert(STR("EngineMessages")); + this->m_ignored_module_names.insert(STR("EngineSettings")); + this->m_ignored_module_names.insert(STR("EyeTracker")); + this->m_ignored_module_names.insert(STR("FacialAnimation")); + this->m_ignored_module_names.insert(STR("FieldSystemCore")); + this->m_ignored_module_names.insert(STR("FieldSystemEngine")); + this->m_ignored_module_names.insert(STR("Foliage")); + this->m_ignored_module_names.insert(STR("GameplayTags")); + this->m_ignored_module_names.insert(STR("GameplayTasks")); + this->m_ignored_module_names.insert(STR("GeometryCache")); + this->m_ignored_module_names.insert(STR("GeometryCacheTracks")); + this->m_ignored_module_names.insert(STR("GeometryCollectionCore")); + this->m_ignored_module_names.insert(STR("GeometryCollectionSimulationCore")); + this->m_ignored_module_names.insert(STR("GeometryCollectionEngine")); + this->m_ignored_module_names.insert(STR("GeometryCollectionTracks")); + this->m_ignored_module_names.insert(STR("GooglePAD")); + this->m_ignored_module_names.insert(STR("HeadMountedDisplay")); + this->m_ignored_module_names.insert(STR("ImageWrapper")); + this->m_ignored_module_names.insert(STR("ImageWriteQueue")); + this->m_ignored_module_names.insert(STR("ImgMedia")); + this->m_ignored_module_names.insert(STR("ImgMediaFactory")); + this->m_ignored_module_names.insert(STR("InputCore")); + this->m_ignored_module_names.insert(STR("InteractiveToolsFramework")); + this->m_ignored_module_names.insert(STR("JsonUtilities")); + this->m_ignored_module_names.insert(STR("Landscape")); + this->m_ignored_module_names.insert(STR("LevelSequence")); + this->m_ignored_module_names.insert(STR("LightPropagationVolumeRuntime")); + this->m_ignored_module_names.insert(STR("LiveLinkInterface")); + this->m_ignored_module_names.insert(STR("LocationServicesBPLibrary")); + this->m_ignored_module_names.insert(STR("LuminRuntimeSettings")); + this->m_ignored_module_names.insert(STR("MagicLeap")); + this->m_ignored_module_names.insert(STR("MagicLeapAR")); + this->m_ignored_module_names.insert(STR("MagicLeapARPin")); + this->m_ignored_module_names.insert(STR("MagicLeapAudio")); + this->m_ignored_module_names.insert(STR("MagicLeapController")); + this->m_ignored_module_names.insert(STR("MagicLeapEyeTracker")); + this->m_ignored_module_names.insert(STR("MagicLeapHandMeshing")); + this->m_ignored_module_names.insert(STR("MagicLeapHandTracking")); + this->m_ignored_module_names.insert(STR("MagicLeapIdentity")); + this->m_ignored_module_names.insert(STR("MagicLeapImageTracker")); + this->m_ignored_module_names.insert(STR("MagicLeapLightEstimation")); + this->m_ignored_module_names.insert(STR("MagicLeapPlanes")); + this->m_ignored_module_names.insert(STR("MagicLeapPrivileges")); + this->m_ignored_module_names.insert(STR("MagicLeapSecureStorage")); + this->m_ignored_module_names.insert(STR("MagicLeapSharedWorld")); + this->m_ignored_module_names.insert(STR("MaterialShaderQualitySettings")); + this->m_ignored_module_names.insert(STR("MediaAssets")); + this->m_ignored_module_names.insert(STR("MediaCompositing")); + this->m_ignored_module_names.insert(STR("MediaUtils")); + this->m_ignored_module_names.insert(STR("MeshDescription")); + this->m_ignored_module_names.insert(STR("MobilePatchingUtils")); + this->m_ignored_module_names.insert(STR("MotoSynth")); + this->m_ignored_module_names.insert(STR("MoviePlayer")); + this->m_ignored_module_names.insert(STR("MovieScene")); + this->m_ignored_module_names.insert(STR("MovieSceneCapture")); + this->m_ignored_module_names.insert(STR("MovieSceneTracks")); + this->m_ignored_module_names.insert(STR("MRMesh")); + this->m_ignored_module_names.insert(STR("NavigationSystem")); + this->m_ignored_module_names.insert(STR("NetCore")); + this->m_ignored_module_names.insert(STR("Niagara")); + this->m_ignored_module_names.insert(STR("NiagaraAnimNotifies")); + this->m_ignored_module_names.insert(STR("NiagaraCore")); + this->m_ignored_module_names.insert(STR("NiagaraShader")); + this->m_ignored_module_names.insert(STR("OculusHMD")); + this->m_ignored_module_names.insert(STR("OculusInput")); + this->m_ignored_module_names.insert(STR("OculusMR")); + this->m_ignored_module_names.insert(STR("OnlineSubsystem")); + this->m_ignored_module_names.insert(STR("OnlineSubsystemUtils")); + this->m_ignored_module_names.insert(STR("Overlay")); + this->m_ignored_module_names.insert(STR("PacketHandler")); + this->m_ignored_module_names.insert(STR("Paper2D")); + this->m_ignored_module_names.insert(STR("PhysicsCore")); + this->m_ignored_module_names.insert(STR("PhysXVehicles")); + this->m_ignored_module_names.insert(STR("ProceduralMeshComponent")); + this->m_ignored_module_names.insert(STR("PropertyAccess")); + this->m_ignored_module_names.insert(STR("PropertyPath")); + this->m_ignored_module_names.insert(STR("Renderer")); + this->m_ignored_module_names.insert(STR("Serialization")); + this->m_ignored_module_names.insert(STR("SessionMessages")); + this->m_ignored_module_names.insert(STR("SignificanceManager")); + this->m_ignored_module_names.insert(STR("Slate")); + this->m_ignored_module_names.insert(STR("SlateCore")); + this->m_ignored_module_names.insert(STR("SoundFields")); + this->m_ignored_module_names.insert(STR("StaticMeshDescription")); + this->m_ignored_module_names.insert(STR("SteamVR")); + this->m_ignored_module_names.insert(STR("SteamVRInputDevice")); + this->m_ignored_module_names.insert(STR("Synthesis")); + this->m_ignored_module_names.insert(STR("TcpMessaging")); + this->m_ignored_module_names.insert(STR("TemplateSequence")); + this->m_ignored_module_names.insert(STR("TimeManagement")); + this->m_ignored_module_names.insert(STR("UdpMessaging")); + this->m_ignored_module_names.insert(STR("UMG")); + this->m_ignored_module_names.insert(STR("UObjectPlugin")); + this->m_ignored_module_names.insert(STR("VariantManagerContent")); + this->m_ignored_module_names.insert(STR("VectorVM")); + this->m_ignored_module_names.insert(STR("WmfMediaFactory")); } } @@ -3663,20 +3663,20 @@ namespace RC::UEGenerator { ignore_selected_modules(); - Output::send(SYSSTR("Cleaning up previously generated SDK (if one exists)\n")); + Output::send(STR("Cleaning up previously generated SDK (if one exists)\n")); if (std::filesystem::exists(m_root_directory)) { std::filesystem::remove_all(m_root_directory); } - Output::send(SYSSTR("Initializing native packages dump\n")); + Output::send(STR("Initializing native packages dump\n")); std::vector native_classes_to_dump; std::vector native_structs_to_dump; std::vector native_enums_to_dump; std::vector native_delegates_to_dump; - Output::send(SYSSTR("Gathering native objects for dumping\n")); + Output::send(STR("Gathering native objects for dumping\n")); UObjectGlobals::ForEachUObject([&](void* raw_object, int32_t chunk_index, int32_t object_index) { UObject* typed_object = static_cast(raw_object); @@ -3721,37 +3721,37 @@ namespace RC::UEGenerator return RC::LoopAction::Continue; }); - Output::send(SYSSTR("Attempting to dump {} native classes\n"), native_classes_to_dump.size()); + Output::send(STR("Attempting to dump {} native classes\n"), native_classes_to_dump.size()); for (UFunction* delegate_signature_function : native_delegates_to_dump) { - // Output::send(SYSSTR("Dumping native delegate type {}\n"), global_delegate_signature->GetName()); + // Output::send(STR("Dumping native delegate type {}\n"), global_delegate_signature->GetName()); generate_object_description_file(delegate_signature_function); } for (UClass* class_to_dump : native_classes_to_dump) { - // Output::send(SYSSTR("Dumping native class {}\n"), class_to_dump->GetName()); + // Output::send(STR("Dumping native class {}\n"), class_to_dump->GetName()); generate_object_description_file(class_to_dump); } - Output::send(SYSSTR("Attempting to dump {} native structs\n"), native_structs_to_dump.size()); + Output::send(STR("Attempting to dump {} native structs\n"), native_structs_to_dump.size()); for (UScriptStruct* struct_to_dump : native_structs_to_dump) { - // Output::send(SYSSTR("Dumping native struct {}\n"), struct_to_dump->GetName()); + // Output::send(STR("Dumping native struct {}\n"), struct_to_dump->GetName()); generate_object_description_file(struct_to_dump); } - Output::send(SYSSTR("Attempting to dump {} native enums\n"), native_enums_to_dump.size()); + Output::send(STR("Attempting to dump {} native enums\n"), native_enums_to_dump.size()); for (UEnum* enum_to_dump : native_enums_to_dump) { - // Output::send(SYSSTR("Dumping native enum {}\n"), enum_to_dump->GetName()); + // Output::send(STR("Dumping native enum {}\n"), enum_to_dump->GetName()); generate_object_description_file(enum_to_dump); } - Output::send(SYSSTR("Writing stub module build files for {} modules\n"), m_module_dependencies.size()); + Output::send(STR("Writing stub module build files for {} modules\n"), m_module_dependencies.size()); for (const auto& module_pair : m_module_dependencies) { generate_module_implementation_file(module_pair.first); @@ -3775,7 +3775,7 @@ namespace RC::UEGenerator { name = get_native_struct_name(std::bit_cast(object)); } - header_file.append_line(std::format(SYSSTR("FORCEINLINE uint32 GetTypeHash(const {}) {{ return 0; }}"), name)); + header_file.append_line(std::format(STR("FORCEINLINE uint32 GetTypeHash(const {}) {{ return 0; }}"), name)); } // Case for FTickFunction struct @@ -3785,32 +3785,32 @@ namespace RC::UEGenerator auto super_struct = struct_object->GetSuperScriptStruct(); if (super_struct) { - if (get_native_struct_name(super_struct) == SYSSTR("FTickFunction")) + if (get_native_struct_name(super_struct) == STR("FTickFunction")) { File::StringType name{}; name = get_native_struct_name(struct_object); - header_file.append_line(SYSSTR("")); - header_file.append_line(SYSSTR("template<>")); - header_file.append_line(std::format(SYSSTR("struct TStructOpsTypeTraits<{}> : public TStructOpsTypeTraitsBase2<{}>"), name, name)); - header_file.append_line(SYSSTR("{")); - header_file.append_line(SYSSTR(" enum")); - header_file.append_line(SYSSTR(" {")); - header_file.append_line(SYSSTR(" WithCopy = false")); - header_file.append_line(SYSSTR(" };")); - header_file.append_line(SYSSTR("};")); + header_file.append_line(STR("")); + header_file.append_line(STR("template<>")); + header_file.append_line(std::format(STR("struct TStructOpsTypeTraits<{}> : public TStructOpsTypeTraitsBase2<{}>"), name, name)); + header_file.append_line(STR("{")); + header_file.append_line(STR(" enum")); + header_file.append_line(STR(" {")); + header_file.append_line(STR(" WithCopy = false")); + header_file.append_line(STR(" };")); + header_file.append_line(STR("};")); } } } header_file.serialize_file_content_to_disk(); } - Output::send(SYSSTR("Done!\n")); + Output::send(STR("Done!\n")); } auto UEHeaderGenerator::generate_object_description_file(UObject* object) -> bool { - const SystemStringType module_name = get_module_name_for_package(object->GetOutermost()); - const SystemStringType file_base_name = get_header_name_for_object(object); + const UEStringType module_name = get_module_name_for_package(object->GetOutermost()); + const UEStringType file_base_name = get_header_name_for_object(object); if (module_name.empty()) { @@ -3868,7 +3868,7 @@ namespace RC::UEGenerator auto iterator = this->m_module_dependencies.find(module_name); if (iterator == this->m_module_dependencies.end()) { - iterator = this->m_module_dependencies.insert({module_name, std::make_shared>()}).first; + iterator = this->m_module_dependencies.insert({module_name, std::make_shared>()}).first; } if (!header_file.has_content_to_save()) @@ -3883,16 +3883,16 @@ namespace RC::UEGenerator header_file.generate_file_contents(); // Record module names used in the headers - std::shared_ptr> out_dependency_module_names = iterator->second; + std::shared_ptr> out_dependency_module_names = iterator->second; header_file.copy_dependency_module_names(*out_dependency_module_names); implementation_file.copy_dependency_module_names(*out_dependency_module_names); return true; } - auto UEHeaderGenerator::generate_object_pre_declaration(UObject* object) -> std::vector> + auto UEHeaderGenerator::generate_object_pre_declaration(UObject* object) -> std::vector> { - std::vector> pre_declarations; + std::vector> pre_declarations; UClass* object_class = object->GetClassPrivate(); @@ -3902,15 +3902,15 @@ namespace RC::UEGenerator if (uclass->IsChildOf(UInterface::StaticClass())) { - pre_declarations.push_back({SYSSTR("class "), get_native_class_name(uclass, true), SYSSTR(";\n")}); + pre_declarations.push_back({STR("class "), get_native_class_name(uclass, true), STR(";\n")}); } - pre_declarations.push_back({SYSSTR("class "), get_native_class_name(uclass, false), SYSSTR(";\n")}); + pre_declarations.push_back({STR("class "), get_native_class_name(uclass, false), STR(";\n")}); } else if (object_class->IsChildOf(UScriptStruct::StaticClass())) { UScriptStruct* script_struct = static_cast(object); - pre_declarations.push_back({SYSSTR("struct "), get_native_struct_name(script_struct), SYSSTR(";\n")}); + pre_declarations.push_back({STR("struct "), get_native_struct_name(script_struct), STR(";\n")}); } else if (object_class->IsChildOf(UEnum::StaticClass())) { @@ -3925,7 +3925,7 @@ namespace RC::UEGenerator return pre_declarations; } - auto UEHeaderGenerator::get_header_name_for_object(UObject* object, bool get_existing_header) -> SystemStringType + auto UEHeaderGenerator::get_header_name_for_object(UObject* object, bool get_existing_header) -> UEStringType { File::StringType header_name{}; UObject* final_object{}; @@ -3933,14 +3933,14 @@ namespace RC::UEGenerator if (object->IsA() || object->IsA()) { // Class and struct headers follow the relevant object name - header_name = to_system(object->GetName()); + header_name = (object->GetName()); final_object = object; } else if (object->IsA()) { // Enumeration usually have the E prefix which will be present in the header names // We do not strip it because there are some broken headers that do not follow that convention (e.g. funny Wwise) - header_name = to_system(object->GetName()); + header_name = (object->GetName()); final_object = object; } else @@ -3960,8 +3960,8 @@ namespace RC::UEGenerator { // Otherwise, remove the postfix and use the function name as the header name // Also append the delegate postfix because apparently there can be conflicts - SystemStringType DelegateName = strip_delegate_signature_postfix(signature_function); - DelegateName.append(SYSSTR("Delegate")); + UEStringType DelegateName = strip_delegate_signature_postfix(signature_function); + DelegateName.append(STR("Delegate")); header_name = DelegateName; final_object = object; } @@ -3978,14 +3978,14 @@ namespace RC::UEGenerator { if (auto it2 = m_dependency_object_to_unique_id.find(final_object); it2 != m_dependency_object_to_unique_id.end()) { - header_name.append(std::format(SYSSTR("{}"), it2->second)); + header_name.append(std::format(STR("{}"), it2->second)); } } else { if (auto it = m_used_file_names.find(header_name); it != m_used_file_names.end()) { - header_name.append(std::format(SYSSTR("{}"), ++it->second.usable_id)); + header_name.append(std::format(STR("{}"), ++it->second.usable_id)); m_dependency_object_to_unique_id.emplace(final_object, it->second.usable_id); } else @@ -4002,7 +4002,7 @@ namespace RC::UEGenerator generate_delegate_type_declaration(signature_function, delegate_class, header_data); } - auto UEHeaderGenerator::determine_primary_game_module_name() -> SystemStringType + auto UEHeaderGenerator::determine_primary_game_module_name() -> UEStringType { /* HMODULE primary_executable_module = GetModuleHandleW(NULL); @@ -4010,21 +4010,21 @@ namespace RC::UEGenerator GetModuleFileNameW(primary_executable_module, module_name_buffer, ARRAYSIZE(module_name_buffer)); // Retrieve the filename from the full path, strip down the extension - FFilePath root_executable_path((SystemStringType(module_name_buffer))); - SystemStringType filename = root_executable_path.filename().replace_extension().wstring(); + FFilePath root_executable_path((UEStringType(module_name_buffer))); + UEStringType filename = root_executable_path.filename().replace_extension().wstring(); // Remove the shipping file postfix - SystemStringType shipping_postfix = SYSSTR("-Win64-Shipping"); + UEStringType shipping_postfix = STR("-Win64-Shipping"); if (filename.ends_with(shipping_postfix)) { filename.erase(filename.length() - shipping_postfix.length()); } return filename; */ - return "Main"; + return STR("Main"); } - auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) -> SystemStringType + auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const UEStringType& module_name, const UEStringType& fallback_name) -> UEStringType { // Retrieve the most top level object located inside the native package UObject* top_level_object = object; @@ -4034,31 +4034,32 @@ namespace RC::UEGenerator top_level_object = top_level_object->GetOuterPrivate(); } - const auto object_name = to_system(top_level_object->GetName()); - return std::format(SYSSTR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), module_name, object_name, fallback_name); + const auto object_name = (top_level_object->GetName()); + return std::format(STR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), module_name, object_name, fallback_name); } GeneratedFile::GeneratedFile(const FFilePath& full_file_path) { this->m_full_file_path = full_file_path; + // [[keep]] this->m_file_base_name = to_system_string(full_file_path.filename().replace_extension()); this->m_current_indent_count = 0; } - auto GeneratedFile::append_line(const SystemStringType& line) -> void + auto GeneratedFile::append_line(const UEStringType& line) -> void { for (int32_t i = 0; i < m_current_indent_count; i++) { - m_file_contents_buffer.append(SYSSTR(" ")); + m_file_contents_buffer.append(STR(" ")); } m_file_contents_buffer.append(line); - m_file_contents_buffer.append(SYSSTR("\n")); + m_file_contents_buffer.append(STR("\n")); } - auto GeneratedFile::append_line_no_indent(const SystemStringType& line) -> void + auto GeneratedFile::append_line_no_indent(const UEStringType& line) -> void { m_file_contents_buffer.append(line); - m_file_contents_buffer.append(SYSSTR("\n")); + m_file_contents_buffer.append(STR("\n")); } auto GeneratedFile::begin_indent_level() -> void @@ -4084,19 +4085,19 @@ namespace RC::UEGenerator // TODO might be slow, maybe move it out into the header generator? std::filesystem::create_directories(this->m_full_file_path.parent_path()); - SystemStreamType file_output_stream; + UEOStreamType file_output_stream; file_output_stream.open(m_full_file_path); if (!file_output_stream.is_open()) { throw std::invalid_argument("Failed to open the header file"); } // TODO: FIX STREAM -// file_output_stream << generate_file_contents().c_str(); + file_output_stream << generate_file_contents().c_str(); file_output_stream.close(); return true; } - auto GeneratedFile::generate_file_contents() -> SystemStringType + auto GeneratedFile::generate_file_contents() -> UEStringType { return m_file_contents_buffer; } @@ -4107,24 +4108,24 @@ namespace RC::UEGenerator } auto GeneratedSourceFile::create_source_file(const FFilePath& root_dir, - const SystemStringType& module_name, - const SystemStringType& base_name, + const UEStringType& module_name, + const UEStringType& base_name, bool is_implementation_file, UObject* object) -> GeneratedSourceFile { FFilePath full_file_path; if (is_implementation_file) { - full_file_path = root_dir / module_name / SYSSTR("Private") / (base_name + SYSSTR(".cpp")); + full_file_path = root_dir / module_name / STR("Private") / (base_name + STR(".cpp")); } else { - full_file_path = root_dir / module_name / SYSSTR("Public") / (base_name + SYSSTR(".h")); + full_file_path = root_dir / module_name / STR("Public") / (base_name + STR(".h")); } return GeneratedSourceFile(full_file_path, module_name, is_implementation_file, object); } - GeneratedSourceFile::GeneratedSourceFile(const FFilePath& file_path, const SystemStringType& file_module_name, bool is_implementation_file, UObject* object) + GeneratedSourceFile::GeneratedSourceFile(const FFilePath& file_path, const UEStringType& file_module_name, bool is_implementation_file, UObject* object) : GeneratedFile(file_path) { this->m_file_module_name = file_module_name; @@ -4137,7 +4138,7 @@ namespace RC::UEGenerator this->m_header_file = header_file; } - auto GeneratedSourceFile::add_extra_include(const SystemStringType& included_file_name) -> void + auto GeneratedSourceFile::add_extra_include(const UEStringType& included_file_name) -> void { this->m_extra_includes.insert(included_file_name); } @@ -4153,44 +4154,44 @@ namespace RC::UEGenerator } } - auto GeneratedSourceFile::generate_file_contents() -> SystemStringType + auto GeneratedSourceFile::generate_file_contents() -> UEStringType { - SystemStringType result_header_contents; + UEStringType result_header_contents; result_header_contents.append(generate_includes_string()); - result_header_contents.append(SYSSTR("\n")); + result_header_contents.append(STR("\n")); - SystemStringType pre_declarations_string = generate_pre_declarations_string(); + UEStringType pre_declarations_string = generate_pre_declarations_string(); if (!pre_declarations_string.empty()) { result_header_contents.append(pre_declarations_string); - result_header_contents.append(SYSSTR("\n")); + result_header_contents.append(STR("\n")); } if (!m_implementation_constructor.empty()) { result_header_contents.append(m_implementation_constructor); - result_header_contents.append(SYSSTR("\n")); + result_header_contents.append(STR("\n")); } if (!m_file_contents_buffer.empty()) { result_header_contents.append(m_file_contents_buffer); - result_header_contents.append(SYSSTR("\n")); + result_header_contents.append(STR("\n")); } return result_header_contents; } - auto GeneratedSourceFile::generate_includes_string() const -> SystemStringType + auto GeneratedSourceFile::generate_includes_string() const -> UEStringType { - SystemStringType result_include_string; - std::vector> include_lines; - std::vector cross_module_includes; + UEStringType result_include_string; + std::vector> include_lines; + std::vector cross_module_includes; // For the header file, we generate the pragma and minimal core includes if (!m_is_implementation_file) { - result_include_string.append(SYSSTR("#pragma once\n")); - result_include_string.append(SYSSTR("#include \"CoreMinimal.h\"\n")); + result_include_string.append(STR("#pragma once\n")); + result_include_string.append(STR("#include \"CoreMinimal.h\"\n")); } // For CPP implementation file, we need to generate the header include if (m_is_implementation_file) @@ -4198,19 +4199,19 @@ namespace RC::UEGenerator if (m_header_file != NULL) { // Generate it if we have the correct header file set - result_include_string.append(std::format(SYSSTR("#include \"{}.h\"\n"), m_header_file->m_file_base_name)); + result_include_string.append(std::format(STR("#include \"{}.h\"\n"), m_header_file->m_file_base_name)); } else { // Otherwise, we generate a simple minimal core include - result_include_string.append(SYSSTR("#include \"CoreMinimal.h\"\n")); + result_include_string.append(STR("#include \"CoreMinimal.h\"\n")); } } // Generate extra includes we might need that do not represent objects - for (const SystemStringType& extra_included_file : m_extra_includes) + for (const UEStringType& extra_included_file : m_extra_includes) { - include_lines.push_back({SYSSTR("#include \""), extra_included_file, SYSSTR("\"\n")}); + include_lines.push_back({STR("#include \""), extra_included_file, STR("\"\n")}); } // Generate includes for the relevant object files @@ -4224,7 +4225,7 @@ namespace RC::UEGenerator continue; } - const SystemStringType object_header_name = UEHeaderGenerator::get_header_name_for_object(dependency_object, true); + const UEStringType object_header_name = UEHeaderGenerator::get_header_name_for_object(dependency_object, true); // Definitely skip include if object in question is placed into this header if (object_header_name == m_file_base_name) @@ -4241,7 +4242,7 @@ namespace RC::UEGenerator } } UObject* package = dependency_object->GetOutermost(); - SystemStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); + UEStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); if (!native_module_name.empty()) { @@ -4249,7 +4250,7 @@ namespace RC::UEGenerator // since generated headers are always located in the module root and follow one file per object convention if (m_file_module_name == native_module_name) { - include_lines.push_back({SYSSTR("#include \""), object_header_name, SYSSTR(".h\"\n")}); + include_lines.push_back({STR("#include \""), object_header_name, STR(".h\"\n")}); } else { @@ -4266,13 +4267,13 @@ namespace RC::UEGenerator // Remove duplicates - there are sometimes multiple instances of the same cross module include cross_module_includes.erase(std::unique(cross_module_includes.begin(), cross_module_includes.end()), cross_module_includes.end()); - for (const SystemStringType& cross_module_include : cross_module_includes) + for (const UEStringType& cross_module_include : cross_module_includes) { result_include_string.append(cross_module_include); } // Sort the includes by module name, since we want to make sure that they are always in the same order - std::sort(include_lines.begin(), include_lines.end(), [](const std::vector& a, const std::vector& b) { + std::sort(include_lines.begin(), include_lines.end(), [](const std::vector& a, const std::vector& b) { return a[1] < b[1]; }); @@ -4287,15 +4288,15 @@ namespace RC::UEGenerator // Last include of the header file should always be a generated one if (!m_is_implementation_file) { - result_include_string.append(std::format(SYSSTR("#include \"{}.generated.h\"\n"), m_file_base_name)); + result_include_string.append(std::format(STR("#include \"{}.generated.h\"\n"), m_file_base_name)); } return result_include_string; } - auto GeneratedSourceFile::generate_pre_declarations_string() const -> SystemStringType + auto GeneratedSourceFile::generate_pre_declarations_string() const -> UEStringType { - SystemStringType result_declarations; - std::vector>> pre_declarations; + UEStringType result_declarations; + std::vector>> pre_declarations; // Generate pre-declarations for the relevant object files for (const auto& dependency_pair : m_dependencies) @@ -4310,7 +4311,7 @@ namespace RC::UEGenerator // We still need to reference the object's owner module UObject* package = dependency_object->GetOutermost(); - SystemStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); + UEStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); if (!native_module_name.empty() && m_file_module_name != native_module_name) { @@ -4323,7 +4324,7 @@ namespace RC::UEGenerator // Sort the entries alphabetically by the class name std::sort(pre_declarations.begin(), pre_declarations.end(), - [](const std::vector>& a, const std::vector>& b) { + [](const std::vector>& a, const std::vector>& b) { return a[0][1] < b[0][1]; }); diff --git a/UE4SS/src/Signatures.cpp b/UE4SS/src/Signatures.cpp index c33a61b65..fce05f4f4 100644 --- a/UE4SS/src/Signatures.cpp +++ b/UE4SS/src/Signatures.cpp @@ -31,7 +31,7 @@ namespace RC lua.register_function("DerefToInt32", LuaLibrary::deref_to_int32); lua.register_function("dereftoint32", LuaLibrary::deref_to_int32); - lua.execute_file(script_file_path_and_name); + lua.execute_file(to_lua(script_file_path_and_name)); constexpr const char* global_register_func_name = "Register"; constexpr const char* global_on_match_found_func_name = "OnMatchFound"; diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 60649e1db..b5c4c43d1 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -236,7 +236,7 @@ namespace RC std::format(SYSSTR("{}"), UE4SS_LIB_VERSION_PRERELEASE == 0 ? SYSSTR("") : std::format(SYSSTR(" PreRelease #{}"), UE4SS_LIB_VERSION_PRERELEASE)), std::format(SYSSTR("{}"), UE4SS_LIB_BETA_STARTED == 0 ? SYSSTR("") : (UE4SS_LIB_IS_BETA == 0 ? SYSSTR(" Beta #?") : std::format(SYSSTR(" Beta #{}"), UE4SS_LIB_VERSION_BETA))), - SYSSTR(UE4SS_LIB_BUILD_GITSHA)); + to_system(UE4SS_LIB_BUILD_GITSHA)); #ifdef __clang__ #define UE4SS_COMPILER SYSSTR("Clang") @@ -244,7 +244,7 @@ namespace RC #define UE4SS_COMPILER SYSSTR("MSVC") #endif - Output::send(SYSSTR("UE4SS Build Configuration: {} ({})\n"), SYSSTR(UE4SS_CONFIGURATION), UE4SS_COMPILER); + Output::send(SYSSTR("UE4SS Build Configuration: {} ({})\n"), to_system(UE4SS_CONFIGURATION), UE4SS_COMPILER); #ifdef WIN32 m_load_library_a_hook = std::make_unique("kernel32.dll", "LoadLibraryA", @@ -1620,17 +1620,6 @@ namespace RC } } - auto UE4SSProgram::find_lua_mod_by_name(SystemStringViewType mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* - { - return static_cast(find_mod_by_name(mod_name, installed_only, is_started)); - } - - auto UE4SSProgram::find_lua_mod_by_name(UEStringViewType mod_name, UE4SSProgram::IsInstalled installed_only, IsStarted is_started) -> LuaMod* - { - auto sysstr = to_system(UEStringType{mod_name}); - return static_cast(find_mod_by_name(sysstr, installed_only, is_started)); - } - auto UE4SSProgram::get_object_dumper_output_directory() -> const SystemStringType { return to_system_string(m_object_dumper_output_directory); diff --git a/UE4SS/src/USMapGenerator/Generator.cpp b/UE4SS/src/USMapGenerator/Generator.cpp index 7701078c2..4d231eb09 100644 --- a/UE4SS/src/USMapGenerator/Generator.cpp +++ b/UE4SS/src/USMapGenerator/Generator.cpp @@ -22,6 +22,8 @@ #include #include "UE4SSProgram.hpp" +#undef min +#undef max namespace RC::OutTheShade { diff --git a/UVTD/include/UVTD/Helpers.hpp b/UVTD/include/UVTD/Helpers.hpp index f1087eec0..31c5096d0 100644 --- a/UVTD/include/UVTD/Helpers.hpp +++ b/UVTD/include/UVTD/Helpers.hpp @@ -200,7 +200,7 @@ namespace RC::UVTD }; // Any members by the name 'LHS' will instead use 'RHS' in generated code. - static inline std::unordered_map s_member_rename_map{ + static inline std::unordered_map s_member_rename_map{ {STR("Class"), STR("ClassPrivate")}, {STR("Name"), STR("NamePrivate")}, {STR("Outer"), STR("OuterPrivate")}, @@ -210,7 +210,7 @@ namespace RC::UVTD auto change_prefix(File::StringType input, bool is_425_plus) -> std::optional; // Workaround that lets us have a unified 'TUObjectArray' struct regardless if the engine version uses a chunked or non-chunked variant of TUObjectArray. - auto unify_uobject_array_if_needed(StringType& out_variable_type) -> bool; + auto unify_uobject_array_if_needed(UEStringType& out_variable_type) -> bool; } // namespace RC::UVTD #endif diff --git a/UVTD/src/Helpers.cpp b/UVTD/src/Helpers.cpp index ddb97c8d8..aa0341644 100644 --- a/UVTD/src/Helpers.cpp +++ b/UVTD/src/Helpers.cpp @@ -39,10 +39,10 @@ namespace RC::UVTD return input; } - auto unify_uobject_array_if_needed(StringType& out_variable_type) -> bool + auto unify_uobject_array_if_needed(UEStringType& out_variable_type) -> bool { - static constexpr StringViewType fixed_uobject_array_string = STR("FFixedUObjectArray"); - static constexpr StringViewType chunked_fixed_uobject_array_string = STR("FChunkedFixedUObjectArray"); + static constexpr UEStringViewType fixed_uobject_array_string = STR("FFixedUObjectArray"); + static constexpr UEStringViewType chunked_fixed_uobject_array_string = STR("FChunkedFixedUObjectArray"); if (auto fixed_uobject_array_pos = out_variable_type.find(fixed_uobject_array_string); fixed_uobject_array_pos != out_variable_type.npos) { out_variable_type.replace(fixed_uobject_array_pos, fixed_uobject_array_string.length(), STR("TUObjectArray")); diff --git a/deps/first/File/include/File/FileDef.hpp b/deps/first/File/include/File/FileDef.hpp index 6d5d4204b..bf1a5258d 100644 --- a/deps/first/File/include/File/FileDef.hpp +++ b/deps/first/File/include/File/FileDef.hpp @@ -28,5 +28,12 @@ namespace RC::File static_assert(false, "Could not setup the 'RC_OS_FILE_TYPE_INCLUDE_FILE' macro because a supported OS was not detected."); #endif #endif +#if RC_DETECTED_OS == _WIN32 +#ifndef RC_OS_FILE_TYPE_INCLUDE_FILE +#define RC_OS_FILE_TYPE_INCLUDE_FILE +#else + static_assert(false, "Could not setup the 'RC_OS_FILE_TYPE_INCLUDE_FILE' macro because a supported OS was not detected."); +#endif +#endif } // namespace RC::File diff --git a/deps/first/File/include/File/Macros.hpp b/deps/first/File/include/File/Macros.hpp index fa0e4aca1..5c3ead676 100644 --- a/deps/first/File/include/File/Macros.hpp +++ b/deps/first/File/include/File/Macros.hpp @@ -9,26 +9,25 @@ #define RC_IS_ANSI 0 #endif -// always use u16string -#define STR(str) u##str - #ifdef LINUX - #define SYSSTR(str) str - #define IOSTR(str) str +#define SYSSTR(str) str +#define IOSTR(str) str +#define STR(str) u##str #else - #if RC_IS_ANSI == 0 - #define SYSSTR(str) u##str - #define IOSTR(str) u##str - #else - #define SYSSTR(str) str - #define IOSTR(str) str - #endif +#if RC_IS_ANSI == 0 +#define SYSSTR(str) L##str +#define IOSTR(str) L##str +#define STR(str) L##str +#else +#define SYSSTR(str) str +#define IOSTR(str) str +#endif #endif #ifdef S static_assert(false, "UE4SS define 'S' is already defined, please solve this"); #else -//#define S(str) STR(str) +// #define S(str) STR(str) #endif #define THROW_INTERNAL_FILE_ERROR(msg) \ @@ -50,26 +49,26 @@ namespace RC::File { typedef std::basic_ofstream u16ofstream; typedef std::basic_ifstream u16ifstream; - + #if RC_IS_ANSI == 1 using StringType = std::string; using StringViewType = std::string_view; using CharType = char; using StreamType = std::ifstream; #else - // System String Types - #ifdef WIN32 - using StringType = std::u16string; - using StringViewType = std::u16string_view; - using CharType = std::u16string::value_type; - using StreamType = u16ifstream; - #else +// System String Types +#ifdef WIN32 + using StringType = std::wstring; + using StringViewType = std::wstring_view; + using CharType = std::wstring::value_type; + using StreamType = std::wifstream; +#else // on linux, use utf8 - using StringType = std::string; - using StringViewType = std::string_view; - using CharType = char; - using StreamType = std::ifstream; - #endif // WIN32 + using StringType = std::string; + using StringViewType = std::string_view; + using CharType = char; + using StreamType = std::ifstream; +#endif // WIN32 #endif // RC_IS_ANSI } // namespace RC::File @@ -86,41 +85,57 @@ namespace RC constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { return std::to_string(std::forward(numeric_value)); }; - #define SystemStringPrint "%s" +#define SystemStringPrint "%s" +#else +// System String Types +#ifdef WIN32 + using SystemStringType = std::wstring; + using SystemStringViewType = std::wstring_view; + using SystemCharType = std::wstring::value_type; + using SystemStreamType = std::wifstream; + constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_wstring(std::forward(numeric_value)); + }; +#define SystemStringPrint "%S" #else - // System String Types - #ifdef WIN32 - using SystemStringType = std::u16string; - using SystemStringViewType = std::u16string_view; - using SystemCharType = std::u16string::value_type; - using SystemStreamType = u16ifstream; - constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return std::to_u16string(std::forward(numeric_value)); - }; - #define SystemStringPrint "%S" - #else // on linux, use utf8 - using SystemStringType = std::string; - using SystemStringViewType = std::string_view; - using SystemCharType = char; - using SystemStreamType = std::ifstream; - constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return std::to_string(std::forward(numeric_value)); - }; - #define SystemStringPrint "%s" - #endif // WIN32 + using SystemStringType = std::string; + using SystemStringViewType = std::string_view; + using SystemCharType = char; + using SystemStreamType = std::ifstream; + constexpr auto ToString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_string(std::forward(numeric_value)); + }; +#define SystemStringPrint "%s" +#endif // WIN32 #endif #if RC_IS_ANSI == 1 using UEStringType = std::string; using UEStringViewType = std::string_view; using UECharType = std::string::value_type; - #define UEStringPrint "%s" +#define UEStringPrint "%s" +#else +#ifdef WIN32 + using UEStringType = std::wstring; + using UEStringViewType = std::wstring_view; + using UECharType = std::wstring::value_type; + using UEIStreamType = std::wifstream; + using UEOStreamType = std::wofstream; + constexpr auto ToUEString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_wstring(std::forward(numeric_value)); + }; #else using UEStringType = std::u16string; using UEStringViewType = std::u16string_view; using UECharType = std::u16string::value_type; - #define UEStringPrint "%S" + using UEIStreamType = std::basic_ifstream; + using UEOStreamType = std::basic_ofstream; + constexpr auto ToUEString = [](auto&& numeric_value) constexpr -> decltype(auto) { + return std::to_u16string(std::forward(numeric_value)); + }; +#endif // WIN32 +#define UEStringPrint "%S" #endif // RC_IS_ANSI } // namespace RC diff --git a/deps/first/File/src/FileType/WinFile.cpp b/deps/first/File/src/FileType/WinFile.cpp index 4d75ad5a9..0cbfd2f84 100644 --- a/deps/first/File/src/FileType/WinFile.cpp +++ b/deps/first/File/src/FileType/WinFile.cpp @@ -28,7 +28,7 @@ namespace RC::File { if constexpr (sizeof(CharType) > 1) { - if (DeleteFileW(file_path_and_name.u16string().c_str()) == 0) + if (DeleteFileW(file_path_and_name.wstring().c_str()) == 0) { THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::delete_file] Was unable to delete file, error: {}", GetLastError())) } diff --git a/deps/first/Helpers/include/Helpers/Format.hpp b/deps/first/Helpers/include/Helpers/Format.hpp index 57ebaea46..2a7d5f861 100644 --- a/deps/first/Helpers/include/Helpers/Format.hpp +++ b/deps/first/Helpers/include/Helpers/Format.hpp @@ -8,6 +8,6 @@ namespace RC template auto static fmt(const std::string_view&& fmt, FmtArgs&&... fmt_args) -> std::string { - return std::vformat(std::forward(fmt), RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + return std::vformat(std::forward(fmt), std::make_format_args(to_stdstr(std::forward(fmt_args))...)); } } \ No newline at end of file diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index 71d36e2c7..15ebeae4d 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -247,6 +247,16 @@ namespace RC } } + auto inline to_wstring(std::wstring_view input) -> std::wstring + { + return std::wstring{input}; + } + + auto inline to_wstring(std::wstring& input) -> std::wstring + { + return std::wstring{input}; + } + auto inline to_wstring(std::string_view input) -> std::wstring { auto temp_input = std::string{input}; @@ -287,7 +297,9 @@ namespace RC auto inline to_string(std::u16string& input) -> std::string { +#pragma warning(disable : 4996) return std::wstring_convert, char16_t>{}.to_bytes(input); +#pragma warning(default : 4996) } auto inline to_string(std::wstring_view input) -> std::string @@ -432,7 +444,41 @@ namespace RC return std::forward(arg); } } + + template + struct is_std_string_type : std::disjunction, std::is_same> + { + }; + + template + struct not_std_string_like_t : std::conjunction>, std::negation>>> + { + }; + + template + auto inline to_std_string(T&& input) -> std::string + { + return to_string(input); + } + + template + auto to_stdstr(T&& arg) + { + if constexpr (can_be_string_view_t::value) + { + return to_stdstr(stringviewify(std::forward(arg))); + } + else if constexpr (not_std_string_like_t>::value) + { + return to_std_string(std::forward(arg)); + } + else + { + return std::forward(arg); + } + } + template struct is_system_string_type : std::disjunction< std::is_same, diff --git a/deps/first/IniParser/include/IniParser/JSON.hpp b/deps/first/IniParser/include/IniParser/JSON.hpp index 1b6e9b602..1ef447b73 100644 --- a/deps/first/IniParser/include/IniParser/JSON.hpp +++ b/deps/first/IniParser/include/IniParser/JSON.hpp @@ -26,31 +26,31 @@ namespace RC::Parser EndOfFile, }; - auto static token_type_to_string(const TokenType token_type) -> SystemStringType + auto static token_type_to_string(const TokenType token_type) -> std::string { switch (token_type) { case Default: - return SYSSTR("Default"); + return std::string("Default"); case OpenCurlyBrace: - return SYSSTR("OpenCurlyBrace"); + return std::string("OpenCurlyBrace"); case CloseCurlyBrace: - return SYSSTR("CloseCurlyBrace"); + return std::string("CloseCurlyBrace"); case OpenSquareBracket: - return SYSSTR("OpenSquareBracket"); + return std::string("OpenSquareBracket"); case CloseSquareBracket: - return SYSSTR("CloseSquareBracket"); + return std::string("CloseSquareBracket"); case Colon: - return SYSSTR("Colon"); + return std::string("Colon"); case Comma: - return SYSSTR("Comma"); + return std::string("Comma"); break; case DoubleQuote: - return SYSSTR("DoubleQuote"); + return std::string("DoubleQuote"); case Characters: - return SYSSTR("Characters"); + return std::string("Characters"); case EndOfFile: - return SYSSTR("EndOfFile"); + return std::string("EndOfFile"); } } @@ -65,7 +65,7 @@ namespace RC::Parser class ItemBase { public: - SystemStringType m_name{SYSSTR("--UNNAMED-ITEM--")}; + UEStringType m_name{STR("--UNNAMED-ITEM--")}; bool m_is_global_scope{false}; public: diff --git a/deps/first/JSON/include/JSON/Array.hpp b/deps/first/JSON/include/JSON/Array.hpp index e4cd241b8..5af5c21b7 100644 --- a/deps/first/JSON/include/JSON/Array.hpp +++ b/deps/first/JSON/include/JSON/Array.hpp @@ -41,7 +41,7 @@ namespace RC::JSON public: auto new_object() -> class Object&; auto new_array() -> class Array&; - auto new_string(const SystemStringType& value) -> void; + auto new_string(const UEStringType& value) -> void; auto new_null() -> void; auto new_bool(bool value) -> void; @@ -87,7 +87,7 @@ namespace RC::JSON } public: - auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> UEStringType override; auto get_type() const -> Type override { return Type::Array; diff --git a/deps/first/JSON/include/JSON/Bool.hpp b/deps/first/JSON/include/JSON/Bool.hpp index ac4c44fc0..c8f8450ec 100644 --- a/deps/first/JSON/include/JSON/Bool.hpp +++ b/deps/first/JSON/include/JSON/Bool.hpp @@ -23,7 +23,7 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> UEStringType override; auto get_type() const -> Type override { return Type::Bool; diff --git a/deps/first/JSON/include/JSON/Common.hpp b/deps/first/JSON/include/JSON/Common.hpp index 99dc44be8..c11653e78 100644 --- a/deps/first/JSON/include/JSON/Common.hpp +++ b/deps/first/JSON/include/JSON/Common.hpp @@ -39,7 +39,7 @@ namespace RC::JSON class ScopeStack; } - auto inline indent(int32_t* indent_level, SystemStringType& string) -> void + auto inline indent(int32_t* indent_level, UEStringType& string) -> void { if (!indent_level) { @@ -48,7 +48,7 @@ namespace RC::JSON for (int32_t i = 0; i < *indent_level; ++i) { - string.append(SYSSTR(" ")); + string.append(STR(" ")); } } } // namespace RC::JSON diff --git a/deps/first/JSON/include/JSON/KeyValuePair.hpp b/deps/first/JSON/include/JSON/KeyValuePair.hpp index 8c665ab32..ef0a8c829 100644 --- a/deps/first/JSON/include/JSON/KeyValuePair.hpp +++ b/deps/first/JSON/include/JSON/KeyValuePair.hpp @@ -5,13 +5,13 @@ namespace RC::JSON template struct TypedKeyValuePair { - const SystemStringType& key; + const UEStringType& key; T* value{}; }; struct KeyValuePair { - SystemStringType key{}; + UEStringType key{}; std::unique_ptr value{}; template diff --git a/deps/first/JSON/include/JSON/Null.hpp b/deps/first/JSON/include/JSON/Null.hpp index 27aeab023..7fe5d5497 100644 --- a/deps/first/JSON/include/JSON/Null.hpp +++ b/deps/first/JSON/include/JSON/Null.hpp @@ -13,7 +13,7 @@ namespace RC::JSON ~Null() override = default; public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> UEStringType override; auto get_type() const -> Type override { return Type::Null; diff --git a/deps/first/JSON/include/JSON/Number.hpp b/deps/first/JSON/include/JSON/Number.hpp index 9fc269624..8ae06c560 100644 --- a/deps/first/JSON/include/JSON/Number.hpp +++ b/deps/first/JSON/include/JSON/Number.hpp @@ -167,7 +167,7 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> UEStringType override; auto get_type() const -> JSON::Type override { return JSON::Type::Number; diff --git a/deps/first/JSON/include/JSON/Object.hpp b/deps/first/JSON/include/JSON/Object.hpp index 207225cc9..f9d670fde 100644 --- a/deps/first/JSON/include/JSON/Object.hpp +++ b/deps/first/JSON/include/JSON/Object.hpp @@ -30,7 +30,7 @@ namespace RC::JSON #pragma warning(disable : 4251) private: - std::unordered_map> m_members{}; + std::unordered_map> m_members{}; IsGlobalObject m_is_global_object{IsGlobalObject::No}; #pragma warning(default : 4251) @@ -44,17 +44,17 @@ namespace RC::JSON auto operator=(const Object&) -> Object& = delete; private: - auto find_value_by_key(const SystemStringType& key) const -> Value*; - auto find_value_by_key(const SystemStringType& key) -> Value*; + auto find_value_by_key(const UEStringType& key) const -> Value*; + auto find_value_by_key(const UEStringType& key) -> Value*; public: - auto new_object(SystemStringType name) -> Object&; - auto new_array(SystemStringType name) -> class Array&; - auto new_string(SystemStringType name, const SystemStringType& value) -> void; - auto new_null(SystemStringType name) -> void; - auto new_bool(SystemStringType name, bool value) -> void; + auto new_object(UEStringType name) -> Object&; + auto new_array(UEStringType name) -> class Array&; + auto new_string(UEStringType name, const UEStringType& value) -> void; + auto new_null(UEStringType name) -> void; + auto new_bool(UEStringType name, bool value) -> void; - auto add_object(SystemStringType name, std::unique_ptr) -> void; + auto add_object(UEStringType name, std::unique_ptr) -> void; auto get() -> decltype(m_members)& { @@ -66,7 +66,7 @@ namespace RC::JSON }; template - auto get(const SystemStringType& key) const -> ValueType& + auto get(const UEStringType& key) const -> ValueType& { auto value = find_value_by_key(key); if (!value) @@ -77,7 +77,7 @@ namespace RC::JSON } template - auto get(const SystemStringType& key) -> ValueType& + auto get(const UEStringType& key) -> ValueType& { auto value = find_value_by_key(key); if (!value) @@ -88,12 +88,12 @@ namespace RC::JSON } template - auto new_number(SystemStringType name, number_type value) -> void + auto new_number(UEStringType name, number_type value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> UEStringType override; auto get_type() const -> Type override { return Type::Object; diff --git a/deps/first/JSON/include/JSON/Parser/Parser.hpp b/deps/first/JSON/include/JSON/Parser/Parser.hpp index 252c7d02a..03eb9d4b8 100644 --- a/deps/first/JSON/include/JSON/Parser/Parser.hpp +++ b/deps/first/JSON/include/JSON/Parser/Parser.hpp @@ -10,6 +10,6 @@ namespace RC::JSON::Parser { - RC_JSON_API auto parse(SystemStringType& input) -> std::unique_ptr; + RC_JSON_API auto parse(File::StringType& input) -> std::unique_ptr; RC_JSON_API auto parse(const File::Handle&) -> std::unique_ptr; } // namespace RC::JSON::Parser diff --git a/deps/first/JSON/include/JSON/Parser/TokenParser.hpp b/deps/first/JSON/include/JSON/Parser/TokenParser.hpp index 35e003afa..1a80a435a 100644 --- a/deps/first/JSON/include/JSON/Parser/TokenParser.hpp +++ b/deps/first/JSON/include/JSON/Parser/TokenParser.hpp @@ -79,7 +79,7 @@ namespace RC::JSON::Parser } } template - auto add_element_to_top(SystemStringType key, std::unique_ptr value) -> ValueType* + auto add_element_to_top(UEStringType key, std::unique_ptr value) -> ValueType* { auto& top = peek_top(); if (top.is()) @@ -107,7 +107,7 @@ namespace RC::JSON::Parser private: std::unique_ptr m_global_object; ScopeStack m_scope_stack{}; - SystemStringType m_last_key{}; + UEStringType m_last_key{}; std::unique_ptr m_last_value{}; State m_current_state{State::StartOfFile}; TokenType m_expected_token{}; @@ -115,7 +115,7 @@ namespace RC::JSON::Parser bool m_defer_element_creation{}; public: - TokenParser(const ParserBase::Tokenizer& tokenizer, SystemStringType& input) : ParserBase::TokenParser(tokenizer, input) + TokenParser(const ParserBase::Tokenizer& tokenizer, UEStringType& input) : ParserBase::TokenParser(tokenizer, input) { } virtual ~TokenParser() = default; diff --git a/deps/first/JSON/include/JSON/String.hpp b/deps/first/JSON/include/JSON/String.hpp index f62602ddf..24cbe0e92 100644 --- a/deps/first/JSON/include/JSON/String.hpp +++ b/deps/first/JSON/include/JSON/String.hpp @@ -14,25 +14,25 @@ namespace RC::JSON RC_JSON_API constexpr static Type static_type = Type::String; private: - SystemStringType m_data{}; + UEStringType m_data{}; public: RC_JSON_API String() = default; - RC_JSON_API explicit String(SystemStringViewType string); + RC_JSON_API explicit String(UEStringViewType string); RC_JSON_API ~String() override = default; public: - RC_JSON_API auto get() -> SystemStringType& + RC_JSON_API auto get() -> UEStringType& { return m_data; } - RC_JSON_API auto get_view() const -> SystemStringViewType + RC_JSON_API auto get_view() const -> UEStringViewType { return m_data; } public: - RC_JSON_API auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; + RC_JSON_API auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> UEStringType override; RC_JSON_API auto get_type() const -> Type override { return Type::String; diff --git a/deps/first/JSON/src/Array.cpp b/deps/first/JSON/src/Array.cpp index 413d103f8..01001995f 100644 --- a/deps/first/JSON/src/Array.cpp +++ b/deps/first/JSON/src/Array.cpp @@ -36,22 +36,22 @@ namespace RC::JSON m_members.emplace_back(std::move(object)); } - auto Array::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType + auto Array::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType { if (!indent_level) { throw std::runtime_error{"Must supply an indent_level pointer"}; }; - SystemStringType array_as_string{}; + UEStringType array_as_string{}; if (should_format == ShouldFormat::Yes && !m_members.empty()) { - array_as_string.append(SYSSTR("[\n")); + array_as_string.append(STR("[\n")); } else { - array_as_string.append(SYSSTR("[")); + array_as_string.append(STR("[")); } ++(*indent_level); @@ -70,11 +70,11 @@ namespace RC::JSON { if (should_format == ShouldFormat::Yes) { - array_as_string.append(SYSSTR(",\n")); + array_as_string.append(STR(",\n")); } else { - array_as_string.append(SYSSTR(",")); + array_as_string.append(STR(",")); } } @@ -85,13 +85,13 @@ namespace RC::JSON if (should_format == ShouldFormat::Yes && !m_members.empty()) { - array_as_string.append(SYSSTR("\n")); + array_as_string.append(STR("\n")); indent(indent_level, array_as_string); - array_as_string.append(SYSSTR("]")); + array_as_string.append(STR("]")); } else { - array_as_string.append(SYSSTR("]")); + array_as_string.append(STR("]")); } if (!m_members.empty()) diff --git a/deps/first/JSON/src/Bool.cpp b/deps/first/JSON/src/Bool.cpp index 62b894131..af6afda93 100644 --- a/deps/first/JSON/src/Bool.cpp +++ b/deps/first/JSON/src/Bool.cpp @@ -6,10 +6,10 @@ namespace RC::JSON { } - auto Bool::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType + auto Bool::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType { (void)should_format; (void)indent_level; - return m_underlying_value ? SYSSTR("true") : SYSSTR("false"); + return m_underlying_value ? STR("true") : STR("false"); } } // namespace RC::JSON diff --git a/deps/first/JSON/src/Null.cpp b/deps/first/JSON/src/Null.cpp index 0cbda75f9..2aa883bc1 100644 --- a/deps/first/JSON/src/Null.cpp +++ b/deps/first/JSON/src/Null.cpp @@ -2,10 +2,10 @@ namespace RC::JSON { - auto Null::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType + auto Null::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType { (void)should_format; (void)indent_level; - return SYSSTR("null"); + return STR("null"); } } // namespace RC::JSON diff --git a/deps/first/JSON/src/Number.cpp b/deps/first/JSON/src/Number.cpp index eb97ade3b..859bb13be 100644 --- a/deps/first/JSON/src/Number.cpp +++ b/deps/first/JSON/src/Number.cpp @@ -42,7 +42,7 @@ namespace RC::JSON m_stored_type = Type::Double; } - auto Number::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType + auto Number::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType { (void)should_format; (void)indent_level; diff --git a/deps/first/JSON/src/Object.cpp b/deps/first/JSON/src/Object.cpp index 172ed07cd..9ba33bd19 100644 --- a/deps/first/JSON/src/Object.cpp +++ b/deps/first/JSON/src/Object.cpp @@ -6,7 +6,7 @@ namespace RC::JSON { - auto Object::find_value_by_key(const SystemStringType& look_for_key) const -> Value* + auto Object::find_value_by_key(const UEStringType& look_for_key) const -> Value* { if (auto it = m_members.find(look_for_key); it != m_members.end()) { @@ -17,7 +17,7 @@ namespace RC::JSON return nullptr; } } - auto Object::find_value_by_key(const SystemStringType& look_for_key) -> Value* + auto Object::find_value_by_key(const UEStringType& look_for_key) -> Value* { if (auto it = m_members.find(look_for_key); it != m_members.end()) { @@ -29,52 +29,52 @@ namespace RC::JSON } } - auto Object::new_object(SystemStringType name) -> Object& + auto Object::new_object(UEStringType name) -> Object& { return *static_cast(m_members.emplace(std::move(name), std::make_unique()).first->second.get()); } - auto Object::new_array(SystemStringType name) -> Array& + auto Object::new_array(UEStringType name) -> Array& { return *static_cast(m_members.emplace(std::move(name), std::make_unique()).first->second.get()); } - auto Object::new_string(SystemStringType name, const SystemStringType& value) -> void + auto Object::new_string(UEStringType name, const UEStringType& value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto Object::new_null(SystemStringType name) -> void + auto Object::new_null(UEStringType name) -> void { m_members.emplace(std::move(name), std::make_unique()); } - auto Object::new_bool(SystemStringType name, bool value) -> void + auto Object::new_bool(UEStringType name, bool value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto Object::add_object(SystemStringType name, std::unique_ptr object) -> void + auto Object::add_object(UEStringType name, std::unique_ptr object) -> void { m_members.emplace(std::move(name), std::move(object)); } - auto Object::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType + auto Object::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType { if (!indent_level) { throw std::runtime_error{"Must supply an indent_level pointer"}; }; - SystemStringType object_as_string{}; + UEStringType object_as_string{}; if (should_format == ShouldFormat::Yes && !m_members.empty()) { - object_as_string.append(SYSSTR("{\n")); + object_as_string.append(STR("{\n")); } else { - object_as_string.append(SYSSTR("{")); + object_as_string.append(STR("{")); } ++(*indent_level); @@ -87,18 +87,18 @@ namespace RC::JSON indent(indent_level, object_as_string); } - object_as_string.append(std::format(SYSSTR("\"{}\":"), key)); + object_as_string.append(std::format(STR("\"{}\":"), key)); object_as_string.append(value->serialize(should_format, indent_level)); if (member_count + 1 < m_members.size()) { if (should_format == ShouldFormat::Yes) { - object_as_string.append(SYSSTR(",\n")); + object_as_string.append(STR(",\n")); } else { - object_as_string.append(SYSSTR(",")); + object_as_string.append(STR(",")); } } @@ -109,13 +109,13 @@ namespace RC::JSON if (should_format == ShouldFormat::Yes && !m_members.empty()) { - object_as_string.append(SYSSTR("\n")); + object_as_string.append(STR("\n")); indent(indent_level, object_as_string); - object_as_string.append(SYSSTR("}")); + object_as_string.append(STR("}")); } else { - object_as_string.append(SYSSTR("}")); + object_as_string.append(STR("}")); } if (!m_members.empty() || m_is_global_object == IsGlobalObject::Yes) diff --git a/deps/first/JSON/src/Parser/Parser.cpp b/deps/first/JSON/src/Parser/Parser.cpp index 7d2cc80ca..c76f2bcc0 100644 --- a/deps/first/JSON/src/Parser/Parser.cpp +++ b/deps/first/JSON/src/Parser/Parser.cpp @@ -11,12 +11,12 @@ namespace RC::JSON::Parser { ParserBase::TokenContainer tc; - tc.add(ParserBase::Token::create(TokenType::CarriageReturn, SYSSTR("CarriageReturn"), SYSSTR("\r"))); - tc.add(ParserBase::Token::create(TokenType::NewLine, SYSSTR("NewLine"), SYSSTR("\n"))); - tc.add(ParserBase::Token::create(TokenType::DoubleQuote, SYSSTR("DoubleQuote"), SYSSTR("\""))); + tc.add(ParserBase::Token::create(TokenType::CarriageReturn, STR("CarriageReturn"), STR("\r"))); + tc.add(ParserBase::Token::create(TokenType::NewLine, STR("NewLine"), STR("\n"))); + tc.add(ParserBase::Token::create(TokenType::DoubleQuote, STR("DoubleQuote"), STR("\""))); tc.add(ParserBase::Token::create(TokenType::Characters, - SYSSTR("Characters"), - SYSSTR(""), + STR("Characters"), + STR(""), ParserBase::Token::HasData::Yes)); // Empty identifier will match everything that no other token identifier matches tc.add(ParserBase::Token::create(TokenType::ClosingCurlyBrace, STR("ClosingCurlyBrace"), STR("}"))); tc.add(ParserBase::Token::create(TokenType::OpeningCurlyBrace, STR("OpeningCurlyBrace"), STR("{"))); @@ -32,7 +32,7 @@ namespace RC::JSON::Parser return tc; } - static auto parse_internal(SystemStringType& input) -> std::unique_ptr + static auto parse_internal(UEStringType& input) -> std::unique_ptr { // Tokenize -> START ParserBase::Tokenizer tokenizer; @@ -56,12 +56,13 @@ namespace RC::JSON::Parser auto parse(SystemStringType& input) -> std::unique_ptr { - return Internal::parse_internal(input); + auto ue_input = to_ue(input); + return Internal::parse_internal(ue_input); } auto parse(const File::Handle& file) -> std::unique_ptr { - auto input = file.read_all(); + auto input = to_ue(file.read_all()); return Internal::parse_internal(input); } } // namespace RC::JSON::Parser diff --git a/deps/first/JSON/src/Parser/TokenParser.cpp b/deps/first/JSON/src/Parser/TokenParser.cpp index 6c91cb483..cad2ee6c6 100644 --- a/deps/first/JSON/src/Parser/TokenParser.cpp +++ b/deps/first/JSON/src/Parser/TokenParser.cpp @@ -32,17 +32,10 @@ namespace RC::JSON::Parser throw std::runtime_error{e}; \ } - static auto is_number(SystemStringViewType data) -> bool + static auto is_number(UEStringViewType data) -> bool { - return std::ranges::all_of(data.begin(), data.end(), [&](const SystemCharType c) { - if constexpr (std::is_same_v) - { - return std::iswdigit(c) != 0; - } - else - { - return std::isdigit(c) != 0; - } + return std::ranges::all_of(data.begin(), data.end(), [&](const UECharType c) { + return std::iswdigit((wchar_t)c) != 0; }); } @@ -71,9 +64,9 @@ namespace RC::JSON::Parser return m_storage.back(); } - static auto has_only_spaces(const SystemStringType& data) -> bool + static auto has_only_spaces(const UEStringType& data) -> bool { - return std::all_of(data.begin(), data.end(), [](File::CharType c) { + return std::all_of(data.begin(), data.end(), [](UECharType c) { return std::isspace(c) || c == '\n'; }); } @@ -171,7 +164,7 @@ namespace RC::JSON::Parser else if (m_current_state == State::ReadValue) { auto data_raw = get_data(token); - SystemStringType data_no_spaces = data_raw; + UEStringType data_no_spaces = data_raw; data_no_spaces.erase(std::remove_if(data_no_spaces.begin(), data_no_spaces.end(), [](wchar_t c) { diff --git a/deps/first/JSON/src/String.cpp b/deps/first/JSON/src/String.cpp index 6a89d1165..619f2de65 100644 --- a/deps/first/JSON/src/String.cpp +++ b/deps/first/JSON/src/String.cpp @@ -2,12 +2,12 @@ namespace RC::JSON { - String::String(SystemStringViewType string) : m_data(string) + String::String(UEStringViewType string) : m_data(string) { } - auto String::serialize([[maybe_unused]] ShouldFormat should_format, [[maybe_unused]] int32_t* indent_level) -> SystemStringType + auto String::serialize([[maybe_unused]] ShouldFormat should_format, [[maybe_unused]] int32_t* indent_level) -> UEStringType { - return std::format(SYSSTR("\"{}\""), m_data); + return std::format(STR("\"{}\""), m_data); } } // namespace RC::JSON diff --git a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp index 31a88779a..afe1bb9ce 100644 --- a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp +++ b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp @@ -521,9 +521,9 @@ namespace RC::LuaMadeSimple } RC_LMS_API auto execute_file(std::string_view) const -> void; - RC_LMS_API auto execute_file(std::u16string_view) const -> void; + RC_LMS_API auto execute_file(std::wstring_view) const -> void; RC_LMS_API auto execute_string(std::string_view) const -> void; - RC_LMS_API auto execute_string(std::u16string_view) const -> void; + RC_LMS_API auto execute_string(std::wstring_view) const -> void; RC_LMS_API auto open_all_libs() const -> void; RC_LMS_API auto set_hook(lua_Hook, int32_t mask, int32_t count) const -> void; diff --git a/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp b/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp index 71da33188..35cfa56b6 100644 --- a/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp +++ b/deps/first/LuaMadeSimple/src/LuaMadeSimple.cpp @@ -434,7 +434,7 @@ namespace RC::LuaMadeSimple } } - auto Lua::execute_file(std::u16string_view file_name_and_path) const -> void + auto Lua::execute_file(std::wstring_view file_name_and_path) const -> void { #pragma warning(disable : 4244) std::string file_name_and_path_ansi = std::string(file_name_and_path.begin(), file_name_and_path.end()); @@ -455,7 +455,7 @@ namespace RC::LuaMadeSimple } } - auto Lua::execute_string(std::u16string_view code) const -> void + auto Lua::execute_string(std::wstring_view code) const -> void { #pragma warning(disable : 4244) std::string code_ansi = std::string(code.begin(), code.end()); diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp index 77ad45442..b82b3e5bb 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp @@ -345,8 +345,6 @@ namespace RC using SignatureContainerMap = std::unordered_map>; RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; -#ifdef WIN32 - RC_SPSS_API auto static string_scan(std::u16string_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; -#endif + RC_SPSS_API auto static string_scan(std::wstring_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; }; } // namespace RC diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp index ea849dbd0..63ec115a0 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp @@ -14,11 +14,6 @@ #include #include -#ifdef LINUX -#include -#define byte uint8_t -#endif - namespace RC { ScanTargetArray SigScannerStaticData::m_modules_info; @@ -375,7 +370,7 @@ namespace RC return vector_of_signatures; } - auto SinglePassScanner::string_scan(std::u16string_view string_to_scan_for, ScanTarget scan_target) -> void* + auto SinglePassScanner::string_scan(std::wstring_view string_to_scan_for, ScanTarget scan_target) -> void* { auto module = SigScannerStaticData::m_modules_info[scan_target]; @@ -406,7 +401,7 @@ namespace RC break; } - std::u16string_view maybe_string = std::u16string_view((const wchar_t*)region_start, string_to_scan_for.size()); + auto maybe_string = std::wstring_view((const wchar_t*)region_start, string_to_scan_for.size()); if (maybe_string == string_to_scan_for) { address_found = region_start; From c40cbd85a370145f3dc4ecf8f9b158d37a7f063c Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Mon, 19 Feb 2024 18:24:36 -0600 Subject: [PATCH 052/213] update macro --- deps/first/File/include/File/Macros.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/File/include/File/Macros.hpp b/deps/first/File/include/File/Macros.hpp index 5c3ead676..18cc97f4f 100644 --- a/deps/first/File/include/File/Macros.hpp +++ b/deps/first/File/include/File/Macros.hpp @@ -132,7 +132,7 @@ namespace RC using UEIStreamType = std::basic_ifstream; using UEOStreamType = std::basic_ofstream; constexpr auto ToUEString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return std::to_u16string(std::forward(numeric_value)); + return to_ue(std::to_string(std::forward(numeric_value))); }; #endif // WIN32 #define UEStringPrint "%S" From c3ff41d38e99e40e5ad4eb1b35b665a38cc21d74 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Mon, 19 Feb 2024 19:48:39 -0600 Subject: [PATCH 053/213] remove ununsed func --- deps/first/File/include/File/Macros.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/deps/first/File/include/File/Macros.hpp b/deps/first/File/include/File/Macros.hpp index 18cc97f4f..1a87c683c 100644 --- a/deps/first/File/include/File/Macros.hpp +++ b/deps/first/File/include/File/Macros.hpp @@ -122,18 +122,12 @@ namespace RC using UECharType = std::wstring::value_type; using UEIStreamType = std::wifstream; using UEOStreamType = std::wofstream; - constexpr auto ToUEString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return std::to_wstring(std::forward(numeric_value)); - }; #else using UEStringType = std::u16string; using UEStringViewType = std::u16string_view; using UECharType = std::u16string::value_type; using UEIStreamType = std::basic_ifstream; using UEOStreamType = std::basic_ofstream; - constexpr auto ToUEString = [](auto&& numeric_value) constexpr -> decltype(auto) { - return to_ue(std::to_string(std::forward(numeric_value))); - }; #endif // WIN32 #define UEStringPrint "%S" #endif // RC_IS_ANSI From 24b5d9d6f6e29a98cccb8fd19428a1a9549ce80b Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Tue, 20 Feb 2024 04:22:51 -0600 Subject: [PATCH 054/213] seperate FileString --- UE4SS/include/GUI/ConsoleOutputDevice.hpp | 4 +- UE4SS/include/ObjectDumper/ObjectToString.hpp | 2 +- .../SDKGenerator/UEHeaderGenerator.hpp | 2 +- UE4SS/include/SettingsManager.hpp | 2 +- UE4SS/src/GUI/ConsoleOutputDevice.cpp | 6 +- UE4SS/src/GUI/Dumpers.cpp | 8 +- UE4SS/src/GUI/LiveView.cpp | 2 +- UE4SS/src/Mod/LuaMod.cpp | 8 +- UE4SS/src/SDKGenerator/Common.cpp | 84 +++--- UE4SS/src/SDKGenerator/Generator.cpp | 126 ++++----- UE4SS/src/SDKGenerator/JSONDumper.cpp | 8 +- UE4SS/src/SDKGenerator/TMapOverrideGen.cpp | 4 +- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 20 +- UE4SS/src/SettingsManager.cpp | 38 +-- UE4SS/src/Signatures.cpp | 14 +- UE4SS/src/UE4SSProgram.cpp | 24 +- UVTD/include/UVTD/Helpers.hpp | 16 +- UVTD/include/UVTD/MemberVarsDumper.hpp | 4 +- UVTD/include/UVTD/Symbols.hpp | 55 ++-- UVTD/include/UVTD/TemplateClassParser.hpp | 6 +- UVTD/include/UVTD/TypeContainer.hpp | 4 +- UVTD/include/UVTD/UnrealVirtualGenerator.hpp | 4 +- UVTD/include/UVTD/VTableDumper.hpp | 4 +- UVTD/src/Helpers.cpp | 20 +- UVTD/src/MemberVarsDumper.cpp | 38 +-- UVTD/src/MemberVarsWrapperGenerator.cpp | 20 +- UVTD/src/SolBindingsGenerator.cpp | 12 +- UVTD/src/Symbols.cpp | 25 +- UVTD/src/TemplateClassParser.cpp | 8 +- UVTD/src/TypeContainer.cpp | 4 +- UVTD/src/UVTD.cpp | 2 +- UVTD/src/UnrealVirtualGenerator.cpp | 126 ++++----- UVTD/src/VTableDumper.cpp | 50 ++-- .../DynamicOutput/DebugConsoleDevice.hpp | 4 +- .../include/DynamicOutput/FileDevice.hpp | 4 +- .../include/DynamicOutput/Output.hpp | 36 +-- .../include/DynamicOutput/OutputDevice.hpp | 10 +- .../include/DynamicOutput/TestDevice.hpp | 4 +- .../DynamicOutput/src/DebugConsoleDevice.cpp | 4 +- deps/first/DynamicOutput/src/Output.cpp | 2 +- deps/first/DynamicOutput/src/OutputDevice.cpp | 8 +- .../File/include/File/FileType/FileBase.hpp | 17 +- .../File/include/File/FileType/StdFile.hpp | 7 +- .../File/include/File/FileType/WinFile.hpp | 6 +- .../File/include/File/HandleTemplate.hpp | 14 +- deps/first/File/include/File/Macros.hpp | 14 +- deps/first/File/src/FileType/StdFile.cpp | 35 ++- deps/first/File/src/FileType/WinFile.cpp | 101 +++++-- deps/first/Helpers/include/Helpers/Format.hpp | 6 + deps/first/Helpers/include/Helpers/String.hpp | 252 ++++++++++-------- deps/first/IniParser/src/Ini.cpp | 47 ++-- deps/first/IniParser/src/JSON.cpp | 46 ++-- deps/first/IniParser/src/TokenParser.cpp | 80 +++--- deps/first/IniParser/src/Value.cpp | 6 +- .../first/JSON/include/JSON/Parser/Parser.hpp | 1 + deps/first/JSON/src/Parser/Parser.cpp | 10 +- .../include/ParserBase/Tokenizer.hpp | 2 +- deps/first/ParserBase/src/Tokenizer.cpp | 14 +- 58 files changed, 804 insertions(+), 676 deletions(-) diff --git a/UE4SS/include/GUI/ConsoleOutputDevice.hpp b/UE4SS/include/GUI/ConsoleOutputDevice.hpp index d1fdf58d6..f05768c88 100644 --- a/UE4SS/include/GUI/ConsoleOutputDevice.hpp +++ b/UE4SS/include/GUI/ConsoleOutputDevice.hpp @@ -30,7 +30,7 @@ namespace RC::Output public: auto has_optional_arg() const -> bool override; - auto receive(File::StringViewType fmt) const -> void override; - auto receive_with_optional_arg(File::StringViewType fmt, int32_t optional_arg = 0) const -> void override; + auto receive(SystemStringViewType fmt) const -> void override; + auto receive_with_optional_arg(SystemStringViewType fmt, int32_t optional_arg = 0) const -> void override; }; } // namespace RC::Output diff --git a/UE4SS/include/ObjectDumper/ObjectToString.hpp b/UE4SS/include/ObjectDumper/ObjectToString.hpp index 3cbf96a8d..e4f72a78d 100644 --- a/UE4SS/include/ObjectDumper/ObjectToString.hpp +++ b/UE4SS/include/ObjectDumper/ObjectToString.hpp @@ -12,7 +12,7 @@ namespace RC::ObjectDumper extern std::unordered_map object_to_string_functions; using ObjectToStringComplexDeclCallable = const std::function&; - using ObjectToStringComplexDecl = std::function; + using ObjectToStringComplexDecl = std::function; extern std::unordered_map object_to_string_complex_functions; auto get_to_string(size_t hash) -> ObjectToStringDecl; diff --git a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp index 3b4e21d1f..3c20fb778 100644 --- a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp +++ b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp @@ -351,7 +351,7 @@ namespace RC::UEGenerator auto static get_property_access_modifier(FProperty* property) -> AccessModifier; auto static get_function_access_modifier(UFunction* function) -> AccessModifier; auto static create_string_literal(const UEStringType& string) -> UEStringType; - auto static get_header_name_for_object(UObject* object, bool get_existing_header = false) -> UEStringType; + auto static get_header_name_for_object(UObject* object, bool get_existing_header = false) -> SystemStringType; auto static generate_cross_module_include(UObject* object, const UEStringType& module_name, const UEStringType& fallback_name) -> UEStringType; }; } // namespace RC::UEGenerator diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index a2186e21c..51ff5a954 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -17,7 +17,7 @@ namespace RC public: struct SectionOverrides { - File::StringType ModsFolderPath{}; + UEStringType ModsFolderPath{}; } Overrides; struct SectionGeneral diff --git a/UE4SS/src/GUI/ConsoleOutputDevice.cpp b/UE4SS/src/GUI/ConsoleOutputDevice.cpp index 7e0ac8e67..b2ecb3c11 100644 --- a/UE4SS/src/GUI/ConsoleOutputDevice.cpp +++ b/UE4SS/src/GUI/ConsoleOutputDevice.cpp @@ -11,17 +11,17 @@ namespace RC::Output return true; } - auto ConsoleDevice::receive(File::StringViewType fmt) const -> void + auto ConsoleDevice::receive(SystemStringViewType fmt) const -> void { receive_with_optional_arg(fmt, Color::NoColor); } - auto ConsoleDevice::receive_with_optional_arg(File::StringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void + auto ConsoleDevice::receive_with_optional_arg(SystemStringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void { #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE printf_s("ConsoleDevice received: %S", m_formatter(fmt).c_str()); #else - auto fmt_copy = File::StringType{fmt}; + auto fmt_copy = SystemStringType{fmt}; if (fmt_copy.ends_with(STR('\n'))) { fmt_copy.pop_back(); diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index 736f76460..9279d31dd 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -398,14 +398,14 @@ namespace RC::GUI::Dumpers if (ImGui::Button("Dump CXX Headers\n")) { - File::StringType working_dir{UE4SSProgram::get_program().get_working_directory()}; - UE4SSProgram::get_program().generate_cxx_headers(working_dir + STR("\\CXXHeaderDump")); + SystemStringType working_dir{UE4SSProgram::get_program().get_working_directory()}; + UE4SSProgram::get_program().generate_cxx_headers(working_dir + SYSSTR("\\CXXHeaderDump")); } if (ImGui::Button("Generate Lua Types\n")) { - File::StringType working_dir{UE4SSProgram::get_program().get_working_directory()}; - UE4SSProgram::get_program().generate_lua_types(working_dir + STR("\\Mods\\shared\\types")); + SystemStringType working_dir{UE4SSProgram::get_program().get_working_directory()}; + UE4SSProgram::get_program().generate_lua_types(working_dir + SYSSTR("\\Mods\\shared\\types")); } } } // namespace RC::GUI::Dumpers diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index ded85b3dd..c5f083ddf 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -717,7 +717,7 @@ namespace RC::GUI auto& file_device = output.get_device(); file_device.set_file_name_and_path(UEStringType{UE4SSProgram::get_program().get_working_directory()} + std::format(SYSSTR("\\watches\\ue4ss_watch_{}_{}.txt"), object_name, property_name)); - file_device.set_formatter([](File::StringViewType string) -> File::StringType { + file_device.set_formatter([](SystemStringViewType string) -> SystemStringType { const auto when_as_string = std::format(SYSSTR("{:%Y-%m-%d %H:%M:%S}"), std::chrono::system_clock::now()); return std::format(SYSSTR("[{}] {}"), when_as_string, string); }); diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 29bff6c4a..6b3228fa9 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -647,7 +647,7 @@ namespace RC // Give the full path to the 'Scripts' directory to the mod container std::filesystem::path mod_path_fs = m_mod_path; auto path = (mod_path_fs / SYSSTR("scripts")); - m_scripts_path = to_system_string(path); + m_scripts_path = to_system(path); // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod if (!std::filesystem::exists(path)) @@ -4241,7 +4241,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } return TRY([&] { - auto command = to_system(cmd); + auto command = to_system_string(cmd); auto command_parts = explode_by_occurrence(command, ' '); SystemStringType command_name; if (command_parts.size() > 1) @@ -4301,8 +4301,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. (void)executor; return TRY([&] { - auto command = to_system(cmd); - auto command_parts = explode_by_occurrence(command, ' '); + auto command = to_system_string(cmd); + auto command_parts = explode_by_occurrence(command, SYSSTR(' ')); SystemStringType command_name; if (command_parts.size() > 1) { diff --git a/UE4SS/src/SDKGenerator/Common.cpp b/UE4SS/src/SDKGenerator/Common.cpp index 47321eb3c..b410fc421 100644 --- a/UE4SS/src/SDKGenerator/Common.cpp +++ b/UE4SS/src/SDKGenerator/Common.cpp @@ -37,28 +37,28 @@ namespace RC::UEGenerator { using namespace Unreal; - auto get_native_class_name(UClass* uclass, bool interface_name) -> File::StringType + auto get_native_class_name(UClass* uclass, bool interface_name) -> UEStringType { - File::StringType result_string; + UEStringType result_string; if (interface_name) { - result_string.append(SYSSTR("I")); + result_string.append(STR("I")); } else if (uclass->IsChildOf()) { - result_string.append(SYSSTR("A")); + result_string.append(STR("A")); } else { - result_string.append(SYSSTR("U")); + result_string.append(STR("U")); } if ((uclass->GetClassFlags() & Unreal::CLASS_Deprecated) != 0) { - result_string.append(SYSSTR("DEPRECATED_")); + result_string.append(STR("DEPRECATED_")); } - result_string.append(to_system(uclass->GetName())); + result_string.append(to_ue(uclass->GetName())); return result_string; } @@ -74,43 +74,43 @@ namespace RC::UEGenerator } } - auto get_native_enum_name(UEnum* uenum, bool include_type) -> File::StringType + auto get_native_enum_name(UEnum* uenum, bool include_type) -> UEStringType { - SystemStringType result_string; + UEStringType result_string; // Seems to be not needed, because enum objects, unlike classes or structs, retain their normal E prefix // ResultString.append(SYSSTR("E")); - result_string.append(to_system(uenum->GetName())); + result_string.append(to_ue(uenum->GetName())); // Namespaced enums need to have ::Type appended for the type if (uenum->GetCppForm() == UEnum::ECppForm::Namespaced && include_type) { - result_string.append(SYSSTR("::Type")); + result_string.append(STR("::Type")); } return result_string; } - auto get_native_struct_name(UScriptStruct* script_struct) -> File::StringType + auto get_native_struct_name(UScriptStruct* script_struct) -> UEStringType { - SystemStringType result_string; + UEStringType result_string; - result_string.append(SYSSTR("F")); - result_string.append(to_system(script_struct->GetName())); + result_string.append(STR("F")); + result_string.append(to_ue(script_struct->GetName())); return result_string; } - auto sanitize_property_name(const File::StringType& property_name) -> File::StringType + auto sanitize_property_name(const UEStringType& property_name) -> UEStringType { - SystemStringType resulting_name = property_name; + UEStringType resulting_name = property_name; // Remove heading underscore, used by private variables in some games - if (resulting_name.length() >= 2 && resulting_name[0] == '_') + if (resulting_name.length() >= 2 && resulting_name[0] == STR('_')) { resulting_name.erase(0, 1); } // Remove heading m if it is followed by uppercase letter, used by variables in some games - if (resulting_name.length() >= 2 && resulting_name[0] == 'm' && towupper(resulting_name[1]) == resulting_name[1]) + if (resulting_name.length() >= 2 && resulting_name[0] == STR('m') && towupper(resulting_name[1]) == resulting_name[1]) { resulting_name.erase(0, 1); } @@ -123,14 +123,14 @@ namespace RC::UEGenerator return resulting_name; } - auto generate_delegate_name(FProperty* property, const File::StringType& context_name) -> File::StringType + auto generate_delegate_name(FProperty* property, const UEStringType& context_name) -> SystemStringType { const auto property_name = sanitize_property_name(to_system_string(property->GetName())); - return std::format(SYSSTR("F{}{}"), context_name, property_name); + return std::format(SYSSTR("F{}{}"), to_system(context_name), to_system(property_name)); } auto generate_property_cxx_name(FProperty* property, bool is_top_level_declaration, UObject* class_context, EnableForwardDeclarations enable_forward_declarations) - -> File::StringType + -> UEStringType { const auto field_class_name = to_system(property->GetClass().GetName()); @@ -143,7 +143,7 @@ namespace RC::UEGenerator if (enum_value != NULL) { // Non-EnumClass enumerations should be wrapped into TEnumAsByte according to UHT - const SystemStringType enum_type_name = get_native_enum_name(enum_value); + const SystemStringType enum_type_name = to_system(get_native_enum_name(enum_value)); return std::format(SYSSTR("TEnumAsByte<{}>"), enum_type_name); } return SYSSTR("uint8"); @@ -224,7 +224,7 @@ namespace RC::UEGenerator return SYSSTR("UClass*"); } - File::StringType meta_class_name{}; + SystemStringType meta_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { meta_class_name = SYSSTR("class "); @@ -299,7 +299,7 @@ namespace RC::UEGenerator return SYSSTR("TWeakObjectPtr"); } - File::StringType property_class_name{}; + SystemStringType property_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { property_class_name = std::format(SYSSTR("class ")); @@ -318,7 +318,7 @@ namespace RC::UEGenerator return SYSSTR("TLazyObjectPtr"); } - File::StringType property_class_name{}; + SystemStringType property_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { property_class_name = SYSSTR("class "); @@ -352,7 +352,7 @@ namespace RC::UEGenerator return SYSSTR("FScriptInterface"); } - File::StringType interface_class_name{}; + SystemStringType interface_class_name{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes) { interface_class_name = SYSSTR("class "); @@ -418,7 +418,7 @@ namespace RC::UEGenerator FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - File::StringType inner_property_type{}; + SystemStringType inner_property_type{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes && !is_integral_type(inner_property)) { if (inner_property->IsA()) @@ -446,8 +446,8 @@ namespace RC::UEGenerator FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - File::StringType key_type{}; - File::StringType value_type{}; + SystemStringType key_type{}; + SystemStringType value_type{}; if (enable_forward_declarations == EnableForwardDeclarations::Yes && !is_integral_type(key_property) && !is_integral_type(value_property)) { if (!key_property->IsA()) @@ -482,7 +482,7 @@ namespace RC::UEGenerator throw std::runtime_error(RC::fmt("Unsupported property class " SystemStringPrint, field_class_name)); } - auto generate_property_lua_name(FProperty* property, bool is_top_level_declaration, UObject* class_context) -> File::StringType + auto generate_property_lua_name(FProperty* property, bool is_top_level_declaration, UObject* class_context) -> SystemStringType { const auto field_class_name = to_system(property->GetClass().GetName()); @@ -602,7 +602,7 @@ namespace RC::UEGenerator return SYSSTR("TWeakObjectPtr"); } - File::StringType property_class_name{}; + SystemStringType property_class_name{}; property_class_name.append(get_native_class_name(property_class, false)); return std::format(SYSSTR("TWeakObjectPtr<{}>"), property_class_name); } @@ -617,7 +617,7 @@ namespace RC::UEGenerator return SYSSTR("TLazyObjectPtr"); } - File::StringType property_class_name{}; + SystemStringType property_class_name{}; property_class_name.append(get_native_class_name(property_class, false)); return std::format(SYSSTR("TLazyObjectPtr<{}>"), property_class_name); } @@ -647,7 +647,7 @@ namespace RC::UEGenerator return SYSSTR("UClass"); } - File::StringType meta_class_name{}; + SystemStringType meta_class_name{}; meta_class_name.append(get_native_class_name(meta_class, false)); return std::format(SYSSTR("TSubclassOf<{}>"), meta_class_name); } @@ -683,7 +683,7 @@ namespace RC::UEGenerator return SYSSTR("FScriptInterface"); } - File::StringType interface_class_name{}; + SystemStringType interface_class_name{}; interface_class_name.append(get_native_class_name(interface_class, true)); return std::format(SYSSTR("TScriptInterface<{}>"), interface_class_name); } @@ -745,7 +745,7 @@ namespace RC::UEGenerator FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - File::StringType inner_property_type{}; + SystemStringType inner_property_type{}; inner_property_type.append(generate_property_lua_name(inner_property, is_top_level_declaration, class_context)); return std::format(SYSSTR("TArray<{}>"), inner_property_type); } @@ -766,8 +766,8 @@ namespace RC::UEGenerator FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - File::StringType key_type{}; - File::StringType value_type{}; + SystemStringType key_type{}; + SystemStringType value_type{}; key_type.append(generate_property_lua_name(key_property, is_top_level_declaration, class_context)); value_type.append(generate_property_lua_name(value_property, is_top_level_declaration, class_context)); @@ -790,7 +790,7 @@ namespace RC::UEGenerator throw std::runtime_error(RC::fmt("Unsupported property class {}", field_class_name)); } - auto get_native_delegate_type_name(Unreal::UFunction* signature_function, Unreal::UClass* current_class, bool strip_outer_name) -> File::StringType + auto get_native_delegate_type_name(Unreal::UFunction* signature_function, Unreal::UClass* current_class, bool strip_outer_name) -> SystemStringType { if (!is_delegate_signature_function(signature_function)) { @@ -798,7 +798,7 @@ namespace RC::UEGenerator } // Delegate names always start with F and have __DelegateSignature postfix - File::StringType delegate_type_name = strip_delegate_signature_postfix(signature_function); + SystemStringType delegate_type_name = strip_delegate_signature_postfix(signature_function); delegate_type_name.insert(0, SYSSTR("F")); // Return the delegate name without the outer name if we have been requested to strip it @@ -818,7 +818,7 @@ namespace RC::UEGenerator { // For interface, delegates are declared inside the interface definition bool is_class_interface = delegate_outer_class->IsChildOf(); - const File::StringType outer_class_name = get_native_class_name(delegate_outer_class, is_class_interface); + const SystemStringType outer_class_name = get_native_class_name(delegate_outer_class, is_class_interface); delegate_type_name.insert(0, SYSSTR("::")); delegate_type_name.insert(0, outer_class_name); @@ -837,7 +837,7 @@ namespace RC::UEGenerator return (function->GetFunctionFlags() & Unreal::FUNC_Delegate) != 0 && function->GetName().ends_with(DELEGATE_SIGNATURE_POSTFIX); } - auto strip_delegate_signature_postfix(Unreal::UFunction* signature_function) -> File::StringType + auto strip_delegate_signature_postfix(Unreal::UFunction* signature_function) -> SystemStringType { if (!is_delegate_signature_function(signature_function)) { diff --git a/UE4SS/src/SDKGenerator/Generator.cpp b/UE4SS/src/SDKGenerator/Generator.cpp index eb9f931dc..ee56e318e 100644 --- a/UE4SS/src/SDKGenerator/Generator.cpp +++ b/UE4SS/src/SDKGenerator/Generator.cpp @@ -71,18 +71,18 @@ namespace RC::UEGenerator { std::filesystem::path primary_file_name; std::filesystem::path secondary_file_name; - std::vector ordered_primary_file_contents; - std::vector ordered_secondary_file_contents; - File::StringType package_name; + std::vector ordered_primary_file_contents; + std::vector ordered_secondary_file_contents; + SystemStringType package_name; File::Handle primary_file; File::Handle secondary_file; bool primary_file_has_no_contents; bool secondary_file_has_no_contents; }; - auto generate_tab(size_t num_tabs = 1) -> File::StringType + auto generate_tab(size_t num_tabs = 1) -> SystemStringType { - File::StringType tab_storage{}; + SystemStringType tab_storage{}; for (size_t i = 0; i < num_tabs; ++i) { tab_storage += SYSSTR(" "); @@ -90,7 +90,7 @@ namespace RC::UEGenerator return tab_storage; } - auto generate_prefix(UStruct* obj) -> File::StringType + auto generate_prefix(UStruct* obj) -> SystemStringType { UClass* obj_class = obj->GetClassPrivate(); if (obj_class->IsChildOf()) @@ -102,7 +102,7 @@ namespace RC::UEGenerator return SYSSTR("class"); } } - auto generate_class_name(UStruct* class_to_generate) -> File::StringType + auto generate_class_name(UStruct* class_to_generate) -> SystemStringType { if (class_to_generate->GetClassPrivate()->IsChildOf()) { @@ -134,7 +134,7 @@ namespace RC::UEGenerator // Map of FName.ComparisonIndex -> File::Handle std::unordered_map m_files{}; - std::unordered_map m_file_names{}; + std::unordered_map m_file_names{}; std::unordered_map m_classes_dumped{}; public: @@ -158,7 +158,7 @@ namespace RC::UEGenerator sort_files(generated_file.ordered_primary_file_contents); - File::StringType combined_file_contents; + SystemStringType combined_file_contents; for (auto& line : generated_file.ordered_primary_file_contents) { combined_file_contents.append(line); @@ -170,7 +170,7 @@ namespace RC::UEGenerator } else { - generated_file.primary_file.write_string_to_file(combined_file_contents); + generated_file.primary_file.write_file_string_to_file(to_file(combined_file_contents)); } specification.generate_file_footer(generated_file); @@ -185,7 +185,7 @@ namespace RC::UEGenerator sort_files(generated_file.ordered_secondary_file_contents); - File::StringType combined_file_contents; + SystemStringType combined_file_contents; for (auto& line : generated_file.ordered_secondary_file_contents) { combined_file_contents.append(line); @@ -197,7 +197,7 @@ namespace RC::UEGenerator } else { - generated_file.secondary_file.write_string_to_file(combined_file_contents); + generated_file.secondary_file.write_file_string_to_file(to_file(combined_file_contents)); } generated_file.secondary_file.close(); @@ -205,11 +205,11 @@ namespace RC::UEGenerator } } - auto sort_files(std::vector& content) -> void + auto sort_files(std::vector& content) -> void { - std::vector struct_content; - std::vector class_content; - std::vector other_content; + std::vector struct_content; + std::vector class_content; + std::vector other_content; for (auto& line : content) { if (line.starts_with(SYSSTR("struct"))) @@ -237,7 +237,7 @@ namespace RC::UEGenerator content.insert(content.end(), other_content.begin(), other_content.end()); } - auto sort_types(std::vector& content) -> void + auto sort_types(std::vector& content) -> void { std::sort(content.begin(), content.end(), [&](const auto& a, const auto& b) { auto a_class_name = get_class_name(a); @@ -265,7 +265,7 @@ namespace RC::UEGenerator return object->GetClassPrivate()->GetNamePrivate().Equals(Unreal::GPackageName); } - auto generate_offset_comment(XProperty* property, File::StringType& line) -> File::StringType + auto generate_offset_comment(XProperty* property, SystemStringType& line) -> SystemStringType { if (UE4SSProgram::settings_manager.CXXHeaderGenerator.DumpOffsetsAndSizes) { @@ -323,7 +323,7 @@ namespace RC::UEGenerator auto generate_function_declaration(ObjectInfo& owner, const FunctionInfo& function_info, GeneratedFile& generated_file, - File::StringType& out_current_class_content, + SystemStringType& out_current_class_content, IsDelegateFunction is_delegate_function = IsDelegateFunction::No) -> void { std::optional return_property_info = [&]() -> std::optional { @@ -342,7 +342,7 @@ namespace RC::UEGenerator return return_property_info.has_value() ? return_property_info.value().property : nullptr; }(); - File::StringType function_name{to_system(function_info.function->GetName())}; + SystemStringType function_name {to_system(function_info.function->GetName())}; if (is_delegate_function == IsDelegateFunction::Yes) { // Remove the last 19 characters, which is always '__DelegateSignature' for delegates @@ -364,7 +364,7 @@ namespace RC::UEGenerator out_current_class_content.append(current_class_content); } - auto generate_class_dependency(ObjectInfo& owner, UStruct* inherited_class, File::StringType& current_class_content) -> void + auto generate_class_dependency(ObjectInfo& owner, UStruct* inherited_class, SystemStringType& current_class_content) -> void { if (!inherited_class) { @@ -377,7 +377,7 @@ namespace RC::UEGenerator if (package_file_for_inherited_class) { auto& inherited_object_info = m_classes_dumped.emplace(inherited_class, ObjectInfo{inherited_class, &owner}).first->second; - File::StringType new_class_content{}; + SystemStringType new_class_content{}; generate_class(inherited_object_info, *package_file_for_inherited_class, new_class_content); if (!package_file_for_inherited_class->primary_file_has_no_contents) { @@ -389,7 +389,7 @@ namespace RC::UEGenerator } } - auto generate_class_dependency_from_property(ObjectInfo& owner, XProperty* property, File::StringType& current_class_content) -> bool + auto generate_class_dependency_from_property(ObjectInfo& owner, XProperty* property, SystemStringType& current_class_content) -> bool { if (property->IsA()) { @@ -441,7 +441,7 @@ namespace RC::UEGenerator return false; } - auto make_function_info(ObjectInfo& owner, UFunction* function, File::StringType& current_class_content) -> FunctionInfo + auto make_function_info(ObjectInfo& owner, UFunction* function, SystemStringType& current_class_content) -> FunctionInfo { FunctionInfo function_info{ .function = function, @@ -461,7 +461,7 @@ namespace RC::UEGenerator return function_info; } - auto generate_class(ObjectInfo object_info, GeneratedFile& generated_file, File::StringType& current_class_content) -> XProperty* + auto generate_class(ObjectInfo object_info, GeneratedFile& generated_file, SystemStringType& current_class_content) -> XProperty* { UStruct* native_class = static_cast(object_info.object); if (specification.should_generate_class(native_class)) @@ -477,7 +477,7 @@ namespace RC::UEGenerator { generated_file.secondary_file_has_no_contents = false; - File::StringType content_buffer; + SystemStringType content_buffer; UEnum* uenum = static_cast(native_object); specification.generate_enum_declaration(content_buffer, uenum); @@ -498,7 +498,7 @@ namespace RC::UEGenerator generated_file.ordered_secondary_file_contents.push_back(content_buffer); } - auto generate_package(UObject* package, File::StringType& out) -> void + auto generate_package(UObject* package, SystemStringType& out) -> void { UObjectGlobals::ForEachUObject([&](void* object, [[maybe_unused]] int32_t chunk_index, [[maybe_unused]] int32_t object_index) { return LoopAction::Continue; @@ -538,10 +538,10 @@ namespace RC::UEGenerator else { // Get rid of everything before the last slash + the last slash, leaving only the actual name - File::StringType package_name = to_system(package->GetNamePrivate().ToString()); + SystemStringType package_name = to_system(package->GetNamePrivate().ToString()); package_name = package_name.substr(package_name.rfind(SYSSTR("/")) + 1); - File::StringType package_name_all_lower = package_name; - std::transform(package_name_all_lower.begin(), package_name_all_lower.end(), package_name_all_lower.begin(), [](File::CharType c) { + SystemStringType package_name_all_lower = package_name; + std::transform(package_name_all_lower.begin(), package_name_all_lower.end(), package_name_all_lower.begin(), [](SystemCharType c) { return std::towlower(c); }); @@ -565,7 +565,7 @@ namespace RC::UEGenerator std::filesystem::path directory_to_generate_in = (m_directory_to_generate_in); #endif - File::StringType ext = specification.get_file_extension(); + SystemStringType ext = specification.get_file_extension(); std::filesystem::path primary_file_path_and_name = directory_to_generate_in; primary_file_path_and_name.append(package_name); primary_file_path_and_name.replace_extension(ext); @@ -647,7 +647,7 @@ namespace RC::UEGenerator { // Generate a class for this object auto& object_info = m_classes_dumped.emplace(object, ObjectInfo{object}).first->second; - File::StringType class_content{}; + SystemStringType class_content{}; generate_class(object_info, *package_file, class_content); if (!package_file->primary_file_has_no_contents) { @@ -671,7 +671,7 @@ namespace RC::UEGenerator class CXXHeaderGenerator { public: - auto get_file_extension() -> File::StringType + auto get_file_extension() -> SystemStringType { return SYSSTR(".hpp"); } @@ -689,7 +689,7 @@ namespace RC::UEGenerator { generated_file.primary_file.write_string_to_file(std::format(SYSSTR("#endif\n"))); } - auto generate_enum_declaration(File::StringType& content_buffer, UEnum* uenum) -> void + auto generate_enum_declaration(SystemStringType& content_buffer, UEnum* uenum) -> void { const auto cpp_form = uenum->GetCppForm(); if (cpp_form == UEnum::ECppForm::Regular) @@ -705,7 +705,7 @@ namespace RC::UEGenerator content_buffer.append(std::format(SYSSTR("enum class {} {{\n"), get_native_enum_name(uenum, false))); } } - auto generate_enum_member(File::StringType& content_buffer, UEnum* uenum, const File::StringType& enum_value_name, const Unreal::FEnumNamePair& elem) -> void + auto generate_enum_member(SystemStringType& content_buffer, UEnum* uenum, const SystemStringType& enum_value_name, const Unreal::FEnumNamePair& elem) -> void { content_buffer.append(std::format(SYSSTR("{}{}{} = {},\n"), generate_tab(), @@ -713,7 +713,7 @@ namespace RC::UEGenerator enum_value_name, elem.Value)); } - auto generate_enum_end(File::StringType& content_buffer, UEnum* uenum) -> void + auto generate_enum_end(SystemStringType& content_buffer, UEnum* uenum) -> void { const auto cpp_form = uenum->GetCppForm(); content_buffer.append(std::format(SYSSTR("{}}};"), cpp_form == UEnum::ECppForm::Namespaced ? generate_tab() : SYSSTR(""))); @@ -727,10 +727,10 @@ namespace RC::UEGenerator { return true; } - auto generate_class(TypeGenerator* generator, ObjectInfo& object_info, GeneratedFile& generated_file, File::StringType& current_class_content) + auto generate_class(TypeGenerator* generator, ObjectInfo& object_info, GeneratedFile& generated_file, SystemStringType& current_class_content) { UStruct* native_class = static_cast(object_info.object); - File::StringType content_buffer{}; + SystemStringType content_buffer{}; UStruct* inherits_from_class = native_class->GetSuperStruct(); @@ -876,7 +876,7 @@ namespace RC::UEGenerator current_class_content.append(content_buffer); } - auto generate_class_declaration(File::StringType& content_buffer, UStruct* native_class, UStruct* inherits_from_class) -> void + auto generate_class_declaration(SystemStringType& content_buffer, UStruct* native_class, UStruct* inherits_from_class) -> void { auto class_name = generate_class_name(native_class); if (inherits_from_class) @@ -889,8 +889,8 @@ namespace RC::UEGenerator content_buffer.append(std::format(SYSSTR("{} {}\n{{\n"), generate_prefix(native_class), class_name)); } } - auto generate_class_struct_end(File::StringType& content_buffer, - const File::StringType& class_name, + auto generate_class_struct_end(SystemStringType& content_buffer, + const SystemStringType& class_name, size_t class_size, int32_t num_padding_elements, XProperty* last_property_in_this_class) -> void @@ -932,7 +932,7 @@ namespace RC::UEGenerator } } } - auto generate_class_end(File::StringType& content_buffer, size_t class_size) -> void + auto generate_class_end(SystemStringType& content_buffer, size_t class_size) -> void { if (UE4SSProgram::settings_manager.CXXHeaderGenerator.DumpOffsetsAndSizes) { @@ -945,14 +945,14 @@ namespace RC::UEGenerator } auto generate_function_declaration(TypeGenerator* generator, - File::StringType& current_class_content, + SystemStringType& current_class_content, ObjectInfo& owner, const FunctionInfo& function_info, - File::StringType function_name, + SystemStringType function_name, XProperty* return_property, std::optional return_property_info) -> void { - File::StringType function_type_name{}; + SystemStringType function_type_name{}; if (return_property) { try @@ -1019,9 +1019,9 @@ namespace RC::UEGenerator class LuaTypesGenerator { private: - auto is_valid_lua_symbol(const File::StringType& str) -> bool + auto is_valid_lua_symbol(const SystemStringType& str) -> bool { - static const std::set keywords = {SYSSTR("and"), SYSSTR("break"), SYSSTR("do"), SYSSTR("else"), SYSSTR("elseif"), SYSSTR("end"), + static const std::set keywords = {SYSSTR("and"), SYSSTR("break"), SYSSTR("do"), SYSSTR("else"), SYSSTR("elseif"), SYSSTR("end"), SYSSTR("false"), SYSSTR("for"), SYSSTR("function"), SYSSTR("if"), SYSSTR("in"), SYSSTR("local"), SYSSTR("nil"), SYSSTR("not"), SYSSTR("or"), SYSSTR("repeat"), SYSSTR("return"), SYSSTR("then"), SYSSTR("true"), SYSSTR("until"), SYSSTR("while")}; @@ -1046,9 +1046,9 @@ namespace RC::UEGenerator } return true; } - auto quote_lua_symbol(const File::StringType& symbol) -> File::StringType + auto quote_lua_symbol(const SystemStringType& symbol) -> SystemStringType { - File::StringType quoted; + SystemStringType quoted; quoted.reserve(symbol.size() + 2); quoted.push_back('\''); for (auto it = symbol.begin(); it != symbol.end(); ++it) @@ -1063,9 +1063,9 @@ namespace RC::UEGenerator quoted.push_back('\''); return quoted; } - auto make_valid_symbol(const File::StringType& symbol) -> File::StringType + auto make_valid_symbol(const SystemStringType& symbol) -> SystemStringType { - File::StringType valid; + SystemStringType valid; valid.reserve(symbol.size()); auto it = symbol.begin(); if (it == symbol.end() || std::isdigit(*it)) @@ -1081,7 +1081,7 @@ namespace RC::UEGenerator } public: - auto get_file_extension() -> File::StringType + auto get_file_extension() -> SystemStringType { return SYSSTR(".lua"); } @@ -1092,16 +1092,16 @@ namespace RC::UEGenerator auto generate_file_footer(GeneratedFile& generated_file) -> void { } - auto generate_enum_declaration(File::StringType& content_buffer, UEnum* uenum) -> void + auto generate_enum_declaration(SystemStringType& content_buffer, UEnum* uenum) -> void { auto enum_name = to_system(uenum->GetName()); content_buffer.append(std::format(SYSSTR("---@enum {}\n{} = {{\n"), enum_name, enum_name)); } - auto generate_enum_member(File::StringType& content_buffer, UEnum* uenum, const File::StringType& enum_value_name, const Unreal::FEnumNamePair& elem) -> void + auto generate_enum_member(SystemStringType& content_buffer, UEnum* uenum, const SystemStringType& enum_value_name, const Unreal::FEnumNamePair& elem) -> void { content_buffer.append(std::format(SYSSTR("{}{} = {},\n"), generate_tab(), enum_value_name, elem.Value)); } - auto generate_enum_end(File::StringType& content_buffer, UEnum* uenum) -> void + auto generate_enum_end(SystemStringType& content_buffer, UEnum* uenum) -> void { content_buffer.append(SYSSTR("}")); } @@ -1111,10 +1111,10 @@ namespace RC::UEGenerator // skip UObject to define externally return native_class != UObject::StaticClass(); } - auto generate_class(TypeGenerator* generator, ObjectInfo& object_info, GeneratedFile& generated_file, File::StringType& current_class_content) + auto generate_class(TypeGenerator* generator, ObjectInfo& object_info, GeneratedFile& generated_file, SystemStringType& current_class_content) { UStruct* native_class = static_cast(object_info.object); - File::StringType content_buffer{}; + SystemStringType content_buffer{}; UStruct* inherits_from_class = native_class->GetSuperStruct(); @@ -1203,7 +1203,7 @@ namespace RC::UEGenerator current_class_content.append(content_buffer); } - auto generate_class_declaration(File::StringType& content_buffer, UStruct* native_class, UStruct* inherits_from_class) -> void + auto generate_class_declaration(SystemStringType& content_buffer, UStruct* native_class, UStruct* inherits_from_class) -> void { auto class_name = generate_class_name(native_class); if (inherits_from_class) @@ -1215,23 +1215,23 @@ namespace RC::UEGenerator content_buffer.append(std::format(SYSSTR("---@class {}\n"), class_name)); } } - auto generate_class_struct_end(File::StringType& content_buffer, - const File::StringType& class_name, + auto generate_class_struct_end(SystemStringType& content_buffer, + const SystemStringType& class_name, size_t class_size, int32_t num_padding_elements, XProperty* last_property_in_this_class) -> void { content_buffer.append(std::format(SYSSTR("{} = {{}}\n"), class_name)); } - auto generate_class_end(File::StringType& content_buffer, size_t class_size) -> void + auto generate_class_end(SystemStringType& content_buffer, size_t class_size) -> void { } auto generate_function_declaration(TypeGenerator* generator, - File::StringType& current_class_content, + SystemStringType& current_class_content, ObjectInfo& owner, const FunctionInfo& function_info, - File::StringType function_name, + SystemStringType function_name, XProperty* return_property, std::optional return_property_info) -> void { diff --git a/UE4SS/src/SDKGenerator/JSONDumper.cpp b/UE4SS/src/SDKGenerator/JSONDumper.cpp index 5920f4f0c..710e5d8b1 100644 --- a/UE4SS/src/SDKGenerator/JSONDumper.cpp +++ b/UE4SS/src/SDKGenerator/JSONDumper.cpp @@ -15,7 +15,7 @@ namespace RC::UEGenerator::JSONDumper { using namespace ::RC::Unreal; - auto static is_valid_class_to_dump(File::StringViewType class_name, UObject* object) -> bool + auto static is_valid_class_to_dump(SystemStringViewType class_name, UObject* object) -> bool { static bool is_below_425 = Unreal::Version::IsBelow(4, 25); if (is_below_425 && Unreal::TypeChecker::is_property(object)) @@ -177,7 +177,7 @@ namespace RC::UEGenerator::JSONDumper return should_skip_general_function(function); } - auto static should_skip_event(File::StringViewType event_name) -> bool + auto static should_skip_event(SystemStringViewType event_name) -> bool { if (event_name.find(SYSSTR("BndEvt")) != event_name.npos) { @@ -186,7 +186,7 @@ namespace RC::UEGenerator::JSONDumper return false; } - auto dump_to_json(File::StringViewType file_name) -> void + auto dump_to_json(SystemStringViewType file_name) -> void { Output::send(SYSSTR("Loading all assets...\n")); UAssetRegistry::LoadAllAssets(); @@ -337,7 +337,7 @@ namespace RC::UEGenerator::JSONDumper auto json_file = File::open(file_name, File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); int32_t indent_level{}; - json_file.write_string_to_file(json.serialize(JSON::ShouldFormat::Yes, &indent_level)); + json_file.write_file_string_to_file(to_file(json.serialize(JSON::ShouldFormat::Yes, &indent_level))); json_file.close(); Output::send(SYSSTR("Unloading all forcefully loaded assets\n")); diff --git a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp index 25012e71e..d12859ad4 100644 --- a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp +++ b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp @@ -118,8 +118,8 @@ namespace RC::UEGenerator File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); - uaapifile.write_string_to_file(uaapi_object.serialize(JSON::ShouldFormat::Yes, &indent_level)); - fmodelfile.write_string_to_file(fm_object.serialize(JSON::ShouldFormat::Yes, &indent_level)); + uaapifile.write_file_string_to_file(to_file(uaapi_object.serialize(JSON::ShouldFormat::Yes, &indent_level))); + fmodelfile.write_file_string_to_file(to_file(fm_object.serialize(JSON::ShouldFormat::Yes, &indent_level))); Output::send(SYSSTR("Finished Dumping {} TMap Properties\n"), num_objects_generated); MapProperties.clear(); } diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index f2e5c2942..18182c4e8 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -58,7 +58,7 @@ namespace RC::UEGenerator { using namespace RC::Unreal; - std::map UEHeaderGenerator::m_used_file_names{}; + std::map UEHeaderGenerator::m_used_file_names{}; std::map UEHeaderGenerator::m_dependency_object_to_unique_id{}; auto static is_subtype_struct_valid(UScriptStruct* subtype) -> bool @@ -3766,7 +3766,7 @@ namespace RC::UEGenerator bool is_class = object->IsA(); if ((is_struct || is_class) && m_structs_that_need_get_type_hash.find(std::bit_cast(object)) != m_structs_that_need_get_type_hash.end()) { - File::StringType name{}; + SystemStringType name{}; if (is_class) { name = get_native_class_name(std::bit_cast(object)); @@ -3787,11 +3787,11 @@ namespace RC::UEGenerator { if (get_native_struct_name(super_struct) == STR("FTickFunction")) { - File::StringType name{}; + SystemStringType name{}; name = get_native_struct_name(struct_object); header_file.append_line(STR("")); header_file.append_line(STR("template<>")); - header_file.append_line(std::format(STR("struct TStructOpsTypeTraits<{}> : public TStructOpsTypeTraitsBase2<{}>"), name, name)); + header_file.append_line(std::format(SYSSTR("struct TStructOpsTypeTraits<{}> : public TStructOpsTypeTraitsBase2<{}>"), name, name)); header_file.append_line(STR("{")); header_file.append_line(STR(" enum")); header_file.append_line(STR(" {")); @@ -3925,22 +3925,22 @@ namespace RC::UEGenerator return pre_declarations; } - auto UEHeaderGenerator::get_header_name_for_object(UObject* object, bool get_existing_header) -> UEStringType + auto UEHeaderGenerator::get_header_name_for_object(UObject* object, bool get_existing_header) -> SystemStringType { - File::StringType header_name{}; + SystemStringType header_name{}; UObject* final_object{}; if (object->IsA() || object->IsA()) { // Class and struct headers follow the relevant object name - header_name = (object->GetName()); + header_name = to_system(object->GetName()); final_object = object; } else if (object->IsA()) { // Enumeration usually have the E prefix which will be present in the header names // We do not strip it because there are some broken headers that do not follow that convention (e.g. funny Wwise) - header_name = (object->GetName()); + header_name = to_system(object->GetName()); final_object = object; } else @@ -3978,14 +3978,14 @@ namespace RC::UEGenerator { if (auto it2 = m_dependency_object_to_unique_id.find(final_object); it2 != m_dependency_object_to_unique_id.end()) { - header_name.append(std::format(STR("{}"), it2->second)); + header_name.append(std::format(SYSSTR("{}"), it2->second)); } } else { if (auto it = m_used_file_names.find(header_name); it != m_used_file_names.end()) { - header_name.append(std::format(STR("{}"), ++it->second.usable_id)); + header_name.append(std::format(SYSSTR("{}"), ++it->second.usable_id)); m_dependency_object_to_unique_id.emplace(final_object, it->second.usable_id); } else diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index e9419c0fb..d47b12afb 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -5,7 +5,7 @@ #define REGISTER_STRING_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_string(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_string(section_name, STR(#key)); \ } \ catch (std::exception&) \ { \ @@ -14,7 +14,7 @@ #define REGISTER_INT64_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_int64(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_int64(section_name, STR(#key)); \ } \ catch (std::exception&) \ { \ @@ -23,7 +23,7 @@ #define REGISTER_BOOL_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_bool(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_bool(section_name, STR(#key)); \ } \ catch (std::exception&) \ { \ @@ -32,7 +32,7 @@ #define REGISTER_FLOAT_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_float(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_float(section_name, STR(#key)); \ } \ catch (std::exception&) \ { \ @@ -46,10 +46,10 @@ namespace RC Ini::Parser parser; parser.parse(file); file.close(); - constexpr static File::CharType section_overrides[] = SYSSTR("Overrides"); + constexpr static UECharType section_overrides[] = STR("Overrides"); REGISTER_STRING_SETTING(Overrides.ModsFolderPath, section_overrides, ModsFolderPath) - constexpr static File::CharType section_general[] = SYSSTR("General"); + constexpr static UECharType section_general[] = STR("General"); REGISTER_BOOL_SETTING(General.EnableHotReloadSystem, section_general, EnableHotReloadSystem) REGISTER_BOOL_SETTING(General.UseCache, section_general, UseCache) REGISTER_BOOL_SETTING(General.InvalidateCacheIfDLLDiffers, section_general, InvalidateCacheIfDLLDiffers) @@ -57,19 +57,19 @@ namespace RC REGISTER_INT64_SETTING(General.SecondsToScanBeforeGivingUp, section_general, SecondsToScanBeforeGivingUp) REGISTER_BOOL_SETTING(General.UseUObjectArrayCache, section_general, bUseUObjectArrayCache) - constexpr static File::CharType section_engine_version_override[] = SYSSTR("EngineVersionOverride"); + constexpr static UECharType section_engine_version_override[] = STR("EngineVersionOverride"); REGISTER_INT64_SETTING(EngineVersionOverride.MajorVersion, section_engine_version_override, MajorVersion) REGISTER_INT64_SETTING(EngineVersionOverride.MinorVersion, section_engine_version_override, MinorVersion) - constexpr static File::CharType section_object_dumper[] = SYSSTR("ObjectDumper"); + constexpr static UECharType section_object_dumper[] = STR("ObjectDumper"); REGISTER_BOOL_SETTING(ObjectDumper.LoadAllAssetsBeforeDumpingObjects, section_object_dumper, LoadAllAssetsBeforeDumpingObjects) - constexpr static File::CharType section_cxx_header_generator[] = SYSSTR("CXXHeaderGenerator"); + constexpr static UECharType section_cxx_header_generator[] = STR("CXXHeaderGenerator"); REGISTER_BOOL_SETTING(CXXHeaderGenerator.DumpOffsetsAndSizes, section_cxx_header_generator, DumpOffsetsAndSizes) REGISTER_BOOL_SETTING(CXXHeaderGenerator.KeepMemoryLayout, section_cxx_header_generator, KeepMemoryLayout) REGISTER_BOOL_SETTING(CXXHeaderGenerator.LoadAllAssetsBeforeGeneratingCXXHeaders, section_cxx_header_generator, LoadAllAssetsBeforeGeneratingCXXHeaders) - constexpr static File::CharType section_uht_header_generator[] = SYSSTR("UHTHeaderGenerator"); + constexpr static UECharType section_uht_header_generator[] = STR("UHTHeaderGenerator"); REGISTER_BOOL_SETTING(UHTHeaderGenerator.IgnoreAllCoreEngineModules, section_uht_header_generator, IgnoreAllCoreEngineModules) REGISTER_BOOL_SETTING(UHTHeaderGenerator.IgnoreEngineAndCoreUObject, section_uht_header_generator, IgnoreEngineAndCoreUObject) REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeAllFunctionsBlueprintCallable, section_uht_header_generator, MakeAllFunctionsBlueprintCallable) @@ -77,37 +77,37 @@ namespace RC REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeEnumClassesBlueprintType, section_uht_header_generator, MakeEnumClassesBlueprintType) REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeAllConfigsEngineConfig, section_uht_header_generator, MakeAllConfigsEngineConfig) - constexpr static File::CharType section_debug[] = SYSSTR("Debug"); + constexpr static UECharType section_debug[] = STR("Debug"); REGISTER_BOOL_SETTING(Debug.SimpleConsoleEnabled, section_debug, ConsoleEnabled) REGISTER_BOOL_SETTING(Debug.DebugConsoleEnabled, section_debug, GuiConsoleEnabled) REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) REGISTER_FLOAT_SETTING(Debug.DebugGUIFontScaling, section_debug, GuiConsoleFontScaling) #ifdef HAS_GUI - SystemStringType graphics_api_string{}; + UEStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) - if (String::iequal(graphics_api_string, SYSSTR("DX11")) || String::iequal(graphics_api_string, SYSSTR("D3D11"))) + if (String::iequal(graphics_api_string, STR("DX11")) || String::iequal(graphics_api_string, STR("D3D11"))) { Debug.GraphicsAPI = GUI::GfxBackend::DX11; } - else if (String::iequal(graphics_api_string, SYSSTR("OpenGL"))) + else if (String::iequal(graphics_api_string, STR("OpenGL"))) { Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; } #endif REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); - ///constexpr static File::CharType section_crash_dump[] = SYSSTR("CrashDump"); + ///constexpr static UECharType section_crash_dump[] = SSTR("CrashDump"); ///REGISTER_BOOL_SETTING(CrashDump.EnableDumping, section_crash_dump, EnableDumping); ///REGISTER_BOOL_SETTING(CrashDump.FullMemoryDump, section_crash_dump, FullMemoryDump); - constexpr static File::CharType section_threads[] = SYSSTR("Threads"); + constexpr static UECharType section_threads[] = STR("Threads"); REGISTER_INT64_SETTING(Threads.SigScannerNumThreads, section_threads, SigScannerNumThreads) REGISTER_INT64_SETTING(Threads.SigScannerMultithreadingModuleSizeThreshold, section_threads, SigScannerMultithreadingModuleSizeThreshold) - constexpr static File::CharType section_memory[] = SYSSTR("Memory"); + constexpr static UECharType section_memory[] = STR("Memory"); REGISTER_INT64_SETTING(Memory.MaxMemoryUsageDuringAssetLoading, section_memory, MaxMemoryUsageDuringAssetLoading) - constexpr static File::CharType section_hooks[] = SYSSTR("Hooks"); + constexpr static UECharType section_hooks[] = STR("Hooks"); REGISTER_BOOL_SETTING(Hooks.HookProcessInternal, section_hooks, HookProcessInternal) REGISTER_BOOL_SETTING(Hooks.HookProcessLocalScriptFunction, section_hooks, HookProcessLocalScriptFunction) REGISTER_BOOL_SETTING(Hooks.HookLoadMap, section_hooks, HookLoadMap) @@ -118,7 +118,7 @@ namespace RC REGISTER_BOOL_SETTING(Hooks.HookAActorTick, section_hooks, HookAActorTick) REGISTER_INT64_SETTING(Hooks.FExecVTableOffsetInLocalPlayer, section_hooks, FExecVTableOffsetInLocalPlayer) - constexpr static File::CharType section_experimental_features[] = SYSSTR("ExperimentalFeatures"); + constexpr static UECharType section_experimental_features[] = STR("ExperimentalFeatures"); REGISTER_BOOL_SETTING(Experimental.GUIUFunctionCaller, section_experimental_features, GUIUFunctionCaller) } } // namespace RC diff --git a/UE4SS/src/Signatures.cpp b/UE4SS/src/Signatures.cpp index fce05f4f4..e841b64bc 100644 --- a/UE4SS/src/Signatures.cpp +++ b/UE4SS/src/Signatures.cpp @@ -91,7 +91,7 @@ namespace RC auto setup_lua_scan_overrides(std::filesystem::path& working_directory, Unreal::UnrealInitializer::Config& config) -> void { - SystemStringType lua_guobjectarray_scan_script = to_system_string(working_directory / "UE4SS_Signatures/GUObjectArray.lua"); + auto lua_guobjectarray_scan_script = to_system(working_directory / "UE4SS_Signatures/GUObjectArray.lua"); if (std::filesystem::exists(lua_guobjectarray_scan_script)) { config.ScanOverrides.guobjectarray = [lua_guobjectarray_scan_script](std::vector& signature_containers, @@ -113,7 +113,7 @@ namespace RC }; } - SystemStringType lua_fts_scan_script = to_system_string(working_directory / "UE4SS_Signatures/FName_ToString.lua"); + auto lua_fts_scan_script = to_system(working_directory / "UE4SS_Signatures/FName_ToString.lua"); if (std::filesystem::exists(lua_fts_scan_script)) { config.ScanOverrides.fname_to_string = [lua_fts_scan_script](std::vector& signature_containers, @@ -135,7 +135,7 @@ namespace RC }; } - SystemStringType lua_fnc_scan_script = to_system_string(working_directory / "UE4SS_Signatures/FName_Constructor.lua"); + auto lua_fnc_scan_script = to_system(working_directory / "UE4SS_Signatures/FName_Constructor.lua"); if (std::filesystem::exists(lua_fnc_scan_script)) { config.ScanOverrides.fname_constructor = [lua_fnc_scan_script](std::vector& signature_containers, @@ -168,8 +168,8 @@ namespace RC } // For compatibility, we look for 'FMemory_Free.lua' if 'GMalloc.lua' doesn't exist. - SystemStringType lua_ffree_scan_script_new = to_system_string(working_directory / "UE4SS_Signatures/GMalloc.lua"); - SystemStringType lua_ffree_scan_script_compat = to_system_string(working_directory / "UE4SS_Signatures/FMemory_Free.lua"); + auto lua_ffree_scan_script_new = to_system(working_directory / "UE4SS_Signatures/GMalloc.lua"); + auto lua_ffree_scan_script_compat = to_system(working_directory / "UE4SS_Signatures/FMemory_Free.lua"); auto lua_ffree_scan_script = std::filesystem::exists(lua_ffree_scan_script_new) ? lua_ffree_scan_script_new : lua_ffree_scan_script_compat; if (std::filesystem::exists(lua_ffree_scan_script)) { @@ -193,7 +193,7 @@ namespace RC }; } - SystemStringType lua_sco_scan_script = to_system_string(working_directory / "UE4SS_Signatures/StaticConstructObject.lua"); + auto lua_sco_scan_script = to_system(working_directory / "UE4SS_Signatures/StaticConstructObject.lua"); if (std::filesystem::exists(lua_sco_scan_script)) { config.ScanOverrides.static_construct_object = [lua_sco_scan_script](std::vector& signature_containers, @@ -215,7 +215,7 @@ namespace RC }; } - SystemStringType lua_ftc_scan_script = to_system_string(working_directory / "UE4SS_Signatures/FText_Constructor.lua"); + auto lua_ftc_scan_script = to_system(working_directory / "UE4SS_Signatures/FText_Constructor.lua"); if (std::filesystem::exists(lua_ftc_scan_script)) { config.ScanOverrides.ftext_constructor = [lua_ftc_scan_script](std::vector& signature_containers, diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index b5c4c43d1..cf3378d28 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -202,7 +202,7 @@ namespace RC // Setup the log file auto& file_device = Output::set_default_devices(); - file_device.set_file_name_and_path(to_system_string(m_log_directory / m_log_file_name)); + file_device.set_file_name_and_path(to_system(m_log_directory / m_log_file_name)); create_simple_console(); @@ -210,7 +210,7 @@ namespace RC if (settings_manager.Debug.DebugConsoleEnabled) { m_console_device = &Output::set_default_devices(); - m_console_device->set_formatter([](File::StringViewType string) -> File::StringType { + m_console_device->set_formatter([](SystemStringViewType string) -> SystemStringType { return std::format(SYSSTR("[{}] {}"), std::format(SYSSTR("{:%X}"), std::chrono::system_clock::now()), string); }); if (settings_manager.Debug.DebugConsoleVisible) @@ -399,8 +399,8 @@ namespace RC { ProfilerScope(); const std::filesystem::path moduleFilePath = std::filesystem::path(moduleFilePathString); - m_root_directory = to_system_string(moduleFilePath.parent_path()); - m_module_file_path = to_system_string(moduleFilePath); + m_root_directory = to_system(moduleFilePath.parent_path()); + m_module_file_path = to_system(moduleFilePath); // The default working directory is the root directory // Can be changed by creating a directory in the root directory @@ -458,7 +458,7 @@ namespace RC } } - auto UE4SSProgram::create_emergency_console_for_early_error(File::StringViewType error_message) -> void + auto UE4SSProgram::create_emergency_console_for_early_error(SystemStringViewType error_message) -> void { settings_manager.Debug.SimpleConsoleEnabled = true; create_simple_console(); @@ -485,7 +485,7 @@ namespace RC { m_debug_console_device = &Output::set_default_devices(); Output::set_default_log_level(); - m_debug_console_device->set_formatter([](File::StringViewType string) -> File::StringType { + m_debug_console_device->set_formatter([](SystemStringViewType string) ->SystemStringType { return std::format(SYSSTR("[{}] {}"), std::format(SYSSTR("{:%X}"), std::chrono::system_clock::now()), string); }); #ifdef WIN32 @@ -1410,7 +1410,7 @@ namespace RC Output::send(SYSSTR("All mods re-installed\n")); } - auto UE4SSProgram::get_module_directory() -> File::StringViewType + auto UE4SSProgram::get_module_directory() -> SystemStringViewType { m_module_file_path_str = to_system_string(m_module_file_path); return m_module_file_path_str; @@ -1421,13 +1421,13 @@ namespace RC return m_game_executable_directory.c_str(); } - auto UE4SSProgram::get_working_directory() -> File::StringViewType + auto UE4SSProgram::get_working_directory() -> SystemStringViewType { m_working_directory_str = to_system_string(m_working_directory); return m_working_directory_str; } - auto UE4SSProgram::get_mods_directory() -> File::StringViewType + auto UE4SSProgram::get_mods_directory() -> SystemStringViewType { m_mods_directory_str = to_system_string(m_mods_directory); return m_mods_directory_str; @@ -1438,7 +1438,7 @@ namespace RC return m_legacy_root_directory.c_str(); } - auto UE4SSProgram::get_game_directory() -> File::StringViewType + auto UE4SSProgram::get_game_directory() -> SystemStringViewType { m_game_executable_str = to_system_string(m_game_executable_directory); return m_game_executable_str; @@ -1778,8 +1778,8 @@ namespace RC Output::Targets scoped_dumper_out; auto& file_device = scoped_dumper_out.get_device(); file_device.set_file_name_and_path(output_path_and_file_name); - file_device.set_formatter([](File::StringViewType string) -> File::StringType { - return File::StringType{string}; + file_device.set_formatter([](SystemStringViewType string) -> SystemStringType { + return SystemStringType{string}; }); // Make string & reserve massive amounts of space to hopefully not reach the end of the string and require more diff --git a/UVTD/include/UVTD/Helpers.hpp b/UVTD/include/UVTD/Helpers.hpp index 31c5096d0..327785576 100644 --- a/UVTD/include/UVTD/Helpers.hpp +++ b/UVTD/include/UVTD/Helpers.hpp @@ -32,7 +32,7 @@ namespace RC::UVTD struct ObjectItem { - File::StringType name{}; + UEStringType name{}; ValidForVTable valid_for_vtable{}; ValidForMemberVars valid_for_member_vars{}; }; @@ -105,7 +105,7 @@ namespace RC::UVTD {STR("FFixedUObjectArray"), ValidForVTable::No, ValidForMemberVars::Yes}, {STR("FUObjectItem"), ValidForVTable::No, ValidForMemberVars::Yes}}; - static inline std::unordered_map> s_private_variables{ + static inline std::unordered_map> s_private_variables{ {STR("FField"), { STR("ClassPrivate"), @@ -115,15 +115,15 @@ namespace RC::UVTD }}, }; - static std::unordered_set s_non_case_preserving_variants{ + static std::unordered_set s_non_case_preserving_variants{ {STR("4_27")}, }; - static std::unordered_set s_case_preserving_variants{ + static std::unordered_set s_case_preserving_variants{ {STR("4_27_CasePreserving")}, }; - static inline std::unordered_set s_valid_udt_names{STR("UScriptStruct::ICppStructOps"), + static inline std::unordered_set s_valid_udt_names{STR("UScriptStruct::ICppStructOps"), STR("UObjectBase"), STR("UObjectBaseUtility"), STR("UObject"), @@ -181,7 +181,7 @@ namespace RC::UVTD STR("USetProperty"), STR("FFrame")}; - static inline std::vector s_uprefix_to_fprefix{ + static inline std::vector s_uprefix_to_fprefix{ STR("UProperty"), STR("UMulticastDelegateProperty"), STR("UObjectPropertyBase"), @@ -206,8 +206,8 @@ namespace RC::UVTD {STR("Outer"), STR("OuterPrivate")}, }; - auto to_string_type(const char* c_str) -> File::StringType; - auto change_prefix(File::StringType input, bool is_425_plus) -> std::optional; + auto to_string_type(const char* c_str) -> UEStringType; + auto change_prefix(UEStringType input, bool is_425_plus) -> std::optional; // Workaround that lets us have a unified 'TUObjectArray' struct regardless if the engine version uses a chunked or non-chunked variant of TUObjectArray. auto unify_uobject_array_if_needed(UEStringType& out_variable_type) -> bool; diff --git a/UVTD/include/UVTD/MemberVarsDumper.hpp b/UVTD/include/UVTD/MemberVarsDumper.hpp index f6868fcf5..4637d4560 100644 --- a/UVTD/include/UVTD/MemberVarsDumper.hpp +++ b/UVTD/include/UVTD/MemberVarsDumper.hpp @@ -24,12 +24,12 @@ namespace RC::UVTD private: auto process_class(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* class_record, - const File::StringType& class_name, + const UEStringType& class_name, const SymbolNameInfo& name_info) -> void; auto process_member(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::FieldList* field_record, Class& class_entry) -> void; private: - auto dump_member_variable_layouts(std::unordered_map& names) -> void; + auto dump_member_variable_layouts(std::unordered_map& names) -> void; public: auto generate_code() -> void; diff --git a/UVTD/include/UVTD/Symbols.hpp b/UVTD/include/UVTD/Symbols.hpp index bc34b0f0b..fece2ba2d 100644 --- a/UVTD/include/UVTD/Symbols.hpp +++ b/UVTD/include/UVTD/Symbols.hpp @@ -8,6 +8,9 @@ #include +#include +#include + #include #include #include @@ -45,25 +48,25 @@ namespace RC::UVTD struct MemberVariable { - File::StringType type; - File::StringType name; + UEStringType type; + UEStringType name; int32_t offset; }; struct FunctionParam { - File::StringType type; + UEStringType type; auto to_string() const -> File::StringType { - return std::format(SYSSTR("{}"), type); + return std::format(IOSTR("{}"), to_file(type)); } }; struct MethodSignature { - File::StringType return_type; - File::StringType name; + UEStringType return_type; + UEStringType name; std::vector params; bool const_qualifier; @@ -74,16 +77,16 @@ namespace RC::UVTD for (size_t i = 0; i < params.size(); i++) { bool should_add_comma = i < params.size() - 1; - params_string.append(std::format(SYSSTR("{}{}"), params[i].to_string(), should_add_comma ? STR(", ") : STR(""))); + params_string.append(fmtfile(IOSTR("{}{}"), params[i].to_string(), should_add_comma ? IOSTR(", ") : IOSTR(""))); } - return std::format(SYSSTR("{} {}({}){};"), return_type, name, params_string, const_qualifier ? STR("const") : STR("")); + return fmtfile(IOSTR("{} {}({}){};"), return_type, name, params_string, const_qualifier ? IOSTR("const") : IOSTR("")); } }; struct MethodBody { - File::StringType name; + UEStringType name; MethodSignature signature; uint32_t offset; bool is_overload; @@ -91,11 +94,11 @@ namespace RC::UVTD struct Class { - File::StringType class_name; - File::StringType class_name_clean; + UEStringType class_name; + UEStringType class_name_clean; std::map functions; // Key: Variable name - std::map variables; + std::map variables; uint32_t last_virtual_offset{}; ValidForVTable valid_for_vtable{ValidForVTable::No}; ValidForMemberVars valid_for_member_vars{ValidForMemberVars::No}; @@ -106,24 +109,24 @@ namespace RC::UVTD public: struct MemberVariable { - File::StringType type; + UEStringType type; int32_t offset; }; struct EnumEntry { - File::StringType name; - File::StringType name_clean; - std::map variables; + UEStringType name; + UEStringType name_clean; + std::map variables; }; struct Class { - File::StringType class_name; - File::StringType class_name_clean; + UEStringType class_name; + UEStringType class_name_clean; std::map functions; // Key: Variable name - std::map variables; + std::map variables; uint32_t last_virtual_offset; ValidForVTable valid_for_vtable{ValidForVTable::No}; ValidForMemberVars valid_for_member_vars{ValidForMemberVars::No}; @@ -151,18 +154,18 @@ namespace RC::UVTD Symbols& operator=(const Symbols& other); public: - auto get_or_create_enum_entry(const File::StringType& symbol_name, const File::StringType& symbol_name_clean) -> EnumEntry&; - auto get_or_create_class_entry(const File::StringType& symbol_name, const File::StringType& symbol_name_clean, const SymbolNameInfo& name_info) -> Class&; + auto get_or_create_enum_entry(const UEStringType& symbol_name, const UEStringType& symbol_name_clean) -> EnumEntry&; + auto get_or_create_class_entry(const UEStringType& symbol_name, const UEStringType& symbol_name_clean, const SymbolNameInfo& name_info) -> Class&; - auto generate_method_signature(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* function_record, File::StringType method_name) + auto generate_method_signature(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* function_record, UEStringType method_name) -> MethodSignature; public: - auto static get_type_name(const PDB::TPIStream& tpi_stream, uint32_t record_index, bool check_valid = false) -> File::StringType; - auto static get_method_name(const PDB::CodeView::TPI::FieldList* method_record) -> File::StringType; - auto static get_leaf_name(const char* data, PDB::CodeView::TPI::TypeRecordKind kind) -> File::StringType; + auto static get_type_name(const PDB::TPIStream& tpi_stream, uint32_t record_index, bool check_valid = false) -> UEStringType; + auto static get_method_name(const PDB::CodeView::TPI::FieldList* method_record) -> UEStringType; + auto static get_leaf_name(const char* data, PDB::CodeView::TPI::TypeRecordKind kind) -> UEStringType; - auto static clean_name(File::StringType name) -> File::StringType; + auto static clean_name(UEStringType name) -> UEStringType; auto static is_virtual(PDB::CodeView::TPI::MemberAttributes attributes) -> bool; diff --git a/UVTD/include/UVTD/TemplateClassParser.hpp b/UVTD/include/UVTD/TemplateClassParser.hpp index 1e6467747..f7ccf5e6f 100644 --- a/UVTD/include/UVTD/TemplateClassParser.hpp +++ b/UVTD/include/UVTD/TemplateClassParser.hpp @@ -9,14 +9,14 @@ namespace RC::UVTD { struct ParsedTemplateClass { - File::StringType class_name; - std::vector template_args; + UEStringType class_name; + std::vector template_args; }; class TemplateClassParser { public: - static ParsedTemplateClass Parse(File::StringViewType input); + static ParsedTemplateClass Parse(UEStringViewType input); }; } // namespace RC::UVTD diff --git a/UVTD/include/UVTD/TypeContainer.hpp b/UVTD/include/UVTD/TypeContainer.hpp index 21d483ce2..1106669f1 100644 --- a/UVTD/include/UVTD/TypeContainer.hpp +++ b/UVTD/include/UVTD/TypeContainer.hpp @@ -11,7 +11,7 @@ namespace RC::UVTD class TypeContainer { private: - using ClassEntries = std::unordered_map; + using ClassEntries = std::unordered_map; ClassEntries class_entries; @@ -25,7 +25,7 @@ namespace RC::UVTD } public: - auto get_or_create_class_entry(const File::StringType& symbol_name, const File::StringType& symbol_name_clean, const SymbolNameInfo& name_info) -> Class&; + auto get_or_create_class_entry(const UEStringType& symbol_name, const UEStringType& symbol_name_clean, const SymbolNameInfo& name_info) -> Class&; }; } // namespace RC::UVTD diff --git a/UVTD/include/UVTD/UnrealVirtualGenerator.hpp b/UVTD/include/UVTD/UnrealVirtualGenerator.hpp index a6a90df91..0a7547dfe 100644 --- a/UVTD/include/UVTD/UnrealVirtualGenerator.hpp +++ b/UVTD/include/UVTD/UnrealVirtualGenerator.hpp @@ -8,13 +8,13 @@ namespace RC::UVTD class UnrealVirtualGenerator { private: - File::StringType pdb_name; + SystemStringType pdb_name; TypeContainer type_container; public: UnrealVirtualGenerator() = delete; - explicit UnrealVirtualGenerator(File::StringType pdb_name, TypeContainer container) + explicit UnrealVirtualGenerator(SystemStringType pdb_name, TypeContainer container) : pdb_name(std::move(pdb_name)), type_container(std::move(container)) { } diff --git a/UVTD/include/UVTD/VTableDumper.hpp b/UVTD/include/UVTD/VTableDumper.hpp index e4993d7b3..f0c3848c8 100644 --- a/UVTD/include/UVTD/VTableDumper.hpp +++ b/UVTD/include/UVTD/VTableDumper.hpp @@ -39,14 +39,14 @@ namespace RC::UVTD private: auto process_class(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* class_record, - const File::StringType& class_name, + const UEStringType& class_name, const SymbolNameInfo& name_info) -> void; auto process_method_overload_list(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::FieldList* method_record, Class& class_entry) -> void; auto process_onemethod(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::FieldList* onemethod_record, Class& class_entry) -> void; private: - auto dump_vtable_for_symbol(std::unordered_map& names) -> void; + auto dump_vtable_for_symbol(std::unordered_map& names) -> void; public: static auto output_cleanup() -> void; diff --git a/UVTD/src/Helpers.cpp b/UVTD/src/Helpers.cpp index aa0341644..85f60db03 100644 --- a/UVTD/src/Helpers.cpp +++ b/UVTD/src/Helpers.cpp @@ -5,26 +5,12 @@ namespace RC::UVTD { - auto to_string_type(const char* c_str) -> File::StringType + auto to_string_type(const char* c_str) -> UEStringType { -#if RC_IS_ANSI == 1 - return File::StringType(c_str); -#else - size_t count = strlen(c_str) + 1; - wchar_t* converted_method_name = new wchar_t[count]; - - size_t num_of_char_converted = 0; - mbstowcs_s(&num_of_char_converted, converted_method_name, count, c_str, count); - - auto converted = File::StringType(converted_method_name); - - delete[] converted_method_name; - - return converted; -#endif + return to_ue(c_str); } - auto change_prefix(File::StringType input, bool is_425_plus) -> std::optional + auto change_prefix(UEStringType input, bool is_425_plus) -> std::optional { for (const auto& prefixed : s_uprefix_to_fprefix) { diff --git a/UVTD/src/MemberVarsDumper.cpp b/UVTD/src/MemberVarsDumper.cpp index 4070394de..faad159c0 100644 --- a/UVTD/src/MemberVarsDumper.cpp +++ b/UVTD/src/MemberVarsDumper.cpp @@ -7,7 +7,7 @@ namespace RC::UVTD { - static inline std::vector s_types_to_not_dump{ + static inline std::vector s_types_to_not_dump{ STR("FUnversionedStructSchema"), STR("ELifetimeCondition"), STR("UAISystemBase"), @@ -110,14 +110,14 @@ namespace RC::UVTD auto MemberVarsDumper::process_class(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* class_record, - const File::StringType& name, + const UEStringType& name, const SymbolNameInfo& name_info) -> void { auto changed = change_prefix(name, symbols.is_425_plus); if (!changed.has_value()) return; - File::StringType class_name = *changed; - File::StringType class_name_clean = Symbols::clean_name(class_name); + auto class_name = *changed; + auto class_name_clean = Symbols::clean_name(class_name); auto& class_entry = type_container.get_or_create_class_entry(class_name, class_name_clean, name_info); auto fields = tpi_stream.GetTypeRecord(class_record->data.LF_CLASS.field); @@ -136,11 +136,11 @@ namespace RC::UVTD auto MemberVarsDumper::process_member(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::FieldList* field_record, Class& class_entry) -> void { - File::StringType member_name = Symbols::get_leaf_name(field_record->data.LF_STMEMBER.name, field_record->data.LF_MEMBER.lfEasy.kind); + auto member_name = Symbols::get_leaf_name(field_record->data.LF_STMEMBER.name, field_record->data.LF_MEMBER.lfEasy.kind); auto changed = change_prefix(Symbols::get_type_name(tpi_stream, field_record->data.LF_MEMBER.index), symbols.is_425_plus); if (!changed.has_value()) return; - File::StringType type_name = *changed; + auto type_name = *changed; for (const auto& type_to_not_dump : s_types_to_not_dump) { @@ -156,7 +156,7 @@ namespace RC::UVTD variable.offset = *(uint16_t*)field_record->data.LF_MEMBER.offset; } - auto MemberVarsDumper::dump_member_variable_layouts(std::unordered_map& names) -> void + auto MemberVarsDumper::dump_member_variable_layouts(std::unordered_map& names) -> void { Output::send(SYSSTR("Dumping {} symbols for {}\n"), names.size(), symbols.pdb_file_path.filename().stem().wstring()); @@ -169,7 +169,7 @@ namespace RC::UVTD { if (type_record->data.LF_CLASS.property.fwdref) continue; - const File::StringType class_name = Symbols::get_leaf_name(type_record->data.LF_CLASS.data, type_record->data.LF_CLASS.lfEasy.kind); + const SystemStringType class_name = Symbols::get_leaf_name(type_record->data.LF_CLASS.data, type_record->data.LF_CLASS.lfEasy.kind); if (!names.contains(class_name)) continue; const auto name_info = names.find(class_name); @@ -184,7 +184,7 @@ namespace RC::UVTD auto MemberVarsDumper::generate_code() -> void { - std::unordered_map member_vars_names; + std::unordered_map member_vars_names; for (ObjectItem& item : s_object_items) { @@ -197,7 +197,7 @@ namespace RC::UVTD auto MemberVarsDumper::generate_files() -> void { - File::StringType pdb_name = symbols.pdb_file_path.filename().stem(); + SystemStringType pdb_name = symbols.pdb_file_path.filename().stem(); auto default_template_file = std::filesystem::path{STR("MemberVariableLayout.ini")}; @@ -206,8 +206,8 @@ namespace RC::UVTD Output::Targets default_ini_dumper; auto& default_ini_file_device = default_ini_dumper.get_device(); default_ini_file_device.set_file_name_and_path(member_variable_layouts_templates_output_path / default_template_file); - default_ini_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + default_ini_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); auto template_file = std::format(SYSSTR("MemberVariableLayout_{}_Template.ini"), pdb_name); @@ -217,8 +217,8 @@ namespace RC::UVTD Output::Targets ini_dumper; auto& ini_file_device = ini_dumper.get_device(); ini_file_device.set_file_name_and_path(member_variable_layouts_templates_output_path / template_file); - ini_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + ini_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); auto pdb_name_no_underscore = pdb_name; @@ -232,15 +232,15 @@ namespace RC::UVTD } auto default_setter_src_file = member_variable_layouts_gen_function_bodies_path / - std::format(SYSSTR("{}_MemberVariableLayout_DefaultSetter_{}.cpp"), pdb_name, class_entry.class_name_clean); + std::format(SYSSTR("{}_MemberVariableLayout_DefaultSetter_{}.cpp"), pdb_name, to_system(class_entry.class_name_clean)); Output::send(SYSSTR("Generating file '{}'\n"), default_setter_src_file.wstring()); Output::Targets default_setter_src_dumper; auto& default_setter_src_file_device = default_setter_src_dumper.get_device(); default_setter_src_file_device.set_file_name_and_path(default_setter_src_file); - default_setter_src_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + default_setter_src_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); ini_dumper.send(STR("[{}]\n"), class_entry.class_name); @@ -251,8 +251,8 @@ namespace RC::UVTD ini_dumper.send(STR("{} = 0x{:X}\n"), variable.name, variable.offset); default_ini_dumper.send(STR("{} = -1\n"), variable.name); - File::StringType final_variable_name = variable.name; - File::StringType final_class_name = class_entry.class_name; + SystemStringType final_variable_name = variable.name; + SystemStringType final_class_name = class_entry.class_name; if (variable.name == STR("EnumFlags")) { diff --git a/UVTD/src/MemberVarsWrapperGenerator.cpp b/UVTD/src/MemberVarsWrapperGenerator.cpp index e276f3975..cb341c924 100644 --- a/UVTD/src/MemberVarsWrapperGenerator.cpp +++ b/UVTD/src/MemberVarsWrapperGenerator.cpp @@ -15,8 +15,8 @@ namespace RC::UVTD Output::Targets macro_setter_dumper; auto& macro_setter_file_device = macro_setter_dumper.get_device(); macro_setter_file_device.set_file_name_and_path(macro_setter_file); - macro_setter_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + macro_setter_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); for (const auto& [class_name, class_entry] : type_container.get_class_entries()) @@ -34,8 +34,8 @@ namespace RC::UVTD Output::Targets header_wrapper_dumper; auto& wrapper_header_file_device = header_wrapper_dumper.get_device(); wrapper_header_file_device.set_file_name_and_path(wrapper_header_file); - wrapper_header_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + wrapper_header_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); auto wrapper_src_file = @@ -46,14 +46,14 @@ namespace RC::UVTD Output::Targets wrapper_src_dumper; auto& wrapper_src_file_device = wrapper_src_dumper.get_device(); wrapper_src_file_device.set_file_name_and_path(wrapper_src_file); - wrapper_src_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + wrapper_src_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); auto final_class_name = class_entry.class_name; unify_uobject_array_if_needed(final_class_name); - header_wrapper_dumper.send(STR("static std::unordered_map MemberOffsets;\n\n")); - wrapper_src_dumper.send(STR("std::unordered_map {}::MemberOffsets{{}};\n\n"), final_class_name); + header_wrapper_dumper.send(STR("static std::unordered_map MemberOffsets;\n\n")); + wrapper_src_dumper.send(STR("std::unordered_map {}::MemberOffsets{{}};\n\n"), final_class_name); auto private_variables_for_class = s_private_variables.find(class_entry.class_name); @@ -83,8 +83,8 @@ namespace RC::UVTD bool is_private{private_variables_for_class != s_private_variables.end() && private_variables_for_class->second.find(variable.name) != private_variables_for_class->second.end()}; - File::StringType final_variable_name = variable.name; - File::StringType final_type_name = variable.type; + UEStringType final_variable_name = variable.name; + UEStringType final_type_name = variable.type; if (variable.name == STR("EnumFlags")) { diff --git a/UVTD/src/SolBindingsGenerator.cpp b/UVTD/src/SolBindingsGenerator.cpp index d869a091f..d1ac24751 100644 --- a/UVTD/src/SolBindingsGenerator.cpp +++ b/UVTD/src/SolBindingsGenerator.cpp @@ -26,19 +26,19 @@ namespace RC::UVTD auto final_class_name = class_name; - auto wrapper_header_file = sol_bindings_output_path / std::format(SYSSTR("SolBindings_{}.hpp"), final_class_name_clean); + auto wrapper_header_file = sol_bindings_output_path / std::format(SYSSTR("SolBindings_{}.hpp"), to_system(final_class_name_clean)); - Output::send(SYSSTR("Generating file '{}'\n"), wrapper_header_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), wrapper_header_file); Output::Targets header_wrapper_dumper; auto& wrapper_header_file_device = header_wrapper_dumper.get_device(); wrapper_header_file_device.set_file_name_and_path(wrapper_header_file); - wrapper_header_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + wrapper_header_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); - header_wrapper_dumper.send(STR("auto sol_class_{} = sol().new_usertype<{}>(\"{}\""), final_class_name, final_class_name, final_class_name); + header_wrapper_dumper.send(SYSSTR("auto sol_class_{} = sol().new_usertype<{}>(\"{}\""), final_class_name, final_class_name, final_class_name); for (const auto& [variable_name, variable] : class_entry.variables) { @@ -67,7 +67,7 @@ namespace RC::UVTD continue; } - File::StringType final_variable_name = variable.name; + UEStringType final_variable_name = variable.name; if (variable.name == STR("EnumFlags")) { diff --git a/UVTD/src/Symbols.cpp b/UVTD/src/Symbols.cpp index 67b6a3722..c9c320767 100644 --- a/UVTD/src/Symbols.cpp +++ b/UVTD/src/Symbols.cpp @@ -56,7 +56,7 @@ namespace RC::UVTD return *this; } - auto Symbols::generate_method_signature(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* function_record, File::StringType method_name) + auto Symbols::generate_method_signature(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* function_record, SystemStringType method_name) -> MethodSignature { MethodSignature signature{}; @@ -81,7 +81,7 @@ namespace RC::UVTD return signature; } - auto Symbols::get_type_name(const PDB::TPIStream& tpi_stream, uint32_t record_index, bool check_valid) -> File::StringType + auto Symbols::get_type_name(const PDB::TPIStream& tpi_stream, uint32_t record_index, bool check_valid) -> UEStringType { if (record_index < tpi_stream.GetFirstTypeIndex()) { @@ -214,7 +214,7 @@ namespace RC::UVTD { case PDB::CodeView::TPI::TypeRecordKind::LF_CLASS: case PDB::CodeView::TPI::TypeRecordKind::LF_STRUCTURE: { - File::StringType name = get_leaf_name(record->data.LF_CLASS.data, record->data.LF_CLASS.lfEasy.kind); + UEStringType name = get_leaf_name(record->data.LF_CLASS.data, record->data.LF_CLASS.lfEasy.kind); ParsedTemplateClass parsed = TemplateClassParser::Parse(name); if (parsed.class_name == STR("TMap")) @@ -228,11 +228,11 @@ namespace RC::UVTD return to_string_type(record->data.LF_ENUM.name); case PDB::CodeView::TPI::TypeRecordKind::LF_MODIFIER: { const auto modifier_attr = record->data.LF_MODIFIER.attr; - std::vector modifiers{}; + std::vector modifiers{}; if (modifier_attr.MOD_volatile) modifiers.push_back(STR("volatile")); - File::StringType modifier_string{}; + UEStringType modifier_string{}; for (const auto& modifier : modifiers) { modifier_string += modifier + STR(" "); @@ -244,17 +244,18 @@ namespace RC::UVTD return get_type_name(tpi_stream, record->data.LF_POINTER.utype, check_valid) + STR("*"); case PDB::CodeView::TPI::TypeRecordKind::LF_MFUNCTION: case PDB::CodeView::TPI::TypeRecordKind::LF_PROCEDURE: { - File::StringType return_type = get_type_name(tpi_stream, record->data.LF_PROCEDURE.rvtype, true); - File::StringType args = get_type_name(tpi_stream, record->data.LF_PROCEDURE.arglist, check_valid); + UEStringType return_type = get_type_name(tpi_stream, record->data.LF_PROCEDURE.rvtype, true); + UEStringType args = get_type_name(tpi_stream, record->data.LF_PROCEDURE.arglist, check_valid); return std::format(SYSSTR("std::function<{}({})>"), return_type, args); } case PDB::CodeView::TPI::TypeRecordKind::LF_ARGLIST: { - File::StringType args{}; + UEStringType args{}; for (size_t i = 0; i < record->data.LF_ARGLIST.count; i++) { bool should_add_comma = i < record->data.LF_ARGLIST.count - 1; - args.append(std::format(SYSSTR("{}{}"), get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true), should_add_comma ? STR(", ") : STR(""))); + //args.append(std::format(SYSSTR("{}{}"), get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true), should_add_comma ? STR(", ") : STR(""))); + args.append(get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true) + (should_add_comma ? STR(", ") : STR(""))); } return args; @@ -267,7 +268,7 @@ namespace RC::UVTD } } - auto Symbols::get_method_name(const PDB::CodeView::TPI::FieldList* method_record) -> File::StringType + auto Symbols::get_method_name(const PDB::CodeView::TPI::FieldList* method_record) -> UEStringType { auto methodAttributes = static_cast(method_record->data.LF_ONEMETHOD.attributes.mprop); switch (methodAttributes) @@ -311,7 +312,7 @@ namespace RC::UVTD return 0; } - auto Symbols::get_leaf_name(const char* data, PDB::CodeView::TPI::TypeRecordKind kind) -> File::StringType + auto Symbols::get_leaf_name(const char* data, PDB::CodeView::TPI::TypeRecordKind kind) -> UEStringType { auto name = to_string_type(&data[get_leaf_size(kind)]); if (auto it = s_member_rename_map.find(name); it != s_member_rename_map.end()) @@ -324,7 +325,7 @@ namespace RC::UVTD } } - auto Symbols::clean_name(File::StringType name) -> File::StringType + auto Symbols::clean_name(UEStringType name) -> UEStringType { std::replace(name.begin(), name.end(), ':', '_'); std::replace(name.begin(), name.end(), '~', '$'); diff --git a/UVTD/src/TemplateClassParser.cpp b/UVTD/src/TemplateClassParser.cpp index f69004ccd..49f966fac 100644 --- a/UVTD/src/TemplateClassParser.cpp +++ b/UVTD/src/TemplateClassParser.cpp @@ -2,22 +2,22 @@ namespace RC::UVTD { - ParsedTemplateClass TemplateClassParser::Parse(File::StringViewType input) + ParsedTemplateClass TemplateClassParser::Parse(UEStringViewType input) { ParsedTemplateClass parsed{}; - for (const File::StringType::value_type character : input) + for (const UEStringType::value_type character : input) { if (character == STR('<')) break; parsed.class_name += character; } size_t nesting_level = 0; - File::StringType current_param{}; + UEStringType current_param{}; for (size_t i = parsed.class_name.size(); i < input.size(); i++) { - const File::StringType::value_type character = input[i]; + const UEStringType::value_type character = input[i]; bool is_nesting_character = false; if (character == STR('>') && nesting_level == 1) break; diff --git a/UVTD/src/TypeContainer.cpp b/UVTD/src/TypeContainer.cpp index 772aeceb5..242fc762e 100644 --- a/UVTD/src/TypeContainer.cpp +++ b/UVTD/src/TypeContainer.cpp @@ -21,7 +21,7 @@ namespace RC::UVTD } } - auto TypeContainer::get_or_create_class_entry(const File::StringType& symbol_name, const File::StringType& symbol_name_clean, const SymbolNameInfo& name_info) + auto TypeContainer::get_or_create_class_entry(const UEStringType& symbol_name, const UEStringType& symbol_name_clean, const SymbolNameInfo& name_info) -> Class& { auto& class_entry = [&]() -> auto& @@ -32,7 +32,7 @@ namespace RC::UVTD } else { - return class_entries.emplace(symbol_name_clean, Class{.class_name = File::StringType{symbol_name}, .class_name_clean = symbol_name_clean}) + return class_entries.emplace(symbol_name_clean, Class{.class_name = UEStringType{symbol_name}, .class_name_clean = symbol_name_clean}) .first->second; } } diff --git a/UVTD/src/UVTD.cpp b/UVTD/src/UVTD.cpp index e53c5fe78..13853ae80 100644 --- a/UVTD/src/UVTD.cpp +++ b/UVTD/src/UVTD.cpp @@ -111,7 +111,7 @@ namespace RC::UVTD generator.generate_files(); } - File::StringType pdb_name = pdb.filename().stem(); + SystemStringType pdb_name = pdb.filename().stem(); UnrealVirtualGenerator virtual_generator(pdb_name, run_container); virtual_generator.generate_files(); diff --git a/UVTD/src/UnrealVirtualGenerator.cpp b/UVTD/src/UnrealVirtualGenerator.cpp index 979c45eab..ad38042b7 100644 --- a/UVTD/src/UnrealVirtualGenerator.cpp +++ b/UVTD/src/UnrealVirtualGenerator.cpp @@ -17,19 +17,19 @@ namespace RC::UVTD Output::Targets virtual_header_dumper; auto& virtual_header_file_device = virtual_header_dumper.get_device(); virtual_header_file_device.set_file_name_and_path(virtual_header_file); - virtual_header_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + virtual_header_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); auto virtual_src_file = virtual_gen_function_bodies_path / std::format(SYSSTR("UnrealVirtual{}.cpp"), pdb_name_no_underscore); - Output::send(SYSSTR("Generating file '{}'\n"), virtual_src_file.wstring()); + Output::send(SYSSTR("Generating file '{}'\n"), virtual_src_file); Output::Targets virtual_src_dumper; auto& virtual_src_file_device = virtual_src_dumper.get_device(); virtual_src_file_device.set_file_name_and_path(virtual_src_file); - virtual_src_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + virtual_src_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); bool is_case_preserving_pdb = !(s_case_preserving_variants.find(pdb_name) == s_case_preserving_variants.end()); @@ -37,77 +37,77 @@ namespace RC::UVTD if (!is_case_preserving_pdb) { - virtual_header_dumper.send(STR("#ifndef RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); - virtual_header_dumper.send(STR("#define RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); - virtual_header_dumper.send(STR("#include \n\n")); - virtual_header_dumper.send(STR("namespace RC::Unreal\n")); - virtual_header_dumper.send(STR("{\n")); - virtual_header_dumper.send(STR(" class UnrealVirtual{} : public UnrealVirtualBaseVC\n"), pdb_name_no_underscore); - virtual_header_dumper.send(STR(" {\n")); - virtual_header_dumper.send(STR(" auto set_virtual_offsets() -> void override;\n")); - virtual_header_dumper.send(STR(" };\n")); - virtual_header_dumper.send(STR("}\n\n\n")); - virtual_header_dumper.send(STR("#endif //RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); - - virtual_src_dumper.send(STR("#include \n\n"), pdb_name_no_underscore); - virtual_src_dumper.send(STR("#include \n\n")); - virtual_src_dumper.send(STR("// These are all the structs that have virtuals that need to have their offset set\n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("#include \n")); - // virtual_src_dumper.send(STR("#include \n")); - virtual_src_dumper.send(STR("\n")); - virtual_src_dumper.send(STR("namespace RC::Unreal\n")); - virtual_src_dumper.send(STR("{\n")); - virtual_src_dumper.send(STR(" void UnrealVirtual{}::set_virtual_offsets()\n"), pdb_name_no_underscore); - virtual_src_dumper.send(STR(" {\n")); + virtual_header_dumper.send(SYSSTR("#ifndef RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); + virtual_header_dumper.send(SYSSTR("#define RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); + virtual_header_dumper.send(SYSSTR("#include \n\n")); + virtual_header_dumper.send(SYSSTR("namespace RC::Unreal\n")); + virtual_header_dumper.send(SYSSTR("{\n")); + virtual_header_dumper.send(SYSSTR(" class UnrealVirtual{} : public UnrealVirtualBaseVC\n"), pdb_name_no_underscore); + virtual_header_dumper.send(SYSSTR(" {\n")); + virtual_header_dumper.send(SYSSTR(" auto set_virtual_offsets() -> void override;\n")); + virtual_header_dumper.send(SYSSTR(" };\n")); + virtual_header_dumper.send(SYSSTR("}\n\n\n")); + virtual_header_dumper.send(SYSSTR("#endif //RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); + + virtual_src_dumper.send(SYSSTR("#include \n\n"), pdb_name_no_underscore); + virtual_src_dumper.send(SYSSTR("#include \n\n")); + virtual_src_dumper.send(SYSSTR("// These are all the structs that have virtuals that need to have their offset set\n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("#include \n")); + // virtual_src_dumper.send(SYSSTR("#include \n")); + virtual_src_dumper.send(SYSSTR("\n")); + virtual_src_dumper.send(SYSSTR("namespace RC::Unreal\n")); + virtual_src_dumper.send(SYSSTR("{\n")); + virtual_src_dumper.send(SYSSTR(" void UnrealVirtual{}::set_virtual_offsets()\n"), pdb_name_no_underscore); + virtual_src_dumper.send(SYSSTR(" {\n")); } for (const auto& [class_name, class_entry] : type_container.get_class_entries()) { if (!class_entry.functions.empty() && class_entry.valid_for_vtable == ValidForVTable::Yes && !is_case_preserving_pdb) { - virtual_src_dumper.send(STR("#include \n"), pdb_name, class_name); + virtual_src_dumper.send(SYSSTR("#include \n"), pdb_name, class_name); } } if (!is_case_preserving_pdb) { - virtual_src_dumper.send(STR("\n")); + virtual_src_dumper.send(SYSSTR("\n")); // Second & third passes just to separate VTable includes and MemberOffsets includes. if (is_non_case_preserving_pdb) { - virtual_src_dumper.send(STR("#ifdef WITH_CASE_PRESERVING_NAME\n")); + virtual_src_dumper.send(SYSSTR("#ifdef WITH_CASE_PRESERVING_NAME\n")); for (const auto& [class_name, class_entry] : type_container.get_class_entries()) { if (class_entry.variables.empty()) @@ -117,7 +117,9 @@ namespace RC::UVTD if (class_entry.valid_for_member_vars == ValidForMemberVars::Yes) { - virtual_src_dumper.send(STR("#include \n"), pdb_name, class_name); + virtual_src_dumper.send(SYSSTR("#include \n"), + pdb_name, + class_name); } } virtual_src_dumper.send(STR("#else\n")); diff --git a/UVTD/src/VTableDumper.cpp b/UVTD/src/VTableDumper.cpp index 0cdc54cf0..1e060ac2d 100644 --- a/UVTD/src/VTableDumper.cpp +++ b/UVTD/src/VTableDumper.cpp @@ -25,14 +25,14 @@ namespace RC::UVTD { auto VTableDumper::process_class(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::Record* class_record, - const File::StringType& name, + const UEStringType& name, const SymbolNameInfo& name_info) -> void { auto changed = change_prefix(name, symbols.is_425_plus); if (!changed.has_value()) return; - File::StringType class_name = *changed; - File::StringType class_name_clean = Symbols::clean_name(class_name); + UEStringType class_name = *changed; + UEStringType class_name_clean = Symbols::clean_name(class_name); auto& class_entry = type_container.get_or_create_class_entry(class_name, class_name_clean, name_info); @@ -65,8 +65,8 @@ namespace RC::UVTD { auto list = tpi_stream.GetTypeRecord(method_record->data.LF_METHOD.mList); - File::StringType method_name = Symbols::get_method_name(method_record); - File::StringType method_name_clean = Symbols::clean_name(method_name); + UEStringType method_name = Symbols::get_method_name(method_record); + UEStringType method_name_clean = Symbols::clean_name(method_name); // this is required because METHOD struct size is not constant :) size_t next_offset = 0; @@ -87,7 +87,7 @@ namespace RC::UVTD if (!Symbols::is_virtual(overload_record->METHOD.attributes)) continue; if (!function_record || function_record->header.kind != PDB::CodeView::TPI::TypeRecordKind::LF_MFUNCTION) continue; - File::StringType overload_name = method_name_clean; + UEStringType overload_name = method_name_clean; if (overload_index != 0) { overload_name += std::format(SYSSTR("_{}"), overload_index); @@ -104,13 +104,13 @@ namespace RC::UVTD auto VTableDumper::process_onemethod(const PDB::TPIStream& tpi_stream, const PDB::CodeView::TPI::FieldList* method_record, Class& class_entry) -> void { - static std::unordered_map> functions_already_dumped{}; + static std::unordered_map> functions_already_dumped{}; const auto is_virtual = method_record->data.LF_ONEMETHOD.attributes.mprop == (uint16_t)PDB::CodeView::TPI::MethodProperty::Intro || method_record->data.LF_ONEMETHOD.attributes.mprop == (uint16_t)PDB::CodeView::TPI::MethodProperty::PureIntro; if (!is_virtual) return; - File::StringType method_name = Symbols::get_method_name(method_record); + UEStringType method_name = Symbols::get_method_name(method_record); int32_t vtable_offset = method_record->data.LF_ONEMETHOD.vbaseoff[0]; auto function_record = tpi_stream.GetTypeRecord(method_record->data.LF_ONEMETHOD.index); @@ -127,7 +127,7 @@ namespace RC::UVTD Output::send(SYSSTR(" method {} offset {}\n"), method_name, vtable_offset); - File::StringType method_name_clean = Symbols::clean_name(method_name); + UEStringType method_name_clean = Symbols::clean_name(method_name); auto& function = class_entry.functions[vtable_offset]; function.name = method_name_clean; @@ -137,7 +137,7 @@ namespace RC::UVTD functions_already_dumped.emplace(method_name, 1); } - auto VTableDumper::dump_vtable_for_symbol(std::unordered_map& names) -> void + auto VTableDumper::dump_vtable_for_symbol(std::unordered_map& names) -> void { Output::send(SYSSTR("Dumping {} struct symbols for {}\n"), names.size(), symbols.pdb_file_path.filename().stem().wstring()); @@ -150,7 +150,7 @@ namespace RC::UVTD { if (type_record->data.LF_CLASS.property.fwdref) continue; - const File::StringType class_name = Symbols::get_leaf_name(type_record->data.LF_CLASS.data, type_record->data.LF_CLASS.lfEasy.kind); + const UEStringType class_name = Symbols::get_leaf_name(type_record->data.LF_CLASS.data, type_record->data.LF_CLASS.lfEasy.kind); if (!names.contains(class_name)) continue; const auto name_info = names.find(class_name); @@ -164,7 +164,7 @@ namespace RC::UVTD auto VTableDumper::generate_code() -> void { - std::unordered_map vtable_names; + std::unordered_map vtable_names; for (const auto& object_item : s_object_items) { if (object_item.valid_for_vtable != ValidForVTable::Yes) continue; @@ -177,7 +177,7 @@ namespace RC::UVTD auto VTableDumper::generate_files() -> void { - File::StringType pdb_name = symbols.pdb_file_path.filename().stem(); + UEStringType pdb_name = symbols.pdb_file_path.filename().stem(); for (const auto& [class_name, class_entry] : type_container.get_class_entries()) { @@ -186,8 +186,8 @@ namespace RC::UVTD auto& function_body_file_device = function_body_dumper.get_device(); function_body_file_device.set_file_name_and_path(vtable_gen_output_function_bodies_path / std::format(SYSSTR("{}_VTableOffsets_{}_FunctionBody.cpp"), pdb_name, class_name)); - function_body_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + function_body_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); for (const auto& [function_index, function_entry] : class_entry.functions) @@ -198,13 +198,13 @@ namespace RC::UVTD local_class_name.replace(0, 1, STR("F")); } - function_body_dumper.send(STR("if (auto it = {}::VTableLayoutMap.find(STR(\"{}\")); it == {}::VTableLayoutMap.end())\n"), + function_body_dumper.send(SYSSTR("if (auto it = {}::VTableLayoutMap.find(STR(\"{}\")); it == {}::VTableLayoutMap.end())\n"), local_class_name, function_entry.name, local_class_name); - function_body_dumper.send(STR("{\n")); - function_body_dumper.send(STR(" {}::VTableLayoutMap.emplace(STR(\"{}\"), 0x{:X});\n"), local_class_name, function_entry.name, function_entry.offset); - function_body_dumper.send(STR("}\n\n")); + function_body_dumper.send(SYSSTR("{\n")); + function_body_dumper.send(SYSSTR(" {}::VTableLayoutMap.emplace(STR(\"{}\"), 0x{:X});\n"), local_class_name, function_entry.name, function_entry.offset); + function_body_dumper.send(SYSSTR("}\n\n")); } } @@ -213,24 +213,24 @@ namespace RC::UVTD Output::Targets ini_dumper; auto& ini_file_device = ini_dumper.get_device(); ini_file_device.set_file_name_and_path(vtable_templates_output_path / template_file); - ini_file_device.set_formatter([](File::StringViewType string) { - return File::StringType{string}; + ini_file_device.set_formatter([](SystemStringViewType string) { + return SystemStringType{string}; }); for (const auto& [class_name, class_entry] : type_container.get_class_entries()) { - ini_dumper.send(STR("[{}]\n"), class_entry.class_name); + ini_dumper.send(SYSSTR("[{}]\n"), class_entry.class_name); for (const auto& [function_index, function_entry] : class_entry.functions) { if (function_entry.is_overload) { - ini_dumper.send(STR("; {}\n"), function_entry.signature.to_string()); + ini_dumper.send(SYSSTR("; {}\n"), function_entry.signature.to_string()); } - ini_dumper.send(STR("{}\n"), function_entry.name); + ini_dumper.send(SYSSTR("{}\n"), function_entry.name); } - ini_dumper.send(STR("\n")); + ini_dumper.send(SYSSTR("\n")); } } diff --git a/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp index ff5c57191..4538c9904 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/DebugConsoleDevice.hpp @@ -35,8 +35,8 @@ namespace RC::Output public: auto has_optional_arg() const -> bool override; - auto receive(File::StringViewType fmt) const -> void override; - auto receive_with_optional_arg(File::StringViewType fmt, int32_t optional_arg = 0) const -> void override; + auto receive(SystemStringViewType fmt) const -> void override; + auto receive_with_optional_arg(SystemStringViewType fmt, int32_t optional_arg = 0) const -> void override; }; } // namespace RC::Output diff --git a/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp index 28b2d3bb2..e0f017d07 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp @@ -72,7 +72,7 @@ namespace RC::Output // Due to the design of the Output system the opening of the file is done in receive instead of in the constructor // It's opened only once and stays open until the Output object (not the device) leaves scope // The destructor is responsible for closing the file - auto receive(File::StringViewType fmt) const -> void override + auto receive(SystemStringViewType fmt) const -> void override { if (!m_is_device_ready) { @@ -86,7 +86,7 @@ namespace RC::Output } // OutputDevice Interface -> END - auto set_file_name_and_path(const File::StringType& file_name_and_path) -> void + auto set_file_name_and_path(const SystemStringType& file_name_and_path) -> void { m_file_name_and_path = file_name_and_path; } diff --git a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp index b3633fa30..59a52419a 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp @@ -118,7 +118,7 @@ namespace RC::Output }; template - auto send(File::StringViewType content, OptionalArg optional_arg) -> void + auto send(SystemStringViewType content, OptionalArg optional_arg) -> void { if (m_opened_devices.empty()) { @@ -141,14 +141,14 @@ namespace RC::Output } template - auto send(File::StringViewType&& content, FmtArgs&&... fmt_args) -> void + auto send(SystemStringViewType&& content, FmtArgs&&... fmt_args) -> void { if (m_opened_devices.empty()) { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } - auto formated = std::vformat(std::forward(content), RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + auto formated = std::vformat(std::forward(content), RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); for (const auto& device : m_opened_devices) { @@ -166,14 +166,14 @@ namespace RC::Output } template - auto send(File::StringViewType content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void + auto send(SystemStringViewType content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void { if (m_opened_devices.empty()) { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); for (const auto& device : m_opened_devices) { @@ -189,7 +189,7 @@ namespace RC::Output } } - auto send(const File::StringType& content) -> void + auto send(const SystemStringType& content) -> void { if (m_opened_devices.empty()) { @@ -212,14 +212,14 @@ namespace RC::Output } template - auto send(File::StringViewType content, FmtArg&& fmt_arg, FmtArgs&&... fmt_args) -> void + auto send(SystemStringViewType content, FmtArg&& fmt_arg, FmtArgs&&... fmt_args) -> void { if (m_opened_devices.empty()) { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_arg), std::forward(fmt_args))...)); + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_arg), std::forward(fmt_args))...)); for (const auto& device : m_opened_devices) { @@ -236,7 +236,7 @@ namespace RC::Output } template - auto send(const File::StringType& content) -> void + auto send(const SystemStringType& content) -> void { if (m_opened_devices.empty()) { @@ -294,9 +294,9 @@ namespace RC::Output } template - auto send(File::StringViewType content, FmtArgs&&... fmt_args) -> void + auto send(SystemStringViewType content, FmtArgs&&... fmt_args) -> void { - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) @@ -313,9 +313,9 @@ namespace RC::Output } template - auto send(File::StringViewType content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void + auto send(SystemStringViewType content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void { - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) @@ -331,10 +331,10 @@ namespace RC::Output } } - auto RC_DYNOUT_API send(File::StringViewType content) -> void; + auto RC_DYNOUT_API send(SystemStringViewType content) -> void; template - auto send(File::StringViewType content, OptionalArg optional_arg) -> void + auto send(SystemStringViewType content, OptionalArg optional_arg) -> void { for (const auto& device : DefaultTargets::get_default_devices_ref()) { @@ -352,9 +352,9 @@ namespace RC::Output } template - auto send(File::StringViewType content, FmtArgs&&... fmt_args) -> void + auto send(SystemStringViewType content, FmtArgs&&... fmt_args) -> void { - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_file(std::forward(fmt_args))...)); + auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) @@ -371,7 +371,7 @@ namespace RC::Output } template - auto send(File::StringViewType content) -> void + auto send(SystemStringViewType content) -> void { for (const auto& device : DefaultTargets::get_default_devices_ref()) { diff --git a/deps/first/DynamicOutput/include/DynamicOutput/OutputDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/OutputDevice.hpp index c7d65d6b0..5c69f46ba 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/OutputDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/OutputDevice.hpp @@ -46,7 +46,7 @@ namespace RC::Output mutable bool m_is_device_ready{}; // Formatter function - using Formatter = File::StringType (*)(File::StringViewType); + using Formatter = SystemStringType (*)(SystemStringViewType); Formatter m_formatter{&default_format_string}; public: @@ -55,10 +55,10 @@ namespace RC::Output public: virtual auto has_optional_arg() const -> bool; - virtual auto receive(File::StringViewType fmt) const -> void = 0; + virtual auto receive(SystemStringViewType fmt) const -> void = 0; // The 'optional_arg' type should be cast to the proper enum by the derived class - virtual auto receive_with_optional_arg(File::StringViewType fmt, int32_t optional_arg = 0) const -> void; + virtual auto receive_with_optional_arg(SystemStringViewType fmt, int32_t optional_arg = 0) const -> void; virtual auto lock() const -> void{}; @@ -68,8 +68,8 @@ namespace RC::Output auto set_formatter(Formatter new_formatter) -> void; protected: - auto static get_now_as_string() -> const File::StringType; - auto static default_format_string(File::StringViewType) -> File::StringType; + auto static get_now_as_string() -> const SystemStringType; + auto static default_format_string(SystemStringViewType) -> SystemStringType; }; } // namespace RC::Output diff --git a/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp index 48c6249cf..c10b6fd9b 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp @@ -38,12 +38,12 @@ namespace RC::Output return true; } - auto receive(File::StringViewType fmt) const -> void override + auto receive(SystemStringViewType fmt) const -> void override { receive_with_optional_arg(fmt, 0); } - auto receive_with_optional_arg(File::StringViewType fmt, int32_t optional_arg) const -> void override + auto receive_with_optional_arg(SystemStringViewType fmt, int32_t optional_arg) const -> void override { OptionalArgTest typed_optional_arg = static_cast(optional_arg); switch (typed_optional_arg) diff --git a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp index a7864f557..5ac4b8471 100644 --- a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp +++ b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp @@ -62,12 +62,12 @@ namespace RC::Output return true; } - auto DebugConsoleDevice::receive(File::StringViewType fmt) const -> void + auto DebugConsoleDevice::receive(SystemStringViewType fmt) const -> void { receive_with_optional_arg(fmt, Color::NoColor); } - auto DebugConsoleDevice::receive_with_optional_arg(File::StringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void + auto DebugConsoleDevice::receive_with_optional_arg(SystemStringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void { #ifdef WIN32 set_windows_console_out_mode_if_needed(); diff --git a/deps/first/DynamicOutput/src/Output.cpp b/deps/first/DynamicOutput/src/Output.cpp index 1c6d7a73b..d2e2c9732 100644 --- a/deps/first/DynamicOutput/src/Output.cpp +++ b/deps/first/DynamicOutput/src/Output.cpp @@ -28,7 +28,7 @@ namespace RC::Output default_devices.clear(); } - auto send(File::StringViewType content) -> void + auto send(SystemStringViewType content) -> void { for (const auto& device : DefaultTargets::get_default_devices_ref()) { diff --git a/deps/first/DynamicOutput/src/OutputDevice.cpp b/deps/first/DynamicOutput/src/OutputDevice.cpp index e7bae076e..df93faab6 100644 --- a/deps/first/DynamicOutput/src/OutputDevice.cpp +++ b/deps/first/DynamicOutput/src/OutputDevice.cpp @@ -10,7 +10,7 @@ namespace RC::Output return false; } - auto OutputDevice::receive_with_optional_arg([[maybe_unused]] File::StringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void + auto OutputDevice::receive_with_optional_arg([[maybe_unused]] SystemStringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void { // This only exists to make it not required to implement // Most devices probably won't use this @@ -22,14 +22,14 @@ namespace RC::Output m_formatter = new_formatter; } - auto OutputDevice::get_now_as_string() -> const File::StringType + auto OutputDevice::get_now_as_string() -> const SystemStringType { auto now = std::chrono::system_clock::now(); - const File::StringType when_as_string = std::format(SYSSTR("{:%Y-%m-%d %X}"), now); + const SystemStringType when_as_string = std::format(SYSSTR("{:%Y-%m-%d %X}"), now); return when_as_string; } - auto OutputDevice::default_format_string(File::StringViewType string_to_format) -> File::StringType + auto OutputDevice::default_format_string(SystemStringViewType string_to_format) -> SystemStringType { return std::format(SYSSTR("[{}] {}"), get_now_as_string(), string_to_format); } diff --git a/deps/first/File/include/File/FileType/FileBase.hpp b/deps/first/File/include/File/FileType/FileBase.hpp index b648c3695..09568f101 100644 --- a/deps/first/File/include/File/FileType/FileBase.hpp +++ b/deps/first/File/include/File/FileType/FileBase.hpp @@ -74,7 +74,8 @@ namespace RC::File // Write a string to the currently opened file // Throws std::runtime_error if an error occurred - virtual auto write_string_to_file(StringViewType) -> void = 0; + // Keep this function use UEStringViewType so it's wstring_view and compatible with old FileInterface + virtual auto write_string_to_file(UEStringViewType) -> void = 0; // Returns whether the currently opened file is the same as another opened file // Throws std::runtime_error if an error occurred @@ -82,7 +83,8 @@ namespace RC::File // Returns the entire contents of the currently opened file as a string // Throws std::runtime_error if an error occurred - virtual auto read_all() const -> StringType = 0; + // Keep this function use UEStringViewType so it's wstring_view and compatible with old FileInterface + virtual auto read_all() const -> UEStringType = 0; virtual auto memory_map() -> std::span = 0; @@ -91,6 +93,17 @@ namespace RC::File // Throws std::runtime_error if an error occurred auto static open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> InternalFileType; */ + + + // Write a string to the currently opened file + // Throws std::runtime_error if an error occurred + // This is the actual function uses StringType. + virtual auto write_file_string_to_file(StringViewType) -> void = 0; + + // Returns the entire contents of the currently opened file as a string + // Throws std::runtime_error if an error occurred + // This is the actual function uses StringType. + virtual auto read_file_all() const -> StringType = 0; }; template diff --git a/deps/first/File/include/File/FileType/StdFile.hpp b/deps/first/File/include/File/FileType/StdFile.hpp index a4282998d..bf9343df4 100644 --- a/deps/first/File/include/File/FileType/StdFile.hpp +++ b/deps/first/File/include/File/FileType/StdFile.hpp @@ -71,11 +71,14 @@ namespace RC::File RC_FILE_API auto serialize_item(const GenericItemData& data, bool is_internal_item = false) -> void override; RC_FILE_API auto get_serialized_item(size_t data_size, bool is_internal_item = false) -> void* override; RC_FILE_API auto close_current_file() -> void override; - RC_FILE_API auto write_string_to_file(StringViewType string_to_write) -> void override; + RC_FILE_API auto write_string_to_file(UEStringViewType string_to_write) -> void override; RC_FILE_API auto is_same_as(StdFile& other_file) -> bool override; - [[nodiscard]] RC_FILE_API auto read_all() const -> StringType override; + [[nodiscard]] RC_FILE_API auto read_all() const -> UEStringType override; [[nodiscard]] RC_FILE_API auto memory_map() -> std::span override; [[nodiscard]] RC_FILE_API auto static open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> StdFile; + + [[nodiscard]] RC_FILE_API auto read_file_all() const -> SystemStringType override; + RC_FILE_API auto auto write_file_string_to_file(StringViewType) -> void override; // File Interface -> END }; diff --git a/deps/first/File/include/File/FileType/WinFile.hpp b/deps/first/File/include/File/FileType/WinFile.hpp index 4c630dcb9..89d075330 100644 --- a/deps/first/File/include/File/FileType/WinFile.hpp +++ b/deps/first/File/include/File/FileType/WinFile.hpp @@ -75,11 +75,13 @@ namespace RC::File RC_FILE_API auto serialize_item(const GenericItemData& data, bool is_internal_item = false) -> void override; RC_FILE_API auto get_serialized_item(size_t data_size, bool is_internal_item = false) -> void* override; RC_FILE_API auto close_current_file() -> void override; - RC_FILE_API auto write_string_to_file(StringViewType string_to_write) -> void override; + RC_FILE_API auto write_string_to_file(UEStringViewType string_to_write) -> void override; + RC_FILE_API auto write_file_string_to_file(StringViewType string_to_write) -> void override; RC_FILE_API auto is_same_as(WinFile& other_file) -> bool override; - [[nodiscard]] RC_FILE_API auto read_all() const -> StringType override; + [[nodiscard]] RC_FILE_API auto read_all() const -> UEStringType override; [[nodiscard]] RC_FILE_API auto memory_map() -> std::span override; [[nodiscard]] RC_FILE_API auto static open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> WinFile; + [[nodiscard]] RC_FILE_API auto read_file_all() const -> StringType override; // File Interface -> END }; diff --git a/deps/first/File/include/File/HandleTemplate.hpp b/deps/first/File/include/File/HandleTemplate.hpp index 9cebc64a5..388a92194 100644 --- a/deps/first/File/include/File/HandleTemplate.hpp +++ b/deps/first/File/include/File/HandleTemplate.hpp @@ -159,16 +159,26 @@ namespace RC::File return *data; } - auto write_string_to_file(StringViewType string_to_write) -> void + auto write_string_to_file(UEStringViewType string_to_write) -> void { m_internal_handle.write_string_to_file(string_to_write); } - [[nodiscard]] auto read_all() const -> StringType + auto write_file_string_to_file(StringViewType string_to_write) -> void + { + m_internal_handle.write_file_string_to_file(string_to_write); + } + + [[nodiscard]] auto read_all() const -> UEStringType { return m_internal_handle.read_all(); } + [[nodiscard]] auto read_file_all() const -> StringType + { + return m_internal_handle.read_file_all(); + } + [[nodiscard]] auto memory_map() -> std::span { return m_internal_handle.memory_map(); diff --git a/deps/first/File/include/File/Macros.hpp b/deps/first/File/include/File/Macros.hpp index 1a87c683c..16499700c 100644 --- a/deps/first/File/include/File/Macros.hpp +++ b/deps/first/File/include/File/Macros.hpp @@ -16,7 +16,7 @@ #else #if RC_IS_ANSI == 0 #define SYSSTR(str) L##str -#define IOSTR(str) L##str +#define IOSTR(str) str #define STR(str) L##str #else #define SYSSTR(str) str @@ -47,9 +47,13 @@ construct a Targets object and supply your own devices.") \ namespace RC::File { - typedef std::basic_ofstream u16ofstream; - typedef std::basic_ifstream u16ifstream; - + using StringType = std::string; + using StringViewType = std::string_view; + using CharType = char; + using StreamType = std::ifstream; + using IStreamType = std::ifstream; + using OStreamType = std::ofstream; +/* #if RC_IS_ANSI == 1 using StringType = std::string; using StringViewType = std::string_view; @@ -70,7 +74,7 @@ namespace RC::File using StreamType = std::ifstream; #endif // WIN32 #endif // RC_IS_ANSI - +*/ } // namespace RC::File namespace RC diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index e15bd4ccb..cd41b2658 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -298,16 +298,32 @@ namespace RC::File { return m_is_file_open; } - - auto StdFile::write_string_to_file(StringViewType string_to_write) -> void + + auto StdFile::write_string_to_file(UEStringViewType string_to_write) -> void { - try { - write_to_file(*this, string_to_write.data(), string_to_write.size()); + try + { + static std::wstring_convert, char16_t> converter{}; + atuo utf8_string = converter.to_bytes(input); + write_file_string_to_file(*this, utf8_string.data(), utf8_string.size()); } catch (const std::exception& e) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::write_string_to_file] Tried writing string to file but could not convert to utf-8. Error: {}", e.what())) } } + auto StdFile::write_file_string_to_file(StringViewType string_to_write) -> void + { + try + { + write_to_file(*this, string_to_write.data(), string_to_write.size()); + } + catch (const std::exception& e) + { + THROW_INTERNAL_FILE_ERROR( + std::format("[StdFile::write_string_to_file] Tried writing string to file but could not convert to utf-8. Error: {}", e.what())) + } + } + auto StdFile::is_same_as(StdFile& other_file) -> bool { struct stat file_info{}; @@ -375,7 +391,7 @@ namespace RC::File return true; } - auto StdFile::read_all() const -> StringType + auto StdFile::read_file_all() const -> StringType { StreamType stream{get_file_path(), std::ios::in | std::ios::binary}; if (!stream) @@ -401,14 +417,19 @@ namespace RC::File { return {}; } - file_contents.resize(size); + file_contents.resize(size - start); stream.seekg(start, std::ios::beg); - stream.read(&file_contents[0], file_contents.size()); + stream.read(&file_contents[0], file_contents.size() - start); stream.close(); return file_contents; } } + auto StdFile::read_all() const -> UEStringType + { + auto utf8_string = read_file_all(); + return std::wstring_convert, char16_t>{}.from_bytes(utf8_string); + } auto StdFile::memory_map() -> std::span { diff --git a/deps/first/File/src/FileType/WinFile.cpp b/deps/first/File/src/FileType/WinFile.cpp index 0cbfd2f84..2e573c9e6 100644 --- a/deps/first/File/src/FileType/WinFile.cpp +++ b/deps/first/File/src/FileType/WinFile.cpp @@ -380,7 +380,7 @@ namespace RC::File return m_is_file_open; } - auto WinFile::write_string_to_file(StringViewType string_to_write) -> void + auto WinFile::write_string_to_file(UEStringViewType string_to_write) -> void { int string_size = WideCharToMultiByte(CP_UTF8, 0, string_to_write.data(), static_cast(string_to_write.size()), NULL, 0, NULL, NULL); if (string_size == 0) @@ -399,6 +399,12 @@ namespace RC::File write_to_file(*this, string_converted_to_utf8.c_str(), string_size); } + + auto WinFile::write_file_string_to_file(StringViewType string_to_write) -> void + { + write_to_file(*this, string_to_write.data(), string_to_write.length()); + } + auto WinFile::is_same_as(WinFile& other_file) -> bool { BY_HANDLE_FILE_INFORMATION file_info{}; @@ -452,38 +458,85 @@ namespace RC::File return true; } - auto WinFile::read_all() const -> StringType + auto WinFile::read_all() const -> UEStringType + { + auto file_contents = read_file_all(); + int string_size = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)file_contents.c_str(), static_cast(file_contents.size()), NULL, 0); + if (string_size == 0) + { + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_all] Tried reading entire file but could not convert to utf-16. Error: {}", GetLastError())) + } + + UEStringType string_converted_to_utf16(string_size, 0); + if (MultiByteToWideChar(CP_UTF8, 0, (LPCCH)file_contents.c_str(), static_cast(file_contents.size()), &string_converted_to_utf16[0], string_size) == 0) + { + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_all] Tried reading entire file but could not convert to utf-16. Error: {}", GetLastError())) + } + + return string_converted_to_utf16; + } + + auto WinFile::read_file_all() const -> StringType { - StreamType stream{get_file_path(), std::ios::in | std::ios::binary}; - if (!stream) + // get file handle, const_cast is safe here because we will restore the file pointer + auto handle = const_cast(this)->get_file(); + + // backup file pointer + auto file_pointer = SetFilePointer(handle, 0, nullptr, FILE_CURRENT); + + LONG file_size{}; + if (!GetFileSizeEx(handle, (PLARGE_INTEGER)&file_size)) { - THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_all] Tried to read entire file but returned error {}", errno)) + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not get file size. Error: {}", GetLastError())) } - else + + // move pointer to begin + SetFilePointer(handle, 0, nullptr, FILE_BEGIN); + + if (file_size >= 3ul) { - // Strip the BOM if it exists - File::StreamType::off_type start{}; - File::CharType bom[3]{}; - stream.read(bom, 3); - if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) + // check BOM + constexpr size_t bom_size = 3; + char bom[bom_size]; + DWORD bytes_read{}; + + if (!ReadFile(handle, bom, bom_size, &bytes_read, nullptr)) { - // BOM: UTF-8 - start = 3; + // try restoring file pointer + SetFilePointer(handle, file_pointer, nullptr, FILE_BEGIN); + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not read BOM. Error: {}", GetLastError())) } - - StringType file_contents; - stream.seekg(0, std::ios::end); - auto size = stream.tellg(); - if (size == -1) + if (bytes_read != bom_size) { - return {}; + // try restoring file pointer + SetFilePointer(handle, file_pointer, nullptr, FILE_BEGIN); + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not read BOM. Error: {}", GetLastError())) + } + if (bom[0] == '\xEF' && bom[1] == '\xBB' && bom[2] == '\xBF') + { + file_size -= 3; + } + else + { + // roll back + SetFilePointer(handle, 0, nullptr, FILE_BEGIN); } - file_contents.resize(size); - stream.seekg(start, std::ios::beg); - stream.read(&file_contents[0], file_contents.size()); - stream.close(); - return file_contents; } + + StringType file_contents(file_size, 0); + DWORD bytes_read{}; + if (!ReadFile(handle, &file_contents[0], file_size, &bytes_read, nullptr)) + { + // try restoring file pointer + SetFilePointer(handle, file_pointer, nullptr, FILE_BEGIN); + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not read file contents. Error: {}", GetLastError())) + } + + file_contents[bytes_read] = 0; + + // restore file pointer + SetFilePointer(handle, file_pointer, nullptr, FILE_BEGIN); + return file_contents; } auto WinFile::memory_map() -> std::span diff --git a/deps/first/Helpers/include/Helpers/Format.hpp b/deps/first/Helpers/include/Helpers/Format.hpp index 2a7d5f861..c06528b89 100644 --- a/deps/first/Helpers/include/Helpers/Format.hpp +++ b/deps/first/Helpers/include/Helpers/Format.hpp @@ -10,4 +10,10 @@ namespace RC { return std::vformat(std::forward(fmt), std::make_format_args(to_stdstr(std::forward(fmt_args))...)); } + + template + auto static fmtfile(const File::StringViewType&& fmt, FmtArgs&&... fmt_args) -> std::string + { + return std::vformat(std::forward(fmt), std::make_format_args(to_file(std::forward(fmt_args))...)); + } } \ No newline at end of file diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index 15ebeae4d..7311c682b 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -212,17 +212,67 @@ namespace RC } /* explode_by_occurrence -> END */ - auto inline to_wstring(std::string& input) -> std::wstring + // ----------------------------- // + #define STRING_DISPATCH(STRING_T, ts, tw, tu16) \ + if constexpr (std::is_same_v) \ + { \ + return ts(std::forward(input)); \ + } \ + else if constexpr (std::is_same_v) \ + { \ + return tw(std::forward(input)); \ + } \ + else if constexpr (std::is_same_v) \ + { \ + return tu16(std::forward(input)); \ + } \ + else \ + { \ + static_assert(dependent_false::value, "Unsupported " #STRING_T "."); \ + } + // ----------------------------- // + #define PATH_QUIRK(STRINGT) \ + if constexpr (std::is_same_v, std::filesystem::path> \ + || std::is_same_v, const std::filesystem::path>) \ + { \ + STRING_DISPATCH(STRINGT, to_string_path, to_wstring_path, to_u16string_path); \ + } + // ----------------------------- // + + #define TO_STRING_QUIRK_DISPATCH(STRINGT) \ + PATH_QUIRK(STRINGT) \ + else \ + { \ + STRING_DISPATCH(STRINGT, to_string, to_wstring, to_u16string); \ + } + // ----------------------------- // + + auto inline to_string_path(const std::filesystem::path& input) -> std::string + { + return input.string(); + } + + auto inline to_wstring_path(const std::filesystem::path& input) -> std::wstring + { + return input.wstring(); + } + + auto inline to_u16string_path(const std::filesystem::path& input) -> std::u16string { - #if WIN32 + return input.u16string(); + } + + auto inline to_wstring(std::string_view input) -> std::wstring + { +#if WIN32 #pragma warning(disable : 4996) - static std::wstring_convert> converter{}; - return converter.from_bytes(input); + static std::wstring_convert> converter{}; + return converter.from_bytes(input.data(), input.data() + input.length()); #pragma warning(default : 4996) - #else - static std::wstring_convert> converter{}; - return converter.from_bytes(input); - #endif +#else + static std::wstring_convert> converter{}; + return converter.from_bytes(input.data(), input.data() + input.length()); +#endif } auto inline to_const_wstring(std::string_view input) -> const std::wstring& @@ -257,11 +307,6 @@ namespace RC return std::wstring{input}; } - auto inline to_wstring(std::string_view input) -> std::wstring - { - auto temp_input = std::string{input}; - return to_wstring(temp_input); - } auto inline to_wstring(std::u16string& input) -> std::wstring { @@ -275,43 +320,41 @@ namespace RC auto inline to_wstring(std::u16string_view input) -> std::wstring { #ifdef WIN32 - auto temp_input = std::u16string{input}; - return to_wstring(temp_input); + return {input.begin(), input.end()}; #else - return to_wstring(std::u16string{input}); + throw std::runtime_error{"There is no reason to use this function on non-Windows platforms"}; #endif } - auto inline to_string(std::wstring& input) -> std::string + /* + auto inline to_string(std::u16string& input) -> std::string { -#ifdef WIN32 #pragma warning(disable : 4996) - static std::wstring_convert> converter{}; + static std::wstring_convert, char16_t> converter{}; return converter.to_bytes(input); #pragma warning(default : 4996) -#else - static std::wstring_convert> converter{}; - return converter.to_bytes(input); -#endif } + */ - auto inline to_string(std::u16string& input) -> std::string + auto inline to_string(std::wstring_view input) -> std::string { +#ifdef WIN32 #pragma warning(disable : 4996) - return std::wstring_convert, char16_t>{}.to_bytes(input); + static std::wstring_convert> converter{}; + return converter.to_bytes(input.data(), input.data() + input.length()); #pragma warning(default : 4996) - } - - auto inline to_string(std::wstring_view input) -> std::string - { - auto temp_input = std::wstring{input}; - return to_string(temp_input); +#else + static std::wstring_convert> converter{}; + return converter.to_bytes(input.data(), input.data() + input.length()); +#endif } auto inline to_string(std::u16string_view input) -> std::string { - auto temp_input = std::u16string{input}; - return to_string(temp_input); +#pragma warning(disable : 4996) + static std::wstring_convert, char16_t> converter{}; + return converter.to_bytes(input.data(), input.data() + input.length()); +#pragma warning(default : 4996) } auto inline to_string(std::string_view input) -> std::string @@ -335,22 +378,30 @@ namespace RC auto inline to_u16string(std::wstring_view input) -> std::u16string { - auto temp_input = std::wstring{input}; - return to_u16string(temp_input); + return to_u16string(std::wstring(input)); } + /* auto inline to_u16string(std::string& input) -> std::u16string { // codecvt_utf8_utf16 #pragma warning(disable : 4996) - return std::wstring_convert, char16_t>{}.from_bytes(input); + static std::wstring_convert, char16_t> converter {}; + return converter.from_bytes(input); #pragma warning(default : 4996) } + */ auto inline to_u16string(std::string_view input) -> std::u16string { + /* auto temp_input = std::string{input}; - return to_u16string(temp_input); + return to_u16string(temp_input);*/ + // codecvt_utf8_utf16 +#pragma warning(disable : 4996) + static std::wstring_convert, char16_t> converter{}; + return converter.from_bytes(input.data(), input.data() + input.length()); +#pragma warning(default : 4996) } auto inline to_u16string(std::u16string_view input) -> std::u16string @@ -378,6 +429,11 @@ namespace RC template struct dependent_false : std::false_type {}; + template + struct dependent_ensure : std::true_type {}; + template + struct dependent_ensure : std::false_type {}; + template auto stringviewify(T&& tp) { if constexpr (std::is_same_v, UECharType*> || std::is_same_v, const UECharType*>) { @@ -414,26 +470,18 @@ namespace RC template auto inline to_file_string(T&& input) -> File::StringType { - if constexpr (std::is_same_v) - { - return to_string(input); - } - else if constexpr (std::is_same_v) - { - return to_wstring(input); - } - else if constexpr (std::is_same_v) - { - return to_u16string(input); - } else { - static_assert(dependent_false::value, "Unsupported SystemStringType."); - } + TO_STRING_QUIRK_DISPATCH(File::StringType); } template - auto to_file(T&& arg) { - if constexpr (can_be_string_view_t::value) { - return to_file_string(stringviewify(std::forward(arg))); + auto to_file(T&& arg) + { + if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) + { + return to_file_string(std::forward(arg)); + } + else if constexpr (can_be_string_view_t::value) { + return to_file(stringviewify(std::forward(arg))); } else if constexpr (not_file_string_like_t>::value) { @@ -447,25 +495,27 @@ namespace RC template struct is_std_string_type : std::disjunction, std::is_same> - { - }; + {}; template struct not_std_string_like_t : std::conjunction>, std::negation>>> - { - }; + { }; template auto inline to_std_string(T&& input) -> std::string { - return to_string(input); + return to_string(std::forward(input)); } template auto to_stdstr(T&& arg) { - if constexpr (can_be_string_view_t::value) + if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) + { + return to_std_string(std::forward(arg)); + } + else if constexpr (can_be_string_view_t::value) { return to_stdstr(stringviewify(std::forward(arg))); } @@ -490,49 +540,18 @@ namespace RC template auto inline to_system_string(T&& input) -> SystemStringType { - if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) { - // just a workaround here - auto hold = input; - if constexpr (std::is_same_v) - { - return input.string(); - } - else if constexpr (std::is_same_v) - { - return input.wstring(); - } - else if constexpr (std::is_same_v) - { - return input.u16string(); - } - else - { - static_assert(dependent_false::value, "Unsupported SystemStringType."); - } - } - else - if constexpr (std::is_same_v) - { - return to_string(input); - } - else if constexpr (std::is_same_v) - { - return to_wstring(input); - } - else if constexpr (std::is_same_v) - { - return to_u16string(input); - } - else - { - static_assert(dependent_false::value, "Unsupported SystemStringType."); - } + TO_STRING_QUIRK_DISPATCH(SystemStringType); } template auto to_system(T&& arg) { + if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) + { + return to_system_string(std::forward(arg)); + } + else if constexpr (can_be_string_view_t::value) { - return to_system_string(stringviewify(std::forward(arg))); + return to_system(stringviewify(std::forward(arg))); } else if constexpr (not_system_string_like_t>::value) { @@ -555,29 +574,19 @@ namespace RC template auto inline to_ue_string(T&& input) -> UEStringType { - if constexpr (std::is_same_v) - { - return to_string(input); - } - else if constexpr (std::is_same_v) - { - return to_wstring(input); - } - else if constexpr (std::is_same_v) - { - return to_u16string(input); - } - else - { - static_assert(dependent_false::value, "Unsupported SystemStringType."); - } + TO_STRING_QUIRK_DISPATCH(UEStringType); } template - auto to_ue(T&& arg) { - if constexpr (can_be_string_view_t::value) + auto to_ue(T&& arg) + { + if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) + { + return to_ue_string(std::forward(arg)); + } + else if constexpr (can_be_string_view_t::value) { - return to_ue_string(stringviewify(std::forward(arg))); + return to_ue(stringviewify(std::forward(arg))); } else if constexpr (not_ue_string_like_t>::value) { @@ -602,7 +611,7 @@ namespace RC auto to_lua(T&& arg) { if constexpr (can_be_string_view_t::value || not_lua_string_like_t>::value) { - return to_string((arg)); + return to_string(std::forward(arg)); } else { @@ -610,8 +619,15 @@ namespace RC } } + // TODO: add an option to allow compile failure if to_XXXX failed. + // e.g., to_ue -> must be able to convert to uestring, not passthrough. + #define csfor_lua(x) (to_lua((x)).c_str()) + #undef TO_STRING_QUIRK_DISPATCH + #undef PATH_QUIRK + #undef STRING_DISPATCH + namespace String { auto inline iequal(std::wstring_view a, std::wstring_view b) diff --git a/deps/first/IniParser/src/Ini.cpp b/deps/first/IniParser/src/Ini.cpp index f2bd072cc..84dd3c093 100644 --- a/deps/first/IniParser/src/Ini.cpp +++ b/deps/first/IniParser/src/Ini.cpp @@ -1,10 +1,11 @@ #include #include #include +#include namespace RC::Ini { - auto Parser::parse_internal(SystemStringType& input) -> void + auto Parser::parse_internal(UEStringType& input) -> void { // Tokenize -> START ParserBase::Tokenizer tokenizer; @@ -24,24 +25,24 @@ namespace RC::Ini { ParserBase::TokenContainer tc; - tc.add(ParserBase::Token::create(IniTokenType::CarriageReturn, SYSSTR("CarriageReturn"), SYSSTR("\r"))); - tc.add(ParserBase::Token::create(IniTokenType::NewLine, SYSSTR("NewLine"), SYSSTR("\n"))); - tc.add(ParserBase::Token::create(IniTokenType::Space, SYSSTR("Space"), SYSSTR(" "))); + tc.add(ParserBase::Token::create(IniTokenType::CarriageReturn, STR("CarriageReturn"), STR("\r"))); + tc.add(ParserBase::Token::create(IniTokenType::NewLine, STR("NewLine"), STR("\n"))); + tc.add(ParserBase::Token::create(IniTokenType::Space, STR("Space"), STR(" "))); tc.add(ParserBase::Token::create(IniTokenType::Characters, - SYSSTR("Characters"), - SYSSTR(""), + STR("Characters"), + STR(""), ParserBase::Token::HasData::Yes)); // Empty identifier will match everything that no other token identifier matches - tc.add(ParserBase::Token::create /**/ (IniTokenType::Equals, SYSSTR("Equals"), SYSSTR("="))); - tc.add(ParserBase::Token::create(IniTokenType::ClosingSquareBracket, SYSSTR("CloseSquareBracket"), SYSSTR("]"))); - tc.add(ParserBase::Token::create(IniTokenType::OpeningSquareBracket, SYSSTR("OpenSquareBracket"), SYSSTR("["))); - tc.add(ParserBase::Token::create(IniTokenType::SemiColon, SYSSTR("SemiColon"), SYSSTR(";"))); + tc.add(ParserBase::Token::create /**/ (IniTokenType::Equals, STR("Equals"), STR("="))); + tc.add(ParserBase::Token::create(IniTokenType::ClosingSquareBracket, STR("CloseSquareBracket"), STR("]"))); + tc.add(ParserBase::Token::create(IniTokenType::OpeningSquareBracket, STR("OpenSquareBracket"), STR("["))); + tc.add(ParserBase::Token::create(IniTokenType::SemiColon, STR("SemiColon"), STR(";"))); tc.set_eof_token(IniTokenType::EndOfFile); return tc; } - auto Parser::get_value(const SystemStringType& section, const SystemStringType& key, CanThrow can_throw) const + auto Parser::get_value(const UEStringType& section, const UEStringType& key, CanThrow can_throw) const -> std::optional> { if (!m_parsing_is_complete) @@ -76,7 +77,7 @@ namespace RC::Ini } } - auto Parser::parse(SystemStringType& input) -> void + auto Parser::parse(UEStringType& input) -> void { parse_internal(input); } @@ -87,7 +88,7 @@ namespace RC::Ini parse_internal(input); } - auto Parser::get_list(const SystemStringType& section) -> List + auto Parser::get_list(const UEStringType& section) -> List { const auto& section_iter = m_sections.find(section); @@ -101,13 +102,13 @@ namespace RC::Ini } } - auto Parser::get_ordered_list(const SystemStringType& section) -> List + auto Parser::get_ordered_list(const UEStringType& section) -> List { return get_list(section); } - auto Parser::get_string(const SystemStringType& section, const SystemStringType& key, const SystemStringType& default_value) const noexcept - -> const SystemStringType& + auto Parser::get_string(const UEStringType& section, const UEStringType& key, const UEStringType& default_value) const noexcept + -> const UEStringType& { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -128,7 +129,7 @@ namespace RC::Ini } } - auto Parser::get_string(const SystemStringType& section, const SystemStringType& key) const -> const SystemStringType& + auto Parser::get_string(const UEStringType& section, const UEStringType& key) const -> const UEStringType& { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -149,7 +150,7 @@ namespace RC::Ini } } - auto Parser::get_int64(const SystemStringType& section, const SystemStringType& key, int64_t default_value) const noexcept -> int64_t + auto Parser::get_int64(const UEStringType& section, const UEStringType& key, int64_t default_value) const noexcept -> int64_t { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -170,7 +171,7 @@ namespace RC::Ini } } - auto Parser::get_int64(const SystemStringType& section, const SystemStringType& key) const -> int64_t + auto Parser::get_int64(const UEStringType& section, const UEStringType& key) const -> int64_t { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -191,7 +192,7 @@ namespace RC::Ini } } - auto Parser::get_float(const SystemStringType& section, const SystemStringType& key, float default_value) const noexcept -> float + auto Parser::get_float(const UEStringType& section, const UEStringType& key, float default_value) const noexcept -> float { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -212,7 +213,7 @@ namespace RC::Ini } } - auto Parser::get_float(const SystemStringType& section, const SystemStringType& key) const -> float + auto Parser::get_float(const UEStringType& section, const UEStringType& key) const -> float { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -233,7 +234,7 @@ namespace RC::Ini } } - auto Parser::get_bool(const SystemStringType& section, const SystemStringType& key, bool default_value) const noexcept -> bool + auto Parser::get_bool(const UEStringType& section, const UEStringType& key, bool default_value) const noexcept -> bool { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -254,7 +255,7 @@ namespace RC::Ini } } - auto Parser::get_bool(const SystemStringType& section, const SystemStringType& key) const -> bool + auto Parser::get_bool(const UEStringType& section, const UEStringType& key) const -> bool { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) diff --git a/deps/first/IniParser/src/JSON.cpp b/deps/first/IniParser/src/JSON.cpp index b84c2659c..37a6ba088 100644 --- a/deps/first/IniParser/src/JSON.cpp +++ b/deps/first/IniParser/src/JSON.cpp @@ -11,7 +11,7 @@ namespace RC::Parser return std::string{in.begin(), in.end()}; } - static auto has_only_spaces(const SystemStringType& data) -> bool + static auto has_only_spaces(const UEStringType& data) -> bool { if (std::all_of(data.begin(), data.end(), [](File::CharType c) { return std::isspace(c) || c == '\n'; @@ -27,11 +27,11 @@ namespace RC::Parser } } - auto JSONInternal::ItemBase::get_name() -> SystemStringViewType + auto JSONInternal::ItemBase::get_name() -> UEStringViewType { if (m_is_global_scope) { - return SYSSTR("-- IS ANONYMOUS GLOBAL --"); + return STR("-- IS ANONYMOUS GLOBAL --"); } else { @@ -39,31 +39,31 @@ namespace RC::Parser } } - auto JSONInternal::StringItem::to_string() -> SystemStringType + auto JSONInternal::StringItem::to_string() -> UEStringType { - return std::format(SYSSTR("String = \"{}\""), m_value); + return std::format(STR("String = \"{}\""), m_value); } - auto JSONInternal::ObjectScope::to_string() -> SystemStringType + auto JSONInternal::ObjectScope::to_string() -> UEStringType { - SystemStringType str = std::format(SYSSTR("Object = \"{}\""), get_name()); + UEStringType str = std::format(STR("Object = \"{}\""), get_name()); for (const auto& member : m_members) { - str.append(std::format(SYSSTR("\n\"{}\" = {}"), member->get_name(), member->to_string())); + str.append(std::format(STR("\n\"{}\" = {}"), member->get_name(), member->to_string())); } return str; } - auto JSONInternal::ArrayScope::to_string() -> SystemStringType + auto JSONInternal::ArrayScope::to_string() -> UEStringType { - return std::format(SYSSTR("Array = \"{}\""), get_name()); + return std::format(STR("Array = \"{}\""), get_name()); } - auto JSONInternal::TokenParser::token_to_string(const Token& token) -> SystemStringType + auto JSONInternal::TokenParser::token_to_string(const Token& token) -> UEStringType { - SystemStringType string{}; + UEStringType string{}; // TODO: Support manual escaping of double quotes with '\' while (peek().get_type() != TokenType::DoubleQuote) @@ -342,18 +342,18 @@ namespace RC::Parser } } - auto JSON::parse_internal(SystemStringType& input) -> void + auto JSON::parse_internal(UEStringType& input) -> void { Tokenizer tokenizer; TokenContainer tc; - tc.add(Token::create(JSONInternal::TokenType::OpenCurlyBrace, SYSSTR("OpenCurlyBrace"), SYSSTR("{"))); - tc.add(Token::create(JSONInternal::TokenType::CloseCurlyBrace, SYSSTR("CloseCurlyBrace"), SYSSTR("}"))); - tc.add(Token::create(JSONInternal::TokenType::OpenSquareBracket, SYSSTR("OpenSquareBracket"), SYSSTR("["))); - tc.add(Token::create(JSONInternal::TokenType::CloseSquareBracket, SYSSTR("CloseSquareBracket"), SYSSTR("]"))); - tc.add(Token::create(JSONInternal::TokenType::Colon, SYSSTR("Colon"), SYSSTR(":"))); - tc.add(Token::create(JSONInternal::TokenType::Comma, SYSSTR("Comma"), SYSSTR(","))); - tc.add(Token::create(JSONInternal::TokenType::DoubleQuote, SYSSTR("DoubleQuote"), SYSSTR("\""))); - tc.add(Token::create(JSONInternal::TokenType::Characters, SYSSTR("Characters"), SYSSTR(""), Token::HasData::Yes)); + tc.add(Token::create(JSONInternal::TokenType::OpenCurlyBrace, STR("OpenCurlyBrace"), STR("{"))); + tc.add(Token::create(JSONInternal::TokenType::CloseCurlyBrace, STR("CloseCurlyBrace"), STR("}"))); + tc.add(Token::create(JSONInternal::TokenType::OpenSquareBracket, STR("OpenSquareBracket"), STR("["))); + tc.add(Token::create(JSONInternal::TokenType::CloseSquareBracket, STR("CloseSquareBracket"), STR("]"))); + tc.add(Token::create(JSONInternal::TokenType::Colon, STR("Colon"), STR(":"))); + tc.add(Token::create(JSONInternal::TokenType::Comma, STR("Comma"), STR(","))); + tc.add(Token::create(JSONInternal::TokenType::DoubleQuote, STR("DoubleQuote"), STR("\""))); + tc.add(Token::create(JSONInternal::TokenType::Characters, STR("Characters"), STR(""), Token::HasData::Yes)); tc.set_eof_token(JSONInternal::TokenType::EndOfFile); tokenizer.set_available_tokens(std::move(tc)); tokenizer.tokenize(input); @@ -362,7 +362,7 @@ namespace RC::Parser m_token_parser->parse(); } - auto JSON::parse(SystemStringType& input) -> void + auto JSON::parse(UEStringType& input) -> void { parse_internal(input); } @@ -391,7 +391,7 @@ namespace RC::Parser */ /**/ - SystemStringType input = LR"( + UEStringType input = LR"( { "my key": "my string, value", "my second key": "my other string value", diff --git a/deps/first/IniParser/src/TokenParser.cpp b/deps/first/IniParser/src/TokenParser.cpp index 7ce0adff1..4933bc66d 100644 --- a/deps/first/IniParser/src/TokenParser.cpp +++ b/deps/first/IniParser/src/TokenParser.cpp @@ -28,10 +28,10 @@ namespace RC::Ini bool is_bool{false}; }; - auto static is_int(SystemStringType data) -> Int + auto static is_int(UEStringType data) -> Int { bool has_0x_prefix = [&]() { - return (data.size() > 2 && data[0] == SYSSTR('0') && (data[1] == SYSSTR('x') || data[1] == SYSSTR('X'))); + return (data.size() > 2 && data[0] == STR('0') && (data[1] == STR('x') || data[1] == STR('X'))); }(); if (!has_0x_prefix && data[0] != L'-' && std::iswdigit(data[0]) == 0) @@ -40,13 +40,13 @@ namespace RC::Ini } else { - SystemStringType string = has_0x_prefix ? SystemStringType{data.begin() + 2, data.end()} : data; - if (!has_0x_prefix && data[0] == SYSSTR('-')) + UEStringType string = has_0x_prefix ? UEStringType{data.begin() + 2, data.end()} : data; + if (!has_0x_prefix && data[0] == STR('-')) { - string = SystemStringType{string.begin() + 1, string.end()}; + string = UEStringType{string.begin() + 1, string.end()}; } - bool is_int = std::ranges::all_of(string.begin(), string.end(), [&](const File::CharType c) { - if constexpr (std::is_same_v) + bool is_int = std::ranges::all_of(string.begin(), string.end(), [&](const UECharType c) { + if constexpr (std::is_same_v) { return has_0x_prefix ? std::iswxdigit(c) : std::iswdigit(c) != 0; } @@ -60,10 +60,10 @@ namespace RC::Ini } } - auto static is_float(SystemStringType data) -> Float + auto static is_float(UEStringType data) -> Float { bool has_decimal_or_negative_prefix = [&]() { - return data.size() > 1 && data[0] == SYSSTR('.') || data[0] == SYSSTR('-'); + return data.size() > 1 && data[0] == STR('.') || data[0] == STR('-'); }(); if (!has_decimal_or_negative_prefix && std::iswdigit(data[0]) == 0) @@ -72,19 +72,19 @@ namespace RC::Ini } else { - SystemStringType string = data.ends_with(SYSSTR('f')) ? SystemStringType{data.begin(), data.end() - 1} : data; + UEStringType string = data.ends_with(STR('f')) ? UEStringType{data.begin(), data.end() - 1} : data; if (has_decimal_or_negative_prefix) { - string = SystemStringType{string.begin() + 1, string.end()}; + string = UEStringType{string.begin() + 1, string.end()}; } - bool is_float = std::ranges::all_of(string.begin(), string.end(), [&](const File::CharType c) { - if constexpr (std::is_same_v) + bool is_float = std::ranges::all_of(string.begin(), string.end(), [&](const UECharType c) { + if constexpr (std::is_same_v) { - return has_decimal_or_negative_prefix ? std::iswxdigit(c) : std::iswdigit(c) != 0 || c == SYSSTR('.'); + return has_decimal_or_negative_prefix ? std::iswxdigit(c) : std::iswdigit(c) != 0 || c == STR('.'); } else { - return has_decimal_or_negative_prefix ? std::isxdigit(c) : std::isdigit(c) != 0 || c == SYSSTR('.'); + return has_decimal_or_negative_prefix ? std::isxdigit(c) : std::isdigit(c) != 0 || c == STR('.'); } }); @@ -92,17 +92,17 @@ namespace RC::Ini } } - auto static is_bool(const SystemStringType& data) -> Bool + auto static is_bool(const UEStringType& data) -> Bool { - SystemStringType all_lower_string_data = data; - std::transform(all_lower_string_data.begin(), all_lower_string_data.end(), all_lower_string_data.begin(), [](SystemCharType c) { + UEStringType all_lower_string_data = data; + std::transform(all_lower_string_data.begin(), all_lower_string_data.end(), all_lower_string_data.begin(), [](UECharType c) { return std::towlower(c); }); - if (all_lower_string_data == SYSSTR("true") || all_lower_string_data == SYSSTR("1")) + if (all_lower_string_data == STR("true") || all_lower_string_data == STR("1")) { return Bool{.value = true, .is_bool = true}; } - else if (all_lower_string_data == SYSSTR("false") || all_lower_string_data == SYSSTR("0")) + else if (all_lower_string_data == STR("false") || all_lower_string_data == STR("0")) { return Bool{.value = false, .is_bool = true}; } @@ -112,7 +112,7 @@ namespace RC::Ini } } - auto TokenParser::find_variable_by_name(Section* section, const RC::SystemStringType& name) -> std::optional> + auto TokenParser::find_variable_by_name(Section* section, const RC::UEStringType& name) -> std::optional> { auto const& var = section->key_value_pairs.find(name); if (var != section->key_value_pairs.end()) @@ -125,7 +125,7 @@ namespace RC::Ini } } - auto TokenParser::find_variable_by_name(const SystemStringType& name) -> std::optional> + auto TokenParser::find_variable_by_name(const UEStringType& name) -> std::optional> { size_t occurrence_of_dot = name.find_first_of(L'.'); if (occurrence_of_dot == name.npos || occurrence_of_dot + 1 > name.size()) @@ -141,38 +141,38 @@ namespace RC::Ini } else { - const SystemStringType requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); + const UEStringType requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); return find_variable_by_name(&requested_section->second, requested_variable_name); } } } - auto state_to_string(State state) -> SystemStringType + auto state_to_string(State state) -> UEStringType { switch (state) { case State::StartOfFile: - return SYSSTR("StartOfFile"); + return STR("StartOfFile"); case State::SetSectionValue: - return SYSSTR("SetSectionValue"); + return STR("SetSectionValue"); case State::NewLineStarted: - return SYSSTR("NewLineStarted"); + return STR("NewLineStarted"); case State::CreateNewOrSetCurrentSection: - return SYSSTR("CreateNewOrSetCurrentSection"); + return STR("CreateNewOrSetCurrentSection"); case State::CreateSectionKey: - return SYSSTR("CreateSectionKey"); + return STR("CreateSectionKey"); case State::StoreSectionKey: - return SYSSTR("StoreSectionKey"); + return STR("StoreSectionKey"); } - return SYSSTR("UnknownState"); + return STR("UnknownState"); } - auto TokenParser::characters_to_string(const ParserBase::Token& characters_token) -> SystemStringType + auto TokenParser::characters_to_string(const ParserBase::Token& characters_token) -> UEStringType { auto* current_token = &characters_token; - SystemStringType full_value{}; + UEStringType full_value{}; while (true) { const auto token_type = current_token->get_type(); @@ -182,7 +182,7 @@ namespace RC::Ini } else if (token_type == IniTokenType::Space) { - full_value.append(SYSSTR(" ")); + full_value.append(STR(" ")); } else if (token_type == IniTokenType::Characters) { @@ -190,7 +190,7 @@ namespace RC::Ini } else if (token_type == IniTokenType::Equals) { - full_value.append(SYSSTR("=")); + full_value.append(STR("=")); } else if (token_type == IniTokenType::ClosingSquareBracket) { @@ -201,15 +201,15 @@ namespace RC::Ini // The next token is the last token on this line and since it's ] we don't want to include it in the string break; } - full_value.append(SYSSTR("]")); + full_value.append(STR("]")); } else if (token_type == IniTokenType::OpeningSquareBracket) { - full_value.append(SYSSTR("[")); + full_value.append(STR("[")); } else if (token_type == IniTokenType::SemiColon) { - full_value.append(SYSSTR(";")); + full_value.append(STR(";")); } // Exit early and let the state machine deal with the new line @@ -290,7 +290,7 @@ namespace RC::Ini { if (m_current_state == State::CreateNewOrSetCurrentSection) { - m_current_character_data.append(SYSSTR(" ")); + m_current_character_data.append(STR(" ")); } } @@ -381,7 +381,7 @@ namespace RC::Ini // Create the value with the correct key and an empty value and store a pointer to it so that the value can be set later m_current_value = &m_current_section->key_value_pairs.emplace(m_current_character_data, Value{}).first->second; - m_current_value->add_string_value(SYSSTR("")); + m_current_value->add_string_value(STR("")); m_current_value->set_ref(m_current_value); m_current_character_data.clear(); diff --git a/deps/first/IniParser/src/Value.cpp b/deps/first/IniParser/src/Value.cpp index 36a23fa59..71ddc24b4 100644 --- a/deps/first/IniParser/src/Value.cpp +++ b/deps/first/IniParser/src/Value.cpp @@ -20,7 +20,7 @@ namespace RC::Ini m_ref = new_ref; } - auto Value::get_string_value() const -> const SystemStringType& + auto Value::get_string_value() const -> const UEStringType& { return m_string_value; } @@ -52,7 +52,7 @@ namespace RC::Ini add_type(); } - auto Value::add_int64_value(const SystemStringType& data, int base) -> void + auto Value::add_int64_value(const UEStringType& data, int base) -> void { m_int64_value = std::stoi(data, nullptr, base); @@ -64,7 +64,7 @@ namespace RC::Ini add_type(); } - auto Value::add_float_value(const SystemStringType& data) -> void + auto Value::add_float_value(const UEStringType& data) -> void { m_float_value = std::stof(data, nullptr); diff --git a/deps/first/JSON/include/JSON/Parser/Parser.hpp b/deps/first/JSON/include/JSON/Parser/Parser.hpp index 03eb9d4b8..5efa7f690 100644 --- a/deps/first/JSON/include/JSON/Parser/Parser.hpp +++ b/deps/first/JSON/include/JSON/Parser/Parser.hpp @@ -11,5 +11,6 @@ namespace RC::JSON::Parser { RC_JSON_API auto parse(File::StringType& input) -> std::unique_ptr; + RC_JSON_API auto parse(UEStringType& input) -> std::unique_ptr; RC_JSON_API auto parse(const File::Handle&) -> std::unique_ptr; } // namespace RC::JSON::Parser diff --git a/deps/first/JSON/src/Parser/Parser.cpp b/deps/first/JSON/src/Parser/Parser.cpp index c76f2bcc0..e249a3973 100644 --- a/deps/first/JSON/src/Parser/Parser.cpp +++ b/deps/first/JSON/src/Parser/Parser.cpp @@ -54,15 +54,21 @@ namespace RC::JSON::Parser } } // namespace Internal - auto parse(SystemStringType& input) -> std::unique_ptr + auto parse(File::StringType& input) -> std::unique_ptr { auto ue_input = to_ue(input); return Internal::parse_internal(ue_input); } + auto parse(UEStringType& input) -> std::unique_ptr + { + auto ue_input = input; + return Internal::parse_internal(ue_input); + } + auto parse(const File::Handle& file) -> std::unique_ptr { - auto input = to_ue(file.read_all()); + auto input = file.read_all(); return Internal::parse_internal(input); } } // namespace RC::JSON::Parser diff --git a/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp b/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp index 8812f1ddb..dafa64c95 100644 --- a/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp +++ b/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp @@ -43,7 +43,7 @@ namespace RC::ParserBase public: RC_PB_API auto set_available_tokens(TokenContainer&&) -> void; // TODO: Maybe the constructor should take the input instead of 'tokenize' - RC_PB_API auto tokenize(const SystemStringType& input) -> void; + RC_PB_API auto tokenize(const UEStringType& input) -> void; [[nodiscard]] RC_PB_API auto get_tokens() const -> const std::vector&; [[nodiscard]] RC_PB_API auto get_last_token() const -> const Token&; }; diff --git a/deps/first/ParserBase/src/Tokenizer.cpp b/deps/first/ParserBase/src/Tokenizer.cpp index 37a9e28a9..afe228c51 100644 --- a/deps/first/ParserBase/src/Tokenizer.cpp +++ b/deps/first/ParserBase/src/Tokenizer.cpp @@ -41,7 +41,7 @@ namespace RC::ParserBase m_token_container = std::move(token_container); } - auto Tokenizer::tokenize(const SystemStringType& input) -> void + auto Tokenizer::tokenize(const UEStringType& input) -> void { // printf_s("Tokenizer::tokenize()\n\n"); @@ -75,12 +75,12 @@ namespace RC::ParserBase throw std::runtime_error{"[Tokenizer::tokenize] Input was empty"}; } - SystemStringType a; + UEStringType a; - const File::CharType* input_array = input.c_str(); + const UECharType* input_array = input.c_str(); size_t global_cursor{}; - auto peek = [&](SystemStringType& out_str, const File::CharType* character, size_t num_chars) -> void { + auto peek = [&](SystemStringType& out_str, const UECharType* character, size_t num_chars) -> void { if (global_cursor + num_chars <= input.size()) { for (size_t i = 0; i < num_chars; ++i) @@ -102,7 +102,7 @@ namespace RC::ParserBase TokenFoundWrapper empty_token{}; size_t start_of_empty_token{}; bool start_of_empty_token_set{}; - const File::CharType* c = input_array; + const UECharType* c = input_array; auto deal_with_possible_empty_token = [&]() { if (empty_token.token) @@ -137,8 +137,8 @@ namespace RC::ParserBase int advance_cursor_by{-1}; bool all_rules_obeyed{true}; - SystemStringViewType identifier_to_find = token.get_identifier(); - SystemStringType compare_to; + UEStringViewType identifier_to_find = token.get_identifier(); + UEStringType compare_to; size_t identifier_size = identifier_to_find.size(); peek(compare_to, c, identifier_size); bool identifier_should_match_all = identifier_to_find.empty(); From be621ef7174f5b630de1e1b1bd8eddef1f95efd4 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 20 Feb 2024 06:11:57 -0600 Subject: [PATCH 055/213] Linux pong, use System String on parser --- UE4SS/include/Mod/CppMod.hpp | 8 +- UE4SS/include/Mod/CppUserModBase.hpp | 6 +- UE4SS/include/Mod/Mod.hpp | 7 +- .../SDKGenerator/UEHeaderGenerator.hpp | 136 +- UE4SS/include/SettingsManager.hpp | 2 +- UE4SS/src/GUI/Dumpers.cpp | 8 +- UE4SS/src/GUI/LiveView.cpp | 4 +- UE4SS/src/LuaType/LuaModRef.cpp | 4 +- UE4SS/src/Mod/CppMod.cpp | 12 +- UE4SS/src/Mod/CppUserModBase.cpp | 2 +- UE4SS/src/Mod/LuaMod.cpp | 2 +- UE4SS/src/SDKGenerator/Common.cpp | 36 +- UE4SS/src/SDKGenerator/Generator.cpp | 15 +- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 1548 +++++++++-------- UE4SS/src/SettingsManager.cpp | 36 +- UE4SS/src/UE4SSProgram.cpp | 2 +- .../include/DynamicOutput/FileDevice.hpp | 3 +- .../File/include/File/FileType/StdFile.hpp | 2 +- deps/first/File/src/FileType/StdFile.cpp | 4 +- deps/first/IniParser/src/Ini.cpp | 48 +- deps/first/IniParser/src/JSON.cpp | 4 +- deps/first/IniParser/src/TokenParser.cpp | 74 +- deps/first/IniParser/src/Value.cpp | 6 +- deps/first/JSON/include/JSON/Array.hpp | 4 +- deps/first/JSON/include/JSON/Bool.hpp | 2 +- deps/first/JSON/include/JSON/Common.hpp | 4 +- deps/first/JSON/include/JSON/KeyValuePair.hpp | 4 +- deps/first/JSON/include/JSON/Null.hpp | 2 +- deps/first/JSON/include/JSON/Number.hpp | 2 +- deps/first/JSON/include/JSON/Object.hpp | 26 +- .../JSON/include/JSON/Parser/TokenParser.hpp | 6 +- deps/first/JSON/include/JSON/String.hpp | 10 +- deps/first/JSON/src/Array.cpp | 18 +- deps/first/JSON/src/Bool.cpp | 4 +- deps/first/JSON/src/Null.cpp | 4 +- deps/first/JSON/src/Number.cpp | 2 +- deps/first/JSON/src/Object.cpp | 36 +- deps/first/JSON/src/Parser/Parser.cpp | 38 +- deps/first/JSON/src/Parser/TokenParser.cpp | 12 +- deps/first/JSON/src/String.cpp | 6 +- .../include/ParserBase/Tokenizer.hpp | 2 +- deps/first/ParserBase/src/Tokenizer.cpp | 14 +- 42 files changed, 1087 insertions(+), 1078 deletions(-) diff --git a/UE4SS/include/Mod/CppMod.hpp b/UE4SS/include/Mod/CppMod.hpp index b12a60e2c..18466a457 100644 --- a/UE4SS/include/Mod/CppMod.hpp +++ b/UE4SS/include/Mod/CppMod.hpp @@ -28,7 +28,7 @@ namespace RC typedef void (*uninstall_type)(CppUserModBase*); private: - UEStringType m_dlls_path; + SystemStringType m_dlls_path; #ifdef WIN32 HMODULE m_main_dll_module = NULL; DLL_DIRECTORY_COOKIE m_dlls_path_cookie = NULL; @@ -39,7 +39,7 @@ namespace RC CppUserModBase* m_mod = nullptr; public: - CppMod(UE4SSProgram&, UEStringType&& mod_name, UEStringType&& mod_path); + CppMod(UE4SSProgram&, SystemStringType&& mod_name, SystemStringType&& mod_path); CppMod(CppMod&) = delete; CppMod(CppMod&&) = delete; ~CppMod() override; @@ -57,7 +57,7 @@ namespace RC auto fire_on_lua_start(LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, std::vector& hook_luas) -> void; - auto fire_on_lua_stop(UEStringViewType mod_name, + auto fire_on_lua_stop(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -70,6 +70,6 @@ namespace RC auto fire_ui_init() -> void override; auto fire_program_start() -> void override; auto fire_update() -> void override; - auto fire_dll_load(UEStringViewType dll_name) -> void; + auto fire_dll_load(SystemStringViewType dll_name) -> void; }; } // namespace RC diff --git a/UE4SS/include/Mod/CppUserModBase.hpp b/UE4SS/include/Mod/CppUserModBase.hpp index cab82b4b6..e512a317a 100644 --- a/UE4SS/include/Mod/CppUserModBase.hpp +++ b/UE4SS/include/Mod/CppUserModBase.hpp @@ -75,7 +75,7 @@ namespace RC * @param async_lua This is the Lua instance for asynchronous things like ExecuteAsync and ExecuteWithDelay. * @param hook_luas This is a container of Lua instances that are used for game-thread hooks like ExecuteInGameThread. */ - RC_UE4SS_API virtual auto on_lua_start(UEStringViewType mod_name, + RC_UE4SS_API virtual auto on_lua_start(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -106,7 +106,7 @@ namespace RC * @param async_lua This is the Lua instance for asynchronous things like ExecuteAsync and ExecuteWithDelay. * @param hook_luas This is a container of Lua instances that are used for game-thread hooks like ExecuteInGameThread. */ - RC_UE4SS_API virtual auto on_lua_stop(UEStringViewType mod_name, + RC_UE4SS_API virtual auto on_lua_stop(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -128,7 +128,7 @@ namespace RC { } - RC_UE4SS_API virtual auto on_dll_load(UEStringViewType dll_name) -> void + RC_UE4SS_API virtual auto on_dll_load(SystemStringViewType dll_name) -> void { } diff --git a/UE4SS/include/Mod/Mod.hpp b/UE4SS/include/Mod/Mod.hpp index fd921777c..19d8f145d 100644 --- a/UE4SS/include/Mod/Mod.hpp +++ b/UE4SS/include/Mod/Mod.hpp @@ -26,8 +26,9 @@ namespace RC protected: #pragma warning(disable : 4251) - UEStringType m_mod_name; - UEStringType m_mod_path; + // we almost never use this to interact with UE + SystemStringType m_mod_name; + SystemStringType m_mod_path; #pragma warning(default : 4251) protected: @@ -45,7 +46,7 @@ namespace RC }; public: - Mod(UE4SSProgram&, UEStringType&& mod_name, UEStringType&& mod_path); + Mod(UE4SSProgram&, SystemStringType&& mod_name, SystemStringType&& mod_path); virtual ~Mod() = default; public: diff --git a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp index 3c20fb778..744682980 100644 --- a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp +++ b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp @@ -67,14 +67,14 @@ namespace RC::UEGenerator struct PropertyTypeDeclarationContext { - UEStringType context_name; + SystemStringType context_name; class GeneratedSourceFile* source_file; bool is_top_level_declaration; bool* out_is_bitmask_bool; - PropertyTypeDeclarationContext(const UEStringType& context_name, + PropertyTypeDeclarationContext(const SystemStringType& context_name, GeneratedSourceFile* source_file = NULL, bool is_top_level_declaration = false, bool* out_is_bitmask_bool = NULL) @@ -93,10 +93,10 @@ namespace RC::UEGenerator struct StringInsensitiveCompare { - auto operator()(const UEStringType& a, const UEStringType& b) const -> bool + auto operator()(const SystemStringType& a, const SystemStringType& b) const -> bool { #ifdef LINUX - // TODO: Create a case insensitive string compare for Linux + // Create a case insensitive string compare for Linux return strcasecmp(a.c_str(), b.c_str()) < 0; #else return _wcsicmp(a.c_str(), b.c_str()) < 0; @@ -104,15 +104,15 @@ namespace RC::UEGenerator } }; - using CaseInsensitiveSet = ::std::set; + using CaseInsensitiveSet = ::std::set; class GeneratedFile { protected: - UEStringType m_file_base_name; + SystemStringType m_file_base_name; FFilePath m_full_file_path; - UEStringType m_file_contents_buffer; + SystemStringType m_file_contents_buffer; int32_t m_current_indent_count; public: @@ -124,23 +124,23 @@ namespace RC::UEGenerator GeneratedFile(GeneratedFile&&) = default; auto operator=(const GeneratedFile&) -> void = delete; - auto append_line(const UEStringType& line) -> void; - auto append_line_no_indent(const UEStringType& line) -> void; + auto append_line(const SystemStringType& line) -> void; + auto append_line_no_indent(const SystemStringType& line) -> void; auto begin_indent_level() -> void; auto end_indent_level() -> void; auto serialize_file_content_to_disk() -> bool; virtual auto has_content_to_save() const -> bool; - virtual auto generate_file_contents() -> UEStringType; + virtual auto generate_file_contents() -> SystemStringType; }; class GeneratedSourceFile : public GeneratedFile { private: - UEStringType m_file_module_name; + SystemStringType m_file_module_name; ::std::map m_dependencies; - ::std::set m_extra_includes; - mutable ::std::set m_dependency_module_names; + ::std::set m_extra_includes; + mutable ::std::set m_dependency_module_names; UObject* m_object; GeneratedSourceFile* m_header_file; bool m_is_implementation_file; @@ -150,11 +150,11 @@ namespace RC::UEGenerator // workaround for clang tuple bug // https://github.com/llvm/llvm-project/issues/17042 struct attachment_data { - UEStringType property_type; // <0> - UEStringType attach_string; // <1> + SystemStringType property_type; // <0> + SystemStringType attach_string; // <1> bool access_type; // <2> - attachment_data(const UEStringType& property_type, const UEStringType& attach_string, bool access_type) + attachment_data(const SystemStringType& property_type, const SystemStringType& attach_string, bool access_type) : property_type(property_type), attach_string(attach_string), access_type(access_type) { } @@ -165,11 +165,11 @@ namespace RC::UEGenerator auto operator=(attachment_data&&) -> attachment_data& = default; }; - UEStringType m_implementation_constructor; - ::std::unordered_set parent_property_names{}; + SystemStringType m_implementation_constructor; + ::std::unordered_set parent_property_names{}; ::std::map attachments{}; - GeneratedSourceFile(const FFilePath& file_path, const UEStringType& file_module_name, bool is_implementation_file, UObject* object); + GeneratedSourceFile(const FFilePath& file_path, const SystemStringType& file_module_name, bool is_implementation_file, UObject* object); // Delete copy and move constructors and assignment operator GeneratedSourceFile(const GeneratedSourceFile&) = delete; @@ -178,9 +178,9 @@ namespace RC::UEGenerator auto set_header_file(GeneratedSourceFile* header_file) -> void; auto add_dependency_object(UObject* object, DependencyLevel dependency_level) -> void; - auto add_extra_include(const UEStringType& included_file_name) -> void; + auto add_extra_include(const SystemStringType& included_file_name) -> void; - auto get_header_module_name() const -> const UEStringType& + auto get_header_module_name() const -> const SystemStringType& { return m_file_module_name; } @@ -204,30 +204,30 @@ namespace RC::UEGenerator virtual auto has_content_to_save() const -> bool override; - auto copy_dependency_module_names(::std::set& out_dependency_module_names) const -> void + auto copy_dependency_module_names(::std::set& out_dependency_module_names) const -> void { out_dependency_module_names.insert(m_dependency_module_names.begin(), m_dependency_module_names.end()); } auto static create_source_file(const FFilePath& root_dir, - const UEStringType& module_name, - const UEStringType& base_name, + const SystemStringType& module_name, + const SystemStringType& base_name, bool is_implementation_file, UObject* object) -> GeneratedSourceFile; - virtual auto generate_file_contents() -> UEStringType override; + virtual auto generate_file_contents() -> SystemStringType override; protected: auto has_dependency(UObject* object, DependencyLevel dependency_level) -> bool; - auto generate_pre_declarations_string() const -> UEStringType; - auto generate_includes_string() const -> UEStringType; + auto generate_pre_declarations_string() const -> SystemStringType; + auto generate_includes_string() const -> SystemStringType; }; struct UniqueName { static constexpr int32_t HAS_NO_DUPLICATES = 1; - UEStringType name{}; + SystemStringType name{}; int32_t usable_id{HAS_NO_DUPLICATES}; }; @@ -235,22 +235,22 @@ namespace RC::UEGenerator { private: FFilePath m_root_directory; - UEStringType m_primary_module_name; + SystemStringType m_primary_module_name; - ::std::set m_forced_module_dependencies; - ::std::set m_ignored_module_names; - ::std::set m_classes_with_object_initializer; + ::std::set m_forced_module_dependencies; + ::std::set m_ignored_module_names; + ::std::set m_classes_with_object_initializer; - ::std::unordered_map m_underlying_enum_types; - ::std::set m_blueprint_visible_enums; - ::std::set m_blueprint_visible_structs; - ::std::map>> m_module_dependencies; + ::std::unordered_map m_underlying_enum_types; + ::std::set m_blueprint_visible_enums; + ::std::set m_blueprint_visible_structs; + ::std::map>> m_module_dependencies; ::std::vector m_header_files; ::std::unordered_set m_structs_that_need_get_type_hash; // Storage to ensure that we don't have duplicate file names - static ::std::map m_used_file_names; + static ::std::map m_used_file_names; static ::std::map m_dependency_object_to_unique_id; // Storage for class defaultsubojects when populating property initializers @@ -268,8 +268,8 @@ namespace RC::UEGenerator auto dump_native_packages() -> void; auto generate_object_description_file(UObject* object) -> bool; - auto generate_module_build_file(const UEStringType& module_name) -> void; - auto generate_module_implementation_file(const UEStringType& module_name) -> void; + auto generate_module_build_file(const SystemStringType& module_name) -> void; + auto generate_module_implementation_file(const SystemStringType& module_name) -> void; private: auto generate_interface_definition(UClass* function, GeneratedSourceFile& header_data) -> void; @@ -289,7 +289,7 @@ namespace RC::UEGenerator const CaseInsensitiveSet& blacklisted_property_names, bool generate_as_override = false) -> void; - auto generate_property_value(UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const UEStringType& property_scope) + auto generate_property_value(UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const SystemStringType& property_scope) -> void; auto generate_function_implementation(UClass* uclass, UFunction* function, @@ -297,49 +297,49 @@ namespace RC::UEGenerator bool is_generating_interface, const CaseInsensitiveSet& blacklisted_property_names) -> void; - auto generate_interface_flags(UClass* uinterface) const -> UEStringType; - auto generate_class_flags(UClass* uclass) const -> UEStringType; - auto generate_struct_flags(UScriptStruct* script_struct) const -> UEStringType; - auto generate_enum_flags(UEnum* uenum) const -> UEStringType; - auto generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> UEStringType; - auto generate_property_flags(FProperty* property) const -> UEStringType; - auto generate_function_argument_flags(FProperty* property) const -> UEStringType; - auto generate_function_flags(UFunction* function, bool is_function_pure_virtual = false) const -> UEStringType; + auto generate_interface_flags(UClass* uinterface) const -> SystemStringType; + auto generate_class_flags(UClass* uclass) const -> SystemStringType; + auto generate_struct_flags(UScriptStruct* script_struct) const -> SystemStringType; + auto generate_enum_flags(UEnum* uenum) const -> SystemStringType; + auto generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> SystemStringType; + auto generate_property_flags(FProperty* property) const -> SystemStringType; + auto generate_function_argument_flags(FProperty* property) const -> SystemStringType; + auto generate_function_flags(UFunction* function, bool is_function_pure_virtual = false) const -> SystemStringType; auto generate_function_parameter_list(UClass* property, UFunction* function, GeneratedSourceFile& header_data, bool generate_comma_before_name, - const UEStringType& context_name, + const SystemStringType& context_name, const CaseInsensitiveSet& blacklisted_property_names, - int32_t* out_num_params = NULL) -> UEStringType; - auto generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const UEStringType& ContextName) -> UEStringType; + int32_t* out_num_params = NULL) -> SystemStringType; + auto generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType; - auto generate_enum_value(UEnum* uenum, int64_t enum_value) -> UEStringType; + auto generate_enum_value(UEnum* uenum, int64_t enum_value) -> SystemStringType; auto generate_simple_assignment_expression(FProperty* property, - const UEStringType& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const UEStringType& property_scope, - const UEStringType& operator_type = SYSSTR(" = ")) -> void; + const SystemStringType& property_scope, + const SystemStringType& operator_type = SYSSTR(" = ")) -> void; auto generate_advanced_assignment_expression(FProperty* property, - const UEStringType& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const UEStringType& property_scope, - const UEStringType& property_type, - const UEStringType& operator_type = SYSSTR(" = ")) -> void; + const SystemStringType& property_scope, + const SystemStringType& property_type, + const SystemStringType& operator_type = SYSSTR(" = ")) -> void; - auto static generate_parameter_count_string(int32_t parameter_count) -> UEStringType; - auto static determine_primary_game_module_name() -> UEStringType; + auto static generate_parameter_count_string(int32_t parameter_count) -> SystemStringType; + auto static determine_primary_game_module_name() -> SystemStringType; public: - auto add_module_and_sub_module_dependencies(::std::set& out_module_dependencies, const UEStringType& module_name, bool add_self_module = true) + auto add_module_and_sub_module_dependencies(::std::set& out_module_dependencies, const SystemStringType& module_name, bool add_self_module = true) -> void; auto static collect_blacklisted_property_names(UObject* property) -> CaseInsensitiveSet; - auto static generate_object_pre_declaration(UObject* object) -> ::std::vector<::std::vector>; + auto static generate_object_pre_declaration(UObject* object) -> ::std::vector<::std::vector>; - auto static convert_module_name_to_api_name(const UEStringType& module_name) -> UEStringType; - auto static get_module_name_for_package(UObject* package) -> UEStringType; - auto static sanitize_enumeration_name(const UEStringType& enumeration_name) -> UEStringType; + auto static convert_module_name_to_api_name(const SystemStringType& module_name) -> SystemStringType; + auto static get_module_name_for_package(UObject* package) -> SystemStringType; + auto static sanitize_enumeration_name(const SystemStringType& enumeration_name) -> SystemStringType; auto static get_highest_enum(UEnum* uenum) -> int64_t; auto static get_lowest_enum(UEnum* uenum) -> int64_t; @@ -350,8 +350,8 @@ namespace RC::UEGenerator auto static append_access_modifier(GeneratedSourceFile& header_data, AccessModifier needed_access, AccessModifier& current_access) -> void; auto static get_property_access_modifier(FProperty* property) -> AccessModifier; auto static get_function_access_modifier(UFunction* function) -> AccessModifier; - auto static create_string_literal(const UEStringType& string) -> UEStringType; + auto static create_string_literal(const SystemStringType& string) -> SystemStringType; auto static get_header_name_for_object(UObject* object, bool get_existing_header = false) -> SystemStringType; - auto static generate_cross_module_include(UObject* object, const UEStringType& module_name, const UEStringType& fallback_name) -> UEStringType; + auto static generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) -> SystemStringType; }; } // namespace RC::UEGenerator diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index 51ff5a954..e5dfd9724 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -17,7 +17,7 @@ namespace RC public: struct SectionOverrides { - UEStringType ModsFolderPath{}; + SystemStringType ModsFolderPath{}; } Overrides; struct SectionGeneral diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index 9279d31dd..7e21b5cac 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -313,27 +313,27 @@ namespace RC::GUI::Dumpers { Output::send(SYSSTR("Dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); static auto dump_actor_class = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.StaticMeshActor")); - std::wstring file_buffer{}; + UEStringType file_buffer{}; file_buffer.append(generate_actors_csv_file(dump_actor_class)); auto file = File::open(std::format(SYSSTR("{}\\{}-ue4ss_static_mesh_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); - file.write_string_to_file(file_buffer); + file.write_file_string_to_file(to_file(file_buffer)); Output::send(SYSSTR("Finished dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); } void call_generate_all_actor_file() { Output::send(SYSSTR("Dumping CSV of all loaded actor types, positions and mesh properties\n")); - std::wstring file_buffer{}; + UEStringType file_buffer{}; file_buffer.append(generate_actors_csv_file(AActor::StaticClass())); auto file = File::open(std::format(SYSSTR("{}\\{}-ue4ss_actor_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); - file.write_string_to_file(file_buffer); + file.write_file_string_to_file(to_file(file_buffer)); Output::send(SYSSTR("Finished dumping CSV of all loaded actor types, positions and mesh properties\n")); } diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index c5f083ddf..6b3ac426b 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -586,7 +586,7 @@ namespace RC::GUI bool is_legacy = !std::filesystem::exists(working_directory_path) && std::filesystem::exists(legacy_root_directory_path); auto json_file = File::open(is_legacy ? legacy_root_directory_path : working_directory_path, File::OpenFor::Reading, File::OverwriteExistingFile::No, File::CreateIfNonExistent::Yes); - auto json_file_contents = json_file.read_all(); + auto json_file_contents = json_file.read_file_all(); if (json_file_contents.empty()) { return; @@ -680,7 +680,7 @@ namespace RC::GUI File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); int32_t json_indent_level{}; - json_file.write_string_to_file(json.serialize(JSON::ShouldFormat::Yes, &json_indent_level)); + json_file.write_file_string_to_file(to_file(json.serialize(JSON::ShouldFormat::Yes, &json_indent_level))); } static auto save_watches_to_disk() -> void diff --git a/UE4SS/src/LuaType/LuaModRef.cpp b/UE4SS/src/LuaType/LuaModRef.cpp index afa23cc94..75fddb7f7 100644 --- a/UE4SS/src/LuaType/LuaModRef.cpp +++ b/UE4SS/src/LuaType/LuaModRef.cpp @@ -50,7 +50,7 @@ No overload found for function 'SetSharedVariable'. { throw std::runtime_error{error_overload_not_found}; } - auto variable_name = to_system(lua.get_string()); + auto variable_name = to_system_string(lua.get_string()); RC::LuaMod::SharedLuaVariable* currently_stored_value{}; if (auto it = RC::LuaMod::m_shared_lua_variables.find(variable_name); it != RC::LuaMod::m_shared_lua_variables.end()) @@ -159,7 +159,7 @@ No overload found for function 'GetSharedVariable'. { throw std::runtime_error{error_overload_not_found}; } - auto variable_name = to_system(lua.get_string()); + auto variable_name = to_system_string(lua.get_string()); if (auto it = RC::LuaMod::m_shared_lua_variables.find(variable_name); it != RC::LuaMod::m_shared_lua_variables.end()) { diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 46c12761c..13e833d7e 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -12,7 +12,7 @@ namespace RC { - CppMod::CppMod(UE4SSProgram& program, UEStringType&& mod_name, UEStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) + CppMod::CppMod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) { std::filesystem::path m_dlls_path = m_mod_path; @@ -20,7 +20,7 @@ namespace RC if (!std::filesystem::exists(m_dlls_path)) { - Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), to_system(m_mod_name)); + Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), (m_mod_name)); set_installable(false); return; } @@ -68,7 +68,7 @@ namespace RC if (!Output::has_internal_error()) { Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), - to_system_string(std::filesystem::path{m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)) + SYSSTR("\n"), + to_system_string(std::filesystem::path{m_dlls_path} / CONCATENATE_WIDE_STRING("main", DLLEXT)), m_mod_name, e.what()); } @@ -88,7 +88,7 @@ namespace RC } } - auto CppMod::fire_on_lua_start(UEStringViewType mod_name, + auto CppMod::fire_on_lua_start(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -109,7 +109,7 @@ namespace RC } } - auto CppMod::fire_on_lua_stop(UEStringViewType mod_name, + auto CppMod::fire_on_lua_stop(SystemStringViewType mod_name, LuaMadeSimple::Lua& lua, LuaMadeSimple::Lua& main_lua, LuaMadeSimple::Lua& async_lua, @@ -162,7 +162,7 @@ namespace RC } } - auto CppMod::fire_dll_load(UEStringViewType dll_name) -> void + auto CppMod::fire_dll_load(SystemStringViewType dll_name) -> void { if (m_mod) { diff --git a/UE4SS/src/Mod/CppUserModBase.cpp b/UE4SS/src/Mod/CppUserModBase.cpp index 8d6efa925..866c5ec53 100644 --- a/UE4SS/src/Mod/CppUserModBase.cpp +++ b/UE4SS/src/Mod/CppUserModBase.cpp @@ -8,7 +8,7 @@ namespace RC { if (ModIntendedSDKVersion.empty()) { - ModIntendedSDKVersion = std::format(SYSSTR("{}.{}.{}"), UE4SS_LIB_VERSION_MAJOR, UE4SS_LIB_VERSION_MINOR, UE4SS_LIB_VERSION_HOTFIX); + ModIntendedSDKVersion = to_ue(std::format(SYSSTR("{}.{}.{}"), UE4SS_LIB_VERSION_MAJOR, UE4SS_LIB_VERSION_MINOR, UE4SS_LIB_VERSION_HOTFIX)); } } diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 6b3228fa9..40cbf1a8d 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -4107,7 +4107,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } catch (std::runtime_error& e) { - logln(to_system(e.what())); + logln(to_system_string(e.what())); } // We always return true when the console Lua executor is enabled in order to suppress other handlers diff --git a/UE4SS/src/SDKGenerator/Common.cpp b/UE4SS/src/SDKGenerator/Common.cpp index b410fc421..00c87403e 100644 --- a/UE4SS/src/SDKGenerator/Common.cpp +++ b/UE4SS/src/SDKGenerator/Common.cpp @@ -37,28 +37,28 @@ namespace RC::UEGenerator { using namespace Unreal; - auto get_native_class_name(UClass* uclass, bool interface_name) -> UEStringType + auto get_native_class_name(UClass* uclass, bool interface_name) -> SystemStringType { - UEStringType result_string; + SystemStringType result_string; if (interface_name) { - result_string.append(STR("I")); + result_string.append(SYSSTR("I")); } else if (uclass->IsChildOf()) { - result_string.append(STR("A")); + result_string.append(SYSSTR("A")); } else { - result_string.append(STR("U")); + result_string.append(SYSSTR("U")); } if ((uclass->GetClassFlags() & Unreal::CLASS_Deprecated) != 0) { - result_string.append(STR("DEPRECATED_")); + result_string.append(SYSSTR("DEPRECATED_")); } - result_string.append(to_ue(uclass->GetName())); + result_string.append(to_system(uclass->GetName())); return result_string; } @@ -74,35 +74,35 @@ namespace RC::UEGenerator } } - auto get_native_enum_name(UEnum* uenum, bool include_type) -> UEStringType + auto get_native_enum_name(UEnum* uenum, bool include_type) -> SystemStringType { - UEStringType result_string; + SystemStringType result_string; // Seems to be not needed, because enum objects, unlike classes or structs, retain their normal E prefix // ResultString.append(SYSSTR("E")); - result_string.append(to_ue(uenum->GetName())); + result_string.append(to_system(uenum->GetName())); // Namespaced enums need to have ::Type appended for the type if (uenum->GetCppForm() == UEnum::ECppForm::Namespaced && include_type) { - result_string.append(STR("::Type")); + result_string.append(SYSSTR("::Type")); } return result_string; } - auto get_native_struct_name(UScriptStruct* script_struct) -> UEStringType + auto get_native_struct_name(UScriptStruct* script_struct) -> SystemStringType { - UEStringType result_string; + SystemStringType result_string; - result_string.append(STR("F")); - result_string.append(to_ue(script_struct->GetName())); + result_string.append(SYSSTR("F")); + result_string.append(to_system(script_struct->GetName())); return result_string; } - auto sanitize_property_name(const UEStringType& property_name) -> UEStringType + auto sanitize_property_name(const SystemStringType& property_name) -> SystemStringType { - UEStringType resulting_name = property_name; + SystemStringType resulting_name = property_name; // Remove heading underscore, used by private variables in some games if (resulting_name.length() >= 2 && resulting_name[0] == STR('_')) @@ -130,7 +130,7 @@ namespace RC::UEGenerator } auto generate_property_cxx_name(FProperty* property, bool is_top_level_declaration, UObject* class_context, EnableForwardDeclarations enable_forward_declarations) - -> UEStringType + -> SystemStringType { const auto field_class_name = to_system(property->GetClass().GetName()); diff --git a/UE4SS/src/SDKGenerator/Generator.cpp b/UE4SS/src/SDKGenerator/Generator.cpp index ee56e318e..253575d7f 100644 --- a/UE4SS/src/SDKGenerator/Generator.cpp +++ b/UE4SS/src/SDKGenerator/Generator.cpp @@ -677,17 +677,22 @@ namespace RC::UEGenerator } auto generate_file_header(GeneratedFile& generated_file) -> void { - generated_file.primary_file.write_string_to_file( - std::format(SYSSTR("#ifndef UE4SS_SDK_{}_HPP\n#define UE4SS_SDK_{}_HPP\n\n"), generated_file.package_name, generated_file.package_name)); + generated_file.primary_file.write_file_string_to_file( + to_file(std::format(SYSSTR("#ifndef UE4SS_SDK_{}_HPP\n#define UE4SS_SDK_{}_HPP\n\n"), generated_file.package_name, generated_file.package_name)) + ); if (!generated_file.secondary_file_has_no_contents) { - generated_file.primary_file.write_string_to_file(std::format(SYSSTR("#include \"{}\"\n\n"), generated_file.secondary_file_name.filename().c_str())); + generated_file.primary_file.write_file_string_to_file( + to_file(std::format(SYSSTR("#include \"{}\"\n\n"), generated_file.secondary_file_name.filename().c_str())) + ); } } auto generate_file_footer(GeneratedFile& generated_file) -> void { - generated_file.primary_file.write_string_to_file(std::format(SYSSTR("#endif\n"))); + generated_file.primary_file.write_file_string_to_file( + IOSTR(SYSSTR("#endif\n")) + ); } auto generate_enum_declaration(SystemStringType& content_buffer, UEnum* uenum) -> void { @@ -1087,7 +1092,7 @@ namespace RC::UEGenerator } auto generate_file_header(GeneratedFile& generated_file) -> void { - generated_file.primary_file.write_string_to_file(SYSSTR("---@meta\n\n")); + generated_file.primary_file.write_file_string_to_file(IOSTR("---@meta\n\n")); } auto generate_file_footer(GeneratedFile& generated_file) -> void { diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index 18182c4e8..eb1600273 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -136,7 +136,7 @@ namespace RC::UEGenerator } } - auto string_to_uppercase(UEStringType s) -> UEStringType + auto string_to_uppercase(SystemStringType s) -> SystemStringType { std::transform(s.begin(), s.end(), s.begin(), [](wchar_t c) { return towupper(c); @@ -146,8 +146,8 @@ namespace RC::UEGenerator class FlagFormatHelper { - std::set m_switches; - std::map> m_parameters; + std::set m_switches; + std::map> m_parameters; std::shared_ptr m_meta_helper; FlagFormatHelper(bool is_root_helper) @@ -163,14 +163,14 @@ namespace RC::UEGenerator { } - auto add_switch(const UEStringType& switch_name) -> void + auto add_switch(const SystemStringType& switch_name) -> void { m_switches.insert(switch_name); } - auto add_parameter(const UEStringType& parameter_name, const UEStringType& parameter_value) -> void + auto add_parameter(const SystemStringType& parameter_name, const SystemStringType& parameter_value) -> void { - if (parameter_name == STR("meta")) + if (parameter_name == SYSSTR("meta")) { throw std::invalid_argument("Use get_meta() to add metadata to the flag declaration"); } @@ -191,54 +191,54 @@ namespace RC::UEGenerator return m_meta_helper.get(); } - auto build_flag_string() const -> UEStringType + auto build_flag_string() const -> SystemStringType { - UEStringType resulting_string; + SystemStringType resulting_string; - for (const UEStringType& switch_name : m_switches) + for (const SystemStringType& switch_name : m_switches) { resulting_string.append(switch_name); - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(", ")); } for (const auto& parameter_pair : m_parameters) { resulting_string.append(parameter_pair.first); - resulting_string.append(STR("=")); - const std::set& parameter_values = parameter_pair.second; + resulting_string.append(SYSSTR("=")); + const std::set& parameter_values = parameter_pair.second; if (parameter_values.size() != 1) { - resulting_string.append(STR("(")); + resulting_string.append(SYSSTR("(")); - for (const UEStringType& parameter_value : parameter_values) + for (const SystemStringType& parameter_value : parameter_values) { resulting_string.append(parameter_value); - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(", ")); } if (parameter_values.size() != 0) { resulting_string.erase(resulting_string.size() - 1, 1); } - resulting_string.append(STR(")")); + resulting_string.append(SYSSTR(")")); } else { resulting_string.append(*parameter_values.begin()); } - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(", ")); } if (m_meta_helper) { - const UEStringType meta_flag_string = m_meta_helper->build_flag_string(); + const SystemStringType meta_flag_string = m_meta_helper->build_flag_string(); if (!meta_flag_string.empty()) { - resulting_string.append(STR("meta=(")); + resulting_string.append(SYSSTR("meta=(")); resulting_string.append(meta_flag_string); - resulting_string.append(STR(")")); - resulting_string.append(STR(", ")); + resulting_string.append(SYSSTR(")")); + resulting_string.append(SYSSTR(", ")); } } @@ -250,69 +250,71 @@ namespace RC::UEGenerator } }; - auto UEHeaderGenerator::generate_module_build_file(const UEStringType& module_name) -> void + auto UEHeaderGenerator::generate_module_build_file(const SystemStringType& module_name) -> void { - const FFilePath module_file_path = m_root_directory / module_name / std::format(STR("{}.Build.cs"), module_name); + auto module_name_sys = to_system(module_name); + const FFilePath module_file_path = m_root_directory / module_name_sys / std::format(SYSSTR("{}.Build.cs"), module_name_sys); GeneratedFile module_build_file = GeneratedFile(module_file_path); - module_build_file.append_line(STR("using UnrealBuildTool;")); - module_build_file.append_line(STR("")); + module_build_file.append_line(SYSSTR("using UnrealBuildTool;")); + module_build_file.append_line(SYSSTR("")); - module_build_file.append_line(std::format(STR("public class {} : ModuleRules {{"), module_name)); + module_build_file.append_line(std::format(SYSSTR("public class {} : ModuleRules {{"), module_name_sys)); module_build_file.begin_indent_level(); - module_build_file.append_line(std::format(STR("public {}(ReadOnlyTargetRules Target) : base(Target) {{"), module_name)); + module_build_file.append_line(std::format(SYSSTR("public {}(ReadOnlyTargetRules Target) : base(Target) {{"), module_name_sys)); module_build_file.begin_indent_level(); - module_build_file.append_line(STR("PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;")); + module_build_file.append_line(SYSSTR("PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;")); if (Version::IsAtLeast(4, 24)) { - module_build_file.append_line(STR("bLegacyPublicIncludePaths = false;")); - module_build_file.append_line(STR("ShadowVariableWarningLevel = WarningLevel.Warning;")); + module_build_file.append_line(SYSSTR("bLegacyPublicIncludePaths = false;")); + module_build_file.append_line(SYSSTR("ShadowVariableWarningLevel = WarningLevel.Warning;")); } - module_build_file.append_line(STR("")); - module_build_file.append_line(STR("PublicDependencyModuleNames.AddRange(new string[] {")); + module_build_file.append_line(SYSSTR("")); + module_build_file.append_line(SYSSTR("PublicDependencyModuleNames.AddRange(new string[] {")); module_build_file.begin_indent_level(); - std::set all_module_dependencies = this->m_forced_module_dependencies; - std::set clean_module_dependencies{}; + std::set all_module_dependencies = this->m_forced_module_dependencies; + std::set clean_module_dependencies{}; add_module_and_sub_module_dependencies(clean_module_dependencies, module_name, false); all_module_dependencies.insert(clean_module_dependencies.begin(), clean_module_dependencies.end()); - for (const UEStringType& other_module_name : all_module_dependencies) + for (const SystemStringType& other_module_name : all_module_dependencies) { - module_build_file.append_line(std::format(STR("\"{}\","), other_module_name)); + module_build_file.append_line(std::format(SYSSTR("\"{}\","), to_system(other_module_name))); } module_build_file.end_indent_level(); - module_build_file.append_line(STR("});")); + module_build_file.append_line(SYSSTR("});")); module_build_file.end_indent_level(); - module_build_file.append_line(STR("}")); + module_build_file.append_line(SYSSTR("}")); module_build_file.end_indent_level(); - module_build_file.append_line(STR("}")); + module_build_file.append_line(SYSSTR("}")); module_build_file.serialize_file_content_to_disk(); } - auto UEHeaderGenerator::generate_module_implementation_file(const UEStringType& module_name) -> void + auto UEHeaderGenerator::generate_module_implementation_file(const SystemStringType& module_name) -> void { - const FFilePath module_file_path = m_root_directory / module_name / STR("Private") / std::format(STR("{}Module.cpp"), module_name); + auto module_name_sys = to_system(module_name); + const FFilePath module_file_path = m_root_directory / module_name_sys / SYSSTR("Private") / std::format(SYSSTR("{}Module.cpp"), module_name_sys); GeneratedFile module_impl_file = GeneratedFile(module_file_path); - module_impl_file.append_line(STR("#include \"Modules/ModuleManager.h\"")); - module_impl_file.append_line(STR("")); + module_impl_file.append_line(SYSSTR("#include \"Modules/ModuleManager.h\"")); + module_impl_file.append_line(SYSSTR("")); if (module_name != m_primary_module_name) { - module_impl_file.append_line(std::format(STR("IMPLEMENT_MODULE(FDefaultGameModuleImpl, {});"), module_name)); + module_impl_file.append_line(std::format(SYSSTR("IMPLEMENT_MODULE(FDefaultGameModuleImpl, {});"), module_name_sys)); } else { - module_impl_file.append_line(std::format(STR("IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, {}, {});"), module_name, module_name)); + module_impl_file.append_line(std::format(SYSSTR("IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, {}, {});"), module_name_sys, module_name_sys)); } module_impl_file.serialize_file_content_to_disk(); @@ -320,40 +322,40 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_interface_definition(UClass* uclass, GeneratedSourceFile& header_data) -> void { - const UEStringType interface_class_native_name = get_native_class_name(uclass); - const UEStringType interface_flags_string = generate_interface_flags(uclass); + const SystemStringType interface_class_native_name = get_native_class_name(uclass); + const SystemStringType interface_flags_string = generate_interface_flags(uclass); - UEStringType maybe_api_name; + SystemStringType maybe_api_name; if ((uclass->GetClassFlags() & CLASS_RequiredAPI) != 0) { maybe_api_name.append(convert_module_name_to_api_name(header_data.get_header_module_name())); - maybe_api_name.append(STR(" ")); + maybe_api_name.append(SYSSTR(" ")); } UClass* super_class = uclass->GetSuperClass(); header_data.add_dependency_object(super_class, DependencyLevel::Include); - UEStringType parent_interface_class_name = get_native_class_name(super_class); + SystemStringType parent_interface_class_name = get_native_class_name(super_class); // Generate interface UCLASS declaration - header_data.append_line(std::format(STR("UINTERFACE({})"), interface_flags_string)); - header_data.append_line(std::format(STR("class {}{} : public {} {{"), maybe_api_name, interface_class_native_name, parent_interface_class_name)); + header_data.append_line(std::format(SYSSTR("UINTERFACE({})"), interface_flags_string)); + header_data.append_line(std::format(SYSSTR("class {}{} : public {} {{"), maybe_api_name, interface_class_native_name, parent_interface_class_name)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); header_data.end_indent_level(); - header_data.append_line(STR("};")); - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("};")); + header_data.append_line(SYSSTR("")); // Generate interface real class declaration - const UEStringType interface_native_name = get_native_class_name(uclass, true); - const UEStringType parent_interface_name = get_native_class_name(super_class, true); + const SystemStringType interface_native_name = get_native_class_name(uclass, true); + const SystemStringType parent_interface_name = get_native_class_name(super_class, true); - header_data.append_line(std::format(STR("class {}{} : public {} {{"), maybe_api_name, interface_native_name, parent_interface_name)); + header_data.append_line(std::format(SYSSTR("class {}{} : public {} {{"), maybe_api_name, interface_native_name, parent_interface_name)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -370,7 +372,7 @@ namespace RC::UEGenerator } if (NumDelegatesGenerated) { - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("")); } // Generate interface functions @@ -384,30 +386,30 @@ namespace RC::UEGenerator } header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); } auto UEHeaderGenerator::generate_object_definition(UClass* uclass, GeneratedSourceFile& header_data) -> void { - const UEStringType class_native_name = get_native_class_name(uclass); - const UEStringType class_flags_string = generate_class_flags(uclass); + const SystemStringType class_native_name = get_native_class_name(uclass); + const SystemStringType class_flags_string = generate_class_flags(uclass); - UEStringType maybe_api_name; + SystemStringType maybe_api_name; if ((uclass->GetClassFlags() & CLASS_RequiredAPI) != 0) { maybe_api_name.append(convert_module_name_to_api_name(header_data.get_header_module_name())); - maybe_api_name.append(STR(" ")); + maybe_api_name.append(SYSSTR(" ")); } UClass* super_class = uclass->GetSuperClass(); - UEStringType parent_class_name; + SystemStringType parent_class_name; if (super_class) { parent_class_name = get_native_class_name(super_class); } else { - parent_class_name = STR("UObjectBaseUtility"); + parent_class_name = SYSSTR("UObjectBaseUtility"); } if (super_class) @@ -415,23 +417,23 @@ namespace RC::UEGenerator header_data.add_dependency_object(super_class, DependencyLevel::Include); } - UEStringType interface_list_string; + SystemStringType interface_list_string; auto implemented_interfaces = uclass->GetInterfaces(); for (const RC::Unreal::FImplementedInterface& uinterface : implemented_interfaces) { header_data.add_dependency_object(uinterface.Class, DependencyLevel::Include); - const UEStringType interface_name = get_native_class_name(uinterface.Class, true); + const SystemStringType interface_name = get_native_class_name(uinterface.Class, true); - interface_list_string.append(STR(", public ")); + interface_list_string.append(SYSSTR(", public ")); interface_list_string.append(interface_name); } - header_data.append_line(std::format(STR("UCLASS({})"), class_flags_string)); - header_data.append_line(std::format(STR("class {}{} : public {}{} {{"), maybe_api_name, class_native_name, parent_class_name, interface_list_string)); + header_data.append_line(std::format(SYSSTR("UCLASS({})"), class_flags_string)); + header_data.append_line(std::format(SYSSTR("class {}{} : public {}{} {{"), maybe_api_name, class_native_name, parent_class_name, interface_list_string)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -451,7 +453,7 @@ namespace RC::UEGenerator } if (NumDelegatesGenerated) { - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("")); } // Generate properties @@ -475,19 +477,19 @@ namespace RC::UEGenerator append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); // Generate constructor - UEStringType constructor_string; + SystemStringType constructor_string; if (uclass->IsChildOf() || uclass->IsChildOf()) { - constructor_string.append(STR("const FObjectInitializer& ObjectInitializer")); + constructor_string.append(SYSSTR("const FObjectInitializer& ObjectInitializer")); } - header_data.append_line(std::format(STR("{}({});"), class_native_name, constructor_string)); - header_data.append_line_no_indent(STR("")); + header_data.append_line(std::format(SYSSTR("{}({});"), class_native_name, constructor_string)); + header_data.append_line_no_indent(SYSSTR("")); // Generate GetLifetimeReplicatedProps override if we have encountered replicated properties if (encountered_replicated_properties) { - header_data.append_line(STR("virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;")); - header_data.append_line_no_indent(STR("")); + header_data.append_line(SYSSTR("virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;")); + header_data.append_line_no_indent(SYSSTR("")); } // Generate functions @@ -505,8 +507,8 @@ namespace RC::UEGenerator // Generate overrides for all inherited virtual functions if (implemented_interfaces.Num() > 0) { - header_data.append_line_no_indent(STR("")); - header_data.append_line(STR("// Fix for true pure virtual functions not being implemented")); + header_data.append_line_no_indent(SYSSTR("")); + header_data.append_line(SYSSTR("// Fix for true pure virtual functions not being implemented")); } for (const RC::Unreal::FImplementedInterface& uinterface : implemented_interfaces) { @@ -523,33 +525,33 @@ namespace RC::UEGenerator } header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); } auto UEHeaderGenerator::generate_struct_definition(UScriptStruct* script_struct, GeneratedSourceFile& header_data) -> void { - const UEStringType struct_native_name = get_native_struct_name(script_struct); - const UEStringType struct_flags_string = generate_struct_flags(script_struct); + const SystemStringType struct_native_name = get_native_struct_name(script_struct); + const SystemStringType struct_flags_string = generate_struct_flags(script_struct); - UEStringType api_macro_name = convert_module_name_to_api_name(header_data.get_header_module_name()); - api_macro_name.append(STR(" ")); + SystemStringType api_macro_name = convert_module_name_to_api_name(header_data.get_header_module_name()); + api_macro_name.append(SYSSTR(" ")); bool is_struct_exported = (script_struct->GetStructFlags() & STRUCT_RequiredAPI) != 0; UScriptStruct* super_struct = script_struct->GetSuperScriptStruct(); - UEStringType parent_struct_declaration; + SystemStringType parent_struct_declaration; if (super_struct) { header_data.add_dependency_object(super_struct, DependencyLevel::Include); - const UEStringType super_struct_native_name = get_native_struct_name(super_struct); - parent_struct_declaration.append(std::format(STR(" : public {}"), super_struct_native_name)); + const SystemStringType super_struct_native_name = get_native_struct_name(super_struct); + parent_struct_declaration.append(std::format(SYSSTR(" : public {}"), super_struct_native_name)); } - header_data.append_line(std::format(STR("USTRUCT({})"), struct_flags_string)); - header_data.append_line(std::format(STR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : STR(""), struct_native_name, parent_struct_declaration)); + header_data.append_line(std::format(SYSSTR("USTRUCT({})"), struct_flags_string)); + header_data.append_line(std::format(SYSSTR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name, parent_struct_declaration)); header_data.begin_indent_level(); - header_data.append_line(STR("GENERATED_BODY()")); + header_data.append_line(SYSSTR("GENERATED_BODY()")); AccessModifier current_access_modifier = AccessModifier::None; append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); @@ -572,34 +574,34 @@ namespace RC::UEGenerator // Generate constructor and make sure it's public append_access_modifier(header_data, AccessModifier::Public, current_access_modifier); - header_data.append_line(std::format(STR("{}{}();"), !is_struct_exported ? api_macro_name : STR(""), struct_native_name)); + header_data.append_line(std::format(SYSSTR("{}{}();"), !is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name)); header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); } auto UEHeaderGenerator::generate_enum_definition(UEnum* uenum, GeneratedSourceFile& header_data) -> void { - const UEStringType native_enum_name = get_native_enum_name(uenum, false); + const SystemStringType native_enum_name = get_native_enum_name(uenum, false); const int64 highest_enum_value = get_highest_enum(uenum); const bool can_use_uint8_override = (highest_enum_value <= 255 && get_lowest_enum(uenum) >= 0); - const UEStringType enum_flags_string = generate_enum_flags(uenum); + const SystemStringType enum_flags_string = generate_enum_flags(uenum); const auto underlying_type = m_underlying_enum_types.find(native_enum_name); const bool has_known_underlying_type = underlying_type != m_underlying_enum_types.end(); UEnum::ECppForm cpp_form = uenum->GetCppForm(); bool enum_is_uint8{false}; - header_data.append_line(std::format(STR("UENUM({})"), enum_flags_string)); + header_data.append_line(std::format(SYSSTR("UENUM({})"), enum_flags_string)); if (cpp_form == UEnum::ECppForm::Namespaced) { - header_data.append_line(std::format(STR("namespace {} {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("namespace {} {{"), native_enum_name)); header_data.begin_indent_level(); - header_data.append_line(STR("enum Type {")); + header_data.append_line(SYSSTR("enum Type {")); } else if (cpp_form == UEnum::ECppForm::Regular) { - header_data.append_line(std::format(STR("enum {} {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("enum {} {{"), native_enum_name)); } else if (cpp_form == UEnum::ECppForm::EnumClass) { @@ -607,33 +609,33 @@ namespace RC::UEGenerator { if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeEnumClassesBlueprintType && can_use_uint8_override) { - header_data.append_line(std::format(STR("enum class {} : uint8 {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("enum class {} : uint8 {{"), native_enum_name)); enum_is_uint8 = true; } else { // Enum has never been used in any native classes or structures, go with implicit type - header_data.append_line(std::format(STR("enum class {} {{"), native_enum_name)); + header_data.append_line(std::format(SYSSTR("enum class {} {{"), native_enum_name)); } } else { - UEStringType underlying_type_string = underlying_type->second; + SystemStringType underlying_type_string = underlying_type->second; - header_data.append_line(std::format(STR("enum class {} : {} {{"), native_enum_name, underlying_type_string)); + header_data.append_line(std::format(SYSSTR("enum class {} : {} {{"), native_enum_name, underlying_type_string)); } } header_data.begin_indent_level(); - UEStringType enum_prefix = uenum->GenerateEnumPrefix(); + auto enum_prefix = uenum->GenerateEnumPrefix(); int64 expected_next_enum_value = 0; bool last_value_was_negative_one{false}; std::set enum_name_set{}; for (auto [Name, Value] : uenum->ForEachName()) { - UEStringType enum_name = Name.ToString(); - auto result_enumeration_line = sanitize_enumeration_name((enum_name)); + auto enum_name = Name.ToString(); + auto result_enumeration_line = sanitize_enumeration_name(to_system_string(enum_name)); auto pre_append_result_line = result_enumeration_line; // If an enum name is listed in the array twice, that likely means it is used as the value for another enum. Long story short, don't print it. @@ -651,23 +653,23 @@ namespace RC::UEGenerator auto first_name_with_value = uenum->GetNameByValue(Value).ToString(); if (first_name_with_value != Name.ToString()) { - result_enumeration_line.append(std::format(STR(" = {}"), sanitize_enumeration_name((first_name_with_value)))); + result_enumeration_line.append(std::format(SYSSTR(" = {}"), sanitize_enumeration_name(to_system_string(first_name_with_value)))); } else if (Value != expected_next_enum_value || last_value_was_negative_one) { - const auto CastString = (enum_is_uint8 && Value < 0) ? STR("(uint8)") : STR(""); - const auto MinusSign = Value < 0 ? STR("-") : STR(""); - result_enumeration_line.append(std::format(STR(" = {}{}{}"), CastString, MinusSign, Value < 0 ? -Value : Value)); + const auto CastString = (enum_is_uint8 && Value < 0) ? SYSSTR("(uint8)") : SYSSTR(""); + const auto MinusSign = Value < 0 ? SYSSTR("-") : SYSSTR(""); + result_enumeration_line.append(std::format(SYSSTR(" = {}{}{}"), CastString, MinusSign, Value < 0 ? -Value : Value)); } expected_next_enum_value = Value + 1; last_value_was_negative_one = (Value == -1); - UEStringType pre_append_result_line_lower = pre_append_result_line; + SystemStringType pre_append_result_line_lower = pre_append_result_line; std::transform(pre_append_result_line_lower.begin(), pre_append_result_line_lower.end(), pre_append_result_line_lower.begin(), ::towlower); - if (pre_append_result_line_lower.ends_with(STR("_max"))) + if (pre_append_result_line_lower.ends_with(SYSSTR("_max"))) { - const auto expected_full_constant_name = std::format(STR("{}_MAX"), to_system(enum_prefix)); - UEStringType expected_full_constant_name_lower = expected_full_constant_name; + const auto expected_full_constant_name = std::format(SYSSTR("{}_MAX"), to_system(enum_prefix)); + SystemStringType expected_full_constant_name_lower = expected_full_constant_name; std::transform(expected_full_constant_name_lower.begin(), expected_full_constant_name_lower.end(), expected_full_constant_name_lower.begin(), ::towlower); int64_t expected_max_value = highest_enum_value + 1; @@ -679,33 +681,33 @@ namespace RC::UEGenerator continue; } // Otherwise, just make sure it's hidden and not visible to the end user - result_enumeration_line.append(STR(" UMETA(Hidden)")); + result_enumeration_line.append(SYSSTR(" UMETA(Hidden)")); } - result_enumeration_line.append(STR(",")); + result_enumeration_line.append(SYSSTR(",")); header_data.append_line(result_enumeration_line); } header_data.end_indent_level(); - header_data.append_line(STR("};")); + header_data.append_line(SYSSTR("};")); if (cpp_form == UEnum::ECppForm::Namespaced) { header_data.end_indent_level(); - header_data.append_line(STR("}")); + header_data.append_line(SYSSTR("}")); } } auto UEHeaderGenerator::generate_delegate_type_declaration(UFunction* signature_function, UClass* delegate_class, GeneratedSourceFile& header_data) -> void { - UEStringType owning_class; + SystemStringType owning_class; if (delegate_class == nullptr) { - owning_class = STR("UObject*"); + owning_class = SYSSTR("UObject*"); } else { - owning_class = (delegate_class->GetNamePrivate().ToString()); + owning_class = to_system(delegate_class->GetNamePrivate().ToString()); } auto function_flags = signature_function->GetFunctionFlags(); @@ -720,52 +722,52 @@ namespace RC::UEGenerator const bool is_multicast = (function_flags & Unreal::FUNC_MulticastDelegate) != 0; const bool declared_const = (function_flags & FUNC_Const) != 0; - const UEStringType delegate_type_name = get_native_delegate_type_name(signature_function, nullptr, true); + const SystemStringType delegate_type_name = get_native_delegate_type_name(signature_function, nullptr, true); FProperty* return_value_property = signature_function->GetReturnProperty(); - UEStringType delegate_macro_string; + SystemStringType delegate_macro_string; // Delegate macro declaration is only allowed on the top level delegates, class-based types are limited to being implicit if (signature_function->GetOuterPrivate()->IsA()) { - delegate_macro_string.append(STR("UDELEGATE(")); + delegate_macro_string.append(SYSSTR("UDELEGATE(")); delegate_macro_string.append(generate_function_flags(signature_function)); - delegate_macro_string.append(STR(") ")); + delegate_macro_string.append(SYSSTR(") ")); } PropertyTypeDeclarationContext context(delegate_type_name, &header_data); int32_t num_delegate_parameters = 0; - UEStringType delegate_parameter_list = + SystemStringType delegate_parameter_list = generate_function_parameter_list(nullptr, signature_function, header_data, true, context.context_name, {}, &num_delegate_parameters); if (num_delegate_parameters > 0) { - delegate_parameter_list.insert(0, STR(", ")); + delegate_parameter_list.insert(0, SYSSTR(", ")); } if (num_delegate_parameters > 9) { - Output::send(STR("Invalid delegate parameter count in Delegate: {}. Using _TooMany\n"), delegate_type_name); + Output::send(SYSSTR("Invalid delegate parameter count in Delegate: {}. Using _TooMany\n"), delegate_type_name); } - UEStringType return_value_declaration; + SystemStringType return_value_declaration; if (return_value_property != NULL) { return_value_declaration = generate_property_type_declaration(return_value_property, context); - return_value_declaration.append(STR(", ")); + return_value_declaration.append(SYSSTR(", ")); } - UEStringType delegate_declaration_string = std::format(STR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), + SystemStringType delegate_declaration_string = std::format(SYSSTR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), delegate_macro_string, - is_multicast ? STR("_MULTICAST") : STR(""), - is_sparse ? STR("_SPARSE") : STR(""), - return_value_property ? STR("_RetVal") : STR(""), + is_multicast ? SYSSTR("_MULTICAST") : SYSSTR(""), + is_sparse ? SYSSTR("_SPARSE") : SYSSTR(""), + return_value_property ? SYSSTR("_RetVal") : SYSSTR(""), generate_parameter_count_string(num_delegate_parameters), - declared_const ? STR("_Const") : STR(""), + declared_const ? SYSSTR("_Const") : SYSSTR(""), return_value_declaration, delegate_type_name, // TODO: Actually get delegate property name. - is_sparse ? std::format(STR("{}, {}"), owning_class, STR("EnterPropertyName")) : STR(""), + is_sparse ? std::format(SYSSTR("{}, {}"), owning_class, SYSSTR("EnterPropertyName")) : SYSSTR(""), delegate_parameter_list); header_data.append_line(delegate_declaration_string); @@ -773,32 +775,32 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_object_implementation(UClass* uclass, GeneratedSourceFile& implementation_file) -> void { - const UEStringType class_native_name = get_native_class_name(uclass); + auto class_native_name = get_native_class_name(uclass); - UEStringType constructor_content_string; - UEStringType constructor_postfix_string; + SystemStringType constructor_content_string; + SystemStringType constructor_postfix_string; UClass* super_class = uclass->GetSuperClass(); - const UEStringType native_parent_class_name = super_class ? get_native_class_name(super_class) : STR("UObjectUtility"); + const SystemStringType native_parent_class_name = super_class ? get_native_class_name(super_class) : SYSSTR("UObjectUtility"); // Generate constructor implementation except for overrides. // If class is a child of AActor we add the UObjectInitializer constructor. // This may not be required in all cases, but is necessary to override subcomponents and does not hurt anything. - UEStringType object_initializer_overrides; + SystemStringType object_initializer_overrides; if (uclass->IsChildOf() || uclass->IsChildOf()) { - constructor_content_string.append(STR("const FObjectInitializer& ObjectInitializer")); - constructor_postfix_string.append(std::format(STR(") : Super(ObjectInitializer{}"), object_initializer_overrides)); + constructor_content_string.append(SYSSTR("const FObjectInitializer& ObjectInitializer")); + constructor_postfix_string.append(std::format(SYSSTR(") : Super(ObjectInitializer{}"), object_initializer_overrides)); } // If parent class contains the UObjectInitializer constructor without default value, // we need to create the explicit call to such constructor and pass UObjectInitializer::Get() as the argument. else if (m_classes_with_object_initializer.contains(native_parent_class_name)) { - constructor_postfix_string.append(std::format(STR(") : {}(FObjectInitializer::Get()"), native_parent_class_name)); + constructor_postfix_string.append(std::format(SYSSTR(") : {}(FObjectInitializer::Get()"), native_parent_class_name)); } implementation_file.m_implementation_constructor.append( - std::format(STR("{}::{}({}{}"), class_native_name, class_native_name, constructor_content_string, constructor_postfix_string)); + std::format(SYSSTR("{}::{}({}{}"), class_native_name, class_native_name, constructor_content_string, constructor_postfix_string)); implementation_file.begin_indent_level(); @@ -809,12 +811,12 @@ namespace RC::UEGenerator { for (FProperty* property : uclass->OrderedForEachPropertyInChain()) { - generate_property_value(uclass, property, class_default_object, implementation_file, STR("this->")); + generate_property_value(uclass, property, class_default_object, implementation_file, SYSSTR("this->")); } } else { - implementation_file.append_line(STR("// Null default object.")); + implementation_file.append_line(SYSSTR("// Null default object.")); } m_class_subobjects.clear(); @@ -823,20 +825,20 @@ namespace RC::UEGenerator { if ((attachment.second).access_type == false) { - generate_simple_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, STR("this->"), STR("->")); + generate_simple_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, SYSSTR("this->"), SYSSTR("->")); } else { - generate_advanced_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, STR("this->"), (attachment.second).property_type, STR("->")); + generate_advanced_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, SYSSTR("this->"), (attachment.second).property_type, SYSSTR("->")); } } implementation_file.end_indent_level(); - implementation_file.append_line(STR("}\n")); + implementation_file.append_line(SYSSTR("}\n")); // Finalize constructor. We do this after the property generation because we need information from the properties // to determine the required overrides within the constructor. - implementation_file.m_implementation_constructor.append(STR(") {")); + implementation_file.m_implementation_constructor.append(SYSSTR(") {")); CaseInsensitiveSet blacklisted_property_names = collect_blacklisted_property_names(uclass); @@ -846,7 +848,7 @@ namespace RC::UEGenerator if (!is_delegate_signature_function(function)) { generate_function_implementation(uclass, function, implementation_file, false, blacklisted_property_names); - implementation_file.append_line(STR("")); + implementation_file.append_line(SYSSTR("")); } } @@ -860,35 +862,35 @@ namespace RC::UEGenerator // Generate replicated properties implementation if we really need it if (encountered_replicated_properties) { - implementation_file.add_extra_include(STR("Net/UnrealNetwork.h")); + implementation_file.add_extra_include(SYSSTR("Net/UnrealNetwork.h")); implementation_file.append_line( - std::format(STR("void {}::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const {{"), class_native_name)); + std::format(SYSSTR("void {}::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const {{"), class_native_name)); implementation_file.begin_indent_level(); - implementation_file.append_line(STR("Super::GetLifetimeReplicatedProps(OutLifetimeProps);")); - implementation_file.append_line(STR("")); + implementation_file.append_line(SYSSTR("Super::GetLifetimeReplicatedProps(OutLifetimeProps);")); + implementation_file.append_line(SYSSTR("")); for (FProperty* property : uclass->ForEachProperty()) { if ((property->GetPropertyFlags() & CPF_Net) != 0) { - implementation_file.append_line(std::format(STR("DOREPLIFETIME({}, {});"), class_native_name, (property->GetName()))); + implementation_file.append_line(std::format(SYSSTR("DOREPLIFETIME({}, {});"), class_native_name, to_system(property->GetName()))); } } implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); - implementation_file.append_line(STR("")); + implementation_file.append_line(SYSSTR("}")); + implementation_file.append_line(SYSSTR("")); } } auto UEHeaderGenerator::generate_struct_implementation(UScriptStruct* script_struct, GeneratedSourceFile& implementation_file) -> void { - const UEStringType struct_native_name = get_native_struct_name(script_struct); + const SystemStringType struct_native_name = get_native_struct_name(script_struct); // Generate constructor implementation and initialize properties inside - implementation_file.m_implementation_constructor.append(std::format(STR("{}::{}() {{"), struct_native_name, struct_native_name)); + implementation_file.m_implementation_constructor.append(std::format(SYSSTR("{}::{}() {{"), struct_native_name, struct_native_name)); implementation_file.begin_indent_level(); // Generate properties @@ -899,26 +901,26 @@ namespace RC::UEGenerator for (FProperty* property : script_struct->OrderedForEachPropertyInChain()) { - generate_property_value(script_struct, property, struct_default_object, implementation_file, STR("this->")); + generate_property_value(script_struct, property, struct_default_object, implementation_file, SYSSTR("this->")); } // TODO: ScriptStruct->DestroyStruct(StructDefaultObject); free(struct_default_object); implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); + implementation_file.append_line(SYSSTR("}")); } auto UEHeaderGenerator::generate_property(UObject* uclass, FProperty* property, GeneratedSourceFile& header_data) -> void { - const UEStringType property_flags_string = generate_property_flags(property); + const SystemStringType property_flags_string = generate_property_flags(property); bool is_bitmask_bool = false; - PropertyTypeDeclarationContext Context((uclass->GetName()), &header_data, true, &is_bitmask_bool); + PropertyTypeDeclarationContext Context(to_system(uclass->GetName()), &header_data, true, &is_bitmask_bool); - UEStringType property_type_string{}; + SystemStringType property_type_string{}; bool type_is_valid = true; - UEStringType error_string{}; + SystemStringType error_string{}; try { property_type_string = generate_property_type_declaration(property, Context); @@ -931,29 +933,29 @@ namespace RC::UEGenerator if (!type_is_valid) { - Output::send(STR("Warning: {}\n"), error_string); - header_data.append_line(std::format(STR("// UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(STR("// Missed Property: {}"), (property->GetName()))); - header_data.append_line(std::format(STR("// {}"), error_string)); - header_data.append_line(STR("")); + Output::send(SYSSTR("Warning: {}\n"), error_string); + header_data.append_line(std::format(SYSSTR("// UPROPERTY({})"), property_flags_string)); + header_data.append_line(std::format(SYSSTR("// Missed Property: {}"), to_system(property->GetName()))); + header_data.append_line(std::format(SYSSTR("// {}"), error_string)); + header_data.append_line(SYSSTR("")); return; } - UEStringType property_extra_declaration; + SystemStringType property_extra_declaration; if (property->GetArrayDim() != 1) { - property_extra_declaration.append(STR("[")); - property_extra_declaration.append(to_ue(std::to_string(property->GetArrayDim()))); - property_extra_declaration.append(STR("]")); + property_extra_declaration.append(SYSSTR("[")); + property_extra_declaration.append(to_system(std::to_string(property->GetArrayDim()))); + property_extra_declaration.append(SYSSTR("]")); } else if (is_bitmask_bool) { - property_extra_declaration.append(STR(": 1")); + property_extra_declaration.append(SYSSTR(": 1")); } - header_data.append_line(std::format(STR("UPROPERTY({})"), property_flags_string)); - header_data.append_line(std::format(STR("{} {}{};"), property_type_string, (property->GetName()), property_extra_declaration)); - header_data.append_line(STR("")); + header_data.append_line(std::format(SYSSTR("UPROPERTY({})"), property_flags_string)); + header_data.append_line(std::format(SYSSTR("{} {}{};"), property_type_string, to_system(property->GetName()), property_extra_declaration)); + header_data.append_line(SYSSTR("")); } // TODO FUNC_Final is not properly handled (should be always set except some weird cases) @@ -965,90 +967,90 @@ namespace RC::UEGenerator bool generate_as_override) -> void { auto function_flags = function->GetFunctionFlags(); - const UEStringType context_name = uclass->GetName(); + const auto context_name = uclass->GetName(); bool is_function_pure_virtual = generate_as_override; - UEStringType function_modifier_string; + SystemStringType function_modifier_string; if ((function_flags & FUNC_Static) != 0) { - function_modifier_string.append(STR("static ")); + function_modifier_string.append(SYSSTR("static ")); } else if ((function_flags & FUNC_BlueprintEvent) == 0 && is_generating_interface) { // When we have a blueprint function that is not blueprint event inside the interface, // it means we are dealing with the native interface that cannot be implemented via blueprints // and uses pure virtual functions implemented through native code - function_modifier_string.append(STR("virtual ")); + function_modifier_string.append(SYSSTR("virtual ")); is_function_pure_virtual = true; } FProperty* return_property = function->GetReturnProperty(); - UEStringType return_property_string; + SystemStringType return_property_string; if (return_property != NULL) { - PropertyTypeDeclarationContext context((uclass->GetName()), &header_data); + PropertyTypeDeclarationContext context(to_system(uclass->GetName()), &header_data); return_property_string = generate_property_type_declaration(return_property, context); } else { - return_property_string = STR("void"); + return_property_string = SYSSTR("void"); } - UEStringType function_extra_postfix_string; + SystemStringType function_extra_postfix_string; if ((function_flags & FUNC_Const) != 0) { - function_extra_postfix_string.append(STR(" const")); + function_extra_postfix_string.append(SYSSTR(" const")); } if (is_function_pure_virtual) { - UEStringType return_statement_string; + SystemStringType return_statement_string; if (return_property != NULL) { - const auto default_property_value = generate_default_property_value(return_property, header_data, (context_name)); - return_statement_string = std::format(STR(" return {};"), default_property_value); + const auto default_property_value = generate_default_property_value(return_property, header_data, to_system_string(context_name)); + return_statement_string = std::format(SYSSTR(" return {};"), default_property_value); } if (generate_as_override) { - function_extra_postfix_string.append(STR(" override")); + function_extra_postfix_string.append(SYSSTR(" override")); } - function_extra_postfix_string.append(std::format(STR(" PURE_VIRTUAL({},{})"), (function->GetName()), return_statement_string)); + function_extra_postfix_string.append(std::format(SYSSTR(" PURE_VIRTUAL({},{})"), to_system(function->GetName()), return_statement_string)); } - auto function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, (context_name), blacklisted_property_names); + auto function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, to_system_string(context_name), blacklisted_property_names); const auto function_flags_string = generate_function_flags(function, is_function_pure_virtual); - header_data.append_line(std::format(STR("UFUNCTION({})"), function_flags_string)); + header_data.append_line(std::format(SYSSTR("UFUNCTION({})"), function_flags_string)); // Format for virtual functions // virtual () PURE_VIRTUAL(, ) - header_data.append_line(std::format(STR("{}{} {}({}){};"), + header_data.append_line(std::format(SYSSTR("{}{} {}({}){};"), function_modifier_string, return_property_string, - (function->GetName()), + to_system(function->GetName()), function_argument_list, function_extra_postfix_string)); - header_data.append_line(STR("")); + header_data.append_line(SYSSTR("")); } - auto UEHeaderGenerator::generate_enum_value(UEnum* uenum, int64_t enum_value) -> UEStringType + auto UEHeaderGenerator::generate_enum_value(UEnum* uenum, int64_t enum_value) -> SystemStringType { UEnum::ECppForm cpp_form = uenum->GetCppForm(); - const UEStringType enum_native_name = get_native_enum_name(uenum, false); + const SystemStringType enum_native_name = get_native_enum_name(uenum, false); - UEStringType enum_constant_name; + SystemStringType enum_constant_name; for (auto [Name, Value] : uenum->ForEachName()) { if (Value == enum_value) { - enum_constant_name = sanitize_enumeration_name((Name.ToString())); + enum_constant_name = sanitize_enumeration_name(to_system_string(Name.ToString())); } } if (enum_constant_name.empty()) { - Output::send(STR("Warning: Invalid value for enum '{}', casting instead of using enum name. Value '{}' will be cast to the enum.\n"), + Output::send(SYSSTR("Warning: Invalid value for enum '{}', casting instead of using enum name. Value '{}' will be cast to the enum.\n"), enum_native_name, enum_value); - return std::format(STR("({}){}"), enum_native_name, enum_value); + return std::format(SYSSTR("({}){}"), enum_native_name, enum_value); } else { @@ -1057,57 +1059,57 @@ namespace RC::UEGenerator { return enum_constant_name; } - return std::format(STR("{}::{}"), enum_native_name, enum_constant_name); + return std::format(SYSSTR("{}::{}"), enum_native_name, enum_constant_name); } } auto UEHeaderGenerator::generate_simple_assignment_expression(FProperty* property, - const UEStringType& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const UEStringType& property_scope, - const UEStringType& operator_type) -> void + const SystemStringType& property_scope, + const SystemStringType& operator_type) -> void { - const auto field_class_name = (property->GetName()); + const auto field_class_name = to_system(property->GetName()); if (property->GetArrayDim() == 1) { - implementation_file.append_line(std::format(STR("{}{}{}{};"), property_scope, field_class_name, operator_type, value)); + implementation_file.append_line(std::format(SYSSTR("{}{}{}{};"), property_scope, field_class_name, operator_type, value)); } else { for (int32_t i = 0; i < property->GetArrayDim(); i++) { - implementation_file.append_line(std::format(STR("{}{}[{}]{}{};"), property_scope, field_class_name, i, operator_type, value)); + implementation_file.append_line(std::format(SYSSTR("{}{}[{}]{}{};"), property_scope, field_class_name, i, operator_type, value)); } } } auto UEHeaderGenerator::generate_advanced_assignment_expression(FProperty* property, - const UEStringType& value, + const SystemStringType& value, GeneratedSourceFile& implementation_file, - const UEStringType& property_scope, - const UEStringType& property_type, - const UEStringType& operator_type) -> void + const SystemStringType& property_scope, + const SystemStringType& property_type, + const SystemStringType& operator_type) -> void { - const auto field_class_name = (property->GetName()); - implementation_file.append_line(std::format(STR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); + const auto field_class_name = to_system(property->GetName()); + implementation_file.append_line(std::format(SYSSTR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); if (property->GetArrayDim() == 1) { - implementation_file.append_line(std::format(STR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); + implementation_file.append_line(std::format(SYSSTR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); } else { for (int32_t i = 0; i < property->GetArrayDim(); i++) { implementation_file.append_line( - std::format(STR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), field_class_name, property_scope, field_class_name, i, operator_type, value)); + std::format(SYSSTR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), field_class_name, property_scope, field_class_name, i, operator_type, value)); } } } auto UEHeaderGenerator::generate_property_value( - UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const UEStringType& property_scope) -> void + UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const SystemStringType& property_scope) -> void { - const UEStringType property_name = property->GetName(); + const auto property_name = property->GetName(); if (property_name == STR("NativeClass") || property_name == STR("hudClass")) { return; } const bool private_access_modifier = get_property_access_modifier(property) == AccessModifier::Private; bool super_and_no_access = false; @@ -1115,7 +1117,7 @@ namespace RC::UEGenerator UStruct* super; void* super_object = nullptr; FProperty* super_property = nullptr; - const UEStringType property_type = generate_property_cxx_name(property, true, ustruct); + const auto property_type = generate_property_cxx_name(property, true, ustruct); auto as_class = Cast(ustruct); if (as_class) { @@ -1156,10 +1158,10 @@ namespace RC::UEGenerator } UEnum* uenum = byte_property->GetEnum(); - UEStringType result_property_value; + SystemStringType result_property_value; if (uenum != NULL) { - const UEStringType enum_type_name = get_native_enum_name(uenum); + const SystemStringType enum_type_name = get_native_enum_name(uenum); result_property_value = generate_enum_value(uenum, *byte_property_value); } else @@ -1167,7 +1169,7 @@ namespace RC::UEGenerator #ifdef WIN32 result_property_value = std::to_wstring(*byte_property_value); #else - result_property_value = to_ue(std::to_string(*byte_property_value)); + result_property_value = std::to_string(*byte_property_value); #endif } @@ -1208,7 +1210,7 @@ namespace RC::UEGenerator } implementation_file.add_dependency_object(uenum, DependencyLevel::Include); - UEStringType result_property_value = generate_enum_value(uenum, value); + SystemStringType result_property_value = generate_enum_value(uenum, value); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1250,7 +1252,7 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - const UEStringType result_property_value = result_bool_value ? STR("true") : STR("false"); + const SystemStringType result_property_value = result_bool_value ? SYSSTR("true") : SYSSTR("false"); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1284,7 +1286,7 @@ namespace RC::UEGenerator if (name_value_string != STR("None")) { - const UEStringType result_property_value = std::format(STR("TEXT(\"{}\")"), name_value_string); + const auto result_property_value = std::format(SYSSTR("TEXT(\"{}\")"), to_system(name_value_string)); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1301,13 +1303,13 @@ namespace RC::UEGenerator if (property->IsA()) { FString* string_value = property->ContainerPtrToValuePtr(object); - const auto string_value_string = (UEStringType (string_value->GetCharArray())); + const auto string_value_string = (to_system (string_value->GetCharArray())); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FString* super_string_value = super_property->ContainerPtrToValuePtr(super_object); - const auto super_string_value_string = (UEStringType (super_string_value->GetCharArray())); + const auto super_string_value_string = (to_system (super_string_value->GetCharArray())); if (string_value_string == super_string_value_string) { return; @@ -1315,9 +1317,9 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - if (string_value_string != STR("")) + if (string_value_string != SYSSTR("")) { - const UEStringType result_value = create_string_literal(string_value_string); + const SystemStringType result_value = create_string_literal(string_value_string); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_value, implementation_file, property_scope); @@ -1350,7 +1352,7 @@ namespace RC::UEGenerator if (text_value_string != STR("")) { - const auto result_property_value = std::format(STR("FText::FromString({})"), create_string_literal((text_value_string))); + const auto result_property_value = std::format(SYSSTR("FText::FromString({})"), create_string_literal(to_system(text_value_string))); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_property_value, implementation_file, property_scope); @@ -1386,11 +1388,11 @@ namespace RC::UEGenerator // If class value is NULL, generate a simple NULL assignment if (!super_and_no_access) { - generate_simple_assignment_expression(property, STR("NULL"), implementation_file, property_scope); + generate_simple_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope); } else { - generate_advanced_assignment_expression(property, STR("NULL"), implementation_file, property_scope, property_type); + generate_advanced_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope, property_type); } } else if ((class_value->GetClassFlags() & CLASS_Native) != 0) @@ -1398,8 +1400,8 @@ namespace RC::UEGenerator implementation_file.add_dependency_object(class_value, DependencyLevel::Include); // Otherwise, generate StaticClass call, assuming the class is native - const UEStringType object_class_name = get_native_class_name(class_value); - const UEStringType initializer = std::format(STR("{}::StaticClass()"), object_class_name); + const SystemStringType object_class_name = get_native_class_name(class_value); + const SystemStringType initializer = std::format(SYSSTR("{}::StaticClass()"), object_class_name); if (!super_and_no_access) { @@ -1413,7 +1415,7 @@ namespace RC::UEGenerator else { // Unhandled case, reference to the non-native blueprint class potentially? - Output::send(STR("Unhandled default value of the FClassProperty {}: {}\n"), (property->GetFullName()), (class_value->GetFullName())); + Output::send(SYSSTR("Unhandled default value of the FClassProperty {}: {}\n"), (property->GetFullName()), (class_value->GetFullName())); } return; } @@ -1444,11 +1446,11 @@ namespace RC::UEGenerator // TODO: Needs additional checks to see if the class is abstract to potentially change this to a default object init if (!super_and_no_access) { - generate_simple_assignment_expression(property, STR("NULL"), implementation_file, property_scope); + generate_simple_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope); } else { - generate_advanced_assignment_expression(property, STR("NULL"), implementation_file, property_scope, property_type); + generate_advanced_assignment_expression(property, SYSSTR("NULL"), implementation_file, property_scope, property_type); } return; } @@ -1472,7 +1474,7 @@ namespace RC::UEGenerator } bool parent_component_found = false; - UEStringType prior_property_variable{}; + SystemStringType prior_property_variable{}; // Check to see if any other property in the super initialized a component with the same name to ensure // we are not creating the subobject in a child class unnecessarily. @@ -1499,33 +1501,33 @@ namespace RC::UEGenerator // Generate an initializer by either setting this property to a pre-existing property // overriding the object class of an existing component, or creating a new default subobject - UEStringType initializer{}; + SystemStringType initializer{}; if (auto it = m_class_subobjects.find(object_name); it != m_class_subobjects.end()) { // Set property to equal previous property referencing the same object - initializer = it->second; - FProperty* prior_property = ustruct->GetPropertyByNameInChain(to_ue(initializer).c_str()); + initializer = to_system(it->second); + FProperty* prior_property = ustruct->GetPropertyByNameInChain(it->second.c_str()); bool prior_private = get_property_access_modifier(prior_property) == AccessModifier::Private; if (prior_private) { UObject* check_sub_object_value = *prior_property->ContainerPtrToValuePtr(object); - UEStringType prior_prop_class_name = STR("NULL"); + SystemStringType prior_prop_class_name = SYSSTR("NULL"); if (check_sub_object_value->GetClassPrivate() != nullptr) { prior_prop_class_name = get_native_class_name(check_sub_object_value->GetClassPrivate()); } implementation_file.append_line( - std::format(STR("FProperty* p_{}_Prior = GetClass()->FindPropertyByName(\"{}\");"), initializer, initializer)); - initializer = std::format(STR("*p_{}_Prior->ContainerPtrToValuePtr<{}*>(this)"), initializer, prior_prop_class_name); + std::format(SYSSTR("FProperty* p_{}_Prior = GetClass()->FindPropertyByName(\"{}\");"), initializer, initializer)); + initializer = std::format(SYSSTR("*p_{}_Prior->ContainerPtrToValuePtr<{}*>(this)"), initializer, prior_prop_class_name); } if (!super_and_no_access) { - initializer = std::format(STR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); + initializer = std::format(SYSSTR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); } else { - initializer = std::format(STR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); + initializer = std::format(SYSSTR("({}*){}"), get_native_class_name(object_property->GetPropertyClass()), initializer); generate_advanced_assignment_expression(property, initializer, implementation_file, property_scope, property_type); } } @@ -1534,15 +1536,15 @@ namespace RC::UEGenerator // Add an objectinitializer default subobject class override to the constructor implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); implementation_file.m_implementation_constructor.append( - std::format(STR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), object_name)); + std::format(SYSSTR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), to_system(object_name))); m_class_subobjects.try_emplace(object_name, (property->GetName())); } else { // Generate a CreateDefaultSubobject function call implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); - const UEStringType object_class_name = get_native_class_name(object_class_type); - initializer = std::format(STR("CreateDefaultSubobject<{}>(TEXT(\"{}\"))"), object_class_name, object_name); + const SystemStringType object_class_name = get_native_class_name(object_class_type); + initializer = std::format(SYSSTR("CreateDefaultSubobject<{}>(TEXT(\"{}\"))"), object_class_name, to_system(object_name)); m_class_subobjects.try_emplace(object_name, (property->GetName())); if (!super_and_no_access) { @@ -1563,13 +1565,13 @@ namespace RC::UEGenerator if (attach_parent_object_value != NULL) { const auto attach_parent_object_name = (attach_parent_object_value->GetName()); - const UEStringType operator_type = STR("->"); + const SystemStringType operator_type = SYSSTR("->"); bool parent_found = false; - UEStringType attach_string; + SystemStringType attach_string; if (auto it = m_class_subobjects.find(attach_parent_object_name); it != m_class_subobjects.end()) { // Set property to equal previous property referencing the same object - attach_string = std::format(STR("SetupAttachment({})"), it->second); + attach_string = std::format(SYSSTR("SetupAttachment({})"), to_system(it->second)); parent_found = true; } else if (as_class) @@ -1587,20 +1589,20 @@ namespace RC::UEGenerator { if (get_property_access_modifier(check_object_property) != AccessModifier::Private) { - attach_string = std::format(STR("SetupAttachment({})"), (check_property->GetName())); + attach_string = std::format(SYSSTR("SetupAttachment({})"), to_system(check_property->GetName())); } else { - auto parent_property_name = std::format(STR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), - (check_property->GetName()), - (check_property->GetName())); + auto parent_property_name = std::format(SYSSTR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), + to_system(check_property->GetName()), + to_system(check_property->GetName())); if (!implementation_file.parent_property_names.contains(parent_property_name)) { implementation_file.parent_property_names.emplace(parent_property_name); implementation_file.append_line(parent_property_name); } - attach_string = std::format(STR("SetupAttachment(p_{}_Parent->ContainerPtrToValuePtr<{}>(this))"), - (check_property->GetName()), + attach_string = std::format(SYSSTR("SetupAttachment(p_{}_Parent->ContainerPtrToValuePtr<{}>(this))"), + to_system(check_property->GetName()), get_native_class_name(check_sub_object_value->GetClassPrivate())); implementation_file.add_dependency_object(check_sub_object_value->GetClassPrivate(), DependencyLevel::Include); } @@ -1642,8 +1644,8 @@ namespace RC::UEGenerator // Generate a ::StaticClass call if this object represents a class implementation_file.add_dependency_object(sub_object_as_class, DependencyLevel::Include); - const UEStringType object_class_name = get_native_class_name(sub_object_as_class); - const UEStringType initializer = std::format(STR("{}::StaticClass()"), object_class_name); + const SystemStringType object_class_name = get_native_class_name(sub_object_as_class); + const SystemStringType initializer = std::format(SYSSTR("{}::StaticClass()"), object_class_name); if (!super_and_no_access) { generate_simple_assignment_expression(property, initializer, implementation_file, property_scope); @@ -1656,14 +1658,14 @@ namespace RC::UEGenerator } // Unhandled case, might be some external object reference - Output::send(STR("Unhandled default value of the FObjectProperty {}: {}\n"), (property->GetFullName()), (sub_object_value->GetFullName())); + Output::send(SYSSTR("Unhandled default value of the FObjectProperty {}: {}\n"), (property->GetFullName()), (sub_object_value->GetFullName())); return; } // Struct properties are serialization as normal struct constructors with custom scope // TODO there are a lot of issues with that regarding member access, unnecessary assignments and so on - /*if (FieldClassName == STR("StructProperty")) { + /*if (FieldClassName == SYSSTR("StructProperty")) { XStructProperty* StructProperty = static_cast(Property); UScriptStruct* ScriptStruct = StructProperty->get_script_struct(); @@ -1672,7 +1674,7 @@ namespace RC::UEGenerator } void* StructDataPointer = StructProperty->container_ptr_to_value_ptr(Object); - const UEStringType NewPropertyScope = std::format(STR("{}{}."), PropertyScope, StructProperty->GetName()); + const SystemStringType NewPropertyScope = std::format(SYSSTR("{}{}."), PropertyScope, StructProperty->GetName()); //Generate values for each struct property //TODO we do not really need to generate assignments for each struct member, we only really need members that are different from the constructor set @@ -1702,7 +1704,7 @@ namespace RC::UEGenerator { if (!super_and_no_access) { - implementation_file.append_line(std::format(STR("{}{}.AddDefaulted({});"), property_scope, (property->GetName()), (int32_t)property_value->Num())); + implementation_file.append_line(std::format(SYSSTR("{}{}.AddDefaulted({});"), property_scope, to_system(property->GetName()), (int32_t)property_value->Num())); } else { @@ -1737,16 +1739,16 @@ namespace RC::UEGenerator super_and_no_access = private_access_modifier; } - UEStringType number_constant_string; + SystemStringType number_constant_string; if (!numeric_property->IsFloatingPoint()) { int64 value = numeric_property->GetSignedIntPropertyValue(numeric_property->ContainerPtrToValuePtr(object)); - number_constant_string = to_ue(ToString(value)); + number_constant_string = to_system(ToString(value)); } else { double value = numeric_property->GetFloatingPointPropertyValue(numeric_property->ContainerPtrToValuePtr(object)); - number_constant_string = std::format(STR("{:.2f}f"), value); + number_constant_string = std::format(SYSSTR("{:.2f}f"), value); } if (!super_and_no_access) { @@ -1767,23 +1769,23 @@ namespace RC::UEGenerator const CaseInsensitiveSet& blacklisted_property_names) -> void { const auto class_native_name = get_native_class_name(uclass, is_generating_interface); - const auto raw_function_name = (function->GetName()); + const auto raw_function_name = to_system(function->GetName()); auto function_flags = function->GetFunctionFlags(); - PropertyTypeDeclarationContext context((uclass->GetName()), &implementation_file); + PropertyTypeDeclarationContext context(to_system(uclass->GetName()), &implementation_file); - UEStringType function_implementation_name; - UEStringType net_validate_function_name; + SystemStringType function_implementation_name; + SystemStringType net_validate_function_name; bool is_input_function_const = ((function_flags)&FUNC_Const) != 0; if ((function_flags & FUNC_Net) != 0) { // Network functions always have the implementation inside the _Implementation function - function_implementation_name = std::format(STR("{}::{}_Implementation"), class_native_name, raw_function_name); + function_implementation_name = std::format(SYSSTR("{}::{}_Implementation"), class_native_name, raw_function_name); // Validated network functions by default have their validation function name set to _Validate if ((function_flags & FUNC_NetValidate) != 0) { - net_validate_function_name = std::format(STR("{}::{}_Validate"), class_native_name, raw_function_name); + net_validate_function_name = std::format(SYSSTR("{}::{}_Validate"), class_native_name, raw_function_name); } } else if ((function_flags & FUNC_BlueprintEvent) != 0) @@ -1792,16 +1794,16 @@ namespace RC::UEGenerator // BlueprintImplementableEvents do not have any native functions at all, they're just thunks if ((function_flags & FUNC_Native) != 0) { - function_implementation_name = std::format(STR("{}::{}_Implementation"), class_native_name, raw_function_name); + function_implementation_name = std::format(SYSSTR("{}::{}_Implementation"), class_native_name, raw_function_name); } } else { // Otherwise, normal UFunctions get a standard name matching the function in question - function_implementation_name = std::format(STR("{}::{}"), class_native_name, raw_function_name); + function_implementation_name = std::format(SYSSTR("{}::{}"), class_native_name, raw_function_name); } - UEStringType function_parameter_list; + SystemStringType function_parameter_list; if (!function_implementation_name.empty() || !net_validate_function_name.empty()) { function_parameter_list = @@ -1812,63 +1814,63 @@ namespace RC::UEGenerator { FProperty* return_value_property = function->GetReturnProperty(); - const UEStringType return_value_type = return_value_property ? generate_property_type_declaration(return_value_property, context) : STR("void"); + const SystemStringType return_value_type = return_value_property ? generate_property_type_declaration(return_value_property, context) : SYSSTR("void"); - implementation_file.append_line(std::format(STR("{} {}({}){} {{"), + implementation_file.append_line(std::format(SYSSTR("{} {}({}){} {{"), return_value_type, function_implementation_name, function_parameter_list, - is_input_function_const ? STR(" const") : STR(""))); + is_input_function_const ? SYSSTR(" const") : SYSSTR(""))); implementation_file.begin_indent_level(); if (return_value_property != NULL) { - const UEStringType default_value = generate_default_property_value(return_value_property, implementation_file, context.context_name); - implementation_file.append_line(std::format(STR("return {};"), default_value)); + const SystemStringType default_value = generate_default_property_value(return_value_property, implementation_file, context.context_name); + implementation_file.append_line(std::format(SYSSTR("return {};"), default_value)); } implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); + implementation_file.append_line(SYSSTR("}")); } if (!net_validate_function_name.empty()) { - implementation_file.append_line(std::format(STR("bool {}({}) {{"), net_validate_function_name, function_parameter_list)); + implementation_file.append_line(std::format(SYSSTR("bool {}({}) {{"), net_validate_function_name, function_parameter_list)); implementation_file.begin_indent_level(); - implementation_file.append_line(STR("return true;")); + implementation_file.append_line(SYSSTR("return true;")); implementation_file.end_indent_level(); - implementation_file.append_line(STR("}")); + implementation_file.append_line(SYSSTR("}")); } } - auto UEHeaderGenerator::generate_parameter_count_string(int32_t parameter_count) -> UEStringType + auto UEHeaderGenerator::generate_parameter_count_string(int32_t parameter_count) -> SystemStringType { switch (parameter_count) { case 0: - return STR(""); + return SYSSTR(""); case 1: - return STR("_OneParam"); + return SYSSTR("_OneParam"); case 2: - return STR("_TwoParams"); + return SYSSTR("_TwoParams"); case 3: - return STR("_ThreeParams"); + return SYSSTR("_ThreeParams"); case 4: - return STR("_FourParams"); + return SYSSTR("_FourParams"); case 5: - return STR("_FiveParams"); + return SYSSTR("_FiveParams"); case 6: - return STR("_SixParams"); + return SYSSTR("_SixParams"); case 7: - return STR("_SevenParams"); + return SYSSTR("_SevenParams"); case 8: - return STR("_EightParams"); + return SYSSTR("_EightParams"); case 9: - return STR("_NineParams"); + return SYSSTR("_NineParams"); default: - return STR("_TooMany"); + return SYSSTR("_TooMany"); } } @@ -1880,15 +1882,15 @@ namespace RC::UEGenerator if (needed_access == AccessModifier::Public) { - header_data.append_line_no_indent(STR("public:")); + header_data.append_line_no_indent(SYSSTR("public:")); } else if (needed_access == AccessModifier::Protected) { - header_data.append_line_no_indent(STR("protected:")); + header_data.append_line_no_indent(SYSSTR("protected:")); } else if (needed_access == AccessModifier::Private) { - header_data.append_line_no_indent(STR("private:")); + header_data.append_line_no_indent(SYSSTR("private:")); } } } @@ -1931,10 +1933,10 @@ namespace RC::UEGenerator return AccessModifier::Public; } - auto UEHeaderGenerator::create_string_literal(const UEStringType& string) -> UEStringType + auto UEHeaderGenerator::create_string_literal(const SystemStringType& string) -> SystemStringType { - UEStringType result; - result.append(STR("TEXT(\"")); + SystemStringType result; + result.append(SYSSTR("TEXT(\"")); bool previous_character_was_hex = false; @@ -1943,28 +1945,28 @@ namespace RC::UEGenerator { switch (ch) { - case STR('\r'): { + case SYSSTR('\r'): { continue; } - case STR('\n'): { - result.append(STR("\\n")); + case SYSSTR('\n'): { + result.append(SYSSTR("\\n")); previous_character_was_hex = false; break; } - case STR('\\'): { - result.append(STR("\\\\")); + case SYSSTR('\\'): { + result.append(SYSSTR("\\\\")); previous_character_was_hex = false; break; } - case STR('\"'): { - result.append(STR("\\\"")); + case SYSSTR('\"'): { + result.append(SYSSTR("\\\"")); previous_character_was_hex = false; break; } default: { if ((unsigned char)ch < 31 || (unsigned char)ch >= 128) { - result.append(std::format(STR("\\x{:04X}"), ch)); + result.append(std::format(SYSSTR("\\x{:04X}"), ch)); previous_character_was_hex = true; } else @@ -1973,7 +1975,7 @@ namespace RC::UEGenerator // appended to the hex sequence, causing a different number if (previous_character_was_hex && iswxdigit(ch) != 0) { - result.append(STR("\")TEXT(\"")); + result.append(SYSSTR("\")TEXT(\"")); } previous_character_was_hex = false; result.push_back(ch); @@ -1982,19 +1984,19 @@ namespace RC::UEGenerator } } } - result.append(STR("\")")); + result.append(SYSSTR("\")")); return result; } - auto UEHeaderGenerator::convert_module_name_to_api_name(const UEStringType& module_name) -> UEStringType + auto UEHeaderGenerator::convert_module_name_to_api_name(const SystemStringType& module_name) -> SystemStringType { - UEStringType uppercase_string = string_to_uppercase(module_name); - uppercase_string.append(STR("_API")); + SystemStringType uppercase_string = string_to_uppercase(module_name); + uppercase_string.append(SYSSTR("_API")); return uppercase_string; } - auto UEHeaderGenerator::add_module_and_sub_module_dependencies(std::set& out_module_dependencies, - const UEStringType& module_name, + auto UEHeaderGenerator::add_module_and_sub_module_dependencies(std::set& out_module_dependencies, + const SystemStringType& module_name, bool add_self_module) -> void { // Prevent infinite recursion @@ -2010,7 +2012,7 @@ namespace RC::UEGenerator const auto iterator = m_module_dependencies.find(module_name); if (iterator != m_module_dependencies.end()) { - for (const UEStringType& DependencyModuleName : *iterator->second) + for (const SystemStringType& DependencyModuleName : *iterator->second) { out_module_dependencies.insert(DependencyModuleName); } @@ -2027,12 +2029,12 @@ namespace RC::UEGenerator for (FProperty* property : class_object->ForEachProperty()) { - result_set.insert((property->GetName())); + result_set.insert(to_system(property->GetName())); } for (UFunction* function : class_object->ForEachFunction()) { - result_set.insert((function->GetName())); + result_set.insert(to_system(function->GetName())); } } else if (uclass->GetClassPrivate()->IsChildOf(UScriptStruct::StaticClass())) @@ -2041,7 +2043,7 @@ namespace RC::UEGenerator for (FProperty* property : script_struct->ForEachProperty()) { - result_set.insert((property->GetName())); + result_set.insert(to_system(property->GetName())); } } return result_set; @@ -2049,7 +2051,7 @@ namespace RC::UEGenerator // TODO CannotImplementInterfaceInBlueprint is not exactly right, // TODO you can have interface with no implementable blueprint methods but that you can still implement in blueprint - auto UEHeaderGenerator::generate_interface_flags(UClass* uinterface) const -> UEStringType + auto UEHeaderGenerator::generate_interface_flags(UClass* uinterface) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2061,7 +2063,7 @@ namespace RC::UEGenerator if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(STR("MinimalAPI")); + flag_format_helper.add_switch(SYSSTR("MinimalAPI")); } ClassBlueprintInfo blueprint_info = get_class_blueprint_info(uinterface); @@ -2071,22 +2073,22 @@ namespace RC::UEGenerator { if (!parent_blueprint_info.is_blueprintable) { - flag_format_helper.add_switch(STR("Blueprintable")); + flag_format_helper.add_switch(SYSSTR("Blueprintable")); } } else if (blueprint_info.is_blueprint_type) { if (!parent_blueprint_info.is_blueprint_type) { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } - flag_format_helper.get_meta()->add_switch(STR("CannotImplementInterfaceInBlueprint")); + flag_format_helper.get_meta()->add_switch(SYSSTR("CannotImplementInterfaceInBlueprint")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_class_flags(UClass* uclass) const -> UEStringType + auto UEHeaderGenerator::generate_class_flags(UClass* uclass) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2098,7 +2100,7 @@ namespace RC::UEGenerator if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(STR("MinimalAPI")); + flag_format_helper.add_switch(SYSSTR("MinimalAPI")); } ClassBlueprintInfo blueprint_info = get_class_blueprint_info(uclass); @@ -2110,7 +2112,7 @@ namespace RC::UEGenerator if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(STR("Blueprintable")); + flag_format_helper.add_switch(SYSSTR("Blueprintable")); } else { @@ -2118,97 +2120,97 @@ namespace RC::UEGenerator { if (!parent_blueprint_info.is_blueprintable) { - flag_format_helper.add_switch(STR("Blueprintable")); + flag_format_helper.add_switch(SYSSTR("Blueprintable")); } } else if (blueprint_info.is_blueprint_type) { if (!parent_blueprint_info.is_blueprint_type) { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } } } if ((class_own_flags & CLASS_Deprecated) != 0) { - flag_format_helper.add_switch(STR("Deprecated")); + flag_format_helper.add_switch(SYSSTR("Deprecated")); } if ((class_own_flags & CLASS_Abstract) != 0) { - flag_format_helper.add_switch(STR("Abstract")); + flag_format_helper.add_switch(SYSSTR("Abstract")); } if ((class_own_flags & CLASS_MinimalAPI) != 0) { - flag_format_helper.add_switch(STR("MinimalAPI")); + flag_format_helper.add_switch(SYSSTR("MinimalAPI")); } if ((class_own_flags & CLASS_NoExport) != 0) { - flag_format_helper.add_switch(STR("NoExport")); + flag_format_helper.add_switch(SYSSTR("NoExport")); } // TODO not quite the case, because UHT boilerplate implicitly marks every native class as CLASS_Intrinsic // if ((ClassOwnFlags & CLASS_Intrinsic) != 0) { - // FlagFormatHelper.AddSwitch(STR("Intrinsic")); + // FlagFormatHelper.AddSwitch(SYSSTR("Intrinsic")); // } if ((class_own_flags & CLASS_Const) != 0) { - flag_format_helper.add_switch(STR("Const")); + flag_format_helper.add_switch(SYSSTR("Const")); } if ((class_own_flags & CLASS_DefaultToInstanced) != 0) { - flag_format_helper.add_switch(STR("DefaultToInstanced")); + flag_format_helper.add_switch(SYSSTR("DefaultToInstanced")); } UClass* class_within = uclass->GetClassWithin(); if (class_within != NULL && class_within != UObject::StaticClass() && (super_class == NULL || class_within != super_class->GetClassWithin())) { - flag_format_helper.add_parameter(STR("Within"), (class_within->GetName())); + flag_format_helper.add_parameter(SYSSTR("Within"), to_system(class_within->GetName())); } if ((class_own_flags & CLASS_Transient) != 0) { - flag_format_helper.add_switch(STR("Transient")); + flag_format_helper.add_switch(SYSSTR("Transient")); } else if ((parent_class_flags & CLASS_Transient) != 0) { - flag_format_helper.add_switch(STR("NonTransient")); + flag_format_helper.add_switch(SYSSTR("NonTransient")); } if ((class_own_flags & CLASS_EditInlineNew) != 0) { - flag_format_helper.add_switch(STR("EditInlineNew")); + flag_format_helper.add_switch(SYSSTR("EditInlineNew")); } else if ((class_flags & CLASS_EditInlineNew) == 0 && (parent_class_flags & CLASS_EditInlineNew) != 0) { - flag_format_helper.add_switch(STR("NotEditInlineNew")); + flag_format_helper.add_switch(SYSSTR("NotEditInlineNew")); } if ((class_own_flags & CLASS_NotPlaceable) != 0) { - flag_format_helper.add_switch(STR("NotPlaceable")); + flag_format_helper.add_switch(SYSSTR("NotPlaceable")); } else if ((class_flags & CLASS_NotPlaceable) == 0 && (parent_class_flags & CLASS_NotPlaceable) != 0) { - flag_format_helper.add_switch(STR("Placeable")); + flag_format_helper.add_switch(SYSSTR("Placeable")); } bool add_config_name{false}; if ((class_own_flags & CLASS_DefaultConfig) != 0) { - flag_format_helper.add_switch(STR("DefaultConfig")); + flag_format_helper.add_switch(SYSSTR("DefaultConfig")); add_config_name = true; } if ((class_own_flags & CLASS_GlobalUserConfig) != 0) { - flag_format_helper.add_switch(STR("GlobalUserConfig")); + flag_format_helper.add_switch(SYSSTR("GlobalUserConfig")); add_config_name = true; } if ((class_own_flags & CLASS_ProjectUserConfig) != 0) { - flag_format_helper.add_switch(STR("ProjectUserConfig")); + flag_format_helper.add_switch(SYSSTR("ProjectUserConfig")); add_config_name = true; } @@ -2220,58 +2222,58 @@ namespace RC::UEGenerator } } - const UEStringType class_config_name = uclass->GetClassConfigName().ToString(); + const auto class_config_name = uclass->GetClassConfigName().ToString(); if (super_class == NULL || class_config_name != super_class->GetClassConfigName().ToString()) { - flag_format_helper.add_parameter(STR("Config"), (class_config_name)); + flag_format_helper.add_parameter(SYSSTR("Config"), to_system(class_config_name)); // Don't add our override config if we add the real one here add_config_name = false; } if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllConfigsEngineConfig && add_config_name) { - flag_format_helper.add_parameter(STR("Config"), STR("Engine")); + flag_format_helper.add_parameter(SYSSTR("Config"), SYSSTR("Engine")); } if ((class_own_flags & CLASS_PerObjectConfig) != 0) { - flag_format_helper.add_switch(STR("PerObjectConfig")); + flag_format_helper.add_switch(SYSSTR("PerObjectConfig")); } if ((class_own_flags & CLASS_ConfigDoNotCheckDefaults) != 0) { - flag_format_helper.add_switch(STR("ConfigDoNotCheckDefaults")); + flag_format_helper.add_switch(SYSSTR("ConfigDoNotCheckDefaults")); } if ((class_own_flags & CLASS_HideDropDown) != 0) { - flag_format_helper.add_switch(STR("HideDropdown")); + flag_format_helper.add_switch(SYSSTR("HideDropdown")); } if ((class_own_flags & CLASS_CollapseCategories) != 0) { - flag_format_helper.add_switch(STR("CollapseCategories")); + flag_format_helper.add_switch(SYSSTR("CollapseCategories")); } else if ((parent_class_flags & CLASS_CollapseCategories) != 0) { - flag_format_helper.add_switch(STR("DontCollapseCategories")); + flag_format_helper.add_switch(SYSSTR("DontCollapseCategories")); } // Mark all UActorComponent derived classes as BlueprintSpawnableComponent by default // This will allow using them inside the Simple Construction Script of the blueprint assets if (uclass->IsChildOf()) { - flag_format_helper.get_meta()->add_switch(STR("BlueprintSpawnableComponent")); - flag_format_helper.add_parameter(STR("ClassGroup"), STR("Custom")); + flag_format_helper.get_meta()->add_switch(SYSSTR("BlueprintSpawnableComponent")); + flag_format_helper.add_parameter(SYSSTR("ClassGroup"), SYSSTR("Custom")); } return flag_format_helper.build_flag_string(); } /**/ - auto UEHeaderGenerator::generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> UEStringType + auto UEHeaderGenerator::generate_property_type_declaration(FProperty* property, const PropertyTypeDeclarationContext& context) -> SystemStringType { UClass* current_class = Unreal::Cast(property->GetOutermostOwner()); - const UEStringType field_class_name = property->GetClass().GetName(); + const auto field_class_name = property->GetClass().GetName(); // Byte Property if (property->IsA()) @@ -2286,7 +2288,7 @@ namespace RC::UEGenerator context.source_file->add_dependency_object(enum_value, DependencyLevel::Include); } - const UEStringType enum_type_name = get_native_enum_name(enum_value); + const SystemStringType enum_type_name = get_native_enum_name(enum_value); if ((property->GetPropertyFlags() & CPF_BlueprintVisible) != 0) { @@ -2294,9 +2296,9 @@ namespace RC::UEGenerator } // Non-EnumClass enumerations should be wrapped into TEnumAsByte according to UHT, but implicit uint8s should not use TEnumAsByte - return std::format(STR("TEnumAsByte<{}>"), enum_type_name); + return std::format(SYSSTR("TEnumAsByte<{}>"), enum_type_name); } - return STR("uint8"); + return SYSSTR("uint8"); } // Enum Property @@ -2313,14 +2315,14 @@ namespace RC::UEGenerator { context.source_file->add_dependency_object(uenum, DependencyLevel::Include); } - const UEStringType enum_type_name = get_native_enum_name(uenum); + const SystemStringType enum_type_name = get_native_enum_name(uenum); if ((property->GetPropertyFlags() & CPF_BlueprintVisible) != 0) { this->m_blueprint_visible_enums.insert(enum_type_name); } - const UEStringType underlying_enum_type = generate_property_type_declaration(underlying_property, context); + const SystemStringType underlying_enum_type = generate_property_type_declaration(underlying_property, context); this->m_underlying_enum_types.insert({enum_type_name, underlying_enum_type}); return enum_type_name; } @@ -2334,48 +2336,48 @@ namespace RC::UEGenerator if (bool_property->GetFieldMask() != 255) { *context.out_is_bitmask_bool = true; - return STR("uint8"); + return SYSSTR("uint8"); } } - return STR("bool"); + return SYSSTR("bool"); } // Standard Numeric Properties if (property->IsA()) { - return STR("int8"); + return SYSSTR("int8"); } else if (property->IsA()) { - return STR("int16"); + return SYSSTR("int16"); } else if (property->IsA()) { - return STR("int32"); + return SYSSTR("int32"); } else if (property->IsA()) { - return STR("int64"); + return SYSSTR("int64"); } else if (property->IsA()) { - return STR("uint16"); + return SYSSTR("uint16"); } else if (property->IsA()) { - return STR("uint32"); + return SYSSTR("uint32"); } else if (property->IsA()) { - return STR("uint64"); + return SYSSTR("uint64"); } else if (property->IsA()) { - return STR("float"); + return SYSSTR("float"); } else if (property->IsA()) { - return STR("double"); + return SYSSTR("double"); } // Class Properties @@ -2386,23 +2388,23 @@ namespace RC::UEGenerator if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return STR("UClass*"); + return SYSSTR("UClass*"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(meta_class, DependencyLevel::PreDeclaration); - context.source_file->add_extra_include(STR("Templates/SubclassOf.h")); + context.source_file->add_extra_include(SYSSTR("Templates/SubclassOf.h")); } - const UEStringType meta_class_name = get_native_class_name(meta_class, false); + const SystemStringType meta_class_name = get_native_class_name(meta_class, false); - return std::format(STR("TSubclassOf<{}>"), meta_class_name); + return std::format(SYSSTR("TSubclassOf<{}>"), meta_class_name); } if (auto* class_property = CastField(property); class_property) { // TODO: Confirm that this is accurate - return STR("TClassPtr"); + return SYSSTR("TClassPtr"); } if (property->IsA()) @@ -2412,16 +2414,16 @@ namespace RC::UEGenerator if (meta_class == NULL || meta_class == UObject::StaticClass()) { - return STR("TSoftClassPtr"); + return SYSSTR("TSoftClassPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(meta_class, DependencyLevel::PreDeclaration); } - const UEStringType meta_class_name = get_native_class_name(meta_class, false); + const SystemStringType meta_class_name = get_native_class_name(meta_class, false); - return std::format(STR("TSoftClassPtr<{}>"), meta_class_name); + return std::format(SYSSTR("TSoftClassPtr<{}>"), meta_class_name); } // Object Properties @@ -2434,15 +2436,15 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("UObject*"); + return SYSSTR("UObject*"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const UEStringType property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("{}*"), property_class_name); + return std::format(SYSSTR("{}*"), property_class_name); } if (auto* object_property = CastField(property); object_property) @@ -2451,7 +2453,7 @@ namespace RC::UEGenerator if (!property_class) { - return STR("TObjectPtr"); + return SYSSTR("TObjectPtr"); } else { @@ -2461,7 +2463,7 @@ namespace RC::UEGenerator } const auto property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TObjectPtr<{}>"), property_class_name); } } @@ -2472,16 +2474,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TWeakObjectPtr"); + return SYSSTR("TWeakObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const UEStringType property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TWeakObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TWeakObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -2491,16 +2493,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TLazyObjectPtr"); + return SYSSTR("TLazyObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const UEStringType property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TLazyObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TLazyObjectPtr<{}>"), property_class_name); } if (property->IsA()) @@ -2510,16 +2512,16 @@ namespace RC::UEGenerator if (property_class == NULL) { - return STR("TSoftObjectPtr"); + return SYSSTR("TSoftObjectPtr"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(property_class, DependencyLevel::PreDeclaration); } - const UEStringType property_class_name = get_native_class_name(property_class, false); + const SystemStringType property_class_name = get_native_class_name(property_class, false); - return std::format(STR("TSoftObjectPtr<{}>"), property_class_name); + return std::format(SYSSTR("TSoftObjectPtr<{}>"), property_class_name); } // Interface Property @@ -2530,16 +2532,16 @@ namespace RC::UEGenerator if (interface_class == NULL || interface_class == UInterface::StaticClass()) { - return STR("FScriptInterface"); + return SYSSTR("FScriptInterface"); } if (context.source_file != NULL) { context.source_file->add_dependency_object(interface_class, DependencyLevel::PreDeclaration); } - const UEStringType interface_class_name = get_native_class_name(interface_class, true); + const SystemStringType interface_class_name = get_native_class_name(interface_class, true); - return std::format(STR("TScriptInterface<{}>"), interface_class_name); + return std::format(SYSSTR("TScriptInterface<{}>"), interface_class_name); } // Struct Property @@ -2552,7 +2554,7 @@ namespace RC::UEGenerator { throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } - const UEStringType native_struct_name = get_native_struct_name(script_struct); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); if (context.source_file != NULL) { @@ -2621,8 +2623,8 @@ namespace RC::UEGenerator if (property->IsA()) { FFieldPathProperty* field_path_property = static_cast(property); - const auto property_class_name = (field_path_property->GetPropertyClass()->GetName()); - return std::format(STR("TFieldPath"), property_class_name); + const auto property_class_name = to_system(field_path_property->GetPropertyClass()->GetName()); + return std::format(SYSSTR("TFieldPath"), property_class_name); } // Collection and Map Properties @@ -2632,8 +2634,8 @@ namespace RC::UEGenerator FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - const UEStringType inner_property_type = generate_property_type_declaration(inner_property, context.inner_context()); - return std::format(STR("TArray<{}>"), inner_property_type); + const SystemStringType inner_property_type = generate_property_type_declaration(inner_property, context.inner_context()); + return std::format(SYSSTR("TArray<{}>"), inner_property_type); } if (property->IsA()) @@ -2641,8 +2643,8 @@ namespace RC::UEGenerator FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const UEStringType element_property_type = generate_property_type_declaration(element_prop, context.inner_context()); - return std::format(STR("TSet<{}>"), element_property_type); + const SystemStringType element_property_type = generate_property_type_declaration(element_prop, context.inner_context()); + return std::format(SYSSTR("TSet<{}>"), element_property_type); } // TODO: This is missing support for freeze image map properties because XMapProperty is incomplete. (low priority) @@ -2652,24 +2654,24 @@ namespace RC::UEGenerator FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - const UEStringType key_type = generate_property_type_declaration(key_property, context.inner_context()); - const UEStringType value_type = generate_property_type_declaration(value_property, context.inner_context()); + const SystemStringType key_type = generate_property_type_declaration(key_property, context.inner_context()); + const SystemStringType value_type = generate_property_type_declaration(value_property, context.inner_context()); - return std::format(STR("TMap<{}, {}>"), key_type, value_type); + return std::format(SYSSTR("TMap<{}, {}>"), key_type, value_type); } // Standard properties that do not have any special attributes if (property->IsA()) { - return STR("FName"); + return SYSSTR("FName"); } else if (property->IsA()) { - return STR("FString"); + return SYSSTR("FString"); } else if (property->IsA()) { - return STR("FText"); + return SYSSTR("FText"); } throw std::runtime_error(RC::fmt("[generate_property_type_declaration] Unsupported property class '{}', full name: '{}'", field_class_name, @@ -2677,38 +2679,38 @@ namespace RC::UEGenerator } //*/ - auto UEHeaderGenerator::generate_function_argument_flags(FProperty* property) const -> UEStringType + auto UEHeaderGenerator::generate_function_argument_flags(FProperty* property) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; auto property_flags = property->GetPropertyFlags(); // CPF_ConstParm is handled explicitly in the parameter list generator, it will generate const before parameter // if ((PropertyFlags & CPF_ConstParm) != 0) { - // FlagFormatHelper.AddSwitch(STR("Const")); + // FlagFormatHelper.AddSwitch(SYSSTR("Const")); // } // We only want to add UPARAM(Ref) when parameter is marked as reference AND output, // while not being marked as constant, because if it's marked as constant, it might be a parameter passed by const reference if ((property_flags & CPF_ReferenceParm) != 0 && (property_flags & CPF_OutParm) != 0 && (property_flags & CPF_ConstParm) == 0) { - flag_format_helper.add_switch(STR("Ref")); + flag_format_helper.add_switch(SYSSTR("Ref")); } if ((property_flags & CPF_RepSkip) != 0) { - flag_format_helper.add_switch(STR("NotReplicated")); + flag_format_helper.add_switch(SYSSTR("NotReplicated")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_property_flags(FProperty* property) const -> UEStringType + auto UEHeaderGenerator::generate_property_flags(FProperty* property) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; auto property_flags = property->GetPropertyFlags(); if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(STR("EditAnywhere")); + flag_format_helper.add_switch(SYSSTR("EditAnywhere")); } else if ((property_flags & CPF_Edit) != 0) { @@ -2716,97 +2718,97 @@ namespace RC::UEGenerator { if ((property_flags & CPF_DisableEditOnTemplate) != 0) { - flag_format_helper.add_switch(STR("VisibleInstanceOnly")); + flag_format_helper.add_switch(SYSSTR("VisibleInstanceOnly")); } else if ((property_flags & CPF_DisableEditOnInstance) != 0) { - flag_format_helper.add_switch(STR("VisibleDefaultsOnly")); + flag_format_helper.add_switch(SYSSTR("VisibleDefaultsOnly")); } else { - flag_format_helper.add_switch(STR("VisibleAnywhere")); + flag_format_helper.add_switch(SYSSTR("VisibleAnywhere")); } } else { if ((property_flags & CPF_DisableEditOnTemplate) != 0) { - flag_format_helper.add_switch(STR("EditInstanceOnly")); + flag_format_helper.add_switch(SYSSTR("EditInstanceOnly")); } else if ((property_flags & CPF_DisableEditOnInstance) != 0) { - flag_format_helper.add_switch(STR("EditDefaultsOnly")); + flag_format_helper.add_switch(SYSSTR("EditDefaultsOnly")); } else { - flag_format_helper.add_switch(STR("EditAnywhere")); + flag_format_helper.add_switch(SYSSTR("EditAnywhere")); } } } if ((property_flags & CPF_NoClear) != 0) { - flag_format_helper.add_switch(STR("NoClear")); + flag_format_helper.add_switch(SYSSTR("NoClear")); } if ((property_flags & CPF_EditFixedSize) != 0) { - flag_format_helper.add_switch(STR("EditFixedSize")); + flag_format_helper.add_switch(SYSSTR("EditFixedSize")); } if ((property_flags & CPF_SimpleDisplay) != 0) { - flag_format_helper.add_switch(STR("SimpleDisplay")); + flag_format_helper.add_switch(SYSSTR("SimpleDisplay")); } if ((property_flags & CPF_AdvancedDisplay) != 0) { - flag_format_helper.add_switch(STR("AdvancedDisplay")); + flag_format_helper.add_switch(SYSSTR("AdvancedDisplay")); } if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { if (property->GetArrayDim() == 1 && is_subtype_valid(property)) { - flag_format_helper.add_switch(STR("BlueprintReadWrite")); + flag_format_helper.add_switch(SYSSTR("BlueprintReadWrite")); } - flag_format_helper.get_meta()->add_parameter(STR("AllowPrivateAccess"), STR("true")); + flag_format_helper.get_meta()->add_parameter(SYSSTR("AllowPrivateAccess"), SYSSTR("true")); } else if ((property_flags & CPF_BlueprintVisible) != 0) { if ((property_flags & CPF_BlueprintReadOnly) != 0) { - flag_format_helper.add_switch(STR("BlueprintReadOnly")); + flag_format_helper.add_switch(SYSSTR("BlueprintReadOnly")); } else { - flag_format_helper.add_switch(STR("BlueprintReadWrite")); + flag_format_helper.add_switch(SYSSTR("BlueprintReadWrite")); } if ((property_flags & CPF_NativeAccessSpecifierPrivate) != 0) { - flag_format_helper.get_meta()->add_parameter(STR("AllowPrivateAccess"), STR("true")); + flag_format_helper.get_meta()->add_parameter(SYSSTR("AllowPrivateAccess"), SYSSTR("true")); } } if ((property_flags & CPF_BlueprintAssignable) != 0) { - flag_format_helper.add_switch(STR("BlueprintAssignable")); + flag_format_helper.add_switch(SYSSTR("BlueprintAssignable")); } if ((property_flags & CPF_BlueprintCallable) != 0) { - flag_format_helper.add_switch(STR("BlueprintCallable")); + flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); } if ((property_flags & CPF_BlueprintAuthorityOnly) != 0) { - flag_format_helper.add_switch(STR("BlueprintAuthorityOnly")); + flag_format_helper.add_switch(SYSSTR("BlueprintAuthorityOnly")); } if ((property_flags & CPF_Config) != 0) { if ((property_flags & CPF_GlobalConfig) != 0) { - flag_format_helper.add_switch(STR("GlobalConfig")); + flag_format_helper.add_switch(SYSSTR("GlobalConfig")); } else { - flag_format_helper.add_switch(STR("Config")); + flag_format_helper.add_switch(SYSSTR("Config")); } } @@ -2814,55 +2816,55 @@ namespace RC::UEGenerator { if ((property_flags & CPF_RepNotify) != 0) { - const auto rep_notify_func_name = (property->GetRepNotifyFunc().ToString()); - flag_format_helper.add_parameter(STR("ReplicatedUsing"), rep_notify_func_name); + const auto rep_notify_func_name = to_system(property->GetRepNotifyFunc().ToString()); + flag_format_helper.add_parameter(SYSSTR("ReplicatedUsing"), rep_notify_func_name); } else { - flag_format_helper.add_switch(STR("Replicated")); + flag_format_helper.add_switch(SYSSTR("Replicated")); } } if ((property_flags & CPF_RepSkip) != 0) { - flag_format_helper.add_switch(STR("NotReplicated")); + flag_format_helper.add_switch(SYSSTR("NotReplicated")); } if ((property_flags & CPF_AssetRegistrySearchable) != 0) { - flag_format_helper.add_switch(STR("AssetRegistrySearchable")); + flag_format_helper.add_switch(SYSSTR("AssetRegistrySearchable")); } if ((property_flags & CPF_Interp) != 0) { - flag_format_helper.add_switch(STR("Interp")); + flag_format_helper.add_switch(SYSSTR("Interp")); } if ((property_flags & CPF_SaveGame) != 0) { - flag_format_helper.add_switch(STR("SaveGame")); + flag_format_helper.add_switch(SYSSTR("SaveGame")); } if ((property_flags & CPF_NonTransactional) != 0) { - flag_format_helper.add_switch(STR("NonTransactional")); + flag_format_helper.add_switch(SYSSTR("NonTransactional")); } if ((property_flags & CPF_Transient) != 0) { - flag_format_helper.add_switch(STR("Transient")); + flag_format_helper.add_switch(SYSSTR("Transient")); } if ((property_flags & CPF_DuplicateTransient) != 0) { - flag_format_helper.add_switch(STR("DuplicateTransient")); + flag_format_helper.add_switch(SYSSTR("DuplicateTransient")); } if ((property_flags & CPF_TextExportTransient) != 0) { - flag_format_helper.add_switch(STR("TextExportTransient")); + flag_format_helper.add_switch(SYSSTR("TextExportTransient")); } if ((property_flags & CPF_NonPIEDuplicateTransient) != 0) { - flag_format_helper.add_switch(STR("NonPIEDuplicateTransient")); + flag_format_helper.add_switch(SYSSTR("NonPIEDuplicateTransient")); } if ((property_flags & CPF_SkipSerialization) != 0) { - flag_format_helper.add_switch(STR("SkipSerialization")); + flag_format_helper.add_switch(SYSSTR("SkipSerialization")); } // Need to have all of these flags, otherwise we might accidentally get Instanced of delegate properties; CPF_ExportObject is not set for delegate properties @@ -2875,16 +2877,16 @@ namespace RC::UEGenerator (property->IsA() || (property->IsA() && static_cast(property)->GetInner()->IsA()) || (property->IsA() && static_cast(property)->GetValueProp()->IsA()))) { - flag_format_helper.add_switch(STR("Instanced")); + flag_format_helper.add_switch(SYSSTR("Instanced")); } else if ((property_flags & CPF_ExportObject) != 0) { - flag_format_helper.add_switch(STR("Export")); + flag_format_helper.add_switch(SYSSTR("Export")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_struct_flags(UScriptStruct* script_struct) const -> UEStringType + auto UEHeaderGenerator::generate_struct_flags(UScriptStruct* script_struct) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2894,29 +2896,29 @@ namespace RC::UEGenerator EStructFlags struct_own_flags = (EStructFlags)(struct_flags & (~(parent_struct_flags & STRUCT_Inherit))); - const UEStringType native_struct_name = get_native_struct_name(script_struct); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); if (is_struct_blueprint_type(script_struct) || m_blueprint_visible_structs.contains(native_struct_name) || UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeAllPropertyBlueprintsReadWrite) { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } if ((struct_own_flags & STRUCT_NoExport) != 0) { - flag_format_helper.add_switch(STR("NoExport")); + flag_format_helper.add_switch(SYSSTR("NoExport")); } if ((struct_own_flags & STRUCT_Atomic) != 0) { - flag_format_helper.add_switch(STR("Atomic")); + flag_format_helper.add_switch(SYSSTR("Atomic")); } if ((struct_own_flags & STRUCT_Immutable) != 0) { - flag_format_helper.add_switch(STR("Immutable")); + flag_format_helper.add_switch(SYSSTR("Immutable")); } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::generate_enum_flags(UEnum* uenum) const -> UEStringType + auto UEHeaderGenerator::generate_enum_flags(UEnum* uenum) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -2925,9 +2927,9 @@ namespace RC::UEGenerator if ((((int32_t)enum_flags) & ((int32_t)EEnumFlags::Flags)) != 0) { - flag_format_helper.add_switch(STR("Flags")); + flag_format_helper.add_switch(SYSSTR("Flags")); } - const UEStringType enum_native_name = get_native_enum_name(uenum); + const SystemStringType enum_native_name = get_native_enum_name(uenum); if (UE4SSProgram::settings_manager.UHTHeaderGenerator.MakeEnumClassesBlueprintType) { @@ -2935,30 +2937,30 @@ namespace RC::UEGenerator if (cpp_form == UEnum::ECppForm::EnumClass) { const auto underlying_type = m_underlying_enum_types.find(enum_native_name); - if (underlying_type->second == STR("uint8") || + if (underlying_type->second == SYSSTR("uint8") || (underlying_type == m_underlying_enum_types.end() && (get_highest_enum(uenum) <= 255 && get_lowest_enum(uenum) >= 0))) { // Underlying type is implicit or explicitly uint8. - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } } else { - flag_format_helper.add_switch(STR("BlueprintType")); + flag_format_helper.add_switch(SYSSTR("BlueprintType")); } } return flag_format_helper.build_flag_string(); } - auto UEHeaderGenerator::sanitize_enumeration_name(const UEStringType& enumeration_name) -> UEStringType + auto UEHeaderGenerator::sanitize_enumeration_name(const SystemStringType& enumeration_name) -> SystemStringType { - UEStringType result_enum_name = enumeration_name; + SystemStringType result_enum_name = enumeration_name; // Remove enumeration name from the string - size_t enum_name_string_split = enumeration_name.find(STR("::")); - if (enum_name_string_split != UEStringType::npos) + size_t enum_name_string_split = enumeration_name.find(SYSSTR("::")); + if (enum_name_string_split != SystemStringType::npos) { result_enum_name.erase(0, enum_name_string_split + 2); } @@ -2973,14 +2975,14 @@ namespace RC::UEGenerator } int64 highest_enum_value = 0; - const auto enum_prefix = (uenum->GenerateEnumPrefix()); - const auto expected_max_name = std::format(STR("{}_MAX"), enum_prefix); + const auto enum_prefix = to_system(uenum->GenerateEnumPrefix()); + const auto expected_max_name = std::format(SYSSTR("{}_MAX"), enum_prefix); auto expected_max_name_lower = expected_max_name; std::transform(expected_max_name_lower.begin(), expected_max_name_lower.end(), expected_max_name_lower.begin(), ::towlower); for (auto [Name, Value] : uenum->ForEachName()) { - auto enum_name = sanitize_enumeration_name((Name.ToString())); + auto enum_name = sanitize_enumeration_name(to_system_string(Name.ToString())); auto enum_name_lower = enum_name; std::transform(enum_name_lower.begin(), enum_name_lower.end(), enum_name_lower.begin(), ::towlower); if ((enum_name_lower != expected_max_name_lower && enum_name_lower != sanitize_enumeration_name(expected_max_name_lower)) && Value > highest_enum_value) @@ -3009,7 +3011,7 @@ namespace RC::UEGenerator return lowest_enum_value; } - auto UEHeaderGenerator::generate_function_flags(UFunction* function, bool is_function_pure_virtual) const -> UEStringType + auto UEHeaderGenerator::generate_function_flags(UFunction* function, bool is_function_pure_virtual) const -> SystemStringType { FlagFormatHelper flag_format_helper{}; @@ -3030,7 +3032,7 @@ namespace RC::UEGenerator // Interface functions cannot be BlueprintPure if ((function_flags & FUNC_BlueprintPure) != 0 && !is_interface_function) { - flag_format_helper.add_switch(STR("BlueprintPure")); + flag_format_helper.add_switch(SYSSTR("BlueprintPure")); } else { @@ -3038,9 +3040,9 @@ namespace RC::UEGenerator // it has been explicitly marked as blueprint impure, and we need to preserve this behavior if ((function_flags & FUNC_Const) != 0 && !is_interface_function) { - flag_format_helper.add_parameter(STR("BlueprintPure"), STR("false")); + flag_format_helper.add_parameter(SYSSTR("BlueprintPure"), SYSSTR("false")); } - flag_format_helper.add_switch(STR("BlueprintCallable")); + flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); blueprint_callable_added = true; } } @@ -3058,7 +3060,7 @@ namespace RC::UEGenerator if (!has_invalid_param) { - flag_format_helper.add_switch(STR("BlueprintCallable")); + flag_format_helper.add_switch(SYSSTR("BlueprintCallable")); } } @@ -3066,11 +3068,11 @@ namespace RC::UEGenerator { if ((function_flags & FUNC_Native) != 0) { - flag_format_helper.add_switch(STR("BlueprintNativeEvent")); + flag_format_helper.add_switch(SYSSTR("BlueprintNativeEvent")); } else { - flag_format_helper.add_switch(STR("BlueprintImplementableEvent")); + flag_format_helper.add_switch(SYSSTR("BlueprintImplementableEvent")); } } @@ -3078,50 +3080,50 @@ namespace RC::UEGenerator { if ((function_flags & FUNC_NetServer) != 0) { - flag_format_helper.add_switch(STR("Server")); + flag_format_helper.add_switch(SYSSTR("Server")); } else if ((function_flags & FUNC_NetClient) != 0) { - flag_format_helper.add_switch(STR("Client")); + flag_format_helper.add_switch(SYSSTR("Client")); } else if ((function_flags & FUNC_NetMulticast) != 0) { - flag_format_helper.add_switch(STR("NetMulticast")); + flag_format_helper.add_switch(SYSSTR("NetMulticast")); } else if ((function_flags & FUNC_NetRequest) != 0) { - flag_format_helper.add_switch(STR("ServiceRequest")); + flag_format_helper.add_switch(SYSSTR("ServiceRequest")); } else if ((function_flags & FUNC_NetResponse) != 0) { - flag_format_helper.add_switch(STR("ServiceResponse")); + flag_format_helper.add_switch(SYSSTR("ServiceResponse")); } if ((function_flags & FUNC_NetReliable) != 0) { - flag_format_helper.add_switch(STR("Reliable")); + flag_format_helper.add_switch(SYSSTR("Reliable")); } else { - flag_format_helper.add_switch(STR("Unreliable")); + flag_format_helper.add_switch(SYSSTR("Unreliable")); } if ((function_flags & FUNC_NetValidate) != 0) { - flag_format_helper.add_switch(STR("WithValidation")); + flag_format_helper.add_switch(SYSSTR("WithValidation")); } } if ((function_flags & FUNC_Exec) != 0) { - flag_format_helper.add_switch(STR("Exec")); + flag_format_helper.add_switch(SYSSTR("Exec")); } if ((function_flags & FUNC_BlueprintAuthorityOnly) != 0) { - flag_format_helper.add_switch(STR("BlueprintAuthorityOnly")); + flag_format_helper.add_switch(SYSSTR("BlueprintAuthorityOnly")); } if ((function_flags & FUNC_BlueprintCosmetic) != 0) { - flag_format_helper.add_switch(STR("BlueprintCosmetic")); + flag_format_helper.add_switch(SYSSTR("BlueprintCosmetic")); } static auto latent_action_info = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.LatentActionInfo")); @@ -3129,11 +3131,11 @@ namespace RC::UEGenerator bool bLAFound = false; for (FProperty* param : function->ForEachProperty()) { - auto param_name = (param->GetName()); + auto param_name = to_system(param->GetName()); auto param_uc_name = string_to_uppercase(param_name); - if (param_uc_name.find(STR("WORLDCONTEXT")) != param_uc_name.npos) + if (param_uc_name.find(SYSSTR("WORLDCONTEXT")) != param_uc_name.npos) { - flag_format_helper.get_meta()->add_parameter(STR("WorldContext"), std::format(STR("\"{}\""), param_name)); + flag_format_helper.get_meta()->add_parameter(SYSSTR("WorldContext"), std::format(SYSSTR("\"{}\""), param_name)); bWCFound = true; } if (auto as_struct_property = CastField(param); as_struct_property) @@ -3141,8 +3143,8 @@ namespace RC::UEGenerator // We now know this is a StructProperty. if (as_struct_property->GetStruct()->IsChildOf(latent_action_info)) { - flag_format_helper.get_meta()->add_parameter(STR("LatentInfo"), std::format(STR("\"{}\""), param_name)); - flag_format_helper.get_meta()->add_switch(STR("Latent")); + flag_format_helper.get_meta()->add_parameter(SYSSTR("LatentInfo"), std::format(SYSSTR("\"{}\""), param_name)); + flag_format_helper.get_meta()->add_switch(SYSSTR("Latent")); bLAFound = true; } } @@ -3159,28 +3161,28 @@ namespace RC::UEGenerator UFunction* function, GeneratedSourceFile& header_data, bool generate_comma_before_name, - const UEStringType& context_name, + const SystemStringType& context_name, const CaseInsensitiveSet& blacklisted_property_names, - int32_t* out_num_params) -> UEStringType + int32_t* out_num_params) -> SystemStringType { - UEStringType function_arguments_string; + SystemStringType function_arguments_string; for (FProperty* property : function->ForEachProperty()) { auto property_flags = property->GetPropertyFlags(); if ((property_flags & CPF_Parm) != 0 && (property_flags & CPF_ReturnParm) == 0) { - UEStringType param_declaration; + SystemStringType param_declaration; // We only generate UPARAM declarations if we are not generating the implementation file if (!header_data.is_implementation_file()) { - const UEStringType parameter_flags_string = generate_function_argument_flags(property); + const SystemStringType parameter_flags_string = generate_function_argument_flags(property); if (!parameter_flags_string.empty()) { - param_declaration.append(STR("UPARAM(")); + param_declaration.append(SYSSTR("UPARAM(")); param_declaration.append(parameter_flags_string); - param_declaration.append(STR(") ")); + param_declaration.append(SYSSTR(") ")); } } @@ -3192,7 +3194,7 @@ namespace RC::UEGenerator // Append const keyword to the parameter declaration if it is marked as const parameter if ((property_flags & CPF_ConstParm) != 0 || should_force_const_ref) { - param_declaration.append(STR("const ")); + param_declaration.append(SYSSTR("const ")); } PropertyTypeDeclarationContext context(context_name, &header_data); @@ -3202,27 +3204,27 @@ namespace RC::UEGenerator // which would also be always set for output parameters if ((property_flags & (CPF_ReferenceParm | CPF_OutParm)) != 0 || should_force_const_ref) { - param_declaration.append(STR("&")); + param_declaration.append(SYSSTR("&")); } if (generate_comma_before_name) { - param_declaration.append(STR(",")); + param_declaration.append(SYSSTR(",")); } - param_declaration.append(STR(" ")); + param_declaration.append(SYSSTR(" ")); - auto property_name = (property->GetName()); + auto property_name = to_system_string(property->GetName()); // If property name is blacklisted, capitalize first letter and prepend New if ((uclass && is_function_parameter_shadowing(uclass, property)) || blacklisted_property_names.contains(property_name)) { property_name[0] = towupper(property_name[0]); - property_name.insert(0, STR("New")); + property_name.insert(0, SYSSTR("New")); } param_declaration.append(property_name); function_arguments_string.append(param_declaration); - function_arguments_string.append(STR(", ")); + function_arguments_string.append(SYSSTR(", ")); if (out_num_params) { (*out_num_params)++; @@ -3238,7 +3240,7 @@ namespace RC::UEGenerator return function_arguments_string; } - auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const UEStringType& ContextName) -> UEStringType + auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType { const auto field_class_name = (property->GetClass().GetName()); PropertyTypeDeclarationContext context(ContextName, &header_data); @@ -3254,7 +3256,7 @@ namespace RC::UEGenerator const int64_t first_enum_constant_value = Enum->GetEnumNameByIndex(0).Value; return generate_enum_value(Enum, first_enum_constant_value); } - return STR("0"); + return SYSSTR("0"); } // Enum Property @@ -3274,36 +3276,36 @@ namespace RC::UEGenerator // Bool Property if (field_class_name == STR("BoolProperty")) { - return STR("false"); + return SYSSTR("false"); } // Standard Numeric Properties if (field_class_name == STR("Int8Property") || field_class_name == STR("Int16Property") || field_class_name == STR("IntProperty") || field_class_name == STR("Int64Property") || field_class_name == STR("UInt16Property") || field_class_name == STR("UInt32Property") || field_class_name == STR("UInt64Property")) { - return STR("0"); + return SYSSTR("0"); } if (field_class_name == STR("FloatProperty")) { - return STR("0.0f"); + return SYSSTR("0.0f"); } if (field_class_name == STR("DoubleProperty")) { - return STR("0.0"); + return SYSSTR("0.0"); } // Object Properties if (field_class_name == STR("ObjectProperty") || field_class_name == STR("WeakObjectProperty") || field_class_name == STR("LazyObjectProperty") || field_class_name == STR("SoftObjectProperty") || field_class_name == STR("AssetObjectProperty") || property->IsA()) { - return STR("NULL"); + return SYSSTR("NULL"); } // Class Properties if (field_class_name == STR("ClassProperty") || field_class_name == STR("SoftClassProperty") || field_class_name == STR("InterfaceProperty") || field_class_name == STR("AssetClassProperty") || property->IsA()) { - return STR("NULL"); + return SYSSTR("NULL"); } // Struct Property @@ -3316,22 +3318,22 @@ namespace RC::UEGenerator { throw std::runtime_error(RC::fmt("Struct is NULL for StructProperty {}", property->GetName())); } - const UEStringType native_struct_name = get_native_struct_name(script_struct); - return std::format(STR("{}{{}}"), native_struct_name); + const SystemStringType native_struct_name = get_native_struct_name(script_struct); + return std::format(SYSSTR("{}{{}}"), native_struct_name); } // Delegate Properties if (field_class_name == STR("DelegateProperty") || field_class_name == STR("MulticastInlineDelegateProperty") || field_class_name == STR("MulticastSparseDelegateProperty")) { - const UEStringType delegate_type_name = generate_delegate_name(property, context.context_name); - return std::format(STR("{}()"), delegate_type_name); + const SystemStringType delegate_type_name = generate_delegate_name(property, context.context_name); + return std::format(SYSSTR("{}()"), delegate_type_name); } // Field path property if (field_class_name == STR("FieldPathProperty")) { - return STR("FFieldPath()"); + return SYSSTR("FFieldPath()"); } // Collection and Map Properties @@ -3340,8 +3342,8 @@ namespace RC::UEGenerator FArrayProperty* array_property = static_cast(property); FProperty* inner_property = array_property->GetInner(); - const UEStringType inner_property_type = generate_property_type_declaration(inner_property, context); - return std::format(STR("TArray<{}>()"), inner_property_type); + const SystemStringType inner_property_type = generate_property_type_declaration(inner_property, context); + return std::format(SYSSTR("TArray<{}>()"), inner_property_type); } if (field_class_name == STR("SetProperty")) @@ -3349,8 +3351,8 @@ namespace RC::UEGenerator FSetProperty* set_property = static_cast(property); FProperty* element_prop = set_property->GetElementProp(); - const UEStringType element_property_type = generate_property_type_declaration(element_prop, context); - return std::format(STR("TSet<{}>()"), element_property_type); + const SystemStringType element_property_type = generate_property_type_declaration(element_prop, context); + return std::format(SYSSTR("TSet<{}>()"), element_property_type); } if (field_class_name == STR("MapProperty")) @@ -3359,24 +3361,24 @@ namespace RC::UEGenerator FProperty* key_property = map_property->GetKeyProp(); FProperty* value_property = map_property->GetValueProp(); - const UEStringType key_type = generate_property_type_declaration(key_property, context); - const UEStringType value_type = generate_property_type_declaration(value_property, context); + const auto key_type = generate_property_type_declaration(key_property, context); + const auto value_type = generate_property_type_declaration(value_property, context); - return std::format(STR("TMap<{}, {}>()"), key_type, value_type); + return std::format(SYSSTR("TMap<{}, {}>()"), key_type, value_type); } // Various string, name and text properties if (field_class_name == STR("NameProperty")) { - return STR("NAME_None"); + return SYSSTR("NAME_None"); } if (field_class_name == STR("StrProperty")) { - return STR("TEXT(\"\")"); + return SYSSTR("TEXT(\"\")"); } if (field_class_name == STR("TextProperty")) { - return STR("FText::GetEmpty()"); + return SYSSTR("FText::GetEmpty()"); } throw std::runtime_error(RC::fmt("[generate_default_property_value] Unsupported property class '{}', full name: '{}'", field_class_name, @@ -3470,18 +3472,18 @@ namespace RC::UEGenerator return is_shadowing; } - auto UEHeaderGenerator::get_module_name_for_package(UObject* package) -> UEStringType + auto UEHeaderGenerator::get_module_name_for_package(UObject* package) -> SystemStringType { if (package->GetOuterPrivate() != NULL) { throw std::invalid_argument("Encountered a package with an outer object set"); } - auto package_name = (package->GetName()); - if (!package_name.starts_with(STR("/Script/"))) + auto package_name = to_system_string(package->GetName()); + if (!package_name.starts_with(SYSSTR("/Script/"))) { - return STR(""); + return SYSSTR(""); } - package_name.erase(0, UEStringType(STR("/Script/")).length()); + package_name.erase(0, SystemStringType(SYSSTR("/Script/")).length()); return package_name; } @@ -3491,22 +3493,22 @@ namespace RC::UEGenerator this->m_primary_module_name = determine_primary_game_module_name(); // Force inclusion of Core and CoreUObject into all the generated module build files - this->m_forced_module_dependencies.insert(STR("Core")); - this->m_forced_module_dependencies.insert(STR("CoreUObject")); + this->m_forced_module_dependencies.insert(SYSSTR("Core")); + this->m_forced_module_dependencies.insert(SYSSTR("CoreUObject")); // TODO not optimal, but still needed for the majority of the cases - this->m_forced_module_dependencies.insert(STR("Engine")); + this->m_forced_module_dependencies.insert(SYSSTR("Engine")); // Add few classes that require explicit UObjectInitializer constructor call, excluding classes inheriting from AActor. - this->m_classes_with_object_initializer.insert(STR("UUserWidget")); - this->m_classes_with_object_initializer.insert(STR("UListView")); - this->m_classes_with_object_initializer.insert(STR("UMovieSceneTrack")); - this->m_classes_with_object_initializer.insert(STR("USoundWaveProcedural")); - this->m_classes_with_object_initializer.insert(STR("URichTextBlock")); - this->m_classes_with_object_initializer.insert(STR("URichTextBlockImageDecorator")); - this->m_classes_with_object_initializer.insert(STR("URichTextBlockDecorator")); - this->m_classes_with_object_initializer.insert(STR("USkeletalMeshComponentBudgeted")); - this->m_classes_with_object_initializer.insert(STR("UIpNetDriver")); - this->m_classes_with_object_initializer.insert(STR("UAITask")); + this->m_classes_with_object_initializer.insert(SYSSTR("UUserWidget")); + this->m_classes_with_object_initializer.insert(SYSSTR("UListView")); + this->m_classes_with_object_initializer.insert(SYSSTR("UMovieSceneTrack")); + this->m_classes_with_object_initializer.insert(SYSSTR("USoundWaveProcedural")); + this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlock")); + this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlockImageDecorator")); + this->m_classes_with_object_initializer.insert(SYSSTR("URichTextBlockDecorator")); + this->m_classes_with_object_initializer.insert(SYSSTR("USkeletalMeshComponentBudgeted")); + this->m_classes_with_object_initializer.insert(SYSSTR("UIpNetDriver")); + this->m_classes_with_object_initializer.insert(SYSSTR("UAITask")); } auto UEHeaderGenerator::ignore_selected_modules() -> void @@ -3518,144 +3520,144 @@ namespace RC::UEGenerator if (UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreEngineAndCoreUObject || UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreAllCoreEngineModules) { - this->m_ignored_module_names.insert(STR("Engine")); - this->m_ignored_module_names.insert(STR("CoreUObject")); + this->m_ignored_module_names.insert(SYSSTR("Engine")); + this->m_ignored_module_names.insert(SYSSTR("CoreUObject")); } // Skip all core engine packages if requested if (UE4SSProgram::settings_manager.UHTHeaderGenerator.IgnoreAllCoreEngineModules) { - this->m_ignored_module_names.insert(STR("ActorLayerUtilities")); - this->m_ignored_module_names.insert(STR("ActorSequence")); - this->m_ignored_module_names.insert(STR("AIModule")); - this->m_ignored_module_names.insert(STR("AndroidPermission")); - this->m_ignored_module_names.insert(STR("AnimationCore")); - this->m_ignored_module_names.insert(STR("AnimationSharing")); - this->m_ignored_module_names.insert(STR("AnimGraphRuntime")); - this->m_ignored_module_names.insert(STR("AppleImageUtils")); - this->m_ignored_module_names.insert(STR("ArchVisCharacter")); - this->m_ignored_module_names.insert(STR("AssetRegistry")); - this->m_ignored_module_names.insert(STR("AssetTags")); - this->m_ignored_module_names.insert(STR("AudioAnalyzer")); - this->m_ignored_module_names.insert(STR("AudioCapture")); - this->m_ignored_module_names.insert(STR("AudioExtensions")); - this->m_ignored_module_names.insert(STR("AudioMixer")); - this->m_ignored_module_names.insert(STR("AudioPlatformConfiguration")); - this->m_ignored_module_names.insert(STR("AudioSynesthesia")); - this->m_ignored_module_names.insert(STR("AugmentedReality")); - this->m_ignored_module_names.insert(STR("AutomationUtils")); - this->m_ignored_module_names.insert(STR("AvfMediaFactory")); - this->m_ignored_module_names.insert(STR("BuildPatchServices")); - this->m_ignored_module_names.insert(STR("CableComponent")); - this->m_ignored_module_names.insert(STR("Chaos")); - this->m_ignored_module_names.insert(STR("ChaosCloth")); - this->m_ignored_module_names.insert(STR("ChaosNiagara")); - this->m_ignored_module_names.insert(STR("ChaosSolvers")); - this->m_ignored_module_names.insert(STR("ChaosSolverEngine")); - this->m_ignored_module_names.insert(STR("CinematicCamera")); - this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeCommon")); - this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeInterface")); - this->m_ignored_module_names.insert(STR("ClothingSystemRuntimeNv")); - this->m_ignored_module_names.insert(STR("CustomMeshComponent")); - this->m_ignored_module_names.insert(STR("DatasmithContent")); - this->m_ignored_module_names.insert(STR("DeveloperSettings")); - this->m_ignored_module_names.insert(STR("EditableMesh")); - this->m_ignored_module_names.insert(STR("EngineMessages")); - this->m_ignored_module_names.insert(STR("EngineSettings")); - this->m_ignored_module_names.insert(STR("EyeTracker")); - this->m_ignored_module_names.insert(STR("FacialAnimation")); - this->m_ignored_module_names.insert(STR("FieldSystemCore")); - this->m_ignored_module_names.insert(STR("FieldSystemEngine")); - this->m_ignored_module_names.insert(STR("Foliage")); - this->m_ignored_module_names.insert(STR("GameplayTags")); - this->m_ignored_module_names.insert(STR("GameplayTasks")); - this->m_ignored_module_names.insert(STR("GeometryCache")); - this->m_ignored_module_names.insert(STR("GeometryCacheTracks")); - this->m_ignored_module_names.insert(STR("GeometryCollectionCore")); - this->m_ignored_module_names.insert(STR("GeometryCollectionSimulationCore")); - this->m_ignored_module_names.insert(STR("GeometryCollectionEngine")); - this->m_ignored_module_names.insert(STR("GeometryCollectionTracks")); - this->m_ignored_module_names.insert(STR("GooglePAD")); - this->m_ignored_module_names.insert(STR("HeadMountedDisplay")); - this->m_ignored_module_names.insert(STR("ImageWrapper")); - this->m_ignored_module_names.insert(STR("ImageWriteQueue")); - this->m_ignored_module_names.insert(STR("ImgMedia")); - this->m_ignored_module_names.insert(STR("ImgMediaFactory")); - this->m_ignored_module_names.insert(STR("InputCore")); - this->m_ignored_module_names.insert(STR("InteractiveToolsFramework")); - this->m_ignored_module_names.insert(STR("JsonUtilities")); - this->m_ignored_module_names.insert(STR("Landscape")); - this->m_ignored_module_names.insert(STR("LevelSequence")); - this->m_ignored_module_names.insert(STR("LightPropagationVolumeRuntime")); - this->m_ignored_module_names.insert(STR("LiveLinkInterface")); - this->m_ignored_module_names.insert(STR("LocationServicesBPLibrary")); - this->m_ignored_module_names.insert(STR("LuminRuntimeSettings")); - this->m_ignored_module_names.insert(STR("MagicLeap")); - this->m_ignored_module_names.insert(STR("MagicLeapAR")); - this->m_ignored_module_names.insert(STR("MagicLeapARPin")); - this->m_ignored_module_names.insert(STR("MagicLeapAudio")); - this->m_ignored_module_names.insert(STR("MagicLeapController")); - this->m_ignored_module_names.insert(STR("MagicLeapEyeTracker")); - this->m_ignored_module_names.insert(STR("MagicLeapHandMeshing")); - this->m_ignored_module_names.insert(STR("MagicLeapHandTracking")); - this->m_ignored_module_names.insert(STR("MagicLeapIdentity")); - this->m_ignored_module_names.insert(STR("MagicLeapImageTracker")); - this->m_ignored_module_names.insert(STR("MagicLeapLightEstimation")); - this->m_ignored_module_names.insert(STR("MagicLeapPlanes")); - this->m_ignored_module_names.insert(STR("MagicLeapPrivileges")); - this->m_ignored_module_names.insert(STR("MagicLeapSecureStorage")); - this->m_ignored_module_names.insert(STR("MagicLeapSharedWorld")); - this->m_ignored_module_names.insert(STR("MaterialShaderQualitySettings")); - this->m_ignored_module_names.insert(STR("MediaAssets")); - this->m_ignored_module_names.insert(STR("MediaCompositing")); - this->m_ignored_module_names.insert(STR("MediaUtils")); - this->m_ignored_module_names.insert(STR("MeshDescription")); - this->m_ignored_module_names.insert(STR("MobilePatchingUtils")); - this->m_ignored_module_names.insert(STR("MotoSynth")); - this->m_ignored_module_names.insert(STR("MoviePlayer")); - this->m_ignored_module_names.insert(STR("MovieScene")); - this->m_ignored_module_names.insert(STR("MovieSceneCapture")); - this->m_ignored_module_names.insert(STR("MovieSceneTracks")); - this->m_ignored_module_names.insert(STR("MRMesh")); - this->m_ignored_module_names.insert(STR("NavigationSystem")); - this->m_ignored_module_names.insert(STR("NetCore")); - this->m_ignored_module_names.insert(STR("Niagara")); - this->m_ignored_module_names.insert(STR("NiagaraAnimNotifies")); - this->m_ignored_module_names.insert(STR("NiagaraCore")); - this->m_ignored_module_names.insert(STR("NiagaraShader")); - this->m_ignored_module_names.insert(STR("OculusHMD")); - this->m_ignored_module_names.insert(STR("OculusInput")); - this->m_ignored_module_names.insert(STR("OculusMR")); - this->m_ignored_module_names.insert(STR("OnlineSubsystem")); - this->m_ignored_module_names.insert(STR("OnlineSubsystemUtils")); - this->m_ignored_module_names.insert(STR("Overlay")); - this->m_ignored_module_names.insert(STR("PacketHandler")); - this->m_ignored_module_names.insert(STR("Paper2D")); - this->m_ignored_module_names.insert(STR("PhysicsCore")); - this->m_ignored_module_names.insert(STR("PhysXVehicles")); - this->m_ignored_module_names.insert(STR("ProceduralMeshComponent")); - this->m_ignored_module_names.insert(STR("PropertyAccess")); - this->m_ignored_module_names.insert(STR("PropertyPath")); - this->m_ignored_module_names.insert(STR("Renderer")); - this->m_ignored_module_names.insert(STR("Serialization")); - this->m_ignored_module_names.insert(STR("SessionMessages")); - this->m_ignored_module_names.insert(STR("SignificanceManager")); - this->m_ignored_module_names.insert(STR("Slate")); - this->m_ignored_module_names.insert(STR("SlateCore")); - this->m_ignored_module_names.insert(STR("SoundFields")); - this->m_ignored_module_names.insert(STR("StaticMeshDescription")); - this->m_ignored_module_names.insert(STR("SteamVR")); - this->m_ignored_module_names.insert(STR("SteamVRInputDevice")); - this->m_ignored_module_names.insert(STR("Synthesis")); - this->m_ignored_module_names.insert(STR("TcpMessaging")); - this->m_ignored_module_names.insert(STR("TemplateSequence")); - this->m_ignored_module_names.insert(STR("TimeManagement")); - this->m_ignored_module_names.insert(STR("UdpMessaging")); - this->m_ignored_module_names.insert(STR("UMG")); - this->m_ignored_module_names.insert(STR("UObjectPlugin")); - this->m_ignored_module_names.insert(STR("VariantManagerContent")); - this->m_ignored_module_names.insert(STR("VectorVM")); - this->m_ignored_module_names.insert(STR("WmfMediaFactory")); + this->m_ignored_module_names.insert(SYSSTR("ActorLayerUtilities")); + this->m_ignored_module_names.insert(SYSSTR("ActorSequence")); + this->m_ignored_module_names.insert(SYSSTR("AIModule")); + this->m_ignored_module_names.insert(SYSSTR("AndroidPermission")); + this->m_ignored_module_names.insert(SYSSTR("AnimationCore")); + this->m_ignored_module_names.insert(SYSSTR("AnimationSharing")); + this->m_ignored_module_names.insert(SYSSTR("AnimGraphRuntime")); + this->m_ignored_module_names.insert(SYSSTR("AppleImageUtils")); + this->m_ignored_module_names.insert(SYSSTR("ArchVisCharacter")); + this->m_ignored_module_names.insert(SYSSTR("AssetRegistry")); + this->m_ignored_module_names.insert(SYSSTR("AssetTags")); + this->m_ignored_module_names.insert(SYSSTR("AudioAnalyzer")); + this->m_ignored_module_names.insert(SYSSTR("AudioCapture")); + this->m_ignored_module_names.insert(SYSSTR("AudioExtensions")); + this->m_ignored_module_names.insert(SYSSTR("AudioMixer")); + this->m_ignored_module_names.insert(SYSSTR("AudioPlatformConfiguration")); + this->m_ignored_module_names.insert(SYSSTR("AudioSynesthesia")); + this->m_ignored_module_names.insert(SYSSTR("AugmentedReality")); + this->m_ignored_module_names.insert(SYSSTR("AutomationUtils")); + this->m_ignored_module_names.insert(SYSSTR("AvfMediaFactory")); + this->m_ignored_module_names.insert(SYSSTR("BuildPatchServices")); + this->m_ignored_module_names.insert(SYSSTR("CableComponent")); + this->m_ignored_module_names.insert(SYSSTR("Chaos")); + this->m_ignored_module_names.insert(SYSSTR("ChaosCloth")); + this->m_ignored_module_names.insert(SYSSTR("ChaosNiagara")); + this->m_ignored_module_names.insert(SYSSTR("ChaosSolvers")); + this->m_ignored_module_names.insert(SYSSTR("ChaosSolverEngine")); + this->m_ignored_module_names.insert(SYSSTR("CinematicCamera")); + this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeCommon")); + this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeInterface")); + this->m_ignored_module_names.insert(SYSSTR("ClothingSystemRuntimeNv")); + this->m_ignored_module_names.insert(SYSSTR("CustomMeshComponent")); + this->m_ignored_module_names.insert(SYSSTR("DatasmithContent")); + this->m_ignored_module_names.insert(SYSSTR("DeveloperSettings")); + this->m_ignored_module_names.insert(SYSSTR("EditableMesh")); + this->m_ignored_module_names.insert(SYSSTR("EngineMessages")); + this->m_ignored_module_names.insert(SYSSTR("EngineSettings")); + this->m_ignored_module_names.insert(SYSSTR("EyeTracker")); + this->m_ignored_module_names.insert(SYSSTR("FacialAnimation")); + this->m_ignored_module_names.insert(SYSSTR("FieldSystemCore")); + this->m_ignored_module_names.insert(SYSSTR("FieldSystemEngine")); + this->m_ignored_module_names.insert(SYSSTR("Foliage")); + this->m_ignored_module_names.insert(SYSSTR("GameplayTags")); + this->m_ignored_module_names.insert(SYSSTR("GameplayTasks")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCache")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCacheTracks")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionCore")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionSimulationCore")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionEngine")); + this->m_ignored_module_names.insert(SYSSTR("GeometryCollectionTracks")); + this->m_ignored_module_names.insert(SYSSTR("GooglePAD")); + this->m_ignored_module_names.insert(SYSSTR("HeadMountedDisplay")); + this->m_ignored_module_names.insert(SYSSTR("ImageWrapper")); + this->m_ignored_module_names.insert(SYSSTR("ImageWriteQueue")); + this->m_ignored_module_names.insert(SYSSTR("ImgMedia")); + this->m_ignored_module_names.insert(SYSSTR("ImgMediaFactory")); + this->m_ignored_module_names.insert(SYSSTR("InputCore")); + this->m_ignored_module_names.insert(SYSSTR("InteractiveToolsFramework")); + this->m_ignored_module_names.insert(SYSSTR("JsonUtilities")); + this->m_ignored_module_names.insert(SYSSTR("Landscape")); + this->m_ignored_module_names.insert(SYSSTR("LevelSequence")); + this->m_ignored_module_names.insert(SYSSTR("LightPropagationVolumeRuntime")); + this->m_ignored_module_names.insert(SYSSTR("LiveLinkInterface")); + this->m_ignored_module_names.insert(SYSSTR("LocationServicesBPLibrary")); + this->m_ignored_module_names.insert(SYSSTR("LuminRuntimeSettings")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeap")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapAR")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapARPin")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapAudio")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapController")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapEyeTracker")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapHandMeshing")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapHandTracking")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapIdentity")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapImageTracker")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapLightEstimation")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapPlanes")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapPrivileges")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapSecureStorage")); + this->m_ignored_module_names.insert(SYSSTR("MagicLeapSharedWorld")); + this->m_ignored_module_names.insert(SYSSTR("MaterialShaderQualitySettings")); + this->m_ignored_module_names.insert(SYSSTR("MediaAssets")); + this->m_ignored_module_names.insert(SYSSTR("MediaCompositing")); + this->m_ignored_module_names.insert(SYSSTR("MediaUtils")); + this->m_ignored_module_names.insert(SYSSTR("MeshDescription")); + this->m_ignored_module_names.insert(SYSSTR("MobilePatchingUtils")); + this->m_ignored_module_names.insert(SYSSTR("MotoSynth")); + this->m_ignored_module_names.insert(SYSSTR("MoviePlayer")); + this->m_ignored_module_names.insert(SYSSTR("MovieScene")); + this->m_ignored_module_names.insert(SYSSTR("MovieSceneCapture")); + this->m_ignored_module_names.insert(SYSSTR("MovieSceneTracks")); + this->m_ignored_module_names.insert(SYSSTR("MRMesh")); + this->m_ignored_module_names.insert(SYSSTR("NavigationSystem")); + this->m_ignored_module_names.insert(SYSSTR("NetCore")); + this->m_ignored_module_names.insert(SYSSTR("Niagara")); + this->m_ignored_module_names.insert(SYSSTR("NiagaraAnimNotifies")); + this->m_ignored_module_names.insert(SYSSTR("NiagaraCore")); + this->m_ignored_module_names.insert(SYSSTR("NiagaraShader")); + this->m_ignored_module_names.insert(SYSSTR("OculusHMD")); + this->m_ignored_module_names.insert(SYSSTR("OculusInput")); + this->m_ignored_module_names.insert(SYSSTR("OculusMR")); + this->m_ignored_module_names.insert(SYSSTR("OnlineSubsystem")); + this->m_ignored_module_names.insert(SYSSTR("OnlineSubsystemUtils")); + this->m_ignored_module_names.insert(SYSSTR("Overlay")); + this->m_ignored_module_names.insert(SYSSTR("PacketHandler")); + this->m_ignored_module_names.insert(SYSSTR("Paper2D")); + this->m_ignored_module_names.insert(SYSSTR("PhysicsCore")); + this->m_ignored_module_names.insert(SYSSTR("PhysXVehicles")); + this->m_ignored_module_names.insert(SYSSTR("ProceduralMeshComponent")); + this->m_ignored_module_names.insert(SYSSTR("PropertyAccess")); + this->m_ignored_module_names.insert(SYSSTR("PropertyPath")); + this->m_ignored_module_names.insert(SYSSTR("Renderer")); + this->m_ignored_module_names.insert(SYSSTR("Serialization")); + this->m_ignored_module_names.insert(SYSSTR("SessionMessages")); + this->m_ignored_module_names.insert(SYSSTR("SignificanceManager")); + this->m_ignored_module_names.insert(SYSSTR("Slate")); + this->m_ignored_module_names.insert(SYSSTR("SlateCore")); + this->m_ignored_module_names.insert(SYSSTR("SoundFields")); + this->m_ignored_module_names.insert(SYSSTR("StaticMeshDescription")); + this->m_ignored_module_names.insert(SYSSTR("SteamVR")); + this->m_ignored_module_names.insert(SYSSTR("SteamVRInputDevice")); + this->m_ignored_module_names.insert(SYSSTR("Synthesis")); + this->m_ignored_module_names.insert(SYSSTR("TcpMessaging")); + this->m_ignored_module_names.insert(SYSSTR("TemplateSequence")); + this->m_ignored_module_names.insert(SYSSTR("TimeManagement")); + this->m_ignored_module_names.insert(SYSSTR("UdpMessaging")); + this->m_ignored_module_names.insert(SYSSTR("UMG")); + this->m_ignored_module_names.insert(SYSSTR("UObjectPlugin")); + this->m_ignored_module_names.insert(SYSSTR("VariantManagerContent")); + this->m_ignored_module_names.insert(SYSSTR("VectorVM")); + this->m_ignored_module_names.insert(SYSSTR("WmfMediaFactory")); } } @@ -3663,20 +3665,20 @@ namespace RC::UEGenerator { ignore_selected_modules(); - Output::send(STR("Cleaning up previously generated SDK (if one exists)\n")); + Output::send(SYSSTR("Cleaning up previously generated SDK (if one exists)\n")); if (std::filesystem::exists(m_root_directory)) { std::filesystem::remove_all(m_root_directory); } - Output::send(STR("Initializing native packages dump\n")); + Output::send(SYSSTR("Initializing native packages dump\n")); std::vector native_classes_to_dump; std::vector native_structs_to_dump; std::vector native_enums_to_dump; std::vector native_delegates_to_dump; - Output::send(STR("Gathering native objects for dumping\n")); + Output::send(SYSSTR("Gathering native objects for dumping\n")); UObjectGlobals::ForEachUObject([&](void* raw_object, int32_t chunk_index, int32_t object_index) { UObject* typed_object = static_cast(raw_object); @@ -3721,37 +3723,37 @@ namespace RC::UEGenerator return RC::LoopAction::Continue; }); - Output::send(STR("Attempting to dump {} native classes\n"), native_classes_to_dump.size()); + Output::send(SYSSTR("Attempting to dump {} native classes\n"), native_classes_to_dump.size()); for (UFunction* delegate_signature_function : native_delegates_to_dump) { - // Output::send(STR("Dumping native delegate type {}\n"), global_delegate_signature->GetName()); + // Output::send(SYSSTR("Dumping native delegate type {}\n"), global_delegate_signature->GetName()); generate_object_description_file(delegate_signature_function); } for (UClass* class_to_dump : native_classes_to_dump) { - // Output::send(STR("Dumping native class {}\n"), class_to_dump->GetName()); + // Output::send(SYSSTR("Dumping native class {}\n"), class_to_dump->GetName()); generate_object_description_file(class_to_dump); } - Output::send(STR("Attempting to dump {} native structs\n"), native_structs_to_dump.size()); + Output::send(SYSSTR("Attempting to dump {} native structs\n"), native_structs_to_dump.size()); for (UScriptStruct* struct_to_dump : native_structs_to_dump) { - // Output::send(STR("Dumping native struct {}\n"), struct_to_dump->GetName()); + // Output::send(SYSSTR("Dumping native struct {}\n"), struct_to_dump->GetName()); generate_object_description_file(struct_to_dump); } - Output::send(STR("Attempting to dump {} native enums\n"), native_enums_to_dump.size()); + Output::send(SYSSTR("Attempting to dump {} native enums\n"), native_enums_to_dump.size()); for (UEnum* enum_to_dump : native_enums_to_dump) { - // Output::send(STR("Dumping native enum {}\n"), enum_to_dump->GetName()); + // Output::send(SYSSTR("Dumping native enum {}\n"), enum_to_dump->GetName()); generate_object_description_file(enum_to_dump); } - Output::send(STR("Writing stub module build files for {} modules\n"), m_module_dependencies.size()); + Output::send(SYSSTR("Writing stub module build files for {} modules\n"), m_module_dependencies.size()); for (const auto& module_pair : m_module_dependencies) { generate_module_implementation_file(module_pair.first); @@ -3775,7 +3777,7 @@ namespace RC::UEGenerator { name = get_native_struct_name(std::bit_cast(object)); } - header_file.append_line(std::format(STR("FORCEINLINE uint32 GetTypeHash(const {}) {{ return 0; }}"), name)); + header_file.append_line(std::format(SYSSTR("FORCEINLINE uint32 GetTypeHash(const {}) {{ return 0; }}"), name)); } // Case for FTickFunction struct @@ -3785,32 +3787,32 @@ namespace RC::UEGenerator auto super_struct = struct_object->GetSuperScriptStruct(); if (super_struct) { - if (get_native_struct_name(super_struct) == STR("FTickFunction")) + if (get_native_struct_name(super_struct) == SYSSTR("FTickFunction")) { SystemStringType name{}; name = get_native_struct_name(struct_object); - header_file.append_line(STR("")); - header_file.append_line(STR("template<>")); + header_file.append_line(SYSSTR("")); + header_file.append_line(SYSSTR("template<>")); header_file.append_line(std::format(SYSSTR("struct TStructOpsTypeTraits<{}> : public TStructOpsTypeTraitsBase2<{}>"), name, name)); - header_file.append_line(STR("{")); - header_file.append_line(STR(" enum")); - header_file.append_line(STR(" {")); - header_file.append_line(STR(" WithCopy = false")); - header_file.append_line(STR(" };")); - header_file.append_line(STR("};")); + header_file.append_line(SYSSTR("{")); + header_file.append_line(SYSSTR(" enum")); + header_file.append_line(SYSSTR(" {")); + header_file.append_line(SYSSTR(" WithCopy = false")); + header_file.append_line(SYSSTR(" };")); + header_file.append_line(SYSSTR("};")); } } } header_file.serialize_file_content_to_disk(); } - Output::send(STR("Done!\n")); + Output::send(SYSSTR("Done!\n")); } auto UEHeaderGenerator::generate_object_description_file(UObject* object) -> bool { - const UEStringType module_name = get_module_name_for_package(object->GetOutermost()); - const UEStringType file_base_name = get_header_name_for_object(object); + const SystemStringType module_name = get_module_name_for_package(object->GetOutermost()); + const SystemStringType file_base_name = get_header_name_for_object(object); if (module_name.empty()) { @@ -3868,7 +3870,7 @@ namespace RC::UEGenerator auto iterator = this->m_module_dependencies.find(module_name); if (iterator == this->m_module_dependencies.end()) { - iterator = this->m_module_dependencies.insert({module_name, std::make_shared>()}).first; + iterator = this->m_module_dependencies.insert({module_name, std::make_shared>()}).first; } if (!header_file.has_content_to_save()) @@ -3883,16 +3885,16 @@ namespace RC::UEGenerator header_file.generate_file_contents(); // Record module names used in the headers - std::shared_ptr> out_dependency_module_names = iterator->second; + std::shared_ptr> out_dependency_module_names = iterator->second; header_file.copy_dependency_module_names(*out_dependency_module_names); implementation_file.copy_dependency_module_names(*out_dependency_module_names); return true; } - auto UEHeaderGenerator::generate_object_pre_declaration(UObject* object) -> std::vector> + auto UEHeaderGenerator::generate_object_pre_declaration(UObject* object) -> std::vector> { - std::vector> pre_declarations; + std::vector> pre_declarations; UClass* object_class = object->GetClassPrivate(); @@ -3902,15 +3904,15 @@ namespace RC::UEGenerator if (uclass->IsChildOf(UInterface::StaticClass())) { - pre_declarations.push_back({STR("class "), get_native_class_name(uclass, true), STR(";\n")}); + pre_declarations.push_back({SYSSTR("class "), get_native_class_name(uclass, true), SYSSTR(";\n")}); } - pre_declarations.push_back({STR("class "), get_native_class_name(uclass, false), STR(";\n")}); + pre_declarations.push_back({SYSSTR("class "), get_native_class_name(uclass, false), SYSSTR(";\n")}); } else if (object_class->IsChildOf(UScriptStruct::StaticClass())) { UScriptStruct* script_struct = static_cast(object); - pre_declarations.push_back({STR("struct "), get_native_struct_name(script_struct), STR(";\n")}); + pre_declarations.push_back({SYSSTR("struct "), get_native_struct_name(script_struct), SYSSTR(";\n")}); } else if (object_class->IsChildOf(UEnum::StaticClass())) { @@ -3960,8 +3962,8 @@ namespace RC::UEGenerator { // Otherwise, remove the postfix and use the function name as the header name // Also append the delegate postfix because apparently there can be conflicts - UEStringType DelegateName = strip_delegate_signature_postfix(signature_function); - DelegateName.append(STR("Delegate")); + SystemStringType DelegateName = strip_delegate_signature_postfix(signature_function); + DelegateName.append(SYSSTR("Delegate")); header_name = DelegateName; final_object = object; } @@ -4002,7 +4004,7 @@ namespace RC::UEGenerator generate_delegate_type_declaration(signature_function, delegate_class, header_data); } - auto UEHeaderGenerator::determine_primary_game_module_name() -> UEStringType + auto UEHeaderGenerator::determine_primary_game_module_name() -> SystemStringType { /* HMODULE primary_executable_module = GetModuleHandleW(NULL); @@ -4010,21 +4012,21 @@ namespace RC::UEGenerator GetModuleFileNameW(primary_executable_module, module_name_buffer, ARRAYSIZE(module_name_buffer)); // Retrieve the filename from the full path, strip down the extension - FFilePath root_executable_path((UEStringType(module_name_buffer))); - UEStringType filename = root_executable_path.filename().replace_extension().wstring(); + FFilePath root_executable_path((SystemStringType(module_name_buffer))); + SystemStringType filename = root_executable_path.filename().replace_extension().wstring(); // Remove the shipping file postfix - UEStringType shipping_postfix = STR("-Win64-Shipping"); + SystemStringType shipping_postfix = SYSSTR("-Win64-Shipping"); if (filename.ends_with(shipping_postfix)) { filename.erase(filename.length() - shipping_postfix.length()); } return filename; */ - return STR("Main"); + return SYSSTR("Main"); } - auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const UEStringType& module_name, const UEStringType& fallback_name) -> UEStringType + auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) -> SystemStringType { // Retrieve the most top level object located inside the native package UObject* top_level_object = object; @@ -4034,8 +4036,8 @@ namespace RC::UEGenerator top_level_object = top_level_object->GetOuterPrivate(); } - const auto object_name = (top_level_object->GetName()); - return std::format(STR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), module_name, object_name, fallback_name); + const auto object_name = to_system(top_level_object->GetName()); + return std::format(SYSSTR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), to_system(module_name), object_name, to_system(fallback_name)); } GeneratedFile::GeneratedFile(const FFilePath& full_file_path) @@ -4046,20 +4048,20 @@ namespace RC::UEGenerator this->m_current_indent_count = 0; } - auto GeneratedFile::append_line(const UEStringType& line) -> void + auto GeneratedFile::append_line(const SystemStringType& line) -> void { for (int32_t i = 0; i < m_current_indent_count; i++) { - m_file_contents_buffer.append(STR(" ")); + m_file_contents_buffer.append(SYSSTR(" ")); } m_file_contents_buffer.append(line); - m_file_contents_buffer.append(STR("\n")); + m_file_contents_buffer.append(SYSSTR("\n")); } - auto GeneratedFile::append_line_no_indent(const UEStringType& line) -> void + auto GeneratedFile::append_line_no_indent(const SystemStringType& line) -> void { m_file_contents_buffer.append(line); - m_file_contents_buffer.append(STR("\n")); + m_file_contents_buffer.append(SYSSTR("\n")); } auto GeneratedFile::begin_indent_level() -> void @@ -4097,7 +4099,7 @@ namespace RC::UEGenerator return true; } - auto GeneratedFile::generate_file_contents() -> UEStringType + auto GeneratedFile::generate_file_contents() -> SystemStringType { return m_file_contents_buffer; } @@ -4108,24 +4110,24 @@ namespace RC::UEGenerator } auto GeneratedSourceFile::create_source_file(const FFilePath& root_dir, - const UEStringType& module_name, - const UEStringType& base_name, + const SystemStringType& module_name, + const SystemStringType& base_name, bool is_implementation_file, UObject* object) -> GeneratedSourceFile { FFilePath full_file_path; if (is_implementation_file) { - full_file_path = root_dir / module_name / STR("Private") / (base_name + STR(".cpp")); + full_file_path = root_dir / module_name / SYSSTR("Private") / (base_name + SYSSTR(".cpp")); } else { - full_file_path = root_dir / module_name / STR("Public") / (base_name + STR(".h")); + full_file_path = root_dir / module_name / SYSSTR("Public") / (base_name + SYSSTR(".h")); } return GeneratedSourceFile(full_file_path, module_name, is_implementation_file, object); } - GeneratedSourceFile::GeneratedSourceFile(const FFilePath& file_path, const UEStringType& file_module_name, bool is_implementation_file, UObject* object) + GeneratedSourceFile::GeneratedSourceFile(const FFilePath& file_path, const SystemStringType& file_module_name, bool is_implementation_file, UObject* object) : GeneratedFile(file_path) { this->m_file_module_name = file_module_name; @@ -4138,7 +4140,7 @@ namespace RC::UEGenerator this->m_header_file = header_file; } - auto GeneratedSourceFile::add_extra_include(const UEStringType& included_file_name) -> void + auto GeneratedSourceFile::add_extra_include(const SystemStringType& included_file_name) -> void { this->m_extra_includes.insert(included_file_name); } @@ -4154,44 +4156,44 @@ namespace RC::UEGenerator } } - auto GeneratedSourceFile::generate_file_contents() -> UEStringType + auto GeneratedSourceFile::generate_file_contents() -> SystemStringType { - UEStringType result_header_contents; + SystemStringType result_header_contents; result_header_contents.append(generate_includes_string()); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); - UEStringType pre_declarations_string = generate_pre_declarations_string(); + SystemStringType pre_declarations_string = generate_pre_declarations_string(); if (!pre_declarations_string.empty()) { result_header_contents.append(pre_declarations_string); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); } if (!m_implementation_constructor.empty()) { result_header_contents.append(m_implementation_constructor); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); } if (!m_file_contents_buffer.empty()) { result_header_contents.append(m_file_contents_buffer); - result_header_contents.append(STR("\n")); + result_header_contents.append(SYSSTR("\n")); } return result_header_contents; } - auto GeneratedSourceFile::generate_includes_string() const -> UEStringType + auto GeneratedSourceFile::generate_includes_string() const -> SystemStringType { - UEStringType result_include_string; - std::vector> include_lines; - std::vector cross_module_includes; + SystemStringType result_include_string; + std::vector> include_lines; + std::vector cross_module_includes; // For the header file, we generate the pragma and minimal core includes if (!m_is_implementation_file) { - result_include_string.append(STR("#pragma once\n")); - result_include_string.append(STR("#include \"CoreMinimal.h\"\n")); + result_include_string.append(SYSSTR("#pragma once\n")); + result_include_string.append(SYSSTR("#include \"CoreMinimal.h\"\n")); } // For CPP implementation file, we need to generate the header include if (m_is_implementation_file) @@ -4199,19 +4201,19 @@ namespace RC::UEGenerator if (m_header_file != NULL) { // Generate it if we have the correct header file set - result_include_string.append(std::format(STR("#include \"{}.h\"\n"), m_header_file->m_file_base_name)); + result_include_string.append(std::format(SYSSTR("#include \"{}.h\"\n"), m_header_file->m_file_base_name)); } else { // Otherwise, we generate a simple minimal core include - result_include_string.append(STR("#include \"CoreMinimal.h\"\n")); + result_include_string.append(SYSSTR("#include \"CoreMinimal.h\"\n")); } } // Generate extra includes we might need that do not represent objects - for (const UEStringType& extra_included_file : m_extra_includes) + for (const SystemStringType& extra_included_file : m_extra_includes) { - include_lines.push_back({STR("#include \""), extra_included_file, STR("\"\n")}); + include_lines.push_back({SYSSTR("#include \""), extra_included_file, SYSSTR("\"\n")}); } // Generate includes for the relevant object files @@ -4225,7 +4227,7 @@ namespace RC::UEGenerator continue; } - const UEStringType object_header_name = UEHeaderGenerator::get_header_name_for_object(dependency_object, true); + const SystemStringType object_header_name = UEHeaderGenerator::get_header_name_for_object(dependency_object, true); // Definitely skip include if object in question is placed into this header if (object_header_name == m_file_base_name) @@ -4242,7 +4244,7 @@ namespace RC::UEGenerator } } UObject* package = dependency_object->GetOutermost(); - UEStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); + SystemStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); if (!native_module_name.empty()) { @@ -4250,7 +4252,7 @@ namespace RC::UEGenerator // since generated headers are always located in the module root and follow one file per object convention if (m_file_module_name == native_module_name) { - include_lines.push_back({STR("#include \""), object_header_name, STR(".h\"\n")}); + include_lines.push_back({SYSSTR("#include \""), object_header_name, SYSSTR(".h\"\n")}); } else { @@ -4267,13 +4269,13 @@ namespace RC::UEGenerator // Remove duplicates - there are sometimes multiple instances of the same cross module include cross_module_includes.erase(std::unique(cross_module_includes.begin(), cross_module_includes.end()), cross_module_includes.end()); - for (const UEStringType& cross_module_include : cross_module_includes) + for (const SystemStringType& cross_module_include : cross_module_includes) { result_include_string.append(cross_module_include); } // Sort the includes by module name, since we want to make sure that they are always in the same order - std::sort(include_lines.begin(), include_lines.end(), [](const std::vector& a, const std::vector& b) { + std::sort(include_lines.begin(), include_lines.end(), [](const std::vector& a, const std::vector& b) { return a[1] < b[1]; }); @@ -4288,15 +4290,15 @@ namespace RC::UEGenerator // Last include of the header file should always be a generated one if (!m_is_implementation_file) { - result_include_string.append(std::format(STR("#include \"{}.generated.h\"\n"), m_file_base_name)); + result_include_string.append(std::format(SYSSTR("#include \"{}.generated.h\"\n"), m_file_base_name)); } return result_include_string; } - auto GeneratedSourceFile::generate_pre_declarations_string() const -> UEStringType + auto GeneratedSourceFile::generate_pre_declarations_string() const -> SystemStringType { - UEStringType result_declarations; - std::vector>> pre_declarations; + SystemStringType result_declarations; + std::vector>> pre_declarations; // Generate pre-declarations for the relevant object files for (const auto& dependency_pair : m_dependencies) @@ -4311,7 +4313,7 @@ namespace RC::UEGenerator // We still need to reference the object's owner module UObject* package = dependency_object->GetOutermost(); - UEStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); + SystemStringType native_module_name = UEHeaderGenerator::get_module_name_for_package(package); if (!native_module_name.empty() && m_file_module_name != native_module_name) { @@ -4324,7 +4326,7 @@ namespace RC::UEGenerator // Sort the entries alphabetically by the class name std::sort(pre_declarations.begin(), pre_declarations.end(), - [](const std::vector>& a, const std::vector>& b) { + [](const std::vector>& a, const std::vector>& b) { return a[0][1] < b[0][1]; }); diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index d47b12afb..107815087 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -5,7 +5,7 @@ #define REGISTER_STRING_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_string(section_name, STR(#key)); \ + (member_var) = parser.get_string(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -14,7 +14,7 @@ #define REGISTER_INT64_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_int64(section_name, STR(#key)); \ + (member_var) = parser.get_int64(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -23,7 +23,7 @@ #define REGISTER_BOOL_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_bool(section_name, STR(#key)); \ + (member_var) = parser.get_bool(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -32,7 +32,7 @@ #define REGISTER_FLOAT_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_float(section_name, STR(#key)); \ + (member_var) = parser.get_float(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -46,10 +46,10 @@ namespace RC Ini::Parser parser; parser.parse(file); file.close(); - constexpr static UECharType section_overrides[] = STR("Overrides"); + constexpr static SystemCharType section_overrides[] = SYSSTR("Overrides"); REGISTER_STRING_SETTING(Overrides.ModsFolderPath, section_overrides, ModsFolderPath) - constexpr static UECharType section_general[] = STR("General"); + constexpr static SystemCharType section_general[] = SYSSTR("General"); REGISTER_BOOL_SETTING(General.EnableHotReloadSystem, section_general, EnableHotReloadSystem) REGISTER_BOOL_SETTING(General.UseCache, section_general, UseCache) REGISTER_BOOL_SETTING(General.InvalidateCacheIfDLLDiffers, section_general, InvalidateCacheIfDLLDiffers) @@ -57,19 +57,19 @@ namespace RC REGISTER_INT64_SETTING(General.SecondsToScanBeforeGivingUp, section_general, SecondsToScanBeforeGivingUp) REGISTER_BOOL_SETTING(General.UseUObjectArrayCache, section_general, bUseUObjectArrayCache) - constexpr static UECharType section_engine_version_override[] = STR("EngineVersionOverride"); + constexpr static SystemCharType section_engine_version_override[] = SYSSTR("EngineVersionOverride"); REGISTER_INT64_SETTING(EngineVersionOverride.MajorVersion, section_engine_version_override, MajorVersion) REGISTER_INT64_SETTING(EngineVersionOverride.MinorVersion, section_engine_version_override, MinorVersion) - constexpr static UECharType section_object_dumper[] = STR("ObjectDumper"); + constexpr static SystemCharType section_object_dumper[] = SYSSTR("ObjectDumper"); REGISTER_BOOL_SETTING(ObjectDumper.LoadAllAssetsBeforeDumpingObjects, section_object_dumper, LoadAllAssetsBeforeDumpingObjects) - constexpr static UECharType section_cxx_header_generator[] = STR("CXXHeaderGenerator"); + constexpr static SystemCharType section_cxx_header_generator[] = SYSSTR("CXXHeaderGenerator"); REGISTER_BOOL_SETTING(CXXHeaderGenerator.DumpOffsetsAndSizes, section_cxx_header_generator, DumpOffsetsAndSizes) REGISTER_BOOL_SETTING(CXXHeaderGenerator.KeepMemoryLayout, section_cxx_header_generator, KeepMemoryLayout) REGISTER_BOOL_SETTING(CXXHeaderGenerator.LoadAllAssetsBeforeGeneratingCXXHeaders, section_cxx_header_generator, LoadAllAssetsBeforeGeneratingCXXHeaders) - constexpr static UECharType section_uht_header_generator[] = STR("UHTHeaderGenerator"); + constexpr static SystemCharType section_uht_header_generator[] = SYSSTR("UHTHeaderGenerator"); REGISTER_BOOL_SETTING(UHTHeaderGenerator.IgnoreAllCoreEngineModules, section_uht_header_generator, IgnoreAllCoreEngineModules) REGISTER_BOOL_SETTING(UHTHeaderGenerator.IgnoreEngineAndCoreUObject, section_uht_header_generator, IgnoreEngineAndCoreUObject) REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeAllFunctionsBlueprintCallable, section_uht_header_generator, MakeAllFunctionsBlueprintCallable) @@ -77,7 +77,7 @@ namespace RC REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeEnumClassesBlueprintType, section_uht_header_generator, MakeEnumClassesBlueprintType) REGISTER_BOOL_SETTING(UHTHeaderGenerator.MakeAllConfigsEngineConfig, section_uht_header_generator, MakeAllConfigsEngineConfig) - constexpr static UECharType section_debug[] = STR("Debug"); + constexpr static SystemCharType section_debug[] = SYSSTR("Debug"); REGISTER_BOOL_SETTING(Debug.SimpleConsoleEnabled, section_debug, ConsoleEnabled) REGISTER_BOOL_SETTING(Debug.DebugConsoleEnabled, section_debug, GuiConsoleEnabled) REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) @@ -85,29 +85,29 @@ namespace RC #ifdef HAS_GUI UEStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) - if (String::iequal(graphics_api_string, STR("DX11")) || String::iequal(graphics_api_string, STR("D3D11"))) + if (String::iequal(graphics_api_string, SYSSTR("DX11")) || String::iequal(graphics_api_string, SYSSTR("D3D11"))) { Debug.GraphicsAPI = GUI::GfxBackend::DX11; } - else if (String::iequal(graphics_api_string, STR("OpenGL"))) + else if (String::iequal(graphics_api_string, SYSSTR("OpenGL"))) { Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; } #endif REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); - ///constexpr static UECharType section_crash_dump[] = SSTR("CrashDump"); + ///constexpr static SystemCharType section_crash_dump[] = SSTR("CrashDump"); ///REGISTER_BOOL_SETTING(CrashDump.EnableDumping, section_crash_dump, EnableDumping); ///REGISTER_BOOL_SETTING(CrashDump.FullMemoryDump, section_crash_dump, FullMemoryDump); - constexpr static UECharType section_threads[] = STR("Threads"); + constexpr static SystemCharType section_threads[] = SYSSTR("Threads"); REGISTER_INT64_SETTING(Threads.SigScannerNumThreads, section_threads, SigScannerNumThreads) REGISTER_INT64_SETTING(Threads.SigScannerMultithreadingModuleSizeThreshold, section_threads, SigScannerMultithreadingModuleSizeThreshold) - constexpr static UECharType section_memory[] = STR("Memory"); + constexpr static SystemCharType section_memory[] = SYSSTR("Memory"); REGISTER_INT64_SETTING(Memory.MaxMemoryUsageDuringAssetLoading, section_memory, MaxMemoryUsageDuringAssetLoading) - constexpr static UECharType section_hooks[] = STR("Hooks"); + constexpr static SystemCharType section_hooks[] = SYSSTR("Hooks"); REGISTER_BOOL_SETTING(Hooks.HookProcessInternal, section_hooks, HookProcessInternal) REGISTER_BOOL_SETTING(Hooks.HookProcessLocalScriptFunction, section_hooks, HookProcessLocalScriptFunction) REGISTER_BOOL_SETTING(Hooks.HookLoadMap, section_hooks, HookLoadMap) @@ -118,7 +118,7 @@ namespace RC REGISTER_BOOL_SETTING(Hooks.HookAActorTick, section_hooks, HookAActorTick) REGISTER_INT64_SETTING(Hooks.FExecVTableOffsetInLocalPlayer, section_hooks, FExecVTableOffsetInLocalPlayer) - constexpr static UECharType section_experimental_features[] = STR("ExperimentalFeatures"); + constexpr static SystemCharType section_experimental_features[] = SYSSTR("ExperimentalFeatures"); REGISTER_BOOL_SETTING(Experimental.GUIUFunctionCaller, section_experimental_features, GUIUFunctionCaller) } } // namespace RC diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index cf3378d28..dd3bcee1f 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -508,7 +508,7 @@ namespace RC if (std::filesystem::exists(file_path)) { auto file = File::open(file_path); - if (auto file_contents = file.read_all(); !file_contents.empty()) + if (auto file_contents = file.read_file_all(); !file_contents.empty()) { Ini::Parser parser; parser.parse(file_contents); diff --git a/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp index e0f017d07..5ce4e9f70 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/FileDevice.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace RC::Output { @@ -82,7 +83,7 @@ namespace RC::Output // Do file output stuff here // File should already be open & be ready for writing (happens in constructor) - m_file.write_string_to_file(m_formatter(fmt)); + m_file.write_file_string_to_file(to_file(m_formatter(fmt))); } // OutputDevice Interface -> END diff --git a/deps/first/File/include/File/FileType/StdFile.hpp b/deps/first/File/include/File/FileType/StdFile.hpp index bf9343df4..cb2c9f2f8 100644 --- a/deps/first/File/include/File/FileType/StdFile.hpp +++ b/deps/first/File/include/File/FileType/StdFile.hpp @@ -78,7 +78,7 @@ namespace RC::File [[nodiscard]] RC_FILE_API auto static open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> StdFile; [[nodiscard]] RC_FILE_API auto read_file_all() const -> SystemStringType override; - RC_FILE_API auto auto write_file_string_to_file(StringViewType) -> void override; + RC_FILE_API auto write_file_string_to_file(StringViewType) -> void override; // File Interface -> END }; diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index cd41b2658..af6ae5979 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -304,8 +304,8 @@ namespace RC::File try { static std::wstring_convert, char16_t> converter{}; - atuo utf8_string = converter.to_bytes(input); - write_file_string_to_file(*this, utf8_string.data(), utf8_string.size()); + auto utf8_string = converter.to_bytes(string_to_write.begin(), string_to_write.begin() + string_to_write.size()); + write_file_string_to_file(utf8_string); } catch (const std::exception& e) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::write_string_to_file] Tried writing string to file but could not convert to utf-8. Error: {}", e.what())) } diff --git a/deps/first/IniParser/src/Ini.cpp b/deps/first/IniParser/src/Ini.cpp index 84dd3c093..652b1f667 100644 --- a/deps/first/IniParser/src/Ini.cpp +++ b/deps/first/IniParser/src/Ini.cpp @@ -5,7 +5,7 @@ namespace RC::Ini { - auto Parser::parse_internal(UEStringType& input) -> void + auto Parser::parse_internal(SystemStringType& input) -> void { // Tokenize -> START ParserBase::Tokenizer tokenizer; @@ -25,24 +25,24 @@ namespace RC::Ini { ParserBase::TokenContainer tc; - tc.add(ParserBase::Token::create(IniTokenType::CarriageReturn, STR("CarriageReturn"), STR("\r"))); - tc.add(ParserBase::Token::create(IniTokenType::NewLine, STR("NewLine"), STR("\n"))); - tc.add(ParserBase::Token::create(IniTokenType::Space, STR("Space"), STR(" "))); + tc.add(ParserBase::Token::create(IniTokenType::CarriageReturn, SYSSTR("CarriageReturn"), SYSSTR("\r"))); + tc.add(ParserBase::Token::create(IniTokenType::NewLine, SYSSTR("NewLine"), SYSSTR("\n"))); + tc.add(ParserBase::Token::create(IniTokenType::Space, SYSSTR("Space"), SYSSTR(" "))); tc.add(ParserBase::Token::create(IniTokenType::Characters, - STR("Characters"), - STR(""), + SYSSTR("Characters"), + SYSSTR(""), ParserBase::Token::HasData::Yes)); // Empty identifier will match everything that no other token identifier matches - tc.add(ParserBase::Token::create /**/ (IniTokenType::Equals, STR("Equals"), STR("="))); - tc.add(ParserBase::Token::create(IniTokenType::ClosingSquareBracket, STR("CloseSquareBracket"), STR("]"))); - tc.add(ParserBase::Token::create(IniTokenType::OpeningSquareBracket, STR("OpenSquareBracket"), STR("["))); - tc.add(ParserBase::Token::create(IniTokenType::SemiColon, STR("SemiColon"), STR(";"))); + tc.add(ParserBase::Token::create /**/ (IniTokenType::Equals, SYSSTR("Equals"), SYSSTR("="))); + tc.add(ParserBase::Token::create(IniTokenType::ClosingSquareBracket, SYSSTR("CloseSquareBracket"), SYSSTR("]"))); + tc.add(ParserBase::Token::create(IniTokenType::OpeningSquareBracket, SYSSTR("OpenSquareBracket"), SYSSTR("["))); + tc.add(ParserBase::Token::create(IniTokenType::SemiColon, SYSSTR("SemiColon"), SYSSTR(";"))); tc.set_eof_token(IniTokenType::EndOfFile); return tc; } - auto Parser::get_value(const UEStringType& section, const UEStringType& key, CanThrow can_throw) const + auto Parser::get_value(const SystemStringType& section, const SystemStringType& key, CanThrow can_throw) const -> std::optional> { if (!m_parsing_is_complete) @@ -77,18 +77,18 @@ namespace RC::Ini } } - auto Parser::parse(UEStringType& input) -> void + auto Parser::parse(SystemStringType& input) -> void { parse_internal(input); } auto Parser::parse(const File::Handle& file) -> void { - auto input = file.read_all(); + auto input = file.read_file_all(); parse_internal(input); } - auto Parser::get_list(const UEStringType& section) -> List + auto Parser::get_list(const SystemStringType& section) -> List { const auto& section_iter = m_sections.find(section); @@ -102,13 +102,13 @@ namespace RC::Ini } } - auto Parser::get_ordered_list(const UEStringType& section) -> List + auto Parser::get_ordered_list(const SystemStringType& section) -> List { return get_list(section); } - auto Parser::get_string(const UEStringType& section, const UEStringType& key, const UEStringType& default_value) const noexcept - -> const UEStringType& + auto Parser::get_string(const SystemStringType& section, const SystemStringType& key, const SystemStringType& default_value) const noexcept + -> const SystemStringType& { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -129,7 +129,7 @@ namespace RC::Ini } } - auto Parser::get_string(const UEStringType& section, const UEStringType& key) const -> const UEStringType& + auto Parser::get_string(const SystemStringType& section, const SystemStringType& key) const -> const SystemStringType& { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -150,7 +150,7 @@ namespace RC::Ini } } - auto Parser::get_int64(const UEStringType& section, const UEStringType& key, int64_t default_value) const noexcept -> int64_t + auto Parser::get_int64(const SystemStringType& section, const SystemStringType& key, int64_t default_value) const noexcept -> int64_t { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -171,7 +171,7 @@ namespace RC::Ini } } - auto Parser::get_int64(const UEStringType& section, const UEStringType& key) const -> int64_t + auto Parser::get_int64(const SystemStringType& section, const SystemStringType& key) const -> int64_t { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -192,7 +192,7 @@ namespace RC::Ini } } - auto Parser::get_float(const UEStringType& section, const UEStringType& key, float default_value) const noexcept -> float + auto Parser::get_float(const SystemStringType& section, const SystemStringType& key, float default_value) const noexcept -> float { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -213,7 +213,7 @@ namespace RC::Ini } } - auto Parser::get_float(const UEStringType& section, const UEStringType& key) const -> float + auto Parser::get_float(const SystemStringType& section, const SystemStringType& key) const -> float { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) @@ -234,7 +234,7 @@ namespace RC::Ini } } - auto Parser::get_bool(const UEStringType& section, const UEStringType& key, bool default_value) const noexcept -> bool + auto Parser::get_bool(const SystemStringType& section, const SystemStringType& key, bool default_value) const noexcept -> bool { const auto maybe_value = get_value(section, key, CanThrow::No); if (!maybe_value.has_value()) @@ -255,7 +255,7 @@ namespace RC::Ini } } - auto Parser::get_bool(const UEStringType& section, const UEStringType& key) const -> bool + auto Parser::get_bool(const SystemStringType& section, const SystemStringType& key) const -> bool { const auto maybe_value = get_value(section, key); if (!maybe_value.has_value()) diff --git a/deps/first/IniParser/src/JSON.cpp b/deps/first/IniParser/src/JSON.cpp index 37a6ba088..033e494a7 100644 --- a/deps/first/IniParser/src/JSON.cpp +++ b/deps/first/IniParser/src/JSON.cpp @@ -362,14 +362,14 @@ namespace RC::Parser m_token_parser->parse(); } - auto JSON::parse(UEStringType& input) -> void + auto JSON::parse(SystemStringType& input) -> void { parse_internal(input); } auto JSON::parse(File::Handle& file) -> void { - auto input = file.read_all(); + auto input = file.read_file_all(); parse_internal(input); } diff --git a/deps/first/IniParser/src/TokenParser.cpp b/deps/first/IniParser/src/TokenParser.cpp index 4933bc66d..a107a1589 100644 --- a/deps/first/IniParser/src/TokenParser.cpp +++ b/deps/first/IniParser/src/TokenParser.cpp @@ -28,22 +28,22 @@ namespace RC::Ini bool is_bool{false}; }; - auto static is_int(UEStringType data) -> Int + auto static is_int(SystemStringType data) -> Int { bool has_0x_prefix = [&]() { - return (data.size() > 2 && data[0] == STR('0') && (data[1] == STR('x') || data[1] == STR('X'))); + return (data.size() > 2 && data[0] == SYSSTR('0') && (data[1] == SYSSTR('x') || data[1] == SYSSTR('X'))); }(); - if (!has_0x_prefix && data[0] != L'-' && std::iswdigit(data[0]) == 0) + if (!has_0x_prefix && data[0] != SYSSTR('-') && std::iswdigit(data[0]) == 0) { return Int{0, 10, false}; } else { - UEStringType string = has_0x_prefix ? UEStringType{data.begin() + 2, data.end()} : data; - if (!has_0x_prefix && data[0] == STR('-')) + SystemStringType string = has_0x_prefix ? SystemStringType{data.begin() + 2, data.end()} : data; + if (!has_0x_prefix && data[0] == SYSSTR('-')) { - string = UEStringType{string.begin() + 1, string.end()}; + string = SystemStringType{string.begin() + 1, string.end()}; } bool is_int = std::ranges::all_of(string.begin(), string.end(), [&](const UECharType c) { if constexpr (std::is_same_v) @@ -60,10 +60,10 @@ namespace RC::Ini } } - auto static is_float(UEStringType data) -> Float + auto static is_float(SystemStringType data) -> Float { bool has_decimal_or_negative_prefix = [&]() { - return data.size() > 1 && data[0] == STR('.') || data[0] == STR('-'); + return data.size() > 1 && data[0] == SYSSTR('.') || data[0] == SYSSTR('-'); }(); if (!has_decimal_or_negative_prefix && std::iswdigit(data[0]) == 0) @@ -72,19 +72,19 @@ namespace RC::Ini } else { - UEStringType string = data.ends_with(STR('f')) ? UEStringType{data.begin(), data.end() - 1} : data; + SystemStringType string = data.ends_with(SYSSTR('f')) ? SystemStringType{data.begin(), data.end() - 1} : data; if (has_decimal_or_negative_prefix) { - string = UEStringType{string.begin() + 1, string.end()}; + string = SystemStringType{string.begin() + 1, string.end()}; } bool is_float = std::ranges::all_of(string.begin(), string.end(), [&](const UECharType c) { if constexpr (std::is_same_v) { - return has_decimal_or_negative_prefix ? std::iswxdigit(c) : std::iswdigit(c) != 0 || c == STR('.'); + return has_decimal_or_negative_prefix ? std::iswxdigit(c) : std::iswdigit(c) != 0 || c == SYSSTR('.'); } else { - return has_decimal_or_negative_prefix ? std::isxdigit(c) : std::isdigit(c) != 0 || c == STR('.'); + return has_decimal_or_negative_prefix ? std::isxdigit(c) : std::isdigit(c) != 0 || c == SYSSTR('.'); } }); @@ -92,17 +92,17 @@ namespace RC::Ini } } - auto static is_bool(const UEStringType& data) -> Bool + auto static is_bool(const SystemStringType& data) -> Bool { - UEStringType all_lower_string_data = data; + SystemStringType all_lower_string_data = data; std::transform(all_lower_string_data.begin(), all_lower_string_data.end(), all_lower_string_data.begin(), [](UECharType c) { return std::towlower(c); }); - if (all_lower_string_data == STR("true") || all_lower_string_data == STR("1")) + if (all_lower_string_data == SYSSTR("true") || all_lower_string_data == SYSSTR("1")) { return Bool{.value = true, .is_bool = true}; } - else if (all_lower_string_data == STR("false") || all_lower_string_data == STR("0")) + else if (all_lower_string_data == SYSSTR("false") || all_lower_string_data == SYSSTR("0")) { return Bool{.value = false, .is_bool = true}; } @@ -112,7 +112,7 @@ namespace RC::Ini } } - auto TokenParser::find_variable_by_name(Section* section, const RC::UEStringType& name) -> std::optional> + auto TokenParser::find_variable_by_name(Section* section, const RC::SystemStringType& name) -> std::optional> { auto const& var = section->key_value_pairs.find(name); if (var != section->key_value_pairs.end()) @@ -125,9 +125,9 @@ namespace RC::Ini } } - auto TokenParser::find_variable_by_name(const UEStringType& name) -> std::optional> + auto TokenParser::find_variable_by_name(const SystemStringType& name) -> std::optional> { - size_t occurrence_of_dot = name.find_first_of(L'.'); + size_t occurrence_of_dot = name.find_first_of(SYSSTR('.')); if (occurrence_of_dot == name.npos || occurrence_of_dot + 1 > name.size()) { return find_variable_by_name(m_current_section, name); @@ -141,38 +141,38 @@ namespace RC::Ini } else { - const UEStringType requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); + const SystemStringType requested_variable_name = name.substr(occurrence_of_dot + 1, name.size()); return find_variable_by_name(&requested_section->second, requested_variable_name); } } } - auto state_to_string(State state) -> UEStringType + auto state_to_string(State state) -> SystemStringType { switch (state) { case State::StartOfFile: - return STR("StartOfFile"); + return SYSSTR("StartOfFile"); case State::SetSectionValue: - return STR("SetSectionValue"); + return SYSSTR("SetSectionValue"); case State::NewLineStarted: - return STR("NewLineStarted"); + return SYSSTR("NewLineStarted"); case State::CreateNewOrSetCurrentSection: - return STR("CreateNewOrSetCurrentSection"); + return SYSSTR("CreateNewOrSetCurrentSection"); case State::CreateSectionKey: - return STR("CreateSectionKey"); + return SYSSTR("CreateSectionKey"); case State::StoreSectionKey: - return STR("StoreSectionKey"); + return SYSSTR("StoreSectionKey"); } - return STR("UnknownState"); + return SYSSTR("UnknownState"); } - auto TokenParser::characters_to_string(const ParserBase::Token& characters_token) -> UEStringType + auto TokenParser::characters_to_string(const ParserBase::Token& characters_token) -> SystemStringType { auto* current_token = &characters_token; - UEStringType full_value{}; + SystemStringType full_value{}; while (true) { const auto token_type = current_token->get_type(); @@ -182,7 +182,7 @@ namespace RC::Ini } else if (token_type == IniTokenType::Space) { - full_value.append(STR(" ")); + full_value.append(SYSSTR(" ")); } else if (token_type == IniTokenType::Characters) { @@ -190,7 +190,7 @@ namespace RC::Ini } else if (token_type == IniTokenType::Equals) { - full_value.append(STR("=")); + full_value.append(SYSSTR("=")); } else if (token_type == IniTokenType::ClosingSquareBracket) { @@ -201,15 +201,15 @@ namespace RC::Ini // The next token is the last token on this line and since it's ] we don't want to include it in the string break; } - full_value.append(STR("]")); + full_value.append(SYSSTR("]")); } else if (token_type == IniTokenType::OpeningSquareBracket) { - full_value.append(STR("[")); + full_value.append(SYSSTR("[")); } else if (token_type == IniTokenType::SemiColon) { - full_value.append(STR(";")); + full_value.append(SYSSTR(";")); } // Exit early and let the state machine deal with the new line @@ -290,7 +290,7 @@ namespace RC::Ini { if (m_current_state == State::CreateNewOrSetCurrentSection) { - m_current_character_data.append(STR(" ")); + m_current_character_data.append(SYSSTR(" ")); } } @@ -381,7 +381,7 @@ namespace RC::Ini // Create the value with the correct key and an empty value and store a pointer to it so that the value can be set later m_current_value = &m_current_section->key_value_pairs.emplace(m_current_character_data, Value{}).first->second; - m_current_value->add_string_value(STR("")); + m_current_value->add_string_value(SYSSTR("")); m_current_value->set_ref(m_current_value); m_current_character_data.clear(); diff --git a/deps/first/IniParser/src/Value.cpp b/deps/first/IniParser/src/Value.cpp index 71ddc24b4..36a23fa59 100644 --- a/deps/first/IniParser/src/Value.cpp +++ b/deps/first/IniParser/src/Value.cpp @@ -20,7 +20,7 @@ namespace RC::Ini m_ref = new_ref; } - auto Value::get_string_value() const -> const UEStringType& + auto Value::get_string_value() const -> const SystemStringType& { return m_string_value; } @@ -52,7 +52,7 @@ namespace RC::Ini add_type(); } - auto Value::add_int64_value(const UEStringType& data, int base) -> void + auto Value::add_int64_value(const SystemStringType& data, int base) -> void { m_int64_value = std::stoi(data, nullptr, base); @@ -64,7 +64,7 @@ namespace RC::Ini add_type(); } - auto Value::add_float_value(const UEStringType& data) -> void + auto Value::add_float_value(const SystemStringType& data) -> void { m_float_value = std::stof(data, nullptr); diff --git a/deps/first/JSON/include/JSON/Array.hpp b/deps/first/JSON/include/JSON/Array.hpp index 5af5c21b7..e4cd241b8 100644 --- a/deps/first/JSON/include/JSON/Array.hpp +++ b/deps/first/JSON/include/JSON/Array.hpp @@ -41,7 +41,7 @@ namespace RC::JSON public: auto new_object() -> class Object&; auto new_array() -> class Array&; - auto new_string(const UEStringType& value) -> void; + auto new_string(const SystemStringType& value) -> void; auto new_null() -> void; auto new_bool(bool value) -> void; @@ -87,7 +87,7 @@ namespace RC::JSON } public: - auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> UEStringType override; + auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Array; diff --git a/deps/first/JSON/include/JSON/Bool.hpp b/deps/first/JSON/include/JSON/Bool.hpp index c8f8450ec..ac4c44fc0 100644 --- a/deps/first/JSON/include/JSON/Bool.hpp +++ b/deps/first/JSON/include/JSON/Bool.hpp @@ -23,7 +23,7 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> UEStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Bool; diff --git a/deps/first/JSON/include/JSON/Common.hpp b/deps/first/JSON/include/JSON/Common.hpp index c11653e78..99dc44be8 100644 --- a/deps/first/JSON/include/JSON/Common.hpp +++ b/deps/first/JSON/include/JSON/Common.hpp @@ -39,7 +39,7 @@ namespace RC::JSON class ScopeStack; } - auto inline indent(int32_t* indent_level, UEStringType& string) -> void + auto inline indent(int32_t* indent_level, SystemStringType& string) -> void { if (!indent_level) { @@ -48,7 +48,7 @@ namespace RC::JSON for (int32_t i = 0; i < *indent_level; ++i) { - string.append(STR(" ")); + string.append(SYSSTR(" ")); } } } // namespace RC::JSON diff --git a/deps/first/JSON/include/JSON/KeyValuePair.hpp b/deps/first/JSON/include/JSON/KeyValuePair.hpp index ef0a8c829..8c665ab32 100644 --- a/deps/first/JSON/include/JSON/KeyValuePair.hpp +++ b/deps/first/JSON/include/JSON/KeyValuePair.hpp @@ -5,13 +5,13 @@ namespace RC::JSON template struct TypedKeyValuePair { - const UEStringType& key; + const SystemStringType& key; T* value{}; }; struct KeyValuePair { - UEStringType key{}; + SystemStringType key{}; std::unique_ptr value{}; template diff --git a/deps/first/JSON/include/JSON/Null.hpp b/deps/first/JSON/include/JSON/Null.hpp index 7fe5d5497..27aeab023 100644 --- a/deps/first/JSON/include/JSON/Null.hpp +++ b/deps/first/JSON/include/JSON/Null.hpp @@ -13,7 +13,7 @@ namespace RC::JSON ~Null() override = default; public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> UEStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Null; diff --git a/deps/first/JSON/include/JSON/Number.hpp b/deps/first/JSON/include/JSON/Number.hpp index 8ae06c560..9fc269624 100644 --- a/deps/first/JSON/include/JSON/Number.hpp +++ b/deps/first/JSON/include/JSON/Number.hpp @@ -167,7 +167,7 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> UEStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> JSON::Type override { return JSON::Type::Number; diff --git a/deps/first/JSON/include/JSON/Object.hpp b/deps/first/JSON/include/JSON/Object.hpp index f9d670fde..207225cc9 100644 --- a/deps/first/JSON/include/JSON/Object.hpp +++ b/deps/first/JSON/include/JSON/Object.hpp @@ -30,7 +30,7 @@ namespace RC::JSON #pragma warning(disable : 4251) private: - std::unordered_map> m_members{}; + std::unordered_map> m_members{}; IsGlobalObject m_is_global_object{IsGlobalObject::No}; #pragma warning(default : 4251) @@ -44,17 +44,17 @@ namespace RC::JSON auto operator=(const Object&) -> Object& = delete; private: - auto find_value_by_key(const UEStringType& key) const -> Value*; - auto find_value_by_key(const UEStringType& key) -> Value*; + auto find_value_by_key(const SystemStringType& key) const -> Value*; + auto find_value_by_key(const SystemStringType& key) -> Value*; public: - auto new_object(UEStringType name) -> Object&; - auto new_array(UEStringType name) -> class Array&; - auto new_string(UEStringType name, const UEStringType& value) -> void; - auto new_null(UEStringType name) -> void; - auto new_bool(UEStringType name, bool value) -> void; + auto new_object(SystemStringType name) -> Object&; + auto new_array(SystemStringType name) -> class Array&; + auto new_string(SystemStringType name, const SystemStringType& value) -> void; + auto new_null(SystemStringType name) -> void; + auto new_bool(SystemStringType name, bool value) -> void; - auto add_object(UEStringType name, std::unique_ptr) -> void; + auto add_object(SystemStringType name, std::unique_ptr) -> void; auto get() -> decltype(m_members)& { @@ -66,7 +66,7 @@ namespace RC::JSON }; template - auto get(const UEStringType& key) const -> ValueType& + auto get(const SystemStringType& key) const -> ValueType& { auto value = find_value_by_key(key); if (!value) @@ -77,7 +77,7 @@ namespace RC::JSON } template - auto get(const UEStringType& key) -> ValueType& + auto get(const SystemStringType& key) -> ValueType& { auto value = find_value_by_key(key); if (!value) @@ -88,12 +88,12 @@ namespace RC::JSON } template - auto new_number(UEStringType name, number_type value) -> void + auto new_number(SystemStringType name, number_type value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> UEStringType override; + auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; auto get_type() const -> Type override { return Type::Object; diff --git a/deps/first/JSON/include/JSON/Parser/TokenParser.hpp b/deps/first/JSON/include/JSON/Parser/TokenParser.hpp index 1a80a435a..35e003afa 100644 --- a/deps/first/JSON/include/JSON/Parser/TokenParser.hpp +++ b/deps/first/JSON/include/JSON/Parser/TokenParser.hpp @@ -79,7 +79,7 @@ namespace RC::JSON::Parser } } template - auto add_element_to_top(UEStringType key, std::unique_ptr value) -> ValueType* + auto add_element_to_top(SystemStringType key, std::unique_ptr value) -> ValueType* { auto& top = peek_top(); if (top.is()) @@ -107,7 +107,7 @@ namespace RC::JSON::Parser private: std::unique_ptr m_global_object; ScopeStack m_scope_stack{}; - UEStringType m_last_key{}; + SystemStringType m_last_key{}; std::unique_ptr m_last_value{}; State m_current_state{State::StartOfFile}; TokenType m_expected_token{}; @@ -115,7 +115,7 @@ namespace RC::JSON::Parser bool m_defer_element_creation{}; public: - TokenParser(const ParserBase::Tokenizer& tokenizer, UEStringType& input) : ParserBase::TokenParser(tokenizer, input) + TokenParser(const ParserBase::Tokenizer& tokenizer, SystemStringType& input) : ParserBase::TokenParser(tokenizer, input) { } virtual ~TokenParser() = default; diff --git a/deps/first/JSON/include/JSON/String.hpp b/deps/first/JSON/include/JSON/String.hpp index 24cbe0e92..f62602ddf 100644 --- a/deps/first/JSON/include/JSON/String.hpp +++ b/deps/first/JSON/include/JSON/String.hpp @@ -14,25 +14,25 @@ namespace RC::JSON RC_JSON_API constexpr static Type static_type = Type::String; private: - UEStringType m_data{}; + SystemStringType m_data{}; public: RC_JSON_API String() = default; - RC_JSON_API explicit String(UEStringViewType string); + RC_JSON_API explicit String(SystemStringViewType string); RC_JSON_API ~String() override = default; public: - RC_JSON_API auto get() -> UEStringType& + RC_JSON_API auto get() -> SystemStringType& { return m_data; } - RC_JSON_API auto get_view() const -> UEStringViewType + RC_JSON_API auto get_view() const -> SystemStringViewType { return m_data; } public: - RC_JSON_API auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> UEStringType override; + RC_JSON_API auto serialize(ShouldFormat should_format = ShouldFormat::No, int32_t* indent_level = nullptr) -> SystemStringType override; RC_JSON_API auto get_type() const -> Type override { return Type::String; diff --git a/deps/first/JSON/src/Array.cpp b/deps/first/JSON/src/Array.cpp index 01001995f..413d103f8 100644 --- a/deps/first/JSON/src/Array.cpp +++ b/deps/first/JSON/src/Array.cpp @@ -36,22 +36,22 @@ namespace RC::JSON m_members.emplace_back(std::move(object)); } - auto Array::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType + auto Array::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { if (!indent_level) { throw std::runtime_error{"Must supply an indent_level pointer"}; }; - UEStringType array_as_string{}; + SystemStringType array_as_string{}; if (should_format == ShouldFormat::Yes && !m_members.empty()) { - array_as_string.append(STR("[\n")); + array_as_string.append(SYSSTR("[\n")); } else { - array_as_string.append(STR("[")); + array_as_string.append(SYSSTR("[")); } ++(*indent_level); @@ -70,11 +70,11 @@ namespace RC::JSON { if (should_format == ShouldFormat::Yes) { - array_as_string.append(STR(",\n")); + array_as_string.append(SYSSTR(",\n")); } else { - array_as_string.append(STR(",")); + array_as_string.append(SYSSTR(",")); } } @@ -85,13 +85,13 @@ namespace RC::JSON if (should_format == ShouldFormat::Yes && !m_members.empty()) { - array_as_string.append(STR("\n")); + array_as_string.append(SYSSTR("\n")); indent(indent_level, array_as_string); - array_as_string.append(STR("]")); + array_as_string.append(SYSSTR("]")); } else { - array_as_string.append(STR("]")); + array_as_string.append(SYSSTR("]")); } if (!m_members.empty()) diff --git a/deps/first/JSON/src/Bool.cpp b/deps/first/JSON/src/Bool.cpp index af6afda93..62b894131 100644 --- a/deps/first/JSON/src/Bool.cpp +++ b/deps/first/JSON/src/Bool.cpp @@ -6,10 +6,10 @@ namespace RC::JSON { } - auto Bool::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType + auto Bool::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { (void)should_format; (void)indent_level; - return m_underlying_value ? STR("true") : STR("false"); + return m_underlying_value ? SYSSTR("true") : SYSSTR("false"); } } // namespace RC::JSON diff --git a/deps/first/JSON/src/Null.cpp b/deps/first/JSON/src/Null.cpp index 2aa883bc1..0cbda75f9 100644 --- a/deps/first/JSON/src/Null.cpp +++ b/deps/first/JSON/src/Null.cpp @@ -2,10 +2,10 @@ namespace RC::JSON { - auto Null::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType + auto Null::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { (void)should_format; (void)indent_level; - return STR("null"); + return SYSSTR("null"); } } // namespace RC::JSON diff --git a/deps/first/JSON/src/Number.cpp b/deps/first/JSON/src/Number.cpp index 859bb13be..eb97ade3b 100644 --- a/deps/first/JSON/src/Number.cpp +++ b/deps/first/JSON/src/Number.cpp @@ -42,7 +42,7 @@ namespace RC::JSON m_stored_type = Type::Double; } - auto Number::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType + auto Number::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { (void)should_format; (void)indent_level; diff --git a/deps/first/JSON/src/Object.cpp b/deps/first/JSON/src/Object.cpp index 9ba33bd19..172ed07cd 100644 --- a/deps/first/JSON/src/Object.cpp +++ b/deps/first/JSON/src/Object.cpp @@ -6,7 +6,7 @@ namespace RC::JSON { - auto Object::find_value_by_key(const UEStringType& look_for_key) const -> Value* + auto Object::find_value_by_key(const SystemStringType& look_for_key) const -> Value* { if (auto it = m_members.find(look_for_key); it != m_members.end()) { @@ -17,7 +17,7 @@ namespace RC::JSON return nullptr; } } - auto Object::find_value_by_key(const UEStringType& look_for_key) -> Value* + auto Object::find_value_by_key(const SystemStringType& look_for_key) -> Value* { if (auto it = m_members.find(look_for_key); it != m_members.end()) { @@ -29,52 +29,52 @@ namespace RC::JSON } } - auto Object::new_object(UEStringType name) -> Object& + auto Object::new_object(SystemStringType name) -> Object& { return *static_cast(m_members.emplace(std::move(name), std::make_unique()).first->second.get()); } - auto Object::new_array(UEStringType name) -> Array& + auto Object::new_array(SystemStringType name) -> Array& { return *static_cast(m_members.emplace(std::move(name), std::make_unique()).first->second.get()); } - auto Object::new_string(UEStringType name, const UEStringType& value) -> void + auto Object::new_string(SystemStringType name, const SystemStringType& value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto Object::new_null(UEStringType name) -> void + auto Object::new_null(SystemStringType name) -> void { m_members.emplace(std::move(name), std::make_unique()); } - auto Object::new_bool(UEStringType name, bool value) -> void + auto Object::new_bool(SystemStringType name, bool value) -> void { m_members.emplace(std::move(name), std::make_unique(value)); } - auto Object::add_object(UEStringType name, std::unique_ptr object) -> void + auto Object::add_object(SystemStringType name, std::unique_ptr object) -> void { m_members.emplace(std::move(name), std::move(object)); } - auto Object::serialize(ShouldFormat should_format, int32_t* indent_level) -> UEStringType + auto Object::serialize(ShouldFormat should_format, int32_t* indent_level) -> SystemStringType { if (!indent_level) { throw std::runtime_error{"Must supply an indent_level pointer"}; }; - UEStringType object_as_string{}; + SystemStringType object_as_string{}; if (should_format == ShouldFormat::Yes && !m_members.empty()) { - object_as_string.append(STR("{\n")); + object_as_string.append(SYSSTR("{\n")); } else { - object_as_string.append(STR("{")); + object_as_string.append(SYSSTR("{")); } ++(*indent_level); @@ -87,18 +87,18 @@ namespace RC::JSON indent(indent_level, object_as_string); } - object_as_string.append(std::format(STR("\"{}\":"), key)); + object_as_string.append(std::format(SYSSTR("\"{}\":"), key)); object_as_string.append(value->serialize(should_format, indent_level)); if (member_count + 1 < m_members.size()) { if (should_format == ShouldFormat::Yes) { - object_as_string.append(STR(",\n")); + object_as_string.append(SYSSTR(",\n")); } else { - object_as_string.append(STR(",")); + object_as_string.append(SYSSTR(",")); } } @@ -109,13 +109,13 @@ namespace RC::JSON if (should_format == ShouldFormat::Yes && !m_members.empty()) { - object_as_string.append(STR("\n")); + object_as_string.append(SYSSTR("\n")); indent(indent_level, object_as_string); - object_as_string.append(STR("}")); + object_as_string.append(SYSSTR("}")); } else { - object_as_string.append(STR("}")); + object_as_string.append(SYSSTR("}")); } if (!m_members.empty() || m_is_global_object == IsGlobalObject::Yes) diff --git a/deps/first/JSON/src/Parser/Parser.cpp b/deps/first/JSON/src/Parser/Parser.cpp index e249a3973..9fc11867f 100644 --- a/deps/first/JSON/src/Parser/Parser.cpp +++ b/deps/first/JSON/src/Parser/Parser.cpp @@ -11,28 +11,28 @@ namespace RC::JSON::Parser { ParserBase::TokenContainer tc; - tc.add(ParserBase::Token::create(TokenType::CarriageReturn, STR("CarriageReturn"), STR("\r"))); - tc.add(ParserBase::Token::create(TokenType::NewLine, STR("NewLine"), STR("\n"))); - tc.add(ParserBase::Token::create(TokenType::DoubleQuote, STR("DoubleQuote"), STR("\""))); + tc.add(ParserBase::Token::create(TokenType::CarriageReturn, SYSSTR("CarriageReturn"), SYSSTR("\r"))); + tc.add(ParserBase::Token::create(TokenType::NewLine, SYSSTR("NewLine"), SYSSTR("\n"))); + tc.add(ParserBase::Token::create(TokenType::DoubleQuote, SYSSTR("DoubleQuote"), SYSSTR("\""))); tc.add(ParserBase::Token::create(TokenType::Characters, - STR("Characters"), - STR(""), + SYSSTR("Characters"), + SYSSTR(""), ParserBase::Token::HasData::Yes)); // Empty identifier will match everything that no other token identifier matches - tc.add(ParserBase::Token::create(TokenType::ClosingCurlyBrace, STR("ClosingCurlyBrace"), STR("}"))); - tc.add(ParserBase::Token::create(TokenType::OpeningCurlyBrace, STR("OpeningCurlyBrace"), STR("{"))); - tc.add(ParserBase::Token::create(TokenType::ClosingSquareBracket, STR("ClosingSquareBracket"), STR("]"))); - tc.add(ParserBase::Token::create(TokenType::OpeningSquareBracket, STR("OpeningSquareBracket"), STR("["))); - tc.add(ParserBase::Token::create(TokenType::Comma, STR("Comma"), STR(","))); - tc.add(ParserBase::Token::create(TokenType::Colon, STR("Colon"), STR(":"))); - tc.add(ParserBase::Token::create(TokenType::True, STR("True"), STR("true"))); - tc.add(ParserBase::Token::create(TokenType::False, STR("False"), STR("false"))); + tc.add(ParserBase::Token::create(TokenType::ClosingCurlyBrace, SYSSTR("ClosingCurlyBrace"), SYSSTR("}"))); + tc.add(ParserBase::Token::create(TokenType::OpeningCurlyBrace, SYSSTR("OpeningCurlyBrace"), SYSSTR("{"))); + tc.add(ParserBase::Token::create(TokenType::ClosingSquareBracket, SYSSTR("ClosingSquareBracket"), SYSSTR("]"))); + tc.add(ParserBase::Token::create(TokenType::OpeningSquareBracket, SYSSTR("OpeningSquareBracket"), SYSSTR("["))); + tc.add(ParserBase::Token::create(TokenType::Comma, SYSSTR("Comma"), SYSSTR(","))); + tc.add(ParserBase::Token::create(TokenType::Colon, SYSSTR("Colon"), SYSSTR(":"))); + tc.add(ParserBase::Token::create(TokenType::True, SYSSTR("True"), SYSSTR("true"))); + tc.add(ParserBase::Token::create(TokenType::False, SYSSTR("False"), SYSSTR("false"))); tc.set_eof_token(TokenType::EndOfFile); return tc; } - static auto parse_internal(UEStringType& input) -> std::unique_ptr + static auto parse_internal(SystemStringType& input) -> std::unique_ptr { // Tokenize -> START ParserBase::Tokenizer tokenizer; @@ -56,19 +56,19 @@ namespace RC::JSON::Parser auto parse(File::StringType& input) -> std::unique_ptr { - auto ue_input = to_ue(input); - return Internal::parse_internal(ue_input); + auto sys_input = to_system(input); + return Internal::parse_internal(sys_input); } auto parse(UEStringType& input) -> std::unique_ptr { - auto ue_input = input; - return Internal::parse_internal(ue_input); + auto sys_input = to_system(input); + return Internal::parse_internal(sys_input); } auto parse(const File::Handle& file) -> std::unique_ptr { - auto input = file.read_all(); + auto input = file.read_file_all(); return Internal::parse_internal(input); } } // namespace RC::JSON::Parser diff --git a/deps/first/JSON/src/Parser/TokenParser.cpp b/deps/first/JSON/src/Parser/TokenParser.cpp index cad2ee6c6..0d3728175 100644 --- a/deps/first/JSON/src/Parser/TokenParser.cpp +++ b/deps/first/JSON/src/Parser/TokenParser.cpp @@ -32,9 +32,9 @@ namespace RC::JSON::Parser throw std::runtime_error{e}; \ } - static auto is_number(UEStringViewType data) -> bool + static auto is_number(SystemStringViewType data) -> bool { - return std::ranges::all_of(data.begin(), data.end(), [&](const UECharType c) { + return std::ranges::all_of(data.begin(), data.end(), [&](const SystemCharType c) { return std::iswdigit((wchar_t)c) != 0; }); } @@ -64,10 +64,10 @@ namespace RC::JSON::Parser return m_storage.back(); } - static auto has_only_spaces(const UEStringType& data) -> bool + static auto has_only_spaces(const SystemStringType& data) -> bool { - return std::all_of(data.begin(), data.end(), [](UECharType c) { - return std::isspace(c) || c == '\n'; + return std::all_of(data.begin(), data.end(), [](SystemCharType c) { + return std::iswspace(c) || c == SYSSTR('\n'); }); } @@ -164,7 +164,7 @@ namespace RC::JSON::Parser else if (m_current_state == State::ReadValue) { auto data_raw = get_data(token); - UEStringType data_no_spaces = data_raw; + SystemStringType data_no_spaces = data_raw; data_no_spaces.erase(std::remove_if(data_no_spaces.begin(), data_no_spaces.end(), [](wchar_t c) { diff --git a/deps/first/JSON/src/String.cpp b/deps/first/JSON/src/String.cpp index 619f2de65..6a89d1165 100644 --- a/deps/first/JSON/src/String.cpp +++ b/deps/first/JSON/src/String.cpp @@ -2,12 +2,12 @@ namespace RC::JSON { - String::String(UEStringViewType string) : m_data(string) + String::String(SystemStringViewType string) : m_data(string) { } - auto String::serialize([[maybe_unused]] ShouldFormat should_format, [[maybe_unused]] int32_t* indent_level) -> UEStringType + auto String::serialize([[maybe_unused]] ShouldFormat should_format, [[maybe_unused]] int32_t* indent_level) -> SystemStringType { - return std::format(STR("\"{}\""), m_data); + return std::format(SYSSTR("\"{}\""), m_data); } } // namespace RC::JSON diff --git a/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp b/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp index dafa64c95..8812f1ddb 100644 --- a/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp +++ b/deps/first/ParserBase/include/ParserBase/Tokenizer.hpp @@ -43,7 +43,7 @@ namespace RC::ParserBase public: RC_PB_API auto set_available_tokens(TokenContainer&&) -> void; // TODO: Maybe the constructor should take the input instead of 'tokenize' - RC_PB_API auto tokenize(const UEStringType& input) -> void; + RC_PB_API auto tokenize(const SystemStringType& input) -> void; [[nodiscard]] RC_PB_API auto get_tokens() const -> const std::vector&; [[nodiscard]] RC_PB_API auto get_last_token() const -> const Token&; }; diff --git a/deps/first/ParserBase/src/Tokenizer.cpp b/deps/first/ParserBase/src/Tokenizer.cpp index afe228c51..68630bbf1 100644 --- a/deps/first/ParserBase/src/Tokenizer.cpp +++ b/deps/first/ParserBase/src/Tokenizer.cpp @@ -41,7 +41,7 @@ namespace RC::ParserBase m_token_container = std::move(token_container); } - auto Tokenizer::tokenize(const UEStringType& input) -> void + auto Tokenizer::tokenize(const SystemStringType& input) -> void { // printf_s("Tokenizer::tokenize()\n\n"); @@ -75,12 +75,12 @@ namespace RC::ParserBase throw std::runtime_error{"[Tokenizer::tokenize] Input was empty"}; } - UEStringType a; + SystemStringType a; - const UECharType* input_array = input.c_str(); + const SystemCharType* input_array = input.c_str(); size_t global_cursor{}; - auto peek = [&](SystemStringType& out_str, const UECharType* character, size_t num_chars) -> void { + auto peek = [&](SystemStringType& out_str, const SystemCharType* character, size_t num_chars) -> void { if (global_cursor + num_chars <= input.size()) { for (size_t i = 0; i < num_chars; ++i) @@ -102,7 +102,7 @@ namespace RC::ParserBase TokenFoundWrapper empty_token{}; size_t start_of_empty_token{}; bool start_of_empty_token_set{}; - const UECharType* c = input_array; + const SystemCharType* c = input_array; auto deal_with_possible_empty_token = [&]() { if (empty_token.token) @@ -137,8 +137,8 @@ namespace RC::ParserBase int advance_cursor_by{-1}; bool all_rules_obeyed{true}; - UEStringViewType identifier_to_find = token.get_identifier(); - UEStringType compare_to; + SystemStringViewType identifier_to_find = token.get_identifier(); + SystemStringType compare_to; size_t identifier_size = identifier_to_find.size(); peek(compare_to, c, identifier_size); bool identifier_should_match_all = identifier_to_find.empty(); From 2cb322d941ca59ddbbd7c61d9f787b2282d95fe2 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Tue, 20 Feb 2024 06:17:08 -0600 Subject: [PATCH 056/213] windows ping --- UE4SS/src/SDKGenerator/Generator.cpp | 2 +- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 2 +- UE4SS/src/UE4SSProgram.cpp | 3 ++- deps/first/IniParser/src/Ini.cpp | 2 +- deps/first/JSON/src/Parser/Parser.cpp | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/UE4SS/src/SDKGenerator/Generator.cpp b/UE4SS/src/SDKGenerator/Generator.cpp index 253575d7f..44a8ee9ae 100644 --- a/UE4SS/src/SDKGenerator/Generator.cpp +++ b/UE4SS/src/SDKGenerator/Generator.cpp @@ -691,7 +691,7 @@ namespace RC::UEGenerator auto generate_file_footer(GeneratedFile& generated_file) -> void { generated_file.primary_file.write_file_string_to_file( - IOSTR(SYSSTR("#endif\n")) + IOSTR("#endif\n") ); } auto generate_enum_declaration(SystemStringType& content_buffer, UEnum* uenum) -> void diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index eb1600273..a91bcdab6 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -1319,7 +1319,7 @@ namespace RC::UEGenerator if (string_value_string != SYSSTR("")) { - const SystemStringType result_value = create_string_literal(string_value_string); + const auto result_value = create_string_literal(to_system_string(string_value_string)); if (!super_and_no_access) { generate_simple_assignment_expression(property, result_value, implementation_file, property_scope); diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index dd3bcee1f..1f0671ce6 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -511,7 +511,8 @@ namespace RC if (auto file_contents = file.read_file_all(); !file_contents.empty()) { Ini::Parser parser; - parser.parse(file_contents); + auto content = to_system_string(file_contents); + parser.parse(content); file.close(); // The following code is auto-generated. diff --git a/deps/first/IniParser/src/Ini.cpp b/deps/first/IniParser/src/Ini.cpp index 652b1f667..8d2bcf5ca 100644 --- a/deps/first/IniParser/src/Ini.cpp +++ b/deps/first/IniParser/src/Ini.cpp @@ -84,7 +84,7 @@ namespace RC::Ini auto Parser::parse(const File::Handle& file) -> void { - auto input = file.read_file_all(); + auto input = to_system_string(file.read_file_all()); parse_internal(input); } diff --git a/deps/first/JSON/src/Parser/Parser.cpp b/deps/first/JSON/src/Parser/Parser.cpp index 9fc11867f..96ba288ac 100644 --- a/deps/first/JSON/src/Parser/Parser.cpp +++ b/deps/first/JSON/src/Parser/Parser.cpp @@ -68,7 +68,7 @@ namespace RC::JSON::Parser auto parse(const File::Handle& file) -> std::unique_ptr { - auto input = file.read_file_all(); + auto input = to_system_string(file.read_file_all()); return Internal::parse_internal(input); } } // namespace RC::JSON::Parser From d427714e57d17d0378952c7af96e77c87c0b93e2 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 20 Feb 2024 06:44:10 -0600 Subject: [PATCH 057/213] add windows builder --- .github/workflows/windows-test.yml | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/windows-test.yml diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml new file mode 100644 index 000000000..9ed5fec96 --- /dev/null +++ b/.github/workflows/windows-test.yml @@ -0,0 +1,52 @@ +name: Linux Test Build + +on: + workflow_dispatch: + push: + branches: [ "linux-port" ] + paths: + - "UE4SS/src/**" + - "UE4SS/include/**" + - "UE4SS/generated_src/**" + - "UE4SS/generated_include/**" + - "deps/**" + - "UE4SS/proxy_generator/**" + - ".github/**" + - "CMakeLists.txt" + +permissions: + contents: read + +jobs: + make-release: + runs-on: windows-2022 + steps: + - name: Setup github SSH + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSHKEY }} + known_hosts: unnecessary + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 # needed to get commits since last tag + ssh-key: ${{ secrets.SSHKEY }} + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + - name: Setup Ninja + uses: seanmiddleditch/gha-setup-ninja@v3 + - name: Setup Rust + uses: dtolnay/rust-toolchain@1.76.0 + - name: Build + run: | + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Windows + cmake --build build + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: Windows-Release + path: build/Output/Game__Shipping__Win64/UE4SS/bin From c12d6cf1e3b34f689b2817082d03508a871e5b34 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 20 Feb 2024 06:53:11 -0600 Subject: [PATCH 058/213] update script --- .github/workflows/linux-test.yml | 2 +- .github/workflows/windows-test.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index e5e98c5dc..aec579a6d 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -11,7 +11,7 @@ on: - "UE4SS/generated_include/**" - "deps/**" - "UE4SS/proxy_generator/**" - - ".github/**" + - ".github/linux-test.yml" - "CMakeLists.txt" permissions: diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml index 9ed5fec96..ceef6c554 100644 --- a/.github/workflows/windows-test.yml +++ b/.github/workflows/windows-test.yml @@ -11,7 +11,7 @@ on: - "UE4SS/generated_include/**" - "deps/**" - "UE4SS/proxy_generator/**" - - ".github/**" + - ".github/windows-test.yml" - "CMakeLists.txt" permissions: @@ -40,7 +40,7 @@ jobs: uses: dtolnay/rust-toolchain@1.76.0 - name: Build run: | - cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Windows + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 cmake --build build env: SCCACHE_GHA_ENABLED: "true" From e38c19ecf1083c4ffa66b94a4f1b893600adb51e Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 20 Feb 2024 06:55:17 -0600 Subject: [PATCH 059/213] change name --- .github/workflows/windows-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml index ceef6c554..b1a2310a9 100644 --- a/.github/workflows/windows-test.yml +++ b/.github/workflows/windows-test.yml @@ -1,4 +1,4 @@ -name: Linux Test Build +name: Windows Test Build on: workflow_dispatch: From e6aa2024859eab79a39afd32c5f0c4f3685081e5 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 20 Feb 2024 06:55:57 -0600 Subject: [PATCH 060/213] change path --- .github/workflows/linux-test.yml | 2 +- .github/workflows/windows-test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index aec579a6d..ba2a7d2be 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -11,7 +11,7 @@ on: - "UE4SS/generated_include/**" - "deps/**" - "UE4SS/proxy_generator/**" - - ".github/linux-test.yml" + - ".github/workflows/linux-test.yml" - "CMakeLists.txt" permissions: diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml index b1a2310a9..769d597e2 100644 --- a/.github/workflows/windows-test.yml +++ b/.github/workflows/windows-test.yml @@ -11,7 +11,7 @@ on: - "UE4SS/generated_include/**" - "deps/**" - "UE4SS/proxy_generator/**" - - ".github/windows-test.yml" + - ".github/workflows/windows-test.yml" - "CMakeLists.txt" permissions: From d4e4db18f4b37f621c168757ceb25b2d3cd17da9 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 20 Feb 2024 07:04:49 -0600 Subject: [PATCH 061/213] remove unused flag --- .github/workflows/windows-test.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml index 769d597e2..13bbb3892 100644 --- a/.github/workflows/windows-test.yml +++ b/.github/workflows/windows-test.yml @@ -42,9 +42,6 @@ jobs: run: | cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 cmake --build build - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - name: Upload Artifacts uses: actions/upload-artifact@v3 with: From 567aeff7d79c5cc11541970849017067e728c590 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 20 Feb 2024 07:16:50 -0600 Subject: [PATCH 062/213] fix type --- UE4SS/proxy_generator/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UE4SS/proxy_generator/main.cpp b/UE4SS/proxy_generator/main.cpp index 8feee84e8..44701910b 100644 --- a/UE4SS/proxy_generator/main.cpp +++ b/UE4SS/proxy_generator/main.cpp @@ -170,10 +170,10 @@ int _tmain(int argc, TCHAR* argv[]) cpp_file << "void load_original_dll()" << endl; cpp_file << "{" << endl; - cpp_file << " File::CharType path[MAX_PATH];" << endl; + cpp_file << " SystemCharType path[MAX_PATH];" << endl; cpp_file << " GetSystemDirectory(path, MAX_PATH);" << endl; cpp_file << endl; - cpp_file << std::format(" File::StringType dll_path = File::StringType(path) + STR(\"\\\\{}\");", input_dll_name.string()) << endl; + cpp_file << std::format(" SystemStringType dll_path = SystemStringType(path) + SYSSTR(\"\\\\{}\");", input_dll_name.string()) << endl; cpp_file << endl; cpp_file << " SOriginalDll = LoadLibrary(dll_path.c_str());" << endl; cpp_file << " if (!SOriginalDll)" << endl; From 5f40e5fced5d88f618910210c9de8e8aceeb7fa5 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 02:36:28 -0600 Subject: [PATCH 063/213] move platform specific codes --- .../include/SigScanner/Linux/DLData.hpp | 26 - .../SigScanner/SinglePassSigScanner.hpp | 346 ++++++++- .../SigScanner/SinglePassSigScannerLinux.hpp | 356 +-------- .../SigScanner/SinglePassSigScannerWin32.hpp | 332 +-------- .../src/SinglePassSigScanner.cpp | 676 +++++++++++++++++ .../src/SinglePassSigScannerLinux.cpp | 668 +---------------- .../src/SinglePassSigScannerWin32.cpp | 690 +----------------- 7 files changed, 1094 insertions(+), 2000 deletions(-) delete mode 100644 deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp create mode 100644 deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp deleted file mode 100644 index cd39a1938..000000000 --- a/deps/first/SinglePassSigScanner/include/SigScanner/Linux/DLData.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -struct DLData -{ - std::string libname; - uint8_t* base_address; - uint64_t map_start, map_end; - size_t size; - // sorted by start address - std::set> phdrs; - std::tuple find_phdr(uint8_t* addr) { - for (auto& phdr : phdrs) { - // use end address to find the phdr - if (std::get<0>(phdr) + std::get<1>(phdr) > addr) { - return phdr; - } - } - return std::make_tuple(nullptr, 0, 0); - } -}; diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp index bdd83425f..65479d1a6 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp @@ -1,7 +1,351 @@ #pragma once +#include +#include +#include +#include + +#include + + #ifdef WIN32 #include "SinglePassSigScannerWin32.hpp" #else #include "SinglePassSigScannerLinux.hpp" -#endif \ No newline at end of file +#endif + +#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) +#define LO_NIBBLE(b) ((b)&0x0F) + +namespace RC +{ + enum class ScanTarget + { + MainExe, + + AIModule, + Analytics, + AnalyticsET, + AnimationCore, + AnimGraphRuntime, + AppFramework, + ApplicationCore, + AssetRegistry, + AudioCaptureCore, + AudioCaptureRtAudio, + AudioExtensions, + AudioMixer, + AudioMixerCore, + AudioMixerXAudio2, + AudioPlatformConfiguration, + AugmentedReality, + AVEncoder, + AVIWriter, + BuildPatchServices, + BuildSettings, + Cbor, + CEF3Utils, + Chaos, + ChaosCore, + ChaosSolverEngine, + ChaosSolvers, + CinematicCamera, + ClothingSystemRuntimeCommon, + ClothingSystemRuntimeInterface, + ClothingSystemRuntimeNv, + Core, + CoreUObject, + CrunchCompression, + D3D11RHI, + D3D12RHI, + Engine, + EngineMessages, + EngineSettings, + EyeTracker, + FieldSystemCore, + FieldSystemEngine, + FieldSystemSimulationCore, + Foliage, + GameplayMediaEncoder, + GameplayTags, + GameplayTasks, + GeometryCollectionCore, + GeometryCollectionEngine, + GeometryCollectionSimulationCore, + HeadMountedDisplay, + HTTP, + HttpNetworkReplayStreaming, + HTTPServer, + Icmp, + ImageCore, + ImageWrapper, + ImageWriteQueue, + InputCore, + InputDevice, + InstallBundleManager, + InstancedSplines, + InteractiveToolsFramework, + Json, + JsonUtilities, + Landscape, + LauncherCheck, + LauncherPlatform, + LevelSequence, + LocalFileNetworkReplayStreaming, + MaterialShaderQualitySettings, + Media, + MediaAssets, + MediaUtils, + MeshDescription, + MeshUtilitiesCommon, + Messaging, + MessagingCommon, + MoviePlayer, + MovieScene, + MovieSceneCapture, + MovieSceneTracks, + MRMesh, + NavigationSystem, + Navmesh, + NetCore, + Networking, + NetworkReplayStreaming, + NonRealtimeAudioRenderer, + NullDrv, + NullNetworkReplayStreaming, + OpenGLDrv, + Overlay, + PacketHandler, + PakFile, + PerfCounters, + PhysicsCore, + PhysicsSQ, + PhysXCooking, + PreLoadScreen, + Projects, + PropertyPath, + RawMesh, + ReliabilityHandlerComponent, + RenderCore, + Renderer, + RHI, + RSA, + SandboxFile, + Serialization, + SessionMessages, + SessionServices, + SignalProcessing, + Slate, + SlateCore, + SlateNullRenderer, + SlateRHIRenderer, + Sockets, + SoundFieldRendering, + SSL, + StaticMeshDescription, + StreamingPauseRendering, + SynthBenchmark, + TimeManagement, + TraceLog, + UELibSampleRate, + UMG, + VectorVM, + Voice, + Voronoi, + VulkanRHI, + WebBrowser, + WindowsPlatformFeatures, + XAudio2, + + Max, + }; + + auto RC_SPSS_API ScanTargetToString(ScanTarget scan_target) -> std::string; + auto RC_SPSS_API ScanTargetToString(size_t scan_target) -> std::string; + + class RC_SPSS_API ScanTargetArray + { + public: + std::array(ScanTarget::Max)> array{}; + + auto operator[](ScanTarget index) -> ModuleOS&; + }; + + // Static storage to be used across all sig scanner types + // At the moment the only scanner type that exists is SinglePassScanner + // In the future there might be a multi-threaded version of SinglePassScanner + class RC_SPSS_API SigScannerStaticData + { + public: + // Store all of the MODULEINFO structs for all of the scan targets + // Can a vector of something non-windows be stored here and then a static MODULEINFO can be created in the cpp file ? + static ScanTargetArray m_modules_info; + static bool m_is_modular; + }; + + struct RC_SPSS_API SignatureContainerLight + { + // The scanner will set this to whichever signature a match was found for + size_t index_into_signatures{}; + + // The scanner will set this to the address of the current match (if a match was found) + // This is guaranteed to be non-null when 'callable' is called + uint8_t* match_address{}; + }; + + struct RC_SPSS_API SignatureData + { + std::string signature{}; + + // TODO: Add 'ScanTarget' in here and remove 'ScanTarget' from the 'start_scan' function + + // The user-code can cast the custom data to their own enum type before using + // It will be zero-defaulted in the event of no custom data being supplied + int32_t custom_data{}; + + // A mask that's used for the StdFind scanning method. + std::string mask{}; + }; + + class SignatureContainer + { + private: + // Member variables in this class shouldn't be mutable outside of the scanner internals + // They cannot simply be private because this class isn't part of the scanner + // They cannot be const because they need to be mutated by the scanner + // The solution is to make everything private and give the scanner access by using the 'friend' keyword + friend class SinglePassScanner; + + private: + std::vector signatures; + const std::function on_match_found; + const std::function on_scan_finished; + + // Whether to store the results and pass them to on_scan_completed + const bool store_results{}; + + // The scanner will store results in here if 'store_results' is true + std::vector result_store{}; + + // True if the scan was successful, otherwise false + bool did_succeed{false}; + + // The scanner will use this to cancel all future calls to 'callable' if the 'callable' signaled + bool ignore{}; + + // The scanner will set this to whichever signature a match was found for + size_t index_into_signatures{}; + + // The scanner will set this to the address of the current match (if a match was found) + // This is guaranteed to be non-null when 'callable' is called + uint8_t* match_address{}; + + // The scanner will set this to the size of the signature that was matched + size_t match_signature_size{}; + + public: + template + SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param) + : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param) + { + } + + template + SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param, bool store_results_param) + : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param), store_results(store_results_param) + { + } + + public: + [[nodiscard]] auto get_match_address() const -> uint8_t* + { + return match_address; + } + [[nodiscard]] auto get_index_into_signatures() const -> size_t + { + return index_into_signatures; + } + [[nodiscard]] auto get_did_succeed() -> bool& + { + return did_succeed; + } + [[nodiscard]] auto get_did_succeed() const -> bool + { + return did_succeed; + } + [[nodiscard]] auto get_signatures() const -> const std::vector& + { + return signatures; + } + [[nodiscard]] auto get_result_store() const -> const std::vector& + { + return result_store; + } + [[nodiscard]] auto get_match_signature_size() const -> size_t + { + return match_signature_size; + } + }; + + class SinglePassScanner + { + private: + static std::mutex m_scanner_mutex; + + public: + enum class ScanMethod + { + Scalar, + StdFind, + }; + + public: + RC_SPSS_API static uint32_t m_num_threads; + RC_SPSS_API static ScanMethod m_scan_method; + + // The minimum size a module has to be for multi-threading to be enabled + // Smaller modules might increase the cost of scanning due to the cost of creating threads + RC_SPSS_API static uint32_t m_multithreading_module_size_threshold; + + private: + RC_SPSS_API auto static string_to_vector(std::string_view signature) -> std::vector; + RC_SPSS_API auto static string_to_vector(const std::vector& signatures) -> std::vector>; + RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; + + RC_SPSS_API auto static get_system_info() -> SystemInfo; + + public: + RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, + uint8_t* end_address, + SystemInfo& info, + std::vector& signature_containers) -> void; + RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, + uint8_t* end_address, + SystemInfo& info, + std::vector& signature_containers) -> void; + RC_SPSS_API auto static scanner_work_thread_stdfind(uint8_t* start_address, + uint8_t* end_address, + SystemInfo& info, + std::vector& signature_containers) -> void; + + using SignatureContainerMap = std::unordered_map>; + RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; + RC_SPSS_API auto static string_scan(std::wstring_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; + }; + + + namespace Platform { + // Get the start address of the system + auto get_start_address(SystemInfo &info) -> uint8_t*; + + // Get the end address of the system + auto get_end_address(SystemInfo &info) -> uint8_t*; + + // Get the size of the module + auto get_module_size(ModuleOS &info) -> uint32_t; + + // Get the base address of the module + auto get_module_base(ModuleOS &info) -> uint8_t*; + }; // namespace Platform + +}; // namespace RC diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp index c50f68f09..2c87ceec9 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp @@ -1,336 +1,32 @@ #pragma once -#include -#include -#include -#include - -#include - -#include - -#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) -#define LO_NIBBLE(b) ((b)&0x0F) +#include +#include +#include +#include namespace RC { - enum class ScanTarget - { - MainExe, - - AIModule, - Analytics, - AnalyticsET, - AnimationCore, - AnimGraphRuntime, - AppFramework, - ApplicationCore, - AssetRegistry, - AudioCaptureCore, - AudioCaptureRtAudio, - AudioExtensions, - AudioMixer, - AudioMixerCore, - AudioMixerXAudio2, - AudioPlatformConfiguration, - AugmentedReality, - AVEncoder, - AVIWriter, - BuildPatchServices, - BuildSettings, - Cbor, - CEF3Utils, - Chaos, - ChaosCore, - ChaosSolverEngine, - ChaosSolvers, - CinematicCamera, - ClothingSystemRuntimeCommon, - ClothingSystemRuntimeInterface, - ClothingSystemRuntimeNv, - Core, - CoreUObject, - CrunchCompression, - D3D11RHI, - D3D12RHI, - Engine, - EngineMessages, - EngineSettings, - EyeTracker, - FieldSystemCore, - FieldSystemEngine, - FieldSystemSimulationCore, - Foliage, - GameplayMediaEncoder, - GameplayTags, - GameplayTasks, - GeometryCollectionCore, - GeometryCollectionEngine, - GeometryCollectionSimulationCore, - HeadMountedDisplay, - HTTP, - HttpNetworkReplayStreaming, - HTTPServer, - Icmp, - ImageCore, - ImageWrapper, - ImageWriteQueue, - InputCore, - InputDevice, - InstallBundleManager, - InstancedSplines, - InteractiveToolsFramework, - Json, - JsonUtilities, - Landscape, - LauncherCheck, - LauncherPlatform, - LevelSequence, - LocalFileNetworkReplayStreaming, - MaterialShaderQualitySettings, - Media, - MediaAssets, - MediaUtils, - MeshDescription, - MeshUtilitiesCommon, - Messaging, - MessagingCommon, - MoviePlayer, - MovieScene, - MovieSceneCapture, - MovieSceneTracks, - MRMesh, - NavigationSystem, - Navmesh, - NetCore, - Networking, - NetworkReplayStreaming, - NonRealtimeAudioRenderer, - NullDrv, - NullNetworkReplayStreaming, - OpenGLDrv, - Overlay, - PacketHandler, - PakFile, - PerfCounters, - PhysicsCore, - PhysicsSQ, - PhysXCooking, - PreLoadScreen, - Projects, - PropertyPath, - RawMesh, - ReliabilityHandlerComponent, - RenderCore, - Renderer, - RHI, - RSA, - SandboxFile, - Serialization, - SessionMessages, - SessionServices, - SignalProcessing, - Slate, - SlateCore, - SlateNullRenderer, - SlateRHIRenderer, - Sockets, - SoundFieldRendering, - SSL, - StaticMeshDescription, - StreamingPauseRendering, - SynthBenchmark, - TimeManagement, - TraceLog, - UELibSampleRate, - UMG, - VectorVM, - Voice, - Voronoi, - VulkanRHI, - WebBrowser, - WindowsPlatformFeatures, - XAudio2, - - Max, - }; - - auto RC_SPSS_API ScanTargetToString(ScanTarget scan_target) -> std::string; - auto RC_SPSS_API ScanTargetToString(size_t scan_target) -> std::string; - -#ifdef WIN32 - class RC_SPSS_API ScanTargetArray - { - public: - std::array(ScanTarget::Max)> array{}; - - auto operator[](ScanTarget index) -> MODULEINFO&; - }; -#else - class RC_SPSS_API ScanTargetArray - { - public: - std::array(ScanTarget::Max)> array{}; - - auto operator[](ScanTarget index) -> DLData&; - }; -#endif - // Static storage to be used across all sig scanner types - // At the moment the only scanner type that exists is SinglePassScanner - // In the future there might be a multi-threaded version of SinglePassScanner - class RC_SPSS_API SigScannerStaticData - { - public: - // Store all of the MODULEINFO structs for all of the scan targets - // Can a vector of something non-windows be stored here and then a static MODULEINFO can be created in the cpp file ? - static ScanTargetArray m_modules_info; - static bool m_is_modular; - }; - - struct RC_SPSS_API SignatureContainerLight - { - // The scanner will set this to whichever signature a match was found for - size_t index_into_signatures{}; - - // The scanner will set this to the address of the current match (if a match was found) - // This is guaranteed to be non-null when 'callable' is called - uint8_t* match_address{}; - }; - - struct RC_SPSS_API SignatureData - { - std::string signature{}; - - // TODO: Add 'ScanTarget' in here and remove 'ScanTarget' from the 'start_scan' function - - // The user-code can cast the custom data to their own enum type before using - // It will be zero-defaulted in the event of no custom data being supplied - int32_t custom_data{}; - - // A mask that's used for the StdFind scanning method. - std::string mask{}; - }; - - class SignatureContainer - { - private: - // Member variables in this class shouldn't be mutable outside of the scanner internals - // They cannot simply be private because this class isn't part of the scanner - // They cannot be const because they need to be mutated by the scanner - // The solution is to make everything private and give the scanner access by using the 'friend' keyword - friend class SinglePassScanner; - - private: - std::vector signatures; - const std::function on_match_found; - const std::function on_scan_finished; - - // Whether to store the results and pass them to on_scan_completed - const bool store_results{}; - - // The scanner will store results in here if 'store_results' is true - std::vector result_store{}; - - // True if the scan was successful, otherwise false - bool did_succeed{false}; - - // The scanner will use this to cancel all future calls to 'callable' if the 'callable' signaled - bool ignore{}; - - // The scanner will set this to whichever signature a match was found for - size_t index_into_signatures{}; - - // The scanner will set this to the address of the current match (if a match was found) - // This is guaranteed to be non-null when 'callable' is called - uint8_t* match_address{}; - - // The scanner will set this to the size of the signature that was matched - size_t match_signature_size{}; - - public: - template - SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param) - : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param) - { - } - - template - SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param, bool store_results_param) - : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param), store_results(store_results_param) - { - } - - public: - [[nodiscard]] auto get_match_address() const -> uint8_t* - { - return match_address; - } - [[nodiscard]] auto get_index_into_signatures() const -> size_t - { - return index_into_signatures; - } - [[nodiscard]] auto get_did_succeed() -> bool& - { - return did_succeed; - } - [[nodiscard]] auto get_did_succeed() const -> bool - { - return did_succeed; - } - [[nodiscard]] auto get_signatures() const -> const std::vector& - { - return signatures; - } - [[nodiscard]] auto get_result_store() const -> const std::vector& - { - return result_store; - } - [[nodiscard]] auto get_match_signature_size() const -> size_t - { - return match_signature_size; - } - }; - - class SinglePassScanner - { - private: - static std::mutex m_scanner_mutex; - - public: - enum class ScanMethod - { - Scalar, - StdFind, - }; - - public: - RC_SPSS_API static uint32_t m_num_threads; - RC_SPSS_API static ScanMethod m_scan_method; - - // The minimum size a module has to be for multi-threading to be enabled - // Smaller modules might increase the cost of scanning due to the cost of creating threads - RC_SPSS_API static uint32_t m_multithreading_module_size_threshold; - - private: - RC_SPSS_API auto static string_to_vector(std::string_view signature) -> std::vector; - RC_SPSS_API auto static string_to_vector(const std::vector& signatures) -> std::vector>; - RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; - - public: - RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, - uint8_t* end_address, - DLData& info, - std::vector& signature_containers) -> void; - RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, - uint8_t* end_address, - DLData& info, - std::vector& signature_containers) -> void; - RC_SPSS_API auto static scanner_work_thread_stdfind(uint8_t* start_address, - uint8_t* end_address, - DLData& info, - std::vector& signature_containers) -> void; - - using SignatureContainerMap = std::unordered_map>; - RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; - }; + struct DLData + { + std::string libname; + uint8_t* base_address; + uint64_t map_start, map_end; + size_t size; + // sorted by start address + std::set> phdrs; + std::tuple find_phdr(uint8_t* addr) { + for (auto& phdr : phdrs) { + // use end address to find the phdr + if (std::get<0>(phdr) + std::get<1>(phdr) > addr) { + return phdr; + } + } + return std::make_tuple(nullptr, 0, 0); + } + }; + + using ModuleInfo = DLData; + using ModuleOS = DLData; + using SystemInfo = DLData; } // namespace RC diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp index b82b3e5bb..ed27eeedf 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerWin32.hpp @@ -1,15 +1,7 @@ #pragma once -#include -#include -#include -#include - #include -#define HI_NIBBLE(b) (((b) >> 4) & 0x0F) -#define LO_NIBBLE(b) ((b)&0x0F) - // Windows.h forward declarations struct _SYSTEM_INFO; typedef _SYSTEM_INFO SYSTEM_INFO; @@ -26,325 +18,7 @@ namespace RC void* EntryPoint; RC_SPSS_API auto operator=(MODULEINFO) -> WIN_MODULEINFO&; }; - - enum class ScanTarget - { - MainExe, - - AIModule, - Analytics, - AnalyticsET, - AnimationCore, - AnimGraphRuntime, - AppFramework, - ApplicationCore, - AssetRegistry, - AudioCaptureCore, - AudioCaptureRtAudio, - AudioExtensions, - AudioMixer, - AudioMixerCore, - AudioMixerXAudio2, - AudioPlatformConfiguration, - AugmentedReality, - AVEncoder, - AVIWriter, - BuildPatchServices, - BuildSettings, - Cbor, - CEF3Utils, - Chaos, - ChaosCore, - ChaosSolverEngine, - ChaosSolvers, - CinematicCamera, - ClothingSystemRuntimeCommon, - ClothingSystemRuntimeInterface, - ClothingSystemRuntimeNv, - Core, - CoreUObject, - CrunchCompression, - D3D11RHI, - D3D12RHI, - Engine, - EngineMessages, - EngineSettings, - EyeTracker, - FieldSystemCore, - FieldSystemEngine, - FieldSystemSimulationCore, - Foliage, - GameplayMediaEncoder, - GameplayTags, - GameplayTasks, - GeometryCollectionCore, - GeometryCollectionEngine, - GeometryCollectionSimulationCore, - HeadMountedDisplay, - HTTP, - HttpNetworkReplayStreaming, - HTTPServer, - Icmp, - ImageCore, - ImageWrapper, - ImageWriteQueue, - InputCore, - InputDevice, - InstallBundleManager, - InstancedSplines, - InteractiveToolsFramework, - Json, - JsonUtilities, - Landscape, - LauncherCheck, - LauncherPlatform, - LevelSequence, - LocalFileNetworkReplayStreaming, - MaterialShaderQualitySettings, - Media, - MediaAssets, - MediaUtils, - MeshDescription, - MeshUtilitiesCommon, - Messaging, - MessagingCommon, - MoviePlayer, - MovieScene, - MovieSceneCapture, - MovieSceneTracks, - MRMesh, - NavigationSystem, - Navmesh, - NetCore, - Networking, - NetworkReplayStreaming, - NonRealtimeAudioRenderer, - NullDrv, - NullNetworkReplayStreaming, - OpenGLDrv, - Overlay, - PacketHandler, - PakFile, - PerfCounters, - PhysicsCore, - PhysicsSQ, - PhysXCooking, - PreLoadScreen, - Projects, - PropertyPath, - RawMesh, - ReliabilityHandlerComponent, - RenderCore, - Renderer, - RHI, - RSA, - SandboxFile, - Serialization, - SessionMessages, - SessionServices, - SignalProcessing, - Slate, - SlateCore, - SlateNullRenderer, - SlateRHIRenderer, - Sockets, - SoundFieldRendering, - SSL, - StaticMeshDescription, - StreamingPauseRendering, - SynthBenchmark, - TimeManagement, - TraceLog, - UELibSampleRate, - UMG, - VectorVM, - Voice, - Voronoi, - VulkanRHI, - WebBrowser, - WindowsPlatformFeatures, - XAudio2, - - Max, - }; - - auto RC_SPSS_API ScanTargetToString(ScanTarget scan_target) -> std::string; - auto RC_SPSS_API ScanTargetToString(size_t scan_target) -> std::string; - -#ifdef WIN32 - class RC_SPSS_API ScanTargetArray - { - public: - std::array(ScanTarget::Max)> array{}; - - auto operator[](ScanTarget index) -> MODULEINFO&; - }; -#else - class RC_SPSS_API ScanTargetArray - { - public: - std::array(ScanTarget::Max)> array{}; - - auto operator[](ScanTarget index) -> DLData&; - }; -#endif - // Static storage to be used across all sig scanner types - // At the moment the only scanner type that exists is SinglePassScanner - // In the future there might be a multi-threaded version of SinglePassScanner - class RC_SPSS_API SigScannerStaticData - { - public: - // Store all of the MODULEINFO structs for all of the scan targets - // Can a vector of something non-windows be stored here and then a static MODULEINFO can be created in the cpp file ? - static ScanTargetArray m_modules_info; - static bool m_is_modular; - }; - - struct RC_SPSS_API SignatureContainerLight - { - // The scanner will set this to whichever signature a match was found for - size_t index_into_signatures{}; - - // The scanner will set this to the address of the current match (if a match was found) - // This is guaranteed to be non-null when 'callable' is called - uint8_t* match_address{}; - }; - - struct RC_SPSS_API SignatureData - { - std::string signature{}; - - // TODO: Add 'ScanTarget' in here and remove 'ScanTarget' from the 'start_scan' function - - // The user-code can cast the custom data to their own enum type before using - // It will be zero-defaulted in the event of no custom data being supplied - int32_t custom_data{}; - - // A mask that's used for the StdFind scanning method. - std::string mask{}; - }; - - class SignatureContainer - { - private: - // Member variables in this class shouldn't be mutable outside of the scanner internals - // They cannot simply be private because this class isn't part of the scanner - // They cannot be const because they need to be mutated by the scanner - // The solution is to make everything private and give the scanner access by using the 'friend' keyword - friend class SinglePassScanner; - - private: - std::vector signatures; - const std::function on_match_found; - const std::function on_scan_finished; - - // Whether to store the results and pass them to on_scan_completed - const bool store_results{}; - - // The scanner will store results in here if 'store_results' is true - std::vector result_store{}; - - // True if the scan was successful, otherwise false - bool did_succeed{false}; - - // The scanner will use this to cancel all future calls to 'callable' if the 'callable' signaled - bool ignore{}; - - // The scanner will set this to whichever signature a match was found for - size_t index_into_signatures{}; - - // The scanner will set this to the address of the current match (if a match was found) - // This is guaranteed to be non-null when 'callable' is called - uint8_t* match_address{}; - - // The scanner will set this to the size of the signature that was matched - size_t match_signature_size{}; - - public: - template - SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param) - : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param) - { - } - - template - SignatureContainer(std::vector sig_param, OnMatchFound on_match_found_param, OnScanFinished on_scan_finished_param, bool store_results_param) - : signatures(std::move(sig_param)), on_match_found(on_match_found_param), on_scan_finished(on_scan_finished_param), store_results(store_results_param) - { - } - - public: - [[nodiscard]] auto get_match_address() const -> uint8_t* - { - return match_address; - } - [[nodiscard]] auto get_index_into_signatures() const -> size_t - { - return index_into_signatures; - } - [[nodiscard]] auto get_did_succeed() -> bool& - { - return did_succeed; - } - [[nodiscard]] auto get_did_succeed() const -> bool - { - return did_succeed; - } - [[nodiscard]] auto get_signatures() const -> const std::vector& - { - return signatures; - } - [[nodiscard]] auto get_result_store() const -> const std::vector& - { - return result_store; - } - [[nodiscard]] auto get_match_signature_size() const -> size_t - { - return match_signature_size; - } - }; - - class SinglePassScanner - { - private: - static std::mutex m_scanner_mutex; - - public: - enum class ScanMethod - { - Scalar, - StdFind, - }; - - public: - RC_SPSS_API static uint32_t m_num_threads; - RC_SPSS_API static ScanMethod m_scan_method; - - // The minimum size a module has to be for multi-threading to be enabled - // Smaller modules might increase the cost of scanning due to the cost of creating threads - RC_SPSS_API static uint32_t m_multithreading_module_size_threshold; - - private: - RC_SPSS_API auto static string_to_vector(std::string_view signature) -> std::vector; - RC_SPSS_API auto static string_to_vector(const std::vector& signatures) -> std::vector>; - RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; - - public: - RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, - uint8_t* end_address, - SYSTEM_INFO& info, - std::vector& signature_containers) -> void; - RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, - uint8_t* end_address, - SYSTEM_INFO& info, - std::vector& signature_containers) -> void; - RC_SPSS_API auto static scanner_work_thread_stdfind(uint8_t* start_address, - uint8_t* end_address, - SYSTEM_INFO& info, - std::vector& signature_containers) -> void; - - using SignatureContainerMap = std::unordered_map>; - RC_SPSS_API auto static start_scan(SignatureContainerMap& signature_containers) -> void; - RC_SPSS_API auto static string_scan(std::wstring_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; - }; + using ModuleInfo = WIN_MODULEINFO; + using ModuleOS = MODULEINFO; + using SystemInfo = SYSTEM_INFO; } // namespace RC diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp new file mode 100644 index 000000000..9f40e296e --- /dev/null +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp @@ -0,0 +1,676 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace RC +{ + ScanTargetArray SigScannerStaticData::m_modules_info; + bool SigScannerStaticData::m_is_modular; + + uint32_t SinglePassScanner::m_num_threads = 8; + SinglePassScanner::ScanMethod SinglePassScanner::m_scan_method = ScanMethod::Scalar; + uint32_t SinglePassScanner::m_multithreading_module_size_threshold = 0x1000000; + std::mutex SinglePassScanner::m_scanner_mutex{}; + + auto ScanTargetArray::operator[](ScanTarget index) -> ModuleOS& + { + return array[static_cast(index)]; + } + + auto ScanTargetToString(ScanTarget scan_target) -> std::string + { + switch (scan_target) + { + case ScanTarget::MainExe: + return {"MainExe"}; + case ScanTarget::AIModule: + return {"AIModule"}; + case ScanTarget::Analytics: + return {"Analytics"}; + case ScanTarget::AnalyticsET: + return {"AnalyticsET"}; + case ScanTarget::AnimationCore: + return {"AnimationCore"}; + case ScanTarget::AnimGraphRuntime: + return {"AnimGraphRuntime"}; + case ScanTarget::AppFramework: + return {"AppFramework"}; + case ScanTarget::ApplicationCore: + return {"ApplicationCore"}; + case ScanTarget::AssetRegistry: + return {"AssetRegistry"}; + case ScanTarget::AudioCaptureCore: + return {"AudioCaptureCore"}; + case ScanTarget::AudioCaptureRtAudio: + return {"AudioCaptureRtAudio"}; + case ScanTarget::AudioExtensions: + return {"AudioExtensions"}; + case ScanTarget::AudioMixer: + return {"AudioMixer"}; + case ScanTarget::AudioMixerCore: + return {"AudioMixerCore"}; + case ScanTarget::AudioMixerXAudio2: + return {"AudioMixerXAudio2"}; + case ScanTarget::AudioPlatformConfiguration: + return {"AudioPlatformConfiguration"}; + case ScanTarget::AugmentedReality: + return {"AugmentedReality"}; + case ScanTarget::AVEncoder: + return {"AVEncoder"}; + case ScanTarget::AVIWriter: + return {"AVIWriter"}; + case ScanTarget::BuildPatchServices: + return {"BuildPatchServices"}; + case ScanTarget::BuildSettings: + return {"BuildSettings"}; + case ScanTarget::Cbor: + return {"Cbor"}; + case ScanTarget::CEF3Utils: + return {"CEF3Utils"}; + case ScanTarget::Chaos: + return {"Chaos"}; + case ScanTarget::ChaosCore: + return {"ChaosCore"}; + case ScanTarget::ChaosSolverEngine: + return {"ChaosSolverEngine"}; + case ScanTarget::ChaosSolvers: + return {"ChaosSolvers"}; + case ScanTarget::CinematicCamera: + return {"CinematicCamera"}; + case ScanTarget::ClothingSystemRuntimeCommon: + return {"ClothingSystemRuntimeCommon"}; + case ScanTarget::ClothingSystemRuntimeInterface: + return {"ClothingSystemRuntimeInterface"}; + case ScanTarget::ClothingSystemRuntimeNv: + return {"ClothingSystemRuntimeNv"}; + case ScanTarget::Core: + return {"Core"}; + case ScanTarget::CoreUObject: + return {"CoreUObject"}; + case ScanTarget::CrunchCompression: + return {"CrunchCompression"}; + case ScanTarget::D3D11RHI: + return {"D3D11RHI"}; + case ScanTarget::D3D12RHI: + return {"D3D12RHI"}; + case ScanTarget::Engine: + return {"Engine"}; + case ScanTarget::EngineMessages: + return {"EngineMessages"}; + case ScanTarget::EngineSettings: + return {"EngineSettings"}; + case ScanTarget::EyeTracker: + return {"EyeTracker"}; + case ScanTarget::FieldSystemCore: + return {"FieldSystemCore"}; + case ScanTarget::FieldSystemEngine: + return {"FieldSystemEngine"}; + case ScanTarget::FieldSystemSimulationCore: + return {"FieldSystemSimulationCore"}; + case ScanTarget::Foliage: + return {"Foliage"}; + case ScanTarget::GameplayMediaEncoder: + return {"GameplayMediaEncoder"}; + case ScanTarget::GameplayTags: + return {"GameplayTags"}; + case ScanTarget::GameplayTasks: + return {"GameplayTasks"}; + case ScanTarget::GeometryCollectionCore: + return {"GeometryCollectionCore"}; + case ScanTarget::GeometryCollectionEngine: + return {"GeometryCollectionEngine"}; + case ScanTarget::GeometryCollectionSimulationCore: + return {"GeometryCollectionSimulationCore"}; + case ScanTarget::HeadMountedDisplay: + return {"HeadMountedDisplay"}; + case ScanTarget::HTTP: + return {"HTTP"}; + case ScanTarget::HttpNetworkReplayStreaming: + return {"HttpNetworkReplayStreaming"}; + case ScanTarget::HTTPServer: + return {"HTTPServer"}; + case ScanTarget::Icmp: + return {"Icmp"}; + case ScanTarget::ImageCore: + return {"ImageCore"}; + case ScanTarget::ImageWrapper: + return {"ImageWrapper"}; + case ScanTarget::ImageWriteQueue: + return {"ImageWriteQueue"}; + case ScanTarget::InputCore: + return {"InputCore"}; + case ScanTarget::InputDevice: + return {"InputDevice"}; + case ScanTarget::InstallBundleManager: + return {"InstallBundleManager"}; + case ScanTarget::InstancedSplines: + return {"InstancedSplines"}; + case ScanTarget::InteractiveToolsFramework: + return {"InteractiveToolsFramework"}; + case ScanTarget::Json: + return {"Json"}; + case ScanTarget::JsonUtilities: + return {"JsonUtilities"}; + case ScanTarget::Landscape: + return {"Landscape"}; + case ScanTarget::LauncherCheck: + return {"LauncherCheck"}; + case ScanTarget::LauncherPlatform: + return {"LauncherPlatform"}; + case ScanTarget::LevelSequence: + return {"LevelSequence"}; + case ScanTarget::LocalFileNetworkReplayStreaming: + return {"LocalFileNetworkReplayStreaming"}; + case ScanTarget::MaterialShaderQualitySettings: + return {"MaterialShaderQualitySettings"}; + case ScanTarget::Media: + return {"Media"}; + case ScanTarget::MediaAssets: + return {"MediaAssets"}; + case ScanTarget::MediaUtils: + return {"MediaUtils"}; + case ScanTarget::MeshDescription: + return {"MeshDescription"}; + case ScanTarget::MeshUtilitiesCommon: + return {"MeshUtilitiesCommon"}; + case ScanTarget::Messaging: + return {"Messaging"}; + case ScanTarget::MessagingCommon: + return {"MessagingCommon"}; + case ScanTarget::MoviePlayer: + return {"MoviePlayer"}; + case ScanTarget::MovieScene: + return {"MovieScene"}; + case ScanTarget::MovieSceneCapture: + return {"MovieSceneCapture"}; + case ScanTarget::MovieSceneTracks: + return {"MovieSceneTracks"}; + case ScanTarget::MRMesh: + return {"MRMesh"}; + case ScanTarget::NavigationSystem: + return {"NavigationSystem"}; + case ScanTarget::Navmesh: + return {"Navmesh"}; + case ScanTarget::NetCore: + return {"NetCore"}; + case ScanTarget::Networking: + return {"Networking"}; + case ScanTarget::NetworkReplayStreaming: + return {"NetworkReplayStreaming"}; + case ScanTarget::NonRealtimeAudioRenderer: + return {"NonRealtimeAudioRenderer"}; + case ScanTarget::NullDrv: + return {"NullDrv"}; + case ScanTarget::NullNetworkReplayStreaming: + return {"NullNetworkReplayStreaming"}; + case ScanTarget::OpenGLDrv: + return {"OpenGLDrv"}; + case ScanTarget::Overlay: + return {"Overlay"}; + case ScanTarget::PacketHandler: + return {"PacketHandler"}; + case ScanTarget::PakFile: + return {"PakFile"}; + case ScanTarget::PerfCounters: + return {"PerfCounters"}; + case ScanTarget::PhysicsCore: + return {"PhysicsCore"}; + case ScanTarget::PhysicsSQ: + return {"PhysicsSQ"}; + case ScanTarget::PhysXCooking: + return {"PhysXCooking"}; + case ScanTarget::PreLoadScreen: + return {"PreLoadScreen"}; + case ScanTarget::Projects: + return {"Projects"}; + case ScanTarget::PropertyPath: + return {"PropertyPath"}; + case ScanTarget::RawMesh: + return {"RawMesh"}; + case ScanTarget::ReliabilityHandlerComponent: + return {"ReliabilityHandlerComponent"}; + case ScanTarget::RenderCore: + return {"RenderCore"}; + case ScanTarget::Renderer: + return {"Renderer"}; + case ScanTarget::RHI: + return {"RHI"}; + case ScanTarget::RSA: + return {"RSA"}; + case ScanTarget::SandboxFile: + return {"SandboxFile"}; + case ScanTarget::Serialization: + return {"Serialization"}; + case ScanTarget::SessionMessages: + return {"SessionMessages"}; + case ScanTarget::SessionServices: + return {"SessionServices"}; + case ScanTarget::SignalProcessing: + return {"SignalProcessing"}; + case ScanTarget::Slate: + return {"Slate"}; + case ScanTarget::SlateCore: + return {"SlateCore"}; + case ScanTarget::SlateNullRenderer: + return {"SlateNullRenderer"}; + case ScanTarget::SlateRHIRenderer: + return {"SlateRHIRenderer"}; + case ScanTarget::Sockets: + return {"Sockets"}; + case ScanTarget::SoundFieldRendering: + return {"SoundFieldRendering"}; + case ScanTarget::SSL: + return {"SSL"}; + case ScanTarget::StaticMeshDescription: + return {"StaticMeshDescription"}; + case ScanTarget::StreamingPauseRendering: + return {"StreamingPauseRendering"}; + case ScanTarget::SynthBenchmark: + return {"SynthBenchmark"}; + case ScanTarget::TimeManagement: + return {"TimeManagement"}; + case ScanTarget::TraceLog: + return {"TraceLog"}; + case ScanTarget::UELibSampleRate: + return {"UELibSampleRate"}; + case ScanTarget::UMG: + return {"UMG"}; + case ScanTarget::VectorVM: + return {"VectorVM"}; + case ScanTarget::Voice: + return {"Voice"}; + case ScanTarget::Voronoi: + return {"Voronoi"}; + case ScanTarget::VulkanRHI: + return {"VulkanRHI"}; + case ScanTarget::WebBrowser: + return {"WebBrowser"}; + case ScanTarget::WindowsPlatformFeatures: + return {"WindowsPlatformFeatures"}; + case ScanTarget::XAudio2: + return {"XAudio2"}; + case ScanTarget::Max: + return {"Max"}; + } + + throw std::runtime_error{std::format("Invalid param for ScanTargetToString, param: {}", static_cast(scan_target))}; + } + + auto ScanTargetToString(size_t scan_target) -> std::string + { + return ScanTargetToString(static_cast(scan_target)); + } + + static auto ConvertHexCharToInt(char ch) -> int + { + if (ch >= '0' && ch <= '9') return ch - '0'; + if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; + if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; + return -1; + } + + auto SinglePassScanner::string_to_vector(std::string_view signature) -> std::vector + { + std::vector bytes; + char* const start = const_cast(signature.data()); + char* const end = const_cast(signature.data()) + strlen(signature.data()); + + for (char* current = start; current < end; current++) + { + if (*current == '?') + { + bytes.push_back(-1); + } + else if (std::isxdigit(*current)) + { + bytes.push_back(ConvertHexCharToInt(*current)); + } + } + + return bytes; + } + + auto SinglePassScanner::string_to_vector(const std::vector& signatures) -> std::vector> + { + std::vector> vector_of_signatures; + vector_of_signatures.reserve(signatures.size()); + + for (const auto& signature_data : signatures) + { + vector_of_signatures.emplace_back(string_to_vector(signature_data.signature)); + } + + return vector_of_signatures; + } + + struct PatternData + { + std::vector pattern{}; + std::vector mask{}; + SignatureContainer* signature_container{}; + }; + + static auto CharToByte(char symbol) -> uint8_t + { + if (symbol >= 'a' && symbol <= 'z') + { + return symbol - 'a' + 0xA; + } + else if (symbol >= 'A' && symbol <= 'Z') + { + return symbol - 'A' + 0xA; + } + else if (symbol >= '0' && symbol <= '9') + { + return symbol - '0'; + } + else + { + return 0; + } + } + + static auto make_mask(std::string_view pattern, SignatureContainer& signature_container, const size_t data_size) -> PatternData + { + PatternData pattern_data{}; + + if (pattern.length() < 1 || pattern[0] == '?') + { + throw std::runtime_error{std::format("[make_mask] A pattern cannot start with a wildcard.\nPattern: {}", pattern)}; + } + + for (size_t i = 0; i < pattern.length(); i++) + { + char symbol = pattern[i]; + char next_symbol = ((i + 1) < pattern.length()) ? pattern[i + 1] : 0; + if (symbol == ' ') + { + continue; + } + + if (symbol == '?') + { + pattern_data.pattern.push_back(0x00); + pattern_data.mask.push_back(0x00); + + if (next_symbol == '?') + { + ++i; + } + continue; + } + + uint8_t byte = CharToByte(symbol) << 4 | CharToByte(next_symbol); + + pattern_data.pattern.push_back(byte); + pattern_data.mask.push_back(0xff); + + ++i; + } + + static constexpr size_t Alignment = 32; + size_t count = (size_t)std::ceil((float)data_size / Alignment); + size_t padding_size = count * Alignment - data_size; + + for (size_t i = 0; i < padding_size; i++) + { + pattern_data.pattern.push_back(0x00); + pattern_data.mask.push_back(0x00); + } + + pattern_data.signature_container = &signature_container; + return pattern_data; + } + + auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, SystemInfo& info, std::vector& signature_containers) + -> void + { + ProfilerSetThreadName("UE4SS-ScannerWorkThread"); + ProfilerScope(); + + switch (m_scan_method) + { + case ScanMethod::Scalar: + scanner_work_thread_scalar(start_address, end_address, info, signature_containers); + break; + case ScanMethod::StdFind: + scanner_work_thread_stdfind(start_address, end_address, info, signature_containers); + break; + } + } + + static auto format_aob_string(std::string& str) -> void + { + if (str.size() < 4) + { + return; + } + if (str[3] != '/') + { + return; + } + + std::erase_if(str, [&](const char c) { + return c == ' '; + }); + + std::ranges::transform(str, str.begin(), [&str](const char c) { + return c == '/' ? ' ' : c; + }); + } + + auto SinglePassScanner::format_aob_strings(std::vector& signature_containers) -> void + { + std::lock_guard safe_scope(m_scanner_mutex); + for (auto& signature_container : signature_containers) + { + for (auto& signature : signature_container.signatures) + { + format_aob_string(signature.signature); + } + } + } + + auto SinglePassScanner::scanner_work_thread_stdfind(uint8_t* start_address, + uint8_t* end_address, + SystemInfo& info, + std::vector& signature_containers) -> void + { + ProfilerScope(); + + if (!start_address) + { + start_address = Platform::get_start_address(info); + } + if (!end_address) + { + end_address = Platform::get_end_address(info); + } + + format_aob_strings(signature_containers); + + std::vector> pattern_datas{}; + for (auto& signature_container : signature_containers) + { + auto& pattern_data = pattern_datas.emplace_back(); + for (auto& signature : signature_container.signatures) + { + pattern_data.emplace_back(make_mask(signature.signature, signature_container, end_address - start_address)); + } + } + + // Loop everything + for (size_t container_index = 0; const auto& patterns : pattern_datas) + { + for (size_t signature_index = 0; const auto& pattern_data : patterns) + { + // If the container is refusing more calls then skip to the next container + if (pattern_data.signature_container->ignore) + { + break; + } + + auto it = start_address; + auto end = it + (end_address - start_address) - (pattern_data.pattern.size()) + 1; + uint8_t needle = pattern_data.pattern[0]; + + bool skip_to_next_container{}; + while (end != (it = std::find(it, end, needle))) + { + bool found = true; + for (size_t pattern_offset = 0; pattern_offset < pattern_data.pattern.size(); ++pattern_offset) + { + if ((it[pattern_offset] & pattern_data.mask[pattern_offset]) != pattern_data.pattern[pattern_offset]) + { + found = false; + break; + } + } + + if (found) + { + { + std::lock_guard safe_scope(m_scanner_mutex); + + // Checking for the second time if the container is refusing more calls + // This is required when multi-threading is enabled + if (pattern_data.signature_container->ignore) + { + skip_to_next_container = true; + break; + } + + // One of the signatures have found a full match so lets forward the details to the callable + pattern_data.signature_container->index_into_signatures = signature_index; + pattern_data.signature_container->match_address = it; + pattern_data.signature_container->match_signature_size = pattern_data.pattern.size(); + + skip_to_next_container = pattern_data.signature_container->on_match_found(*pattern_data.signature_container); + pattern_data.signature_container->ignore = skip_to_next_container; + + // Store results if the container at the containers request + if (pattern_data.signature_container->store_results) + { + pattern_data.signature_container->result_store.emplace_back( + SignatureContainerLight{.index_into_signatures = signature_index, .match_address = it}); + } + } + } + + it++; + } + + if (skip_to_next_container) + { + // A match was found and signaled to skip to the next container + break; + } + + ++signature_index; + } + ++container_index; + } + } + + auto SinglePassScanner::start_scan(SignatureContainerMap& signature_containers) -> void + { + SystemInfo info = get_system_info(); + + // If not modular then the containers get merged into one scan target + // That way there are no extra scans + // If modular then loop the containers and retrieve the scan target for each and pass everything to the do_scan() lambda + fprintf(stderr, "signature_containers.size() = %d\n", signature_containers.size()); + if (!SigScannerStaticData::m_is_modular) + { + ModuleOS merged_module_info{}; + std::vector merged_containers; + + for (const auto& [scan_target, outer_container] : signature_containers) + { + merged_module_info = *std::bit_cast(&SigScannerStaticData::m_modules_info[scan_target]); + fprintf(stderr, "outer_container len = %d\n", outer_container.size()); + for (const auto& signature_container : outer_container) + { + merged_containers.emplace_back(signature_container); + } + } + + if (merged_containers.empty()) + { + fprintf(stderr, "No containers to merge\n"); + return ; + //throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " + // "an internal error."}; + } + + uint8_t* module_start_address = Platform::get_module_base(merged_module_info); + + if (Platform::get_module_size(merged_module_info) >= m_multithreading_module_size_threshold) + { + // Module is large enough to make it overall faster to scan with multiple threads + std::vector> scan_threads; + + // Higher values are better for debugging + // You will get a bigger diminishing returns the faster your computer is (especially in release mode) + uint32_t range = Platform::get_module_size(merged_module_info) / m_num_threads; + + // Calculating the ranges for each thread to scan and starting the scan + uint32_t last_range{}; + for (uint32_t thread_id = 0; thread_id < m_num_threads; ++thread_id) + { + scan_threads.emplace_back(std::async(std::launch::async, + &scanner_work_thread, + module_start_address + last_range, + module_start_address + last_range + range, + std::ref(info), + std::ref(merged_containers))); + + last_range += range; + } + + for (const auto& scan_thread : scan_threads) + { + scan_thread.wait(); + } + } + else + { + // Module is too small to make it overall faster to scan with multiple threads + uint8_t* module_end_address = static_cast(module_start_address + Platform::get_module_size(merged_module_info)); + scanner_work_thread(module_start_address, module_end_address, merged_module_info, merged_containers); + } + + for (auto& container : merged_containers) + { + container.on_scan_finished(container); + } + } + else + { + // This ranged for loop is performing a copy of unordered_map> + // Is this required ? Would it be worth trying to avoid copying here ? + // Right now it can't be auto& or const auto& because the do_scan function takes a non-const since it needs to mutate the values inside the vector + auto info = SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; + for (auto& [scan_target, signature_container] : signature_containers) + { + uint8_t* module_start_address = static_cast(Platform::get_module_base(SigScannerStaticData::m_modules_info[scan_target])); + uint8_t* module_end_address = static_cast(module_start_address + Platform::get_module_size(SigScannerStaticData::m_modules_info[scan_target])); + + scanner_work_thread(module_start_address, module_end_address, info, signature_container); + + for (auto& container : signature_container) + { + container.on_scan_finished(container); + } + } + } + } +}; // namespace RC + diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp index b29b3aa9b..6fea0c84f 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp @@ -11,446 +11,39 @@ #include -#define byte uint8_t - namespace RC { - ScanTargetArray SigScannerStaticData::m_modules_info; - bool SigScannerStaticData::m_is_modular; - - uint32_t SinglePassScanner::m_num_threads = 8; - SinglePassScanner::ScanMethod SinglePassScanner::m_scan_method = ScanMethod::Scalar; - uint32_t SinglePassScanner::m_multithreading_module_size_threshold = 0x1000000; - std::mutex SinglePassScanner::m_scanner_mutex{}; - - auto ScanTargetArray::operator[](ScanTarget index) -> DLData& - { - return array[static_cast(index)]; - } - - - auto ScanTargetToString(ScanTarget scan_target) -> std::string - { - switch (scan_target) - { - case ScanTarget::MainExe: - return {"MainExe"}; - case ScanTarget::AIModule: - return {"AIModule"}; - case ScanTarget::Analytics: - return {"Analytics"}; - case ScanTarget::AnalyticsET: - return {"AnalyticsET"}; - case ScanTarget::AnimationCore: - return {"AnimationCore"}; - case ScanTarget::AnimGraphRuntime: - return {"AnimGraphRuntime"}; - case ScanTarget::AppFramework: - return {"AppFramework"}; - case ScanTarget::ApplicationCore: - return {"ApplicationCore"}; - case ScanTarget::AssetRegistry: - return {"AssetRegistry"}; - case ScanTarget::AudioCaptureCore: - return {"AudioCaptureCore"}; - case ScanTarget::AudioCaptureRtAudio: - return {"AudioCaptureRtAudio"}; - case ScanTarget::AudioExtensions: - return {"AudioExtensions"}; - case ScanTarget::AudioMixer: - return {"AudioMixer"}; - case ScanTarget::AudioMixerCore: - return {"AudioMixerCore"}; - case ScanTarget::AudioMixerXAudio2: - return {"AudioMixerXAudio2"}; - case ScanTarget::AudioPlatformConfiguration: - return {"AudioPlatformConfiguration"}; - case ScanTarget::AugmentedReality: - return {"AugmentedReality"}; - case ScanTarget::AVEncoder: - return {"AVEncoder"}; - case ScanTarget::AVIWriter: - return {"AVIWriter"}; - case ScanTarget::BuildPatchServices: - return {"BuildPatchServices"}; - case ScanTarget::BuildSettings: - return {"BuildSettings"}; - case ScanTarget::Cbor: - return {"Cbor"}; - case ScanTarget::CEF3Utils: - return {"CEF3Utils"}; - case ScanTarget::Chaos: - return {"Chaos"}; - case ScanTarget::ChaosCore: - return {"ChaosCore"}; - case ScanTarget::ChaosSolverEngine: - return {"ChaosSolverEngine"}; - case ScanTarget::ChaosSolvers: - return {"ChaosSolvers"}; - case ScanTarget::CinematicCamera: - return {"CinematicCamera"}; - case ScanTarget::ClothingSystemRuntimeCommon: - return {"ClothingSystemRuntimeCommon"}; - case ScanTarget::ClothingSystemRuntimeInterface: - return {"ClothingSystemRuntimeInterface"}; - case ScanTarget::ClothingSystemRuntimeNv: - return {"ClothingSystemRuntimeNv"}; - case ScanTarget::Core: - return {"Core"}; - case ScanTarget::CoreUObject: - return {"CoreUObject"}; - case ScanTarget::CrunchCompression: - return {"CrunchCompression"}; - case ScanTarget::D3D11RHI: - return {"D3D11RHI"}; - case ScanTarget::D3D12RHI: - return {"D3D12RHI"}; - case ScanTarget::Engine: - return {"Engine"}; - case ScanTarget::EngineMessages: - return {"EngineMessages"}; - case ScanTarget::EngineSettings: - return {"EngineSettings"}; - case ScanTarget::EyeTracker: - return {"EyeTracker"}; - case ScanTarget::FieldSystemCore: - return {"FieldSystemCore"}; - case ScanTarget::FieldSystemEngine: - return {"FieldSystemEngine"}; - case ScanTarget::FieldSystemSimulationCore: - return {"FieldSystemSimulationCore"}; - case ScanTarget::Foliage: - return {"Foliage"}; - case ScanTarget::GameplayMediaEncoder: - return {"GameplayMediaEncoder"}; - case ScanTarget::GameplayTags: - return {"GameplayTags"}; - case ScanTarget::GameplayTasks: - return {"GameplayTasks"}; - case ScanTarget::GeometryCollectionCore: - return {"GeometryCollectionCore"}; - case ScanTarget::GeometryCollectionEngine: - return {"GeometryCollectionEngine"}; - case ScanTarget::GeometryCollectionSimulationCore: - return {"GeometryCollectionSimulationCore"}; - case ScanTarget::HeadMountedDisplay: - return {"HeadMountedDisplay"}; - case ScanTarget::HTTP: - return {"HTTP"}; - case ScanTarget::HttpNetworkReplayStreaming: - return {"HttpNetworkReplayStreaming"}; - case ScanTarget::HTTPServer: - return {"HTTPServer"}; - case ScanTarget::Icmp: - return {"Icmp"}; - case ScanTarget::ImageCore: - return {"ImageCore"}; - case ScanTarget::ImageWrapper: - return {"ImageWrapper"}; - case ScanTarget::ImageWriteQueue: - return {"ImageWriteQueue"}; - case ScanTarget::InputCore: - return {"InputCore"}; - case ScanTarget::InputDevice: - return {"InputDevice"}; - case ScanTarget::InstallBundleManager: - return {"InstallBundleManager"}; - case ScanTarget::InstancedSplines: - return {"InstancedSplines"}; - case ScanTarget::InteractiveToolsFramework: - return {"InteractiveToolsFramework"}; - case ScanTarget::Json: - return {"Json"}; - case ScanTarget::JsonUtilities: - return {"JsonUtilities"}; - case ScanTarget::Landscape: - return {"Landscape"}; - case ScanTarget::LauncherCheck: - return {"LauncherCheck"}; - case ScanTarget::LauncherPlatform: - return {"LauncherPlatform"}; - case ScanTarget::LevelSequence: - return {"LevelSequence"}; - case ScanTarget::LocalFileNetworkReplayStreaming: - return {"LocalFileNetworkReplayStreaming"}; - case ScanTarget::MaterialShaderQualitySettings: - return {"MaterialShaderQualitySettings"}; - case ScanTarget::Media: - return {"Media"}; - case ScanTarget::MediaAssets: - return {"MediaAssets"}; - case ScanTarget::MediaUtils: - return {"MediaUtils"}; - case ScanTarget::MeshDescription: - return {"MeshDescription"}; - case ScanTarget::MeshUtilitiesCommon: - return {"MeshUtilitiesCommon"}; - case ScanTarget::Messaging: - return {"Messaging"}; - case ScanTarget::MessagingCommon: - return {"MessagingCommon"}; - case ScanTarget::MoviePlayer: - return {"MoviePlayer"}; - case ScanTarget::MovieScene: - return {"MovieScene"}; - case ScanTarget::MovieSceneCapture: - return {"MovieSceneCapture"}; - case ScanTarget::MovieSceneTracks: - return {"MovieSceneTracks"}; - case ScanTarget::MRMesh: - return {"MRMesh"}; - case ScanTarget::NavigationSystem: - return {"NavigationSystem"}; - case ScanTarget::Navmesh: - return {"Navmesh"}; - case ScanTarget::NetCore: - return {"NetCore"}; - case ScanTarget::Networking: - return {"Networking"}; - case ScanTarget::NetworkReplayStreaming: - return {"NetworkReplayStreaming"}; - case ScanTarget::NonRealtimeAudioRenderer: - return {"NonRealtimeAudioRenderer"}; - case ScanTarget::NullDrv: - return {"NullDrv"}; - case ScanTarget::NullNetworkReplayStreaming: - return {"NullNetworkReplayStreaming"}; - case ScanTarget::OpenGLDrv: - return {"OpenGLDrv"}; - case ScanTarget::Overlay: - return {"Overlay"}; - case ScanTarget::PacketHandler: - return {"PacketHandler"}; - case ScanTarget::PakFile: - return {"PakFile"}; - case ScanTarget::PerfCounters: - return {"PerfCounters"}; - case ScanTarget::PhysicsCore: - return {"PhysicsCore"}; - case ScanTarget::PhysicsSQ: - return {"PhysicsSQ"}; - case ScanTarget::PhysXCooking: - return {"PhysXCooking"}; - case ScanTarget::PreLoadScreen: - return {"PreLoadScreen"}; - case ScanTarget::Projects: - return {"Projects"}; - case ScanTarget::PropertyPath: - return {"PropertyPath"}; - case ScanTarget::RawMesh: - return {"RawMesh"}; - case ScanTarget::ReliabilityHandlerComponent: - return {"ReliabilityHandlerComponent"}; - case ScanTarget::RenderCore: - return {"RenderCore"}; - case ScanTarget::Renderer: - return {"Renderer"}; - case ScanTarget::RHI: - return {"RHI"}; - case ScanTarget::RSA: - return {"RSA"}; - case ScanTarget::SandboxFile: - return {"SandboxFile"}; - case ScanTarget::Serialization: - return {"Serialization"}; - case ScanTarget::SessionMessages: - return {"SessionMessages"}; - case ScanTarget::SessionServices: - return {"SessionServices"}; - case ScanTarget::SignalProcessing: - return {"SignalProcessing"}; - case ScanTarget::Slate: - return {"Slate"}; - case ScanTarget::SlateCore: - return {"SlateCore"}; - case ScanTarget::SlateNullRenderer: - return {"SlateNullRenderer"}; - case ScanTarget::SlateRHIRenderer: - return {"SlateRHIRenderer"}; - case ScanTarget::Sockets: - return {"Sockets"}; - case ScanTarget::SoundFieldRendering: - return {"SoundFieldRendering"}; - case ScanTarget::SSL: - return {"SSL"}; - case ScanTarget::StaticMeshDescription: - return {"StaticMeshDescription"}; - case ScanTarget::StreamingPauseRendering: - return {"StreamingPauseRendering"}; - case ScanTarget::SynthBenchmark: - return {"SynthBenchmark"}; - case ScanTarget::TimeManagement: - return {"TimeManagement"}; - case ScanTarget::TraceLog: - return {"TraceLog"}; - case ScanTarget::UELibSampleRate: - return {"UELibSampleRate"}; - case ScanTarget::UMG: - return {"UMG"}; - case ScanTarget::VectorVM: - return {"VectorVM"}; - case ScanTarget::Voice: - return {"Voice"}; - case ScanTarget::Voronoi: - return {"Voronoi"}; - case ScanTarget::VulkanRHI: - return {"VulkanRHI"}; - case ScanTarget::WebBrowser: - return {"WebBrowser"}; - case ScanTarget::WindowsPlatformFeatures: - return {"WindowsPlatformFeatures"}; - case ScanTarget::XAudio2: - return {"XAudio2"}; - case ScanTarget::Max: - return {"Max"}; - } - - throw std::runtime_error{std::format("Invalid param for ScanTargetToString, param: {}", static_cast(scan_target))}; - } - - auto ScanTargetToString(size_t scan_target) -> std::string - { - return ScanTargetToString(static_cast(scan_target)); - } - - static auto ConvertHexCharToInt(char ch) -> int - { - if (ch >= '0' && ch <= '9') return ch - '0'; - if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; - if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; - return -1; - } - - auto SinglePassScanner::string_to_vector(std::string_view signature) -> std::vector - { - std::vector bytes; - char* const start = const_cast(signature.data()); - char* const end = const_cast(signature.data()) + strlen(signature.data()); - - for (char* current = start; current < end; current++) - { - if (*current == '?') - { - bytes.push_back(-1); - } - else if (std::isxdigit(*current)) - { - bytes.push_back(ConvertHexCharToInt(*current)); - } - } - return bytes; - } - - auto SinglePassScanner::string_to_vector(const std::vector& signatures) -> std::vector> + auto SinglePassScanner::get_system_info() -> SystemInfo { - std::vector> vector_of_signatures; - vector_of_signatures.reserve(signatures.size()); - - for (const auto& signature_data : signatures) - { - vector_of_signatures.emplace_back(string_to_vector(signature_data.signature)); - } - - return vector_of_signatures; + return SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; } - struct PatternData - { - std::vector pattern{}; - std::vector mask{}; - SignatureContainer* signature_container{}; - }; - static auto CharToByte(char symbol) -> uint8_t - { - if (symbol >= 'a' && symbol <= 'z') - { - return symbol - 'a' + 0xA; - } - else if (symbol >= 'A' && symbol <= 'Z') - { - return symbol - 'A' + 0xA; + namespace Platform { + auto get_start_address(DLData &info) -> uint8_t* { + return info.base_address; } - else if (symbol >= '0' && symbol <= '9') - { - return symbol - '0'; - } - else - { - return 0; - } - } - static auto make_mask(std::string_view pattern, SignatureContainer& signature_container, const size_t data_size) -> PatternData - { - PatternData pattern_data{}; - - if (pattern.length() < 1 || pattern[0] == '?') - { - throw std::runtime_error{std::format("[make_mask] A pattern cannot start with a wildcard.\nPattern: {}", pattern)}; + auto get_end_address(DLData &info) -> uint8_t* { + return info.base_address + info.size; } - for (size_t i = 0; i < pattern.length(); i++) - { - char symbol = pattern[i]; - char next_symbol = ((i + 1) < pattern.length()) ? pattern[i + 1] : 0; - if (symbol == ' ') - { - continue; - } - - if (symbol == '?') - { - pattern_data.pattern.push_back(0x00); - pattern_data.mask.push_back(0x00); - - if (next_symbol == '?') - { - ++i; - } - continue; - } - - uint8_t byte = CharToByte(symbol) << 4 | CharToByte(next_symbol); - - pattern_data.pattern.push_back(byte); - pattern_data.mask.push_back(0xff); - - ++i; + auto get_module_size(DLData &info) -> uint32_t { + return info.size; } - static constexpr size_t Alignment = 32; - size_t count = (size_t)std::ceil((float)data_size / Alignment); - size_t padding_size = count * Alignment - data_size; - - for (size_t i = 0; i < padding_size; i++) - { - pattern_data.pattern.push_back(0x00); - pattern_data.mask.push_back(0x00); + auto get_module_base(DLData &info) -> uint8_t* { + return info.base_address; } + }; // namespace Platform - pattern_data.signature_container = &signature_container; - return pattern_data; + auto SinglePassScanner::string_scan(std::wstring_view string_to_scan_for, ScanTarget scan_target) -> void* { + throw std::runtime_error{"[SinglePassSigScanner::string_scan] Not implemented for Linux"}; } - auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, DLData& info, std::vector& signature_containers) - -> void - { - ProfilerSetThreadName("UE4SS-ScannerWorkThread"); - ProfilerScope(); - - switch (m_scan_method) - { - case ScanMethod::Scalar: - scanner_work_thread_scalar(start_address, end_address, info, signature_containers); - break; - case ScanMethod::StdFind: - scanner_work_thread_stdfind(start_address, end_address, info, signature_containers); - break; - } - } + // This function may have problem becasue we're not checking the memory region's permissions auto SinglePassScanner::scanner_work_thread_scalar(uint8_t* start_address, uint8_t* end_address, DLData& info, @@ -537,8 +130,8 @@ namespace RC for (size_t sig_i = 0; sig_i < sig.size(); sig_i += 2) { - if (sig.at(sig_i) != -1 && sig.at(sig_i) != HI_NIBBLE(*(byte*)(region_start + (sig_i / 2))) || - sig.at(sig_i + 1) != -1 && sig.at(sig_i + 1) != LO_NIBBLE(*(byte*)(region_start + (sig_i / 2)))) + if (sig.at(sig_i) != -1 && sig.at(sig_i) != HI_NIBBLE(*(uint8_t*)(region_start + (sig_i / 2))) || + sig.at(sig_i + 1) != -1 && sig.at(sig_i + 1) != LO_NIBBLE(*(uint8_t*)(region_start + (sig_i / 2)))) { break; } @@ -593,231 +186,4 @@ namespace RC } } - - static auto format_aob_string(std::string& str) -> void - { - if (str.size() < 4) - { - return; - } - if (str[3] != '/') - { - return; - } - - std::erase_if(str, [&](const char c) { - return c == ' '; - }); - - std::ranges::transform(str, str.begin(), [&str](const char c) { - return c == '/' ? ' ' : c; - }); - } - - auto SinglePassScanner::format_aob_strings(std::vector& signature_containers) -> void - { - std::lock_guard safe_scope(m_scanner_mutex); - for (auto& signature_container : signature_containers) - { - for (auto& signature : signature_container.signatures) - { - format_aob_string(signature.signature); - } - } - } - - auto SinglePassScanner::scanner_work_thread_stdfind(uint8_t* start_address, - uint8_t* end_address, - DLData& info, - std::vector& signature_containers) -> void - { - ProfilerScope(); - - if (!start_address) - { - start_address = static_cast(info.base_address); - } - if (!end_address) - { - end_address = static_cast(info.base_address + info.size); - } - - format_aob_strings(signature_containers); - - std::vector> pattern_datas{}; - for (auto& signature_container : signature_containers) - { - auto& pattern_data = pattern_datas.emplace_back(); - for (auto& signature : signature_container.signatures) - { - pattern_data.emplace_back(make_mask(signature.signature, signature_container, end_address - start_address)); - } - } - - // Loop everything - for (size_t container_index = 0; const auto& patterns : pattern_datas) - { - for (size_t signature_index = 0; const auto& pattern_data : patterns) - { - // If the container is refusing more calls then skip to the next container - if (pattern_data.signature_container->ignore) - { - break; - } - - auto it = start_address; - auto end = it + (end_address - start_address) - (pattern_data.pattern.size()) + 1; - uint8_t needle = pattern_data.pattern[0]; - - bool skip_to_next_container{}; - while (end != (it = std::find(it, end, needle))) - { - bool found = true; - for (size_t pattern_offset = 0; pattern_offset < pattern_data.pattern.size(); ++pattern_offset) - { - if ((it[pattern_offset] & pattern_data.mask[pattern_offset]) != pattern_data.pattern[pattern_offset]) - { - found = false; - break; - } - } - - if (found) - { - { - std::lock_guard safe_scope(m_scanner_mutex); - - // Checking for the second time if the container is refusing more calls - // This is required when multi-threading is enabled - if (pattern_data.signature_container->ignore) - { - skip_to_next_container = true; - break; - } - - // One of the signatures have found a full match so lets forward the details to the callable - pattern_data.signature_container->index_into_signatures = signature_index; - pattern_data.signature_container->match_address = it; - pattern_data.signature_container->match_signature_size = pattern_data.pattern.size(); - - skip_to_next_container = pattern_data.signature_container->on_match_found(*pattern_data.signature_container); - pattern_data.signature_container->ignore = skip_to_next_container; - - // Store results if the container at the containers request - if (pattern_data.signature_container->store_results) - { - pattern_data.signature_container->result_store.emplace_back( - SignatureContainerLight{.index_into_signatures = signature_index, .match_address = it}); - } - } - } - - it++; - } - - if (skip_to_next_container) - { - // A match was found and signaled to skip to the next container - break; - } - - ++signature_index; - } - ++container_index; - } - } - - auto SinglePassScanner::start_scan(SignatureContainerMap& signature_containers) -> void - { - //DLData info = SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; - - // If not modular then the containers get merged into one scan target - // That way there are no extra scans - // If modular then loop the containers and retrieve the scan target for each and pass everything to the do_scan() lambda - fprintf(stderr, "signature_containers.size() = %d\n", signature_containers.size()); - if (!SigScannerStaticData::m_is_modular) - { - DLData merged_module_info{}; - std::vector merged_containers; - - for (const auto& [scan_target, outer_container] : signature_containers) - { - merged_module_info = *std::bit_cast(&SigScannerStaticData::m_modules_info[scan_target]); - fprintf(stderr, "outer_container len = %d\n", outer_container.size()); - for (const auto& signature_container : outer_container) - { - merged_containers.emplace_back(signature_container); - } - } - - if (merged_containers.empty()) - { - fprintf(stderr, "No containers to merge\n"); - return ; - //throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " - // "an internal error."}; - } - - uint8_t* module_start_address = static_cast(merged_module_info.base_address); - - if (merged_module_info.size >= m_multithreading_module_size_threshold) - { - // Module is large enough to make it overall faster to scan with multiple threads - std::vector> scan_threads; - - // Higher values are better for debugging - // You will get a bigger diminishing returns the faster your computer is (especially in release mode) - uint32_t range = merged_module_info.size / m_num_threads; - - // Calculating the ranges for each thread to scan and starting the scan - uint32_t last_range{}; - for (uint32_t thread_id = 0; thread_id < m_num_threads; ++thread_id) - { - scan_threads.emplace_back(std::async(std::launch::async, - &scanner_work_thread, - module_start_address + last_range, - module_start_address + last_range + range, - std::ref(merged_module_info), - std::ref(merged_containers))); - - last_range += range; - } - - for (const auto& scan_thread : scan_threads) - { - scan_thread.wait(); - } - } - else - { - // Module is too small to make it overall faster to scan with multiple threads - uint8_t* module_end_address = static_cast(module_start_address + merged_module_info.size); - scanner_work_thread(module_start_address, module_end_address, merged_module_info, merged_containers); - } - - for (auto& container : merged_containers) - { - container.on_scan_finished(container); - } - } - else - { - // This ranged for loop is performing a copy of unordered_map> - // Is this required ? Would it be worth trying to avoid copying here ? - // Right now it can't be auto& or const auto& because the do_scan function takes a non-const since it needs to mutate the values inside the vector - auto info = SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; - for (auto& [scan_target, signature_container] : signature_containers) - { - uint8_t* module_start_address = static_cast(SigScannerStaticData::m_modules_info[scan_target].base_address); - uint8_t* module_end_address = static_cast(module_start_address + SigScannerStaticData::m_modules_info[scan_target].size); - - scanner_work_thread(module_start_address, module_end_address, info, signature_container); - - for (auto& container : signature_container) - { - container.on_scan_finished(container); - } - } - } - } } // namespace RC \ No newline at end of file diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp index 63ec115a0..381ca5a4a 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp @@ -16,358 +16,42 @@ namespace RC { - ScanTargetArray SigScannerStaticData::m_modules_info; - bool SigScannerStaticData::m_is_modular; - - uint32_t SinglePassScanner::m_num_threads = 8; - SinglePassScanner::ScanMethod SinglePassScanner::m_scan_method = ScanMethod::Scalar; - uint32_t SinglePassScanner::m_multithreading_module_size_threshold = 0x1000000; - std::mutex SinglePassScanner::m_scanner_mutex{}; -#ifdef WIN32 - auto WIN_MODULEINFO::operator=(MODULEINFO other) -> WIN_MODULEINFO& + + auto SinglePassScanner::get_system_info() -> SystemInfo { - lpBaseOfDll = other.lpBaseOfDll; - SizeOfImage = other.SizeOfImage; - EntryPoint = other.EntryPoint; - return *this; - } - - auto ScanTargetArray::operator[](ScanTarget index) -> MODULEINFO& - { - return *std::bit_cast(&array[static_cast(index)]); - } -#else - auto ScanTargetArray::operator[](ScanTarget index) -> DLData& - { - return array[static_cast(index)]; + SYSTEM_INFO info{}; + GetSystemInfo(&info); + return info; } -#endif - - auto ScanTargetToString(ScanTarget scan_target) -> std::string - { - switch (scan_target) - { - case ScanTarget::MainExe: - return {"MainExe"}; - case ScanTarget::AIModule: - return {"AIModule"}; - case ScanTarget::Analytics: - return {"Analytics"}; - case ScanTarget::AnalyticsET: - return {"AnalyticsET"}; - case ScanTarget::AnimationCore: - return {"AnimationCore"}; - case ScanTarget::AnimGraphRuntime: - return {"AnimGraphRuntime"}; - case ScanTarget::AppFramework: - return {"AppFramework"}; - case ScanTarget::ApplicationCore: - return {"ApplicationCore"}; - case ScanTarget::AssetRegistry: - return {"AssetRegistry"}; - case ScanTarget::AudioCaptureCore: - return {"AudioCaptureCore"}; - case ScanTarget::AudioCaptureRtAudio: - return {"AudioCaptureRtAudio"}; - case ScanTarget::AudioExtensions: - return {"AudioExtensions"}; - case ScanTarget::AudioMixer: - return {"AudioMixer"}; - case ScanTarget::AudioMixerCore: - return {"AudioMixerCore"}; - case ScanTarget::AudioMixerXAudio2: - return {"AudioMixerXAudio2"}; - case ScanTarget::AudioPlatformConfiguration: - return {"AudioPlatformConfiguration"}; - case ScanTarget::AugmentedReality: - return {"AugmentedReality"}; - case ScanTarget::AVEncoder: - return {"AVEncoder"}; - case ScanTarget::AVIWriter: - return {"AVIWriter"}; - case ScanTarget::BuildPatchServices: - return {"BuildPatchServices"}; - case ScanTarget::BuildSettings: - return {"BuildSettings"}; - case ScanTarget::Cbor: - return {"Cbor"}; - case ScanTarget::CEF3Utils: - return {"CEF3Utils"}; - case ScanTarget::Chaos: - return {"Chaos"}; - case ScanTarget::ChaosCore: - return {"ChaosCore"}; - case ScanTarget::ChaosSolverEngine: - return {"ChaosSolverEngine"}; - case ScanTarget::ChaosSolvers: - return {"ChaosSolvers"}; - case ScanTarget::CinematicCamera: - return {"CinematicCamera"}; - case ScanTarget::ClothingSystemRuntimeCommon: - return {"ClothingSystemRuntimeCommon"}; - case ScanTarget::ClothingSystemRuntimeInterface: - return {"ClothingSystemRuntimeInterface"}; - case ScanTarget::ClothingSystemRuntimeNv: - return {"ClothingSystemRuntimeNv"}; - case ScanTarget::Core: - return {"Core"}; - case ScanTarget::CoreUObject: - return {"CoreUObject"}; - case ScanTarget::CrunchCompression: - return {"CrunchCompression"}; - case ScanTarget::D3D11RHI: - return {"D3D11RHI"}; - case ScanTarget::D3D12RHI: - return {"D3D12RHI"}; - case ScanTarget::Engine: - return {"Engine"}; - case ScanTarget::EngineMessages: - return {"EngineMessages"}; - case ScanTarget::EngineSettings: - return {"EngineSettings"}; - case ScanTarget::EyeTracker: - return {"EyeTracker"}; - case ScanTarget::FieldSystemCore: - return {"FieldSystemCore"}; - case ScanTarget::FieldSystemEngine: - return {"FieldSystemEngine"}; - case ScanTarget::FieldSystemSimulationCore: - return {"FieldSystemSimulationCore"}; - case ScanTarget::Foliage: - return {"Foliage"}; - case ScanTarget::GameplayMediaEncoder: - return {"GameplayMediaEncoder"}; - case ScanTarget::GameplayTags: - return {"GameplayTags"}; - case ScanTarget::GameplayTasks: - return {"GameplayTasks"}; - case ScanTarget::GeometryCollectionCore: - return {"GeometryCollectionCore"}; - case ScanTarget::GeometryCollectionEngine: - return {"GeometryCollectionEngine"}; - case ScanTarget::GeometryCollectionSimulationCore: - return {"GeometryCollectionSimulationCore"}; - case ScanTarget::HeadMountedDisplay: - return {"HeadMountedDisplay"}; - case ScanTarget::HTTP: - return {"HTTP"}; - case ScanTarget::HttpNetworkReplayStreaming: - return {"HttpNetworkReplayStreaming"}; - case ScanTarget::HTTPServer: - return {"HTTPServer"}; - case ScanTarget::Icmp: - return {"Icmp"}; - case ScanTarget::ImageCore: - return {"ImageCore"}; - case ScanTarget::ImageWrapper: - return {"ImageWrapper"}; - case ScanTarget::ImageWriteQueue: - return {"ImageWriteQueue"}; - case ScanTarget::InputCore: - return {"InputCore"}; - case ScanTarget::InputDevice: - return {"InputDevice"}; - case ScanTarget::InstallBundleManager: - return {"InstallBundleManager"}; - case ScanTarget::InstancedSplines: - return {"InstancedSplines"}; - case ScanTarget::InteractiveToolsFramework: - return {"InteractiveToolsFramework"}; - case ScanTarget::Json: - return {"Json"}; - case ScanTarget::JsonUtilities: - return {"JsonUtilities"}; - case ScanTarget::Landscape: - return {"Landscape"}; - case ScanTarget::LauncherCheck: - return {"LauncherCheck"}; - case ScanTarget::LauncherPlatform: - return {"LauncherPlatform"}; - case ScanTarget::LevelSequence: - return {"LevelSequence"}; - case ScanTarget::LocalFileNetworkReplayStreaming: - return {"LocalFileNetworkReplayStreaming"}; - case ScanTarget::MaterialShaderQualitySettings: - return {"MaterialShaderQualitySettings"}; - case ScanTarget::Media: - return {"Media"}; - case ScanTarget::MediaAssets: - return {"MediaAssets"}; - case ScanTarget::MediaUtils: - return {"MediaUtils"}; - case ScanTarget::MeshDescription: - return {"MeshDescription"}; - case ScanTarget::MeshUtilitiesCommon: - return {"MeshUtilitiesCommon"}; - case ScanTarget::Messaging: - return {"Messaging"}; - case ScanTarget::MessagingCommon: - return {"MessagingCommon"}; - case ScanTarget::MoviePlayer: - return {"MoviePlayer"}; - case ScanTarget::MovieScene: - return {"MovieScene"}; - case ScanTarget::MovieSceneCapture: - return {"MovieSceneCapture"}; - case ScanTarget::MovieSceneTracks: - return {"MovieSceneTracks"}; - case ScanTarget::MRMesh: - return {"MRMesh"}; - case ScanTarget::NavigationSystem: - return {"NavigationSystem"}; - case ScanTarget::Navmesh: - return {"Navmesh"}; - case ScanTarget::NetCore: - return {"NetCore"}; - case ScanTarget::Networking: - return {"Networking"}; - case ScanTarget::NetworkReplayStreaming: - return {"NetworkReplayStreaming"}; - case ScanTarget::NonRealtimeAudioRenderer: - return {"NonRealtimeAudioRenderer"}; - case ScanTarget::NullDrv: - return {"NullDrv"}; - case ScanTarget::NullNetworkReplayStreaming: - return {"NullNetworkReplayStreaming"}; - case ScanTarget::OpenGLDrv: - return {"OpenGLDrv"}; - case ScanTarget::Overlay: - return {"Overlay"}; - case ScanTarget::PacketHandler: - return {"PacketHandler"}; - case ScanTarget::PakFile: - return {"PakFile"}; - case ScanTarget::PerfCounters: - return {"PerfCounters"}; - case ScanTarget::PhysicsCore: - return {"PhysicsCore"}; - case ScanTarget::PhysicsSQ: - return {"PhysicsSQ"}; - case ScanTarget::PhysXCooking: - return {"PhysXCooking"}; - case ScanTarget::PreLoadScreen: - return {"PreLoadScreen"}; - case ScanTarget::Projects: - return {"Projects"}; - case ScanTarget::PropertyPath: - return {"PropertyPath"}; - case ScanTarget::RawMesh: - return {"RawMesh"}; - case ScanTarget::ReliabilityHandlerComponent: - return {"ReliabilityHandlerComponent"}; - case ScanTarget::RenderCore: - return {"RenderCore"}; - case ScanTarget::Renderer: - return {"Renderer"}; - case ScanTarget::RHI: - return {"RHI"}; - case ScanTarget::RSA: - return {"RSA"}; - case ScanTarget::SandboxFile: - return {"SandboxFile"}; - case ScanTarget::Serialization: - return {"Serialization"}; - case ScanTarget::SessionMessages: - return {"SessionMessages"}; - case ScanTarget::SessionServices: - return {"SessionServices"}; - case ScanTarget::SignalProcessing: - return {"SignalProcessing"}; - case ScanTarget::Slate: - return {"Slate"}; - case ScanTarget::SlateCore: - return {"SlateCore"}; - case ScanTarget::SlateNullRenderer: - return {"SlateNullRenderer"}; - case ScanTarget::SlateRHIRenderer: - return {"SlateRHIRenderer"}; - case ScanTarget::Sockets: - return {"Sockets"}; - case ScanTarget::SoundFieldRendering: - return {"SoundFieldRendering"}; - case ScanTarget::SSL: - return {"SSL"}; - case ScanTarget::StaticMeshDescription: - return {"StaticMeshDescription"}; - case ScanTarget::StreamingPauseRendering: - return {"StreamingPauseRendering"}; - case ScanTarget::SynthBenchmark: - return {"SynthBenchmark"}; - case ScanTarget::TimeManagement: - return {"TimeManagement"}; - case ScanTarget::TraceLog: - return {"TraceLog"}; - case ScanTarget::UELibSampleRate: - return {"UELibSampleRate"}; - case ScanTarget::UMG: - return {"UMG"}; - case ScanTarget::VectorVM: - return {"VectorVM"}; - case ScanTarget::Voice: - return {"Voice"}; - case ScanTarget::Voronoi: - return {"Voronoi"}; - case ScanTarget::VulkanRHI: - return {"VulkanRHI"}; - case ScanTarget::WebBrowser: - return {"WebBrowser"}; - case ScanTarget::WindowsPlatformFeatures: - return {"WindowsPlatformFeatures"}; - case ScanTarget::XAudio2: - return {"XAudio2"}; - case ScanTarget::Max: - return {"Max"}; + namespace Platform { + // Get the start address of the system + auto get_start_address(SystemInfo &info) -> uint8_t* { + return static_cast(info.lpMinimumApplicationAddress); } - throw std::runtime_error{std::format("Invalid param for ScanTargetToString, param: {}", static_cast(scan_target))}; - } - - auto ScanTargetToString(size_t scan_target) -> std::string - { - return ScanTargetToString(static_cast(scan_target)); - } - - static auto ConvertHexCharToInt(char ch) -> int - { - if (ch >= '0' && ch <= '9') return ch - '0'; - if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; - if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; - return -1; - } - - auto SinglePassScanner::string_to_vector(std::string_view signature) -> std::vector - { - std::vector bytes; - char* const start = const_cast(signature.data()); - char* const end = const_cast(signature.data()) + strlen(signature.data()); - - for (char* current = start; current < end; current++) - { - if (*current == '?') - { - bytes.push_back(-1); - } - else if (std::isxdigit(*current)) - { - bytes.push_back(ConvertHexCharToInt(*current)); - } + // Get the end address of the system + auto get_end_address(SystemInfo &info) -> uint8_t* { + return static_cast(info.lpMaximumApplicationAddress); } - return bytes; - } - - auto SinglePassScanner::string_to_vector(const std::vector& signatures) -> std::vector> - { - std::vector> vector_of_signatures; - vector_of_signatures.reserve(signatures.size()); - - for (const auto& signature_data : signatures) - { - vector_of_signatures.emplace_back(string_to_vector(signature_data.signature)); + // Get the size of the module + auto get_module_size(ModuleOS &info) -> size_t { + return info.SizeOfImage; } - return vector_of_signatures; + // Get the base address of the module + auto get_module_base(ModuleOS &info) -> uint8_t* { + return static_cast(info.lpBaseOfDll); + } + }; // namespace Platform + + auto WIN_MODULEINFO::operator=(MODULEINFO other) -> WIN_MODULEINFO& + { + lpBaseOfDll = other.lpBaseOfDll; + SizeOfImage = other.SizeOfImage; + EntryPoint = other.EntryPoint; + return *this; } auto SinglePassScanner::string_scan(std::wstring_view string_to_scan_for, ScanTarget scan_target) -> void* @@ -420,102 +104,6 @@ namespace RC return address_found; } - struct PatternData - { - std::vector pattern{}; - std::vector mask{}; - SignatureContainer* signature_container{}; - }; - - static auto CharToByte(char symbol) -> uint8_t - { - if (symbol >= 'a' && symbol <= 'z') - { - return symbol - 'a' + 0xA; - } - else if (symbol >= 'A' && symbol <= 'Z') - { - return symbol - 'A' + 0xA; - } - else if (symbol >= '0' && symbol <= '9') - { - return symbol - '0'; - } - else - { - return 0; - } - } - - static auto make_mask(std::string_view pattern, SignatureContainer& signature_container, const size_t data_size) -> PatternData - { - PatternData pattern_data{}; - - if (pattern.length() < 1 || pattern[0] == '?') - { - throw std::runtime_error{std::format("[make_mask] A pattern cannot start with a wildcard.\nPattern: {}", pattern)}; - } - - for (size_t i = 0; i < pattern.length(); i++) - { - char symbol = pattern[i]; - char next_symbol = ((i + 1) < pattern.length()) ? pattern[i + 1] : 0; - if (symbol == ' ') - { - continue; - } - - if (symbol == '?') - { - pattern_data.pattern.push_back(0x00); - pattern_data.mask.push_back(0x00); - - if (next_symbol == '?') - { - ++i; - } - continue; - } - - uint8_t byte = CharToByte(symbol) << 4 | CharToByte(next_symbol); - - pattern_data.pattern.push_back(byte); - pattern_data.mask.push_back(0xff); - - ++i; - } - - static constexpr size_t Alignment = 32; - size_t count = (size_t)std::ceil((float)data_size / Alignment); - size_t padding_size = count * Alignment - data_size; - - for (size_t i = 0; i < padding_size; i++) - { - pattern_data.pattern.push_back(0x00); - pattern_data.mask.push_back(0x00); - } - - pattern_data.signature_container = &signature_container; - return pattern_data; - } - - auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, SYSTEM_INFO& info, std::vector& signature_containers) - -> void - { - ProfilerSetThreadName("UE4SS-ScannerWorkThread"); - ProfilerScope(); - - switch (m_scan_method) - { - case ScanMethod::Scalar: - scanner_work_thread_scalar(start_address, end_address, info, signature_containers); - break; - case ScanMethod::StdFind: - scanner_work_thread_stdfind(start_address, end_address, info, signature_containers); - break; - } - } - auto SinglePassScanner::scanner_work_thread_scalar(uint8_t* start_address, uint8_t* end_address, SYSTEM_INFO& info, @@ -663,228 +251,4 @@ namespace RC } } } - - static auto format_aob_string(std::string& str) -> void - { - if (str.size() < 4) - { - return; - } - if (str[3] != '/') - { - return; - } - - std::erase_if(str, [&](const char c) { - return c == ' '; - }); - - std::ranges::transform(str, str.begin(), [&str](const char c) { - return c == '/' ? ' ' : c; - }); - } - - auto SinglePassScanner::format_aob_strings(std::vector& signature_containers) -> void - { - std::lock_guard safe_scope(m_scanner_mutex); - for (auto& signature_container : signature_containers) - { - for (auto& signature : signature_container.signatures) - { - format_aob_string(signature.signature); - } - } - } - - auto SinglePassScanner::scanner_work_thread_stdfind(uint8_t* start_address, - uint8_t* end_address, - SYSTEM_INFO& info, - std::vector& signature_containers) -> void - { - ProfilerScope(); - - if (!start_address) - { - start_address = static_cast(info.lpMinimumApplicationAddress); - } - if (!end_address) - { - start_address = static_cast(info.lpMaximumApplicationAddress); - } - - format_aob_strings(signature_containers); - - std::vector> pattern_datas{}; - for (auto& signature_container : signature_containers) - { - auto& pattern_data = pattern_datas.emplace_back(); - for (auto& signature : signature_container.signatures) - { - pattern_data.emplace_back(make_mask(signature.signature, signature_container, end_address - start_address)); - } - } - - // Loop everything - for (size_t container_index = 0; const auto& patterns : pattern_datas) - { - for (size_t signature_index = 0; const auto& pattern_data : patterns) - { - // If the container is refusing more calls then skip to the next container - if (pattern_data.signature_container->ignore) - { - break; - } - - auto it = start_address; - auto end = it + (end_address - start_address) - (pattern_data.pattern.size()) + 1; - uint8_t needle = pattern_data.pattern[0]; - - bool skip_to_next_container{}; - while (end != (it = std::find(it, end, needle))) - { - bool found = true; - for (size_t pattern_offset = 0; pattern_offset < pattern_data.pattern.size(); ++pattern_offset) - { - if ((it[pattern_offset] & pattern_data.mask[pattern_offset]) != pattern_data.pattern[pattern_offset]) - { - found = false; - break; - } - } - - if (found) - { - { - std::lock_guard safe_scope(m_scanner_mutex); - - // Checking for the second time if the container is refusing more calls - // This is required when multi-threading is enabled - if (pattern_data.signature_container->ignore) - { - skip_to_next_container = true; - break; - } - - // One of the signatures have found a full match so lets forward the details to the callable - pattern_data.signature_container->index_into_signatures = signature_index; - pattern_data.signature_container->match_address = it; - pattern_data.signature_container->match_signature_size = pattern_data.pattern.size(); - - skip_to_next_container = pattern_data.signature_container->on_match_found(*pattern_data.signature_container); - pattern_data.signature_container->ignore = skip_to_next_container; - - // Store results if the container at the containers request - if (pattern_data.signature_container->store_results) - { - pattern_data.signature_container->result_store.emplace_back( - SignatureContainerLight{.index_into_signatures = signature_index, .match_address = it}); - } - } - } - - it++; - } - - if (skip_to_next_container) - { - // A match was found and signaled to skip to the next container - break; - } - - ++signature_index; - } - ++container_index; - } - } - - auto SinglePassScanner::start_scan(SignatureContainerMap& signature_containers) -> void - { - SYSTEM_INFO info{}; - GetSystemInfo(&info); - - // If not modular then the containers get merged into one scan target - // That way there are no extra scans - // If modular then loop the containers and retrieve the scan target for each and pass everything to the do_scan() lambda - - if (!SigScannerStaticData::m_is_modular) - { - MODULEINFO merged_module_info{}; - std::vector merged_containers; - - for (const auto& [scan_target, outer_container] : signature_containers) - { - merged_module_info = *std::bit_cast(&SigScannerStaticData::m_modules_info[scan_target]); - for (const auto& signature_container : outer_container) - { - merged_containers.emplace_back(signature_container); - } - } - - if (merged_containers.empty()) - { - throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " - "an internal error."}; - } - - uint8_t* module_start_address = static_cast(merged_module_info.lpBaseOfDll); - - if (merged_module_info.SizeOfImage >= m_multithreading_module_size_threshold) - { - // Module is large enough to make it overall faster to scan with multiple threads - std::vector> scan_threads; - - // Higher values are better for debugging - // You will get a bigger diminishing returns the faster your computer is (especially in release mode) - uint32_t range = merged_module_info.SizeOfImage / m_num_threads; - - // Calculating the ranges for each thread to scan and starting the scan - uint32_t last_range{}; - for (uint32_t thread_id = 0; thread_id < m_num_threads; ++thread_id) - { - scan_threads.emplace_back(std::async(std::launch::async, - &scanner_work_thread, - module_start_address + last_range, - module_start_address + last_range + range, - std::ref(info), - std::ref(merged_containers))); - - last_range += range; - } - - for (const auto& scan_thread : scan_threads) - { - scan_thread.wait(); - } - } - else - { - // Module is too small to make it overall faster to scan with multiple threads - uint8_t* module_end_address = static_cast(module_start_address + merged_module_info.SizeOfImage); - scanner_work_thread(module_start_address, module_end_address, info, merged_containers); - } - - for (auto& container : merged_containers) - { - container.on_scan_finished(container); - } - } - else - { - // This ranged for loop is performing a copy of unordered_map> - // Is this required ? Would it be worth trying to avoid copying here ? - // Right now it can't be auto& or const auto& because the do_scan function takes a non-const since it needs to mutate the values inside the vector - for (auto& [scan_target, signature_container] : signature_containers) - { - uint8_t* module_start_address = static_cast(SigScannerStaticData::m_modules_info[scan_target].lpBaseOfDll); - uint8_t* module_end_address = static_cast(module_start_address + SigScannerStaticData::m_modules_info[scan_target].SizeOfImage); - - scanner_work_thread(module_start_address, module_end_address, info, signature_container); - - for (auto& container : signature_container) - { - container.on_scan_finished(container); - } - } - } - } } // namespace RC \ No newline at end of file From d983fe1ccb47b3f16efc1aab35fe822c9ea6c0c1 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Feb 2024 03:12:36 -0600 Subject: [PATCH 064/213] windows fix --- UE4SS/src/UE4SSProgram.cpp | 2 +- deps/first/Helpers/include/Helpers/String.hpp | 12 +++--- .../SigScanner/SinglePassSigScanner.hpp | 19 ++++----- .../src/SinglePassSigScanner.cpp | 25 +++++------- .../src/SinglePassSigScannerLinux.cpp | 25 +++++++----- .../src/SinglePassSigScannerWin32.cpp | 39 +++++++++++-------- 6 files changed, 65 insertions(+), 57 deletions(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 1f0671ce6..e9719d82a 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -274,7 +274,7 @@ namespace RC SYSSTR("")); m_load_library_ex_w_hook->hook(); #endif - Unreal::UnrealInitializer::SetupUnrealModules(); + Unreal::UnrealInitializer::Platform::SetupUnrealModules(); setup_mods(); install_cpp_mods(); diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index 7311c682b..fc91baf72 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -436,12 +436,12 @@ namespace RC template auto stringviewify(T&& tp) { - if constexpr (std::is_same_v, UECharType*> || std::is_same_v, const UECharType*>) { - return UEStringViewType{tp}; - } else if constexpr (std::is_same_v, SystemCharType*> || std::is_same_v, const SystemCharType*>) { - return SystemStringViewType{tp}; - } else if constexpr (std::is_same_v, File::CharType*> || std::is_same_v, const File::CharType*>) { - return File::StringViewType{tp}; + if constexpr (std::is_same_v, char*> || std::is_same_v, const char*>) { + return std::string_view{tp}; + } else if constexpr (std::is_same_v, wchar_t*> || std::is_same_v, const wchar_t*>) { + return std::wstring_view{tp}; + } else if constexpr (std::is_same_v, char16_t*> || std::is_same_v, const char16_t*>) { + return std::u16string_view{tp}; } else { return std::forward(tp); } diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp index 65479d1a6..efd8b74a0 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp @@ -312,20 +312,18 @@ namespace RC RC_SPSS_API auto static string_to_vector(const std::vector& signatures) -> std::vector>; RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; - RC_SPSS_API auto static get_system_info() -> SystemInfo; - public: RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, uint8_t* end_address, - SystemInfo& info, + SystemInfo* info, std::vector& signature_containers) -> void; RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, uint8_t* end_address, - SystemInfo& info, + SystemInfo* info, std::vector& signature_containers) -> void; RC_SPSS_API auto static scanner_work_thread_stdfind(uint8_t* start_address, uint8_t* end_address, - SystemInfo& info, + SystemInfo* info, std::vector& signature_containers) -> void; using SignatureContainerMap = std::unordered_map>; @@ -335,17 +333,20 @@ namespace RC namespace Platform { + // Get the system info + auto get_system_info() -> SystemInfo*; + // Get the start address of the system - auto get_start_address(SystemInfo &info) -> uint8_t*; + auto get_start_address(SystemInfo *info) -> uint8_t*; // Get the end address of the system - auto get_end_address(SystemInfo &info) -> uint8_t*; + auto get_end_address(SystemInfo *info) -> uint8_t*; // Get the size of the module - auto get_module_size(ModuleOS &info) -> uint32_t; + auto get_module_size(ModuleOS *info) -> uint32_t; // Get the base address of the module - auto get_module_base(ModuleOS &info) -> uint8_t*; + auto get_module_base(ModuleOS *info) -> uint8_t*; }; // namespace Platform }; // namespace RC diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp index 9f40e296e..54b8c6cbb 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp @@ -18,11 +18,6 @@ namespace RC SinglePassScanner::ScanMethod SinglePassScanner::m_scan_method = ScanMethod::Scalar; uint32_t SinglePassScanner::m_multithreading_module_size_threshold = 0x1000000; std::mutex SinglePassScanner::m_scanner_mutex{}; - - auto ScanTargetArray::operator[](ScanTarget index) -> ModuleOS& - { - return array[static_cast(index)]; - } auto ScanTargetToString(ScanTarget scan_target) -> std::string { @@ -429,7 +424,7 @@ namespace RC return pattern_data; } - auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, SystemInfo& info, std::vector& signature_containers) + auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, SystemInfo *info, std::vector& signature_containers) -> void { ProfilerSetThreadName("UE4SS-ScannerWorkThread"); @@ -480,7 +475,7 @@ namespace RC auto SinglePassScanner::scanner_work_thread_stdfind(uint8_t* start_address, uint8_t* end_address, - SystemInfo& info, + SystemInfo* info, std::vector& signature_containers) -> void { ProfilerScope(); @@ -581,7 +576,7 @@ namespace RC auto SinglePassScanner::start_scan(SignatureContainerMap& signature_containers) -> void { - SystemInfo info = get_system_info(); + SystemInfo* info = Platform::get_system_info(); // If not modular then the containers get merged into one scan target // That way there are no extra scans @@ -589,12 +584,12 @@ namespace RC fprintf(stderr, "signature_containers.size() = %d\n", signature_containers.size()); if (!SigScannerStaticData::m_is_modular) { - ModuleOS merged_module_info{}; + ModuleOS* merged_module_info{}; std::vector merged_containers; for (const auto& [scan_target, outer_container] : signature_containers) { - merged_module_info = *std::bit_cast(&SigScannerStaticData::m_modules_info[scan_target]); + merged_module_info = std::bit_cast(&SigScannerStaticData::m_modules_info[scan_target]); fprintf(stderr, "outer_container len = %d\n", outer_container.size()); for (const auto& signature_container : outer_container) { @@ -629,7 +624,7 @@ namespace RC &scanner_work_thread, module_start_address + last_range, module_start_address + last_range + range, - std::ref(info), + info, std::ref(merged_containers))); last_range += range; @@ -644,7 +639,7 @@ namespace RC { // Module is too small to make it overall faster to scan with multiple threads uint8_t* module_end_address = static_cast(module_start_address + Platform::get_module_size(merged_module_info)); - scanner_work_thread(module_start_address, module_end_address, merged_module_info, merged_containers); + scanner_work_thread(module_start_address, module_end_address, info, merged_containers); } for (auto& container : merged_containers) @@ -657,11 +652,11 @@ namespace RC // This ranged for loop is performing a copy of unordered_map> // Is this required ? Would it be worth trying to avoid copying here ? // Right now it can't be auto& or const auto& because the do_scan function takes a non-const since it needs to mutate the values inside the vector - auto info = SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; + auto info = Platform::get_system_info(); for (auto& [scan_target, signature_container] : signature_containers) { - uint8_t* module_start_address = static_cast(Platform::get_module_base(SigScannerStaticData::m_modules_info[scan_target])); - uint8_t* module_end_address = static_cast(module_start_address + Platform::get_module_size(SigScannerStaticData::m_modules_info[scan_target])); + uint8_t* module_start_address = static_cast(Platform::get_module_base(&SigScannerStaticData::m_modules_info[scan_target])); + uint8_t* module_end_address = static_cast(module_start_address + Platform::get_module_size(&SigScannerStaticData::m_modules_info[scan_target])); scanner_work_thread(module_start_address, module_end_address, info, signature_container); diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp index 6fea0c84f..ee5eeb082 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp @@ -14,27 +14,32 @@ namespace RC { - auto SinglePassScanner::get_system_info() -> SystemInfo + auto ScanTargetArray::operator[](ScanTarget index) -> ModuleOS& { - return SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; + return array[static_cast(index)]; } + namespace Platform + { + auto SinglePassScanner::get_system_info() -> SystemInfo* + { + return &SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; + } - namespace Platform { - auto get_start_address(DLData &info) -> uint8_t* { - return info.base_address; + auto get_start_address(DLData *info) -> uint8_t* { + return info->base_address; } - auto get_end_address(DLData &info) -> uint8_t* { - return info.base_address + info.size; + auto get_end_address(DLData *info) -> uint8_t* { + return info->base_address + info.size; } - auto get_module_size(DLData &info) -> uint32_t { - return info.size; + auto get_module_size(DLData *info) -> uint32_t { + return info->size; } auto get_module_base(DLData &info) -> uint8_t* { - return info.base_address; + return info->base_address; } }; // namespace Platform diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp index 381ca5a4a..ba669e4a0 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp @@ -17,32 +17,39 @@ namespace RC { - auto SinglePassScanner::get_system_info() -> SystemInfo + auto ScanTargetArray::operator[](ScanTarget index) -> ModuleOS& { - SYSTEM_INFO info{}; - GetSystemInfo(&info); - return info; + return *std::bit_cast(&array[static_cast(index)]); } - namespace Platform { + + namespace Platform + { + auto get_system_info() -> SystemInfo* + { + static SYSTEM_INFO info{}; + GetSystemInfo(&info); + return &info; + } + // Get the start address of the system - auto get_start_address(SystemInfo &info) -> uint8_t* { - return static_cast(info.lpMinimumApplicationAddress); + auto get_start_address(SystemInfo *info) -> uint8_t* { + return static_cast(info->lpMinimumApplicationAddress); } // Get the end address of the system - auto get_end_address(SystemInfo &info) -> uint8_t* { - return static_cast(info.lpMaximumApplicationAddress); + auto get_end_address(SystemInfo *info) -> uint8_t* { + return static_cast(info->lpMaximumApplicationAddress); } // Get the size of the module - auto get_module_size(ModuleOS &info) -> size_t { - return info.SizeOfImage; + auto get_module_size(ModuleOS *info) -> uint32_t { + return info->SizeOfImage; } // Get the base address of the module - auto get_module_base(ModuleOS &info) -> uint8_t* { - return static_cast(info.lpBaseOfDll); + auto get_module_base(ModuleOS *info) -> uint8_t* { + return static_cast(info->lpBaseOfDll); } }; // namespace Platform @@ -106,17 +113,17 @@ namespace RC auto SinglePassScanner::scanner_work_thread_scalar(uint8_t* start_address, uint8_t* end_address, - SYSTEM_INFO& info, + SYSTEM_INFO* info, std::vector& signature_containers) -> void { ProfilerScope(); if (!start_address) { - start_address = static_cast(info.lpMinimumApplicationAddress); + start_address = static_cast(info->lpMinimumApplicationAddress); } if (!end_address) { - start_address = static_cast(info.lpMaximumApplicationAddress); + start_address = static_cast(info->lpMaximumApplicationAddress); } MEMORY_BASIC_INFORMATION memory_info{}; From 8b5b5a4069e723407d7a2c01d1d59820678919ec Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 03:18:54 -0600 Subject: [PATCH 065/213] fix pointers --- .../src/SinglePassSigScannerLinux.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp index ee5eeb082..c26def15d 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp @@ -21,7 +21,7 @@ namespace RC namespace Platform { - auto SinglePassScanner::get_system_info() -> SystemInfo* + auto get_system_info() -> SystemInfo* { return &SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; } @@ -31,14 +31,14 @@ namespace RC } auto get_end_address(DLData *info) -> uint8_t* { - return info->base_address + info.size; + return info->base_address + info->size; } auto get_module_size(DLData *info) -> uint32_t { return info->size; } - auto get_module_base(DLData &info) -> uint8_t* { + auto get_module_base(DLData *info) -> uint8_t* { return info->base_address; } }; // namespace Platform @@ -51,17 +51,17 @@ namespace RC // This function may have problem becasue we're not checking the memory region's permissions auto SinglePassScanner::scanner_work_thread_scalar(uint8_t* start_address, uint8_t* end_address, - DLData& info, + DLData* info, std::vector& signature_containers) -> void { ProfilerScope(); if (!start_address) { - start_address = static_cast(info.base_address); + start_address = Platform::get_start_address(info); } if (!end_address) { - end_address = static_cast(info.base_address + info.size); + end_address = Platform::get_end_address(info); } // TODO: Nasty nasty nasty. Come up with a better solution... wtf @@ -98,7 +98,7 @@ namespace RC // Loop everything for (uint8_t* i = start_address; i < end_address; ++i) { - auto addr = info.find_phdr(i); + auto addr = info->find_phdr(i); if (addr == std::make_tuple(nullptr, 0, 0)) { continue; From 2bc81be3dbfcddf06f893f9cd35fd125d8b4f30c Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 17:10:43 -0600 Subject: [PATCH 066/213] A tui that you can interact with... --- UE4SS/include/GUI/GUI.hpp | 16 +++ UE4SS/include/GUI/TUI.hpp | 39 ++++++ UE4SS/include/SettingsManager.hpp | 4 + UE4SS/include/UE4SSProgram.hpp | 3 + UE4SS/src/GUI/ConsoleOutputDevice.cpp | 2 +- UE4SS/src/GUI/Dumpers.cpp | 94 +++++++------- UE4SS/src/GUI/GUI.cpp | 41 ++++-- UE4SS/src/GUI/ImGuiUtility.cpp | 27 ++-- UE4SS/src/GUI/LiveView.cpp | 121 ++++++++++-------- UE4SS/src/GUI/SearcherWidget.cpp | 2 +- UE4SS/src/GUI/TUI.cpp | 113 ++++++++++++++++ UE4SS/src/GUI/UFunctionCallerWidget.cpp | 16 +-- UE4SS/src/SettingsManager.cpp | 6 +- UE4SS/src/UE4SSProgram.cpp | 3 +- .../Constructs/Views/EnumerateView.hpp | 79 ++++++++++++ deps/first/MProgram/include/ErrorObject.hpp | 4 +- 16 files changed, 434 insertions(+), 136 deletions(-) create mode 100644 UE4SS/include/GUI/TUI.hpp create mode 100644 UE4SS/src/GUI/TUI.cpp diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index 76026b6ec..b7fb9ace0 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -11,6 +11,12 @@ #include struct ImGuiSettingsHandler; +#ifdef LINUX +namespace ImGui { + static void BeginDisabled(bool disabled = true) {} + static void EndDisabled() {} +} +#endif namespace RC::GUI { @@ -18,13 +24,23 @@ namespace RC::GUI enum class GfxBackend { +#ifdef WIN32 DX11, GLFW3_OpenGL3, +#endif +#ifdef LINUX + TUI +#endif }; enum class OSBackend { +#ifdef WIN32 Windows, +#endif +#ifdef LINUX + TUI, +#endif }; struct WindowSize diff --git a/UE4SS/include/GUI/TUI.hpp b/UE4SS/include/GUI/TUI.hpp new file mode 100644 index 000000000..fc39efa7b --- /dev/null +++ b/UE4SS/include/GUI/TUI.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace RC::GUI +{ + class Backend_TUI : public OSBackendBase + { + public: + auto init() -> void override; + auto imgui_backend_newframe() -> void override; + auto create_window() -> void override; + auto exec_message_loop(bool* exit_requested) -> void override; + auto shutdown() -> void override; + auto cleanup() -> void override; + auto get_window_handle() -> void* override; + auto get_window_size() -> WindowSize override; + auto on_gfx_backend_set() -> void override; + }; + + class Backend_GfxTUI : public GfxBackendBase + { + public: + ~Backend_GfxTUI() = default; + + public: + auto init() -> void override; + auto imgui_backend_newframe() -> void override; + auto render(const float clear_color_with_alpha[4]) -> void override; + auto shutdown() -> void override; + auto cleanup() -> void override; + auto create_device() -> bool override; + auto cleanup_device() -> void override; + auto handle_window_resize(int64_t param_1, int64_t param_2) -> void override; + auto on_os_backend_set() -> void override; + auto get_window_size() -> WindowSize override; + auto exit_requested() -> bool override; + }; +} // namespace RC::GUI diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index e5dfd9724..608fd0b1d 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -65,7 +65,11 @@ namespace RC bool DebugConsoleVisible{true}; float DebugGUIFontScaling{1.0}; #ifdef HAS_GUI + #ifdef WIN32 GUI::GfxBackend GraphicsAPI{GUI::GfxBackend::GLFW3_OpenGL3}; + #else + GUI::GfxBackend GraphicsAPI{GUI::GfxBackend::TUI}; + #endif #endif int64_t LiveViewObjectsPerGroup{64 * 1024 / 2}; } Debug; diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index c1f1ccfd4..fcafdb21c 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -13,6 +13,7 @@ #include #ifdef HAS_GUI +#include #include #include #endif @@ -256,10 +257,12 @@ namespace RC { return ImGui::GetCurrentContext(); } + #ifdef WIN32 RC_UE4SS_API static auto get_current_imgui_allocator_functions(ImGuiMemAllocFunc* alloc_func, ImGuiMemFreeFunc* free_func, void** user_data) -> void { return ImGui::GetAllocatorFunctions(alloc_func, free_func, user_data); } + #endif #endif RC_UE4SS_API auto queue_event(EventCallable callable, void* data) -> void; RC_UE4SS_API auto is_queue_empty() -> bool; diff --git a/UE4SS/src/GUI/ConsoleOutputDevice.cpp b/UE4SS/src/GUI/ConsoleOutputDevice.cpp index b2ecb3c11..dd6ee6145 100644 --- a/UE4SS/src/GUI/ConsoleOutputDevice.cpp +++ b/UE4SS/src/GUI/ConsoleOutputDevice.cpp @@ -19,7 +19,7 @@ namespace RC::Output auto ConsoleDevice::receive_with_optional_arg(SystemStringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void { #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE - printf_s("ConsoleDevice received: %S", m_formatter(fmt).c_str()); + printf_s("ConsoleDevice received: " SystemStringPrint, m_formatter(fmt).c_str()); #else auto fmt_copy = SystemStringType{fmt}; if (fmt_copy.ends_with(STR('\n'))) diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index 7e21b5cac..6f3e4e3e4 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -82,9 +82,9 @@ namespace RC::GUI::Dumpers FMeshUVChannelInfo UVChannelData; }; - auto generate_root_component_csv(UObject* root_component) -> UEStringType + auto generate_root_component_csv(UObject* root_component) -> SystemStringType { - UEStringType root_actor_buffer{}; + SystemStringType root_actor_buffer{}; static auto location_property = root_component->GetPropertyByNameInChain(STR("RelativeLocation")); static auto rotation_property = root_component->GetPropertyByNameInChain(STR("RelativeRotation")); @@ -93,26 +93,26 @@ namespace RC::GUI::Dumpers auto location = root_component->GetValuePtrByPropertyNameInChain(STR("RelativeLocation")); FString location_string{}; location_property->ExportTextItem(location_string, location, nullptr, nullptr, 0); - root_actor_buffer.append(std::format(SYSSTR("\"{}\","), location_string.GetCharArray())); + root_actor_buffer.append(std::format(SYSSTR("\"{}\","), to_system(location_string.GetCharArray()))); auto rotation = root_component->GetValuePtrByPropertyNameInChain(STR("RelativeRotation")); FString rotation_string{}; rotation_property->ExportTextItem(rotation_string, rotation, nullptr, nullptr, 0); - root_actor_buffer.append(std::format(SYSSTR("\"{}\","), rotation_string.GetCharArray())); + root_actor_buffer.append(std::format(SYSSTR("\"{}\","), to_system(rotation_string.GetCharArray()))); auto scale = root_component->GetValuePtrByPropertyNameInChain(STR("RelativeScale3D")); FString scale_string{}; scale_property->ExportTextItem(scale_string, scale, nullptr, nullptr, 0); - root_actor_buffer.append(std::format(SYSSTR("\"{}\","), scale_string.GetCharArray())); + root_actor_buffer.append(std::format(SYSSTR("\"{}\","), to_system(scale_string.GetCharArray()))); return root_actor_buffer; } - static auto generate_actors_csv_file(UClass* dump_actor_class) -> UEStringType + static auto generate_actors_csv_file(UClass* dump_actor_class) -> SystemStringType { - UEStringType file_buffer{}; + SystemStringType file_buffer{}; - file_buffer.append(STR("---,Actor,Location,Rotation,Scale,Meshes\n")); + file_buffer.append(SYSSTR("---,Actor,Location,Rotation,Scale,Meshes\n")); size_t actor_count{}; FindObjectSearcher(dump_actor_class, AnySuperStruct::StaticClass()).ForEach([&](UObject* object) { @@ -129,7 +129,7 @@ namespace RC::GUI::Dumpers return LoopAction::Continue; } - UEStringType actor_buffer{}; + SystemStringType actor_buffer{}; actor_buffer.append(std::format(SYSSTR("Row_{},"), actor_count)); @@ -137,22 +137,22 @@ namespace RC::GUI::Dumpers static auto class_property = game_mode_base->GetPropertyByNameInChain(STR("GameStateClass")); FString actor_class_string{}; class_property->ExportTextItem(actor_class_string, &actor->GetClassPrivate(), nullptr, nullptr, 0); - actor_buffer.append(std::format(SYSSTR("{},"), actor_class_string.GetCharArray())); + actor_buffer.append(std::format(SYSSTR("{},"), to_system(actor_class_string.GetCharArray()))); // TODO: build system to handle other types of components - possibly including a way to specify which components to dump and which properties are important via a config file actor_buffer.append(generate_root_component_csv(*root_component)); - actor_buffer.append(STR("\"")); + actor_buffer.append(SYSSTR("\"")); static auto static_mesh_component_class = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.StaticMeshComponent")); const auto& static_mesh_components = actor->K2_GetComponentsByClass(static_mesh_component_class); if (static_mesh_components.Num() > 0) { - actor_buffer.append(STR("(")); + actor_buffer.append(SYSSTR("(")); for (auto [static_mesh_component_ptr, static_mesh_component_index] : static_mesh_components | views::enumerate) { const auto mesh = *static_mesh_component_ptr->GetValuePtrByPropertyNameInChain(STR("StaticMesh")); if (!mesh) { - Output::send(STR("SKIPPING COMPONENT! StaticMeshComponent '{}' has no mesh.\n"), + Output::send(SYSSTR("SKIPPING COMPONENT! StaticMeshComponent '{}' has no mesh.\n"), static_mesh_component_ptr->GetOuterPrivate()->GetName()); continue; } @@ -160,7 +160,7 @@ namespace RC::GUI::Dumpers static auto mesh_property = static_mesh_component_ptr->GetPropertyByNameInChain(STR("StaticMesh")); FString mesh_string{}; mesh_property->ExportTextItem(mesh_string, &mesh, nullptr, nullptr, 0); - actor_buffer.append(std::format(SYSSTR("(StaticMesh={}',"), mesh_string.GetCharArray())); + actor_buffer.append(std::format(SYSSTR("(StaticMesh={}',"), to_system(mesh_string.GetCharArray()))); auto materials_for_each_body = [&](const UObject* material_interface) { if (material_interface) @@ -169,7 +169,7 @@ namespace RC::GUI::Dumpers const auto material_type_space_location = material_full_name.find(STR(" ")); if (material_type_space_location == material_full_name.npos) { - Output::send(STR("SKIPPING MATERIAL! Was unable to find space in full material name in component: '{}'.\n"), + Output::send(SYSSTR("SKIPPING MATERIAL! Was unable to find space in full material name in component: '{}'.\n"), material_full_name); return; } @@ -181,9 +181,9 @@ namespace RC::GUI::Dumpers auto material_typeless_name = UEStringViewType{material_full_name.begin() + static_cast(material_type_space_location) + 1, material_full_name.end()}; - actor_buffer.append(std::format(SYSSTR("{}'"), material_interface->GetClassPrivate()->GetName())); - actor_buffer.append(std::format(SYSSTR("\"\"{}"), material_typeless_name)); - actor_buffer.append(STR("\"\"'")); + actor_buffer.append(std::format(SYSSTR("{}'"),to_system(material_interface->GetClassPrivate()->GetName()))); + actor_buffer.append(std::format(SYSSTR("\"\"{}"), to_system(material_typeless_name))); + actor_buffer.append(SYSSTR("\"\"'")); } }; @@ -192,18 +192,18 @@ namespace RC::GUI::Dumpers const auto materials = *mesh->GetValuePtrByPropertyName>(STR("StaticMaterials")); if (materials.GetData()) { - actor_buffer.append(STR("Materials=(")); + actor_buffer.append(SYSSTR("Materials=(")); } for (auto [material, material_index] : materials | views::enumerate) { materials_for_each_body(material.MaterialInterface); if (material_index + 1 < materials.Num()) { - actor_buffer.append(STR(",")); + actor_buffer.append(SYSSTR(",")); } else { - actor_buffer.append(STR(")")); + actor_buffer.append(SYSSTR(")")); } } } @@ -212,31 +212,31 @@ namespace RC::GUI::Dumpers const auto& materials = *mesh->GetValuePtrByPropertyName>(STR("StaticMaterials")); if (materials.GetData()) { - actor_buffer.append(STR("Materials=(")); + actor_buffer.append(SYSSTR("Materials=(")); } for (auto [material, material_index] : materials | views::enumerate) { materials_for_each_body(material.MaterialInterface); if (material_index + 1 < materials.Num()) { - actor_buffer.append(STR(",")); + actor_buffer.append(SYSSTR(",")); } else { - actor_buffer.append(STR(")")); + actor_buffer.append(SYSSTR(")")); } } } - actor_buffer.append(STR(")")); + actor_buffer.append(SYSSTR(")")); if (static_mesh_component_index + 1 < static_mesh_components.Num()) { - actor_buffer.append(STR(",")); + actor_buffer.append(SYSSTR(",")); } } - actor_buffer.append(STR(")")); + actor_buffer.append(SYSSTR(")")); } - actor_buffer.append(STR("\"\n")); + actor_buffer.append(SYSSTR("\"\n")); file_buffer.append(actor_buffer); ++actor_count; @@ -246,7 +246,7 @@ namespace RC::GUI::Dumpers return file_buffer; } - static auto generate_actors_json_file(UClass* class_to_dump) -> UEStringType + static auto generate_actors_json_file(UClass* class_to_dump) -> SystemStringType { auto global_json_array = JSON::Array{}; @@ -267,37 +267,37 @@ namespace RC::GUI::Dumpers auto& actor_json_object = global_json_array.new_object(); - actor_json_object.new_string(STR("Name"), std::format(SYSSTR("Row_{}"), actor_count)); + actor_json_object.new_string(SYSSTR("Name"), std::format(SYSSTR("Row_{}"), actor_count)); static auto game_mode_base = UObjectGlobals::FindFirstOf(STR("GameModeBase")); static auto class_property = game_mode_base->GetPropertyByNameInChain(STR("GameStateClass")); FString actor_class_string{}; class_property->ExportTextItem(actor_class_string, &actor->GetClassPrivate(), nullptr, nullptr, 0); - actor_json_object.new_string(STR("Actor"), std::format(SYSSTR("{}"), UEStringViewType{actor_class_string.GetCharArray()})); + actor_json_object.new_string(SYSSTR("Actor"), std::format(SYSSTR("{}"), to_system(actor_class_string.GetCharArray()))); - auto& root_component_json_object = actor_json_object.new_object(STR("RootComponent")); + auto& root_component_json_object = actor_json_object.new_object(SYSSTR("RootComponent")); FString root_component_class_string{}; class_property->ExportTextItem(root_component_class_string, &(*root_component)->GetClassPrivate(), nullptr, nullptr, 0); - root_component_json_object.new_string(STR("SceneComponentClass"), std::format(SYSSTR("{}"), UEStringViewType{root_component_class_string.GetCharArray()})); + root_component_json_object.new_string(SYSSTR("SceneComponentClass"), std::format(SYSSTR("{}"), to_system(root_component_class_string.GetCharArray()))); - auto& location_json_object = root_component_json_object.new_object(STR("Location")); + auto& location_json_object = root_component_json_object.new_object(SYSSTR("Location")); auto location = (*root_component)->GetValuePtrByPropertyNameInChain(STR("RelativeLocation")); - location_json_object.new_number(STR("X"), location->X()); - location_json_object.new_number(STR("Y"), location->Y()); - location_json_object.new_number(STR("Z"), location->Z()); + location_json_object.new_number(SYSSTR("X"), location->X()); + location_json_object.new_number(SYSSTR("Y"), location->Y()); + location_json_object.new_number(SYSSTR("Z"), location->Z()); - auto& rotation_json_object = root_component_json_object.new_object(STR("Rotation")); + auto& rotation_json_object = root_component_json_object.new_object(SYSSTR("Rotation")); auto rotation = (*root_component)->GetValuePtrByPropertyNameInChain(STR("RelativeRotation")); - rotation_json_object.new_number(STR("Pitch"), rotation->GetPitch()); - rotation_json_object.new_number(STR("Yaw"), rotation->GetYaw()); - rotation_json_object.new_number(STR("Roll"), rotation->GetRoll()); + rotation_json_object.new_number(SYSSTR("Pitch"), rotation->GetPitch()); + rotation_json_object.new_number(SYSSTR("Yaw"), rotation->GetYaw()); + rotation_json_object.new_number(SYSSTR("Roll"), rotation->GetRoll()); - auto& scale_json_object = root_component_json_object.new_object(STR("Scale")); + auto& scale_json_object = root_component_json_object.new_object(SYSSTR("Scale")); auto scale = (*root_component)->GetValuePtrByPropertyNameInChain(STR("RelativeScale3D")); - scale_json_object.new_number(STR("X"), scale->X()); - scale_json_object.new_number(STR("Y"), scale->Y()); - scale_json_object.new_number(STR("Z"), scale->Z()); + scale_json_object.new_number(SYSSTR("X"), scale->X()); + scale_json_object.new_number(SYSSTR("Y"), scale->Y()); + scale_json_object.new_number(SYSSTR("Z"), scale->Z()); ++actor_count; return LoopAction::Continue; @@ -313,7 +313,7 @@ namespace RC::GUI::Dumpers { Output::send(SYSSTR("Dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); static auto dump_actor_class = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.StaticMeshActor")); - UEStringType file_buffer{}; + SystemStringType file_buffer{}; file_buffer.append(generate_actors_csv_file(dump_actor_class)); auto file = File::open(std::format(SYSSTR("{}\\{}-ue4ss_static_mesh_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), @@ -327,7 +327,7 @@ namespace RC::GUI::Dumpers void call_generate_all_actor_file() { Output::send(SYSSTR("Dumping CSV of all loaded actor types, positions and mesh properties\n")); - UEStringType file_buffer{}; + SystemStringType file_buffer{}; file_buffer.append(generate_actors_csv_file(AActor::StaticClass())); auto file = File::open(std::format(SYSSTR("{}\\{}-ue4ss_actor_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), File::OpenFor::Writing, diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index f0021d9f2..00b35265e 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -6,10 +6,15 @@ #include #include #include -#include #include -#include + +#ifdef WIN32 #include +#include +#include +#else +#include +#endif #include #include @@ -17,12 +22,22 @@ #undef TEXT #endif +#ifdef WIN32 #include "Roboto.hpp" #include "FaSolid900.hpp" -#include #include -#include +#else // LINUX +#define ICON_FA_TERMINAL +#define ICON_FA_ARCHIVE +#define ICON_FA_SYNC +#define ICON_FA_FILE_ALT +#define ICON_FA_EYE +#define ICON_FA_PUZZLE_PIECE +#endif + +#include +#include namespace RC::GUI { ImColor g_imgui_bg_color{0.22f, 0.22f, 0.22f, 1.00f}; @@ -93,8 +108,10 @@ namespace RC::GUI m_event_thread_busy = true; UE4SSProgram::get_program().queue_event( [](void* data) { - UE4SSProgram::dump_all_objects_and_properties(UE4SSProgram::get_program().get_object_dumper_output_directory() + STR("\\") + - UE4SSProgram::m_object_dumper_file_name); + UE4SSProgram::dump_all_objects_and_properties( + to_system( std::filesystem::path { UE4SSProgram::get_program().get_object_dumper_output_directory() } + / UE4SSProgram::m_object_dumper_file_name) + ); static_cast(data)->m_event_thread_busy = false; }, this); @@ -481,7 +498,7 @@ namespace RC::GUI io.Fonts->Clear(); float base_font_size = 14 * UE4SSProgram::settings_manager.Debug.DebugGUIFontScaling; - +#ifdef WIN32 ImFontConfig font_cfg; font_cfg.FontDataOwnedByAtlas = false; // if true it will try to free memory and fail io.Fonts->AddFontFromMemoryTTF(Roboto, sizeof(Roboto), base_font_size, &font_cfg); @@ -494,7 +511,7 @@ namespace RC::GUI icons_cfg.PixelSnapH = true; icons_cfg.GlyphMinAdvanceX = icon_font_size; io.Fonts->AddFontFromMemoryTTF(FaSolid900, sizeof(FaSolid900), icon_font_size, &icons_cfg, icons_ranges); - +#endif m_os_backend->init(); m_gfx_backend->init(); @@ -512,6 +529,7 @@ namespace RC::GUI { switch (backend) { + #ifdef WIN32 case GfxBackend::DX11: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); @@ -520,6 +538,11 @@ namespace RC::GUI m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); break; + #else + case GfxBackend::TUI: + m_gfx_backend = std::make_unique(); + m_os_backend = std::make_unique(); + #endif } m_gfx_backend->set_os_backend(m_os_backend.get()); @@ -550,7 +573,7 @@ namespace RC::GUI if (!debugging_ui) { - Output::send(STR("Could not start GUI render thread because 'debugging_ui' was nullptr.")); + Output::send(SYSSTR("Could not start GUI render thread because 'debugging_ui' was nullptr.")); return; } debugging_ui->setup(std::move(stop_token)); diff --git a/UE4SS/src/GUI/ImGuiUtility.cpp b/UE4SS/src/GUI/ImGuiUtility.cpp index 858516299..78c9b8ebf 100644 --- a/UE4SS/src/GUI/ImGuiUtility.cpp +++ b/UE4SS/src/GUI/ImGuiUtility.cpp @@ -14,8 +14,13 @@ namespace RC::GUI // NOTE: This function makes use of 'imgui_internal.h'. // As a result, this function is prone to break if you update Imgui. ImGuiContext& g = *GImGui; + #ifdef WIN32 const char* child_window_name = NULL; ImFormatStringToTempBuffer(&child_window_name, NULL, "%s/%s_%08X", g.CurrentWindow->Name, label, ImGui::GetID(label)); + #else + static char child_window_name[1024]; + sprintf(child_window_name, "%s/%s_%08X", g.CurrentWindow->Name, label, ImGui::GetID(label)); + #endif ImGuiWindow* child_window = ImGui::FindWindowByName(child_window_name); if (child_window) { @@ -98,12 +103,12 @@ namespace RC::GUI static auto dump_json_integer_value(const JSON::Number& element) -> void; static int indent_level{}; - static auto indent() -> std::wstring + static auto indent() -> SystemStringType { - std::wstring indents{}; + SystemStringType indents{}; for (int i = 0; i < indent_level; ++i) { - indents.append(STR(" ")); + indents.append(SYSSTR(" ")); } return indents; } @@ -150,7 +155,7 @@ namespace RC::GUI static auto dump_json_object_pair(const JSON::TypedKeyValuePair element) -> void { - Output::send(STR("{}Object: {}\n"), indent(), element.key); + Output::send(SYSSTR("{}Object: {}\n"), indent(), element.key); const auto& object = element.value->get(); for (const auto& [_, inner_element] : object) @@ -163,7 +168,7 @@ namespace RC::GUI static auto dump_json_array_pair(const JSON::TypedKeyValuePair element) -> void { - Output::send(STR("{}Array: {}\n"), indent(), element.key); + Output::send(SYSSTR("{}Array: {}\n"), indent(), element.key); const auto& array = element.value->get(); for (const auto& inner_element : array) @@ -176,18 +181,18 @@ namespace RC::GUI static auto dump_json_string_pair(const JSON::TypedKeyValuePair element) -> void { - Output::send(STR("{}String: {} == {}\n"), indent(), element.key, element.value->get_view()); + Output::send(SYSSTR("{}String: {} == {}\n"), indent(), element.key, element.value->get_view()); } static auto dump_json_integer_pair(const JSON::TypedKeyValuePair element) -> void { - Output::send(STR("{}Integer: {} == {}\n"), indent(), element.key, element.value->get()); + Output::send(SYSSTR("{}Integer: {} == {}\n"), indent(), element.key, element.value->get()); } static auto dump_json_object_value(const JSON::Object& element) -> void { ++indent_level; - Output::send(STR("{}Object \n"), indent()); + Output::send(SYSSTR("{}Object \n"), indent()); const auto& object = element.get(); for (const auto& [_, inner_element] : object) @@ -203,7 +208,7 @@ namespace RC::GUI static auto dump_json_array_value(const JSON::Array& element) -> void { ++indent_level; - Output::send(STR("{}Array \n"), indent()); + Output::send(SYSSTR("{}Array \n"), indent()); const auto& array = element.get(); for (const auto& inner_element : array) @@ -218,11 +223,11 @@ namespace RC::GUI static auto dump_json_string_value(const JSON::String& element) -> void { - Output::send(STR("{}String: {}\n"), indent(), element.get_view()); + Output::send(SYSSTR("{}String: {}\n"), indent(), element.get_view()); } static auto dump_json_integer_value(const JSON::Number& element) -> void { - Output::send(STR("{}Integer: {}\n"), indent(), element.get()); + Output::send(SYSSTR("{}Integer: {}\n"), indent(), element.get()); } } // namespace RC::GUI diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 6b3ac426b..98161d44c 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -46,9 +47,19 @@ #include #include #include -#include #include +#ifdef WIN32 +#include +#else +#define ICON_FA_ANGLE_DOUBLE_LEFT "<<" +#define ICON_FA_ANGLE_DOUBLE_RIGHT ">>" +#define ICON_FA_BAN +#define ICON_FA_COPY +#define ICON_FA_EYE +#define ICON_FA_SEARCH +#endif + #undef max #undef min @@ -564,16 +575,16 @@ namespace RC::GUI auto object_full_name = watch.container->GetFullName(); auto object_type_space_location = object_full_name.find(STR(" ")); auto object_typeless_name = UEStringType{object_full_name.begin() + object_type_space_location + 1, object_full_name.end()}; - json_object->new_string(STR("AcquisitionID"), object_typeless_name); + json_object->new_string(SYSSTR("AcquisitionID"), to_system(object_typeless_name)); break; } case LiveView::Watch::AcquisitionMethod::FindFirstOf: - json_object->new_string(STR("AcquisitionID"), watch.container->GetClassPrivate()->GetName()); + json_object->new_string(SYSSTR("AcquisitionID"), to_system(watch.container->GetClassPrivate()->GetName())); break; } - json_object->new_string(STR("PropertyName"), watch.property_name); - json_object->new_number(STR("AcquisitionMethod"), static_cast(watch.acquisition_method)); - json_object->new_number(STR("WatchType"), + json_object->new_string(SYSSTR("PropertyName"), to_system(watch.property_name)); + json_object->new_number(SYSSTR("AcquisitionMethod"), static_cast(watch.acquisition_method)); + json_object->new_number(SYSSTR("WatchType"), watch.container->IsA() ? static_cast(LiveView::Watch::Type::Function) : static_cast(LiveView::Watch::Type::Property)); return json_object; @@ -593,18 +604,18 @@ namespace RC::GUI } auto json_global_object = JSON::Parser::parse(json_file_contents); - const auto& elements = json_global_object->get(STR("Watches")); + const auto& elements = json_global_object->get(SYSSTR("Watches")); elements.for_each([](JSON::Value& element) { if (!element.is()) { throw std::runtime_error{"Invalid watch in 'watches.meta.json'"}; } auto& json_watch_object = *element.as(); - auto acquisition_id = json_watch_object.get(STR("AcquisitionID")).get_view(); - auto property_name = json_watch_object.get(STR("PropertyName")).get_view(); + auto acquisition_id = to_ue(json_watch_object.get(SYSSTR("AcquisitionID")).get_view()); + auto property_name = to_ue(json_watch_object.get(SYSSTR("PropertyName")).get_view()); auto acquisition_method = - static_cast(json_watch_object.get(STR("AcquisitionMethod")).get()); - auto watch_type = static_cast(json_watch_object.get(STR("WatchType")).get()); + static_cast(json_watch_object.get(SYSSTR("AcquisitionMethod")).get()); + auto watch_type = static_cast(json_watch_object.get(SYSSTR("WatchType")).get()); UObject* object{}; switch (acquisition_method) @@ -661,7 +672,7 @@ namespace RC::GUI static auto internal_save_watches_to_disk() -> void { auto json = JSON::Object{}; - auto& json_uobjects = json.new_array(STR("Watches")); + auto& json_uobjects = json.new_array(SYSSTR("Watches")); { std::lock_guard lock{LiveView::Watch::s_watch_lock}; @@ -715,8 +726,8 @@ namespace RC::GUI LiveView::Watch::Watch(UEStringType&& object_name, UEStringType&& property_name) : object_name(object_name), property_name(property_name) { auto& file_device = output.get_device(); - file_device.set_file_name_and_path(UEStringType{UE4SSProgram::get_program().get_working_directory()} + - std::format(SYSSTR("\\watches\\ue4ss_watch_{}_{}.txt"), object_name, property_name)); + file_device.set_file_name_and_path(to_system_string(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} + / "watches" / std::format("ue4ss_watch_{}_{}.txt", to_string(object_name), to_string(property_name)))); file_device.set_formatter([](SystemStringViewType string) -> SystemStringType { const auto when_as_string = std::format(SYSSTR("{:%Y-%m-%d %H:%M:%S}"), std::chrono::system_clock::now()); return std::format(SYSSTR("[{}] {}"), when_as_string, string); @@ -1719,7 +1730,7 @@ namespace RC::GUI { if (ImGui::IsItemClicked()) { - printf_s("Clicked: %S\n", ustruct->GetFullName().c_str()); + printf_s("Clicked: " SystemStringPrint "\n", to_system(ustruct->GetFullName()).c_str()); select_object(0, ustruct->GetObjectItem(), ustruct, AffectsHistory::Yes); } } @@ -1958,13 +1969,13 @@ namespace RC::GUI } auto value_as_string = Unreal::UKismetNodeHelperLibrary::GetEnumeratorUserFriendlyName(uenum, enum_index); ImGui::SameLine(); - ImGui::Text("%S", value_as_string.c_str()); + ImGui::Text(SystemStringPrint, to_system(value_as_string).c_str()); render_property_value_context_menu(); } else { ImGui::SameLine(); - ImGui::Text("%S", property_text.GetCharArray()); + ImGui::Text(SystemStringPrint, to_system_string(property_text.GetCharArray()).c_str()); render_property_value_context_menu(); } @@ -1976,7 +1987,7 @@ namespace RC::GUI if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%S", property->GetFullName().c_str()); + ImGui::Text(SystemStringPrint, to_system_string(property->GetFullName()).c_str()); ImGui::Separator(); ImGui::Text("Offset: 0x%X", property->GetOffset_Internal()); ImGui::Text("Size: 0x%X", property->GetSize()); @@ -1989,7 +2000,7 @@ namespace RC::GUI { parent_name = obj ? obj->GetName() : STR("None"); } - auto edit_property_value_modal_name = to_string(std::format(SYSSTR("Edit value of property: {}->{}"), parent_name, property->GetName())); + auto edit_property_value_modal_name = to_string(std::format(SYSSTR("Edit value of property: {}->{}"), to_system(parent_name), to_system(property->GetName()))); if (open_edit_value_popup) { @@ -2011,7 +2022,7 @@ namespace RC::GUI if (ImGui::Button("Apply")) { FOutputDevice placeholder_device{}; - if (!property->ImportText(to_wstring(m_current_property_value_buffer).c_str(), property->ContainerPtrToValuePtr(container), NULL, obj, &placeholder_device)) + if (!property->ImportText(to_ue(m_current_property_value_buffer).c_str(), property->ContainerPtrToValuePtr(container), NULL, obj, &placeholder_device)) { m_modal_edit_property_value_error_unable_to_edit = true; ImGui::OpenPopup("UnableToSetNewPropertyValueError"); @@ -2078,8 +2089,8 @@ namespace RC::GUI ++index; ImGui::TableNextColumn(); - ImGui::Text("%S", enum_name.c_str()); - if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("context-menu-{}"), enum_name)).c_str())) + ImGui::Text(SystemStringPrint, to_system(enum_name).c_str()); + if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("context-menu-{}"), to_system(enum_name))).c_str())) { if (ImGui::MenuItem("Copy name")) { @@ -2094,11 +2105,11 @@ namespace RC::GUI } ImGui::TableNextColumn(); - ImGui::Text("%S", enum_friendly_name.c_str()); + ImGui::Text(SystemStringPrint, to_system(enum_friendly_name).c_str()); ImGui::TableNextColumn(); ImGui::Text("%lld", name.Value); - if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("context-menu-{}-{}"), enum_name, name.Value)).c_str())) + if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("context-menu-{}-{}"), to_system(enum_name), to_system(name.Value))).c_str())) { if (ImGui::MenuItem("Copy value")) { @@ -2113,7 +2124,7 @@ namespace RC::GUI } ImGui::TableNextColumn(); - ImGui::PushID(to_string(std::format(SYSSTR("button_add_{}"), enum_name)).c_str()); + ImGui::PushID(to_string(std::format(SYSSTR("button_add_{}"), to_system(enum_name))).c_str()); if (ImGui::Button("+")) { open_add_name_popup = true; @@ -2121,18 +2132,18 @@ namespace RC::GUI } ImGui::PopID(); ImGui::SameLine(); - ImGui::PushID(to_string(std::format(SYSSTR("button_remove_{}"), enum_name)).c_str()); + ImGui::PushID(to_string(std::format(SYSSTR("button_remove_{}"), to_system(enum_name))).c_str()); if (ImGui::Button("-")) { uenum->RemoveFromNamesAt(index, 1); } ImGui::PopID(); - std::string edit_enum_name_modal_name = to_string(std::format(SYSSTR("Edit enum name for: {}"), name.Key.ToString())); + std::string edit_enum_name_modal_name = to_string(std::format(SYSSTR("Edit enum name for: {}"), to_system(name.Key.ToString()))); - std::string edit_enum_value_modal_name = to_string(std::format(SYSSTR("Edit enum value for: {}"), name.Key.ToString())); + std::string edit_enum_value_modal_name = to_string(std::format(SYSSTR("Edit enum value for: {}"), to_system(name.Key.ToString()))); - std::string add_enum_name_modal_name = to_string(std::format(SYSSTR("Enter new enum name after: {}"), name.Key.ToString())); + std::string add_enum_name_modal_name = to_string(std::format(SYSSTR("Enter new enum name after: {}"), to_system(name.Key.ToString()))); if (open_edit_name_popup) { @@ -2179,7 +2190,7 @@ namespace RC::GUI if (ImGui::Button("Apply")) { FOutputDevice placeholder_device{}; - UEStringType new_name = to_wstring(m_current_property_value_buffer); + UEStringType new_name = to_ue(m_current_property_value_buffer); FName new_key = FName(new_name, FNAME_Add); uenum->EditNameAt(index, new_key); if (uenum->GetEnumNames()[index].Key.ToString() != new_name) @@ -2263,7 +2274,7 @@ namespace RC::GUI if (ImGui::Button("Apply")) { FOutputDevice placeholder_device{}; - UEStringType new_name = to_wstring(m_current_property_value_buffer); + UEStringType new_name = to_ue(m_current_property_value_buffer); FName new_key = FName(new_name, FNAME_Add); int64 value = names[index].Value; @@ -2540,7 +2551,7 @@ namespace RC::GUI ImGui::EndPopup(); } ImGui::Text("ClassPrivate: %s", to_string(object->GetClassPrivate()->GetName()).c_str()); - ImGui::Text("Path: %S", object->GetPathName().c_str()); + ImGui::Text("Path: " SystemStringPrint, to_system(object->GetPathName()).c_str()); render_flags(object, "ObjectFlags"); if (auto as_class = Cast(object); as_class) { @@ -2584,7 +2595,7 @@ namespace RC::GUI auto supers_super = *supers_super_it; super_size -= supers_super->GetPropertiesSize(); } - ImGui::Text("%S: 0x%X (0x%X)", super->GetName().c_str(), super_size, super->GetPropertiesSize()); + ImGui::Text(SystemStringPrint ": 0x%X (0x%X)", to_system(super->GetName()).c_str(), super_size, super->GetPropertiesSize()); } ImGui::Unindent(); @@ -2614,7 +2625,7 @@ namespace RC::GUI bool tried_to_open_nullptr_property{}; auto property_full_name = property->GetFullName(); - ImGui::Text("Selected: %S", property->GetName().c_str()); + ImGui::Text("Selected: " SystemStringPrint , to_system(property->GetName()).c_str()); ImGui::Text("Address: %016llX", std::bit_cast(property)); if (ImGui::BeginPopupContextItem(to_string(property_full_name).c_str())) { @@ -2624,8 +2635,8 @@ namespace RC::GUI } ImGui::EndPopup(); } - ImGui::Text("Class: %S", property->GetClass().GetName().c_str()); - ImGui::Text("Path: %S", property->GetPathName().c_str()); + ImGui::Text("Class: " SystemStringPrint, to_system(property->GetClass().GetName()).c_str()); + ImGui::Text("Path: " SystemStringPrint, to_system(property->GetPathName()).c_str()); ImGui::Separator(); @@ -2689,7 +2700,7 @@ namespace RC::GUI ImGui::Unindent(); ImGui::Text("RepIndex: %i (0x%X)", property->GetRepIndex(), property->GetRepIndex()); ImGui::Text("OffsetInternal: %i (0x%X)", property->GetOffset_Internal(), property->GetOffset_Internal()); - ImGui::Text("RepNotifyFunc: %S", property->GetRepNotifyFunc().ToString().c_str()); + ImGui::Text("RepNotifyFunc: " SystemStringPrint, to_system(property->GetRepNotifyFunc().ToString()).c_str()); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); @@ -2698,7 +2709,7 @@ namespace RC::GUI } auto render_property_pointer = [](std::string_view pointer_name, FProperty* property) { - ImGui::Text("%s: %p %S", pointer_name.data(), property, property ? property->GetFullName().c_str() : STR("None")); + ImGui::Text("%s: %p " SystemStringPrint, pointer_name.data(), property, property ? to_system(property->GetFullName()).c_str() : SYSSTR("None")); return property; }; int go_to_property_menu_count{}; @@ -2909,12 +2920,12 @@ namespace RC::GUI watch.property_value = std::move(live_value_string); - const auto when_as_string = std::format(SYSSTR("{:%H:%M:%S}"), std::chrono::system_clock::now()); - watch.history.append(to_string(when_as_string + STR(" ") + watch.property_value + STR("\n"))); + const auto when_as_string = std::format("{:%H:%M:%S}", std::chrono::system_clock::now()); + watch.history.append(when_as_string + " " + to_string(watch.property_value) + "\n"); if (watch.write_to_file) { - watch.output.send(STR("{}\n"), watch.property_value); + watch.output.send(SYSSTR("{}\n"), watch.property_value); } } @@ -2946,11 +2957,11 @@ namespace RC::GUI auto num_params = function->GetNumParms(); const auto when_as_string = std::format(SYSSTR("{:%H:%M:%S}"), std::chrono::system_clock::now()); - UEStringType buffer{std::format(SYSSTR("Received call @ {}.\n"), when_as_string)}; + auto buffer { std::format(SYSSTR("Received call @ {}.\n"), when_as_string)}; - buffer.append(std::format(SYSSTR(" Context:\n {}\n"), context.Context->GetFullName())); + buffer.append(std::format(SYSSTR(" Context:\n {}\n"), to_system(context.Context->GetFullName()))); - buffer.append(STR(" Locals:\n")); + buffer.append(SYSSTR(" Locals:\n")); bool has_local_params{}; for (const auto& param : function->ForEachProperty()) { @@ -2962,15 +2973,15 @@ namespace RC::GUI FString param_text{}; auto container_ptr = param->ContainerPtrToValuePtr(context.TheStack.Locals()); param->ExportTextItem(param_text, container_ptr, container_ptr, std::bit_cast(function), NULL); - buffer.append(std::format(SYSSTR(" {} = {}\n"), param->GetName(), param_text.GetCharArray())); + buffer.append(std::format(SYSSTR(" {} = {}\n"), to_system(param->GetName()), to_system(param_text.GetCharArray()))); } if (!has_local_params) { - buffer.append(STR(" \n")); + buffer.append(SYSSTR(" \n")); } bool has_out_params{}; - buffer.append(STR(" Out:\n")); + buffer.append(SYSSTR(" Out:\n")); for (const auto& param : function->ForEachProperty()) { if (param->HasAnyPropertyFlags(CPF_ReturnParm)) @@ -2985,28 +2996,28 @@ namespace RC::GUI FString param_text{}; auto container_ptr = FindOutParamValueAddress(context.TheStack, param); param->ExportTextItem(param_text, container_ptr, container_ptr, std::bit_cast(function), NULL); - buffer.append(std::format(SYSSTR(" {} = {}\n"), param->GetName(), param_text.GetCharArray())); + buffer.append(std::format(SYSSTR(" {} = {}\n"), to_system(param->GetName()), to_system(param_text.GetCharArray()))); } if (!has_out_params) { - buffer.append(STR(" \n")); + buffer.append(SYSSTR(" \n")); } - buffer.append(STR(" ReturnValue\n")); + buffer.append(SYSSTR(" ReturnValue\n")); auto return_property = function->GetReturnProperty(); if (return_property) { FString return_property_text{}; auto container_ptr = context.RESULT_DECL; return_property->ExportTextItem(return_property_text, container_ptr, container_ptr, std::bit_cast(function), NULL); - buffer.append(std::format(SYSSTR(" {}"), return_property_text.GetCharArray())); + buffer.append(std::format(SYSSTR(" {}"), to_system(return_property_text.GetCharArray()))); } else { - buffer.append(STR(" ")); + buffer.append(SYSSTR(" ")); } - buffer.append(STR("\n\n")); + buffer.append(SYSSTR("\n\n")); watch.history.append(to_string(buffer)); if (watch.write_to_file) @@ -3417,7 +3428,7 @@ namespace RC::GUI // Remember to update text width calculations for the last ImGui::PushItemWidth call if this text gets updated. if (ImGui::Button(ICON_FA_COPY " Copy search result")) { - UEStringType result{}; + SystemStringType result{}; auto is_below_425 = Version::IsBelow(4, 25); for (const auto& search_result : s_name_search_results) { @@ -3615,7 +3626,7 @@ namespace RC::GUI ImGui::PopStyleVar(); ImGui::TableNextColumn(); - ImGui::Text("%S.%S", watch.object_name.c_str(), watch.property_name.c_str()); + ImGui::Text(SystemStringPrint "." SystemStringPrint, to_system(watch.object_name).c_str(), to_system(watch.property_name).c_str()); if (watch.show_history) { ImGui::PushID(std::format("history_{}", watch.hash).c_str()); diff --git a/UE4SS/src/GUI/SearcherWidget.cpp b/UE4SS/src/GUI/SearcherWidget.cpp index 214a68a92..2249d68f0 100644 --- a/UE4SS/src/GUI/SearcherWidget.cpp +++ b/UE4SS/src/GUI/SearcherWidget.cpp @@ -1,7 +1,7 @@ #include #include - +#define strncpy_s(dest, destsz, src, count) strncpy((dest), (src), (((count) < (destsz)) ? (count) : (destsz))) namespace RC::GUI { SearcherWidget::SearcherWidget(SearchModeChangedCallback ufunction_caller_search_mode_changed_callback, diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/TUI.cpp new file mode 100644 index 000000000..35596b7f9 --- /dev/null +++ b/UE4SS/src/GUI/TUI.cpp @@ -0,0 +1,113 @@ +#include + +#include + +#include +#include + +#include + +namespace RC::GUI +{ + static ImTui::TScreen * g_screen = nullptr; + + void Backend_TUI::init() { + //fprintf(stderr, "Backend_TUI::init\n"); + g_screen = ImTui_ImplNcurses_Init(true); + + // disable stderr + freopen("/dev/null", "w", stderr); + + atexit([]() { + // ensure that the screen is destroyed + ImTui_ImplNcurses_Shutdown(); + g_screen = nullptr; + }); + } + + void Backend_TUI::imgui_backend_newframe() { + //fprintf(stderr, "Backend_TUI::imgui_backend_newframe\n"); + ImTui_ImplNcurses_NewFrame(); + } + + void Backend_TUI::create_window() { + // Do nothing + } + + void Backend_TUI::exec_message_loop(bool* exit_requested) { + ImTui_ImplNcurses_ProcessEvent(); + *exit_requested = false; + } + + void Backend_TUI::shutdown() { + ImTui_ImplNcurses_Shutdown(); + g_screen = nullptr; + } + + void Backend_TUI::cleanup() { + // Do nothing + } + + void* Backend_TUI::get_window_handle() { + return g_screen; + } + + WindowSize Backend_TUI::get_window_size() { + if (g_screen) { + return {g_screen->nx, g_screen->ny}; + } else { + return {0, 0}; + } + } + + void Backend_TUI::on_gfx_backend_set() { + // Do nothing + } + + void Backend_GfxTUI::init() { + ImTui_ImplText_Init(); + } + + void Backend_GfxTUI::imgui_backend_newframe() { + ImTui_ImplText_NewFrame(); + } + + void Backend_GfxTUI::render(const float clear_color_with_alpha[4]) { + ImTui_ImplText_RenderDrawData(ImGui::GetDrawData(), g_screen); + ImTui_ImplNcurses_DrawScreen(); + } + + void Backend_GfxTUI::shutdown() { + ImTui_ImplText_Shutdown(); + setvbuf(stdout, NULL, _IOLBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); + } + + void Backend_GfxTUI::cleanup() { + // Do nothing + } + + bool Backend_GfxTUI::create_device() { + return true; + } + + void Backend_GfxTUI::cleanup_device() { + // Do nothing + } + + void Backend_GfxTUI::handle_window_resize(int64_t param_1, int64_t param_2) { + // Do nothing + } + + void Backend_GfxTUI::on_os_backend_set() { + // Do nothing + } + + WindowSize Backend_GfxTUI::get_window_size() { + return {g_screen->nx, g_screen->ny}; + } + + bool Backend_GfxTUI::exit_requested() { + return false; + } +}; // namespace RC::GUI diff --git a/UE4SS/src/GUI/UFunctionCallerWidget.cpp b/UE4SS/src/GUI/UFunctionCallerWidget.cpp index 4d1bef2ea..7a08ff14f 100644 --- a/UE4SS/src/GUI/UFunctionCallerWidget.cpp +++ b/UE4SS/src/GUI/UFunctionCallerWidget.cpp @@ -142,7 +142,7 @@ namespace RC::GUI static bool s_do_call{}; static UObject* s_instance{}; - static UEStringType s_cmd{}; + static SystemStringType s_cmd{}; static FOutputDevice s_ar{}; static UFunction* s_function{}; static UObject* s_executor{}; @@ -154,7 +154,7 @@ namespace RC::GUI auto& function_flags = s_function->GetFunctionFlags(); function_flags |= FUNC_Exec; Output::send(SYSSTR("Processing command: {}\n"), s_cmd); - bool call_succeeded = s_instance->ProcessConsoleExec(s_cmd.c_str(), s_ar, s_executor); + bool call_succeeded = s_instance->ProcessConsoleExec(to_ue(s_cmd).c_str(), s_ar, s_executor); Output::send(SYSSTR("call_succeeded: {}\n"), call_succeeded); function_flags &= ~FUNC_Exec; } @@ -170,7 +170,7 @@ namespace RC::GUI auto cmd = std::format(SYSSTR("{}"), to_system(function->GetName())); for (const auto& param : m_params_for_selected_function) { - cmd.append(std::format(SYSSTR(" {}"), to_wstring(param.value_from_ui))); + cmd.append(std::format(SYSSTR(" {}"), to_system(param.value_from_ui))); } Output::send(SYSSTR("Queueing command: {}\n"), cmd); @@ -226,23 +226,23 @@ namespace RC::GUI { if (auto as_struct_property = CastField(param.unreal_param); as_struct_property) { - ImGui::Text("%S (%S)", param.unreal_param->GetClass().GetName().c_str(), as_struct_property->GetStruct()->GetName().c_str()); + ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_struct_property->GetStruct()->GetName()).c_str()); } else if (auto as_array_property = CastField(param.unreal_param); as_array_property) { - ImGui::Text("%S (%S)", param.unreal_param->GetClass().GetName().c_str(), as_array_property->GetInner()->GetName().c_str()); + ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_array_property->GetInner()->GetName()).c_str()); } else if (auto as_object_property = CastField(param.unreal_param); as_object_property) { - ImGui::Text("%S (%S)", param.unreal_param->GetClass().GetName().c_str(), as_object_property->GetPropertyClass()->GetName().c_str()); + ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_object_property->GetPropertyClass()->GetName()).c_str()); } else if (auto as_class_property = CastField(param.unreal_param); as_class_property) { - ImGui::Text("%S (%S)", param.unreal_param->GetClass().GetName().c_str(), as_class_property->GetMetaClass()->GetName().c_str()); + ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_class_property->GetMetaClass()->GetName()).c_str()); } else { - ImGui::Text("%S", param.unreal_param->GetClass().GetName().c_str()); + ImGui::Text(SystemStringPrint, to_system(param.unreal_param->GetClass().GetName()).c_str()); } } diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index 107815087..f9752440c 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -83,8 +83,9 @@ namespace RC REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) REGISTER_FLOAT_SETTING(Debug.DebugGUIFontScaling, section_debug, GuiConsoleFontScaling) #ifdef HAS_GUI - UEStringType graphics_api_string{}; + SystemStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) + #ifdef WIN32 if (String::iequal(graphics_api_string, SYSSTR("DX11")) || String::iequal(graphics_api_string, SYSSTR("D3D11"))) { Debug.GraphicsAPI = GUI::GfxBackend::DX11; @@ -93,6 +94,9 @@ namespace RC { Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; } + #else + Debug.GraphicsAPI = GUI::GfxBackend::TUI; + #endif #endif REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index e9719d82a..3fad57539 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -846,7 +846,7 @@ namespace RC { m_debugging_gui.get_live_view().set_listeners_allowed(false); } - +#ifdef HAS_INPUT m_input_handler.register_keydown_event(Input::Key::O, {Input::ModifierKey::CONTROL}, [&]() { TRY([&] { auto was_gui_open = get_debugging_ui().is_open(); @@ -858,6 +858,7 @@ namespace RC } }); }); +#endif } #endif diff --git a/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp b/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp index 409dc7e36..78bbc59d8 100644 --- a/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp +++ b/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp @@ -1,5 +1,7 @@ #pragma once +#ifndef __clang__ + #include #include @@ -158,3 +160,80 @@ namespace RC inline constexpr details::EnumerateViewClosure enumerate; } } // namespace RC + + +#else + +#include + +// A simple enumerate impl for clang to avoid https://github.com/llvm/llvm-project/issues/60704 +namespace RC +{ + + namespace views + { + template + struct internal_enumerate { + T& iterable; + size_t index; + + template + struct iterator : std::iterator> { + using iterator_category = std::input_iterator_tag; + using value_type = std::pair; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + + size_t index; + It iter; + + explicit iterator(size_t index, It iter) : index(index), iter(iter) {} + + iterator& operator++() { + ++index; + ++iter; + return *this; + } + + bool operator!=(const iterator& other) const { + return iter != other.iter; + } + + value_type operator*() const { + return {*iter, index}; + } + }; + + auto begin() { + return iterator>(0, iterable.begin()); + } + + auto end() { + return iterator>(0, iterable.end()); + } + + explicit internal_enumerate(T& iterable) : iterable(iterable), index(0) {} + + internal_enumerate operator | (T& iterable) { + return internal_enumerate(iterable); + } + }; + + struct enumerate_op {}; + // operator | + template + internal_enumerate operator | (T& iterable, enumerate_op) { + return internal_enumerate(iterable); + } + + // T&& version + template + internal_enumerate operator | (T&& iterable, enumerate_op) { + return internal_enumerate(iterable); + } + + inline constexpr enumerate_op enumerate; + }; +} // namespace RC +#endif // __clang__ diff --git a/deps/first/MProgram/include/ErrorObject.hpp b/deps/first/MProgram/include/ErrorObject.hpp index d6204045e..63bd1e670 100644 --- a/deps/first/MProgram/include/ErrorObject.hpp +++ b/deps/first/MProgram/include/ErrorObject.hpp @@ -5,7 +5,7 @@ #ifdef LINUX #define sprintf_s snprintf -#define strncpy_s strncpy +#define strncpy_s(dest, destsz, src, count) strncpy((dest), (src), (((count) < (destsz)) ? (count) : (destsz))) #endif namespace RC @@ -55,7 +55,7 @@ namespace RC // The default message will be used which can't be too small since it's calculated at compile-time if (msg_len < sizeof(m_message)) { - strncpy_s(m_message, message, msg_len); + strncpy_s(m_message, msg_len, message, msg_len); } } From 4d771f145a9884502c5b60e7e03128fc0e7920cc Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 17:16:40 -0600 Subject: [PATCH 067/213] use stderr for internal error to avoid breaking the UI --- UE4SS/include/ExceptionHandling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/include/ExceptionHandling.hpp b/UE4SS/include/ExceptionHandling.hpp index 5b9315866..71fdef3ba 100644 --- a/UE4SS/include/ExceptionHandling.hpp +++ b/UE4SS/include/ExceptionHandling.hpp @@ -12,7 +12,7 @@ } \ else \ { \ - printf_s("Internal Error: %s\n", e.what()); \ + fprintf(stderr, "Internal Error: %s\n", e.what()); \ } namespace RC From 9615cad4ffe7a82b149a707461a49fb37ddbb4db Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 20:48:43 -0600 Subject: [PATCH 068/213] use system call fs --- .../File/include/File/FileType/StdFile.hpp | 5 +- deps/first/File/src/FileType/StdFile.cpp | 190 ++++++++++-------- 2 files changed, 108 insertions(+), 87 deletions(-) diff --git a/deps/first/File/include/File/FileType/StdFile.hpp b/deps/first/File/include/File/FileType/StdFile.hpp index cb2c9f2f8..adbf8886a 100644 --- a/deps/first/File/include/File/FileType/StdFile.hpp +++ b/deps/first/File/include/File/FileType/StdFile.hpp @@ -16,7 +16,7 @@ namespace RC::File class StdFile : public FileInterface { private: - using HANDLE = FILE*; + using HANDLE = int; // ;FILE*; struct IdentifyingProperties { @@ -43,7 +43,8 @@ namespace RC::File private: auto static create_all_directories(const std::filesystem::path& file_name_and_path) -> void; - + auto static calc_open_flags(const std::filesystem::path &file_name_and_path, const OpenProperties& open_properties) -> int; + private: auto close_file() -> void; diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index af6ae5979..eb3d42f97 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -6,16 +6,87 @@ #include #include +#include namespace RC::File { + auto StdFile::create_all_directories(const std::filesystem::path& file_name_and_path) -> void + { + if (file_name_and_path.parent_path().empty()) + { + return; + } + + try + { + std::filesystem::create_directories(file_name_and_path.parent_path()); + } + catch (const std::filesystem::filesystem_error& e) + { + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::create_all_directories] Tried creating directories '{}' but encountered an error. Error: {}", + file_name_and_path.string(), + e.what())) + } + } + + auto StdFile::calc_open_flags(const std::filesystem::path &file_name_and_path, const OpenProperties& open_properties) -> int + { + + int flags {}; + int rwflags {}; + switch (open_properties.open_for) + { + case OpenFor::Writing: + rwflags = O_WRONLY; + break; + case OpenFor::Appending: + rwflags = O_WRONLY; + flags = O_APPEND; + break; + case OpenFor::Reading: + rwflags = O_RDONLY; + break; + default: + printf("open_for: %d\n", open_properties.open_for); + THROW_INTERNAL_FILE_ERROR("[StdFile::open_file] Tried to open file but received invalid data for the 'OpenFor' parameter.") + } + + if (open_properties.overwrite_existing_file == OverwriteExistingFile::Yes) { + flags |= O_CREAT | O_TRUNC; + if (rwflags == O_RDONLY) + { + rwflags = O_RDWR; + } + create_all_directories(file_name_and_path); + } + else if (open_properties.create_if_non_existent == CreateIfNonExistent::Yes) + { + flags |= O_CREAT; + if (rwflags == O_RDONLY) + { + rwflags = O_RDWR; + } + create_all_directories(file_name_and_path); + } + else + { + if (!std::filesystem::exists(file_name_and_path)) + { + printf("file_name_and_path: %s not exists\n", file_name_and_path.string().c_str()); + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::open_file] Tried opening file but file does not exist: {}", file_name_and_path.string())) + } + } + + return rwflags | flags; + } + auto StdFile::is_valid() noexcept -> bool { - return m_file != nullptr; + return m_file > 0; } auto StdFile::invalidate_file() noexcept -> void { - m_file = nullptr; + m_file = 0; } auto StdFile::delete_file(const std::filesystem::path& file_path_and_name) -> void @@ -51,7 +122,8 @@ namespace RC::File auto StdFile::get_raw_handle() noexcept -> void* { - return static_cast(m_file); + long a = m_file; + return (void*)(a); } auto StdFile::get_file_path() const noexcept -> const std::filesystem::path& @@ -77,7 +149,7 @@ namespace RC::File THROW_INTERNAL_FILE_ERROR("[StdFile::write_to_file] Tried writing to file but the file is not open") } - size_t bytes_written = fwrite(data, sizeof(DataType), num_bytes_to_write, file.get_file()); + size_t bytes_written = write(file.get_file(), data, sizeof(DataType) * num_bytes_to_write); if (bytes_written < 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::write_to_file] Tried writing to file but was unable to complete operation. Error: {}", bytes_written)); } @@ -92,7 +164,7 @@ namespace RC::File } struct stat file_info{}; - fstat(fileno(m_file), &file_info); + fstat(m_file, &file_info); serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_dev}, true); serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_ino}, true); @@ -216,7 +288,7 @@ namespace RC::File } Handle cache_file = open(m_serialization_file_path_and_name); - auto bytes_read = fread(&m_cache, cache_size, 1, (HANDLE) cache_file.get_raw_handle()); + auto bytes_read = read((int)cache_file.get_raw_handle(), &m_cache, cache_size); if (bytes_read < 0) { THROW_INTERNAL_FILE_ERROR( @@ -243,26 +315,6 @@ namespace RC::File close_file(); } - auto StdFile::create_all_directories(const std::filesystem::path& file_name_and_path) -> void - { - if (file_name_and_path.parent_path().empty()) - { - return; - } - - try - { - std::filesystem::create_directories(file_name_and_path.parent_path()); - } - catch (const std::filesystem::filesystem_error& e) - { - THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::create_all_directories] Tried creating directories '{}' but encountered an error. Error: {}", - file_name_and_path.string(), - e.what())) - } - } - - auto StdFile::close_file() -> void { if (m_memory_map) @@ -284,7 +336,7 @@ namespace RC::File return; } - if (fclose(m_file) != 0) + if (m_file != 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::close_file] Was unable to close file, error: {}", errno)) } @@ -327,13 +379,13 @@ namespace RC::File auto StdFile::is_same_as(StdFile& other_file) -> bool { struct stat file_info{}; - if (fstat(fileno(m_file), &file_info) != 0) + if (fstat(m_file, &file_info) != 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::is_same_as] Tried retrieving file information by handle. Error: {}", errno)) } struct stat other_file_info{}; - if (fstat(fileno(other_file.get_file()), &other_file_info) != 0) + if (fstat(other_file.get_file(), &other_file_info) != 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::is_same_as] Tried retrieving file information by handle. Error: {}", errno)) } @@ -393,34 +445,35 @@ namespace RC::File auto StdFile::read_file_all() const -> StringType { - StreamType stream{get_file_path(), std::ios::in | std::ios::binary}; - if (!stream) + auto file_name_and_path = get_file_path(); + int flags = O_RDONLY; + int readfd = ::open(file_name_and_path.string().c_str(), flags); + if (readfd < 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::read_all] Tried to read entire file but returned error {}", errno)) } else { // Strip the BOM if it exists - File::StreamType::off_type start{}; File::CharType bom[3]{}; - stream.read(bom, 3); + read(readfd, bom, 3); + off_t start = 0; if ((unsigned char)bom[0] == 0xEF && (unsigned char)bom[1] == 0xBB && (unsigned char)bom[2] == 0xBF) { // BOM: UTF-8 start = 3; } - StringType file_contents; - stream.seekg(0, std::ios::end); - auto size = stream.tellg(); + File::StringType file_contents; + ssize_t size = lseek(readfd, 0, SEEK_END); + lseek(readfd, start, SEEK_SET); if (size == -1) { return {}; } file_contents.resize(size - start); - stream.seekg(start, std::ios::beg); - stream.read(&file_contents[0], file_contents.size() - start); - stream.close(); + read(readfd, &file_contents[0], size - start); + close(readfd); return file_contents; } } @@ -447,13 +500,11 @@ namespace RC::File } // seek to get size to map while keep original file position - auto original_position = ftell(m_file); - fseek(m_file, 0, SEEK_END); - auto file_size = ftell(m_file); - fseek(m_file, original_position, SEEK_SET); - + auto original_position = lseek(m_file, 0, SEEK_CUR); + auto file_size = lseek(m_file, 0, SEEK_END); + lseek(m_file, original_position, SEEK_SET); - auto res = mmap(nullptr, file_size, flags, MAP_SHARED, fileno(m_file), 0); + auto res = mmap(nullptr, file_size, flags, MAP_SHARED, m_file, 0); if (res == (void*) -1) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::memory_map] Tried to memory map file but 'mmap' returned error: {}", errno)) @@ -476,59 +527,28 @@ namespace RC::File { THROW_INTERNAL_FILE_ERROR("[StdFile::open_file] Tried to open file but file_name_and_path was empty.") } - const char* modes; - switch (open_properties.open_for) - { - case OpenFor::Writing: - if (open_properties.overwrite_existing_file == OverwriteExistingFile::Yes) { - modes = "wb+"; - } else { - modes = "wb"; - } - break; - case OpenFor::Appending: - modes = "ab"; - break; - case OpenFor::Reading: - modes = "rb"; - break; - default: - printf("open_for: %d\n", open_properties.open_for); - THROW_INTERNAL_FILE_ERROR("[StdFile::open_file] Tried to open file but received invalid data for the 'OpenFor' parameter.") - } - if (open_properties.overwrite_existing_file == OverwriteExistingFile::Yes) { - create_all_directories(file_name_and_path); - } - else if (open_properties.create_if_non_existent == CreateIfNonExistent::Yes) - { - create_all_directories(file_name_and_path); - } - else - { - if (!std::filesystem::exists(file_name_and_path)) - { - printf("file_name_and_path: %s not exists\n", file_name_and_path.string().c_str()); - THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::open_file] Tried opening file but file does not exist: {}", file_name_and_path.string())) - } - } + int flags = calc_open_flags(file_name_and_path, open_properties); StdFile file{}; // This very badly named API may create a new file or it may not but it will always open a file (unless there's an error) - file.set_file(fopen(file_name_and_path.string().c_str(), modes)); + int fd = ::open(file_name_and_path.string().c_str(), flags); - if (file.get_file() == NULL) + if (fd > 0) + { + file.set_file(fd); + } + else { std::string_view open_type = open_properties.open_for == OpenFor::Writing || open_properties.open_for == OpenFor::Appending ? "writing" : "reading"; - int error = errno; - printf("open file %s failed, error: %d\n", file_name_and_path.string().c_str(), error); + fprintf(stderr, "open file %s failed, error: %d\n", file_name_and_path.string().c_str(), errno); THROW_INTERNAL_FILE_ERROR( std::format("[StdFile::open_file] Tried opening file for {} but encountered an error. Path & File: {} | errno = {}\n", open_type, file_name_and_path.string(), - error)) + errno)) } file.m_file_path_and_name = file_name_and_path; From f023892f2f4509fed995a70d49d2d052bb49b746 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 20:49:09 -0600 Subject: [PATCH 069/213] fix size --- UE4SS/include/GUI/LiveView.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UE4SS/include/GUI/LiveView.hpp b/UE4SS/include/GUI/LiveView.hpp index 3ac0306c0..64e4d5071 100644 --- a/UE4SS/include/GUI/LiveView.hpp +++ b/UE4SS/include/GUI/LiveView.hpp @@ -89,7 +89,11 @@ namespace RC::GUI UObject* m_currently_opened_tree_node{}; std::string m_current_property_value_buffer{}; int64_t m_current_enum_value_buffer{}; + #ifdef WIN32 float m_top_size{300.0f}; + #else + float m_top_size{14.0f}; + #endif float m_bottom_size{0.0f}; UFunctionCallerWidget* m_function_caller_widget{}; bool m_is_searching_by_name{}; From 6bab15e939f71337adc408f7a6494a094468d106 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 20:49:20 -0600 Subject: [PATCH 070/213] print to stderr --- UE4SS/src/GUI/GUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 00b35265e..855e7a1b2 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -354,7 +354,7 @@ namespace RC::GUI } else { - printf_s("Internal Error: %s\n", e.what()); + fprintf(stderr, "Internal Error: %s\n", e.what()); } // You're not allowed to throw exceptions directly inside a frame! From 8a1d14439e68667041bba62f468c353d6431b310 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 20:49:31 -0600 Subject: [PATCH 071/213] fix size --- UE4SS/src/GUI/LiveView.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 98161d44c..4368b50eb 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -63,6 +63,14 @@ #undef max #undef min +#ifdef WIN32 +#define XOFFSET (-14.0f) +#define XDIV 1 +#else +#define XOFFSET 0 +#define XDIV (6.66f) +#endif + namespace RC::GUI { using namespace Unreal; @@ -2818,7 +2826,7 @@ namespace RC::GUI auto LiveView::render_info_panel() -> void { - ImGui::BeginChild("LiveView_InfoPanel", {-16.0f, m_bottom_size}, true, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("LiveView_InfoPanel", {XOFFSET, m_bottom_size}, true, ImGuiWindowFlags_HorizontalScrollbar); size_t next_object_index_to_select{}; @@ -3084,6 +3092,7 @@ namespace RC::GUI // Update this text if corresponding button's text changes. Textinput width = Spacing + Window margin + Button padding + Button text width ImGui::PushItemWidth(-(8.0f + 16.0f + ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::CalcTextSize(ICON_FA_COPY " Copy search result").x)); + // TODO: merge conflict, make sure this width is onky for TUI: old value is (-160.0f / XDIV bool push_inactive_text_color = !m_search_field_cleared; if (push_inactive_text_color) { @@ -3445,6 +3454,7 @@ namespace RC::GUI m_top_size = std::max(ImGui::GetFrameHeight(), std::round(split_pane_height * (m_top_size / (m_top_size + m_bottom_size)))); } m_bottom_size = std::max(ImGui::GetFrameHeight(), split_pane_height - m_top_size); + // do we need ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, XOFFSET); on TUI? ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16.0f); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); From 4ced93e4acdb84e8107abde1361004c8ddb22841 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 20:50:08 -0600 Subject: [PATCH 072/213] disable buffer --- UE4SS/src/GUI/TUI.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/TUI.cpp index 35596b7f9..420375a46 100644 --- a/UE4SS/src/GUI/TUI.cpp +++ b/UE4SS/src/GUI/TUI.cpp @@ -16,8 +16,10 @@ namespace RC::GUI g_screen = ImTui_ImplNcurses_Init(true); // disable stderr - freopen("/dev/null", "w", stderr); - + freopen("./tui.log", "w", stderr); + setbuf(stderr, NULL); + fprintf(stderr, "Backend_TUI::init\n"); + fflush(stderr); atexit([]() { // ensure that the screen is destroyed ImTui_ImplNcurses_Shutdown(); From 79c7fd31c15bba27c9ed671908e0f09e1f3eba48 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 21 Feb 2024 20:55:56 -0600 Subject: [PATCH 073/213] fix close --- deps/first/File/src/FileType/StdFile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index eb3d42f97..96b354dab 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -336,12 +336,13 @@ namespace RC::File return; } - if (m_file != 0) + if (close(m_file) == -1) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::close_file] Was unable to close file, error: {}", errno)) } else { + m_file = 0; set_is_file_open(false); } } From 04b4868b486258b746a6e6f55ab86c47c86bfcfd Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:24:53 -0600 Subject: [PATCH 074/213] *GeneratedFile->UEGeneratedFile and bug fix & perf improve --- .../SDKGenerator/UEHeaderGenerator.hpp | 14 +++---- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 37 ++++++++++--------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp index 744682980..62f00ca6d 100644 --- a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp +++ b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp @@ -106,7 +106,7 @@ namespace RC::UEGenerator using CaseInsensitiveSet = ::std::set; - class GeneratedFile + class UEGeneratedFile { protected: SystemStringType m_file_base_name; @@ -116,13 +116,13 @@ namespace RC::UEGenerator int32_t m_current_indent_count; public: - GeneratedFile(const FFilePath& full_file_path); - virtual ~GeneratedFile() = default; + UEGeneratedFile(const FFilePath& full_file_path); + virtual ~UEGeneratedFile() = default; // Delete copy and move constructors and assignment operator - GeneratedFile(const GeneratedFile&) = delete; - GeneratedFile(GeneratedFile&&) = default; - auto operator=(const GeneratedFile&) -> void = delete; + UEGeneratedFile(const UEGeneratedFile&) = delete; + UEGeneratedFile(UEGeneratedFile&&) = default; + auto operator=(const UEGeneratedFile&) -> void = delete; auto append_line(const SystemStringType& line) -> void; auto append_line_no_indent(const SystemStringType& line) -> void; @@ -134,7 +134,7 @@ namespace RC::UEGenerator virtual auto generate_file_contents() -> SystemStringType; }; - class GeneratedSourceFile : public GeneratedFile + class GeneratedSourceFile : public UEGeneratedFile { private: SystemStringType m_file_module_name; diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index a91bcdab6..e8b0139a7 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -254,7 +254,7 @@ namespace RC::UEGenerator { auto module_name_sys = to_system(module_name); const FFilePath module_file_path = m_root_directory / module_name_sys / std::format(SYSSTR("{}.Build.cs"), module_name_sys); - GeneratedFile module_build_file = GeneratedFile(module_file_path); + UEGeneratedFile module_build_file = UEGeneratedFile(module_file_path); module_build_file.append_line(SYSSTR("using UnrealBuildTool;")); module_build_file.append_line(SYSSTR("")); @@ -304,7 +304,7 @@ namespace RC::UEGenerator { auto module_name_sys = to_system(module_name); const FFilePath module_file_path = m_root_directory / module_name_sys / SYSSTR("Private") / std::format(SYSSTR("{}Module.cpp"), module_name_sys); - GeneratedFile module_impl_file = GeneratedFile(module_file_path); + UEGeneratedFile module_impl_file = UEGeneratedFile(module_file_path); module_impl_file.append_line(SYSSTR("#include \"Modules/ModuleManager.h\"")); module_impl_file.append_line(SYSSTR("")); @@ -2937,10 +2937,11 @@ namespace RC::UEGenerator if (cpp_form == UEnum::ECppForm::EnumClass) { const auto underlying_type = m_underlying_enum_types.find(enum_native_name); - if (underlying_type->second == SYSSTR("uint8") || - (underlying_type == m_underlying_enum_types.end() && - (get_highest_enum(uenum) <= 255 && - get_lowest_enum(uenum) >= 0))) + if ((underlying_type == m_underlying_enum_types.end() && + (get_highest_enum(uenum) <= 255 && + get_lowest_enum(uenum) >= 0)) || + ((underlying_type != m_underlying_enum_types.end()) && + (underlying_type->second == SYSSTR("uint8")))) { // Underlying type is implicit or explicitly uint8. flag_format_helper.add_switch(SYSSTR("BlueprintType")); @@ -4040,7 +4041,7 @@ namespace RC::UEGenerator return std::format(SYSSTR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), to_system(module_name), object_name, to_system(fallback_name)); } - GeneratedFile::GeneratedFile(const FFilePath& full_file_path) + UEGeneratedFile::UEGeneratedFile(const FFilePath& full_file_path) { this->m_full_file_path = full_file_path; // [[keep]] @@ -4048,7 +4049,7 @@ namespace RC::UEGenerator this->m_current_indent_count = 0; } - auto GeneratedFile::append_line(const SystemStringType& line) -> void + auto UEGeneratedFile::append_line(const SystemStringType& line) -> void { for (int32_t i = 0; i < m_current_indent_count; i++) { @@ -4058,18 +4059,18 @@ namespace RC::UEGenerator m_file_contents_buffer.append(SYSSTR("\n")); } - auto GeneratedFile::append_line_no_indent(const SystemStringType& line) -> void + auto UEGeneratedFile::append_line_no_indent(const SystemStringType& line) -> void { m_file_contents_buffer.append(line); m_file_contents_buffer.append(SYSSTR("\n")); } - auto GeneratedFile::begin_indent_level() -> void + auto UEGeneratedFile::begin_indent_level() -> void { m_current_indent_count++; } - auto GeneratedFile::end_indent_level() -> void + auto UEGeneratedFile::end_indent_level() -> void { m_current_indent_count--; if (m_current_indent_count < 0) @@ -4078,7 +4079,7 @@ namespace RC::UEGenerator } } - auto GeneratedFile::serialize_file_content_to_disk() -> bool + auto UEGeneratedFile::serialize_file_content_to_disk() -> bool { if (!has_content_to_save()) { @@ -4086,7 +4087,9 @@ namespace RC::UEGenerator } // TODO might be slow, maybe move it out into the header generator? std::filesystem::create_directories(this->m_full_file_path.parent_path()); - + auto file = File::open(m_full_file_path, File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); + file.write_file_string_to_file(to_file(generate_file_contents())); + /* UEOStreamType file_output_stream; file_output_stream.open(m_full_file_path); if (!file_output_stream.is_open()) @@ -4095,16 +4098,16 @@ namespace RC::UEGenerator } // TODO: FIX STREAM file_output_stream << generate_file_contents().c_str(); - file_output_stream.close(); + file_output_stream.close();*/ return true; } - auto GeneratedFile::generate_file_contents() -> SystemStringType + auto UEGeneratedFile::generate_file_contents() -> SystemStringType { return m_file_contents_buffer; } - auto GeneratedFile::has_content_to_save() const -> bool + auto UEGeneratedFile::has_content_to_save() const -> bool { return !m_file_contents_buffer.empty(); } @@ -4128,7 +4131,7 @@ namespace RC::UEGenerator } GeneratedSourceFile::GeneratedSourceFile(const FFilePath& file_path, const SystemStringType& file_module_name, bool is_implementation_file, UObject* object) - : GeneratedFile(file_path) + : UEGeneratedFile(file_path) { this->m_file_module_name = file_module_name; this->m_is_implementation_file = is_implementation_file; From 820ffe3ab129674ae10f64ffcafafc8fad06849b Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:25:12 -0600 Subject: [PATCH 075/213] type fix --- UE4SS/src/SDKGenerator/Common.cpp | 2 +- UE4SS/src/SDKGenerator/TMapOverrideGen.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/UE4SS/src/SDKGenerator/Common.cpp b/UE4SS/src/SDKGenerator/Common.cpp index 00c87403e..1a85f72a7 100644 --- a/UE4SS/src/SDKGenerator/Common.cpp +++ b/UE4SS/src/SDKGenerator/Common.cpp @@ -123,7 +123,7 @@ namespace RC::UEGenerator return resulting_name; } - auto generate_delegate_name(FProperty* property, const UEStringType& context_name) -> SystemStringType + auto generate_delegate_name(FProperty* property, const SystemStringType& context_name) -> SystemStringType { const auto property_name = sanitize_property_name(to_system_string(property->GetName())); return std::format(SYSSTR("F{}{}"), to_system(context_name), to_system(property_name)); diff --git a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp index d12859ad4..9516d89a0 100644 --- a/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp +++ b/UE4SS/src/SDKGenerator/TMapOverrideGen.cpp @@ -110,11 +110,11 @@ namespace RC::UEGenerator // Retrieve JSON as a string. int32_t indent_level{}; - auto uaapifile = open(SystemStringType{UE4SSProgram::get_program().get_working_directory()} + SYSSTR("\\UAssetAPITMapOverrides.json"), + auto uaapifile = open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("UAssetAPITMapOverrides.json"), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); - auto fmodelfile = open(SystemStringType{UE4SSProgram::get_program().get_working_directory()} + SYSSTR("\\FModelTMapOverrides.json"), + auto fmodelfile = open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("FModelTMapOverrides.json"), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); From 731d0166650ea3098d611b4b9aa783edeb8b375f Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:25:47 -0600 Subject: [PATCH 076/213] use w+ for overwrite --- UE4SS/src/GUI/TUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/TUI.cpp index 420375a46..12bd4bec0 100644 --- a/UE4SS/src/GUI/TUI.cpp +++ b/UE4SS/src/GUI/TUI.cpp @@ -16,7 +16,7 @@ namespace RC::GUI g_screen = ImTui_ImplNcurses_Init(true); // disable stderr - freopen("./tui.log", "w", stderr); + freopen("./tui.log", "w+", stderr); setbuf(stderr, NULL); fprintf(stderr, "Backend_TUI::init\n"); fflush(stderr); From d3fd5d312f528a36265c095adb044b91c2ab40dc Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:26:08 -0600 Subject: [PATCH 077/213] use filesystem::path --- UE4SS/src/GUI/Dumpers.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index 6f3e4e3e4..1fb0a1a45 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -315,8 +315,9 @@ namespace RC::GUI::Dumpers static auto dump_actor_class = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.StaticMeshActor")); SystemStringType file_buffer{}; file_buffer.append(generate_actors_csv_file(dump_actor_class)); + auto path = std::filesystem::path {UE4SSProgram::get_program().get_working_directory()} / std::format(SYSSTR("{}-ue4ss_static_mesh_data.csv"), long(std::time(nullptr))); auto file = - File::open(std::format(SYSSTR("{}\\{}-ue4ss_static_mesh_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), + File::open(path, File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); @@ -328,8 +329,9 @@ namespace RC::GUI::Dumpers { Output::send(SYSSTR("Dumping CSV of all loaded actor types, positions and mesh properties\n")); SystemStringType file_buffer{}; + auto path = std::filesystem::path {UE4SSProgram::get_program().get_working_directory()} / std::format(SYSSTR("{}-ue4ss_actor_data.csv"), long(std::time(nullptr))); file_buffer.append(generate_actors_csv_file(AActor::StaticClass())); - auto file = File::open(std::format(SYSSTR("{}\\{}-ue4ss_actor_data.csv"), UE4SSProgram::get_program().get_working_directory(), long(std::time(nullptr))), + auto file = File::open(path, File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); From 0e3b86b79a174ef353c427ef57ed52f2f9b8714d Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:26:17 -0600 Subject: [PATCH 078/213] use filesystem::path --- UE4SS/src/GUI/Dumpers.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index 1fb0a1a45..d06ab06a2 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -400,14 +400,14 @@ namespace RC::GUI::Dumpers if (ImGui::Button("Dump CXX Headers\n")) { - SystemStringType working_dir{UE4SSProgram::get_program().get_working_directory()}; - UE4SSProgram::get_program().generate_cxx_headers(working_dir + SYSSTR("\\CXXHeaderDump")); + std::filesystem::path working_dir{UE4SSProgram::get_program().get_working_directory()}; + UE4SSProgram::get_program().generate_cxx_headers(working_dir / SYSSTR("CXXHeaderDump")); } if (ImGui::Button("Generate Lua Types\n")) { - SystemStringType working_dir{UE4SSProgram::get_program().get_working_directory()}; - UE4SSProgram::get_program().generate_lua_types(working_dir + SYSSTR("\\Mods\\shared\\types")); + std::filesystem::path working_dir{UE4SSProgram::get_program().get_working_directory()}; + UE4SSProgram::get_program().generate_lua_types(working_dir / SYSSTR("Mods") / SYSSTR("shared") SYSSTR("types")); } } } // namespace RC::GUI::Dumpers From 1896d4119ee38468e52dff86bc2212489e9f5f2e Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:26:25 -0600 Subject: [PATCH 079/213] fix permission --- deps/first/File/src/FileType/StdFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index 96b354dab..5a7cab89f 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -534,7 +534,7 @@ namespace RC::File StdFile file{}; // This very badly named API may create a new file or it may not but it will always open a file (unless there's an error) - int fd = ::open(file_name_and_path.string().c_str(), flags); + int fd = ::open(file_name_and_path.string().c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); if (fd > 0) { From c5c40973a744733f875e8385e2dc900a12a44bf7 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:26:36 -0600 Subject: [PATCH 080/213] define Linux GUI scale --- UE4SS/include/GUI/GUI.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index b7fb9ace0..c3c55bd9b 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -11,6 +11,18 @@ #include struct ImGuiSettingsHandler; +#ifdef WIN32 +#define XOFFSET (-14.0f) +#define XDIV 1 +#define YDIV 1 +#else +#ifdef LINUX +#define XOFFSET 0 +#define XDIV (6.66f) +#define YDIV (21.1f) +#endif +#endif + #ifdef LINUX namespace ImGui { static void BeginDisabled(bool disabled = true) {} From c58db4860c7a3403c3ae6304230a4250aef61b68 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:26:49 -0600 Subject: [PATCH 081/213] linux scaling --- UE4SS/src/GUI/Console.cpp | 6 ++++-- UE4SS/src/GUI/GUI.cpp | 8 +++++++- UE4SS/src/GUI/LiveView.cpp | 21 ++++++++++----------- deps/first/patternsleuth | 2 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/UE4SS/src/GUI/Console.cpp b/UE4SS/src/GUI/Console.cpp index aa781d920..b4b9cf465 100644 --- a/UE4SS/src/GUI/Console.cpp +++ b/UE4SS/src/GUI/Console.cpp @@ -130,7 +130,9 @@ namespace RC::GUI /**/ std::lock_guard guard(m_lines_mutex); - m_text_editor.Render("TextEditor", {-16.0f, -31.0f + -8.0f}); + // TODO: ensure this ydiv is okay? + // the old value is const float footer_height_to_reserve = ((ImGui::GetStyle().ItemSpacing.y * 10.0f) + ImGui::GetFrameHeightWithSpacing()) / YDIV; + m_text_editor.Render("TextEditor", {-16.0f / , (-31.0f + -8.0f) / YDIV}); ImGui_AutoScroll("TextEditor", &m_previous_max_scroll_y); //*/ @@ -138,7 +140,7 @@ namespace RC::GUI auto Console::render_search_box() -> void { - m_filter.Draw("Search log", 200); + m_filter.Draw("Search log", 200 / XDIV); } static auto LogLevel_to_ImColor(Color::Color color) -> std::pair diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 855e7a1b2..d2965de4c 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -227,7 +227,11 @@ namespace RC::GUI ImGuiStyle& style = ImGui::GetStyle(); style.WindowPadding = ImVec2(8, 8); + #ifdef WIN32 style.FramePadding = ImVec2(12, 5); + #else + style.FramePadding = ImVec2(0.5f, 0.5f); + #endif style.CellPadding = ImVec2(3, 3); style.ItemSpacing = ImVec2(8, 4); style.ItemInnerSpacing = ImVec2(4, 4); @@ -355,11 +359,13 @@ namespace RC::GUI else { fprintf(stderr, "Internal Error: %s\n", e.what()); + fflush(stderr); } // You're not allowed to throw exceptions directly inside a frame! // Use GUI::TRY to move exceptions to the end of the frame. - abort(); + //abort(); + asm("int3"); } ImGui::Render(); diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 4368b50eb..a4c5e5cad 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -63,14 +63,6 @@ #undef max #undef min -#ifdef WIN32 -#define XOFFSET (-14.0f) -#define XDIV 1 -#else -#define XOFFSET 0 -#define XDIV (6.66f) -#endif - namespace RC::GUI { using namespace Unreal; @@ -3578,8 +3570,9 @@ namespace RC::GUI load_watches_from_disk(); s_watches_loaded_from_disk = true; } - - ImGui::BeginChild("watch_render_frame", {-16.0f, -31.0f + -8.0f}); + float xoffset = (XOFFSET == 0) ? (0.0f) : (XOFFSET - 2); + // TODO: ensure this / XDIV is okay? the old value is -35/XDIV + ImGui::BeginChild("watch_render_frame", {xoffset, (-31.0f + -8.0f) / XDIV}); if (ImGui::Button("All Off")) { @@ -3592,11 +3585,15 @@ namespace RC::GUI } static int num_columns = 3; + #ifdef WIN32 ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, {2.0f, 2.0f}); + #endif if (ImGui::BeginTable("watch_table", num_columns, ImGuiTableFlags_Borders)) { + // TODO: do we need controls_width = (XDIV == 1) ? (60.0f) : (60.0f / XDIV + 5.0f);? ImGui::TableSetupColumn("Controls", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFrameHeight() * 3.0f + 4.0f); ImGui::TableSetupColumn("Watch Identifier", ImGuiTableColumnFlags_WidthStretch); + // TODO: why height here? ImGui::TableSetupColumn("Save", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFrameHeight()); ImGui::TableHeadersRow(); @@ -3652,7 +3649,7 @@ namespace RC::GUI { save_watches_to_disk(); } - ImGui::SetNextWindowSize({690.0f, 0.0f}); + ImGui::SetNextWindowSize({690.0f / XDIV, 0.0f}); if (ImGui::BeginPopupContextItem(to_string(std::format(SYSSTR("##watch-from-disk-settings-popup-{}"), watch.hash)).c_str())) { ImGui::Text("Acquisition Method"); @@ -3674,7 +3671,9 @@ namespace RC::GUI } ImGui::EndTable(); + #ifdef WIN32 ImGui::PopStyleVar(); + #endif } ImGui::EndChild(); } diff --git a/deps/first/patternsleuth b/deps/first/patternsleuth index a26ec954d..baed68bcc 160000 --- a/deps/first/patternsleuth +++ b/deps/first/patternsleuth @@ -1 +1 @@ -Subproject commit a26ec954d63adc70660f962f27586cf5fc5972e5 +Subproject commit baed68bccfed9d0ea794259c087317e636e64bdc From 527843a69f6aaaa4287df9c04575dd36a40750c9 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 03:26:58 -0600 Subject: [PATCH 082/213] change header gen --- scripts/HeaderGen.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index 8a8835a8b..d35784dbb 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -16,9 +16,9 @@ }} """ -MEMBER_TEMPLATE = """if (auto it = {ClassName}::MemberOffsets.find(SYSSTR("{MemberName}")); it == {ClassName}::MemberOffsets.end()) +MEMBER_TEMPLATE = """if (auto it = {ClassName}::MemberOffsets.find(STR("{MemberName}")); it == {ClassName}::MemberOffsets.end()) {{ - {ClassName}::MemberOffsets.emplace(SYSSTR("{MemberName}"), 0x{MemberOffset:02x}); + {ClassName}::MemberOffsets.emplace(STR("{MemberName}"), 0x{MemberOffset:02x}); }} """ @@ -30,10 +30,13 @@ def __init__(self, name, offset): self.offset = offset def GenerateMember(self, className, count = None): + generated_name = self.name + if self.name == "EnumFlags": + generated_name = "EnumFlags_Internal" if count and count != 0: - return MEMBER_TEMPLATE.format(ClassName = className, MemberName = f"{self.name}_{count}", MemberOffset = self.offset) + return MEMBER_TEMPLATE.format(ClassName = className, MemberName = f"{generated_name}_{count}", MemberOffset = self.offset) else: - return MEMBER_TEMPLATE.format(ClassName = className, MemberName = self.name, MemberOffset = self.offset) + return MEMBER_TEMPLATE.format(ClassName = className, MemberName = generated_name, MemberOffset = self.offset) class CVFunc: def __init__(self, mangledname, name, slotoffset): From e250ee9b641e28c58b92f21784bb3d5737727861 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 05:50:41 -0600 Subject: [PATCH 083/213] fix lock --- deps/first/LuaRaw/src/luauser.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/deps/first/LuaRaw/src/luauser.c b/deps/first/LuaRaw/src/luauser.c index 813e29364..ad134b81e 100644 --- a/deps/first/LuaRaw/src/luauser.c +++ b/deps/first/LuaRaw/src/luauser.c @@ -65,9 +65,8 @@ void LuaLockInitial(lua_State * L){ } void LuaLockFinal(lua_State * L){ - if (lua_lock_mutex.init){ - pthread_mutex_destroy(&lua_lock_mutex.mutex); - lua_lock_mutex.init = false; + if (lua_lock_mutex.init) { + LuaUnlock(L); } } From de95408727a2468bfaeb3886946387e06d9aff45 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 05:50:53 -0600 Subject: [PATCH 084/213] optimize the script path --- UE4SS/src/UE4SSProgram.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 3fad57539..9e9f7b87a 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1053,6 +1053,11 @@ namespace RC // Create the mod but don't install it yet if (std::filesystem::exists(sub_directory.path() / "scripts")) m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); + #ifdef LINUX + else if (std::filesystem::exists(sub_directory.path() / "Scripts")) + // avoid we have both "scripts" and "Scripts" in the same mod + m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); + #endif #ifdef HAS_CPPMOD if (std::filesystem::exists(sub_directory.path() / "dlls")) m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); @@ -1121,8 +1126,8 @@ namespace RC { continue; } - #endif mod->fire_unreal_init(); + #endif } } @@ -1149,8 +1154,8 @@ namespace RC { continue; } - #endif mod->fire_program_start(); + #endif } } From a0fca04325eaf9b85d7aaa3b475aa21da70ff151 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 05:51:02 -0600 Subject: [PATCH 085/213] add spacing --- UE4SS/src/GUI/Dumpers.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index d06ab06a2..0eeeddfc8 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -345,6 +345,13 @@ namespace RC::GUI::Dumpers { return; } + + // this give the button a little bit of space between the top of the window + // and the buttons themselves + #ifdef LINUX + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, {0.0f, 1.0f}); + ImGui::Spacing(); + #endif if (ImGui::Button("Dump all static actor meshes to file")) { @@ -409,5 +416,10 @@ namespace RC::GUI::Dumpers std::filesystem::path working_dir{UE4SSProgram::get_program().get_working_directory()}; UE4SSProgram::get_program().generate_lua_types(working_dir / SYSSTR("Mods") / SYSSTR("shared") SYSSTR("types")); } + + + #ifdef LINUX + ImGui::PopStyleVar(); + #endif } } // namespace RC::GUI::Dumpers From 050bca0604d8083cacc508ba9c8865b8d04c21fa Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 05:51:10 -0600 Subject: [PATCH 086/213] optimize scripts --- UE4SS/src/Mod/LuaMod.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 40cbf1a8d..87a723238 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -647,13 +647,25 @@ namespace RC // Give the full path to the 'Scripts' directory to the mod container std::filesystem::path mod_path_fs = m_mod_path; auto path = (mod_path_fs / SYSSTR("scripts")); - m_scripts_path = to_system(path); - - // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod - if (!std::filesystem::exists(path)) + if (std::filesystem::exists(path)) { - set_installable(false); - return; + // "scripts" get priority over "Scripts" + m_scripts_path = to_system(path); + } + else + { + // failed, we try the other case + path = (mod_path_fs / SYSSTR("Scripts")); + if (std::filesystem::exists(path)) + { + m_scripts_path = to_system(path); + } + else + { + // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod + set_installable(false); + return; + } } } @@ -831,8 +843,8 @@ namespace RC lua_getfield(lua_state, -1, "path"); std::string current_paths = lua_tostring(lua_state, -1); - current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); lua_pop(lua_state, 1); @@ -841,8 +853,8 @@ namespace RC lua_getfield(lua_state, -1, "cpath"); std::string current_cpaths = lua_tostring(lua_state, -1); - current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); lua_pop(lua_state, 1); lua_pushstring(lua_state, current_cpaths.c_str()); From 969c6c6b7a271eefe51822cbe9550bc0b870c8b8 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 06:53:34 -0600 Subject: [PATCH 087/213] size tweak --- UE4SS/src/GUI/LiveView.cpp | 3 ++- UE4SS/src/GUI/UFunctionCallerWidget.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index a4c5e5cad..1b3628726 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -3445,8 +3445,9 @@ namespace RC::GUI // Window height changed, scale panes by ratio m_top_size = std::max(ImGui::GetFrameHeight(), std::round(split_pane_height * (m_top_size / (m_top_size + m_bottom_size)))); } + // TODO: check the size for TUI as m_bottom_size = (ImGui::GetContentRegionMaxAbs().y - m_top_size) - 2.0f; m_bottom_size = std::max(ImGui::GetFrameHeight(), split_pane_height - m_top_size); - // do we need ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, XOFFSET); on TUI? + // TODO: do we need ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, XOFFSET); on TUI? ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16.0f); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); diff --git a/UE4SS/src/GUI/UFunctionCallerWidget.cpp b/UE4SS/src/GUI/UFunctionCallerWidget.cpp index 7a08ff14f..3ce3e5930 100644 --- a/UE4SS/src/GUI/UFunctionCallerWidget.cpp +++ b/UE4SS/src/GUI/UFunctionCallerWidget.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -323,7 +324,7 @@ namespace RC::GUI ImGui::OpenPopup(popup_modal_id.c_str()); } - ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, {925.0f, 300.0f}); + ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, {925.0f / XDIV, 300.0f / YDIV}); if (ImGui::BeginPopupModal(popup_modal_id.c_str(), &is_open)) { ImGui::PushItemWidth(-1.0f); From ad4b5816b6ea669c84fa3c2afcdf755c7ed84cb5 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 12:39:17 -0600 Subject: [PATCH 088/213] hightlight the color on TUI --- UE4SS/src/GUI/GUI.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index d2965de4c..dcb058c24 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -285,8 +285,13 @@ namespace RC::GUI style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.55f, 0.22f, 0.45f, 1.00f); style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); style.Colors[ImGuiCol_Button] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); + #ifdef WIN32 style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); + #else + style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.4f, 0.5f, 0.8f, 1.00f); + style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.65f, 0.4f, 0.50f, 1.00f); + #endif style.Colors[ImGuiCol_Header] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f); style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f); @@ -297,8 +302,13 @@ namespace RC::GUI style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.92f, 0.24f, 0.84f, 0.67f); style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.92f, 0.24f, 0.84f, 0.95f); style.Colors[ImGuiCol_Tab] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); + #ifdef WIN32 style.Colors[ImGuiCol_TabHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_TabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); + #else + style.Colors[ImGuiCol_TabHovered] = ImVec4(0.4f, 0.5f, 0.8f, 1.00f); + style.Colors[ImGuiCol_TabActive] = ImVec4(0.65f, 0.4f, 0.50f, 1.00f); + #endif style.Colors[ImGuiCol_TabUnfocused] = ImVec4(0.07f, 0.10f, 0.15f, 0.97f); style.Colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.14f, 0.26f, 0.42f, 1.00f); style.Colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); From fd079f7ad8d27956a8c227d655cde275cc9db459 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 19:26:16 -0600 Subject: [PATCH 089/213] add TUI configure --- UE4SS/include/SettingsManager.hpp | 23 +++++++++++++++++++++++ UE4SS/src/SettingsManager.cpp | 21 +++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index 608fd0b1d..fdd2830fe 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -109,6 +109,29 @@ namespace RC bool GUIUFunctionCaller{false}; } Experimental; +#ifdef LINUX + struct TUIFeatures + { + int ButtonLeft = 1; + int ButtonRight = 3; + int WheelUp = 4; + int WheelDown = 5; + bool TUIAsInputSource = true; + bool TUINerdFont = true; + SystemStringType TerminalCode = "f120"; + SystemStringType ArchiveCode = "f187"; + SystemStringType SyncCode = "f46a"; + SystemStringType FileCode = "f15b"; + SystemStringType EyeCode = "f06e"; + SystemStringType PuzzlePieceCode = "f12e"; + SystemStringType AngleLeftCode = "f100"; + SystemStringType AngleRightCode = "f101"; + SystemStringType BanCode = "f05e"; + SystemStringType CopyCode = "f0c5"; + SystemStringType SearchCode = "f002"; + } TUI; +#endif + public: SettingsManager() = default; diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index f9752440c..8ae745ad7 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -124,5 +124,26 @@ namespace RC constexpr static SystemCharType section_experimental_features[] = SYSSTR("ExperimentalFeatures"); REGISTER_BOOL_SETTING(Experimental.GUIUFunctionCaller, section_experimental_features, GUIUFunctionCaller) + + #ifdef LINUX + constexpr static SystemCharType section_tui_features[] = SYSSTR("TUI"); + REGISTER_INT64_SETTING(TUI.ButtonLeft, section_tui_features, ButtonLeft) + REGISTER_INT64_SETTING(TUI.ButtonRight, section_tui_features, ButtonRight) + REGISTER_INT64_SETTING(TUI.WheelUp, section_tui_features, WheelUp) + REGISTER_INT64_SETTING(TUI.WheelDown, section_tui_features, WheelDown) + REGISTER_BOOL_SETTING(TUI.TUIAsInputSource, section_tui_features, TUIAsInputSource) + REGISTER_BOOL_SETTING(TUI.TUINerdFont, section_tui_features, TUINerdFont) + REGISTER_STRING_SETTING(TUI.TerminalCode, section_tui_features, TerminalCode) + REGISTER_STRING_SETTING(TUI.ArchiveCode, section_tui_features, ArchiveCode) + REGISTER_STRING_SETTING(TUI.SyncCode, section_tui_features, SyncCode) + REGISTER_STRING_SETTING(TUI.FileCode, section_tui_features, FileCode) + REGISTER_STRING_SETTING(TUI.EyeCode, section_tui_features, EyeCode) + REGISTER_STRING_SETTING(TUI.PuzzlePieceCode, section_tui_features, PuzzlePieceCode) + REGISTER_STRING_SETTING(TUI.AngleLeftCode, section_tui_features, AngleLeftCode) + REGISTER_STRING_SETTING(TUI.AngleRightCode, section_tui_features, AngleRightCode) + REGISTER_STRING_SETTING(TUI.BanCode, section_tui_features, BanCode) + REGISTER_STRING_SETTING(TUI.CopyCode, section_tui_features, CopyCode) + REGISTER_STRING_SETTING(TUI.SearchCode, section_tui_features, SearchCode) + #endif } } // namespace RC From ca3c52b0155eafdb34f2c38e89595928f8cbeb5f Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 20:26:20 -0600 Subject: [PATCH 090/213] nerd font tweak --- UE4SS/include/GUI/GUI.hpp | 6 ++++++ UE4SS/include/GUI/NerdFont.hpp | 14 ++++++++++++++ UE4SS/include/SettingsManager.hpp | 3 ++- UE4SS/src/GUI/GUI.cpp | 21 ++++++++------------- UE4SS/src/GUI/LiveView.cpp | 22 ++++++++-------------- UE4SS/src/SettingsManager.cpp | 2 ++ 6 files changed, 40 insertions(+), 28 deletions(-) create mode 100644 UE4SS/include/GUI/NerdFont.hpp diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index c3c55bd9b..d1d6e2b35 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -303,4 +303,10 @@ namespace RC::GUI code_to_try(); }); } + +#ifdef WIN32 + #define ATTACH_ICON(icon, str) icon str +#else + #define ATTACH_ICON(icon, str) ((icon str) + (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1))) +#endif } // namespace RC::GUI diff --git a/UE4SS/include/GUI/NerdFont.hpp b/UE4SS/include/GUI/NerdFont.hpp new file mode 100644 index 000000000..b44ed3935 --- /dev/null +++ b/UE4SS/include/GUI/NerdFont.hpp @@ -0,0 +1,14 @@ +#pragma once + +#define ICON_FA_TERMINAL "\uf120" +#define ICON_FA_ARCHIVE "\uf187" +#define ICON_FA_SYNC "\uf46a" +#define ICON_FA_FILE_ALT "\uf15b" +#define ICON_FA_EYE "\uf06e" +#define ICON_FA_PUZZLE_PIECE "\uf12e" + +#define ICON_FA_ANGLE_DOUBLE_LEFT "<<" +#define ICON_FA_ANGLE_DOUBLE_RIGHT ">>" +#define ICON_FA_BAN "\uf05e" +#define ICON_FA_COPY "\uf0c5" +#define ICON_FA_SEARCH "\uf002" diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index fdd2830fe..0304c291c 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -118,6 +118,7 @@ namespace RC int WheelDown = 5; bool TUIAsInputSource = true; bool TUINerdFont = true; + /* SystemStringType TerminalCode = "f120"; SystemStringType ArchiveCode = "f187"; SystemStringType SyncCode = "f46a"; @@ -128,7 +129,7 @@ namespace RC SystemStringType AngleRightCode = "f101"; SystemStringType BanCode = "f05e"; SystemStringType CopyCode = "f0c5"; - SystemStringType SearchCode = "f002"; + SystemStringType SearchCode = "f002";*/ } TUI; #endif diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index dcb058c24..12eaec493 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -27,12 +27,7 @@ #include "FaSolid900.hpp" #include #else // LINUX -#define ICON_FA_TERMINAL -#define ICON_FA_ARCHIVE -#define ICON_FA_SYNC -#define ICON_FA_FILE_ALT -#define ICON_FA_EYE -#define ICON_FA_PUZZLE_PIECE +#include #endif @@ -91,7 +86,7 @@ namespace RC::GUI if (ImGui::BeginTabBar("##MainTabBar", ImGuiTabBarFlags_None)) { - if (ImGui::BeginTabItem(ICON_FA_TERMINAL " Console")) + if (ImGui::BeginTabItem(ATTACH_ICON(ICON_FA_TERMINAL, " Console"))) { get_console().render_search_box(); @@ -103,7 +98,7 @@ namespace RC::GUI { ImGui::BeginDisabled(true); } - if (ImGui::Button(ICON_FA_ARCHIVE " Dump Objects & Properties")) + if (ImGui::Button(ATTACH_ICON(ICON_FA_ARCHIVE, " Dump Objects & Properties"))) { m_event_thread_busy = true; UE4SSProgram::get_program().queue_event( @@ -126,7 +121,7 @@ namespace RC::GUI ImGui::BeginDisabled(true); } ImGui::SameLine(); - if (ImGui::Button(ICON_FA_SYNC " Restart All Mods")) + if (ImGui::Button(ATTACH_ICON(ICON_FA_SYNC, " Restart All Mods"))) { m_event_thread_busy = true; UE4SSProgram::get_program().queue_event( @@ -154,7 +149,7 @@ namespace RC::GUI { ImGui::BeginDisabled(true); } - if (ImGui::BeginTabItem(ICON_FA_FILE_ALT " Live View")) + if (ImGui::BeginTabItem(ATTACH_ICON(ICON_FA_FILE_ALT, " Live View"))) { listeners_are_required = true; m_live_view.set_listeners(); @@ -166,7 +161,7 @@ namespace RC::GUI should_unset_listeners = true; } - if (ImGui::BeginTabItem(ICON_FA_EYE " Watches")) + if (ImGui::BeginTabItem(ATTACH_ICON(ICON_FA_EYE, " Watches"))) { listeners_are_required = true; m_live_view.render_watches(); @@ -182,13 +177,13 @@ namespace RC::GUI m_live_view.unset_listeners(); } - if (ImGui::BeginTabItem(ICON_FA_ARCHIVE " Dumpers")) + if (ImGui::BeginTabItem(ATTACH_ICON(ICON_FA_ARCHIVE, " Dumpers"))) { Dumpers::render(); ImGui::EndTabItem(); } - if (ImGui::BeginTabItem(ICON_FA_PUZZLE_PIECE " BP Mods")) + if (ImGui::BeginTabItem(ATTACH_ICON(ICON_FA_PUZZLE_PIECE, " BP Mods"))) { BPMods::render(); ImGui::EndTabItem(); diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 1b3628726..02465d961 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -52,12 +52,7 @@ #ifdef WIN32 #include #else -#define ICON_FA_ANGLE_DOUBLE_LEFT "<<" -#define ICON_FA_ANGLE_DOUBLE_RIGHT ">>" -#define ICON_FA_BAN -#define ICON_FA_COPY -#define ICON_FA_EYE -#define ICON_FA_SEARCH +#include #endif #undef max @@ -2859,7 +2854,7 @@ namespace RC::GUI { ImGui::BeginDisabled(); } - if (ImGui::Button(ICON_FA_SEARCH " Find functions")) + if (ImGui::Button(ATTACH_ICON(ICON_FA_SEARCH," Find functions"))) { m_function_caller_widget->open_widget_deferred(); } @@ -3401,7 +3396,7 @@ namespace RC::GUI if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::BeginTooltip(); - ImGui::Text(ICON_FA_BAN " Feature disabled due to 'General.bUseUObjectArrayCache' being set to 0 in UE4SS-settings.ini."); + ImGui::Text(ATTACH_ICON(ICON_FA_BAN, " Feature disabled due to 'General.bUseUObjectArrayCache' being set to 0 in UE4SS-settings.ini.")); ImGui::EndTooltip(); } } @@ -3425,9 +3420,7 @@ namespace RC::GUI } ImGui::SameLine(); - - // Remember to update text width calculations for the last ImGui::PushItemWidth call if this text gets updated. - if (ImGui::Button(ICON_FA_COPY " Copy search result")) + if (ImGui::Button(ATTACH_ICON(ICON_FA_COPY, " Copy search result"))) { SystemStringType result{}; auto is_below_425 = Version::IsBelow(4, 25); @@ -3448,6 +3441,7 @@ namespace RC::GUI // TODO: check the size for TUI as m_bottom_size = (ImGui::GetContentRegionMaxAbs().y - m_top_size) - 2.0f; m_bottom_size = std::max(ImGui::GetFrameHeight(), split_pane_height - m_top_size); // TODO: do we need ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, XOFFSET); on TUI? + // TODO: we need false, 0.5f? ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16.0f); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); @@ -3460,7 +3454,7 @@ namespace RC::GUI auto render_context_menu = [&] { if (ImGui::BeginPopupContextItem(tree_node_name.c_str())) { - if (ImGui::MenuItem(ICON_FA_COPY " Copy Full Name")) + if (ImGui::MenuItem(ATTACH_ICON(ICON_FA_COPY, " Copy Full Name"))) { Output::send(SYSSTR("Copy Full Name: {}\n"), object->GetFullName()); ImGui::SetClipboardText(tree_node_name.c_str()); @@ -3472,14 +3466,14 @@ namespace RC::GUI if (function_watcher_it == s_watch_map.end()) { ImGui::Separator(); - if (ImGui::MenuItem(ICON_FA_EYE " Watch value")) + if (ImGui::MenuItem(ATTACH_ICON(ICON_FA_EYE, " Watch value"))) { add_watch(watch_id, static_cast(object)); } } else { - ImGui::Checkbox(ICON_FA_EYE " Watch value", &function_watcher_it->second->enabled); + ImGui::Checkbox(ATTACH_ICON(ICON_FA_EYE, " Watch value"), &function_watcher_it->second->enabled); } } ImGui::EndPopup(); diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index 8ae745ad7..ba3863e24 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -133,6 +133,7 @@ namespace RC REGISTER_INT64_SETTING(TUI.WheelDown, section_tui_features, WheelDown) REGISTER_BOOL_SETTING(TUI.TUIAsInputSource, section_tui_features, TUIAsInputSource) REGISTER_BOOL_SETTING(TUI.TUINerdFont, section_tui_features, TUINerdFont) + /* REGISTER_STRING_SETTING(TUI.TerminalCode, section_tui_features, TerminalCode) REGISTER_STRING_SETTING(TUI.ArchiveCode, section_tui_features, ArchiveCode) REGISTER_STRING_SETTING(TUI.SyncCode, section_tui_features, SyncCode) @@ -144,6 +145,7 @@ namespace RC REGISTER_STRING_SETTING(TUI.BanCode, section_tui_features, BanCode) REGISTER_STRING_SETTING(TUI.CopyCode, section_tui_features, CopyCode) REGISTER_STRING_SETTING(TUI.SearchCode, section_tui_features, SearchCode) + */ #endif } } // namespace RC From 1c84bbbfaf8204ad22e678b8a111cf87b8a00b80 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 20:51:38 -0600 Subject: [PATCH 091/213] add TUI switch and verify console setting at start --- UE4SS/src/SettingsManager.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index ba3863e24..7b3bd31f3 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -82,6 +82,15 @@ namespace RC REGISTER_BOOL_SETTING(Debug.DebugConsoleEnabled, section_debug, GuiConsoleEnabled) REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) REGISTER_FLOAT_SETTING(Debug.DebugGUIFontScaling, section_debug, GuiConsoleFontScaling) + + #ifdef LINUX + #ifdef HAS_GUI + if (Debug.SimpleConsoleEnabled && Debug.DebugConsoleVisible && Debug.DebugConsoleEnabled) { + Debug.SimpleConsoleEnabled = false; + } + #endif + #endif + #ifdef HAS_GUI SystemStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) From 8fec8ce92471b88711abef0db3b98b4aac382716 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 21:06:45 -0600 Subject: [PATCH 092/213] add patch --- deps/third/imtui/fix-size-cjk-and-mouse.patch | 333 ++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 deps/third/imtui/fix-size-cjk-and-mouse.patch diff --git a/deps/third/imtui/fix-size-cjk-and-mouse.patch b/deps/third/imtui/fix-size-cjk-and-mouse.patch new file mode 100644 index 000000000..08eb7016c --- /dev/null +++ b/deps/third/imtui/fix-size-cjk-and-mouse.patch @@ -0,0 +1,333 @@ +diff --git a/include/imtui/imtui.h b/include/imtui/imtui.h +index b77c342..100a4d8 100644 +--- a/include/imtui/imtui.h ++++ b/include/imtui/imtui.h +@@ -21,7 +21,12 @@ using TColor = unsigned char; + // 0x0000FFFF - char + // 0x00FF0000 - foreground color + // 0xFF000000 - background color +-using TCell = uint32_t; ++//using TCell = uint32_t; ++ ++// 0x00000000FFFFFFFF - char ++// 0x000000FF00000000 - foreground color ++// 0x0000FF0000000000 - background color ++using TCell = uint64_t; + + struct TScreen { + int nx = 0; +diff --git a/src/imtui-impl-ncurses.cpp b/src/imtui-impl-ncurses.cpp +index 1d454ba..8b58dcf 100644 +--- a/src/imtui-impl-ncurses.cpp ++++ b/src/imtui-impl-ncurses.cpp +@@ -101,7 +101,8 @@ ImTui::TScreen * ImTui_ImplNcurses_Init(bool mouseSupport, float fps_active, flo + } + fps_idle = std::min(fps_active, fps_idle); + g_vsync = VSync(fps_active, fps_idle); +- ++ ++ setlocale(LC_ALL,""); + initscr(); + use_default_colors(); + start_color(); +@@ -150,6 +151,42 @@ ImTui::TScreen * ImTui_ImplNcurses_Init(bool mouseSupport, float fps_active, flo + + getmaxyx(stdscr, screenSizeY, screenSizeX); + ImGui::GetIO().DisplaySize = ImVec2(screenSizeX, screenSizeY); ++ static char encoding_table[64]; ++ for (int i = 0; i < 26; i++) { ++ encoding_table[i] = 'A' + i; ++ encoding_table[i + 26] = 'a' + i; ++ } ++ for (int i = 0; i < 10; i++) { ++ encoding_table[i + 52] = '0' + i; ++ } ++ encoding_table[62] = '+'; ++ encoding_table[63] = '/'; ++ ImGui::GetIO().SetClipboardTextFn = [](void* user_data, const char* text) { ++ // ncurses clipboard ++ int length = strlen(text); ++ refresh(); ++ printf("\e]52;c;"); ++ fprintf(stderr, "Base64: "); ++ for (int i = 0; i < length; ) { ++ uint32_t c = 0; ++ for (int j = 0; j < 3; j++) { ++ c = (c << 8) | (i < length ? (uint8_t) text[i++] : 0); ++ } ++ for (int j = 3; j >= 0; j--) { ++ printf("%c", encoding_table[(c >> (6*j)) & 0x3F]); ++ fprintf(stderr, "%c", encoding_table[(c >> (6*j)) & 0x3F]); ++ } ++ } ++ int pad = (length + 2) % 3; ++ for (int i = 0; i < pad; i++) { ++ printf("="); ++ fprintf(stderr, "="); ++ } ++ fprintf(stderr, "\n"); ++ printf("\a"); ++ fflush(stdout); ++ refresh(); ++ }; + + return g_screen; + } +@@ -178,8 +215,10 @@ bool ImTui_ImplNcurses_NewFrame() { + + static int mx = 0; + static int my = 0; +- static int lbut = 0; +- static int rbut = 0; ++ static int lbutdown = 0; ++ static int rbutdown = 0; ++ static int lbutup = 0; ++ static int rbutup = 0; + static unsigned long mstate = 0; + static char input[3]; + +@@ -196,8 +235,8 @@ bool ImTui_ImplNcurses_NewFrame() { + + if (c == ERR) { + if ((mstate & 0xf) == 0x1) { +- lbut = 0; +- rbut = 0; ++ lbutdown = lbutup = 0; ++ rbutdown = rbutup = 0; + } + break; + } else if (c == KEY_MOUSE) { +@@ -206,10 +245,14 @@ bool ImTui_ImplNcurses_NewFrame() { + mx = event.x; + my = event.y; + mstate = event.bstate; +- if ((mstate & 0x000f) == 0x0002) lbut = 1; +- if ((mstate & 0x000f) == 0x0001) lbut = 0; +- if ((mstate & 0xf000) == 0x2000) rbut = 1; +- if ((mstate & 0xf000) == 0x1000) rbut = 0; ++ if ((mstate & BUTTON1_PRESSED)) {lbutdown = 1; lbutup = 0; } ++ if ((mstate & BUTTON1_RELEASED)) {lbutdown = 0; lbutup = 1; } ++ if ((mstate & BUTTON3_PRESSED)) {rbutdown = 1; rbutup = 0; } ++ if ((mstate & BUTTON3_RELEASED)) {rbutdown = 0; rbutup = 1; } ++ ImGui::GetIO().MouseWheel = 0; ++ if ((mstate & BUTTON4_PRESSED)) {ImGui::GetIO().MouseWheel = 1; } ++ if ((mstate & BUTTON5_PRESSED)) {ImGui::GetIO().MouseWheel = -1; } ++ + //printf("mstate = 0x%016lx\n", mstate); + ImGui::GetIO().KeyCtrl |= ((mstate & 0x0F000000) == 0x01000000); + } +@@ -266,8 +309,12 @@ bool ImTui_ImplNcurses_NewFrame() { + + ImGui::GetIO().MousePos.x = mx; + ImGui::GetIO().MousePos.y = my; +- ImGui::GetIO().MouseDown[0] = lbut; +- ImGui::GetIO().MouseDown[1] = rbut; ++ ++ ImGui::GetIO().MouseDown[0] = lbutdown; ++ ImGui::GetIO().MouseDown[1] = rbutdown; ++ ++ ImGui::GetIO().MouseReleased[0] = lbutup; ++ ImGui::GetIO().MouseReleased[1] = rbutup; + + ImGui::GetIO().DeltaTime = g_vsync.delta_s(); + +@@ -315,8 +362,10 @@ void ImTui_ImplNcurses_DrawScreen(bool active) { + move(y, 0); + for (int x = 0; x < nx; ++x) { + const auto cell = g_screen->data[y*nx + x]; +- const uint16_t f = (cell & 0x00FF0000) >> 16; +- const uint16_t b = (cell & 0xFF000000) >> 24; ++ // const uint16_t f = (cell & 0x00FF0000) >> 16; ++ // const uint16_t b = (cell & 0xFF000000) >> 24; ++ const uint16_t f = ((cell >> 32) & 0xff); ++ const uint16_t b = ((cell >> 40) & 0xff); + const uint16_t p = b*256 + f; + + if (colPairs[p].first == false) { +@@ -337,8 +386,25 @@ void ImTui_ImplNcurses_DrawScreen(bool active) { + lastp = p; + } + +- const uint16_t c = cell & 0x0000FFFF; +- curs[ic++] = c > 0 ? c : ' '; ++ const uint32_t c = cell & 0xFFFFFFFF; ++ if (c > 0) { ++ // unicode to utf-8 ++ if (c < 0x80) { ++ curs[ic++] = (char) c; ++ } else if (c < 0x800) { ++ curs[ic++] = (char) (0xC0 | (c >> 6)); ++ curs[ic++] = (char) (0x80 | (c & 0x3F)); ++ } else if (c < 0x10000) { ++ curs[ic++] = (char) (0xE0 | (c >> 12)); ++ curs[ic++] = (char) (0x80 | ((c >> 6) & 0x3F)); ++ curs[ic++] = (char) (0x80 | (c & 0x3F)); ++ } else { ++ curs[ic++] = (char) (0xF0 | (c >> 18)); ++ curs[ic++] = (char) (0x80 | ((c >> 12) & 0x3F)); ++ curs[ic++] = (char) (0x80 | ((c >> 6) & 0x3F)); ++ curs[ic++] = (char) (0x80 | (c & 0x3F)); ++ } ++ } else curs[ic++] = ' '; + } + + if (curs.size() > 0) { +diff --git a/src/imtui-impl-text.cpp b/src/imtui-impl-text.cpp +index 48f0e70..afaa68f 100644 +--- a/src/imtui-impl-text.cpp ++++ b/src/imtui-impl-text.cpp +@@ -92,9 +92,12 @@ void drawTriangle(ImVec2 p0, ImVec2 p1, ImVec2 p2, unsigned char col, ImTui::TSc + while (len--) { + if (x >= 0 && x < screen->nx && y + ymin >= 0 && y + ymin < screen->ny) { + auto & cell = screen->data[(y + ymin)*screen->nx + x]; +- cell &= 0x00FF0000; ++ cell &= ~0x0000ff00fffffffful; + cell |= ' '; +- cell |= ((ImTui::TCell)(col) << 24); ++ cell |= ((uint64_t)col) << 40; ++ //cell &= 0x00FF0000; ++ //cell |= ' '; ++ //cell |= ((ImTui::TCell)(col) << 24); + } + ++x; + } +@@ -102,7 +105,7 @@ void drawTriangle(ImVec2 p0, ImVec2 p1, ImVec2 p2, unsigned char col, ImTui::TSc + } + } + +-inline ImTui::TColor rgbToAnsi256(ImU32 col, bool doAlpha) { ++ImTui::TColor rgbToAnsi256(ImU32 col, bool doAlpha) { + ImTui::TColor r = col & 0x000000FF; + ImTui::TColor g = (col & 0x0000FF00) >> 8; + ImTui::TColor b = (col & 0x00FF0000) >> 16; +@@ -196,8 +199,8 @@ void ImTui_ImplText_RenderDrawData(ImDrawData * drawData, ImTui::TScreen * scree + auto uv2 = cmd_list->VtxBuffer[vidx2].uv; + + auto col0 = cmd_list->VtxBuffer[vidx0].col; +- //auto col1 = cmd_list->VtxBuffer[vidx1].col; +- //auto col2 = cmd_list->VtxBuffer[vidx2].col; ++ auto col1 = cmd_list->VtxBuffer[vidx1].col; ++ auto col2 = cmd_list->VtxBuffer[vidx2].col; + + if (uv0.x != uv1.x || uv0.x != uv2.x || uv1.x != uv2.x || + uv0.y != uv1.y || uv0.y != uv2.y || uv1.y != uv2.y) { +@@ -225,9 +228,9 @@ void ImTui_ImplText_RenderDrawData(ImDrawData * drawData, ImTui::TScreen * scree + if (xx < clip_rect.x || xx >= clip_rect.z || yy < clip_rect.y || yy >= clip_rect.w) { + } else { + auto & cell = screen->data[yy*screen->nx + xx]; +- cell &= 0xFF000000; +- cell |= (col0 & 0xff000000) >> 24; +- cell |= ((ImTui::TCell)(rgbToAnsi256(col0, false)) << 16); ++ cell &= ~0xFFFFFFFFFFul; ++ cell |= (((uint64_t)rgbToAnsi256(col0, false)) << 32) ; // set color ++ cell |= (col0 >> 24) | (col1 >> 24 << 8) | (col2 >> 24 << 16); // set character + } + i += 3; + } else { +diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt +index b9c1f67..9d7f201 100644 +--- a/third-party/CMakeLists.txt ++++ b/third-party/CMakeLists.txt +@@ -18,6 +18,7 @@ add_library(imgui-for-imtui STATIC + imgui/imgui/imgui_demo.cpp + imgui/imgui/imgui_widgets.cpp + imgui/imgui/imgui_tables.cpp ++ imgui/imgui/misc/cpp/imgui_stdlib.cpp + ) + + target_include_directories(imgui-for-imtui INTERFACE +Submodule third-party/imgui/imgui contains modified content +diff --git a/third-party/imgui/imgui/imgui.cpp b/third-party/imgui/imgui/imgui.cpp +index c3f7d376..50c8acaf 100644 +--- a/third-party/imgui/imgui/imgui.cpp ++++ b/third-party/imgui/imgui/imgui.cpp +@@ -8457,9 +8457,9 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) + ImVec2 ref_pos = NavCalcPreferredRefPos(); + ImRect r_avoid; + if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)) +- r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); ++ r_avoid = ImRect(ref_pos.x - 1, ref_pos.y - 1, ref_pos.x + 1, ref_pos.y + 1); + else +- r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. ++ r_avoid = ImRect(ref_pos.x - 1, ref_pos.y - 1, ref_pos.x + 1 * sc, ref_pos.y + 1 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. + return FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip); + } + IM_ASSERT(0); +diff --git a/third-party/imgui/imgui/imgui_draw.cpp b/third-party/imgui/imgui/imgui_draw.cpp +index dc719e68..295fb2da 100644 +--- a/third-party/imgui/imgui/imgui_draw.cpp ++++ b/third-party/imgui/imgui/imgui_draw.cpp +@@ -3490,7 +3490,9 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col + } + + col &= 0x00FFFFFF; +- col |= (c << 24); ++ ImU32 c0 = (c & 0xFF) << 24; ++ ImU32 c1 = ((c >> 8) & 0xFF) << 24; ++ ImU32 c2 = ((c >> 16) & 0xFF) << 24; + // Support for untinted glyphs + ImU32 glyph_col = glyph->Colored ? col_untinted : col; + +@@ -3498,9 +3500,9 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col + { + idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); + idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); +- vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = glyph_col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; +- vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = glyph_col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; +- vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = glyph_col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; ++ vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = glyph_col | c0; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; ++ vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = glyph_col | c1; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; ++ vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = glyph_col | c2; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; + vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = glyph_col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2; + vtx_write += 4; + vtx_current_idx += 4; +diff --git a/third-party/imgui/imgui/imgui_widgets.cpp b/third-party/imgui/imgui/imgui_widgets.cpp +index 85a1d6bc..f10d9c55 100644 +--- a/third-party/imgui/imgui/imgui_widgets.cpp ++++ b/third-party/imgui/imgui/imgui_widgets.cpp +@@ -678,7 +678,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags + pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y; + //ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); + ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y + style.FramePadding.y * 2.0f); +- ++ size.x += 4; + const ImRect bb(pos, pos + size); + ItemSize(size, style.FramePadding.y); + if (!ItemAdd(bb, id)) +@@ -1073,7 +1073,7 @@ bool ImGui::Checkbox(const char* label, bool* v) + + const float square_sz = GetFrameHeight(); + const ImVec2 pos = window->DC.CursorPos; +- const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); ++ const ImRect total_bb(pos, pos + ImVec2(square_sz * 3 + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); + ItemSize(total_bb, style.FramePadding.y); + if (!ItemAdd(total_bb, id)) + { +@@ -1089,7 +1089,7 @@ bool ImGui::Checkbox(const char* label, bool* v) + MarkItemEdited(id); + } + +- const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); ++ const ImRect check_bb(pos, pos + ImVec2(square_sz * 3, square_sz)); + RenderNavHighlight(total_bb, id); + RenderFrame(check_bb.Min, check_bb.Max + ImVec2(0.5f, 0.0f), GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); + ImU32 check_col = GetColorU32(ImGuiCol_CheckMark); +@@ -1101,13 +1101,16 @@ bool ImGui::Checkbox(const char* label, bool* v) + //ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f))); + //window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); + const float pad = 0.5f; +- RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f, "O"); ++ RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f, "[O]"); + } + else if (*v) + { + //const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); + const float pad = 0.5f; +- RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); ++ RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f, "[X]"); ++ } else { ++ const float pad = 0.5f; ++ RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f, "[ ]"); + } + + ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); From a439b78cc1141cc044e82513e7fa3ccab8ba0b9f Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Feb 2024 21:57:26 -0600 Subject: [PATCH 093/213] fix scrollbar size on windows --- UE4SS/src/GUI/GUI.cpp | 5 ++++- UE4SS/src/GUI/LiveView.cpp | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 12eaec493..f53fe8c3b 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -369,8 +369,11 @@ namespace RC::GUI // You're not allowed to throw exceptions directly inside a frame! // Use GUI::TRY to move exceptions to the end of the frame. - //abort(); + #ifdef WIN32 + __debugbreak(); + #else asm("int3"); + #endif } ImGui::Render(); diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 02465d961..6489e3a2b 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -3445,8 +3445,12 @@ namespace RC::GUI ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16.0f); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); - ImGui::BeginChild("LiveView_TreeView", {-16.0f, m_top_size}, true); +#ifdef WIN32 + ImGui::BeginChild("LiveView_TreeView", {-16.0f, m_top_size}, true); +#else + ImGui::BeginChild("LiveView_TreeView", {0, m_top_size}, true); +#endif auto do_iteration = [&](int32_t int_data_1 = 0, int32_t int_data_2 = 0) { ((*this).*((*this).m_object_iterator))(int_data_1, int_data_2, [&](UObject* object) { auto tree_node_name = std::string{get_object_full_name(object)}; From e3e9c9396811e5fbc9a33e1192e97e165568dfd5 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 22 Feb 2024 22:13:02 -0600 Subject: [PATCH 094/213] fix crash on ctrl+c --- UE4SS/src/GUI/TUI.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/TUI.cpp index 12bd4bec0..1eb5fac80 100644 --- a/UE4SS/src/GUI/TUI.cpp +++ b/UE4SS/src/GUI/TUI.cpp @@ -10,6 +10,7 @@ namespace RC::GUI { static ImTui::TScreen * g_screen = nullptr; + static bool tui_shutdown = false; void Backend_TUI::init() { //fprintf(stderr, "Backend_TUI::init\n"); @@ -22,8 +23,9 @@ namespace RC::GUI fflush(stderr); atexit([]() { // ensure that the screen is destroyed - ImTui_ImplNcurses_Shutdown(); - g_screen = nullptr; + // ImTui_ImplNcurses_Shutdown(); do not call this here, we may not in UI thread + // set shutdown flag to allow async shutdown on UI thread + tui_shutdown = true; }); } @@ -44,6 +46,7 @@ namespace RC::GUI void Backend_TUI::shutdown() { ImTui_ImplNcurses_Shutdown(); g_screen = nullptr; + tui_shutdown = true; } void Backend_TUI::cleanup() { @@ -75,6 +78,9 @@ namespace RC::GUI } void Backend_GfxTUI::render(const float clear_color_with_alpha[4]) { + if (tui_shutdown) { + return; + } ImTui_ImplText_RenderDrawData(ImGui::GetDrawData(), g_screen); ImTui_ImplNcurses_DrawScreen(); } @@ -110,6 +116,6 @@ namespace RC::GUI } bool Backend_GfxTUI::exit_requested() { - return false; + return tui_shutdown; } }; // namespace RC::GUI From a141b741ca3a6861de640bce7e0e2e7720e5f486 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 23 Feb 2024 03:41:54 -0600 Subject: [PATCH 095/213] run when cmake change --- .github/workflows/linux-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index ba2a7d2be..38076f3fe 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -13,6 +13,7 @@ on: - "UE4SS/proxy_generator/**" - ".github/workflows/linux-test.yml" - "CMakeLists.txt" + - "cmake/**" permissions: contents: read From d884e70ccc88aab1c259caca9ed6691b3e345bfb Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 23 Feb 2024 04:42:45 -0600 Subject: [PATCH 096/213] use wide char version --- deps/third/imtui/fix-size-cjk-and-mouse.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/deps/third/imtui/fix-size-cjk-and-mouse.patch b/deps/third/imtui/fix-size-cjk-and-mouse.patch index 08eb7016c..88f327161 100644 --- a/deps/third/imtui/fix-size-cjk-and-mouse.patch +++ b/deps/third/imtui/fix-size-cjk-and-mouse.patch @@ -1,3 +1,16 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9376c4a..5e24536 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -64,6 +64,8 @@ if (IMTUI_SUPPORT_NCURSES) + if (MINGW) + set(CURSES_LIBRARIES pdcurses) + else() ++ set(CURSES_NEED_NCURSES TRUE) ++ set(CURSES_NEED_WIDE TRUE) + find_package(Curses REQUIRED) + CHECK_LIBRARY_EXISTS("${CURSES_NCURSES_LIBRARY}" + nodelay "" CURSES_NCURSES_HAS_NODELAY) diff --git a/include/imtui/imtui.h b/include/imtui/imtui.h index b77c342..100a4d8 100644 --- a/include/imtui/imtui.h From 3747005bdbf4780a9d684a35432e6a7e7e0e9c2f Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 24 Feb 2024 07:36:00 -0600 Subject: [PATCH 097/213] Case-insensitive path lookup --- UE4SS/src/Mod/LuaMod.cpp | 41 ++++++++++---------- UE4SS/src/UE4SSProgram.cpp | 43 +++++++++++---------- deps/first/File/include/File/File.hpp | 5 +++ deps/first/File/src/File.cpp | 54 +++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 40 deletions(-) diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 87a723238..8410ad9aa 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -646,26 +646,17 @@ namespace RC // Verify that there's a 'Scripts' directory // Give the full path to the 'Scripts' directory to the mod container std::filesystem::path mod_path_fs = m_mod_path; - auto path = (mod_path_fs / SYSSTR("scripts")); - if (std::filesystem::exists(path)) + auto scripts_directory = File::get_path_if_exists(mod_path_fs, "Scripts"); + if (scripts_directory) { // "scripts" get priority over "Scripts" - m_scripts_path = to_system(path); + m_scripts_path = to_system(*scripts_directory); } else { - // failed, we try the other case - path = (mod_path_fs / SYSSTR("Scripts")); - if (std::filesystem::exists(path)) - { - m_scripts_path = to_system(path); - } - else - { - // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod - set_installable(false); - return; - } + // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod + set_installable(false); + return; } } @@ -843,8 +834,12 @@ namespace RC lua_getfield(lua_state, -1, "path"); std::string current_paths = lua_tostring(lua_state, -1); - current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); - current_paths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + auto scripts_directory = File::get_path_if_exists(m_mod_path, "Scripts"); + if (scripts_directory) + { + auto scripts_path = ((*scripts_directory) / "?.lua").string(); + current_paths.append(std::format(";{}", scripts_path)); + } current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); current_paths.append(std::format(";{}" LUA_DIRSEP "shared" LUA_DIRSEP "?" LUA_DIRSEP "?.lua", to_string(m_program.get_mods_directory()).c_str())); lua_pop(lua_state, 1); @@ -853,9 +848,13 @@ namespace RC lua_getfield(lua_state, -1, "cpath"); std::string current_cpaths = lua_tostring(lua_state, -1); - current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); - current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "Scripts" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); - current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "?.dll", to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + if (scripts_directory) + { + #define STRINGIFY(x) #x + auto dlls_path = ((*scripts_directory) / ("?" STRINGIFY(DLLEXT))).string(); + current_cpaths.append(std::format(";{}", dlls_path)); + } + current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "?" STRINGIFY(DLLEXT), to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); lua_pop(lua_state, 1); lua_pushstring(lua_state, current_cpaths.c_str()); lua_setfield(lua_state, -2, "cpath"); @@ -2274,7 +2273,7 @@ No overload found for function 'CreateLogicModsDirectory'. lua.throw_error("CreateLogicModsDirectory: Could not locate the \"Content\" directory because the directory structure is unknown (not " "/Game/Content)\n"); } - auto logic_mods_dir = game_content_dir / "Paks/LogicMods"; + auto logic_mods_dir = game_content_dir / "Paks" / "LogicMods"; if (std::filesystem::exists(logic_mods_dir)) { Output::send( diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 9e9f7b87a..ec941cc8c 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -445,13 +445,23 @@ namespace RC } m_log_directory = m_working_directory; - m_settings_path_and_file.append(m_settings_file_name); - - // Check for legacy locations and update paths accordingly - if (std::filesystem::exists(m_legacy_root_directory / m_settings_file_name) && !std::filesystem::exists(m_settings_path_and_file)) + auto resolaved_settings_file = File::get_path_if_exists(m_settings_path_and_file, m_settings_file_name); + if (resolaved_settings_file) + { + m_settings_path_and_file = *resolaved_settings_file; + } + else { - m_settings_path_and_file = m_legacy_root_directory / m_settings_file_name; + // Check for legacy locations and update paths accordingly + resolaved_settings_file = File::get_path_if_exists(m_legacy_root_directory, m_settings_file_name); + if (resolaved_settings_file) + { + m_settings_path_and_file = *resolaved_settings_file; + } else { + throw std::runtime_error{"UE4SS-Settings.ini file not found"}; + } } + if (std::filesystem::exists(m_legacy_root_directory / "Mods") && !std::filesystem::exists(m_mods_directory)) { m_mods_directory = m_legacy_root_directory / "Mods"; @@ -1051,17 +1061,14 @@ namespace RC else { // Create the mod but don't install it yet - if (std::filesystem::exists(sub_directory.path() / "scripts")) - m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); - #ifdef LINUX - else if (std::filesystem::exists(sub_directory.path() / "Scripts")) - // avoid we have both "scripts" and "Scripts" in the same mod + auto scripts_directory = File::get_path_if_exists(sub_directory.path(), "Scripts"); + auto dlls_directory = File::get_path_if_exists(sub_directory.path(), "dlls"); + if (scripts_directory) { m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); - #endif -#ifdef HAS_CPPMOD - if (std::filesystem::exists(sub_directory.path() / "dlls")) + } + if (dlls_directory) { m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); -#endif + } } } } @@ -1247,14 +1254,12 @@ namespace RC return std::format("is_directory ran into error {}", ec.value()); } - if (!std::filesystem::exists(mod_directory.path() / "enabled.txt", ec)) + auto enabled = File::get_path_if_exists(mod_directory.path(), "enabled.txt"); + + if (!enabled.has_value()) { continue; } - if (ec.value() != 0) - { - return std::format("exists ran into error {}", ec.value()); - } auto mod = UE4SSProgram::find_mod_by_name(to_system_string(mod_directory.path().stem()), UE4SSProgram::IsInstalled::Yes); if (!dynamic_cast(mod)) diff --git a/deps/first/File/include/File/File.hpp b/deps/first/File/include/File/File.hpp index c0e38bf13..6b6dee62b 100644 --- a/deps/first/File/include/File/File.hpp +++ b/deps/first/File/include/File/File.hpp @@ -13,4 +13,9 @@ namespace RC::File CreateIfNonExistent = CreateIfNonExistent::No) -> Handle; RC_FILE_API auto delete_file(const std::filesystem::path& file_path_and_name) -> void; + + + // Search a path that can access `base / tail`, where the tail part is allowed to be case insensitive. + // Returns the path found or std::nullopt if no path was found. + RC_FILE_API auto get_path_if_exists(const std::filesystem::path& base, const std::filesystem::path& tail) -> std::optional; } // namespace RC::File diff --git a/deps/first/File/src/File.cpp b/deps/first/File/src/File.cpp index 6869475cb..c2cfe7a1d 100644 --- a/deps/first/File/src/File.cpp +++ b/deps/first/File/src/File.cpp @@ -1,7 +1,19 @@ #include +#include namespace RC::File { + // we can't access helper/string here? or can we add helper to file's dep? + static bool case_insensitive_equals(char a, char b) + { + return std::tolower(static_cast(a)) == std::tolower(static_cast(b)); + } + + static bool case_insensitive_compare(const std::string& a, const std::string& b) + { + return std::equal(a.begin(), a.end(), b.begin(), b.end(), case_insensitive_equals); + } + auto construct_handle(const std::filesystem::path& file_name, const OpenProperties& open_properties) -> Handle { auto internal_handle = Handle::FileType::open_file(file_name, open_properties); @@ -26,4 +38,46 @@ namespace RC::File { Handle::FileType::delete_file(file_path_and_name); } + + auto get_path_if_exists(const std::filesystem::path& base, const std::filesystem::path& tail) -> std::optional + { + if (!std::filesystem::exists(base)) + { + throw std::runtime_error("Base path does not exist: " + base.string()); + } + if (tail.is_absolute()) + { + throw std::runtime_error("Tail path must be relative: " + tail.string()); + } + auto normalized_tail = tail.lexically_normal(); + auto full_path = base.lexically_normal(); + for (const auto& part : normalized_tail) + { + if (std::filesystem::exists(full_path / part)) + { + full_path /= part; + } + else + { + bool found = false; + for (const auto& entry : std::filesystem::directory_iterator(full_path)) + { + // case-insensitive comparison + auto entry_filename = entry.path().filename().string(); + auto part_filename = part.string(); + if (case_insensitive_compare(entry_filename, part_filename)) + { + full_path /= entry.path().filename(); + found = true; + break; + } + } + if (!found) + { + return std::nullopt; + } + } + } + return full_path; + } } // namespace RC::File \ No newline at end of file From addb306f42c43a475cdfd2694d542a70bc5ba20d Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 24 Feb 2024 15:50:36 -0600 Subject: [PATCH 098/213] use Helper/String for case-insensitive cmp --- deps/first/File/src/File.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/deps/first/File/src/File.cpp b/deps/first/File/src/File.cpp index c2cfe7a1d..4a2356356 100644 --- a/deps/first/File/src/File.cpp +++ b/deps/first/File/src/File.cpp @@ -1,19 +1,10 @@ #include #include +#include + namespace RC::File { - // we can't access helper/string here? or can we add helper to file's dep? - static bool case_insensitive_equals(char a, char b) - { - return std::tolower(static_cast(a)) == std::tolower(static_cast(b)); - } - - static bool case_insensitive_compare(const std::string& a, const std::string& b) - { - return std::equal(a.begin(), a.end(), b.begin(), b.end(), case_insensitive_equals); - } - auto construct_handle(const std::filesystem::path& file_name, const OpenProperties& open_properties) -> Handle { auto internal_handle = Handle::FileType::open_file(file_name, open_properties); @@ -65,7 +56,7 @@ namespace RC::File // case-insensitive comparison auto entry_filename = entry.path().filename().string(); auto part_filename = part.string(); - if (case_insensitive_compare(entry_filename, part_filename)) + if (String::iequal(entry_filename, part_filename)) { full_path /= entry.path().filename(); found = true; From 849126bb11d78d48517f8324a818232e3de0a0c7 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 00:43:06 -0600 Subject: [PATCH 099/213] add uengine --- scripts/HeaderGen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/HeaderGen.py b/scripts/HeaderGen.py index d35784dbb..631050879 100755 --- a/scripts/HeaderGen.py +++ b/scripts/HeaderGen.py @@ -124,7 +124,7 @@ def GetClassNames(search_dir = DEFAULT_SEARCH_DIR): # replace _ to : return [x.replace("_", ":") for x in l] """ - return ['FArchiveState', 'UDataTable', 'FConsoleManager', 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct::ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] + return ['FArchiveState', 'UDataTable', 'FConsoleManager', "UEngine", 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct::ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] AdditonalClasses = [] From 04668e945fb2095506172a3e5f040ceba097294e Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 00:45:18 -0600 Subject: [PATCH 100/213] Add input source for Linux TUI and update input handler initialization --- UE4SS/include/SettingsManager.hpp | 1 + UE4SS/include/UE4SSProgram.hpp | 8 +- UE4SS/src/GUI/TUI.cpp | 27 +- UE4SS/src/SettingsManager.cpp | 9 +- UE4SS/src/UE4SSProgram.cpp | 24 +- UVTD/src/UVTD.cpp | 4 +- deps/first/Input/include/Input/Common.hpp | 13 + deps/first/Input/include/Input/Handler.hpp | 87 ++-- deps/first/Input/include/Input/KeyDef.hpp | 58 ++- .../Input/Platform/NcursesInputSource.hpp | 32 ++ .../Input/Platform/QueueInputSource.hpp | 42 ++ .../Input/Platform/Win32APIInputSource.hpp | 68 +++ .../include/Input/PlatformInputSource.hpp | 35 ++ deps/first/Input/include/Input/RingBuffer.hpp | 48 +++ deps/first/Input/src/Handler.cpp | 396 ++++++------------ deps/first/Input/src/KeyDef.cpp | 71 ++++ .../Input/src/Platform/NcursesInputSource.cpp | 219 ++++++++++ .../Input/src/Platform/QueneInputSource.cpp | 43 ++ .../src/Platform/Win32APIInputSource.cpp | 98 +++++ deps/first/Input/src/PlatformInit.cpp | 16 + 20 files changed, 969 insertions(+), 330 deletions(-) create mode 100644 deps/first/Input/include/Input/Platform/NcursesInputSource.hpp create mode 100644 deps/first/Input/include/Input/Platform/QueueInputSource.hpp create mode 100644 deps/first/Input/include/Input/Platform/Win32APIInputSource.hpp create mode 100644 deps/first/Input/include/Input/PlatformInputSource.hpp create mode 100644 deps/first/Input/include/Input/RingBuffer.hpp create mode 100644 deps/first/Input/src/Platform/NcursesInputSource.cpp create mode 100644 deps/first/Input/src/Platform/QueneInputSource.cpp create mode 100644 deps/first/Input/src/Platform/Win32APIInputSource.cpp create mode 100644 deps/first/Input/src/PlatformInit.cpp diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index 0304c291c..cc682614c 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -28,6 +28,7 @@ namespace RC bool EnableDebugKeyBindings{false}; int64_t SecondsToScanBeforeGivingUp{30}; bool UseUObjectArrayCache{true}; + SystemStringType InputSource{"Default"}; } General; struct SectionEngineVersionOverride diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index fcafdb21c..eeb7ec7d1 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -108,7 +108,7 @@ namespace RC protected: #ifdef HAS_INPUT - Input::Handler m_input_handler{SYSSTR("ConsoleWindowClass"), SYSSTR("UnrealWindow")}; + Input::Handler m_input_handler; #endif std::jthread m_event_loop; @@ -245,6 +245,12 @@ namespace RC RC_UE4SS_API auto generate_uht_compatible_headers() -> void; RC_UE4SS_API auto generate_cxx_headers(const std::filesystem::path& output_dir) -> void; RC_UE4SS_API auto generate_lua_types(const std::filesystem::path& output_dir) -> void; +#ifdef HAS_INPUT + auto get_input_handler() -> Input::Handler& + { + return m_input_handler; + } +#endif #ifdef HAS_GUI auto get_debugging_ui() -> GUI::DebuggingGUI& { diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/TUI.cpp index 1eb5fac80..e7a4f229a 100644 --- a/UE4SS/src/GUI/TUI.cpp +++ b/UE4SS/src/GUI/TUI.cpp @@ -1,5 +1,8 @@ #include +#include +#include + #include #include @@ -11,13 +14,17 @@ namespace RC::GUI { static ImTui::TScreen * g_screen = nullptr; static bool tui_shutdown = false; - + static std::shared_ptr ncurses_source{}; + int saved_stderr = -1; void Backend_TUI::init() { //fprintf(stderr, "Backend_TUI::init\n"); g_screen = ImTui_ImplNcurses_Init(true); + auto source = Input::Handler::get_input_source("Ncurses"); + ncurses_source = std::dynamic_pointer_cast(source); // disable stderr - freopen("./tui.log", "w+", stderr); + saved_stderr = dup(STDERR_FILENO); + freopen("/dev/null", "w", stderr); setbuf(stderr, NULL); fprintf(stderr, "Backend_TUI::init\n"); fflush(stderr); @@ -31,7 +38,17 @@ namespace RC::GUI void Backend_TUI::imgui_backend_newframe() { //fprintf(stderr, "Backend_TUI::imgui_backend_newframe\n"); - ImTui_ImplNcurses_NewFrame(); + if (ncurses_source) { + ncurses_source->begin_frame(); + } + ImTui_ImplNcurses_NewFrame([] (int x) { + if (ncurses_source) { + ncurses_source->receive_input(x); + } + }); + if (ncurses_source) { + ncurses_source->end_frame(); + } } void Backend_TUI::create_window() { @@ -47,6 +64,10 @@ namespace RC::GUI ImTui_ImplNcurses_Shutdown(); g_screen = nullptr; tui_shutdown = true; + dup2(saved_stderr, STDERR_FILENO); + close(saved_stderr); + saved_stderr = -1; + fprintf(stderr, "Backend_TUI::shutdown, stderr restored\n"); } void Backend_TUI::cleanup() { diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index 7b3bd31f3..00935cfef 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -56,6 +56,7 @@ namespace RC REGISTER_BOOL_SETTING(General.EnableDebugKeyBindings, section_general, EnableDebugKeyBindings) REGISTER_INT64_SETTING(General.SecondsToScanBeforeGivingUp, section_general, SecondsToScanBeforeGivingUp) REGISTER_BOOL_SETTING(General.UseUObjectArrayCache, section_general, bUseUObjectArrayCache) + REGISTER_STRING_SETTING(General.InputSource, section_general, InputSource) constexpr static SystemCharType section_engine_version_override[] = SYSSTR("EngineVersionOverride"); REGISTER_INT64_SETTING(EngineVersionOverride.MajorVersion, section_engine_version_override, MajorVersion) @@ -83,14 +84,6 @@ namespace RC REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) REGISTER_FLOAT_SETTING(Debug.DebugGUIFontScaling, section_debug, GuiConsoleFontScaling) - #ifdef LINUX - #ifdef HAS_GUI - if (Debug.SimpleConsoleEnabled && Debug.DebugConsoleVisible && Debug.DebugConsoleEnabled) { - Debug.SimpleConsoleEnabled = false; - } - #endif - #endif - #ifdef HAS_GUI SystemStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index ec941cc8c..3e5a326b0 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -200,6 +200,10 @@ namespace RC m_debugging_gui.set_gfx_backend(settings_manager.Debug.GraphicsAPI); #endif +#ifdef HAS_INPUT + m_input_handler.init(); +#endif + // Setup the log file auto& file_device = Output::set_default_devices(); file_device.set_file_name_and_path(to_system(m_log_directory / m_log_file_name)); @@ -907,6 +911,20 @@ namespace RC SYSSTR("FAssetData not available in <4.17, ignoring 'LoadAllAssetsBeforeDumpingObjects' & 'LoadAllAssetsBeforeGeneratingCXXHeaders'.")); } + +#ifdef HAS_INPUT + if (! settings_manager.General.InputSource.empty()) + { + if (m_input_handler.set_input_source(settings_manager.General.InputSource)) { + Output::send(SYSSTR("Input source set to: {}\n"), m_input_handler.get_current_input_source()); + } + else + { + Output::send(SYSSTR("Failed to set input source to: {}\n"), settings_manager.General.InputSource); + } + } +#endif + install_lua_mods(); LuaMod::on_program_start(); fire_program_start_for_cpp_mods(); @@ -1370,9 +1388,7 @@ namespace RC // Remove key binds that were set from Lua scripts #ifdef HAS_INPUT - auto& key_events = m_input_handler.get_events(); - std::erase_if(key_events, [](Input::KeySet& input_event) -> bool { - bool were_all_events_registered_from_lua = true; + m_input_handler.get_events_safe([&](Input::KeySet& input_event) -> void { for (auto& [key, vector_of_key_data] : input_event.key_data) { std::erase_if(vector_of_key_data, [&](Input::KeyData& key_data) -> bool { @@ -1389,8 +1405,6 @@ namespace RC } }); } - - return were_all_events_registered_from_lua; }); #endif diff --git a/UVTD/src/UVTD.cpp b/UVTD/src/UVTD.cpp index 13853ae80..32817de0b 100644 --- a/UVTD/src/UVTD.cpp +++ b/UVTD/src/UVTD.cpp @@ -25,7 +25,7 @@ namespace RC::UVTD { bool processing_events{false}; - Input::Handler input_handler{L"ConsoleWindowClass", L"UnrealWindow"}; + Input::Handler input_handler {}; auto static event_loop_update() -> void { @@ -38,6 +38,8 @@ namespace RC::UVTD auto main(DumpSettings dump_settings) -> void { + input_handler.init(); + input_handler.set_input_source("Win32Async"); static std::vector pdbs_to_dump{ "PDBs/4_10.pdb", "PDBs/4_11.pdb", diff --git a/deps/first/Input/include/Input/Common.hpp b/deps/first/Input/include/Input/Common.hpp index ca6c5f89a..15451f69b 100644 --- a/deps/first/Input/include/Input/Common.hpp +++ b/deps/first/Input/include/Input/Common.hpp @@ -1,6 +1,9 @@ #pragma once +#ifdef WIN32 + #ifndef RC_INPUT_EXPORTS + #ifndef RC_INPUT_BUILD_STATIC #ifndef RC_INPUT_API #define RC_INPUT_API __declspec(dllimport) @@ -10,8 +13,18 @@ #define RC_INPUT_API #endif #endif + #else #ifndef RC_INPUT_API #define RC_INPUT_API __declspec(dllexport) #endif #endif + +#else + +#ifndef RC_INPUT_API +#define RC_INPUT_API +#endif + +#endif + diff --git a/deps/first/Input/include/Input/Handler.hpp b/deps/first/Input/include/Input/Handler.hpp index ebc1ad592..c411474a6 100644 --- a/deps/first/Input/include/Input/Handler.hpp +++ b/deps/first/Input/include/Input/Handler.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -14,17 +15,24 @@ namespace RC::Input { using EventCallbackCallable = std::function; - - auto is_modifier_key_required(ModifierKey, std::vector) -> bool; + + struct InputEvent + { + Key key; + ModifierKeys modifier_keys{}; + }; struct KeyData { - std::vector required_modifier_keys{}; - std::vector callbacks{}; + ModifierKeys required_modifier_keys{}; + EventCallbackCallable callback{}; uint8_t custom_data{}; +<<<<<<< HEAD void* custom_data2{}; bool requires_modifier_keys{}; bool is_down{}; +======= +>>>>>>> 83b273a (Add input source for Linux TUI and update input handler initialization) }; struct KeySet @@ -32,48 +40,30 @@ namespace RC::Input std::unordered_map> key_data; }; + class PlatformInputSource; class RC_INPUT_API Handler { private: - std::vector m_active_window_classes{}; - std::vector m_key_sets{}; - std::unordered_map m_modifier_keys_down{}; - bool m_any_keys_are_down{}; + //std::vector m_key_sets{}; + KeySet m_key_set{}; bool m_allow_input{true}; + std::array m_subscribed_keys{}; + + std::shared_ptr m_platform_handler; + std::mutex m_event_mutex; public: - Handler() = delete; - template - explicit Handler(WindowClasses... window_classes) - { - static_assert(std::conjunction...>::value, "WindowClasses must be of type const wchar_t*"); - - m_modifier_keys_down.emplace(ModifierKey::SHIFT, false); - m_modifier_keys_down.emplace(ModifierKey::CONTROL, false); - m_modifier_keys_down.emplace(ModifierKey::ALT, false); - - register_window_classes(window_classes...); - } - - private: - template - auto register_window_classes(WindowClass window_class) -> void - { - m_active_window_classes.emplace_back(window_class); - } - - template - auto register_window_classes(WindowClass window_class, WindowClasses... window_classes) -> void - { - m_active_window_classes.emplace_back(window_class); - register_window_classes(window_classes...); - } - - auto are_modifier_keys_down(const std::vector&) -> bool; - auto is_program_focused() -> bool; + Handler() {}; + // Input source and event processing public: + auto set_input_source(std::string source) -> bool; auto process_event() -> void; + + // Interfaces for UE4SS and ModSystem for event registration + public: + auto init() -> void; + auto register_keydown_event(Input::Key, EventCallbackCallable, uint8_t custom_data = 0, void* custom_data2 = nullptr) -> void; using ModifierKeyArray = std::array; @@ -82,10 +72,31 @@ namespace RC::Input auto is_keydown_event_registered(Input::Key) -> bool; auto is_keydown_event_registered(Input::Key, const ModifierKeyArray&) -> bool; + + auto get_events_safe(std::function) -> void; + auto clear_subscribed_keys() -> void; - auto get_events() -> std::vector&; + auto has_event_on_key(Input::Key key) -> bool; + auto get_subscribed_keys() const -> const std::array& { return m_subscribed_keys; } + auto get_allow_input() -> bool; auto set_allow_input(bool new_value) -> void; + + auto get_current_input_source() -> std::string; + + private: + static std::unordered_map> m_input_sources_store; + static auto register_input_source(std::shared_ptr input_source) -> void; + + public: + static auto get_input_source(std::string source) -> std::shared_ptr + { + if (m_input_sources_store.find(source) != m_input_sources_store.end()) + { + return m_input_sources_store[source]; + } + return nullptr; + } }; } // namespace RC::Input diff --git a/deps/first/Input/include/Input/KeyDef.hpp b/deps/first/Input/include/Input/KeyDef.hpp index 02ec12976..91ba0e1fb 100644 --- a/deps/first/Input/include/Input/KeyDef.hpp +++ b/deps/first/Input/include/Input/KeyDef.hpp @@ -1,13 +1,12 @@ #pragma once #include - +#include namespace RC::Input { static constexpr uint32_t max_callbacks_per_event = 30; static constexpr uint8_t max_keys = 0xFF; -#ifdef _WIN32 enum Key : uint8_t { RESERVED_START_OF_ENUM = 0x0, @@ -244,11 +243,60 @@ namespace RC::Input MODIFIER_KEYS_MAX, }; + static inline bool is_modify_key_valid(ModifierKey key) + { + return (key < MODIFIER_KEYS_MAX) && (key > MOD_KEY_START_OF_ENUM); + } + + struct ModifierKeys + { + /// SAFETY: This is a bitfield, following static_assert ensures that the bitfield is not larger than 32 bits + uint32_t keys; + + // allow ops between keys + + auto operator|(const ModifierKeys &key) -> ModifierKeys&; + auto operator|=(const ModifierKeys &key) -> ModifierKeys&; + auto operator|(const ModifierKey &key) -> ModifierKeys&; + auto operator|=(const ModifierKey &key) -> ModifierKeys&; + + auto operator==(const ModifierKeys& key) const -> bool; + auto operator!=(const ModifierKeys& key) const -> bool; + + auto operator<(const ModifierKeys& key) const -> bool; + auto operator>(const ModifierKeys& key) const -> bool; + + + ModifierKeys(const ModifierKey key) : keys{is_modify_key_valid(key) ? (1 << key) : 0} {}; + ModifierKeys(const ModifierKeys& other) : keys{other.keys} {}; + + ModifierKeys() : keys{0} {}; + + template + ModifierKeys(ModifierKey key, Args... args) : keys{ (is_modify_key_valid(key) ? (1 << key) : 0) | ModifierKeys(args...).keys} {}; + + ModifierKeys(std::initializer_list keys); + + template + ModifierKeys(const TArray& keys) : keys{0} + { + for (auto key : keys) + { + if (is_modify_key_valid(key)) + { + this->keys |= (1 << key); + } + } + } + + bool empty() const { return keys == 0; } + }; + static constexpr uint8_t max_modifier_keys = MODIFIER_KEYS_MAX; + static_assert(max_modifier_keys < 32, "Modifier keys cannot exceed 32"); -#else - static_assert(false, "The input library only works on Windows."); -#endif + auto operator&(const ModifierKeys& keys, const ModifierKey& key) -> bool; + auto operator&(const ModifierKeys& keys, const ModifierKeys& key) -> bool; auto operator++(Input::Key& key) -> Input::Key&; } // namespace RC::Input diff --git a/deps/first/Input/include/Input/Platform/NcursesInputSource.hpp b/deps/first/Input/include/Input/Platform/NcursesInputSource.hpp new file mode 100644 index 000000000..feba5ea4c --- /dev/null +++ b/deps/first/Input/include/Input/Platform/NcursesInputSource.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace RC::Input +{ + + class NcursesInputSource : public QueueInputSource + { + public: + auto begin_frame() -> void; + auto receive_input(int input) -> void; + auto end_frame() -> void; + + private: + /// SAFETY: Only update inside begin_frame ... receive_input(...) ... end_frame + std::vector m_key_cur{}; + std::vector m_key_last{}; + bool m_is_alt_down; + + public: + NcursesInputSource():m_is_alt_down(false) { + m_key_cur.resize(256, false); + m_key_last.resize(256, false); + } + + auto is_available() -> bool override; + const char* get_name() override { return "Ncurses"; } + }; + +} diff --git a/deps/first/Input/include/Input/Platform/QueueInputSource.hpp b/deps/first/Input/include/Input/Platform/QueueInputSource.hpp new file mode 100644 index 000000000..e80fbbb84 --- /dev/null +++ b/deps/first/Input/include/Input/Platform/QueueInputSource.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#include + +namespace RC::Input +{ + class QueueInputSource : public PlatformInputSource + { + private: + static constexpr int max_inputs = 256; + RingBufferSPSC m_input_queue; + protected: + bool m_activated {false}; + private: + /// SAFETY: Only update and return m_input_events + /// in process_event and flush_events functions + std::vector m_input_events; + public: + ~QueueInputSource() = default; + + // QueeueInputSource is not a implemented input source + // and should not be used directly + bool is_available() override { return false; }; + + bool activate() override { return m_activated = true; }; + + bool deactivate() override { m_activated = false; return true; }; + + std::vector& process_event(Handler* handler) override; + + int source_priority() override { return 0; } + + const char* get_name() override { return "Queue"; } + + public: + auto push_input_event(const InputEvent& event) -> void; + }; + +}; // RC::Input \ No newline at end of file diff --git a/deps/first/Input/include/Input/Platform/Win32APIInputSource.hpp b/deps/first/Input/include/Input/Platform/Win32APIInputSource.hpp new file mode 100644 index 000000000..72b6dc12f --- /dev/null +++ b/deps/first/Input/include/Input/Platform/Win32APIInputSource.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace RC::Input +{ + class Win32InputSource : public PlatformInputSource + { + private: + std::vector m_active_window_classes{}; + std::unordered_map m_modifier_keys_down{}; + bool m_any_keys_are_down{}; + bool m_activated {false}; + std::array m_key_down{}; + + private: + /// SAFETY: Only update and return m_input_events + /// in the process_event function + std::vector m_input_events{}; + public: + template + explicit Win32InputSource(WindowClasses... window_classes) + { + static_assert(std::conjunction...>::value, "WindowClasses must be of type const wchar_t*"); + + m_modifier_keys_down.emplace(ModifierKey::SHIFT, false); + m_modifier_keys_down.emplace(ModifierKey::CONTROL, false); + m_modifier_keys_down.emplace(ModifierKey::ALT, false); + + register_window_classes(window_classes...); + } + + private: + template + auto register_window_classes(WindowClass window_class) -> void + { + m_active_window_classes.emplace_back(window_class); + } + + template + auto register_window_classes(WindowClass window_class, WindowClasses... window_classes) -> void + { + m_active_window_classes.emplace_back(window_class); + register_window_classes(window_classes...); + } + + auto are_modifier_keys_down(const std::vector&) -> bool; + auto is_program_focused() -> bool; + + public: + bool is_available() override { return true; }; + + bool activate() override { m_key_down.fill(false); return m_activated = true; }; + + bool deactivate() override { m_activated = false; return true; }; + + std::vector& Win32InputSource::process_event(Handler* handler) override; + ~Win32InputSource() = default; + int source_priority() override { return 0; } + + const char* get_name() override { return "Win32Async"; } + }; +}; diff --git a/deps/first/Input/include/Input/PlatformInputSource.hpp b/deps/first/Input/include/Input/PlatformInputSource.hpp new file mode 100644 index 000000000..f488f26d9 --- /dev/null +++ b/deps/first/Input/include/Input/PlatformInputSource.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include +#include + +namespace RC::Input +{ + + class PlatformInputSource + { + public: + /// Check if the input source is available + virtual bool is_available() { return false; }; + + /// Initialize the input source + virtual bool activate() { return false; }; + + /// Initialize the input source + virtual bool deactivate() { return false; }; + + /// Get the priority of the input source, smaller number means higher priority + virtual int source_priority() { return 999; }; + + /// Process the event and return the input events in the frame + virtual std::vector& process_event(Handler* handler) = 0; + + virtual ~PlatformInputSource() = default; + + virtual const char* get_name() { return "Unknown"; } + }; + +}; // RC::Input + diff --git a/deps/first/Input/include/Input/RingBuffer.hpp b/deps/first/Input/include/Input/RingBuffer.hpp new file mode 100644 index 000000000..d786d70b5 --- /dev/null +++ b/deps/first/Input/include/Input/RingBuffer.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +namespace RC::Input +{ + /// SAFETY: This is ONLY a single producer, single consumer lock-free queue + template + struct RingBufferSPSC + { + T m_queue[max_buffer]; + std::atomic m_head{0}; + std::atomic m_tail{0}; + + // tail belongs to the producer + auto push(const T& event) -> bool + { + auto current_tail = m_tail.load(std::memory_order_relaxed); + int next_tail = (current_tail + 1) % max_buffer; + if (next_tail == m_head.load(std::memory_order_acquire)) + { + // Queue is full + return false; + } + + m_queue[current_tail] = event; + m_tail.store(next_tail, std::memory_order_release); + return true; + } + + // head belongs to the consumer + auto pop() -> std::optional + { + auto current_head = m_head.load(std::memory_order_relaxed); + if (current_head == m_tail.load(std::memory_order_acquire)) + { + // Queue is empty + return std::nullopt; + } + + T event = m_queue[current_head]; + m_head.store((current_head + 1) % max_buffer, std::memory_order_release); + return event; + } + }; +} // RC::Input + diff --git a/deps/first/Input/src/Handler.cpp b/deps/first/Input/src/Handler.cpp index 8533a9aec..ecc6ce4bd 100644 --- a/deps/first/Input/src/Handler.cpp +++ b/deps/first/Input/src/Handler.cpp @@ -1,345 +1,203 @@ #include +#include +#include #include - -#define NOMINMAX -#include - +#include namespace RC::Input { - auto is_modifier_key_required(ModifierKey modifier_key, std::vector modifier_keys) -> bool - { - for (const auto& required_modifier_key : modifier_keys) - { - if (required_modifier_key == ModifierKey::MOD_KEY_START_OF_ENUM) - { - continue; - } - - if (modifier_key == required_modifier_key) - { - return true; - } - } - - return false; - } - - auto Handler::are_modifier_keys_down(const std::vector& required_modifier_keys) -> bool - { - bool are_required_modifier_keys_down = true; - - for (const auto& [modifier_key, modifier_key_is_down] : m_modifier_keys_down) - { - for (const auto& required_modifier_key : required_modifier_keys) - { - if (modifier_key == required_modifier_key && !modifier_key_is_down) - { - are_required_modifier_keys_down = false; - } - - if (modifier_key != required_modifier_key && modifier_key_is_down && !is_modifier_key_required(modifier_key, required_modifier_keys)) - { - return false; - } - } - } - - return are_required_modifier_keys_down; - } - - auto Handler::is_program_focused() -> bool - { - HWND hwnd = GetForegroundWindow(); - if (!hwnd) return false; - - wchar_t current_window_class_name[MAX_PATH]; - if (!GetClassNameW(hwnd, current_window_class_name, MAX_PATH)) return false; - - for (const auto& active_window_class : m_active_window_classes) - { - if (wcscmp(current_window_class_name, active_window_class) == 0) - { - return true; - } - } - - return false; - } + std::unordered_map> Handler::m_input_sources_store; auto Handler::process_event() -> void { - if (!is_program_focused()) + if (m_platform_handler == nullptr) { return; } std::vector callbacks_to_call{}; + + auto events = m_platform_handler->process_event(this); - bool skip_this_frame = !get_allow_input(); - bool is_any_modifier_keys_down = false; - bool any_keys_are_down = false; - - if (m_any_keys_are_down) - { - skip_this_frame = true; - } - - // Check if any modifier keys are down - for (auto& [modifier_key, key_is_down] : m_modifier_keys_down) - { - if (GetAsyncKeyState(modifier_key)) - { - is_any_modifier_keys_down = true; - key_is_down = true; - } - else - { - key_is_down = false; - } - } - - for (auto& key_set_data : m_key_sets) { - for (auto& [key, key_data_array] : key_set_data.key_data) + // Lock the event mutex to access the key_set + auto event_update_lock = std::lock_guard(m_event_mutex); + for (auto& event : events) { - for (auto& key_data : key_data_array) + auto key_set_array = m_key_set.key_data[event.key]; + for (auto& key_data : key_set_array) { - if (GetAsyncKeyState(key) && !key_data.is_down) - { - any_keys_are_down = true; - bool should_propagate = true; - - if (key_data.requires_modifier_keys) - { - if (!are_modifier_keys_down(key_data.required_modifier_keys)) - { - should_propagate = false; - } - } - - if (!key_data.requires_modifier_keys && is_any_modifier_keys_down) - { - should_propagate = false; - } - - if (should_propagate) - { - key_data.is_down = true; - for (const auto& callback : key_data.callbacks) - { - callbacks_to_call.emplace_back(callback); - } - } - } - else if (!GetAsyncKeyState(key) && key_data.is_down) + if (key_data.required_modifier_keys == event.modifier_keys) { - key_data.is_down = false; + callbacks_to_call.emplace_back(key_data.callback); } } } } - - if (any_keys_are_down) - { - m_any_keys_are_down = true; - } - else - { - m_any_keys_are_down = false; - } - + + + // No need to lock the event mutex to call the callbacks + // this avoids key registration inside the callback for (const auto& callback : callbacks_to_call) { - if (skip_this_frame) - { - return; - } callback(); } } auto Handler::register_keydown_event(Input::Key key, EventCallbackCallable callback, uint8_t custom_data, void* custom_data2) -> void { - KeySet& key_set = [&]() -> KeySet& { - for (auto& key_set : m_key_sets) - { - if (key_set.key_data.contains(key)) - { - return key_set; - } - } - - return m_key_sets.emplace_back(KeySet{}); - }(); - - KeyData& key_data = key_set.key_data[key].emplace_back(); - key_data.callbacks.emplace_back(callback); + auto event_update_lock = std::lock_guard(m_event_mutex); + KeyData& key_data = m_key_set.key_data[key].emplace_back(); + key_data.callback = callback; key_data.custom_data = custom_data; key_data.custom_data2 = custom_data2; + m_subscribed_keys[key] = true; } auto Handler::register_keydown_event( Input::Key key, const ModifierKeyArray& modifier_keys, const EventCallbackCallable& callback, uint8_t custom_data, void* custom_data2) -> void { - KeySet& key_set = [&]() -> KeySet& { - for (auto& key_set : m_key_sets) - { - if (key_set.key_data.contains(key)) - { - return key_set; - } - } - - return m_key_sets.emplace_back(KeySet{}); - }(); - - KeyData& key_data = key_set.key_data[key].emplace_back(); - key_data.callbacks.emplace_back(callback); + auto event_update_lock = std::lock_guard(m_event_mutex); + KeyData& key_data = m_key_set.key_data[key].emplace_back(); + key_data.callback = callback; key_data.custom_data = custom_data; key_data.custom_data2 = custom_data2; key_data.requires_modifier_keys = true; + key_data.required_modifier_keys = modifier_keys; + m_subscribed_keys[key] = true; + } - for (const auto& modifier_key : modifier_keys) + auto Handler::is_keydown_event_registered(Input::Key key) -> bool + { + auto event_update_lock = std::lock_guard(m_event_mutex); + auto key_data = m_key_set.key_data.find(key); + if (key_data == m_key_set.key_data.end()) + { + return false; + } + for (const auto& key_data_container : key_data->second) { - if (modifier_key != ModifierKey::MOD_KEY_START_OF_ENUM) + if (key_data_container.required_modifier_keys.empty()) { - key_data.required_modifier_keys.emplace_back(modifier_key); + return true; } } + return false; } - auto Handler::is_keydown_event_registered(Input::Key key) -> bool + auto Handler::is_keydown_event_registered(Input::Key key, const ModifierKeyArray& modifier_keys_array) -> bool { - bool is_key_registered{}; - bool is_key_registered_with_no_modifier_keys = true; - for (const auto& key_set : m_key_sets) + auto event_update_lock = std::lock_guard(m_event_mutex); + auto key_data = m_key_set.key_data.find(key); + auto modifier_keys = ModifierKeys(modifier_keys_array); + if (key_data == m_key_set.key_data.end()) + { + return false; + } + for (const auto& key_data_container : key_data->second) { - for (const auto& [key_registered, key_data_container] : key_set.key_data) + if (key_data_container.required_modifier_keys == modifier_keys) { - if (key_registered == key) - { - is_key_registered = true; - } - else - { - continue; - } + return true; + } + } + return false; + } - for (const auto& key_data : key_data_container) - { - if (key_data.requires_modifier_keys) - { - is_key_registered_with_no_modifier_keys = false; - break; - } - } + auto Handler::has_event_on_key(Input::Key key) -> bool + { + return m_subscribed_keys[key]; + } - if (!is_key_registered_with_no_modifier_keys) - { - break; - } - } + auto Handler::get_events_safe(std::function callback) -> void + { + auto event_update_lock = std::lock_guard(m_event_mutex); + callback(m_key_set); + } - if (!is_key_registered_with_no_modifier_keys) - { - break; - } - } + auto Handler::clear_subscribed_keys() -> void + { + m_subscribed_keys.fill(false); + } + + auto Handler::get_allow_input() -> bool + { + return m_allow_input; + } - return is_key_registered && is_key_registered_with_no_modifier_keys; + auto Handler::set_allow_input(bool new_value) -> void + { + m_allow_input = new_value; } - auto Handler::is_keydown_event_registered(Input::Key key, const ModifierKeyArray& modifier_keys) -> bool + /// Set the input source to the given source + /// SAFETY: Only call this function from the main thread + auto Handler::set_input_source(std::string source) -> bool { - bool is_key_registered{}; - bool all_modifier_keys_match{}; - for (const auto& key_set : m_key_sets) + auto event_update_lock = std::lock_guard(m_event_mutex); + std::shared_ptr next_input_source = nullptr; + if (source == "Default") { - for (const auto& [key_registered, key_data_container] : key_set.key_data) + // find the highest priority input source + int highest_priority = INT_MAX; + for (auto& input_source : m_input_sources_store) { - if (key_registered == key) - { - is_key_registered = true; - } - else + if (!input_source.second->is_available()) { continue; } - - all_modifier_keys_match = false; - for (const auto& key_data : key_data_container) - { - if (!key_data.requires_modifier_keys && !modifier_keys.empty()) - { - all_modifier_keys_match = false; - continue; - } - - if (!key_data.requires_modifier_keys && modifier_keys.empty()) - { - all_modifier_keys_match = true; - break; - } - - for (const auto& modifier_key : key_data.required_modifier_keys) - { - for (const auto modifier_key_to_check : modifier_keys) - { - if (modifier_key_to_check == ModifierKey::MOD_KEY_START_OF_ENUM) - { - continue; - } - - if (modifier_key_to_check == modifier_key) - { - all_modifier_keys_match = true; - } - else - { - all_modifier_keys_match = false; - } - } - - if (all_modifier_keys_match) - { - break; - } - } - - if (all_modifier_keys_match) - { - break; - } - } - - if (all_modifier_keys_match) + auto priority = input_source.second->source_priority(); + if (priority < highest_priority) { - break; + next_input_source = input_source.second; + highest_priority = priority; } } - - if (all_modifier_keys_match) + if (highest_priority == INT_MAX) { - break; + return false; + } + } else { + auto input_source = m_input_sources_store.find(source); + if (input_source == m_input_sources_store.end()) + { + return false; + } + next_input_source = input_source->second; + if (!next_input_source->is_available()) + { + return false; } } - - return is_key_registered && all_modifier_keys_match; - } - - auto Handler::get_events() -> std::vector& - { - return m_key_sets; + if (next_input_source != m_platform_handler) + { + if (m_platform_handler != nullptr) + { + m_platform_handler->deactivate(); + } + next_input_source->activate(); + m_platform_handler = next_input_source; + return true; + } + return true; } - auto Handler::get_allow_input() -> bool + // register the input source to the input source store + auto Handler::register_input_source(std::shared_ptr input_source) -> void { - return m_allow_input; + std::string name = input_source->get_name(); + if (m_input_sources_store.find(name) == m_input_sources_store.end()) + { + m_input_sources_store[name] = input_source; + } } - auto Handler::set_allow_input(bool new_value) -> void + auto Handler::get_current_input_source() -> std::string { - m_allow_input = new_value; + if (m_platform_handler == nullptr) + { + return "None"; + } + return m_platform_handler->get_name(); } } // namespace RC::Input diff --git a/deps/first/Input/src/KeyDef.cpp b/deps/first/Input/src/KeyDef.cpp index 5e73dbbc1..0f4c93c3e 100644 --- a/deps/first/Input/src/KeyDef.cpp +++ b/deps/first/Input/src/KeyDef.cpp @@ -1,4 +1,5 @@ #include +#include namespace RC::Input { @@ -14,4 +15,74 @@ namespace RC::Input return key; } + + auto ModifierKeys::operator|(const ModifierKeys& rkeys) -> ModifierKeys& + { + keys |= rkeys.keys; + return *this; + } + + + auto ModifierKeys::operator|(const ModifierKey& key) -> ModifierKeys& + { + if (is_modify_key_valid(key)) + { + keys |= (1 << key); + } + return *this; + } + + + auto ModifierKeys::operator|=(const ModifierKeys& rkeys) -> ModifierKeys& + { + return *this = *this | rkeys; + } + + + auto ModifierKeys::operator|=(const ModifierKey& key) -> ModifierKeys& + { + return *this = *this | key; + } + + auto ModifierKeys::operator==(const ModifierKeys& key) const -> bool + { + return keys == key.keys; + } + + auto ModifierKeys::operator<(const ModifierKeys& rkeys) const -> bool + { + return keys < rkeys.keys; + } + + auto ModifierKeys::operator>(const ModifierKeys& rkeys) const -> bool + { + return keys > rkeys.keys; + } + + auto ModifierKeys::operator!=(const ModifierKeys& key) const -> bool + { + return keys != key.keys; + } + + ModifierKeys::ModifierKeys(std::initializer_list keys) + { + for (auto key : keys) + { + if (is_modify_key_valid(key)) + { + this->keys |= (1 << key); + } + } + } + + auto operator&(const ModifierKeys& keys, const ModifierKey& key) -> bool + { + return !! (keys.keys & (1 << key)); + } + + auto operator&(const ModifierKeys& keys, const ModifierKeys& key) -> bool + { + return !! (keys.keys & key.keys); + } + } // namespace RC::Input diff --git a/deps/first/Input/src/Platform/NcursesInputSource.cpp b/deps/first/Input/src/Platform/NcursesInputSource.cpp new file mode 100644 index 000000000..686babecb --- /dev/null +++ b/deps/first/Input/src/Platform/NcursesInputSource.cpp @@ -0,0 +1,219 @@ +#include +#include + +namespace RC::Input +{ + auto NcursesInputSource::begin_frame() -> void + { + std::fill(m_key_cur.begin(), m_key_cur.end(), false); + } + + static Key translate_control_key(int k) { + switch (k) { + case 0: return Key::SPACE; + case 1: return Key::A; + case 2: return Key::B; + case 3: return Key::C; + case 4: return Key::D; + case 5: return Key::E; + case 6: return Key::F; + case 7: return Key::G; + case 8: return Key::H; + case 9: return Key::I; + case 10: return Key::J; + case 11: return Key::K; + case 12: return Key::L; + case 13: return Key::M; + case 14: return Key::N; + case 15: return Key::O; + case 16: return Key::P; + case 17: return Key::Q; + case 18: return Key::R; + case 19: return Key::S; + case 20: return Key::T; + case 21: return Key::U; + case 22: return Key::V; + case 23: return Key::W; + case 24: return Key::X; + case 25: return Key::Y; + case 26: return Key::Z; + // case 27: return Key::Escape; + case 28: return Key::BACKSPACE; + //case 29: return Key::CtrlRightBracket; + //case 30: return Key::CtrlCircumflex; + // case 31: return Key::CtrlUnderscore; + default: return Key::RESERVED_START_OF_ENUM; + } + } + + #define KEY_DOWN 0402 /* down-arrow key */ + #define KEY_UP 0403 /* up-arrow key */ + #define KEY_LEFT 0404 /* left-arrow key */ + #define KEY_RIGHT 0405 /* right-arrow key */ + #define KEY_HOME 0406 /* home key */ + #define KEY_BACKSPACE 0407 /* backspace key */ + #define KEY_F0 0410 /* Function keys. Space for 64 */ + #define KEY_F(n) (KEY_F0+(n)) /* Value of function key n */ + #define KEY_DC 0512 /* delete-character key */ + #define KEY_IC 0513 /* insert-character key */ + + static Key translate_key_may_shift(int ch, bool &shifted) { + shifted = false; + if (ch >= 97 && ch <= 122) { + return static_cast(ch - 97 + static_cast(Key::A)); + } + if (ch >= 65 && ch <= 90) { + // capital letter + shifted = true; + return static_cast(ch - 65 + static_cast(Key::A)); + } + + if (ch >= 48 && ch <= 57) { + return static_cast(ch - 48 + static_cast(Key::ZERO)); + } + switch (ch) { + case 32: return Key::SPACE; + // case 10: return Key::ENTER; + // case 27: return Key::ESCAPE; + case 127: return Key::BACKSPACE; + case KEY_DOWN: return Key::DOWN_ARROW; + case KEY_UP: return Key::UP_ARROW; + case KEY_LEFT: return Key::LEFT_ARROW; + case KEY_RIGHT: return Key::RIGHT_ARROW; + case KEY_HOME: return Key::HOME; + case KEY_BACKSPACE: return Key::BACKSPACE; + case KEY_F(1): return Key::F1; + case KEY_F(2): return Key::F2; + case KEY_F(3): return Key::F3; + case KEY_F(4): return Key::F4; + case KEY_F(5): return Key::F5; + case KEY_F(6): return Key::F6; + case KEY_F(7): return Key::F7; + case KEY_F(8): return Key::F8; + case KEY_F(9): return Key::F9; + case KEY_F(10): return Key::F10; + case KEY_F(11): return Key::F11; + case KEY_F(12): return Key::F12; + case KEY_DC: return Key::DEL; + case KEY_IC: return Key::INS; + } + #define CASE_CHAR(normal_ch, shifted_ch, key) \ + case normal_ch: shifted = false; \ + case shifted_ch: return key; + shifted = true; + switch (ch) { + case '!': + return Key::ONE; + case '@': + return Key::TWO; + case '#': + return Key::THREE; + case '$': + return Key::FOUR; + case '%': + return Key::FIVE; + case '^': + return Key::SIX; + case '&': + return Key::SEVEN; + case '*': + return Key::EIGHT; + case '(': + return Key::NINE; + case ')': + return Key::ZERO; // Shift+0 produces ')' + CASE_CHAR('`', '~', Key::OEM_THREE) // key ~ is oem 3 on windows + CASE_CHAR('-', '_', Key::OEM_MINUS) // key _ is oem minus on windows + CASE_CHAR('=', '+', Key::OEM_PLUS) // key + is oem plus on windows + CASE_CHAR('[', '{', Key::OEM_FOUR) // key { is oem four on windows + CASE_CHAR(']', '}', Key::OEM_SIX) // key } is oem 6 on windows + CASE_CHAR('\\', '|', Key::OEM_FIVE) // key | is oem 5 on windows + CASE_CHAR(';', ':', Key::OEM_ONE) // key : is oem semicolon on windows + CASE_CHAR('\'', '"', Key::OEM_SEVEN) // key " is oem apostrophe on windows + CASE_CHAR(',', '<', Key::OEM_COMMA) // key < is oem comma on windows + CASE_CHAR('.', '>', Key::OEM_PERIOD) // key > is oem period on windows + CASE_CHAR('/', '?', Key::OEM_TWO) // key ? is oem 2 on windows + default: + shifted = false; + return Key::RESERVED_START_OF_ENUM; + } + } + + auto NcursesInputSource::receive_input(int input) -> void + { + if (!m_activated) { + return; + } + + // input is ncurse's key code + if (input == 27) { + // esc key + m_is_alt_down = true; + } + else + { + auto control_down = false; + auto shift_down = false; + auto key_code = -1; + if (input >= 0 && input < 32) { + Key input_key = translate_control_key(input); + if (input_key != Key::RESERVED_START_OF_ENUM) { + key_code = static_cast(input_key); + control_down = true; + } + } else { + Key input_key = translate_key_may_shift(input, shift_down); + if (input_key != Key::RESERVED_START_OF_ENUM) + { + key_code = static_cast(input_key); + } + } + if (key_code != -1) { + m_key_cur[key_code] = true; + if (!m_key_last[key_code]) { + // keydown + ModifierKeys modifier_keys{}; + modifier_keys |= (control_down ? ModifierKey::CONTROL : ModifierKey::MOD_KEY_START_OF_ENUM); + modifier_keys |= (shift_down ? ModifierKey::SHIFT : ModifierKey::MOD_KEY_START_OF_ENUM); + modifier_keys |= (m_is_alt_down ? ModifierKey::ALT : ModifierKey::MOD_KEY_START_OF_ENUM); + push_input_event({static_cast(key_code), modifier_keys}); + auto modify_to_string = [](ModifierKeys modifier_keys) -> std::string { + std::string result; + if (modifier_keys & ModifierKey::CONTROL) { + result += "Control"; + } + if (modifier_keys & ModifierKey::SHIFT) { + if (!result.empty()) { + result += "+"; + } + result += "Shift"; + } + if (modifier_keys & ModifierKey::ALT) { + if (!result.empty()) { + result += "+"; + } + result += "Alt"; + } + return result; + }; + Output::send(SYSSTR("NcursesInputSource::receive_input: key down {} {}"), static_cast(input), modify_to_string(modifier_keys)); + } + else + { + Output::send(SYSSTR("NcursesInputSource::receive_input: key repeat {}"), static_cast(input)); + } + } + m_is_alt_down = false; + } + } + + auto NcursesInputSource::end_frame() -> void + { + std::swap(m_key_cur, m_key_last); + } + + auto NcursesInputSource::is_available() -> bool + { + return true; + } +} // namespace RC::Input \ No newline at end of file diff --git a/deps/first/Input/src/Platform/QueneInputSource.cpp b/deps/first/Input/src/Platform/QueneInputSource.cpp new file mode 100644 index 000000000..55952b833 --- /dev/null +++ b/deps/first/Input/src/Platform/QueneInputSource.cpp @@ -0,0 +1,43 @@ +#include +#include + +#include + +namespace RC::Input +{ + auto QueueInputSource::push_input_event(const InputEvent& event) -> void + { + if (m_activated) { + m_input_queue.push(event); + Output::send(SYSSTR("QueueInputSource::push_input_event: {}"), (int) event.key); + } + } + + // even if not activated, we still consume the remaining events in the queue + std::vector& QueueInputSource::process_event(Handler* handler) + { + m_input_events.clear(); + + auto event = m_input_queue.pop(); + auto& key_set = handler->get_subscribed_keys(); + while (event) + { + Output::send(SYSSTR("QueueInputSource::reveive key event: {}"), (int) event->key); + if (key_set[event->key]) + { + m_input_events.emplace_back(*event); + } + event = m_input_queue.pop(); + } + + if (!m_activated) { + m_input_events.clear(); + } + + if (!handler->get_allow_input()) { + m_input_events.clear(); + } + + return m_input_events; + } +}; // RC::Input diff --git a/deps/first/Input/src/Platform/Win32APIInputSource.cpp b/deps/first/Input/src/Platform/Win32APIInputSource.cpp new file mode 100644 index 000000000..a76a22e93 --- /dev/null +++ b/deps/first/Input/src/Platform/Win32APIInputSource.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +#define NOMINMAX +#include + +auto Win32InputSource::is_program_focused() -> bool +{ + HWND hwnd = GetForegroundWindow(); + if (!hwnd) return false; + wchar_t current_window_class_name[MAX_PATH]; + if (!GetClassNameW(hwnd, current_window_class_name, MAX_PATH)) return false; + for (const auto& active_window_class : m_active_window_classes) + {Win32InputSourceWin32InputSource + if (wcscmp(current_window_class_name, active_window_class) == 0) + { + return true; + } + } + return false; +} + +std::vector& Win32InputSource::process_event(Handler* handler) +{ + if (!is_program_focused()) + { + return std::nullopt; + } + + m_input_events.clear(); + + if (! m_activated) + { + return m_input_events; + } + + bool skip_this_frame = !handler->get_allow_input(); + + if (m_any_keys_are_down) + { + skip_this_frame = true; + } + + bool any_keys_are_down = false; + + // Check if any modifier keys are down + ModifierKeys modifier_keys{}; + for (auto& [modifier_key, key_is_down] : m_modifier_keys_down) + { + if (GetAsyncKeyState(modifier_key)) + { + modifier_keys |= modifier_key; + key_is_down = true; + } + else + { + key_is_down = false; + } + } + + auto& subscribed_keys = handler->get_subscribed_keys(); + + for (int key = 0; key < max_keys; ++key) + { + if (subscribed_keys[key]) + { + auto keyed = GetAsyncKeyState(key); + if (keyed && !m_key_down[key]) + { + any_keys_are_down = true; + m_key_down[key] = true; + m_input_events.emplace_back({static_cast(key), modifier_keys}); + } + else if (!keyed && m_key_down[key]) + { + m_key_down[key] = false; + } + } + } + + + if (any_keys_are_down) + { + m_any_keys_are_down = true; + } + else + { + m_any_keys_are_down = false; + } + + if (skip_this_frame) + { + m_input_events.clear(); + } + return m_input_events; +} diff --git a/deps/first/Input/src/PlatformInit.cpp b/deps/first/Input/src/PlatformInit.cpp new file mode 100644 index 000000000..3eef0bf14 --- /dev/null +++ b/deps/first/Input/src/PlatformInit.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +namespace RC::Input +{ + auto Handler::init() -> void + { + #ifdef WIN32 + register_input_source(std::make_shared(L"ConsoleWindowClass", L"UnrealWindow")); + #endif + #ifdef LINUX + register_input_source(std::make_shared()); + #endif + } +} \ No newline at end of file From 423373f058e07fba3057fe1c2525ae501b94df07 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 00:45:38 -0600 Subject: [PATCH 101/213] add input related callbacks to imtui --- deps/third/imtui/fix-size-cjk-and-mouse.patch | 92 ++++++++++++++++--- 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/deps/third/imtui/fix-size-cjk-and-mouse.patch b/deps/third/imtui/fix-size-cjk-and-mouse.patch index 88f327161..0f039c337 100644 --- a/deps/third/imtui/fix-size-cjk-and-mouse.patch +++ b/deps/third/imtui/fix-size-cjk-and-mouse.patch @@ -11,6 +11,28 @@ index 9376c4a..5e24536 100644 find_package(Curses REQUIRED) CHECK_LIBRARY_EXISTS("${CURSES_NCURSES_LIBRARY}" nodelay "" CURSES_NCURSES_HAS_NODELAY) +diff --git a/include/imtui/imtui-impl-ncurses.h b/include/imtui/imtui-impl-ncurses.h +index 51e64d3..5a05359 100644 +--- a/include/imtui/imtui-impl-ncurses.h ++++ b/include/imtui/imtui-impl-ncurses.h +@@ -4,6 +4,8 @@ + + #pragma once + ++#include ++ + namespace ImTui { + struct TScreen; + } +@@ -19,7 +21,7 @@ ImTui::TScreen * ImTui_ImplNcurses_Init(bool mouseSupport, float fps_active = 60 + void ImTui_ImplNcurses_Shutdown(); + + // returns true if there is any user input from the keyboard/mouse +-bool ImTui_ImplNcurses_NewFrame(); ++bool ImTui_ImplNcurses_NewFrame(std::function inputCallback); + + // active - specify which redraw rate to use: fps_active or fps_idle + void ImTui_ImplNcurses_DrawScreen(bool active = true); diff --git a/include/imtui/imtui.h b/include/imtui/imtui.h index b77c342..100a4d8 100644 --- a/include/imtui/imtui.h @@ -30,10 +52,20 @@ index b77c342..100a4d8 100644 struct TScreen { int nx = 0; diff --git a/src/imtui-impl-ncurses.cpp b/src/imtui-impl-ncurses.cpp -index 1d454ba..8b58dcf 100644 +index 1d454ba..40adeee 100644 --- a/src/imtui-impl-ncurses.cpp +++ b/src/imtui-impl-ncurses.cpp -@@ -101,7 +101,8 @@ ImTui::TScreen * ImTui_ImplNcurses_Init(bool mouseSupport, float fps_active, flo +@@ -27,6 +27,9 @@ + #include + #endif + ++#include ++#include ++ + #include + #include + #include +@@ -101,7 +104,8 @@ ImTui::TScreen * ImTui_ImplNcurses_Init(bool mouseSupport, float fps_active, flo } fps_idle = std::min(fps_active, fps_idle); g_vsync = VSync(fps_active, fps_idle); @@ -43,7 +75,7 @@ index 1d454ba..8b58dcf 100644 initscr(); use_default_colors(); start_color(); -@@ -150,6 +151,42 @@ ImTui::TScreen * ImTui_ImplNcurses_Init(bool mouseSupport, float fps_active, flo +@@ -150,15 +154,57 @@ ImTui::TScreen * ImTui_ImplNcurses_Init(bool mouseSupport, float fps_active, flo getmaxyx(stdscr, screenSizeY, screenSizeX); ImGui::GetIO().DisplaySize = ImVec2(screenSizeX, screenSizeY); @@ -62,7 +94,6 @@ index 1d454ba..8b58dcf 100644 + int length = strlen(text); + refresh(); + printf("\e]52;c;"); -+ fprintf(stderr, "Base64: "); + for (int i = 0; i < length; ) { + uint32_t c = 0; + for (int j = 0; j < 3; j++) { @@ -70,15 +101,12 @@ index 1d454ba..8b58dcf 100644 + } + for (int j = 3; j >= 0; j--) { + printf("%c", encoding_table[(c >> (6*j)) & 0x3F]); -+ fprintf(stderr, "%c", encoding_table[(c >> (6*j)) & 0x3F]); + } + } + int pad = (length + 2) % 3; + for (int i = 0; i < pad; i++) { + printf("="); -+ fprintf(stderr, "="); + } -+ fprintf(stderr, "\n"); + printf("\a"); + fflush(stdout); + refresh(); @@ -86,7 +114,35 @@ index 1d454ba..8b58dcf 100644 return g_screen; } -@@ -178,8 +215,10 @@ bool ImTui_ImplNcurses_NewFrame() { + ++void reset_terminal_modes() { ++ struct termios term; ++ tcgetattr(STDIN_FILENO, &term); ++ term.c_iflag |= (ICRNL | INLCR); // Translate CR to NL on input ++ term.c_oflag |= (ONLCR); // Translate NL to CR-NL on output ++ tcsetattr(STDIN_FILENO, TCSANOW, &term); ++} ++ + void ImTui_ImplNcurses_Shutdown() { + // ref #11 : https://github.com/ggerganov/imtui/issues/11 + printf("\033[?1003l\n"); // Disable mouse movement events, as l = low + + endwin(); ++ reset_shell_mode(); ++ reset_terminal_modes(); + + if (g_screen) { + delete g_screen; +@@ -167,7 +213,7 @@ void ImTui_ImplNcurses_Shutdown() { + g_screen = nullptr; + } + +-bool ImTui_ImplNcurses_NewFrame() { ++bool ImTui_ImplNcurses_NewFrame(std::function inputCallback) { + bool hasInput = false; + + int screenSizeX = 0; +@@ -178,8 +224,10 @@ bool ImTui_ImplNcurses_NewFrame() { static int mx = 0; static int my = 0; @@ -99,7 +155,7 @@ index 1d454ba..8b58dcf 100644 static unsigned long mstate = 0; static char input[3]; -@@ -196,8 +235,8 @@ bool ImTui_ImplNcurses_NewFrame() { +@@ -196,8 +244,8 @@ bool ImTui_ImplNcurses_NewFrame() { if (c == ERR) { if ((mstate & 0xf) == 0x1) { @@ -110,7 +166,7 @@ index 1d454ba..8b58dcf 100644 } break; } else if (c == KEY_MOUSE) { -@@ -206,10 +245,14 @@ bool ImTui_ImplNcurses_NewFrame() { +@@ -206,10 +254,14 @@ bool ImTui_ImplNcurses_NewFrame() { mx = event.x; my = event.y; mstate = event.bstate; @@ -129,7 +185,17 @@ index 1d454ba..8b58dcf 100644 //printf("mstate = 0x%016lx\n", mstate); ImGui::GetIO().KeyCtrl |= ((mstate & 0x0F000000) == 0x01000000); } -@@ -266,8 +309,12 @@ bool ImTui_ImplNcurses_NewFrame() { +@@ -252,8 +304,8 @@ bool ImTui_ImplNcurses_NewFrame() { + } else { + keysDown[c] = true; + } ++ inputCallback(c); + } +- + hasInput = true; + } + +@@ -266,8 +318,12 @@ bool ImTui_ImplNcurses_NewFrame() { ImGui::GetIO().MousePos.x = mx; ImGui::GetIO().MousePos.y = my; @@ -144,7 +210,7 @@ index 1d454ba..8b58dcf 100644 ImGui::GetIO().DeltaTime = g_vsync.delta_s(); -@@ -315,8 +362,10 @@ void ImTui_ImplNcurses_DrawScreen(bool active) { +@@ -315,8 +371,10 @@ void ImTui_ImplNcurses_DrawScreen(bool active) { move(y, 0); for (int x = 0; x < nx; ++x) { const auto cell = g_screen->data[y*nx + x]; @@ -157,7 +223,7 @@ index 1d454ba..8b58dcf 100644 const uint16_t p = b*256 + f; if (colPairs[p].first == false) { -@@ -337,8 +386,25 @@ void ImTui_ImplNcurses_DrawScreen(bool active) { +@@ -337,8 +395,25 @@ void ImTui_ImplNcurses_DrawScreen(bool active) { lastp = p; } From 66af6115e9f71bd4744950615796cc647b38e293 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 00:46:58 -0600 Subject: [PATCH 102/213] missed commit for case-insensitive find mods.txt --- UE4SS/src/UE4SSProgram.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 3e5a326b0..40faa9c86 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1205,15 +1205,15 @@ namespace RC Output::send(SYSSTR("Starting mods (from mods.txt load order)...\n")); std::filesystem::path mods_directory = UE4SSProgram::get_program().get_mods_directory(); - SystemStringType enabled_mods_file{mods_directory / "mods.txt"}; - if (!std::filesystem::exists(enabled_mods_file)) + auto enabled_mods_file = File::get_path_if_exists(mods_directory, "mods.txt"); + if (!enabled_mods_file.has_value()) { Output::send(SYSSTR("No mods.txt file found...\n")); } else { // 'mods.txt' exists, lets parse it - SystemStreamType mods_stream{enabled_mods_file}; + SystemStreamType mods_stream{ *enabled_mods_file}; SystemStringType current_line; while (std::getline(mods_stream, current_line)) From c1abf058384ae3406c671d52d87c1708fb32afef Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 00:47:32 -0600 Subject: [PATCH 103/213] begin to add cppmod back --- UE4SS/include/Mod/CppMod.hpp | 2 ++ UE4SS/include/UE4SSProgram.hpp | 2 -- UE4SS/src/Mod/CppMod.cpp | 7 ++++++- UE4SS/src/Mod/LuaMod.cpp | 16 +--------------- UE4SS/src/UE4SSProgram.cpp | 18 +----------------- 5 files changed, 10 insertions(+), 35 deletions(-) diff --git a/UE4SS/include/Mod/CppMod.hpp b/UE4SS/include/Mod/CppMod.hpp index 18466a457..5f10e78b9 100644 --- a/UE4SS/include/Mod/CppMod.hpp +++ b/UE4SS/include/Mod/CppMod.hpp @@ -32,6 +32,8 @@ namespace RC #ifdef WIN32 HMODULE m_main_dll_module = NULL; DLL_DIRECTORY_COOKIE m_dlls_path_cookie = NULL; +#else + void * m_dl_handle = nullptr; #endif start_type m_start_mod_func = nullptr; uninstall_type m_uninstall_mod_func = nullptr; diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index eeb7ec7d1..37a0e5a10 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -24,9 +24,7 @@ #include #include -#ifdef HAS_CPPMOD #include -#endif #include #include #include diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 13e833d7e..3a08fbb67 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -8,6 +8,8 @@ #ifdef LINUX #define printf_s printf +#define _GNU_SOURCE +#include #endif namespace RC @@ -20,7 +22,7 @@ namespace RC if (!std::filesystem::exists(m_dlls_path)) { - Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), (m_mod_name)); + Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), m_mod_name); set_installable(false); return; } @@ -53,6 +55,9 @@ namespace RC set_installable(false); return; } + +#else + #endif } diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 8410ad9aa..72b0a298e 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -27,12 +27,7 @@ #include #include - -#ifdef HAS_CPPMOD #include -#endif - - #include #pragma warning(disable : 4005) #include @@ -3336,7 +3331,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. lua_setglobal(lua.get_lua_state(), "__OriginalReturnValue"); } -#ifdef HAS_CPPMOD + auto LuaMod::fire_on_lua_start_for_cpp_mods() -> void { if (!is_started()) @@ -3376,15 +3371,6 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. } } } -#else - auto LuaMod::fire_on_lua_start_for_cpp_mods() -> void - { - } - - auto LuaMod::fire_on_lua_stop_for_cpp_mods() -> void - { - } -#endif auto LuaMod::start_mod() -> void { diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 40faa9c86..88856b50a 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -29,9 +29,7 @@ #include #include #include -#ifdef HAS_CPPMOD #include -#endif #include #include #include @@ -1131,9 +1129,7 @@ namespace RC auto UE4SSProgram::install_cpp_mods() -> void { - #ifdef HAS_CPPMOD install_mods(get_program().m_mods); - #endif } auto UE4SSProgram::install_lua_mods() -> void @@ -1146,13 +1142,11 @@ namespace RC ProfilerScope(); for (const auto& mod : m_mods) { - #ifdef HAS_CPPMOD if (!dynamic_cast(mod.get())) { continue; } mod->fire_unreal_init(); - #endif } } @@ -1174,13 +1168,11 @@ namespace RC ProfilerScope(); for (const auto& mod : m_mods) { - #ifdef HAS_CPPMOD if (!dynamic_cast(mod.get())) { continue; } mod->fire_program_start(); - #endif } } @@ -1188,12 +1180,10 @@ namespace RC { for (const auto& mod : m_mods) { - #ifdef HAS_CPPMOD if (auto cpp_mod = dynamic_cast(mod.get()); cpp_mod) { cpp_mod->fire_dll_load(dll_name); } - #endif } } @@ -1314,13 +1304,13 @@ namespace RC auto UE4SSProgram::start_cpp_mods(IsInitialStartup is_initial_startup) -> void { - #ifdef HAS_CPPMOD ProfilerScope(); auto error_message = start_mods(); if (!error_message.empty()) { set_error(error_message.c_str()); } + #ifdef HAS_UI // If this is the initial startup, notify mods that the UI has initialized. // This isn't completely accurate since the UI will usually have started a while ago. // However, we can't immediately notify mods of this because no mods have been started at that point. @@ -1336,19 +1326,15 @@ namespace RC { ProfilerScope(); -#ifdef HAS_CPPMOD std::vector cpp_mods{}; -#endif std::vector lua_mods{}; for (auto& mod : m_mods) { -#ifdef HAS_CPPMOD if (auto cpp_mod = dynamic_cast(mod.get()); cpp_mod) { cpp_mods.emplace_back(cpp_mod); } else -#endif if (auto lua_mod = dynamic_cast(mod.get()); lua_mod) { lua_mods.emplace_back(lua_mod); @@ -1361,12 +1347,10 @@ namespace RC mod->uninstall(); } -#ifdef HAS_CPPMOD for (auto& mod : cpp_mods) { mod->uninstall(); } -#endif m_mods.clear(); LuaMod::global_uninstall(); } From c110143412f430033b6987daa586905b71e0114e Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Feb 2024 01:21:31 -0600 Subject: [PATCH 104/213] fix windows input build --- UE4SS/include/SettingsManager.hpp | 2 +- UE4SS/src/UE4SSProgram.cpp | 3 +- deps/first/Input/include/Input/Handler.hpp | 2 + deps/first/Input/include/Input/KeyDef.hpp | 2 +- ...utSource.hpp => Win32AsyncInputSource.hpp} | 8 +- .../src/Platform/Win32APIInputSource.cpp | 98 ----------------- .../src/Platform/Win32AsyncInputSource.cpp | 102 ++++++++++++++++++ deps/first/Input/src/PlatformInit.cpp | 4 +- 8 files changed, 114 insertions(+), 107 deletions(-) rename deps/first/Input/include/Input/Platform/{Win32APIInputSource.hpp => Win32AsyncInputSource.hpp} (89%) delete mode 100644 deps/first/Input/src/Platform/Win32APIInputSource.cpp create mode 100644 deps/first/Input/src/Platform/Win32AsyncInputSource.cpp diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index cc682614c..b9610c91e 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -28,7 +28,7 @@ namespace RC bool EnableDebugKeyBindings{false}; int64_t SecondsToScanBeforeGivingUp{30}; bool UseUObjectArrayCache{true}; - SystemStringType InputSource{"Default"}; + SystemStringType InputSource{SYSSTR("Default")}; } General; struct SectionEngineVersionOverride diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 88856b50a..7a4ee1d32 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -913,7 +913,8 @@ namespace RC #ifdef HAS_INPUT if (! settings_manager.General.InputSource.empty()) { - if (m_input_handler.set_input_source(settings_manager.General.InputSource)) { + if (m_input_handler.set_input_source(to_string(settings_manager.General.InputSource))) + { Output::send(SYSSTR("Input source set to: {}\n"), m_input_handler.get_current_input_source()); } else diff --git a/deps/first/Input/include/Input/Handler.hpp b/deps/first/Input/include/Input/Handler.hpp index c411474a6..ad80b6841 100644 --- a/deps/first/Input/include/Input/Handler.hpp +++ b/deps/first/Input/include/Input/Handler.hpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include diff --git a/deps/first/Input/include/Input/KeyDef.hpp b/deps/first/Input/include/Input/KeyDef.hpp index 91ba0e1fb..8aeff94c6 100644 --- a/deps/first/Input/include/Input/KeyDef.hpp +++ b/deps/first/Input/include/Input/KeyDef.hpp @@ -267,7 +267,7 @@ namespace RC::Input auto operator>(const ModifierKeys& key) const -> bool; - ModifierKeys(const ModifierKey key) : keys{is_modify_key_valid(key) ? (1 << key) : 0} {}; + ModifierKeys(const ModifierKey key) : keys{is_modify_key_valid(key) ? (1u << key) : 0} {}; ModifierKeys(const ModifierKeys& other) : keys{other.keys} {}; ModifierKeys() : keys{0} {}; diff --git a/deps/first/Input/include/Input/Platform/Win32APIInputSource.hpp b/deps/first/Input/include/Input/Platform/Win32AsyncInputSource.hpp similarity index 89% rename from deps/first/Input/include/Input/Platform/Win32APIInputSource.hpp rename to deps/first/Input/include/Input/Platform/Win32AsyncInputSource.hpp index 72b6dc12f..90c75c75d 100644 --- a/deps/first/Input/include/Input/Platform/Win32APIInputSource.hpp +++ b/deps/first/Input/include/Input/Platform/Win32AsyncInputSource.hpp @@ -9,7 +9,7 @@ namespace RC::Input { - class Win32InputSource : public PlatformInputSource + class Win32AsyncInputSource : public PlatformInputSource { private: std::vector m_active_window_classes{}; @@ -24,7 +24,7 @@ namespace RC::Input std::vector m_input_events{}; public: template - explicit Win32InputSource(WindowClasses... window_classes) + explicit Win32AsyncInputSource(WindowClasses... window_classes) { static_assert(std::conjunction...>::value, "WindowClasses must be of type const wchar_t*"); @@ -59,8 +59,8 @@ namespace RC::Input bool deactivate() override { m_activated = false; return true; }; - std::vector& Win32InputSource::process_event(Handler* handler) override; - ~Win32InputSource() = default; + std::vector& process_event(Handler* handler) override; + ~Win32AsyncInputSource() = default; int source_priority() override { return 0; } const char* get_name() override { return "Win32Async"; } diff --git a/deps/first/Input/src/Platform/Win32APIInputSource.cpp b/deps/first/Input/src/Platform/Win32APIInputSource.cpp deleted file mode 100644 index a76a22e93..000000000 --- a/deps/first/Input/src/Platform/Win32APIInputSource.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include - -#define NOMINMAX -#include - -auto Win32InputSource::is_program_focused() -> bool -{ - HWND hwnd = GetForegroundWindow(); - if (!hwnd) return false; - wchar_t current_window_class_name[MAX_PATH]; - if (!GetClassNameW(hwnd, current_window_class_name, MAX_PATH)) return false; - for (const auto& active_window_class : m_active_window_classes) - {Win32InputSourceWin32InputSource - if (wcscmp(current_window_class_name, active_window_class) == 0) - { - return true; - } - } - return false; -} - -std::vector& Win32InputSource::process_event(Handler* handler) -{ - if (!is_program_focused()) - { - return std::nullopt; - } - - m_input_events.clear(); - - if (! m_activated) - { - return m_input_events; - } - - bool skip_this_frame = !handler->get_allow_input(); - - if (m_any_keys_are_down) - { - skip_this_frame = true; - } - - bool any_keys_are_down = false; - - // Check if any modifier keys are down - ModifierKeys modifier_keys{}; - for (auto& [modifier_key, key_is_down] : m_modifier_keys_down) - { - if (GetAsyncKeyState(modifier_key)) - { - modifier_keys |= modifier_key; - key_is_down = true; - } - else - { - key_is_down = false; - } - } - - auto& subscribed_keys = handler->get_subscribed_keys(); - - for (int key = 0; key < max_keys; ++key) - { - if (subscribed_keys[key]) - { - auto keyed = GetAsyncKeyState(key); - if (keyed && !m_key_down[key]) - { - any_keys_are_down = true; - m_key_down[key] = true; - m_input_events.emplace_back({static_cast(key), modifier_keys}); - } - else if (!keyed && m_key_down[key]) - { - m_key_down[key] = false; - } - } - } - - - if (any_keys_are_down) - { - m_any_keys_are_down = true; - } - else - { - m_any_keys_are_down = false; - } - - if (skip_this_frame) - { - m_input_events.clear(); - } - return m_input_events; -} diff --git a/deps/first/Input/src/Platform/Win32AsyncInputSource.cpp b/deps/first/Input/src/Platform/Win32AsyncInputSource.cpp new file mode 100644 index 000000000..d9f32f967 --- /dev/null +++ b/deps/first/Input/src/Platform/Win32AsyncInputSource.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include + +#define NOMINMAX +#include + +namespace RC::Input +{ + + auto Win32AsyncInputSource::is_program_focused() -> bool + { + HWND hwnd = GetForegroundWindow(); + if (!hwnd) return false; + wchar_t current_window_class_name[MAX_PATH]; + if (!GetClassNameW(hwnd, current_window_class_name, MAX_PATH)) return false; + for (const auto& active_window_class : m_active_window_classes) + { + if (wcscmp(current_window_class_name, active_window_class) == 0) + { + return true; + } + } + return false; + } + + std::vector& Win32AsyncInputSource::process_event(Handler* handler) + { + m_input_events.clear(); + + if (!is_program_focused()) + { + return m_input_events; + } + + if (!m_activated) + { + return m_input_events; + } + + bool skip_this_frame = !handler->get_allow_input(); + + if (m_any_keys_are_down) + { + skip_this_frame = true; + } + + bool any_keys_are_down = false; + + // Check if any modifier keys are down + ModifierKeys modifier_keys{}; + for (auto& [modifier_key, key_is_down] : m_modifier_keys_down) + { + if (GetAsyncKeyState(modifier_key)) + { + modifier_keys |= modifier_key; + key_is_down = true; + } + else + { + key_is_down = false; + } + } + + auto& subscribed_keys = handler->get_subscribed_keys(); + + for (int key = 0; key < max_keys; ++key) + { + if (subscribed_keys[key]) + { + auto keyed = GetAsyncKeyState(key); + if (keyed && !m_key_down[key]) + { + any_keys_are_down = true; + m_key_down[key] = true; + m_input_events.emplace_back(InputEvent {static_cast(key), modifier_keys}); + } + else if (!keyed && m_key_down[key]) + { + m_key_down[key] = false; + } + } + } + + if (any_keys_are_down) + { + m_any_keys_are_down = true; + } + else + { + m_any_keys_are_down = false; + } + + if (skip_this_frame) + { + m_input_events.clear(); + } + return m_input_events; + } + +} // namespace RC::Input diff --git a/deps/first/Input/src/PlatformInit.cpp b/deps/first/Input/src/PlatformInit.cpp index 3eef0bf14..54d23e278 100644 --- a/deps/first/Input/src/PlatformInit.cpp +++ b/deps/first/Input/src/PlatformInit.cpp @@ -1,13 +1,13 @@ #include #include -#include +#include namespace RC::Input { auto Handler::init() -> void { #ifdef WIN32 - register_input_source(std::make_shared(L"ConsoleWindowClass", L"UnrealWindow")); + register_input_source(std::make_shared(L"ConsoleWindowClass", L"UnrealWindow")); #endif #ifdef LINUX register_input_source(std::make_shared()); From 994b80bcdc3661099d9e9115eb87fb3a9f6c0041 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 02:31:43 -0600 Subject: [PATCH 105/213] update db --- scripts/database_.pkl | Bin 119580 -> 174210 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/scripts/database_.pkl b/scripts/database_.pkl index af0e14c5c5fd4076a1470da208ac56eb79314de5..6b9608581f49d80a97633c889eaca8fd17f9b397 100644 GIT binary patch literal 174210 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

2hK;LOm|XNfB!H*w`P9 zUk12t0qO~n0j~%en4}$ZfEv5C+r5mT{YeGv5A6rXfb})9sbNP2I8F@<&HxKJU1R)3 zLG@^ifnH|r7U;EPCB93y(y-&IC=?>rM(vg9^rc}Mo5^EOpy0?oQS@b$v6p!Y09Rl8GlsF!A>=X!i2g-{jPO|dyZb6MzUieC( zv-_m`h|daY)JLpzAzMI4X`yX8m)Ds}{lx>Z7jyl0iQlifa6xn{0bdC_!ve%p6{&8Pm-AA`bf>nd<3VaCHeE0lldu; zIUy%=$#HXxO~v^$+;)urh(d~0ZucxzAH5_3M1#)=EZA5xR!9F*cqFQ$$X0UL&5kyD zS%gW^MxmzI;$%`rzaZd#WfVrLgPA#7@`?Z_>7sp6`0JW0`4tf%Miu4s2YXRv)I_f; zT)!qNxkxr}HbwMnf*YrZ%JF3br|Y552&hL7=Os1gc0)P9vXn zNg62f+uaW_OOD04N}2=(R4htsxn<3_oG<994m#gfkW7@ zN(PfXE?F`yR|#}-rln~87I<2oWuxH6=2`BhS>;Uc>y(^wiyEwiEKA88wfd88acmIW zsKtRAF-}*mxAXNy!aFX*Qi7{if1X1wsiH`=WgAsol118In45lWR{NcK}I18lhf><^t(i+ z*pprd5lyjX!P(R!awHw~1HKWOrL(?YiIZ^F2VpI9V6OMh`k;srx3dP$DQnKOu@_xe z6^5I~PKJ3cfxaVmZVvy4TnQ_p4QNtI@)jamMh8v9d_T)J#(#7~Yeff_K|+~q-!u61u|+* z;toWYcXrRTsL7kvxOmT+YAn0iKX4uu!D0^_$)ffQ?ewz$-zsb}X8+60JrC2_uxj5X zq9q-5!?7P|md?9(Dwz__yHjy8J>MSjcZuw&9&s_wJs&yUx_Ym$h+0>CMc4zGY8Sju z5TkYh8yOzNq{UqjiVH9h7hE z(;EH&)Eq7fO4fT~K_4X|tur9=gkG@m#DYGq$-;D)Aj)H~f4=ARCwYJ}M|lj%pFe%* zQzCPMK15L-LsD}>e1_YO@gFP7W6-CrsY@b2bWN!!kAXGg+5eZqBXRbtD38f*b}a47 zB20>s~T{mfaLIm%;6 z;?Y&FLz>ZCC5;Ci>lkT9zIB`}1T$a2GlXEwo~DOj76-WLAs7QVQ-!|ns=l`oSftydDD|lWuvIoW)UEADOG8tW zB|NRt&sFt0gL}4VMX-8W_VSa1y_CR5FGf#HP3|ZiE)P*Hj4Xhhvw*siy@y)k~8GqcxsSs;}*BUY~9pv5t&ye>`@XI_ekV<$l*CY5%Dr5jRzT{ zi63nSF#xFeZ z6G>cVU`O5TY1|Ks40lfh z0`gpiJW^jWG7k9`dJA`Fb$ob7b!t#O$-@!MN^!j1+UQ;<%-6-!gV!@zc*#2B4Nmj2 zw(sLMFAqI~#EFB0uno02n_pf)$_F#09oc1uzV@Ou{gmLGRdWpf|=6^0t)Kid7f zoE{k-FC8fQlXZR-O%OR=j&2t5vUki2xNjj!?Fd$xJCE`-!!yPsaQ*IB32k|h)4hPdE4Usnpq#%^(CN4WKP>2(T!CUF zMENBxOd1QRd`=-CbHyPKQQ zTy8wZfAnUwqNA@mGU>DlJ;(FVCUHYrL=^6ZB(u9M3Y{TMe3^97vu1)s&xpWWI)^5A z%4^;$1vzfr1Sy#j`01!(YlKIpwWAUzBm6S$SL=n5f4@=*QxW9UL*aHojUEar!6||` zxZAg7NwPLXIK&4tMwI7|V6}g6@OTXQs zU!~}Gm+N(kW_Vk4SS^-{LP`Y?nAnk~Q`4em!Mg5>9@f7zL$nlv<3IdiQ~`~qkUZD6r&JoQqoiy{wI-uyAIW_Ta%x4C4m*DXc78ee z4Agwyq;4NB(*sZU)8n}|@;*Vn*-s1fjX+1bN6rAx!9TpGips9_Ntqos?n8pRJVFM@ z3ojtZTL`kt#Dojj2Q?s23-r%`xD1H(j#P07Lq3EnK#(oL=vcmm3yNw#0SQ#^uE;F1 zdw4)V*TvIA&a2?!j$Z0Md{7Cjtzd%cx=cu{>Ko$bnkfs4WYoS(sXf&*YVHkHLBrci z1}UVw2^3Ce;Ir3EwZ>eZ>*PzmK_+mF)QY@6sAV)LKOPyI&qRj^hZA{BSL)#cIDerRIy z7#|Y$Cwa4AEewChr+vovX*cUx;F&3ps=?PZfVl=3tUj~9EiywD236=Obg*1B6XkV{ za9e$=fZil6fcPvSq9D$y4wVS;K(SWF(dRzQ@isK&<8SWH(ztu7y_0^GlW#tO-RLV~ z^BbC^kw}(zSJY{-y*NHTSR8W8_P$4xZ-98a$o)QaEI3(qQmO`>&h}H{XLSo?G&T$+ZM2JDPRAg`7|Pf@46qw_d9CRL9Fh$J)(L@d*)Ym5&hwJWm2*Eyi@W zRZAD}v3vcvz=sPVAOrRV!d^{QsU#-_vb)Rq(+n}jf3*6#ENHd6SSeDbiK)Z>85-~+ zUaFv_dbq1V{sqy6%X#_W&T^gfpkw=rtZtQtoi+4Vn*2eMd%2=+uaIh6sz+7e%bI*Y zk*{+)Dcb@)yKvBz>IvNrLw~2!Zf~VlIzV!k=t$E;Y3~qU)BqO=V6E&5@F*53wpS*- z%)b@=y>51en%y!8GSXih{yvGnqFY`yBvxbIcdRlrTB}yduVd!&ug=Imr2(GNyA!<} zt61wV9PaQ>Qv*_*`Hv{hk}15&X_L>9&M>TSgf+hu*+Y**1xrRrWUTssV)Rq1y=^gX zp?7fJw97BoM$3WbvH6wk_3$r(y&_6Sz`N%|pGMe+4syHq`9iPy?#>6{jN8G!+`yQ* zs{c*ctchuaPRyAZtFp`L+v%)uTF#(XBQC4&rnACzjMlP=F6rSsfCJdrFC?O;pH$L=kS@FeMt%#s(Z=L3CRd_znW9C$P27?~_LW#WiK zafTctb7o;Cj%~yd&zH<#RO7zo(oBrE5Mx|Ejxr{_SvGoS!EY;*`YvA-)2C;&FCUq^ zD}?v0i4gd0*M5=f-hsX;>#+&^NAk`>I_4ex^)$}vVlfS>!jh{^I#sqa^>^gKKNOzxx za4$&}?kEZO?&~1j^v8Gx-FazhcTP}u-v7LG$GwCwjjxnX?bb=^)`y;#ZUtZIIdrcj zwR@+jd$sG)J?A3GG`_*hQiVK2Lb97IqK>8Pk=Azc%2YmQiH|skT}G6{;@TUcpPRb* zHes+lLW&*rB4H!=*A?05>7Bt4JFu0b=pBN-(nAdV3xxlO7r)R<0fzSC(5O1U#4hR| zEl&1L7HgCBedWnf_ZWs>r^hv=lD{cwE9PLlO2mC(I&VmSnWTTcU;2C;0(EDySgzEs zzwCQN_6=#AA^8=O{8iosR3OuQs8p}RKcj}evqCqeL}z!_OR(6@A?y_~*2Lg|`&Hu3 zj&gUx=JVtvRa^~+#<4(qF!?+nd~Wu)0Gnrs4VSrd*|4+PVS~BTJKYOqraZ3^c@Rdj zp&`mO5(S}d&pK-9tiuTqXf>r_?yQOY^Mc&q5(4;H0_N(JZXffT0>p^NrG2a?uW!{w zelURt`NyVW-zdSMC@HYrf#2d~I5nsRBh+}4F_?r}Z&<0{|RAPGjyLoFp zFh;Cvg}*953-r%GI!Z|N3S)Ha&3XD3ZaKz(v@7_gy%N7SF14Np9Zio@bNA32&5pP6 z?ewG0Ur=e1x6?Ok5ga3c*xS~j!iJ_0XO#Gn0PN}zq^+k~pG45!HkIEkP3H%{1`CUy zbyob-BmQRvB`M+`4@goUb}weW-vcOgB%nM1j37@SAmYl~C-lP-akV(k2`WO%1~m{l z#=ks7Y~DtijXhEylE!oK3z~2=dfxHiQ-`kL^GrC#fAo}C(ZN%qr#Lz4OQn4bZ7@BS z1ix~Un=?;7MpQCSXl|-`66Bdh;4|i#eL}jGmS+}$pH80H`EM7h#wo8}HM? z$CHi6^>^B$-{896y8o;iPTDnSQcohm2v5XfSN1plV2A`8H-L*-eiQI zDfTxQZH)iuqh(#k?y2#~@=&o(wJhw5O=b-G-_RCEOzL&XZxf|^%)qDGMXuynR?qib z{H_di>RfyabtI`D&))^g?@JF7<|GW}B-vB9m>&s?XvQ>7-6Z6sB<2^~LKAE8DQ^<< zt`yuEXJp?bOcOJ*kt3hjsVtW)7YZYP>N?+tOk|OM?PjSk@F*=XsFT;+H15f)5H^`~ zFfR6%)U9M~RF`8t)tdZCE2 zBB2x(Ukyr{9_cp}ep0wZZzw>cOM<@c3j0e$lDINitOg_rl*bB>oQmXWvK$OA6)vlM zv@j<5I#elb>T&X&hu7hJbHD!Qz9G8Upf!O`x*WN$R6Hn7x1PzGm1>t)Vvz$yw-0m( zh;5auL=K_*D@h!nP??4Fh-ro*okHcKpGa5)Vw>4yuPfSr}Y)gew~+eJxu z?!4P39N>|*3BlzIxU8pV7UR{&P-E_3q%r=ZRnG-maYti!b=bPG(+N^`g)ZD(oE#b@ zJ$%wl8s1GbtYhwOx`CuvGDu@pJXRX!$d2Ro=+U%oOiR^g`X)+4gj%h+xr%+7_T`{m zNVGiwju1Ye3Acc79uaPJz{wQP5}LYe9l#UmA#*Aeu!ntCUwR}p4^t$4UJ zK8|W;UNHuAlU-=CqP=pUTq*6Q=nLhL`g}lxxQq07);s zEx8RA!j-usEFQr%SW$qMS@DESXLeYaZAfbcc2~h};c?w9)53cl=Uls7><7*iyVj^&3;SCFyV64l&?bN)f?$BQ2<@&?@i2`AWxLyg{WOKCn24>drFf>sY-!jUPl~Tk!wI}47i!uM5^q;>`qZw@j_|t%QcQ?dN5mq+w ztxfaq)L3~40eZ$aR(qe&$4O@c6 zIj~q|v1slu4;^eDG3EV7L70nQ(CRXj1Y8~t1taf9SrmkDyP+@F+t*|zZ~bpUnjcUD zt!*Bmt+miL^Vx!S(-1_M{Z4_t- z?spkzg@Dj=H2xpKT4Ip^X#z;Lp0HWM_+&z)uBZP{UDYiBIR^u8AB-)#st4#MC*kF` z`Zu}%6r`Jk5HJmZ@tj_vF=h|f|5aVYNf_E|1k@7@y)jlTLKRwoHr7wv%342aQxH~2 z1-Tvs97;qRaHLN2iB79b*(EmKjeoQuK{9I7qVr-P>+UlN07tp;PJ5(-mWhh;e%g4){NN6Y;la5AD6QVcDC$J-*8Y ze?^oIkXO(pBnyQDoL5_v4JzWb_r_1t)xv0<8c*vSlGb2&84T@1Ip2)k#LF(8+gjn) z7}pfME@AfI)?U~-a&HzZVkOH7X&h8me%!5szsw;A>^XG7HAZ;;^jD!Rmm<3I9SY1L z0@zi6{j4QpzCf;mBNZ7luCrY}G&K&3skduSes6m-?Te$W{SVNARjqXnx8tAb+DBV| zZkVcD)dW-yh)Rv1^H4YhjHj5E@@?V?8#JQ9TB=k;M!t+|eQRBh zv^!T{W4Bv4*i)RUm$;geeH;7dY{Gd=7x9no*HjxqcN`RYs&iqj!W^FAVnc9Sb*eI4 zZy)US?gD+y1J({UObp09hX=Qe)>!TAJe8Lm99F13{y=HGI#ix?G`CSfTVxObihZPA zB(*DaQ$M9jOpwQjoQc`DtwE~?y~FDi7OoPYQ>Xo`&Fb5uEl!$E?tb!>r84Ic+?2$3Q0K zbTx{j!v4jX&>+wi=oKgn?|j5O8wI>P`X;KA5jm9mApVg4MUmtdKBTeAJTMU8Dg;1a z*b$&P&u3P!1<>}o6&{*OeWY4D6cNW#pp7|~YwFjH+_Uk7NcfWMd?4>Lke9Cn*mI@O z?BdWzOqMh7!I%g3FN;twOb3H7*C5Q!=-?Hevub)$}8LJ>eikLA&}K_3%Pyp8G-0(vK)y@FDM(3@go zeoP5!kpPVyE(i;`-A?hkd_n-@y)N(uIhb)yxW@&{SaJHTuL`OiasLI0t(|2k{z$=Ws_4<_m8*XDa#_~veuzMzErXnIq;Svhd*wHLcT+fYg%@cm}0|cUTqQ{6b_e()YeY@>7`d!4X&H09#1ry*xOgI*2f~@dLsjZ<+EUklqqK*rxAf# zCYTGfQv|pif$~hH^f1&)fpf!9uZYT+&+*E17gxJyc+7RVMi{L2HiqntaGY?p0ee%< zz|ZS3gWo(K?>AqcCeH@QGvw)iD|bOWw@ITg6RB<&sn#d3z*udBY`CD|%pcNKMp4XM ziX!Gr%Oae#mKW|$VYo1C2mB`BBXz~ar>ceZ(4k6;++<;X?z;qciA4|SHbBF2b)fT9 z?#_VTs&;SQg&aOUugcxRk4oRgfq?lIFn_?qoYJ4IcG{)nu+Hdsx<{mGj6;PiJ0Xk5 z?8+h0L*|t-B=&Hb0fDfyc!{G>WZ(DdY#gzot5`5|FM&-li+2HVqM>$4ST zzm!;Gi2}tGk0XngzSrbb`ld1aO_T z!R#!Ud1f`&=b|SJtUWxknDikZ8=yZR5}<&Wiw5@Rz}|C|Q>o)(dAu~-UriFg?CL>b zwA$Matj>c~lG*DIg4yA(s_ITm`0E0AaIIJSaF|gVNL_fPr-8gFx;80a60^ir(2!|Z zt(eNH{(^4Og`+$=d9=}8%}UESBBF~T=NAH>n&8 zt7Ll$oD=wdgorseqpOYZRw>n?pUUM-)k*`~#-nc){E}|5#nWQnXgPB2=uNuCPHM4` zE~-(^uICkmlbWuF=x*xUwv%pyIPyNKY4#J%jeXn5ka0-X5lW%7 zqw>F|Nk@rvK2p4gX=ie%-ma-oooG=&73KU+O?Z+BSJO#OmMz_tp;Se#<+h8CI0yST zbd%H6q;VJJcyFDWtU^iPc9?kd{)5x%J-XFdYSlnR+9&Y6=nW(0<4~W~)ToAX>I=kl<)B4g9Xc4PtN$V0;1V@hZqj$s z-G!qL{zo+VUlREWlYIMBtzLCM;vZ=G%S3y?bR^lZhrLz0{N5VkJ z8)*wj#Q_DKf;M|90WwMNBG^vc&oRI$c0k#5w7GGGX!xH(z&!PnCpPva!+T>MW1kny z#U?4XO3vBBT?`ve<_Im}_OglcM2Mm(fWj$VFkV8GX7vr!3XKu#NdXLApa_;TL2}v` zZiR)AISvVQPfeokqviJgvcN1d2>2X8HWcDeAx4ulPZ+7E1Z!bP2q?}9LtrL^%CRm@ z+Z_TAp(DT?ucwt<1|`5aRSZFq5UizRe5yVwXOI-Ov^w~80cvomfX3-$D31`LwFY{G zB>K_D*WTPg|38;&SKwq|nSy>p@Rvv0fdS{C!EX^V*rW(~BTR??mcTD_S^=Ch*5F(- zz_(6J&>e%cDg7M<>QDoe)7p@Ru0iu{{FBJ>|AX46z%n@=nKu&AR$Sb3k*z!3_CrFv{wd_UpV_~2y zSBDh1oC}CRl^$h!Vh2T8$?a7ePz$5%Ul}*t&MxW(mmauC?qfqG372XJaN8ZUcT<_B zVLzLB32Zik4cx_=O@0&nzP&W}O0@yCe+B&@hczXS94=ZfG%XVNwXx06ohI->m{{}4 zwQi$V3o3j<2Kdo?YRd$Cd4v|AeCyoak2cXojTFe00=dkg1mG4(X|F@dF%LdwH!aBa zm`}MzK$qIoz~rP!q>qF>cQLbl#`Uo*IGNJ=h;Sc}*t97Ph}6-YZ^Uxe-Y($e9x$3g ze7>5Fz)UE4gWq5{u$uoj+n-mf!KPq zOlln?j*OJ8rLf)XIOrhfS>Ra5zk%Zw)P=p@2YU{%Nc+>`<(hbS`m0kzqwVD}df2d? z|2r(oX8b?Wvb0~JOTY zxd1`z1C;M3*(XrDcft1wA{z-dJ-T=i$j;L2C>|``U!BASeQza!eS)~eq663^fN^q6 zIA8^JJW`eg-MzFGhldo9MFOD90D=cn;~3T9Q0bh!&+Qb>eV|kutkx-?KKSa1ov%#L1qL72T*YdHJ4IcpL*1^w6g4* znUQE@fG%Y1yv%JNMmD-UIu6|M<$B`?=fM?z!jQcbjuczy3vy|1AGi z#^wGUb=t%jZ*GBWvU7RguF{#n#N{tUhX=)!l{s!b(o&Nvz(pkur2VD_Qr)1|tVl`>>cb{UbA$S_a_NJh zuB<}(JE)m%W`VI_Wxh@RZ1;fP%2JFp%!s z8der;DKO1k*}Td+ZgNSPw@G4pd09z$S-f+yE7!TQ;IS%AT$-~e$LU=ut!y!SB_U~a zTdM+n>`i&BJg3T%Go-wv#Oo|AO_=N~F3WOESXr>`A^7!z9VuEuh33SRmw6J3TxF@Q zVrQ1qTjVNslvzApC3siC4r#AFI|VD?JH?2=fasm_MFeWBo{bgAxeDELKc-_d{z%X>OwD5Tq<#&0u^?%B zgCQ(LI?-S-t0P5*k0Sca@R;lf_SjNs6&I?W_Gb_QaP!^L#evk zii$_$>b6%Vl(3}H|WWi2vO%#EK z3(!;!3RZ$rJ-HJfHb=lw0(gi6^~uF$PH(;=*Qw&kSOIwq%5$XoiJ?k8bjU^0&cr54 zYM!9}oEWL3P7u^)17ctzlP>pfF0B~Q2|P^tct8e}GO2FT1en64-h&%S&n0z%=}h`E zDFZ4QzSo+Z;ei$YQfzV*Ji)L-2Go&eBsYfz4EwfW^`-ZcJHsM|Z#N@jwGV6qOBoKH z%k0vKfn7ji(z1ccfK=^iXe9kJusb}>q+xAZOOBLCc$P_XQx?JVOtPdVz)MUTo;np? zVaSZoP`aJk1YToOXj(6LgQ2Gb_2fxw4!fDOHZ30BX41v9Bxzei4R+~7OVxlusqg`l zRt*{nA2aFpph<9)NqOlWIKiYd>673zlaewf!52(=JEIcL^NEgui%fcYa58+ur0)g~ zgYTKtFLMn1#H433Q{iVOUC$f{zcQ)&kY(@(la34-5C1T!byipNea=gxTmFZyIH7Me ztOR)AP%Lq@t~&FC^^=+>tE@SY<94JZk-&q7x|~x=Jl?XnLKm$7O1;nt)Ko$Rrh8oz z)COr3rL(Bie~4=uH^OcYJ)2n+E~CQWRI+&938|f<%;iy8b%>0U^gA0V)x<8SF*}

&0=Il}#Kuba0u&cgu4s8VW#4eQywHMTTyPE1c^FNL5 z&LFjZvpaMHq206J><_&_`ryqh=m%2W-N_IK()QhTq-nc5!vOwg0;GWS$L^;f9i%yX zcEAvjy6hbX!$4ZSw+Kdo6!2CWi~}j_t#rr*Y4ckSm;jRY?HMo;r1@{Bfd`~BZ#$qA zr0(wwg()B{dnW^?gLLJc3~i-6s4A;u*=Lo~_9ep;Ag$S#4+~(${#meydfcB0OF{a4 ze{7}1vGST`eyCZrta%DmUK-^Yr}QVzn&X{0IMNDPOwaSnq#U0N@A;UdR4w`qd*rBIwWUEfoDpVtE|vD#F6hD=_yu? z@_894X%0jvW%#0?_C64Ml`}+nyn&JkRBM5cE}7+#@OuelJqFV81OYZlsDPE}k?` z9(9}NoT}_|zW{9^kU624%-+elRBLH}Pr$YlO#498%4QCV@=K`?I^$j@(OYA^{#c;6 zjad{^NpckDsa58P43r%2+Z6$y`?#onhpGn-a~0=#rYMJSQqT?1N|}_M)I3`=EV{VhmSg zYFd9jhR`I}gn~?G=@41DOA9<@@h(T9M;VH{uZmWZ57r;2Xyuw{WjJreoaFH4O>uag zapm4pk6Pt_61XiKXAT4f{I~0xG6OAq7jag!yq;c_H$CP+yp>qN`bEQBZ^WzIw z+7^y9aZvH2P<}E>>i1D-S4A&@qV8E<*O=wXo%pD#I#G4aN2&$MD5xhs3RlX|EE;U& zM-7Ii7pG5ldc7`gPqYh5aaPDXD&^oqL@PZ$R<&&x)RK=?OG22SKJ#(dSj80TiyjMj zk4C=I(fVE{@0=B&2mzYKL1qq0a+OgmP+AigDY|HSsIgLRO$2rPAzM#Ho6SU<%Xyo@ zX`XTla~&mRan7i>mjc)lL z9^y>;K0?}ZxFPiPlMWvq34Q&f=p!Q_)=!#sBm)xtq)(5O!9YJL>1YuQ@{@KS9R!(v zBIav$tP2eFlUVn9($r(IFw#$Y=U6U`^^+oxkA@sSsq%OsR5pOo;)5-9eQ z&U`Wzyna&piD59=Pug-K7pD11rjtqVxSuralh%FtjP{)9BwS)&+N7*=>DsR!^g8>TO?vlS z7r5dl{eEsZeCH=+oG+EWO4CS3&JTy1H2w=2@Qa@``NC-U-47eAhcM~-g>3lSPm23$ z0{rVIZT-p(;4g)JJstx6rDu09rK?xR!XSSs;kyjT^q26vVKCHRy7k>S7)c#` zKL*D7OWVI63pxH$@HMA4-=Aw#Rj8D4EmT^0EdkvA()nxCq1ay<{zH`X`9D_h(j5M& zo2^j($-L5zl=h_ie8(8?r6iVWk*E-W?gTLK3`wkm8=ML12CdZnN~qo&Rg z)Khm=)-q2}@7;}PpcvbeGBss9bzLW6YMIx8k*Aq8w>l13Bmg|xv1QOI=gBKCbaGc9 zcC)GlV2Qx;fS(+P*Xf`<&xBOxWM`oYwp@(l!+R ze{w$g_WKzH6{W7+(xINha&?a3H5t1qfVET(^mRc^XDSBl64WZzOc{smk*R6&4nK%* zkTRVVg?Y1F>W3i1J94VCB%g8VzMR!Z_kLGJFynkWT)MJA{9 z=KQI{cNyh{c|%-9<+O`*`t(Z4&Z`QzAt#n(aM3|RKere3vQxubyUb0|(L zFXr1T(+7b`{7Bj?{4gk8qW) ztkT^>K;&JKHYT}tZ@mRzygaO!$sSi8-*)>pfXZR@6Tkuv46MBn#){$+xgEJU&Qn;g zkdnkSN!5~>AS3a29aH7-lLWb)p4C-yGewZc=~+~7h2{?u-EHUHg``g@CZ+zbw83D} z!eKpAt(sYa>~ByHW0)ZKF|bxc75$AA{hj6g1q{h`s*@vQMCm178dRNEOLdj1T=#g< z_DKU%?ZIKD?eR|BT;%Cvj3^sM80UEi;*=}F7__bM3}sv^ZC?TqbwA4*BRAT z?h)jpMi!}T(kq(muWV92AW$krxv1OLq;7JmAdfSt*N5qXyvd}ty2l0iiiveoN`AH= zw+~YL?zw_IHi*?xq8AAAq97JMP9e92GC6I#yje>xmU$ZQq?092h1w4<7QjRDc9O>) z50W6t=`ItUM4DNBrD;o|?loRFlrPwM4E zL7rZNyhV_=1~XOO?-fD56wFk~>TQDD(4rRm4nZDoVG&AZ?v%-C%>!t_e%YC+O2+LL zW&L@XHgR}uZ}ye|Y~cVCpKX?-bYiV2ai2hK=cq8gYN9=asWun~WCX^9u!v3yW_}XSW>c#8r-EE)Wo^1B26aXz zrwtFJK^eHN4RPjriq+?MXGPU>R#rbpQT4p2TEMHCGo6mY|ET`8z?E=Zu$-Cv58!3d zkISZx7`_$c^)?nZO40rIqS?8;S$&3sGAWdXQU_5#3doZj5+n{@9(8tdLv#>nSFg~w z1bLWUt*5^V@*=xBQu$qw_t{yPlI?#9@^!mlVI9^`X>a#sa@tvWz=NDq%d)%< z+BDYOV?ZE}+;C1E7ClD6kpP*Tc8=H9@Y*#DKr6~G@p5a1*GZ?W54NTJ@K?3Y8blX$ zLe=YDkRT5ZWvXnrMYOEdP|I|t>~s{Dmx$ew>K=sKCU8cMGtwqHpXQf4vBt4Nr~n0X zkR^j+URQ3RlY@DHQawn1d|OXI!#LFHbI|`4bcYLUBaRJDFP4WVr$}pt-i-vXI|tf) z!0G^;I3}FR2(d|MEYKP9Xdi}AL!4!`ykt{>EZ|5@#*nxSk4LpFX(7sIX{3$2R65jJ zF2J^RSrW7l_={oZQI^zn&t#w%!=q8uR$GiAwPp|;2SD*EVlt3x6c?3?Y&!Qnc5I1q!kU;5F zk9v5I|2<5m*)gjDON3Fppw8+A%pc!uz#7B2Ks?`o#Y1i&MuxKyFd-0UgcELJAl^L0 z>fpI>)>G?|2VPYdZ-leD*d>CcLTMmA5y2cVB@n-hU>=wrh{GDP9+j0GDj$OxeYbOJ z#Su@){E@HW80AX?8I)L3$FlDE0;46~2T;VP&M7@53WKT8pWBUM)fnWi5`~SZ(7?^) z5sfbukmdw2%BMSzz^srlIJ*&Rs9VkdHo8{_;>(RlZfk|yu;evj;vbDjCL02=ek7X; zn*#aic@x|lNz&XLh?7pUdU!XI*!yze>O(9F$47!c7DTaj@G3RZmK0-q6bWHRAfAb0 zePEZ&^!nJYF?F*y5KsNWB5^@umIeC)@vFwHA$}6g!Ybe6C%IAipj8`JKvA04soDkK6y-@YT(eyM=!4kX0+vCrplU=N-?{(8WB)rc3~x7Q zR%Lkehp0W8Y6sFGm#ajns_wrd6EE@*OgPI0|Ue%_vC zz*r47@4yluN5gN!41jzMU4aS5GaYD>ZViTXWO-0b?Q|rIUE7hxfLH#J36nMaCf!Jw zropOCBCuUqVD;&89XE26k^aHyU058f z)8K(FEEAs5psg#5stm|ZDCS{s^=-cAcm>%QHFW#1X7KZ(=(IfzFQ8V~^76wG(WT9j zl0>>^qHyN!t)iG)pN{uR?rXg2Dx~{0fym;T%@KUNL{TO0C{bnauM6OC0vb3lg8~^k z_Ez?`ONQX2Y?8`e4Zfbu#=$-fT8EO<-qYaZp~Qs`HF#twTLXtRm^X~Y!f}O~zB`OH zg;N@N4QIodRd^VEAy>5YCda4rle04&s6s6<>)=Ih3@|a#Ft5>+q`bffp4+ z=b%TV{;pI*Y&krim`P{IlO1%i)l+Nr?0mHvY|e=(oZ_e`eE?Uo<61Q=BnO$7S$kEV zuKZM8Xw8Xp6c$o^N*4|bUA3<|-ISsD#0b_{IrZDsEogF*TzPqF|9q#qSewH$nd$lY z%F+EH%103AY&oPixlZCtOdh%U(o#o``Ub_{53u|SWlqA>+yY1O1ZQ3*-OZ_vPf1Ys z9^feA@q$frgz+c<^)u#4VCa?8kx zEu=e=@}=w#?~IJQmh)objl5Dn`)>*mIBvpwZgQohM36;ieu>xL>#4D=q9PM(@ruBVJvH_ zoP1Y79x#@v?#=WN`BzO6jJfd=^wg2>k?>#~l_i%l|mp zh!uS`AE(Z0CkXPyacTuh668(e)X_nTAYU4%p2r|TZZMuj^;OJcuuM+jW3!8~2?5J$ zRa)bkWR_^-$?@tv{V+j(XFO}Jw40Hl=`noTvgC%xrOse&$P{76$EF_LJ##6+zEb%TnC#%5& zk3i-TQlCj@yJb%9xRmt`8317<|yZiLiqs0z?-1Oz7Cx~sJ!I@8H5*d)u)OJMcquE zHK&|ZnJ3ek>!c&VTApgL01n|mlUzz$75Pj>InHGQmBmrUI6Cj=Jm>sZg4##|B_F2* z$!*EUsl_#J3$K=8cqC7q+FUDYiz5`8uKE)b_j*xW$cGTZ*N~Dt@-B&9IvaD=;K{QB zDxbF4(_F>>jjp6GUEI$Jco}b*^Z8K>*eozpIp+U4hTkG!GdPSc$d{J!b1d~Y8m|b* zEDq7ud(=*An~cEr`Rc6e4nZEBuMP`#iuN}0_5xFD-C^A=ins7$GbNiy7LOFlTLQO- zZFt@x4TN;r&{iB1@wY%*us;$R9olo1>`FZF{IO7$VVLV{3tMAa}4o^M$Y#-N(;Xs z5EnVZmKp5}Uuj7#&w0cpp<6NsLWece4gP6wAQxqHX@+NR^pKhj|b6RHci5 ziR#99p1n+PE~TwTb9Kph?aR7jiAdO93fMCB1W++0N2y(k_2TEr$mQyq>jW^QPy z!$ZYvsI+aj2BST+yX~mM0uLJvU3DVA`IU!IJ$0B|!g}la@(~!_eRa5`giV7O9qK2s zd61yP<&#*BHd!vN3dK(*Q35Q)%UVL34*Pm(lRsF8GrhD!&(`6GUfOMs(4n!EB^$ z8uVl~Q9JX&0G5nkVfgE0%COGXVY4YL8RqHGJB1C0r*wF13gz7v>o966?E{zV@Rg|$ zjvJ>^W^a`a4^L&u+O@t>;jO96hHWcYC)l9F+zMjsCLQjnptR^_V)!)5NxV$Fn8wPr zuZk)S(J_s(A@?ho4qHyAG{X)Z4xi4_VV4eHp3VlsULF26oyM_Ghv_p&Fz@N`e>2!< z?T4a%7+#t|LvK2hG8~6>m^YIRgX22fHG639I&X|P|(6bUZtu<8q1BSLaZIG(i6_X`KK%J?1|_DHM}l-YOq{ zg7|OI%Ng#dxvUM?_52g2B&e&$r{~fhJ6w+!=TZ(eQjgK|NJ*mgm^Y91=q>a-*ByZ$ z%%dLK=;eern@>aQpqFO#v}4MAN+@=bL3Vs@KB-j?4&ur0UeHG`oghr+0@hv|qv!fs zWyf&~NVT3_KnbM;JzifxAI;9B4Sw$@NypOkxcy010fY6}>M2s{Y(2j86n!b1c0z;Z zg~YTmdQ4wP8syO9x`ou2Q;$~`(#N;2p43Pk`-frTBAQx}9?KVz3?}LMM_~BdBFajY zQ;St>y|zM(qJ?z1V+;JVigLs=_1I!DOViF4C1IGcn1sH1F&V}@J$|*AO@XKMICKf= z$6`J1SVD%oT#xscP}XLZ9^;qN@3nedv6OhWL64`F5>GejvHmhP2{!9-$ud?5FYEE{ zG7{~pdK|u-M7=|g+m`c>g3oI4@^b2}*$OhCy?WfRf>dmu9)Dj!@_kQ_2@;_{Bne4m zXovOaw~~#P2A$Vn{z~fR6me@M8=^fUMqURmt|WDjT*Z3AmwFttie>A*@-aOVJ0SIQ zdKK#qm-T2`%|>ajin6*GvzpEuo?6X%X@3x;P<(bZDe^a~SwG_qL8{L)nu45wte5__ z51Hx2O{=*)k@b_(E^6>9k|F=4$HX=4ak!_)q6(;s7uT@PT4s1hLu8$0Yjfy_c>8- z57i6E%!pHe>9$!EzD0#5Dx}X&O6abVQw`c88h+~~^=kZzApi7|I$ql*$o03d`fU`$ z*dco28!3Oz17*muQ&jP6Axqd}sP>ZYZ=u7xcMQTy-rvF^;eY|7UM5RFXy6(2C|vY1 zYXyf4xaVcoQg@6uV{{)g;7>2JsH7A8r_6M1jMwX^hwN8dEh-$C@PrY5cD5?#lYG%sY(W3_A9vm(ynQ=wH z@xJ236Poj7{6^HnaN_;0J zHCwtVBk|BH>TUCFLH_3zwhn$X;JA-iQ{1{VJ0m=RCD zO70@Sh;_G-Bi0#l!Zs48$%xywvGHIr;*P=O_nN;(3zpp|YXUz}>;`p>{N%Mh9(;}5 zP`D8|13S0VYSzMtx3^Oq*T#q$J7|^aV8q!& zsM@t1wCHr9uKXYr+rCZ)-@}O8?@{a0>$Ir#F=GECS6>pbi)e?v7 zr#d@jfz`v8_tV_>_yqO)ewyApK0)QYOY%J66VyNNQXF(p7Sw7u2WZ(j<`YQ7 zCoB+44=@WZv_Mlh=@ZS5@6j+m^D#Q{eNvgTGNT*gi|>=RUhr|-_yH-=C7HpISoHzz zAikBk9D$cVp!NBhkJTLyl1#7rbZqxQlI1N~>hZceg8z4nnD`-U7XOEj|IMocl8bAc z;{PM_Up~9k%U-M2I`OZN(7q4ZMgS9+&`t<63E_14m^IMpOmSiCIh}u*G0E30b{yi1lbzSFTxQ;;}<~xj46Qu3UBZ)5qlh(NiY;WVjvP zK0#_1ahMD{oErBX*au+lVd^f@Bo62g9;Ssh+Qbj&>toyz5`GJlu-a#j5YyTaj2r6h zBeec@FmXd|iDQqFJi3^;wbsKoj*<`PVG>q)|0wBLACs_B_c2dz>a=OYfd!PH>ro6Nx*;?UK6MOTjjtVj0>=f_pyiVEmM|YEjNf+|o=B zoV0wkLuqgo9I^xRKP5Lf(9}Ue-Y)=s9bcR1n7C9@i!TPd%vdm@Gqt5 zSuT>y?)d~5e2@0Ho{J;|79>r!XRN4 z4K5RR>_OZrn&8sQB<#9D!YabA(7F;%t#PZEb)9K(`xOe1BZGu#Ec=7}VV`eEv!a8< zDz)+(QuG!<+&E~#3=+#s=C^#`NOic5Z~m4V=n^Efzxh=%^&UZDQCoVI)z|e2BHkL^ zeS+|ftE}mO{`{vbilA)%EmL6yoyKq@P;xV#gM>W%#rb*lS?U0}3|oK4n(9(S+bKaf z>O0nl4Z;Jh$pOhXjdpy;QduU((1jt4{GPelP_(qARkx850&vIo#JQ0{!e$!!5yfzg zC}WA`{0>q6HRfPBc%d5S!x<)XUqhcB*JS&1 zGHc~EMmN+^SWdUW)N7}_S?+G-hU`pT19_h z?ct*!9BYIqT=xs9@ex_1v)Ly?nx0=-FZQWIn%hjE#go61cs}=uH1ZCy^PJE4Cfy-x z{n{tj3wKD^S9~IE_Z!LgJD*6$nW>f8zfrXDqb$<;c;z=X8E(qbY>Kmfr>*oavLLJA z_i9t?1%H!a{XtUx*Jo|%e^TdQ7E95VKS?J8&0;AE_=`lYH}j<^8pr)bo6aD!Sc=a4 zMe__XbNNSL%fD%ns$&+$xcP53NL$a$dHEnVrParPjsIcw8bxqAUxI2`SQIbWfw}+C z+?$#eLBiYrP-x!LEH6K;?$Um{tyu&KZ{MYnb~FonA{W*Tx|)Uea@-?N)YHs8(F*8m ze&~dBIPqU%N~~GoiNfxY8ECR$7$lm7JDPEyw0WR!HuvunZw8rH^@rZNOnFl7O!KOF z(5hwjgQ?KDlkZugTFdDOc~Yw`!3G#(=0VYTa8TzAMu5{d)+~SoaG8a3{ScrJ6#1q^ zE}{=iG7C>T)sG%rDK~RZ>w*e-YW1<3KhXByH^0;VK!LVdthGr2Pz3XQ^SqHoigGD{ zDn8|#VqqYxg~euJ32ij=e#>%Ml%Y6V13h4slK-bQ&>7a6#YM@+S{Mu)gfP}Zqem# zGk&Uv-td-ku+0qg*35n}J~C7dZZJR&yf16aDEP?CjdU0sA>RK&fy6~43E~s8hziL{ zwK&EEo#0by@nINAw%QXumxUINnjj!E^+|465RjSrB=>$0$>)ksSY)PJ3^zjy_)eBs zD3YzF!jC?&9Wn!%sVug6@QW;@7I-U|-oE+WC!fg{>hy0K#wWCRka=qHoCVs#zdjpn z6$0G>f`yGf8A3x24CXdE74*TvJcnDM3j_so^PC1D!MJkIFuWl=4^hEFS*|sN<edsb#)S!GP6Gp+C5k)1-|{8Wj1a*$mplB;Pc*HY4*X_e~R;6MHIr)68m4446qn z=Ba|$nnMiC_RYCL3vR2v@o#NGdi0cU$ah;12Nwrphn6rBmIw2gwwG>|n8GS*w#b=*+r`{h zw}EWfDP~>KhP=Wa->eU}A$h*z8+3SE>gs?z*oHW-E%}IpV#Ei7aa&tx9RIOz#LcU8 znI3u*i@%?!jKhw~Lr&or?g9x=9HJva?LC&u&*rGJ$6^OYdiZx4-im-*jD z_vK(5(4G|G+hClMLAjY1+mpDj1>?o`Fchu_W48{F47Y-DP6txCJHdFc0}O#bgRyQ$ z(tx`{4E(J*tm;Sx{+I*54vo8rH!z{O@=RUhYQIO0r1X8-`&*cbEyO7U@EhDEzKFDQJd8>K5G)V|&oi zX%=tO=+3fWQ4eTdIgI}l`vZROn(ppA;&6GCJP!HMQ48IMr29bLiihtID5p180C|?v z;=?7-({A(;bq!s12;g{Z+EYE{Jh=cz_XO1|4if})eEwd=*r_)- zq0%Bbeu|X({iw&0y`haX`9}*pA!z?2TKhiG7Z%9Bad{t-#v=ZAE7bNS2`#nY;J)PS zB#X4^MiczDFD;5F|1F)nuE+8HAQqk$zf*7M@x$H_ECpYWlos3wgJ(ItEvEFRI?r3A z@S7d*NPqHUFIl98H``&C7%0}hB8DC%S+0jlU;j+&bPN>0YZmF9x(Sa|1QVLNHpot|)%(_11AAPqht8vAVk1rMh!*fj}8!xt6_e~-jn zNl>Ld|6mRq{)obf$*=-0TJS!ddc!vsoIeoq;d=|-90*I`CksBF0>j~F3!Y7ZsoGyf z&AQT8f7iuHspL@puweT%h?H*prsvEG#$~Bc4RmIEEpZagP4Z+=U@my-A}Yt86P4dnK4;p0(sOL z&xTNJJ_!m!cn{Akkdmt+ov;`-4r7hVYwkz4;UP!6y8CV!S* zRfac0M97*umL87W9pX!Fj^#EevywPIj^_Jr2(B3itKfqWY&V{E10RRrzVYxRrp=%z zKh;4ys}mu(jsJT(1cP%RN%w`|%oic($bqP4=lD-q)AbKNJygBT;Qm_hX?qUXm3J;L z%jC4~e&k+FbQDUTY~<2clQmwk`&OWObCjMRn9@C_8XsYPFChInL_?5RkK)ryGKU{U zc|4U@R+;G%AwT~VugKN76D5F2ydfJkB)(`ZsJBI@GHj~xuANW<#)LV>*qmZ<*N^Wi5l{oZz1%!Wpc5Dj*}-lA2E)*qJ{Z+pt?zY zUy$F=qeb1%ibf~B`KhsDg%c8W2CM8Q3|2hkq$o7VihlV73$bEaKCLo!thhLz!lZgu zJdsZ;M}!rv6DWL&vf^0&Z&NG2Jb`w5Ev-muHU`>S(NRDVY)32ZDWGjiS1amWf;DHvqM`V+wmnO0mnkv3~Xt$1f5l)*?V zx(lHg##-?lz0?LdR*WrzOvtz5>LQ}Mtr%EL`;}rVmK8&P=EajsDX(|Dm^|WS>uL{0 z+ta8k4|&VSt!R0I5-OWL&>H4g@wA7=JDG2=;S zf$^nedH`0SeO$?Sl;pOiEdFbZ7{LFZDeDaP34&Y-^yq&iaER>Ib*<4%2j|ku%4%8-P$JgrUxC}tkWC&A!MSfD$J0uVDp$Di{ z`?RR-nhdHJXg(L@t&>6ZiT9VH(M!BhgMvv)o4g<}*Er^pPs+G23dAjrpv!k&djE~j z{lS+$>Z`z4Mhf(w9Bp~ejRgD0nx|^_2ZzoMazSyQk?UfmEZ46g}?~ z{euef`vEqLo(40uIvaNzRna(l8f7ipJ1Nor*)*zeqWgc-VIx>un>u55?5kWRv}E`1owve#P7H z^lb7QNj7XYhx|^ejhpsB$gpwe5QZ1#(E6Tb;~pX%hTAab39|0dHvHiU>TkRa+s%bh zkY~fHxn$b~HvDWZ(F<)@Zyq_j5*rrIqtr;5ja&9um}#I3!pvzy@2@pq>a0Yu~22>zGDb1vvGeAfsLP{6@R4-y-$&oTVum3PmwcR zZ^PjWX%ZW4+-ar33pV^`A@#e(hNBk|)3)01`XX2f+if_fiXL{}X~SQuU?}XdVaj4^ z=N%iqy_lBw12#-v0uDGx?eKpO+0eWc2Ej2KcX3a^NgIBy=jgg-G)D|plsPK8|Fz+q`f01T?aQx z6srC#K_2{R!|as=y=%k$E9v)Rc5Jc=+~9BLZgMYZ>F(lcT6BzdT)JAFiU_uI-n3EPafn+6h|)w*Mor!wOvL_@s`&@Th6jKe9W|FB7`z4=D8sB)qUJKH8O9$Sl;2&Vr|}A%^gtWk%Pyiv zmzCpfEASf$A57nM$q&9#az?)1uEcc^xb1`s$cZcSD&L2Qc6Y8W4Wx(6T=}X@R5!U4 zZ>~`XLp=q#!CG~?w2vUCt);|@!VC5nJUO0DG=?9C5)be5ITg09k! zOt~>!vkp{G3}p-Qv2~PG8NvTHx<}aYk9Cy!9Bt=Ukuzbu9p^nwt|-rrN1rCwRbb~2 zwkANK9dp-{e=D)$Yy96bJN~nt?`-TCzk&SC3_HF+=O!@Aj(*RO-5anG~l`c~R;#zxxTw%bU%wKejOF|gi_=QmQ}Mmu)jMCs%g?6_zX zHMYf$mo|}K*((1VhNGS%ue{xk8=s>++)nx5P>gyWVzhhYSo1VAJ!VJ$%`}6PcFfyMGyTktuWY83^S{JdZGRj;a(#Aw{{%L|Gj3%EiVxVuG{hUOOVs(mgrhXtGamda3%c*cFxjrO8?E4 J^3t5P{|9H*R Date: Sun, 25 Feb 2024 02:37:04 -0600 Subject: [PATCH 106/213] add cppmod for linux --- UE4SS/src/Mod/CppMod.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 3a08fbb67..85c82f443 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -57,7 +57,26 @@ namespace RC } #else + // use RTLD_LOCAL to avoid symbol conflicts + m_dl_handle = dlopen(dll_path.string().c_str(), RTLD_NOW | RTLD_LOCAL); + if (!m_dl_handle) + { + Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), to_system_string(dll_path), m_mod_name, dlerror()); + set_installable(false); + return; + } + m_start_mod_func = reinterpret_cast(dlsym(m_dl_handle, "start_mod")); + m_uninstall_mod_func = reinterpret_cast(dlsym(m_dl_handle, "uninstall_mod")); + + if (!m_start_mod_func || !m_uninstall_mod_func) + { + Output::send(SYSSTR("Failed to find exported mod lifecycle functions for mod {}\n"), m_mod_name); + dlclose(m_dl_handle); + m_dl_handle = NULL; + set_installable(false); + return; + } #endif } @@ -183,6 +202,12 @@ namespace RC FreeLibrary(m_main_dll_module); RemoveDllDirectory(m_dlls_path_cookie); } + #else + if (m_dl_handle) + { + dlclose(m_dl_handle); + m_dl_handle = NULL; + } #endif } } // namespace RC \ No newline at end of file From d0e90a9e9c6df39017c2144d39bb4adab90190c8 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 02:45:34 -0600 Subject: [PATCH 107/213] use get_path_if_exists to look up --- UE4SS/src/Mod/CppMod.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 85c82f443..bf321f5ad 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -16,20 +16,27 @@ namespace RC { CppMod::CppMod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) { - std::filesystem::path m_dlls_path = m_mod_path; - - m_dlls_path = m_dlls_path / SYSSTR("dlls"); - - if (!std::filesystem::exists(m_dlls_path)) + auto resolved_dlls_path = File::get_path_if_exists(mod_path, SYSSTR("dlls")); + if (resolved_dlls_path) + { + m_dlls_path = to_system_string(*resolved_dlls_path); + } + else { Output::send(SYSSTR("Could not find the dlls folder for mod {}\n"), m_mod_name); set_installable(false); return; } - #define STRINGIFY(x) #x #define CONCATENATE_WIDE_STRING(name, ext) SYSSTR(name) STRINGIFY(ext) - auto dll_path = m_dlls_path / CONCATENATE_WIDE_STRING("main", DLLEXT); + auto resolved_dll_path = File::get_path_if_exists(m_dlls_path, CONCATENATE_WIDE_STRING("main", DLLEXT)); + if (!resolved_dll_path) + { + Output::send(SYSSTR("Could not find the main dll for mod {}\n"), m_mod_name); + set_installable(false); + return; + } + auto dll_path = to_system_string(*resolved_dll_path); #ifdef WIN32 // Add mods dlls directory to search path for dynamic/shared linked libraries in mods m_dlls_path_cookie = AddDllDirectory(m_dlls_path.c_str()); @@ -58,7 +65,7 @@ namespace RC #else // use RTLD_LOCAL to avoid symbol conflicts - m_dl_handle = dlopen(dll_path.string().c_str(), RTLD_NOW | RTLD_LOCAL); + m_dl_handle = dlopen(dll_path.c_str(), RTLD_NOW | RTLD_LOCAL); if (!m_dl_handle) { Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), to_system_string(dll_path), m_mod_name, dlerror()); From 29ccaa53db2aab1245e41ad3ef3c9f54e37d4a40 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 03:35:22 -0600 Subject: [PATCH 108/213] add GLFW support, seperate build required, it looks a bit weird on WSLg.. --- UE4SS/include/GUI/GUI.hpp | 7 +++++-- UE4SS/include/GUI/LiveView.hpp | 2 +- UE4SS/src/GUI/GLFW3_OpenGL3.cpp | 2 +- UE4SS/src/GUI/GUI.cpp | 18 ++++++++++++------ UE4SS/src/GUI/LiveView.cpp | 8 ++++---- UE4SS/src/SettingsManager.cpp | 4 ++++ 6 files changed, 27 insertions(+), 14 deletions(-) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index d1d6e2b35..e9ec3bc26 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -11,7 +11,8 @@ #include struct ImGuiSettingsHandler; -#ifdef WIN32 + +#if defined(WIN32) || defined(HAS_GLFW) #define XOFFSET (-14.0f) #define XDIV 1 #define YDIV 1 @@ -24,11 +25,13 @@ struct ImGuiSettingsHandler; #endif #ifdef LINUX +#ifndef HAS_GLFW namespace ImGui { static void BeginDisabled(bool disabled = true) {} static void EndDisabled() {} } #endif +#endif namespace RC::GUI { @@ -38,8 +41,8 @@ namespace RC::GUI { #ifdef WIN32 DX11, - GLFW3_OpenGL3, #endif + GLFW3_OpenGL3, #ifdef LINUX TUI #endif diff --git a/UE4SS/include/GUI/LiveView.hpp b/UE4SS/include/GUI/LiveView.hpp index 64e4d5071..1a4e28915 100644 --- a/UE4SS/include/GUI/LiveView.hpp +++ b/UE4SS/include/GUI/LiveView.hpp @@ -89,7 +89,7 @@ namespace RC::GUI UObject* m_currently_opened_tree_node{}; std::string m_current_property_value_buffer{}; int64_t m_current_enum_value_buffer{}; - #ifdef WIN32 + #if defined(WIN32) || defined(HAS_GLFW) float m_top_size{300.0f}; #else float m_top_size{14.0f}; diff --git a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp index 24727ba9a..77e238d1b 100644 --- a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp +++ b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp @@ -14,7 +14,7 @@ namespace RC::GUI { static void glfw_error_callback(int error, const char* description) { - Output::send(STR("Glfw Error {}: {}\n"), error, to_wstring(description)); + Output::send(SYSSTR("Glfw Error {}: {}\n"), error, description); } auto Backend_GLFW3_OpenGL3::init() -> void diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index f53fe8c3b..8ce90cc46 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -13,6 +13,9 @@ #include #include #else +#ifdef HAS_GLFW +#include +#endif #include #endif @@ -22,7 +25,7 @@ #undef TEXT #endif -#ifdef WIN32 +#if defined(WIN32) || defined(HAS_GLFW) #include "Roboto.hpp" #include "FaSolid900.hpp" #include @@ -222,7 +225,7 @@ namespace RC::GUI ImGuiStyle& style = ImGui::GetStyle(); style.WindowPadding = ImVec2(8, 8); - #ifdef WIN32 + #if defined(WIN32) || defined(HAS_GLFW) style.FramePadding = ImVec2(12, 5); #else style.FramePadding = ImVec2(0.5f, 0.5f); @@ -280,7 +283,7 @@ namespace RC::GUI style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.55f, 0.22f, 0.45f, 1.00f); style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); style.Colors[ImGuiCol_Button] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); - #ifdef WIN32 + #if defined(WIN32) || defined(HAS_GLFW) style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); #else @@ -297,7 +300,7 @@ namespace RC::GUI style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.92f, 0.24f, 0.84f, 0.67f); style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.92f, 0.24f, 0.84f, 0.95f); style.Colors[ImGuiCol_Tab] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); - #ifdef WIN32 + #if defined(WIN32) || defined(HAS_GLFW) style.Colors[ImGuiCol_TabHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_TabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); #else @@ -512,7 +515,7 @@ namespace RC::GUI io.Fonts->Clear(); float base_font_size = 14 * UE4SSProgram::settings_manager.Debug.DebugGUIFontScaling; -#ifdef WIN32 +#if defined(WIN32) || defined(HAS_GLFW) ImFontConfig font_cfg; font_cfg.FontDataOwnedByAtlas = false; // if true it will try to free memory and fail io.Fonts->AddFontFromMemoryTTF(Roboto, sizeof(Roboto), base_font_size, &font_cfg); @@ -548,15 +551,18 @@ namespace RC::GUI m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); break; + #else + #ifdef HAS_GLFW case GfxBackend::GLFW3_OpenGL3: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); break; - #else + #else case GfxBackend::TUI: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); #endif + #endif } m_gfx_backend->set_os_backend(m_os_backend.get()); diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 6489e3a2b..833f3982c 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -49,7 +49,7 @@ #include #include -#ifdef WIN32 +#if defined(WIN32) || defined(HAS_GLFW) #include #else #include @@ -3446,7 +3446,7 @@ namespace RC::GUI ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); -#ifdef WIN32 +#if defined(WIN32) || defined(HAS_GLFW) ImGui::BeginChild("LiveView_TreeView", {-16.0f, m_top_size}, true); #else ImGui::BeginChild("LiveView_TreeView", {0, m_top_size}, true); @@ -3584,7 +3584,7 @@ namespace RC::GUI } static int num_columns = 3; - #ifdef WIN32 + #if defined(WIN32) || defined(HAS_GLFW) ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, {2.0f, 2.0f}); #endif if (ImGui::BeginTable("watch_table", num_columns, ImGuiTableFlags_Borders)) @@ -3670,7 +3670,7 @@ namespace RC::GUI } ImGui::EndTable(); - #ifdef WIN32 + #if defined(WIN32) || defined(HAS_GLFW) ImGui::PopStyleVar(); #endif } diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index 00935cfef..1c7eaab99 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -97,9 +97,13 @@ namespace RC Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; } #else + #ifdef HAS_GLFW + Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; + #else Debug.GraphicsAPI = GUI::GfxBackend::TUI; #endif #endif + #endif REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); ///constexpr static SystemCharType section_crash_dump[] = SSTR("CrashDump"); From a8b8c90e9c47ff343277aff04be01dcb9dd4b7ec Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 03:45:40 -0600 Subject: [PATCH 109/213] clang format --- UE4SS/generated_include/MacroSetter.hpp | 33 +- UE4SS/include/Common.hpp | 1 - UE4SS/include/ExceptionHandling.hpp | 4 +- UE4SS/include/GUI/GUI.hpp | 17 +- UE4SS/include/GUI/LiveView.hpp | 6 +- UE4SS/include/GUI/NerdFont.hpp | 2 +- UE4SS/include/GUI/TUI.hpp | 48 +- UE4SS/include/Mod/CppMod.hpp | 2 +- UE4SS/include/Mod/CppUserModBase.hpp | 4 +- UE4SS/include/Platform.hpp | 4 +- .../SDKGenerator/UEHeaderGenerator.hpp | 19 +- UE4SS/include/SettingsManager.hpp | 12 +- UE4SS/include/UE4SSProgram.hpp | 12 +- UE4SS/src/EntryLinux.cpp | 391 +++++++++-------- UE4SS/src/EntryWin32.cpp | 7 +- UE4SS/src/GUI/Dumpers.cpp | 41 +- UE4SS/src/GUI/GUI.cpp | 45 +- UE4SS/src/GUI/ImGuiUtility.cpp | 6 +- UE4SS/src/GUI/LiveView.cpp | 24 +- UE4SS/src/GUI/TUI.cpp | 87 ++-- UE4SS/src/GUI/UFunctionCallerWidget.cpp | 16 +- UE4SS/src/LuaLibrary.cpp | 6 +- UE4SS/src/LuaType/LuaCustomProperty.cpp | 3 +- UE4SS/src/LuaType/LuaUObject.cpp | 2 +- UE4SS/src/Mod/CppMod.cpp | 11 +- UE4SS/src/Mod/CppUserModBase.cpp | 2 +- UE4SS/src/Mod/LuaMod.cpp | 410 +++++++++--------- UE4SS/src/Mod/Mod.cpp | 1 - UE4SS/src/ObjectDumper/ObjectToString.cpp | 3 +- UE4SS/src/SDKGenerator/Common.cpp | 2 +- UE4SS/src/SDKGenerator/Generator.cpp | 53 +-- UE4SS/src/SDKGenerator/JSONDumper.cpp | 2 +- UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp | 134 +++--- UE4SS/src/SettingsManager.cpp | 74 ++-- UE4SS/src/UE4SSProgram.cpp | 90 ++-- UE4SS/src/USMapGenerator/Generator.cpp | 2 +- UVTD/include/UVTD/Helpers.hpp | 112 ++--- UVTD/include/UVTD/Symbols.hpp | 2 +- UVTD/src/Helpers.cpp | 3 +- UVTD/src/MemberVarsWrapperGenerator.cpp | 8 +- UVTD/src/Symbols.cpp | 2 +- UVTD/src/TypeContainer.cpp | 12 +- UVTD/src/UVTD.cpp | 2 +- UVTD/src/VTableDumper.cpp | 5 +- .../ASMHelper/include/ASMHelper/Common.hpp | 1 - .../Constructs/Views/EnumerateView.hpp | 51 ++- .../include/DynamicOutput/Output.hpp | 3 +- .../include/DynamicOutput/TestDevice.hpp | 2 +- .../DynamicOutput/src/DebugConsoleDevice.cpp | 14 +- deps/first/File/include/File/File.hpp | 3 +- .../File/include/File/FileType/FileBase.hpp | 1 - .../File/include/File/FileType/StdFile.hpp | 8 +- deps/first/File/include/File/Macros.hpp | 44 +- deps/first/File/src/File.cpp | 4 +- deps/first/File/src/FileType/StdFile.cpp | 66 +-- deps/first/File/src/FileType/WinFile.cpp | 39 +- .../first/Helpers/include/Helpers/Casting.hpp | 3 +- deps/first/Helpers/include/Helpers/Format.hpp | 2 +- deps/first/Helpers/include/Helpers/String.hpp | 315 ++++++++------ deps/first/IniParser/src/Experimental.cpp | 5 +- deps/first/Input/include/Input/Common.hpp | 1 - deps/first/Input/include/Input/Handler.hpp | 27 +- deps/first/Input/include/Input/KeyDef.hpp | 20 +- .../Input/Platform/NcursesInputSource.hpp | 44 +- .../Input/Platform/QueueInputSource.hpp | 77 ++-- .../Input/Platform/Win32AsyncInputSource.hpp | 106 +++-- .../include/Input/PlatformInputSource.hpp | 58 ++- deps/first/Input/include/Input/RingBuffer.hpp | 5 +- deps/first/Input/src/Handler.cpp | 15 +- deps/first/Input/src/KeyDef.cpp | 9 +- .../Input/src/Platform/NcursesInputSource.cpp | 328 ++++++++------ .../Input/src/Platform/QueneInputSource.cpp | 17 +- .../src/Platform/Win32AsyncInputSource.cpp | 2 +- deps/first/Input/src/PlatformInit.cpp | 14 +- deps/first/JSON/include/JSON/Bool.hpp | 3 +- deps/first/JSON/include/JSON/Null.hpp | 3 +- deps/first/JSON/include/JSON/Number.hpp | 3 +- .../include/LuaMadeSimple/Common.hpp | 1 - .../include/LuaMadeSimple/LuaMadeSimple.hpp | 2 +- .../include/SigScanner/Common.hpp | 1 - .../SigScanner/SinglePassSigScanner.hpp | 23 +- .../SigScanner/SinglePassSigScannerLinux.hpp | 9 +- .../src/SinglePassSigScanner.cpp | 12 +- .../src/SinglePassSigScannerLinux.cpp | 29 +- .../src/SinglePassSigScannerWin32.cpp | 18 +- 85 files changed, 1732 insertions(+), 1378 deletions(-) diff --git a/UE4SS/generated_include/MacroSetter.hpp b/UE4SS/generated_include/MacroSetter.hpp index d041d9aaf..6a0eb0afa 100644 --- a/UE4SS/generated_include/MacroSetter.hpp +++ b/UE4SS/generated_include/MacroSetter.hpp @@ -74,7 +74,8 @@ if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("EventGraphFunction" Unreal::UFunction::MemberOffsets.emplace(STR("EventGraphFunction"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("FirstPropertyToInit"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("FirstPropertyToInit"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("Func"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("Func"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("Func"), -1); val != -1) + Unreal::UFunction::MemberOffsets.emplace(STR("Func"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("FunctionFlags"), -1); val != -1) Unreal::UFunction::MemberOffsets.emplace(STR("FunctionFlags"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UFunction"), SYSSTR("NumParms"), -1); val != -1) @@ -110,7 +111,8 @@ if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("PropertyLink"), -1); Unreal::UStruct::MemberOffsets.emplace(STR("PropertyLink"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("RefLink"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("RefLink"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("Script"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("Script"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("Script"), -1); val != -1) + Unreal::UStruct::MemberOffsets.emplace(STR("Script"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("ScriptAndPropertyObjectReferences"), -1); val != -1) Unreal::UStruct::MemberOffsets.emplace(STR("ScriptAndPropertyObjectReferences"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UStruct"), SYSSTR("ScriptObjectReferences"), -1); val != -1) @@ -351,7 +353,8 @@ if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("LastNetUpdateTime"), - Unreal::AActor::MemberOffsets.emplace(STR("LastNetUpdateTime"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("LastRenderTime"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("LastRenderTime"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("Layers"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("Layers"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("Layers"), -1); val != -1) + Unreal::AActor::MemberOffsets.emplace(STR("Layers"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("MinNetUpdateFrequency"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("MinNetUpdateFrequency"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetCullDistanceSquared"), -1); val != -1) @@ -362,7 +365,8 @@ if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetDriverName"), -1); Unreal::AActor::MemberOffsets.emplace(STR("NetDriverName"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetPriority"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetPriority"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetTag"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetTag"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetTag"), -1); val != -1) + Unreal::AActor::MemberOffsets.emplace(STR("NetTag"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetUpdateFrequency"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("NetUpdateFrequency"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("NetUpdateTime"), -1); val != -1) @@ -475,7 +479,8 @@ if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHasFinishedSpawning") Unreal::AActor::MemberOffsets.emplace(STR("bHasFinishedSpawning"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHasRegisteredAllComponents"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bHasRegisteredAllComponents"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHidden"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bHidden"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bHidden"), -1); val != -1) + Unreal::AActor::MemberOffsets.emplace(STR("bHidden"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bIgnoresOriginShifting"), -1); val != -1) Unreal::AActor::MemberOffsets.emplace(STR("bIgnoresOriginShifting"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("AActor"), SYSSTR("bIsEditorOnlyActor"), -1); val != -1) @@ -633,7 +638,8 @@ if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("FlagsPrivate"), -1); v if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("NamePrivate"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("NamePrivate"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("Next"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("Next"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("Owner"), -1); val != -1) Unreal::FField::MemberOffsets.emplace(STR("Owner"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("FField"), SYSSTR("Owner"), -1); val != -1) + Unreal::FField::MemberOffsets.emplace(STR("Owner"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("FClassProperty"), SYSSTR("MetaClass"), -1); val != -1) Unreal::FClassProperty::MemberOffsets.emplace(STR("MetaClass"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("FBoolProperty"), SYSSTR("ByteMask"), -1); val != -1) @@ -692,7 +698,8 @@ if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("LevelSequenceActors"), Unreal::UWorld::MemberOffsets.emplace(STR("LevelSequenceActors"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NextSwitchCountdown"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NextSwitchCountdown"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NextURL"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NextURL"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NextURL"), -1); val != -1) + Unreal::UWorld::MemberOffsets.emplace(STR("NextURL"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumInvalidReflectionCaptureComponents"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("NumInvalidReflectionCaptureComponents"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("NumLightingUnbuiltObjects"), -1); val != -1) @@ -769,7 +776,8 @@ if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bHack_Force_UsesGameHi Unreal::UWorld::MemberOffsets.emplace(STR("bHack_Force_UsesGameHiddenFlags_True"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bHasEverBeenInitialized"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bHasEverBeenInitialized"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bInTick"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bInTick"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bInTick"), -1); val != -1) + Unreal::UWorld::MemberOffsets.emplace(STR("bInTick"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bInitializedAndNeedsCleanup"), -1); val != -1) Unreal::UWorld::MemberOffsets.emplace(STR("bInitializedAndNeedsCleanup"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UWorld"), SYSSTR("bIsBuilt"), -1); val != -1) @@ -866,11 +874,14 @@ if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("SparseClassDataStruct" Unreal::UClass::MemberOffsets.emplace(STR("SparseClassDataStruct"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("UberGraphFramePointerProperty"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("UberGraphFramePointerProperty"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("bCooked"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("bCooked"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("bCooked"), -1); val != -1) + Unreal::UClass::MemberOffsets.emplace(STR("bCooked"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UClass"), SYSSTR("bLayoutChanging"), -1); val != -1) Unreal::UClass::MemberOffsets.emplace(STR("bLayoutChanging"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("CppForm"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("CppForm"), static_cast(val)); -if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("CppType"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("CppType"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("CppForm"), -1); val != -1) + Unreal::UEnum::MemberOffsets.emplace(STR("CppForm"), static_cast(val)); +if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("CppType"), -1); val != -1) + Unreal::UEnum::MemberOffsets.emplace(STR("CppType"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("EnumDisplayNameFn"), -1); val != -1) Unreal::UEnum::MemberOffsets.emplace(STR("EnumDisplayNameFn"), static_cast(val)); if (auto val = parser.get_int64(SYSSTR("UEnum"), SYSSTR("EnumFlags_Internal"), -1); val != -1) diff --git a/UE4SS/include/Common.hpp b/UE4SS/include/Common.hpp index 5aaf184f8..ac04e76f1 100644 --- a/UE4SS/include/Common.hpp +++ b/UE4SS/include/Common.hpp @@ -18,5 +18,4 @@ #define RC_UE4SS_API #endif - #endif diff --git a/UE4SS/include/ExceptionHandling.hpp b/UE4SS/include/ExceptionHandling.hpp index 71fdef3ba..ee87974a2 100644 --- a/UE4SS/include/ExceptionHandling.hpp +++ b/UE4SS/include/ExceptionHandling.hpp @@ -8,11 +8,11 @@ #define UE4SS_ERROR_OUTPUTTER() \ if (!Output::has_internal_error()) \ { \ - Output::send(SYSSTR("Error: {}\n"), to_system(e.what())); \ + Output::send(SYSSTR("Error: {}\n"), to_system(e.what())); \ } \ else \ { \ - fprintf(stderr, "Internal Error: %s\n", e.what()); \ + fprintf(stderr, "Internal Error: %s\n", e.what()); \ } namespace RC diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index e9ec3bc26..b9f332caa 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -26,10 +26,15 @@ struct ImGuiSettingsHandler; #ifdef LINUX #ifndef HAS_GLFW -namespace ImGui { - static void BeginDisabled(bool disabled = true) {} - static void EndDisabled() {} -} +namespace ImGui +{ + static void BeginDisabled(bool disabled = true) + { + } + static void EndDisabled() + { + } +} // namespace ImGui #endif #endif @@ -308,8 +313,8 @@ namespace RC::GUI } #ifdef WIN32 - #define ATTACH_ICON(icon, str) icon str +#define ATTACH_ICON(icon, str) icon str #else - #define ATTACH_ICON(icon, str) ((icon str) + (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1))) +#define ATTACH_ICON(icon, str) ((icon str) + (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1))) #endif } // namespace RC::GUI diff --git a/UE4SS/include/GUI/LiveView.hpp b/UE4SS/include/GUI/LiveView.hpp index 1a4e28915..7737b3c37 100644 --- a/UE4SS/include/GUI/LiveView.hpp +++ b/UE4SS/include/GUI/LiveView.hpp @@ -89,11 +89,11 @@ namespace RC::GUI UObject* m_currently_opened_tree_node{}; std::string m_current_property_value_buffer{}; int64_t m_current_enum_value_buffer{}; - #if defined(WIN32) || defined(HAS_GLFW) +#if defined(WIN32) || defined(HAS_GLFW) float m_top_size{300.0f}; - #else +#else float m_top_size{14.0f}; - #endif +#endif float m_bottom_size{0.0f}; UFunctionCallerWidget* m_function_caller_widget{}; bool m_is_searching_by_name{}; diff --git a/UE4SS/include/GUI/NerdFont.hpp b/UE4SS/include/GUI/NerdFont.hpp index b44ed3935..5289858cb 100644 --- a/UE4SS/include/GUI/NerdFont.hpp +++ b/UE4SS/include/GUI/NerdFont.hpp @@ -1,4 +1,4 @@ -#pragma once +#pragma once #define ICON_FA_TERMINAL "\uf120" #define ICON_FA_ARCHIVE "\uf187" diff --git a/UE4SS/include/GUI/TUI.hpp b/UE4SS/include/GUI/TUI.hpp index fc39efa7b..abaaebd54 100644 --- a/UE4SS/include/GUI/TUI.hpp +++ b/UE4SS/include/GUI/TUI.hpp @@ -6,34 +6,34 @@ namespace RC::GUI { class Backend_TUI : public OSBackendBase { - public: - auto init() -> void override; - auto imgui_backend_newframe() -> void override; - auto create_window() -> void override; - auto exec_message_loop(bool* exit_requested) -> void override; - auto shutdown() -> void override; - auto cleanup() -> void override; - auto get_window_handle() -> void* override; - auto get_window_size() -> WindowSize override; - auto on_gfx_backend_set() -> void override; + public: + auto init() -> void override; + auto imgui_backend_newframe() -> void override; + auto create_window() -> void override; + auto exec_message_loop(bool* exit_requested) -> void override; + auto shutdown() -> void override; + auto cleanup() -> void override; + auto get_window_handle() -> void* override; + auto get_window_size() -> WindowSize override; + auto on_gfx_backend_set() -> void override; }; class Backend_GfxTUI : public GfxBackendBase { - public: - ~Backend_GfxTUI() = default; + public: + ~Backend_GfxTUI() = default; - public: - auto init() -> void override; - auto imgui_backend_newframe() -> void override; - auto render(const float clear_color_with_alpha[4]) -> void override; - auto shutdown() -> void override; - auto cleanup() -> void override; - auto create_device() -> bool override; - auto cleanup_device() -> void override; - auto handle_window_resize(int64_t param_1, int64_t param_2) -> void override; - auto on_os_backend_set() -> void override; - auto get_window_size() -> WindowSize override; - auto exit_requested() -> bool override; + public: + auto init() -> void override; + auto imgui_backend_newframe() -> void override; + auto render(const float clear_color_with_alpha[4]) -> void override; + auto shutdown() -> void override; + auto cleanup() -> void override; + auto create_device() -> bool override; + auto cleanup_device() -> void override; + auto handle_window_resize(int64_t param_1, int64_t param_2) -> void override; + auto on_os_backend_set() -> void override; + auto get_window_size() -> WindowSize override; + auto exit_requested() -> bool override; }; } // namespace RC::GUI diff --git a/UE4SS/include/Mod/CppMod.hpp b/UE4SS/include/Mod/CppMod.hpp index 5f10e78b9..f7b0014ec 100644 --- a/UE4SS/include/Mod/CppMod.hpp +++ b/UE4SS/include/Mod/CppMod.hpp @@ -33,7 +33,7 @@ namespace RC HMODULE m_main_dll_module = NULL; DLL_DIRECTORY_COOKIE m_dlls_path_cookie = NULL; #else - void * m_dl_handle = nullptr; + void* m_dl_handle = nullptr; #endif start_type m_start_mod_func = nullptr; uninstall_type m_uninstall_mod_func = nullptr; diff --git a/UE4SS/include/Mod/CppUserModBase.hpp b/UE4SS/include/Mod/CppUserModBase.hpp index e512a317a..924c25922 100644 --- a/UE4SS/include/Mod/CppUserModBase.hpp +++ b/UE4SS/include/Mod/CppUserModBase.hpp @@ -31,9 +31,9 @@ namespace RC class CppUserModBase { protected: - #ifdef HAS_GUI +#ifdef HAS_GUI std::vector> GUITabs{}; - #endif +#endif public: UEStringType ModName{}; UEStringType ModVersion{}; diff --git a/UE4SS/include/Platform.hpp b/UE4SS/include/Platform.hpp index 3f3dc91f1..8ec568f2a 100644 --- a/UE4SS/include/Platform.hpp +++ b/UE4SS/include/Platform.hpp @@ -1,5 +1,5 @@ -#pragma once +#pragma once #include std::filesystem::path get_executable_path(); -void add_dlsearch_folder(std::filesystem::path &path); +void add_dlsearch_folder(std::filesystem::path& path); diff --git a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp index 62f00ca6d..584b6afb0 100644 --- a/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp +++ b/UE4SS/include/SDKGenerator/UEHeaderGenerator.hpp @@ -95,12 +95,12 @@ namespace RC::UEGenerator { auto operator()(const SystemStringType& a, const SystemStringType& b) const -> bool { - #ifdef LINUX +#ifdef LINUX // Create a case insensitive string compare for Linux return strcasecmp(a.c_str(), b.c_str()) < 0; - #else +#else return _wcsicmp(a.c_str(), b.c_str()) < 0; - #endif +#endif } }; @@ -147,12 +147,13 @@ namespace RC::UEGenerator bool m_needs_get_type_hash; public: - // workaround for clang tuple bug + // workaround for clang tuple bug // https://github.com/llvm/llvm-project/issues/17042 - struct attachment_data { + struct attachment_data + { SystemStringType property_type; // <0> SystemStringType attach_string; // <1> - bool access_type; // <2> + bool access_type; // <2> attachment_data(const SystemStringType& property_type, const SystemStringType& attach_string, bool access_type) : property_type(property_type), attach_string(attach_string), access_type(access_type) @@ -163,7 +164,6 @@ namespace RC::UEGenerator attachment_data(attachment_data&& other) = default; auto operator=(const attachment_data&) -> attachment_data& = default; auto operator=(attachment_data&&) -> attachment_data& = default; - }; SystemStringType m_implementation_constructor; ::std::unordered_set parent_property_names{}; @@ -331,8 +331,9 @@ namespace RC::UEGenerator auto static determine_primary_game_module_name() -> SystemStringType; public: - auto add_module_and_sub_module_dependencies(::std::set& out_module_dependencies, const SystemStringType& module_name, bool add_self_module = true) - -> void; + auto add_module_and_sub_module_dependencies(::std::set& out_module_dependencies, + const SystemStringType& module_name, + bool add_self_module = true) -> void; auto static collect_blacklisted_property_names(UObject* property) -> CaseInsensitiveSet; auto static generate_object_pre_declaration(UObject* object) -> ::std::vector<::std::vector>; diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index b9610c91e..02ad3d89f 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -65,13 +65,13 @@ namespace RC bool DebugConsoleEnabled{true}; bool DebugConsoleVisible{true}; float DebugGUIFontScaling{1.0}; - #ifdef HAS_GUI - #ifdef WIN32 +#ifdef HAS_GUI +#ifdef WIN32 GUI::GfxBackend GraphicsAPI{GUI::GfxBackend::GLFW3_OpenGL3}; - #else +#else GUI::GfxBackend GraphicsAPI{GUI::GfxBackend::TUI}; - #endif - #endif +#endif +#endif int64_t LiveViewObjectsPerGroup{64 * 1024 / 2}; } Debug; @@ -111,7 +111,7 @@ namespace RC } Experimental; #ifdef LINUX - struct TUIFeatures + struct TUIFeatures { int ButtonLeft = 1; int ButtonRight = 3; diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index 37a0e5a10..9997cb80f 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -124,7 +124,7 @@ namespace RC std::filesystem::path m_module_file_path; std::filesystem::path m_working_directory; std::filesystem::path m_mods_directory; - + SystemStringType m_module_file_path_str; SystemStringType m_working_directory_str; SystemStringType m_game_executable_str; @@ -261,12 +261,12 @@ namespace RC { return ImGui::GetCurrentContext(); } - #ifdef WIN32 +#ifdef WIN32 RC_UE4SS_API static auto get_current_imgui_allocator_functions(ImGuiMemAllocFunc* alloc_func, ImGuiMemFreeFunc* free_func, void** user_data) -> void { return ImGui::GetAllocatorFunctions(alloc_func, free_func, user_data); } - #endif +#endif #endif RC_UE4SS_API auto queue_event(EventCallable callable, void* data) -> void; RC_UE4SS_API auto is_queue_empty() -> bool; @@ -315,14 +315,14 @@ namespace RC template static auto find_mod_by_name(SystemStringViewType mod_name, IsInstalled is_installed = IsInstalled::No, IsStarted is_started = IsStarted::No) -> T* { - return find_mod_by_name(to_system_string(mod_name), is_installed, is_started); + return find_mod_by_name(to_system_string(mod_name), is_installed, is_started); }; template RC_UE4SS_API static auto find_lua_mod_by_name(S mod_name, IsInstalled is_installed = IsInstalled::No, IsStarted is_started = IsStarted::No) -> LuaMod* { - auto mod_name_str = to_system_string(mod_name); - return static_cast(find_mod_by_name(mod_name_str, is_installed, is_started)); + auto mod_name_str = to_system_string(mod_name); + return static_cast(find_mod_by_name(mod_name_str, is_installed, is_started)); } static auto static_cleanup() -> void; RC_UE4SS_API static auto get_program() -> UE4SSProgram& diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 349affc86..260c40cea 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -23,42 +23,49 @@ void UE4SS_Start() { // find libUE4SS.so path using dlfcn Dl_info dl_info; - if (dladdr((void *)UE4SS_Start, &dl_info) == 0) + if (dladdr((void*)UE4SS_Start, &dl_info) == 0) { std::cerr << "Failed to find libUE4SS.so path" << std::endl; return; } - //#define EARLY_THROW_TEST - #ifdef EARLY_THROW_TEST - try { +// #define EARLY_THROW_TEST +#ifdef EARLY_THROW_TEST + try + { throw std::runtime_error{"Hello from Here!"}; - } catch (std::exception& e) { + } + catch (std::exception& e) + { fprintf(stderr, "%s\n", e.what()); } - #endif +#endif auto ue4sspath = to_system_string(dl_info.dli_fname); auto program = new UE4SSProgram(ue4sspath, {}); - + // use pthread here - pthread_create(&ue4ss_mainthread, nullptr, [](void *arg) -> void * { - auto program = (UE4SSProgram *)arg; - program->init(); - fprintf(stderr, "inited in thread\n"); - if (auto e = program->get_error_object(); e->has_error()) - { - // If the output system errored out then use printf_s as a fallback - // Logging will only happen to the debug console but it's something at least - if (!Output::has_internal_error()) - { - Output::send(SYSSTR("Fatal Error: {}\n"), e->get_message()); - } - else - { - printf("Error: %s\n", e->get_message()); - } - } - return nullptr; - }, program); + pthread_create( + &ue4ss_mainthread, + nullptr, + [](void* arg) -> void* { + auto program = (UE4SSProgram*)arg; + program->init(); + fprintf(stderr, "inited in thread\n"); + if (auto e = program->get_error_object(); e->has_error()) + { + // If the output system errored out then use printf_s as a fallback + // Logging will only happen to the debug console but it's something at least + if (!Output::has_internal_error()) + { + Output::send(SYSSTR("Fatal Error: {}\n"), e->get_message()); + } + else + { + printf("Error: %s\n", e->get_message()); + } + } + return nullptr; + }, + program); } static bool UE4SSInited = false; @@ -75,196 +82,224 @@ void __attribute__((constructor)) UE4SS_Init() { } */ -static int (*next_main)(int, char **, char **); +static int (*next_main)(int, char**, char**); static bool inited = false; -int hooked_main(int argc, char **argv, char **envp) { +int hooked_main(int argc, char** argv, char** envp) +{ // delay the hook to make sure all objects are constructed fprintf(stderr, "Running hooked main before actual main my pid = %d\n", getpid()); - if (!inited) { + if (!inited) + { fprintf(stderr, "Do another hook?\n"); UE4SS_Start(); inited = true; - } else { + } + else + { fprintf(stderr, "UE4SS already inited? \n"); } return next_main(argc, argv, envp); } -#define ALIGN_UP_PAGE(x) (( ((unsigned long)(x)) + 0xFFF) & ~0xFFF) +#define ALIGN_UP_PAGE(x) ((((unsigned long)(x)) + 0xFFF) & ~0xFFF) #define ALIGN_DOWN_PAGE(x) (((unsigned long)(x)) & ~0xFFF) -extern char **environ; +extern char** environ; -extern "C" { +extern "C" +{ -struct link_map_private { - Elf64_Addr l_addr; - char *l_name; - Elf64_Dyn *l_ld; - struct link_map_private *l_next, *l_prev; - struct link_map_private *l_real; - Lmid_t l_ns; - struct libname_list *l_libname; - Elf64_Dyn *l_info[DT_NUM + 0 + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM]; -}; + struct link_map_private + { + Elf64_Addr l_addr; + char* l_name; + Elf64_Dyn* l_ld; + struct link_map_private *l_next, *l_prev; + struct link_map_private* l_real; + Lmid_t l_ns; + struct libname_list* l_libname; + Elf64_Dyn* l_info[DT_NUM + 0 + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM]; + }; -int __libc_start_main( - int (*main)(int, char **, char **), - int argc, - char **argv, - int (*init)(int, char **, char **), - void (*fini)(void), - void (*rtld_fini)(void), - void *stack_end) -{ - next_main = main; - typeof(&__libc_start_main) orig = (typeof(&__libc_start_main))dlsym(RTLD_NEXT, "__libc_start_main"); - // gxx fix - Dl_info dl_info; - Elf64_Sym *sym; - // libsteam_api is okay, the UE engine is causing problem - void *current___cxa_throw = dlsym(RTLD_DEFAULT, "__cxa_throw"); - dladdr1(current___cxa_throw, &dl_info, (void**) &sym, RTLD_DL_SYMENT); - fprintf(stderr, "__cxa_throw found in %s @ %p\n", dl_info.dli_fname, current___cxa_throw); - if ((unsigned long)current___cxa_throw < 0x7fffffff) { - fprintf(stderr, "maybe UE, patched\n"); - mprotect((void*)ALIGN_DOWN_PAGE(sym), ALIGN_UP_PAGE(sym + 1) - ALIGN_DOWN_PAGE(sym), PROT_READ | PROT_WRITE); - sym->st_info = ELF64_ST_INFO(STB_LOCAL, ELF64_ST_TYPE(sym->st_info)); - sym->st_other = STV_INTERNAL; - // assume this is UE5's address range and remove this symbol - void *working___cxa_throw = dlsym(RTLD_DEFAULT, "__cxa_throw"); - struct link_map_private* map1; - dladdr1(working___cxa_throw, &dl_info, (void**) &map1, RTLD_DL_SYMENT); - fprintf(stderr, "now we're using __cxa_throw from %s @ %p\n", dl_info.dli_fname, working___cxa_throw); + int __libc_start_main( + int (*main)(int, char**, char**), int argc, char** argv, int (*init)(int, char**, char**), void (*fini)(void), void (*rtld_fini)(void), void* stack_end) + { + next_main = main; + typeof(&__libc_start_main) orig = (typeof(&__libc_start_main))dlsym(RTLD_NEXT, "__libc_start_main"); + // gxx fix + Dl_info dl_info; + Elf64_Sym* sym; + // libsteam_api is okay, the UE engine is causing problem + void* current___cxa_throw = dlsym(RTLD_DEFAULT, "__cxa_throw"); + dladdr1(current___cxa_throw, &dl_info, (void**)&sym, RTLD_DL_SYMENT); + fprintf(stderr, "__cxa_throw found in %s @ %p\n", dl_info.dli_fname, current___cxa_throw); + if ((unsigned long)current___cxa_throw < 0x7fffffff) + { + fprintf(stderr, "maybe UE, patched\n"); + mprotect((void*)ALIGN_DOWN_PAGE(sym), ALIGN_UP_PAGE(sym + 1) - ALIGN_DOWN_PAGE(sym), PROT_READ | PROT_WRITE); + sym->st_info = ELF64_ST_INFO(STB_LOCAL, ELF64_ST_TYPE(sym->st_info)); + sym->st_other = STV_INTERNAL; + // assume this is UE5's address range and remove this symbol + void* working___cxa_throw = dlsym(RTLD_DEFAULT, "__cxa_throw"); + struct link_map_private* map1; + dladdr1(working___cxa_throw, &dl_info, (void**)&map1, RTLD_DL_SYMENT); + fprintf(stderr, "now we're using __cxa_throw from %s @ %p\n", dl_info.dli_fname, working___cxa_throw); - struct data_encap { - void *working___cxa_throw; - void *current___cxa_throw; - } data = {working___cxa_throw, current___cxa_throw}; - dl_iterate_phdr([](struct dl_phdr_info *info, size_t size, void *data) -> int { - auto working___cxa_throw = ((struct data_encap*)data)->working___cxa_throw; - auto current___cxa_throw = ((struct data_encap*)data)->current___cxa_throw; - fprintf(stderr, "Examing %s @ %p... \n", info->dlpi_name, info->dlpi_addr); - // skip vdso - if (strstr(info->dlpi_name, "vdso") != nullptr) { - fprintf(stderr, " Skipping %s\n", info->dlpi_name); - return 0; - } - // get dynamic - Elf64_Dyn *dyn = nullptr; - for (int i = 0; i < info->dlpi_phnum; i++) { - if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) { - dyn = (Elf64_Dyn *)(info->dlpi_phdr[i].p_vaddr + info->dlpi_addr); - } - } + struct data_encap + { + void* working___cxa_throw; + void* current___cxa_throw; + } data = {working___cxa_throw, current___cxa_throw}; + dl_iterate_phdr( + [](struct dl_phdr_info* info, size_t size, void* data) -> int { + auto working___cxa_throw = ((struct data_encap*)data)->working___cxa_throw; + auto current___cxa_throw = ((struct data_encap*)data)->current___cxa_throw; + fprintf(stderr, "Examing %s @ %p... \n", info->dlpi_name, info->dlpi_addr); + // skip vdso + if (strstr(info->dlpi_name, "vdso") != nullptr) + { + fprintf(stderr, " Skipping %s\n", info->dlpi_name); + return 0; + } + // get dynamic + Elf64_Dyn* dyn = nullptr; + for (int i = 0; i < info->dlpi_phnum; i++) + { + if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) + { + dyn = (Elf64_Dyn*)(info->dlpi_phdr[i].p_vaddr + info->dlpi_addr); + } + } - // iterate dynamic, find relocation to __cxa_throw - struct RELA_INFOS { - Elf64_Rela *rela; - ssize_t sz; - } rela_infos[2] = {}; - // symbol table - Elf64_Sym *sym = nullptr; - // string table - char *strtab = nullptr; - for (int i = 0; dyn[i].d_tag != DT_NULL; i++) { - // DT_JMPREL - if (dyn[i].d_tag == DT_JMPREL) { - rela_infos[0].rela = (Elf64_Rela *)(dyn[i].d_un.d_ptr); - } - if (dyn[i].d_tag == DT_RELA) { - rela_infos[1].rela = (Elf64_Rela *)(dyn[i].d_un.d_ptr); - } - // DT_SYMTAB - if (dyn[i].d_tag == DT_SYMTAB) { - sym = (Elf64_Sym *)(dyn[i].d_un.d_ptr); - } - // DT_STRTAB - if (dyn[i].d_tag == DT_STRTAB) { - strtab = (char *)(dyn[i].d_un.d_ptr); - } - // DT_PLTRELSZ - if (dyn[i].d_tag == DT_PLTRELSZ) { - rela_infos[0].sz = dyn[i].d_un.d_val; - } - // DT_RELASZ - if (dyn[i].d_tag == DT_RELASZ) { - rela_infos[1].sz = dyn[i].d_un.d_val; - } - } - if (sym == nullptr || strtab == nullptr) { - fprintf(stderr, " No sym or strtab found %p %p\n", sym, strtab); - return 0; - } - if ((rela_infos[0].rela == nullptr) && (rela_infos[1].rela == nullptr)) { - fprintf(stderr, " No rela found %p %p\n", rela_infos[0].rela, rela_infos[1].rela); - return 0; - } - auto process_rela = [&] (Elf64_Rela *rela, ssize_t sz, Elf64_Sym *sym, char *strtab) { - fprintf(stderr, " Found rela @ %p, sym @ %p, strtab @ %p\n", rela, sym, strtab); - for (int i = 0; i < sz / sizeof(Elf64_Rela); i++) { - if (sym[ELF64_R_SYM(rela[i].r_info)].st_name != 0) { - char *name = strtab + sym[ELF64_R_SYM(rela[i].r_info)].st_name; - if (strncmp(name, "__cxa_throw", 11) == 0) { - fprintf(stderr, " Found __cxa_throw symbol @ %p\n", rela[i].r_offset); - } else { - continue; + // iterate dynamic, find relocation to __cxa_throw + struct RELA_INFOS + { + Elf64_Rela* rela; + ssize_t sz; + } rela_infos[2] = {}; + // symbol table + Elf64_Sym* sym = nullptr; + // string table + char* strtab = nullptr; + for (int i = 0; dyn[i].d_tag != DT_NULL; i++) + { + // DT_JMPREL + if (dyn[i].d_tag == DT_JMPREL) + { + rela_infos[0].rela = (Elf64_Rela*)(dyn[i].d_un.d_ptr); + } + if (dyn[i].d_tag == DT_RELA) + { + rela_infos[1].rela = (Elf64_Rela*)(dyn[i].d_un.d_ptr); + } + // DT_SYMTAB + if (dyn[i].d_tag == DT_SYMTAB) + { + sym = (Elf64_Sym*)(dyn[i].d_un.d_ptr); + } + // DT_STRTAB + if (dyn[i].d_tag == DT_STRTAB) + { + strtab = (char*)(dyn[i].d_un.d_ptr); + } + // DT_PLTRELSZ + if (dyn[i].d_tag == DT_PLTRELSZ) + { + rela_infos[0].sz = dyn[i].d_un.d_val; + } + // DT_RELASZ + if (dyn[i].d_tag == DT_RELASZ) + { + rela_infos[1].sz = dyn[i].d_un.d_val; + } } - // got table address - unsigned long* address = (unsigned long *)(rela[i].r_offset + info->dlpi_addr); - if (*address == (unsigned long)current___cxa_throw) { - fprintf(stderr, " Found __cxa_throw in .plt.got @ %p, offset = %d\n", address, rela[i].r_offset); - mprotect((void*)ALIGN_DOWN_PAGE(address), ALIGN_UP_PAGE(address + 1) - ALIGN_DOWN_PAGE(address), PROT_READ | PROT_WRITE); - *address = (unsigned long)working___cxa_throw; - fprintf(stderr, " Patched __cxa_throw to @ %p\n", working___cxa_throw); + if (sym == nullptr || strtab == nullptr) + { + fprintf(stderr, " No sym or strtab found %p %p\n", sym, strtab); + return 0; } - } - } - }; - for (int i = 0; i < 2; i++) { - if (rela_infos[i].rela != nullptr) { - process_rela(rela_infos[i].rela, rela_infos[i].sz, sym, strtab); - } - } - return 0; - }, &data); - - } - - // remove LD_PRELOAD from environ - int nenv = 0; - for (int i = 0; environ[i]; i++) - nenv ++; - for (int i = 0; i < nenv; i++) { - if (strncmp(environ[i], "LD_PRELOAD=", 11) == 0) { - fprintf(stderr, "Found LD_PRELOAD @%d %s\n", i, environ[i]); - environ[i] = environ[nenv - 1]; - nenv --; + if ((rela_infos[0].rela == nullptr) && (rela_infos[1].rela == nullptr)) + { + fprintf(stderr, " No rela found %p %p\n", rela_infos[0].rela, rela_infos[1].rela); + return 0; + } + auto process_rela = [&](Elf64_Rela* rela, ssize_t sz, Elf64_Sym* sym, char* strtab) { + fprintf(stderr, " Found rela @ %p, sym @ %p, strtab @ %p\n", rela, sym, strtab); + for (int i = 0; i < sz / sizeof(Elf64_Rela); i++) + { + if (sym[ELF64_R_SYM(rela[i].r_info)].st_name != 0) + { + char* name = strtab + sym[ELF64_R_SYM(rela[i].r_info)].st_name; + if (strncmp(name, "__cxa_throw", 11) == 0) + { + fprintf(stderr, " Found __cxa_throw symbol @ %p\n", rela[i].r_offset); + } + else + { + continue; + } + // got table address + unsigned long* address = (unsigned long*)(rela[i].r_offset + info->dlpi_addr); + if (*address == (unsigned long)current___cxa_throw) + { + fprintf(stderr, " Found __cxa_throw in .plt.got @ %p, offset = %d\n", address, rela[i].r_offset); + mprotect((void*)ALIGN_DOWN_PAGE(address), ALIGN_UP_PAGE(address + 1) - ALIGN_DOWN_PAGE(address), PROT_READ | PROT_WRITE); + *address = (unsigned long)working___cxa_throw; + fprintf(stderr, " Patched __cxa_throw to @ %p\n", working___cxa_throw); + } + } + } + }; + for (int i = 0; i < 2; i++) + { + if (rela_infos[i].rela != nullptr) + { + process_rela(rela_infos[i].rela, rela_infos[i].sz, sym, strtab); + } + } + return 0; + }, + &data); } - } - environ[nenv] = NULL; - return orig(hooked_main, argc, argv, init, fini, rtld_fini, stack_end); -} + // remove LD_PRELOAD from environ + int nenv = 0; + for (int i = 0; environ[i]; i++) + nenv++; + for (int i = 0; i < nenv; i++) + { + if (strncmp(environ[i], "LD_PRELOAD=", 11) == 0) + { + fprintf(stderr, "Found LD_PRELOAD @%d %s\n", i, environ[i]); + environ[i] = environ[nenv - 1]; + nenv--; + } + } + environ[nenv] = NULL; + return orig(hooked_main, argc, argv, init, fini, rtld_fini, stack_end); + } } // destructor void __attribute__((destructor)) UE4SS_End() { - if (UE4SSInited) { + if (UE4SSInited) + { // UE4SSProgram::static_cleanup(); UE4SSInited = false; } } -std::filesystem::path get_executable_path() { +std::filesystem::path get_executable_path() +{ // get executable path on Linux char result[1024]; ssize_t count = readlink("/proc/self/exe", result, 1023); return std::filesystem::path(std::string(result, (count > 0) ? count : 0)); } -void add_dlsearch_folder(std::filesystem::path &path) { +void add_dlsearch_folder(std::filesystem::path& path) +{ // not implemented } diff --git a/UE4SS/src/EntryWin32.cpp b/UE4SS/src/EntryWin32.cpp index 31deff417..ab98cd195 100644 --- a/UE4SS/src/EntryWin32.cpp +++ b/UE4SS/src/EntryWin32.cpp @@ -135,14 +135,15 @@ auto WIN_API_FUNCTION_NAME(HMODULE hModule, DWORD ul_reason_for_call, [[maybe_un return TRUE; } -std::filesystem::path get_executable_path() { +std::filesystem::path get_executable_path() +{ wchar_t exe_path_buffer[1024]; GetModuleFileNameW(GetModuleHandle(nullptr), exe_path_buffer, 1023); return std::filesystem::path(exe_path_buffer); } - -void add_dlsearch_folder(std::filesystem::path &path) { +void add_dlsearch_folder(std::filesystem::path& path) +{ SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); // Make sure game directory DLLs are also included AddDllDirectory(path.c_str()); diff --git a/UE4SS/src/GUI/Dumpers.cpp b/UE4SS/src/GUI/Dumpers.cpp index 0eeeddfc8..655cd4426 100644 --- a/UE4SS/src/GUI/Dumpers.cpp +++ b/UE4SS/src/GUI/Dumpers.cpp @@ -169,8 +169,9 @@ namespace RC::GUI::Dumpers const auto material_type_space_location = material_full_name.find(STR(" ")); if (material_type_space_location == material_full_name.npos) { - Output::send(SYSSTR("SKIPPING MATERIAL! Was unable to find space in full material name in component: '{}'.\n"), - material_full_name); + Output::send( + SYSSTR("SKIPPING MATERIAL! Was unable to find space in full material name in component: '{}'.\n"), + material_full_name); return; } @@ -179,9 +180,9 @@ namespace RC::GUI::Dumpers throw std::runtime_error{"integer overflow when converting material_type_space_location signed\n"}; } auto material_typeless_name = UEStringViewType{material_full_name.begin() + static_cast(material_type_space_location) + 1, - material_full_name.end()}; + material_full_name.end()}; - actor_buffer.append(std::format(SYSSTR("{}'"),to_system(material_interface->GetClassPrivate()->GetName()))); + actor_buffer.append(std::format(SYSSTR("{}'"), to_system(material_interface->GetClassPrivate()->GetName()))); actor_buffer.append(std::format(SYSSTR("\"\"{}"), to_system(material_typeless_name))); actor_buffer.append(SYSSTR("\"\"'")); } @@ -315,12 +316,9 @@ namespace RC::GUI::Dumpers static auto dump_actor_class = UObjectGlobals::StaticFindObject(nullptr, nullptr, STR("/Script/Engine.StaticMeshActor")); SystemStringType file_buffer{}; file_buffer.append(generate_actors_csv_file(dump_actor_class)); - auto path = std::filesystem::path {UE4SSProgram::get_program().get_working_directory()} / std::format(SYSSTR("{}-ue4ss_static_mesh_data.csv"), long(std::time(nullptr))); - auto file = - File::open(path, - File::OpenFor::Writing, - File::OverwriteExistingFile::Yes, - File::CreateIfNonExistent::Yes); + auto path = std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / + std::format(SYSSTR("{}-ue4ss_static_mesh_data.csv"), long(std::time(nullptr))); + auto file = File::open(path, File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); file.write_file_string_to_file(to_file(file_buffer)); Output::send(SYSSTR("Finished dumping CSV of all loaded static mesh actors, positions and mesh properties\n")); } @@ -329,12 +327,10 @@ namespace RC::GUI::Dumpers { Output::send(SYSSTR("Dumping CSV of all loaded actor types, positions and mesh properties\n")); SystemStringType file_buffer{}; - auto path = std::filesystem::path {UE4SSProgram::get_program().get_working_directory()} / std::format(SYSSTR("{}-ue4ss_actor_data.csv"), long(std::time(nullptr))); + auto path = std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / + std::format(SYSSTR("{}-ue4ss_actor_data.csv"), long(std::time(nullptr))); file_buffer.append(generate_actors_csv_file(AActor::StaticClass())); - auto file = File::open(path, - File::OpenFor::Writing, - File::OverwriteExistingFile::Yes, - File::CreateIfNonExistent::Yes); + auto file = File::open(path, File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); file.write_file_string_to_file(to_file(file_buffer)); Output::send(SYSSTR("Finished dumping CSV of all loaded actor types, positions and mesh properties\n")); } @@ -345,13 +341,13 @@ namespace RC::GUI::Dumpers { return; } - - // this give the button a little bit of space between the top of the window - // and the buttons themselves - #ifdef LINUX + +// this give the button a little bit of space between the top of the window +// and the buttons themselves +#ifdef LINUX ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, {0.0f, 1.0f}); ImGui::Spacing(); - #endif +#endif if (ImGui::Button("Dump all static actor meshes to file")) { @@ -417,9 +413,8 @@ namespace RC::GUI::Dumpers UE4SSProgram::get_program().generate_lua_types(working_dir / SYSSTR("Mods") / SYSSTR("shared") SYSSTR("types")); } - - #ifdef LINUX +#ifdef LINUX ImGui::PopStyleVar(); - #endif +#endif } } // namespace RC::GUI::Dumpers diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 8ce90cc46..9cd68ef48 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -107,9 +107,8 @@ namespace RC::GUI UE4SSProgram::get_program().queue_event( [](void* data) { UE4SSProgram::dump_all_objects_and_properties( - to_system( std::filesystem::path { UE4SSProgram::get_program().get_object_dumper_output_directory() } - / UE4SSProgram::m_object_dumper_file_name) - ); + to_system(std::filesystem::path{UE4SSProgram::get_program().get_object_dumper_output_directory()} / + UE4SSProgram::m_object_dumper_file_name)); static_cast(data)->m_event_thread_busy = false; }, this); @@ -225,11 +224,11 @@ namespace RC::GUI ImGuiStyle& style = ImGui::GetStyle(); style.WindowPadding = ImVec2(8, 8); - #if defined(WIN32) || defined(HAS_GLFW) +#if defined(WIN32) || defined(HAS_GLFW) style.FramePadding = ImVec2(12, 5); - #else +#else style.FramePadding = ImVec2(0.5f, 0.5f); - #endif +#endif style.CellPadding = ImVec2(3, 3); style.ItemSpacing = ImVec2(8, 4); style.ItemInnerSpacing = ImVec2(4, 4); @@ -283,13 +282,13 @@ namespace RC::GUI style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.55f, 0.22f, 0.45f, 1.00f); style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); style.Colors[ImGuiCol_Button] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); - #if defined(WIN32) || defined(HAS_GLFW) +#if defined(WIN32) || defined(HAS_GLFW) style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); - #else +#else style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.4f, 0.5f, 0.8f, 1.00f); style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.65f, 0.4f, 0.50f, 1.00f); - #endif +#endif style.Colors[ImGuiCol_Header] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f); style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f); @@ -300,13 +299,13 @@ namespace RC::GUI style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.92f, 0.24f, 0.84f, 0.67f); style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.92f, 0.24f, 0.84f, 0.95f); style.Colors[ImGuiCol_Tab] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); - #if defined(WIN32) || defined(HAS_GLFW) +#if defined(WIN32) || defined(HAS_GLFW) style.Colors[ImGuiCol_TabHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_TabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); - #else +#else style.Colors[ImGuiCol_TabHovered] = ImVec4(0.4f, 0.5f, 0.8f, 1.00f); style.Colors[ImGuiCol_TabActive] = ImVec4(0.65f, 0.4f, 0.50f, 1.00f); - #endif +#endif style.Colors[ImGuiCol_TabUnfocused] = ImVec4(0.07f, 0.10f, 0.15f, 0.97f); style.Colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.14f, 0.26f, 0.42f, 1.00f); style.Colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); @@ -370,13 +369,13 @@ namespace RC::GUI fflush(stderr); } - // You're not allowed to throw exceptions directly inside a frame! - // Use GUI::TRY to move exceptions to the end of the frame. - #ifdef WIN32 +// You're not allowed to throw exceptions directly inside a frame! +// Use GUI::TRY to move exceptions to the end of the frame. +#ifdef WIN32 __debugbreak(); - #else +#else asm("int3"); - #endif +#endif } ImGui::Render(); @@ -546,23 +545,23 @@ namespace RC::GUI { switch (backend) { - #ifdef WIN32 +#ifdef WIN32 case GfxBackend::DX11: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); break; - #else - #ifdef HAS_GLFW +#else +#ifdef HAS_GLFW case GfxBackend::GLFW3_OpenGL3: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); break; - #else +#else case GfxBackend::TUI: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); - #endif - #endif +#endif +#endif } m_gfx_backend->set_os_backend(m_os_backend.get()); diff --git a/UE4SS/src/GUI/ImGuiUtility.cpp b/UE4SS/src/GUI/ImGuiUtility.cpp index 78c9b8ebf..ec08cdac0 100644 --- a/UE4SS/src/GUI/ImGuiUtility.cpp +++ b/UE4SS/src/GUI/ImGuiUtility.cpp @@ -14,13 +14,13 @@ namespace RC::GUI // NOTE: This function makes use of 'imgui_internal.h'. // As a result, this function is prone to break if you update Imgui. ImGuiContext& g = *GImGui; - #ifdef WIN32 +#ifdef WIN32 const char* child_window_name = NULL; ImFormatStringToTempBuffer(&child_window_name, NULL, "%s/%s_%08X", g.CurrentWindow->Name, label, ImGui::GetID(label)); - #else +#else static char child_window_name[1024]; sprintf(child_window_name, "%s/%s_%08X", g.CurrentWindow->Name, label, ImGui::GetID(label)); - #endif +#endif ImGuiWindow* child_window = ImGui::FindWindowByName(child_window_name); if (child_window) { diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 833f3982c..7c0d15af4 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -721,8 +721,8 @@ namespace RC::GUI LiveView::Watch::Watch(UEStringType&& object_name, UEStringType&& property_name) : object_name(object_name), property_name(property_name) { auto& file_device = output.get_device(); - file_device.set_file_name_and_path(to_system_string(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} - / "watches" / std::format("ue4ss_watch_{}_{}.txt", to_string(object_name), to_string(property_name)))); + file_device.set_file_name_and_path(to_system_string(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / "watches" / + std::format("ue4ss_watch_{}_{}.txt", to_string(object_name), to_string(property_name)))); file_device.set_formatter([](SystemStringViewType string) -> SystemStringType { const auto when_as_string = std::format(SYSSTR("{:%Y-%m-%d %H:%M:%S}"), std::chrono::system_clock::now()); return std::format(SYSSTR("[{}] {}"), when_as_string, string); @@ -1995,7 +1995,8 @@ namespace RC::GUI { parent_name = obj ? obj->GetName() : STR("None"); } - auto edit_property_value_modal_name = to_string(std::format(SYSSTR("Edit value of property: {}->{}"), to_system(parent_name), to_system(property->GetName()))); + auto edit_property_value_modal_name = + to_string(std::format(SYSSTR("Edit value of property: {}->{}"), to_system(parent_name), to_system(property->GetName()))); if (open_edit_value_popup) { @@ -2620,7 +2621,7 @@ namespace RC::GUI bool tried_to_open_nullptr_property{}; auto property_full_name = property->GetFullName(); - ImGui::Text("Selected: " SystemStringPrint , to_system(property->GetName()).c_str()); + ImGui::Text("Selected: " SystemStringPrint, to_system(property->GetName()).c_str()); ImGui::Text("Address: %016llX", std::bit_cast(property)); if (ImGui::BeginPopupContextItem(to_string(property_full_name).c_str())) { @@ -2854,7 +2855,7 @@ namespace RC::GUI { ImGui::BeginDisabled(); } - if (ImGui::Button(ATTACH_ICON(ICON_FA_SEARCH," Find functions"))) + if (ImGui::Button(ATTACH_ICON(ICON_FA_SEARCH, " Find functions"))) { m_function_caller_widget->open_widget_deferred(); } @@ -2952,7 +2953,7 @@ namespace RC::GUI auto num_params = function->GetNumParms(); const auto when_as_string = std::format(SYSSTR("{:%H:%M:%S}"), std::chrono::system_clock::now()); - auto buffer { std::format(SYSSTR("Received call @ {}.\n"), when_as_string)}; + auto buffer{std::format(SYSSTR("Received call @ {}.\n"), when_as_string)}; buffer.append(std::format(SYSSTR(" Context:\n {}\n"), to_system(context.Context->GetFullName()))); @@ -3584,10 +3585,11 @@ namespace RC::GUI } static int num_columns = 3; - #if defined(WIN32) || defined(HAS_GLFW) +#if defined(WIN32) || defined(HAS_GLFW) ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, {2.0f, 2.0f}); - #endif - if (ImGui::BeginTable("watch_table", num_columns, ImGuiTableFlags_Borders)) +#endif + // TODO: do we need ImGuiTableFlags_NoPadOuterX? + if (ImGui::BeginTable("watch_table", num_columns, ImGuiTableFlags_Borders | ImGuiTableFlags_NoPadOuterX)) { // TODO: do we need controls_width = (XDIV == 1) ? (60.0f) : (60.0f / XDIV + 5.0f);? ImGui::TableSetupColumn("Controls", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFrameHeight() * 3.0f + 4.0f); @@ -3670,9 +3672,9 @@ namespace RC::GUI } ImGui::EndTable(); - #if defined(WIN32) || defined(HAS_GLFW) +#if defined(WIN32) || defined(HAS_GLFW) ImGui::PopStyleVar(); - #endif +#endif } ImGui::EndChild(); } diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/TUI.cpp index e7a4f229a..71d7cfb66 100644 --- a/UE4SS/src/GUI/TUI.cpp +++ b/UE4SS/src/GUI/TUI.cpp @@ -12,12 +12,13 @@ namespace RC::GUI { - static ImTui::TScreen * g_screen = nullptr; + static ImTui::TScreen* g_screen = nullptr; static bool tui_shutdown = false; static std::shared_ptr ncurses_source{}; int saved_stderr = -1; - void Backend_TUI::init() { - //fprintf(stderr, "Backend_TUI::init\n"); + void Backend_TUI::init() + { + // fprintf(stderr, "Backend_TUI::init\n"); g_screen = ImTui_ImplNcurses_Init(true); auto source = Input::Handler::get_input_source("Ncurses"); ncurses_source = std::dynamic_pointer_cast(source); @@ -36,31 +37,38 @@ namespace RC::GUI }); } - void Backend_TUI::imgui_backend_newframe() { - //fprintf(stderr, "Backend_TUI::imgui_backend_newframe\n"); - if (ncurses_source) { + void Backend_TUI::imgui_backend_newframe() + { + // fprintf(stderr, "Backend_TUI::imgui_backend_newframe\n"); + if (ncurses_source) + { ncurses_source->begin_frame(); } - ImTui_ImplNcurses_NewFrame([] (int x) { - if (ncurses_source) { + ImTui_ImplNcurses_NewFrame([](int x) { + if (ncurses_source) + { ncurses_source->receive_input(x); } }); - if (ncurses_source) { + if (ncurses_source) + { ncurses_source->end_frame(); } } - void Backend_TUI::create_window() { + void Backend_TUI::create_window() + { // Do nothing } - void Backend_TUI::exec_message_loop(bool* exit_requested) { + void Backend_TUI::exec_message_loop(bool* exit_requested) + { ImTui_ImplNcurses_ProcessEvent(); *exit_requested = false; } - void Backend_TUI::shutdown() { + void Backend_TUI::shutdown() + { ImTui_ImplNcurses_Shutdown(); g_screen = nullptr; tui_shutdown = true; @@ -70,73 +78,92 @@ namespace RC::GUI fprintf(stderr, "Backend_TUI::shutdown, stderr restored\n"); } - void Backend_TUI::cleanup() { + void Backend_TUI::cleanup() + { // Do nothing } - void* Backend_TUI::get_window_handle() { + void* Backend_TUI::get_window_handle() + { return g_screen; } - WindowSize Backend_TUI::get_window_size() { - if (g_screen) { + WindowSize Backend_TUI::get_window_size() + { + if (g_screen) + { return {g_screen->nx, g_screen->ny}; - } else { + } + else + { return {0, 0}; } } - void Backend_TUI::on_gfx_backend_set() { + void Backend_TUI::on_gfx_backend_set() + { // Do nothing } - void Backend_GfxTUI::init() { + void Backend_GfxTUI::init() + { ImTui_ImplText_Init(); } - void Backend_GfxTUI::imgui_backend_newframe() { + void Backend_GfxTUI::imgui_backend_newframe() + { ImTui_ImplText_NewFrame(); } - void Backend_GfxTUI::render(const float clear_color_with_alpha[4]) { - if (tui_shutdown) { + void Backend_GfxTUI::render(const float clear_color_with_alpha[4]) + { + if (tui_shutdown) + { return; } ImTui_ImplText_RenderDrawData(ImGui::GetDrawData(), g_screen); ImTui_ImplNcurses_DrawScreen(); } - void Backend_GfxTUI::shutdown() { + void Backend_GfxTUI::shutdown() + { ImTui_ImplText_Shutdown(); setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IONBF, 0); } - void Backend_GfxTUI::cleanup() { + void Backend_GfxTUI::cleanup() + { // Do nothing } - bool Backend_GfxTUI::create_device() { + bool Backend_GfxTUI::create_device() + { return true; } - void Backend_GfxTUI::cleanup_device() { + void Backend_GfxTUI::cleanup_device() + { // Do nothing } - void Backend_GfxTUI::handle_window_resize(int64_t param_1, int64_t param_2) { + void Backend_GfxTUI::handle_window_resize(int64_t param_1, int64_t param_2) + { // Do nothing } - void Backend_GfxTUI::on_os_backend_set() { + void Backend_GfxTUI::on_os_backend_set() + { // Do nothing } - WindowSize Backend_GfxTUI::get_window_size() { + WindowSize Backend_GfxTUI::get_window_size() + { return {g_screen->nx, g_screen->ny}; } - bool Backend_GfxTUI::exit_requested() { + bool Backend_GfxTUI::exit_requested() + { return tui_shutdown; } }; // namespace RC::GUI diff --git a/UE4SS/src/GUI/UFunctionCallerWidget.cpp b/UE4SS/src/GUI/UFunctionCallerWidget.cpp index 3ce3e5930..5e8351b6f 100644 --- a/UE4SS/src/GUI/UFunctionCallerWidget.cpp +++ b/UE4SS/src/GUI/UFunctionCallerWidget.cpp @@ -227,19 +227,27 @@ namespace RC::GUI { if (auto as_struct_property = CastField(param.unreal_param); as_struct_property) { - ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_struct_property->GetStruct()->GetName()).c_str()); + ImGui::Text(SystemStringPrint " (" SystemStringPrint ")", + to_system(param.unreal_param->GetClass().GetName()).c_str(), + to_system(as_struct_property->GetStruct()->GetName()).c_str()); } else if (auto as_array_property = CastField(param.unreal_param); as_array_property) { - ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_array_property->GetInner()->GetName()).c_str()); + ImGui::Text(SystemStringPrint " (" SystemStringPrint ")", + to_system(param.unreal_param->GetClass().GetName()).c_str(), + to_system(as_array_property->GetInner()->GetName()).c_str()); } else if (auto as_object_property = CastField(param.unreal_param); as_object_property) { - ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_object_property->GetPropertyClass()->GetName()).c_str()); + ImGui::Text(SystemStringPrint " (" SystemStringPrint ")", + to_system(param.unreal_param->GetClass().GetName()).c_str(), + to_system(as_object_property->GetPropertyClass()->GetName()).c_str()); } else if (auto as_class_property = CastField(param.unreal_param); as_class_property) { - ImGui::Text(SystemStringPrint" (" SystemStringPrint ")", to_system(param.unreal_param->GetClass().GetName()).c_str(), to_system(as_class_property->GetMetaClass()->GetName()).c_str()); + ImGui::Text(SystemStringPrint " (" SystemStringPrint ")", + to_system(param.unreal_param->GetClass().GetName()).c_str(), + to_system(as_class_property->GetMetaClass()->GetName()).c_str()); } else { diff --git a/UE4SS/src/LuaLibrary.cpp b/UE4SS/src/LuaLibrary.cpp index c02ff101f..6c138eeab 100644 --- a/UE4SS/src/LuaLibrary.cpp +++ b/UE4SS/src/LuaLibrary.cpp @@ -78,11 +78,11 @@ namespace RC::LuaLibrary } int32_t* int32_ptr = reinterpret_cast(lua.get_integer()); - #ifdef WIN32 +#ifdef WIN32 auto self = GetCurrentProcess(); - #else +#else auto self = getpid(); - #endif +#endif int32_t int32_val = Helper::Casting::offset_deref_safe(int32_ptr, 0, self); if (int32_val == 0) diff --git a/UE4SS/src/LuaType/LuaCustomProperty.cpp b/UE4SS/src/LuaType/LuaCustomProperty.cpp index 26ba59068..e029e458b 100644 --- a/UE4SS/src/LuaType/LuaCustomProperty.cpp +++ b/UE4SS/src/LuaType/LuaCustomProperty.cpp @@ -12,7 +12,8 @@ namespace RC::LuaType { LuaCustomProperty::PropertyList LuaCustomProperty::StaticStorage::property_list; - LuaCustomProperty::LuaCustomProperty(SystemStringType name, std::unique_ptr property) : m_name(name), m_property(std::move(property)) + LuaCustomProperty::LuaCustomProperty(SystemStringType name, std::unique_ptr property) + : m_name(name), m_property(std::move(property)) { } diff --git a/UE4SS/src/LuaType/LuaUObject.cpp b/UE4SS/src/LuaType/LuaUObject.cpp index e5fdc1a57..d35c3443f 100644 --- a/UE4SS/src/LuaType/LuaUObject.cpp +++ b/UE4SS/src/LuaType/LuaUObject.cpp @@ -1107,7 +1107,7 @@ namespace RC::LuaType if (params.lua.is_string()) { auto lua_string = params.lua.get_string(); - auto fstring = Unreal::FString{ to_ue(lua_string).c_str() }; + auto fstring = Unreal::FString{to_ue(lua_string).c_str()}; *string = fstring; } else if (params.lua.is_userdata()) diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index bf321f5ad..e9bf9d5ac 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -44,7 +44,10 @@ namespace RC if (!m_main_dll_module) { - Output::send(SYSSTR("Failed to load dll <{}> for mod {}, error code: 0x{:x}\n"), to_system_string(dll_path), m_mod_name, GetLastError()); + Output::send(SYSSTR("Failed to load dll <{}> for mod {}, error code: 0x{:x}\n"), + to_system_string(dll_path), + m_mod_name, + GetLastError()); set_installable(false); return; } @@ -203,18 +206,18 @@ namespace RC CppMod::~CppMod() { - #ifdef WIN32 +#ifdef WIN32 if (m_main_dll_module) { FreeLibrary(m_main_dll_module); RemoveDllDirectory(m_dlls_path_cookie); } - #else +#else if (m_dl_handle) { dlclose(m_dl_handle); m_dl_handle = NULL; } - #endif +#endif } } // namespace RC \ No newline at end of file diff --git a/UE4SS/src/Mod/CppUserModBase.cpp b/UE4SS/src/Mod/CppUserModBase.cpp index 866c5ec53..45a7decb1 100644 --- a/UE4SS/src/Mod/CppUserModBase.cpp +++ b/UE4SS/src/Mod/CppUserModBase.cpp @@ -14,7 +14,7 @@ namespace RC CppUserModBase::~CppUserModBase() { - #ifdef HAS_GUI +#ifdef HAS_GUI for (const auto& tab : GUITabs) { if (tab) diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index 72b0a298e..e30e6a3ae 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -263,11 +263,11 @@ namespace RC auto parameter_type_name = to_system(property_type_name.ToString()); auto parameter_name = to_system(lua_data.return_property->GetName()); - Output::send( - SYSSTR("Tried altering return value of a hooked UFunction without a registered handler for return type Return property '{}' of type " - "'{}' not supported."), - parameter_name, - parameter_type_name); + Output::send(SYSSTR("Tried altering return value of a hooked UFunction without a registered handler for return type Return property '{}' " + "of type " + "'{}' not supported."), + parameter_name, + parameter_type_name); } } }; @@ -635,7 +635,7 @@ namespace RC efindname_table.make_global("EFindName"); } - LuaMod::LuaMod(UE4SSProgram& program, SystemStringType && mod_name, SystemStringType && mod_path) + LuaMod::LuaMod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)), m_lua(LuaMadeSimple::new_state()) { // Verify that there's a 'Scripts' directory @@ -646,8 +646,8 @@ namespace RC { // "scripts" get priority over "Scripts" m_scripts_path = to_system(*scripts_directory); - } - else + } + else { // If the 'Scripts' directory doesn't exist then mark the mod as non-installable and move on to the next mod set_installable(false); @@ -845,11 +845,12 @@ namespace RC std::string current_cpaths = lua_tostring(lua_state, -1); if (scripts_directory) { - #define STRINGIFY(x) #x +#define STRINGIFY(x) #x auto dlls_path = ((*scripts_directory) / ("?" STRINGIFY(DLLEXT))).string(); current_cpaths.append(std::format(";{}", dlls_path)); } - current_cpaths.append(std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "?" STRINGIFY(DLLEXT), to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); + current_cpaths.append( + std::format(";{}" LUA_DIRSEP "{}" LUA_DIRSEP "?" STRINGIFY(DLLEXT), to_string(m_program.get_mods_directory()).c_str(), to_string(get_name()))); lua_pop(lua_state, 1); lua_pushstring(lua_state, current_cpaths.c_str()); lua_setfield(lua_state, -2, "cpath"); @@ -905,7 +906,7 @@ No overload found for function 'StaticFindObject'. Unreal::UClass* param_class{}; Unreal::UObject* param_in_outer{}; - SystemStringType param_name{}; + SystemStringType param_name{}; bool param_exact_class{}; // P1 (Class), userdata @@ -1064,7 +1065,7 @@ No overload found for function 'FindAllOf'. lua.set_nil(); return 1; }); - + if (is_true_mod == Mod::IsTrueMod::Yes) { #ifdef HAS_INPUT @@ -1120,7 +1121,6 @@ No overload found for function 'IsKeyBindRegistered'. { lua.set_bool(mod->m_program.is_keydown_event_registered(key_to_check)); } - } else { @@ -1461,8 +1461,8 @@ No overload found for function 'UnregisterHook'. { lua.throw_error("Could not dump objects and properties because the pointer to 'Mod' was nullptr"); } - UE4SSProgram::dump_all_objects_and_properties(to_system_string(std::filesystem::path{mod->m_program.get_object_dumper_output_directory()} / - UE4SSProgram::m_object_dumper_file_name)); + UE4SSProgram::dump_all_objects_and_properties( + to_system_string(std::filesystem::path{mod->m_program.get_object_dumper_output_directory()} / UE4SSProgram::m_object_dumper_file_name)); return 0; }); @@ -1641,9 +1641,9 @@ No overload found for function 'RegisterCustomProperty'. struct PropertyInfo { - SystemStringType name{}; + SystemStringType name{}; PropertyTypeInfo type{}; // Figure out what to do here, it shouldn't be just a string - SystemStringType belongs_to_class{}; + SystemStringType belongs_to_class{}; int32_t offset_internal{-1}; int32_t element_size{-1}; // Is this required for trivial types like integers and floats ? @@ -2150,7 +2150,7 @@ No overload found for function 'IterateGameDirectories'. if (!std::filesystem::exists(game_content_dir)) { Output::send(SYSSTR("IterateGameDirectories: Could not locate the root directory because the directory structure is unknown " - "(not /Game/Binaries/Win64)\n")); + "(not /Game/Binaries/Win64)\n")); lua.set_nil(); return 1; } @@ -3331,7 +3331,6 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. lua_setglobal(lua.get_lua_state(), "__OriginalReturnValue"); } - auto LuaMod::fire_on_lua_start_for_cpp_mods() -> void { if (!is_started()) @@ -3389,7 +3388,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. // Don't crash on syntax errors. try { - main_lua()->execute_file(to_system_string(std::filesystem::path {m_scripts_path} / SYSSTR("main.lua"))); + main_lua()->execute_file(to_system_string(std::filesystem::path{m_scripts_path} / SYSSTR("main.lua"))); } catch (std::runtime_error& e) { @@ -3433,8 +3432,14 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. std::erase_if(g_hooked_script_function_data, [&](std::unique_ptr& item) -> bool { if (item->mod == this) { - Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), to_system(item->unreal_function->GetName()), item->pre_callback_id, item->mod->get_name()); - Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), to_system(item->unreal_function->GetName()), item->post_callback_id, item->mod->get_name()); + Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), + to_system(item->unreal_function->GetName()), + item->pre_callback_id, + item->mod->get_name()); + Output::send(SYSSTR("\tUnregistering hook by id '{}#{}' for mod {}\n"), + to_system(item->unreal_function->GetName()), + item->post_callback_id, + item->mod->get_name()); item->unreal_function->UnregisterHook(item->pre_callback_id); item->unreal_function->UnregisterHook(item->post_callback_id); return true; @@ -3495,7 +3500,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. { return; } - if (auto it = callback_container.find(precise_name_match ? to_system(Stack.Node()->GetFullName()) : to_system(Stack.Node()->GetName())); it != callback_container.end()) + if (auto it = callback_container.find(precise_name_match ? to_system(Stack.Node()->GetFullName()) : to_system(Stack.Node()->GetName())); + it != callback_container.end()) { const auto& callback_data = it->second; for (const auto& [lua_ptr, registry_index] : callback_data.registry_indexes) @@ -3590,7 +3596,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. else { Output::send(SYSSTR("Tried altering return value of a custom BP function without a registered handler for return type Return " - "property '{}' of type '{}' not supported."), + "property '{}' of type '{}' not supported."), return_property->GetName(), return_property_type.ToString()); } @@ -3820,8 +3826,10 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. return constructed_object; }); - Unreal::Hook::RegisterULocalPlayerExecPreCallback([](Unreal::ULocalPlayer* context, Unreal::UWorld* in_world, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar) - -> Unreal::Hook::ULocalPlayerExecCallbackReturnValue { + Unreal::Hook::RegisterULocalPlayerExecPreCallback([](Unreal::ULocalPlayer* context, + Unreal::UWorld* in_world, + const RC::Unreal::TCHAR* cmd, + Unreal::FOutputDevice& ar) -> Unreal::Hook::ULocalPlayerExecCallbackReturnValue { return TRY([&] { for (const auto& callback_data : m_local_player_exec_pre_callbacks) { @@ -3880,8 +3888,10 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); }); - Unreal::Hook::RegisterULocalPlayerExecPostCallback([](Unreal::ULocalPlayer* context, Unreal::UWorld* in_world, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar) - -> Unreal::Hook::ULocalPlayerExecCallbackReturnValue { + Unreal::Hook::RegisterULocalPlayerExecPostCallback([](Unreal::ULocalPlayer* context, + Unreal::UWorld* in_world, + const RC::Unreal::TCHAR* cmd, + Unreal::FOutputDevice& ar) -> Unreal::Hook::ULocalPlayerExecCallbackReturnValue { return TRY([&] { for (const auto& callback_data : m_local_player_exec_post_callbacks) { @@ -4037,91 +4047,92 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); // Lua from the in-game console. - Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { - auto logln = [&ar](const SystemStringType& log_message) { - Output::send(std::format(SYSSTR("{}\n"), log_message)); - ar.Log((const RC::Unreal::TCHAR*) log_message.c_str()); - }; + Unreal::Hook::RegisterProcessConsoleExecCallback( + [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { + auto logln = [&ar](const SystemStringType& log_message) { + Output::send(std::format(SYSSTR("{}\n"), log_message)); + ar.Log((const RC::Unreal::TCHAR*)log_message.c_str()); + }; - if (!LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luastart"))) - { - start_console_lua_executor(); - logln(SYSSTR("Console Lua executor started")); - return true; - } - else if (LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luastop"))) - { - stop_console_lua_executor(); - logln(SYSSTR("Console Lua executor stopped")); - return true; - } - else if (LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luarestart"))) - { - stop_console_lua_executor(); - start_console_lua_executor(); - logln(SYSSTR("Console Lua executor restarted")); - return true; - } - else if (String::iequal(UEStringViewType{(UECharType*)cmd}, STR("clear"))) - { - // TODO: Replace with proper implementation when we have UGameViewportClient and UConsole. - // This should be fairly cross-game & cross-engine-version compatible even without the proper implementation. - // This is because I don't think they've changed the layout here and we have a reflected property right before the unreflected one that we're looking for. - Unreal::UObject** console = static_cast(context->GetValuePtrByPropertyName(STR("ViewportConsole"))); - auto* default_texture_white = std::bit_cast*>( - static_cast((*console)->GetValuePtrByPropertyNameInChain(STR("DefaultTexture_White"))) + 0x8); - auto* scrollback = std::bit_cast(std::bit_cast(default_texture_white) + 0x10); - default_texture_white->SetNum(0); - default_texture_white->SetMax(0); - *scrollback = 0; - return true; - } - else if (LuaStatics::console_executor_enabled) - { - if (!LuaStatics::console_executor) - { - logln(SYSSTR("Console Lua executor is enabled but the Lua instance is nullptr. Please try run RC_LUA_START again.")); - return true; - } + if (!LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luastart"))) + { + start_console_lua_executor(); + logln(SYSSTR("Console Lua executor started")); + return true; + } + else if (LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luastop"))) + { + stop_console_lua_executor(); + logln(SYSSTR("Console Lua executor stopped")); + return true; + } + else if (LuaStatics::console_executor_enabled && String::iequal(UEStringViewType{(UECharType*)cmd}, STR("luarestart"))) + { + stop_console_lua_executor(); + start_console_lua_executor(); + logln(SYSSTR("Console Lua executor restarted")); + return true; + } + else if (String::iequal(UEStringViewType{(UECharType*)cmd}, STR("clear"))) + { + // TODO: Replace with proper implementation when we have UGameViewportClient and UConsole. + // This should be fairly cross-game & cross-engine-version compatible even without the proper implementation. + // This is because I don't think they've changed the layout here and we have a reflected property right before the unreflected one that we're looking for. + Unreal::UObject** console = static_cast(context->GetValuePtrByPropertyName(STR("ViewportConsole"))); + auto* default_texture_white = std::bit_cast*>( + static_cast((*console)->GetValuePtrByPropertyNameInChain(STR("DefaultTexture_White"))) + 0x8); + auto* scrollback = std::bit_cast(std::bit_cast(default_texture_white) + 0x10); + default_texture_white->SetNum(0); + default_texture_white->SetMax(0); + *scrollback = 0; + return true; + } + else if (LuaStatics::console_executor_enabled) + { + if (!LuaStatics::console_executor) + { + logln(SYSSTR("Console Lua executor is enabled but the Lua instance is nullptr. Please try run RC_LUA_START again.")); + return true; + } - LuaLibrary::set_outputdevice_ref(*LuaStatics::console_executor, &ar); + LuaLibrary::set_outputdevice_ref(*LuaStatics::console_executor, &ar); - // logln(std::format(SYSSTR("Executing '{}' as Lua"), cmd)); + // logln(std::format(SYSSTR("Executing '{}' as Lua"), cmd)); - try - { - if (int status = luaL_loadstring(LuaStatics::console_executor->get_lua_state(), to_string((UECharType*)cmd).c_str()); status != LUA_OK) - { - LuaStatics::console_executor->throw_error( - std::format("luaL_loadstring returned {}", LuaStatics::console_executor->resolve_status_message(status, true))); - } + try + { + if (int status = luaL_loadstring(LuaStatics::console_executor->get_lua_state(), to_string((UECharType*)cmd).c_str()); status != LUA_OK) + { + LuaStatics::console_executor->throw_error( + std::format("luaL_loadstring returned {}", LuaStatics::console_executor->resolve_status_message(status, true))); + } - if (int status = lua_pcall(LuaStatics::console_executor->get_lua_state(), 0, LUA_MULTRET, 0); status != LUA_OK) + if (int status = lua_pcall(LuaStatics::console_executor->get_lua_state(), 0, LUA_MULTRET, 0); status != LUA_OK) + { + LuaStatics::console_executor->throw_error( + std::format("lua_pcall returned {}", LuaStatics::console_executor->resolve_status_message(status, true))); + } + } + catch (std::runtime_error& e) + { + logln(to_system_string(e.what())); + } + + // We always return true when the console Lua executor is enabled in order to suppress other handlers + return true; + } + else { - LuaStatics::console_executor->throw_error( - std::format("lua_pcall returned {}", LuaStatics::console_executor->resolve_status_message(status, true))); + return false; } - } - catch (std::runtime_error& e) - { - logln(to_system_string(e.what())); - } - - // We always return true when the console Lua executor is enabled in order to suppress other handlers - return true; - } - else - { - return false; - } - }); + }); // RegisterProcessConsoleExecPreHook Unreal::Hook::RegisterProcessConsoleExecGlobalPreCallback( [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { return TRY([&] { - auto command = UEStringViewType{(const UECharType*) cmd}; - auto command_parts = explode_by_occurrence((const UECharType*) cmd, ' '); + auto command = UEStringViewType{(const UECharType*)cmd}; + auto command_parts = explode_by_occurrence((const UECharType*)cmd, ' '); for (const auto& callback_data : m_process_console_exec_pre_callbacks) { @@ -4176,7 +4187,7 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. Unreal::Hook::RegisterProcessConsoleExecGlobalPostCallback( [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> std::pair { return TRY([&] { - auto command = UEStringViewType {(const UECharType*) cmd}; + auto command = UEStringViewType{(const UECharType*)cmd}; auto command_parts = explode_by_occurrence((const UECharType*)cmd, ' '); for (const auto& callback_data : m_process_console_exec_post_callbacks) @@ -4229,129 +4240,131 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. }); // RegisterConsoleCommandHandler - Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { - (void)executor; + Unreal::Hook::RegisterProcessConsoleExecCallback( + [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { + (void)executor; - if (!Unreal::Cast(context)) - { - return false; - } + if (!Unreal::Cast(context)) + { + return false; + } - return TRY([&] { - auto command = to_system_string(cmd); - auto command_parts = explode_by_occurrence(command, ' '); - SystemStringType command_name; - if (command_parts.size() > 1) - { - command_name = command_parts[0]; - } - else - { - command_name = command; - } + return TRY([&] { + auto command = to_system_string(cmd); + auto command_parts = explode_by_occurrence(command, ' '); + SystemStringType command_name; + if (command_parts.size() > 1) + { + command_name = command_parts[0]; + } + else + { + command_name = command; + } - if (auto it = m_custom_command_lua_pre_callbacks.find(command_name); it != m_custom_command_lua_pre_callbacks.end()) - { - const auto& callback_data = it->second; + if (auto it = m_custom_command_lua_pre_callbacks.find(command_name); it != m_custom_command_lua_pre_callbacks.end()) + { + const auto& callback_data = it->second; - // This is a promise that we're in the game thread, used by other functions to ensure that we don't execute when unsafe - set_is_in_game_thread(callback_data.lua, true); + // This is a promise that we're in the game thread, used by other functions to ensure that we don't execute when unsafe + set_is_in_game_thread(callback_data.lua, true); - bool return_value{}; + bool return_value{}; - for (const auto& [lua, registry_index] : callback_data.registry_indexes) - { - callback_data.lua.registry().get_function_ref(registry_index.lua_index); - callback_data.lua.set_string(to_string(command)); + for (const auto& [lua, registry_index] : callback_data.registry_indexes) + { + callback_data.lua.registry().get_function_ref(registry_index.lua_index); + callback_data.lua.set_string(to_string(command)); - auto params_table = callback_data.lua.prepare_new_table(); - for (size_t i = 1; i < command_parts.size(); ++i) - { - const auto& command_part = command_parts[i]; - params_table.add_pair(i, to_string(command_part).c_str()); - } + auto params_table = callback_data.lua.prepare_new_table(); + for (size_t i = 1; i < command_parts.size(); ++i) + { + const auto& command_part = command_parts[i]; + params_table.add_pair(i, to_string(command_part).c_str()); + } - LuaType::FOutputDevice::construct(callback_data.lua, &ar); + LuaType::FOutputDevice::construct(callback_data.lua, &ar); - callback_data.lua.call_function(3, 1); + callback_data.lua.call_function(3, 1); - if (!callback_data.lua.is_bool()) - { - throw std::runtime_error{"A custom console command handle must return true or false"}; - } + if (!callback_data.lua.is_bool()) + { + throw std::runtime_error{"A custom console command handle must return true or false"}; + } - return_value = callback_data.lua.get_bool(); - } - // No longer promising to be in the game thread - set_is_in_game_thread(callback_data.lua, false); + return_value = callback_data.lua.get_bool(); + } + // No longer promising to be in the game thread + set_is_in_game_thread(callback_data.lua, false); - return return_value; - } + return return_value; + } - return false; - }); - }); + return false; + }); + }); // RegisterConsoleCommandGlobalHandler - Unreal::Hook::RegisterProcessConsoleExecCallback([](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { - (void)context; - (void)executor; + Unreal::Hook::RegisterProcessConsoleExecCallback( + [](Unreal::UObject* context, const RC::Unreal::TCHAR* cmd, Unreal::FOutputDevice& ar, Unreal::UObject* executor) -> bool { + (void)context; + (void)executor; - return TRY([&] { - auto command = to_system_string(cmd); - auto command_parts = explode_by_occurrence(command, SYSSTR(' ')); - SystemStringType command_name; - if (command_parts.size() > 1) - { - command_name = command_parts[0]; - } - else - { - command_name = command; - } + return TRY([&] { + auto command = to_system_string(cmd); + auto command_parts = explode_by_occurrence(command, SYSSTR(' ')); + SystemStringType command_name; + if (command_parts.size() > 1) + { + command_name = command_parts[0]; + } + else + { + command_name = command; + } - if (auto it = m_global_command_lua_callbacks.find(command_name); it != m_global_command_lua_callbacks.end()) - { - const auto& callback_data = it->second; + if (auto it = m_global_command_lua_callbacks.find(command_name); it != m_global_command_lua_callbacks.end()) + { + const auto& callback_data = it->second; - // This is a promise that we're in the game thread, used by other functions to ensure that we don't execute when unsafe - set_is_in_game_thread(callback_data.lua, true); + // This is a promise that we're in the game thread, used by other functions to ensure that we don't execute when unsafe + set_is_in_game_thread(callback_data.lua, true); - bool return_value{}; + bool return_value{}; - for (const auto& [lua, registry_index] : callback_data.registry_indexes) - { - callback_data.lua.registry().get_function_ref(registry_index.lua_index); - callback_data.lua.set_string(to_string(command)); + for (const auto& [lua, registry_index] : callback_data.registry_indexes) + { + callback_data.lua.registry().get_function_ref(registry_index.lua_index); + callback_data.lua.set_string(to_string(command)); - auto params_table = callback_data.lua.prepare_new_table(); - for (size_t i = 1; i < command_parts.size(); ++i) - { - const auto& command_part = command_parts[i]; - params_table.add_pair(i, to_string(command_part).c_str()); - } + auto params_table = callback_data.lua.prepare_new_table(); + for (size_t i = 1; i < command_parts.size(); ++i) + { + const auto& command_part = command_parts[i]; + params_table.add_pair(i, to_string(command_part).c_str()); + } - LuaType::FOutputDevice::construct(callback_data.lua, &ar); + LuaType::FOutputDevice::construct(callback_data.lua, &ar); - callback_data.lua.call_function(3, 1); + callback_data.lua.call_function(3, 1); - if (!callback_data.lua.is_bool()) - { - throw std::runtime_error{"A custom console command handle must return true or false"}; - } + if (!callback_data.lua.is_bool()) + { + throw std::runtime_error{"A custom console command handle must return true or false"}; + } - return_value = callback_data.lua.get_bool(); - } + return_value = callback_data.lua.get_bool(); + } - // No longer promising to be in the game thread - set_is_in_game_thread(callback_data.lua, false); + // No longer promising to be in the game thread + set_is_in_game_thread(callback_data.lua, false); - return return_value; - } + return return_value; + } - return false; - }); - }); + return false; + }); + }); if (Unreal::UObject::ProcessLocalScriptFunctionInternal.is_ready() && Unreal::Version::IsAtLeast(4, 22)) { @@ -4418,7 +4431,8 @@ No overload found for function 'FPackageName:IsValidLongPackageName'. catch (std::runtime_error& e) { Output::send(SYSSTR("[{}] {}\n"), - to_system(action.type == LuaMod::ActionType::Loop ? SYSSTR("LoopAsync") : SYSSTR("DelayedAction")), + to_system(action.type == LuaMod::ActionType::Loop ? SYSSTR("LoopAsync") + : SYSSTR("DelayedAction")), to_system(e.what())); } diff --git a/UE4SS/src/Mod/Mod.cpp b/UE4SS/src/Mod/Mod.cpp index 933c04107..944cb43ec 100644 --- a/UE4SS/src/Mod/Mod.cpp +++ b/UE4SS/src/Mod/Mod.cpp @@ -47,7 +47,6 @@ #include #pragma warning(default : 4005) - namespace RC { diff --git a/UE4SS/src/ObjectDumper/ObjectToString.cpp b/UE4SS/src/ObjectDumper/ObjectToString.cpp index 687e1da67..332874e4a 100644 --- a/UE4SS/src/ObjectDumper/ObjectToString.cpp +++ b/UE4SS/src/ObjectDumper/ObjectToString.cpp @@ -139,7 +139,8 @@ namespace RC::ObjectDumper FMapProperty* typed_this = static_cast(p_this); FProperty* key_property = typed_this->GetKeyProp(); FProperty* value_property = typed_this->GetValueProp(); - out_line.append(std::format(SYSSTR(" [kp: {:016X}] [vp: {:016X}]"), reinterpret_cast(key_property), reinterpret_cast(value_property))); + out_line.append( + std::format(SYSSTR(" [kp: {:016X}] [vp: {:016X}]"), reinterpret_cast(key_property), reinterpret_cast(value_property))); } auto mapproperty_to_string_complex(void* p_this, SystemStringType& out_line, ObjectToStringComplexDeclCallable callable) -> void diff --git a/UE4SS/src/SDKGenerator/Common.cpp b/UE4SS/src/SDKGenerator/Common.cpp index 1a85f72a7..2bc9d5db2 100644 --- a/UE4SS/src/SDKGenerator/Common.cpp +++ b/UE4SS/src/SDKGenerator/Common.cpp @@ -252,7 +252,7 @@ namespace RC::UEGenerator { return SYSSTR("TSoftClassPtr"); } - + const SystemStringType meta_class_name = get_native_class_name(meta_class, false); return std::format(SYSSTR("TSoftClassPtr<{}>"), meta_class_name); } diff --git a/UE4SS/src/SDKGenerator/Generator.cpp b/UE4SS/src/SDKGenerator/Generator.cpp index 44a8ee9ae..81be14545 100644 --- a/UE4SS/src/SDKGenerator/Generator.cpp +++ b/UE4SS/src/SDKGenerator/Generator.cpp @@ -342,7 +342,7 @@ namespace RC::UEGenerator return return_property_info.has_value() ? return_property_info.value().property : nullptr; }(); - SystemStringType function_name {to_system(function_info.function->GetName())}; + SystemStringType function_name{to_system(function_info.function->GetName())}; if (is_delegate_function == IsDelegateFunction::Yes) { // Remove the last 19 characters, which is always '__DelegateSignature' for delegates @@ -557,13 +557,13 @@ namespace RC::UEGenerator m_file_names.emplace(package_name_all_lower, FileName{}); } - // The '\\?\' at the beginning of the string unlocks path size restriction from MAX_PATH to 32k - #ifdef WIN32 +// The '\\?\' at the beginning of the string unlocks path size restriction from MAX_PATH to 32k +#ifdef WIN32 std::filesystem::path directory_to_generate_in = std::filesystem::path("\\\\?\\"); directory_to_generate_in += (m_directory_to_generate_in); - #else - std::filesystem::path directory_to_generate_in = (m_directory_to_generate_in); - #endif +#else + std::filesystem::path directory_to_generate_in = (m_directory_to_generate_in); +#endif SystemStringType ext = specification.get_file_extension(); std::filesystem::path primary_file_path_and_name = directory_to_generate_in; @@ -677,22 +677,18 @@ namespace RC::UEGenerator } auto generate_file_header(GeneratedFile& generated_file) -> void { - generated_file.primary_file.write_file_string_to_file( - to_file(std::format(SYSSTR("#ifndef UE4SS_SDK_{}_HPP\n#define UE4SS_SDK_{}_HPP\n\n"), generated_file.package_name, generated_file.package_name)) - ); + generated_file.primary_file.write_file_string_to_file(to_file( + std::format(SYSSTR("#ifndef UE4SS_SDK_{}_HPP\n#define UE4SS_SDK_{}_HPP\n\n"), generated_file.package_name, generated_file.package_name))); if (!generated_file.secondary_file_has_no_contents) { generated_file.primary_file.write_file_string_to_file( - to_file(std::format(SYSSTR("#include \"{}\"\n\n"), generated_file.secondary_file_name.filename().c_str())) - ); + to_file(std::format(SYSSTR("#include \"{}\"\n\n"), generated_file.secondary_file_name.filename().c_str()))); } } auto generate_file_footer(GeneratedFile& generated_file) -> void { - generated_file.primary_file.write_file_string_to_file( - IOSTR("#endif\n") - ); + generated_file.primary_file.write_file_string_to_file(IOSTR("#endif\n")); } auto generate_enum_declaration(SystemStringType& content_buffer, UEnum* uenum) -> void { @@ -792,7 +788,9 @@ namespace RC::UEGenerator } catch (std::exception& e) { - Output::send(SYSSTR("Could not generate property '{}' because: {}\n"),to_system(property->GetFullName()), to_system(e.what())); + Output::send(SYSSTR("Could not generate property '{}' because: {}\n"), + to_system(property->GetFullName()), + to_system(e.what())); continue; } @@ -921,8 +919,9 @@ namespace RC::UEGenerator printf_s("last_property_offset: %X\n", last_property_offset); printf_s("first_property_offset: %X\n", first_property_offset); - auto padding_part_one = std::format(SYSSTR("{}char {}[0x{:X}];"), generate_tab(), std::format(SYSSTR("padding_{}"), num_padding_elements), padding_size); - out.append(std::format(SYSSTR("{:85} // 0x{:04X} (size: 0x{:X})\n"), padding_part_one, last_property_offset + last_property_size, padding_size)); + auto padding_part_one = std::format(SYSSTR("{}char {}[0x{:X}];"), generate_tab(), std::format(SYSSTR("padding_{}"), + num_padding_elements), padding_size); out.append(std::format(SYSSTR("{:85} // 0x{:04X} (size: 0x{:X})\n"), padding_part_one, + last_property_offset + last_property_size, padding_size)); } } //*/ @@ -1026,10 +1025,11 @@ namespace RC::UEGenerator private: auto is_valid_lua_symbol(const SystemStringType& str) -> bool { - static const std::set keywords = {SYSSTR("and"), SYSSTR("break"), SYSSTR("do"), SYSSTR("else"), SYSSTR("elseif"), SYSSTR("end"), - SYSSTR("false"), SYSSTR("for"), SYSSTR("function"), SYSSTR("if"), SYSSTR("in"), SYSSTR("local"), - SYSSTR("nil"), SYSSTR("not"), SYSSTR("or"), SYSSTR("repeat"), SYSSTR("return"), SYSSTR("then"), - SYSSTR("true"), SYSSTR("until"), SYSSTR("while")}; + static const std::set keywords = {SYSSTR("and"), SYSSTR("break"), SYSSTR("do"), SYSSTR("else"), SYSSTR("elseif"), + SYSSTR("end"), SYSSTR("false"), SYSSTR("for"), SYSSTR("function"), SYSSTR("if"), + SYSSTR("in"), SYSSTR("local"), SYSSTR("nil"), SYSSTR("not"), SYSSTR("or"), + SYSSTR("repeat"), SYSSTR("return"), SYSSTR("then"), SYSSTR("true"), SYSSTR("until"), + SYSSTR("while")}; if (keywords.contains(str)) { return false; @@ -1174,13 +1174,16 @@ namespace RC::UEGenerator } else { - content_buffer.append( - std::format(SYSSTR("---@field [{}] {}\n"), quote_lua_symbol(property_name), generate_property_lua_name(property, true, native_class))); + content_buffer.append(std::format(SYSSTR("---@field [{}] {}\n"), + quote_lua_symbol(property_name), + generate_property_lua_name(property, true, native_class))); } } catch (std::exception& e) { - Output::send(SYSSTR("Could not generate property '{}' because: {}\n"), to_system(property->GetFullName()), to_system(e.what())); + Output::send(SYSSTR("Could not generate property '{}' because: {}\n"), + to_system(property->GetFullName()), + to_system(e.what())); continue; } @@ -1256,7 +1259,7 @@ namespace RC::UEGenerator catch (std::exception& e) { Output::send(SYSSTR("Could not generate function '{}' because: {}\n"), - to_system( function_info.function->GetFullName()), + to_system(function_info.function->GetFullName()), to_system(e.what())); return; } diff --git a/UE4SS/src/SDKGenerator/JSONDumper.cpp b/UE4SS/src/SDKGenerator/JSONDumper.cpp index 710e5d8b1..0b98a75e0 100644 --- a/UE4SS/src/SDKGenerator/JSONDumper.cpp +++ b/UE4SS/src/SDKGenerator/JSONDumper.cpp @@ -296,7 +296,7 @@ namespace RC::UEGenerator::JSONDumper } auto& bp_property = properties.new_object(); - bp_property.new_string(SYSSTR("name"),to_system(property->GetName())); + bp_property.new_string(SYSSTR("name"), to_system(property->GetName())); bp_property.new_string(SYSSTR("type"), generate_property_cxx_name(property, true, object_as_class)); } diff --git a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp index e8b0139a7..6af35660c 100644 --- a/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp +++ b/UE4SS/src/SDKGenerator/UEHeaderGenerator.cpp @@ -259,7 +259,7 @@ namespace RC::UEGenerator module_build_file.append_line(SYSSTR("using UnrealBuildTool;")); module_build_file.append_line(SYSSTR("")); - module_build_file.append_line(std::format(SYSSTR("public class {} : ModuleRules {{"), module_name_sys)); + module_build_file.append_line(std::format(SYSSTR("public class {} : ModuleRules {{"), module_name_sys)); module_build_file.begin_indent_level(); module_build_file.append_line(std::format(SYSSTR("public {}(ReadOnlyTargetRules Target) : base(Target) {{"), module_name_sys)); @@ -548,7 +548,8 @@ namespace RC::UEGenerator } header_data.append_line(std::format(SYSSTR("USTRUCT({})"), struct_flags_string)); - header_data.append_line(std::format(SYSSTR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name, parent_struct_declaration)); + header_data.append_line( + std::format(SYSSTR("struct {}{}{} {{"), is_struct_exported ? api_macro_name : SYSSTR(""), struct_native_name, parent_struct_declaration)); header_data.begin_indent_level(); header_data.append_line(SYSSTR("GENERATED_BODY()")); @@ -647,7 +648,7 @@ namespace RC::UEGenerator { enum_name_set.emplace(enum_name); } - + // Taking advantage of GetNameByValue returning the first result for the value to determine if there are any enumerator names that // reference an already declared value/name. auto first_name_with_value = uenum->GetNameByValue(Value).ToString(); @@ -671,11 +672,12 @@ namespace RC::UEGenerator const auto expected_full_constant_name = std::format(SYSSTR("{}_MAX"), to_system(enum_prefix)); SystemStringType expected_full_constant_name_lower = expected_full_constant_name; std::transform(expected_full_constant_name_lower.begin(), expected_full_constant_name_lower.end(), expected_full_constant_name_lower.begin(), ::towlower); - + int64_t expected_max_value = highest_enum_value + 1; // Skip enum _MAX constant if it has a matching name and is 1 greater than the highest value used, which means it has been autogenerated - if ((pre_append_result_line_lower == expected_full_constant_name_lower || pre_append_result_line_lower == sanitize_enumeration_name(expected_full_constant_name_lower)) && + if ((pre_append_result_line_lower == expected_full_constant_name_lower || + pre_append_result_line_lower == sanitize_enumeration_name(expected_full_constant_name_lower)) && Value == expected_max_value) { continue; @@ -757,18 +759,19 @@ namespace RC::UEGenerator return_value_declaration.append(SYSSTR(", ")); } - SystemStringType delegate_declaration_string = std::format(SYSSTR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), - delegate_macro_string, - is_multicast ? SYSSTR("_MULTICAST") : SYSSTR(""), - is_sparse ? SYSSTR("_SPARSE") : SYSSTR(""), - return_value_property ? SYSSTR("_RetVal") : SYSSTR(""), - generate_parameter_count_string(num_delegate_parameters), - declared_const ? SYSSTR("_Const") : SYSSTR(""), - return_value_declaration, - delegate_type_name, - // TODO: Actually get delegate property name. - is_sparse ? std::format(SYSSTR("{}, {}"), owning_class, SYSSTR("EnterPropertyName")) : SYSSTR(""), - delegate_parameter_list); + SystemStringType delegate_declaration_string = + std::format(SYSSTR("{}DECLARE_DYNAMIC{}{}_DELEGATE{}{}{}({}{}{}{});"), + delegate_macro_string, + is_multicast ? SYSSTR("_MULTICAST") : SYSSTR(""), + is_sparse ? SYSSTR("_SPARSE") : SYSSTR(""), + return_value_property ? SYSSTR("_RetVal") : SYSSTR(""), + generate_parameter_count_string(num_delegate_parameters), + declared_const ? SYSSTR("_Const") : SYSSTR(""), + return_value_declaration, + delegate_type_name, + // TODO: Actually get delegate property name. + is_sparse ? std::format(SYSSTR("{}, {}"), owning_class, SYSSTR("EnterPropertyName")) : SYSSTR(""), + delegate_parameter_list); header_data.append_line(delegate_declaration_string); } @@ -829,10 +832,15 @@ namespace RC::UEGenerator } else { - generate_advanced_assignment_expression(attachment.first, (attachment.second).attach_string, implementation_file, SYSSTR("this->"), (attachment.second).property_type, SYSSTR("->")); + generate_advanced_assignment_expression(attachment.first, + (attachment.second).attach_string, + implementation_file, + SYSSTR("this->"), + (attachment.second).property_type, + SYSSTR("->")); } } - + implementation_file.end_indent_level(); implementation_file.append_line(SYSSTR("}\n")); @@ -1017,7 +1025,8 @@ namespace RC::UEGenerator function_extra_postfix_string.append(std::format(SYSSTR(" PURE_VIRTUAL({},{})"), to_system(function->GetName()), return_statement_string)); } - auto function_argument_list = generate_function_parameter_list(uclass, function, header_data, false, to_system_string(context_name), blacklisted_property_names); + auto function_argument_list = + generate_function_parameter_list(uclass, function, header_data, false, to_system_string(context_name), blacklisted_property_names); const auto function_flags_string = generate_function_flags(function, is_function_pure_virtual); header_data.append_line(std::format(SYSSTR("UFUNCTION({})"), function_flags_string)); @@ -1094,14 +1103,20 @@ namespace RC::UEGenerator implementation_file.append_line(std::format(SYSSTR("const FProperty* p_{} = GetClass()->FindPropertyByName(\"{}\");"), field_class_name, field_class_name)); if (property->GetArrayDim() == 1) { - implementation_file.append_line(std::format(SYSSTR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); + implementation_file.append_line( + std::format(SYSSTR("(*p_{}->ContainerPtrToValuePtr<{}>(this)){}{};"), field_class_name, property_type, operator_type, value)); } else { for (int32_t i = 0; i < property->GetArrayDim(); i++) { - implementation_file.append_line( - std::format(SYSSTR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), field_class_name, property_scope, field_class_name, i, operator_type, value)); + implementation_file.append_line(std::format(SYSSTR("*p_{}->ContainerPtrToValuePtr<{}>(this){}[{}]{}{};"), + field_class_name, + property_scope, + field_class_name, + i, + operator_type, + value)); } } } @@ -1110,7 +1125,10 @@ namespace RC::UEGenerator UStruct* ustruct, FProperty* property, void* object, GeneratedSourceFile& implementation_file, const SystemStringType& property_scope) -> void { const auto property_name = property->GetName(); - if (property_name == STR("NativeClass") || property_name == STR("hudClass")) { return; } + if (property_name == STR("NativeClass") || property_name == STR("hudClass")) + { + return; + } const bool private_access_modifier = get_property_access_modifier(property) == AccessModifier::Private; bool super_and_no_access = false; // Populate super for checks to ensure values are only initialized if they are overriden in the child class @@ -1166,11 +1184,11 @@ namespace RC::UEGenerator } else { - #ifdef WIN32 +#ifdef WIN32 result_property_value = std::to_wstring(*byte_property_value); - #else +#else result_property_value = std::to_string(*byte_property_value); - #endif +#endif } if (!super_and_no_access) @@ -1260,7 +1278,10 @@ namespace RC::UEGenerator else { // Skip private bitmask bools TODO: Fix setting these - if (bool_property->GetFieldMask() != 255) { return; } + if (bool_property->GetFieldMask() != 255) + { + return; + } generate_advanced_assignment_expression(property, result_property_value, implementation_file, property_scope, property_type); } return; @@ -1303,13 +1324,13 @@ namespace RC::UEGenerator if (property->IsA()) { FString* string_value = property->ContainerPtrToValuePtr(object); - const auto string_value_string = (to_system (string_value->GetCharArray())); + const auto string_value_string = (to_system(string_value->GetCharArray())); // Ensure property either does not exist in parent class or is overriden in the CDO for the child class if (super_property != nullptr) { FString* super_string_value = super_property->ContainerPtrToValuePtr(super_object); - const auto super_string_value_string = (to_system (super_string_value->GetCharArray())); + const auto super_string_value_string = (to_system(super_string_value->GetCharArray())); if (string_value_string == super_string_value_string) { return; @@ -1537,7 +1558,7 @@ namespace RC::UEGenerator implementation_file.add_dependency_object(object_class_type, DependencyLevel::Include); implementation_file.m_implementation_constructor.append( std::format(SYSSTR(".SetDefaultSubobjectClass<{}>(TEXT(\"{}\"))"), get_native_class_name(object_class_type), to_system(object_name))); - m_class_subobjects.try_emplace(object_name, (property->GetName())); + m_class_subobjects.try_emplace(object_name, (property->GetName())); } else { @@ -1593,9 +1614,10 @@ namespace RC::UEGenerator } else { - auto parent_property_name = std::format(SYSSTR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), - to_system(check_property->GetName()), - to_system(check_property->GetName())); + auto parent_property_name = + std::format(SYSSTR("const FProperty* p_{}_Parent = GetClass()->FindPropertyByName(\"{}\");"), + to_system(check_property->GetName()), + to_system(check_property->GetName())); if (!implementation_file.parent_property_names.contains(parent_property_name)) { implementation_file.parent_property_names.emplace(parent_property_name); @@ -1617,11 +1639,11 @@ namespace RC::UEGenerator { if (!super_and_no_access) { - implementation_file.attachments.try_emplace(property, GeneratedSourceFile::attachment_data {property_type, attach_string, false}); + implementation_file.attachments.try_emplace(property, GeneratedSourceFile::attachment_data{property_type, attach_string, false}); } else { - implementation_file.attachments.try_emplace(property, GeneratedSourceFile::attachment_data {property_type, attach_string, true}); + implementation_file.attachments.try_emplace(property, GeneratedSourceFile::attachment_data{property_type, attach_string, true}); } } } @@ -1704,7 +1726,8 @@ namespace RC::UEGenerator { if (!super_and_no_access) { - implementation_file.append_line(std::format(SYSSTR("{}{}.AddDefaulted({});"), property_scope, to_system(property->GetName()), (int32_t)property_value->Num())); + implementation_file.append_line( + std::format(SYSSTR("{}{}.AddDefaulted({});"), property_scope, to_system(property->GetName()), (int32_t)property_value->Num())); } else { @@ -2280,7 +2303,7 @@ namespace RC::UEGenerator { FByteProperty* byte_property = static_cast(property); UEnum* enum_value = byte_property->GetEnum(); - + if (enum_value != NULL) { if (context.source_file != NULL) @@ -2673,9 +2696,8 @@ namespace RC::UEGenerator { return SYSSTR("FText"); } - throw std::runtime_error(RC::fmt("[generate_property_type_declaration] Unsupported property class '{}', full name: '{}'", - field_class_name, - property->GetFullName())); + throw std::runtime_error( + RC::fmt("[generate_property_type_declaration] Unsupported property class '{}', full name: '{}'", field_class_name, property->GetFullName())); } //*/ @@ -2920,7 +2942,7 @@ namespace RC::UEGenerator auto UEHeaderGenerator::generate_enum_flags(UEnum* uenum) const -> SystemStringType { - + FlagFormatHelper flag_format_helper{}; auto enum_flags = uenum->GetEnumFlags(); @@ -2937,11 +2959,8 @@ namespace RC::UEGenerator if (cpp_form == UEnum::ECppForm::EnumClass) { const auto underlying_type = m_underlying_enum_types.find(enum_native_name); - if ((underlying_type == m_underlying_enum_types.end() && - (get_highest_enum(uenum) <= 255 && - get_lowest_enum(uenum) >= 0)) || - ((underlying_type != m_underlying_enum_types.end()) && - (underlying_type->second == SYSSTR("uint8")))) + if ((underlying_type == m_underlying_enum_types.end() && (get_highest_enum(uenum) <= 255 && get_lowest_enum(uenum) >= 0)) || + ((underlying_type != m_underlying_enum_types.end()) && (underlying_type->second == SYSSTR("uint8")))) { // Underlying type is implicit or explicitly uint8. flag_format_helper.add_switch(SYSSTR("BlueprintType")); @@ -2980,7 +2999,7 @@ namespace RC::UEGenerator const auto expected_max_name = std::format(SYSSTR("{}_MAX"), enum_prefix); auto expected_max_name_lower = expected_max_name; std::transform(expected_max_name_lower.begin(), expected_max_name_lower.end(), expected_max_name_lower.begin(), ::towlower); - + for (auto [Name, Value] : uenum->ForEachName()) { auto enum_name = sanitize_enumeration_name(to_system_string(Name.ToString())); @@ -3241,7 +3260,8 @@ namespace RC::UEGenerator return function_arguments_string; } - auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) -> SystemStringType + auto UEHeaderGenerator::generate_default_property_value(FProperty* property, GeneratedSourceFile& header_data, const SystemStringType& ContextName) + -> SystemStringType { const auto field_class_name = (property->GetClass().GetName()); PropertyTypeDeclarationContext context(ContextName, &header_data); @@ -3381,9 +3401,8 @@ namespace RC::UEGenerator { return SYSSTR("FText::GetEmpty()"); } - throw std::runtime_error(RC::fmt("[generate_default_property_value] Unsupported property class '{}', full name: '{}'", - field_class_name, - property->GetFullName())); + throw std::runtime_error( + RC::fmt("[generate_default_property_value] Unsupported property class '{}', full name: '{}'", field_class_name, property->GetFullName())); } auto UEHeaderGenerator::get_class_blueprint_info(UClass* uclass) -> ClassBlueprintInfo @@ -3864,8 +3883,7 @@ namespace RC::UEGenerator } else { - throw std::runtime_error( - RC::fmt("Provided object {} is not of a supported type: {}", object->GetName(), object->GetClassPrivate()->GetName())); + throw std::runtime_error(RC::fmt("Provided object {} is not of a supported type: {}", object->GetName(), object->GetClassPrivate()->GetName())); } auto iterator = this->m_module_dependencies.find(module_name); @@ -4027,7 +4045,8 @@ namespace RC::UEGenerator return SYSSTR("Main"); } - auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) -> SystemStringType + auto UEHeaderGenerator::generate_cross_module_include(UObject* object, const SystemStringType& module_name, const SystemStringType& fallback_name) + -> SystemStringType { // Retrieve the most top level object located inside the native package UObject* top_level_object = object; @@ -4038,7 +4057,10 @@ namespace RC::UEGenerator } const auto object_name = to_system(top_level_object->GetName()); - return std::format(SYSSTR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), to_system(module_name), object_name, to_system(fallback_name)); + return std::format(SYSSTR("//CROSS-MODULE INCLUDE V2: -ModuleName={} -ObjectName={} -FallbackName={}\n"), + to_system(module_name), + object_name, + to_system(fallback_name)); } UEGeneratedFile::UEGeneratedFile(const FFilePath& full_file_path) diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index 1c7eaab99..eeae83936 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -5,7 +5,7 @@ #define REGISTER_STRING_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_string(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_string(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -14,7 +14,7 @@ #define REGISTER_INT64_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_int64(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_int64(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -23,7 +23,7 @@ #define REGISTER_BOOL_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_bool(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_bool(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -32,7 +32,7 @@ #define REGISTER_FLOAT_SETTING(member_var, section_name, key) \ try \ { \ - (member_var) = parser.get_float(section_name, SYSSTR(#key)); \ + (member_var) = parser.get_float(section_name, SYSSTR(#key)); \ } \ catch (std::exception&) \ { \ @@ -84,10 +84,10 @@ namespace RC REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) REGISTER_FLOAT_SETTING(Debug.DebugGUIFontScaling, section_debug, GuiConsoleFontScaling) - #ifdef HAS_GUI +#ifdef HAS_GUI SystemStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) - #ifdef WIN32 +#ifdef WIN32 if (String::iequal(graphics_api_string, SYSSTR("DX11")) || String::iequal(graphics_api_string, SYSSTR("D3D11"))) { Debug.GraphicsAPI = GUI::GfxBackend::DX11; @@ -96,19 +96,19 @@ namespace RC { Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; } - #else - #ifdef HAS_GLFW +#else +#ifdef HAS_GLFW Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; - #else +#else Debug.GraphicsAPI = GUI::GfxBackend::TUI; - #endif - #endif - #endif +#endif +#endif +#endif REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); - ///constexpr static SystemCharType section_crash_dump[] = SSTR("CrashDump"); - ///REGISTER_BOOL_SETTING(CrashDump.EnableDumping, section_crash_dump, EnableDumping); - ///REGISTER_BOOL_SETTING(CrashDump.FullMemoryDump, section_crash_dump, FullMemoryDump); + /// constexpr static SystemCharType section_crash_dump[] = SSTR("CrashDump"); + /// REGISTER_BOOL_SETTING(CrashDump.EnableDumping, section_crash_dump, EnableDumping); + /// REGISTER_BOOL_SETTING(CrashDump.FullMemoryDump, section_crash_dump, FullMemoryDump); constexpr static SystemCharType section_threads[] = SYSSTR("Threads"); REGISTER_INT64_SETTING(Threads.SigScannerNumThreads, section_threads, SigScannerNumThreads) @@ -131,27 +131,27 @@ namespace RC constexpr static SystemCharType section_experimental_features[] = SYSSTR("ExperimentalFeatures"); REGISTER_BOOL_SETTING(Experimental.GUIUFunctionCaller, section_experimental_features, GUIUFunctionCaller) - #ifdef LINUX - constexpr static SystemCharType section_tui_features[] = SYSSTR("TUI"); - REGISTER_INT64_SETTING(TUI.ButtonLeft, section_tui_features, ButtonLeft) - REGISTER_INT64_SETTING(TUI.ButtonRight, section_tui_features, ButtonRight) - REGISTER_INT64_SETTING(TUI.WheelUp, section_tui_features, WheelUp) - REGISTER_INT64_SETTING(TUI.WheelDown, section_tui_features, WheelDown) - REGISTER_BOOL_SETTING(TUI.TUIAsInputSource, section_tui_features, TUIAsInputSource) - REGISTER_BOOL_SETTING(TUI.TUINerdFont, section_tui_features, TUINerdFont) - /* - REGISTER_STRING_SETTING(TUI.TerminalCode, section_tui_features, TerminalCode) - REGISTER_STRING_SETTING(TUI.ArchiveCode, section_tui_features, ArchiveCode) - REGISTER_STRING_SETTING(TUI.SyncCode, section_tui_features, SyncCode) - REGISTER_STRING_SETTING(TUI.FileCode, section_tui_features, FileCode) - REGISTER_STRING_SETTING(TUI.EyeCode, section_tui_features, EyeCode) - REGISTER_STRING_SETTING(TUI.PuzzlePieceCode, section_tui_features, PuzzlePieceCode) - REGISTER_STRING_SETTING(TUI.AngleLeftCode, section_tui_features, AngleLeftCode) - REGISTER_STRING_SETTING(TUI.AngleRightCode, section_tui_features, AngleRightCode) - REGISTER_STRING_SETTING(TUI.BanCode, section_tui_features, BanCode) - REGISTER_STRING_SETTING(TUI.CopyCode, section_tui_features, CopyCode) - REGISTER_STRING_SETTING(TUI.SearchCode, section_tui_features, SearchCode) - */ - #endif +#ifdef LINUX + constexpr static SystemCharType section_tui_features[] = SYSSTR("TUI"); + REGISTER_INT64_SETTING(TUI.ButtonLeft, section_tui_features, ButtonLeft) + REGISTER_INT64_SETTING(TUI.ButtonRight, section_tui_features, ButtonRight) + REGISTER_INT64_SETTING(TUI.WheelUp, section_tui_features, WheelUp) + REGISTER_INT64_SETTING(TUI.WheelDown, section_tui_features, WheelDown) + REGISTER_BOOL_SETTING(TUI.TUIAsInputSource, section_tui_features, TUIAsInputSource) + REGISTER_BOOL_SETTING(TUI.TUINerdFont, section_tui_features, TUINerdFont) + /* + REGISTER_STRING_SETTING(TUI.TerminalCode, section_tui_features, TerminalCode) + REGISTER_STRING_SETTING(TUI.ArchiveCode, section_tui_features, ArchiveCode) + REGISTER_STRING_SETTING(TUI.SyncCode, section_tui_features, SyncCode) + REGISTER_STRING_SETTING(TUI.FileCode, section_tui_features, FileCode) + REGISTER_STRING_SETTING(TUI.EyeCode, section_tui_features, EyeCode) + REGISTER_STRING_SETTING(TUI.PuzzlePieceCode, section_tui_features, PuzzlePieceCode) + REGISTER_STRING_SETTING(TUI.AngleLeftCode, section_tui_features, AngleLeftCode) + REGISTER_STRING_SETTING(TUI.AngleRightCode, section_tui_features, AngleRightCode) + REGISTER_STRING_SETTING(TUI.BanCode, section_tui_features, BanCode) + REGISTER_STRING_SETTING(TUI.CopyCode, section_tui_features, CopyCode) + REGISTER_STRING_SETTING(TUI.SearchCode, section_tui_features, SearchCode) + */ +#endif } } // namespace RC diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 7a4ee1d32..71131c4f6 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -97,7 +97,7 @@ namespace RC #define OUTPUT_MEMBER_OFFSETS_FOR_STRUCT(StructName) \ for (const auto& [name, offset] : Unreal::StructName::MemberOffsets) \ { \ - Output::send(SYSSTR(#StructName "::{} = 0x{:X}\n"), name, offset); \ + Output::send(SYSSTR(#StructName "::{} = 0x{:X}\n"), name, offset); \ } auto output_all_member_offsets() -> void @@ -235,9 +235,12 @@ namespace RC UE4SS_LIB_VERSION_MAJOR, UE4SS_LIB_VERSION_MINOR, UE4SS_LIB_VERSION_HOTFIX, - std::format(SYSSTR("{}"), UE4SS_LIB_VERSION_PRERELEASE == 0 ? SYSSTR("") : std::format(SYSSTR(" PreRelease #{}"), UE4SS_LIB_VERSION_PRERELEASE)), std::format(SYSSTR("{}"), - UE4SS_LIB_BETA_STARTED == 0 ? SYSSTR("") : (UE4SS_LIB_IS_BETA == 0 ? SYSSTR(" Beta #?") : std::format(SYSSTR(" Beta #{}"), UE4SS_LIB_VERSION_BETA))), + UE4SS_LIB_VERSION_PRERELEASE == 0 ? SYSSTR("") : std::format(SYSSTR(" PreRelease #{}"), UE4SS_LIB_VERSION_PRERELEASE)), + std::format(SYSSTR("{}"), + UE4SS_LIB_BETA_STARTED == 0 + ? SYSSTR("") + : (UE4SS_LIB_IS_BETA == 0 ? SYSSTR(" Beta #?") : std::format(SYSSTR(" Beta #{}"), UE4SS_LIB_VERSION_BETA))), to_system(UE4SS_LIB_BUILD_GITSHA)); #ifdef __clang__ @@ -354,7 +357,7 @@ namespace RC { auto& module = SigScannerStaticData::m_modules_info.array[i]; // only log modules with unique addresses (non-modular builds have everything in MainExe) - if (i == static_cast(ScanTarget::MainExe) || main_exe_ptr != module.base_address) + if (i == static_cast(ScanTarget::MainExe) || main_exe_ptr != module.base_address) { auto module_name = to_system(ScanTargetToString(i)); // FIXME: FIX Why this won't WORK? @@ -474,7 +477,7 @@ namespace RC { settings_manager.Debug.SimpleConsoleEnabled = true; create_simple_console(); - printf_s( SystemStringPrint "\n", error_message.data()); + printf_s(SystemStringPrint "\n", error_message.data()); } auto UE4SSProgram::setup_mod_directory_path() -> void @@ -497,7 +500,7 @@ namespace RC { m_debug_console_device = &Output::set_default_devices(); Output::set_default_log_level(); - m_debug_console_device->set_formatter([](SystemStringViewType string) ->SystemStringType { + m_debug_console_device->set_formatter([](SystemStringViewType string) -> SystemStringType { return std::format(SYSSTR("[{}] {}"), std::format(SYSSTR("{:%X}"), std::chrono::system_clock::now()), string); }); #ifdef WIN32 @@ -631,18 +634,20 @@ namespace RC }; Output::send(SYSSTR("UObjectBase\n")); - uint32_t uobjectbase_size = retrieve_vtable_layout_from_ini(SYSSTR("UObjectBase"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { - uint32_t offset = calculate_virtual_function_offset(index, 0); - Output::send(SYSSTR("UObjectBase::{} = 0x{:X}\n"), item, offset); - Unreal::UObjectBase::VTableLayoutMap.emplace(item_ue, offset); - }); + uint32_t uobjectbase_size = + retrieve_vtable_layout_from_ini(SYSSTR("UObjectBase"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { + uint32_t offset = calculate_virtual_function_offset(index, 0); + Output::send(SYSSTR("UObjectBase::{} = 0x{:X}\n"), item, offset); + Unreal::UObjectBase::VTableLayoutMap.emplace(item_ue, offset); + }); Output::send(SYSSTR("UObjectBaseUtility\n")); - uint32_t uobjectbaseutility_size = retrieve_vtable_layout_from_ini(SYSSTR("UObjectBaseUtility"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { - uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size); - Output::send(SYSSTR("UObjectBaseUtility::{} = 0x{:X}\n"), item, offset); - Unreal::UObjectBaseUtility::VTableLayoutMap.emplace(item_ue, offset); - }); + uint32_t uobjectbaseutility_size = + retrieve_vtable_layout_from_ini(SYSSTR("UObjectBaseUtility"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { + uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size); + Output::send(SYSSTR("UObjectBaseUtility::{} = 0x{:X}\n"), item, offset); + Unreal::UObjectBaseUtility::VTableLayoutMap.emplace(item_ue, offset); + }); Output::send(SYSSTR("UObject\n")); uint32_t uobject_size = retrieve_vtable_layout_from_ini(SYSSTR("UObject"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { @@ -756,11 +761,12 @@ namespace RC }); Output::send(SYSSTR("AGameModeBase\n")); - uint32_t agamemodebase_size = retrieve_vtable_layout_from_ini(SYSSTR("AGameModeBase"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { - uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size, aactor_size); - Output::send(SYSSTR("AGameModeBase::{} = 0x{:X}\n"), item, offset); - Unreal::AGameModeBase::VTableLayoutMap.emplace(item_ue, offset); - }); + uint32_t agamemodebase_size = + retrieve_vtable_layout_from_ini(SYSSTR("AGameModeBase"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { + uint32_t offset = calculate_virtual_function_offset(index, uobjectbase_size, uobjectbaseutility_size, uobject_size, aactor_size); + Output::send(SYSSTR("AGameModeBase::{} = 0x{:X}\n"), item, offset); + Unreal::AGameModeBase::VTableLayoutMap.emplace(item_ue, offset); + }); Output::send(SYSSTR("AGameMode\n")); retrieve_vtable_layout_from_ini(SYSSTR("AGameMode"), [&](uint32_t index, SystemStringType& item, UEStringType& item_ue) { @@ -795,11 +801,11 @@ namespace RC file.close(); } - + fprintf(stderr, "Loading offset done\n"); }); - fprintf(stderr, "Setting hooks\n"); + fprintf(stderr, "Setting hooks\n"); config.bHookProcessInternal = settings_manager.Hooks.HookProcessInternal; config.bHookProcessLocalScriptFunction = settings_manager.Hooks.HookProcessLocalScriptFunction; config.bHookLoadMap = settings_manager.Hooks.HookLoadMap; @@ -909,19 +915,18 @@ namespace RC SYSSTR("FAssetData not available in <4.17, ignoring 'LoadAllAssetsBeforeDumpingObjects' & 'LoadAllAssetsBeforeGeneratingCXXHeaders'.")); } - #ifdef HAS_INPUT - if (! settings_manager.General.InputSource.empty()) - { - if (m_input_handler.set_input_source(to_string(settings_manager.General.InputSource))) + if (!settings_manager.General.InputSource.empty()) { - Output::send(SYSSTR("Input source set to: {}\n"), m_input_handler.get_current_input_source()); - } - else - { - Output::send(SYSSTR("Failed to set input source to: {}\n"), settings_manager.General.InputSource); + if (m_input_handler.set_input_source(to_string(settings_manager.General.InputSource))) + { + Output::send(SYSSTR("Input source set to: {}\n"), m_input_handler.get_current_input_source()); + } + else + { + Output::send(SYSSTR("Failed to set input source to: {}\n"), settings_manager.General.InputSource); + } } - } #endif install_lua_mods(); @@ -1080,10 +1085,12 @@ namespace RC // Create the mod but don't install it yet auto scripts_directory = File::get_path_if_exists(sub_directory.path(), "Scripts"); auto dlls_directory = File::get_path_if_exists(sub_directory.path(), "dlls"); - if (scripts_directory) { + if (scripts_directory) + { m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); } - if (dlls_directory) { + if (dlls_directory) + { m_mods.emplace_back(std::make_unique(*this, to_system_string(sub_directory.path().stem()), to_system_string(sub_directory.path()))); } } @@ -1204,7 +1211,7 @@ namespace RC else { // 'mods.txt' exists, lets parse it - SystemStreamType mods_stream{ *enabled_mods_file}; + SystemStreamType mods_stream{*enabled_mods_file}; SystemStringType current_line; while (std::getline(mods_stream, current_line)) @@ -1326,7 +1333,7 @@ namespace RC auto UE4SSProgram::uninstall_mods() -> void { ProfilerScope(); - + std::vector cpp_mods{}; std::vector lua_mods{}; for (auto& mod : m_mods) @@ -1335,8 +1342,7 @@ namespace RC { cpp_mods.emplace_back(cpp_mod); } - else - if (auto lua_mod = dynamic_cast(mod.get()); lua_mod) + else if (auto lua_mod = dynamic_cast(mod.get()); lua_mod) { lua_mods.emplace_back(lua_mod); } @@ -1371,8 +1377,8 @@ namespace RC uninstall_mods(); - // Remove key binds that were set from Lua scripts - #ifdef HAS_INPUT +// Remove key binds that were set from Lua scripts +#ifdef HAS_INPUT m_input_handler.get_events_safe([&](Input::KeySet& input_event) -> void { for (auto& [key, vector_of_key_data] : input_event.key_data) { @@ -1391,7 +1397,7 @@ namespace RC }); } }); - #endif +#endif // Remove all custom properties // Uncomment when custom properties are working diff --git a/UE4SS/src/USMapGenerator/Generator.cpp b/UE4SS/src/USMapGenerator/Generator.cpp index 4d231eb09..d1e783ec3 100644 --- a/UE4SS/src/USMapGenerator/Generator.cpp +++ b/UE4SS/src/USMapGenerator/Generator.cpp @@ -203,7 +203,7 @@ namespace RC::OutTheShade auto generate_usmap() -> void { Output::send(SYSSTR("Mappings Generator by OutTheShade\nAttempting to dump mappings...\nPort of https://github.com/OutTheShade/UnrealMappingsDumper " - "Commit SHA 4da8c66\n")); + "Commit SHA 4da8c66\n")); StreamWriter Buffer; std::unordered_map NameMap; diff --git a/UVTD/include/UVTD/Helpers.hpp b/UVTD/include/UVTD/Helpers.hpp index 327785576..ba9ab4377 100644 --- a/UVTD/include/UVTD/Helpers.hpp +++ b/UVTD/include/UVTD/Helpers.hpp @@ -124,62 +124,62 @@ namespace RC::UVTD }; static inline std::unordered_set s_valid_udt_names{STR("UScriptStruct::ICppStructOps"), - STR("UObjectBase"), - STR("UObjectBaseUtility"), - STR("UObject"), - STR("UStruct"), - STR("UGameViewportClient"), - STR("UScriptStruct"), - STR("FOutputDevice"), - // STR("UConsole"), - STR("FMalloc"), - STR("FArchive"), - STR("FArchiveState"), - STR("AGameModeBase"), - STR("AGameMode"), - STR("AActor"), - STR("AHUD"), - STR("UPlayer"), - STR("ULocalPlayer"), - STR("FExec"), - STR("UField"), - STR("FField"), - STR("FProperty"), - STR("UProperty"), - STR("FNumericProperty"), - STR("UNumericProperty"), - STR("FMulticastDelegateProperty"), - STR("UMulticastDelegateProperty"), - STR("FObjectPropertyBase"), - STR("UObjectPropertyBase"), - STR("UStructProperty"), - STR("FStructProperty"), - STR("UArrayProperty"), - STR("FArrayProperty"), - STR("UMapProperty"), - STR("FMapProperty"), - STR("UWorld"), - STR("UFunction"), - STR("FBoolProperty"), - STR("UClass"), - STR("UEnum"), - STR("UBoolProperty"), - STR("FByteProperty"), - STR("UByteProperty"), - STR("FEnumProperty"), - STR("UEnumProperty"), - STR("FClassProperty"), - STR("UClassProperty"), - STR("FSoftClassProperty"), - STR("USoftClassProperty"), - STR("FDelegateProperty"), - STR("UDelegateProperty"), - STR("FInterfaceProperty"), - STR("UInterfaceProperty"), - STR("FFieldPathProperty"), - STR("FSetProperty"), - STR("USetProperty"), - STR("FFrame")}; + STR("UObjectBase"), + STR("UObjectBaseUtility"), + STR("UObject"), + STR("UStruct"), + STR("UGameViewportClient"), + STR("UScriptStruct"), + STR("FOutputDevice"), + // STR("UConsole"), + STR("FMalloc"), + STR("FArchive"), + STR("FArchiveState"), + STR("AGameModeBase"), + STR("AGameMode"), + STR("AActor"), + STR("AHUD"), + STR("UPlayer"), + STR("ULocalPlayer"), + STR("FExec"), + STR("UField"), + STR("FField"), + STR("FProperty"), + STR("UProperty"), + STR("FNumericProperty"), + STR("UNumericProperty"), + STR("FMulticastDelegateProperty"), + STR("UMulticastDelegateProperty"), + STR("FObjectPropertyBase"), + STR("UObjectPropertyBase"), + STR("UStructProperty"), + STR("FStructProperty"), + STR("UArrayProperty"), + STR("FArrayProperty"), + STR("UMapProperty"), + STR("FMapProperty"), + STR("UWorld"), + STR("UFunction"), + STR("FBoolProperty"), + STR("UClass"), + STR("UEnum"), + STR("UBoolProperty"), + STR("FByteProperty"), + STR("UByteProperty"), + STR("FEnumProperty"), + STR("UEnumProperty"), + STR("FClassProperty"), + STR("UClassProperty"), + STR("FSoftClassProperty"), + STR("USoftClassProperty"), + STR("FDelegateProperty"), + STR("UDelegateProperty"), + STR("FInterfaceProperty"), + STR("UInterfaceProperty"), + STR("FFieldPathProperty"), + STR("FSetProperty"), + STR("USetProperty"), + STR("FFrame")}; static inline std::vector s_uprefix_to_fprefix{ STR("UProperty"), diff --git a/UVTD/include/UVTD/Symbols.hpp b/UVTD/include/UVTD/Symbols.hpp index fece2ba2d..4c1797b58 100644 --- a/UVTD/include/UVTD/Symbols.hpp +++ b/UVTD/include/UVTD/Symbols.hpp @@ -8,8 +8,8 @@ #include -#include #include +#include #include #include diff --git a/UVTD/src/Helpers.cpp b/UVTD/src/Helpers.cpp index 85f60db03..8f8baff47 100644 --- a/UVTD/src/Helpers.cpp +++ b/UVTD/src/Helpers.cpp @@ -34,7 +34,8 @@ namespace RC::UVTD out_variable_type.replace(fixed_uobject_array_pos, fixed_uobject_array_string.length(), STR("TUObjectArray")); return true; } - else if (auto chunked_fixed_uobject_array_pos = out_variable_type.find(chunked_fixed_uobject_array_string); chunked_fixed_uobject_array_pos != out_variable_type.npos) + else if (auto chunked_fixed_uobject_array_pos = out_variable_type.find(chunked_fixed_uobject_array_string); + chunked_fixed_uobject_array_pos != out_variable_type.npos) { out_variable_type.replace(chunked_fixed_uobject_array_pos, chunked_fixed_uobject_array_string.length(), STR("TUObjectArray")); return true; diff --git a/UVTD/src/MemberVarsWrapperGenerator.cpp b/UVTD/src/MemberVarsWrapperGenerator.cpp index cb341c924..854ccc662 100644 --- a/UVTD/src/MemberVarsWrapperGenerator.cpp +++ b/UVTD/src/MemberVarsWrapperGenerator.cpp @@ -38,8 +38,8 @@ namespace RC::UVTD return SystemStringType{string}; }); - auto wrapper_src_file = - member_variable_layouts_gen_output_include_path / std::format(SYSSTR("MemberVariableLayout_SrcWrapper_{}.hpp"), class_entry.class_name_clean); + auto wrapper_src_file = member_variable_layouts_gen_output_include_path / + std::format(SYSSTR("MemberVariableLayout_SrcWrapper_{}.hpp"), class_entry.class_name_clean); Output::send(SYSSTR("Generating file '{}'\n"), wrapper_src_file.wstring()); @@ -151,9 +151,7 @@ namespace RC::UVTD wrapper_src_dumper.send(STR("}\n\n")); } - macro_setter_dumper.send(STR("if (auto val = parser.get_int64(STR(\"{}\"), STR(\"{}\"), -1); val != -1)\n"), - final_class_name, - final_variable_name); + macro_setter_dumper.send(STR("if (auto val = parser.get_int64(STR(\"{}\"), STR(\"{}\"), -1); val != -1)\n"), final_class_name, final_variable_name); macro_setter_dumper.send(STR(" Unreal::{}::MemberOffsets.emplace(STR(\"{}\"), static_cast(val));\n"), final_class_name, final_variable_name); diff --git a/UVTD/src/Symbols.cpp b/UVTD/src/Symbols.cpp index c9c320767..13fd5d233 100644 --- a/UVTD/src/Symbols.cpp +++ b/UVTD/src/Symbols.cpp @@ -254,7 +254,7 @@ namespace RC::UVTD for (size_t i = 0; i < record->data.LF_ARGLIST.count; i++) { bool should_add_comma = i < record->data.LF_ARGLIST.count - 1; - //args.append(std::format(SYSSTR("{}{}"), get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true), should_add_comma ? STR(", ") : STR(""))); + // args.append(std::format(SYSSTR("{}{}"), get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true), should_add_comma ? STR(", ") : STR(""))); args.append(get_type_name(tpi_stream, record->data.LF_ARGLIST.arg[i], true) + (should_add_comma ? STR(", ") : STR(""))); } diff --git a/UVTD/src/TypeContainer.cpp b/UVTD/src/TypeContainer.cpp index 242fc762e..dec0bba6c 100644 --- a/UVTD/src/TypeContainer.cpp +++ b/UVTD/src/TypeContainer.cpp @@ -21,22 +21,18 @@ namespace RC::UVTD } } - auto TypeContainer::get_or_create_class_entry(const UEStringType& symbol_name, const UEStringType& symbol_name_clean, const SymbolNameInfo& name_info) - -> Class& + auto TypeContainer::get_or_create_class_entry(const UEStringType& symbol_name, const UEStringType& symbol_name_clean, const SymbolNameInfo& name_info) -> Class& { - auto& class_entry = [&]() -> auto& - { + auto& class_entry = [&]() -> auto& { if (auto it = class_entries.find(symbol_name); it != class_entries.end()) { return it->second; } else { - return class_entries.emplace(symbol_name_clean, Class{.class_name = UEStringType{symbol_name}, .class_name_clean = symbol_name_clean}) - .first->second; + return class_entries.emplace(symbol_name_clean, Class{.class_name = UEStringType{symbol_name}, .class_name_clean = symbol_name_clean}).first->second; } - } - (); + }(); class_entry.valid_for_member_vars = name_info.valid_for_member_vars; class_entry.valid_for_vtable = name_info.valid_for_vtable; diff --git a/UVTD/src/UVTD.cpp b/UVTD/src/UVTD.cpp index 32817de0b..52464c910 100644 --- a/UVTD/src/UVTD.cpp +++ b/UVTD/src/UVTD.cpp @@ -25,7 +25,7 @@ namespace RC::UVTD { bool processing_events{false}; - Input::Handler input_handler {}; + Input::Handler input_handler{}; auto static event_loop_update() -> void { diff --git a/UVTD/src/VTableDumper.cpp b/UVTD/src/VTableDumper.cpp index 1e060ac2d..6b94bd71c 100644 --- a/UVTD/src/VTableDumper.cpp +++ b/UVTD/src/VTableDumper.cpp @@ -203,7 +203,10 @@ namespace RC::UVTD function_entry.name, local_class_name); function_body_dumper.send(SYSSTR("{\n")); - function_body_dumper.send(SYSSTR(" {}::VTableLayoutMap.emplace(STR(\"{}\"), 0x{:X});\n"), local_class_name, function_entry.name, function_entry.offset); + function_body_dumper.send(SYSSTR(" {}::VTableLayoutMap.emplace(STR(\"{}\"), 0x{:X});\n"), + local_class_name, + function_entry.name, + function_entry.offset); function_body_dumper.send(SYSSTR("}\n\n")); } } diff --git a/deps/first/ASMHelper/include/ASMHelper/Common.hpp b/deps/first/ASMHelper/include/ASMHelper/Common.hpp index 58638eef5..c65782a06 100644 --- a/deps/first/ASMHelper/include/ASMHelper/Common.hpp +++ b/deps/first/ASMHelper/include/ASMHelper/Common.hpp @@ -24,4 +24,3 @@ #endif #endif - diff --git a/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp b/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp index 78bbc59d8..cf921b6aa 100644 --- a/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp +++ b/deps/first/Constructs/include/Constructs/Views/EnumerateView.hpp @@ -161,7 +161,6 @@ namespace RC } } // namespace RC - #else #include @@ -169,16 +168,18 @@ namespace RC // A simple enumerate impl for clang to avoid https://github.com/llvm/llvm-project/issues/60704 namespace RC { - + namespace views { template - struct internal_enumerate { + struct internal_enumerate + { T& iterable; size_t index; - - template - struct iterator : std::iterator> { + + template + struct iterator : std::iterator> + { using iterator_category = std::input_iterator_tag; using value_type = std::pair; using difference_type = std::ptrdiff_t; @@ -188,52 +189,66 @@ namespace RC size_t index; It iter; - explicit iterator(size_t index, It iter) : index(index), iter(iter) {} + explicit iterator(size_t index, It iter) : index(index), iter(iter) + { + } - iterator& operator++() { + iterator& operator++() + { ++index; ++iter; return *this; } - bool operator!=(const iterator& other) const { + bool operator!=(const iterator& other) const + { return iter != other.iter; } - value_type operator*() const { + value_type operator*() const + { return {*iter, index}; } }; - auto begin() { + auto begin() + { return iterator>(0, iterable.begin()); } - auto end() { + auto end() + { return iterator>(0, iterable.end()); } - explicit internal_enumerate(T& iterable) : iterable(iterable), index(0) {} + explicit internal_enumerate(T& iterable) : iterable(iterable), index(0) + { + } - internal_enumerate operator | (T& iterable) { + internal_enumerate operator|(T& iterable) + { return internal_enumerate(iterable); } }; - struct enumerate_op {}; + struct enumerate_op + { + }; // operator | template - internal_enumerate operator | (T& iterable, enumerate_op) { + internal_enumerate operator|(T& iterable, enumerate_op) + { return internal_enumerate(iterable); } // T&& version template - internal_enumerate operator | (T&& iterable, enumerate_op) { + internal_enumerate operator|(T&& iterable, enumerate_op) + { return internal_enumerate(iterable); } inline constexpr enumerate_op enumerate; - }; + }; // namespace views } // namespace RC #endif // __clang__ diff --git a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp index 59a52419a..69a77d747 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp @@ -30,7 +30,6 @@ #endif #endif - namespace RC::Output { template @@ -124,7 +123,7 @@ namespace RC::Output { THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } - + for (const auto& device : m_opened_devices) { ASSERT_OUTPUT_DEVICE_IS_VALID(device) diff --git a/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp b/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp index c10b6fd9b..01859086e 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/TestDevice.hpp @@ -63,7 +63,7 @@ namespace RC::Output } #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE - printf_s("TestDevice received: "SystemStringPrint, fmt.c_str()); + printf_s("TestDevice received: " SystemStringPrint, fmt.c_str()); #else printf_s(SystemStringPrint, fmt.data()); #endif diff --git a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp index 5ac4b8471..06322c1d7 100644 --- a/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp +++ b/deps/first/DynamicOutput/src/DebugConsoleDevice.cpp @@ -39,7 +39,7 @@ namespace RC::Output return "\033[0;0m"; } - #ifdef WIN32 +#ifdef WIN32 auto DebugConsoleDevice::set_windows_console_out_mode_if_needed() const -> void { if (m_windows_console_mode_set) @@ -55,7 +55,7 @@ namespace RC::Output } m_windows_console_mode_set = true; } - #endif +#endif auto DebugConsoleDevice::has_optional_arg() const -> bool { @@ -69,18 +69,18 @@ namespace RC::Output auto DebugConsoleDevice::receive_with_optional_arg(SystemStringViewType fmt, [[maybe_unused]] int32_t optional_arg) const -> void { - #ifdef WIN32 +#ifdef WIN32 set_windows_console_out_mode_if_needed(); - #endif +#endif #if ENABLE_OUTPUT_DEVICE_DEBUG_MODE printf_s("DebugConsoleDevice received: %S", m_formatter(fmt).c_str()); #else #ifdef WIN32 - printf_s("%s" SystemStringPrint"\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); + printf_s("%s" SystemStringPrint "\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); #else - fprintf(stderr, "%s" SystemStringPrint"\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); - + fprintf(stderr, "%s" SystemStringPrint "\033[0m", log_level_to_color(static_cast(optional_arg)).c_str(), m_formatter(fmt).c_str()); + #endif #endif } diff --git a/deps/first/File/include/File/File.hpp b/deps/first/File/include/File/File.hpp index 6b6dee62b..9f5049dbc 100644 --- a/deps/first/File/include/File/File.hpp +++ b/deps/first/File/include/File/File.hpp @@ -14,8 +14,7 @@ namespace RC::File RC_FILE_API auto delete_file(const std::filesystem::path& file_path_and_name) -> void; - - // Search a path that can access `base / tail`, where the tail part is allowed to be case insensitive. + // Search a path that can access `base / tail`, where the tail part is allowed to be case insensitive. // Returns the path found or std::nullopt if no path was found. RC_FILE_API auto get_path_if_exists(const std::filesystem::path& base, const std::filesystem::path& tail) -> std::optional; } // namespace RC::File diff --git a/deps/first/File/include/File/FileType/FileBase.hpp b/deps/first/File/include/File/FileType/FileBase.hpp index 09568f101..51332e3a7 100644 --- a/deps/first/File/include/File/FileType/FileBase.hpp +++ b/deps/first/File/include/File/FileType/FileBase.hpp @@ -94,7 +94,6 @@ namespace RC::File auto static open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> InternalFileType; */ - // Write a string to the currently opened file // Throws std::runtime_error if an error occurred // This is the actual function uses StringType. diff --git a/deps/first/File/include/File/FileType/StdFile.hpp b/deps/first/File/include/File/FileType/StdFile.hpp index adbf8886a..b44e98deb 100644 --- a/deps/first/File/include/File/FileType/StdFile.hpp +++ b/deps/first/File/include/File/FileType/StdFile.hpp @@ -20,7 +20,9 @@ namespace RC::File struct IdentifyingProperties { - struct stat file_stat{}; + struct stat file_stat + { + }; }; private: @@ -43,8 +45,8 @@ namespace RC::File private: auto static create_all_directories(const std::filesystem::path& file_name_and_path) -> void; - auto static calc_open_flags(const std::filesystem::path &file_name_and_path, const OpenProperties& open_properties) -> int; - + auto static calc_open_flags(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> int; + private: auto close_file() -> void; diff --git a/deps/first/File/include/File/Macros.hpp b/deps/first/File/include/File/Macros.hpp index 16499700c..c8db3fd0c 100644 --- a/deps/first/File/include/File/Macros.hpp +++ b/deps/first/File/include/File/Macros.hpp @@ -53,28 +53,28 @@ namespace RC::File using StreamType = std::ifstream; using IStreamType = std::ifstream; using OStreamType = std::ofstream; -/* -#if RC_IS_ANSI == 1 - using StringType = std::string; - using StringViewType = std::string_view; - using CharType = char; - using StreamType = std::ifstream; -#else -// System String Types -#ifdef WIN32 - using StringType = std::wstring; - using StringViewType = std::wstring_view; - using CharType = std::wstring::value_type; - using StreamType = std::wifstream; -#else - // on linux, use utf8 - using StringType = std::string; - using StringViewType = std::string_view; - using CharType = char; - using StreamType = std::ifstream; -#endif // WIN32 -#endif // RC_IS_ANSI -*/ + /* + #if RC_IS_ANSI == 1 + using StringType = std::string; + using StringViewType = std::string_view; + using CharType = char; + using StreamType = std::ifstream; + #else + // System String Types + #ifdef WIN32 + using StringType = std::wstring; + using StringViewType = std::wstring_view; + using CharType = std::wstring::value_type; + using StreamType = std::wifstream; + #else + // on linux, use utf8 + using StringType = std::string; + using StringViewType = std::string_view; + using CharType = char; + using StreamType = std::ifstream; + #endif // WIN32 + #endif // RC_IS_ANSI + */ } // namespace RC::File namespace RC diff --git a/deps/first/File/src/File.cpp b/deps/first/File/src/File.cpp index 4a2356356..5f2bd8103 100644 --- a/deps/first/File/src/File.cpp +++ b/deps/first/File/src/File.cpp @@ -30,7 +30,7 @@ namespace RC::File Handle::FileType::delete_file(file_path_and_name); } - auto get_path_if_exists(const std::filesystem::path& base, const std::filesystem::path& tail) -> std::optional + auto get_path_if_exists(const std::filesystem::path& base, const std::filesystem::path& tail) -> std::optional { if (!std::filesystem::exists(base)) { @@ -44,7 +44,7 @@ namespace RC::File auto full_path = base.lexically_normal(); for (const auto& part : normalized_tail) { - if (std::filesystem::exists(full_path / part)) + if (std::filesystem::exists(full_path / part)) { full_path /= part; } diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index 5a7cab89f..7d9425691 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -29,11 +29,11 @@ namespace RC::File } } - auto StdFile::calc_open_flags(const std::filesystem::path &file_name_and_path, const OpenProperties& open_properties) -> int + auto StdFile::calc_open_flags(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> int { - int flags {}; - int rwflags {}; + int flags{}; + int rwflags{}; switch (open_properties.open_for) { case OpenFor::Writing: @@ -51,7 +51,8 @@ namespace RC::File THROW_INTERNAL_FILE_ERROR("[StdFile::open_file] Tried to open file but received invalid data for the 'OpenFor' parameter.") } - if (open_properties.overwrite_existing_file == OverwriteExistingFile::Yes) { + if (open_properties.overwrite_existing_file == OverwriteExistingFile::Yes) + { flags |= O_CREAT | O_TRUNC; if (rwflags == O_RDONLY) { @@ -85,7 +86,8 @@ namespace RC::File return m_file > 0; } - auto StdFile::invalidate_file() noexcept -> void { + auto StdFile::invalidate_file() noexcept -> void + { m_file = 0; } @@ -109,7 +111,6 @@ namespace RC::File m_file = new_file; } - auto StdFile::get_file() -> HANDLE { return m_file; @@ -150,7 +151,8 @@ namespace RC::File } size_t bytes_written = write(file.get_file(), data, sizeof(DataType) * num_bytes_to_write); - if (bytes_written < 0) { + if (bytes_written < 0) + { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::write_to_file] Tried writing to file but was unable to complete operation. Error: {}", bytes_written)); } } @@ -163,7 +165,9 @@ namespace RC::File "'set_serialization_output_file'") } - struct stat file_info{}; + struct stat file_info + { + }; fstat(m_file, &file_info); serialize_item(GenericItemData{.data_type = GenericDataType::UnsignedLong, .data_ulong = file_info.st_dev}, true); @@ -177,7 +181,6 @@ namespace RC::File serialize_item(GenericItemData{.data_type = GenericDataType::SignedLong, .data_long = file_info.st_atime}, true); serialize_item(GenericItemData{.data_type = GenericDataType::SignedLong, .data_long = file_info.st_mtime}, true); serialize_item(GenericItemData{.data_type = GenericDataType::SignedLong, .data_long = file_info.st_ctime}, true); - } auto StdFile::deserialize_identifying_properties() -> void @@ -193,13 +196,13 @@ namespace RC::File m_identifying_properties.file_stat.st_atime = *static_cast(get_serialized_item(sizeof(signed long), true)); m_identifying_properties.file_stat.st_mtime = *static_cast(get_serialized_item(sizeof(signed long), true)); m_identifying_properties.file_stat.st_ctime = *static_cast(get_serialized_item(sizeof(signed long), true)); - m_offset_to_next_serialized_item = 11*8; + m_offset_to_next_serialized_item = 11 * 8; m_has_cached_identifying_properties = true; - } - auto StdFile::is_deserialized_and_live_equal() -> bool { + auto StdFile::is_deserialized_and_live_equal() -> bool + { if (!m_has_cached_identifying_properties) { if (!std::filesystem::exists(m_serialization_file_path_and_name)) @@ -235,7 +238,6 @@ namespace RC::File write_to_file(output_file.get_underlying_type(), &data, sizeof(DataType)); } - auto StdFile::serialize_item(const GenericItemData& data, bool is_internal_item) -> void { if (m_serialization_file_path_and_name.empty()) @@ -276,7 +278,6 @@ namespace RC::File serialization_file.close(); } - auto StdFile::get_serialized_item(size_t data_size, bool is_internal_item) -> void* { if (!m_has_cache_in_memory) @@ -351,16 +352,19 @@ namespace RC::File { return m_is_file_open; } - + auto StdFile::write_string_to_file(UEStringViewType string_to_write) -> void - { + { try { static std::wstring_convert, char16_t> converter{}; auto utf8_string = converter.to_bytes(string_to_write.begin(), string_to_write.begin() + string_to_write.size()); write_file_string_to_file(utf8_string); - } catch (const std::exception& e) { - THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::write_string_to_file] Tried writing string to file but could not convert to utf-8. Error: {}", e.what())) + } + catch (const std::exception& e) + { + THROW_INTERNAL_FILE_ERROR( + std::format("[StdFile::write_string_to_file] Tried writing string to file but could not convert to utf-8. Error: {}", e.what())) } } @@ -379,13 +383,17 @@ namespace RC::File auto StdFile::is_same_as(StdFile& other_file) -> bool { - struct stat file_info{}; + struct stat file_info + { + }; if (fstat(m_file, &file_info) != 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::is_same_as] Tried retrieving file information by handle. Error: {}", errno)) } - struct stat other_file_info{}; + struct stat other_file_info + { + }; if (fstat(other_file.get_file(), &other_file_info) != 0) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::is_same_as] Tried retrieving file information by handle. Error: {}", errno)) @@ -504,20 +512,19 @@ namespace RC::File auto original_position = lseek(m_file, 0, SEEK_CUR); auto file_size = lseek(m_file, 0, SEEK_END); lseek(m_file, original_position, SEEK_SET); - + auto res = mmap(nullptr, file_size, flags, MAP_SHARED, m_file, 0); - if (res == (void*) -1) + if (res == (void*)-1) { THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::memory_map] Tried to memory map file but 'mmap' returned error: {}", errno)) } - m_memory_map = (uint8_t*) res; + m_memory_map = (uint8_t*)res; m_memory_map_size = file_size; return std::span(m_memory_map, file_size); } - auto StdFile::open_file(const std::filesystem::path& file_name_and_path, const OpenProperties& open_properties) -> StdFile { // Reminder: std::filesystem::canonical() will get the full path & file name on the drive @@ -545,11 +552,10 @@ namespace RC::File std::string_view open_type = open_properties.open_for == OpenFor::Writing || open_properties.open_for == OpenFor::Appending ? "writing" : "reading"; fprintf(stderr, "open file %s failed, error: %d\n", file_name_and_path.string().c_str(), errno); - THROW_INTERNAL_FILE_ERROR( - std::format("[StdFile::open_file] Tried opening file for {} but encountered an error. Path & File: {} | errno = {}\n", - open_type, - file_name_and_path.string(), - errno)) + THROW_INTERNAL_FILE_ERROR(std::format("[StdFile::open_file] Tried opening file for {} but encountered an error. Path & File: {} | errno = {}\n", + open_type, + file_name_and_path.string(), + errno)) } file.m_file_path_and_name = file_name_and_path; @@ -558,4 +564,4 @@ namespace RC::File return file; } -} +} // namespace RC::File diff --git a/deps/first/File/src/FileType/WinFile.cpp b/deps/first/File/src/FileType/WinFile.cpp index 2e573c9e6..d626da606 100644 --- a/deps/first/File/src/FileType/WinFile.cpp +++ b/deps/first/File/src/FileType/WinFile.cpp @@ -399,7 +399,6 @@ namespace RC::File write_to_file(*this, string_converted_to_utf8.c_str(), string_size); } - auto WinFile::write_file_string_to_file(StringViewType string_to_write) -> void { write_to_file(*this, string_to_write.data(), string_to_write.length()); @@ -462,18 +461,18 @@ namespace RC::File { auto file_contents = read_file_all(); int string_size = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)file_contents.c_str(), static_cast(file_contents.size()), NULL, 0); - if (string_size == 0) - { - THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_all] Tried reading entire file but could not convert to utf-16. Error: {}", GetLastError())) - } + if (string_size == 0) + { + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_all] Tried reading entire file but could not convert to utf-16. Error: {}", GetLastError())) + } - UEStringType string_converted_to_utf16(string_size, 0); + UEStringType string_converted_to_utf16(string_size, 0); if (MultiByteToWideChar(CP_UTF8, 0, (LPCCH)file_contents.c_str(), static_cast(file_contents.size()), &string_converted_to_utf16[0], string_size) == 0) - { - THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_all] Tried reading entire file but could not convert to utf-16. Error: {}", GetLastError())) - } + { + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_all] Tried reading entire file but could not convert to utf-16. Error: {}", GetLastError())) + } - return string_converted_to_utf16; + return string_converted_to_utf16; } auto WinFile::read_file_all() const -> StringType @@ -510,15 +509,15 @@ namespace RC::File { // try restoring file pointer SetFilePointer(handle, file_pointer, nullptr, FILE_BEGIN); - THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not read BOM. Error: {}", GetLastError())) - } + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not read BOM. Error: {}", GetLastError())) + } if (bom[0] == '\xEF' && bom[1] == '\xBB' && bom[2] == '\xBF') - { + { file_size -= 3; - } + } else { - // roll back + // roll back SetFilePointer(handle, 0, nullptr, FILE_BEGIN); } } @@ -526,17 +525,17 @@ namespace RC::File StringType file_contents(file_size, 0); DWORD bytes_read{}; if (!ReadFile(handle, &file_contents[0], file_size, &bytes_read, nullptr)) - { + { // try restoring file pointer SetFilePointer(handle, file_pointer, nullptr, FILE_BEGIN); - THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not read file contents. Error: {}", GetLastError())) - } + THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::read_file_all] Tried reading entire file but could not read file contents. Error: {}", GetLastError())) + } - file_contents[bytes_read] = 0; + file_contents[bytes_read] = 0; // restore file pointer SetFilePointer(handle, file_pointer, nullptr, FILE_BEGIN); - return file_contents; + return file_contents; } auto WinFile::memory_map() -> std::span diff --git a/deps/first/Helpers/include/Helpers/Casting.hpp b/deps/first/Helpers/include/Helpers/Casting.hpp index 05d5cf8df..3fbd4e3be 100644 --- a/deps/first/Helpers/include/Helpers/Casting.hpp +++ b/deps/first/Helpers/include/Helpers/Casting.hpp @@ -75,7 +75,7 @@ namespace RC::Helper::Casting return ptr_cast_deref_safe(base_ptr, offset, process_handle); } #else -// use process_vm_readv + // use process_vm_readv template auto ptr_cast_deref_safe(From ptr, int32_t offset, pid_t process_handle) -> To { @@ -101,7 +101,6 @@ namespace RC::Helper::Casting { return *data_ptr; } - } // Compatibility with older code from before 'ptr_cast' existed diff --git a/deps/first/Helpers/include/Helpers/Format.hpp b/deps/first/Helpers/include/Helpers/Format.hpp index c06528b89..ad07b76cb 100644 --- a/deps/first/Helpers/include/Helpers/Format.hpp +++ b/deps/first/Helpers/include/Helpers/Format.hpp @@ -16,4 +16,4 @@ namespace RC { return std::vformat(std::forward(fmt), std::make_format_args(to_file(std::forward(fmt_args))...)); } -} \ No newline at end of file +} // namespace RC \ No newline at end of file diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index fc91baf72..c9a4790bf 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -210,41 +210,40 @@ namespace RC // No occurrence was found, returning empty string for now return {}; } - /* explode_by_occurrence -> END */ - - // ----------------------------- // - #define STRING_DISPATCH(STRING_T, ts, tw, tu16) \ - if constexpr (std::is_same_v) \ - { \ - return ts(std::forward(input)); \ - } \ - else if constexpr (std::is_same_v) \ - { \ - return tw(std::forward(input)); \ - } \ - else if constexpr (std::is_same_v) \ - { \ - return tu16(std::forward(input)); \ - } \ - else \ - { \ - static_assert(dependent_false::value, "Unsupported " #STRING_T "."); \ - } - // ----------------------------- // - #define PATH_QUIRK(STRINGT) \ - if constexpr (std::is_same_v, std::filesystem::path> \ - || std::is_same_v, const std::filesystem::path>) \ - { \ - STRING_DISPATCH(STRINGT, to_string_path, to_wstring_path, to_u16string_path); \ - } +/* explode_by_occurrence -> END */ + +// ----------------------------- // +#define STRING_DISPATCH(STRING_T, ts, tw, tu16) \ + if constexpr (std::is_same_v) \ + { \ + return ts(std::forward(input)); \ + } \ + else if constexpr (std::is_same_v) \ + { \ + return tw(std::forward(input)); \ + } \ + else if constexpr (std::is_same_v) \ + { \ + return tu16(std::forward(input)); \ + } \ + else \ + { \ + static_assert(dependent_false::value, "Unsupported " #STRING_T "."); \ + } +// ----------------------------- // +#define PATH_QUIRK(STRINGT) \ + if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) \ + { \ + STRING_DISPATCH(STRINGT, to_string_path, to_wstring_path, to_u16string_path); \ + } // ----------------------------- // - #define TO_STRING_QUIRK_DISPATCH(STRINGT) \ - PATH_QUIRK(STRINGT) \ - else \ - { \ - STRING_DISPATCH(STRINGT, to_string, to_wstring, to_u16string); \ - } +#define TO_STRING_QUIRK_DISPATCH(STRINGT) \ + PATH_QUIRK(STRINGT) \ + else \ + { \ + STRING_DISPATCH(STRINGT, to_string, to_wstring, to_u16string); \ + } // ----------------------------- // auto inline to_string_path(const std::filesystem::path& input) -> std::string @@ -307,7 +306,6 @@ namespace RC return std::wstring{input}; } - auto inline to_wstring(std::u16string& input) -> std::wstring { #ifdef WIN32 @@ -415,92 +413,152 @@ namespace RC } // Type traits to check if T is a string type that needs conversion - template - struct is_string_like_t : std::false_type {}; + template + struct is_string_like_t : std::false_type + { + }; // Specializations for the types that need conversion - template<> struct is_string_like_t : std::true_type {}; - template<> struct is_string_like_t : std::true_type {}; - template<> struct is_string_like_t : std::true_type {}; - template<> struct is_string_like_t : std::true_type {}; - template<> struct is_string_like_t : std::true_type {}; - template<> struct is_string_like_t : std::true_type {}; + template <> + struct is_string_like_t : std::true_type + { + }; + template <> + struct is_string_like_t : std::true_type + { + }; + template <> + struct is_string_like_t : std::true_type + { + }; + template <> + struct is_string_like_t : std::true_type + { + }; + template <> + struct is_string_like_t : std::true_type + { + }; + template <> + struct is_string_like_t : std::true_type + { + }; template - struct dependent_false : std::false_type {}; + struct dependent_false : std::false_type + { + }; template - struct dependent_ensure : std::true_type {}; + struct dependent_ensure : std::true_type + { + }; template - struct dependent_ensure : std::false_type {}; + struct dependent_ensure : std::false_type + { + }; template - auto stringviewify(T&& tp) { - if constexpr (std::is_same_v, char*> || std::is_same_v, const char*>) { + auto stringviewify(T&& tp) + { + if constexpr (std::is_same_v, char*> || std::is_same_v, const char*>) + { return std::string_view{tp}; - } else if constexpr (std::is_same_v, wchar_t*> || std::is_same_v, const wchar_t*>) { + } + else if constexpr (std::is_same_v, wchar_t*> || std::is_same_v, const wchar_t*>) + { return std::wstring_view{tp}; - } else if constexpr (std::is_same_v, char16_t*> || std::is_same_v, const char16_t*>) { + } + else if constexpr (std::is_same_v, char16_t*> || std::is_same_v, const char16_t*>) + { return std::u16string_view{tp}; - } else { + } + else + { return std::forward(tp); } } - template - struct _can_be_string_view_t : std::false_type {}; - template<> struct _can_be_string_view_t : std::true_type {}; - template<> struct _can_be_string_view_t : std::true_type {}; - template<> struct _can_be_string_view_t : std::true_type {}; - template<> struct _can_be_string_view_t : std::true_type {}; - template<> struct _can_be_string_view_t : std::true_type {}; - template<> struct _can_be_string_view_t : std::true_type {}; + template + struct _can_be_string_view_t : std::false_type + { + }; + template <> + struct _can_be_string_view_t : std::true_type + { + }; + template <> + struct _can_be_string_view_t : std::true_type + { + }; + template <> + struct _can_be_string_view_t : std::true_type + { + }; + template <> + struct _can_be_string_view_t : std::true_type + { + }; + template <> + struct _can_be_string_view_t : std::true_type + { + }; + template <> + struct _can_be_string_view_t : std::true_type + { + }; - template - struct can_be_string_view_t : _can_be_string_view_t> {}; + template + struct can_be_string_view_t : _can_be_string_view_t> + { + }; - template - struct is_file_string_type : std::disjunction< - std::is_same, - std::is_same - > {}; + template + struct is_file_string_type : std::disjunction, std::is_same> + { + }; - template - struct not_file_string_like_t : std::conjunction>, std::negation>>> {}; + template + struct not_file_string_like_t : std::conjunction>, std::negation>>> + { + }; template - auto inline to_file_string(T&& input) -> File::StringType { + auto inline to_file_string(T&& input) -> File::StringType + { TO_STRING_QUIRK_DISPATCH(File::StringType); } - template + template auto to_file(T&& arg) { if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) { return to_file_string(std::forward(arg)); } - else if constexpr (can_be_string_view_t::value) { + else if constexpr (can_be_string_view_t::value) + { return to_file(stringviewify(std::forward(arg))); - } - else if constexpr (not_file_string_like_t>::value) + } + else if constexpr (not_file_string_like_t>::value) { return to_file_string(std::forward(arg)); - } - else + } + else { return std::forward(arg); } } - + template struct is_std_string_type : std::disjunction, std::is_same> - {}; + { + }; template struct not_std_string_like_t : std::conjunction>, std::negation>>> - { }; - + { + }; template auto inline to_std_string(T&& input) -> std::string @@ -528,92 +586,99 @@ namespace RC return std::forward(arg); } } - - template - struct is_system_string_type : std::disjunction< - std::is_same, - std::is_same - > {}; - template - struct not_system_string_like_t : std::conjunction>,std::negation>>> {}; + template + struct is_system_string_type : std::disjunction, std::is_same> + { + }; + + template + struct not_system_string_like_t : std::conjunction>, std::negation>>> + { + }; template - auto inline to_system_string(T&& input) -> SystemStringType { + auto inline to_system_string(T&& input) -> SystemStringType + { TO_STRING_QUIRK_DISPATCH(SystemStringType); } - template - auto to_system(T&& arg) { + template + auto to_system(T&& arg) + { if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) { return to_system_string(std::forward(arg)); } - else - if constexpr (can_be_string_view_t::value) { + else if constexpr (can_be_string_view_t::value) + { return to_system(stringviewify(std::forward(arg))); - } - else if constexpr (not_system_string_like_t>::value) + } + else if constexpr (not_system_string_like_t>::value) { return to_system_string(std::forward(arg)); - } - else + } + else { return std::forward(arg); } } - template - struct is_ue_string_type : std::disjunction< - std::is_same, - std::is_same - > {}; + template + struct is_ue_string_type : std::disjunction, std::is_same> + { + }; - template - struct not_ue_string_like_t : std::conjunction>, std::negation>>> {}; + template + struct not_ue_string_like_t : std::conjunction>, std::negation>>> + { + }; template - auto inline to_ue_string(T&& input) -> UEStringType { + auto inline to_ue_string(T&& input) -> UEStringType + { TO_STRING_QUIRK_DISPATCH(UEStringType); } - template + template auto to_ue(T&& arg) { if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) { return to_ue_string(std::forward(arg)); } - else if constexpr (can_be_string_view_t::value) + else if constexpr (can_be_string_view_t::value) { return to_ue(stringviewify(std::forward(arg))); - } - else if constexpr (not_ue_string_like_t>::value) + } + else if constexpr (not_ue_string_like_t>::value) { return to_ue_string(std::forward(arg)); - } - else + } + else { return std::forward(arg); } } - template - struct is_lua_string_type : std::disjunction< - std::is_same, - std::is_same - > {}; + template + struct is_lua_string_type : std::disjunction, std::is_same> + { + }; - template - struct not_lua_string_like_t : std::negation>> {}; + template + struct not_lua_string_like_t : std::negation>> + { + }; - template - auto to_lua(T&& arg) { - if constexpr (can_be_string_view_t::value || not_lua_string_like_t>::value) + template + auto to_lua(T&& arg) + { + if constexpr (can_be_string_view_t::value || not_lua_string_like_t>::value) { return to_string(std::forward(arg)); - } - else + } + else { return std::forward(arg); } @@ -622,11 +687,11 @@ namespace RC // TODO: add an option to allow compile failure if to_XXXX failed. // e.g., to_ue -> must be able to convert to uestring, not passthrough. - #define csfor_lua(x) (to_lua((x)).c_str()) +#define csfor_lua(x) (to_lua((x)).c_str()) - #undef TO_STRING_QUIRK_DISPATCH - #undef PATH_QUIRK - #undef STRING_DISPATCH +#undef TO_STRING_QUIRK_DISPATCH +#undef PATH_QUIRK +#undef STRING_DISPATCH namespace String { diff --git a/deps/first/IniParser/src/Experimental.cpp b/deps/first/IniParser/src/Experimental.cpp index 8a5f01fcd..dd9855920 100644 --- a/deps/first/IniParser/src/Experimental.cpp +++ b/deps/first/IniParser/src/Experimental.cpp @@ -545,8 +545,9 @@ namespace RC::Parser::Experimental auto close_square_bracket_token = tc.add(Parser::Token::create(TokenType::ClosingSquareBracket, SYSSTR("CloseSquareBracket"), SYSSTR("]"))); - auto token = - Parser::Token::create(TokenType::OpeningSquareBracket, SYSSTR("OpenSquareBracket"), SYSSTR("[")); + auto token = Parser::Token::create(TokenType::OpeningSquareBracket, + SYSSTR("OpenSquareBracket"), + SYSSTR("[")); tc.add(std::move(token)); tc.add(Parser::Token::create(TokenType::SemiColon, SYSSTR("SemiColon"), SYSSTR(";"))); diff --git a/deps/first/Input/include/Input/Common.hpp b/deps/first/Input/include/Input/Common.hpp index 15451f69b..c2ab71801 100644 --- a/deps/first/Input/include/Input/Common.hpp +++ b/deps/first/Input/include/Input/Common.hpp @@ -27,4 +27,3 @@ #endif #endif - diff --git a/deps/first/Input/include/Input/Handler.hpp b/deps/first/Input/include/Input/Handler.hpp index ad80b6841..dcdd6ee9b 100644 --- a/deps/first/Input/include/Input/Handler.hpp +++ b/deps/first/Input/include/Input/Handler.hpp @@ -17,7 +17,7 @@ namespace RC::Input { using EventCallbackCallable = std::function; - + struct InputEvent { Key key; @@ -46,23 +46,23 @@ namespace RC::Input class RC_INPUT_API Handler { private: - //std::vector m_key_sets{}; + // std::vector m_key_sets{}; KeySet m_key_set{}; bool m_allow_input{true}; std::array m_subscribed_keys{}; - + std::shared_ptr m_platform_handler; std::mutex m_event_mutex; public: - Handler() {}; + Handler(){}; - // Input source and event processing + // Input source and event processing public: auto set_input_source(std::string source) -> bool; auto process_event() -> void; - // Interfaces for UE4SS and ModSystem for event registration + // Interfaces for UE4SS and ModSystem for event registration public: auto init() -> void; @@ -74,13 +74,16 @@ namespace RC::Input auto is_keydown_event_registered(Input::Key) -> bool; auto is_keydown_event_registered(Input::Key, const ModifierKeyArray&) -> bool; - - auto get_events_safe(std::function) -> void; + + auto get_events_safe(std::function) -> void; auto clear_subscribed_keys() -> void; auto has_event_on_key(Input::Key key) -> bool; - auto get_subscribed_keys() const -> const std::array& { return m_subscribed_keys; } - + auto get_subscribed_keys() const -> const std::array& + { + return m_subscribed_keys; + } + auto get_allow_input() -> bool; auto set_allow_input(bool new_value) -> void; @@ -89,11 +92,11 @@ namespace RC::Input private: static std::unordered_map> m_input_sources_store; static auto register_input_source(std::shared_ptr input_source) -> void; - + public: static auto get_input_source(std::string source) -> std::shared_ptr { - if (m_input_sources_store.find(source) != m_input_sources_store.end()) + if (m_input_sources_store.find(source) != m_input_sources_store.end()) { return m_input_sources_store[source]; } diff --git a/deps/first/Input/include/Input/KeyDef.hpp b/deps/first/Input/include/Input/KeyDef.hpp index 8aeff94c6..6c950ab5f 100644 --- a/deps/first/Input/include/Input/KeyDef.hpp +++ b/deps/first/Input/include/Input/KeyDef.hpp @@ -252,13 +252,13 @@ namespace RC::Input { /// SAFETY: This is a bitfield, following static_assert ensures that the bitfield is not larger than 32 bits uint32_t keys; - + // allow ops between keys - auto operator|(const ModifierKeys &key) -> ModifierKeys&; - auto operator|=(const ModifierKeys &key) -> ModifierKeys&; - auto operator|(const ModifierKey &key) -> ModifierKeys&; - auto operator|=(const ModifierKey &key) -> ModifierKeys&; + auto operator|(const ModifierKeys& key) -> ModifierKeys&; + auto operator|=(const ModifierKeys& key) -> ModifierKeys&; + auto operator|(const ModifierKey& key) -> ModifierKeys&; + auto operator|=(const ModifierKey& key) -> ModifierKeys&; auto operator==(const ModifierKeys& key) const -> bool; auto operator!=(const ModifierKeys& key) const -> bool; @@ -266,14 +266,13 @@ namespace RC::Input auto operator<(const ModifierKeys& key) const -> bool; auto operator>(const ModifierKeys& key) const -> bool; - ModifierKeys(const ModifierKey key) : keys{is_modify_key_valid(key) ? (1u << key) : 0} {}; ModifierKeys(const ModifierKeys& other) : keys{other.keys} {}; ModifierKeys() : keys{0} {}; - + template - ModifierKeys(ModifierKey key, Args... args) : keys{ (is_modify_key_valid(key) ? (1 << key) : 0) | ModifierKeys(args...).keys} {}; + ModifierKeys(ModifierKey key, Args... args) : keys{(is_modify_key_valid(key) ? (1 << key) : 0) | ModifierKeys(args...).keys} {}; ModifierKeys(std::initializer_list keys); @@ -289,7 +288,10 @@ namespace RC::Input } } - bool empty() const { return keys == 0; } + bool empty() const + { + return keys == 0; + } }; static constexpr uint8_t max_modifier_keys = MODIFIER_KEYS_MAX; diff --git a/deps/first/Input/include/Input/Platform/NcursesInputSource.hpp b/deps/first/Input/include/Input/Platform/NcursesInputSource.hpp index feba5ea4c..624f32d50 100644 --- a/deps/first/Input/include/Input/Platform/NcursesInputSource.hpp +++ b/deps/first/Input/include/Input/Platform/NcursesInputSource.hpp @@ -3,30 +3,34 @@ #include #include -namespace RC::Input +namespace RC::Input { class NcursesInputSource : public QueueInputSource { - public: - auto begin_frame() -> void; - auto receive_input(int input) -> void; - auto end_frame() -> void; - - private: - /// SAFETY: Only update inside begin_frame ... receive_input(...) ... end_frame - std::vector m_key_cur{}; - std::vector m_key_last{}; - bool m_is_alt_down; - - public: - NcursesInputSource():m_is_alt_down(false) { - m_key_cur.resize(256, false); - m_key_last.resize(256, false); - } + public: + auto begin_frame() -> void; + auto receive_input(int input) -> void; + auto end_frame() -> void; - auto is_available() -> bool override; - const char* get_name() override { return "Ncurses"; } + private: + /// SAFETY: Only update inside begin_frame ... receive_input(...) ... end_frame + std::vector m_key_cur{}; + std::vector m_key_last{}; + bool m_is_alt_down; + + public: + NcursesInputSource() : m_is_alt_down(false) + { + m_key_cur.resize(256, false); + m_key_last.resize(256, false); + } + + auto is_available() -> bool override; + const char* get_name() override + { + return "Ncurses"; + } }; -} +} // namespace RC::Input diff --git a/deps/first/Input/include/Input/Platform/QueueInputSource.hpp b/deps/first/Input/include/Input/Platform/QueueInputSource.hpp index e80fbbb84..b184cc9e3 100644 --- a/deps/first/Input/include/Input/Platform/QueueInputSource.hpp +++ b/deps/first/Input/include/Input/Platform/QueueInputSource.hpp @@ -9,34 +9,53 @@ namespace RC::Input { class QueueInputSource : public PlatformInputSource { - private: - static constexpr int max_inputs = 256; - RingBufferSPSC m_input_queue; - protected: - bool m_activated {false}; - private: - /// SAFETY: Only update and return m_input_events - /// in process_event and flush_events functions - std::vector m_input_events; - public: - ~QueueInputSource() = default; - - // QueeueInputSource is not a implemented input source - // and should not be used directly - bool is_available() override { return false; }; - - bool activate() override { return m_activated = true; }; - - bool deactivate() override { m_activated = false; return true; }; - - std::vector& process_event(Handler* handler) override; - - int source_priority() override { return 0; } - - const char* get_name() override { return "Queue"; } - - public: - auto push_input_event(const InputEvent& event) -> void; + private: + static constexpr int max_inputs = 256; + RingBufferSPSC m_input_queue; + + protected: + bool m_activated{false}; + + private: + /// SAFETY: Only update and return m_input_events + /// in process_event and flush_events functions + std::vector m_input_events; + + public: + ~QueueInputSource() = default; + + // QueeueInputSource is not a implemented input source + // and should not be used directly + bool is_available() override + { + return false; + }; + + bool activate() override + { + return m_activated = true; + }; + + bool deactivate() override + { + m_activated = false; + return true; + }; + + std::vector& process_event(Handler* handler) override; + + int source_priority() override + { + return 0; + } + + const char* get_name() override + { + return "Queue"; + } + + public: + auto push_input_event(const InputEvent& event) -> void; }; -}; // RC::Input \ No newline at end of file +}; // namespace RC::Input \ No newline at end of file diff --git a/deps/first/Input/include/Input/Platform/Win32AsyncInputSource.hpp b/deps/first/Input/include/Input/Platform/Win32AsyncInputSource.hpp index 90c75c75d..0564de08a 100644 --- a/deps/first/Input/include/Input/Platform/Win32AsyncInputSource.hpp +++ b/deps/first/Input/include/Input/Platform/Win32AsyncInputSource.hpp @@ -11,58 +11,76 @@ namespace RC::Input { class Win32AsyncInputSource : public PlatformInputSource { - private: - std::vector m_active_window_classes{}; - std::unordered_map m_modifier_keys_down{}; - bool m_any_keys_are_down{}; - bool m_activated {false}; - std::array m_key_down{}; + private: + std::vector m_active_window_classes{}; + std::unordered_map m_modifier_keys_down{}; + bool m_any_keys_are_down{}; + bool m_activated{false}; + std::array m_key_down{}; - private: - /// SAFETY: Only update and return m_input_events - /// in the process_event function - std::vector m_input_events{}; - public: - template - explicit Win32AsyncInputSource(WindowClasses... window_classes) - { - static_assert(std::conjunction...>::value, "WindowClasses must be of type const wchar_t*"); + private: + /// SAFETY: Only update and return m_input_events + /// in the process_event function + std::vector m_input_events{}; - m_modifier_keys_down.emplace(ModifierKey::SHIFT, false); - m_modifier_keys_down.emplace(ModifierKey::CONTROL, false); - m_modifier_keys_down.emplace(ModifierKey::ALT, false); + public: + template + explicit Win32AsyncInputSource(WindowClasses... window_classes) + { + static_assert(std::conjunction...>::value, "WindowClasses must be of type const wchar_t*"); - register_window_classes(window_classes...); - } + m_modifier_keys_down.emplace(ModifierKey::SHIFT, false); + m_modifier_keys_down.emplace(ModifierKey::CONTROL, false); + m_modifier_keys_down.emplace(ModifierKey::ALT, false); - private: - template - auto register_window_classes(WindowClass window_class) -> void - { - m_active_window_classes.emplace_back(window_class); - } + register_window_classes(window_classes...); + } - template - auto register_window_classes(WindowClass window_class, WindowClasses... window_classes) -> void - { - m_active_window_classes.emplace_back(window_class); - register_window_classes(window_classes...); - } + private: + template + auto register_window_classes(WindowClass window_class) -> void + { + m_active_window_classes.emplace_back(window_class); + } - auto are_modifier_keys_down(const std::vector&) -> bool; - auto is_program_focused() -> bool; + template + auto register_window_classes(WindowClass window_class, WindowClasses... window_classes) -> void + { + m_active_window_classes.emplace_back(window_class); + register_window_classes(window_classes...); + } - public: - bool is_available() override { return true; }; + auto are_modifier_keys_down(const std::vector&) -> bool; + auto is_program_focused() -> bool; - bool activate() override { m_key_down.fill(false); return m_activated = true; }; + public: + bool is_available() override + { + return true; + }; - bool deactivate() override { m_activated = false; return true; }; - - std::vector& process_event(Handler* handler) override; - ~Win32AsyncInputSource() = default; - int source_priority() override { return 0; } + bool activate() override + { + m_key_down.fill(false); + return m_activated = true; + }; - const char* get_name() override { return "Win32Async"; } + bool deactivate() override + { + m_activated = false; + return true; + }; + + std::vector& process_event(Handler* handler) override; + ~Win32AsyncInputSource() = default; + int source_priority() override + { + return 0; + } + + const char* get_name() override + { + return "Win32Async"; + } }; -}; +}; // namespace RC::Input diff --git a/deps/first/Input/include/Input/PlatformInputSource.hpp b/deps/first/Input/include/Input/PlatformInputSource.hpp index f488f26d9..387311b9a 100644 --- a/deps/first/Input/include/Input/PlatformInputSource.hpp +++ b/deps/first/Input/include/Input/PlatformInputSource.hpp @@ -9,27 +9,41 @@ namespace RC::Input { class PlatformInputSource - { - public: - /// Check if the input source is available - virtual bool is_available() { return false; }; - - /// Initialize the input source - virtual bool activate() { return false; }; - - /// Initialize the input source - virtual bool deactivate() { return false; }; - - /// Get the priority of the input source, smaller number means higher priority - virtual int source_priority() { return 999; }; - - /// Process the event and return the input events in the frame - virtual std::vector& process_event(Handler* handler) = 0; - - virtual ~PlatformInputSource() = default; - - virtual const char* get_name() { return "Unknown"; } + { + public: + /// Check if the input source is available + virtual bool is_available() + { + return false; + }; + + /// Initialize the input source + virtual bool activate() + { + return false; + }; + + /// Initialize the input source + virtual bool deactivate() + { + return false; + }; + + /// Get the priority of the input source, smaller number means higher priority + virtual int source_priority() + { + return 999; + }; + + /// Process the event and return the input events in the frame + virtual std::vector& process_event(Handler* handler) = 0; + + virtual ~PlatformInputSource() = default; + + virtual const char* get_name() + { + return "Unknown"; + } }; -}; // RC::Input - +}; // namespace RC::Input diff --git a/deps/first/Input/include/Input/RingBuffer.hpp b/deps/first/Input/include/Input/RingBuffer.hpp index d786d70b5..923d36ec9 100644 --- a/deps/first/Input/include/Input/RingBuffer.hpp +++ b/deps/first/Input/include/Input/RingBuffer.hpp @@ -3,7 +3,7 @@ #include #include -namespace RC::Input +namespace RC::Input { /// SAFETY: This is ONLY a single producer, single consumer lock-free queue template @@ -44,5 +44,4 @@ namespace RC::Input return event; } }; -} // RC::Input - +} // namespace RC::Input diff --git a/deps/first/Input/src/Handler.cpp b/deps/first/Input/src/Handler.cpp index ecc6ce4bd..4d9d4eee7 100644 --- a/deps/first/Input/src/Handler.cpp +++ b/deps/first/Input/src/Handler.cpp @@ -16,7 +16,7 @@ namespace RC::Input } std::vector callbacks_to_call{}; - + auto events = m_platform_handler->process_event(this); { @@ -27,15 +27,14 @@ namespace RC::Input auto key_set_array = m_key_set.key_data[event.key]; for (auto& key_data : key_set_array) { - if (key_data.required_modifier_keys == event.modifier_keys) + if (key_data.required_modifier_keys == event.modifier_keys) { callbacks_to_call.emplace_back(key_data.callback); } } } } - - + // No need to lock the event mutex to call the callbacks // this avoids key registration inside the callback for (const auto& callback : callbacks_to_call) @@ -109,7 +108,7 @@ namespace RC::Input return m_subscribed_keys[key]; } - auto Handler::get_events_safe(std::function callback) -> void + auto Handler::get_events_safe(std::function callback) -> void { auto event_update_lock = std::lock_guard(m_event_mutex); callback(m_key_set); @@ -157,7 +156,9 @@ namespace RC::Input { return false; } - } else { + } + else + { auto input_source = m_input_sources_store.find(source); if (input_source == m_input_sources_store.end()) { @@ -186,7 +187,7 @@ namespace RC::Input auto Handler::register_input_source(std::shared_ptr input_source) -> void { std::string name = input_source->get_name(); - if (m_input_sources_store.find(name) == m_input_sources_store.end()) + if (m_input_sources_store.find(name) == m_input_sources_store.end()) { m_input_sources_store[name] = input_source; } diff --git a/deps/first/Input/src/KeyDef.cpp b/deps/first/Input/src/KeyDef.cpp index 0f4c93c3e..9057adc0f 100644 --- a/deps/first/Input/src/KeyDef.cpp +++ b/deps/first/Input/src/KeyDef.cpp @@ -22,7 +22,6 @@ namespace RC::Input return *this; } - auto ModifierKeys::operator|(const ModifierKey& key) -> ModifierKeys& { if (is_modify_key_valid(key)) @@ -32,13 +31,11 @@ namespace RC::Input return *this; } - auto ModifierKeys::operator|=(const ModifierKeys& rkeys) -> ModifierKeys& { return *this = *this | rkeys; } - auto ModifierKeys::operator|=(const ModifierKey& key) -> ModifierKeys& { return *this = *this | key; @@ -68,7 +65,7 @@ namespace RC::Input { for (auto key : keys) { - if (is_modify_key_valid(key)) + if (is_modify_key_valid(key)) { this->keys |= (1 << key); } @@ -77,12 +74,12 @@ namespace RC::Input auto operator&(const ModifierKeys& keys, const ModifierKey& key) -> bool { - return !! (keys.keys & (1 << key)); + return !!(keys.keys & (1 << key)); } auto operator&(const ModifierKeys& keys, const ModifierKeys& key) -> bool { - return !! (keys.keys & key.keys); + return !!(keys.keys & key.keys); } } // namespace RC::Input diff --git a/deps/first/Input/src/Platform/NcursesInputSource.cpp b/deps/first/Input/src/Platform/NcursesInputSource.cpp index 686babecb..f7d98c496 100644 --- a/deps/first/Input/src/Platform/NcursesInputSource.cpp +++ b/deps/first/Input/src/Platform/NcursesInputSource.cpp @@ -8,145 +8,208 @@ namespace RC::Input std::fill(m_key_cur.begin(), m_key_cur.end(), false); } - static Key translate_control_key(int k) { - switch (k) { - case 0: return Key::SPACE; - case 1: return Key::A; - case 2: return Key::B; - case 3: return Key::C; - case 4: return Key::D; - case 5: return Key::E; - case 6: return Key::F; - case 7: return Key::G; - case 8: return Key::H; - case 9: return Key::I; - case 10: return Key::J; - case 11: return Key::K; - case 12: return Key::L; - case 13: return Key::M; - case 14: return Key::N; - case 15: return Key::O; - case 16: return Key::P; - case 17: return Key::Q; - case 18: return Key::R; - case 19: return Key::S; - case 20: return Key::T; - case 21: return Key::U; - case 22: return Key::V; - case 23: return Key::W; - case 24: return Key::X; - case 25: return Key::Y; - case 26: return Key::Z; - // case 27: return Key::Escape; - case 28: return Key::BACKSPACE; - //case 29: return Key::CtrlRightBracket; - //case 30: return Key::CtrlCircumflex; - // case 31: return Key::CtrlUnderscore; - default: return Key::RESERVED_START_OF_ENUM; + static Key translate_control_key(int k) + { + switch (k) + { + case 0: + return Key::SPACE; + case 1: + return Key::A; + case 2: + return Key::B; + case 3: + return Key::C; + case 4: + return Key::D; + case 5: + return Key::E; + case 6: + return Key::F; + case 7: + return Key::G; + case 8: + return Key::H; + case 9: + return Key::I; + case 10: + return Key::J; + case 11: + return Key::K; + case 12: + return Key::L; + case 13: + return Key::M; + case 14: + return Key::N; + case 15: + return Key::O; + case 16: + return Key::P; + case 17: + return Key::Q; + case 18: + return Key::R; + case 19: + return Key::S; + case 20: + return Key::T; + case 21: + return Key::U; + case 22: + return Key::V; + case 23: + return Key::W; + case 24: + return Key::X; + case 25: + return Key::Y; + case 26: + return Key::Z; + // case 27: return Key::Escape; + case 28: + return Key::BACKSPACE; + // case 29: return Key::CtrlRightBracket; + // case 30: return Key::CtrlCircumflex; + // case 31: return Key::CtrlUnderscore; + default: + return Key::RESERVED_START_OF_ENUM; } } - #define KEY_DOWN 0402 /* down-arrow key */ - #define KEY_UP 0403 /* up-arrow key */ - #define KEY_LEFT 0404 /* left-arrow key */ - #define KEY_RIGHT 0405 /* right-arrow key */ - #define KEY_HOME 0406 /* home key */ - #define KEY_BACKSPACE 0407 /* backspace key */ - #define KEY_F0 0410 /* Function keys. Space for 64 */ - #define KEY_F(n) (KEY_F0+(n)) /* Value of function key n */ - #define KEY_DC 0512 /* delete-character key */ - #define KEY_IC 0513 /* insert-character key */ +#define KEY_DOWN 0402 /* down-arrow key */ +#define KEY_UP 0403 /* up-arrow key */ +#define KEY_LEFT 0404 /* left-arrow key */ +#define KEY_RIGHT 0405 /* right-arrow key */ +#define KEY_HOME 0406 /* home key */ +#define KEY_BACKSPACE 0407 /* backspace key */ +#define KEY_F0 0410 /* Function keys. Space for 64 */ +#define KEY_F(n) (KEY_F0 + (n)) /* Value of function key n */ +#define KEY_DC 0512 /* delete-character key */ +#define KEY_IC 0513 /* insert-character key */ - static Key translate_key_may_shift(int ch, bool &shifted) { + static Key translate_key_may_shift(int ch, bool& shifted) + { shifted = false; - if (ch >= 97 && ch <= 122) { + if (ch >= 97 && ch <= 122) + { return static_cast(ch - 97 + static_cast(Key::A)); } - if (ch >= 65 && ch <= 90) { + if (ch >= 65 && ch <= 90) + { // capital letter shifted = true; return static_cast(ch - 65 + static_cast(Key::A)); } - - if (ch >= 48 && ch <= 57) { + + if (ch >= 48 && ch <= 57) + { return static_cast(ch - 48 + static_cast(Key::ZERO)); } - switch (ch) { - case 32: return Key::SPACE; - // case 10: return Key::ENTER; - // case 27: return Key::ESCAPE; - case 127: return Key::BACKSPACE; - case KEY_DOWN: return Key::DOWN_ARROW; - case KEY_UP: return Key::UP_ARROW; - case KEY_LEFT: return Key::LEFT_ARROW; - case KEY_RIGHT: return Key::RIGHT_ARROW; - case KEY_HOME: return Key::HOME; - case KEY_BACKSPACE: return Key::BACKSPACE; - case KEY_F(1): return Key::F1; - case KEY_F(2): return Key::F2; - case KEY_F(3): return Key::F3; - case KEY_F(4): return Key::F4; - case KEY_F(5): return Key::F5; - case KEY_F(6): return Key::F6; - case KEY_F(7): return Key::F7; - case KEY_F(8): return Key::F8; - case KEY_F(9): return Key::F9; - case KEY_F(10): return Key::F10; - case KEY_F(11): return Key::F11; - case KEY_F(12): return Key::F12; - case KEY_DC: return Key::DEL; - case KEY_IC: return Key::INS; + switch (ch) + { + case 32: + return Key::SPACE; + // case 10: return Key::ENTER; + // case 27: return Key::ESCAPE; + case 127: + return Key::BACKSPACE; + case KEY_DOWN: + return Key::DOWN_ARROW; + case KEY_UP: + return Key::UP_ARROW; + case KEY_LEFT: + return Key::LEFT_ARROW; + case KEY_RIGHT: + return Key::RIGHT_ARROW; + case KEY_HOME: + return Key::HOME; + case KEY_BACKSPACE: + return Key::BACKSPACE; + case KEY_F(1): + return Key::F1; + case KEY_F(2): + return Key::F2; + case KEY_F(3): + return Key::F3; + case KEY_F(4): + return Key::F4; + case KEY_F(5): + return Key::F5; + case KEY_F(6): + return Key::F6; + case KEY_F(7): + return Key::F7; + case KEY_F(8): + return Key::F8; + case KEY_F(9): + return Key::F9; + case KEY_F(10): + return Key::F10; + case KEY_F(11): + return Key::F11; + case KEY_F(12): + return Key::F12; + case KEY_DC: + return Key::DEL; + case KEY_IC: + return Key::INS; } - #define CASE_CHAR(normal_ch, shifted_ch, key) \ - case normal_ch: shifted = false; \ - case shifted_ch: return key; +#define CASE_CHAR(normal_ch, shifted_ch, key) \ + case normal_ch: \ + shifted = false; \ + case shifted_ch: \ + return key; shifted = true; - switch (ch) { - case '!': - return Key::ONE; - case '@': - return Key::TWO; - case '#': - return Key::THREE; - case '$': - return Key::FOUR; - case '%': - return Key::FIVE; - case '^': - return Key::SIX; - case '&': - return Key::SEVEN; - case '*': - return Key::EIGHT; - case '(': - return Key::NINE; - case ')': - return Key::ZERO; // Shift+0 produces ')' - CASE_CHAR('`', '~', Key::OEM_THREE) // key ~ is oem 3 on windows - CASE_CHAR('-', '_', Key::OEM_MINUS) // key _ is oem minus on windows - CASE_CHAR('=', '+', Key::OEM_PLUS) // key + is oem plus on windows - CASE_CHAR('[', '{', Key::OEM_FOUR) // key { is oem four on windows - CASE_CHAR(']', '}', Key::OEM_SIX) // key } is oem 6 on windows - CASE_CHAR('\\', '|', Key::OEM_FIVE) // key | is oem 5 on windows - CASE_CHAR(';', ':', Key::OEM_ONE) // key : is oem semicolon on windows + switch (ch) + { + case '!': + return Key::ONE; + case '@': + return Key::TWO; + case '#': + return Key::THREE; + case '$': + return Key::FOUR; + case '%': + return Key::FIVE; + case '^': + return Key::SIX; + case '&': + return Key::SEVEN; + case '*': + return Key::EIGHT; + case '(': + return Key::NINE; + case ')': + return Key::ZERO; // Shift+0 produces ')' + CASE_CHAR('`', '~', Key::OEM_THREE) // key ~ is oem 3 on windows + CASE_CHAR('-', '_', Key::OEM_MINUS) // key _ is oem minus on windows + CASE_CHAR('=', '+', Key::OEM_PLUS) // key + is oem plus on windows + CASE_CHAR('[', '{', Key::OEM_FOUR) // key { is oem four on windows + CASE_CHAR(']', '}', Key::OEM_SIX) // key } is oem 6 on windows + CASE_CHAR('\\', '|', Key::OEM_FIVE) // key | is oem 5 on windows + CASE_CHAR(';', ':', Key::OEM_ONE) // key : is oem semicolon on windows CASE_CHAR('\'', '"', Key::OEM_SEVEN) // key " is oem apostrophe on windows - CASE_CHAR(',', '<', Key::OEM_COMMA) // key < is oem comma on windows + CASE_CHAR(',', '<', Key::OEM_COMMA) // key < is oem comma on windows CASE_CHAR('.', '>', Key::OEM_PERIOD) // key > is oem period on windows - CASE_CHAR('/', '?', Key::OEM_TWO) // key ? is oem 2 on windows - default: - shifted = false; - return Key::RESERVED_START_OF_ENUM; + CASE_CHAR('/', '?', Key::OEM_TWO) // key ? is oem 2 on windows + default: + shifted = false; + return Key::RESERVED_START_OF_ENUM; } } auto NcursesInputSource::receive_input(int input) -> void { - if (!m_activated) { + if (!m_activated) + { return; } // input is ncurse's key code - if (input == 27) { + if (input == 27) + { // esc key m_is_alt_down = true; } @@ -155,22 +218,28 @@ namespace RC::Input auto control_down = false; auto shift_down = false; auto key_code = -1; - if (input >= 0 && input < 32) { + if (input >= 0 && input < 32) + { Key input_key = translate_control_key(input); - if (input_key != Key::RESERVED_START_OF_ENUM) { + if (input_key != Key::RESERVED_START_OF_ENUM) + { key_code = static_cast(input_key); control_down = true; } - } else { + } + else + { Key input_key = translate_key_may_shift(input, shift_down); - if (input_key != Key::RESERVED_START_OF_ENUM) + if (input_key != Key::RESERVED_START_OF_ENUM) { key_code = static_cast(input_key); } } - if (key_code != -1) { + if (key_code != -1) + { m_key_cur[key_code] = true; - if (!m_key_last[key_code]) { + if (!m_key_last[key_code]) + { // keydown ModifierKeys modifier_keys{}; modifier_keys |= (control_down ? ModifierKey::CONTROL : ModifierKey::MOD_KEY_START_OF_ENUM); @@ -179,26 +248,33 @@ namespace RC::Input push_input_event({static_cast(key_code), modifier_keys}); auto modify_to_string = [](ModifierKeys modifier_keys) -> std::string { std::string result; - if (modifier_keys & ModifierKey::CONTROL) { + if (modifier_keys & ModifierKey::CONTROL) + { result += "Control"; } - if (modifier_keys & ModifierKey::SHIFT) { - if (!result.empty()) { + if (modifier_keys & ModifierKey::SHIFT) + { + if (!result.empty()) + { result += "+"; } result += "Shift"; } - if (modifier_keys & ModifierKey::ALT) { - if (!result.empty()) { + if (modifier_keys & ModifierKey::ALT) + { + if (!result.empty()) + { result += "+"; } result += "Alt"; } return result; }; - Output::send(SYSSTR("NcursesInputSource::receive_input: key down {} {}"), static_cast(input), modify_to_string(modifier_keys)); + Output::send(SYSSTR("NcursesInputSource::receive_input: key down {} {}"), + static_cast(input), + modify_to_string(modifier_keys)); } - else + else { Output::send(SYSSTR("NcursesInputSource::receive_input: key repeat {}"), static_cast(input)); } diff --git a/deps/first/Input/src/Platform/QueneInputSource.cpp b/deps/first/Input/src/Platform/QueneInputSource.cpp index 55952b833..f7170101e 100644 --- a/deps/first/Input/src/Platform/QueneInputSource.cpp +++ b/deps/first/Input/src/Platform/QueneInputSource.cpp @@ -7,9 +7,10 @@ namespace RC::Input { auto QueueInputSource::push_input_event(const InputEvent& event) -> void { - if (m_activated) { + if (m_activated) + { m_input_queue.push(event); - Output::send(SYSSTR("QueueInputSource::push_input_event: {}"), (int) event.key); + Output::send(SYSSTR("QueueInputSource::push_input_event: {}"), (int)event.key); } } @@ -17,12 +18,12 @@ namespace RC::Input std::vector& QueueInputSource::process_event(Handler* handler) { m_input_events.clear(); - + auto event = m_input_queue.pop(); auto& key_set = handler->get_subscribed_keys(); while (event) { - Output::send(SYSSTR("QueueInputSource::reveive key event: {}"), (int) event->key); + Output::send(SYSSTR("QueueInputSource::reveive key event: {}"), (int)event->key); if (key_set[event->key]) { m_input_events.emplace_back(*event); @@ -30,14 +31,16 @@ namespace RC::Input event = m_input_queue.pop(); } - if (!m_activated) { + if (!m_activated) + { m_input_events.clear(); } - if (!handler->get_allow_input()) { + if (!handler->get_allow_input()) + { m_input_events.clear(); } return m_input_events; } -}; // RC::Input +}; // namespace RC::Input diff --git a/deps/first/Input/src/Platform/Win32AsyncInputSource.cpp b/deps/first/Input/src/Platform/Win32AsyncInputSource.cpp index d9f32f967..7169ae55f 100644 --- a/deps/first/Input/src/Platform/Win32AsyncInputSource.cpp +++ b/deps/first/Input/src/Platform/Win32AsyncInputSource.cpp @@ -74,7 +74,7 @@ namespace RC::Input { any_keys_are_down = true; m_key_down[key] = true; - m_input_events.emplace_back(InputEvent {static_cast(key), modifier_keys}); + m_input_events.emplace_back(InputEvent{static_cast(key), modifier_keys}); } else if (!keyed && m_key_down[key]) { diff --git a/deps/first/Input/src/PlatformInit.cpp b/deps/first/Input/src/PlatformInit.cpp index 54d23e278..6241c548f 100644 --- a/deps/first/Input/src/PlatformInit.cpp +++ b/deps/first/Input/src/PlatformInit.cpp @@ -6,11 +6,11 @@ namespace RC::Input { auto Handler::init() -> void { - #ifdef WIN32 - register_input_source(std::make_shared(L"ConsoleWindowClass", L"UnrealWindow")); - #endif - #ifdef LINUX - register_input_source(std::make_shared()); - #endif +#ifdef WIN32 + register_input_source(std::make_shared(L"ConsoleWindowClass", L"UnrealWindow")); +#endif +#ifdef LINUX + register_input_source(std::make_shared()); +#endif } -} \ No newline at end of file +} // namespace RC::Input \ No newline at end of file diff --git a/deps/first/JSON/include/JSON/Bool.hpp b/deps/first/JSON/include/JSON/Bool.hpp index ac4c44fc0..fc599f6cc 100644 --- a/deps/first/JSON/include/JSON/Bool.hpp +++ b/deps/first/JSON/include/JSON/Bool.hpp @@ -23,7 +23,8 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) + -> SystemStringType override; auto get_type() const -> Type override { return Type::Bool; diff --git a/deps/first/JSON/include/JSON/Null.hpp b/deps/first/JSON/include/JSON/Null.hpp index 27aeab023..d23353a2e 100644 --- a/deps/first/JSON/include/JSON/Null.hpp +++ b/deps/first/JSON/include/JSON/Null.hpp @@ -13,7 +13,8 @@ namespace RC::JSON ~Null() override = default; public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) + -> SystemStringType override; auto get_type() const -> Type override { return Type::Null; diff --git a/deps/first/JSON/include/JSON/Number.hpp b/deps/first/JSON/include/JSON/Number.hpp index 9fc269624..59a876d15 100644 --- a/deps/first/JSON/include/JSON/Number.hpp +++ b/deps/first/JSON/include/JSON/Number.hpp @@ -167,7 +167,8 @@ namespace RC::JSON } public: - auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) -> SystemStringType override; + auto serialize([[maybe_unused]] ShouldFormat should_format = ShouldFormat::No, [[maybe_unused]] int32_t* indent_level = nullptr) + -> SystemStringType override; auto get_type() const -> JSON::Type override { return JSON::Type::Number; diff --git a/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp b/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp index 9a197a847..59a7e1284 100644 --- a/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp +++ b/deps/first/LuaMadeSimple/include/LuaMadeSimple/Common.hpp @@ -20,7 +20,6 @@ #else - #ifndef RC_LMS_API #define RC_LMS_API #endif diff --git a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp index afe1bb9ce..8cb812271 100644 --- a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp +++ b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp @@ -87,7 +87,7 @@ namespace RC::LuaMadeSimple /** * Helper for dealing with Lua tables passed from Lua to C++ */ - template + template struct RC_LMS_API LuaTableReference { LuaTableData<-1, LuaT> key; diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp index eff4e6fc9..08b03f765 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/Common.hpp @@ -25,4 +25,3 @@ #endif #endif - diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp index efd8b74a0..93b07951b 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScanner.hpp @@ -7,7 +7,6 @@ #include - #ifdef WIN32 #include "SinglePassSigScannerWin32.hpp" #else @@ -18,7 +17,7 @@ #define LO_NIBBLE(b) ((b)&0x0F) namespace RC -{ +{ enum class ScanTarget { MainExe, @@ -170,7 +169,7 @@ namespace RC auto operator[](ScanTarget index) -> ModuleOS&; }; - + // Static storage to be used across all sig scanner types // At the moment the only scanner type that exists is SinglePassScanner // In the future there might be a multi-threaded version of SinglePassScanner @@ -313,10 +312,8 @@ namespace RC RC_SPSS_API auto static format_aob_strings(std::vector& signature_containers) -> void; public: - RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, - uint8_t* end_address, - SystemInfo* info, - std::vector& signature_containers) -> void; + RC_SPSS_API auto static scanner_work_thread(uint8_t* start_address, uint8_t* end_address, SystemInfo* info, std::vector& signature_containers) + -> void; RC_SPSS_API auto static scanner_work_thread_scalar(uint8_t* start_address, uint8_t* end_address, SystemInfo* info, @@ -331,22 +328,22 @@ namespace RC RC_SPSS_API auto static string_scan(std::wstring_view string_to_scan_for, ScanTarget = ScanTarget::MainExe) -> void*; }; - - namespace Platform { + namespace Platform + { // Get the system info auto get_system_info() -> SystemInfo*; // Get the start address of the system - auto get_start_address(SystemInfo *info) -> uint8_t*; + auto get_start_address(SystemInfo* info) -> uint8_t*; // Get the end address of the system - auto get_end_address(SystemInfo *info) -> uint8_t*; + auto get_end_address(SystemInfo* info) -> uint8_t*; // Get the size of the module - auto get_module_size(ModuleOS *info) -> uint32_t; + auto get_module_size(ModuleOS* info) -> uint32_t; // Get the base address of the module - auto get_module_base(ModuleOS *info) -> uint8_t*; + auto get_module_base(ModuleOS* info) -> uint8_t*; }; // namespace Platform }; // namespace RC diff --git a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp index 2c87ceec9..eff263c91 100644 --- a/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp +++ b/deps/first/SinglePassSigScanner/include/SigScanner/SinglePassSigScannerLinux.hpp @@ -15,10 +15,13 @@ namespace RC size_t size; // sorted by start address std::set> phdrs; - std::tuple find_phdr(uint8_t* addr) { - for (auto& phdr : phdrs) { + std::tuple find_phdr(uint8_t* addr) + { + for (auto& phdr : phdrs) + { // use end address to find the phdr - if (std::get<0>(phdr) + std::get<1>(phdr) > addr) { + if (std::get<0>(phdr) + std::get<1>(phdr) > addr) + { return phdr; } } diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp index 54b8c6cbb..2050b5bb6 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScanner.cpp @@ -424,7 +424,7 @@ namespace RC return pattern_data; } - auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, SystemInfo *info, std::vector& signature_containers) + auto SinglePassScanner::scanner_work_thread(uint8_t* start_address, uint8_t* end_address, SystemInfo* info, std::vector& signature_containers) -> void { ProfilerSetThreadName("UE4SS-ScannerWorkThread"); @@ -600,9 +600,9 @@ namespace RC if (merged_containers.empty()) { fprintf(stderr, "No containers to merge\n"); - return ; - //throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " - // "an internal error."}; + return; + // throw std::runtime_error{"[SinglePassScanner::start_scan] Could not merge containers. Either there were not containers to merge or there was " + // "an internal error."}; } uint8_t* module_start_address = Platform::get_module_base(merged_module_info); @@ -656,7 +656,8 @@ namespace RC for (auto& [scan_target, signature_container] : signature_containers) { uint8_t* module_start_address = static_cast(Platform::get_module_base(&SigScannerStaticData::m_modules_info[scan_target])); - uint8_t* module_end_address = static_cast(module_start_address + Platform::get_module_size(&SigScannerStaticData::m_modules_info[scan_target])); + uint8_t* module_end_address = + static_cast(module_start_address + Platform::get_module_size(&SigScannerStaticData::m_modules_info[scan_target])); scanner_work_thread(module_start_address, module_end_address, info, signature_container); @@ -668,4 +669,3 @@ namespace RC } } }; // namespace RC - diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp index c26def15d..f0442052c 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerLinux.cpp @@ -26,33 +26,35 @@ namespace RC return &SigScannerStaticData::m_modules_info[ScanTarget::MainExe]; } - auto get_start_address(DLData *info) -> uint8_t* { + auto get_start_address(DLData* info) -> uint8_t* + { return info->base_address; } - auto get_end_address(DLData *info) -> uint8_t* { + auto get_end_address(DLData* info) -> uint8_t* + { return info->base_address + info->size; } - auto get_module_size(DLData *info) -> uint32_t { + auto get_module_size(DLData* info) -> uint32_t + { return info->size; } - auto get_module_base(DLData *info) -> uint8_t* { + auto get_module_base(DLData* info) -> uint8_t* + { return info->base_address; } }; // namespace Platform - auto SinglePassScanner::string_scan(std::wstring_view string_to_scan_for, ScanTarget scan_target) -> void* { + auto SinglePassScanner::string_scan(std::wstring_view string_to_scan_for, ScanTarget scan_target) -> void* + { throw std::runtime_error{"[SinglePassSigScanner::string_scan] Not implemented for Linux"}; } - // This function may have problem becasue we're not checking the memory region's permissions - auto SinglePassScanner::scanner_work_thread_scalar(uint8_t* start_address, - uint8_t* end_address, - DLData* info, - std::vector& signature_containers) -> void + auto SinglePassScanner::scanner_work_thread_scalar(uint8_t* start_address, uint8_t* end_address, DLData* info, std::vector& signature_containers) + -> void { ProfilerScope(); if (!start_address) @@ -103,11 +105,13 @@ namespace RC { continue; } - if (std::get<0>(addr) > i) { + if (std::get<0>(addr) > i) + { i = std::get<0>(addr); } uint8_t* region_end = static_cast(std::get<0>(addr)) + std::get<1>(addr); - if ((std::get<2>(addr) & PF_R) == 0) { + if ((std::get<2>(addr) & PF_R) == 0) + { i = region_end; continue; } @@ -188,7 +192,6 @@ namespace RC } i = scan_end; - } } } // namespace RC \ No newline at end of file diff --git a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp index ba669e4a0..abbb8f13b 100644 --- a/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp +++ b/deps/first/SinglePassSigScanner/src/SinglePassSigScannerWin32.cpp @@ -10,19 +10,17 @@ #include #endif - #include #include namespace RC { - + auto ScanTargetArray::operator[](ScanTarget index) -> ModuleOS& { return *std::bit_cast(&array[static_cast(index)]); } - namespace Platform { auto get_system_info() -> SystemInfo* @@ -33,26 +31,30 @@ namespace RC } // Get the start address of the system - auto get_start_address(SystemInfo *info) -> uint8_t* { + auto get_start_address(SystemInfo* info) -> uint8_t* + { return static_cast(info->lpMinimumApplicationAddress); } // Get the end address of the system - auto get_end_address(SystemInfo *info) -> uint8_t* { + auto get_end_address(SystemInfo* info) -> uint8_t* + { return static_cast(info->lpMaximumApplicationAddress); } // Get the size of the module - auto get_module_size(ModuleOS *info) -> uint32_t { + auto get_module_size(ModuleOS* info) -> uint32_t + { return info->SizeOfImage; } // Get the base address of the module - auto get_module_base(ModuleOS *info) -> uint8_t* { + auto get_module_base(ModuleOS* info) -> uint8_t* + { return static_cast(info->lpBaseOfDll); } }; // namespace Platform - + auto WIN_MODULEINFO::operator=(MODULEINFO other) -> WIN_MODULEINFO& { lpBaseOfDll = other.lpBaseOfDll; From a1aa84b092df76aa6c8fa9d8d138a06becb14ec1 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 05:03:01 -0600 Subject: [PATCH 110/213] add back glfw3 for win32 --- UE4SS/src/GUI/GUI.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 9cd68ef48..6304744bd 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -550,6 +550,10 @@ namespace RC::GUI m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); break; + case GfxBackend::GLFW3_OpenGL3: + m_gfx_backend = std::make_unique(); + m_os_backend = std::make_unique(); + break; #else #ifdef HAS_GLFW case GfxBackend::GLFW3_OpenGL3: From 07e465ba07489b37bd89c9115902b743fc8066f9 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 15:48:09 -0600 Subject: [PATCH 111/213] remove settings.json --- .vscode/settings.json | 107 ------------------------------------------ 1 file changed, 107 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3fdcaf704..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "files.associations": { - "*.S": "gas", - "tuple": "cpp", - "compare": "cpp", - "cstdint": "cpp", - "*.tcc": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "vector": "cpp", - "optional": "cpp", - "variant": "cpp", - "array": "cpp", - "chrono": "cpp", - "string": "cpp", - "string_view": "cpp", - "format": "cpp", - "initializer_list": "cpp", - "ranges": "cpp", - "span": "cpp", - "regex": "cpp", - "atomic": "cpp", - "bit": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "charconv": "cpp", - "cinttypes": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "codecvt": "cpp", - "concepts": "cpp", - "condition_variable": "cpp", - "coroutine": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "map": "cpp", - "set": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "random": "cpp", - "ratio": "cpp", - "source_location": "cpp", - "system_error": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "numbers": "cpp", - "ostream": "cpp", - "semaphore": "cpp", - "shared_mutex": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "stop_token": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "typeinfo": "cpp", - "any": "cpp", - "cfenv": "cpp", - "expected": "cpp", - "*.inc": "cpp", - "complex": "cpp", - "forward_list": "cpp", - "valarray": "cpp", - "__bit_reference": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__node_handle": "cpp", - "__split_buffer": "cpp", - "__threading_support": "cpp", - "__tree": "cpp", - "__verbose_abort": "cpp", - "execution": "cpp", - "ios": "cpp", - "locale": "cpp", - "print": "cpp", - "queue": "cpp", - "stack": "cpp", - "typeindex": "cpp" - }, - "C_Cpp.default.compileCommands": "build/compile_commands.json", - "cmake.buildTask": true, - "rust-analyzer.linkedProjects": [ - "/home/yangff/Project/RE-UE4SS/deps/first/patternsleuth/Cargo.toml" - ], - "cmake.generator": "Ninja" -} \ No newline at end of file From 4da88c49093f19052dd61712d144a19abe68756d Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 15:53:20 -0600 Subject: [PATCH 112/213] delete empty findzydis.cmake --- cmake/Findzydis.cmake | 1 - 1 file changed, 1 deletion(-) delete mode 100644 cmake/Findzydis.cmake diff --git a/cmake/Findzydis.cmake b/cmake/Findzydis.cmake deleted file mode 100644 index be830bd8c..000000000 --- a/cmake/Findzydis.cmake +++ /dev/null @@ -1 +0,0 @@ -# nothing to do From 3b52284d12e8b747d36cefa29ffd5353613a2d5e Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 17:24:24 -0600 Subject: [PATCH 113/213] add missing header --- deps/first/Function/include/Function/Function.hpp | 1 + deps/first/Input/include/Input/KeyDef.hpp | 1 + deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp | 1 + 3 files changed, 3 insertions(+) diff --git a/deps/first/Function/include/Function/Function.hpp b/deps/first/Function/include/Function/Function.hpp index b3491cd74..55be64fd5 100644 --- a/deps/first/Function/include/Function/Function.hpp +++ b/deps/first/Function/include/Function/Function.hpp @@ -3,6 +3,7 @@ #include #include #include +#include // Note: When we assign to 'm_function_address' from a function pointer, we're probably breaking some rules. // Though it's likely, a function is not guaranteed to be represented as a pointer. diff --git a/deps/first/Input/include/Input/KeyDef.hpp b/deps/first/Input/include/Input/KeyDef.hpp index 6c950ab5f..219c15f79 100644 --- a/deps/first/Input/include/Input/KeyDef.hpp +++ b/deps/first/Input/include/Input/KeyDef.hpp @@ -2,6 +2,7 @@ #include #include +#include namespace RC::Input { static constexpr uint32_t max_callbacks_per_event = 30; diff --git a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp index 8cb812271..04ddf3f94 100644 --- a/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp +++ b/deps/first/LuaMadeSimple/include/LuaMadeSimple/LuaMadeSimple.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include From d640680c99b6b1d28128a1bd99bda707a4b1b6d2 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 17:25:35 -0600 Subject: [PATCH 114/213] add --- UE4SS/include/GUI/GUI.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index b9f332caa..7a60a5863 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include From 2f49a09fdd5806f825dc657af0df9fcf3637a74d Mon Sep 17 00:00:00 2001 From: UE4SS Date: Mon, 26 Feb 2024 00:37:14 +0100 Subject: [PATCH 115/213] Added include to Casting.hpp --- deps/first/Helpers/include/Helpers/Casting.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/deps/first/Helpers/include/Helpers/Casting.hpp b/deps/first/Helpers/include/Helpers/Casting.hpp index 3fbd4e3be..739e06faa 100644 --- a/deps/first/Helpers/include/Helpers/Casting.hpp +++ b/deps/first/Helpers/include/Helpers/Casting.hpp @@ -2,6 +2,7 @@ #include #include +#include #ifdef WIN32 #ifdef _WIN32 From 482bc9ceb0e217ac493cc6a92ee01bf604c9617d Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Feb 2024 17:50:55 -0600 Subject: [PATCH 116/213] avoid clear key binding for none mod usage --- UE4SS/src/UE4SSProgram.cpp | 5 +++++ deps/first/Helpers/include/Helpers/Format.hpp | 2 ++ deps/first/Input/include/Input/Handler.hpp | 1 + deps/first/Input/src/Handler.cpp | 5 +++++ 4 files changed, 13 insertions(+) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 71131c4f6..3a3ad313c 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1395,6 +1395,11 @@ namespace RC return false; } }); + + if (vector_of_key_data.empty()) + { + m_input_handler.clear_subscribed_key(key); + } } }); #endif diff --git a/deps/first/Helpers/include/Helpers/Format.hpp b/deps/first/Helpers/include/Helpers/Format.hpp index ad07b76cb..38bf27cfa 100644 --- a/deps/first/Helpers/include/Helpers/Format.hpp +++ b/deps/first/Helpers/include/Helpers/Format.hpp @@ -3,6 +3,8 @@ #include #include +#include + namespace RC { template diff --git a/deps/first/Input/include/Input/Handler.hpp b/deps/first/Input/include/Input/Handler.hpp index dcdd6ee9b..06bbfe8b3 100644 --- a/deps/first/Input/include/Input/Handler.hpp +++ b/deps/first/Input/include/Input/Handler.hpp @@ -77,6 +77,7 @@ namespace RC::Input auto get_events_safe(std::function) -> void; auto clear_subscribed_keys() -> void; + auto clear_subscribed_key(Key k) -> void; auto has_event_on_key(Input::Key key) -> bool; auto get_subscribed_keys() const -> const std::array& diff --git a/deps/first/Input/src/Handler.cpp b/deps/first/Input/src/Handler.cpp index 4d9d4eee7..29883598d 100644 --- a/deps/first/Input/src/Handler.cpp +++ b/deps/first/Input/src/Handler.cpp @@ -119,6 +119,11 @@ namespace RC::Input m_subscribed_keys.fill(false); } + auto Handler::clear_subscribed_key(Key k) -> void + { + m_subscribed_keys[k] = false; + } + auto Handler::get_allow_input() -> bool { return m_allow_input; From 332e048919f1c16f31d0570541537a8514d303ed Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 25 Feb 2024 18:02:28 -0600 Subject: [PATCH 117/213] fix tab->space --- UE4SS/src/UE4SSProgram.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 3a3ad313c..fbef643f7 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1397,9 +1397,9 @@ namespace RC }); if (vector_of_key_data.empty()) - { + { m_input_handler.clear_subscribed_key(key); - } + } } }); #endif From 5686a89515e78f01bd80d6dfbfc61d1cf5276aac Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 26 Feb 2024 03:32:01 -0600 Subject: [PATCH 118/213] generate SYSSTR for macrosetter.hpp --- UVTD/src/MemberVarsWrapperGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UVTD/src/MemberVarsWrapperGenerator.cpp b/UVTD/src/MemberVarsWrapperGenerator.cpp index 854ccc662..afaa6a897 100644 --- a/UVTD/src/MemberVarsWrapperGenerator.cpp +++ b/UVTD/src/MemberVarsWrapperGenerator.cpp @@ -151,7 +151,7 @@ namespace RC::UVTD wrapper_src_dumper.send(STR("}\n\n")); } - macro_setter_dumper.send(STR("if (auto val = parser.get_int64(STR(\"{}\"), STR(\"{}\"), -1); val != -1)\n"), final_class_name, final_variable_name); + macro_setter_dumper.send(STR("if (auto val = parser.get_int64(SYSSTR(\"{}\"), SYSSTR(\"{}\"), -1); val != -1)\n"), final_class_name, final_variable_name); macro_setter_dumper.send(STR(" Unreal::{}::MemberOffsets.emplace(STR(\"{}\"), static_cast(val));\n"), final_class_name, final_variable_name); From 026193e27261c7c47e941813af4534f1ce0a8b38 Mon Sep 17 00:00:00 2001 From: UE4SS Date: Tue, 27 Feb 2024 00:16:00 +0100 Subject: [PATCH 119/213] Fixed DynamicOutput for Clang 18 Added missing include to String.hpp. Added warning suppressions for clang in String.hpp. --- .../include/DynamicOutput/Output.hpp | 24 +++++++++++---- deps/first/Helpers/include/Helpers/Format.hpp | 5 ++-- deps/first/Helpers/include/Helpers/String.hpp | 29 +++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp index 69a77d747..168a26a10 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp @@ -37,6 +37,20 @@ namespace RC::Output using OutputDevicesContainerType = std::vector>; + static constexpr auto apply_formatting(auto&& content, auto&&... args) + { + // Must switch on the 'content' type at compile-time, otherwise std::string formatting + // won't work on Windows since RC_STD_MAKE_FORMAT_ARGS is set to std::wstring. + if constexpr (not_std_string_like_t>::value) + { + return std::vformat(content, std::make_wformat_args(args...)); + } + else + { + return std::vformat(content, std::make_format_args(args...)); + } + } + auto RC_DYNOUT_API has_internal_error() -> bool; template @@ -147,7 +161,7 @@ namespace RC::Output THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } - auto formated = std::vformat(std::forward(content), RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); + auto formated = apply_formatting(content, to_system(std::forward(fmt_args))...); for (const auto& device : m_opened_devices) { @@ -172,14 +186,14 @@ namespace RC::Output THROW_INTERNAL_FILE_ERROR("[Output::send] Attempted to send but there were no opened devices."); } - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); + auto formated = apply_formatting(content, to_system(std::forward(fmt_args))...); for (const auto& device : m_opened_devices) { ASSERT_OUTPUT_DEVICE_IS_VALID(device) if (device->has_optional_arg()) { - device->receive_with_optional_arg(formated, RC_STD_MAKE_FORMAT_ARGS(static_cast(optional_arg))); + device->receive_with_optional_arg(formated, static_cast(optional_arg)); } else { @@ -295,7 +309,7 @@ namespace RC::Output template auto send(SystemStringViewType content, FmtArgs&&... fmt_args) -> void { - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); + auto formated = apply_formatting(content, to_system(std::forward(fmt_args))...); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) @@ -353,7 +367,7 @@ namespace RC::Output template auto send(SystemStringViewType content, FmtArgs&&... fmt_args) -> void { - auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); + auto formated = apply_formatting(content, to_system(std::forward(fmt_args))...); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) diff --git a/deps/first/Helpers/include/Helpers/Format.hpp b/deps/first/Helpers/include/Helpers/Format.hpp index 38bf27cfa..49b2858c0 100644 --- a/deps/first/Helpers/include/Helpers/Format.hpp +++ b/deps/first/Helpers/include/Helpers/Format.hpp @@ -4,18 +4,19 @@ #include #include +#include namespace RC { template auto static fmt(const std::string_view&& fmt, FmtArgs&&... fmt_args) -> std::string { - return std::vformat(std::forward(fmt), std::make_format_args(to_stdstr(std::forward(fmt_args))...)); + return Output::apply_formatting(fmt, to_stdstr(std::forward(fmt_args))...); } template auto static fmtfile(const File::StringViewType&& fmt, FmtArgs&&... fmt_args) -> std::string { - return std::vformat(std::forward(fmt), std::make_format_args(to_file(std::forward(fmt_args))...)); + return Output::apply_formatting(fmt, to_file(std::forward(fmt_args))...); } } // namespace RC \ No newline at end of file diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index c9a4790bf..1bb4e9ad9 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -269,8 +270,15 @@ namespace RC return converter.from_bytes(input.data(), input.data() + input.length()); #pragma warning(default : 4996) #else +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif static std::wstring_convert> converter{}; return converter.from_bytes(input.data(), input.data() + input.length()); +#endif +#if __clang__ +#pragma clang diagnostic pop #endif } @@ -342,17 +350,31 @@ namespace RC return converter.to_bytes(input.data(), input.data() + input.length()); #pragma warning(default : 4996) #else +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif static std::wstring_convert> converter{}; return converter.to_bytes(input.data(), input.data() + input.length()); +#if __clang__ +#pragma clang diagnostic pop +#endif #endif } auto inline to_string(std::u16string_view input) -> std::string { +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif #pragma warning(disable : 4996) static std::wstring_convert, char16_t> converter{}; return converter.to_bytes(input.data(), input.data() + input.length()); #pragma warning(default : 4996) +#if __clang__ +#pragma clang diagnostic pop +#endif } auto inline to_string(std::string_view input) -> std::string @@ -396,10 +418,17 @@ namespace RC auto temp_input = std::string{input}; return to_u16string(temp_input);*/ // codecvt_utf8_utf16 +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif #pragma warning(disable : 4996) static std::wstring_convert, char16_t> converter{}; return converter.from_bytes(input.data(), input.data() + input.length()); #pragma warning(default : 4996) +#if __clang__ +#pragma clang diagnostic pop +#endif } auto inline to_u16string(std::u16string_view input) -> std::u16string From e01a9fcb3b0a0d00778f5c7a89e8438d3469e514 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 26 Feb 2024 03:33:00 -0600 Subject: [PATCH 120/213] move headergen.py --- {scripts => UVTD/scripts}/HeaderGen.py | 2 +- scripts/database_.pkl | Bin 174210 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) rename {scripts => UVTD/scripts}/HeaderGen.py (99%) delete mode 100644 scripts/database_.pkl diff --git a/scripts/HeaderGen.py b/UVTD/scripts/HeaderGen.py similarity index 99% rename from scripts/HeaderGen.py rename to UVTD/scripts/HeaderGen.py index 631050879..2e7e993b0 100755 --- a/scripts/HeaderGen.py +++ b/UVTD/scripts/HeaderGen.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # generate header file for C++, using DRAWF information from .debug files -# e.g., ./HeaderGen.py -s -g -t ../deps/first/Unreal/generated_include/FunctionBodies /mnt/d/Projects/palworld/UnrealGame-Linux-Shipping.debug +# e.g., ./HeaderGen.py -s -g -t ../../deps/first/Unreal/generated_include/FunctionBodies //UnrealGame-Linux-Shipping.debug import os import sys import re diff --git a/scripts/database_.pkl b/scripts/database_.pkl deleted file mode 100644 index 6b9608581f49d80a97633c889eaca8fd17f9b397..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174210 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

2hK;LOm|XNfB!H*w`P9 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 Date: Mon, 26 Feb 2024 21:49:11 -0600 Subject: [PATCH 121/213] remove unused settings so far --- UE4SS/include/SettingsManager.hpp | 1 - UE4SS/src/SettingsManager.cpp | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index 02ad3d89f..86be1a9ca 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -117,7 +117,6 @@ namespace RC int ButtonRight = 3; int WheelUp = 4; int WheelDown = 5; - bool TUIAsInputSource = true; bool TUINerdFont = true; /* SystemStringType TerminalCode = "f120"; diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index eeae83936..f05feaff1 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -133,11 +133,10 @@ namespace RC #ifdef LINUX constexpr static SystemCharType section_tui_features[] = SYSSTR("TUI"); - REGISTER_INT64_SETTING(TUI.ButtonLeft, section_tui_features, ButtonLeft) + /*REGISTER_INT64_SETTING(TUI.ButtonLeft, section_tui_features, ButtonLeft) REGISTER_INT64_SETTING(TUI.ButtonRight, section_tui_features, ButtonRight) REGISTER_INT64_SETTING(TUI.WheelUp, section_tui_features, WheelUp) - REGISTER_INT64_SETTING(TUI.WheelDown, section_tui_features, WheelDown) - REGISTER_BOOL_SETTING(TUI.TUIAsInputSource, section_tui_features, TUIAsInputSource) + REGISTER_INT64_SETTING(TUI.WheelDown, section_tui_features, WheelDown)*/ REGISTER_BOOL_SETTING(TUI.TUINerdFont, section_tui_features, TUINerdFont) /* REGISTER_STRING_SETTING(TUI.TerminalCode, section_tui_features, TerminalCode) From e8d1c3713e13a0913ada2f1b41def040332bf5a3 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 26 Feb 2024 22:27:03 -0600 Subject: [PATCH 122/213] use build.py to package linux release --- .github/workflows/linux-test.yml | 11 +- assets/UE4SS-settings.ini | 21 ++- tools/buildscripts/build.py | 130 ++++++-------- tools/buildscripts/template.py | 298 +++++++++++++++++++++++++++++++ 4 files changed, 378 insertions(+), 82 deletions(-) create mode 100644 tools/buildscripts/template.py diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 38076f3fe..4aead8c48 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -53,10 +53,17 @@ jobs: env: SCCACHE_GHA_ENABLED: "true" RUSTC_WRAPPER: "sccache" + - name: Stripping + run: | + mkdir prepackage + objcopy --only-keep-debug build/Output/Game__Shipping__Linux/UE4SS/bin/libUE4SS.so ./prepackage/libUE4SS.so.debug + cp build/Output/Game__Shipping__Linux/UE4SS/bin/libUE4SS.so ./prepackage/libUE4SS.so + strip --strip-debug --strip-unneeded ./prepackage/libUE4SS.so + cd ./prepackage && objcopy --add-gnu-debuglink=libUE4SS.so.debug ./libUE4SS.so && cd .. - name: Package - run: .github/package.sh + run: python ./tools/buildscripts/build.py package -d ./prepackage -s linux64 - name: Upload Artifacts uses: actions/upload-artifact@v3 with: name: Linux-Release - path: package/ + path: release/zDEV-UE4SS_0.0.0.zip diff --git a/assets/UE4SS-settings.ini b/assets/UE4SS-settings.ini index 20e8657e1..dbed520ec 100644 --- a/assets/UE4SS-settings.ini +++ b/assets/UE4SS-settings.ini @@ -4,7 +4,7 @@ ModsFolderPath = [General] -EnableHotReloadSystem = 1 +EnableHotReloadSystem = $EnableHotReloadSystem ; Whether the cache system for AOBs will be used. ; Default: 1 @@ -60,7 +60,7 @@ IgnoreAllCoreEngineModules = 0 ; Whether to skip generating the "Engine" and "CoreUObject" packages ; Default: 1 -IgnoreEngineAndCoreUObject = 0 +IgnoreEngineAndCoreUObject = $IgnoreEngineAndCoreUObject ; Whether to force all UFUNCTION macros to have "BlueprintCallable" ; Note: This will cause some errors in the generated headers that you will need to manually fix @@ -84,9 +84,9 @@ MakeAllConfigsEngineConfig = 1 [Debug] ; Whether to enable the external UE4SS debug console. -ConsoleEnabled = 1 +ConsoleEnabled = $ConsoleEnabled GuiConsoleEnabled = 1 -GuiConsoleVisible = 1 +GuiConsoleVisible = $GuiConsoleVisible ; Multiplier for Font Size within the Debug Gui ; Default: 1 @@ -95,7 +95,11 @@ GuiConsoleFontScaling = 1 ; The API that will be used to render the GUI debug window. ; Valid values (case-insensitive): dx11, d3d11, opengl ; Default: opengl +${if os == "linux64"} +GraphicsAPI = tui +${elsif os == "win64"} GraphicsAPI = opengl +${endif} [Threads] ; The number of threads that the sig scanner will use (not real cpu threads, can be over your physical & hyperthreading max) @@ -116,7 +120,7 @@ SigScannerMultithreadingModuleSizeThreshold = 16777216 ; The maximum memory usage (in percentage, see Task Manager %) allowed before asset loading (when LoadAllAssetsBefore* is 1) cannot happen. ; Once this percentage is reached, the asset loader will stop loading and whatever operation was in progress (object dump, or cxx generator) will continue. ; Default: 85 -MaxMemoryUsageDuringAssetLoading = 85 +MaxMemoryUsageDuringAssetLoading = $MaxMemoryUsageDuringAssetLoading [Hooks] HookProcessInternal = 1 @@ -135,4 +139,9 @@ FullMemoryDump = 0 [ExperimentalFeatures] ; Only enable these features if you know what you are doing. -GUIUFunctionCaller = 1 +GUIUFunctionCaller = $GUIUFunctionCaller + +${if os == "linux64"} +[TUI] +TUINerdFont=0 +${endif} diff --git a/tools/buildscripts/build.py b/tools/buildscripts/build.py index 3b193dc5e..260c6ddbc 100755 --- a/tools/buildscripts/build.py +++ b/tools/buildscripts/build.py @@ -6,6 +6,7 @@ import subprocess import argparse from datetime import datetime +from template import EnhancedTemplate # Change dir to repo root os.chdir(os.path.join(os.path.dirname(__file__), '..', '..')) @@ -56,6 +57,20 @@ def release_commit(args): github_output('release_tag', version) +def get_os_files(os): + if os == 'win64': + return { + "dev": ['ue4ss.pdb','ue4ss.dll','dwmapi.dll'], + "release": ['ue4ss.dll', 'dwmapi.dll'] + } + elif os == 'linux64': + return { + "dev": ['libue4ss.so', 'libue4ss.so.debug'], + "release": ['libue4ss.so'] + } + else: + raise Exception(f'unknown os: {os}') + def package(args): is_experimental = args.e @@ -104,6 +119,15 @@ def make_staging_dirs(is_dev_release: bool): 'GUIUFunctionCaller': 0, } + settings_to_modify_in_dev = { + 'GuiConsoleVisible': 1, + 'ConsoleEnabled': 1, + 'EnableHotReloadSystem': 1, + 'IgnoreEngineAndCoreUObject': 0, + 'MaxMemoryUsageDuringAssetLoading': 85, + 'GUIUFunctionCaller': 1, + } + change_modstxt = { 'LineTraceMod': 0, } @@ -129,19 +153,25 @@ def make_staging_dirs(is_dev_release: bool): except: shutil.rmtree(path) - # Change UE4SS-settings.ini - config_path = os.path.join(staging_dir, 'UE4SS-settings.ini') + # change UE4SS-settings.ini + config_path_dev = os.path.join(staging_dev, 'UE4SS-settings.ini') + config_path_release = os.path.join(staging_release, 'UE4SS-settings.ini') + + with open(config_path_release, mode='r', encoding='utf-8-sig') as file: + content_template = EnhancedTemplate(file.read()) + + # apply settings + combined_variables = {**settings_to_modify_in_release, "release_type": "release", "os": args.os} + content_release = content_template.substitute(combined_variables) - if not is_dev_release: - with open(config_path, mode='r', encoding='utf-8-sig') as file: - content = file.read() + combined_variables = {**settings_to_modify_in_dev, "release_type": "dev", "os": args.os} + content_dev = content_template.substitute(combined_variables) - for key, value in settings_to_modify_in_release.items(): - pattern = rf'(^{key}\s*=).*?$' - content = re.sub(pattern, rf'\1 {value}', content, flags=re.MULTILINE) + with open(config_path_release, mode='w', encoding='utf-8-sig') as file: + file.write(content_release) - with open(config_path, mode='w', encoding='utf-8-sig') as file: - file.write(content) + with open(config_path_dev, mode='w', encoding='utf-8-sig') as file: + file.write(content_dev) # Change Mods/mods.txt mods_path = os.path.join(staging_dir, 'Mods/mods.txt') @@ -168,83 +198,35 @@ def make_staging_dirs(is_dev_release: bool): os.makedirs(os.path.join(staging_dir, 'Mods', mod_name, 'config'), exist_ok=True) def package_release(is_dev_release: bool): - version = subprocess.check_output(['git', 'describe', '--tags']).decode('utf-8').strip() + try: + version = subprocess.check_output(['git', 'describe', '--tags']).decode('utf-8').strip() + except: + version = '0.0.0' if is_dev_release: + os_files = get_os_files(args.os)['dev'] main_zip_name = f'zDEV-UE4SS_{version}' staging_dir = staging_dev else: + os_files = get_os_files(args.os)['release'] main_zip_name = f'UE4SS_{version}' staging_dir = staging_release - - ue4ss_dll_path = '' - ue4ss_pdb_path = '' - dwmapi_dll_path = '' - # CPP mods paths - cpp_mods_paths = {mod: '' for mod in CPPMods if is_dev_release or CPPMods[mod]['include_in_release']} - + target_paths = [] scan_start_dir = '.' if str(args.d) != 'None': scan_start_dir = str(args.d) for root, dirs, files in os.walk(scan_start_dir): for file in files: - if file.lower() == "ue4ss.dll": - ue4ss_dll_path = os.path.join(root, file) - if file.lower() == "ue4ss.pdb": - ue4ss_pdb_path = os.path.join(root, file) - if file.lower() == "dwmapi.dll": - dwmapi_dll_path = os.path.join(root, file) - # Find CPP Mod DLLs - for mod_name in cpp_mods_paths: - if file.lower() == mod_name.lower() + '.dll': - cpp_mods_paths[mod_name] = os.path.join(root, file) - - # Create the ue4ss folder in staging_dir - ue4ss_dir = os.path.join(staging_dir, 'ue4ss') - os.makedirs(ue4ss_dir, exist_ok=True) - - # Move all files from assets folder to the ue4ss folder except dwmapi.dll and Mods folder - for root, _, files in os.walk('assets'): - for file in files: - if file.lower() != 'dwmapi.dll' and not os.path.join(root, file).startswith(os.path.join('assets', 'Mods')): - src_path = os.path.join(root, file) - dst_path = os.path.join(ue4ss_dir, os.path.relpath(src_path, 'assets')) - os.makedirs(os.path.dirname(dst_path), exist_ok=True) - shutil.copy(src_path, dst_path) - - # Copy the Mods folder separately to avoid nesting - mods_src = os.path.join('assets', 'Mods') - mods_dst = os.path.join(ue4ss_dir, 'Mods') - shutil.copytree(mods_src, mods_dst, dirs_exist_ok=True) - - # Main dll and pdb - shutil.copy(ue4ss_dll_path, ue4ss_dir) - - # CPP mods - for mod_name, dll_path in cpp_mods_paths.items(): - mod_dir = os.path.join(ue4ss_dir, 'Mods', mod_name, 'dlls') - os.makedirs(mod_dir, exist_ok=True) - shutil.copy(dll_path, os.path.join(mod_dir, 'main.dll')) + if file.lower() in os_files: + target_paths.append(os.path.join(root, file)) - # Create config folder if needed - if is_dev_release or CPPMods[mod_name]['include_in_release']: - if CPPMods[mod_name]['create_config']: - os.makedirs(os.path.join(ue4ss_dir, 'Mods', mod_name, 'config'), exist_ok=True) - - # Proxy - shutil.copy(dwmapi_dll_path, staging_dir) + for target in target_paths: + shutil.copy(target, staging_dir) if is_dev_release: - shutil.copy(ue4ss_pdb_path, ue4ss_dir) - if os.path.exists(os.path.join(scan_start_dir, 'docs')): - shutil.copytree('docs', os.path.join(ue4ss_dir, 'Docs')) - - # Move remaining files to the ue4ss dir - dont_move = ['dwmapi.dll', 'docs', 'ue4ss'] - for file in os.listdir(staging_dir): - if file.lower() not in dont_move: - shutil.move(os.path.join(staging_dir, file), os.path.join(ue4ss_dir, file)) + if os.path.exists(os.path.join(staging_dir, 'docs')): + shutil.copytree('docs', os.path.join(staging_dir, 'docs')) output = os.path.join(release_output, main_zip_name) shutil.make_archive(output, 'zip', staging_dir) @@ -281,16 +263,16 @@ def package_release(is_dev_release: bool): def main(): parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='command', required=True) - package_parser = subparsers.add_parser('package') package_parser.add_argument('-e', action='store_true') package_parser.add_argument('-d', action='store') - + # -s for operating system + package_parser.add_argument('-s', '--os', action='store', default='win64', choices=['win64', 'linux64']) release_commit_parser = subparsers.add_parser('release_commit') release_commit_parser.add_argument('username', nargs='?') - args = parser.parse_args() commands[args.command](args) + if __name__ == "__main__": main() diff --git a/tools/buildscripts/template.py b/tools/buildscripts/template.py new file mode 100644 index 000000000..0635ade4e --- /dev/null +++ b/tools/buildscripts/template.py @@ -0,0 +1,298 @@ +import string +import ast +import operator + +class SafeEvaluator: + """A simple and safe expression evaluator supporting basic operations.""" + ALLOWED_OPERATORS = { + ast.Add: operator.add, + ast.Sub: operator.sub, + ast.Mult: operator.mul, + ast.Div: operator.truediv, + ast.Mod: operator.mod, + ast.Pow: operator.pow, + ast.Eq: operator.eq, + ast.NotEq: operator.ne, + ast.Lt: operator.lt, + ast.LtE: operator.le, + ast.Gt: operator.gt, + ast.GtE: operator.ge, + ast.And: operator.and_, + ast.Or: operator.or_, + ast.Not: operator.not_, + } + + def evaluate(self, expression, variables): + """Evaluate an expression safely.""" + try: + tree = ast.parse(expression, mode='eval') + return self._eval(tree.body, variables) + except: + return False + + def _eval(self, node, variables): + if isinstance(node, ast.Expression): + return self._eval(node.body, variables) + elif isinstance(node, ast.BoolOp): + op = self.ALLOWED_OPERATORS[type(node.op)] + return op(*[self._eval(value, variables) for value in node.values]) + elif isinstance(node, ast.BinOp): + return self.ALLOWED_OPERATORS[type(node.op)](self._eval(node.left, variables), self._eval(node.right, variables)) + elif isinstance(node, ast.UnaryOp): + return self.ALLOWED_OPERATORS[type(node.op)](self._eval(node.operand, variables)) + elif isinstance(node, ast.Compare): + left = self._eval(node.left, variables) + right = self._eval(node.comparators[0], variables) + return self.ALLOWED_OPERATORS[type(node.ops[0])](left, right) + elif isinstance(node, ast.Num): + return node.n + elif isinstance(node, ast.Name): + return variables.get(node.id, False) + elif isinstance(node, ast.Constant): + return node.value + else: + return False +import re +class EnhancedTemplate(string.Template): + delimiter = '$' + + def substitute(self, mapping): + template = self.template + evaluator = SafeEvaluator() + processed_template = self._process_conditionals(template, mapping, evaluator) + return string.Template(processed_template).substitute(mapping) + + def _active(self, cond): + for c, _taken, _kw in cond: + if c == False: + return False + return True + + def _process_conditionals(self, template, mapping, evaluator): + # Improved regex to include elsif and else + pattern = re.compile(r'\$\{(if|elsif|else)(.*?)}\r?\n?|\$\{endif\}\r?\n?') + blocks = [] + cursor = 0 + skip_block = False + conditions = [] + for match in pattern.finditer(template): + start, end = match.span() + keyword, condition = match.groups() + + # Add non-conditional text + if cursor < start: + if self._active(conditions): + blocks.append(template[cursor:start]) + + if keyword == 'if': + cursor = end + cond = evaluator.evaluate(condition.strip(), mapping) + # active, taken + conditions.append((cond, cond, 'if')) + elif keyword == 'elsif': + if len(conditions) == 0: + raise ValueError("elseif without a matching if") + c, taken, kw = conditions[-1] + if kw == 'else': + raise ValueError("elseif after else") + if not taken: + cond = evaluator.evaluate(condition.strip(), mapping) + conditions[-1] = (cond, cond, 'elsif') + else: + conditions[-1] = (False, True, 'elsif') + elif keyword == 'else': + if len(conditions) == 0: + raise ValueError("else without a matching if") + c, taken, kw = conditions[-1] + if not taken: + conditions[-1] = (True, True, 'else') + else: + conditions[-1] = (False, True, 'else') + cursor = end + continue + elif match.group(0).strip() == '${endif}': + if len(conditions) == 0: + raise ValueError("endif without a matching if") + conditions.pop() + cursor = end + continue + + if self._active(conditions): + blocks.append(template[end:match.end()]) + + cursor = match.end() + + if len(conditions) > 0: + print(conditions) + raise ValueError("Unmatched if") + # Add any remaining template content + if cursor < len(template): + blocks.append(template[cursor:]) + + return ''.join(blocks) + + + +def test(): + test_cases = [ + # Simple if + {"template": "Test ${if True}passed${endif}.", "variables": {}, "expected": "Test passed."}, + # if with variable + {"template": "${if condition}Condition met.${endif}", "variables": {"condition": True}, "expected": "Condition met."}, + # if-else (with elsif used as else) + {"template": "${if condition}True.${elsif True}False.${endif}", "variables": {"condition": False}, "expected": "False."}, + # Unmatched condition + {"template": "Always visible ${if condition}Condition met.${endif}", "variables": {"condition": False}, "expected": "Always visible "}, + # Complex condition + {"template": "${if num > 10}Greater.${endif}", "variables": {"num": 15}, "expected": "Greater."}, + # Nested conditions not applicable, adding more varied conditions instead + # Multiple conditions with and + {"template": "${if condition1 and condition2}Both true.${endif}", "variables": {"condition1": True, "condition2": True}, "expected": "Both true."}, + # Multiple conditions with or + {"template": "${if condition1 or condition2}At least one true.${endif}", "variables": {"condition1": False, "condition2": True}, "expected": "At least one true."}, + # Inline if + {"template": "Inline ${if condition}passed${endif}, indeed.", "variables": {"condition": True}, "expected": "Inline passed, indeed."}, + # if-elsif-endif + {"template": "${if condition1}First.${elsif condition2}Second.${endif}", "variables": {"condition1": False, "condition2": True}, "expected": "Second."}, + # if-elsif-elsif-endif + {"template": "${if condition1}First.${elsif condition2}Second.${elsif condition3}Third.${endif}", "variables": {"condition1": False, "condition2": False, "condition3": True}, "expected": "Third."}, + # if-false + {"template": "${if condition}True.${endif}", "variables": {"condition": False}, "expected": ""}, + # Expression with variables + {"template": "${if var1 + var2 == 10}Sum is 10.${endif}", "variables": {"var1": 3, "var2": 7}, "expected": "Sum is 10."}, + # Inequality + {"template": "${if var != 5}Not five.${endif}", "variables": {"var": 3}, "expected": "Not five."}, + # Greater than or equal + {"template": "${if var >= 5}Greater or equal.${endif}", "variables": {"var": 5}, "expected": "Greater or equal."}, + # Less than + {"template": "${if var < 5}Less.${endif}", "variables": {"var": 3}, "expected": "Less."}, + # Not condition + {"template": "${if not condition}Not True.${endif}", "variables": {"condition": False}, "expected": "Not True."}, + # And + Or + {"template": "${if condition1 and (condition2 or condition3)}Complex condition met.${endif}", "variables": {"condition1": True, "condition2": False, "condition3": True}, "expected": "Complex condition met."}, + # Inline with text around + {"template": "Start ${if condition}middle${endif} end.", "variables": {"condition": True}, "expected": "Start middle end."}, + # Using else (via elsif as a workaround) + {"template": "${if condition}First.${elsif True}Else.${endif}", "variables": {"condition": False}, "expected": "Else."}, + # Multiple elseif + {"template": "${if condition1}One.${elsif condition2}Two.${elsif condition3}Three.${endif}", "variables": {"condition1": False, "condition2": False, "condition3": True}, "expected": "Three."}, + # Fallback else + {"template": "${if condition1}One.${elsif condition2}Two.${elsif True}Default.${endif}", "variables": {"condition1": False, "condition2": False}, "expected": "Default."}, + { + "template": """Before conditional block. +${if condition1} +Line 1: Condition 1 is true. +${elsif condition2} +Line 2: Condition 2 is true. + Further line still within Condition 2 block. +${elsif condition3} +Line 3: Condition 3 is true. +${else} +None of the conditions were met. +${endif} +After conditional block.""", + "variables": {"condition1": False, "condition2": True, "condition3": False}, + "expected": """Before conditional block. +Line 2: Condition 2 is true. + Further line still within Condition 2 block. +After conditional block.""" + }, + { + "template": """ +${if condition1} + ${if conditionA}A is true.${else}A is false.${endif} +${elsif condition2} + ${if conditionB} + ${if conditionX}B and X are true.${elsif True}B is true, X is default.${endif} + ${else} + B is false. + ${endif} +${else} + ${if conditionC} + C is true. + ${else} + ${if conditionY}Y is true, but C is false.${else}Default case.${endif} + ${endif} +${endif} +""", + "variables": { + "condition1": False, + "condition2": True, + "conditionA": False, + "conditionB": True, + "conditionC": False, + "conditionX": False, + "conditionY": False + }, + "expected": """ + B is true, X is default.""" + }, + { + "template": """ +${if condition1} + Level 1: Condition 1 is true. + ${if conditionA} + Level 2: Condition A is true. + ${if conditionX}Level 3: X.${elsif conditionY}Level 3: Y.${else}Level 3: Neither X nor Y.${endif} + ${elsif conditionB} + Level 2: Condition B is true. + ${if conditionZ}Level 3: Z is true.${else}Level 3: Z is false.${endif} + ${else} + Level 2: Neither A nor B is true. + ${endif} +${elsif condition2} + Level 1: Condition 2 is true. + ${if conditionC} + Level 2: Condition C is true. + ${else} + Level 2: Condition C is false. + ${if conditionW}Level 3: W.${else}Level 3: Not W.${endif} + ${endif} +${else} + Level 1: Neither condition 1 nor 2 is true. + ${if conditionD} + Level 2: D is true. Default path. + ${else} + Level 2: D is false. Ultimate fallback. + ${endif} +${endif} +""", + "variables": { + "condition1": False, + "condition2": True, + "conditionA": False, + "conditionB": False, + "conditionC": False, + "conditionX": False, + "conditionY": False, + "conditionZ": False, + "conditionW": True, + "conditionD": False + }, + "expected": """ + Level 1: Condition 2 is true. + Level 2: Condition C is false. + Level 3: W.""" + } + ] + def normalize_space(s): + # Replace multiple spaces with a single space + s = re.sub(r'[ ]+', ' ', s) + # Replace multiple newlines with a single newline + s = re.sub(r'(\n\s*)+\n', '\n', s) + # Trim leading and trailing whitespace + s = s.strip() + return s + def compare_strings(s1, s2): + normalized_s1 = normalize_space(s1) + normalized_s2 = normalize_space(s2) + + return normalized_s1 == normalized_s2 + for i, test in enumerate(test_cases, 1): + template = EnhancedTemplate(test["template"]) + output = template.substitute(test["variables"]) + assert compare_strings(output.strip(), test["expected"].strip()), f"Test {i} failed. \n\tTemplate: '{test['template']}'\n\tInput: {test['variables']}\n\tExpected: '{test['expected']}',\n\tGot: '{output}'" + print(f"Test {i} passed.") + +if __name__ == "__main__": + test() \ No newline at end of file From 560492351509dbd42fec6454f8f7268171988012 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 26 Feb 2024 22:27:14 -0600 Subject: [PATCH 123/213] remove unused settings --- UE4SS/include/SettingsManager.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index 86be1a9ca..5b97eca21 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -113,10 +113,10 @@ namespace RC #ifdef LINUX struct TUIFeatures { - int ButtonLeft = 1; + /*int ButtonLeft = 1; int ButtonRight = 3; int WheelUp = 4; - int WheelDown = 5; + int WheelDown = 5;*/ bool TUINerdFont = true; /* SystemStringType TerminalCode = "f120"; From a7906a3a403d708223e9b32067fd9304db79fd1d Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 01:01:24 -0600 Subject: [PATCH 124/213] fix tab -> space --- deps/first/Input/src/Handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/Input/src/Handler.cpp b/deps/first/Input/src/Handler.cpp index 29883598d..0165e16ff 100644 --- a/deps/first/Input/src/Handler.cpp +++ b/deps/first/Input/src/Handler.cpp @@ -121,7 +121,7 @@ namespace RC::Input auto Handler::clear_subscribed_key(Key k) -> void { - m_subscribed_keys[k] = false; + m_subscribed_keys[k] = false; } auto Handler::get_allow_input() -> bool From 40f83623c695e8add6874a95e6c3f625c842c9de Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 01:03:05 -0600 Subject: [PATCH 125/213] define new macro for HAS_UI, HAS_GUI, HAS_TUI for if or not support UI, and its type; use HAS_D3D11 and HAS_GLFW for renders --- UE4SS/include/GUI/GUI.hpp | 26 ++++++++++++++++---------- UE4SS/include/GUI/LiveView.hpp | 2 +- UE4SS/include/Mod/CppUserModBase.hpp | 6 +++--- UE4SS/include/SettingsManager.hpp | 9 +++++---- UE4SS/include/UE4SSProgram.hpp | 8 ++++---- UE4SS/src/GUI/GUI.cpp | 24 ++++++++++++++---------- UE4SS/src/GUI/LiveView.cpp | 12 +++++++----- UE4SS/src/Mod/CppUserModBase.cpp | 4 ++-- UE4SS/src/SettingsManager.cpp | 24 ++++++++++++++++-------- UE4SS/src/UE4SSProgram.cpp | 10 +++++----- 10 files changed, 73 insertions(+), 52 deletions(-) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index 7a60a5863..a0f27b1db 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -13,20 +13,25 @@ struct ImGuiSettingsHandler; -#if defined(WIN32) || defined(HAS_GLFW) +#ifndef HAS_TUI +#ifndef HAS_GUI +static_assert(false, "HAS_GUI or HAS_TUI must be defined."); +#endif + #define XOFFSET (-14.0f) #define XDIV 1 #define YDIV 1 + #else -#ifdef LINUX + +#ifdef HAS_GUI +static_assert(false, "HAS_GUI and HAS_TUI cannot be defined at the same time at this moment."); +#endif + #define XOFFSET 0 #define XDIV (6.66f) #define YDIV (21.1f) -#endif -#endif -#ifdef LINUX -#ifndef HAS_GLFW namespace ImGui { static void BeginDisabled(bool disabled = true) @@ -37,7 +42,6 @@ namespace ImGui } } // namespace ImGui #endif -#endif namespace RC::GUI { @@ -45,11 +49,13 @@ namespace RC::GUI enum class GfxBackend { -#ifdef WIN32 +#ifdef HAS_D3D11 DX11, #endif +#ifdef HAS_GLFW GLFW3_OpenGL3, -#ifdef LINUX +#endif +#ifdef HAS_TUI TUI #endif }; @@ -313,7 +319,7 @@ namespace RC::GUI }); } -#ifdef WIN32 +#ifdef HAS_GUI #define ATTACH_ICON(icon, str) icon str #else #define ATTACH_ICON(icon, str) ((icon str) + (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1))) diff --git a/UE4SS/include/GUI/LiveView.hpp b/UE4SS/include/GUI/LiveView.hpp index 7737b3c37..970206f38 100644 --- a/UE4SS/include/GUI/LiveView.hpp +++ b/UE4SS/include/GUI/LiveView.hpp @@ -89,7 +89,7 @@ namespace RC::GUI UObject* m_currently_opened_tree_node{}; std::string m_current_property_value_buffer{}; int64_t m_current_enum_value_buffer{}; -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI float m_top_size{300.0f}; #else float m_top_size{14.0f}; diff --git a/UE4SS/include/Mod/CppUserModBase.hpp b/UE4SS/include/Mod/CppUserModBase.hpp index 924c25922..36dc14ad2 100644 --- a/UE4SS/include/Mod/CppUserModBase.hpp +++ b/UE4SS/include/Mod/CppUserModBase.hpp @@ -5,7 +5,7 @@ #include #include -#ifdef HAS_GUI +#ifdef HAS_UI #include #include #endif @@ -31,7 +31,7 @@ namespace RC class CppUserModBase { protected: -#ifdef HAS_GUI +#ifdef HAS_UI std::vector> GUITabs{}; #endif public: @@ -132,7 +132,7 @@ namespace RC { } -#ifdef HAS_GUI +#ifdef HAS_UI RC_UE4SS_API virtual auto render_tab() -> void{}; protected: diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index 5b97eca21..acad8d298 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -6,7 +6,7 @@ #include #include -#ifdef HAS_GUI +#ifdef HAS_UI #include #endif @@ -65,10 +65,11 @@ namespace RC bool DebugConsoleEnabled{true}; bool DebugConsoleVisible{true}; float DebugGUIFontScaling{1.0}; -#ifdef HAS_GUI -#ifdef WIN32 +#ifdef HAS_UI +#ifdef HAS_GLFW GUI::GfxBackend GraphicsAPI{GUI::GfxBackend::GLFW3_OpenGL3}; -#else +#endif +#ifdef HAS_TUI GUI::GfxBackend GraphicsAPI{GUI::GfxBackend::TUI}; #endif #endif diff --git a/UE4SS/include/UE4SSProgram.hpp b/UE4SS/include/UE4SSProgram.hpp index 9997cb80f..bacc6dc30 100644 --- a/UE4SS/include/UE4SSProgram.hpp +++ b/UE4SS/include/UE4SSProgram.hpp @@ -12,7 +12,7 @@ #endif #include -#ifdef HAS_GUI +#ifdef HAS_UI #include #include #include @@ -111,7 +111,7 @@ namespace RC std::jthread m_event_loop; public: -#ifdef HAS_GUI +#ifdef HAS_UI std::jthread m_render_thread; #endif private: @@ -139,7 +139,7 @@ namespace RC Output::DebugConsoleDevice* m_debug_console_device{}; Output::ConsoleDevice* m_console_device{}; -#ifdef HAS_GUI +#ifdef HAS_UI GUI::DebuggingGUI m_debugging_gui{}; #endif @@ -249,7 +249,7 @@ namespace RC return m_input_handler; } #endif -#ifdef HAS_GUI +#ifdef HAS_UI auto get_debugging_ui() -> GUI::DebuggingGUI& { return m_debugging_gui; diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 6304744bd..ef7315959 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -10,12 +10,16 @@ #ifdef WIN32 #include +#ifdef HAS_D3D11 #include -#include -#else +#endif +#endif + #ifdef HAS_GLFW #include #endif + +#ifdef HAS_TUI #include #endif @@ -25,11 +29,11 @@ #undef TEXT #endif -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI #include "Roboto.hpp" #include "FaSolid900.hpp" #include -#else // LINUX +#elif defined(HAS_TUI) #include #endif @@ -224,7 +228,7 @@ namespace RC::GUI ImGuiStyle& style = ImGui::GetStyle(); style.WindowPadding = ImVec2(8, 8); -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI style.FramePadding = ImVec2(12, 5); #else style.FramePadding = ImVec2(0.5f, 0.5f); @@ -282,7 +286,7 @@ namespace RC::GUI style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.55f, 0.22f, 0.45f, 1.00f); style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); style.Colors[ImGuiCol_Button] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); #else @@ -299,7 +303,7 @@ namespace RC::GUI style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.92f, 0.24f, 0.84f, 0.67f); style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.92f, 0.24f, 0.84f, 0.95f); style.Colors[ImGuiCol_Tab] = ImVec4(0.51f, 0.23f, 0.42f, 1.00f); -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI style.Colors[ImGuiCol_TabHovered] = ImVec4(0.59f, 0.22f, 0.48f, 1.00f); style.Colors[ImGuiCol_TabActive] = ImVec4(0.63f, 0.24f, 0.50f, 1.00f); #else @@ -514,7 +518,7 @@ namespace RC::GUI io.Fonts->Clear(); float base_font_size = 14 * UE4SSProgram::settings_manager.Debug.DebugGUIFontScaling; -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI ImFontConfig font_cfg; font_cfg.FontDataOwnedByAtlas = false; // if true it will try to free memory and fail io.Fonts->AddFontFromMemoryTTF(Roboto, sizeof(Roboto), base_font_size, &font_cfg); @@ -545,7 +549,7 @@ namespace RC::GUI { switch (backend) { -#ifdef WIN32 +#ifdef HAS_D3D11 case GfxBackend::DX11: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); @@ -560,7 +564,7 @@ namespace RC::GUI m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); break; -#else +#elif defined(HAS_TUI) case GfxBackend::TUI: m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 7c0d15af4..dbf7fdcde 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -49,9 +49,9 @@ #include #include -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI #include -#else +#elif defined(HAS_TUI) #include #endif @@ -3443,15 +3443,17 @@ namespace RC::GUI m_bottom_size = std::max(ImGui::GetFrameHeight(), split_pane_height - m_top_size); // TODO: do we need ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, XOFFSET); on TUI? // TODO: we need false, 0.5f? + // TODO: do we need ImGui_Splitter(false, 0.5f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, ImGui::GetContentRegionMaxAbs().x); for TUI? ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16.0f); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI ImGui::BeginChild("LiveView_TreeView", {-16.0f, m_top_size}, true); #else ImGui::BeginChild("LiveView_TreeView", {0, m_top_size}, true); #endif + auto do_iteration = [&](int32_t int_data_1 = 0, int32_t int_data_2 = 0) { ((*this).*((*this).m_object_iterator))(int_data_1, int_data_2, [&](UObject* object) { auto tree_node_name = std::string{get_object_full_name(object)}; @@ -3585,7 +3587,7 @@ namespace RC::GUI } static int num_columns = 3; -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, {2.0f, 2.0f}); #endif // TODO: do we need ImGuiTableFlags_NoPadOuterX? @@ -3672,7 +3674,7 @@ namespace RC::GUI } ImGui::EndTable(); -#if defined(WIN32) || defined(HAS_GLFW) +#ifdef HAS_GUI ImGui::PopStyleVar(); #endif } diff --git a/UE4SS/src/Mod/CppUserModBase.cpp b/UE4SS/src/Mod/CppUserModBase.cpp index 45a7decb1..c5f30efb7 100644 --- a/UE4SS/src/Mod/CppUserModBase.cpp +++ b/UE4SS/src/Mod/CppUserModBase.cpp @@ -14,7 +14,7 @@ namespace RC CppUserModBase::~CppUserModBase() { -#ifdef HAS_GUI +#ifdef HAS_UI for (const auto& tab : GUITabs) { if (tab) @@ -51,7 +51,7 @@ namespace RC #endif } -#ifdef HAS_GUI +#ifdef HAS_UI auto CppUserModBase::register_tab(UEStringViewType tab_name, GUI::GUITab::RenderFunctionType render_function) -> void { auto& tab = GUITabs.emplace_back(std::make_shared(tab_name, render_function, this)); diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index f05feaff1..b318cebde 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -84,25 +84,33 @@ namespace RC REGISTER_BOOL_SETTING(Debug.DebugConsoleVisible, section_debug, GuiConsoleVisible) REGISTER_FLOAT_SETTING(Debug.DebugGUIFontScaling, section_debug, GuiConsoleFontScaling) -#ifdef HAS_GUI +#ifdef HAS_UI SystemStringType graphics_api_string{}; REGISTER_STRING_SETTING(graphics_api_string, section_debug, GraphicsAPI) -#ifdef WIN32 - if (String::iequal(graphics_api_string, SYSSTR("DX11")) || String::iequal(graphics_api_string, SYSSTR("D3D11"))) + if (false) + { + } +#ifdef HAS_D3D11 + else if (String::iequal(graphics_api_string, SYSSTR("DX11")) || String::iequal(graphics_api_string, SYSSTR("D3D11"))) { Debug.GraphicsAPI = GUI::GfxBackend::DX11; } +#endif +#ifdef HAS_GLFW else if (String::iequal(graphics_api_string, SYSSTR("OpenGL"))) { Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; } -#else -#ifdef HAS_GLFW - Debug.GraphicsAPI = GUI::GfxBackend::GLFW3_OpenGL3; -#else - Debug.GraphicsAPI = GUI::GfxBackend::TUI; #endif +#ifdef HAS_TUI + else if (String::iequal(graphics_api_string, SYSSTR("TUI"))) + { + Debug.GraphicsAPI = GUI::GfxBackend::TUI; + } #endif + else + { + } #endif REGISTER_INT64_SETTING(Debug.LiveViewObjectsPerGroup, section_debug, LiveViewObjectsPerGroup); diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index fbef643f7..7cfae2853 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -17,7 +17,7 @@ #include #include #include -#ifdef HAS_GUI +#ifdef HAS_UI #include #include #include @@ -194,7 +194,7 @@ namespace RC m_crash_dumper.set_full_memory_dump(settings_manager.CrashDump.FullMemoryDump); #endif -#ifdef HAS_GUI +#ifdef HAS_UI m_debugging_gui.set_gfx_backend(settings_manager.Debug.GraphicsAPI); #endif @@ -208,7 +208,7 @@ namespace RC create_simple_console(); -#ifdef HAS_GUI +#ifdef HAS_UI if (settings_manager.Debug.DebugConsoleEnabled) { m_console_device = &Output::set_default_devices(); @@ -853,7 +853,7 @@ namespace RC /* UObjectArray::AddUObjectCreateListener(&FUEDeathListener::UEDeathListener); //*/ -#ifdef HAS_GUI +#ifdef HAS_UI if (settings_manager.Debug.DebugConsoleEnabled) { if (settings_manager.General.UseUObjectArrayCache) @@ -1542,7 +1542,7 @@ namespace RC UAssetRegistry::FreeAllForcefullyLoadedAssets(); Output::send(SYSSTR("SDK generated in {} seconds.\n"), generator_duration); } -#ifdef HAS_GUI +#ifdef HAS_UI auto UE4SSProgram::stop_render_thread() -> void { if (m_render_thread.joinable()) From 351fb56c633f5072799dca6cc9a3544af7d0e290 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 01:03:17 -0600 Subject: [PATCH 126/213] style --- UVTD/src/MemberVarsWrapperGenerator.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/UVTD/src/MemberVarsWrapperGenerator.cpp b/UVTD/src/MemberVarsWrapperGenerator.cpp index afaa6a897..93670d3a0 100644 --- a/UVTD/src/MemberVarsWrapperGenerator.cpp +++ b/UVTD/src/MemberVarsWrapperGenerator.cpp @@ -151,7 +151,9 @@ namespace RC::UVTD wrapper_src_dumper.send(STR("}\n\n")); } - macro_setter_dumper.send(STR("if (auto val = parser.get_int64(SYSSTR(\"{}\"), SYSSTR(\"{}\"), -1); val != -1)\n"), final_class_name, final_variable_name); + macro_setter_dumper.send(STR("if (auto val = parser.get_int64(SYSSTR(\"{}\"), SYSSTR(\"{}\"), -1); val != -1)\n"), + final_class_name, + final_variable_name); macro_setter_dumper.send(STR(" Unreal::{}::MemberOffsets.emplace(STR(\"{}\"), static_cast(val));\n"), final_class_name, final_variable_name); From dd385745df2c12722e4e852fd74fc2ae1b15949d Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 01:19:08 -0600 Subject: [PATCH 127/213] graceful exit, avoid crash or deadlock --- UE4SS/src/EntryLinux.cpp | 9 ++++----- UE4SS/src/GUI/TUI.cpp | 6 ------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/EntryLinux.cpp index 260c40cea..56cbdad39 100644 --- a/UE4SS/src/EntryLinux.cpp +++ b/UE4SS/src/EntryLinux.cpp @@ -18,6 +18,7 @@ using namespace RC; pthread_t ue4ss_mainthread; +static bool UE4SSInited = false; void UE4SS_Start() { @@ -41,7 +42,7 @@ void UE4SS_Start() #endif auto ue4sspath = to_system_string(dl_info.dli_fname); auto program = new UE4SSProgram(ue4sspath, {}); - + UE4SSInited = true; // use pthread here pthread_create( &ue4ss_mainthread, @@ -49,7 +50,6 @@ void UE4SS_Start() [](void* arg) -> void* { auto program = (UE4SSProgram*)arg; program->init(); - fprintf(stderr, "inited in thread\n"); if (auto e = program->get_error_object(); e->has_error()) { // If the output system errored out then use printf_s as a fallback @@ -68,8 +68,6 @@ void UE4SS_Start() program); } -static bool UE4SSInited = false; - /* void __attribute__((constructor)) UE4SS_Init() { // It may not init in correct order.. @@ -286,7 +284,8 @@ void __attribute__((destructor)) UE4SS_End() { if (UE4SSInited) { - // UE4SSProgram::static_cleanup(); + // invoke cleanup when the program ends + UE4SSProgram::static_cleanup(); UE4SSInited = false; } } diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/TUI.cpp index 71d7cfb66..d99920ddc 100644 --- a/UE4SS/src/GUI/TUI.cpp +++ b/UE4SS/src/GUI/TUI.cpp @@ -29,12 +29,6 @@ namespace RC::GUI setbuf(stderr, NULL); fprintf(stderr, "Backend_TUI::init\n"); fflush(stderr); - atexit([]() { - // ensure that the screen is destroyed - // ImTui_ImplNcurses_Shutdown(); do not call this here, we may not in UI thread - // set shutdown flag to allow async shutdown on UI thread - tui_shutdown = true; - }); } void Backend_TUI::imgui_backend_newframe() From 7ea03dbee90a6783f85f7b1dd2430229b11b0dcc Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 01:30:22 -0600 Subject: [PATCH 128/213] this should be == 0 --- deps/first/File/src/FileType/WinFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/File/src/FileType/WinFile.cpp b/deps/first/File/src/FileType/WinFile.cpp index d626da606..6a884eda6 100644 --- a/deps/first/File/src/FileType/WinFile.cpp +++ b/deps/first/File/src/FileType/WinFile.cpp @@ -35,7 +35,7 @@ namespace RC::File } else { - if (DeleteFileA(file_path_and_name.string().c_str()) != 0) + if (DeleteFileA(to_system_string(file_path_and_name).c_str()) == 0) { THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::delete_file] Was unable to delete file, error: {}", GetLastError())) } From 2024c54bbe8c30e985cb506429661781223a740a Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 01:31:38 -0600 Subject: [PATCH 129/213] should judge based on systemchartype, not io type --- deps/first/File/src/FileType/WinFile.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deps/first/File/src/FileType/WinFile.cpp b/deps/first/File/src/FileType/WinFile.cpp index 6a884eda6..c8feed08b 100644 --- a/deps/first/File/src/FileType/WinFile.cpp +++ b/deps/first/File/src/FileType/WinFile.cpp @@ -26,9 +26,9 @@ namespace RC::File auto WinFile::delete_file(const std::filesystem::path& file_path_and_name) -> void { - if constexpr (sizeof(CharType) > 1) + if constexpr (sizeof(SystemCharType) > 1) { - if (DeleteFileW(file_path_and_name.wstring().c_str()) == 0) + if (DeleteFileW(to_system_string(file_path_and_name).c_str()) == 0) { THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::delete_file] Was unable to delete file, error: {}", GetLastError())) } @@ -624,9 +624,9 @@ namespace RC::File WinFile file{}; // This very badly named API may create a new file or it may not but it will always open a file (unless there's an error) - if constexpr (sizeof(CharType) > 1) + if constexpr (sizeof(SystemCharType) > 1) { - file.set_file(CreateFileW(file_name_and_path.wstring().c_str(), + file.set_file(CreateFileW(to_system_string(file_name_and_path).c_str(), desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, @@ -636,7 +636,7 @@ namespace RC::File } else { - file.set_file(CreateFileA(file_name_and_path.string().c_str(), + file.set_file(CreateFileA(to_system_string(file_name_and_path).c_str(), desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, From c2fdffa2e7f54188176b76732a3f4d29942d2770 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 01:33:04 -0600 Subject: [PATCH 130/213] no access to system_string here --- deps/first/File/src/FileType/WinFile.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deps/first/File/src/FileType/WinFile.cpp b/deps/first/File/src/FileType/WinFile.cpp index c8feed08b..c1f247fa8 100644 --- a/deps/first/File/src/FileType/WinFile.cpp +++ b/deps/first/File/src/FileType/WinFile.cpp @@ -28,14 +28,14 @@ namespace RC::File { if constexpr (sizeof(SystemCharType) > 1) { - if (DeleteFileW(to_system_string(file_path_and_name).c_str()) == 0) + if (DeleteFileW(file_path_and_name.wstring().c_str()) == 0) { THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::delete_file] Was unable to delete file, error: {}", GetLastError())) } } else { - if (DeleteFileA(to_system_string(file_path_and_name).c_str()) == 0) + if (DeleteFileA(file_path_and_name.string().c_str()) == 0) { THROW_INTERNAL_FILE_ERROR(std::format("[WinFile::delete_file] Was unable to delete file, error: {}", GetLastError())) } @@ -626,7 +626,7 @@ namespace RC::File // This very badly named API may create a new file or it may not but it will always open a file (unless there's an error) if constexpr (sizeof(SystemCharType) > 1) { - file.set_file(CreateFileW(to_system_string(file_name_and_path).c_str(), + file.set_file(CreateFileW(file_name_and_path.wstring().c_str(), desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, @@ -636,7 +636,7 @@ namespace RC::File } else { - file.set_file(CreateFileA(to_system_string(file_name_and_path).c_str(), + file.set_file(CreateFileA(file_name_and_path.string().c_str(), desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, From ca5f0b431321cb31815f361f321395463a95168c Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 02:32:10 -0600 Subject: [PATCH 131/213] destroy window (seems required for linux) --- UE4SS/src/GUI/GLFW3_OpenGL3.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp index 77e238d1b..1413bcdd8 100644 --- a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp +++ b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp @@ -80,6 +80,8 @@ namespace RC::GUI { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); + glfwDestroyWindow(m_window); + m_window = nullptr; } auto Backend_GLFW3_OpenGL3::cleanup() -> void From c7b4c0c7e0e31af98cf9a25e36cb1d653085231b Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 15:12:55 -0600 Subject: [PATCH 132/213] add Input support for glfw in case we want to ship this as default --- UE4SS/src/GUI/GLFW3_OpenGL3.cpp | 22 ++ .../Input/Platform/GLFW3InputSource.hpp | 28 ++ .../Input/src/Platform/GLFW3InputSource.cpp | 349 ++++++++++++++++++ deps/first/Input/src/PlatformInit.cpp | 6 + 4 files changed, 405 insertions(+) create mode 100644 deps/first/Input/include/Input/Platform/GLFW3InputSource.hpp create mode 100644 deps/first/Input/src/Platform/GLFW3InputSource.cpp diff --git a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp index 1413bcdd8..afbbf968f 100644 --- a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp +++ b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp @@ -10,6 +10,9 @@ #include #include +#include +#include + namespace RC::GUI { static void glfw_error_callback(int error, const char* description) @@ -17,6 +20,8 @@ namespace RC::GUI Output::send(SYSSTR("Glfw Error {}: {}\n"), error, description); } + static std::shared_ptr g_input_source; + auto Backend_GLFW3_OpenGL3::init() -> void { // Setup window @@ -46,6 +51,22 @@ namespace RC::GUI throw std::runtime_error{"Was unable to initialize glad"}; } + if (auto source = Input::Handler::get_input_source("GLFW3")) + { + g_input_source = std::dynamic_pointer_cast(source); + glfwSetKeyCallback(m_window, [](GLFWwindow* window, int key, int scancode, int action, int mods) { + // map keys to windows'definition + if (g_input_source) + { + g_input_source->receive_input(key, action, mods); + } + }); + } + else + { + throw std::runtime_error{"Was unable to get GLFW3 input source"}; + } + int left, top, right, bottom; glfwGetWindowFrameSize(m_window, &left, &top, &right, &bottom); glfwSetWindowSize(m_window, 1280 - left - right, 800 - top - bottom); @@ -82,6 +103,7 @@ namespace RC::GUI ImGui_ImplGlfw_Shutdown(); glfwDestroyWindow(m_window); m_window = nullptr; + g_input_source = nullptr; } auto Backend_GLFW3_OpenGL3::cleanup() -> void diff --git a/deps/first/Input/include/Input/Platform/GLFW3InputSource.hpp b/deps/first/Input/include/Input/Platform/GLFW3InputSource.hpp new file mode 100644 index 000000000..333673b5f --- /dev/null +++ b/deps/first/Input/include/Input/Platform/GLFW3InputSource.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +namespace RC::Input +{ + + class GLFW3InputSource : public QueueInputSource + { + public: + auto begin_frame() -> void; + auto receive_input(int key, int action, int mods) -> void; + auto end_frame() -> void; + + private: + Key m_translate_key[512]; + + public: + auto is_available() -> bool override; + const char* get_name() override + { + return "GLFW3"; + } + GLFW3InputSource(); + }; + +} // namespace RC::Input diff --git a/deps/first/Input/src/Platform/GLFW3InputSource.cpp b/deps/first/Input/src/Platform/GLFW3InputSource.cpp new file mode 100644 index 000000000..776276513 --- /dev/null +++ b/deps/first/Input/src/Platform/GLFW3InputSource.cpp @@ -0,0 +1,349 @@ +#include + +#define GLFW_KEY_SPACE 32 + +#define GLFW_KEY_APOSTROPHE 39 /* ' */ + +#define GLFW_KEY_COMMA 44 /* , */ + +#define GLFW_KEY_MINUS 45 /* - */ + +#define GLFW_KEY_PERIOD 46 /* . */ + +#define GLFW_KEY_SLASH 47 /* / */ + +#define GLFW_KEY_0 48 + +#define GLFW_KEY_1 49 + +#define GLFW_KEY_2 50 + +#define GLFW_KEY_3 51 + +#define GLFW_KEY_4 52 + +#define GLFW_KEY_5 53 + +#define GLFW_KEY_6 54 + +#define GLFW_KEY_7 55 + +#define GLFW_KEY_8 56 + +#define GLFW_KEY_9 57 + +#define GLFW_KEY_SEMICOLON 59 /* ; */ + +#define GLFW_KEY_EQUAL 61 /* = */ + +#define GLFW_KEY_A 65 + +#define GLFW_KEY_B 66 + +#define GLFW_KEY_C 67 + +#define GLFW_KEY_D 68 + +#define GLFW_KEY_E 69 + +#define GLFW_KEY_F 70 + +#define GLFW_KEY_G 71 + +#define GLFW_KEY_H 72 + +#define GLFW_KEY_I 73 + +#define GLFW_KEY_J 74 + +#define GLFW_KEY_K 75 + +#define GLFW_KEY_L 76 + +#define GLFW_KEY_M 77 + +#define GLFW_KEY_N 78 + +#define GLFW_KEY_O 79 + +#define GLFW_KEY_P 80 + +#define GLFW_KEY_Q 81 + +#define GLFW_KEY_R 82 + +#define GLFW_KEY_S 83 + +#define GLFW_KEY_T 84 + +#define GLFW_KEY_U 85 + +#define GLFW_KEY_V 86 + +#define GLFW_KEY_W 87 + +#define GLFW_KEY_X 88 + +#define GLFW_KEY_Y 89 + +#define GLFW_KEY_Z 90 + +#define GLFW_KEY_LEFT_BRACKET 91 /* [ */ + +#define GLFW_KEY_BACKSLASH 92 /* \ */ + +#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */ + +#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */ + +#define GLFW_KEY_WORLD_1 161 /* non-US #1 */ + +#define GLFW_KEY_WORLD_2 162 /* non-US #2 */ + +#define GLFW_KEY_ESCAPE 256 + +#define GLFW_KEY_ENTER 257 + +#define GLFW_KEY_TAB 258 + +#define GLFW_KEY_BACKSPACE 259 + +#define GLFW_KEY_INSERT 260 + +#define GLFW_KEY_DELETE 261 + +#define GLFW_KEY_RIGHT 262 + +#define GLFW_KEY_LEFT 263 + +#define GLFW_KEY_DOWN 264 + +#define GLFW_KEY_UP 265 + +#define GLFW_KEY_PAGE_UP 266 + +#define GLFW_KEY_PAGE_DOWN 267 + +#define GLFW_KEY_HOME 268 + +#define GLFW_KEY_END 269 + +#define GLFW_KEY_CAPS_LOCK 280 + +#define GLFW_KEY_SCROLL_LOCK 281 + +#define GLFW_KEY_NUM_LOCK 282 + +#define GLFW_KEY_PRINT_SCREEN 283 + +#define GLFW_KEY_PAUSE 284 + +#define GLFW_KEY_F1 290 + +#define GLFW_KEY_F2 291 + +#define GLFW_KEY_F3 292 + +#define GLFW_KEY_F4 293 + +#define GLFW_KEY_F5 294 + +#define GLFW_KEY_F6 295 + +#define GLFW_KEY_F7 296 + +#define GLFW_KEY_F8 297 + +#define GLFW_KEY_F9 298 + +#define GLFW_KEY_F10 299 + +#define GLFW_KEY_F11 300 + +#define GLFW_KEY_F12 301 + +#define GLFW_KEY_F13 302 + +#define GLFW_KEY_F14 303 + +#define GLFW_KEY_F15 304 + +#define GLFW_KEY_F16 305 + +#define GLFW_KEY_F17 306 + +#define GLFW_KEY_F18 307 + +#define GLFW_KEY_F19 308 + +#define GLFW_KEY_F20 309 + +#define GLFW_KEY_F21 310 + +#define GLFW_KEY_F22 311 + +#define GLFW_KEY_F23 312 + +#define GLFW_KEY_F24 313 + +#define GLFW_KEY_F25 314 + +#define GLFW_KEY_KP_0 320 + +#define GLFW_KEY_KP_1 321 + +#define GLFW_KEY_KP_2 322 + +#define GLFW_KEY_KP_3 323 + +#define GLFW_KEY_KP_4 324 + +#define GLFW_KEY_KP_5 325 + +#define GLFW_KEY_KP_6 326 + +#define GLFW_KEY_KP_7 327 + +#define GLFW_KEY_KP_8 328 + +#define GLFW_KEY_KP_9 329 + +#define GLFW_KEY_KP_DECIMAL 330 + +#define GLFW_KEY_KP_DIVIDE 331 + +#define GLFW_KEY_KP_MULTIPLY 332 + +#define GLFW_KEY_KP_SUBTRACT 333 + +#define GLFW_KEY_KP_ADD 334 + +#define GLFW_KEY_KP_ENTER 335 + +#define GLFW_KEY_KP_EQUAL 336 + +#define GLFW_KEY_LEFT_SHIFT 340 + +#define GLFW_KEY_LEFT_CONTROL 341 + +#define GLFW_KEY_LEFT_ALT 342 + +#define GLFW_KEY_LEFT_SUPER 343 + +#define GLFW_KEY_RIGHT_SHIFT 344 + +#define GLFW_KEY_RIGHT_CONTROL 345 + +#define GLFW_KEY_RIGHT_ALT 346 + +#define GLFW_KEY_RIGHT_SUPER 347 + +#define GLFW_KEY_MENU 348 + +#define GLFW_KEY_LAST GLFW_KEY_MENU + +#define GLFW_MOD_SHIFT 0x0001 +#define GLFW_MOD_CONTROL 0x0002 +#define GLFW_MOD_ALT 0x0004 + +#define GLFW_RELEASE 0 +#define GLFW_PRESS 1 +#define GLFW_REPEAT 2 + +namespace RC::Input +{ + auto GLFW3InputSource::begin_frame() -> void + { + } + + auto GLFW3InputSource::receive_input(int key, int action, int mods) -> void + { + auto modifier_keys = ModifierKeys{}; + modifier_keys |= (mods & GLFW_MOD_CONTROL ? ModifierKey::CONTROL : ModifierKey::MOD_KEY_START_OF_ENUM); + modifier_keys |= (mods & GLFW_MOD_SHIFT ? ModifierKey::SHIFT : ModifierKey::MOD_KEY_START_OF_ENUM); + modifier_keys |= (mods & GLFW_MOD_ALT ? ModifierKey::ALT : ModifierKey::MOD_KEY_START_OF_ENUM); + if (action == GLFW_PRESS) + { + // translate key + Key input = m_translate_key[key]; + if (input != RESERVED_START_OF_ENUM) + { + push_input_event({input, modifier_keys}); + } + } + } + + auto GLFW3InputSource::end_frame() -> void + { + } + + auto GLFW3InputSource::is_available() -> bool + { + return true; + } + + GLFW3InputSource::GLFW3InputSource() + { + // init to 0 + for (int i = 0; i < 512; ++i) + { + m_translate_key[i] = static_cast(0); + } + // Alphanumeric keys + for (int key = GLFW_KEY_A; key <= GLFW_KEY_Z; ++key) + { + m_translate_key[key] = static_cast(key); + } + for (int key = GLFW_KEY_0; key <= GLFW_KEY_9; ++key) + { + m_translate_key[key] = static_cast(key + 22); + } + + // Symbol keys + m_translate_key[GLFW_KEY_SPACE] = Key::SPACE; + m_translate_key[GLFW_KEY_APOSTROPHE] = Key::OEM_SEVEN; + m_translate_key[GLFW_KEY_COMMA] = Key::OEM_COMMA; + m_translate_key[GLFW_KEY_MINUS] = Key::OEM_MINUS; + m_translate_key[GLFW_KEY_PERIOD] = Key::OEM_PERIOD; + m_translate_key[GLFW_KEY_SLASH] = Key::OEM_TWO; + m_translate_key[GLFW_KEY_SEMICOLON] = Key::OEM_ONE; + m_translate_key[GLFW_KEY_EQUAL] = Key::OEM_PLUS; + m_translate_key[GLFW_KEY_LEFT_BRACKET] = Key::OEM_FOUR; + m_translate_key[GLFW_KEY_BACKSLASH] = Key::OEM_FIVE; + m_translate_key[GLFW_KEY_RIGHT_BRACKET] = Key::OEM_SIX; + m_translate_key[GLFW_KEY_GRAVE_ACCENT] = Key::OEM_THREE; + + // Control keys + m_translate_key[GLFW_KEY_ESCAPE] = Key::ESCAPE; + m_translate_key[GLFW_KEY_ENTER] = Key::RETURN; + m_translate_key[GLFW_KEY_TAB] = Key::TAB; + m_translate_key[GLFW_KEY_BACKSPACE] = Key::BACKSPACE; + m_translate_key[GLFW_KEY_INSERT] = Key::INS; + m_translate_key[GLFW_KEY_DELETE] = Key::DEL; + m_translate_key[GLFW_KEY_RIGHT] = Key::RIGHT_ARROW; + m_translate_key[GLFW_KEY_LEFT] = Key::LEFT_ARROW; + m_translate_key[GLFW_KEY_DOWN] = Key::DOWN_ARROW; + m_translate_key[GLFW_KEY_UP] = Key::UP_ARROW; + m_translate_key[GLFW_KEY_PAGE_UP] = Key::PAGE_UP; + m_translate_key[GLFW_KEY_PAGE_DOWN] = Key::PAGE_DOWN; + m_translate_key[GLFW_KEY_HOME] = Key::HOME; + m_translate_key[GLFW_KEY_END] = Key::END; + m_translate_key[GLFW_KEY_CAPS_LOCK] = Key::CAPS_LOCK; + m_translate_key[GLFW_KEY_SCROLL_LOCK] = Key::SCROLL_LOCK; + m_translate_key[GLFW_KEY_NUM_LOCK] = Key::NUM_LOCK; + m_translate_key[GLFW_KEY_PRINT_SCREEN] = Key::PRINT_SCREEN; + m_translate_key[GLFW_KEY_PAUSE] = Key::PAUSE; + + // Function keys + for (int key = GLFW_KEY_F1; key <= GLFW_KEY_F25; ++key) + { + m_translate_key[key] = static_cast(key + 111); + } + + // Numeric keypad + for (int key = GLFW_KEY_KP_0; key <= GLFW_KEY_KP_EQUAL; ++key) + { + m_translate_key[key] = static_cast(key + 208); + } + } +} // namespace RC::Input \ No newline at end of file diff --git a/deps/first/Input/src/PlatformInit.cpp b/deps/first/Input/src/PlatformInit.cpp index 6241c548f..7d34ac42b 100644 --- a/deps/first/Input/src/PlatformInit.cpp +++ b/deps/first/Input/src/PlatformInit.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace RC::Input { @@ -10,7 +11,12 @@ namespace RC::Input register_input_source(std::make_shared(L"ConsoleWindowClass", L"UnrealWindow")); #endif #ifdef LINUX +#ifdef HAS_TUI register_input_source(std::make_shared()); +#endif +#ifdef HAS_GLFW + register_input_source(std::make_shared()); +#endif #endif } } // namespace RC::Input \ No newline at end of file From 2df257fe7aa57a7b3d5806e7b7f3491d3b357787 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 15:56:40 -0600 Subject: [PATCH 133/213] only use glfw input on linux --- UE4SS/src/GUI/GLFW3_OpenGL3.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp index afbbf968f..b3c89dd0d 100644 --- a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp +++ b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp @@ -11,7 +11,10 @@ #include #include + +#ifdef LINUX #include +#endif namespace RC::GUI { @@ -20,7 +23,9 @@ namespace RC::GUI Output::send(SYSSTR("Glfw Error {}: {}\n"), error, description); } +#ifdef LINUX static std::shared_ptr g_input_source; +#endif auto Backend_GLFW3_OpenGL3::init() -> void { @@ -51,6 +56,12 @@ namespace RC::GUI throw std::runtime_error{"Was unable to initialize glad"}; } + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + throw std::runtime_error{"Was unable to initialize glad"}; + } + +#ifdef LINUX if (auto source = Input::Handler::get_input_source("GLFW3")) { g_input_source = std::dynamic_pointer_cast(source); @@ -66,6 +77,7 @@ namespace RC::GUI { throw std::runtime_error{"Was unable to get GLFW3 input source"}; } +#endif int left, top, right, bottom; glfwGetWindowFrameSize(m_window, &left, &top, &right, &bottom); @@ -103,7 +115,10 @@ namespace RC::GUI ImGui_ImplGlfw_Shutdown(); glfwDestroyWindow(m_window); m_window = nullptr; + +#ifdef LINUX g_input_source = nullptr; +#endif } auto Backend_GLFW3_OpenGL3::cleanup() -> void From ce3ffaabfac1d1ac6e723d0d9fefc64482f6bbf4 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 27 Feb 2024 17:13:41 -0600 Subject: [PATCH 134/213] no need to throw --- UE4SS/src/GUI/GLFW3_OpenGL3.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp index b3c89dd0d..663becc37 100644 --- a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp +++ b/UE4SS/src/GUI/GLFW3_OpenGL3.cpp @@ -73,10 +73,6 @@ namespace RC::GUI } }); } - else - { - throw std::runtime_error{"Was unable to get GLFW3 input source"}; - } #endif int left, top, right, bottom; From 593f6b649c560554a3b459e3f2ded22346a8e607 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 28 Feb 2024 16:28:46 -0600 Subject: [PATCH 135/213] use local fstring --- UE4SS/src/LuaType/LuaFString.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/LuaType/LuaFString.cpp b/UE4SS/src/LuaType/LuaFString.cpp index 36b9bc153..0b4bdcbe2 100644 --- a/UE4SS/src/LuaType/LuaFString.cpp +++ b/UE4SS/src/LuaType/LuaFString.cpp @@ -54,7 +54,7 @@ namespace RC::LuaType table.add_pair("ToString", [](const LuaMadeSimple::Lua& lua) -> int { auto& lua_object = lua.get_userdata(); - const wchar_t* string_data = lua_object.get_local_cpp_object().GetCharArray(); + const UECharType* string_data = lua_object.get_local_cpp_object().GetCharArray(); if (string_data) { lua.set_string(to_string(UEStringType(string_data))); From b4dc2d72ccd9f00fe75e723003d50023fa1f66e6 Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 29 Feb 2024 01:00:02 -0600 Subject: [PATCH 136/213] remove unnecessary convert --- UE4SS/src/LuaType/LuaFOutputDevice.cpp | 2 +- UE4SS/src/LuaType/LuaUEnum.cpp | 2 +- UE4SS/src/LuaType/LuaUObject.cpp | 2 +- UE4SS/src/LuaType/LuaUScriptStruct.cpp | 2 +- UE4SS/src/Mod/LuaMod.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/UE4SS/src/LuaType/LuaFOutputDevice.cpp b/UE4SS/src/LuaType/LuaFOutputDevice.cpp index 7c8566c17..e6f68c15e 100644 --- a/UE4SS/src/LuaType/LuaFOutputDevice.cpp +++ b/UE4SS/src/LuaType/LuaFOutputDevice.cpp @@ -65,7 +65,7 @@ No overload found for function 'Log'. } auto message = lua.get_string(); - lua_object.get_remote_cpp_object()->Log(to_ue(to_system(message)).c_str()); + lua_object.get_remote_cpp_object()->Log(to_ue_string(message).c_str()); return 0; }); diff --git a/UE4SS/src/LuaType/LuaUEnum.cpp b/UE4SS/src/LuaType/LuaUEnum.cpp index ebe3480b6..ea4bcaa95 100644 --- a/UE4SS/src/LuaType/LuaUEnum.cpp +++ b/UE4SS/src/LuaType/LuaUEnum.cpp @@ -243,7 +243,7 @@ No overload found for function 'UEnum.EditNameAt'. lua.throw_error("'UEnum.EditNameAt' could not load parameter for \"NewName\""); } - Unreal::FName new_key = Unreal::FName(to_ue(to_system(param_new_name)), Unreal::FNAME_Add); + Unreal::FName new_key = Unreal::FName(to_ue_string(param_new_name), Unreal::FNAME_Add); lua_object.get_remote_cpp_object()->EditNameAt(param_index, new_key); return 0; diff --git a/UE4SS/src/LuaType/LuaUObject.cpp b/UE4SS/src/LuaType/LuaUObject.cpp index d35c3443f..48510e7f8 100644 --- a/UE4SS/src/LuaType/LuaUObject.cpp +++ b/UE4SS/src/LuaType/LuaUObject.cpp @@ -1233,7 +1233,7 @@ No overload found for function 'IsA'. } else if (lua.is_string()) { - auto* object_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue(to_system(lua.get_string()))); + auto* object_class = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue_string(lua.get_string())); lua.set_bool(is_a_internal(lua, object, object_class)); } else diff --git a/UE4SS/src/LuaType/LuaUScriptStruct.cpp b/UE4SS/src/LuaType/LuaUScriptStruct.cpp index 4959d58bb..27043f813 100644 --- a/UE4SS/src/LuaType/LuaUScriptStruct.cpp +++ b/UE4SS/src/LuaType/LuaUScriptStruct.cpp @@ -196,7 +196,7 @@ namespace RC::LuaType { auto& lua_object = lua.get_userdata(); - Unreal::FName property_name = Unreal::FName(to_ue(to_system(lua.get_string()))); + Unreal::FName property_name = Unreal::FName(to_ue_string(lua.get_string())); // Check if property_name is 'NONE' if (property_name.GetComparisonIndex() == 0) diff --git a/UE4SS/src/Mod/LuaMod.cpp b/UE4SS/src/Mod/LuaMod.cpp index e30e6a3ae..0589d099d 100644 --- a/UE4SS/src/Mod/LuaMod.cpp +++ b/UE4SS/src/Mod/LuaMod.cpp @@ -882,7 +882,7 @@ No overload found for function 'StaticFindObject'. // Ignores any params after P1 if (lua.is_string()) { - Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue(to_system(lua.get_string()))); + Unreal::UObject* object = Unreal::UObjectGlobals::StaticFindObject(nullptr, nullptr, to_ue_string(lua.get_string())); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe @@ -984,7 +984,7 @@ No overload found for function 'FindFirstOf'. // Ignores any params after P1 if (lua.is_string()) { - Unreal::UObject* object = Unreal::UObjectGlobals::FindFirstOf(to_ue(to_system(lua.get_string()))); + Unreal::UObject* object = Unreal::UObjectGlobals::FindFirstOf(to_ue_string(lua.get_string())); // Construct a Lua object of type 'UObject' // Auto constructing is nullptr safe From f37be604261d43cd27d56c48b493bde4be21a1cd Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 2 Mar 2024 03:38:30 -0600 Subject: [PATCH 137/213] modify path and scan folder for what to gen --- UVTD/scripts/HeaderGen.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UVTD/scripts/HeaderGen.py b/UVTD/scripts/HeaderGen.py index 2e7e993b0..bc4e9445b 100755 --- a/UVTD/scripts/HeaderGen.py +++ b/UVTD/scripts/HeaderGen.py @@ -7,7 +7,7 @@ import pickle DEFAULT_FILENAME = "./UnrealGame-Linux-Shipping.debug" -DEFAULT_SEARCH_DIR = "../deps/first/Unreal/generated_include" +DEFAULT_SEARCH_DIR = "../../deps/first/Unreal/generated_include" DEFAULT_GENERATED_DIR = "../generated" FUNCTION_TEMPLATE = """if (auto it = {ClassName}::VTableLayoutMap.find(STR("{FunctionName}")); it == {ClassName}::VTableLayoutMap.end()) @@ -116,15 +116,15 @@ def GenerateVTable(self): def GetClassNames(search_dir = DEFAULT_SEARCH_DIR): # glob all file with pattern "MemberVariableLayout_HeaderWrapper_{ClassName}.hpp" # return list of class names - """ + import glob tabA = [re.search(rf"{Version}_VTableOffsets_(.*)_FunctionBody\.cpp", file).group(1) for file in glob.glob(f"{search_dir}/FunctionBodies/{Version}_VTableOffsets_*.cpp")] tabB = [re.search(rf"{Version}_MemberVariableLayout_DefaultSetter_(.*)\.cpp", file).group(1) for file in glob.glob(f"{search_dir}/FunctionBodies/{Version}_MemberVariableLayout_DefaultSetter_*.cpp")] l = list(dict.fromkeys(tabA + tabB)) # replace _ to : return [x.replace("_", ":") for x in l] - """ - return ['FArchiveState', 'UDataTable', 'FConsoleManager', "UEngine", 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct::ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] + + # return ['FArchiveState', 'UDataTable', 'FConsoleManager', "UEngine", 'UPlayer', 'UObjectBaseUtility', 'AGameMode', 'FMalloc', 'UField', 'UGameViewportClient', 'FField', 'FNumericProperty', 'IConsoleVariable', 'AGameModeBase', 'FMulticastDelegateProperty', 'UObject', 'AActor', 'IConsoleManager', 'IConsoleObject', 'FArchive', 'FConsoleVariableBase', 'FOutputDevice', 'ITextData', 'FProperty', 'FObjectPropertyBase', 'ULocalPlayer', 'UScriptStruct::ICppStructOps', 'UObjectBase', 'FConsoleCommandBase', 'UConsole', 'UStruct', 'IConsoleCommand', 'FInterfaceProperty', 'FByteProperty', 'FSoftClassProperty', 'FStructProperty', 'UEnum', 'FBoolProperty', 'UWorld', 'UClass', 'FEnumProperty', 'FClassProperty', 'FFieldPathProperty', 'FArrayProperty', 'FMapProperty', 'FSetProperty', 'UScriptStruct', 'FDelegateProperty', 'UFunction'] AdditonalClasses = [] From b6c6cce27c6d6d00175183311c13d31707dc64af Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 14 Apr 2024 12:29:46 -0500 Subject: [PATCH 138/213] update upstream --- deps/first/patternsleuth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/patternsleuth b/deps/first/patternsleuth index baed68bcc..33e731e99 160000 --- a/deps/first/patternsleuth +++ b/deps/first/patternsleuth @@ -1 +1 @@ -Subproject commit baed68bccfed9d0ea794259c087317e636e64bdc +Subproject commit 33e731e99f2a6bb7f65a8e95e89fd1c06ce9d1d2 From 0d3568af9601d4bcea588c034eb0c62abf36dc0e Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 11:00:49 -0500 Subject: [PATCH 139/213] min changes --- UE4SS/xmake.lua | 46 +++-- deps/first/xmake.lua | 21 +-- deps/third/imtui/xmake.lua | 52 ++++++ deps/third/xmake.lua | 19 ++- tools/xmakescripts/build_configs.lua | 236 +++++++++++++++++++++++++- tools/xmakescripts/configurations.lua | 51 ++++++ xmake.lua | 31 +++- 7 files changed, 422 insertions(+), 34 deletions(-) create mode 100644 deps/third/imtui/xmake.lua create mode 100644 tools/xmakescripts/configurations.lua diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 8ccee3fcf..76adc1e78 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -1,11 +1,22 @@ includes("proxy_generator") -add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = true, dx11 = true, opengl3 = true, glfw_opengl3 = true , runtimes = get_mode_runtimes()} } ) -add_requires("ImGuiTextEdit v1.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) -add_requires("IconFontCppHeaders v1.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()}}) -add_requires("glfw 3.3.9", { debug = is_mode_debug() , configs = {runtimes = get_mode_runtimes()}}) -add_requires("opengl", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) -add_requires("glaze", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) +if is_plat("windows") and has_config("GUI") then + add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = true, dx11 = true, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) +end + +if has_config("UI") then + add_requires("ImGuiTextEdit v1.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) +end + +if has_config("GUI") then + add_requires("IconFontCppHeaders v1.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) + add_requires("glfw 3.3.9", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) + add_requires("opengl", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) +end + +if is_plat("linux") and has_config("TUI") then + add_requires("imtui v1.0.5", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) +end option("ue4ssBetaIsStarted") set_default(true) @@ -57,17 +68,32 @@ target(projectName) add_deps( "File", "DynamicOutput", "Unreal", "SinglePassSigScanner", "LuaMadeSimple", "Function", - "IniParser", "JSON", "Input", + "IniParser", "JSON", "Constructs", "Helpers", "MProgram", "ScopedTimer", "Profiler", "patternsleuth_bind", "glad", { public = true } ) - add_packages("imgui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) + add_options("UI", "GUI", "TUI", "Input") - add_packages("glaze", "polyhook_2", { public = true }) + if has_config("Input") then + add_deps("Input", { public = true }) + end - add_links("dbghelp", "psapi", "d3d11", { public = true }) + if is_plat("windows") then + if has_config("GUI") then + add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) + add_links("d3d11", { public = true }) + end + elseif is_plat("linux") then + if has_config("GUI") then + add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) + elseif has_config("TUI") then + add_packages("imtui", "ImGuiTextEdit", { public = true }) + end + end + + add_packages("glaze", "polyhook_2", { public = true }) after_load(function (target) local projectRoot = get_config("ue4ssRoot") diff --git a/deps/first/xmake.lua b/deps/first/xmake.lua index 875d9ce34..d0b34abac 100644 --- a/deps/first/xmake.lua +++ b/deps/first/xmake.lua @@ -28,13 +28,14 @@ if is_config("patternsleuth", "local") then add_extrafiles("patternsleuth/**.rs") end --- This option allows users to choose if patternsleuth should be installed as a package --- or if patternsleuth should be built as a dependency by xmake. The `package` option --- should be used if you don't intend on ever modifying the patternsleuth source. --- The `local` option should be used if you want changes in the patternsleuth --- submodule to be included as part of the UE4SS build. -option("patternsleuth") - set_default("package") - set_showmenu(true) - set_values("package", "local") - set_description("Install patternsleuth as a package or build it as a dependency.", "package", "local") +add_requires("cargo::patternsleuth_bind", { debug = is_mode_debug(), configs = { cargo_toml = path.join(os.scriptdir(), "patternsleuth_bind/Cargo.toml"), runtimes = get_mode_runtimes() } }) + +target("patternsleuth_bind") + set_kind("static") + set_values("rust.cratetype", "staticlib") + add_files("patternsleuth_bind/src/lib.rs") + add_packages("cargo::patternsleuth_bind") + if is_plat("windows") then + add_links("ws2_32", "advapi32", "userenv", "ntdll", "oleaut32", "bcrypt", "ole32", { public = true }) + end +-- Patternsleuth -> END diff --git a/deps/third/imtui/xmake.lua b/deps/third/imtui/xmake.lua new file mode 100644 index 000000000..fcb865135 --- /dev/null +++ b/deps/third/imtui/xmake.lua @@ -0,0 +1,52 @@ +package("ImGuiTextEdit") + add_urls("git@github.com:UE4SS-RE/ImGuiColorTextEdit.git") + add_urls("https://github.com/UE4SS-RE/ImGuiColorTextEdit.git") + + add_versions("v1.0", "master") + + add_deps("cmake", "imtui v1.0.5") + + add_includedirs("include", { public = true }) + + on_install(function (package) + local xmake_lua = ([[ + add_rules("mode.debug", "mode.release") + + add_requires("imtui v1.0.5") + + target("ImGuiTextEdit") + set_kind("static") + set_languages("cxx20") + + add_includedirs(".", { public = true }) + add_headerfiles("*.h") + + add_files("*.cpp") + + add_packages("imgui") + ]]) + io.writefile("xmake.lua", xmake_lua) + + import("package.tools.xmake").install(package) + end) +package_end() + +package("imtui") + add_urls("https://github.com/ggerganov/imtui") + + add_versions("v1.0.5", "9f39c3e090c9b1e15557eac38a2f4389462f59df") + add_patches("v1.0.5", "fix-size-cjk-and-mouse.patch") + + add_deps("cmake") + + -- imtui, imtui-ncurses and imgui-for-imtui + on_install(function (package) + local configs = {} + table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) + table.insert(configs, "-DIMTUI_STANDALONE=ON") + table.insert(configs, "-DIMTUI_SUPPORT_NCURSES=ON") + table.insert(configs, "-DIMTUI_BUILD_EXAMPLES=OFF") + + import("package.tools.cmake").install(package, configs) + end) +package_end() diff --git a/deps/third/xmake.lua b/deps/third/xmake.lua index 2f432e0b3..23aec432f 100644 --- a/deps/third/xmake.lua +++ b/deps/third/xmake.lua @@ -1 +1,18 @@ -includes("glad") \ No newline at end of file +includes("zycore") +includes("zydis") +includes("polyhook_2") +includes("glaze") + +if has_config("GUI") then + includes("imgui") +end + +includes("glad") + +if is_plat("windows") then + includes("raw_pdb") +end + +add_requires("zycore v1.5.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) +add_requires("zydis v4.1.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) +add_requires("polyhook_2", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) diff --git a/tools/xmakescripts/build_configs.lua b/tools/xmakescripts/build_configs.lua index d715260fd..1bcc12e07 100644 --- a/tools/xmakescripts/build_configs.lua +++ b/tools/xmakescripts/build_configs.lua @@ -2,6 +2,227 @@ -- It helps people with old mod templates upgrade to the new template. local build_configs = build_configs or {} +local gameDefines = { "UE_GAME" } + +TARGET_TYPES = { + ["Game"] = { + ["defines"] = { + table.unpack(gameDefines) + } + }, + ["CasePreserving"] = { + ["defines"] = { + "WITH_CASE_PRESERVING_NAME", + table.unpack(gameDefines) + } + } +} + +CONFIG_TYPES = { + ["Dev"] = { + ["symbols"] = {"debug"}, + ["defines"] = { + "UE_BUILD_DEVELOPMENT", + "STATS" + }, + ["optimize"] = {"none"} + }, + ["Debug"] = { + ["symbols"] = {"debug"}, + ["defines"] = { + "UE_BUILD_DEBUG" + }, + ["optimize"] = {"none"} + }, + ["Shipping"] = { + ["symbols"] = {"debug"}, + ["defines"] = { + "UE_BUILD_SHIPPING" + }, + ["optimize"] = {"fastest"} + }, + ["Test"] = { + ["symbols"] = {"debug"}, + ["defines"] = { + "UE_BUILD_TEST", + "STATS" + }, + ["optimize"] = {"none"} + } +} + +PLATFORM_TYPES = { + ["Win64"] = { + ["defines"] = { + "PLATFORM_WINDOWS", + "PLATFORM_MICROSOFT", + "OVERRIDE_PLATFORM_HEADER_NAME=Windows", + "UBT_COMPILED_PLATFORM=Win64", + "UNICODE", + "_UNICODE", + "DLLEXT=.dll" + }, + ["cxflags"] = { + "clang_cl::-gcodeview" + } + }, + ["Linux"] = { + ["defines"] = { + "PLATFORM_LINUX", + "PLATFORM_UNIX", + "LINUX", + "OVERRIDE_PLATFORM_HEADER_NAME=Linux", + "UBT_COMPILED_PLATFORM=Linux", + "printf_s=printf", + "DLLEXT=.so" + }, + ["cxflags"] = { + "clang::-fno-delete-null-pointer-checks" + } + } +} + +CLANG_COMPILE_OPTIONS = { + ["cxflags"] = { + "-g", + "-fcolor-diagnostics", + "-Wno-unknown-pragmas", + "-Wno-unused-parameter", + "-fms-extensions", + "-Wignored-attributes" + }, + ["ldflags"] = { + "-g" + }, + ["shflags"] = { + "-g" + } +} + +GNU_COMPILE_OPTIONS = { + ["cxflags"] = { + "-fms-extensions" + } +} + +MSVC_COMPILE_OPTIONS = { + ["cxflags"] = { + "/MP", + "/W3", + "/wd4005", + "/wd4251", + "/wd4068", + "/Zc:inline", + "/Zc:strictStrings", + "/Zc:preprocessor" + }, + ["ldflags"] = { + "/DEBUG:FULL" + }, + ["shflags"] = { + "/DEBUG:FULL" + } +} + +-- Get target types +function get_target_types() + return TARGET_TYPES +end + +-- Get config types +function get_config_types() + return CONFIG_TYPES +end + +-- Get platform types +function get_platform_types() + return PLATFORM_TYPES +end + +-- Get clang compile options +function get_clang_compile_options() + return CLANG_COMPILE_OPTIONS +end + +-- Get gnu compile options +function get_gnu_compile_options() + return GNU_COMPILE_OPTIONS +end + +-- Get msvc compile options +function get_msvc_compile_options() + return MSVC_COMPILE_OPTIONS +end + +-- Apply targe options +function apply_target_options(self, target, options) + for option, values in pairs(options) do + target:add(option, values, { public = true }) + end +end + +-- Returns a list of supported compilation modes +-- CasePreserving__Shipping_Win64, Game_Debug_Win64, etc. +function get_compilation_modes() + local comp_modes = {} + + for target_type, _ in pairs(TARGET_TYPES) do + for config_type, _ in pairs(CONFIG_TYPES) do + for platform_type, _ in pairs(PLATFORM_TYPES) do + local config_name = target_type .. "__" .. config_type .. "__" .. platform_type + table.insert(comp_modes, config_name) + end + end + end + + return comp_modes +end + +-- Get unreal rules +function get_unreal_rules() + local unreal_rules = {} + + for _, config_name in ipairs(get_compilation_modes()) do + local rule_name = "mode." .. config_name + table.insert(unreal_rules, rule_name) + + rule(rule_name) + rule_end() + end + + return unreal_rules +end + +-- Parse mode string into modes +function mode_string_to_modes(self, str) + local modes = {} + for t in string.gmatch(str, "(%w+)") do + table.insert(modes, t) + end + + return { + ["target"] = modes[1], + ["config"] = modes[2], + ["platform"] = modes[3] + } +end + +-- Apply compiler options +function apply_compiler_options(self, target) + for option, values in pairs(self:get_gnu_compile_options()) do + target:add(option, values, { tools = { "gcc", "ld" } }) + end + + for option, values in pairs(self:get_clang_compile_options()) do + target:add(option, values, { tools = { "clang", "lld" } }) + end + + for option, values in pairs(self:get_msvc_compile_options()) do + target:add(option, values, { tools = { "clang_cl", "cl", "link" } }) + end +end + +-- Run on configure step for each target that wants unreal rules function config(self, target) if target:name() == "Unreal" then _warn_unreal_submod_outdated() @@ -26,13 +247,14 @@ function clean_output_dir(self, target) end end -function _warn_mod_template_outdated(target) - print("SUGGESTED TEMPLATE:") - print(format('target("%s")', target:name())) - print(' add_rules("ue4ss.mod")') - print(' add_includedirs(".")') - print(' add_files("*.cpp")') - raise("Your mod's xmake.lua file needs updating.") +-- Get runtime for current mode +function get_mode_runtimes() + local is_debug = is_mode_debug() + if is_plat("windows") then + return is_debug and "MDd" or "MD" + end + -- we don't care about runtime on linux + return "" end function _warn_unreal_submod_outdated() diff --git a/tools/xmakescripts/configurations.lua b/tools/xmakescripts/configurations.lua new file mode 100644 index 000000000..ed3962dd2 --- /dev/null +++ b/tools/xmakescripts/configurations.lua @@ -0,0 +1,51 @@ +-- UI configurations + +option("UI") + set_default(true) + set_showmenu(true) + add_defines("HAS_UI") + set_description("Enable the user iterface.") + +option("GUI") + -- Windows has only GUI + set_default(is_plat("windows")) + set_showmenu(true) + add_defines("HAS_GUI") + add_deps("UI") + set_description("Enable the graphical user interface.") + if is_plat("windows") then + add_defines("HAS_D3D11") + add_defines("HAS_GLFW") + elseif is_plat("linux") then + add_defines("HAS_GLFW") + end + +option("TUI") + -- use TUI by default on Linux + set_default(is_plat("linux")) + set_showmenu(true) + add_defines("HAS_TUI") + add_deps("UI") + set_description("Enable the text user interface. (Not supported on Windows)") + after_check(function (option) + -- mutually exclusive with GUI + if has_config("GUI") then + option:enable(false) + end + if is_plat("windows") then + option:enable(false) + end + end) + +-- Input configurations + +option("Input") + set_default(has_config("UI") or is_plat("windows")) + set_showmenu(true) + add_defines("HAS_INPUT") + set_description("Enable the input system.") + after_check(function (option) + if not has_config("UI") and not is_plat("windows") then + option:enable(false) + end + end) \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 5c3ee1296..78b878ef0 100644 --- a/xmake.lua +++ b/xmake.lua @@ -4,7 +4,28 @@ set_xmakever("2.9.2") -- when UE4SS is sub-moduled/`include("UE4SS")` in another xmake project. set_config("ue4ssRoot", os.scriptdir()) --- All non-binary outputs are written to the Intermediates dir. +includes("tools/xmakescripts/build_configs.lua") +includes("tools/xmakescripts/configurations.lua") + +add_rules(get_unreal_rules()) + +-- Restrict the compilation modes/configs. +set_allowedplats("windows", "linux") +if is_plat("windows") then + set_allowedarchs("x64") +elseif is_plat("linux") then + set_allowedarchs("x86_64") +end +set_allowedmodes(get_compilation_modes()) + +if is_plat("windows") then + set_defaultmode("Game__Shipping__Win64") + set_runtimes(get_mode_runtimes()) +elseif is_plat("linux") then + set_defaultmode("Game__Shipping__Linux") +end + +-- All non-binary outputs are stored in the Intermediates dir. set_config("buildir", "Intermediates") -- Any lua modules in this directory can be imported in the script scope by using @@ -47,9 +68,7 @@ on_install(function(target) end) includes("deps") includes("UE4SS") -includes("UVTD") -includes("cppmods") --- TODO: Remove this before the next release. It only exists to maintain backwards compat --- warnings for older mod templates. -set_config("scriptsRoot", path.join(os.scriptdir(), "tools/xmakescripts")) \ No newline at end of file +if is_plat("windows") then + includes("UVTD") +end From 01d447618dfa2f729368954d96f3175c0353580d Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 11:03:07 -0500 Subject: [PATCH 140/213] recover deps/third/polyhook_2/CMakeLists.txt --- .../packages/p/polyhook_2/CMakeLists.txt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 deps/third-repo/packages/p/polyhook_2/CMakeLists.txt diff --git a/deps/third-repo/packages/p/polyhook_2/CMakeLists.txt b/deps/third-repo/packages/p/polyhook_2/CMakeLists.txt new file mode 100644 index 000000000..f502acff3 --- /dev/null +++ b/deps/third-repo/packages/p/polyhook_2/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.27) + +include(FetchContent) + +set(FETCHCONTENT_QUIET OFF) + +FetchContent_Declare(PolyHook2 + GIT_REPOSITORY https://github.com/stevemk14ebr/PolyHook_2_0.git + GIT_TAG fd2a88f09c8ae89440858fc52573656141013c7f + GIT_PROGRESS ON) + +if (${UE4SS_PolyHook_BUILD_SHARED}) + set(MAKE_POLYHOOK_DEPENDENCIES_SHARED ON) + set(MAKE_POLYHOOK_DEPENDENCIES_STATIC OFF) +else () + set(MAKE_POLYHOOK_DEPENDENCIES_SHARED OFF) + set(MAKE_POLYHOOK_DEPENDENCIES_STATIC ON) +endif () + +set(POLYHOOK_BUILD_DLL ON CACHE BOOL "Build dll & lib instead of tests" FORCE) +set(POLYHOOK_BUILD_SHARED_LIB ${MAKE_POLYHOOK_DEPENDENCIES_SHARED} CACHE BOOL "Build polyhook2 as shared libary" FORCE) +set(POLYHOOK_USE_EXTERNAL_ZYDIS ON CACHE BOOL "Use external zydis libary" FORCE) +set(ASMJIT_STATIC ${MAKE_POLYHOOK_DEPENDENCIES_STATIC} CACHE BOOL "Build 'asmjit' library as static" FORCE) +set(POLYHOOK_BUILD_STATIC_RUNTIME OFF CACHE BOOL "Use static runtime" FORCE) + +# prevent PolyHook from setting MSVC_RUNTIME_LIBRARY to "MultiThreaded$<$:Debug>DLL" by unsetting 'MSVC' var +set(TMP_MSVC ${MSVC}) +unset(MSVC) + +FetchContent_MakeAvailable(PolyHook2) + +# re-enable 'install' and reset 'MSVC' since we're done adding PolyHook +set(MSVC ${TMP_MSVC}) From 6e35bac734a86a74bed0cc7edeb9abb123868792 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 12:41:26 -0500 Subject: [PATCH 141/213] add more fixs for xmake --- UE4SS/xmake.lua | 5 ++++- deps/first/DynamicOutput/xmake.lua | 11 ++++++++++- deps/first/xmake.lua | 6 +++++- deps/third-repo/packages/p/polyhook_2/xmake.lua | 7 ++++++- xmake.lua | 1 + 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 76adc1e78..53f7a80b1 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -1,4 +1,7 @@ -includes("proxy_generator") + +if is_plat("windows") then + includes("proxy_generator") +end if is_plat("windows") and has_config("GUI") then add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = true, dx11 = true, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) diff --git a/deps/first/DynamicOutput/xmake.lua b/deps/first/DynamicOutput/xmake.lua index 52f91b97a..9078849a1 100644 --- a/deps/first/DynamicOutput/xmake.lua +++ b/deps/first/DynamicOutput/xmake.lua @@ -11,4 +11,13 @@ target(projectName) add_files("src/**.cpp") - add_deps("File") \ No newline at end of file + add_deps("File", "Helpers") + + on_load(function (target) + import("target_helpers", { rootdir = get_config("scriptsRoot") }) + + print("Project: " .. projectName .. " (STATIC)") + + target:add("defines", target_helpers.project_name_to_exports_define(projectName)) + target:add("defines", target_helpers.project_name_to_build_static_define(projectName)) + end) diff --git a/deps/first/xmake.lua b/deps/first/xmake.lua index d0b34abac..a68ce4b39 100644 --- a/deps/first/xmake.lua +++ b/deps/first/xmake.lua @@ -6,7 +6,11 @@ includes("File") includes("Function") includes("Helpers") includes("IniParser") -includes("Input") + +if (has_config("Input")) then + includes("Input") +end + includes("JSON") includes("LuaMadeSimple") includes("LuaRaw") diff --git a/deps/third-repo/packages/p/polyhook_2/xmake.lua b/deps/third-repo/packages/p/polyhook_2/xmake.lua index 7cccc343c..e1277306b 100644 --- a/deps/third-repo/packages/p/polyhook_2/xmake.lua +++ b/deps/third-repo/packages/p/polyhook_2/xmake.lua @@ -8,7 +8,12 @@ package("polyhook_2") table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) table.insert(configs, "-DBUILD_SHARED_LIBS=OFF") - + if is_plat("linux") then + table.insert(configs, "-DZYDIS_INCLUDE_DIR=" .. package:dep("zydis"):installdir("include")) + table.insert(configs, "-DZYCORE_INCLUDE_DIR=" .. package:dep("zycore"):installdir("include")) + table.insert(configs, "-DZYCORE_LIBRARY=" .. package:dep("zycore"):installdir("libzycore.a")) + table.insert(configs, "-DZYDIS_LIBRARY=" .. package:dep("zydis"):installdir("libzydis.a")) + end import("package.tools.cmake").install(package, configs, { packagedeps = { "zycore", "zydis" } }) end) diff --git a/xmake.lua b/xmake.lua index 78b878ef0..33fc5d479 100644 --- a/xmake.lua +++ b/xmake.lua @@ -15,6 +15,7 @@ if is_plat("windows") then set_allowedarchs("x64") elseif is_plat("linux") then set_allowedarchs("x86_64") + set_defaultarchs("x86_64") end set_allowedmodes(get_compilation_modes()) From 3e14c5754e1a85e123c5a502bdde4fedbd1e6fd7 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 19:06:57 -0500 Subject: [PATCH 142/213] workaround and restruct --- UE4SS/src/{ => Platform/Linux}/EntryLinux.cpp | 0 .../src/{ => Platform/Win32}/CrashDumper.cpp | 0 UE4SS/src/{ => Platform/Win32}/EntryWin32.cpp | 2 +- UE4SS/xmake.lua | 6 +++++ deps/first/File/xmake.lua | 13 ++++++++++- deps/first/SinglePassSigScanner/xmake.lua | 22 ++++++++++++++++++- xmake.lua | 1 + 7 files changed, 41 insertions(+), 3 deletions(-) rename UE4SS/src/{ => Platform/Linux}/EntryLinux.cpp (100%) rename UE4SS/src/{ => Platform/Win32}/CrashDumper.cpp (100%) rename UE4SS/src/{ => Platform/Win32}/EntryWin32.cpp (97%) diff --git a/UE4SS/src/EntryLinux.cpp b/UE4SS/src/Platform/Linux/EntryLinux.cpp similarity index 100% rename from UE4SS/src/EntryLinux.cpp rename to UE4SS/src/Platform/Linux/EntryLinux.cpp diff --git a/UE4SS/src/CrashDumper.cpp b/UE4SS/src/Platform/Win32/CrashDumper.cpp similarity index 100% rename from UE4SS/src/CrashDumper.cpp rename to UE4SS/src/Platform/Win32/CrashDumper.cpp diff --git a/UE4SS/src/EntryWin32.cpp b/UE4SS/src/Platform/Win32/EntryWin32.cpp similarity index 97% rename from UE4SS/src/EntryWin32.cpp rename to UE4SS/src/Platform/Win32/EntryWin32.cpp index ab98cd195..1c17c80d2 100644 --- a/UE4SS/src/EntryWin32.cpp +++ b/UE4SS/src/Platform/Win32/EntryWin32.cpp @@ -31,7 +31,7 @@ auto thread_dll_start(UE4SSProgram* program) -> unsigned long // Logging will only happen to the debug console but it's something at least if (!Output::has_internal_error()) { - Output::send(STR("Fatal Error: {}\n"), to_wstring(e->get_message())); + Output::send(SYSSTR("Fatal Error: {}\n"), to_wstring(e->get_message())); } else { diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 53f7a80b1..52300eab5 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -67,6 +67,7 @@ target(projectName) add_headerfiles("generated_include/*.hpp") add_files("src/**.cpp") + remove_files("src/Platform/**.cpp") add_deps( "File", "DynamicOutput", "Unreal", @@ -84,11 +85,16 @@ target(projectName) end if is_plat("windows") then + add_files("src/Platform/Win32/**.cpp") if has_config("GUI") then add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) add_links("d3d11", { public = true }) end elseif is_plat("linux") then + add_files("src/Platform/Linux/**.cpp") + if not has_config("UI") then + remove_files("src/GUI/**.cpp") + end if has_config("GUI") then add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) elseif has_config("TUI") then diff --git a/deps/first/File/xmake.lua b/deps/first/File/xmake.lua index 4d8b77072..84487991a 100644 --- a/deps/first/File/xmake.lua +++ b/deps/first/File/xmake.lua @@ -9,4 +9,15 @@ target(projectName) add_includedirs("include", { public = true }) add_headerfiles("include/**.hpp") - add_files("src/**.cpp") \ No newline at end of file + add_files("src/**.cpp") + + add_deps("Helpers") + + on_load(function (target) + import("target_helpers", { rootdir = get_config("scriptsRoot") }) + + print("Project: " .. projectName .. " (STATIC)") + + target:add("defines", target_helpers.project_name_to_exports_define(projectName)) + target:add("defines", target_helpers.project_name_to_build_static_define(projectName)) + end) diff --git a/deps/first/SinglePassSigScanner/xmake.lua b/deps/first/SinglePassSigScanner/xmake.lua index 91b913900..d9bc53c39 100644 --- a/deps/first/SinglePassSigScanner/xmake.lua +++ b/deps/first/SinglePassSigScanner/xmake.lua @@ -8,7 +8,27 @@ target(projectName) add_includedirs("include", { public = true }) add_headerfiles("include/**.hpp") + remove_headerfiles("include/SigScanner/SinglePassSigScanner*?.hpp") add_files("src/**.cpp") + remove_files("src/SinglePassSigScannerWin32.cpp") + remove_files("src/SinglePassSigScannerLinux.cpp") - add_deps("Profiler") \ No newline at end of file + if is_plat("windows") then + add_headerfiles("include/SigScanner/SinglePassSigScannerWin32.hpp") + add_files("src/SinglePassSigScannerWin32.cpp") + elseif is_plat("linux") then + add_headerfiles("include/SigScanner/SinglePassSigScannerLinux.hpp") + add_files("src/SinglePassSigScannerLinux.cpp") + end + + add_deps("Profiler") + + on_load(function (target) + import("target_helpers", { rootdir = get_config("scriptsRoot") }) + + print("Project: " .. projectName .. " (STATIC)") + + target:add("defines", target_helpers.project_name_to_exports_define(projectName)) + target:add("defines", target_helpers.project_name_to_build_static_define(projectName)) + end) diff --git a/xmake.lua b/xmake.lua index 33fc5d479..6e9a9c351 100644 --- a/xmake.lua +++ b/xmake.lua @@ -16,6 +16,7 @@ if is_plat("windows") then elseif is_plat("linux") then set_allowedarchs("x86_64") set_defaultarchs("x86_64") + set_toolchains("clang", "rust") end set_allowedmodes(get_compilation_modes()) From f3d42ee27d8389b5546ae177db34d5050652a101 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 19:16:27 -0500 Subject: [PATCH 143/213] os deps policy --- deps/first/File/xmake.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/deps/first/File/xmake.lua b/deps/first/File/xmake.lua index 84487991a..2c4c90b23 100644 --- a/deps/first/File/xmake.lua +++ b/deps/first/File/xmake.lua @@ -9,7 +9,13 @@ target(projectName) add_includedirs("include", { public = true }) add_headerfiles("include/**.hpp") - add_files("src/**.cpp") + add_files("src/File.cpp") + + if is_plat("windows") then + add_files("src/FileType/WinFile.cpp") + elseif is_plat("linux") then + add_files("src/FileType/StdFile.cpp") + end add_deps("Helpers") From 3c8dfc47c6c1cc5944e40d151f003844b91eb757 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 19:16:36 -0500 Subject: [PATCH 144/213] should be ue string --- UE4SS/src/LuaLibrary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/LuaLibrary.cpp b/UE4SS/src/LuaLibrary.cpp index 6c138eeab..019cdbd68 100644 --- a/UE4SS/src/LuaLibrary.cpp +++ b/UE4SS/src/LuaLibrary.cpp @@ -70,7 +70,7 @@ namespace RC::LuaLibrary Output::send(formatted_string); - if (output_device) output_device->Log(outdevice_string.c_str()); + if (output_device) output_device->Log(to_ue_string(outdevice_string).c_str()); Output::send(SYSSTR("[Fatal] Lua function 'DerefToInt32' must have only 1 parameter and it must be of type 'int'.\n")); lua.set_nil(); From ea87ce5848c807edd63b8404ff6b2ea7ea18f142 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 19:53:17 -0500 Subject: [PATCH 145/213] add -fpic flag --- tools/xmakescripts/build_configs.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/xmakescripts/build_configs.lua b/tools/xmakescripts/build_configs.lua index 1bcc12e07..21c340606 100644 --- a/tools/xmakescripts/build_configs.lua +++ b/tools/xmakescripts/build_configs.lua @@ -89,7 +89,8 @@ CLANG_COMPILE_OPTIONS = { "-Wno-unknown-pragmas", "-Wno-unused-parameter", "-fms-extensions", - "-Wignored-attributes" + "-Wignored-attributes", + "-fPIC" }, ["ldflags"] = { "-g" From e4f67bb559ce0c233d33b22b07fa08e54fbaae20 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 19:53:38 -0500 Subject: [PATCH 146/213] fix rebase bug --- UE4SS/src/LuaLibrary.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/UE4SS/src/LuaLibrary.cpp b/UE4SS/src/LuaLibrary.cpp index 019cdbd68..99c1b1344 100644 --- a/UE4SS/src/LuaLibrary.cpp +++ b/UE4SS/src/LuaLibrary.cpp @@ -72,17 +72,24 @@ namespace RC::LuaLibrary if (output_device) output_device->Log(to_ue_string(outdevice_string).c_str()); + return 0; + } + + auto deref_to_int32(const LuaMadeSimple::Lua& lua) -> int + { + if (lua.get_stack_size() != 1 || !lua.is_integer()) + { Output::send(SYSSTR("[Fatal] Lua function 'DerefToInt32' must have only 1 parameter and it must be of type 'int'.\n")); lua.set_nil(); return 1; } int32_t* int32_ptr = reinterpret_cast(lua.get_integer()); -#ifdef WIN32 + #ifdef WIN32 auto self = GetCurrentProcess(); -#else + #else auto self = getpid(); -#endif + #endif int32_t int32_val = Helper::Casting::offset_deref_safe(int32_ptr, 0, self); if (int32_val == 0) From faa55fc29663224330e3697fd45423ac5c529498 Mon Sep 17 00:00:00 2001 From: Yangff Date: Mon, 15 Apr 2024 20:03:04 -0500 Subject: [PATCH 147/213] buggy globs? --- UE4SS/xmake.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 52300eab5..ad708c87c 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -85,13 +85,14 @@ target(projectName) end if is_plat("windows") then - add_files("src/Platform/Win32/**.cpp") + add_files("src/Platform/Win32/CrashDumper.cpp") + add_files("src/Platform/Win32/EntryWin32.cpp") if has_config("GUI") then add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) add_links("d3d11", { public = true }) end elseif is_plat("linux") then - add_files("src/Platform/Linux/**.cpp") + add_files("src/Platform/Linux/EntryLinux.cpp") if not has_config("UI") then remove_files("src/GUI/**.cpp") end From a816daffe5d4acaeebecffb04bb759b61607ca32 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 02:27:11 -0500 Subject: [PATCH 148/213] use __typeof__ instead of typeof? --- UE4SS/src/Platform/Linux/EntryLinux.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/UE4SS/src/Platform/Linux/EntryLinux.cpp b/UE4SS/src/Platform/Linux/EntryLinux.cpp index 56cbdad39..5aa0fd352 100644 --- a/UE4SS/src/Platform/Linux/EntryLinux.cpp +++ b/UE4SS/src/Platform/Linux/EntryLinux.cpp @@ -7,7 +7,7 @@ #include "UE4SSProgram.hpp" #include "Platform.hpp" -#define _GNU_SOURCE +// #define _GNU_SOURCE #include #include #include @@ -15,6 +15,13 @@ #include #include +// typeof is a gnu extension +#ifndef typeof +#ifdef __clang__ +#define typeof(x) __typeof__(x) +#endif +#endif + using namespace RC; pthread_t ue4ss_mainthread; From 073afefc47e57947e80e390ea09de9efd1362713 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 02:29:00 -0500 Subject: [PATCH 149/213] avoid remove_files issue --- UE4SS/xmake.lua | 4 +--- deps/first/SinglePassSigScanner/xmake.lua | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index ad708c87c..ff247e234 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -66,8 +66,7 @@ target(projectName) add_headerfiles("include/**.hpp") add_headerfiles("generated_include/*.hpp") - add_files("src/**.cpp") - remove_files("src/Platform/**.cpp") + add_files("src/**.cpp|Platform/**.cpp") add_deps( "File", "DynamicOutput", "Unreal", @@ -83,7 +82,6 @@ target(projectName) if has_config("Input") then add_deps("Input", { public = true }) end - if is_plat("windows") then add_files("src/Platform/Win32/CrashDumper.cpp") add_files("src/Platform/Win32/EntryWin32.cpp") diff --git a/deps/first/SinglePassSigScanner/xmake.lua b/deps/first/SinglePassSigScanner/xmake.lua index d9bc53c39..51cf8a5b7 100644 --- a/deps/first/SinglePassSigScanner/xmake.lua +++ b/deps/first/SinglePassSigScanner/xmake.lua @@ -8,11 +8,8 @@ target(projectName) add_includedirs("include", { public = true }) add_headerfiles("include/**.hpp") - remove_headerfiles("include/SigScanner/SinglePassSigScanner*?.hpp") - add_files("src/**.cpp") - remove_files("src/SinglePassSigScannerWin32.cpp") - remove_files("src/SinglePassSigScannerLinux.cpp") + add_files("src/**.cpp|SinglePassSigScanner*?.cpp") if is_plat("windows") then add_headerfiles("include/SigScanner/SinglePassSigScannerWin32.hpp") From 1e0f6aedfb709a4e80a3fc289b37a10d9406e9fe Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 02:35:31 -0500 Subject: [PATCH 150/213] should not use *.? and update unreal --- deps/first/SinglePassSigScanner/xmake.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deps/first/SinglePassSigScanner/xmake.lua b/deps/first/SinglePassSigScanner/xmake.lua index 51cf8a5b7..9eb5b40e9 100644 --- a/deps/first/SinglePassSigScanner/xmake.lua +++ b/deps/first/SinglePassSigScanner/xmake.lua @@ -9,7 +9,8 @@ target(projectName) add_includedirs("include", { public = true }) add_headerfiles("include/**.hpp") - add_files("src/**.cpp|SinglePassSigScanner*?.cpp") + -- *? is not supported? + add_files("src/**.cpp|SinglePassSigScannerWin32.cpp|SinglePassSigScannerLinux.cpp") if is_plat("windows") then add_headerfiles("include/SigScanner/SinglePassSigScannerWin32.hpp") From b6ba28be4e7d2b2b46d2f0c89375a21224a99f8e Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 05:05:08 -0500 Subject: [PATCH 151/213] still can't find imtui? why? --- UE4SS/xmake.lua | 8 ++-- deps/first/Input/xmake.lua | 22 +++++++++- .../packages/i/imguitextedit/xmake.lua | 41 ++++++++++++++++--- deps/third/imtui/xmake.lua | 38 ++--------------- deps/third/xmake.lua | 6 ++- 5 files changed, 67 insertions(+), 48 deletions(-) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index ff247e234..9f03ffbb4 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -3,8 +3,10 @@ if is_plat("windows") then includes("proxy_generator") end -if is_plat("windows") and has_config("GUI") then +if has_config("GUI") then add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = true, dx11 = true, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) +elseif has_config("TUI") then + add_requires("imtui v1.0.5", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) end if has_config("UI") then @@ -17,10 +19,6 @@ if has_config("GUI") then add_requires("opengl", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) end -if is_plat("linux") and has_config("TUI") then - add_requires("imtui v1.0.5", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) -end - option("ue4ssBetaIsStarted") set_default(true) set_showmenu(true) diff --git a/deps/first/Input/xmake.lua b/deps/first/Input/xmake.lua index 02b2c633f..227ef0d34 100644 --- a/deps/first/Input/xmake.lua +++ b/deps/first/Input/xmake.lua @@ -9,4 +9,24 @@ target(projectName) add_includedirs("include", { public = true }) add_headerfiles("include/**.hpp") - add_files("src/**.cpp") \ No newline at end of file + add_files("src/**.cpp|Platform/**.cpp") + + if is_plat("windows") then + add_files("src/Platform/Win32AsyncInputSource.cpp") + add_files("src/Platform/GLFW3InputSource.cpp") + add_files("src/Platform/QueueInputSource.cpp") + end + + if is_plat("linux") then + add_files("src/Platform/GLFW3InputSource.cpp") + add_files("src/Platform/NcursesInputSource.cpp") + end + + on_load(function (target) + import("target_helpers", { rootdir = get_config("scriptsRoot") }) + + print("Project: " .. projectName .. " (STATIC)") + + target:add("defines", target_helpers.project_name_to_exports_define(projectName)) + target:add("defines", target_helpers.project_name_to_build_static_define(projectName)) + end) diff --git a/deps/third-repo/packages/i/imguitextedit/xmake.lua b/deps/third-repo/packages/i/imguitextedit/xmake.lua index bcb2c93ef..21374570a 100644 --- a/deps/third-repo/packages/i/imguitextedit/xmake.lua +++ b/deps/third-repo/packages/i/imguitextedit/xmake.lua @@ -4,12 +4,19 @@ package("ImGuiTextEdit") add_versions("v1.0", "master") - add_deps("cmake", "imgui v1.89") + local imgui_name = "imgui" + + if has_config("GUI") then + add_deps("cmake", "imgui v1.89") + elseif has_config("TUI") then + add_deps("cmake", "imtui v1.0.5") + imgui_name = "imtui" + end add_includedirs("include", { public = true }) on_install(function (package) - local imgui = package:dep("imgui") + local imgui = package:dep(imgui_name) local configs = imgui:requireinfo().configs if configs then @@ -19,7 +26,7 @@ package("ImGuiTextEdit") local xmake_lua = ([[ add_rules("mode.debug", "mode.release") - add_requires("imgui %s", { configs = %s }) + add_requires("%s %s", { configs = %s }) target("ImGuiTextEdit") set_kind("static") @@ -30,10 +37,32 @@ package("ImGuiTextEdit") add_files("*.cpp") - add_packages("imgui") - ]]):format(imgui:version_str(), configs) + add_packages("%s") + ]]):format(imgui_name, imgui:version_str(), configs, imgui_name) io.writefile("xmake.lua", xmake_lua) import("package.tools.xmake").install(package) end) -package_end() \ No newline at end of file +package_end() + +if has_config("GUI") then + package("IconFontCppHeaders") + add_urls("git@github.com:juliettef/IconFontCppHeaders.git") + add_urls("https://github.com/juliettef/IconFontCppHeaders.git") + set_kind("library", { headeronly = true }) + + add_versions("v1.0", "main") + + on_install(function (package) + os.cp("**.h", package:installdir("include")) + end) + + on_test(function (package) + assert(package:check_cxxsnippets({ test = [[ + void test() { + ICON_FA_TERMINAL; + } + ]]}, { includes = { "IconsFontAwesome5.h" } })) + end) + package_end() +end diff --git a/deps/third/imtui/xmake.lua b/deps/third/imtui/xmake.lua index fcb865135..a609db7a4 100644 --- a/deps/third/imtui/xmake.lua +++ b/deps/third/imtui/xmake.lua @@ -1,41 +1,9 @@ -package("ImGuiTextEdit") - add_urls("git@github.com:UE4SS-RE/ImGuiColorTextEdit.git") - add_urls("https://github.com/UE4SS-RE/ImGuiColorTextEdit.git") - - add_versions("v1.0", "master") - - add_deps("cmake", "imtui v1.0.5") - - add_includedirs("include", { public = true }) - - on_install(function (package) - local xmake_lua = ([[ - add_rules("mode.debug", "mode.release") - - add_requires("imtui v1.0.5") - - target("ImGuiTextEdit") - set_kind("static") - set_languages("cxx20") - - add_includedirs(".", { public = true }) - add_headerfiles("*.h") - - add_files("*.cpp") - - add_packages("imgui") - ]]) - io.writefile("xmake.lua", xmake_lua) - - import("package.tools.xmake").install(package) - end) -package_end() - package("imtui") - add_urls("https://github.com/ggerganov/imtui") + add_urls("https://github.com/ggerganov/imtui.git") add_versions("v1.0.5", "9f39c3e090c9b1e15557eac38a2f4389462f59df") - add_patches("v1.0.5", "fix-size-cjk-and-mouse.patch") + local root = get_config("ue4ssRoot") + add_patches("v1.0.5", path.join(root, "deps", "third", "imtui", "fix-size-cjk-and-mouse.patch")) add_deps("cmake") diff --git a/deps/third/xmake.lua b/deps/third/xmake.lua index 23aec432f..a04384296 100644 --- a/deps/third/xmake.lua +++ b/deps/third/xmake.lua @@ -3,7 +3,11 @@ includes("zydis") includes("polyhook_2") includes("glaze") -if has_config("GUI") then +if has_config("TUI") then + includes("imtui") +end + +if has_config("UI") then includes("imgui") end From ad6925fedc92fa46881415babe2e5d8305784806 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 13:46:43 -0500 Subject: [PATCH 152/213] typo --- .../Platform/{QueneInputSource.cpp => QueueInputSource.cpp} | 0 deps/first/Input/xmake.lua | 3 +++ 2 files changed, 3 insertions(+) rename deps/first/Input/src/Platform/{QueneInputSource.cpp => QueueInputSource.cpp} (100%) diff --git a/deps/first/Input/src/Platform/QueneInputSource.cpp b/deps/first/Input/src/Platform/QueueInputSource.cpp similarity index 100% rename from deps/first/Input/src/Platform/QueneInputSource.cpp rename to deps/first/Input/src/Platform/QueueInputSource.cpp diff --git a/deps/first/Input/xmake.lua b/deps/first/Input/xmake.lua index 227ef0d34..10a5afe1c 100644 --- a/deps/first/Input/xmake.lua +++ b/deps/first/Input/xmake.lua @@ -11,6 +11,8 @@ target(projectName) add_files("src/**.cpp|Platform/**.cpp") + add_deps("DynamicOutput") + if is_plat("windows") then add_files("src/Platform/Win32AsyncInputSource.cpp") add_files("src/Platform/GLFW3InputSource.cpp") @@ -20,6 +22,7 @@ target(projectName) if is_plat("linux") then add_files("src/Platform/GLFW3InputSource.cpp") add_files("src/Platform/NcursesInputSource.cpp") + add_files("src/Platform/QueueInputSource.cpp") end on_load(function (target) From c4637d9847cf7458bc0f5402cf0a8f972d1936f1 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 13:55:14 -0500 Subject: [PATCH 153/213] upstream is not merged correctly --- deps/first/patternsleuth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/patternsleuth b/deps/first/patternsleuth index 33e731e99..baed68bcc 160000 --- a/deps/first/patternsleuth +++ b/deps/first/patternsleuth @@ -1 +1 @@ -Subproject commit 33e731e99f2a6bb7f65a8e95e89fd1c06ce9d1d2 +Subproject commit baed68bccfed9d0ea794259c087317e636e64bdc From 4f6697fe6e20e1eaac7e94211a600a8fac647fa6 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 14:00:05 -0500 Subject: [PATCH 154/213] I've no idea why the pattern scan won't work. I'm done --- UE4SS/include/GUI/GUI.hpp | 2 ++ UE4SS/include/GUI/NerdFont.hpp | 2 ++ UE4SS/src/GUI/Console.cpp | 2 +- UE4SS/src/GUI/LiveView.cpp | 4 +-- UE4SS/src/GUI/{ => Platform/D3D11}/DX11.cpp | 0 .../GUI/{ => Platform/GLFW}/GLFW3_OpenGL3.cpp | 0 .../src/GUI/{ => Platform/GUI}/FaSolid900.hpp | 0 UE4SS/src/GUI/{ => Platform/GUI}/Roboto.hpp | 0 UE4SS/src/GUI/{ => Platform/TUI}/TUI.cpp | 2 +- .../GUI/{ => Platform/Windows}/Windows.cpp | 0 UE4SS/xmake.lua | 30 ++++++++++++++----- deps/first/xmake.lua | 6 +--- deps/third/imtui/xmake.lua | 12 ++++++-- 13 files changed, 42 insertions(+), 18 deletions(-) rename UE4SS/src/GUI/{ => Platform/D3D11}/DX11.cpp (100%) rename UE4SS/src/GUI/{ => Platform/GLFW}/GLFW3_OpenGL3.cpp (100%) rename UE4SS/src/GUI/{ => Platform/GUI}/FaSolid900.hpp (100%) rename UE4SS/src/GUI/{ => Platform/GUI}/Roboto.hpp (100%) rename UE4SS/src/GUI/{ => Platform/TUI}/TUI.cpp (98%) rename UE4SS/src/GUI/{ => Platform/Windows}/Windows.cpp (100%) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index a0f27b1db..76498e873 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -321,7 +321,9 @@ namespace RC::GUI #ifdef HAS_GUI #define ATTACH_ICON(icon, str) icon str +#define ICON_ALT(icon, alt) icon #else #define ATTACH_ICON(icon, str) ((icon str) + (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1))) +#define ICON_ALT(icon, alt) (UE4SSProgram::settings_manager.TUI.TUINerdFont) ? (icon) : (alt) #endif } // namespace RC::GUI diff --git a/UE4SS/include/GUI/NerdFont.hpp b/UE4SS/include/GUI/NerdFont.hpp index 5289858cb..e109221b2 100644 --- a/UE4SS/include/GUI/NerdFont.hpp +++ b/UE4SS/include/GUI/NerdFont.hpp @@ -12,3 +12,5 @@ #define ICON_FA_BAN "\uf05e" #define ICON_FA_COPY "\uf0c5" #define ICON_FA_SEARCH "\uf002" +#define ICON_FA_MINUS "\uf068" +#define ICON_FA_PLUS "\uf067" \ No newline at end of file diff --git a/UE4SS/src/GUI/Console.cpp b/UE4SS/src/GUI/Console.cpp index b4b9cf465..5f6979cad 100644 --- a/UE4SS/src/GUI/Console.cpp +++ b/UE4SS/src/GUI/Console.cpp @@ -132,7 +132,7 @@ namespace RC::GUI std::lock_guard guard(m_lines_mutex); // TODO: ensure this ydiv is okay? // the old value is const float footer_height_to_reserve = ((ImGui::GetStyle().ItemSpacing.y * 10.0f) + ImGui::GetFrameHeightWithSpacing()) / YDIV; - m_text_editor.Render("TextEditor", {-16.0f / , (-31.0f + -8.0f) / YDIV}); + m_text_editor.Render("TextEditor", {-16.0f / XDIV, (-31.0f + -8.0f) / YDIV}); ImGui_AutoScroll("TextEditor", &m_previous_max_scroll_y); //*/ diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index dbf7fdcde..24ce20add 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -3018,7 +3018,7 @@ namespace RC::GUI if (watch.write_to_file) { - watch.output.send(STR("{}"), buffer); + watch.output.send(SYSSTR("{}"), buffer); } } @@ -3631,7 +3631,7 @@ namespace RC::GUI ImGui::SameLine(0.0f, 2.0f); ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f, 0.5f)); ImGui::PushID(std::format("collapse_history_{}", watch.hash).c_str()); - ImGui::Selectable(watch.show_history ? ICON_FA_MINUS : ICON_FA_PLUS, &watch.show_history, ImGuiSelectableFlags_NoPadWithHalfSpacing); + ImGui::Selectable(watch.show_history ? ICON_ALT(ICON_FA_MINUS, "-") : ICON_ALT(ICON_FA_PLUS, "+"), &watch.show_history, ImGuiSelectableFlags_NoPadWithHalfSpacing); ImGui::PopID(); ImGui::PopStyleVar(); diff --git a/UE4SS/src/GUI/DX11.cpp b/UE4SS/src/GUI/Platform/D3D11/DX11.cpp similarity index 100% rename from UE4SS/src/GUI/DX11.cpp rename to UE4SS/src/GUI/Platform/D3D11/DX11.cpp diff --git a/UE4SS/src/GUI/GLFW3_OpenGL3.cpp b/UE4SS/src/GUI/Platform/GLFW/GLFW3_OpenGL3.cpp similarity index 100% rename from UE4SS/src/GUI/GLFW3_OpenGL3.cpp rename to UE4SS/src/GUI/Platform/GLFW/GLFW3_OpenGL3.cpp diff --git a/UE4SS/src/GUI/FaSolid900.hpp b/UE4SS/src/GUI/Platform/GUI/FaSolid900.hpp similarity index 100% rename from UE4SS/src/GUI/FaSolid900.hpp rename to UE4SS/src/GUI/Platform/GUI/FaSolid900.hpp diff --git a/UE4SS/src/GUI/Roboto.hpp b/UE4SS/src/GUI/Platform/GUI/Roboto.hpp similarity index 100% rename from UE4SS/src/GUI/Roboto.hpp rename to UE4SS/src/GUI/Platform/GUI/Roboto.hpp diff --git a/UE4SS/src/GUI/TUI.cpp b/UE4SS/src/GUI/Platform/TUI/TUI.cpp similarity index 98% rename from UE4SS/src/GUI/TUI.cpp rename to UE4SS/src/GUI/Platform/TUI/TUI.cpp index d99920ddc..9e74c1a04 100644 --- a/UE4SS/src/GUI/TUI.cpp +++ b/UE4SS/src/GUI/Platform/TUI/TUI.cpp @@ -25,7 +25,7 @@ namespace RC::GUI // disable stderr saved_stderr = dup(STDERR_FILENO); - freopen("/dev/null", "w", stderr); + freopen("./imtui.log", "w", stderr); setbuf(stderr, NULL); fprintf(stderr, "Backend_TUI::init\n"); fflush(stderr); diff --git a/UE4SS/src/GUI/Windows.cpp b/UE4SS/src/GUI/Platform/Windows/Windows.cpp similarity index 100% rename from UE4SS/src/GUI/Windows.cpp rename to UE4SS/src/GUI/Platform/Windows/Windows.cpp diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 9f03ffbb4..401e39d98 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -64,7 +64,27 @@ target(projectName) add_headerfiles("include/**.hpp") add_headerfiles("generated_include/*.hpp") - add_files("src/**.cpp|Platform/**.cpp") + add_files("src/**.cpp|Platform/**.cpp|GUI/**.cpp") + + if has_config("UI") then + add_files("src/GUI/*.cpp") + if is_plat("windows") then + -- we think by deafult windows have everything just for easy... + -- but this maybe not the case + add_files("src/GUI/Platform/D3D11/**.cpp") + add_files("src/GUI/Platform/GLFW/**.cpp") + add_files("src/GUI/Platform/GUI/**.cpp") + add_files("src/GUI/Platform/Windows/**.cpp") + else + if has_config("GUI") then + add_files("src/GUI/Platform/GUI/**.cpp") + add_files("src/GUI/Platform/GLFW/**.cpp") + end + if has_config("TUI") then + add_files("src/GUI/Platform/TUI/**.cpp") + end + end + end add_deps( "File", "DynamicOutput", "Unreal", @@ -77,9 +97,8 @@ target(projectName) add_options("UI", "GUI", "TUI", "Input") - if has_config("Input") then - add_deps("Input", { public = true }) - end + add_deps("Input", { public = true }) + if is_plat("windows") then add_files("src/Platform/Win32/CrashDumper.cpp") add_files("src/Platform/Win32/EntryWin32.cpp") @@ -89,9 +108,6 @@ target(projectName) end elseif is_plat("linux") then add_files("src/Platform/Linux/EntryLinux.cpp") - if not has_config("UI") then - remove_files("src/GUI/**.cpp") - end if has_config("GUI") then add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) elseif has_config("TUI") then diff --git a/deps/first/xmake.lua b/deps/first/xmake.lua index a68ce4b39..d0b34abac 100644 --- a/deps/first/xmake.lua +++ b/deps/first/xmake.lua @@ -6,11 +6,7 @@ includes("File") includes("Function") includes("Helpers") includes("IniParser") - -if (has_config("Input")) then - includes("Input") -end - +includes("Input") includes("JSON") includes("LuaMadeSimple") includes("LuaRaw") diff --git a/deps/third/imtui/xmake.lua b/deps/third/imtui/xmake.lua index a609db7a4..6d65222e1 100644 --- a/deps/third/imtui/xmake.lua +++ b/deps/third/imtui/xmake.lua @@ -1,11 +1,14 @@ package("imtui") add_urls("https://github.com/ggerganov/imtui.git") - add_versions("v1.0.5", "9f39c3e090c9b1e15557eac38a2f4389462f59df") + add_versions("v1.0.5-old", "9f39c3e090c9b1e15557eac38a2f4389462f59df") local root = get_config("ue4ssRoot") add_patches("v1.0.5", path.join(root, "deps", "third", "imtui", "fix-size-cjk-and-mouse.patch")) - add_deps("cmake") + -- WARN: xmake cannot distinguish ncursesw and ncurses, this may cause problem on other systems + add_deps("cmake", "ncurses") + + add_includedirs("include", "include/imgui-for-imtui/", "include/imgui-for-imtui/imgui", "include/imtui", {public = true}) -- imtui, imtui-ncurses and imgui-for-imtui on_install(function (package) @@ -16,5 +19,10 @@ package("imtui") table.insert(configs, "-DIMTUI_BUILD_EXAMPLES=OFF") import("package.tools.cmake").install(package, configs) + print(package:cachedir() .. "/source/imtui/") + print(package:installdir()) + os.cp("third-party/imgui/imgui/misc/cpp/imgui_stdlib.h", package:installdir("include/imgui-for-imtui/imgui/misc/cpp")) + os.cp("third-party/imgui/imgui/imgui_internal.h", package:installdir("include/imgui-for-imtui/imgui")) + os.cp("third-party/imgui/imgui/imstb_textedit.h", package:installdir("include/imgui-for-imtui/imgui")) end) package_end() From 009581c40b769f1ecec260653ca7869b04f11fe9 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 14:04:18 -0500 Subject: [PATCH 155/213] track latest upstream --- deps/first/patternsleuth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/patternsleuth b/deps/first/patternsleuth index baed68bcc..0d5175345 160000 --- a/deps/first/patternsleuth +++ b/deps/first/patternsleuth @@ -1 +1 @@ -Subproject commit baed68bccfed9d0ea794259c087317e636e64bdc +Subproject commit 0d5175345a4827f98bc51df893cf2079ebf53306 From 635fe9a9aa8f90a9b00309949711231dd58683b9 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 15:14:27 -0500 Subject: [PATCH 156/213] I hope I modified it right, because xmake won't build it again --- deps/first/patternsleuth_bind/Cargo.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/deps/first/patternsleuth_bind/Cargo.toml b/deps/first/patternsleuth_bind/Cargo.toml index 25f01784b..9efe6cffd 100644 --- a/deps/first/patternsleuth_bind/Cargo.toml +++ b/deps/first/patternsleuth_bind/Cargo.toml @@ -3,5 +3,8 @@ name = "patternsleuth_bind" version = "0.1.0" edition = "2021" -[dependencies] -patternsleuth = { path = "../patternsleuth/patternsleuth", features = ["process-internal"] } \ No newline at end of file +[target.'cfg( target_os = "linux" )'.dependencies] +patternsleuth = { path = "../patternsleuth/patternsleuth", features = ["process-internal", "image-elf"] } + +[target.'cfg( target_os = "windows" )'.dependencies] +patternsleuth = { path = "../patternsleuth/patternsleuth", features = ["process-internal", "image-pe"] } From 1dda177957af2006f503c393fed8e4534fa01085 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 20:15:22 -0500 Subject: [PATCH 157/213] force link order on linux --- deps/third-repo/packages/p/polyhook_2/xmake.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/deps/third-repo/packages/p/polyhook_2/xmake.lua b/deps/third-repo/packages/p/polyhook_2/xmake.lua index e1277306b..e0f1e5d47 100644 --- a/deps/third-repo/packages/p/polyhook_2/xmake.lua +++ b/deps/third-repo/packages/p/polyhook_2/xmake.lua @@ -5,7 +5,6 @@ package("polyhook_2") on_install(function (package) local configs = {} - table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) table.insert(configs, "-DBUILD_SHARED_LIBS=OFF") if is_plat("linux") then @@ -15,6 +14,11 @@ package("polyhook_2") table.insert(configs, "-DZYDIS_LIBRARY=" .. package:dep("zydis"):installdir("libzydis.a")) end import("package.tools.cmake").install(package, configs, { packagedeps = { "zycore", "zydis" } }) - + print(package:get("links")) + package:add("links", "PolyHook_2") + package:add("links", "asmjit") + package:add("links", "asmtk") + print(package:get("links")) + -- fuckyou() end) package_end() \ No newline at end of file From ac2e0bf9b7ef0d694d77133d8205bf6c4c9dddd7 Mon Sep 17 00:00:00 2001 From: Yangff Date: Tue, 16 Apr 2024 20:21:40 -0500 Subject: [PATCH 158/213] move asmtk -> asmjit --- deps/third-repo/packages/p/polyhook_2/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/third-repo/packages/p/polyhook_2/xmake.lua b/deps/third-repo/packages/p/polyhook_2/xmake.lua index e0f1e5d47..38055a289 100644 --- a/deps/third-repo/packages/p/polyhook_2/xmake.lua +++ b/deps/third-repo/packages/p/polyhook_2/xmake.lua @@ -16,8 +16,8 @@ package("polyhook_2") import("package.tools.cmake").install(package, configs, { packagedeps = { "zycore", "zydis" } }) print(package:get("links")) package:add("links", "PolyHook_2") - package:add("links", "asmjit") package:add("links", "asmtk") + package:add("links", "asmjit") print(package:get("links")) -- fuckyou() end) From be6e97abc1b0185284fcdde6842a165c7e536d6e Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 17 Apr 2024 02:24:01 -0500 Subject: [PATCH 159/213] remove comment --- deps/third-repo/packages/p/polyhook_2/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/deps/third-repo/packages/p/polyhook_2/xmake.lua b/deps/third-repo/packages/p/polyhook_2/xmake.lua index 38055a289..5704f7952 100644 --- a/deps/third-repo/packages/p/polyhook_2/xmake.lua +++ b/deps/third-repo/packages/p/polyhook_2/xmake.lua @@ -19,6 +19,5 @@ package("polyhook_2") package:add("links", "asmtk") package:add("links", "asmjit") print(package:get("links")) - -- fuckyou() end) package_end() \ No newline at end of file From 87dc38f274ce7e42fd7acf86d9a459304ae95217 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 17 Apr 2024 02:32:56 -0500 Subject: [PATCH 160/213] set correct config for imgui --- UE4SS/xmake.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 401e39d98..a6a9baaed 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -4,7 +4,11 @@ if is_plat("windows") then end if has_config("GUI") then - add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = true, dx11 = true, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) + if is_plat("windows") then + add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = true, dx11 = true, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) + else + add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = false, dx11 = false, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) + end elseif has_config("TUI") then add_requires("imtui v1.0.5", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) end From 91f9808502fd4961b4c34f8d0c012628547ef404 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 17 Apr 2024 02:40:57 -0500 Subject: [PATCH 161/213] move back --- UE4SS/src/GUI/{Platform/GUI => }/FaSolid900.hpp | 0 UE4SS/src/GUI/{Platform/GUI => }/Roboto.hpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename UE4SS/src/GUI/{Platform/GUI => }/FaSolid900.hpp (100%) rename UE4SS/src/GUI/{Platform/GUI => }/Roboto.hpp (100%) diff --git a/UE4SS/src/GUI/Platform/GUI/FaSolid900.hpp b/UE4SS/src/GUI/FaSolid900.hpp similarity index 100% rename from UE4SS/src/GUI/Platform/GUI/FaSolid900.hpp rename to UE4SS/src/GUI/FaSolid900.hpp diff --git a/UE4SS/src/GUI/Platform/GUI/Roboto.hpp b/UE4SS/src/GUI/Roboto.hpp similarity index 100% rename from UE4SS/src/GUI/Platform/GUI/Roboto.hpp rename to UE4SS/src/GUI/Roboto.hpp From b94439dd9a73b40484f4410697a4f51f88ad8f3f Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 17 Apr 2024 02:41:03 -0500 Subject: [PATCH 162/213] no file to include --- UE4SS/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index a6a9baaed..4cabf58eb 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -81,7 +81,6 @@ target(projectName) add_files("src/GUI/Platform/Windows/**.cpp") else if has_config("GUI") then - add_files("src/GUI/Platform/GUI/**.cpp") add_files("src/GUI/Platform/GLFW/**.cpp") end if has_config("TUI") then From 0b500abf86b770c2380cd971a58857fdba343f62 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 20 Apr 2024 18:31:23 -0500 Subject: [PATCH 163/213] move plat headers, modify generator path --- UVTD/include/UVTD/Helpers.hpp | 6 +++--- UVTD/scripts/HeaderGen.py | 4 ++-- UVTD/src/UnrealVirtualGenerator.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/UVTD/include/UVTD/Helpers.hpp b/UVTD/include/UVTD/Helpers.hpp index ba9ab4377..fdb1d9da9 100644 --- a/UVTD/include/UVTD/Helpers.hpp +++ b/UVTD/include/UVTD/Helpers.hpp @@ -16,16 +16,16 @@ namespace RC::UVTD { static std::filesystem::path vtable_gen_output_path = "GeneratedVTables"; - static std::filesystem::path vtable_gen_output_include_path = vtable_gen_output_path / "generated_include"; + static std::filesystem::path vtable_gen_output_include_path = vtable_gen_output_path / "generated_include" / "Windows"; static std::filesystem::path vtable_gen_output_src_path = vtable_gen_output_path / "generated_src"; static std::filesystem::path vtable_gen_output_function_bodies_path = vtable_gen_output_include_path / "FunctionBodies"; static std::filesystem::path vtable_templates_output_path = "VTableLayoutTemplates"; static std::filesystem::path virtual_gen_output_path = "GeneratedVirtualImplementations"; - static std::filesystem::path virtual_gen_output_include_path = virtual_gen_output_path / "generated_include"; + static std::filesystem::path virtual_gen_output_include_path = virtual_gen_output_path / "generated_include" / "Windows"; static std::filesystem::path virtual_gen_function_bodies_path = virtual_gen_output_include_path / "FunctionBodies"; static std::filesystem::path member_variable_layouts_gen_output_path = "GeneratedMemberVariableLayouts"; - static std::filesystem::path member_variable_layouts_gen_output_include_path = member_variable_layouts_gen_output_path / "generated_include"; + static std::filesystem::path member_variable_layouts_gen_output_include_path = member_variable_layouts_gen_output_path / "generated_include" / "Windows"; static std::filesystem::path member_variable_layouts_gen_output_src_path = member_variable_layouts_gen_output_path / "generated_src"; static std::filesystem::path member_variable_layouts_gen_function_bodies_path = member_variable_layouts_gen_output_include_path / "FunctionBodies"; static std::filesystem::path member_variable_layouts_templates_output_path = "MemberVarLayoutTemplates"; diff --git a/UVTD/scripts/HeaderGen.py b/UVTD/scripts/HeaderGen.py index bc4e9445b..aff549837 100755 --- a/UVTD/scripts/HeaderGen.py +++ b/UVTD/scripts/HeaderGen.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 # generate header file for C++, using DRAWF information from .debug files -# e.g., ./HeaderGen.py -s -g -t ../../deps/first/Unreal/generated_include/FunctionBodies //UnrealGame-Linux-Shipping.debug +# e.g., ./HeaderGen.py -s -g -t ../../deps/first/Unreal/generated_include/Linux/FunctionBodies //UnrealGame-Linux-Shipping.debug import os import sys import re import pickle DEFAULT_FILENAME = "./UnrealGame-Linux-Shipping.debug" -DEFAULT_SEARCH_DIR = "../../deps/first/Unreal/generated_include" +DEFAULT_SEARCH_DIR = "../../deps/first/Unreal/generated_include/Windows" DEFAULT_GENERATED_DIR = "../generated" FUNCTION_TEMPLATE = """if (auto it = {ClassName}::VTableLayoutMap.find(STR("{FunctionName}")); it == {ClassName}::VTableLayoutMap.end()) diff --git a/UVTD/src/UnrealVirtualGenerator.cpp b/UVTD/src/UnrealVirtualGenerator.cpp index ad38042b7..2c77d96d7 100644 --- a/UVTD/src/UnrealVirtualGenerator.cpp +++ b/UVTD/src/UnrealVirtualGenerator.cpp @@ -39,7 +39,7 @@ namespace RC::UVTD { virtual_header_dumper.send(SYSSTR("#ifndef RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); virtual_header_dumper.send(SYSSTR("#define RC_UNREAL_UNREAL_VIRTUAL{}_HPP\n"), pdb_name_no_underscore); - virtual_header_dumper.send(SYSSTR("#include \n\n")); + virtual_header_dumper.send(SYSSTR("#include \n\n")); virtual_header_dumper.send(SYSSTR("namespace RC::Unreal\n")); virtual_header_dumper.send(SYSSTR("{\n")); virtual_header_dumper.send(SYSSTR(" class UnrealVirtual{} : public UnrealVirtualBaseVC\n"), pdb_name_no_underscore); From 023a6d78a25804c21728af8459aad56c3a394410 Mon Sep 17 00:00:00 2001 From: localcc Date: Sun, 19 May 2024 13:33:38 +0200 Subject: [PATCH 164/213] thing --- UE4SS/src/GUI/LiveView.cpp | 4 +- UE4SS/src/Mod/CppUserModBase.cpp | 45 +++--- UE4SS/src/UE4SSProgram.cpp | 5 +- UE4SS/xmake.lua | 133 ++++++++++-------- deps/first/ParserBase/src/TokenParser.cpp | 2 + .../packages/i/imguitextedit/xmake.lua | 68 +++++---- deps/third/DynoHook/00-compilebugs.patch | 61 -------- deps/third/imtui/xmake.lua | 4 +- deps/third/xmake.lua | 16 +-- deps/xmake.lua | 7 - tools/xmakescripts/configurations.lua | 51 ------- tools/xmakescripts/rules/build_rules.lua | 18 ++- xmake.lua | 19 ++- 13 files changed, 180 insertions(+), 253 deletions(-) delete mode 100644 deps/third/DynoHook/00-compilebugs.patch delete mode 100644 tools/xmakescripts/configurations.lua diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 24ce20add..3bd184703 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -1577,14 +1577,14 @@ namespace RC::GUI std::string search_buffer{m_search_by_name_buffer}; if (search_buffer.empty() || s_apply_search_filters_when_not_searching) { - Output::send(STR("Search all chunks\n")); + Output::send(SYSSTR("Search all chunks\n")); s_name_to_search_by.clear(); m_object_iterator = &LiveView::guobjectarray_iterator; m_is_searching_by_name = false; } else { - Output::send(STR("Search for: {}\n"), search_buffer.empty() ? STR("") : to_wstring(search_buffer)); + Output::send(SYSSTR("Search for: {}\n"), search_buffer.empty() ? STR("") : to_wstring(search_buffer)); s_name_to_search_by = search_buffer; m_object_iterator = &LiveView::guobjectarray_by_name_iterator; m_is_searching_by_name = true; diff --git a/UE4SS/src/Mod/CppUserModBase.cpp b/UE4SS/src/Mod/CppUserModBase.cpp index c5f30efb7..2847aea7e 100644 --- a/UE4SS/src/Mod/CppUserModBase.cpp +++ b/UE4SS/src/Mod/CppUserModBase.cpp @@ -24,29 +24,30 @@ namespace RC } GUITabs.clear(); - auto& key_events = UE4SSProgram::get_program().m_input_handler.get_events(); - std::erase_if(key_events, [&](Input::KeySet& input_event) -> bool { - bool were_all_events_registered_from_this_mod = true; - for (auto& [key, vector_of_key_data] : input_event.key_data) - { - std::erase_if(vector_of_key_data, [&](Input::KeyData& key_data) -> bool { - // custom_data == 1: Bind came from Lua, and custom_data2 is nullptr. - // custom_data == 2: Bind came from C++, and custom_data2 is a pointer to KeyDownEventData. Must free it. - auto event_data = static_cast(key_data.custom_data2); - if (key_data.custom_data == 2 && event_data && event_data->mod == this) - { - delete event_data; - return true; - } - else - { - were_all_events_registered_from_this_mod = false; - return false; - } - }); - } + UE4SSProgram::get_program().m_input_handler.get_events_safe([&](auto& key_events) { + std::erase_if(key_events, [&](Input::KeySet& input_event) -> bool { + bool were_all_events_registered_from_this_mod = true; + for (auto& [key, vector_of_key_data] : input_event.key_data) + { + std::erase_if(vector_of_key_data, [&](Input::KeyData& key_data) -> bool { + // custom_data == 1: Bind came from Lua, and custom_data2 is nullptr. + // custom_data == 2: Bind came from C++, and custom_data2 is a pointer to KeyDownEventData. Must free it. + auto event_data = static_cast(key_data.custom_data2); + if (key_data.custom_data == 2 && event_data && event_data->mod == this) + { + delete event_data; + return true; + } + else + { + were_all_events_registered_from_this_mod = false; + return false; + } + }); + } - return were_all_events_registered_from_this_mod; + return were_all_events_registered_from_this_mod; + }); }); #endif } diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 7cfae2853..3bbe1da43 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1318,7 +1318,8 @@ namespace RC { set_error(error_message.c_str()); } - #ifdef HAS_UI + +#ifdef HAS_UI // If this is the initial startup, notify mods that the UI has initialized. // This isn't completely accurate since the UI will usually have started a while ago. // However, we can't immediately notify mods of this because no mods have been started at that point. @@ -1327,7 +1328,7 @@ namespace RC { fire_ui_init_for_cpp_mods(); } - #endif +#endif } auto UE4SSProgram::uninstall_mods() -> void diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 4cabf58eb..fa5df2d65 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -1,26 +1,18 @@ - -if is_plat("windows") then - includes("proxy_generator") -end - -if has_config("GUI") then - if is_plat("windows") then - add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = true, dx11 = true, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) - else - add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = false, dx11 = false, opengl3 = true, glfw_opengl3 = true, runtimes = get_mode_runtimes() } }) +local hasWindows = is_plat("windows") +local uiMode = get_config("ue4ssUI") + +if uiMode ~= nil and uiMode ~= "None" then + local isTUI = uiMode == "TUI" + add_requires("ImGuiTextEdit v1.0", { debug = is_mode_debug(), configs = { tui = isTUI, runtimes = get_mode_runtimes() } }) + + if uiMode == "GUI" then + add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = hasWindows, dx11 = hasWindows, opengl3 = true, glfw_opengl3 = true , runtimes = get_mode_runtimes()} } ) + add_requires("IconFontCppHeaders v1.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()}}) + add_requires("glfw 3.3.9", { debug = is_mode_debug() , configs = {runtimes = get_mode_runtimes()}}) + add_requires("opengl", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) + elseif uiMode == "TUI" then + add_requires("imtui v1.0.5", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) end -elseif has_config("TUI") then - add_requires("imtui v1.0.5", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) -end - -if has_config("UI") then - add_requires("ImGuiTextEdit v1.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) -end - -if has_config("GUI") then - add_requires("IconFontCppHeaders v1.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) - add_requires("glfw 3.3.9", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) - add_requires("opengl", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) end option("ue4ssBetaIsStarted") @@ -39,6 +31,48 @@ option("ue4ssIsBeta") set_description("Is this a beta release") +option("ue4ssUI") + set_default("GUI") + set_showmenu(true) + + set_values("None", "GUI", "TUI") + + set_description("UE4SS GUI Modes. TUI is not available on windows") + + after_check(function (option) + local value = option:value() + + if value == "TUI" and is_plat("windows") then + raise("TUI is not available on windows") + end + + if value ~= "None" then + option:add("defines", "HAS_UI") + end + + if value == "GUI" then + option:add("defines", "HAS_GUI") + elseif value == "TUI" then + option:add("defines", "HAS_TUI") + end + end) + +option("ue4ssInput") + set_default(true) + set_showmenu(true) + + add_deps("ue4ssUI") + add_defines("HAS_INPUT") + + set_description("Enable the input system.") + + after_check(function (option) + local noUI = option:dep("ue4ssUI"):value() == "None" + if noUI and not is_plat("windows") then + option:enable(false) + end + end) + local projectName = "UE4SS" local function parse_version_string(str) @@ -62,7 +96,7 @@ target(projectName) set_exceptions("cxx") set_default(true) add_rules("ue4ss.defines.exports") - add_options("ue4ssBetaIsStarted", "ue4ssIsBeta") + add_options("ue4ssBetaIsStarted", "ue4ssIsBeta", "ue4ssUI", "ue4ssInput") add_includedirs("include", { public = true }) add_includedirs("generated_include", { public = true }) add_headerfiles("include/**.hpp") @@ -70,22 +104,29 @@ target(projectName) add_files("src/**.cpp|Platform/**.cpp|GUI/**.cpp") - if has_config("UI") then + if uiMode ~= "None" then add_files("src/GUI/*.cpp") - if is_plat("windows") then - -- we think by deafult windows have everything just for easy... - -- but this maybe not the case - add_files("src/GUI/Platform/D3D11/**.cpp") + + add_packages("ImGuiTextEdit", { public = true }) + + if uiMode == "GUI" then add_files("src/GUI/Platform/GLFW/**.cpp") add_files("src/GUI/Platform/GUI/**.cpp") - add_files("src/GUI/Platform/Windows/**.cpp") - else - if has_config("GUI") then - add_files("src/GUI/Platform/GLFW/**.cpp") - end - if has_config("TUI") then - add_files("src/GUI/Platform/TUI/**.cpp") + + add_deps("glad") + + add_packages("ImGui", "IconFontCppHeaders", "glfw", "opengl", { public = true }) + + if is_plat("windows") then + add_files("src/GUI/Platform/D3D11/**.cpp") + add_files("src/GUI/Platform/Windows/**.cpp") + + add_links("d3d11", { public = true }) end + elseif uiMode == "TUI" then + add_files("src/GUI/Platform/TUI/**.cpp") + + add_packages("imtui", { public = true }) end end @@ -95,29 +136,11 @@ target(projectName) "IniParser", "JSON", "Constructs", "Helpers", "MProgram", "ScopedTimer", "Profiler", "patternsleuth_bind", - "glad", { public = true } + { public = true } ) - add_options("UI", "GUI", "TUI", "Input") - add_deps("Input", { public = true }) - - if is_plat("windows") then - add_files("src/Platform/Win32/CrashDumper.cpp") - add_files("src/Platform/Win32/EntryWin32.cpp") - if has_config("GUI") then - add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) - add_links("d3d11", { public = true }) - end - elseif is_plat("linux") then - add_files("src/Platform/Linux/EntryLinux.cpp") - if has_config("GUI") then - add_packages("ImGui", "ImGuiTextEdit", "IconFontCppHeaders", "glfw", "opengl", { public = true }) - elseif has_config("TUI") then - add_packages("imtui", "ImGuiTextEdit", { public = true }) - end - end - + add_packages("glaze", "polyhook_2", { public = true }) after_load(function (target) diff --git a/deps/first/ParserBase/src/TokenParser.cpp b/deps/first/ParserBase/src/TokenParser.cpp index a01c448be..750ca15eb 100644 --- a/deps/first/ParserBase/src/TokenParser.cpp +++ b/deps/first/ParserBase/src/TokenParser.cpp @@ -2,6 +2,8 @@ #include #include +#include + namespace RC::ParserBase { TokenParser::TokenParser(const Tokenizer& tokenizer, SystemStringType& input) : m_tokenizer(tokenizer), m_data(input) diff --git a/deps/third-repo/packages/i/imguitextedit/xmake.lua b/deps/third-repo/packages/i/imguitextedit/xmake.lua index 21374570a..e5f80d4e6 100644 --- a/deps/third-repo/packages/i/imguitextedit/xmake.lua +++ b/deps/third-repo/packages/i/imguitextedit/xmake.lua @@ -4,19 +4,29 @@ package("ImGuiTextEdit") add_versions("v1.0", "master") - local imgui_name = "imgui" + add_configs("tui", { description = "Enable TUI.", default = false, type = "boolean" }) - if has_config("GUI") then - add_deps("cmake", "imgui v1.89") - elseif has_config("TUI") then - add_deps("cmake", "imtui v1.0.5") - imgui_name = "imtui" - end + add_deps("cmake") add_includedirs("include", { public = true }) + local function _get_imgui_name(isTUI) + if isTUI then + return { name = "imtui", version = "v1.0.5" } + else + return { name = "imgui", version = "v1.89" } + end + end + + on_load(function (package) + local imgui = _get_imgui_name(package:config("tui")) + package:add("deps", string.format("%s %s", imgui.name, imgui.version)) + end) + on_install(function (package) - local imgui = package:dep(imgui_name) + local imguiName = _get_imgui_name(package:config("tui")).name + local imgui = package:dep(imguiName) + local configs = imgui:requireinfo().configs if configs then @@ -38,31 +48,29 @@ package("ImGuiTextEdit") add_files("*.cpp") add_packages("%s") - ]]):format(imgui_name, imgui:version_str(), configs, imgui_name) + ]]):format(imguiName, imgui:version_str(), configs, imguiName) io.writefile("xmake.lua", xmake_lua) import("package.tools.xmake").install(package) end) package_end() -if has_config("GUI") then - package("IconFontCppHeaders") - add_urls("git@github.com:juliettef/IconFontCppHeaders.git") - add_urls("https://github.com/juliettef/IconFontCppHeaders.git") - set_kind("library", { headeronly = true }) - - add_versions("v1.0", "main") - - on_install(function (package) - os.cp("**.h", package:installdir("include")) - end) - - on_test(function (package) - assert(package:check_cxxsnippets({ test = [[ - void test() { - ICON_FA_TERMINAL; - } - ]]}, { includes = { "IconsFontAwesome5.h" } })) - end) - package_end() -end +package("IconFontCppHeaders") + add_urls("git@github.com:juliettef/IconFontCppHeaders.git") + add_urls("https://github.com/juliettef/IconFontCppHeaders.git") + set_kind("library", { headeronly = true }) + + add_versions("v1.0", "main") + + on_install(function (package) + os.cp("**.h", package:installdir("include")) + end) + + on_test(function (package) + assert(package:check_cxxsnippets({ test = [[ + void test() { + ICON_FA_TERMINAL; + } + ]]}, { includes = { "IconsFontAwesome5.h" } })) + end) +package_end() diff --git a/deps/third/DynoHook/00-compilebugs.patch b/deps/third/DynoHook/00-compilebugs.patch deleted file mode 100644 index 0df69e274..000000000 --- a/deps/third/DynoHook/00-compilebugs.patch +++ /dev/null @@ -1,61 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 1633c1e..f215704 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -256,7 +256,7 @@ endif() - #Zydis - if(DYNOHOOK_USE_EXTERNAL_ZYDIS) - find_package(zydis REQUIRED) -- target_link_libraries(${PROJECT_NAME} PUBLIC Zydis::Zydis) -+ target_link_libraries(${PROJECT_NAME} PUBLIC Zydis) - else() - target_link_libraries(${PROJECT_NAME} PUBLIC $) - target_include_directories(${PROJECT_NAME} PUBLIC $) -diff --git a/src/detours/x64_detour.cpp b/src/detours/x64_detour.cpp -index 9e309dd..355119d 100644 ---- a/src/detours/x64_detour.cpp -+++ b/src/detours/x64_detour.cpp -@@ -3,6 +3,8 @@ - #include - #include - -+#include -+ - using namespace std::string_literals; - - using namespace dyno; -diff --git a/src/mem_accessor.cpp b/src/mem_accessor.cpp -index c3b6795..1d0b071 100644 ---- a/src/mem_accessor.cpp -+++ b/src/mem_accessor.cpp -@@ -2,6 +2,8 @@ - #include - #include - -+#include -+ - using namespace dyno; - - #if DYNO_PLATFORM_WINDOWS -@@ -74,7 +76,7 @@ static region_t get_region_from_addr(uintptr_t addr) { - res.prot = res.prot | ProtFlag::X; - - if (res.prot == ProtFlag::UNSET) -- res.prot = ProtFlag::NONE; -+ res.prot = ProtFlag::UNSET; - - break; - } -diff --git a/src/x64_hook.cpp b/src/x64_hook.cpp -index b419a45..32c51cc 100644 ---- a/src/x64_hook.cpp -+++ b/src/x64_hook.cpp -@@ -161,7 +161,7 @@ void x64Hook::writeModifyReturnAddress(Assembler& a) { - a.lea(rdx, qword_ptr(rsp, pushed)); - a.mov(rsi, qword_ptr(rsp, pushed)); - a.mov(rdi, this); -- a.sub(rsp, space); -+ a.sub(rsp, reserved); - a.call((void*&) setReturnAddress); // stack should be aligned by 16 bytes, call adds +8 - a.add(rsp, reserved); - #endif diff --git a/deps/third/imtui/xmake.lua b/deps/third/imtui/xmake.lua index 6d65222e1..25e5b9bb8 100644 --- a/deps/third/imtui/xmake.lua +++ b/deps/third/imtui/xmake.lua @@ -1,9 +1,9 @@ package("imtui") add_urls("https://github.com/ggerganov/imtui.git") - add_versions("v1.0.5-old", "9f39c3e090c9b1e15557eac38a2f4389462f59df") + add_versions("v1.0.5", "9f39c3e090c9b1e15557eac38a2f4389462f59df") local root = get_config("ue4ssRoot") - add_patches("v1.0.5", path.join(root, "deps", "third", "imtui", "fix-size-cjk-and-mouse.patch")) + -- add_patches("v1.0.5", path.join(root, "deps", "third", "imtui", "fix-size-cjk-and-mouse.patch")) -- WARN: xmake cannot distinguish ncursesw and ncurses, this may cause problem on other systems add_deps("cmake", "ncurses") diff --git a/deps/third/xmake.lua b/deps/third/xmake.lua index a04384296..24409b73a 100644 --- a/deps/third/xmake.lua +++ b/deps/third/xmake.lua @@ -2,20 +2,10 @@ includes("zycore") includes("zydis") includes("polyhook_2") includes("glaze") - -if has_config("TUI") then - includes("imtui") -end - -if has_config("UI") then - includes("imgui") -end - +-- includes("imtui") +includes("imgui") includes("glad") - -if is_plat("windows") then - includes("raw_pdb") -end +includes("raw_pdb") add_requires("zycore v1.5.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) add_requires("zydis v4.1.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) diff --git a/deps/xmake.lua b/deps/xmake.lua index 45680fba6..62ded994a 100644 --- a/deps/xmake.lua +++ b/deps/xmake.lua @@ -2,10 +2,3 @@ includes("first") -- Third party dependencies includes("third") --- Third party dependencies repository --- Everything that is an xmake package should be inside of this repository -add_repositories("third-party deps/third-repo", { rootdir = get_config("ue4ssRoot") }) - -add_requires("zycore v1.5.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) -add_requires("zydis v4.1.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) -add_requires("polyhook_2", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) \ No newline at end of file diff --git a/tools/xmakescripts/configurations.lua b/tools/xmakescripts/configurations.lua deleted file mode 100644 index ed3962dd2..000000000 --- a/tools/xmakescripts/configurations.lua +++ /dev/null @@ -1,51 +0,0 @@ --- UI configurations - -option("UI") - set_default(true) - set_showmenu(true) - add_defines("HAS_UI") - set_description("Enable the user iterface.") - -option("GUI") - -- Windows has only GUI - set_default(is_plat("windows")) - set_showmenu(true) - add_defines("HAS_GUI") - add_deps("UI") - set_description("Enable the graphical user interface.") - if is_plat("windows") then - add_defines("HAS_D3D11") - add_defines("HAS_GLFW") - elseif is_plat("linux") then - add_defines("HAS_GLFW") - end - -option("TUI") - -- use TUI by default on Linux - set_default(is_plat("linux")) - set_showmenu(true) - add_defines("HAS_TUI") - add_deps("UI") - set_description("Enable the text user interface. (Not supported on Windows)") - after_check(function (option) - -- mutually exclusive with GUI - if has_config("GUI") then - option:enable(false) - end - if is_plat("windows") then - option:enable(false) - end - end) - --- Input configurations - -option("Input") - set_default(has_config("UI") or is_plat("windows")) - set_showmenu(true) - add_defines("HAS_INPUT") - set_description("Enable the input system.") - after_check(function (option) - if not has_config("UI") and not is_plat("windows") then - option:enable(false) - end - end) \ No newline at end of file diff --git a/tools/xmakescripts/rules/build_rules.lua b/tools/xmakescripts/rules/build_rules.lua index 194d2849d..cf4b88545 100644 --- a/tools/xmakescripts/rules/build_rules.lua +++ b/tools/xmakescripts/rules/build_rules.lua @@ -61,7 +61,20 @@ local PLATFORM_TYPES = { "UNICODE", "_UNICODE" }, - + }, + ["Linux"] = { + ["defines"] = { + "PLATFORM_LINUX", + "PLATFORM_UNIX", + "LINUX", + "OVERRIDE_PLATFORM_HEADER_NAME=Linux", + "UBT_COMPILED_PLATFORM=Linux", + "printf_s=printf", + "DLLEXT=.so" + }, + ["cxflags"] = { + "clang::-fno-delete-null-pointer-checks" + } } } @@ -77,7 +90,8 @@ local CLANG_COMPILE_OPTIONS = { "-Wno-unknown-pragmas", "-Wno-unused-parameter", "-fms-extensions", - "-Wignored-attributes" + "-Wignored-attributes", + "-fPIC" }, ["ldflags"] = { "-g" diff --git a/xmake.lua b/xmake.lua index 6e9a9c351..f2862b373 100644 --- a/xmake.lua +++ b/xmake.lua @@ -56,11 +56,15 @@ add_rules("ue4ss.core") -- Restrict the compilation modes/configs. -- These restrictions are inherited upstream and downstream. -- Any project that `includes("UE4SS")` will inherit these global restrictions. -set_allowedplats("windows") -set_allowedarchs("x64") +set_allowedplats("windows", "linux") +set_allowedarchs("x64", "x86_64") set_allowedmodes(modes) -if is_host("windows") then +if is_plat("linux") then + set_toolchains("clang", "rust") +end + +if is_plat("windows") then set_defaultmode("Game__Shipping__Win64") end @@ -70,7 +74,10 @@ on_install(function(target) end) includes("deps") includes("UE4SS") +-- includes("UVTD") -if is_plat("windows") then - includes("UVTD") -end +-- TODO: Remove this before the next release. It only exists to maintain backwards compat +-- warnings for older mod templates. +set_config("scriptsRoot", path.join(os.scriptdir(), "tools/xmakescripts")) + +add_repositories("thirdr deps/thirdr") From 00791f823a59bbcf4458de07b7ecb1d1271f609d Mon Sep 17 00:00:00 2001 From: localcc Date: Sun, 19 May 2024 22:58:09 +0200 Subject: [PATCH 165/213] change init --- UE4SS/src/Platform/Linux/EntryLinux.cpp | 19 +++++++++++++------ UE4SS/src/UE4SSProgram.cpp | 14 ++++++++------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/UE4SS/src/Platform/Linux/EntryLinux.cpp b/UE4SS/src/Platform/Linux/EntryLinux.cpp index 5aa0fd352..d9c582bb9 100644 --- a/UE4SS/src/Platform/Linux/EntryLinux.cpp +++ b/UE4SS/src/Platform/Linux/EntryLinux.cpp @@ -47,16 +47,23 @@ void UE4SS_Start() fprintf(stderr, "%s\n", e.what()); } #endif - auto ue4sspath = to_system_string(dl_info.dli_fname); - auto program = new UE4SSProgram(ue4sspath, {}); - UE4SSInited = true; + + auto ue4sspath = new SystemStringType(to_system_string(dl_info.dli_fname)); // use pthread here pthread_create( &ue4ss_mainthread, nullptr, [](void* arg) -> void* { - auto program = (UE4SSProgram*)arg; - program->init(); + auto ue4sspathPtr = reinterpret_cast(arg); + auto program = new UE4SSProgram(*ue4sspathPtr, {}); + delete ue4sspathPtr; + UE4SSInited = true; + + if (auto e = program->get_error_object(); !e->has_error()) + { + program->init(); + } + if (auto e = program->get_error_object(); e->has_error()) { // If the output system errored out then use printf_s as a fallback @@ -72,7 +79,7 @@ void UE4SS_Start() } return nullptr; }, - program); + ue4sspath); } /* diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 3bbe1da43..c1144be98 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -175,13 +175,20 @@ namespace RC { setup_paths(moduleFilePath); + // Setup the log file + auto& file_device = Output::set_default_devices(); + fprintf(stderr, "log dir: %s\n", (m_log_directory / m_log_file_name).c_str()); + file_device.set_file_name_and_path(to_system(m_log_directory / m_log_file_name)); + + create_simple_console(); + try { settings_manager.deserialize(m_settings_path_and_file); } catch (std::exception& e) { - create_emergency_console_for_early_error(std::format(SYSSTR("The IniParser failed to parse: {}"), to_system(e.what()))); + set_error("The IniParser failed to parse: %s", to_system(e.what()).data()); return; } @@ -202,11 +209,6 @@ namespace RC m_input_handler.init(); #endif - // Setup the log file - auto& file_device = Output::set_default_devices(); - file_device.set_file_name_and_path(to_system(m_log_directory / m_log_file_name)); - - create_simple_console(); #ifdef HAS_UI if (settings_manager.Debug.DebugConsoleEnabled) From 425e76bafa6736c62bc40d3b20a8feeb41181bd3 Mon Sep 17 00:00:00 2001 From: localcc Date: Wed, 22 May 2024 18:41:52 +0200 Subject: [PATCH 166/213] fix xmake compilation --- .../GUI/LiveView/Filter/ClassNamesFilter.hpp | 4 +- .../GUI/LiveView/Filter/HasProperty.hpp | 4 +- .../GUI/LiveView/Filter/HasPropertyType.hpp | 4 +- UE4SS/include/GUI/NerdFont.hpp | 1 + UE4SS/src/GUI/GUI.cpp | 1 + UE4SS/src/GUI/LiveView.1.PVS-Studio.cfg | 40 ----- UE4SS/src/GUI/LiveView.cpp | 143 ++++++++++-------- UE4SS/src/Mod/CppUserModBase.cpp | 40 ++--- UE4SS/src/UE4SSProgram.cpp | 22 +-- UE4SS/xmake.lua | 20 ++- .../packages/i/imguitextedit/xmake.lua | 2 - .../i}/imtui/fix-size-cjk-and-mouse.patch | 0 .../packages/i}/imtui/xmake.lua | 7 +- tools/xmakescripts/rules/build_rules.lua | 9 +- xmake.lua | 2 - 15 files changed, 145 insertions(+), 154 deletions(-) delete mode 100644 UE4SS/src/GUI/LiveView.1.PVS-Studio.cfg rename deps/{third => third-repo/packages/i}/imtui/fix-size-cjk-and-mouse.patch (100%) rename deps/{third => third-repo/packages/i}/imtui/xmake.lua (81%) diff --git a/UE4SS/include/GUI/LiveView/Filter/ClassNamesFilter.hpp b/UE4SS/include/GUI/LiveView/Filter/ClassNamesFilter.hpp index e4206c495..e3df573bb 100644 --- a/UE4SS/include/GUI/LiveView/Filter/ClassNamesFilter.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/ClassNamesFilter.hpp @@ -8,9 +8,9 @@ namespace RC::GUI::Filter class ClassNamesFilter { public: - static inline StringType s_debug_name{STR("ClassNamesFilter")}; + static inline UEStringType s_debug_name{STR("ClassNamesFilter")}; static inline std::string s_internal_class_names{}; - static inline std::vector list_class_names; + static inline std::vector list_class_names; static inline bool b_is_exclude{true}; static auto post_eval(UObject* object) -> bool diff --git a/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp b/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp index 9a390bd24..e5b19b921 100644 --- a/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/HasProperty.hpp @@ -9,8 +9,8 @@ namespace RC::GUI::Filter { public: static inline UEStringType s_debug_name{STR("HasProperty")}; - static inline UEStringType s_value{}; - static inline std::string s_internal_value{}; + static inline std::string s_internal_properties{}; + static inline std::vector list_properties{}; static auto post_eval(UObject* object) -> bool { diff --git a/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp b/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp index 1d7203e44..44af3a079 100644 --- a/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp +++ b/UE4SS/include/GUI/LiveView/Filter/HasPropertyType.hpp @@ -11,8 +11,8 @@ namespace RC::GUI::Filter { public: static inline UEStringType s_debug_name{STR("HasPropertyType")}; - static inline FName s_value{}; - static inline std::string s_internal_value{}; + static inline std::string s_internal_property_types{}; + static inline std::vector list_property_types{}; static auto post_eval(UObject* object) -> bool { diff --git a/UE4SS/include/GUI/NerdFont.hpp b/UE4SS/include/GUI/NerdFont.hpp index e109221b2..03017a056 100644 --- a/UE4SS/include/GUI/NerdFont.hpp +++ b/UE4SS/include/GUI/NerdFont.hpp @@ -6,6 +6,7 @@ #define ICON_FA_FILE_ALT "\uf15b" #define ICON_FA_EYE "\uf06e" #define ICON_FA_PUZZLE_PIECE "\uf12e" +#define ICON_FA_SAVE "\ueb4b" #define ICON_FA_ANGLE_DOUBLE_LEFT "<<" #define ICON_FA_ANGLE_DOUBLE_RIGHT ">>" diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index ef7315959..2f3d2b8a3 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -547,6 +547,7 @@ namespace RC::GUI auto DebuggingGUI::set_gfx_backend(GfxBackend backend) -> void { + Output::send(SYSSTR("Setting gfx backend!\n")); switch (backend) { #ifdef HAS_D3D11 diff --git a/UE4SS/src/GUI/LiveView.1.PVS-Studio.cfg b/UE4SS/src/GUI/LiveView.1.PVS-Studio.cfg deleted file mode 100644 index 5df1eca60..000000000 --- a/UE4SS/src/GUI/LiveView.1.PVS-Studio.cfg +++ /dev/null @@ -1,40 +0,0 @@ -analysis-mode=12 -disable-ms-extensions=yes -exclude-path=*\boost\* -exclude-path=*\zlib\* -exclude-path=*\png\* -exclude-path=*\libpng\* -exclude-path=*\pnglib\* -exclude-path=*\freetype\* -exclude-path=*\ImageMagick\* -exclude-path=*\jpeglib\* -exclude-path=*\libxml\* -exclude-path=*\libxslt\* -exclude-path=*\tifflib\* -exclude-path=*\wxWidgets\* -exclude-path=*\libtiff\* -exclude-path=*\mesa\* -exclude-path=*\cximage\* -exclude-path=*\bzip2-* -exclude-path=*\bzip2\* -exclude-path=*\UE_*\Engine\Source\* -exclude-path=*\wxWidgets\* -exclude-path=*\libtiff\* -exclude-path=*\glm\* -exclude-path=*\spdlog\* -exclude-path=*\cgltf\* -force-stdout-output=yes -fshort-double=no -fshort-float=no -funsigned-char=no -i-file=C:\Users\Kate\Desktop\ue4sswork\RE-UE4SS\UE4SS\src\GUI\LiveView.1.PVS-Studio.i -language=C++ -lic-file=C:\Users\Kate\AppData\Local\Temp\12156350750924277543.lic -new-output-format=yes -output-file=C:\Users\Kate\Desktop\ue4sswork\RE-UE4SS\.PVS-Studio\logs\LiveView.cpp.364.log -platform=x64 -preprocessor=visualcpp -source-file=C:\Users\Kate\Desktop\ue4sswork\RE-UE4SS\UE4SS\src\GUI\LiveView.cpp -sourcetree-root= -std=c++20 -timeout=600 diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 3bd184703..b98097f30 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -287,28 +287,28 @@ namespace RC::GUI }; FLiveViewDeleteListener FLiveViewDeleteListener::LiveViewDeleteListener{}; - static auto add_bool_filter_to_json(JSON::Array& json_filters, const StringType& filter_name, bool is_enabled) -> void + static auto add_bool_filter_to_json(JSON::Array& json_filters, const SystemStringType& filter_name, bool is_enabled) -> void { auto& json_object = json_filters.new_object(); - json_object.new_string(STR("FilterName"), filter_name); - auto& filter_data = json_object.new_object(STR("FilterData")); - filter_data.new_bool(STR("Enabled"), is_enabled); + json_object.new_string(SYSSTR("FilterName"), filter_name); + auto& filter_data = json_object.new_object(SYSSTR("FilterData")); + filter_data.new_bool(SYSSTR("Enabled"), is_enabled); } template - static auto add_array_filter_to_json(JSON::Array& json_filters, const StringType& filter_name, const ContainerType& container, const StringType& array_name) -> void + static auto add_array_filter_to_json(JSON::Array& json_filters, const SystemStringType& filter_name, const ContainerType& container, const SystemStringType& array_name) -> void { auto& json_object = json_filters.new_object(); - json_object.new_string(STR("FilterName"), filter_name); - auto& filter_data = json_object.new_object(STR("FilterData")); + json_object.new_string(SYSSTR("FilterName"), filter_name); + auto& filter_data = json_object.new_object(SYSSTR("FilterData")); - if (array_name == STR("ClassNames")) + if (array_name == SYSSTR("ClassNames")) { - filter_data.new_bool(STR("IsExclude"), Filter::ClassNamesFilter::b_is_exclude); + filter_data.new_bool(SYSSTR("IsExclude"), Filter::ClassNamesFilter::b_is_exclude); } - else if (array_name == STR("FunctionParamFlags")) + else if (array_name == SYSSTR("FunctionParamFlags")) { - filter_data.new_bool(STR("IncludeReturnProperty"), Filter::FunctionParamFlags::s_include_return_property); + filter_data.new_bool(SYSSTR("IncludeReturnProperty"), Filter::FunctionParamFlags::s_include_return_property); } auto& values_array = filter_data.new_array(array_name); @@ -316,7 +316,7 @@ namespace RC::GUI { if constexpr (std::is_same_v) { - values_array.new_string(value.ToString()); + values_array.new_string(to_string(value.ToString())); } else if constexpr (std::is_same_v) { @@ -324,7 +324,7 @@ namespace RC::GUI } else { - values_array.new_string(value); + values_array.new_string(to_string(value)); } } } @@ -332,30 +332,30 @@ namespace RC::GUI static auto internal_save_filters_to_disk() -> void { auto json = JSON::Object{}; - auto& json_filters = json.new_array(STR("Filters")); + auto& json_filters = json.new_array(SYSSTR("Filters")); { - add_bool_filter_to_json(json_filters, STR("IncludeInheritance"), LiveView::s_include_inheritance); - add_bool_filter_to_json(json_filters, STR("UseRegexForSearch"), LiveView::s_use_regex_for_search); - add_bool_filter_to_json(json_filters, STR("ApplySearchFiltersWhenNotSearching"), LiveView::s_apply_search_filters_when_not_searching); - add_bool_filter_to_json(json_filters, Filter::DefaultObjectsOnly::s_debug_name, Filter::DefaultObjectsOnly::s_enabled); - add_bool_filter_to_json(json_filters, Filter::IncludeDefaultObjects::s_debug_name, Filter::IncludeDefaultObjects::s_enabled); - add_bool_filter_to_json(json_filters, Filter::InstancesOnly::s_debug_name, Filter::InstancesOnly::s_enabled); - add_bool_filter_to_json(json_filters, Filter::NonInstancesOnly::s_debug_name, Filter::NonInstancesOnly::s_enabled); + add_bool_filter_to_json(json_filters, SYSSTR("IncludeInheritance"), LiveView::s_include_inheritance); + add_bool_filter_to_json(json_filters, SYSSTR("UseRegexForSearch"), LiveView::s_use_regex_for_search); + add_bool_filter_to_json(json_filters, SYSSTR("ApplySearchFiltersWhenNotSearching"), LiveView::s_apply_search_filters_when_not_searching); + add_bool_filter_to_json(json_filters, to_system(Filter::DefaultObjectsOnly::s_debug_name), Filter::DefaultObjectsOnly::s_enabled); + add_bool_filter_to_json(json_filters, to_system(Filter::IncludeDefaultObjects::s_debug_name), Filter::IncludeDefaultObjects::s_enabled); + add_bool_filter_to_json(json_filters, to_system(Filter::InstancesOnly::s_debug_name), Filter::InstancesOnly::s_enabled); + add_bool_filter_to_json(json_filters, to_system(Filter::NonInstancesOnly::s_debug_name), Filter::NonInstancesOnly::s_enabled); } { - add_array_filter_to_json(json_filters, Filter::ClassNamesFilter::s_debug_name, Filter::ClassNamesFilter::list_class_names, STR("ClassNames")); - add_array_filter_to_json(json_filters, Filter::HasProperty::s_debug_name, Filter::HasProperty::list_properties, STR("Properties")); - add_array_filter_to_json(json_filters, Filter::HasPropertyType::s_debug_name, Filter::HasPropertyType::list_property_types, STR("PropertyTypes")); - add_array_filter_to_json(json_filters, Filter::FunctionParamFlags::s_debug_name, Filter::FunctionParamFlags::s_checkboxes, STR("FunctionParamFlags")); + add_array_filter_to_json(json_filters, to_system(Filter::ClassNamesFilter::s_debug_name), Filter::ClassNamesFilter::list_class_names, SYSSTR("ClassNames")); + add_array_filter_to_json(json_filters, to_system(Filter::HasProperty::s_debug_name), Filter::HasProperty::list_properties, SYSSTR("Properties")); + add_array_filter_to_json(json_filters, to_system(Filter::HasPropertyType::s_debug_name), Filter::HasPropertyType::list_property_types, SYSSTR("PropertyTypes")); + add_array_filter_to_json(json_filters, to_system(Filter::FunctionParamFlags::s_debug_name), Filter::FunctionParamFlags::s_checkboxes, SYSSTR("FunctionParamFlags")); } auto json_file = - File::open(StringType{UE4SSProgram::get_program().get_working_directory()} + std::format(STR("\\liveview\\filters.meta.json")), + File::open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("UE4SS-config") SYSSTR("liveview")SYSSTR("filters.meta.json")), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); int32_t json_indent_level{}; - json_file.write_string_to_file(json.serialize(JSON::ShouldFormat::Yes, &json_indent_level)); + json_file.write_file_string_to_file(json.serialize(JSON::ShouldFormat::Yes, &json_indent_level)); } static auto save_filters_to_disk() -> void @@ -366,7 +366,7 @@ namespace RC::GUI } template - static auto json_array_to_filters_list(JSON::Array& json_array, std::vector& list, StringType type, std::string& internal_value) -> void + static auto json_array_to_filters_list(JSON::Array& json_array, std::vector& list, SystemStringType type, std::string& internal_value) -> void { list.clear(); internal_value.clear(); @@ -375,7 +375,20 @@ namespace RC::GUI { throw std::runtime_error{std::format("Invalid {} in 'filters.meta.json'", to_string(type))}; } - list.emplace_back(item.as()->get_view()); + + if constexpr (std::is_same_v) + { + list.emplace_back(to_system(item.as()->get_view())); + } + else if constexpr(std::is_same_v || std::is_same_v) + { + list.emplace_back(to_ue(item.as()->get_view())); + } + else + { + static_assert(false, "Unsupported string type"); + } + return LoopAction::Continue; }); for (const auto& class_name : list) @@ -399,7 +412,7 @@ namespace RC::GUI static auto internal_load_filters_from_disk() -> void { const auto json_file = - File::open(StringType{UE4SSProgram::get_program().get_working_directory()} + std::format(STR("\\liveview\\filters.meta.json")), + File::open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("UE4SS-config") / SYSSTR("liveview") / SYSSTR("filters.meta.json")), File::OpenFor::Reading, File::OverwriteExistingFile::No, File::CreateIfNonExistent::Yes); @@ -410,68 +423,68 @@ namespace RC::GUI } const auto json_global_object = JSON::Parser::parse(json_file_contents); - const auto& json_filters = json_global_object->get(STR("Filters")); + const auto& json_filters = json_global_object->get(SYSSTR("Filters")); json_filters.for_each([&](const JSON::Value& filter) { if (!filter.is()) { throw std::runtime_error{"Invalid filter in 'filters.meta.json'"}; } auto& json_object = *filter.as(); - auto filter_name = json_object.get(STR("FilterName")).get_view(); - auto& filter_data = json_object.get(STR("FilterData")); + auto filter_name = json_object.get(SYSSTR("FilterName")).get_view(); + auto& filter_data = json_object.get(SYSSTR("FilterData")); - if (filter_name == STR("IncludeInheritance")) + if (filter_name == SYSSTR("IncludeInheritance")) { - LiveView::s_include_inheritance = filter_data.get(STR("Enabled")).get(); + LiveView::s_include_inheritance = filter_data.get(SYSSTR("Enabled")).get(); } - else if (filter_name == STR("UseRegexForSearch")) + else if (filter_name == SYSSTR("UseRegexForSearch")) { - LiveView::s_use_regex_for_search = filter_data.get(STR("Enabled")).get(); + LiveView::s_use_regex_for_search = filter_data.get(SYSSTR("Enabled")).get(); } - else if (filter_name == STR("ApplySearchFiltersWhenNotSearching")) + else if (filter_name == SYSSTR("ApplySearchFiltersWhenNotSearching")) { - LiveView::s_apply_search_filters_when_not_searching = filter_data.get(STR("Enabled")).get(); + LiveView::s_apply_search_filters_when_not_searching = filter_data.get(SYSSTR("Enabled")).get(); } - else if (filter_name == Filter::DefaultObjectsOnly::s_debug_name) + else if (filter_name == to_system(Filter::DefaultObjectsOnly::s_debug_name)) { - Filter::DefaultObjectsOnly::s_enabled = filter_data.get(STR("Enabled")).get(); + Filter::DefaultObjectsOnly::s_enabled = filter_data.get(SYSSTR("Enabled")).get(); } - else if (filter_name == Filter::IncludeDefaultObjects::s_debug_name) + else if (filter_name == to_system(Filter::IncludeDefaultObjects::s_debug_name)) { - Filter::IncludeDefaultObjects::s_enabled = filter_data.get(STR("Enabled")).get(); + Filter::IncludeDefaultObjects::s_enabled = filter_data.get(SYSSTR("Enabled")).get(); } - else if (filter_name == Filter::InstancesOnly::s_debug_name) + else if (filter_name == to_system(Filter::InstancesOnly::s_debug_name)) { - Filter::InstancesOnly::s_enabled = filter_data.get(STR("Enabled")).get(); + Filter::InstancesOnly::s_enabled = filter_data.get(SYSSTR("Enabled")).get(); } - else if (filter_name == Filter::NonInstancesOnly::s_debug_name) + else if (filter_name == to_system(Filter::NonInstancesOnly::s_debug_name)) { - Filter::NonInstancesOnly::s_enabled = filter_data.get(STR("Enabled")).get(); + Filter::NonInstancesOnly::s_enabled = filter_data.get(SYSSTR("Enabled")).get(); } - else if (filter_name == Filter::ClassNamesFilter::s_debug_name) + else if (filter_name == to_system(Filter::ClassNamesFilter::s_debug_name)) { - Filter::ClassNamesFilter::b_is_exclude = filter_data.get(STR("IsExclude")).get(); - auto& class_names = filter_data.get(STR("ClassNames")); - json_array_to_filters_list(class_names, Filter::ClassNamesFilter::list_class_names, STR("class name"), Filter::ClassNamesFilter::s_internal_class_names); + Filter::ClassNamesFilter::b_is_exclude = filter_data.get(SYSSTR("IsExclude")).get(); + auto& class_names = filter_data.get(SYSSTR("ClassNames")); + json_array_to_filters_list(class_names, Filter::ClassNamesFilter::list_class_names, SYSSTR("class name"), Filter::ClassNamesFilter::s_internal_class_names); } - else if (filter_name == Filter::HasProperty::s_debug_name) + else if (filter_name == to_system(Filter::HasProperty::s_debug_name)) { - auto& properties = filter_data.get(STR("Properties")); - json_array_to_filters_list(properties, Filter::HasProperty::list_properties, STR("property"), Filter::HasProperty::s_internal_properties); + auto& properties = filter_data.get(SYSSTR("Properties")); + json_array_to_filters_list(properties, Filter::HasProperty::list_properties, SYSSTR("property"), Filter::HasProperty::s_internal_properties); } - else if (filter_name == Filter::HasPropertyType::s_debug_name) + else if (filter_name == to_system(Filter::HasPropertyType::s_debug_name)) { - auto& property_types = filter_data.get(STR("PropertyTypes")); + auto& property_types = filter_data.get(SYSSTR("PropertyTypes")); json_array_to_filters_list(property_types, Filter::HasPropertyType::list_property_types, - STR("property type"), + SYSSTR("property type"), Filter::HasPropertyType::s_internal_property_types); } - else if (filter_name == Filter::FunctionParamFlags::s_debug_name) + else if (filter_name == to_system(Filter::FunctionParamFlags::s_debug_name)) { - Filter::FunctionParamFlags::s_include_return_property = filter_data.get(STR("IncludeReturnProperty")).get(); + Filter::FunctionParamFlags::s_include_return_property = filter_data.get(SYSSTR("IncludeReturnProperty")).get(); Filter::FunctionParamFlags::s_checkboxes.fill(false); - auto& function_param_flags = filter_data.get(STR("FunctionParamFlags")); + auto& function_param_flags = filter_data.get(SYSSTR("FunctionParamFlags")); if (function_param_flags.get().size() != Filter::FunctionParamFlags::s_checkboxes.size()) { throw std::runtime_error{"Invalid number of function param flag entires in 'filters.meta.json'"}; @@ -1584,7 +1597,7 @@ namespace RC::GUI } else { - Output::send(SYSSTR("Search for: {}\n"), search_buffer.empty() ? STR("") : to_wstring(search_buffer)); + Output::send(SYSSTR("Search for: {}\n"), search_buffer.empty() ? SYSSTR("") : to_system(search_buffer)); s_name_to_search_by = search_buffer; m_object_iterator = &LiveView::guobjectarray_by_name_iterator; m_is_searching_by_name = true; @@ -3210,7 +3223,7 @@ namespace RC::GUI while (std::getline(ss, class_name, ',')) { std::erase_if(class_name, isspace); - Filter::ClassNamesFilter::list_class_names.emplace_back(to_wstring(class_name)); + Filter::ClassNamesFilter::list_class_names.emplace_back(to_ue(class_name)); } } } @@ -3227,7 +3240,7 @@ namespace RC::GUI while (std::getline(ss, class_name, ',')) { std::erase_if(class_name, isspace); - Filter::ClassNamesFilter::list_class_names.emplace_back(to_wstring(class_name)); + Filter::ClassNamesFilter::list_class_names.emplace_back(to_ue(class_name)); } } } @@ -3248,7 +3261,7 @@ namespace RC::GUI while (std::getline(ss, property_name, ',')) { std::erase_if(property_name, isspace); - Filter::HasProperty::list_properties.emplace_back(to_wstring(property_name)); + Filter::HasProperty::list_properties.emplace_back(to_ue(property_name)); } } } @@ -3271,7 +3284,7 @@ namespace RC::GUI std::erase_if(property_type_name, isspace); if (!property_type_name.empty()) { - Filter::HasPropertyType::list_property_types.emplace_back(FName(to_wstring(property_type_name), FNAME_Add)); + Filter::HasPropertyType::list_property_types.emplace_back(FName(to_ue(property_type_name), FNAME_Add)); } } } diff --git a/UE4SS/src/Mod/CppUserModBase.cpp b/UE4SS/src/Mod/CppUserModBase.cpp index 2847aea7e..215f58a23 100644 --- a/UE4SS/src/Mod/CppUserModBase.cpp +++ b/UE4SS/src/Mod/CppUserModBase.cpp @@ -2,6 +2,8 @@ #include #include +#include + namespace RC { CppUserModBase::CppUserModBase() @@ -24,27 +26,25 @@ namespace RC } GUITabs.clear(); - UE4SSProgram::get_program().m_input_handler.get_events_safe([&](auto& key_events) { - std::erase_if(key_events, [&](Input::KeySet& input_event) -> bool { + UE4SSProgram::get_program().m_input_handler.get_events_safe([&](auto& key_set) { + std::erase_if(key_set.key_data, [&](auto& item) -> bool { + auto& [_, key_data] = item; bool were_all_events_registered_from_this_mod = true; - for (auto& [key, vector_of_key_data] : input_event.key_data) - { - std::erase_if(vector_of_key_data, [&](Input::KeyData& key_data) -> bool { - // custom_data == 1: Bind came from Lua, and custom_data2 is nullptr. - // custom_data == 2: Bind came from C++, and custom_data2 is a pointer to KeyDownEventData. Must free it. - auto event_data = static_cast(key_data.custom_data2); - if (key_data.custom_data == 2 && event_data && event_data->mod == this) - { - delete event_data; - return true; - } - else - { - were_all_events_registered_from_this_mod = false; - return false; - } - }); - } + std::erase_if(key_data, [&](Input::KeyData& key_data) -> bool { + // custom_data == 1: Bind came from Lua, and custom_data2 is nullptr. + // custom_data == 2: Bind came from C++, and custom_data2 is a pointer to KeyDownEventData. Must free it. + auto event_data = static_cast(key_data.custom_data2); + if (key_data.custom_data == 2 && event_data && event_data->mod == this) + { + delete event_data; + return true; + } + else + { + were_all_events_registered_from_this_mod = false; + return false; + } + }); return were_all_events_registered_from_this_mod; }); diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index c1144be98..2eb12c0b6 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -232,6 +232,8 @@ namespace RC Output::send(SYSSTR("\n\nFound string '{}' at {}\n\n"), SystemStringViewType{str_to_find}, string_address); //*/ + Output::send(SYSSTR("dir: {}\n"), (m_log_directory / m_log_file_name)); + Output::send(SYSSTR("Console created\n")); Output::send(SYSSTR("UE4SS - v{}.{}.{}{}{} - Git SHA #{}\n"), UE4SS_LIB_VERSION_MAJOR, @@ -336,6 +338,8 @@ namespace RC ProfilerSetThreadName("UE4SS-InitThread"); ProfilerScope(); + Output::send(SYSSTR("Initializing ue4ss program\n")); + try { setup_unreal(); @@ -541,6 +545,8 @@ namespace RC auto UE4SSProgram::setup_unreal() -> void { ProfilerScope(); + Output::send(SYSSTR("Setting up unreal\n")); + // Retrieve offsets from the config file const SystemStringType offset_overrides_section{SYSSTR("OffsetOverrides")}; @@ -1382,10 +1388,11 @@ namespace RC // Remove key binds that were set from Lua scripts #ifdef HAS_INPUT - m_input_handler.get_events_safe([&](Input::KeySet& input_event) -> void { - for (auto& [key, vector_of_key_data] : input_event.key_data) - { - std::erase_if(vector_of_key_data, [&](Input::KeyData& key_data) -> bool { + m_input_handler.get_events_safe([&](auto& key_set) { + std::erase_if(key_set.key_data, [&](auto& item) -> bool { + auto& [_, key_data] = item; + bool were_all_events_registered_from_lua = true; + std::erase_if(key_data, [&](Input::KeyData& key_data) -> bool { // custom_data == 1: Bind came from Lua, and custom_data2 is nullptr. // custom_data == 2: Bind came from C++, and custom_data2 is a pointer to KeyDownEventData. Must free it. if (key_data.custom_data == 1) @@ -1399,11 +1406,8 @@ namespace RC } }); - if (vector_of_key_data.empty()) - { - m_input_handler.clear_subscribed_key(key); - } - } + return were_all_events_registered_from_lua; + }); }); #endif diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index fa5df2d65..7b22b7dbe 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -6,7 +6,10 @@ if uiMode ~= nil and uiMode ~= "None" then add_requires("ImGuiTextEdit v1.0", { debug = is_mode_debug(), configs = { tui = isTUI, runtimes = get_mode_runtimes() } }) if uiMode == "GUI" then - add_requires("imgui v1.89", { debug = is_mode_debug(), configs = { win32 = hasWindows, dx11 = hasWindows, opengl3 = true, glfw_opengl3 = true , runtimes = get_mode_runtimes()} } ) + local imguiConfig = { win32 = hasWindows, dx11 = hasWindows, opengl3 = true, glfw = true , runtimes = get_mode_runtimes()} + add_requires("imgui v1.89", { alias = "ue4ssImGui", debug = is_mode_debug(), configs = imguiConfig } ) + add_requireconfs("ImGuiTextEdit.imgui", { configs = imguiConfig }) + add_requires("IconFontCppHeaders v1.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()}}) add_requires("glfw 3.3.9", { debug = is_mode_debug() , configs = {runtimes = get_mode_runtimes()}}) add_requires("opengl", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) @@ -104,6 +107,12 @@ target(projectName) add_files("src/**.cpp|Platform/**.cpp|GUI/**.cpp") + if is_plat("windows") then + add_files("src/Platform/Win32/CrashDumper.cpp", "src/Platform/Win32/EntryWin32.cpp") + elseif is_plat("linux") then + add_files("src/Platform/Linux/EntryLinux.cpp") + end + if uiMode ~= "None" then add_files("src/GUI/*.cpp") @@ -111,16 +120,19 @@ target(projectName) if uiMode == "GUI" then add_files("src/GUI/Platform/GLFW/**.cpp") - add_files("src/GUI/Platform/GUI/**.cpp") - add_deps("glad") + add_defines("HAS_GLFW", { public = true }) - add_packages("ImGui", "IconFontCppHeaders", "glfw", "opengl", { public = true }) + add_deps("glad", { public = true }) + + add_packages("ue4ssImGui", "IconFontCppHeaders", "glfw", "opengl", { public = true }) if is_plat("windows") then add_files("src/GUI/Platform/D3D11/**.cpp") add_files("src/GUI/Platform/Windows/**.cpp") + add_defines("HAS_D3D11", { public = true }) + add_links("d3d11", { public = true }) end elseif uiMode == "TUI" then diff --git a/deps/third-repo/packages/i/imguitextedit/xmake.lua b/deps/third-repo/packages/i/imguitextedit/xmake.lua index e5f80d4e6..cb665962f 100644 --- a/deps/third-repo/packages/i/imguitextedit/xmake.lua +++ b/deps/third-repo/packages/i/imguitextedit/xmake.lua @@ -6,8 +6,6 @@ package("ImGuiTextEdit") add_configs("tui", { description = "Enable TUI.", default = false, type = "boolean" }) - add_deps("cmake") - add_includedirs("include", { public = true }) local function _get_imgui_name(isTUI) diff --git a/deps/third/imtui/fix-size-cjk-and-mouse.patch b/deps/third-repo/packages/i/imtui/fix-size-cjk-and-mouse.patch similarity index 100% rename from deps/third/imtui/fix-size-cjk-and-mouse.patch rename to deps/third-repo/packages/i/imtui/fix-size-cjk-and-mouse.patch diff --git a/deps/third/imtui/xmake.lua b/deps/third-repo/packages/i/imtui/xmake.lua similarity index 81% rename from deps/third/imtui/xmake.lua rename to deps/third-repo/packages/i/imtui/xmake.lua index 25e5b9bb8..738f1b59a 100644 --- a/deps/third/imtui/xmake.lua +++ b/deps/third-repo/packages/i/imtui/xmake.lua @@ -1,14 +1,15 @@ package("imtui") add_urls("https://github.com/ggerganov/imtui.git") + set_policy("package.install_always", true) + add_versions("v1.0.5", "9f39c3e090c9b1e15557eac38a2f4389462f59df") - local root = get_config("ue4ssRoot") - -- add_patches("v1.0.5", path.join(root, "deps", "third", "imtui", "fix-size-cjk-and-mouse.patch")) + add_patches("v1.0.5", "fix-size-cjk-and-mouse.patch") -- WARN: xmake cannot distinguish ncursesw and ncurses, this may cause problem on other systems add_deps("cmake", "ncurses") - add_includedirs("include", "include/imgui-for-imtui/", "include/imgui-for-imtui/imgui", "include/imtui", {public = true}) + add_includedirs("include", "include/imgui", "include/imgui-for-imtui/", "include/imgui-for-imtui/imgui", "include/imtui", {public = true}) -- imtui, imtui-ncurses and imgui-for-imtui on_install(function (package) diff --git a/tools/xmakescripts/rules/build_rules.lua b/tools/xmakescripts/rules/build_rules.lua index cf4b88545..ccffe6ef5 100644 --- a/tools/xmakescripts/rules/build_rules.lua +++ b/tools/xmakescripts/rules/build_rules.lua @@ -61,6 +61,9 @@ local PLATFORM_TYPES = { "UNICODE", "_UNICODE" }, + ["cxflags"] = { + "clang::-gcodeview" + } }, ["Linux"] = { ["defines"] = { @@ -73,7 +76,8 @@ local PLATFORM_TYPES = { "DLLEXT=.so" }, ["cxflags"] = { - "clang::-fno-delete-null-pointer-checks" + "clang::-fno-delete-null-pointer-checks", + "clang::-gdwarf" } } } @@ -85,7 +89,6 @@ local PLATFORM_TYPES = { local CLANG_COMPILE_OPTIONS = { ["cxflags"] = { "-g", - "-gcodeview", "-fcolor-diagnostics", "-Wno-unknown-pragmas", "-Wno-unused-parameter", @@ -190,7 +193,7 @@ function get_mode_runtimes() return is_mode_debug() and "MDd" or "MD" end - return {} + return "" end --- This local function wraps the global get_mode_runtimes() function. We have to locally wrap the function diff --git a/xmake.lua b/xmake.lua index f2862b373..b21e2adf8 100644 --- a/xmake.lua +++ b/xmake.lua @@ -79,5 +79,3 @@ includes("UE4SS") -- TODO: Remove this before the next release. It only exists to maintain backwards compat -- warnings for older mod templates. set_config("scriptsRoot", path.join(os.scriptdir(), "tools/xmakescripts")) - -add_repositories("thirdr deps/thirdr") From f4103c039da049f13c3da94feb44a891eda0c756 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 24 May 2024 03:05:53 -0500 Subject: [PATCH 167/213] use of moved value --- UE4SS/src/Mod/CppMod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index e9bf9d5ac..38a11dba8 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -16,7 +16,7 @@ namespace RC { CppMod::CppMod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) { - auto resolved_dlls_path = File::get_path_if_exists(mod_path, SYSSTR("dlls")); + auto resolved_dlls_path = File::get_path_if_exists(get_name(), SYSSTR("dlls")); if (resolved_dlls_path) { m_dlls_path = to_system_string(*resolved_dlls_path); From dc6b656d619978eae220a476041b55d75f409d52 Mon Sep 17 00:00:00 2001 From: Yangff Date: Fri, 24 May 2024 03:29:27 -0500 Subject: [PATCH 168/213] add zig tool, add libcxx and remove ArgsParser --- .github/workflows/linux-test.yml | 44 +++++++++++++-------- .github/workflows/windows-test.yml | 8 +++- deps/first/File/src/FileType/StdFile.cpp | 2 +- deps/first/xmake.lua | 2 +- deps/third-repo/packages/i/imtui/xmake.lua | 9 +++-- tools/xmakescripts/modules/mode_builder.lua | 9 +++++ tools/xmakescripts/rules/build_rules.lua | 16 ++++++++ tools/zig/zig-ar | 2 + tools/zig/zig-c++ | 2 + tools/zig/zig-cc | 2 + xmake.lua | 34 +++++++++++++++- 11 files changed, 105 insertions(+), 25 deletions(-) create mode 100755 tools/zig/zig-ar create mode 100755 tools/zig/zig-c++ create mode 100755 tools/zig/zig-cc diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 4aead8c48..e6c9559f8 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -1,7 +1,7 @@ name: Linux Test Build on: - workflow_dispatch: + workflow_dispatch: {} push: branches: [ "linux-port" ] paths: @@ -14,6 +14,8 @@ on: - ".github/workflows/linux-test.yml" - "CMakeLists.txt" - "cmake/**" + - tools/** + - xmake.lua permissions: contents: read @@ -35,29 +37,35 @@ jobs: ssh-key: ${{ secrets.SSHKEY }} - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@v3 - - name: Set up Clang - uses: KyleMayes/install-llvm-action@v1 + - name: Setup LLVM + uses: ZhongRuoyu/setup-llvm@v0 with: - version: "16.0" - platform: x64 - env: true - ubuntu-version: 22.04 + llvm-version: 18 + - uses: goto-bus-stop/setup-zig@v2 + - run: zig cc -v + - name: Upgrade libstdc++ + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo apt -y update + sudo apt -y install --only-upgrade libstdc++6 + sudo apt -y install libstdc++-13-dev - name: Setup Rust uses: dtolnay/rust-toolchain@1.76.0 - - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.3 + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest + actions-cache-folder: '.xmake-cache' + actions-cache-key: 'linux-test' - name: Build run: | - cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Linux -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache - cmake --build build - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" + xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y -m "Game__Shipping__Linux" + XMAKE_COLORTERM=nocolor xmake build -v -D > build.log - name: Stripping run: | mkdir prepackage - objcopy --only-keep-debug build/Output/Game__Shipping__Linux/UE4SS/bin/libUE4SS.so ./prepackage/libUE4SS.so.debug - cp build/Output/Game__Shipping__Linux/UE4SS/bin/libUE4SS.so ./prepackage/libUE4SS.so + objcopy --only-keep-debug Binaries/Game__Shipping__Linux/UE4SS/libUE4SS.so ./prepackage/libUE4SS.so.debug + cp Binaries/Game__Shipping__Linux/UE4SS/libUE4SS.so ./prepackage/libUE4SS.so strip --strip-debug --strip-unneeded ./prepackage/libUE4SS.so cd ./prepackage && objcopy --add-gnu-debuglink=libUE4SS.so.debug ./libUE4SS.so && cd .. - name: Package @@ -66,4 +74,6 @@ jobs: uses: actions/upload-artifact@v3 with: name: Linux-Release - path: release/zDEV-UE4SS_0.0.0.zip + path: | + release/zDEV-UE4SS_0.0.0.zip + build.log diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml index 13bbb3892..394ebe62d 100644 --- a/.github/workflows/windows-test.yml +++ b/.github/workflows/windows-test.yml @@ -34,14 +34,18 @@ jobs: ssh-key: ${{ secrets.SSHKEY }} - name: Setup MSVC uses: ilammy/msvc-dev-cmd@v1 + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@v3 - name: Setup Rust uses: dtolnay/rust-toolchain@1.76.0 - name: Build run: | - cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Game__Shipping__Win64 - cmake --build build + xmake f -m "Game__Shipping__Win64" -y + xmake build - name: Upload Artifacts uses: actions/upload-artifact@v3 with: diff --git a/deps/first/File/src/FileType/StdFile.cpp b/deps/first/File/src/FileType/StdFile.cpp index 7d9425691..70ca0e889 100644 --- a/deps/first/File/src/FileType/StdFile.cpp +++ b/deps/first/File/src/FileType/StdFile.cpp @@ -289,7 +289,7 @@ namespace RC::File } Handle cache_file = open(m_serialization_file_path_and_name); - auto bytes_read = read((int)cache_file.get_raw_handle(), &m_cache, cache_size); + auto bytes_read = read(reinterpret_cast(cache_file.get_raw_handle()), &m_cache, cache_size); if (bytes_read < 0) { THROW_INTERNAL_FILE_ERROR( diff --git a/deps/first/xmake.lua b/deps/first/xmake.lua index d0b34abac..a92fc1d05 100644 --- a/deps/first/xmake.lua +++ b/deps/first/xmake.lua @@ -1,4 +1,4 @@ -includes("ArgsParser") +-- includes("ArgsParser") includes("ASMHelper") includes("Constructs") includes("DynamicOutput") diff --git a/deps/third-repo/packages/i/imtui/xmake.lua b/deps/third-repo/packages/i/imtui/xmake.lua index 738f1b59a..1bcc5fd76 100644 --- a/deps/third-repo/packages/i/imtui/xmake.lua +++ b/deps/third-repo/packages/i/imtui/xmake.lua @@ -7,7 +7,8 @@ package("imtui") add_patches("v1.0.5", "fix-size-cjk-and-mouse.patch") -- WARN: xmake cannot distinguish ncursesw and ncurses, this may cause problem on other systems - add_deps("cmake", "ncurses") + add_deps("cmake") + add_deps("ncurses 6.1") add_includedirs("include", "include/imgui", "include/imgui-for-imtui/", "include/imgui-for-imtui/imgui", "include/imtui", {public = true}) @@ -18,8 +19,10 @@ package("imtui") table.insert(configs, "-DIMTUI_STANDALONE=ON") table.insert(configs, "-DIMTUI_SUPPORT_NCURSES=ON") table.insert(configs, "-DIMTUI_BUILD_EXAMPLES=OFF") - - import("package.tools.cmake").install(package, configs) + print(package:dep("ncurses"):installdir("include")) + local cxflags = {} + table.insert(cxflags, "-I" .. package:dep("ncurses"):installdir("include") .. "/ncursesw") + import("package.tools.cmake").install(package, configs, {cxflags = cxflags}) print(package:cachedir() .. "/source/imtui/") print(package:installdir()) os.cp("third-party/imgui/imgui/misc/cpp/imgui_stdlib.h", package:installdir("include/imgui-for-imtui/imgui/misc/cpp")) diff --git a/tools/xmakescripts/modules/mode_builder.lua b/tools/xmakescripts/modules/mode_builder.lua index a75792472..da8dc2c8a 100644 --- a/tools/xmakescripts/modules/mode_builder.lua +++ b/tools/xmakescripts/modules/mode_builder.lua @@ -15,4 +15,13 @@ function apply_compiler_options(target, opts, tools) for option, values in pairs(opts) do target:add(option, values, { tools = tools }) end +end + +--- Applies build options to a target. +---@param target any xmake target +---@param opts table Map of xmake flag types to flags. Ex. ["ldflags"] = {"/DEBUG:FULL"} +function apply_compiler_options_all(target, opts) + for option, values in pairs(opts) do + target:add(option, values, { force = true }) + end end \ No newline at end of file diff --git a/tools/xmakescripts/rules/build_rules.lua b/tools/xmakescripts/rules/build_rules.lua index ccffe6ef5..17d380eb5 100644 --- a/tools/xmakescripts/rules/build_rules.lua +++ b/tools/xmakescripts/rules/build_rules.lua @@ -104,6 +104,19 @@ local CLANG_COMPILE_OPTIONS = { } } +-- option to use libc++ +option("libcxx") + set_default(false) + set_showmenu(true) + set_description("Use libc++ instead of libstdc++") + +if has_config("libcxx") then + table.insert(CLANG_COMPILE_OPTIONS["cxflags"], "-stdlib=libc++") + table.insert(CLANG_COMPILE_OPTIONS["cxflags"], "-fexperimental-library") + table.insert(CLANG_COMPILE_OPTIONS["ldflags"], "-static-libstdc++") + table.insert(CLANG_COMPILE_OPTIONS["ldflags"], "-l:libc++abi.a") +end + local GNU_COMPILE_OPTIONS = { ["cxflags"] = { "-fms-extensions" @@ -215,6 +228,9 @@ rule("ue4ss.base") -- Compiler flags are set in this rule since unreal modes currently do not change any compiler flags. mode_builder.apply_compiler_options(target, GNU_COMPILE_OPTIONS, {"gcc", "ld"}) mode_builder.apply_compiler_options(target, CLANG_COMPILE_OPTIONS, {"clang", "lld"}) + if has_config("zig") then + mode_builder.apply_compiler_options_all(target, CLANG_COMPILE_OPTIONS) + end mode_builder.apply_compiler_options(target, MSVC_COMPILE_OPTIONS, { "clang_cl", "cl", "link" }) end) diff --git a/tools/zig/zig-ar b/tools/zig/zig-ar new file mode 100755 index 000000000..0cdd6fc93 --- /dev/null +++ b/tools/zig/zig-ar @@ -0,0 +1,2 @@ +#!/bin/bash +exec zig ar "$@" \ No newline at end of file diff --git a/tools/zig/zig-c++ b/tools/zig/zig-c++ new file mode 100755 index 000000000..454db2008 --- /dev/null +++ b/tools/zig/zig-c++ @@ -0,0 +1,2 @@ +#!/bin/bash +exec zig c++ -target x86_64-linux-gnu "$@" \ No newline at end of file diff --git a/tools/zig/zig-cc b/tools/zig/zig-cc new file mode 100755 index 000000000..a6bfd0ffb --- /dev/null +++ b/tools/zig/zig-cc @@ -0,0 +1,2 @@ +#!/bin/bash +exec zig cc -target x86_64-linux-gnu "$@" \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index b21e2adf8..9c4ce203c 100644 --- a/xmake.lua +++ b/xmake.lua @@ -60,8 +60,40 @@ set_allowedplats("windows", "linux") set_allowedarchs("x64", "x86_64") set_allowedmodes(modes) +option("zig") + set_showmenu(true) + set_description("Use the Zig compiler.") + set_default(false) +option_end() + +toolchain("zigcross") + if is_host("windows") then + set_toolset("cc", "$(projectdir)/tools/zig/zig-cc.bat") + set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++.bat") + set_toolset("ld", "$(projectdir)/tools/zig/zig-c++.bat") + set_toolset("sh", "$(projectdir)/tools/zig/zig-c++.bat") + set_toolset("ar", "$(projectdir)/tools/zig/zig-ar.bat") + else + set_toolset("cc", "$(projectdir)/tools/zig/zig-cc") + set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++") + set_toolset("ld", "$(projectdir)/tools/zig/zig-c++") + set_toolset("sh", "$(projectdir)/tools/zig/zig-c++") + set_toolset("ar", "$(projectdir)/tools/zig/zig-ar") + end + add_cxflags("-fexperimental-library") + add_cxflags("-fno-delete-null-pointer-checks") + add_cxflags("-gdwarf") + add_cxflags("-fno-sanitize=undefined") -- can also use O2 to avoid this, but I'd prefer getting clear binary for now + add_shflags("-z", "lazy") +toolchain_end() + if is_plat("linux") then - set_toolchains("clang", "rust") + if has_config("zig") then + set_toolchains("zigcross", "rust") + else + set_toolchains("clang", "rust") + end + set_defaultmode("Game__Shipping__Linux") end if is_plat("windows") then From 421c3a2611e39376a70bd484df5c9ea8cc88d2c8 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 25 May 2024 22:29:55 -0500 Subject: [PATCH 169/213] use TERMINFO, LCALL config for TUI --- UE4SS/include/SettingsManager.hpp | 3 +++ UE4SS/src/GUI/Platform/TUI/TUI.cpp | 8 ++++++++ UE4SS/src/SettingsManager.cpp | 2 ++ assets/UE4SS-settings.ini | 2 ++ 4 files changed, 15 insertions(+) diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index acad8d298..ffcc88691 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -131,6 +131,9 @@ namespace RC SystemStringType BanCode = "f05e"; SystemStringType CopyCode = "f0c5"; SystemStringType SearchCode = "f002";*/ + + SystemStringType TERMINFO = SYSSTR("/usr/share/terminfo"); + SystemStringType LCALL = SYSSTR("en_US.UTF-8"); } TUI; #endif diff --git a/UE4SS/src/GUI/Platform/TUI/TUI.cpp b/UE4SS/src/GUI/Platform/TUI/TUI.cpp index 9e74c1a04..bc22bf250 100644 --- a/UE4SS/src/GUI/Platform/TUI/TUI.cpp +++ b/UE4SS/src/GUI/Platform/TUI/TUI.cpp @@ -8,7 +8,10 @@ #include #include +#include + #include +#include namespace RC::GUI { @@ -19,6 +22,11 @@ namespace RC::GUI void Backend_TUI::init() { // fprintf(stderr, "Backend_TUI::init\n"); + setenv("TERMINFO", UE4SSProgram::settings_manager.TUI.TERMINFO.c_str(), 0); + if (!UE4SSProgram::settings_manager.TUI.LCALL.empty()) + { + setenv("LC_ALL", UE4SSProgram::settings_manager.TUI.LCALL.c_str(), 0); + } g_screen = ImTui_ImplNcurses_Init(true); auto source = Input::Handler::get_input_source("Ncurses"); ncurses_source = std::dynamic_pointer_cast(source); diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index b318cebde..84be1cfc3 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -146,6 +146,8 @@ namespace RC REGISTER_INT64_SETTING(TUI.WheelUp, section_tui_features, WheelUp) REGISTER_INT64_SETTING(TUI.WheelDown, section_tui_features, WheelDown)*/ REGISTER_BOOL_SETTING(TUI.TUINerdFont, section_tui_features, TUINerdFont) + REGISTER_STRING_SETTING(TUI.TERMINFO, section_tui_features, TERMINFO) + REGISTER_STRING_SETTING(TUI.LCALL, section_tui_features, LCALL) /* REGISTER_STRING_SETTING(TUI.TerminalCode, section_tui_features, TerminalCode) REGISTER_STRING_SETTING(TUI.ArchiveCode, section_tui_features, ArchiveCode) diff --git a/assets/UE4SS-settings.ini b/assets/UE4SS-settings.ini index dbed520ec..ba5e098d5 100644 --- a/assets/UE4SS-settings.ini +++ b/assets/UE4SS-settings.ini @@ -144,4 +144,6 @@ GUIUFunctionCaller = $GUIUFunctionCaller ${if os == "linux64"} [TUI] TUINerdFont=0 +TERMINFO=/usr/share/terminfo +LCALL=en_US.UTF-8 ${endif} From 1c086b02f2944c9d75cfcbc8b6e2209f0b4f1fd7 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 00:55:53 -0500 Subject: [PATCH 170/213] add bat for win --- tools/zig/zig-ar.bat | 1 + tools/zig/zig-c++.bat | 1 + tools/zig/zig-cc.bat | 1 + 3 files changed, 3 insertions(+) create mode 100644 tools/zig/zig-ar.bat create mode 100644 tools/zig/zig-c++.bat create mode 100644 tools/zig/zig-cc.bat diff --git a/tools/zig/zig-ar.bat b/tools/zig/zig-ar.bat new file mode 100644 index 000000000..266092cf6 --- /dev/null +++ b/tools/zig/zig-ar.bat @@ -0,0 +1 @@ +zig ar %* \ No newline at end of file diff --git a/tools/zig/zig-c++.bat b/tools/zig/zig-c++.bat new file mode 100644 index 000000000..f0b7f5cb7 --- /dev/null +++ b/tools/zig/zig-c++.bat @@ -0,0 +1 @@ +zig c++ %* \ No newline at end of file diff --git a/tools/zig/zig-cc.bat b/tools/zig/zig-cc.bat new file mode 100644 index 000000000..10df9ce06 --- /dev/null +++ b/tools/zig/zig-cc.bat @@ -0,0 +1 @@ +zig cc %* \ No newline at end of file From a7c738b7239035a00a5002b2b6f1b6c109f3eba4 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 04:29:30 -0500 Subject: [PATCH 171/213] add target --- tools/zig/zig-c++.bat | 2 +- tools/zig/zig-cc.bat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/zig/zig-c++.bat b/tools/zig/zig-c++.bat index f0b7f5cb7..01c4650a7 100644 --- a/tools/zig/zig-c++.bat +++ b/tools/zig/zig-c++.bat @@ -1 +1 @@ -zig c++ %* \ No newline at end of file +zig c++ -target x86_64-linux-gnu %* \ No newline at end of file diff --git a/tools/zig/zig-cc.bat b/tools/zig/zig-cc.bat index 10df9ce06..4fcd3c418 100644 --- a/tools/zig/zig-cc.bat +++ b/tools/zig/zig-cc.bat @@ -1 +1 @@ -zig cc %* \ No newline at end of file +zig cc -target x86_64-linux-gnu %* \ No newline at end of file From 6ed0c2437c4a09cd9e1e7d4d24c78f6f206d8038 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 04:29:44 -0500 Subject: [PATCH 172/213] add allow arch for rust --- xmake.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xmake.lua b/xmake.lua index 9c4ce203c..dca0fe5e9 100644 --- a/xmake.lua +++ b/xmake.lua @@ -57,7 +57,7 @@ add_rules("ue4ss.core") -- These restrictions are inherited upstream and downstream. -- Any project that `includes("UE4SS")` will inherit these global restrictions. set_allowedplats("windows", "linux") -set_allowedarchs("x64", "x86_64") +set_allowedarchs("x64", "x86_64", "x86_64-unknown-linux-gnu") set_allowedmodes(modes) option("zig") @@ -90,6 +90,10 @@ toolchain_end() if is_plat("linux") then if has_config("zig") then set_toolchains("zigcross", "rust") + if is_host("windows") then + set_arch("x86_64-unknown-linux-gnu") + add_rcflags("-C", "linker=$(projectdir)/tools/zig/zig-cc.bat", {force = true}) + end else set_toolchains("clang", "rust") end From 91be338db06f2f6bf10a0b4a7cd24f5c28998fee Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 04:29:59 -0500 Subject: [PATCH 173/213] config for zig as linker --- .cargo/config.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..e5a2ea123 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.x86_64-unknown-linux-gnu] +linker = "./tools/zig/zig-cc.bat" \ No newline at end of file From 30e97acafdec973ac503aa2b05e12a249c0d8106 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 04:30:13 -0500 Subject: [PATCH 174/213] force target and editon in the command --- deps/first/xmake.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deps/first/xmake.lua b/deps/first/xmake.lua index a92fc1d05..c9da56077 100644 --- a/deps/first/xmake.lua +++ b/deps/first/xmake.lua @@ -33,7 +33,11 @@ add_requires("cargo::patternsleuth_bind", { debug = is_mode_debug(), configs = { target("patternsleuth_bind") set_kind("static") set_values("rust.cratetype", "staticlib") + set_values("rust.edition", "2021") add_files("patternsleuth_bind/src/lib.rs") + if is_plat("linux") and is_host("windows") then + add_rcflags("--target=x86_64-unknown-linux-gnu", {force = true}) + end add_packages("cargo::patternsleuth_bind") if is_plat("windows") then add_links("ws2_32", "advapi32", "userenv", "ntdll", "oleaut32", "bcrypt", "ole32", { public = true }) From 93c7ef7ce7ec95327c6d173ef7dd18791cbcf649 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 26 May 2024 04:34:53 -0500 Subject: [PATCH 175/213] test unified .bat proxy --- tools/zig/zig-ar.bat | 6 ++++++ tools/zig/zig-c++.bat | 6 ++++++ tools/zig/zig-cc.bat | 6 ++++++ xmake.lua | 10 +++++----- 4 files changed, 23 insertions(+), 5 deletions(-) mode change 100644 => 100755 tools/zig/zig-ar.bat mode change 100644 => 100755 tools/zig/zig-c++.bat mode change 100644 => 100755 tools/zig/zig-cc.bat diff --git a/tools/zig/zig-ar.bat b/tools/zig/zig-ar.bat old mode 100644 new mode 100755 index 266092cf6..43d9caf4f --- a/tools/zig/zig-ar.bat +++ b/tools/zig/zig-ar.bat @@ -1 +1,7 @@ +#!/bin/bash +# 2>nul || @goto :batch +exec zig ar "$@" +goto :EOF + +:batch zig ar %* \ No newline at end of file diff --git a/tools/zig/zig-c++.bat b/tools/zig/zig-c++.bat old mode 100644 new mode 100755 index 01c4650a7..5c800b57f --- a/tools/zig/zig-c++.bat +++ b/tools/zig/zig-c++.bat @@ -1 +1,7 @@ +#!/bin/bash +# 2>nul || @goto :batch +exec zig c++ -target x86_64-linux-gnu "$@" +goto :EOF + +:batch zig c++ -target x86_64-linux-gnu %* \ No newline at end of file diff --git a/tools/zig/zig-cc.bat b/tools/zig/zig-cc.bat old mode 100644 new mode 100755 index 4fcd3c418..17197ca77 --- a/tools/zig/zig-cc.bat +++ b/tools/zig/zig-cc.bat @@ -1 +1,7 @@ +#!/bin/bash +# 2>nul || @goto :batch +exec zig cc -target x86_64-linux-gnu "$@" +goto :EOF + +:batch zig cc -target x86_64-linux-gnu %* \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index dca0fe5e9..ae7ff10a7 100644 --- a/xmake.lua +++ b/xmake.lua @@ -74,11 +74,11 @@ toolchain("zigcross") set_toolset("sh", "$(projectdir)/tools/zig/zig-c++.bat") set_toolset("ar", "$(projectdir)/tools/zig/zig-ar.bat") else - set_toolset("cc", "$(projectdir)/tools/zig/zig-cc") - set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++") - set_toolset("ld", "$(projectdir)/tools/zig/zig-c++") - set_toolset("sh", "$(projectdir)/tools/zig/zig-c++") - set_toolset("ar", "$(projectdir)/tools/zig/zig-ar") + set_toolset("cc", "$(projectdir)/tools/zig/zig-cc.bat") + set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++.bat") + set_toolset("ld", "$(projectdir)/tools/zig/zig-c++.bat") + set_toolset("sh", "$(projectdir)/tools/zig/zig-c++.bat") + set_toolset("ar", "$(projectdir)/tools/zig/zig-ar.bat") end add_cxflags("-fexperimental-library") add_cxflags("-fno-delete-null-pointer-checks") From 681c83e845d83d97636f5c2f895d9e7505fb91b7 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 04:41:11 -0500 Subject: [PATCH 176/213] make both cmake and cargo happy --- .cargo/config.toml | 2 +- tools/zig/zig-ar.bat | 6 ------ tools/zig/zig-c++.bat | 6 ------ tools/zig/zig-cc-rust.bat | 7 +++++++ tools/zig/zig-cc.bat | 6 ------ xmake.lua | 10 +++++----- 6 files changed, 13 insertions(+), 24 deletions(-) create mode 100644 tools/zig/zig-cc-rust.bat diff --git a/.cargo/config.toml b/.cargo/config.toml index e5a2ea123..dd4d938e1 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [target.x86_64-unknown-linux-gnu] -linker = "./tools/zig/zig-cc.bat" \ No newline at end of file +linker = "./tools/zig/zig-cc-rust.bat" \ No newline at end of file diff --git a/tools/zig/zig-ar.bat b/tools/zig/zig-ar.bat index 43d9caf4f..266092cf6 100755 --- a/tools/zig/zig-ar.bat +++ b/tools/zig/zig-ar.bat @@ -1,7 +1 @@ -#!/bin/bash -# 2>nul || @goto :batch -exec zig ar "$@" -goto :EOF - -:batch zig ar %* \ No newline at end of file diff --git a/tools/zig/zig-c++.bat b/tools/zig/zig-c++.bat index 5c800b57f..01c4650a7 100755 --- a/tools/zig/zig-c++.bat +++ b/tools/zig/zig-c++.bat @@ -1,7 +1 @@ -#!/bin/bash -# 2>nul || @goto :batch -exec zig c++ -target x86_64-linux-gnu "$@" -goto :EOF - -:batch zig c++ -target x86_64-linux-gnu %* \ No newline at end of file diff --git a/tools/zig/zig-cc-rust.bat b/tools/zig/zig-cc-rust.bat new file mode 100644 index 000000000..17197ca77 --- /dev/null +++ b/tools/zig/zig-cc-rust.bat @@ -0,0 +1,7 @@ +#!/bin/bash +# 2>nul || @goto :batch +exec zig cc -target x86_64-linux-gnu "$@" +goto :EOF + +:batch +zig cc -target x86_64-linux-gnu %* \ No newline at end of file diff --git a/tools/zig/zig-cc.bat b/tools/zig/zig-cc.bat index 17197ca77..4fcd3c418 100755 --- a/tools/zig/zig-cc.bat +++ b/tools/zig/zig-cc.bat @@ -1,7 +1 @@ -#!/bin/bash -# 2>nul || @goto :batch -exec zig cc -target x86_64-linux-gnu "$@" -goto :EOF - -:batch zig cc -target x86_64-linux-gnu %* \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index ae7ff10a7..dca0fe5e9 100644 --- a/xmake.lua +++ b/xmake.lua @@ -74,11 +74,11 @@ toolchain("zigcross") set_toolset("sh", "$(projectdir)/tools/zig/zig-c++.bat") set_toolset("ar", "$(projectdir)/tools/zig/zig-ar.bat") else - set_toolset("cc", "$(projectdir)/tools/zig/zig-cc.bat") - set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++.bat") - set_toolset("ld", "$(projectdir)/tools/zig/zig-c++.bat") - set_toolset("sh", "$(projectdir)/tools/zig/zig-c++.bat") - set_toolset("ar", "$(projectdir)/tools/zig/zig-ar.bat") + set_toolset("cc", "$(projectdir)/tools/zig/zig-cc") + set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++") + set_toolset("ld", "$(projectdir)/tools/zig/zig-c++") + set_toolset("sh", "$(projectdir)/tools/zig/zig-c++") + set_toolset("ar", "$(projectdir)/tools/zig/zig-ar") end add_cxflags("-fexperimental-library") add_cxflags("-fno-delete-null-pointer-checks") From 412e220f294a7b63b0473a3b771eda2363d5d200 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 26 May 2024 04:42:04 -0500 Subject: [PATCH 177/213] fix linux permission --- tools/zig/zig-cc-rust.bat | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools/zig/zig-cc-rust.bat diff --git a/tools/zig/zig-cc-rust.bat b/tools/zig/zig-cc-rust.bat old mode 100644 new mode 100755 From 3cf996b99ad90b55830dc3535406b8bd2747a189 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 04:48:01 -0500 Subject: [PATCH 178/213] might be a cleaner way --- tools/zig/zig-cc-rust.bat | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tools/zig/zig-cc-rust.bat b/tools/zig/zig-cc-rust.bat index 17197ca77..2b9db0422 100755 --- a/tools/zig/zig-cc-rust.bat +++ b/tools/zig/zig-cc-rust.bat @@ -1,7 +1,3 @@ -#!/bin/bash -# 2>nul || @goto :batch -exec zig cc -target x86_64-linux-gnu "$@" -goto :EOF - -:batch +:; exec zig cc -target x86_64-linux-gnu "$@"; exit $? +@echo off zig cc -target x86_64-linux-gnu %* \ No newline at end of file From 5b0c58e47ea03bb78a9abc498e2a1fecc5f556a7 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 26 May 2024 04:52:44 -0500 Subject: [PATCH 179/213] switch to zig build --- .github/workflows/linux-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index e6c9559f8..43576b6f1 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -59,7 +59,7 @@ jobs: actions-cache-key: 'linux-test' - name: Build run: | - xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y -m "Game__Shipping__Linux" + xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y --zig=y -m "Game__Shipping__Linux" XMAKE_COLORTERM=nocolor xmake build -v -D > build.log - name: Stripping run: | From 9027adbd2b12bf86620a83cad8a77825cc4ebc5f Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 26 May 2024 04:59:24 -0500 Subject: [PATCH 180/213] the clean way refuse to work, sad --- tools/zig/zig-cc-rust.bat | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/zig/zig-cc-rust.bat b/tools/zig/zig-cc-rust.bat index 2b9db0422..17197ca77 100755 --- a/tools/zig/zig-cc-rust.bat +++ b/tools/zig/zig-cc-rust.bat @@ -1,3 +1,7 @@ -:; exec zig cc -target x86_64-linux-gnu "$@"; exit $? -@echo off +#!/bin/bash +# 2>nul || @goto :batch +exec zig cc -target x86_64-linux-gnu "$@" +goto :EOF + +:batch zig cc -target x86_64-linux-gnu %* \ No newline at end of file From 5ca2cf370098861b86aae80e867174f8b798f764 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 18:10:27 -0500 Subject: [PATCH 181/213] should use scriptdir --- xmake.lua | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/xmake.lua b/xmake.lua index dca0fe5e9..1bf0a790c 100644 --- a/xmake.lua +++ b/xmake.lua @@ -68,17 +68,17 @@ option_end() toolchain("zigcross") if is_host("windows") then - set_toolset("cc", "$(projectdir)/tools/zig/zig-cc.bat") - set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++.bat") - set_toolset("ld", "$(projectdir)/tools/zig/zig-c++.bat") - set_toolset("sh", "$(projectdir)/tools/zig/zig-c++.bat") - set_toolset("ar", "$(projectdir)/tools/zig/zig-ar.bat") + set_toolset("cc", "$(scriptdir)/tools/zig/zig-cc.bat") + set_toolset("cxx", "$(scriptdir)/tools/zig/zig-c++.bat") + set_toolset("ld", "$(scriptdir)/tools/zig/zig-c++.bat") + set_toolset("sh", "$(scriptdir)/tools/zig/zig-c++.bat") + set_toolset("ar", "$(scriptdir)/tools/zig/zig-ar.bat") else - set_toolset("cc", "$(projectdir)/tools/zig/zig-cc") - set_toolset("cxx", "$(projectdir)/tools/zig/zig-c++") - set_toolset("ld", "$(projectdir)/tools/zig/zig-c++") - set_toolset("sh", "$(projectdir)/tools/zig/zig-c++") - set_toolset("ar", "$(projectdir)/tools/zig/zig-ar") + set_toolset("cc", "$(scriptdir)/tools/zig/zig-cc") + set_toolset("cxx", "$(scriptdir)/tools/zig/zig-c++") + set_toolset("ld", "$(scriptdir)/tools/zig/zig-c++") + set_toolset("sh", "$(scriptdir)/tools/zig/zig-c++") + set_toolset("ar", "$(scriptdir)/tools/zig/zig-ar") end add_cxflags("-fexperimental-library") add_cxflags("-fno-delete-null-pointer-checks") @@ -92,7 +92,7 @@ if is_plat("linux") then set_toolchains("zigcross", "rust") if is_host("windows") then set_arch("x86_64-unknown-linux-gnu") - add_rcflags("-C", "linker=$(projectdir)/tools/zig/zig-cc.bat", {force = true}) + add_rcflags("-C", "linker=$(scriptdir)/tools/zig/zig-cc.bat", {force = true}) end else set_toolchains("clang", "rust") From ab9611052741ec54b94e2e58d651d83a07d46faf Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 23:14:18 -0500 Subject: [PATCH 182/213] some attempts --- deps/third-repo/packages/z/zigcc/xmake.lua | 34 ++++++++++++++++++++++ xmake.lua | 2 ++ 2 files changed, 36 insertions(+) create mode 100644 deps/third-repo/packages/z/zigcc/xmake.lua diff --git a/deps/third-repo/packages/z/zigcc/xmake.lua b/deps/third-repo/packages/z/zigcc/xmake.lua new file mode 100644 index 000000000..04e0a6c60 --- /dev/null +++ b/deps/third-repo/packages/z/zigcc/xmake.lua @@ -0,0 +1,34 @@ +package("zigcc") + set_kind("toolchain") + set_homepage("https://www.ziglang.org/") + set_description("Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.") + + on_source(function (package) + local jsonfile = os.tmpfile() .. ".json" + import("net.http") + http.download("https://ziglang.org/download/index.json", jsonfile) + import("core.base.json") + local json = json.loadfile(jsonfile)["master"] + -- print(json) + if is_host("windows") then + -- print("Windows: " .. json["x86_64-windows"]["tarball"]) + package:set("urls", json["x86_64-windows"]["tarball"]) + package:add("versions", "v0.13.0", json["x86_64-windows"]["shasum"]) + elseif is_host("linux") then + -- print("Linux: " .. json["x86_64-linux"]["tarball"]) + package:set("urls", json["x86_64-linux"]["tarball"]) + package:add("versions", "v0.13.0", json["x86_64-linux"]["shasum"]) + else + print("Unsupported platform!") + end + end) + + on_install("@macosx", "@linux", "@windows", "@msys", "@bsd", function (package) + print("Install?" .. package:installdir()) + os.cp("*", package:installdir()) + package:addenv("PATH", package:installdir()) + end) + + on_test(function (package) + os.vrun("zig version") + end) \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 1bf0a790c..b4640833e 100644 --- a/xmake.lua +++ b/xmake.lua @@ -89,6 +89,8 @@ toolchain_end() if is_plat("linux") then if has_config("zig") then + -- add_requires("zigcc", {system = false}) + -- set_toolchains("zigcross@zigcc", "rust") set_toolchains("zigcross", "rust") if is_host("windows") then set_arch("x86_64-unknown-linux-gnu") From 54cbc0a31c04aec55765e7eaa32b2ad9273d3a8f Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 23:15:19 -0500 Subject: [PATCH 183/213] bumpup container version --- .github/workflows/linux-test.yml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 43576b6f1..584d4fe5b 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -22,7 +22,7 @@ permissions: jobs: make-release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.05 steps: - name: Setup github SSH uses: shimataro/ssh-key-action@v2 @@ -35,20 +35,8 @@ jobs: submodules: recursive fetch-depth: 0 # needed to get commits since last tag ssh-key: ${{ secrets.SSHKEY }} - - name: Setup Ninja - uses: seanmiddleditch/gha-setup-ninja@v3 - - name: Setup LLVM - uses: ZhongRuoyu/setup-llvm@v0 - with: - llvm-version: 18 - uses: goto-bus-stop/setup-zig@v2 - run: zig cc -v - - name: Upgrade libstdc++ - run: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test - sudo apt -y update - sudo apt -y install --only-upgrade libstdc++6 - sudo apt -y install libstdc++-13-dev - name: Setup Rust uses: dtolnay/rust-toolchain@1.76.0 - name: Setup xmake From eed044d49dadd34024c89d1fb034832f85336928 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 23:22:12 -0500 Subject: [PATCH 184/213] 24.04 --- .github/workflows/linux-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 584d4fe5b..01ca4016a 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -22,7 +22,7 @@ permissions: jobs: make-release: - runs-on: ubuntu-24.05 + runs-on: ubuntu-24.04 steps: - name: Setup github SSH uses: shimataro/ssh-key-action@v2 From 82d6a5dba2e2f174998e624613fd8722866eec89 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 23:38:23 -0500 Subject: [PATCH 185/213] add -v --- .github/workflows/linux-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 01ca4016a..256f1da9d 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -47,7 +47,7 @@ jobs: actions-cache-key: 'linux-test' - name: Build run: | - xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y --zig=y -m "Game__Shipping__Linux" + xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y --zig=y -v -m "Game__Shipping__Linux" XMAKE_COLORTERM=nocolor xmake build -v -D > build.log - name: Stripping run: | From 15eb0dcc00b30e10fd6f8f892e39da9636772411 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 23:39:39 -0500 Subject: [PATCH 186/213] show log --- .github/workflows/linux-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index 256f1da9d..afd0a73e0 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -48,7 +48,7 @@ jobs: - name: Build run: | xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y --zig=y -v -m "Game__Shipping__Linux" - XMAKE_COLORTERM=nocolor xmake build -v -D > build.log + xmake build - name: Stripping run: | mkdir prepackage From 5d774bfd2ac4fbcc0cba2422b558babc5219663c Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 23:46:11 -0500 Subject: [PATCH 187/213] something wrong with 24.04, roll back --- .github/workflows/linux-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index afd0a73e0..e67902a2c 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -22,7 +22,7 @@ permissions: jobs: make-release: - runs-on: ubuntu-24.04 + runs-on: ubuntu-22.04 steps: - name: Setup github SSH uses: shimataro/ssh-key-action@v2 From 0e0ddb852677580977d993bda1c6a52733310d6c Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 29 May 2024 23:46:39 -0500 Subject: [PATCH 188/213] update cmd --- .github/workflows/linux-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml index e67902a2c..944d26519 100644 --- a/.github/workflows/linux-test.yml +++ b/.github/workflows/linux-test.yml @@ -47,8 +47,8 @@ jobs: actions-cache-key: 'linux-test' - name: Build run: | - xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y --zig=y -v -m "Game__Shipping__Linux" - xmake build + xmake f -y --ue4ssUI=TUI --ue4ssInput=y --ue4ssIsBeta=y --zig=y -m "Game__Shipping__Linux" + XMAKE_COLORTERM=nocolor xmake build -v -D > build.log - name: Stripping run: | mkdir prepackage From 291b378230b3eccefaf02c8f85cc4e6ccf5982bd Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 1 Jun 2024 23:13:25 -0500 Subject: [PATCH 189/213] make cppmod happy --- xmake.lua | 63 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/xmake.lua b/xmake.lua index b4640833e..64e9f4d3f 100644 --- a/xmake.lua +++ b/xmake.lua @@ -68,17 +68,17 @@ option_end() toolchain("zigcross") if is_host("windows") then - set_toolset("cc", "$(scriptdir)/tools/zig/zig-cc.bat") - set_toolset("cxx", "$(scriptdir)/tools/zig/zig-c++.bat") - set_toolset("ld", "$(scriptdir)/tools/zig/zig-c++.bat") - set_toolset("sh", "$(scriptdir)/tools/zig/zig-c++.bat") - set_toolset("ar", "$(scriptdir)/tools/zig/zig-ar.bat") + set_toolset("cc", os.scriptdir() .. "/tools/zig/zig-cc.bat") + set_toolset("cxx", os.scriptdir() .. "/tools/zig/zig-c++.bat") + set_toolset("ld", os.scriptdir() .. "/tools/zig/zig-c++.bat") + set_toolset("sh", os.scriptdir() .. "/tools/zig/zig-c++.bat") + set_toolset("ar", os.scriptdir() .. "/tools/zig/zig-ar.bat") else - set_toolset("cc", "$(scriptdir)/tools/zig/zig-cc") - set_toolset("cxx", "$(scriptdir)/tools/zig/zig-c++") - set_toolset("ld", "$(scriptdir)/tools/zig/zig-c++") - set_toolset("sh", "$(scriptdir)/tools/zig/zig-c++") - set_toolset("ar", "$(scriptdir)/tools/zig/zig-ar") + set_toolset("cc", os.scriptdir() .. "/tools/zig/zig-cc") + set_toolset("cxx", os.scriptdir() .. "/tools/zig/zig-c++") + set_toolset("ld", os.scriptdir() .. "/tools/zig/zig-c++") + set_toolset("sh", os.scriptdir() .. "/tools/zig/zig-c++") + set_toolset("ar", os.scriptdir() .. "/tools/zig/zig-ar") end add_cxflags("-fexperimental-library") add_cxflags("-fno-delete-null-pointer-checks") @@ -87,25 +87,6 @@ toolchain("zigcross") add_shflags("-z", "lazy") toolchain_end() -if is_plat("linux") then - if has_config("zig") then - -- add_requires("zigcc", {system = false}) - -- set_toolchains("zigcross@zigcc", "rust") - set_toolchains("zigcross", "rust") - if is_host("windows") then - set_arch("x86_64-unknown-linux-gnu") - add_rcflags("-C", "linker=$(scriptdir)/tools/zig/zig-cc.bat", {force = true}) - end - else - set_toolchains("clang", "rust") - end - set_defaultmode("Game__Shipping__Linux") -end - -if is_plat("windows") then - set_defaultmode("Game__Shipping__Win64") -end - -- Override the `xmake install` behavior for all targets. -- Targets can re-override the on_install() function to implement custom installation behavior. on_install(function(target) end) @@ -117,3 +98,27 @@ includes("UE4SS") -- TODO: Remove this before the next release. It only exists to maintain backwards compat -- warnings for older mod templates. set_config("scriptsRoot", path.join(os.scriptdir(), "tools/xmakescripts")) + +-- Global initialization for UE4SS, run it in the topmost xmake.lua file. +function ue4ss_init() + if is_plat("linux") then + if has_config("zig") then + -- add_requires("zigcc", {system = false}) + -- set_toolchains("zigcross@zigcc", "rust") + set_toolchains("zigcross", "rust") + if is_host("windows") then + set_arch("x86_64-unknown-linux-gnu") + add_rcflags("-C", "linker=" .. os.scriptdir() .. "/tools/zig/zig-cc.bat", {force = true}) + end + else + set_toolchains("clang", "rust") + end + set_defaultmode("Game__Shipping__Linux") + end + + if is_plat("windows") then + set_defaultmode("Game__Shipping__Win64") + end +end + +ue4ss_init() From 5f40d8bb4ca7fc5f60e0b59193584097b0d26acb Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 1 Jun 2024 23:14:37 -0500 Subject: [PATCH 190/213] with soname we avoid abs path when link with -l * maybe use set_version is the "xmake"-ish way but that failed on my side. https://xmake.io/mirror/manual/global_interfaces.html#set_version --- UE4SS/xmake.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 7b22b7dbe..109f4a904 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -111,6 +111,7 @@ target(projectName) add_files("src/Platform/Win32/CrashDumper.cpp", "src/Platform/Win32/EntryWin32.cpp") elseif is_plat("linux") then add_files("src/Platform/Linux/EntryLinux.cpp") + add_shflags("-Wl,-soname,libUE4SS.so") end if uiMode ~= "None" then From 80ca709102d9677d8adc8a56eb46c3616ba10aa9 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 2 Jun 2024 00:24:32 -0500 Subject: [PATCH 191/213] fix wrong base ath --- UE4SS/src/Mod/CppMod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 38a11dba8..2a826fb06 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -16,7 +16,7 @@ namespace RC { CppMod::CppMod(UE4SSProgram& program, SystemStringType&& mod_name, SystemStringType&& mod_path) : Mod(program, std::move(mod_name), std::move(mod_path)) { - auto resolved_dlls_path = File::get_path_if_exists(get_name(), SYSSTR("dlls")); + auto resolved_dlls_path = File::get_path_if_exists(m_mod_path, SYSSTR("dlls")); if (resolved_dlls_path) { m_dlls_path = to_system_string(*resolved_dlls_path); From b99a555c5b64dcd558b20fa66c95caa51d37e84b Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 2 Jun 2024 00:29:41 -0500 Subject: [PATCH 192/213] use RTLD_LAZY to avoid missing string symbol in platform --- UE4SS/src/Mod/CppMod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UE4SS/src/Mod/CppMod.cpp b/UE4SS/src/Mod/CppMod.cpp index 2a826fb06..eb0989d21 100644 --- a/UE4SS/src/Mod/CppMod.cpp +++ b/UE4SS/src/Mod/CppMod.cpp @@ -68,7 +68,7 @@ namespace RC #else // use RTLD_LOCAL to avoid symbol conflicts - m_dl_handle = dlopen(dll_path.c_str(), RTLD_NOW | RTLD_LOCAL); + m_dl_handle = dlopen(dll_path.c_str(), RTLD_LAZY | RTLD_LOCAL); if (!m_dl_handle) { Output::send(SYSSTR("Failed to load dll <{}> for mod {}, because: {}\n"), to_system_string(dll_path), m_mod_name, dlerror()); From 2ea0eee8f8c9d5e9ac282939c9e4567a022a22f0 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 5 Jun 2024 03:45:42 -0500 Subject: [PATCH 193/213] fix TUI bug * I'm not sure about the difference between two values but the new one cause bug in TUI so I roll it back --- UE4SS/src/GUI/Console.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/UE4SS/src/GUI/Console.cpp b/UE4SS/src/GUI/Console.cpp index 5f6979cad..1d974dd7f 100644 --- a/UE4SS/src/GUI/Console.cpp +++ b/UE4SS/src/GUI/Console.cpp @@ -132,8 +132,12 @@ namespace RC::GUI std::lock_guard guard(m_lines_mutex); // TODO: ensure this ydiv is okay? // the old value is const float footer_height_to_reserve = ((ImGui::GetStyle().ItemSpacing.y * 10.0f) + ImGui::GetFrameHeightWithSpacing()) / YDIV; - m_text_editor.Render("TextEditor", {-16.0f / XDIV, (-31.0f + -8.0f) / YDIV}); + + const float footer_height_to_reserve = ((ImGui::GetStyle().ItemSpacing.y * 10.0f) + ImGui::GetFrameHeightWithSpacing()) / YDIV; + // m_text_editor.Render("TextEditor", {-16.0f / XDIV, (-31.0f + -8.0f) / YDIV}); + m_text_editor.Render("TextEditor", {-16.0f / XDIV, footer_height_to_reserve}); + ImGui_AutoScroll("TextEditor", &m_previous_max_scroll_y); //*/ } From b036ad0efbebf9e92bf5178e69a1b397022f3d93 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 5 Jun 2024 04:19:19 -0500 Subject: [PATCH 194/213] fix ui --- UE4SS/src/GUI/LiveView.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index b98097f30..197b7cce5 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -3093,7 +3093,6 @@ namespace RC::GUI // Update this text if corresponding button's text changes. Textinput width = Spacing + Window margin + Button padding + Button text width ImGui::PushItemWidth(-(8.0f + 16.0f + ImGui::GetStyle().FramePadding.x * 2.0f + ImGui::CalcTextSize(ICON_FA_COPY " Copy search result").x)); - // TODO: merge conflict, make sure this width is onky for TUI: old value is (-160.0f / XDIV bool push_inactive_text_color = !m_search_field_cleared; if (push_inactive_text_color) { @@ -3444,20 +3443,24 @@ namespace RC::GUI } ImGui::SetClipboardText(to_string(result).c_str()); } - + #ifdef HAS_GUI + #define SPLIT_HEIGHT 4.0f + #define WINDOW_MARGIN 31.0f + 8.0f + SPLIT_HEIGHT + #endif + #ifdef HAS_TUI + #define SPLIT_HEIGHT 0.5f + #define WINDOW_MARGIN 0.0f + #endif // Y - Windows title bar offset - Bottom window margin - Splitter height - auto split_pane_height = ImGui::GetContentRegionAvail().y - 31.0f - 8.0f - 4.0f; + auto split_pane_height = ImGui::GetContentRegionAvail().y - WINDOW_MARGIN; if (m_bottom_size > 0 && m_bottom_size + m_top_size != split_pane_height) { // Window height changed, scale panes by ratio m_top_size = std::max(ImGui::GetFrameHeight(), std::round(split_pane_height * (m_top_size / (m_top_size + m_bottom_size)))); } - // TODO: check the size for TUI as m_bottom_size = (ImGui::GetContentRegionMaxAbs().y - m_top_size) - 2.0f; m_bottom_size = std::max(ImGui::GetFrameHeight(), split_pane_height - m_top_size); - // TODO: do we need ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, XOFFSET); on TUI? - // TODO: we need false, 0.5f? - // TODO: do we need ImGui_Splitter(false, 0.5f, &m_top_size, &m_bottom_size, 12.0f, 12.0f, ImGui::GetContentRegionMaxAbs().x); for TUI? - ImGui_Splitter(false, 4.0f, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16.0f); + float xoffset = (XOFFSET == 0) ? (0.0f) : (XOFFSET - 2); + ImGui_Splitter(false, SPLIT_HEIGHT, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), xoffset); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); @@ -3586,7 +3589,6 @@ namespace RC::GUI s_watches_loaded_from_disk = true; } float xoffset = (XOFFSET == 0) ? (0.0f) : (XOFFSET - 2); - // TODO: ensure this / XDIV is okay? the old value is -35/XDIV ImGui::BeginChild("watch_render_frame", {xoffset, (-31.0f + -8.0f) / XDIV}); if (ImGui::Button("All Off")) @@ -3603,14 +3605,13 @@ namespace RC::GUI #ifdef HAS_GUI ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, {2.0f, 2.0f}); #endif - // TODO: do we need ImGuiTableFlags_NoPadOuterX? if (ImGui::BeginTable("watch_table", num_columns, ImGuiTableFlags_Borders | ImGuiTableFlags_NoPadOuterX)) { - // TODO: do we need controls_width = (XDIV == 1) ? (60.0f) : (60.0f / XDIV + 5.0f);? - ImGui::TableSetupColumn("Controls", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFrameHeight() * 3.0f + 4.0f); + float width_controls = std::max(ImGui::CalcTextSize(ICON_FA_COPY "Controls").x, ImGui::GetFrameHeight() * 3.0f + 4.0f); + ImGui::TableSetupColumn("Controls", ImGuiTableColumnFlags_WidthFixed, width_controls); ImGui::TableSetupColumn("Watch Identifier", ImGuiTableColumnFlags_WidthStretch); - // TODO: why height here? - ImGui::TableSetupColumn("Save", ImGuiTableColumnFlags_WidthFixed, ImGui::GetFrameHeight()); + float width_save = std::max(ImGui::CalcTextSize(ICON_FA_COPY "Save").x, ImGui::GetFrameHeight()); + ImGui::TableSetupColumn("Save", ImGuiTableColumnFlags_WidthFixed, width_save); ImGui::TableHeadersRow(); { From b0207eee5b1b91925b0f6749ad6e4f6ec9058ff1 Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 5 Jun 2024 04:45:16 -0500 Subject: [PATCH 195/213] xoffset makes it unable to move --- UE4SS/src/GUI/LiveView.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 197b7cce5..13e2a74d7 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -3459,8 +3459,7 @@ namespace RC::GUI m_top_size = std::max(ImGui::GetFrameHeight(), std::round(split_pane_height * (m_top_size / (m_top_size + m_bottom_size)))); } m_bottom_size = std::max(ImGui::GetFrameHeight(), split_pane_height - m_top_size); - float xoffset = (XOFFSET == 0) ? (0.0f) : (XOFFSET - 2); - ImGui_Splitter(false, SPLIT_HEIGHT, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), xoffset); + ImGui_Splitter(false, SPLIT_HEIGHT, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); From d2c88559f05910a358c31b17f65cc3674ffdecbf Mon Sep 17 00:00:00 2001 From: Yangff Date: Wed, 5 Jun 2024 04:45:35 -0500 Subject: [PATCH 196/213] should allow old code using STR when Output --- .../include/DynamicOutput/Output.hpp | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp index 168a26a10..0ef508aac 100644 --- a/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp +++ b/deps/first/DynamicOutput/include/DynamicOutput/Output.hpp @@ -306,9 +306,10 @@ namespace RC::Output DefaultTargets::set_default_log_level(log_level); } - template - auto send(SystemStringViewType content, FmtArgs&&... fmt_args) -> void + template + auto send(StringView _content, FmtArgs&&... fmt_args) -> void { + auto content = to_system(_content); auto formated = apply_formatting(content, to_system(std::forward(fmt_args))...); for (const auto& device : DefaultTargets::get_default_devices_ref()) { @@ -325,9 +326,10 @@ namespace RC::Output } } - template - auto send(SystemStringViewType content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void + template + auto send(StringView _content, OptionalArg optional_arg, FmtArgs&&... fmt_args) -> void { + auto content = to_system(_content); auto formated = std::vformat(content, RC_STD_MAKE_FORMAT_ARGS(to_system(std::forward(fmt_args))...)); for (const auto& device : DefaultTargets::get_default_devices_ref()) { @@ -346,9 +348,10 @@ namespace RC::Output auto RC_DYNOUT_API send(SystemStringViewType content) -> void; - template - auto send(SystemStringViewType content, OptionalArg optional_arg) -> void + template + auto send(StringView _content, OptionalArg optional_arg) -> void { + auto content = to_system(_content); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) @@ -364,9 +367,10 @@ namespace RC::Output } } - template - auto send(SystemStringViewType content, FmtArgs&&... fmt_args) -> void + template + auto send(StringView _content, FmtArgs&&... fmt_args) -> void { + auto content = to_system(_content); auto formated = apply_formatting(content, to_system(std::forward(fmt_args))...); for (const auto& device : DefaultTargets::get_default_devices_ref()) { @@ -383,9 +387,10 @@ namespace RC::Output } } - template - auto send(SystemStringViewType content) -> void + template + auto send(StringView _content) -> void { + auto content = to_system(_content); for (const auto& device : DefaultTargets::get_default_devices_ref()) { ASSERT_DEFAULT_OUTPUT_DEVICE_IS_VALID(device) From 224ec0befe9dcd711f718ed5e4ae72a6e4babc4e Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 6 Jun 2024 23:29:38 -0500 Subject: [PATCH 197/213] allow access to TUI on both plat (unused on win) --- UE4SS/include/SettingsManager.hpp | 2 -- UE4SS/src/SettingsManager.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/UE4SS/include/SettingsManager.hpp b/UE4SS/include/SettingsManager.hpp index ffcc88691..a90d13711 100644 --- a/UE4SS/include/SettingsManager.hpp +++ b/UE4SS/include/SettingsManager.hpp @@ -111,7 +111,6 @@ namespace RC bool GUIUFunctionCaller{false}; } Experimental; -#ifdef LINUX struct TUIFeatures { /*int ButtonLeft = 1; @@ -135,7 +134,6 @@ namespace RC SystemStringType TERMINFO = SYSSTR("/usr/share/terminfo"); SystemStringType LCALL = SYSSTR("en_US.UTF-8"); } TUI; -#endif public: SettingsManager() = default; diff --git a/UE4SS/src/SettingsManager.cpp b/UE4SS/src/SettingsManager.cpp index 84be1cfc3..eac755d8b 100644 --- a/UE4SS/src/SettingsManager.cpp +++ b/UE4SS/src/SettingsManager.cpp @@ -139,7 +139,6 @@ namespace RC constexpr static SystemCharType section_experimental_features[] = SYSSTR("ExperimentalFeatures"); REGISTER_BOOL_SETTING(Experimental.GUIUFunctionCaller, section_experimental_features, GUIUFunctionCaller) -#ifdef LINUX constexpr static SystemCharType section_tui_features[] = SYSSTR("TUI"); /*REGISTER_INT64_SETTING(TUI.ButtonLeft, section_tui_features, ButtonLeft) REGISTER_INT64_SETTING(TUI.ButtonRight, section_tui_features, ButtonRight) @@ -161,6 +160,5 @@ namespace RC REGISTER_STRING_SETTING(TUI.CopyCode, section_tui_features, CopyCode) REGISTER_STRING_SETTING(TUI.SearchCode, section_tui_features, SearchCode) */ -#endif } } // namespace RC From fb3eb9d1615978c376649ed3020bcb17ff773f3e Mon Sep 17 00:00:00 2001 From: Yangff Date: Thu, 6 Jun 2024 23:30:51 -0500 Subject: [PATCH 198/213] test tui dynamically --- UE4SS/include/GUI/GUI.hpp | 19 +++++++++++++++++++ UE4SS/include/GUI/TUI.hpp | 1 + UE4SS/src/GUI/GUI.cpp | 14 +++++++++++++- UE4SS/src/GUI/Platform/TUI/TUI.cpp | 10 ++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index 76498e873..d373299c9 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -82,6 +82,17 @@ namespace RC::GUI int32_t y; }; + struct BackendProperty { + float x_offset_0; + float x_offset_1; + float xdiv; + float ydiv; + float separator_height; + bool quirk_tui; + }; + + extern BackendProperty g_backend_properties; + class GfxBackendBase { protected: @@ -119,6 +130,9 @@ namespace RC::GUI { return false; }; + virtual auto set_backend_properties(BackendProperty &properties) -> void + { + }; }; class OSBackendBase @@ -319,6 +333,10 @@ namespace RC::GUI }); } + extern bool g_tui_mode; + #define ATTACH_ICON(icon, str) ((icon str) + (g_tui_mode ? (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1)) : 0)) + #define ICON_ALT(icon, alt) (g_tui_mode ? ((UE4SSProgram::settings_manager.TUI.TUINerdFont) ? (icon) : (alt)) : (icon)) +/* #ifdef HAS_GUI #define ATTACH_ICON(icon, str) icon str #define ICON_ALT(icon, alt) icon @@ -326,4 +344,5 @@ namespace RC::GUI #define ATTACH_ICON(icon, str) ((icon str) + (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1))) #define ICON_ALT(icon, alt) (UE4SSProgram::settings_manager.TUI.TUINerdFont) ? (icon) : (alt) #endif +*/ } // namespace RC::GUI diff --git a/UE4SS/include/GUI/TUI.hpp b/UE4SS/include/GUI/TUI.hpp index abaaebd54..6e91a128b 100644 --- a/UE4SS/include/GUI/TUI.hpp +++ b/UE4SS/include/GUI/TUI.hpp @@ -35,5 +35,6 @@ namespace RC::GUI auto on_os_backend_set() -> void override; auto get_window_size() -> WindowSize override; auto exit_requested() -> bool override; + auto set_backend_properties(BackendProperty &properties) -> void override; }; } // namespace RC::GUI diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 2f3d2b8a3..6b1d58938 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -60,6 +60,16 @@ namespace RC::GUI ImColor g_imgui_text_blue_color = ImColor{135, 195, 250, 255}; ImColor g_imgui_text_purple_color = ImColor{170, 145, 255, 255}; + bool g_tui_mode = false; + BackendProperty g_backend_properties = { + .quirk_tui = false, + .separator_height = 4.0f, + .x_offset_0 = -14.0f, + .x_offset_1 = -16.0f, + .xdiv = 1.0f, + .ydiv = 1.0f, + }; + std::vector DebuggingGUI::s_end_of_frame_callbacks{}; auto DebuggingGUI::is_valid() -> bool @@ -548,6 +558,7 @@ namespace RC::GUI auto DebuggingGUI::set_gfx_backend(GfxBackend backend) -> void { Output::send(SYSSTR("Setting gfx backend!\n")); + g_tui_mode = false; switch (backend) { #ifdef HAS_D3D11 @@ -567,16 +578,17 @@ namespace RC::GUI break; #elif defined(HAS_TUI) case GfxBackend::TUI: + g_tui_mode = true; m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); #endif #endif } - m_gfx_backend->set_os_backend(m_os_backend.get()); m_os_backend->set_gfx_backend(m_gfx_backend.get()); m_gfx_backend->on_os_backend_set(); m_os_backend->on_gfx_backend_set(); + m_gfx_backend->set_backend_properties(g_backend_properties); } auto DebuggingGUI::add_tab(std::shared_ptr tab) -> void diff --git a/UE4SS/src/GUI/Platform/TUI/TUI.cpp b/UE4SS/src/GUI/Platform/TUI/TUI.cpp index bc22bf250..3604d5b5a 100644 --- a/UE4SS/src/GUI/Platform/TUI/TUI.cpp +++ b/UE4SS/src/GUI/Platform/TUI/TUI.cpp @@ -168,4 +168,14 @@ namespace RC::GUI { return tui_shutdown; } + + void Backend_GfxTUI::set_backend_properties(BackendProperty& properties) + { + properties.quirk_tui = true; + properties.xdiv = 6.66f; + properties.ydiv = 21.1f; + properties.separator_height = 0.5f; + properties.x_offset_0 = 0; + properties.x_offset_1 = 0; + } }; // namespace RC::GUI From 18598898121f3313b783552e919bcb70a16dbfbc Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 8 Jun 2024 01:21:26 -0500 Subject: [PATCH 199/213] use BackendProperty --- UE4SS/include/GUI/GUI.hpp | 21 ++++++++++----------- UE4SS/src/GUI/GUI.cpp | 3 --- UE4SS/src/GUI/LiveView.cpp | 28 +++++++++------------------- 3 files changed, 19 insertions(+), 33 deletions(-) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index d373299c9..4b0dc0034 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -18,19 +18,12 @@ struct ImGuiSettingsHandler; static_assert(false, "HAS_GUI or HAS_TUI must be defined."); #endif -#define XOFFSET (-14.0f) -#define XDIV 1 -#define YDIV 1 - #else #ifdef HAS_GUI static_assert(false, "HAS_GUI and HAS_TUI cannot be defined at the same time at this moment."); #endif -#define XOFFSET 0 -#define XDIV (6.66f) -#define YDIV (21.1f) namespace ImGui { @@ -91,7 +84,14 @@ namespace RC::GUI bool quirk_tui; }; - extern BackendProperty g_backend_properties; + extern RC_UE4SS_API BackendProperty g_backend_properties; + + #define XOFFSET_0 (g_backend_properties.x_offset_0) + #define XOFFSET_1 (g_backend_properties.x_offset_1) + #define XDIV (g_backend_properties.xdiv) + #define YDIV (g_backend_properties.ydiv) + #define SEPARATOR_HEIGHT (g_backend_properties.separator_height) + #define IS_TUI (g_backend_properties.quirk_tui) class GfxBackendBase { @@ -333,9 +333,8 @@ namespace RC::GUI }); } - extern bool g_tui_mode; - #define ATTACH_ICON(icon, str) ((icon str) + (g_tui_mode ? (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1)) : 0)) - #define ICON_ALT(icon, alt) (g_tui_mode ? ((UE4SSProgram::settings_manager.TUI.TUINerdFont) ? (icon) : (alt)) : (icon)) + #define ATTACH_ICON(icon, str) ((icon str) + (IS_TUI ? (UE4SSProgram::settings_manager.TUI.TUINerdFont ? (0) : (sizeof(icon) - 1)) : 0)) + #define ICON_ALT(icon, alt) (IS_TUI ? ((UE4SSProgram::settings_manager.TUI.TUINerdFont) ? (icon) : (alt)) : (icon)) /* #ifdef HAS_GUI #define ATTACH_ICON(icon, str) icon str diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 6b1d58938..6b5bfa3f2 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -60,7 +60,6 @@ namespace RC::GUI ImColor g_imgui_text_blue_color = ImColor{135, 195, 250, 255}; ImColor g_imgui_text_purple_color = ImColor{170, 145, 255, 255}; - bool g_tui_mode = false; BackendProperty g_backend_properties = { .quirk_tui = false, .separator_height = 4.0f, @@ -558,7 +557,6 @@ namespace RC::GUI auto DebuggingGUI::set_gfx_backend(GfxBackend backend) -> void { Output::send(SYSSTR("Setting gfx backend!\n")); - g_tui_mode = false; switch (backend) { #ifdef HAS_D3D11 @@ -578,7 +576,6 @@ namespace RC::GUI break; #elif defined(HAS_TUI) case GfxBackend::TUI: - g_tui_mode = true; m_gfx_backend = std::make_unique(); m_os_backend = std::make_unique(); #endif diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 13e2a74d7..6aafc3420 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -2827,7 +2827,7 @@ namespace RC::GUI auto LiveView::render_info_panel() -> void { - ImGui::BeginChild("LiveView_InfoPanel", {XOFFSET, m_bottom_size}, true, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("LiveView_InfoPanel", {XOFFSET_0, m_bottom_size}, true, ImGuiWindowFlags_HorizontalScrollbar); size_t next_object_index_to_select{}; @@ -3443,31 +3443,22 @@ namespace RC::GUI } ImGui::SetClipboardText(to_string(result).c_str()); } - #ifdef HAS_GUI - #define SPLIT_HEIGHT 4.0f - #define WINDOW_MARGIN 31.0f + 8.0f + SPLIT_HEIGHT - #endif - #ifdef HAS_TUI - #define SPLIT_HEIGHT 0.5f - #define WINDOW_MARGIN 0.0f - #endif // Y - Windows title bar offset - Bottom window margin - Splitter height - auto split_pane_height = ImGui::GetContentRegionAvail().y - WINDOW_MARGIN; + float window_margin = 0.0f; + if (!IS_TUI) { + window_margin = 31.0f + 8.0f + SEPARATOR_HEIGHT; + } + auto split_pane_height = ImGui::GetContentRegionAvail().y - window_margin; if (m_bottom_size > 0 && m_bottom_size + m_top_size != split_pane_height) { // Window height changed, scale panes by ratio m_top_size = std::max(ImGui::GetFrameHeight(), std::round(split_pane_height * (m_top_size / (m_top_size + m_bottom_size)))); } m_bottom_size = std::max(ImGui::GetFrameHeight(), split_pane_height - m_top_size); - ImGui_Splitter(false, SPLIT_HEIGHT, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16); + ImGui_Splitter(false, SEPARATOR_HEIGHT, &m_top_size, &m_bottom_size, ImGui::GetFrameHeight(), ImGui::GetFrameHeight(), -16); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4{0.156f, 0.156f, 0.156f, 1.0f}); - -#ifdef HAS_GUI - ImGui::BeginChild("LiveView_TreeView", {-16.0f, m_top_size}, true); -#else - ImGui::BeginChild("LiveView_TreeView", {0, m_top_size}, true); -#endif + ImGui::BeginChild("LiveView_TreeView", {XOFFSET_1, m_top_size}, true); auto do_iteration = [&](int32_t int_data_1 = 0, int32_t int_data_2 = 0) { ((*this).*((*this).m_object_iterator))(int_data_1, int_data_2, [&](UObject* object) { @@ -3587,8 +3578,7 @@ namespace RC::GUI load_watches_from_disk(); s_watches_loaded_from_disk = true; } - float xoffset = (XOFFSET == 0) ? (0.0f) : (XOFFSET - 2); - ImGui::BeginChild("watch_render_frame", {xoffset, (-31.0f + -8.0f) / XDIV}); + ImGui::BeginChild("watch_render_frame", {XOFFSET_1, (-31.0f + -8.0f) / XDIV}); if (ImGui::Button("All Off")) { From 2fccc073113ac21f4d01d210db08ab34dbe58839 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 8 Jun 2024 01:29:23 -0500 Subject: [PATCH 200/213] add common.hpp --- UE4SS/include/GUI/GUI.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index 4b0dc0034..eabdf3977 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include From f1f1490c962ddd712a05f9f451d5f808ea10c753 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 8 Jun 2024 17:45:09 -0500 Subject: [PATCH 201/213] add WIN32 and dllext --- tools/xmakescripts/rules/build_rules.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/xmakescripts/rules/build_rules.lua b/tools/xmakescripts/rules/build_rules.lua index 17d380eb5..d21b41d1c 100644 --- a/tools/xmakescripts/rules/build_rules.lua +++ b/tools/xmakescripts/rules/build_rules.lua @@ -56,10 +56,12 @@ local PLATFORM_TYPES = { ["defines"] = { "PLATFORM_WINDOWS", "PLATFORM_MICROSOFT", + "WIN32", "OVERRIDE_PLATFORM_HEADER_NAME=Windows", "UBT_COMPILED_PLATFORM=Win64", "UNICODE", - "_UNICODE" + "_UNICODE", + "DLLEXT=.dll" }, ["cxflags"] = { "clang::-gcodeview" From 3573a60f679cc8aef302cec428d18314110f55d8 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 8 Jun 2024 17:58:07 -0500 Subject: [PATCH 202/213] %s to %S on windows --- UE4SS/src/UE4SSProgram.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 2eb12c0b6..8ce90381e 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -177,7 +177,8 @@ namespace RC // Setup the log file auto& file_device = Output::set_default_devices(); - fprintf(stderr, "log dir: %s\n", (m_log_directory / m_log_file_name).c_str()); + STR + fprintf(stderr, "log dir: "SystemStringPrint"\n", (m_log_directory / m_log_file_name).c_str()); file_device.set_file_name_and_path(to_system(m_log_directory / m_log_file_name)); create_simple_console(); From 6c982791e2bb5b600b82cc974dbc27eb5b51961e Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 8 Jun 2024 17:58:49 -0500 Subject: [PATCH 203/213] designators meet declaration order of class --- UE4SS/src/GUI/GUI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index 6b5bfa3f2..c9100648d 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -61,12 +61,12 @@ namespace RC::GUI ImColor g_imgui_text_purple_color = ImColor{170, 145, 255, 255}; BackendProperty g_backend_properties = { - .quirk_tui = false, - .separator_height = 4.0f, .x_offset_0 = -14.0f, .x_offset_1 = -16.0f, .xdiv = 1.0f, .ydiv = 1.0f, + .separator_height = 4.0f, + .quirk_tui = false, }; std::vector DebuggingGUI::s_end_of_frame_callbacks{}; From 9916917f79936bc4682db32b941e0164563998c1 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 8 Jun 2024 17:59:55 -0500 Subject: [PATCH 204/213] typo --- UE4SS/src/UE4SSProgram.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 8ce90381e..3bf11dc63 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -177,7 +177,6 @@ namespace RC // Setup the log file auto& file_device = Output::set_default_devices(); - STR fprintf(stderr, "log dir: "SystemStringPrint"\n", (m_log_directory / m_log_file_name).c_str()); file_device.set_file_name_and_path(to_system(m_log_directory / m_log_file_name)); From c30456aa3ff6bd2e525c5346630cfefc8d7472f6 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 8 Jun 2024 18:02:46 -0500 Subject: [PATCH 205/213] get rid of the print --- UE4SS/src/UE4SSProgram.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 3bf11dc63..011af40af 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -177,7 +177,6 @@ namespace RC // Setup the log file auto& file_device = Output::set_default_devices(); - fprintf(stderr, "log dir: "SystemStringPrint"\n", (m_log_directory / m_log_file_name).c_str()); file_device.set_file_name_and_path(to_system(m_log_directory / m_log_file_name)); create_simple_console(); From a619ffa45656b3c618283a807aef39d35619ab65 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 8 Jun 2024 18:32:57 -0500 Subject: [PATCH 206/213] add missing links for windows --- UE4SS/xmake.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/UE4SS/xmake.lua b/UE4SS/xmake.lua index 109f4a904..0b5af959b 100644 --- a/UE4SS/xmake.lua +++ b/UE4SS/xmake.lua @@ -109,6 +109,7 @@ target(projectName) if is_plat("windows") then add_files("src/Platform/Win32/CrashDumper.cpp", "src/Platform/Win32/EntryWin32.cpp") + add_links("dbghelp", "psapi", { public = true }) elseif is_plat("linux") then add_files("src/Platform/Linux/EntryLinux.cpp") add_shflags("-Wl,-soname,libUE4SS.so") From e8fd649337d131d323fc6f6dd97022b1f42d9059 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 8 Jun 2024 18:33:03 -0500 Subject: [PATCH 207/213] fix windows string type --- UE4SS/src/GUI/LiveView.cpp | 31 +++++++++---------- deps/first/Helpers/include/Helpers/String.hpp | 11 +++++-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index 6aafc3420..fdc25ad5a 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -316,7 +316,7 @@ namespace RC::GUI { if constexpr (std::is_same_v) { - values_array.new_string(to_string(value.ToString())); + values_array.new_string(to_system(value.ToString())); } else if constexpr (std::is_same_v) { @@ -324,7 +324,7 @@ namespace RC::GUI } else { - values_array.new_string(to_string(value)); + values_array.new_string(to_system(value)); } } } @@ -355,7 +355,7 @@ namespace RC::GUI File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); int32_t json_indent_level{}; - json_file.write_file_string_to_file(json.serialize(JSON::ShouldFormat::Yes, &json_indent_level)); + json_file.write_file_string_to_file(to_file(json.serialize(JSON::ShouldFormat::Yes, &json_indent_level))); } static auto save_filters_to_disk() -> void @@ -365,29 +365,26 @@ namespace RC::GUI }); } + template + static auto to_dest_string(T&& input) { + STRING_DISPATCH_NOERR(std::decay_t, to_string, to_wstring, to_u16string) + else if constexpr(std::is_same_v, FName>) { + return to_ue(input); + } + STRING_DISPATCH_ERROR(Dest) + } + template static auto json_array_to_filters_list(JSON::Array& json_array, std::vector& list, SystemStringType type, std::string& internal_value) -> void { list.clear(); - internal_value.clear(); + internal_value.clear(); json_array.for_each([&](JSON::Value& item) { if (!item.is()) { throw std::runtime_error{std::format("Invalid {} in 'filters.meta.json'", to_string(type))}; } - - if constexpr (std::is_same_v) - { - list.emplace_back(to_system(item.as()->get_view())); - } - else if constexpr(std::is_same_v || std::is_same_v) - { - list.emplace_back(to_ue(item.as()->get_view())); - } - else - { - static_assert(false, "Unsupported string type"); - } + list.emplace_back(to_dest_string(item.as()->get_view())); return LoopAction::Continue; }); diff --git a/deps/first/Helpers/include/Helpers/String.hpp b/deps/first/Helpers/include/Helpers/String.hpp index 1bb4e9ad9..32cc44532 100644 --- a/deps/first/Helpers/include/Helpers/String.hpp +++ b/deps/first/Helpers/include/Helpers/String.hpp @@ -214,7 +214,7 @@ namespace RC /* explode_by_occurrence -> END */ // ----------------------------- // -#define STRING_DISPATCH(STRING_T, ts, tw, tu16) \ +#define STRING_DISPATCH_NOERR(STRING_T, ts, tw, tu16) \ if constexpr (std::is_same_v) \ { \ return ts(std::forward(input)); \ @@ -226,11 +226,18 @@ namespace RC else if constexpr (std::is_same_v) \ { \ return tu16(std::forward(input)); \ - } \ + } + +#define STRING_DISPATCH_ERROR(STRING_T) \ else \ { \ static_assert(dependent_false::value, "Unsupported " #STRING_T "."); \ } + +#define STRING_DISPATCH(STRING_T, ts, tw, tu16) \ + STRING_DISPATCH_NOERR(STRING_T, ts, tw, tu16) \ + STRING_DISPATCH_ERROR(STRING_T) + // ----------------------------- // #define PATH_QUIRK(STRINGT) \ if constexpr (std::is_same_v, std::filesystem::path> || std::is_same_v, const std::filesystem::path>) \ From c90a4c5d5e37c5cc110a88a5e8fd0006675e7bc9 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 8 Jun 2024 19:40:47 -0500 Subject: [PATCH 208/213] fix console size --- UE4SS/include/GUI/GUI.hpp | 1 + UE4SS/src/GUI/Console.cpp | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/UE4SS/include/GUI/GUI.hpp b/UE4SS/include/GUI/GUI.hpp index eabdf3977..453fd0493 100644 --- a/UE4SS/include/GUI/GUI.hpp +++ b/UE4SS/include/GUI/GUI.hpp @@ -92,6 +92,7 @@ namespace RC::GUI #define XDIV (g_backend_properties.xdiv) #define YDIV (g_backend_properties.ydiv) #define SEPARATOR_HEIGHT (g_backend_properties.separator_height) + #define NEGATIVE_MARGIN(x) (IS_TUI ? (-0.01f) : (x)) #define IS_TUI (g_backend_properties.quirk_tui) class GfxBackendBase diff --git a/UE4SS/src/GUI/Console.cpp b/UE4SS/src/GUI/Console.cpp index 1d974dd7f..50b67108d 100644 --- a/UE4SS/src/GUI/Console.cpp +++ b/UE4SS/src/GUI/Console.cpp @@ -132,11 +132,8 @@ namespace RC::GUI std::lock_guard guard(m_lines_mutex); // TODO: ensure this ydiv is okay? // the old value is const float footer_height_to_reserve = ((ImGui::GetStyle().ItemSpacing.y * 10.0f) + ImGui::GetFrameHeightWithSpacing()) / YDIV; - - const float footer_height_to_reserve = ((ImGui::GetStyle().ItemSpacing.y * 10.0f) + ImGui::GetFrameHeightWithSpacing()) / YDIV; - // m_text_editor.Render("TextEditor", {-16.0f / XDIV, (-31.0f + -8.0f) / YDIV}); - m_text_editor.Render("TextEditor", {-16.0f / XDIV, footer_height_to_reserve}); + m_text_editor.Render("TextEditor", {-16.0f / XDIV, NEGATIVE_MARGIN(-31.0f + -8.0f)}); ImGui_AutoScroll("TextEditor", &m_previous_max_scroll_y); //*/ From 98bc01e78178e06316d073e508e72788b65372a3 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sat, 8 Jun 2024 19:42:38 -0500 Subject: [PATCH 209/213] verified value --- UE4SS/src/GUI/Console.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/UE4SS/src/GUI/Console.cpp b/UE4SS/src/GUI/Console.cpp index 50b67108d..42c02a970 100644 --- a/UE4SS/src/GUI/Console.cpp +++ b/UE4SS/src/GUI/Console.cpp @@ -130,9 +130,6 @@ namespace RC::GUI /**/ std::lock_guard guard(m_lines_mutex); - // TODO: ensure this ydiv is okay? - // the old value is const float footer_height_to_reserve = ((ImGui::GetStyle().ItemSpacing.y * 10.0f) + ImGui::GetFrameHeightWithSpacing()) / YDIV; - m_text_editor.Render("TextEditor", {-16.0f / XDIV, NEGATIVE_MARGIN(-31.0f + -8.0f)}); ImGui_AutoScroll("TextEditor", &m_previous_max_scroll_y); From 087e75379073bc068efb0e0bc3367e3572d85071 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 9 Jun 2024 05:22:39 -0500 Subject: [PATCH 210/213] fix xmake fix back diff bug rebase bug windows only rebase bug on tui fix rebase bug fix setting resolve rebase bug rebase bug rebase bug rebase bug --- UE4SS/include/GUI/TUI.hpp | 3 +- UE4SS/include/Mod/CppUserModBase.hpp | 2 +- UE4SS/src/GUI/GUI.cpp | 6 +++- UE4SS/src/GUI/LiveView.cpp | 4 +-- UE4SS/src/GUI/Platform/TUI/TUI.cpp | 7 ++++- UE4SS/src/UE4SSProgram.cpp | 14 ++++------ deps/first/Input/include/Input/Handler.hpp | 3 -- deps/third/xmake.lua | 13 +-------- deps/xmake.lua | 7 +++++ xmake.lua | 32 +++------------------- 10 files changed, 34 insertions(+), 57 deletions(-) diff --git a/UE4SS/include/GUI/TUI.hpp b/UE4SS/include/GUI/TUI.hpp index 6e91a128b..bd22a8127 100644 --- a/UE4SS/include/GUI/TUI.hpp +++ b/UE4SS/include/GUI/TUI.hpp @@ -9,12 +9,13 @@ namespace RC::GUI public: auto init() -> void override; auto imgui_backend_newframe() -> void override; - auto create_window() -> void override; + auto create_window(int loc_x, int loc_y, int size_x, int size_y) -> void override; auto exec_message_loop(bool* exit_requested) -> void override; auto shutdown() -> void override; auto cleanup() -> void override; auto get_window_handle() -> void* override; auto get_window_size() -> WindowSize override; + auto get_window_position() -> WindowPosition override; auto on_gfx_backend_set() -> void override; }; diff --git a/UE4SS/include/Mod/CppUserModBase.hpp b/UE4SS/include/Mod/CppUserModBase.hpp index 36dc14ad2..b9cbf0108 100644 --- a/UE4SS/include/Mod/CppUserModBase.hpp +++ b/UE4SS/include/Mod/CppUserModBase.hpp @@ -136,7 +136,7 @@ namespace RC RC_UE4SS_API virtual auto render_tab() -> void{}; protected: - RC_UE4SS_API auto register_tab(std::wstring_view tab_name, GUI::GUITab::RenderFunctionType) -> void; + RC_UE4SS_API auto register_tab(UEStringViewType tab_name, GUI::GUITab::RenderFunctionType) -> void; RC_UE4SS_API auto register_keydown_event(Input::Key, const Input::EventCallbackCallable&, uint8_t custom_data = 0) -> void; RC_UE4SS_API auto register_keydown_event(Input::Key, const Input::Handler::ModifierKeyArray&, const Input::EventCallbackCallable&, uint8_t custom_data = 0) -> void; diff --git a/UE4SS/src/GUI/GUI.cpp b/UE4SS/src/GUI/GUI.cpp index c9100648d..df201e8fb 100644 --- a/UE4SS/src/GUI/GUI.cpp +++ b/UE4SS/src/GUI/GUI.cpp @@ -13,6 +13,8 @@ #ifdef HAS_D3D11 #include #endif +#else +#define sscanf_s sscanf #endif #ifdef HAS_GLFW @@ -504,10 +506,11 @@ namespace RC::GUI IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - m_imgui_ini_file = to_string(StringType{UE4SSProgram::get_program().get_working_directory()} + STR("\\imgui.ini")); + m_imgui_ini_file = to_string_path(std::filesystem::path {UE4SSProgram::get_program().get_working_directory()} / SYSSTR("imgui.ini")); io.IniFilename = m_imgui_ini_file.c_str(); // Add .ini handle for UserData type + #ifdef WIN32 ImGuiSettingsHandler ini_handler; ini_handler.TypeName = "UE4SSData"; ini_handler.TypeHash = ImHashStr("UE4SSData"); @@ -515,6 +518,7 @@ namespace RC::GUI ini_handler.ReadLineFn = imgui_ue4ss_data_read_line; ini_handler.WriteAllFn = imgui_ue4ss_data_write_all; ImGui::AddSettingsHandler(&ini_handler); + #endif ImGui::LoadIniSettingsFromDisk(m_imgui_ini_file.c_str()); diff --git a/UE4SS/src/GUI/LiveView.cpp b/UE4SS/src/GUI/LiveView.cpp index fdc25ad5a..75534c7bc 100644 --- a/UE4SS/src/GUI/LiveView.cpp +++ b/UE4SS/src/GUI/LiveView.cpp @@ -350,7 +350,7 @@ namespace RC::GUI } auto json_file = - File::open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("UE4SS-config") SYSSTR("liveview")SYSSTR("filters.meta.json")), + File::open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("UE4SS-config") SYSSTR("liveview")SYSSTR("filters.meta.json"), File::OpenFor::Writing, File::OverwriteExistingFile::Yes, File::CreateIfNonExistent::Yes); @@ -409,7 +409,7 @@ namespace RC::GUI static auto internal_load_filters_from_disk() -> void { const auto json_file = - File::open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("UE4SS-config") / SYSSTR("liveview") / SYSSTR("filters.meta.json")), + File::open(std::filesystem::path{UE4SSProgram::get_program().get_working_directory()} / SYSSTR("UE4SS-config") / SYSSTR("liveview") / SYSSTR("filters.meta.json"), File::OpenFor::Reading, File::OverwriteExistingFile::No, File::CreateIfNonExistent::Yes); diff --git a/UE4SS/src/GUI/Platform/TUI/TUI.cpp b/UE4SS/src/GUI/Platform/TUI/TUI.cpp index 3604d5b5a..bb8c1d037 100644 --- a/UE4SS/src/GUI/Platform/TUI/TUI.cpp +++ b/UE4SS/src/GUI/Platform/TUI/TUI.cpp @@ -58,11 +58,16 @@ namespace RC::GUI } } - void Backend_TUI::create_window() + void Backend_TUI::create_window(int loc_x, int loc_y, int size_x, int size_y) { // Do nothing } + WindowPosition Backend_TUI::get_window_position() + { + return {0, 0}; + } + void Backend_TUI::exec_message_loop(bool* exit_requested) { ImTui_ImplNcurses_ProcessEvent(); diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index 011af40af..a8bdc7df7 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -57,7 +57,10 @@ #include #include +#ifdef WIN32 #include +#endif + #include namespace RC @@ -463,10 +466,10 @@ namespace RC else { // Check for legacy locations and update paths accordingly - resolaved_settings_file = File::get_path_if_exists(m_legacy_root_directory, m_settings_file_name); - if (resolaved_settings_file) + auto resolaved_legacy_settings_file = File::get_path_if_exists(m_legacy_root_directory, m_settings_file_name); + if (resolaved_legacy_settings_file) { - m_settings_path_and_file = *resolaved_settings_file; + m_settings_path_and_file = *resolaved_legacy_settings_file; } else { throw std::runtime_error{"UE4SS-Settings.ini file not found"}; } @@ -1444,11 +1447,6 @@ namespace RC return m_module_file_path_str; } - auto UE4SSProgram::get_game_executable_directory() -> File::StringViewType - { - return m_game_executable_directory.c_str(); - } - auto UE4SSProgram::get_working_directory() -> SystemStringViewType { m_working_directory_str = to_system_string(m_working_directory); diff --git a/deps/first/Input/include/Input/Handler.hpp b/deps/first/Input/include/Input/Handler.hpp index 06bbfe8b3..53c428346 100644 --- a/deps/first/Input/include/Input/Handler.hpp +++ b/deps/first/Input/include/Input/Handler.hpp @@ -29,12 +29,9 @@ namespace RC::Input ModifierKeys required_modifier_keys{}; EventCallbackCallable callback{}; uint8_t custom_data{}; -<<<<<<< HEAD void* custom_data2{}; bool requires_modifier_keys{}; bool is_down{}; -======= ->>>>>>> 83b273a (Add input source for Linux TUI and update input handler initialization) }; struct KeySet diff --git a/deps/third/xmake.lua b/deps/third/xmake.lua index 24409b73a..2f432e0b3 100644 --- a/deps/third/xmake.lua +++ b/deps/third/xmake.lua @@ -1,12 +1 @@ -includes("zycore") -includes("zydis") -includes("polyhook_2") -includes("glaze") --- includes("imtui") -includes("imgui") -includes("glad") -includes("raw_pdb") - -add_requires("zycore v1.5.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) -add_requires("zydis v4.1.0", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) -add_requires("polyhook_2", { debug = is_mode_debug(), configs = { runtimes = get_mode_runtimes() } }) +includes("glad") \ No newline at end of file diff --git a/deps/xmake.lua b/deps/xmake.lua index 62ded994a..45680fba6 100644 --- a/deps/xmake.lua +++ b/deps/xmake.lua @@ -2,3 +2,10 @@ includes("first") -- Third party dependencies includes("third") +-- Third party dependencies repository +-- Everything that is an xmake package should be inside of this repository +add_repositories("third-party deps/third-repo", { rootdir = get_config("ue4ssRoot") }) + +add_requires("zycore v1.5.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) +add_requires("zydis v4.1.0", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) +add_requires("polyhook_2", { debug = is_mode_debug(), configs = {runtimes = get_mode_runtimes()} }) \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 64e9f4d3f..d8f8f9df4 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,33 +1,9 @@ -set_xmakever("2.9.2") -- We should use `get_config("ue4ssRoot")` instead of `os.projectdir()` or `$(projectdir)`. -- This is because os.projectdir() will return a higher parent dir -- when UE4SS is sub-moduled/`include("UE4SS")` in another xmake project. set_config("ue4ssRoot", os.scriptdir()) -includes("tools/xmakescripts/build_configs.lua") -includes("tools/xmakescripts/configurations.lua") - -add_rules(get_unreal_rules()) - --- Restrict the compilation modes/configs. -set_allowedplats("windows", "linux") -if is_plat("windows") then - set_allowedarchs("x64") -elseif is_plat("linux") then - set_allowedarchs("x86_64") - set_defaultarchs("x86_64") - set_toolchains("clang", "rust") -end -set_allowedmodes(get_compilation_modes()) - -if is_plat("windows") then - set_defaultmode("Game__Shipping__Win64") - set_runtimes(get_mode_runtimes()) -elseif is_plat("linux") then - set_defaultmode("Game__Shipping__Linux") -end - --- All non-binary outputs are stored in the Intermediates dir. +-- All non-binary outputs are written to the Intermediates dir. set_config("buildir", "Intermediates") -- Any lua modules in this directory can be imported in the script scope by using @@ -35,8 +11,8 @@ set_config("buildir", "Intermediates") -- /modules/rules/my_module.lua import("rules.my_module") add_moduledirs("tools/xmakescripts/modules") --- Load our rule files into the global scope. -includes("tools/xmakescripts/rules/**.lua") +-- Load the build_rules file into the global scope. +includes("tools/xmakescripts/rules/build_rules.lua") -- Generate the mode rules. local modes = generate_compilation_modes() @@ -121,4 +97,4 @@ function ue4ss_init() end end -ue4ss_init() +ue4ss_init() \ No newline at end of file From 3dd00e3a46d76d7063c04fcc6a62b1b84fcf6469 Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 9 Jun 2024 05:52:06 -0500 Subject: [PATCH 211/213] update unreal --- deps/first/Unreal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/first/Unreal b/deps/first/Unreal index 8bbf04eb3..946180f2e 160000 --- a/deps/first/Unreal +++ b/deps/first/Unreal @@ -1 +1 @@ -Subproject commit 8bbf04eb3cb30c2c6815f3cf1f025e2d78b11d47 +Subproject commit 946180f2e93bb1679ab1bd1edc015e4352b57278 From 9b4552068804a5f5ec2309ca378aeb65af40ee1a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 9 Jun 2024 05:58:58 -0500 Subject: [PATCH 212/213] fix windows build --- UE4SS/src/Platform/Win32/CrashDumper.cpp | 2 +- UE4SS/src/UE4SSProgram.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/UE4SS/src/Platform/Win32/CrashDumper.cpp b/UE4SS/src/Platform/Win32/CrashDumper.cpp index 5e35de5f9..95054f573 100644 --- a/UE4SS/src/Platform/Win32/CrashDumper.cpp +++ b/UE4SS/src/Platform/Win32/CrashDumper.cpp @@ -27,7 +27,7 @@ namespace RC LONG WINAPI ExceptionHandler(_EXCEPTION_POINTERS* exception_pointers) { const auto now = time_point_cast(system_clock::now()); - const std::wstring dump_path = std::format(L"{}\\crash_{:%Y_%m_%d_%H_%M_%S}.dmp", StringType{UE4SSProgram::get_program().get_working_directory()}, now); + const std::wstring dump_path = std::format(L"{}\\crash_{:%Y_%m_%d_%H_%M_%S}.dmp", SystemStringType{UE4SSProgram::get_program().get_working_directory()}, now); const HANDLE file = CreateFileW(dump_path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); diff --git a/UE4SS/src/UE4SSProgram.cpp b/UE4SS/src/UE4SSProgram.cpp index a8bdc7df7..75bb0bfd3 100644 --- a/UE4SS/src/UE4SSProgram.cpp +++ b/UE4SS/src/UE4SSProgram.cpp @@ -1459,7 +1459,7 @@ namespace RC return m_mods_directory_str; } - auto UE4SSProgram::get_legacy_root_directory() -> File::StringViewType + auto UE4SSProgram::get_legacy_root_directory() -> SystemStringViewType { return m_legacy_root_directory.c_str(); } From db8c255a06412ace6511202b6090b0cc1cb871db Mon Sep 17 00:00:00 2001 From: Yangff Date: Sun, 9 Jun 2024 06:28:42 -0500 Subject: [PATCH 213/213] mod folder is not copied --- tools/buildscripts/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/buildscripts/build.py b/tools/buildscripts/build.py index 260c6ddbc..94430f3db 100755 --- a/tools/buildscripts/build.py +++ b/tools/buildscripts/build.py @@ -102,7 +102,7 @@ def make_staging_dirs(is_dev_release: bool): # Builds a release version of /assets by copying the directory and then # removing and disabling dev-only settings and files exclude_files = [ - 'Mods/shared/Types.lua', + # 'Mods/shared/Types.lua', 'UE4SS_Signatures', 'VTableLayoutTemplates', 'MemberVarLayoutTemplates',