├── .gitignore ├── Engine ├── IGenerator.hpp ├── Logger.cpp ├── Logger.hpp ├── Main.cpp ├── NameValidator.cpp ├── NameValidator.hpp ├── NamesStore.cpp ├── NamesStore.hpp ├── ObjectsStore.cpp ├── ObjectsStore.hpp ├── Package.cpp ├── Package.hpp ├── PatternFinder.cpp ├── PatternFinder.hpp ├── PrintHelper.cpp ├── PrintHelper.hpp ├── UE4 │ ├── FunctionFlags.cpp │ ├── FunctionFlags.hpp │ ├── GenericTypes.cpp │ ├── GenericTypes.hpp │ ├── Package.cpp │ ├── PropertyFlags.cpp │ └── PropertyFlags.hpp ├── cpplinq.hpp └── tinyformat.h ├── README.md ├── SDK.sln ├── SDK.vcxproj ├── SDK.vcxproj.filters └── Target └── Satisfactory ├── EngineClasses.hpp ├── Generator.cpp ├── GenericTypes.cpp ├── NamesStore.cpp └── ObjectsStore.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | x64/ 3 | .vs/ -------------------------------------------------------------------------------- /Engine/IGenerator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class IGenerator 9 | { 10 | public: 11 | virtual ~IGenerator() = default; 12 | 13 | /// 14 | /// Initializes this object. 15 | /// Add predefined types, ... 16 | /// 17 | /// The module handle. 18 | /// true if it succeeds, false if it fails. 19 | virtual bool Initialize(void* module) = 0; 20 | 21 | /// 22 | /// Gets output directory where the files are getting stored. 23 | /// The name of the game gets appended to this directory. 24 | /// 25 | /// The output directory. 26 | virtual std::string GetOutputDirectory() const 27 | { 28 | return "C:/SDK_GEN"; 29 | } 30 | 31 | /// 32 | /// Gets the name of the game. 33 | /// 34 | /// The game name. 35 | virtual std::string GetGameName() const = 0; 36 | 37 | /// 38 | /// Gets the short name of the game. 39 | /// 40 | /// The short name. 41 | virtual std::string GetGameNameShort() const = 0; 42 | 43 | /// 44 | /// Gets the version of the game. 45 | /// 46 | /// The version of the game. 47 | virtual std::string GetGameVersion() const = 0; 48 | 49 | /// 50 | /// Check if the generator should dump the object and name arrays. 51 | /// 52 | /// true if the arrays should get dumped. 53 | virtual bool ShouldDumpArrays() const 54 | { 55 | return true; 56 | } 57 | 58 | /// 59 | /// Check if the generator should generate empty files (no classes, structs, ...). 60 | /// 61 | /// true if empty files should get generated. 62 | virtual bool ShouldGenerateEmptyFiles() const 63 | { 64 | return false; 65 | } 66 | 67 | /// 68 | /// Check if the generated classes should use strings to identify objects. 69 | /// If false the generated classes use the object index. 70 | /// Warning: The object index may change for non default classes. 71 | /// 72 | /// true if strings should be used. 73 | virtual bool ShouldUseStrings() const 74 | { 75 | return true; 76 | } 77 | 78 | /// 79 | /// Check if strings () should be xor encoded. 80 | /// 81 | /// true if string should be xor encoded. 82 | virtual bool ShouldXorStrings() const 83 | { 84 | return false; 85 | } 86 | 87 | /// 88 | /// Check if static methods should get converted to normal methods. 89 | /// Static methods require a CreateDefaultObject() method in the UObject class. 90 | /// 91 | /// true if static methods should get converted to normal methods. 92 | virtual bool ShouldConvertStaticMethods() const 93 | { 94 | return true; 95 | } 96 | 97 | /// 98 | /// Check if we should generate a function parameters file. 99 | /// Otherwise the parameters are declared inside the function body. 100 | /// If hooks with access to the parameters are need, this method should return true. 101 | /// 102 | /// True if a function parameters file should be generated. 103 | virtual bool ShouldGenerateFunctionParametersFile() const 104 | { 105 | return true; 106 | } 107 | 108 | /// 109 | /// Gets namespace name for the classes. If the name is empty no namespace gets generated. 110 | /// 111 | /// The namespace name. 112 | virtual std::string GetNamespaceName() const 113 | { 114 | return std::string(); 115 | } 116 | 117 | /// 118 | /// Gets a list of custom include files which gets inserted in the SDK. 119 | /// 120 | /// The list of include files. 121 | virtual std::vector GetIncludes() const 122 | { 123 | return {}; 124 | } 125 | 126 | /// 127 | /// Gets the member alignment. 128 | /// https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx 129 | /// 130 | /// The member alignment. 131 | virtual size_t GetGlobalMemberAlignment() const 132 | { 133 | return sizeof(size_t); 134 | } 135 | 136 | /// 137 | /// Gets alignas size for the specific class. 138 | /// http://cppreference.com/w/cpp/language/alignas 139 | /// 140 | /// The name. 141 | /// If the class is not found the return value is 0, else the alignas size. 142 | virtual size_t GetClassAlignas(const std::string& name) const 143 | { 144 | auto it = alignasClasses.find(name); 145 | if (it != std::end(alignasClasses)) 146 | { 147 | return it->second; 148 | } 149 | return 0; 150 | } 151 | 152 | /// 153 | /// Gets the declarations of some basic classes and methods. 154 | /// 155 | /// The basic declarations. 156 | virtual std::string GetBasicDeclarations() const 157 | { 158 | return std::string(); 159 | } 160 | 161 | /// 162 | /// Gets the definitions of the declarations. 163 | /// 164 | /// The basic definitions. 165 | virtual std::string GetBasicDefinitions() const 166 | { 167 | return std::string(); 168 | } 169 | 170 | /// 171 | /// Checks if an override is defined for the given type. 172 | /// 173 | /// The parameter type. 174 | /// If no override is found the original name is returned. 175 | virtual std::string GetOverrideType(const std::string& type) const 176 | { 177 | auto it = overrideTypes.find(type); 178 | if (it == std::end(overrideTypes)) 179 | { 180 | return type; 181 | } 182 | return it->second; 183 | } 184 | 185 | struct PredefinedMember 186 | { 187 | std::string Type; 188 | std::string Name; 189 | }; 190 | 191 | /// 192 | /// Gets the predefined members of the specific class. 193 | /// 194 | /// The name of the class. 195 | /// [out] The predefined members. 196 | /// true if predefined members are found. 197 | virtual bool GetPredefinedClassMembers(const std::string& name, std::vector& members) const 198 | { 199 | auto it = predefinedMembers.find(name); 200 | if (it != std::end(predefinedMembers)) 201 | { 202 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(members)); 203 | 204 | return true; 205 | } 206 | 207 | return false; 208 | } 209 | 210 | /// 211 | /// Gets the static predefined members of the specific class. 212 | /// 213 | /// The name of the class. 214 | /// [out] The predefined members. 215 | /// true if predefined members are found. 216 | virtual bool GetPredefinedClassStaticMembers(const std::string& name, std::vector& members) const 217 | { 218 | auto it = predefinedStaticMembers.find(name); 219 | if (it != std::end(predefinedStaticMembers)) 220 | { 221 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(members)); 222 | 223 | return true; 224 | } 225 | 226 | return false; 227 | } 228 | 229 | using VirtualFunctionPatterns = std::vector>; 230 | 231 | /// 232 | /// Gets the patterns of virtual functions of the specific class. 233 | /// The generator loops the virtual functions of the class and adds a class method if the pattern matches. 234 | /// 235 | /// The name of the class. 236 | /// [out] The patterns. 237 | /// true if patterns are found. 238 | virtual bool GetVirtualFunctionPatterns(const std::string& name, VirtualFunctionPatterns& patterns) const 239 | { 240 | auto it = virtualFunctionPattern.find(name); 241 | if (it != std::end(virtualFunctionPattern)) 242 | { 243 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(patterns)); 244 | 245 | return true; 246 | } 247 | 248 | return false; 249 | } 250 | 251 | struct PredefinedMethod 252 | { 253 | enum class Type 254 | { 255 | Default, 256 | Inline 257 | }; 258 | 259 | std::string Signature; 260 | std::string Body; 261 | Type MethodType; 262 | 263 | /// Adds a predefined method which gets splittet in declaration and definition. 264 | /// The method signature. 265 | /// The method body. 266 | /// The method. 267 | static PredefinedMethod Default(std::string&& signature, std::string&& body) 268 | { 269 | return { signature, body, Type::Default }; 270 | } 271 | 272 | /// Adds a predefined method which gets included as an inline method. 273 | /// The body. 274 | /// The method. 275 | static PredefinedMethod Inline(std::string&& body) 276 | { 277 | return { std::string(), body, Type::Inline }; 278 | } 279 | }; 280 | 281 | /// Gets the predefined methods of the specific class. 282 | /// The name of the class. 283 | /// [out] The predefined methods. 284 | /// true if predefined methods are found. 285 | virtual bool GetPredefinedClassMethods(const std::string& name, std::vector& methods) const 286 | { 287 | auto it = predefinedMethods.find(name); 288 | if (it != std::end(predefinedMethods)) 289 | { 290 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(methods)); 291 | 292 | return true; 293 | } 294 | 295 | return false; 296 | } 297 | 298 | protected: 299 | std::unordered_map alignasClasses; 300 | std::unordered_map overrideTypes; 301 | std::unordered_map> predefinedMembers; 302 | std::unordered_map> predefinedStaticMembers; 303 | std::unordered_map> predefinedMethods; 304 | std::unordered_map virtualFunctionPattern; 305 | }; 306 | -------------------------------------------------------------------------------- /Engine/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.hpp" 2 | 3 | std::ostream* Logger::stream = nullptr; 4 | 5 | void Logger::SetStream(std::ostream* _stream) 6 | { 7 | stream = _stream; 8 | } 9 | 10 | void Logger::Log(const std::string& message) 11 | { 12 | if (stream != nullptr) 13 | { 14 | (*stream) << message << '\n' << std::flush; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Engine/Logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "tinyformat.h" 8 | 9 | class Logger 10 | { 11 | public: 12 | 13 | /// 14 | /// Sets the stream where the output goes to. 15 | /// 16 | /// [in] The stream. 17 | static void SetStream(std::ostream* stream); 18 | 19 | /// 20 | /// Logs the given message. 21 | /// 22 | /// The message. 23 | static void Log(const std::string& message); 24 | 25 | /// 26 | /// Formats and logs the given message. 27 | /// 28 | /// Type of the arguments. 29 | /// Describes the format to use. 30 | /// Variable arguments providing the arguments. 31 | template 32 | static void Log(const char* fmt, const Args&... args) 33 | { 34 | Log(tfm::format(fmt, args...)); 35 | } 36 | 37 | private: 38 | static std::ostream *stream; 39 | }; 40 | -------------------------------------------------------------------------------- /Engine/Main.cpp: -------------------------------------------------------------------------------- 1 | // Unreal Engine SDK Generator 2 | // by KN4CK3R 3 | // https://www.oldschoolhack.me 4 | 5 | #define NOMINMAX 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | namespace fs = std::experimental::filesystem; 15 | #include "cpplinq.hpp" 16 | 17 | #include "Logger.hpp" 18 | 19 | #include "IGenerator.hpp" 20 | #include "ObjectsStore.hpp" 21 | #include "NamesStore.hpp" 22 | #include "Package.hpp" 23 | #include "NameValidator.hpp" 24 | #include "PrintHelper.hpp" 25 | 26 | extern IGenerator* generator; 27 | 28 | /// 29 | /// Dumps the objects and names to files. 30 | /// 31 | /// The path where to create the dumps. 32 | void Dump(const fs::path& path) 33 | { 34 | { 35 | std::ofstream o(path / "ObjectsDump.txt"); 36 | tfm::format(o, "Address: 0x%P\n\n", ObjectsStore::GetAddress()); 37 | 38 | for (auto obj : ObjectsStore()) 39 | { 40 | tfm::format(o, "[%06i] %-100s 0x%P\n", obj.GetIndex(), obj.GetFullName(), obj.GetAddress()); 41 | } 42 | } 43 | 44 | { 45 | std::ofstream o(path / "NamesDump.txt"); 46 | tfm::format(o, "Address: 0x%P\n\n", NamesStore::GetAddress()); 47 | 48 | for (auto name : NamesStore()) 49 | { 50 | tfm::format(o, "[%06i] %s\n", name.Index, name.Name); 51 | } 52 | } 53 | } 54 | 55 | /// 56 | /// Generates the sdk header. 57 | /// 58 | /// The path where to create the sdk header. 59 | /// The list of processed objects. 60 | /// The package order info. 61 | void SaveSDKHeader(const fs::path& path, const std::unordered_map& processedObjects, const std::vector& packages) 62 | { 63 | std::ofstream os(path / "SDK.hpp"); 64 | 65 | os << "#pragma once\n\n" 66 | << tfm::format("// %s SDK\n\n", generator->GetGameName()); 67 | 68 | //include the basics 69 | { 70 | { 71 | std::ofstream os2(path / "SDK" / tfm::format("%s_Basic.hpp", generator->GetGameNameShort())); 72 | 73 | std::vector includes{ { "" }, { "" } }; 74 | 75 | auto&& generatorIncludes = generator->GetIncludes(); 76 | includes.insert(includes.end(), std::begin(generatorIncludes), std::end(generatorIncludes)); 77 | 78 | PrintFileHeader(os2, includes, true); 79 | 80 | os2 << generator->GetBasicDeclarations() << "\n"; 81 | 82 | PrintFileFooter(os2); 83 | 84 | os << "\n#include \"SDK/" << tfm::format("%s_Basic.hpp", generator->GetGameNameShort()) << "\"\n"; 85 | } 86 | { 87 | std::ofstream os2(path / "SDK" / tfm::format("%s_Basic.cpp", generator->GetGameNameShort())); 88 | 89 | std::vector includes2{ 90 | { tfm::format("%s_CoreUObject_classes.hpp", generator->GetGameNameShort()) }, 91 | { tfm::format("%s_Engine_classes.hpp", generator->GetGameNameShort()) } }; 92 | 93 | PrintFileHeader(os2, includes2, false); 94 | 95 | os2 << generator->GetBasicDefinitions() << "\n"; 96 | 97 | PrintFileFooter(os2); 98 | } 99 | } 100 | 101 | using namespace cpplinq; 102 | 103 | //check for missing structs 104 | const auto missing = from(processedObjects) >> where([](auto&& kv) { return kv.second == false; }); 105 | if (missing >> any()) 106 | { 107 | std::ofstream os2(path / "SDK" / tfm::format("%s_MISSING.hpp", generator->GetGameNameShort())); 108 | 109 | PrintFileHeader(os2, true); 110 | 111 | for (auto&& s : missing >> select([](auto&& kv) { return kv.first.Cast(); }) >> experimental::container()) 112 | { 113 | os2 << "// " << s.GetFullName() << "\n// "; 114 | os2 << tfm::format("0x%04X\n", s.GetPropertySize()); 115 | 116 | os2 << "struct " << MakeValidName(s.GetNameCPP()) << "\n{\n"; 117 | os2 << "\tunsigned char UnknownData[0x" << tfm::format("%X", s.GetPropertySize()) << "];\n};\n\n"; 118 | } 119 | 120 | PrintFileFooter(os2); 121 | 122 | os << "\n#include \"SDK/" << tfm::format("%s_MISSING.hpp", generator->GetGameNameShort()) << "\"\n"; 123 | } 124 | 125 | os << "\n"; 126 | 127 | for (auto&& package : packages) 128 | { 129 | os << R"(#include "SDK/)" << GenerateFileName(FileContentType::Classes, package) << "\"\n"; 130 | } 131 | 132 | os << "\n" << "namespace " << generator->GetNamespaceName() << "\n"; 133 | 134 | os << R"({ 135 | static bool DataCompare(PBYTE pData, PBYTE bSig, const char* szMask) 136 | { 137 | for (; *szMask; ++szMask, ++pData, ++bSig) 138 | { 139 | if (*szMask == 'x' && *pData != *bSig) 140 | return false; 141 | } 142 | return (*szMask) == 0; 143 | } 144 | 145 | static DWORD_PTR FindPattern(DWORD_PTR dwAddress, DWORD dwSize, const char* pbSig, const char* szMask, long offset) 146 | { 147 | size_t length = strlen(szMask); 148 | for (size_t i = NULL; i < dwSize - length; i++) 149 | { 150 | if (DataCompare((PBYTE)dwAddress + i, (PBYTE)pbSig, szMask)) 151 | return dwAddress + i + offset; 152 | } 153 | return 0; 154 | } 155 | 156 | static void InitSDK() 157 | { 158 | DWORD_PTR BaseAddress = (DWORD_PTR)GetModuleHandle(NULL); 159 | 160 | MODULEINFO ModuleInfo; 161 | GetModuleInformation(GetCurrentProcess(), (HMODULE)BaseAddress, &ModuleInfo, sizeof(ModuleInfo)); 162 | 163 | auto GNamesAddress = FindPattern(BaseAddress, ModuleInfo.SizeOfImage, 164 | "\x48\x8B\x05\x00\x00\x00\x03\x48\x85\xC0\x0F\x85\x81", "xxx???xxxxxxx", 0); 165 | auto GNamesOffset = *reinterpret_cast(GNamesAddress + 3); 166 | FName::GNames = *reinterpret_cast(GNamesAddress + 7 + GNamesOffset); 167 | 168 | auto GObjectsAddress = FindPattern(BaseAddress, ModuleInfo.SizeOfImage, 169 | "\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x00\x00\x00\x0E\x00\x00\xE8", "xxx????x???xx???xxxx", 0); 170 | auto GObjectsOffset = *reinterpret_cast(GObjectsAddress + 3); 171 | UObject::GObjects = reinterpret_cast(GObjectsAddress + 7 + GObjectsOffset); 172 | 173 | auto GWorldAddress = FindPattern(BaseAddress, ModuleInfo.SizeOfImage, 174 | "\x48\x8B\x1D\x00\x00\x00\x04\x48\x85\xDB\x74\x3B", "xxx???xxxxxx", 0); 175 | auto GWorldOffset = *reinterpret_cast(GWorldAddress + 3); 176 | UWorld::GWorld = reinterpret_cast(GWorldAddress + 7 + GWorldOffset); 177 | } 178 | })"; 179 | } 180 | 181 | /// 182 | /// Process the packages. 183 | /// 184 | /// The path where to create the package files. 185 | void ProcessPackages(const fs::path& path) 186 | { 187 | using namespace cpplinq; 188 | 189 | const auto sdkPath = path / "SDK"; 190 | fs::create_directories(sdkPath); 191 | 192 | std::vector packages; 193 | 194 | std::unordered_map processedObjects; 195 | 196 | auto packageObjects = from(ObjectsStore()) 197 | >> select([](auto&& o) { return o.GetPackageObject(); }) 198 | >> where([](auto&& o) { return o.IsValid(); }) 199 | >> distinct() 200 | >> to_vector(); 201 | 202 | for (auto obj : packageObjects) 203 | { 204 | Package package(obj); 205 | 206 | package.Process(processedObjects); 207 | if (package.Save(sdkPath)) 208 | { 209 | packages.emplace_back(std::move(package)); 210 | } 211 | } 212 | 213 | SaveSDKHeader(path, processedObjects, packages); 214 | } 215 | 216 | DWORD WINAPI OnAttach(LPVOID lpParameter) 217 | { 218 | if (!ObjectsStore::Initialize()) 219 | { 220 | MessageBoxA(nullptr, "ObjectsStore::Initialize failed", "Error", 0); 221 | return -1; 222 | } 223 | if (!NamesStore::Initialize()) 224 | { 225 | MessageBoxA(nullptr, "NamesStore::Initialize failed", "Error", 0); 226 | return -1; 227 | } 228 | 229 | if (!generator->Initialize(lpParameter)) 230 | { 231 | MessageBoxA(nullptr, "Initialize failed", "Error", 0); 232 | return -1; 233 | } 234 | 235 | fs::path outputDirectory(generator->GetOutputDirectory()); 236 | if (!outputDirectory.is_absolute()) 237 | { 238 | char buffer[2048]; 239 | if (GetModuleFileNameA(static_cast(lpParameter), buffer, sizeof(buffer)) == 0) 240 | { 241 | MessageBoxA(nullptr, "GetModuleFileName failed", "Error", 0); 242 | return -1; 243 | } 244 | 245 | outputDirectory = fs::path(buffer).remove_filename() / outputDirectory; 246 | } 247 | 248 | outputDirectory /= generator->GetGameNameShort(); 249 | fs::create_directories(outputDirectory); 250 | 251 | std::ofstream log(outputDirectory / "Generator.log"); 252 | Logger::SetStream(&log); 253 | 254 | if (generator->ShouldDumpArrays()) 255 | { 256 | Dump(outputDirectory); 257 | } 258 | 259 | fs::create_directories(outputDirectory); 260 | 261 | const auto begin = std::chrono::system_clock::now(); 262 | 263 | ProcessPackages(outputDirectory); 264 | 265 | Logger::Log("Finished, took %d seconds.", std::chrono::duration_cast(std::chrono::system_clock::now() - begin).count()); 266 | 267 | Logger::SetStream(nullptr); 268 | 269 | MessageBoxA(nullptr, "Finished!", "Info", 0); 270 | 271 | return 0; 272 | } 273 | 274 | BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) 275 | { 276 | switch (dwReason) 277 | { 278 | case DLL_PROCESS_ATTACH: 279 | DisableThreadLibraryCalls(hModule); 280 | 281 | CreateThread(nullptr, 0, OnAttach, hModule, 0, nullptr); 282 | 283 | return TRUE; 284 | } 285 | 286 | return FALSE; 287 | } 288 | -------------------------------------------------------------------------------- /Engine/NameValidator.cpp: -------------------------------------------------------------------------------- 1 | #include "NameValidator.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include "ObjectsStore.hpp" 7 | 8 | std::string MakeValidName(std::string&& name) 9 | { 10 | static std::unordered_set disallowedChars = { 11 | ' ', '?', '+', '-', ':', '/', '^', '(', ')', '[', 12 | ']', '<', '>', '&', '.', '#', '\'', '"', '%', 13 | }; 14 | 15 | static std::unordered_set disallowedWords = { 16 | "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor", 17 | "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", 18 | "compl", "const", "constexpr", "const_cast", "continue", "decltype", "default", 19 | "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", 20 | "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", 21 | "long", "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr", 22 | "operator", "or", "or_eq", "private", "protected", "public", "register", 23 | "reinterpret_cast", "return", "short", "signed", "sizeof", "static", "static_assert", 24 | "static_cast", "struct", "switch", "template", "this", "thread_local", "throw", 25 | "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", 26 | "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq" 27 | }; 28 | 29 | std::string valid(name); 30 | 31 | for (auto i = 0u; i < name.length(); ++i) 32 | { 33 | if (disallowedChars.find(valid[i]) != disallowedChars.end()) 34 | { 35 | valid[i] = '_'; 36 | } 37 | } 38 | 39 | if (!valid.empty()) 40 | { 41 | if (std::isdigit(valid[0]) || disallowedWords.find(valid) != disallowedWords.end()) 42 | { 43 | valid = '_' + valid; 44 | } 45 | } 46 | 47 | return valid; 48 | } 49 | 50 | std::string SimplifyEnumName(std::string&& name) 51 | { 52 | const auto index = name.find_last_of(':'); 53 | if (index == std::string::npos) 54 | { 55 | return name; 56 | } 57 | 58 | return name.substr(index + 1); 59 | } 60 | 61 | template 62 | std::string MakeUniqueCppNameImpl(const T& t) 63 | { 64 | std::string name; 65 | if (ObjectsStore().CountObjects(t.GetName()) > 1) 66 | { 67 | name += MakeValidName(t.GetOuter().GetName()) + "_"; 68 | } 69 | return name + MakeValidName(t.GetName()); 70 | } 71 | 72 | std::string MakeUniqueCppName(const UEConst& c) 73 | { 74 | return MakeUniqueCppNameImpl(c); 75 | } 76 | 77 | std::string MakeUniqueCppName(const UEEnum& e) 78 | { 79 | auto name = MakeUniqueCppNameImpl(e); 80 | if (!name.empty() && name[0] != 'E') 81 | { 82 | name = 'E' + name; 83 | } 84 | return name; 85 | } 86 | 87 | std::string MakeUniqueCppName(const UEStruct& ss) 88 | { 89 | std::string name; 90 | if (ObjectsStore().CountObjects(ss.GetName()) > 1) 91 | { 92 | name += MakeValidName(ss.GetOuter().GetNameCPP()) + "_"; 93 | } 94 | return name + MakeValidName(ss.GetNameCPP()); 95 | } 96 | -------------------------------------------------------------------------------- /Engine/NameValidator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class UEConst; 6 | class UEEnum; 7 | class UEStruct; 8 | 9 | /// 10 | /// Makes valid C++ name from the given name. 11 | /// 12 | /// The name to process. 13 | /// A valid C++ name. 14 | std::string MakeValidName(std::string&& name); 15 | 16 | std::string SimplifyEnumName(std::string&& name); 17 | 18 | std::string MakeUniqueCppName(const UEConst& c); 19 | std::string MakeUniqueCppName(const UEEnum& e); 20 | std::string MakeUniqueCppName(const UEStruct& ss); 21 | -------------------------------------------------------------------------------- /Engine/NamesStore.cpp: -------------------------------------------------------------------------------- 1 | #include "NamesStore.hpp" 2 | 3 | NamesIterator NamesStore::begin() 4 | { 5 | return NamesIterator(*this, 0); 6 | } 7 | 8 | NamesIterator NamesStore::begin() const 9 | { 10 | return NamesIterator(*this, 0); 11 | } 12 | 13 | NamesIterator NamesStore::end() 14 | { 15 | return NamesIterator(*this); 16 | } 17 | 18 | NamesIterator NamesStore::end() const 19 | { 20 | return NamesIterator(*this); 21 | } 22 | 23 | NamesIterator::NamesIterator(const NamesStore& _store) 24 | : store(_store), 25 | index(_store.GetNamesNum()) 26 | { 27 | } 28 | 29 | NamesIterator::NamesIterator(const NamesStore& _store, size_t _index) 30 | : store(_store), 31 | index(_index) 32 | { 33 | } 34 | 35 | void NamesIterator::swap(NamesIterator& other) noexcept 36 | { 37 | std::swap(index, other.index); 38 | } 39 | 40 | NamesIterator& NamesIterator::operator++() 41 | { 42 | for (++index; index < store.GetNamesNum(); ++index) 43 | { 44 | if (store.IsValid(index)) 45 | { 46 | break; 47 | } 48 | } 49 | return *this; 50 | } 51 | 52 | NamesIterator NamesIterator::operator++ (int) 53 | { 54 | auto tmp(*this); 55 | ++(*this); 56 | return tmp; 57 | } 58 | 59 | bool NamesIterator::operator==(const NamesIterator& rhs) const 60 | { 61 | return index == rhs.index; 62 | } 63 | 64 | bool NamesIterator::operator!=(const NamesIterator& rhs) const 65 | { 66 | return index != rhs.index; 67 | } 68 | 69 | UENameInfo NamesIterator::operator*() const 70 | { 71 | return { index, store.GetById(index) }; 72 | } 73 | 74 | UENameInfo NamesIterator::operator->() const 75 | { 76 | return { index, store.GetById(index) }; 77 | } -------------------------------------------------------------------------------- /Engine/NamesStore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "GenericTypes.hpp" 6 | 7 | class NamesIterator; 8 | 9 | class NamesStore 10 | { 11 | friend NamesIterator; 12 | 13 | public: 14 | 15 | /// 16 | /// Initializes this object. 17 | /// 18 | /// true if it succeeds, false if it fails. 19 | static bool Initialize(); 20 | 21 | /// Gets the address of the global names store. 22 | /// The address of the global names store. 23 | static void* GetAddress(); 24 | 25 | NamesIterator begin(); 26 | 27 | NamesIterator begin() const; 28 | 29 | NamesIterator end(); 30 | 31 | NamesIterator end() const; 32 | 33 | /// 34 | /// Gets the number of available names. 35 | /// 36 | /// The number of names. 37 | size_t GetNamesNum() const; 38 | 39 | /// 40 | /// Test if the given id is valid. 41 | /// 42 | /// The identifier. 43 | /// true if valid, false if not. 44 | bool IsValid(size_t id) const; 45 | 46 | /// 47 | /// Gets a name by id. 48 | /// 49 | /// The identifier. 50 | /// The name. 51 | std::string GetById(size_t id) const; 52 | }; 53 | 54 | struct UENameInfo 55 | { 56 | size_t Index; 57 | std::string Name; 58 | }; 59 | 60 | class NamesIterator : public std::iterator 61 | { 62 | const NamesStore& store; 63 | size_t index; 64 | 65 | public: 66 | NamesIterator(const NamesStore& store); 67 | 68 | explicit NamesIterator(const NamesStore& store, size_t index); 69 | 70 | void swap(NamesIterator& other) noexcept; 71 | 72 | NamesIterator& operator++(); 73 | 74 | NamesIterator operator++ (int); 75 | 76 | bool operator==(const NamesIterator& rhs) const; 77 | 78 | bool operator!=(const NamesIterator& rhs) const; 79 | 80 | UENameInfo operator*() const; 81 | 82 | UENameInfo operator->() const; 83 | }; 84 | -------------------------------------------------------------------------------- /Engine/ObjectsStore.cpp: -------------------------------------------------------------------------------- 1 | #include "ObjectsStore.hpp" 2 | #include 3 | 4 | ObjectsIterator ObjectsStore::begin() 5 | { 6 | return ObjectsIterator(*this, 0); 7 | } 8 | 9 | ObjectsIterator ObjectsStore::begin() const 10 | { 11 | return ObjectsIterator(*this, 0); 12 | } 13 | 14 | ObjectsIterator ObjectsStore::end() 15 | { 16 | return ObjectsIterator(*this); 17 | } 18 | 19 | ObjectsIterator ObjectsStore::end() const 20 | { 21 | return ObjectsIterator(*this); 22 | } 23 | 24 | UEClass ObjectsStore::FindClass(const std::string& name) const 25 | { 26 | for (auto obj : *this) 27 | { 28 | if (obj.GetFullName() == name) 29 | { 30 | return obj.Cast(); 31 | } 32 | } 33 | return UEClass(nullptr); 34 | } 35 | 36 | ObjectsIterator::ObjectsIterator(const ObjectsStore& _store) 37 | : store(_store), 38 | index(_store.GetObjectsNum()) 39 | { 40 | } 41 | 42 | ObjectsIterator::ObjectsIterator(const ObjectsStore& _store, size_t _index) 43 | : store(_store), 44 | index(_index), 45 | current(_store.GetById(_index)) 46 | { 47 | } 48 | 49 | ObjectsIterator::ObjectsIterator(const ObjectsIterator& other) 50 | : store(other.store), 51 | index(other.index), 52 | current(other.current) 53 | { 54 | } 55 | 56 | ObjectsIterator::ObjectsIterator(ObjectsIterator&& other) noexcept 57 | : store(other.store), 58 | index(other.index), 59 | current(other.current) 60 | { 61 | } 62 | 63 | ObjectsIterator& ObjectsIterator::operator=(const ObjectsIterator& rhs) 64 | { 65 | index = rhs.index; 66 | current = rhs.current; 67 | return *this; 68 | } 69 | 70 | void ObjectsIterator::swap(ObjectsIterator& other) noexcept 71 | { 72 | std::swap(index, other.index); 73 | std::swap(current, other.current); 74 | } 75 | 76 | ObjectsIterator& ObjectsIterator::operator++() 77 | { 78 | current = UEObject(); 79 | 80 | for (++index; index < store.GetObjectsNum(); ++index) 81 | { 82 | current = store.GetById(index); 83 | if (current.IsValid()) 84 | { 85 | break; 86 | } 87 | } 88 | return *this; 89 | } 90 | 91 | ObjectsIterator ObjectsIterator::operator++(int) 92 | { 93 | auto tmp(*this); 94 | ++(*this); 95 | return tmp; 96 | } 97 | 98 | bool ObjectsIterator::operator==(const ObjectsIterator& rhs) const 99 | { 100 | return index == rhs.index; 101 | } 102 | 103 | bool ObjectsIterator::operator!=(const ObjectsIterator& rhs) const 104 | { 105 | return index != rhs.index; 106 | } 107 | 108 | UEObject ObjectsIterator::operator*() const 109 | { 110 | assert(current.IsValid() && "ObjectsIterator::current is not valid!"); 111 | 112 | return current; 113 | } 114 | 115 | UEObject ObjectsIterator::operator->() const 116 | { 117 | return operator*(); 118 | } -------------------------------------------------------------------------------- /Engine/ObjectsStore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "GenericTypes.hpp" 6 | 7 | class ObjectsIterator; 8 | 9 | class ObjectsStore 10 | { 11 | public: 12 | 13 | /// 14 | /// Initializes this object. 15 | /// 16 | /// 17 | /// true if it succeeds, false if it fails. 18 | /// 19 | static bool Initialize(); 20 | 21 | /// Gets the address of the global objects store. 22 | /// The address of the global objects store. 23 | static void* GetAddress(); 24 | 25 | ObjectsIterator begin(); 26 | 27 | ObjectsIterator begin() const; 28 | 29 | ObjectsIterator end(); 30 | 31 | ObjectsIterator end() const; 32 | 33 | /// 34 | /// Gets the number of available objects. 35 | /// 36 | /// The number of objects. 37 | size_t GetObjectsNum() const; 38 | 39 | /// 40 | /// Gets the object by id. 41 | /// 42 | /// The identifier. 43 | /// The object. 44 | UEObject GetById(size_t id) const; 45 | 46 | /// 47 | /// Searches for the first class with the given name. 48 | /// 49 | /// The name of the class. 50 | /// The found class which is not valid if no class could be found. 51 | UEClass FindClass(const std::string& name) const; 52 | 53 | /// Count objects which have the same name and type. 54 | /// Type of the object. 55 | /// The name to search for. 56 | /// The number of objects which share a name. 57 | template 58 | size_t CountObjects(const std::string& name) const 59 | { 60 | static std::unordered_map cache; 61 | 62 | auto it = cache.find(name); 63 | if (it != std::end(cache)) 64 | { 65 | return it->second; 66 | } 67 | 68 | size_t count = 0; 69 | for (auto obj : *this) 70 | { 71 | if (obj.IsA() && obj.GetName() == name) 72 | { 73 | ++count; 74 | } 75 | } 76 | 77 | cache[name] = count; 78 | 79 | return count; 80 | } 81 | }; 82 | 83 | /// Holds information about an object. 84 | struct UEObjectInfo 85 | { 86 | /// Zero-based index of the object in the global objects store. 87 | size_t Index; 88 | 89 | /// The object. 90 | UEObject Object; 91 | }; 92 | 93 | /// An iterator for objects. 94 | class ObjectsIterator : public std::iterator 95 | { 96 | const ObjectsStore& store; 97 | size_t index; 98 | UEObject current; 99 | 100 | public: 101 | 102 | /// Constructor. 103 | /// The store to iterate. 104 | ObjectsIterator(const ObjectsStore& store); 105 | 106 | /// Constructor. 107 | /// The store to iterate. 108 | /// Zero-based start index. 109 | explicit ObjectsIterator(const ObjectsStore& store, size_t index); 110 | 111 | ObjectsIterator(const ObjectsIterator& other); 112 | ObjectsIterator(ObjectsIterator&& other) noexcept; 113 | 114 | ObjectsIterator& operator=(const ObjectsIterator& rhs); 115 | 116 | void swap(ObjectsIterator& other) noexcept; 117 | 118 | ObjectsIterator& operator++(); 119 | 120 | ObjectsIterator operator++ (int); 121 | 122 | bool operator==(const ObjectsIterator& rhs) const; 123 | 124 | bool operator!=(const ObjectsIterator& rhs) const; 125 | 126 | UEObject operator*() const; 127 | 128 | UEObject operator->() const; 129 | }; 130 | -------------------------------------------------------------------------------- /Engine/Package.cpp: -------------------------------------------------------------------------------- 1 | #include "Package.hpp" 2 | 3 | #include 4 | #include 5 | #include "tinyformat.h" 6 | #include "cpplinq.hpp" 7 | 8 | #include "IGenerator.hpp" 9 | #include "Logger.hpp" 10 | #include "NameValidator.hpp" 11 | #include "PatternFinder.hpp" 12 | #include "ObjectsStore.hpp" 13 | #include "PropertyFlags.hpp" 14 | #include "FunctionFlags.hpp" 15 | #include "PrintHelper.hpp" 16 | 17 | /// 18 | /// Compare two properties. 19 | /// 20 | /// The first property. 21 | /// The second property. 22 | /// true if the first property compares less, else false. 23 | bool ComparePropertyLess(const UEProperty& lhs, const UEProperty& rhs) 24 | { 25 | if (lhs.GetOffset() == rhs.GetOffset() 26 | && lhs.IsA() 27 | && rhs.IsA()) 28 | { 29 | return lhs.Cast() < rhs.Cast(); 30 | } 31 | 32 | return lhs.GetOffset() < rhs.GetOffset(); 33 | } 34 | 35 | Package::Package(const UEObject& _packageObj) 36 | : packageObj(_packageObj) 37 | { 38 | } 39 | 40 | void Package::Process(std::unordered_map& processedObjects) 41 | { 42 | for (auto obj : ObjectsStore()) 43 | { 44 | const auto package = obj.GetPackageObject(); 45 | if (packageObj == package) 46 | { 47 | if (obj.IsA()) 48 | { 49 | GenerateEnum(obj.Cast()); 50 | } 51 | else if (obj.IsA()) 52 | { 53 | GenerateConst(obj.Cast()); 54 | } 55 | else if (obj.IsA()) 56 | { 57 | GeneratePrerequisites(obj, processedObjects); 58 | } 59 | else if (obj.IsA()) 60 | { 61 | GeneratePrerequisites(obj, processedObjects); 62 | } 63 | } 64 | } 65 | } 66 | 67 | bool Package::Save(const fs::path& path) const 68 | { 69 | extern IGenerator* generator; 70 | 71 | using namespace cpplinq; 72 | 73 | //check if package is empty (no enums, structs or classes without members) 74 | if (generator->ShouldGenerateEmptyFiles() 75 | || (from(enums) >> where([](auto&& e) { return !e.Values.empty(); }) >> any() 76 | || from(scriptStructs) >> where([](auto&& s) { return !s.Members.empty() || !s.PredefinedMethods.empty(); }) >> any() 77 | || from(classes) >> where([](auto&& c) {return !c.Members.empty() || !c.PredefinedMethods.empty() || !c.Methods.empty(); }) >> any() 78 | ) 79 | ) 80 | { 81 | SaveStructs(path); 82 | SaveClasses(path); 83 | SaveFunctions(path); 84 | 85 | return true; 86 | } 87 | 88 | return false; 89 | } 90 | 91 | bool Package::AddDependency(const UEObject& package) const 92 | { 93 | if (package != packageObj) 94 | { 95 | dependencies.insert(package); 96 | 97 | return true; 98 | } 99 | return false; 100 | } 101 | 102 | void Package::GeneratePrerequisites(const UEObject& obj, std::unordered_map& processedObjects) 103 | { 104 | if (!obj.IsValid()) 105 | { 106 | return; 107 | } 108 | 109 | const auto isClass = obj.IsA(); 110 | const auto isScriptStruct = obj.IsA(); 111 | if (!isClass && !isScriptStruct) 112 | { 113 | return; 114 | } 115 | 116 | const auto name = obj.GetName(); 117 | if (name.find("Default__") != std::string::npos 118 | || name.find("") != std::string::npos 119 | || name.find("PLACEHOLDER-CLASS") != std::string::npos) 120 | { 121 | return; 122 | } 123 | 124 | processedObjects[obj] |= false; 125 | 126 | auto classPackage = obj.GetPackageObject(); 127 | if (!classPackage.IsValid()) 128 | { 129 | return; 130 | } 131 | 132 | if (AddDependency(classPackage)) 133 | { 134 | return; 135 | } 136 | 137 | if (processedObjects[obj] == false) 138 | { 139 | processedObjects[obj] = true; 140 | 141 | if (!isScriptStruct) 142 | { 143 | auto outer = obj.GetOuter(); 144 | if (outer.IsValid() && outer != obj) 145 | { 146 | GeneratePrerequisites(outer, processedObjects); 147 | } 148 | } 149 | 150 | auto structObj = obj.Cast(); 151 | 152 | auto super = structObj.GetSuper(); 153 | if (super.IsValid() && super != obj) 154 | { 155 | GeneratePrerequisites(super, processedObjects); 156 | } 157 | 158 | GenerateMemberPrerequisites(structObj.GetChildren().Cast(), processedObjects); 159 | 160 | if (isClass) 161 | { 162 | GenerateClass(obj.Cast()); 163 | } 164 | else 165 | { 166 | GenerateScriptStruct(obj.Cast()); 167 | } 168 | } 169 | } 170 | 171 | void Package::GenerateMemberPrerequisites(const UEProperty& first, std::unordered_map& processedObjects) 172 | { 173 | using namespace cpplinq; 174 | 175 | for (auto prop = first; prop.IsValid(); prop = prop.GetNext().Cast()) 176 | { 177 | const auto info = prop.GetInfo(); 178 | if (info.Type == UEProperty::PropertyType::Primitive) 179 | { 180 | if (prop.IsA()) 181 | { 182 | auto byteProperty = prop.Cast(); 183 | if (byteProperty.IsEnum()) 184 | { 185 | AddDependency(byteProperty.GetEnum().GetPackageObject()); 186 | } 187 | } 188 | else if (prop.IsA()) 189 | { 190 | auto enumProperty = prop.Cast(); 191 | AddDependency(enumProperty.GetEnum().GetPackageObject()); 192 | } 193 | } 194 | else if (info.Type == UEProperty::PropertyType::CustomStruct) 195 | { 196 | GeneratePrerequisites(prop.Cast().GetStruct(), processedObjects); 197 | } 198 | else if (info.Type == UEProperty::PropertyType::Container) 199 | { 200 | std::vector innerProperties; 201 | 202 | if (prop.IsA()) 203 | { 204 | innerProperties.push_back(prop.Cast().GetInner()); 205 | } 206 | else if (prop.IsA()) 207 | { 208 | auto mapProp = prop.Cast(); 209 | innerProperties.push_back(mapProp.GetKeyProperty()); 210 | innerProperties.push_back(mapProp.GetValueProperty()); 211 | } 212 | 213 | for (auto innerProp : from(innerProperties) 214 | >> where([](auto&& p) { return p.GetInfo().Type == UEProperty::PropertyType::CustomStruct; }) 215 | >> experimental::container()) 216 | { 217 | GeneratePrerequisites(innerProp.Cast().GetStruct(), processedObjects); 218 | } 219 | } 220 | else if (prop.IsA()) 221 | { 222 | auto function = prop.Cast(); 223 | 224 | GenerateMemberPrerequisites(function.GetChildren().Cast(), processedObjects); 225 | } 226 | } 227 | } 228 | 229 | void Package::GenerateScriptStruct(const UEScriptStruct& scriptStructObj) 230 | { 231 | extern IGenerator* generator; 232 | 233 | ScriptStruct ss; 234 | ss.Name = scriptStructObj.GetName(); 235 | ss.FullName = scriptStructObj.GetFullName(); 236 | 237 | Logger::Log("ScriptStruct: %-100s - instance: 0x%P", ss.Name, scriptStructObj.GetAddress()); 238 | 239 | ss.NameCpp = MakeValidName(scriptStructObj.GetNameCPP()); 240 | ss.NameCppFull = "struct "; 241 | 242 | //some classes need special alignment 243 | const auto alignment = generator->GetClassAlignas(ss.FullName); 244 | if (alignment != 0) 245 | { 246 | ss.NameCppFull += tfm::format("alignas(%d) ", alignment); 247 | } 248 | 249 | ss.NameCppFull += MakeUniqueCppName(scriptStructObj); 250 | 251 | ss.Size = scriptStructObj.GetPropertySize(); 252 | ss.InheritedSize = 0; 253 | 254 | size_t offset = 0; 255 | 256 | auto super = scriptStructObj.GetSuper(); 257 | if (super.IsValid() && super != scriptStructObj) 258 | { 259 | ss.InheritedSize = offset = super.GetPropertySize(); 260 | 261 | ss.NameCppFull += " : public " + MakeUniqueCppName(super.Cast()); 262 | } 263 | 264 | std::vector properties; 265 | for (auto prop = scriptStructObj.GetChildren().Cast(); prop.IsValid(); prop = prop.GetNext().Cast()) 266 | { 267 | if (prop.GetElementSize() > 0 268 | && !prop.IsA() 269 | && !prop.IsA() 270 | && !prop.IsA() 271 | && !prop.IsA() 272 | ) 273 | { 274 | properties.push_back(prop); 275 | } 276 | } 277 | std::sort(std::begin(properties), std::end(properties), ComparePropertyLess); 278 | 279 | GenerateMembers(scriptStructObj, offset, properties, ss.Members); 280 | 281 | generator->GetPredefinedClassMethods(scriptStructObj.GetFullName(), ss.PredefinedMethods); 282 | 283 | scriptStructs.emplace_back(std::move(ss)); 284 | } 285 | 286 | void Package::GenerateEnum(const UEEnum& enumObj) 287 | { 288 | Enum e; 289 | e.Name = MakeUniqueCppName(enumObj); 290 | 291 | if (e.Name.find("Default__") != std::string::npos 292 | || e.Name.find("PLACEHOLDER-CLASS") != std::string::npos) 293 | { 294 | return; 295 | } 296 | 297 | e.FullName = enumObj.GetFullName(); 298 | 299 | std::unordered_map conflicts; 300 | for (auto&& s : enumObj.GetNames()) 301 | { 302 | const auto clean = MakeValidName(std::move(s)); 303 | 304 | const auto it = conflicts.find(clean); 305 | if (it == std::end(conflicts)) 306 | { 307 | e.Values.push_back(clean); 308 | conflicts[clean] = 1; 309 | } 310 | else 311 | { 312 | e.Values.push_back(clean + tfm::format("%02d", it->second)); 313 | conflicts[clean]++; 314 | } 315 | } 316 | 317 | enums.emplace_back(std::move(e)); 318 | } 319 | 320 | void Package::GenerateConst(const UEConst& constObj) 321 | { 322 | //auto name = MakeValidName(constObj.GetName()); 323 | auto name = MakeUniqueCppName(constObj); 324 | 325 | if (name.find("Default__") != std::string::npos 326 | || name.find("PLACEHOLDER-CLASS") != std::string::npos) 327 | { 328 | return; 329 | } 330 | 331 | constants[name] = constObj.GetValue(); 332 | } 333 | 334 | void Package::GenerateClass(const UEClass& classObj) 335 | { 336 | extern IGenerator* generator; 337 | 338 | Class c; 339 | c.Name = classObj.GetName(); 340 | c.FullName = classObj.GetFullName(); 341 | 342 | Logger::Log("Class: %-100s - instance: 0x%P", c.Name, classObj.GetAddress()); 343 | 344 | c.NameCpp = MakeValidName(classObj.GetNameCPP()); 345 | c.NameCppFull = "class " + c.NameCpp; 346 | 347 | c.Size = classObj.GetPropertySize(); 348 | c.InheritedSize = 0; 349 | 350 | size_t offset = 0; 351 | 352 | auto super = classObj.GetSuper(); 353 | if (super.IsValid() && super != classObj) 354 | { 355 | c.InheritedSize = offset = super.GetPropertySize(); 356 | 357 | c.NameCppFull += " : public " + MakeValidName(super.GetNameCPP()); 358 | } 359 | 360 | std::vector predefinedStaticMembers; 361 | if (generator->GetPredefinedClassStaticMembers(c.FullName, predefinedStaticMembers)) 362 | { 363 | for (auto&& prop : predefinedStaticMembers) 364 | { 365 | Member p; 366 | p.Offset = 0; 367 | p.Size = 0; 368 | p.Name = prop.Name; 369 | p.Type = "static " + prop.Type; 370 | c.Members.push_back(std::move(p)); 371 | } 372 | } 373 | 374 | std::vector predefinedMembers; 375 | if (generator->GetPredefinedClassMembers(c.FullName, predefinedMembers)) 376 | { 377 | for (auto&& prop : predefinedMembers) 378 | { 379 | Member p; 380 | p.Offset = 0; 381 | p.Size = 0; 382 | p.Name = prop.Name; 383 | p.Type = prop.Type; 384 | p.Comment = "NOT AUTO-GENERATED PROPERTY"; 385 | c.Members.push_back(std::move(p)); 386 | } 387 | } 388 | else 389 | { 390 | std::vector properties; 391 | for (auto prop = classObj.GetChildren().Cast(); prop.IsValid(); prop = prop.GetNext().Cast()) 392 | { 393 | if (prop.GetElementSize() > 0 394 | && !prop.IsA() 395 | && !prop.IsA() 396 | && !prop.IsA() 397 | && !prop.IsA() 398 | && (!super.IsValid() 399 | || (super != classObj 400 | && prop.GetOffset() >= super.GetPropertySize() 401 | ) 402 | ) 403 | ) 404 | { 405 | properties.push_back(prop); 406 | } 407 | } 408 | std::sort(std::begin(properties), std::end(properties), ComparePropertyLess); 409 | 410 | GenerateMembers(classObj, offset, properties, c.Members); 411 | } 412 | 413 | generator->GetPredefinedClassMethods(c.FullName, c.PredefinedMethods); 414 | 415 | if (generator->ShouldUseStrings()) 416 | { 417 | c.PredefinedMethods.push_back(IGenerator::PredefinedMethod::Inline(tfm::format(R"( static UClass* StaticClass() 418 | { 419 | static auto ptr = UObject::FindClass(%s); 420 | return ptr; 421 | })", generator->ShouldXorStrings() ? tfm::format("_xor_(\"%s\")", c.FullName) : tfm::format("\"%s\"", c.FullName)))); 422 | } 423 | else 424 | { 425 | c.PredefinedMethods.push_back(IGenerator::PredefinedMethod::Inline(tfm::format(R"( static UClass* StaticClass() 426 | { 427 | static auto ptr = UObject::GetObjectCasted(%d); 428 | return ptr; 429 | })", classObj.GetIndex()))); 430 | } 431 | 432 | GenerateMethods(classObj, c.Methods); 433 | 434 | //search virtual functions 435 | IGenerator::VirtualFunctionPatterns patterns; 436 | if (generator->GetVirtualFunctionPatterns(c.FullName, patterns)) 437 | { 438 | const auto vtable = *reinterpret_cast(classObj.GetAddress()); 439 | 440 | size_t methodCount = 0; 441 | while (true) 442 | { 443 | MEMORY_BASIC_INFORMATION mbi; 444 | auto res = VirtualQuery(reinterpret_cast(vtable[methodCount]), &mbi, sizeof(mbi)); 445 | if (res == 0 || (mbi.Protect != PAGE_EXECUTE_READWRITE && mbi.Protect != PAGE_EXECUTE_READ)) 446 | { 447 | break; 448 | } 449 | ++methodCount; 450 | } 451 | 452 | for (auto&& pattern : patterns) 453 | { 454 | for (auto i = 0u; i < methodCount; ++i) 455 | { 456 | if (vtable[i] != 0 && FindPattern(vtable[i], std::get<2>(pattern), reinterpret_cast(std::get<0>(pattern)), std::get<1>(pattern)) != -1) 457 | { 458 | c.PredefinedMethods.push_back(IGenerator::PredefinedMethod::Inline(tfm::format(std::get<3>(pattern), i))); 459 | break; 460 | } 461 | } 462 | } 463 | } 464 | 465 | classes.emplace_back(std::move(c)); 466 | } 467 | 468 | Package::Member Package::CreatePadding(size_t id, size_t offset, size_t size, std::string reason) 469 | { 470 | Member ss; 471 | ss.Name = tfm::format("UnknownData%02d[0x%X]", id, size); 472 | ss.Type = "unsigned char"; 473 | ss.Offset = offset; 474 | ss.Size = size; 475 | ss.Comment = std::move(reason); 476 | return ss; 477 | } 478 | 479 | Package::Member Package::CreateBitfieldPadding(size_t id, size_t offset, std::string type, size_t bits) 480 | { 481 | Member ss; 482 | ss.Name = tfm::format("UnknownData%02d : %d", id, bits); 483 | ss.Type = std::move(type); 484 | ss.Offset = offset; 485 | ss.Size = 1; 486 | return ss; 487 | } 488 | 489 | //void Package::GenerateMembers(const UEStruct& structObj, size_t offset, const std::vector& properties, std::vector& members) const 490 | //{ 491 | // extern IGenerator* generator; 492 | // 493 | // unsigned long lastBit; 494 | // std::unordered_map uniqueMemberNames; 495 | // size_t unknownDataCounter = 0; 496 | // 497 | // for (auto& prop : properties) 498 | // { 499 | // bool bEmplaced = false; 500 | // if (offset < prop.GetOffset()) 501 | // { 502 | // auto size = prop.GetOffset() - offset; 503 | // if (size >= generator->GetGlobalMemberAlignment()) 504 | // { 505 | // members.emplace_back(Member::Unknown(unknownDataCounter++, offset, size, "MISSED OFFSET")); 506 | // bEmplaced = true; 507 | // } 508 | // } 509 | // 510 | // auto info = prop.GetInfo(); 511 | // if (info.Type != UEProperty::PropertyType::Unknown) 512 | // { 513 | // Member sp; 514 | // sp.Offset = prop.GetOffset(); 515 | // sp.Size = info.Size; 516 | // 517 | // sp.Type = info.CppType; 518 | // sp.Name = MakeValidName(prop.GetName()); 519 | // 520 | // auto it = uniqueMemberNames.find(sp.Name); 521 | // if (it == std::end(uniqueMemberNames)) 522 | // { 523 | // uniqueMemberNames[sp.Name] = 1; 524 | // } 525 | // else 526 | // { 527 | // ++uniqueMemberNames[sp.Name]; 528 | // sp.Name += tfm::format("%02d", it->second); 529 | // } 530 | // 531 | // if (prop.GetArrayDim() > 1) 532 | // { 533 | // sp.Name += tfm::format("[0x%X]", prop.GetArrayDim()); 534 | // } 535 | // 536 | // 537 | // sp.Flags = static_cast(prop.GetPropertyFlags()); 538 | // sp.FlagsString = StringifyFlags(prop.GetPropertyFlags()); 539 | // 540 | // if (prop.IsA()) //seems to be a full byte 541 | // { 542 | // int n_pad = sp.Offset - offset; 543 | // if (prop.GetBitMask() == 0xFF01) { 544 | // //add missing bytes 545 | // if (!bEmplaced && n_pad > 0) { 546 | // members.emplace_back(Member::Unknown(unknownDataCounter++, offset, n_pad, "MISSED OFFSET")); 547 | // } 548 | // } 549 | // else { 550 | // char szBit[124]; 551 | // unsigned long BitMask = prop.GetBitMask(); 552 | // 553 | // bool bSameByte = offset != sp.Offset; 554 | // //check if we are at the same byte, if not check if we added 8 last time. 555 | // if (!bSameByte && BitMask != 0x0101) { 556 | // 557 | // auto sp2 = sp; 558 | // if (lastBit != 0x8080) { 559 | // sp2.Offset -= 1; 560 | // //fill previus byte 561 | // 562 | // while (lastBit < 0x8080) { 563 | // sp2.Type = info.CppType; 564 | // auto newBit = lastBit ? lastBit * 2 : 0x0101; 565 | // sprintf_s(szBit, 124, "%04X", newBit); 566 | // sp2.FlagsString += "MANUAL_ADD_BIT " + std::string(szBit); 567 | // 568 | // sprintf_s(szBit, 124, "%04X_%04X", sp2.Offset, newBit); //PrevBit 569 | // sp2.Name = "bUnknown" + std::string(szBit) + " : 1"; 570 | // members.emplace_back(std::move(sp2)); 571 | // 572 | // lastBit = newBit; 573 | // //add 574 | // } 575 | // 576 | // sp2.Offset++; 577 | // } 578 | // lastBit = 0; 579 | // //get last bitmask and fill it up 580 | // while (lastBit < 0x8080) { 581 | // sp2.Type = info.CppType; 582 | // auto newBit = lastBit ? lastBit * 2 : 0x0101; 583 | // sprintf_s(szBit, 124, "%04X", newBit); 584 | // sp2.FlagsString += "MANUAL_ADD_BIT " + std::string(szBit); 585 | // 586 | // sprintf_s(szBit, 124, "%04X_%04X", sp2.Offset, newBit); //PrevBit 587 | // sp2.Name = "bUnknown" + std::string(szBit) + " : 1"; 588 | // members.emplace_back(std::move(sp2)); 589 | // 590 | // lastBit = newBit; 591 | // break; 592 | // //add 593 | // } 594 | // sprintf_s(szBit, 124, "%04X", BitMask); 595 | // lastBit = BitMask; 596 | // sp.Name += " : 1"; 597 | // sp.FlagsString += " BITFIELD: " + std::string(szBit); 598 | // } 599 | // else { 600 | // //check if missing any bit since last one 601 | // sprintf_s(szBit, 124, "%04X", BitMask); 602 | // if (BitMask == 0x0101) { 603 | // 604 | // //check if last is aligned.. 605 | // } 606 | // else if (lastBit * 2 != BitMask) { //is 0x0101 607 | // //add one bit 608 | // sprintf_s(szBit, 124, "%04X", BitMask / 2); //PrevBit 609 | // auto sp2 = sp; 610 | // sp2.FlagsString += "MANUAL_ADD_BIT " + std::string(szBit); 611 | // 612 | // sprintf_s(szBit, 124, "%04X_%04X", sp.Offset, BitMask / 2); //PrevBit 613 | // sp2.Name = "bUnknown" + std::string(szBit) + " : 1"; 614 | // members.emplace_back(std::move(sp2)); 615 | // //if(BitMask ) 616 | // //check if last bitmask = bitmask/2 617 | // } 618 | // sprintf_s(szBit, 124, "%04X", BitMask); 619 | // lastBit = BitMask; 620 | // sp.Name += " : 1"; 621 | // sp.FlagsString += " BITFIELD: " + std::string(szBit); 622 | // } 623 | // } 624 | // } 625 | // else { 626 | // lastBit = 0x8080; 627 | // } 628 | // 629 | // members.emplace_back(std::move(sp)); 630 | // 631 | // auto sizeMismatch = static_cast(prop.GetElementSize() * prop.GetArrayDim()) - static_cast(info.Size * prop.GetArrayDim()); 632 | // if (sizeMismatch > 0) 633 | // { 634 | // members.emplace_back(Member::Unknown(unknownDataCounter++, offset, sizeMismatch, "FIX WRONG TYPE SIZE OF PREVIUS PROPERTY")); 635 | // } 636 | // } 637 | // else 638 | // { 639 | // auto info2 = prop.GetInfo(); 640 | // auto size = prop.GetElementSize() * prop.GetArrayDim(); 641 | // members.emplace_back(Member::Unknown(unknownDataCounter++, offset, size, "UNKNOWN PROPERTY: " + prop.GetFullName())); 642 | // } 643 | // 644 | // offset = prop.GetOffset() + (prop.GetElementSize() * prop.GetArrayDim()); 645 | // } 646 | // 647 | // if (offset < structObj.GetPropertySize()) 648 | // { 649 | // auto size = structObj.GetPropertySize() - offset; 650 | // if (size >= generator->GetGlobalMemberAlignment()) 651 | // { 652 | // members.emplace_back(Member::Unknown(unknownDataCounter++, offset, size, "MISSED OFFSET")); 653 | // } 654 | // } 655 | //} 656 | 657 | void Package::GenerateMembers(const UEStruct& structObj, size_t offset, const std::vector& properties, std::vector& members) const 658 | { 659 | extern IGenerator* generator; 660 | 661 | std::unordered_map uniqueMemberNames; 662 | size_t unknownDataCounter = 0; 663 | UEBoolProperty previousBitfieldProperty; 664 | 665 | for (auto&& prop : properties) 666 | { 667 | if (offset < prop.GetOffset()) 668 | { 669 | previousBitfieldProperty = UEBoolProperty(); 670 | 671 | const auto size = prop.GetOffset() - offset; 672 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, size, "MISSED OFFSET")); 673 | } 674 | 675 | const auto info = prop.GetInfo(); 676 | if (info.Type != UEProperty::PropertyType::Unknown) 677 | { 678 | Member sp; 679 | sp.Offset = prop.GetOffset(); 680 | sp.Size = info.Size; 681 | 682 | sp.Type = info.CppType; 683 | sp.Name = MakeValidName(prop.GetName()); 684 | 685 | const auto it = uniqueMemberNames.find(sp.Name); 686 | if (it == std::end(uniqueMemberNames)) 687 | { 688 | uniqueMemberNames[sp.Name] = 1; 689 | } 690 | else 691 | { 692 | ++uniqueMemberNames[sp.Name]; 693 | sp.Name += tfm::format("%02d", it->second); 694 | } 695 | 696 | if (prop.GetArrayDim() > 1) 697 | { 698 | sp.Name += tfm::format("[0x%X]", prop.GetArrayDim()); 699 | } 700 | 701 | if (prop.IsA() && prop.Cast().IsBitfield()) 702 | { 703 | auto boolProp = prop.Cast(); 704 | 705 | const auto missingBits = boolProp.GetMissingBitsCount(previousBitfieldProperty); 706 | if (missingBits[1] != -1) 707 | { 708 | if (missingBits[0] > 0) 709 | { 710 | members.emplace_back(CreateBitfieldPadding(unknownDataCounter++, previousBitfieldProperty.GetOffset(), info.CppType, missingBits[0])); 711 | } 712 | if (missingBits[1] > 0) 713 | { 714 | members.emplace_back(CreateBitfieldPadding(unknownDataCounter++, sp.Offset, info.CppType, missingBits[1])); 715 | } 716 | } 717 | else if(missingBits[0] > 0) 718 | { 719 | members.emplace_back(CreateBitfieldPadding(unknownDataCounter++, sp.Offset, info.CppType, missingBits[0])); 720 | } 721 | 722 | previousBitfieldProperty = boolProp; 723 | 724 | sp.Name += " : 1"; 725 | } 726 | else 727 | { 728 | previousBitfieldProperty = UEBoolProperty(); 729 | } 730 | 731 | sp.Flags = static_cast(prop.GetPropertyFlags()); 732 | sp.FlagsString = StringifyFlags(prop.GetPropertyFlags()); 733 | 734 | members.emplace_back(std::move(sp)); 735 | 736 | const auto sizeMismatch = static_cast(prop.GetElementSize() * prop.GetArrayDim()) - static_cast(info.Size * prop.GetArrayDim()); 737 | if (sizeMismatch > 0) 738 | { 739 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, sizeMismatch, "FIX WRONG TYPE SIZE OF PREVIOUS PROPERTY")); 740 | } 741 | } 742 | else 743 | { 744 | const auto size = prop.GetElementSize() * prop.GetArrayDim(); 745 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, size, "UNKNOWN PROPERTY: " + prop.GetFullName())); 746 | } 747 | 748 | offset = prop.GetOffset() + prop.GetElementSize() * prop.GetArrayDim(); 749 | } 750 | 751 | if (offset < structObj.GetPropertySize()) 752 | { 753 | const auto size = structObj.GetPropertySize() - offset; 754 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, size, "MISSED OFFSET")); 755 | } 756 | } 757 | 758 | void Package::GenerateMethods(const UEClass& classObj, std::vector& methods) const 759 | { 760 | extern IGenerator* generator; 761 | 762 | //some classes (AnimBlueprintGenerated...) have multiple members with the same name, so filter them out 763 | std::unordered_set uniqueMethods; 764 | 765 | for (auto prop = classObj.GetChildren().Cast(); prop.IsValid(); prop = prop.GetNext().Cast()) 766 | { 767 | if (prop.IsA()) 768 | { 769 | auto function = prop.Cast(); 770 | 771 | Method m; 772 | m.Index = function.GetIndex(); 773 | m.FullName = function.GetFullName(); 774 | m.Name = MakeValidName(function.GetName()); 775 | 776 | if (uniqueMethods.find(m.FullName) != std::end(uniqueMethods)) 777 | { 778 | continue; 779 | } 780 | uniqueMethods.insert(m.FullName); 781 | 782 | m.IsNative = function.GetFunctionFlags() & UEFunctionFlags::Native; 783 | m.IsStatic = function.GetFunctionFlags() & UEFunctionFlags::Static; 784 | m.FlagsString = StringifyFlags(function.GetFunctionFlags()); 785 | 786 | std::vector> parameters; 787 | 788 | std::unordered_map unique; 789 | for (auto param = function.GetChildren().Cast(); param.IsValid(); param = param.GetNext().Cast()) 790 | { 791 | if (param.GetElementSize() == 0) 792 | { 793 | continue; 794 | } 795 | 796 | const auto info = param.GetInfo(); 797 | if (info.Type != UEProperty::PropertyType::Unknown) 798 | { 799 | using Type = Method::Parameter::Type; 800 | 801 | Method::Parameter p; 802 | 803 | if (!Method::Parameter::MakeType(param.GetPropertyFlags(), p.ParamType)) 804 | { 805 | //child isn't a parameter 806 | continue; 807 | } 808 | 809 | p.PassByReference = false; 810 | p.Name = MakeValidName(param.GetName()); 811 | 812 | const auto it = unique.find(p.Name); 813 | if (it == std::end(unique)) 814 | { 815 | unique[p.Name] = 1; 816 | } 817 | else 818 | { 819 | ++unique[p.Name]; 820 | 821 | p.Name += tfm::format("%02d", it->second); 822 | } 823 | 824 | p.FlagsString = StringifyFlags(param.GetPropertyFlags()); 825 | 826 | p.CppType = info.CppType; 827 | if (param.IsA()) 828 | { 829 | p.CppType = generator->GetOverrideType("bool"); 830 | } 831 | switch (p.ParamType) 832 | { 833 | case Type::Default: 834 | if (prop.GetArrayDim() > 1) 835 | { 836 | p.CppType = p.CppType + "*"; 837 | } 838 | else if (info.CanBeReference) 839 | { 840 | p.PassByReference = true; 841 | } 842 | break; 843 | } 844 | 845 | parameters.emplace_back(std::make_pair(prop, std::move(p))); 846 | } 847 | } 848 | 849 | std::sort(std::begin(parameters), std::end(parameters), [](auto&& lhs, auto&& rhs) { return ComparePropertyLess(lhs.first, rhs.first); }); 850 | 851 | for (auto& param : parameters) 852 | { 853 | m.Parameters.emplace_back(std::move(param.second)); 854 | } 855 | 856 | methods.emplace_back(std::move(m)); 857 | } 858 | } 859 | } 860 | 861 | void Package::SaveStructs(const fs::path& path) const 862 | { 863 | extern IGenerator* generator; 864 | 865 | using namespace cpplinq; 866 | 867 | std::ofstream os(path / GenerateFileName(FileContentType::Structs, *this)); 868 | 869 | std::vector includes{ { tfm::format("%s_Basic.hpp", generator->GetGameNameShort()) } }; 870 | 871 | auto dependencyNames = from(this->dependencies) 872 | >> select([](auto&& p) { return GenerateFileName(FileContentType::Classes, Package(p)); }) 873 | >> experimental::container(); 874 | 875 | includes.insert(includes.end(), std::begin(dependencyNames), std::end(dependencyNames)); 876 | 877 | PrintFileHeader(os, includes, true); 878 | 879 | if (!constants.empty()) 880 | { 881 | PrintSectionHeader(os, "Constants"); 882 | for (auto&& c : constants) { PrintConstant(os, c); } 883 | 884 | os << "\n"; 885 | } 886 | 887 | if (!enums.empty()) 888 | { 889 | PrintSectionHeader(os, "Enums"); 890 | for (auto&& e : enums) { PrintEnum(os, e); os << "\n"; } 891 | 892 | os << "\n"; 893 | } 894 | 895 | if (!scriptStructs.empty()) 896 | { 897 | PrintSectionHeader(os, "Script Structs"); 898 | for (auto&& s : scriptStructs) { PrintStruct(os, s); os << "\n"; } 899 | } 900 | 901 | PrintFileFooter(os); 902 | } 903 | 904 | void Package::SaveClasses(const fs::path& path) const 905 | { 906 | extern IGenerator* generator; 907 | 908 | std::ofstream os(path / GenerateFileName(FileContentType::Classes, *this)); 909 | 910 | PrintFileHeader(os, { GenerateFileName(FileContentType::Structs, *this) }, true); 911 | 912 | if (!classes.empty()) 913 | { 914 | PrintSectionHeader(os, "Classes"); 915 | for (auto&& c : classes) { PrintClass(os, c); os << "\n"; } 916 | } 917 | 918 | PrintFileFooter(os); 919 | } 920 | 921 | void Package::SaveFunctions(const fs::path& path) const 922 | { 923 | extern IGenerator* generator; 924 | 925 | if (generator->ShouldGenerateFunctionParametersFile()) 926 | { 927 | SaveFunctionParameters(path); 928 | } 929 | 930 | std::ofstream os(path / GenerateFileName(FileContentType::Functions, *this)); 931 | 932 | PrintFileHeader(os, { GenerateFileName(FileContentType::FunctionParameters, *this) }, false); 933 | 934 | PrintSectionHeader(os, "Functions"); 935 | 936 | for (auto&& s : scriptStructs) 937 | { 938 | for (auto&& m : s.PredefinedMethods) 939 | { 940 | if (m.MethodType != IGenerator::PredefinedMethod::Type::Inline) 941 | { 942 | os << m.Body << "\n\n"; 943 | } 944 | } 945 | } 946 | 947 | for (auto&& c : classes) 948 | { 949 | for (auto&& m : c.PredefinedMethods) 950 | { 951 | if (m.MethodType != IGenerator::PredefinedMethod::Type::Inline) 952 | { 953 | os << m.Body << "\n\n"; 954 | } 955 | } 956 | 957 | for (auto&& m : c.Methods) 958 | { 959 | //Method Info 960 | os << "// " << m.FullName << "\n" 961 | << "// (" << m.FlagsString << ")\n"; 962 | if (!m.Parameters.empty()) 963 | { 964 | os << "// Parameters:\n"; 965 | for (auto&& param : m.Parameters) 966 | { 967 | tfm::format(os, "// %-30s %-30s (%s)\n", param.CppType, param.Name, param.FlagsString); 968 | } 969 | } 970 | 971 | os << "\n"; 972 | os << BuildMethodSignature(m, c, false) << "\n"; 973 | os << BuildMethodBody(c, m) << "\n\n"; 974 | } 975 | } 976 | 977 | PrintFileFooter(os); 978 | } 979 | 980 | void Package::SaveFunctionParameters(const fs::path& path) const 981 | { 982 | using namespace cpplinq; 983 | 984 | std::ofstream os(path / GenerateFileName(FileContentType::FunctionParameters, *this)); 985 | 986 | PrintFileHeader(os, { GenerateFileName(FileContentType::Classes, *this) }, true); 987 | 988 | PrintSectionHeader(os, "Parameters"); 989 | 990 | for (auto&& c : classes) 991 | { 992 | for (auto&& m : c.Methods) 993 | { 994 | os << "// " << m.FullName << "\n"; 995 | tfm::format(os, "struct %s_%s_Params\n{\n", c.NameCpp, m.Name); 996 | for (auto&& param : m.Parameters) 997 | { 998 | tfm::format(os, "\t%-50s %-58s// (%s)\n", param.CppType, param.Name + ";", param.FlagsString); 999 | } 1000 | os << "};\n\n"; 1001 | } 1002 | } 1003 | 1004 | PrintFileFooter(os); 1005 | } 1006 | 1007 | void Package::PrintConstant(std::ostream& os, const std::pair& c) const 1008 | { 1009 | tfm::format(os, "#define CONST_%-50s %s\n", c.first, c.second); 1010 | } 1011 | 1012 | void Package::PrintEnum(std::ostream& os, const Enum& e) const 1013 | { 1014 | using namespace cpplinq; 1015 | 1016 | os << "// " << e.FullName << "\nenum class " << e.Name << " : uint8_t\n{\n"; 1017 | os << (from(e.Values) 1018 | >> select([](auto&& name, auto&& i) { return tfm::format("\t%-30s = %d", name, i); }) 1019 | >> concatenate(",\n")) 1020 | << "\n};\n\n"; 1021 | } 1022 | 1023 | void Package::PrintStruct(std::ostream& os, const ScriptStruct& ss) const 1024 | { 1025 | using namespace cpplinq; 1026 | 1027 | os << "// " << ss.FullName << "\n// "; 1028 | if (ss.InheritedSize) 1029 | { 1030 | os << tfm::format("0x%04X (0x%04X - 0x%04X)\n", ss.Size - ss.InheritedSize, ss.Size, ss.InheritedSize); 1031 | } 1032 | else 1033 | { 1034 | os << tfm::format("0x%04X\n", ss.Size); 1035 | } 1036 | 1037 | os << ss.NameCppFull << "\n{\n"; 1038 | 1039 | //Member 1040 | os << (from(ss.Members) 1041 | >> select([](auto&& m) { 1042 | return tfm::format("\t%-50s %-58s// 0x%04X(0x%04X)", m.Type, m.Name + ";", m.Offset, m.Size) 1043 | + (!m.Comment.empty() ? " " + m.Comment : "") 1044 | + (!m.FlagsString.empty() ? " (" + m.FlagsString + ")" : ""); 1045 | }) 1046 | >> concatenate("\n")) 1047 | << "\n"; 1048 | 1049 | //Predefined Methods 1050 | if (!ss.PredefinedMethods.empty()) 1051 | { 1052 | os << "\n"; 1053 | for (auto&& m : ss.PredefinedMethods) 1054 | { 1055 | if (m.MethodType == IGenerator::PredefinedMethod::Type::Inline) 1056 | { 1057 | os << m.Body; 1058 | } 1059 | else 1060 | { 1061 | os << "\t" << m.Signature << ";"; 1062 | } 1063 | os << "\n\n"; 1064 | } 1065 | } 1066 | 1067 | os << "};\n"; 1068 | } 1069 | 1070 | void Package::PrintClass(std::ostream& os, const Class& c) const 1071 | { 1072 | using namespace cpplinq; 1073 | 1074 | os << "// " << c.FullName << "\n// "; 1075 | if (c.InheritedSize) 1076 | { 1077 | tfm::format(os, "0x%04X (0x%04X - 0x%04X)\n", c.Size - c.InheritedSize, c.Size, c.InheritedSize); 1078 | } 1079 | else 1080 | { 1081 | tfm::format(os, "0x%04X\n", c.Size); 1082 | } 1083 | 1084 | os << c.NameCppFull << "\n{\npublic:\n"; 1085 | 1086 | //Member 1087 | for (auto&& m : c.Members) 1088 | { 1089 | tfm::format(os, "\t%-50s %-58s// 0x%04X(0x%04X)", m.Type, m.Name + ";", m.Offset, m.Size); 1090 | if (!m.Comment.empty()) 1091 | { 1092 | os << " " << m.Comment; 1093 | } 1094 | if (!m.FlagsString.empty()) 1095 | { 1096 | os << " (" << m.FlagsString << ")"; 1097 | } 1098 | os << "\n"; 1099 | } 1100 | 1101 | //Predefined Methods 1102 | if (!c.PredefinedMethods.empty()) 1103 | { 1104 | os << "\n"; 1105 | for (auto&& m : c.PredefinedMethods) 1106 | { 1107 | if (m.MethodType == IGenerator::PredefinedMethod::Type::Inline) 1108 | { 1109 | os << m.Body; 1110 | } 1111 | else 1112 | { 1113 | os << "\t" << m.Signature << ";"; 1114 | } 1115 | 1116 | os << "\n\n"; 1117 | } 1118 | } 1119 | 1120 | //Methods 1121 | if (!c.Methods.empty()) 1122 | { 1123 | os << "\n"; 1124 | for (auto&& m : c.Methods) 1125 | { 1126 | os << "\t" << BuildMethodSignature(m, {}, true) << ";\n"; 1127 | } 1128 | } 1129 | 1130 | os << "};\n\n"; 1131 | } 1132 | 1133 | std::string Package::BuildMethodSignature(const Method& m, const Class& c, bool inHeader) const 1134 | { 1135 | extern IGenerator* generator; 1136 | 1137 | using namespace cpplinq; 1138 | using Type = Method::Parameter::Type; 1139 | 1140 | std::ostringstream ss; 1141 | 1142 | if (m.IsStatic && inHeader && !generator->ShouldConvertStaticMethods()) 1143 | { 1144 | ss << "static "; 1145 | } 1146 | 1147 | //Return Type 1148 | auto retn = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Return; }); 1149 | if (retn >> any()) 1150 | { 1151 | ss << (retn >> first()).CppType; 1152 | } 1153 | else 1154 | { 1155 | ss << "void"; 1156 | } 1157 | ss << " "; 1158 | 1159 | if (!inHeader) 1160 | { 1161 | ss << c.NameCpp << "::"; 1162 | } 1163 | if (m.IsStatic && generator->ShouldConvertStaticMethods()) 1164 | { 1165 | ss << "STATIC_"; 1166 | } 1167 | ss << m.Name; 1168 | 1169 | //Parameters 1170 | ss << "("; 1171 | ss << (from(m.Parameters) 1172 | >> where([](auto&& param) { return param.ParamType != Type::Return; }) 1173 | >> orderby([](auto&& param) { return param.ParamType; }) 1174 | >> select([](auto&& param) { return (param.PassByReference ? "const " : "") + param.CppType + (param.PassByReference ? "& " : param.ParamType == Type::Out ? "* " : " ") + param.Name; }) 1175 | >> concatenate(", ")); 1176 | ss << ")"; 1177 | 1178 | return ss.str(); 1179 | } 1180 | 1181 | std::string Package::BuildMethodBody(const Class& c, const Method& m) const 1182 | { 1183 | extern IGenerator* generator; 1184 | 1185 | using namespace cpplinq; 1186 | using Type = Method::Parameter::Type; 1187 | 1188 | std::ostringstream ss; 1189 | 1190 | //Function Pointer 1191 | ss << "{\n\tstatic auto fn"; 1192 | 1193 | if (generator->ShouldUseStrings()) 1194 | { 1195 | ss << " = UObject::FindObject("; 1196 | 1197 | if (generator->ShouldXorStrings()) 1198 | { 1199 | ss << "_xor_(\"" << m.FullName << "\")"; 1200 | } 1201 | else 1202 | { 1203 | ss << "\"" << m.FullName << "\""; 1204 | } 1205 | 1206 | ss << ");\n\n"; 1207 | } 1208 | else 1209 | { 1210 | ss << " = UObject::GetObjectCasted(" << m.Index << ");\n\n"; 1211 | } 1212 | 1213 | //Parameters 1214 | if (generator->ShouldGenerateFunctionParametersFile()) 1215 | { 1216 | ss << "\t" << c.NameCpp << "_" << m.Name << "_Params params;\n"; 1217 | } 1218 | else 1219 | { 1220 | ss << "\tstruct\n\t{\n"; 1221 | for (auto&& param : m.Parameters) 1222 | { 1223 | tfm::format(ss, "\t\t%-30s %s;\n", param.CppType, param.Name); 1224 | } 1225 | ss << "\t} params;\n"; 1226 | } 1227 | 1228 | auto defaultParameters = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Default; }); 1229 | if (defaultParameters >> any()) 1230 | { 1231 | for (auto&& param : defaultParameters >> experimental::container()) 1232 | { 1233 | ss << "\tparams." << param.Name << " = " << param.Name << ";\n"; 1234 | } 1235 | } 1236 | 1237 | ss << "\n"; 1238 | 1239 | //Function Call 1240 | ss << "\tauto flags = fn->FunctionFlags;\n"; 1241 | if (m.IsNative) 1242 | { 1243 | ss << "\tfn->FunctionFlags |= 0x" << tfm::format("%X", static_cast>(UEFunctionFlags::Native)) << ";\n"; 1244 | } 1245 | 1246 | ss << "\n"; 1247 | 1248 | if (m.IsStatic && !generator->ShouldConvertStaticMethods()) 1249 | { 1250 | ss << "\tstatic auto defaultObj = StaticClass()->CreateDefaultObject();\n"; 1251 | ss << "\tdefaultObj->ProcessEvent(fn, ¶ms);\n\n"; 1252 | } 1253 | else 1254 | { 1255 | ss << "\tUObject::ProcessEvent(fn, ¶ms);\n\n"; 1256 | } 1257 | 1258 | ss << "\tfn->FunctionFlags = flags;\n"; 1259 | 1260 | //Out Parameters 1261 | auto out = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Out; }); 1262 | if (out >> any()) 1263 | { 1264 | ss << "\n"; 1265 | 1266 | for (auto&& param : out >> experimental::container()) 1267 | { 1268 | ss << "\tif (" << param.Name << " != nullptr)\n"; 1269 | ss << "\t\t*" << param.Name << " = params." << param.Name << ";\n"; 1270 | } 1271 | } 1272 | 1273 | //Return Value 1274 | auto retn = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Return; }); 1275 | if (retn >> any()) 1276 | { 1277 | ss << "\n\treturn params." << (retn >> first()).Name << ";\n"; 1278 | } 1279 | 1280 | ss << "}\n"; 1281 | 1282 | return ss.str(); 1283 | } 1284 | -------------------------------------------------------------------------------- /Engine/Package.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | namespace fs = std::experimental::filesystem; 8 | 9 | #include "GenericTypes.hpp" 10 | 11 | class Package 12 | { 13 | friend struct std::hash; 14 | friend struct PackageDependencyComparer; 15 | friend bool operator==(const Package& lhs, const Package& rhs); 16 | 17 | public: 18 | /// 19 | /// Constructor. 20 | /// 21 | /// The package object. 22 | Package(const UEObject& packageObj); 23 | 24 | std::string GetName() const { return packageObj.GetName(); } 25 | 26 | /// 27 | /// Process the classes the package contains. 28 | /// 29 | void Process(std::unordered_map& processedObjects); 30 | 31 | /// 32 | /// Saves the package classes as C++ code. 33 | /// Files are only generated if there is code present or the generator forces the genertion of empty files. 34 | /// 35 | /// The path to save to. 36 | /// true if files got saved, else false. 37 | bool Save(const fs::path& path) const; 38 | 39 | private: 40 | bool AddDependency(const UEObject& package) const; 41 | 42 | /// 43 | /// Checks and generates the prerequisites of the object. 44 | /// Should be a UEClass or UEScriptStruct. 45 | /// 46 | /// The object. 47 | void GeneratePrerequisites(const UEObject& obj, std::unordered_map& processedObjects); 48 | 49 | /// 50 | /// Checks and generates the prerequisites of the members. 51 | /// 52 | /// The first member in the chain. 53 | void GenerateMemberPrerequisites(const UEProperty& first, std::unordered_map& processedObjects); 54 | 55 | /// 56 | /// Generates a script structure. 57 | /// 58 | /// The script structure object. 59 | void GenerateScriptStruct(const UEScriptStruct& scriptStructObj); 60 | 61 | /// 62 | /// Generates a constant. 63 | /// 64 | /// The constant object. 65 | void GenerateConst(const UEConst& constObj); 66 | 67 | /// 68 | /// Generates an enum. 69 | /// 70 | /// The enum object. 71 | void GenerateEnum(const UEEnum& enumObj); 72 | 73 | /// 74 | /// Generates the class. 75 | /// 76 | /// The class object. 77 | void GenerateClass(const UEClass& classObj); 78 | 79 | /// 80 | /// Writes all structs into the appropriate file. 81 | /// 82 | /// The path to save to. 83 | void SaveStructs(const fs::path& path) const; 84 | 85 | /// 86 | /// Writes all classes into the appropriate file. 87 | /// 88 | /// The path to save to. 89 | void SaveClasses(const fs::path& path) const; 90 | 91 | /// 92 | /// Writes all functions into the appropriate file. 93 | /// 94 | /// The path to save to. 95 | void SaveFunctions(const fs::path& path) const; 96 | 97 | /// 98 | /// Writes all function parameters into the appropriate file. 99 | /// 100 | /// The path to save to. 101 | void SaveFunctionParameters(const fs::path& path) const; 102 | 103 | UEObject packageObj; 104 | mutable std::unordered_set dependencies; 105 | 106 | /// 107 | /// Prints the c++ code of the constant. 108 | /// 109 | /// [in] The stream to print to. 110 | /// The constant to print. 111 | void PrintConstant(std::ostream& os, const std::pair& c) const; 112 | 113 | std::unordered_map constants; 114 | 115 | struct Enum 116 | { 117 | std::string Name; 118 | std::string FullName; 119 | std::vector Values; 120 | }; 121 | 122 | /// 123 | /// Prints the c++ code of the enum. 124 | /// 125 | /// [in] The stream to print to. 126 | /// The enum to print. 127 | void PrintEnum(std::ostream& os, const Enum& e) const; 128 | 129 | std::vector enums; 130 | 131 | struct Member 132 | { 133 | std::string Name; 134 | std::string Type; 135 | 136 | size_t Offset; 137 | size_t Size; 138 | 139 | size_t Flags; 140 | std::string FlagsString; 141 | 142 | std::string Comment; 143 | }; 144 | 145 | /// 146 | /// Generates a padding member. 147 | /// 148 | /// The unique name identifier. 149 | /// The offset. 150 | /// The size. 151 | /// The reason. 152 | /// A padding member. 153 | static Member CreatePadding(size_t id, size_t offset, size_t size, std::string reason); 154 | 155 | /// 156 | /// Generates a padding member. 157 | /// 158 | /// The unique name identifier. 159 | /// The offset. 160 | /// The size. 161 | /// The reason. 162 | /// A padding member. 163 | static Member CreateBitfieldPadding(size_t id, size_t offset, std::string type, size_t bits); 164 | 165 | /// 166 | /// Generates the members of a struct or class. 167 | /// 168 | /// The structure object. 169 | /// The start offset. 170 | /// The properties describing the members. 171 | /// [out] The members of the struct or class. 172 | void GenerateMembers(const UEStruct& structObj, size_t offset, const std::vector& properties, std::vector& members) const; 173 | 174 | struct ScriptStruct 175 | { 176 | std::string Name; 177 | std::string FullName; 178 | std::string NameCpp; 179 | std::string NameCppFull; 180 | 181 | size_t Size; 182 | size_t InheritedSize; 183 | 184 | std::vector Members; 185 | 186 | std::vector PredefinedMethods; 187 | }; 188 | 189 | /// 190 | /// Print the C++ code of the structure. 191 | /// 192 | /// [in] The stream to print to. 193 | /// The structure to print. 194 | void PrintStruct(std::ostream& os, const ScriptStruct& ss) const; 195 | 196 | std::vector scriptStructs; 197 | 198 | struct Method 199 | { 200 | struct Parameter 201 | { 202 | enum class Type 203 | { 204 | Default, 205 | Out, 206 | Return 207 | }; 208 | 209 | Type ParamType; 210 | bool PassByReference; 211 | std::string CppType; 212 | std::string Name; 213 | std::string FlagsString; 214 | 215 | /// 216 | /// Generates a valid type of the property flags. 217 | /// 218 | /// The property flags. 219 | /// [out] The parameter type. 220 | /// true if it is a valid type, else false. 221 | static bool MakeType(UEPropertyFlags flags, Type& type); 222 | }; 223 | 224 | size_t Index; 225 | std::string Name; 226 | std::string FullName; 227 | std::vector Parameters; 228 | std::string FlagsString; 229 | bool IsNative; 230 | bool IsStatic; 231 | }; 232 | 233 | /// 234 | /// Generates the methods of a class. 235 | /// 236 | /// The class object. 237 | /// [out] The methods of the class. 238 | void GenerateMethods(const UEClass& classObj, std::vector& methods) const; 239 | 240 | struct Class : ScriptStruct 241 | { 242 | std::vector VirtualFunctions; 243 | std::vector Methods; 244 | }; 245 | 246 | /// 247 | /// Builds the C++ method signature. 248 | /// 249 | /// The Method to process. 250 | /// Name of the class. 251 | /// true if the signature is used as decleration. 252 | /// The method signature. 253 | std::string BuildMethodSignature(const Method& m, const Class& c, bool inHeader) const; 254 | 255 | /// 256 | /// Builds the c++ method body. 257 | /// 258 | /// The Method to process. 259 | /// The method body. 260 | std::string BuildMethodBody(const Class& c, const Method& m) const; 261 | 262 | /// 263 | /// Print the C++ code of the class. 264 | /// 265 | /// [in] The stream to print to. 266 | /// The class to print. 267 | void PrintClass(std::ostream& os, const Class& c) const; 268 | 269 | std::vector classes; 270 | }; 271 | 272 | namespace std 273 | { 274 | template<> 275 | struct hash 276 | { 277 | size_t operator()(const Package& package) const 278 | { 279 | return std::hash()(package.packageObj.GetAddress()); 280 | } 281 | }; 282 | } 283 | 284 | inline bool operator==(const Package& lhs, const Package& rhs) { return rhs.packageObj.GetAddress() == lhs.packageObj.GetAddress(); } 285 | inline bool operator!=(const Package& lhs, const Package& rhs) { return !(lhs == rhs); } 286 | -------------------------------------------------------------------------------- /Engine/PatternFinder.cpp: -------------------------------------------------------------------------------- 1 | #include "PatternFinder.hpp" 2 | 3 | #include 4 | #include 5 | 6 | uintptr_t FindPattern(HMODULE module, const unsigned char* pattern, const char* mask) 7 | { 8 | MODULEINFO info = { }; 9 | GetModuleInformation(GetCurrentProcess(), module, &info, sizeof(MODULEINFO)); 10 | 11 | return FindPattern(reinterpret_cast(module), info.SizeOfImage, pattern, mask); 12 | } 13 | 14 | uintptr_t FindPattern(uintptr_t start, size_t length, const unsigned char* pattern, const char* mask) 15 | { 16 | size_t pos = 0; 17 | auto maskLength = std::strlen(mask) - 1; 18 | 19 | auto startAdress = start; 20 | for (auto it = startAdress; it < startAdress + length; ++it) 21 | { 22 | if (*reinterpret_cast(it) == pattern[pos] || mask[pos] == '?') 23 | { 24 | if (mask[pos + 1] == '\0') 25 | { 26 | return it - maskLength; 27 | } 28 | 29 | pos++; 30 | } 31 | else 32 | { 33 | pos = 0; 34 | } 35 | } 36 | 37 | return -1; 38 | } 39 | -------------------------------------------------------------------------------- /Engine/PatternFinder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /// 7 | /// Searches for the first pattern in the module. 8 | /// 9 | /// The module to scan. 10 | /// The pattern (Example: "\x12\xAB\x34") 11 | /// The mask (Example: "x?x") 12 | /// The address of the found pattern or -1 if the pattern was not found. 13 | uintptr_t FindPattern(HMODULE module, const unsigned char* pattern, const char* mask); 14 | 15 | /// 16 | /// Searches for the first pattern in the memory region. 17 | /// 18 | /// The start address of the memory region to scan. 19 | /// The length of the memory region. 20 | /// The pattern (Example: "\x12\xAB\x34") 21 | /// The mask (Example: "x?x") 22 | /// The address of the found pattern or -1 if the pattern was not found. 23 | uintptr_t FindPattern(uintptr_t start, size_t length, const unsigned char* pattern, const char* mask); 24 | -------------------------------------------------------------------------------- /Engine/PrintHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintHelper.hpp" 2 | 3 | #include 4 | 5 | #include "IGenerator.hpp" 6 | #include "Package.hpp" 7 | 8 | void PrintFileHeader(std::ostream& os, const std::vector& includes, const bool isHeaderFile) 9 | { 10 | extern IGenerator* generator; 11 | 12 | if (isHeaderFile) 13 | { 14 | os << "#pragma once\n\n"; 15 | } 16 | 17 | os << tfm::format("// %s SDK\n\n", generator->GetGameName()) 18 | << tfm::format("#ifdef _MSC_VER\n\t#pragma pack(push, 0x%X)\n#endif\n\n", generator->GetGlobalMemberAlignment()); 19 | 20 | if (!includes.empty()) 21 | { 22 | for (auto&& i : includes) 23 | { 24 | if (i[0] != '<' && i[0] != '"') 25 | { 26 | os << "#include \"" << i << "\"\n"; 27 | } 28 | else 29 | { 30 | os << "#include " << i << "\n"; 31 | } 32 | } 33 | os << "\n"; 34 | } 35 | 36 | if (!generator->GetNamespaceName().empty()) 37 | { 38 | os << "namespace " << generator->GetNamespaceName() << "\n{\n"; 39 | } 40 | } 41 | 42 | void PrintFileHeader(std::ostream& os, const bool isHeaderFile) 43 | { 44 | extern IGenerator* generator; 45 | 46 | PrintFileHeader(os, std::vector(), isHeaderFile); 47 | } 48 | 49 | void PrintFileFooter(std::ostream& os) 50 | { 51 | extern IGenerator* generator; 52 | 53 | if (!generator->GetNamespaceName().empty()) 54 | { 55 | os << "}\n\n"; 56 | } 57 | 58 | os << "#ifdef _MSC_VER\n\t#pragma pack(pop)\n#endif\n"; 59 | } 60 | 61 | void PrintSectionHeader(std::ostream& os, const char* name) 62 | { 63 | os << "//---------------------------------------------------------------------------\n" 64 | << "//" << name << "\n" 65 | << "//---------------------------------------------------------------------------\n\n"; 66 | } 67 | 68 | std::string GenerateFileName(const FileContentType type, const Package& package) 69 | { 70 | extern IGenerator* generator; 71 | 72 | const char* name = 0; 73 | switch (type) 74 | { 75 | case FileContentType::Structs: 76 | name = "%s_%s_structs.hpp"; 77 | break; 78 | case FileContentType::Classes: 79 | name = "%s_%s_classes.hpp"; 80 | break; 81 | case FileContentType::Functions: 82 | name = "%s_%s_functions.cpp"; 83 | break; 84 | case FileContentType::FunctionParameters: 85 | name = "%s_%s_parameters.hpp"; 86 | break; 87 | default: 88 | assert(false); 89 | } 90 | 91 | return tfm::format(name, generator->GetGameNameShort(), package.GetName()); 92 | } 93 | -------------------------------------------------------------------------------- /Engine/PrintHelper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | void PrintFileHeader(std::ostream& os, const std::vector& includes, const bool isHeaderFile); 7 | 8 | void PrintFileHeader(std::ostream& os, const bool isHeaderFile); 9 | 10 | void PrintFileFooter(std::ostream& os); 11 | 12 | void PrintSectionHeader(std::ostream& os, const char* name); 13 | 14 | enum class FileContentType 15 | { 16 | Structs, 17 | Classes, 18 | Functions, 19 | FunctionParameters 20 | }; 21 | 22 | /// 23 | /// Generates a file name composed by the game name and the package object. 24 | /// 25 | /// The type of the file. 26 | /// 27 | /// The generated file name. 28 | /// 29 | std::string GenerateFileName(const FileContentType type, const class Package& package); 30 | -------------------------------------------------------------------------------- /Engine/UE4/FunctionFlags.cpp: -------------------------------------------------------------------------------- 1 | #include "FunctionFlags.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | std::string StringifyFlags(const UEFunctionFlags flags) 8 | { 9 | std::vector buffer; 10 | 11 | if (flags & UEFunctionFlags::Final) { buffer.push_back("Final"); } 12 | if (flags & UEFunctionFlags::RequiredAPI) { buffer.push_back("RequiredAPI"); } 13 | if (flags & UEFunctionFlags::BlueprintAuthorityOnly) { buffer.push_back("BlueprintAuthorityOnly"); } 14 | if (flags & UEFunctionFlags::BlueprintCosmetic) { buffer.push_back("BlueprintCosmetic"); } 15 | if (flags & UEFunctionFlags::Net) { buffer.push_back("Net"); } 16 | if (flags & UEFunctionFlags::NetReliable) { buffer.push_back("NetReliable"); } 17 | if (flags & UEFunctionFlags::NetRequest) { buffer.push_back("NetRequest"); } 18 | if (flags & UEFunctionFlags::Exec) { buffer.push_back("Exec"); } 19 | if (flags & UEFunctionFlags::Native) { buffer.push_back("Native"); } 20 | if (flags & UEFunctionFlags::Event) { buffer.push_back("Event"); } 21 | if (flags & UEFunctionFlags::NetResponse) { buffer.push_back("NetResponse"); } 22 | if (flags & UEFunctionFlags::Static) { buffer.push_back("Static"); } 23 | if (flags & UEFunctionFlags::NetMulticast) { buffer.push_back("NetMulticast"); } 24 | if (flags & UEFunctionFlags::MulticastDelegate) { buffer.push_back("MulticastDelegate"); } 25 | if (flags & UEFunctionFlags::Public) { buffer.push_back("Public"); } 26 | if (flags & UEFunctionFlags::Private) { buffer.push_back("Private"); } 27 | if (flags & UEFunctionFlags::Protected) { buffer.push_back("Protected"); } 28 | if (flags & UEFunctionFlags::Delegate) { buffer.push_back("Delegate"); } 29 | if (flags & UEFunctionFlags::NetServer) { buffer.push_back("NetServer"); } 30 | if (flags & UEFunctionFlags::HasOutParms) { buffer.push_back("HasOutParms"); } 31 | if (flags & UEFunctionFlags::HasDefaults) { buffer.push_back("HasDefaults"); } 32 | if (flags & UEFunctionFlags::NetClient) { buffer.push_back("NetClient"); } 33 | if (flags & UEFunctionFlags::DLLImport) { buffer.push_back("DLLImport"); } 34 | if (flags & UEFunctionFlags::BlueprintCallable) { buffer.push_back("BlueprintCallable"); } 35 | if (flags & UEFunctionFlags::BlueprintEvent) { buffer.push_back("BlueprintEvent"); } 36 | if (flags & UEFunctionFlags::BlueprintPure) { buffer.push_back("BlueprintPure"); } 37 | if (flags & UEFunctionFlags::Const) { buffer.push_back("Const"); } 38 | if (flags & UEFunctionFlags::NetValidate) { buffer.push_back("NetValidate"); } 39 | 40 | switch (buffer.size()) 41 | { 42 | case 0: 43 | return std::string(); 44 | case 1: 45 | return std::string(buffer[0]); 46 | default: 47 | std::ostringstream os; 48 | std::copy(buffer.begin(), buffer.end() - 1, std::ostream_iterator(os, ", ")); 49 | os << *buffer.rbegin(); 50 | return os.str(); 51 | } 52 | } -------------------------------------------------------------------------------- /Engine/UE4/FunctionFlags.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | enum class UEFunctionFlags : uint32_t 7 | { 8 | Final = 0x00000001, 9 | RequiredAPI = 0x00000002, 10 | BlueprintAuthorityOnly = 0x00000004, 11 | BlueprintCosmetic = 0x00000008, 12 | Net = 0x00000040, 13 | NetReliable = 0x00000080, 14 | NetRequest = 0x00000100, 15 | Exec = 0x00000200, 16 | Native = 0x00000400, 17 | Event = 0x00000800, 18 | NetResponse = 0x00001000, 19 | Static = 0x00002000, 20 | NetMulticast = 0x00004000, 21 | MulticastDelegate = 0x00010000, 22 | Public = 0x00020000, 23 | Private = 0x00040000, 24 | Protected = 0x00080000, 25 | Delegate = 0x00100000, 26 | NetServer = 0x00200000, 27 | HasOutParms = 0x00400000, 28 | HasDefaults = 0x00800000, 29 | NetClient = 0x01000000, 30 | DLLImport = 0x02000000, 31 | BlueprintCallable = 0x04000000, 32 | BlueprintEvent = 0x08000000, 33 | BlueprintPure = 0x10000000, 34 | Const = 0x40000000, 35 | NetValidate = 0x80000000 36 | }; 37 | 38 | inline bool operator&(UEFunctionFlags lhs, UEFunctionFlags rhs) 39 | { 40 | return (static_cast>(lhs) & static_cast>(rhs)) == static_cast>(rhs); 41 | } 42 | 43 | std::string StringifyFlags(const UEFunctionFlags flags); 44 | -------------------------------------------------------------------------------- /Engine/UE4/GenericTypes.cpp: -------------------------------------------------------------------------------- 1 | #include "GenericTypes.hpp" 2 | 3 | void* UEObject::GetAddress() const 4 | { 5 | return object; 6 | } 7 | 8 | UEObject UEObject::GetPackageObject() const 9 | { 10 | UEObject package(nullptr); 11 | 12 | for (auto outer = GetOuter(); outer.IsValid(); outer = outer.GetOuter()) 13 | { 14 | package = outer; 15 | } 16 | 17 | return package; 18 | } 19 | 20 | std::string UEObject::GetFullName() const 21 | { 22 | if (GetClass().IsValid()) 23 | { 24 | std::string temp; 25 | 26 | for (auto outer = GetOuter(); outer.IsValid(); outer = outer.GetOuter()) 27 | { 28 | temp = outer.GetName() + "." + temp; 29 | } 30 | 31 | std::string name = GetClass().GetName(); 32 | name += " "; 33 | name += temp; 34 | name += GetName(); 35 | 36 | return name; 37 | } 38 | 39 | return std::string("(null)"); 40 | } 41 | 42 | std::string UEObject::GetNameCPP() const 43 | { 44 | std::string name; 45 | 46 | if (IsA()) 47 | { 48 | auto c = Cast(); 49 | while (c.IsValid()) 50 | { 51 | const auto className = c.GetName(); 52 | if (className == "Actor") 53 | { 54 | name += "A"; 55 | break; 56 | } 57 | if (className == "Object") 58 | { 59 | name += "U"; 60 | break; 61 | } 62 | 63 | c = c.GetSuper().Cast(); 64 | } 65 | } 66 | else 67 | { 68 | name += "F"; 69 | } 70 | 71 | name += GetName(); 72 | 73 | return name; 74 | } 75 | 76 | UEProperty::Info UEProperty::GetInfo() const 77 | { 78 | if (IsValid()) 79 | { 80 | if (IsA()) 81 | { 82 | return Cast().GetInfo(); 83 | } 84 | if (IsA()) 85 | { 86 | return Cast().GetInfo(); 87 | } 88 | if (IsA()) 89 | { 90 | return Cast().GetInfo(); 91 | } 92 | if (IsA()) 93 | { 94 | return Cast().GetInfo(); 95 | } 96 | if (IsA()) 97 | { 98 | return Cast().GetInfo(); 99 | } 100 | if (IsA()) 101 | { 102 | return Cast().GetInfo(); 103 | } 104 | if (IsA()) 105 | { 106 | return Cast().GetInfo(); 107 | } 108 | if (IsA()) 109 | { 110 | return Cast().GetInfo(); 111 | } 112 | if (IsA()) 113 | { 114 | return Cast().GetInfo(); 115 | } 116 | if (IsA()) 117 | { 118 | return Cast().GetInfo(); 119 | } 120 | if (IsA()) 121 | { 122 | return Cast().GetInfo(); 123 | } 124 | if (IsA()) 125 | { 126 | return Cast().GetInfo(); 127 | } 128 | if (IsA()) 129 | { 130 | return Cast().GetInfo(); 131 | } 132 | if (IsA()) 133 | { 134 | return Cast().GetInfo(); 135 | } 136 | if (IsA()) 137 | { 138 | return Cast().GetInfo(); 139 | } 140 | if (IsA()) 141 | { 142 | return Cast().GetInfo(); 143 | } 144 | if (IsA()) 145 | { 146 | return Cast().GetInfo(); 147 | } 148 | if (IsA()) 149 | { 150 | return Cast().GetInfo(); 151 | } 152 | if (IsA()) 153 | { 154 | return Cast().GetInfo(); 155 | } 156 | if (IsA()) 157 | { 158 | return Cast().GetInfo(); 159 | } 160 | if (IsA()) 161 | { 162 | return Cast().GetInfo(); 163 | } 164 | if (IsA()) 165 | { 166 | return Cast().GetInfo(); 167 | } 168 | if (IsA()) 169 | { 170 | return Cast().GetInfo(); 171 | } 172 | if (IsA()) 173 | { 174 | return Cast().GetInfo(); 175 | } 176 | if (IsA()) 177 | { 178 | return Cast().GetInfo(); 179 | } 180 | if (IsA()) 181 | { 182 | return Cast().GetInfo(); 183 | } 184 | if (IsA()) 185 | { 186 | return Cast().GetInfo(); 187 | } 188 | if (IsA()) 189 | { 190 | return Cast().GetInfo(); 191 | } 192 | 193 | Info info; 194 | if (GetCustomPropertyInfo(*this, info)) 195 | { 196 | return info; 197 | } 198 | } 199 | return { PropertyType::Unknown }; 200 | } 201 | 202 | //--------------------------------------------------------------------------- 203 | //UEByteProperty 204 | //--------------------------------------------------------------------------- 205 | bool UEByteProperty::IsEnum() const 206 | { 207 | return GetEnum().IsValid(); 208 | } 209 | //--------------------------------------------------------------------------- 210 | //UEBoolProperty 211 | //--------------------------------------------------------------------------- 212 | int GetBitPosition(uint8_t value) 213 | { 214 | const int i4 = !(value & 0xf) << 2; 215 | value >>= i4; 216 | 217 | const int i2 = !(value & 0x3) << 1; 218 | value >>= i2; 219 | 220 | const int i1 = !(value & 0x1); 221 | 222 | const int i0 = (value >> i1) & 1 ? 0 : -8; 223 | 224 | return i4 + i2 + i1 + i0; 225 | } 226 | 227 | std::array UEBoolProperty::GetMissingBitsCount(const UEBoolProperty& other) const 228 | { 229 | // If there is no previous bitfield member, just calculate the missing bits. 230 | if (!other.IsValid()) 231 | { 232 | return { GetBitPosition(GetByteMask()), -1 }; 233 | } 234 | 235 | // If both bitfield member belong to the same byte, calculate the bit position difference. 236 | if (GetOffset() == other.GetOffset()) 237 | { 238 | return { GetBitPosition(GetByteMask()) - GetBitPosition(other.GetByteMask()) - 1, -1 }; 239 | } 240 | 241 | // If they have different offsets, we need two distances 242 | // |00001000|00100000| 243 | // 1. ^---^ 244 | // 2. ^--^ 245 | 246 | return { std::numeric_limits::digits - GetBitPosition(other.GetByteMask()) - 1, GetBitPosition(GetByteMask()) }; 247 | } -------------------------------------------------------------------------------- /Engine/UE4/GenericTypes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "PropertyFlags.hpp" 8 | #include "FunctionFlags.hpp" 9 | #include "../IGenerator.hpp" 10 | 11 | class UObject; 12 | class UEClass; 13 | 14 | class UEObject 15 | { 16 | public: 17 | UEObject() 18 | : object(nullptr) 19 | { 20 | } 21 | UEObject(UObject *_object) 22 | : object(_object) 23 | { 24 | } 25 | 26 | bool IsValid() const 27 | { 28 | return object != nullptr; 29 | } 30 | 31 | size_t GetIndex() const; 32 | 33 | UEClass GetClass() const; 34 | 35 | UEObject GetOuter() const; 36 | 37 | std::string GetName() const; 38 | 39 | std::string GetFullName() const; 40 | 41 | std::string GetNameCPP() const; 42 | 43 | UEObject GetPackageObject() const; 44 | 45 | void* GetAddress() const; 46 | 47 | template 48 | Base Cast() const 49 | { 50 | return Base(object); 51 | } 52 | 53 | template 54 | bool IsA() const; 55 | 56 | static UEClass StaticClass(); 57 | 58 | protected: 59 | UObject* object; 60 | }; 61 | 62 | namespace std 63 | { 64 | template<> 65 | struct hash 66 | { 67 | size_t operator()(const UEObject& obj) const 68 | { 69 | return std::hash()(obj.GetAddress()); 70 | } 71 | }; 72 | } 73 | 74 | inline bool operator==(const UEObject& lhs, const UEObject& rhs) { return rhs.GetAddress() == lhs.GetAddress(); } 75 | inline bool operator!=(const UEObject& lhs, const UEObject& rhs) { return !(lhs == rhs); } 76 | 77 | class UEField : public UEObject 78 | { 79 | public: 80 | using UEObject::UEObject; 81 | 82 | UEField GetNext() const; 83 | 84 | static UEClass StaticClass(); 85 | }; 86 | 87 | class UEEnum : public UEField 88 | { 89 | public: 90 | using UEField::UEField; 91 | 92 | std::vector GetNames() const; 93 | 94 | static UEClass StaticClass(); 95 | }; 96 | 97 | class UEConst : public UEField 98 | { 99 | public: 100 | using UEField::UEField; 101 | 102 | std::string GetValue() const; 103 | 104 | static UEClass StaticClass(); 105 | }; 106 | 107 | class UEStruct : public UEField 108 | { 109 | public: 110 | using UEField::UEField; 111 | 112 | UEStruct GetSuper() const; 113 | 114 | UEField GetChildren() const; 115 | 116 | size_t GetPropertySize() const; 117 | 118 | static UEClass StaticClass(); 119 | }; 120 | 121 | class UEScriptStruct : public UEStruct 122 | { 123 | public: 124 | using UEStruct::UEStruct; 125 | 126 | static UEClass StaticClass(); 127 | }; 128 | 129 | class UEFunction : public UEStruct 130 | { 131 | public: 132 | using UEStruct::UEStruct; 133 | 134 | UEFunctionFlags GetFunctionFlags() const; 135 | 136 | static UEClass StaticClass(); 137 | }; 138 | 139 | class UEClass : public UEStruct 140 | { 141 | public: 142 | using UEStruct::UEStruct; 143 | 144 | static UEClass StaticClass(); 145 | }; 146 | 147 | class UEProperty : public UEField 148 | { 149 | public: 150 | using UEField::UEField; 151 | 152 | size_t GetArrayDim() const; 153 | 154 | size_t GetElementSize() const; 155 | 156 | UEPropertyFlags GetPropertyFlags() const; 157 | 158 | size_t GetOffset() const; 159 | 160 | enum class PropertyType 161 | { 162 | Unknown, 163 | Primitive, 164 | PredefinedStruct, 165 | CustomStruct, 166 | Container 167 | }; 168 | 169 | struct Info 170 | { 171 | PropertyType Type; 172 | size_t Size; 173 | bool CanBeReference; 174 | std::string CppType; 175 | 176 | static Info Create(PropertyType type, size_t size, bool reference, std::string&& cppType) 177 | { 178 | extern IGenerator* generator; 179 | 180 | return { type, size, reference, generator->GetOverrideType(cppType) }; 181 | } 182 | }; 183 | 184 | Info GetInfo() const; 185 | 186 | static bool GetCustomPropertyInfo(const UEProperty& property, Info &info); 187 | 188 | static UEClass StaticClass(); 189 | 190 | unsigned long GetBitMask() const; 191 | }; 192 | 193 | class UENumericProperty : public UEProperty 194 | { 195 | public: 196 | using UEProperty::UEProperty; 197 | 198 | static UEClass StaticClass(); 199 | }; 200 | 201 | class UEByteProperty : public UENumericProperty 202 | { 203 | public: 204 | using UENumericProperty::UENumericProperty; 205 | 206 | bool IsEnum() const; 207 | 208 | UEEnum GetEnum() const; 209 | 210 | UEProperty::Info GetInfo() const; 211 | 212 | static UEClass StaticClass(); 213 | }; 214 | 215 | class UEUInt16Property : public UENumericProperty 216 | { 217 | public: 218 | using UENumericProperty::UENumericProperty; 219 | 220 | UEProperty::Info GetInfo() const; 221 | 222 | static UEClass StaticClass(); 223 | }; 224 | 225 | class UEUInt32Property : public UENumericProperty 226 | { 227 | public: 228 | using UENumericProperty::UENumericProperty; 229 | 230 | UEProperty::Info GetInfo() const; 231 | 232 | static UEClass StaticClass(); 233 | }; 234 | 235 | class UEUInt64Property : public UENumericProperty 236 | { 237 | public: 238 | using UENumericProperty::UENumericProperty; 239 | 240 | UEProperty::Info GetInfo() const; 241 | 242 | static UEClass StaticClass(); 243 | }; 244 | 245 | class UEInt8Property : public UENumericProperty 246 | { 247 | public: 248 | using UENumericProperty::UENumericProperty; 249 | 250 | UEProperty::Info GetInfo() const; 251 | 252 | static UEClass StaticClass(); 253 | }; 254 | 255 | class UEInt16Property : public UENumericProperty 256 | { 257 | public: 258 | using UENumericProperty::UENumericProperty; 259 | 260 | UEProperty::Info GetInfo() const; 261 | 262 | static UEClass StaticClass(); 263 | }; 264 | 265 | class UEIntProperty : public UENumericProperty 266 | { 267 | public: 268 | using UENumericProperty::UENumericProperty; 269 | 270 | UEProperty::Info GetInfo() const; 271 | 272 | static UEClass StaticClass(); 273 | }; 274 | 275 | class UEInt64Property : public UENumericProperty 276 | { 277 | public: 278 | using UENumericProperty::UENumericProperty; 279 | 280 | UEProperty::Info GetInfo() const; 281 | 282 | static UEClass StaticClass(); 283 | }; 284 | 285 | class UEFloatProperty : public UENumericProperty 286 | { 287 | public: 288 | using UENumericProperty::UENumericProperty; 289 | 290 | UEProperty::Info GetInfo() const; 291 | 292 | static UEClass StaticClass(); 293 | }; 294 | 295 | class UEDoubleProperty : public UENumericProperty 296 | { 297 | public: 298 | using UENumericProperty::UENumericProperty; 299 | 300 | UEProperty::Info GetInfo() const; 301 | 302 | static UEClass StaticClass(); 303 | }; 304 | 305 | class UEBoolProperty : public UEProperty 306 | { 307 | public: 308 | using UEProperty::UEProperty; 309 | 310 | bool IsNativeBool() const { return GetFieldMask() == 0xFF; } 311 | 312 | bool IsBitfield() const { return !IsNativeBool(); } 313 | 314 | uint8_t GetFieldSize() const; 315 | 316 | uint8_t GetByteOffset() const; 317 | 318 | uint8_t GetByteMask() const; 319 | 320 | uint8_t GetFieldMask() const; 321 | 322 | std::array GetMissingBitsCount(const UEBoolProperty& other) const; 323 | 324 | UEProperty::Info GetInfo() const; 325 | 326 | static UEClass StaticClass(); 327 | }; 328 | 329 | inline bool operator<(const UEBoolProperty& lhs, const UEBoolProperty& rhs) 330 | { 331 | if (lhs.GetByteOffset() == rhs.GetByteOffset()) 332 | { 333 | return lhs.GetByteMask() < rhs.GetByteMask(); 334 | } 335 | return lhs.GetByteOffset() < rhs.GetByteOffset(); 336 | } 337 | 338 | class UEObjectPropertyBase : public UEProperty 339 | { 340 | public: 341 | using UEProperty::UEProperty; 342 | 343 | UEClass GetPropertyClass() const; 344 | 345 | static UEClass StaticClass(); 346 | }; 347 | 348 | class UEObjectProperty : public UEObjectPropertyBase 349 | { 350 | public: 351 | using UEObjectPropertyBase::UEObjectPropertyBase; 352 | 353 | UEProperty::Info GetInfo() const; 354 | 355 | static UEClass StaticClass(); 356 | }; 357 | 358 | class UEClassProperty : public UEObjectProperty 359 | { 360 | public: 361 | using UEObjectProperty::UEObjectProperty; 362 | 363 | UEClass GetMetaClass() const; 364 | 365 | UEProperty::Info GetInfo() const; 366 | 367 | static UEClass StaticClass(); 368 | }; 369 | 370 | class UEInterfaceProperty : public UEProperty 371 | { 372 | public: 373 | using UEProperty::UEProperty; 374 | 375 | UEClass GetInterfaceClass() const; 376 | 377 | UEProperty::Info GetInfo() const; 378 | 379 | static UEClass StaticClass(); 380 | }; 381 | 382 | class UEWeakObjectProperty : public UEObjectPropertyBase 383 | { 384 | public: 385 | using UEObjectPropertyBase::UEObjectPropertyBase; 386 | 387 | UEProperty::Info GetInfo() const; 388 | 389 | static UEClass StaticClass(); 390 | }; 391 | 392 | class UELazyObjectProperty : public UEObjectPropertyBase 393 | { 394 | public: 395 | using UEObjectPropertyBase::UEObjectPropertyBase; 396 | 397 | UEProperty::Info GetInfo() const; 398 | 399 | static UEClass StaticClass(); 400 | }; 401 | 402 | class UEAssetObjectProperty : public UEObjectPropertyBase 403 | { 404 | public: 405 | using UEObjectPropertyBase::UEObjectPropertyBase; 406 | 407 | UEProperty::Info GetInfo() const; 408 | 409 | static UEClass StaticClass(); 410 | }; 411 | 412 | class UEAssetClassProperty : public UEAssetObjectProperty 413 | { 414 | public: 415 | using UEAssetObjectProperty::UEAssetObjectProperty; 416 | 417 | UEClass GetMetaClass() const; 418 | 419 | UEProperty::Info GetInfo() const; 420 | 421 | static UEClass StaticClass(); 422 | }; 423 | 424 | class UESoftObjectProperty : public UEObjectPropertyBase 425 | { 426 | public: 427 | using UEObjectPropertyBase::UEObjectPropertyBase; 428 | 429 | UEProperty::Info GetInfo() const; 430 | 431 | static UEClass StaticClass(); 432 | }; 433 | 434 | class UENameProperty : public UEProperty 435 | { 436 | public: 437 | using UEProperty::UEProperty; 438 | 439 | UEProperty::Info GetInfo() const; 440 | 441 | static UEClass StaticClass(); 442 | }; 443 | 444 | class UEStructProperty : public UEProperty 445 | { 446 | public: 447 | using UEProperty::UEProperty; 448 | 449 | UEScriptStruct GetStruct() const; 450 | 451 | UEProperty::Info GetInfo() const; 452 | 453 | static UEClass StaticClass(); 454 | }; 455 | 456 | class UEStrProperty : public UEProperty 457 | { 458 | public: 459 | using UEProperty::UEProperty; 460 | 461 | UEProperty::Info GetInfo() const; 462 | 463 | static UEClass StaticClass(); 464 | }; 465 | 466 | class UETextProperty : public UEProperty 467 | { 468 | public: 469 | using UEProperty::UEProperty; 470 | 471 | UEProperty::Info GetInfo() const; 472 | 473 | static UEClass StaticClass(); 474 | }; 475 | 476 | class UEArrayProperty : public UEProperty 477 | { 478 | public: 479 | using UEProperty::UEProperty; 480 | 481 | UEProperty GetInner() const; 482 | 483 | UEProperty::Info GetInfo() const; 484 | 485 | static UEClass StaticClass(); 486 | }; 487 | 488 | class UEMapProperty : public UEProperty 489 | { 490 | public: 491 | using UEProperty::UEProperty; 492 | 493 | UEProperty GetKeyProperty() const; 494 | UEProperty GetValueProperty() const; 495 | 496 | UEProperty::Info GetInfo() const; 497 | 498 | static UEClass StaticClass(); 499 | }; 500 | 501 | class UEDelegateProperty : public UEProperty 502 | { 503 | public: 504 | using UEProperty::UEProperty; 505 | 506 | UEFunction GetSignatureFunction() const; 507 | 508 | UEProperty::Info GetInfo() const; 509 | 510 | static UEClass StaticClass(); 511 | }; 512 | 513 | class UEMulticastDelegateProperty : public UEProperty 514 | { 515 | public: 516 | using UEProperty::UEProperty; 517 | 518 | UEFunction GetSignatureFunction() const; 519 | 520 | UEProperty::Info GetInfo() const; 521 | 522 | static UEClass StaticClass(); 523 | }; 524 | 525 | class UEEnumProperty : public UEProperty 526 | { 527 | public: 528 | using UEProperty::UEProperty; 529 | 530 | UENumericProperty GetUnderlyingProperty() const; 531 | UEEnum GetEnum() const; 532 | 533 | UEProperty::Info GetInfo() const; 534 | 535 | static UEClass StaticClass(); 536 | }; 537 | 538 | template 539 | bool UEObject::IsA() const 540 | { 541 | auto cmp = T::StaticClass(); 542 | if (!cmp.IsValid()) 543 | { 544 | return false; 545 | } 546 | 547 | for (auto super = GetClass(); super.IsValid(); super = super.GetSuper().Cast()) 548 | { 549 | if (super.object == cmp.object) 550 | { 551 | return true; 552 | } 553 | } 554 | 555 | return false; 556 | } -------------------------------------------------------------------------------- /Engine/UE4/Package.cpp: -------------------------------------------------------------------------------- 1 | #include "../Package.hpp" 2 | 3 | bool Package::Method::Parameter::MakeType(UEPropertyFlags flags, Type& type) 4 | { 5 | if (flags & UEPropertyFlags::ReturnParm) 6 | { 7 | type = Type::Return; 8 | } 9 | else if (flags & UEPropertyFlags::OutParm) 10 | { 11 | //if it is a const parameter make it a default parameter 12 | if (flags & UEPropertyFlags::ConstParm) 13 | { 14 | type = Type::Default; 15 | } 16 | else 17 | { 18 | type = Type::Out; 19 | } 20 | } 21 | else if (flags & UEPropertyFlags::Parm) 22 | { 23 | type = Type::Default; 24 | } 25 | else 26 | { 27 | return false; 28 | } 29 | 30 | return true; 31 | } -------------------------------------------------------------------------------- /Engine/UE4/PropertyFlags.cpp: -------------------------------------------------------------------------------- 1 | #include "PropertyFlags.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | std::string StringifyFlags(const UEPropertyFlags flags) 8 | { 9 | std::vector buffer; 10 | 11 | if (flags & UEPropertyFlags::Edit) { buffer.push_back("Edit"); } 12 | if (flags & UEPropertyFlags::ConstParm) { buffer.push_back("ConstParm"); } 13 | if (flags & UEPropertyFlags::BlueprintVisible) { buffer.push_back("BlueprintVisible"); } 14 | if (flags & UEPropertyFlags::ExportObject) { buffer.push_back("ExportObject"); } 15 | if (flags & UEPropertyFlags::BlueprintReadOnly) { buffer.push_back("BlueprintReadOnly"); } 16 | if (flags & UEPropertyFlags::Net) { buffer.push_back("Net"); } 17 | if (flags & UEPropertyFlags::EditFixedSize) { buffer.push_back("EditFixedSize"); } 18 | if (flags & UEPropertyFlags::Parm) { buffer.push_back("Parm"); } 19 | if (flags & UEPropertyFlags::OutParm) { buffer.push_back("OutParm"); } 20 | if (flags & UEPropertyFlags::ZeroConstructor) { buffer.push_back("ZeroConstructor"); } 21 | if (flags & UEPropertyFlags::ReturnParm) { buffer.push_back("ReturnParm"); } 22 | if (flags & UEPropertyFlags::DisableEditOnTemplate) { buffer.push_back("DisableEditOnTemplate"); } 23 | if (flags & UEPropertyFlags::Transient) { buffer.push_back("Transient"); } 24 | if (flags & UEPropertyFlags::Config) { buffer.push_back("Config"); } 25 | if (flags & UEPropertyFlags::DisableEditOnInstance) { buffer.push_back("DisableEditOnInstance"); } 26 | if (flags & UEPropertyFlags::EditConst) { buffer.push_back("EditConst"); } 27 | if (flags & UEPropertyFlags::GlobalConfig) { buffer.push_back("GlobalConfig"); } 28 | if (flags & UEPropertyFlags::InstancedReference) { buffer.push_back("InstancedReference"); } 29 | if (flags & UEPropertyFlags::DuplicateTransient) { buffer.push_back("DuplicateTransient"); } 30 | if (flags & UEPropertyFlags::SubobjectReference) { buffer.push_back("SubobjectReference"); } 31 | if (flags & UEPropertyFlags::SaveGame) { buffer.push_back("SaveGame"); } 32 | if (flags & UEPropertyFlags::NoClear) { buffer.push_back("NoClear"); } 33 | if (flags & UEPropertyFlags::ReferenceParm) { buffer.push_back("ReferenceParm"); } 34 | if (flags & UEPropertyFlags::BlueprintAssignable) { buffer.push_back("BlueprintAssignable"); } 35 | if (flags & UEPropertyFlags::Deprecated) { buffer.push_back("Deprecated"); } 36 | if (flags & UEPropertyFlags::IsPlainOldData) { buffer.push_back("IsPlainOldData"); } 37 | if (flags & UEPropertyFlags::RepSkip) { buffer.push_back("RepSkip"); } 38 | if (flags & UEPropertyFlags::RepNotify) { buffer.push_back("RepNotify"); } 39 | if (flags & UEPropertyFlags::Interp) { buffer.push_back("Interp"); } 40 | if (flags & UEPropertyFlags::NonTransactional) { buffer.push_back("NonTransactional"); } 41 | if (flags & UEPropertyFlags::EditorOnly) { buffer.push_back("EditorOnly"); } 42 | if (flags & UEPropertyFlags::NoDestructor) { buffer.push_back("NoDestructor"); } 43 | if (flags & UEPropertyFlags::AutoWeak) { buffer.push_back("AutoWeak"); } 44 | if (flags & UEPropertyFlags::ContainsInstancedReference) { buffer.push_back("ContainsInstancedReference"); } 45 | if (flags & UEPropertyFlags::AssetRegistrySearchable) { buffer.push_back("AssetRegistrySearchable"); } 46 | if (flags & UEPropertyFlags::SimpleDisplay) { buffer.push_back("SimpleDisplay"); } 47 | if (flags & UEPropertyFlags::AdvancedDisplay) { buffer.push_back("AdvancedDisplay"); } 48 | if (flags & UEPropertyFlags::Protected) { buffer.push_back("Protected"); } 49 | if (flags & UEPropertyFlags::BlueprintCallable) { buffer.push_back("BlueprintCallable"); } 50 | if (flags & UEPropertyFlags::BlueprintAuthorityOnly) { buffer.push_back("BlueprintAuthorityOnly"); } 51 | if (flags & UEPropertyFlags::TextExportTransient) { buffer.push_back("TextExportTransient"); } 52 | if (flags & UEPropertyFlags::NonPIEDuplicateTransient) { buffer.push_back("NonPIEDuplicateTransient"); } 53 | if (flags & UEPropertyFlags::ExposeOnSpawn) { buffer.push_back("ExposeOnSpawn"); } 54 | if (flags & UEPropertyFlags::PersistentInstance) { buffer.push_back("PersistentInstance"); } 55 | if (flags & UEPropertyFlags::UObjectWrapper) { buffer.push_back("UObjectWrapper"); } 56 | if (flags & UEPropertyFlags::HasGetValueTypeHash) { buffer.push_back("HasGetValueTypeHash"); } 57 | if (flags & UEPropertyFlags::NativeAccessSpecifierPublic) { buffer.push_back("NativeAccessSpecifierPublic"); } 58 | if (flags & UEPropertyFlags::NativeAccessSpecifierProtected) { buffer.push_back("NativeAccessSpecifierProtected"); } 59 | if (flags & UEPropertyFlags::NativeAccessSpecifierPrivate) { buffer.push_back("NativeAccessSpecifierPrivate"); } 60 | 61 | switch (buffer.size()) 62 | { 63 | case 0: 64 | return std::string(); 65 | case 1: 66 | return std::string(buffer[0]); 67 | default: 68 | std::ostringstream os; 69 | std::copy(buffer.begin(), buffer.end() - 1, std::ostream_iterator(os, ", ")); 70 | os << *buffer.rbegin(); 71 | return os.str(); 72 | } 73 | } -------------------------------------------------------------------------------- /Engine/UE4/PropertyFlags.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | enum class UEPropertyFlags : uint64_t 7 | { 8 | Edit = 0x0000000000000001, 9 | ConstParm = 0x0000000000000002, 10 | BlueprintVisible = 0x0000000000000004, 11 | ExportObject = 0x0000000000000008, 12 | BlueprintReadOnly = 0x0000000000000010, 13 | Net = 0x0000000000000020, 14 | EditFixedSize = 0x0000000000000040, 15 | Parm = 0x0000000000000080, 16 | OutParm = 0x0000000000000100, 17 | ZeroConstructor = 0x0000000000000200, 18 | ReturnParm = 0x0000000000000400, 19 | DisableEditOnTemplate = 0x0000000000000800, 20 | Transient = 0x0000000000002000, 21 | Config = 0x0000000000004000, 22 | DisableEditOnInstance = 0x0000000000010000, 23 | EditConst = 0x0000000000020000, 24 | GlobalConfig = 0x0000000000040000, 25 | InstancedReference = 0x0000000000080000, 26 | DuplicateTransient = 0x0000000000200000, 27 | SubobjectReference = 0x0000000000400000, 28 | SaveGame = 0x0000000001000000, 29 | NoClear = 0x0000000002000000, 30 | ReferenceParm = 0x0000000008000000, 31 | BlueprintAssignable = 0x0000000010000000, 32 | Deprecated = 0x0000000020000000, 33 | IsPlainOldData = 0x0000000040000000, 34 | RepSkip = 0x0000000080000000, 35 | RepNotify = 0x0000000100000000, 36 | Interp = 0x0000000200000000, 37 | NonTransactional = 0x0000000400000000, 38 | EditorOnly = 0x0000000800000000, 39 | NoDestructor = 0x0000001000000000, 40 | AutoWeak = 0x0000004000000000, 41 | ContainsInstancedReference = 0x0000008000000000, 42 | AssetRegistrySearchable = 0x0000010000000000, 43 | SimpleDisplay = 0x0000020000000000, 44 | AdvancedDisplay = 0x0000040000000000, 45 | Protected = 0x0000080000000000, 46 | BlueprintCallable = 0x0000100000000000, 47 | BlueprintAuthorityOnly = 0x0000200000000000, 48 | TextExportTransient = 0x0000400000000000, 49 | NonPIEDuplicateTransient = 0x0000800000000000, 50 | ExposeOnSpawn = 0x0001000000000000, 51 | PersistentInstance = 0x0002000000000000, 52 | UObjectWrapper = 0x0004000000000000, 53 | HasGetValueTypeHash = 0x0008000000000000, 54 | NativeAccessSpecifierPublic = 0x0010000000000000, 55 | NativeAccessSpecifierProtected = 0x0020000000000000, 56 | NativeAccessSpecifierPrivate = 0x0040000000000000 57 | }; 58 | 59 | inline bool operator&(UEPropertyFlags lhs, UEPropertyFlags rhs) 60 | { 61 | return (static_cast>(lhs) & static_cast>(rhs)) == static_cast>(rhs); 62 | } 63 | 64 | std::string StringifyFlags(const UEPropertyFlags flags); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Satisfactory SDK Generator 2 | A tool to generate an SDK for the game Satisfactory. 3 | 4 | ### Credits: 5 | KN4CK3R - Original UE4 SDK Generator 6 | Kronos - Satisfactory Engine Updates and Patterns 7 | -------------------------------------------------------------------------------- /SDK.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDK", "SDK.vcxproj", "{8421CC8C-A3DB-4F2F-9672-4DDAA9C9D391}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {8421CC8C-A3DB-4F2F-9672-4DDAA9C9D391}.Release|x64.ActiveCfg = Release|x64 14 | {8421CC8C-A3DB-4F2F-9672-4DDAA9C9D391}.Release|x64.Build.0 = Release|x64 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | GlobalSection(ExtensibilityGlobals) = postSolution 20 | SolutionGuid = {6B75601A-A585-41FC-8002-52E6E7F39A81} 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SDK.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | {8421CC8C-A3DB-4F2F-9672-4DDAA9C9D391} 11 | 10.0.18362.0 12 | 13 | 14 | 15 | DynamicLibrary 16 | false 17 | v141 18 | false 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | false 31 | 32 | 33 | 34 | 35 | 36 | $(IntDir)%(RelativeDir)\ 37 | .\Engine;.\Engine\UE4 38 | true 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /SDK.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Engine 6 | 7 | 8 | Engine 9 | 10 | 11 | Engine 12 | 13 | 14 | Engine 15 | 16 | 17 | Engine 18 | 19 | 20 | Engine\UE4 21 | 22 | 23 | Engine 24 | 25 | 26 | Engine 27 | 28 | 29 | Engine\UE4 30 | 31 | 32 | Engine\UE4 33 | 34 | 35 | Engine\UE4 36 | 37 | 38 | Engine 39 | 40 | 41 | Target 42 | 43 | 44 | Target 45 | 46 | 47 | Target 48 | 49 | 50 | Target 51 | 52 | 53 | 54 | 55 | {5fb70966-5939-4bcf-b096-6b909315ed0d} 56 | 57 | 58 | {77ff275a-574c-4908-9ae5-345300346f41} 59 | 60 | 61 | {a26524a5-e93e-4916-9676-f1b69c386a9e} 62 | 63 | 64 | 65 | 66 | Engine\UE4 67 | 68 | 69 | Engine 70 | 71 | 72 | Engine 73 | 74 | 75 | Engine 76 | 77 | 78 | Engine 79 | 80 | 81 | Engine 82 | 83 | 84 | Engine 85 | 86 | 87 | Engine\UE4 88 | 89 | 90 | Engine\UE4 91 | 92 | 93 | Engine 94 | 95 | 96 | Engine 97 | 98 | 99 | Engine 100 | 101 | 102 | Engine 103 | 104 | 105 | Target 106 | 107 | 108 | -------------------------------------------------------------------------------- /Target/Satisfactory/EngineClasses.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct FPointer 4 | { 5 | uintptr_t Dummy; 6 | }; 7 | 8 | struct FQWord 9 | { 10 | int32_t A; 11 | int32_t B; 12 | }; 13 | 14 | struct FName 15 | { 16 | int32_t ComparisonIndex; 17 | int32_t Number; 18 | }; 19 | 20 | template 21 | class TArray 22 | { 23 | friend class FString; 24 | 25 | public: 26 | TArray() 27 | { 28 | Data = nullptr; 29 | Count = Max = 0; 30 | }; 31 | 32 | size_t Num() const 33 | { 34 | return Count; 35 | }; 36 | 37 | T& operator[](size_t i) 38 | { 39 | return Data[i]; 40 | }; 41 | 42 | const T& operator[](size_t i) const 43 | { 44 | return Data[i]; 45 | }; 46 | 47 | bool IsValidIndex(size_t i) const 48 | { 49 | return i < Num(); 50 | } 51 | 52 | private: 53 | T* Data; 54 | int32_t Count; 55 | int32_t Max; 56 | }; 57 | 58 | template 59 | class TPair 60 | { 61 | public: 62 | KeyType Key; 63 | ValueType Value; 64 | }; 65 | 66 | class FString : public TArray 67 | { 68 | public: 69 | std::string ToString() const 70 | { 71 | const int size = WideCharToMultiByte(CP_UTF8, 0, Data, Count, nullptr, 0, nullptr, nullptr); 72 | std::string str(size, 0); 73 | WideCharToMultiByte(CP_UTF8, 0, Data, Count, &str[0], size, nullptr, nullptr); 74 | return str; 75 | } 76 | }; 77 | 78 | class FScriptInterface 79 | { 80 | private: 81 | UObject* ObjectPointer; 82 | void* InterfacePointer; 83 | 84 | public: 85 | UObject* GetObject() const 86 | { 87 | return ObjectPointer; 88 | } 89 | 90 | UObject*& GetObjectRef() 91 | { 92 | return ObjectPointer; 93 | } 94 | 95 | void* GetInterface() const 96 | { 97 | return ObjectPointer != nullptr ? InterfacePointer : nullptr; 98 | } 99 | }; 100 | 101 | template 102 | class TScriptInterface : public FScriptInterface 103 | { 104 | public: 105 | InterfaceType* operator->() const 106 | { 107 | return (InterfaceType*)GetInterface(); 108 | } 109 | 110 | InterfaceType& operator*() const 111 | { 112 | return *((InterfaceType*)GetInterface()); 113 | } 114 | 115 | operator bool() const 116 | { 117 | return GetInterface() != nullptr; 118 | } 119 | }; 120 | 121 | struct FText 122 | { 123 | char UnknownData[0x28]; 124 | }; 125 | 126 | struct FScriptDelegate 127 | { 128 | char UnknownData[0x14]; 129 | }; 130 | 131 | struct FScriptMulticastDelegate 132 | { 133 | char UnknownData[0x10]; 134 | }; 135 | 136 | struct FWeakObjectPtr 137 | { 138 | int32_t ObjectIndex; 139 | int32_t ObjectSerialNumber; 140 | }; 141 | 142 | struct FStringAssetReference 143 | { 144 | FString AssetLongPathname; 145 | }; 146 | 147 | template 148 | class TPersistentObjectPtr 149 | { 150 | public: 151 | FWeakObjectPtr WeakPtr; 152 | int32_t TagAtLastTest; 153 | TObjectID ObjectID; 154 | }; 155 | 156 | class FAssetPtr : public TPersistentObjectPtr 157 | { 158 | 159 | }; 160 | 161 | struct FSoftObjectPath 162 | { 163 | FName AssetPathName; 164 | FString SubPathString; 165 | }; 166 | 167 | class FSoftObjectPtr : public TPersistentObjectPtr 168 | { 169 | 170 | }; 171 | 172 | struct FGuid 173 | { 174 | uint32_t A; 175 | uint32_t B; 176 | uint32_t C; 177 | uint32_t D; 178 | }; 179 | 180 | struct FUniqueObjectGuid 181 | { 182 | FGuid Guid; 183 | }; 184 | 185 | class FLazyObjectPtr : public TPersistentObjectPtr 186 | { 187 | 188 | }; 189 | 190 | class UObject 191 | { 192 | public: 193 | FPointer VTableObject; 194 | int32_t ObjectFlags; 195 | int32_t InternalIndex; 196 | class UClass* Class; 197 | FName Name; 198 | UObject* Outer; 199 | }; 200 | 201 | class UField : public UObject 202 | { 203 | public: 204 | UField* Next; 205 | }; 206 | 207 | class UEnum : public UField 208 | { 209 | public: 210 | FString CppType; 211 | TArray> Names; 212 | int64_t CppForm; 213 | FText EnumDisplayNameFn; 214 | }; 215 | 216 | class UProperty : public UField 217 | { 218 | public: 219 | int32_t ArrayDim; 220 | int32_t ElementSize; 221 | FQWord PropertyFlags; 222 | int16_t RepIndex; 223 | uint8_t BlueprintReplicationCondition; 224 | char UnknownData[0x1]; 225 | int32_t Offset; 226 | FName RepNotifyFunc; 227 | UProperty* PropertyLinkNext; 228 | UProperty* NextRef; 229 | UProperty* DestructorLinkNext; 230 | UProperty* PostConstructLinkNext; 231 | }; 232 | 233 | class UStruct : public UField 234 | { 235 | public: 236 | char UnknownData00[0x10]; 237 | UStruct* SuperField; 238 | UField* Children; 239 | int32_t PropertySize; 240 | int32_t MinAlignment; 241 | char UnknownData01[0x40]; 242 | }; 243 | 244 | class UFunction : public UStruct 245 | { 246 | public: 247 | uint32_t FunctionFlags; 248 | uint8_t NumParms; 249 | char UnknownData00[0x1]; 250 | uint16_t ParmsSize; 251 | uint16_t ReturnValueOffset; 252 | uint16_t RPCId; 253 | uint16_t RPCResponseId; 254 | UProperty* FirstPropertyToInit; 255 | void* Func; 256 | }; 257 | 258 | class UClass : public UStruct 259 | { 260 | public: 261 | char UnknownData[0x1A0]; 262 | }; 263 | 264 | class UScriptStruct : public UStruct 265 | { 266 | public: 267 | char UnknownData[0x18]; 268 | }; 269 | 270 | class UNumericProperty : public UProperty 271 | { 272 | public: 273 | 274 | }; 275 | 276 | class UByteProperty : public UNumericProperty 277 | { 278 | public: 279 | UEnum* Enum; 280 | }; 281 | 282 | class UUInt16Property : public UNumericProperty 283 | { 284 | public: 285 | 286 | }; 287 | 288 | class UUInt32Property : public UNumericProperty 289 | { 290 | public: 291 | 292 | }; 293 | 294 | class UUInt64Property : public UNumericProperty 295 | { 296 | public: 297 | 298 | }; 299 | 300 | class UInt8Property : public UNumericProperty 301 | { 302 | public: 303 | 304 | }; 305 | 306 | class UInt16Property : public UNumericProperty 307 | { 308 | public: 309 | 310 | }; 311 | 312 | class UIntProperty : public UNumericProperty 313 | { 314 | public: 315 | 316 | }; 317 | 318 | class UInt64Property : public UNumericProperty 319 | { 320 | public: 321 | 322 | }; 323 | 324 | class UFloatProperty : public UNumericProperty 325 | { 326 | public: 327 | 328 | }; 329 | 330 | class UDoubleProperty : public UNumericProperty 331 | { 332 | public: 333 | 334 | }; 335 | 336 | class UBoolProperty : public UProperty 337 | { 338 | public: 339 | uint8_t FieldSize; 340 | uint8_t ByteOffset; 341 | uint8_t ByteMask; 342 | uint8_t FieldMask; 343 | }; 344 | 345 | class UObjectPropertyBase : public UProperty 346 | { 347 | public: 348 | UClass* PropertyClass; 349 | }; 350 | 351 | class UObjectProperty : public UObjectPropertyBase 352 | { 353 | public: 354 | 355 | }; 356 | 357 | class UClassProperty : public UObjectProperty 358 | { 359 | public: 360 | UClass* MetaClass; 361 | }; 362 | 363 | class UInterfaceProperty : public UProperty 364 | { 365 | public: 366 | UClass* InterfaceClass; 367 | }; 368 | 369 | class UWeakObjectProperty : public UObjectPropertyBase 370 | { 371 | public: 372 | 373 | }; 374 | 375 | class ULazyObjectProperty : public UObjectPropertyBase 376 | { 377 | public: 378 | 379 | }; 380 | 381 | class UAssetObjectProperty : public UObjectPropertyBase 382 | { 383 | public: 384 | 385 | }; 386 | 387 | class UAssetClassProperty : public UAssetObjectProperty 388 | { 389 | public: 390 | UClass* MetaClass; 391 | }; 392 | 393 | class UNameProperty : public UProperty 394 | { 395 | public: 396 | 397 | }; 398 | 399 | class UStructProperty : public UProperty 400 | { 401 | public: 402 | UScriptStruct* Struct; 403 | }; 404 | 405 | class UStrProperty : public UProperty 406 | { 407 | public: 408 | 409 | }; 410 | 411 | class UTextProperty : public UProperty 412 | { 413 | public: 414 | 415 | }; 416 | 417 | class UArrayProperty : public UProperty 418 | { 419 | public: 420 | UProperty* Inner; 421 | }; 422 | 423 | class UMapProperty : public UProperty 424 | { 425 | public: 426 | UProperty* KeyProp; 427 | UProperty* ValueProp; 428 | }; 429 | 430 | class UDelegateProperty : public UProperty 431 | { 432 | public: 433 | UFunction* SignatureFunction; 434 | }; 435 | 436 | class UMulticastDelegateProperty : public UProperty 437 | { 438 | public: 439 | UFunction* SignatureFunction; 440 | }; 441 | 442 | class UEnumProperty : public UProperty 443 | { 444 | public: 445 | UNumericProperty* UnderlyingProp; 446 | UEnum* Enum; 447 | }; 448 | -------------------------------------------------------------------------------- /Target/Satisfactory/Generator.cpp: -------------------------------------------------------------------------------- 1 | #include "NamesStore.hpp" 2 | 3 | class Generator : public IGenerator 4 | { 5 | public: 6 | bool Initialize(void* module) override 7 | { 8 | alignasClasses = { 9 | { "ScriptStruct CoreUObject.Plane", 16 }, 10 | { "ScriptStruct CoreUObject.Quat", 16 }, 11 | { "ScriptStruct CoreUObject.Transform", 16 }, 12 | { "ScriptStruct CoreUObject.Vector4", 16 }, 13 | { "ScriptStruct Engine.RootMotionSourceGroup", 8 } 14 | }; 15 | 16 | virtualFunctionPattern["Class CoreUObject.Object"] = { 17 | { "\x44\x88\x7D\x00\x48\x89", "xxxxxx", 0x400, R"( inline void ProcessEvent(class UFunction* function, void* parms) 18 | { 19 | return GetVFunction(this, %d)(this, function, parms); 20 | })" } 21 | }; 22 | virtualFunctionPattern["Class CoreUObject.Class"] = { 23 | { "\x4C\x8B\xDC\x57\x48\x81\xEC", "xxxxxxx", 0x200, R"( inline UObject* CreateDefaultObject() 24 | { 25 | return GetVFunction(this, %d)(this); 26 | })" } 27 | }; 28 | 29 | predefinedMembers["Class CoreUObject.Object"] = { 30 | { "void*", "Vtable" }, 31 | { "int32_t", "ObjectFlags" }, 32 | { "int32_t", "InternalIndex" }, 33 | { "class UClass*", "Class" }, 34 | { "FName", "Name" }, 35 | { "class UObject*", "Outer" } 36 | }; 37 | predefinedStaticMembers["Class CoreUObject.Object"] = { 38 | { "FUObjectArray*", "GObjects" } 39 | }; 40 | predefinedMembers["Class CoreUObject.Field"] = { 41 | { "class UField*", "Next" } 42 | }; 43 | predefinedMembers["Class CoreUObject.Struct"] = { 44 | { "char", "UnknownData00[0x10]"}, 45 | { "class UStruct*", "SuperField" }, 46 | { "class UField*", "Children" }, 47 | { "int32_t", "PropertySize" }, 48 | { "int32_t", "MinAlignment" }, 49 | { "char", "UnknownData01[0x40]"} 50 | }; 51 | predefinedMembers["Class CoreUObject.Function"] = { 52 | { "int32_t", "FunctionFlags" }, 53 | { "int8_t", "NumParms" }, 54 | { "char", "UnknownData[0x1]"}, 55 | { "int16_t", "ParmsSize" }, 56 | { "int16_t", "ReturnValueOffset" }, 57 | { "int16_t", "RPCId" }, 58 | { "int16_t", "RPCResponseId" }, 59 | { "class UProperty*", "FirstPropertyToInit" }, 60 | { "void*", "Func" } 61 | }; 62 | 63 | predefinedMethods["ScriptStruct CoreUObject.Vector2D"] = { 64 | PredefinedMethod::Inline(R"( inline FVector2D() 65 | : X(0), Y(0) 66 | { })"), 67 | PredefinedMethod::Inline(R"( inline FVector2D(float x, float y) 68 | : X(x), 69 | Y(y) 70 | { })") 71 | }; 72 | predefinedMethods["ScriptStruct CoreUObject.LinearColor"] = { 73 | PredefinedMethod::Inline(R"( inline FLinearColor() 74 | : R(0), G(0), B(0), A(0) 75 | { })"), 76 | PredefinedMethod::Inline(R"( inline FLinearColor(float r, float g, float b, float a) 77 | : R(r), 78 | G(g), 79 | B(b), 80 | A(a) 81 | { })") 82 | }; 83 | 84 | predefinedMethods["Class CoreUObject.Object"] = { 85 | PredefinedMethod::Inline(R"( static inline FChunkedFixedUObjectArray& GetGlobalObjects() 86 | { 87 | return GObjects->ObjObjects; 88 | })"), 89 | PredefinedMethod::Default("std::string GetName() const", R"(std::string UObject::GetName() const 90 | { 91 | std::string name(Name.GetName()); 92 | if (Name.Number > 0) 93 | { 94 | name += '_' + std::to_string(Name.Number); 95 | } 96 | 97 | auto pos = name.rfind('/'); 98 | if (pos == std::string::npos) 99 | { 100 | return name; 101 | } 102 | 103 | return name.substr(pos + 1); 104 | })"), 105 | PredefinedMethod::Default("std::string GetFullName() const", R"(std::string UObject::GetFullName() const 106 | { 107 | std::string name; 108 | 109 | if (Class != nullptr) 110 | { 111 | std::string temp; 112 | for (auto p = Outer; p; p = p->Outer) 113 | { 114 | temp = p->GetName() + "." + temp; 115 | } 116 | 117 | name = Class->GetName(); 118 | name += " "; 119 | name += temp; 120 | name += GetName(); 121 | } 122 | 123 | return name; 124 | })"), 125 | PredefinedMethod::Inline(R"( template 126 | static T* FindObject(const std::string& name) 127 | { 128 | for (int i = 0; i < GetGlobalObjects().Num(); ++i) 129 | { 130 | auto object = GetGlobalObjects().GetByIndex(i).Object; 131 | 132 | if (object == nullptr) 133 | { 134 | continue; 135 | } 136 | 137 | if (object->GetFullName() == name) 138 | { 139 | return static_cast(object); 140 | } 141 | } 142 | return nullptr; 143 | })"), 144 | PredefinedMethod::Inline(R"( static UClass* FindClass(const std::string& name) 145 | { 146 | return FindObject(name); 147 | })"), 148 | PredefinedMethod::Inline(R"( template 149 | static T* GetObjectCasted(std::size_t index) 150 | { 151 | return static_cast(GetGlobalObjects().GetByIndex(index).Object); 152 | })"), 153 | PredefinedMethod::Default("bool IsA(UClass* cmp) const", R"(bool UObject::IsA(UClass* cmp) const 154 | { 155 | for (auto super = Class; super; super = static_cast(super->SuperField)) 156 | { 157 | if (super == cmp) 158 | { 159 | return true; 160 | } 161 | } 162 | 163 | return false; 164 | })") 165 | }; 166 | predefinedMethods["Class CoreUObject.Class"] = { 167 | PredefinedMethod::Inline(R"( template 168 | inline T* CreateDefaultObject() 169 | { 170 | return static_cast(CreateDefaultObject()); 171 | })") 172 | }; 173 | 174 | predefinedMethods["Class Engine.World"] = { 175 | PredefinedMethod::Inline(R"( static UWorld** GWorld; 176 | static inline UWorld* GetWorld() 177 | { 178 | return *GWorld; 179 | };)") 180 | }; 181 | 182 | return true; 183 | } 184 | 185 | std::string GetGameName() const override 186 | { 187 | return "Satisfactory"; 188 | } 189 | 190 | std::string GetGameNameShort() const override 191 | { 192 | return "FG"; 193 | } 194 | 195 | std::string GetGameVersion() const override 196 | { 197 | return "V1.0"; 198 | } 199 | 200 | std::string GetNamespaceName() const override 201 | { 202 | return "SDK"; 203 | } 204 | 205 | std::vector GetIncludes() const override 206 | { 207 | return { }; 208 | } 209 | 210 | std::string GetOutputDirectory() const 211 | { 212 | return "C:/SDK_GEN"; //TODO: add a feature so users can customize this 213 | } 214 | 215 | std::string GetBasicDeclarations() const override 216 | { 217 | return R"(template 218 | inline Fn GetVFunction(const void *instance, std::size_t index) 219 | { 220 | auto vtable = *reinterpret_cast(const_cast(instance)); 221 | return reinterpret_cast(vtable[index]); 222 | } 223 | 224 | template 225 | class TArray 226 | { 227 | friend class FString; 228 | 229 | public: 230 | inline TArray() 231 | { 232 | Data = nullptr; 233 | Count = Max = 0; 234 | }; 235 | 236 | inline int Num() const 237 | { 238 | return Count; 239 | }; 240 | 241 | inline T& operator[](int i) 242 | { 243 | return Data[i]; 244 | }; 245 | 246 | inline const T& operator[](int i) const 247 | { 248 | return Data[i]; 249 | }; 250 | 251 | inline bool IsValidIndex(int i) const 252 | { 253 | return i < Num(); 254 | } 255 | 256 | private: 257 | T* Data; 258 | int Count; 259 | int Max; 260 | }; 261 | 262 | class UObject; 263 | 264 | class FUObjectItem 265 | { 266 | public: 267 | UObject* Object; 268 | int Flags; 269 | int ClusterRootIndex; 270 | int SerialNumber; 271 | }; 272 | 273 | class FChunkedFixedUObjectArray 274 | { 275 | public: 276 | inline int Num() const 277 | { 278 | return NumElements; 279 | } 280 | 281 | enum 282 | { 283 | NumElementsPerChunk = 64 * 1024, 284 | }; 285 | 286 | inline FUObjectItem const* GetObjectPtr(int Index) const 287 | { 288 | auto ChunkIndex = Index / NumElementsPerChunk; 289 | auto WithinChunkIndex = Index % NumElementsPerChunk; 290 | auto Chunk = Objects[ChunkIndex]; 291 | return Chunk + WithinChunkIndex; 292 | } 293 | 294 | inline FUObjectItem const& GetByIndex(int Index) const 295 | { 296 | return *GetObjectPtr(Index); 297 | } 298 | 299 | private: 300 | FUObjectItem** Objects; 301 | FUObjectItem* PreAllocatedObjects; 302 | int MaxElements; 303 | int NumElements; 304 | int MaxChunks; 305 | int NumChunks; 306 | }; 307 | 308 | class FUObjectArray 309 | { 310 | public: 311 | int ObjFirstGCIndex; 312 | int ObjLastNonGCIndex; 313 | int MaxObjectsNotConsideredByGC; 314 | bool OpenForDisregardForGC; 315 | FChunkedFixedUObjectArray ObjObjects; 316 | }; 317 | 318 | class FNameEntry 319 | { 320 | public: 321 | inline const char* GetAnsiName() const 322 | { 323 | return AnsiName; 324 | } 325 | 326 | inline const wchar_t* GetWideName() const 327 | { 328 | return WideName; 329 | } 330 | 331 | private: 332 | FNameEntry* HashNext; 333 | int Index; 334 | 335 | union 336 | { 337 | char AnsiName[1024]; 338 | wchar_t WideName[1024]; 339 | }; 340 | }; 341 | 342 | class TNameEntryArray 343 | { 344 | public: 345 | inline int Num() const 346 | { 347 | return NumElements; 348 | } 349 | 350 | inline bool IsValidIndex(int Index) const 351 | { 352 | return Index < Num() && Index >= 0; 353 | } 354 | 355 | inline FNameEntry const* const& operator[](int Index) const 356 | { 357 | return *GetItemPtr(Index); 358 | } 359 | 360 | private: 361 | enum { 362 | ElementsPerChunk = 16 * 1024, 363 | ChunkTableSize = (4 * 1024 * 1024 + ElementsPerChunk - 1) / ElementsPerChunk 364 | }; 365 | 366 | inline FNameEntry const* const* GetItemPtr(int Index) const 367 | { 368 | const auto ChunkIndex = Index / ElementsPerChunk; 369 | const auto WithinChunkIndex = Index % ElementsPerChunk; 370 | const auto Chunk = Chunks[ChunkIndex]; 371 | return Chunk + WithinChunkIndex; 372 | } 373 | 374 | FNameEntry** Chunks[ChunkTableSize]; 375 | int NumElements; 376 | int NumChunks; 377 | }; 378 | 379 | struct FName 380 | { 381 | int ComparisonIndex; 382 | int Number; 383 | 384 | inline FName() 385 | : ComparisonIndex(0), 386 | Number(0) 387 | { 388 | }; 389 | 390 | inline FName(int i) 391 | : ComparisonIndex(i), 392 | Number(0) 393 | { 394 | }; 395 | 396 | FName(const char* nameToFind) 397 | : ComparisonIndex(0), 398 | Number(0) 399 | { 400 | static std::unordered_set cache; 401 | 402 | for (auto i : cache) 403 | { 404 | if (!std::strcmp(GetGlobalNames()[i]->GetAnsiName(), nameToFind)) 405 | { 406 | ComparisonIndex = i; 407 | 408 | return; 409 | } 410 | } 411 | 412 | for (auto i = 0; i < GetGlobalNames().Num(); ++i) 413 | { 414 | if (GetGlobalNames()[i] != nullptr) 415 | { 416 | if (!std::strcmp(GetGlobalNames()[i]->GetAnsiName(), nameToFind)) 417 | { 418 | cache.insert(i); 419 | 420 | ComparisonIndex = i; 421 | 422 | return; 423 | } 424 | } 425 | } 426 | }; 427 | 428 | static TNameEntryArray *GNames; 429 | static inline TNameEntryArray& GetGlobalNames() 430 | { 431 | return *GNames; 432 | }; 433 | 434 | inline const char* GetName() const 435 | { 436 | return GetGlobalNames()[ComparisonIndex]->GetAnsiName(); 437 | }; 438 | 439 | inline bool operator==(const FName &other) const 440 | { 441 | return ComparisonIndex == other.ComparisonIndex; 442 | }; 443 | }; 444 | 445 | class FString : public TArray 446 | { 447 | public: 448 | inline FString() 449 | { 450 | }; 451 | 452 | FString(const wchar_t* other) 453 | { 454 | Max = Count = *other ? static_cast(std::wcslen(other)) + 1 : 0; 455 | 456 | if (Count) 457 | { 458 | Data = const_cast(other); 459 | } 460 | }; 461 | 462 | inline bool IsValid() const 463 | { 464 | return Data != nullptr; 465 | } 466 | 467 | inline const wchar_t* c_str() const 468 | { 469 | return Data; 470 | } 471 | 472 | std::string ToString() const 473 | { 474 | const auto length = std::wcslen(Data); 475 | 476 | std::string str(length, '\0'); 477 | 478 | std::use_facet>(std::locale()).narrow(Data, Data + length, '?', &str[0]); 479 | 480 | return str; 481 | } 482 | }; 483 | 484 | template 485 | class TEnumAsByte 486 | { 487 | public: 488 | inline TEnumAsByte() 489 | { 490 | } 491 | 492 | inline TEnumAsByte(TEnum _value) 493 | : value(static_cast(_value)) 494 | { 495 | } 496 | 497 | explicit inline TEnumAsByte(int32_t _value) 498 | : value(static_cast(_value)) 499 | { 500 | } 501 | 502 | explicit inline TEnumAsByte(uint8_t _value) 503 | : value(_value) 504 | { 505 | } 506 | 507 | inline operator TEnum() const 508 | { 509 | return (TEnum)value; 510 | } 511 | 512 | inline TEnum GetValue() const 513 | { 514 | return (TEnum)value; 515 | } 516 | 517 | private: 518 | uint8_t value; 519 | }; 520 | 521 | class FScriptInterface 522 | { 523 | private: 524 | UObject* ObjectPointer; 525 | void* InterfacePointer; 526 | 527 | public: 528 | inline UObject* GetObject() const 529 | { 530 | return ObjectPointer; 531 | } 532 | 533 | inline UObject*& GetObjectRef() 534 | { 535 | return ObjectPointer; 536 | } 537 | 538 | inline void* GetInterface() const 539 | { 540 | return ObjectPointer != nullptr ? InterfacePointer : nullptr; 541 | } 542 | }; 543 | 544 | template 545 | class TScriptInterface : public FScriptInterface 546 | { 547 | public: 548 | inline InterfaceType* operator->() const 549 | { 550 | return (InterfaceType*)GetInterface(); 551 | } 552 | 553 | inline InterfaceType& operator*() const 554 | { 555 | return *((InterfaceType*)GetInterface()); 556 | } 557 | 558 | inline operator bool() const 559 | { 560 | return GetInterface() != nullptr; 561 | } 562 | }; 563 | 564 | class FTextData { 565 | public: 566 | char UnknownData[0x28]; 567 | wchar_t* Name; 568 | __int32 Length; 569 | }; 570 | 571 | struct FText { 572 | FTextData* Data; 573 | char UnknownData[0x10]; 574 | 575 | wchar_t* Get() const { 576 | if (Data) 577 | return Data->Name; 578 | 579 | return nullptr; 580 | } 581 | }; 582 | 583 | struct FScriptDelegate 584 | { 585 | char UnknownData[0x14]; 586 | }; 587 | 588 | struct FScriptMulticastDelegate 589 | { 590 | char UnknownData[0x10]; 591 | }; 592 | 593 | template 594 | class TMap 595 | { 596 | char UnknownData[0x50]; 597 | }; 598 | 599 | struct FWeakObjectPtr 600 | { 601 | public: 602 | bool IsValid() const; 603 | 604 | UObject* Get() const; 605 | 606 | int32_t ObjectIndex; 607 | int32_t ObjectSerialNumber; 608 | }; 609 | 610 | template 611 | struct TWeakObjectPtr : private TWeakObjectPtrBase 612 | { 613 | public: 614 | inline T* Get() const 615 | { 616 | return (T*)TWeakObjectPtrBase::Get(); 617 | } 618 | 619 | inline T& operator*() const 620 | { 621 | return *Get(); 622 | } 623 | 624 | inline T* operator->() const 625 | { 626 | return Get(); 627 | } 628 | 629 | inline bool IsValid() const 630 | { 631 | return TWeakObjectPtrBase::IsValid(); 632 | } 633 | }; 634 | 635 | template 636 | class TAutoPointer : public TBASE 637 | { 638 | public: 639 | inline operator T*() const 640 | { 641 | return TBASE::Get(); 642 | } 643 | 644 | inline operator const T*() const 645 | { 646 | return (const T*)TBASE::Get(); 647 | } 648 | 649 | explicit inline operator bool() const 650 | { 651 | return TBASE::Get() != nullptr; 652 | } 653 | }; 654 | 655 | template 656 | class TAutoWeakObjectPtr : public TAutoPointer> 657 | { 658 | public: 659 | }; 660 | 661 | template 662 | class TPersistentObjectPtr 663 | { 664 | public: 665 | FWeakObjectPtr WeakPtr; 666 | int32_t TagAtLastTest; 667 | TObjectID ObjectID; 668 | }; 669 | 670 | struct FStringAssetReference_ 671 | { 672 | char UnknownData[0x10]; 673 | }; 674 | 675 | class FAssetPtr : public TPersistentObjectPtr 676 | { 677 | 678 | }; 679 | 680 | template 681 | class TAssetPtr : FAssetPtr 682 | { 683 | 684 | }; 685 | 686 | struct FSoftObjectPath 687 | { 688 | FName AssetPathName; 689 | FString SubPathString; 690 | }; 691 | 692 | class FSoftObjectPtr : public TPersistentObjectPtr 693 | { 694 | 695 | }; 696 | 697 | template 698 | class TSoftObjectPtr : FSoftObjectPtr 699 | { 700 | 701 | }; 702 | 703 | struct FUniqueObjectGuid_ 704 | { 705 | char UnknownData[0x10]; 706 | }; 707 | 708 | class FLazyObjectPtr : public TPersistentObjectPtr 709 | { 710 | 711 | }; 712 | 713 | template 714 | class TLazyObjectPtr : FLazyObjectPtr 715 | { 716 | 717 | }; 718 | 719 | class UClass; 720 | 721 | template 722 | class TSubclassOf 723 | { 724 | public: 725 | TSubclassOf(UClass* Class) { 726 | this->Class = Class; 727 | } 728 | 729 | inline UClass* GetClass() 730 | { 731 | return Class; 732 | } 733 | private: 734 | UClass* Class; 735 | };)"; 736 | } 737 | 738 | std::string GetBasicDefinitions() const override 739 | { 740 | return R"(TNameEntryArray* FName::GNames = nullptr; 741 | FUObjectArray* UObject::GObjects = nullptr; 742 | UWorld** UWorld::GWorld = nullptr;)"; 743 | } 744 | }; 745 | 746 | Generator _generator; 747 | IGenerator* generator = &_generator; 748 | -------------------------------------------------------------------------------- /Target/Satisfactory/GenericTypes.cpp: -------------------------------------------------------------------------------- 1 | #include "NameValidator.hpp" 2 | #include "NamesStore.hpp" 3 | #include "ObjectsStore.hpp" 4 | #include "EngineClasses.hpp" 5 | 6 | //--------------------------------------------------------------------------- 7 | //UEObject 8 | //--------------------------------------------------------------------------- 9 | size_t UEObject::GetIndex() const 10 | { 11 | return object->InternalIndex; 12 | } 13 | //--------------------------------------------------------------------------- 14 | UEClass UEObject::GetClass() const 15 | { 16 | return UEClass(object->Class); 17 | } 18 | //--------------------------------------------------------------------------- 19 | UEObject UEObject::GetOuter() const 20 | { 21 | return UEObject(object->Outer); 22 | } 23 | //--------------------------------------------------------------------------- 24 | std::string UEObject::GetName() const 25 | { 26 | auto name = NamesStore().GetById(object->Name.ComparisonIndex); 27 | if (object->Name.Number > 0) 28 | { 29 | name += '_' + std::to_string(object->Name.Number); 30 | } 31 | 32 | auto pos = name.rfind('/'); 33 | if (pos == std::string::npos) 34 | { 35 | return name; 36 | } 37 | 38 | return name.substr(pos + 1); 39 | } 40 | //--------------------------------------------------------------------------- 41 | UEClass UEObject::StaticClass() 42 | { 43 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Object"); 44 | return c; 45 | } 46 | //--------------------------------------------------------------------------- 47 | //UEField 48 | //--------------------------------------------------------------------------- 49 | UEField UEField::GetNext() const 50 | { 51 | return UEField(static_cast(object)->Next); 52 | } 53 | //--------------------------------------------------------------------------- 54 | UEClass UEField::StaticClass() 55 | { 56 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Field"); 57 | return c; 58 | } 59 | //--------------------------------------------------------------------------- 60 | //UEEnum 61 | //--------------------------------------------------------------------------- 62 | std::vector UEEnum::GetNames() const 63 | { 64 | std::vector buffer; 65 | auto& names = static_cast(object)->Names; 66 | 67 | for (auto i = 0; i < names.Num(); ++i) 68 | { 69 | //buffer.push_back(NamesStore().GetById(names[i].ComparisonIndex)); 70 | buffer.push_back(SimplifyEnumName(NamesStore().GetById(names[i].Key.ComparisonIndex))); 71 | } 72 | 73 | return buffer; 74 | } 75 | //--------------------------------------------------------------------------- 76 | UEClass UEEnum::StaticClass() 77 | { 78 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Enum"); 79 | return c; 80 | } 81 | //--------------------------------------------------------------------------- 82 | //UEConst 83 | //--------------------------------------------------------------------------- 84 | std::string UEConst::GetValue() const 85 | { 86 | throw; 87 | } 88 | //--------------------------------------------------------------------------- 89 | UEClass UEConst::StaticClass() 90 | { 91 | //not supported by UE4 92 | return nullptr; 93 | } 94 | //--------------------------------------------------------------------------- 95 | //UEStruct 96 | //--------------------------------------------------------------------------- 97 | UEStruct UEStruct::GetSuper() const 98 | { 99 | return UEStruct(static_cast(object)->SuperField); 100 | } 101 | //--------------------------------------------------------------------------- 102 | UEField UEStruct::GetChildren() const 103 | { 104 | return UEField(static_cast(object)->Children); 105 | } 106 | //--------------------------------------------------------------------------- 107 | size_t UEStruct::GetPropertySize() const 108 | { 109 | return static_cast(object)->PropertySize; 110 | } 111 | //--------------------------------------------------------------------------- 112 | UEClass UEStruct::StaticClass() 113 | { 114 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Struct"); 115 | return c; 116 | } 117 | //--------------------------------------------------------------------------- 118 | //UEScriptStruct 119 | //--------------------------------------------------------------------------- 120 | UEClass UEScriptStruct::StaticClass() 121 | { 122 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ScriptStruct"); 123 | return c; 124 | } 125 | //--------------------------------------------------------------------------- 126 | //UEFunction 127 | //--------------------------------------------------------------------------- 128 | UEFunctionFlags UEFunction::GetFunctionFlags() const 129 | { 130 | return static_cast(static_cast(object)->FunctionFlags); 131 | } 132 | //--------------------------------------------------------------------------- 133 | UEClass UEFunction::StaticClass() 134 | { 135 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Function"); 136 | return c; 137 | } 138 | //--------------------------------------------------------------------------- 139 | //UEClass 140 | //--------------------------------------------------------------------------- 141 | UEClass UEClass::StaticClass() 142 | { 143 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Class"); 144 | return c; 145 | } 146 | //--------------------------------------------------------------------------- 147 | //UEProperty 148 | //--------------------------------------------------------------------------- 149 | size_t UEProperty::GetArrayDim() const 150 | { 151 | return static_cast(object)->ArrayDim; 152 | } 153 | //--------------------------------------------------------------------------- 154 | size_t UEProperty::GetElementSize() const 155 | { 156 | return static_cast(object)->ElementSize; 157 | } 158 | //--------------------------------------------------------------------------- 159 | UEPropertyFlags UEProperty::GetPropertyFlags() const 160 | { 161 | return static_cast(static_cast(object)->PropertyFlags.A); 162 | } 163 | //--------------------------------------------------------------------------- 164 | size_t UEProperty::GetOffset() const 165 | { 166 | return static_cast(object)->Offset; 167 | } 168 | //--------------------------------------------------------------------------- 169 | UEClass UEProperty::StaticClass() 170 | { 171 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Property"); 172 | return c; 173 | } 174 | //--------------------------------------------------------------------------- 175 | //unsigned long UEProperty::GetBitMask() const 176 | //{ 177 | // unsigned long bm = static_cast(object)->BitMask; 178 | // return *(WORD*)((ULONG_PTR)&bm + 2); 179 | //} 180 | //--------------------------------------------------------------------------- 181 | //UENumericProperty 182 | //--------------------------------------------------------------------------- 183 | UEClass UENumericProperty::StaticClass() 184 | { 185 | static auto c = ObjectsStore().FindClass("Class CoreUObject.NumericProperty"); 186 | return c; 187 | } 188 | //--------------------------------------------------------------------------- 189 | //UEByteProperty 190 | //--------------------------------------------------------------------------- 191 | UEEnum UEByteProperty::GetEnum() const 192 | { 193 | return UEEnum(static_cast(object)->Enum); 194 | } 195 | //--------------------------------------------------------------------------- 196 | UEProperty::Info UEByteProperty::GetInfo() const 197 | { 198 | if (IsEnum()) 199 | { 200 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, "TEnumAsByte<" + MakeUniqueCppName(GetEnum()) + ">"); 201 | } 202 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, "unsigned char"); 203 | } 204 | //--------------------------------------------------------------------------- 205 | UEClass UEByteProperty::StaticClass() 206 | { 207 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ByteProperty"); 208 | return c; 209 | } 210 | //--------------------------------------------------------------------------- 211 | //UEUInt16Property 212 | //--------------------------------------------------------------------------- 213 | UEProperty::Info UEUInt16Property::GetInfo() const 214 | { 215 | return Info::Create(PropertyType::Primitive, sizeof(uint16_t), false, "uint16_t"); 216 | } 217 | //--------------------------------------------------------------------------- 218 | UEClass UEUInt16Property::StaticClass() 219 | { 220 | static auto c = ObjectsStore().FindClass("Class CoreUObject.UInt16Property"); 221 | return c; 222 | } 223 | //--------------------------------------------------------------------------- 224 | //UEUInt32Property 225 | //--------------------------------------------------------------------------- 226 | UEProperty::Info UEUInt32Property::GetInfo() const 227 | { 228 | return Info::Create(PropertyType::Primitive, sizeof(uint32_t), false, "uint32_t"); 229 | } 230 | //--------------------------------------------------------------------------- 231 | UEClass UEUInt32Property::StaticClass() 232 | { 233 | static auto c = ObjectsStore().FindClass("Class CoreUObject.UInt32Property"); 234 | return c; 235 | } 236 | //--------------------------------------------------------------------------- 237 | //UEUInt64Property 238 | //--------------------------------------------------------------------------- 239 | UEProperty::Info UEUInt64Property::GetInfo() const 240 | { 241 | return Info::Create(PropertyType::Primitive, sizeof(uint64_t), false, "uint64_t"); 242 | } 243 | //--------------------------------------------------------------------------- 244 | UEClass UEUInt64Property::StaticClass() 245 | { 246 | static auto c = ObjectsStore().FindClass("Class CoreUObject.UInt64Property"); 247 | return c; 248 | } 249 | //--------------------------------------------------------------------------- 250 | //UEInt8Property 251 | //--------------------------------------------------------------------------- 252 | UEProperty::Info UEInt8Property::GetInfo() const 253 | { 254 | return Info::Create(PropertyType::Primitive, sizeof(int8_t), false, "int8_t"); 255 | } 256 | //--------------------------------------------------------------------------- 257 | UEClass UEInt8Property::StaticClass() 258 | { 259 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Int8Property"); 260 | return c; 261 | } 262 | //--------------------------------------------------------------------------- 263 | //UEInt16Property 264 | //--------------------------------------------------------------------------- 265 | UEProperty::Info UEInt16Property::GetInfo() const 266 | { 267 | return Info::Create(PropertyType::Primitive, sizeof(int16_t), false, "int16_t"); 268 | } 269 | //--------------------------------------------------------------------------- 270 | UEClass UEInt16Property::StaticClass() 271 | { 272 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Int16Property"); 273 | return c; 274 | } 275 | //--------------------------------------------------------------------------- 276 | //UEIntProperty 277 | //--------------------------------------------------------------------------- 278 | UEProperty::Info UEIntProperty::GetInfo() const 279 | { 280 | return Info::Create(PropertyType::Primitive, sizeof(int), false, "int"); 281 | } 282 | //--------------------------------------------------------------------------- 283 | UEClass UEIntProperty::StaticClass() 284 | { 285 | static auto c = ObjectsStore().FindClass("Class CoreUObject.IntProperty"); 286 | return c; 287 | } 288 | //--------------------------------------------------------------------------- 289 | //UEInt64Property 290 | //--------------------------------------------------------------------------- 291 | UEProperty::Info UEInt64Property::GetInfo() const 292 | { 293 | return Info::Create(PropertyType::Primitive, sizeof(int64_t), false, "int64_t"); 294 | } 295 | //--------------------------------------------------------------------------- 296 | UEClass UEInt64Property::StaticClass() 297 | { 298 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Int64Property"); 299 | return c; 300 | } 301 | //--------------------------------------------------------------------------- 302 | //UEFloatProperty 303 | //--------------------------------------------------------------------------- 304 | UEProperty::Info UEFloatProperty::GetInfo() const 305 | { 306 | return Info::Create(PropertyType::Primitive, sizeof(float), false, "float"); 307 | } 308 | //--------------------------------------------------------------------------- 309 | UEClass UEFloatProperty::StaticClass() 310 | { 311 | static auto c = ObjectsStore().FindClass("Class CoreUObject.FloatProperty"); 312 | return c; 313 | } 314 | //--------------------------------------------------------------------------- 315 | //UEDoubleProperty 316 | //--------------------------------------------------------------------------- 317 | UEProperty::Info UEDoubleProperty::GetInfo() const 318 | { 319 | return Info::Create(PropertyType::Primitive, sizeof(double), false, "double"); 320 | } 321 | //--------------------------------------------------------------------------- 322 | UEClass UEDoubleProperty::StaticClass() 323 | { 324 | static auto c = ObjectsStore().FindClass("Class CoreUObject.DoubleProperty"); 325 | return c; 326 | } 327 | //--------------------------------------------------------------------------- 328 | //UEBoolProperty 329 | //--------------------------------------------------------------------------- 330 | uint8_t UEBoolProperty::GetFieldSize() const 331 | { 332 | return static_cast(object)->FieldSize; 333 | } 334 | //--------------------------------------------------------------------------- 335 | uint8_t UEBoolProperty::GetByteOffset() const 336 | { 337 | return static_cast(object)->ByteOffset; 338 | } 339 | //--------------------------------------------------------------------------- 340 | uint8_t UEBoolProperty::GetByteMask() const 341 | { 342 | return static_cast(object)->ByteMask; 343 | } 344 | //--------------------------------------------------------------------------- 345 | uint8_t UEBoolProperty::GetFieldMask() const 346 | { 347 | return static_cast(object)->FieldMask; 348 | } 349 | //--------------------------------------------------------------------------- 350 | UEProperty::Info UEBoolProperty::GetInfo() const 351 | { 352 | if (IsNativeBool()) 353 | { 354 | return Info::Create(PropertyType::Primitive, sizeof(bool), false, "bool"); 355 | } 356 | return Info::Create(PropertyType::Primitive, sizeof(unsigned char), false, "unsigned char"); 357 | } 358 | //--------------------------------------------------------------------------- 359 | UEClass UEBoolProperty::StaticClass() 360 | { 361 | static auto c = ObjectsStore().FindClass("Class CoreUObject.BoolProperty"); 362 | return c; 363 | } 364 | //--------------------------------------------------------------------------- 365 | //UEObjectPropertyBase 366 | //--------------------------------------------------------------------------- 367 | UEClass UEObjectPropertyBase::GetPropertyClass() const 368 | { 369 | return UEClass(static_cast(object)->PropertyClass); 370 | } 371 | //--------------------------------------------------------------------------- 372 | UEClass UEObjectPropertyBase::StaticClass() 373 | { 374 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ObjectPropertyBase"); 375 | return c; 376 | } 377 | //--------------------------------------------------------------------------- 378 | //UEObjectProperty 379 | //--------------------------------------------------------------------------- 380 | UEProperty::Info UEObjectProperty::GetInfo() const 381 | { 382 | return Info::Create(PropertyType::Primitive, sizeof(void*), false, "class " + MakeValidName(GetPropertyClass().GetNameCPP()) + "*"); 383 | } 384 | //--------------------------------------------------------------------------- 385 | UEClass UEObjectProperty::StaticClass() 386 | { 387 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ObjectProperty"); 388 | return c; 389 | } 390 | //--------------------------------------------------------------------------- 391 | //UEClassProperty 392 | //--------------------------------------------------------------------------- 393 | UEClass UEClassProperty::GetMetaClass() const 394 | { 395 | return UEClass(static_cast(object)->MetaClass); 396 | } 397 | //--------------------------------------------------------------------------- 398 | UEProperty::Info UEClassProperty::GetInfo() const 399 | { 400 | return Info::Create(PropertyType::Primitive, sizeof(void*), false, "class " + MakeValidName(GetMetaClass().GetNameCPP()) + "*"); 401 | } 402 | //--------------------------------------------------------------------------- 403 | UEClass UEClassProperty::StaticClass() 404 | { 405 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ClassProperty"); 406 | return c; 407 | } 408 | //--------------------------------------------------------------------------- 409 | //UEInterfaceProperty 410 | //--------------------------------------------------------------------------- 411 | UEClass UEInterfaceProperty::GetInterfaceClass() const 412 | { 413 | return UEClass(static_cast(object)->InterfaceClass); 414 | } 415 | //--------------------------------------------------------------------------- 416 | UEProperty::Info UEInterfaceProperty::GetInfo() const 417 | { 418 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FScriptInterface), true, "TScriptInterface"); 419 | } 420 | //--------------------------------------------------------------------------- 421 | UEClass UEInterfaceProperty::StaticClass() 422 | { 423 | static auto c = ObjectsStore().FindClass("Class CoreUObject.InterfaceProperty"); 424 | return c; 425 | } 426 | //--------------------------------------------------------------------------- 427 | //UEWeakObjectProperty 428 | //--------------------------------------------------------------------------- 429 | UEProperty::Info UEWeakObjectProperty::GetInfo() const 430 | { 431 | return Info::Create(PropertyType::Container, sizeof(FWeakObjectPtr), false, "TWeakObjectPtr"); 432 | } 433 | //--------------------------------------------------------------------------- 434 | UEClass UEWeakObjectProperty::StaticClass() 435 | { 436 | static auto c = ObjectsStore().FindClass("Class CoreUObject.WeakObjectProperty"); 437 | return c; 438 | } 439 | //--------------------------------------------------------------------------- 440 | //UELazyObjectProperty 441 | //--------------------------------------------------------------------------- 442 | UEProperty::Info UELazyObjectProperty::GetInfo() const 443 | { 444 | return Info::Create(PropertyType::Container, sizeof(FLazyObjectPtr), false, "TLazyObjectPtr"); 445 | } 446 | //--------------------------------------------------------------------------- 447 | UEClass UELazyObjectProperty::StaticClass() 448 | { 449 | static auto c = ObjectsStore().FindClass("Class CoreUObject.LazyObjectProperty"); 450 | return c; 451 | } 452 | //--------------------------------------------------------------------------- 453 | //UEAssetObjectProperty 454 | //--------------------------------------------------------------------------- 455 | UEProperty::Info UEAssetObjectProperty::GetInfo() const 456 | { 457 | return Info::Create(PropertyType::Container, sizeof(FAssetPtr), false, "TAssetPtr"); 458 | } 459 | //--------------------------------------------------------------------------- 460 | UEClass UEAssetObjectProperty::StaticClass() 461 | { 462 | static auto c = ObjectsStore().FindClass("Class CoreUObject.AssetObjectProperty"); 463 | return c; 464 | } 465 | //--------------------------------------------------------------------------- 466 | //UEAssetClassProperty 467 | //--------------------------------------------------------------------------- 468 | UEClass UEAssetClassProperty::GetMetaClass() const 469 | { 470 | return UEClass(static_cast(object)->MetaClass); 471 | } 472 | //--------------------------------------------------------------------------- 473 | UEProperty::Info UEAssetClassProperty::GetInfo() const 474 | { 475 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, ""); 476 | } 477 | //--------------------------------------------------------------------------- 478 | UEClass UEAssetClassProperty::StaticClass() 479 | { 480 | static auto c = ObjectsStore().FindClass("Class CoreUObject.AssetClassProperty"); 481 | return c; 482 | } 483 | //--------------------------------------------------------------------------- 484 | //UESoftObjectProperty 485 | //--------------------------------------------------------------------------- 486 | UEProperty::Info UESoftObjectProperty::GetInfo() const 487 | { 488 | return Info::Create(PropertyType::Container, sizeof(FSoftObjectPtr), false, "TSoftObjectPtr"); 489 | } 490 | //--------------------------------------------------------------------------- 491 | UEClass UESoftObjectProperty::StaticClass() 492 | { 493 | static auto c = ObjectsStore().FindClass("Class CoreUObject.SoftObjectProperty"); 494 | return c; 495 | } 496 | //--------------------------------------------------------------------------- 497 | //UENameProperty 498 | //--------------------------------------------------------------------------- 499 | UEProperty::Info UENameProperty::GetInfo() const 500 | { 501 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FName), true, "struct FName"); 502 | } 503 | //--------------------------------------------------------------------------- 504 | UEClass UENameProperty::StaticClass() 505 | { 506 | static auto c = ObjectsStore().FindClass("Class CoreUObject.NameProperty"); 507 | return c; 508 | } 509 | //--------------------------------------------------------------------------- 510 | //UEStructProperty 511 | //--------------------------------------------------------------------------- 512 | UEScriptStruct UEStructProperty::GetStruct() const 513 | { 514 | return UEScriptStruct(static_cast(object)->Struct); 515 | } 516 | //--------------------------------------------------------------------------- 517 | UEProperty::Info UEStructProperty::GetInfo() const 518 | { 519 | return Info::Create(PropertyType::CustomStruct, GetElementSize(), true, "struct " + MakeUniqueCppName(GetStruct())); 520 | } 521 | //--------------------------------------------------------------------------- 522 | UEClass UEStructProperty::StaticClass() 523 | { 524 | static auto c = ObjectsStore().FindClass("Class CoreUObject.StructProperty"); 525 | return c; 526 | } 527 | //--------------------------------------------------------------------------- 528 | //UEStrProperty 529 | //--------------------------------------------------------------------------- 530 | UEProperty::Info UEStrProperty::GetInfo() const 531 | { 532 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FString), true, "class FString"); 533 | } 534 | //--------------------------------------------------------------------------- 535 | UEClass UEStrProperty::StaticClass() 536 | { 537 | static auto c = ObjectsStore().FindClass("Class CoreUObject.StrProperty"); 538 | return c; 539 | } 540 | //--------------------------------------------------------------------------- 541 | //UETextProperty 542 | //--------------------------------------------------------------------------- 543 | UEProperty::Info UETextProperty::GetInfo() const 544 | { 545 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FText), true, "struct FText"); 546 | } 547 | //--------------------------------------------------------------------------- 548 | UEClass UETextProperty::StaticClass() 549 | { 550 | static auto c = ObjectsStore().FindClass("Class CoreUObject.TextProperty"); 551 | return c; 552 | } 553 | //--------------------------------------------------------------------------- 554 | //UEArrayProperty 555 | //--------------------------------------------------------------------------- 556 | UEProperty UEArrayProperty::GetInner() const 557 | { 558 | return UEProperty(static_cast(object)->Inner); 559 | } 560 | //--------------------------------------------------------------------------- 561 | UEProperty::Info UEArrayProperty::GetInfo() const 562 | { 563 | auto inner = GetInner().GetInfo(); 564 | if (inner.Type != PropertyType::Unknown) 565 | { 566 | extern IGenerator* generator; 567 | 568 | return Info::Create(PropertyType::Container, sizeof(TArray), false, "TArray<" + generator->GetOverrideType(inner.CppType) + ">"); 569 | } 570 | 571 | return { PropertyType::Unknown }; 572 | } 573 | //--------------------------------------------------------------------------- 574 | UEClass UEArrayProperty::StaticClass() 575 | { 576 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ArrayProperty"); 577 | return c; 578 | } 579 | //--------------------------------------------------------------------------- 580 | //UEMapProperty 581 | //--------------------------------------------------------------------------- 582 | UEProperty UEMapProperty::GetKeyProperty() const 583 | { 584 | return UEProperty(static_cast(object)->KeyProp); 585 | } 586 | //--------------------------------------------------------------------------- 587 | UEProperty UEMapProperty::GetValueProperty() const 588 | { 589 | return UEProperty(static_cast(object)->ValueProp); 590 | } 591 | //--------------------------------------------------------------------------- 592 | UEProperty::Info UEMapProperty::GetInfo() const 593 | { 594 | auto key = GetKeyProperty().GetInfo(); 595 | auto value = GetValueProperty().GetInfo(); 596 | if (key.Type != PropertyType::Unknown && value.Type != PropertyType::Unknown) 597 | { 598 | extern IGenerator* generator; 599 | 600 | return Info::Create(PropertyType::Container, 0x50, false, "TMap<" + generator->GetOverrideType(key.CppType) + ", " + generator->GetOverrideType(value.CppType) + ">"); 601 | } 602 | 603 | return { PropertyType::Unknown }; 604 | } 605 | //--------------------------------------------------------------------------- 606 | UEClass UEMapProperty::StaticClass() 607 | { 608 | static auto c = ObjectsStore().FindClass("Class CoreUObject.MapProperty"); 609 | return c; 610 | } 611 | //--------------------------------------------------------------------------- 612 | //UEDelegateProperty 613 | //--------------------------------------------------------------------------- 614 | UEFunction UEDelegateProperty::GetSignatureFunction() const 615 | { 616 | return UEFunction(static_cast(object)->SignatureFunction); 617 | } 618 | //--------------------------------------------------------------------------- 619 | UEProperty::Info UEDelegateProperty::GetInfo() const 620 | { 621 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FScriptDelegate), true, "struct FScriptDelegate"); 622 | } 623 | //--------------------------------------------------------------------------- 624 | UEClass UEDelegateProperty::StaticClass() 625 | { 626 | static auto c = ObjectsStore().FindClass("Class CoreUObject.DelegateProperty"); 627 | return c; 628 | } 629 | //--------------------------------------------------------------------------- 630 | //UEMulticastDelegateProperty 631 | //--------------------------------------------------------------------------- 632 | UEFunction UEMulticastDelegateProperty::GetSignatureFunction() const 633 | { 634 | return UEFunction(static_cast(object)->SignatureFunction); 635 | } 636 | //--------------------------------------------------------------------------- 637 | UEProperty::Info UEMulticastDelegateProperty::GetInfo() const 638 | { 639 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FScriptMulticastDelegate), true, "struct FScriptMulticastDelegate"); 640 | } 641 | //--------------------------------------------------------------------------- 642 | UEClass UEMulticastDelegateProperty::StaticClass() 643 | { 644 | static auto c = ObjectsStore().FindClass("Class CoreUObject.MulticastDelegateProperty"); 645 | return c; 646 | } 647 | //--------------------------------------------------------------------------- 648 | //UEEnumProperty 649 | //--------------------------------------------------------------------------- 650 | UENumericProperty UEEnumProperty::GetUnderlyingProperty() const 651 | { 652 | return UENumericProperty(static_cast(object)->UnderlyingProp); 653 | } 654 | //--------------------------------------------------------------------------- 655 | UEEnum UEEnumProperty::GetEnum() const 656 | { 657 | return UEEnum(static_cast(object)->Enum); 658 | } 659 | //--------------------------------------------------------------------------- 660 | UEProperty::Info UEEnumProperty::GetInfo() const 661 | { 662 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, MakeUniqueCppName(GetEnum())); 663 | } 664 | //--------------------------------------------------------------------------- 665 | UEClass UEEnumProperty::StaticClass() 666 | { 667 | static auto c = ObjectsStore().FindClass("Class CoreUObject.EnumProperty"); 668 | return c; 669 | } 670 | //--------------------------------------------------------------------------- 671 | 672 | //--------------------------------------------------------------------------- 673 | //GetCustomPropertyInfo for game depended properties. 674 | //--------------------------------------------------------------------------- 675 | bool UEProperty::GetCustomPropertyInfo(const UEProperty& property, Info &info) 676 | { 677 | return false; 678 | } 679 | //--------------------------------------------------------------------------- 680 | -------------------------------------------------------------------------------- /Target/Satisfactory/NamesStore.cpp: -------------------------------------------------------------------------------- 1 | #include "NamesStore.hpp" 2 | #include "PatternFinder.hpp" 3 | 4 | class FNameEntry 5 | { 6 | public: 7 | FNameEntry* HashNext; 8 | int Index; 9 | char AnsiName[1024]; 10 | }; 11 | 12 | class TNameEntryArray 13 | { 14 | public: 15 | enum 16 | { 17 | ElementsPerChunk = 16 * 1024, 18 | ChunkTableSize = (4 * 1024 * 1024 + ElementsPerChunk - 1) / ElementsPerChunk 19 | }; 20 | 21 | bool IsValidIndex(int Index) 22 | { 23 | return Index >= 0 && Index < NumElements && GetById(Index); 24 | } 25 | 26 | FNameEntry*& GetById(int Index) 27 | { 28 | return *GetItemPtr(Index); 29 | } 30 | 31 | FNameEntry** GetItemPtr(int Index) 32 | { 33 | auto ChunkIndex = Index / ElementsPerChunk; 34 | auto WithinChunkIndex = Index % ElementsPerChunk; 35 | auto Chunk = Chunks[ChunkIndex]; 36 | return Chunk + WithinChunkIndex; 37 | } 38 | 39 | FNameEntry** Chunks[ChunkTableSize]; 40 | int NumElements; 41 | int NumChunks; 42 | }; 43 | 44 | TNameEntryArray* GlobalNames; 45 | 46 | bool NamesStore::Initialize() 47 | { 48 | auto Address = FindPattern(GetModuleHandleW(0), (unsigned char*)"\x48\x8B\x05\x00\x00\x00\x03\x48\x85\xC0\x0F\x85\x81", "xxx???xxxxxxx"); 49 | GlobalNames = *(TNameEntryArray**)(Address + *(DWORD*)(Address + 0x3) + 0x7); 50 | 51 | return true; 52 | } 53 | 54 | void* NamesStore::GetAddress() 55 | { 56 | return GlobalNames; 57 | } 58 | 59 | size_t NamesStore::GetNamesNum() const 60 | { 61 | return GlobalNames->NumElements; 62 | } 63 | 64 | bool NamesStore::IsValid(size_t id) const 65 | { 66 | return GlobalNames->IsValidIndex(id); 67 | } 68 | 69 | std::string NamesStore::GetById(size_t id) const 70 | { 71 | return GlobalNames->GetById(id)->AnsiName; 72 | } 73 | -------------------------------------------------------------------------------- /Target/Satisfactory/ObjectsStore.cpp: -------------------------------------------------------------------------------- 1 | #include "ObjectsStore.hpp" 2 | #include "PatternFinder.hpp" 3 | 4 | class FUObjectItem 5 | { 6 | public: 7 | UObject* Object; 8 | int Flags; 9 | int ClusterRootIndex; 10 | int SerialNumber; 11 | }; 12 | 13 | class FChunkedFixedUObjectArray 14 | { 15 | public: 16 | enum 17 | { 18 | ElementsPerChunk = 64 * 1024 19 | }; 20 | 21 | FUObjectItem& GetByIndex(int Index) 22 | { 23 | return *GetObjectPtr(Index); 24 | } 25 | 26 | FUObjectItem* GetObjectPtr(int Index) 27 | { 28 | auto ChunkIndex = Index / ElementsPerChunk; 29 | auto WithinChunkIndex = Index % ElementsPerChunk; 30 | auto Chunk = Objects[ChunkIndex]; 31 | return Chunk + WithinChunkIndex; 32 | } 33 | 34 | FUObjectItem** Objects; 35 | FUObjectItem* PreAllocatedObjects; 36 | int MaxElements; 37 | int NumElements; 38 | int MaxChunks; 39 | int NumChunks; 40 | }; 41 | 42 | class FUObjectArray 43 | { 44 | public: 45 | int ObjFirstGCIndex; 46 | int ObjLastNonGCIndex; 47 | int MaxObjectsNotConsideredByGC; 48 | bool OpenForDisregardForGC; 49 | FChunkedFixedUObjectArray ObjObjects; 50 | }; 51 | 52 | FUObjectArray* GlobalObjects; 53 | 54 | bool ObjectsStore::Initialize() 55 | { 56 | auto Address = FindPattern(GetModuleHandleW(0), (unsigned char*)"\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x00\x00\x00\x0E\x00\x00\xE8", "xxx????x???xx???xxxx"); 57 | GlobalObjects = (FUObjectArray*)(Address + *(DWORD*)(Address + 0x3) + 0x7); 58 | 59 | return true; 60 | } 61 | 62 | void* ObjectsStore::GetAddress() 63 | { 64 | return GlobalObjects; 65 | } 66 | 67 | size_t ObjectsStore::GetObjectsNum() const 68 | { 69 | return GlobalObjects->ObjObjects.NumElements; 70 | } 71 | 72 | UEObject ObjectsStore::GetById(size_t id) const 73 | { 74 | return GlobalObjects->ObjObjects.GetByIndex(id).Object; 75 | } 76 | --------------------------------------------------------------------------------