├── .gitignore ├── README.md ├── SDKs └── BGMI_(v1.8.0)_64Bit.zip ├── Source ├── AndroidManifest.xml ├── jni │ ├── Android.mk │ ├── Application.mk │ └── src │ │ ├── EngineClasses.hpp │ │ ├── Generator.cpp │ │ ├── IGenerator.hpp │ │ ├── Includes.h │ │ ├── Logger.cpp │ │ ├── Logger.hpp │ │ ├── Main.cpp │ │ ├── Main.h │ │ ├── NameValidator.cpp │ │ ├── NameValidator.hpp │ │ ├── NamesStore.cpp │ │ ├── NamesStore.hpp │ │ ├── ObjectsStore.cpp │ │ ├── ObjectsStore.hpp │ │ ├── Package.cpp │ │ ├── Package.hpp │ │ ├── PrintHelper.cpp │ │ ├── PrintHelper.hpp │ │ ├── Tools.cpp │ │ ├── Tools.h │ │ ├── UE4 │ │ ├── FunctionFlags.cpp │ │ ├── FunctionFlags.hpp │ │ ├── GenericTypes.cpp │ │ ├── GenericTypes.hpp │ │ ├── PropertyFlags.cpp │ │ └── PropertyFlags.hpp │ │ ├── cpplinq.hpp │ │ └── tinyformat.h ├── libs │ └── arm64-v8a │ │ └── libnative-lib.so ├── ndk.cmd ├── project.properties ├── res │ └── values │ │ └── strings.xml └── src │ └── com │ └── ue4 │ └── sdkgen │ └── HelloJni.java └── Target └── BGMI ├── EngineClasses.hpp ├── Generator.cpp ├── GenericTypes.cpp ├── NamesStore.cpp └── ObjectsStore.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /Source/build 2 | /Source/gen 3 | /Source/bin 4 | /Source/obj -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## UE4-SDK-GENERATOR for Android 2 | UnrealEngine-4 Sdk Generator for Android Devices. 3 | * Generated SDKs [HERE](https://github.com/D-R-99/UE4SDKGenerator/tree/master/SDKs/) 4 | * This Tool is just Converted for Android from @KN4CK3R 's UE4SDKGen. 5 | * Currently Tested on 64Bit Version of BGMI, But can support other games that have EngineVersion from 4.18 to 4.22. 6 | 7 | ## How to Use: 8 | 9 | * Add Apk's pkgname and other details in Main.h. 10 | * Add GName and GObject Offsets in Main.h. 11 | * Change Files in Target Dir according to Game's structure and replace that files in Source Dir. 12 | * Compile all files in the Source Directory (x64 Release). 13 | * Comiple With AIDE(64bit NDK Support) -OR- 14 | * Compile With AndroidStudio (click on ndk.cmd file and RUN, if u have cmd execute plugin Installed.) 15 | * Add Lib in Apk. And add this Smali code to Load Lib 16 | 17 | ``` 18 | const-string v0, "native-lib" 19 | invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V 20 | ``` 21 | 22 | * Make sure Apk have Write Permission in media folder. 23 | * SDK will be Generated in /sdcard/Android/media/PKG-NAME folder. 24 | 25 | ## Notes 26 | 27 | * It will Start generating sdk after 5 second delay, at that time maybe not all objects loaded, so less files will be generated, Increase Delay in Main.cpp to Generate SDK in Lobby. 28 | * Generator.log This file contains the log messages the generator outputs. NamesDump.txt This file is generated if ShouldDumpArrays() is true and it contains all names available in the names array. ObjectsDump.txt This file is generated if ShouldDumpArrays() is true and it contains all objects names available in the objects array. SDK.hpp This file contains all includes you need for the SDK. 29 | * Most of the time you don't need all the cpp files. Add Needed Headers in SDK.hpp. 30 | 31 | ## ToDo 32 | 33 | * Adding Pattern scan for ProcessEvent. 34 | * Adding Missing Field like "ComponentToWorld". 35 | * Fix FunctionFlags not dumped in xxx_functions.cpp. 36 | 37 | if you have a suggestion on how to improve this sdk, please open an issue. 38 | -------------------------------------------------------------------------------- /SDKs/BGMI_(v1.8.0)_64Bit.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s4m33r89/UE4SDKGenerator/6f8125f03f9a7fe9ce07b19003e459ba266c7555/SDKs/BGMI_(v1.8.0)_64Bit.zip -------------------------------------------------------------------------------- /Source/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Source/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | MAIN_LOCAL_PATH := $(call my-dir) 3 | include $(CLEAR_VARS) 4 | 5 | # Here is the name of your lib. 6 | # When you change the lib name, change also on System.loadLibrary("") under OnCreate method on StaticActivity.java 7 | # Both must have same name 8 | LOCAL_MODULE := native-lib 9 | 10 | # Code optimization 11 | LOCAL_ARM_MODE := arm 12 | LOCAL_CFLAGS := -Wno-error=format-security -fpermissive 13 | LOCAL_CFLAGS += -fno-rtti -fno-exceptions -std=c++14 14 | LOCAL_CPPFLAGS += -ffunction-sections -fdata-sections 15 | LOCAL_LDFLAGS += -Wl,--strip-all 16 | 17 | # Here you add the cpp file 18 | LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH) 19 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/UE4 20 | LOCAL_SRC_FILES := src/Main.cpp \ 21 | src/Tools.cpp \ 22 | src/Logger.cpp \ 23 | src/UE4/FunctionFlags.cpp \ 24 | src/UE4/PropertyFlags.cpp \ 25 | src/ObjectsStore.cpp \ 26 | src/NamesStore.cpp \ 27 | src/Generator.cpp \ 28 | src/NameValidator.cpp \ 29 | src/UE4/GenericTypes.cpp \ 30 | src/PrintHelper.cpp \ 31 | src/Package.cpp \ 32 | 33 | 34 | LOCAL_LDLIBS := -llog -landroid 35 | include $(BUILD_SHARED_LIBRARY) 36 | -------------------------------------------------------------------------------- /Source/jni/Application.mk: -------------------------------------------------------------------------------- 1 | NDK_TOOLCHAIN_VERSION := 4.9 2 | APP_STL := c++_static 3 | APP_ABI := arm64-v8a 4 | -------------------------------------------------------------------------------- /Source/jni/src/EngineClasses.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef unsigned char uint8; 8 | typedef unsigned short int uint16; 9 | typedef unsigned int uint32; 10 | typedef unsigned long long uint64; 11 | 12 | // Signed base types. 13 | typedef signed char __int8; 14 | typedef signed short int __int16; 15 | typedef signed int __int32; 16 | typedef signed long long __int64; 17 | 18 | struct FPointer 19 | { 20 | uintptr_t Dummy; 21 | }; 22 | 23 | struct FQWord 24 | { 25 | int A; 26 | int B; 27 | }; 28 | 29 | struct FName 30 | { 31 | int32_t ComparisonIndex; 32 | int32_t Number; 33 | }; 34 | 35 | template 36 | struct TArray 37 | { 38 | friend struct FString; 39 | 40 | public: 41 | TArray() 42 | { 43 | Data = nullptr; 44 | Count = Max = 0; 45 | }; 46 | 47 | size_t Num() const 48 | { 49 | return Count; 50 | }; 51 | 52 | T& operator[](size_t i) 53 | { 54 | return Data[i]; 55 | }; 56 | 57 | const T& operator[](size_t i) const 58 | { 59 | return Data[i]; 60 | }; 61 | 62 | bool IsValidIndex(size_t i) const 63 | { 64 | return i < Num(); 65 | } 66 | 67 | private: 68 | T* Data; 69 | int32_t Count; 70 | int32_t Max; 71 | }; 72 | 73 | template 74 | class TPair 75 | { 76 | public: 77 | KeyType Key; 78 | ValueType Value; 79 | }; 80 | 81 | struct FString : public TArray 82 | { 83 | std::string ToString() const 84 | { 85 | //Add Later 86 | std::string str; 87 | return str; 88 | } 89 | }; 90 | 91 | class FScriptInterface 92 | { 93 | private: 94 | UObject* ObjectPointer; 95 | void* InterfacePointer; 96 | 97 | public: 98 | UObject* GetObject() const 99 | { 100 | return ObjectPointer; 101 | } 102 | 103 | UObject*& GetObjectRef() 104 | { 105 | return ObjectPointer; 106 | } 107 | 108 | void* GetInterface() const 109 | { 110 | return ObjectPointer != nullptr ? InterfacePointer : nullptr; 111 | } 112 | }; 113 | 114 | template 115 | class TScriptInterface : public FScriptInterface 116 | { 117 | public: 118 | InterfaceType* operator->() const 119 | { 120 | return (InterfaceType*)GetInterface(); 121 | } 122 | 123 | InterfaceType& operator*() const 124 | { 125 | return *((InterfaceType*)GetInterface()); 126 | } 127 | 128 | operator bool() const 129 | { 130 | return GetInterface() != nullptr; 131 | } 132 | }; 133 | 134 | struct FText 135 | { 136 | char UnknownData[0x18]; 137 | }; 138 | 139 | struct FWeakObjectPtr 140 | { 141 | int32_t ObjectIndex; 142 | int32_t ObjectSerialNumber; 143 | }; 144 | 145 | struct FStringAssetReference 146 | { 147 | FString AssetLongPathname; 148 | }; 149 | 150 | template 151 | class TPersistentObjectPtr 152 | { 153 | public: 154 | FWeakObjectPtr WeakPtr; 155 | int32_t TagAtLastTest; 156 | TObjectID ObjectID; 157 | }; 158 | 159 | class FAssetPtr : public TPersistentObjectPtr 160 | { 161 | 162 | }; 163 | 164 | struct FGuid 165 | { 166 | uint32_t A; 167 | uint32_t B; 168 | uint32_t C; 169 | uint32_t D; 170 | }; 171 | 172 | struct FUniqueObjectGuid 173 | { 174 | FGuid Guid; 175 | }; 176 | 177 | class FLazyObjectPtr : public TPersistentObjectPtr 178 | { 179 | 180 | }; 181 | 182 | struct FScriptDelegate 183 | { 184 | unsigned char UnknownData[16]; 185 | }; 186 | 187 | struct FScriptMulticastDelegate 188 | { 189 | unsigned char UnknownData[16]; 190 | }; 191 | 192 | class UClass; 193 | 194 | class UObject 195 | { 196 | public: 197 | FPointer VTableObject; //0 198 | int32_t ObjectFlags; //8 199 | int32_t InternalIndex; //c 200 | UClass* Class; //10 201 | FName Name; //18 202 | UObject* Outer; // 203 | }; 204 | 205 | class UField : public UObject 206 | { 207 | public: 208 | UField* Next; 209 | }; 210 | 211 | class UEnum : public UField 212 | { 213 | public: 214 | FString CppType; //0x0030 215 | TArray> Names; //0x0040 216 | __int64 CppForm; //0x0050 217 | }; 218 | 219 | class UStruct : public UField 220 | { 221 | public: 222 | UStruct* SuperField; 223 | UField* Children; 224 | int32_t PropertySize; 225 | int32_t MinAlignment; 226 | char pad_0x0048[0x28]; 227 | }; 228 | 229 | class UScriptStruct : public UStruct 230 | { 231 | public: 232 | char pad_0x0088[0x10]; //0x0088 233 | }; 234 | 235 | class UFunction : public UStruct 236 | { 237 | public: 238 | /*__int32 FunctionFlags; //0x0088 239 | __int16 RepOffset; //0x008C 240 | __int8 NumParms; //0x008E 241 | char pad_0x008F[0x1]; //0x008F 242 | __int16 ParmsSize; //0x0090 243 | __int16 ReturnValueOffset; //0x0092 244 | __int16 RPCId; //0x0094 245 | __int16 RPCResponseId; //0x0096 246 | class UProperty* FirstPropertyToInit; //0x0098 247 | UFunction* EventGraphFunction; //0x00A0 248 | __int32 EventGraphCallOffset; //0x00A8 249 | char pad_0x00AC[0x4]; //0x00AC 250 | void* Func; //0x00B0 251 | */ 252 | int32_t FunctionFlags; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 253 | int8_t NumParms; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 254 | int16_t ParmsSize; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 255 | int16_t ReturnValueOffset; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 256 | int16_t RPCId; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 257 | int16_t RPCResponseId; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 258 | char pad[0xC]; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 259 | void* Func; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 260 | 261 | }; 262 | 263 | class UClass : public UStruct 264 | { 265 | public: 266 | char pad_0x0088[0x170]; //0x0088 267 | }; 268 | 269 | class UProperty : public UField 270 | { 271 | public: 272 | __int32 ArrayDim; //0x0030 273 | __int32 ElementSize; //0x0034 274 | FQWord PropertyFlags; //0x0038 275 | __int32 PropertySize; //0x0040 276 | __int32 Offset; //0x0044 277 | char pad_0x0054[0x28]; //0x0048 278 | }; 279 | 280 | class UNumericProperty : public UProperty 281 | { 282 | public: 283 | 284 | }; 285 | 286 | class UByteProperty : public UNumericProperty 287 | { 288 | public: 289 | UEnum* Enum; // 0x0088 (0x04) 290 | }; 291 | 292 | class UUInt16Property : public UNumericProperty 293 | { 294 | public: 295 | 296 | }; 297 | 298 | class UUInt32Property : public UNumericProperty 299 | { 300 | public: 301 | 302 | }; 303 | 304 | class UUInt64Property : public UNumericProperty 305 | { 306 | public: 307 | 308 | }; 309 | 310 | class UInt8Property : public UNumericProperty 311 | { 312 | public: 313 | 314 | }; 315 | 316 | class UInt16Property : public UNumericProperty 317 | { 318 | public: 319 | 320 | }; 321 | 322 | class UIntProperty : public UNumericProperty 323 | { 324 | public: 325 | 326 | }; 327 | 328 | class UInt64Property : public UNumericProperty 329 | { 330 | public: 331 | 332 | }; 333 | 334 | class UFloatProperty : public UNumericProperty 335 | { 336 | public: 337 | 338 | }; 339 | 340 | class UDoubleProperty : public UNumericProperty 341 | { 342 | public: 343 | 344 | }; 345 | 346 | class UBoolProperty : public UProperty 347 | { 348 | public: 349 | uint8_t FieldSize; 350 | uint8_t ByteOffset; 351 | uint8_t ByteMask; 352 | uint8_t FieldMask; 353 | }; 354 | 355 | class UObjectPropertyBase : public UProperty 356 | { 357 | public: 358 | UClass* PropertyClass; 359 | }; 360 | 361 | class UObjectProperty : public UObjectPropertyBase 362 | { 363 | public: 364 | 365 | }; 366 | 367 | class UClassProperty : public UObjectProperty 368 | { 369 | public: 370 | UClass* MetaClass; 371 | }; 372 | 373 | class UInterfaceProperty : public UProperty 374 | { 375 | public: 376 | UClass* InterfaceClass; 377 | }; 378 | 379 | class UWeakObjectProperty : public UObjectPropertyBase 380 | { 381 | public: 382 | 383 | }; 384 | 385 | class ULazyObjectProperty : public UObjectPropertyBase 386 | { 387 | public: 388 | 389 | }; 390 | 391 | class UAssetObjectProperty : public UObjectPropertyBase 392 | { 393 | public: 394 | 395 | }; 396 | 397 | class UAssetClassProperty : public UAssetObjectProperty 398 | { 399 | public: 400 | UClass* MetaClass; 401 | }; 402 | 403 | class UNameProperty : public UProperty 404 | { 405 | public: 406 | 407 | }; 408 | 409 | class UStructProperty : public UProperty 410 | { 411 | public: 412 | UScriptStruct* Struct; 413 | }; 414 | 415 | class UStrProperty : public UProperty 416 | { 417 | public: 418 | 419 | }; 420 | 421 | class UTextProperty : public UProperty 422 | { 423 | public: 424 | 425 | }; 426 | 427 | class UArrayProperty : public UProperty 428 | { 429 | public: 430 | UProperty* Inner; 431 | }; 432 | 433 | class UMapProperty : public UProperty 434 | { 435 | public: 436 | UProperty* KeyProp; 437 | UProperty* ValueProp; 438 | }; 439 | 440 | class UDelegateProperty : public UProperty 441 | { 442 | public: 443 | UFunction* SignatureFunction; 444 | }; 445 | 446 | class UMulticastDelegateProperty : public UProperty 447 | { 448 | public: 449 | UFunction* SignatureFunction; 450 | }; 451 | 452 | class UEnumProperty : public UProperty 453 | { 454 | public: 455 | class UNumericProperty* UnderlyingProp; //0x0070 456 | class UEnum* Enum; //0x0078 457 | }; //Size: 0x0080 458 | -------------------------------------------------------------------------------- /Source/jni/src/Generator.cpp: -------------------------------------------------------------------------------- 1 | #include "IGenerator.hpp" 2 | #include "ObjectsStore.hpp" 3 | #include "NamesStore.hpp" 4 | #include "Main.h" 5 | 6 | class Generator : public IGenerator 7 | { 8 | public: 9 | bool Initialize(void* module) override 10 | { 11 | alignasClasses = { 12 | { "ScriptStruct CoreUObject.Plane", 16 }, 13 | { "ScriptStruct CoreUObject.Quat", 16 }, 14 | { "ScriptStruct CoreUObject.Transform", 16 }, 15 | { "ScriptStruct CoreUObject.Vector4", 16 }, 16 | 17 | { "ScriptStruct Engine.RootMotionSourceGroup", 8 } 18 | }; 19 | 20 | virtualFunctionPattern["Class CoreUObject.Object"] = { 21 | { "\x45\x33\xF6\x4D\x8B\xE0", "xxxxxx", 71, R"( inline void ProcessEvent(class UFunction* function, void* parms) 22 | { 23 | return GetVFunction(this, %d)(this, function, parms); 24 | })" 25 | ,71 } 26 | }; 27 | virtualFunctionPattern["Class CoreUObject.Class"] = { 28 | { "\x4C\x8B\xDC\x57\x48\x81\xEC", "xxxxxxx", 107, R"( inline UObject* CreateDefaultObject() 29 | { 30 | return GetVFunction(this, %d)(this); 31 | })" 32 | ,107 } 33 | }; 34 | 35 | predefinedMembers["Class CoreUObject.Object"] = { 36 | { "void*", "Vtable" }, 37 | { "int32_t", "ObjectFlags" }, 38 | { "int32_t", "InternalIndex" }, 39 | { "class UClass*", "Class" }, 40 | { "FName", "Name" }, 41 | { "class UObject*", "Outer" } 42 | }; 43 | predefinedStaticMembers["Class CoreUObject.Object"] = { 44 | { "FUObjectArray*", "GObjects" } 45 | }; 46 | predefinedMembers["Class CoreUObject.Field"] = { 47 | { "class UField*", "Next" } 48 | }; 49 | predefinedMembers["Class CoreUObject.Struct"] = { 50 | { "class UStruct*", "SuperField" }, 51 | { "class UField*", "Children" }, 52 | { "int32_t", "PropertySize" }, 53 | { "int32_t", "MinAlignment" }, 54 | { "unsigned char", "UnknownData0x0048[0x28]" } 55 | }; 56 | predefinedMembers["Class CoreUObject.Function"] = { 57 | { "int32_t", "FunctionFlags" }, 58 | //{ "int16_t", "RepOffset" }, 59 | { "int8_t", "NumParms" }, 60 | { "int16_t", "ParmsSize" }, 61 | { "int16_t", "ReturnValueOffset" }, 62 | { "int16_t", "RPCId" }, 63 | { "int16_t", "RPCResponseId" }, 64 | //{ "class UProperty*", "FirstPropertyToInit" }, 65 | //{ "class UFunction*", "EventGraphFunction" }, 66 | //{ "int32_t", "EventGraphCallOffset" }, 67 | { "unsigned char", "UnknownData0x00c[0xC]" }, 68 | { "void*", "Func" } 69 | }; 70 | 71 | predefinedMethods["ScriptStruct CoreUObject.Vector2D"] = { 72 | PredefinedMethod::Inline(R"( inline FVector2D() 73 | : X(0), Y(0) 74 | { })"), 75 | PredefinedMethod::Inline(R"( inline FVector2D(float x, float y) 76 | : X(x), 77 | Y(y) 78 | { })") 79 | }; 80 | predefinedMethods["ScriptStruct CoreUObject.LinearColor"] = { 81 | PredefinedMethod::Inline(R"( inline FLinearColor() 82 | : R(0), G(0), B(0), A(0) 83 | { })"), 84 | PredefinedMethod::Inline(R"( inline FLinearColor(float r, float g, float b, float a) 85 | : R(r), 86 | G(g), 87 | B(b), 88 | A(a) 89 | { })") 90 | }; 91 | 92 | predefinedMethods["Class CoreUObject.Object"] = { 93 | PredefinedMethod::Inline(R"( static inline TUObjectArray& GetGlobalObjects() 94 | { 95 | return GObjects->ObjObjects; 96 | })"), 97 | PredefinedMethod::Default("std::string GetName() const", R"(std::string UObject::GetName() const 98 | { 99 | std::string name(Name.GetName()); 100 | if (Name.Number > 0) 101 | { 102 | name += '_' + std::to_string(Name.Number); 103 | } 104 | 105 | auto pos = name.rfind('/'); 106 | if (pos == std::string::npos) 107 | { 108 | return name; 109 | } 110 | 111 | return name.substr(pos + 1); 112 | })"), 113 | PredefinedMethod::Default("std::string GetFullName() const", R"(std::string UObject::GetFullName() const 114 | { 115 | std::string name; 116 | 117 | if (Class != nullptr) 118 | { 119 | std::string temp; 120 | for (auto p = Outer; p; p = p->Outer) 121 | { 122 | temp = p->GetName() + "." + temp; 123 | } 124 | 125 | name = Class->GetName(); 126 | name += " "; 127 | name += temp; 128 | name += GetName(); 129 | } 130 | 131 | return name; 132 | })"), 133 | PredefinedMethod::Inline(R"( template 134 | static T* FindObject(const std::string& name) 135 | { 136 | for (int i = 0; i < GetGlobalObjects().Num(); ++i) 137 | { 138 | auto object = GetGlobalObjects().GetByIndex(i); 139 | 140 | if (object == nullptr) 141 | { 142 | continue; 143 | } 144 | 145 | if (object->GetFullName() == name) 146 | { 147 | return static_cast(object); 148 | } 149 | } 150 | return nullptr; 151 | })"), 152 | PredefinedMethod::Inline(R"( static UClass* FindClass(const std::string& name) 153 | { 154 | return FindObject(name); 155 | })"), 156 | PredefinedMethod::Inline(R"( template 157 | static T* GetObjectCasted(std::size_t index) 158 | { 159 | return static_cast(GetGlobalObjects().GetByIndex(index)); 160 | })"), 161 | PredefinedMethod::Default("bool IsA(UClass* cmp) const", R"(bool UObject::IsA(UClass* cmp) const 162 | { 163 | for (auto super = Class; super; super = static_cast(super->SuperField)) 164 | { 165 | if (super == cmp) 166 | { 167 | return true; 168 | } 169 | } 170 | 171 | return false; 172 | })") 173 | }; 174 | predefinedMethods["Class CoreUObject.Class"] = { 175 | PredefinedMethod::Inline(R"( template 176 | inline T* CreateDefaultObject() 177 | { 178 | return static_cast(CreateDefaultObject()); 179 | })") 180 | }; 181 | 182 | return true; 183 | } 184 | 185 | std::string GetGameName() const override 186 | { 187 | return gameFullName; 188 | } 189 | 190 | std::string GetGameNameShort() const override 191 | { 192 | return gameShortName; 193 | } 194 | 195 | std::string GetGameVersion() const override 196 | { 197 | return gameVersion; 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 GetBasicDeclarations() const override 211 | { 212 | return R"(template 213 | inline Fn GetVFunction(void *thiz, int idx) 214 | { 215 | auto VTable = *reinterpret_cast(const_cast(thiz)); 216 | return (Fn)(VTable[idx]); 217 | } 218 | 219 | class UObject; 220 | 221 | class FUObjectItem 222 | { 223 | public: 224 | UObject* Object; 225 | int32_t Flags; 226 | int32_t ClusterIndex; 227 | int32_t SerialNumber; 228 | 229 | enum class ObjectFlags : int32_t 230 | { 231 | None = 0, 232 | Native = 1 << 25, 233 | Async = 1 << 26, 234 | AsyncLoading = 1 << 27, 235 | Unreachable = 1 << 28, 236 | PendingKill = 1 << 29, 237 | RootSet = 1 << 30, 238 | NoStrongReference = 1 << 31 239 | }; 240 | 241 | inline bool IsUnreachable() const 242 | { 243 | return !!(Flags & static_cast>(ObjectFlags::Unreachable)); 244 | } 245 | inline bool IsPendingKill() const 246 | { 247 | return !!(Flags & static_cast>(ObjectFlags::PendingKill)); 248 | } 249 | }; 250 | 251 | class TUObjectArray 252 | { 253 | public: 254 | inline int32_t Num() const 255 | { 256 | return NumElements; 257 | } 258 | 259 | inline UObject* GetByIndex(int32_t index) const 260 | { 261 | return Objects[index].Object; 262 | } 263 | 264 | inline FUObjectItem* GetItemByIndex(int32_t index) const 265 | { 266 | if (index < NumElements) 267 | { 268 | return &Objects[index]; 269 | } 270 | return nullptr; 271 | } 272 | 273 | private: 274 | FUObjectItem* Objects; 275 | int32_t MaxElements; 276 | int32_t NumElements; 277 | }; 278 | 279 | class FUObjectArray 280 | { 281 | public: 282 | int32_t ObjFirstGCIndex; 283 | int32_t ObjLastNonGCIndex; 284 | int32_t MaxObjectsNotConsideredByGC; 285 | int32_t OpenForDisregardForGC; 286 | TUObjectArray ObjObjects; 287 | }; 288 | 289 | template 290 | struct TArray 291 | { 292 | friend struct FString; 293 | 294 | public: 295 | inline TArray() 296 | { 297 | Data = nullptr; 298 | Count = Max = 0; 299 | }; 300 | 301 | inline int Num() const 302 | { 303 | return Count; 304 | }; 305 | 306 | inline T& operator[](int i) 307 | { 308 | return Data[i]; 309 | }; 310 | 311 | inline const T& operator[](int i) const 312 | { 313 | return Data[i]; 314 | }; 315 | 316 | inline bool IsValidIndex(int i) const 317 | { 318 | return i < Num(); 319 | } 320 | 321 | private: 322 | T* Data; 323 | int32_t Count; 324 | int32_t Max; 325 | }; 326 | 327 | class FNameEntry 328 | { 329 | public: 330 | static const auto NAME_WIDE_MASK = 0x1; 331 | static const auto NAME_INDEX_SHIFT = 1; 332 | 333 | int32_t Index; 334 | #if defined(__LP64__) 335 | char pad[0x8]; 336 | #else 337 | char pad[0x4]; 338 | #endif 339 | 340 | union 341 | { 342 | char AnsiName[1024]; 343 | wchar_t WideName[1024]; 344 | }; 345 | 346 | inline const int32_t GetIndex() const 347 | { 348 | return Index >> NAME_INDEX_SHIFT; 349 | } 350 | 351 | inline bool IsWide() const 352 | { 353 | return Index & NAME_WIDE_MASK; 354 | } 355 | 356 | inline const char* GetAnsiName() const 357 | { 358 | return AnsiName; 359 | } 360 | 361 | inline const wchar_t* GetWideName() const 362 | { 363 | return WideName; 364 | } 365 | }; 366 | 367 | template 368 | class TStaticIndirectArrayThreadSafeRead 369 | { 370 | public: 371 | inline size_t Num() const 372 | { 373 | return NumElements; 374 | } 375 | 376 | inline bool IsValidIndex(int32_t index) const 377 | { 378 | return index < Num() && index > 0; 379 | } 380 | 381 | inline ElementType const* const& operator[](int32_t index) const 382 | { 383 | return *GetItemPtr(index); 384 | } 385 | 386 | private: 387 | inline ElementType const* const* GetItemPtr(int32_t Index) const 388 | { 389 | int32_t ChunkIndex = Index / ElementsPerChunk; 390 | int32_t WithinChunkIndex = Index % ElementsPerChunk; 391 | ElementType** Chunk = Chunks[ChunkIndex]; 392 | return Chunk + WithinChunkIndex; 393 | } 394 | 395 | enum 396 | { 397 | ChunkTableSize = (MaxTotalElements + ElementsPerChunk - 1) / ElementsPerChunk 398 | }; 399 | 400 | ElementType** Chunks[ChunkTableSize]; 401 | int32_t NumElements; 402 | int32_t NumChunks; 403 | }; 404 | 405 | using TNameEntryArray = TStaticIndirectArrayThreadSafeRead; 406 | 407 | struct FName 408 | { 409 | union 410 | { 411 | struct 412 | { 413 | int32_t ComparisonIndex; 414 | int32_t Number; 415 | }; 416 | }; 417 | 418 | inline FName() 419 | : ComparisonIndex(0), 420 | Number(0) 421 | { 422 | }; 423 | 424 | inline FName(int32_t i) 425 | : ComparisonIndex(i), 426 | Number(0) 427 | { 428 | }; 429 | 430 | FName(const char* nameToFind) 431 | : ComparisonIndex(0), 432 | Number(0) 433 | { 434 | static std::unordered_set cache; 435 | 436 | for (auto i : cache) 437 | { 438 | if (!std::strcmp(GetNames()[i]->GetAnsiName(), nameToFind)) 439 | { 440 | ComparisonIndex = i; 441 | 442 | return; 443 | } 444 | } 445 | 446 | for (auto i = 0; i < GetNames().Num(); ++i) 447 | { 448 | if (GetNames()[i] != nullptr) 449 | { 450 | if (!std::strcmp(GetNames()[i]->GetAnsiName(), nameToFind)) 451 | { 452 | cache.insert(i); 453 | 454 | ComparisonIndex = i; 455 | 456 | return; 457 | } 458 | } 459 | } 460 | }; 461 | 462 | static TNameEntryArray *GNames; 463 | static inline TNameEntryArray& GetNames() 464 | { 465 | return *GNames; 466 | }; 467 | 468 | inline const char* GetName() const 469 | { 470 | return GetNames()[ComparisonIndex]->GetAnsiName(); 471 | }; 472 | 473 | inline bool operator==(const FName &other) const 474 | { 475 | return ComparisonIndex == other.ComparisonIndex; 476 | }; 477 | }; 478 | 479 | struct FString : private TArray 480 | { 481 | inline FString() 482 | { 483 | } 484 | 485 | FString(const std::wstring s) 486 | { 487 | Max = Count = !s.empty() ? (s.length() * 2) + 1 : 0; 488 | if (Count) 489 | { 490 | Data = (unsigned short *)(s.data()); 491 | } 492 | } 493 | 494 | FString(const wchar_t *s) : FString(std::wstring(s)) { 495 | } 496 | 497 | FString(const wchar_t *s, int len) : FString(std::wstring(s, s + len)) { 498 | } 499 | 500 | FString(const std::string s) { 501 | std::wstring_convert> converter; 502 | std::wstring ws = converter.from_bytes(s); 503 | 504 | Max = Count = !ws.empty() ? (ws.length() * 2) + 1 : 0; 505 | if (Count) 506 | { 507 | Data = (unsigned short *)(ws.data()); 508 | } 509 | } 510 | 511 | FString(const char *s) : FString(std::string(s)) { 512 | } 513 | 514 | FString(const char *s, int len) : FString(std::string(s, s + len)) { 515 | } 516 | 517 | inline bool IsValid() const 518 | { 519 | return Data != nullptr; 520 | } 521 | 522 | inline const wchar_t* ToWString() const 523 | { 524 | wchar_t *output = new wchar_t[Count + 1]; 525 | 526 | for (int i = 0; i < Count; i++) { 527 | const char16_t uc = Data[i]; 528 | if (uc - 0xd800u >= 2048u) { 529 | output[i] = uc; 530 | } else { 531 | if ((uc & 0xfffffc00) == 0xd800 && (uc & 0xfffffc00) == 0xdc00) 532 | output[i] = (uc << 10) + Data[i] - 0x35fdc00; 533 | else 534 | output[i] = L'?'; 535 | } 536 | } 537 | 538 | output[Count] = 0; 539 | return output; 540 | } 541 | 542 | inline const char* ToString() const 543 | { 544 | std::wstring_convert,char16_t> convert; 545 | return convert.to_bytes(std::u16string(Data, Data + Count)).c_str(); 546 | } 547 | }; 548 | 549 | template 550 | class TEnumAsByte 551 | { 552 | public: 553 | inline TEnumAsByte() 554 | { 555 | } 556 | 557 | inline TEnumAsByte(TEnum _value) 558 | : value(static_cast(_value)) 559 | { 560 | } 561 | 562 | explicit inline TEnumAsByte(int32_t _value) 563 | : value(static_cast(_value)) 564 | { 565 | } 566 | 567 | explicit inline TEnumAsByte(uint8_t _value) 568 | : value(_value) 569 | { 570 | } 571 | 572 | inline operator TEnum() const 573 | { 574 | return (TEnum)value; 575 | } 576 | 577 | inline TEnum GetValue() const 578 | { 579 | return (TEnum)value; 580 | } 581 | 582 | private: 583 | uint8_t value; 584 | }; 585 | 586 | class FScriptInterface 587 | { 588 | private: 589 | UObject* ObjectPointer; 590 | void* InterfacePointer; 591 | 592 | public: 593 | inline UObject* GetObject() const 594 | { 595 | return ObjectPointer; 596 | } 597 | 598 | inline UObject*& GetObjectRef() 599 | { 600 | return ObjectPointer; 601 | } 602 | 603 | inline void* GetInterface() const 604 | { 605 | return ObjectPointer != nullptr ? InterfacePointer : nullptr; 606 | } 607 | }; 608 | 609 | template 610 | class TScriptInterface : public FScriptInterface 611 | { 612 | public: 613 | inline InterfaceType* operator->() const 614 | { 615 | return (InterfaceType*)GetInterface(); 616 | } 617 | 618 | inline InterfaceType& operator*() const 619 | { 620 | return *((InterfaceType*)GetInterface()); 621 | } 622 | 623 | inline operator bool() const 624 | { 625 | return GetInterface() != nullptr; 626 | } 627 | }; 628 | 629 | struct FText 630 | { 631 | #if defined(__LP64__) 632 | char pad[24]; 633 | #else 634 | char pad[12]; 635 | #endif 636 | }; 637 | 638 | struct FScriptDelegate 639 | { 640 | char pad[16]; 641 | }; 642 | 643 | struct FScriptMulticastDelegate 644 | { 645 | #if defined(__LP64__) 646 | char pad[16]; 647 | #else 648 | char pad[12]; 649 | #endif 650 | }; 651 | 652 | template 653 | class TMap 654 | { 655 | #if defined(__LP64__) 656 | char pad[80]; 657 | #else 658 | char pad[60]; 659 | #endif 660 | }; 661 | 662 | struct FWeakObjectPtr 663 | { 664 | public: 665 | inline bool SerialNumbersMatch(FUObjectItem* ObjectItem) const 666 | { 667 | return ObjectItem->SerialNumber == ObjectSerialNumber; 668 | } 669 | 670 | bool IsValid() const; 671 | 672 | UObject* Get() const; 673 | 674 | int32_t ObjectIndex; 675 | int32_t ObjectSerialNumber; 676 | }; 677 | 678 | template 679 | struct TWeakObjectPtr : private TWeakObjectPtrBase 680 | { 681 | public: 682 | inline T* Get() const 683 | { 684 | return (T*)TWeakObjectPtrBase::Get(); 685 | } 686 | 687 | inline T& operator*() const 688 | { 689 | return *Get(); 690 | } 691 | 692 | inline T* operator->() const 693 | { 694 | return Get(); 695 | } 696 | 697 | inline bool IsValid() const 698 | { 699 | return TWeakObjectPtrBase::IsValid(); 700 | } 701 | }; 702 | 703 | template 704 | class TAutoPointer : public TBASE 705 | { 706 | public: 707 | inline operator T*() const 708 | { 709 | return TBASE::Get(); 710 | } 711 | 712 | inline operator const T*() const 713 | { 714 | return (const T*)TBASE::Get(); 715 | } 716 | 717 | explicit inline operator bool() const 718 | { 719 | return TBASE::Get() != nullptr; 720 | } 721 | }; 722 | 723 | template 724 | class TAutoWeakObjectPtr : public TAutoPointer> 725 | { 726 | public: 727 | }; 728 | 729 | template 730 | class TPersistentObjectPtr 731 | { 732 | public: 733 | FWeakObjectPtr WeakPtr; 734 | int32_t TagAtLastTest; 735 | TObjectID ObjectID; 736 | }; 737 | 738 | struct FStringAssetReference_ 739 | { 740 | 741 | }; 742 | 743 | class FAssetPtr : public TPersistentObjectPtr 744 | { 745 | 746 | }; 747 | 748 | template 749 | class TAssetPtr : FAssetPtr 750 | { 751 | 752 | }; 753 | 754 | struct FUniqueObjectGuid_ 755 | { 756 | 757 | }; 758 | 759 | class FLazyObjectPtr : public TPersistentObjectPtr 760 | { 761 | 762 | }; 763 | 764 | template 765 | class TLazyObjectPtr : FLazyObjectPtr 766 | { 767 | 768 | };)"; 769 | } 770 | 771 | std::string GetBasicDefinitions() const override 772 | { 773 | return R"(TNameEntryArray* FName::GNames = nullptr; 774 | FUObjectArray* UObject::GUObjectArray = nullptr; 775 | //--------------------------------------------------------------------------- 776 | bool FWeakObjectPtr::IsValid() const 777 | { 778 | if (ObjectSerialNumber == 0) 779 | { 780 | return false; 781 | } 782 | if (ObjectIndex < 0) 783 | { 784 | return false; 785 | } 786 | auto ObjectItem = UObject::GetGlobalObjects().GetItemByIndex(ObjectIndex); 787 | if (!ObjectItem) 788 | { 789 | return false; 790 | } 791 | if (!SerialNumbersMatch(ObjectItem)) 792 | { 793 | return false; 794 | } 795 | return !(ObjectItem->IsUnreachable() || ObjectItem->IsPendingKill()); 796 | } 797 | //--------------------------------------------------------------------------- 798 | UObject* FWeakObjectPtr::Get() const 799 | { 800 | if (IsValid()) 801 | { 802 | auto ObjectItem = UObject::GetGlobalObjects().GetItemByIndex(ObjectIndex); 803 | if (ObjectItem) 804 | { 805 | return ObjectItem->Object; 806 | } 807 | } 808 | return nullptr; 809 | } 810 | //---------------------------------------------------------------------------)"; 811 | } 812 | }; 813 | 814 | Generator _generator; 815 | IGenerator* generator = &_generator; 816 | -------------------------------------------------------------------------------- /Source/jni/src/IGenerator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | //#include "Dyno.h" 8 | 9 | class IGenerator 10 | { 11 | public: 12 | virtual ~IGenerator() = default; 13 | 14 | /// 15 | /// Initializes this object. 16 | /// Add predefined types, ... 17 | /// 18 | /// The module handle. 19 | /// true if it succeeds, false if it fails. 20 | virtual bool Initialize(void* module) = 0; 21 | 22 | /// 23 | /// Gets output directory where the files are getting stored. 24 | /// The name of the game gets appended to this directory. 25 | /// 26 | /// The output directory. 27 | virtual std::string GetOutputDirectory(std::string pkgName1) const 28 | { 29 | //std::string pkgName1 = "com.pubg.imobile"; 30 | std::string Media_Folder1 = "/storage/emulated/0/Android/media/" + pkgName1; 31 | return Media_Folder1; 32 | } 33 | 34 | /// 35 | /// Gets the name of the game. 36 | /// 37 | /// The game name. 38 | virtual std::string GetGameName() const = 0; 39 | 40 | /// 41 | /// Gets the short name of the game. 42 | /// 43 | /// The short name. 44 | virtual std::string GetGameNameShort() const = 0; 45 | 46 | /// 47 | /// Gets the version of the game. 48 | /// 49 | /// The version of the game. 50 | virtual std::string GetGameVersion() const = 0; 51 | 52 | /// 53 | /// Check if the generator should dump the object and name arrays. 54 | /// 55 | /// true if the arrays should get dumped. 56 | virtual bool ShouldDumpArrays() const 57 | { 58 | return true; 59 | } 60 | 61 | /// 62 | /// Check if the generator should generate empty files (no classes, structs, ...). 63 | /// 64 | /// true if empty files should get generated. 65 | virtual bool ShouldGenerateEmptyFiles() const 66 | { 67 | return false; 68 | } 69 | 70 | /// 71 | /// Check if the generated classes should use strings to identify objects. 72 | /// If false the generated classes use the object index. 73 | /// Warning: The object index may change for non default classes. 74 | /// 75 | /// true if strings should be used. 76 | virtual bool ShouldUseStrings() const 77 | { 78 | return true; 79 | } 80 | 81 | /// 82 | /// Check if strings () should be xor encoded. 83 | /// 84 | /// true if string should be xor encoded. 85 | virtual bool ShouldXorStrings() const 86 | { 87 | return false; 88 | } 89 | 90 | /// 91 | /// Check if static methods should get converted to normal methods. 92 | /// Static methods require a CreateDefaultObject() method in the UObject class. 93 | /// 94 | /// true if static methods should get converted to normal methods. 95 | virtual bool ShouldConvertStaticMethods() const 96 | { 97 | return true; 98 | } 99 | 100 | /// 101 | /// Check if we should generate a function parameters file. 102 | /// Otherwise the parameters are declared inside the function body. 103 | /// If hooks with access to the parameters are need, this method should return true. 104 | /// 105 | /// True if a function parameters file should be generated. 106 | virtual bool ShouldGenerateFunctionParametersFile() const 107 | { 108 | return true; 109 | } 110 | 111 | /// 112 | /// Gets namespace name for the classes. If the name is empty no namespace gets generated. 113 | /// 114 | /// The namespace name. 115 | virtual std::string GetNamespaceName() const 116 | { 117 | return std::string(); 118 | } 119 | 120 | /// 121 | /// Gets a list of custom include files which gets inserted in the SDK. 122 | /// 123 | /// The list of include files. 124 | virtual std::vector GetIncludes() const 125 | { 126 | return {}; 127 | } 128 | 129 | /// 130 | /// Gets the member alignment. 131 | /// https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx 132 | /// 133 | /// The member alignment. 134 | virtual size_t GetGlobalMemberAlignment() const 135 | { 136 | return sizeof(size_t); 137 | } 138 | 139 | /// 140 | /// Gets alignas size for the specific class. 141 | /// http://cppreference.com/w/cpp/language/alignas 142 | /// 143 | /// The name. 144 | /// If the class is not found the return value is 0, else the alignas size. 145 | virtual size_t GetClassAlignas(const std::string& name) const 146 | { 147 | auto it = alignasClasses.find(name); 148 | if (it != std::end(alignasClasses)) 149 | { 150 | return it->second; 151 | } 152 | return 0; 153 | } 154 | 155 | /// 156 | /// Gets the declarations of some basic classes and methods. 157 | /// 158 | /// The basic declarations. 159 | virtual std::string GetBasicDeclarations() const 160 | { 161 | return std::string(); 162 | } 163 | 164 | /// 165 | /// Gets the definitions of the declarations. 166 | /// 167 | /// The basic definitions. 168 | virtual std::string GetBasicDefinitions() const 169 | { 170 | return std::string(); 171 | } 172 | 173 | /// 174 | /// Checks if an override is defined for the given type. 175 | /// 176 | /// The parameter type. 177 | /// If no override is found the original name is returned. 178 | virtual std::string GetOverrideType(const std::string& type) const 179 | { 180 | auto it = overrideTypes.find(type); 181 | if (it == std::end(overrideTypes)) 182 | { 183 | return type; 184 | } 185 | return it->second; 186 | } 187 | 188 | struct PredefinedMember 189 | { 190 | std::string Type; 191 | std::string Name; 192 | }; 193 | 194 | /// 195 | /// Gets the predefined members of the specific class. 196 | /// 197 | /// The name of the class. 198 | /// [out] The predefined members. 199 | /// true if predefined members are found. 200 | virtual bool GetPredefinedClassMembers(const std::string& name, std::vector& members) const 201 | { 202 | auto it = predefinedMembers.find(name); 203 | if (it != std::end(predefinedMembers)) 204 | { 205 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(members)); 206 | 207 | return true; 208 | } 209 | 210 | return false; 211 | } 212 | 213 | /// 214 | /// Gets the static predefined members of the specific class. 215 | /// 216 | /// The name of the class. 217 | /// [out] The predefined members. 218 | /// true if predefined members are found. 219 | virtual bool GetPredefinedClassStaticMembers(const std::string& name, std::vector& members) const 220 | { 221 | auto it = predefinedStaticMembers.find(name); 222 | if (it != std::end(predefinedStaticMembers)) 223 | { 224 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(members)); 225 | 226 | return true; 227 | } 228 | 229 | return false; 230 | } 231 | 232 | using VirtualFunctionPatterns = std::vector>; 233 | 234 | /// 235 | /// Gets the patterns of virtual functions of the specific class. 236 | /// The generator loops the virtual functions of the class and adds a class method if the pattern matches. 237 | /// 238 | /// The name of the class. 239 | /// [out] The patterns. 240 | /// true if patterns are found. 241 | virtual bool GetVirtualFunctionPatterns(const std::string& name, VirtualFunctionPatterns& patterns) const 242 | { 243 | auto it = virtualFunctionPattern.find(name); 244 | if (it != std::end(virtualFunctionPattern)) 245 | { 246 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(patterns)); 247 | 248 | return true; 249 | } 250 | 251 | return false; 252 | } 253 | 254 | struct PredefinedMethod 255 | { 256 | enum class Type 257 | { 258 | Default, 259 | Inline 260 | }; 261 | 262 | std::string Signature; 263 | std::string Body; 264 | Type MethodType; 265 | 266 | /// Adds a predefined method which gets splittet in declaration and definition. 267 | /// The method signature. 268 | /// The method body. 269 | /// The method. 270 | static PredefinedMethod Default(std::string&& signature, std::string&& body) 271 | { 272 | return { signature, body, Type::Default }; 273 | } 274 | 275 | /// Adds a predefined method which gets included as an inline method. 276 | /// The body. 277 | /// The method. 278 | static PredefinedMethod Inline(std::string&& body) 279 | { 280 | return { std::string(), body, Type::Inline }; 281 | } 282 | }; 283 | 284 | /// Gets the predefined methods of the specific class. 285 | /// The name of the class. 286 | /// [out] The predefined methods. 287 | /// true if predefined methods are found. 288 | virtual bool GetPredefinedClassMethods(const std::string& name, std::vector& methods) const 289 | { 290 | auto it = predefinedMethods.find(name); 291 | if (it != std::end(predefinedMethods)) 292 | { 293 | std::copy(std::begin(it->second), std::end(it->second), std::back_inserter(methods)); 294 | 295 | return true; 296 | } 297 | 298 | return false; 299 | } 300 | 301 | protected: 302 | std::unordered_map alignasClasses; 303 | std::unordered_map overrideTypes; 304 | std::unordered_map> predefinedMembers; 305 | std::unordered_map> predefinedStaticMembers; 306 | std::unordered_map> predefinedMethods; 307 | std::unordered_map virtualFunctionPattern; 308 | }; 309 | -------------------------------------------------------------------------------- /Source/jni/src/Includes.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDES_H 2 | #define INCLUDES_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | //#include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | enum daLogType { 48 | daDEBUG = 3, 49 | daERROR = 6, 50 | daINFO = 4, 51 | daWARN = 5 52 | }; 53 | 54 | //Change this to another Log Tag if ya want. IN the batch script I provide you change the log tag then too 55 | #define TAG "Dyno-SDKGen" 56 | 57 | #define LOGD(...) ((void)__android_log_print(daDEBUG, TAG, __VA_ARGS__)) 58 | #define LOGE(...) ((void)__android_log_print(daERROR, TAG, __VA_ARGS__)) 59 | #define LOGI(...) ((void)__android_log_print(daINFO, TAG, __VA_ARGS__)) 60 | #define LOGW(...) ((void)__android_log_print(daWARN, TAG, __VA_ARGS__)) 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /Source/jni/src/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 | -------------------------------------------------------------------------------- /Source/jni/src/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 | -------------------------------------------------------------------------------- /Source/jni/src/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "Main.h" 2 | #include "Tools.h" 3 | #include "cpplinq.hpp" 4 | #include "tinyformat.h" 5 | 6 | #include "Logger.hpp" 7 | 8 | #include "IGenerator.hpp" 9 | 10 | #include "ObjectsStore.hpp" 11 | #include "NamesStore.hpp" 12 | #include "Package.hpp" 13 | #include "NameValidator.hpp" 14 | 15 | #include "PrintHelper.hpp" 16 | 17 | extern IGenerator* generator; 18 | 19 | /// 20 | /// Dumps the objects and names to files. 21 | /// 22 | /// The path where to create the dumps. 23 | void Dump(std::string path) 24 | { 25 | { 26 | std::ofstream o(path + "/" + "ObjectsDump.txt"); 27 | tfm::format(o, "Address: %P\n\n", ObjectsStore::GetAddress()); 28 | 29 | for (auto obj : ObjectsStore()) 30 | { 31 | tfm::format(o, "[%06i] %-100s 0x%P\n", obj.GetIndex(), obj.GetFullName(), obj.GetAddress()); 32 | } 33 | } 34 | 35 | { 36 | std::ofstream o(path + "/" + "NamesDump.txt"); 37 | tfm::format(o, "Address: %P\n\n", NamesStore::GetAddress()); 38 | 39 | for (auto name : NamesStore()) 40 | { 41 | tfm::format(o, "[%06i] %s\n", name.Index, name.Name); 42 | } 43 | } 44 | } 45 | 46 | void SaveSDKHeader(std::string path, const std::unordered_map& processedObjects, const std::vector>& packages) 47 | { 48 | std::ofstream os(path + "/" + "SDK.hpp"); 49 | 50 | os << "#pragma once\n\n" 51 | << tfm::format("// %s (%s) SDK by Dyno\n\n", generator->GetGameName(), generator->GetGameVersion()); 52 | 53 | //Includes 54 | os << "#include \n"; 55 | os << "#include \n"; 56 | for (auto&& i : generator->GetIncludes()) 57 | { 58 | os << "#include " << i << "\n"; 59 | } 60 | 61 | //include the basics 62 | { 63 | { 64 | std::ofstream os2(path + "/SDK" + "/" + tfm::format("%s_Basic.hpp", generator->GetGameNameShort())); 65 | std::vector incs = { 66 | "", 67 | "", 68 | "", 69 | "" 70 | }; 71 | PrintFileHeader(os2, incs, true); 72 | 73 | os2 << generator->GetBasicDeclarations() << "\n"; 74 | 75 | PrintFileFooter(os2); 76 | 77 | os << "\n#include \"SDK/" << tfm::format("%s_Basic.hpp", generator->GetGameNameShort()) << "\"\n"; 78 | } 79 | { 80 | std::ofstream os2(path + "/SDK" + "/" + tfm::format("%s_Basic.cpp", generator->GetGameNameShort())); 81 | 82 | PrintFileHeader(os2, { "\"../SDK.hpp\"" }, false); 83 | 84 | os2 << generator->GetBasicDefinitions() << "\n"; 85 | 86 | PrintFileFooter(os2); 87 | } 88 | } 89 | 90 | using namespace cpplinq; 91 | 92 | //check for missing structs 93 | const auto missing = from(processedObjects) >> where([](auto&& kv) { return kv.second == false; }); 94 | if (missing >> any()) 95 | { 96 | std::ofstream os2(path + "/SDK" + "/" + tfm::format("%s_MISSING.hpp", generator->GetGameNameShort())); 97 | 98 | PrintFileHeader(os2, true); 99 | 100 | /* 101 | for (auto&& s : missing >> select([](auto&& kv) { return kv.first.Cast(); }) >> experimental::container()) 102 | { 103 | os2 << "// " << s.GetFullName() << "\n// "; 104 | os2 << tfm::format("0x%04X\n", s.GetPropertySize()); 105 | 106 | os2 << "struct " << MakeValidName(s.GetNameCPP()) << "\n{\n"; 107 | os2 << "\tunsigned char UnknownData[0x" << tfm::format("%X", s.GetPropertySize()) << "];\n};\n\n"; 108 | } 109 | */ 110 | 111 | PrintFileFooter(os2); 112 | 113 | os << "\n#include \"SDK/" << tfm::format("%s_MISSING.hpp", generator->GetGameNameShort()) << "\"\n"; 114 | } 115 | 116 | os << "\n"; 117 | 118 | for (auto&& package : packages) 119 | { 120 | os << R"(#include "SDK/)" << GenerateFileName(FileContentType::Structs, *package) << "\"\n"; 121 | os << R"(#include "SDK/)" << GenerateFileName(FileContentType::Classes, *package) << "\"\n"; 122 | if (generator->ShouldGenerateFunctionParametersFile()) 123 | { 124 | os << R"(#include "SDK/)" << GenerateFileName(FileContentType::FunctionParameters, *package) << "\"\n"; 125 | } 126 | } 127 | } 128 | 129 | /// 130 | /// Process the packages. 131 | /// 132 | /// The path where to create the package files. 133 | void ProcessPackages(std::string path) 134 | { 135 | using namespace cpplinq; 136 | 137 | const auto sdkPath = path + "/SDK"; 138 | mkdir(sdkPath.c_str(), 0777); 139 | 140 | std::vector> packages; 141 | 142 | std::unordered_map processedObjects; 143 | 144 | auto packageObjects = from(ObjectsStore()) 145 | >> select([](auto&& o) { return o.GetPackageObject(); }) 146 | >> where([](auto&& o) { return o.IsValid(); }) 147 | >> distinct() 148 | >> to_vector(); 149 | 150 | for (auto obj : packageObjects) 151 | { 152 | auto package = std::make_unique(obj); 153 | 154 | package->Process(processedObjects); 155 | if (package->Save(sdkPath)) 156 | { 157 | Package::PackageMap[obj] = package.get(); 158 | 159 | packages.emplace_back(std::move(package)); 160 | } 161 | } 162 | 163 | if (!packages.empty()) 164 | { 165 | // std::sort doesn't work, so use a simple bubble sort 166 | //std::sort(std::begin(packages), std::end(packages), PackageDependencyComparer()); 167 | const PackageDependencyComparer comparer; 168 | for (auto i = 0u; i < packages.size() - 1; ++i) 169 | { 170 | for (auto j = 0u; j < packages.size() - i - 1; ++j) 171 | { 172 | if (!comparer(packages[j], packages[j + 1])) 173 | { 174 | std::swap(packages[j], packages[j + 1]); 175 | } 176 | } 177 | } 178 | } 179 | 180 | SaveSDKHeader(path, processedObjects, packages); 181 | } 182 | 183 | void *main_thread(void *) { 184 | 185 | UE4 = Tools::GetBaseAddress(lib_name); 186 | while (!UE4) { 187 | UE4 = Tools::GetBaseAddress(lib_name); 188 | sleep(1); 189 | } 190 | 191 | //Delay 192 | sleep(5); 193 | 194 | uintptr_t GName_Addr = getTNameArrayAddr(); 195 | uintptr_t GObject_Addr = getFUObjecrtArrayAddr(); 196 | 197 | if (!ObjectsStore::Initialize(GObject_Addr)) 198 | { 199 | return ; 200 | } 201 | if (!NamesStore::Initialize(GName_Addr)) 202 | { 203 | return ; 204 | } 205 | 206 | if (!generator->Initialize(UE4)) 207 | { 208 | return ; 209 | } 210 | 211 | //file1 << NamesStore().GetById(2).c_str() << endl; 212 | //file1 << dec << ObjectsStore().GetObjectsNum() << endl; 213 | 214 | std::string outputDirectory = generator->GetOutputDirectory(pkgName); 215 | 216 | #if defined(__LP64__) 217 | outputDirectory += "/" + generator->GetGameNameShort() + "_(v" + generator->GetGameVersion() + ")_64Bit"; 218 | #else 219 | outputDirectory += "/" + generator->GetGameNameShort() + "_(v" + generator->GetGameVersion() + ")_32Bit"; 220 | #endif 221 | 222 | mkdir(outputDirectory.c_str(), 0777); 223 | 224 | std::ofstream log(outputDirectory + "/Generator.log"); 225 | Logger::SetStream(&log); 226 | 227 | Logger::Log("Cheking LOGs"); 228 | 229 | Dump(outputDirectory); 230 | 231 | const auto begin = std::chrono::system_clock::now(); 232 | 233 | ProcessPackages(outputDirectory); 234 | 235 | Logger::Log("Finished, took %d seconds.", std::chrono::duration_cast(std::chrono::system_clock::now() - begin).count()); 236 | 237 | return 0; 238 | } 239 | 240 | extern "C" 241 | JNIEXPORT int JNI_OnLoad(JavaVM* vm, void* reserved) { 242 | JNIEnv* env; 243 | if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { 244 | return JNI_ERR; 245 | } 246 | 247 | Media_Folder = "/storage/emulated/0/Android/media/" + pkgName; 248 | 249 | struct stat info; 250 | if( stat( Media_Folder.c_str(), &info ) != 0 ){ 251 | LOGE( "cannot access %s\n", Media_Folder.c_str() ); 252 | mkdir(Media_Folder.c_str(), 0777); 253 | } 254 | 255 | // file1.open(Media_Folder + "/gen_log.txt"); 256 | 257 | pthread_t m_thread; 258 | pthread_create(&m_thread, 0, main_thread, 0); 259 | 260 | return JNI_VERSION_1_6; 261 | } 262 | 263 | extern "C" 264 | { 265 | void __attribute__ ((visibility ("default"))) OnLoad() 266 | { 267 | 268 | Media_Folder = "/storage/emulated/0/Android/media/" + pkgName; 269 | 270 | struct stat info; 271 | if( stat( Media_Folder.c_str(), &info ) != 0 ){ 272 | LOGE( "cannot access %s\n", Media_Folder.c_str() ); 273 | mkdir(Media_Folder.c_str(), 0777); 274 | } 275 | 276 | //file1.open(Media_Folder + "/gen_log.txt"); 277 | 278 | pthread_t thread; 279 | pthread_create(&thread, 0, main_thread, 0); 280 | 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /Source/jni/src/Main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef DYNO_H 4 | #define DYNO_H 5 | 6 | #include "Includes.h" 7 | using namespace std; 8 | 9 | //static ofstream file1; 10 | static std::string Media_Folder; 11 | 12 | static uintptr_t UE4 = 0; 13 | static char* lib_name = "libUE4.so"; 14 | static std::string pkgName = "com.pubg.imobile"; 15 | 16 | static std::string gameVersion = "1.8.0"; 17 | static std::string gameShortName = "BGMI"; 18 | static std::string gameFullName = "Battlegrounds Mobile India"; 19 | 20 | 21 | #if defined(__LP64__) 22 | //static uintptr_t GWorld_Offset = 0; 23 | static uintptr_t GNames_Offset = 0; 24 | static uintptr_t GUObjectArray_Offset = 0; 25 | #else 26 | //static uintptr_t GWorld_Offset = 0; 27 | static uintptr_t GNames_Offset = 0; 28 | static uintptr_t GUObjectArray_Offset = 0; 29 | #endif 30 | 31 | // Change this if dereferenced 32 | static uintptr_t getTNameArrayAddr() { 33 | uintptr_t GNameAddr = *(uintptr_t*) (UE4 + GNames_Offset); 34 | return GNameAddr; 35 | } 36 | 37 | static uintptr_t getFUObjecrtArrayAddr() { 38 | uintptr_t GObjectAddr = UE4 + GUObjectArray_Offset; 39 | return GObjectAddr; 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Source/jni/src/NameValidator.cpp: -------------------------------------------------------------------------------- 1 | #include "NameValidator.hpp" 2 | 3 | #include 4 | 5 | #include "ObjectsStore.hpp" 6 | 7 | std::string MakeValidName(std::string&& name) 8 | { 9 | std::string valid(name); 10 | 11 | for (auto i = 0u; i < name.length(); ++i) 12 | { 13 | if (valid[i] == ' ' 14 | || valid[i] == '?' 15 | || valid[i] == '+' 16 | || valid[i] == '-' 17 | || valid[i] == ':' 18 | || valid[i] == '/' 19 | || valid[i] == '^' 20 | || valid[i] == '(' 21 | || valid[i] == ')' 22 | || valid[i] == '[' 23 | || valid[i] == ']' 24 | || valid[i] == '<' 25 | || valid[i] == '>' 26 | || valid[i] == '&' 27 | || valid[i] == '.' 28 | || valid[i] == '#' 29 | || valid[i] == '\'' 30 | || valid[i] == '"' 31 | || valid[i] == '%') 32 | { 33 | valid[i] = '_'; 34 | } 35 | } 36 | 37 | if (!valid.empty()) 38 | { 39 | if (std::isdigit(valid[0])) 40 | { 41 | valid = '_' + valid; 42 | } 43 | } 44 | 45 | return valid; 46 | } 47 | 48 | std::string SimplifyEnumName(std::string&& name) 49 | { 50 | const auto index = name.find_last_of(':'); 51 | if (index == std::string::npos) 52 | { 53 | return name; 54 | } 55 | 56 | return name.substr(index + 1); 57 | } 58 | 59 | template 60 | std::string MakeUniqueCppNameImpl(const T& t) 61 | { 62 | std::string name; 63 | if (ObjectsStore().CountObjects(t.GetName()) > 1) 64 | { 65 | name += MakeValidName(t.GetOuter().GetName()) + "_"; 66 | } 67 | return name + MakeValidName(t.GetName()); 68 | } 69 | 70 | std::string MakeUniqueCppName(const UEConst& c) 71 | { 72 | return MakeUniqueCppNameImpl(c); 73 | } 74 | 75 | std::string MakeUniqueCppName(const UEEnum& e) 76 | { 77 | auto name = MakeUniqueCppNameImpl(e); 78 | if (!name.empty() && name[0] != 'E') 79 | { 80 | name = 'E' + name; 81 | } 82 | return name; 83 | } 84 | 85 | std::string MakeUniqueCppName(const UEStruct& ss) 86 | { 87 | std::string name; 88 | if (ObjectsStore().CountObjects(ss.GetName()) > 1) 89 | { 90 | name += MakeValidName(ss.GetOuter().GetNameCPP()) + "_"; 91 | } 92 | return name + MakeValidName(ss.GetNameCPP()); 93 | } 94 | -------------------------------------------------------------------------------- /Source/jni/src/NameValidator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class UEConst; 6 | class UEEnum; 7 | class UEStruct; 8 | 9 | 10 | 11 | /// 12 | /// Makes valid C++ name from the given name. 13 | /// 14 | /// The name to process. 15 | /// A valid C++ name. 16 | std::string MakeValidName(std::string&& name); 17 | 18 | std::string SimplifyEnumName(std::string&& name); 19 | 20 | std::string MakeUniqueCppName(const UEConst& c); 21 | std::string MakeUniqueCppName(const UEEnum& e); 22 | std::string MakeUniqueCppName(const UEStruct& ss); 23 | -------------------------------------------------------------------------------- /Source/jni/src/NamesStore.cpp: -------------------------------------------------------------------------------- 1 | #include "NamesStore.hpp" 2 | 3 | #include "EngineClasses.hpp" 4 | 5 | NamesIterator NamesStore::begin() 6 | { 7 | return NamesIterator(*this, 0); 8 | } 9 | 10 | NamesIterator NamesStore::begin() const 11 | { 12 | return NamesIterator(*this, 0); 13 | } 14 | 15 | NamesIterator NamesStore::end() 16 | { 17 | return NamesIterator(*this); 18 | } 19 | 20 | NamesIterator NamesStore::end() const 21 | { 22 | return NamesIterator(*this); 23 | } 24 | 25 | NamesIterator::NamesIterator(const NamesStore& _store) 26 | : store(_store), 27 | index(_store.GetNamesNum()) 28 | { 29 | } 30 | 31 | NamesIterator::NamesIterator(const NamesStore& _store, size_t _index) 32 | : store(_store), 33 | index(_index) 34 | { 35 | } 36 | 37 | void NamesIterator::swap(NamesIterator& other) noexcept 38 | { 39 | std::swap(index, other.index); 40 | } 41 | 42 | NamesIterator& NamesIterator::operator++() 43 | { 44 | for (++index; index < store.GetNamesNum(); ++index) 45 | { 46 | if (store.IsValid(index)) 47 | { 48 | break; 49 | } 50 | } 51 | return *this; 52 | } 53 | 54 | NamesIterator NamesIterator::operator++ (int) 55 | { 56 | auto tmp(*this); 57 | ++(*this); 58 | return tmp; 59 | } 60 | 61 | bool NamesIterator::operator==(const NamesIterator& rhs) const 62 | { 63 | return index == rhs.index; 64 | } 65 | 66 | bool NamesIterator::operator!=(const NamesIterator& rhs) const 67 | { 68 | return index != rhs.index; 69 | } 70 | 71 | UENameInfo NamesIterator::operator*() const 72 | { 73 | return { index, store.GetById(index) }; 74 | } 75 | 76 | UENameInfo NamesIterator::operator->() const 77 | { 78 | return { index, store.GetById(index) }; 79 | } 80 | 81 | class FNameEntry 82 | { 83 | public: 84 | 85 | FNameEntry* HashNext; 86 | __int32 Index; 87 | union 88 | { 89 | char AnsiName[1024]; 90 | wchar_t WideName[1024]; 91 | }; 92 | 93 | const char* GetName() const 94 | { 95 | return AnsiName; 96 | } 97 | }; 98 | 99 | template 100 | class TStaticIndirectArrayThreadSafeRead 101 | { 102 | public: 103 | int32_t Num() const 104 | { 105 | return NumElements; 106 | } 107 | 108 | bool IsValidIndex(int32_t index) const 109 | { 110 | return index >= 0 && index < Num() && GetById(index) != nullptr; 111 | } 112 | 113 | ElementType const* const& GetById(int32_t index) const 114 | { 115 | return *GetItemPtr(index); 116 | } 117 | 118 | private: 119 | ElementType const* const* GetItemPtr(int32_t Index) const 120 | { 121 | int32_t ChunkIndex = Index / ElementsPerChunk; 122 | int32_t WithinChunkIndex = Index % ElementsPerChunk; 123 | ElementType** Chunk = Chunks[ChunkIndex]; 124 | return Chunk + WithinChunkIndex; 125 | } 126 | 127 | enum 128 | { 129 | ChunkTableSize = (MaxTotalElements + ElementsPerChunk - 1) / ElementsPerChunk 130 | }; 131 | 132 | ElementType** Chunks[ChunkTableSize]; 133 | __int32 NumElements; 134 | __int32 NumChunks; 135 | }; 136 | 137 | using TNameEntryArray = TStaticIndirectArrayThreadSafeRead; 138 | 139 | TNameEntryArray* GlobalNames = nullptr; 140 | 141 | bool NamesStore::Initialize(uintptr_t GNames_Addr) 142 | { 143 | if(GNames_Addr == 0) 144 | return false; 145 | 146 | GlobalNames = (TNameEntryArray*) (GNames_Addr); 147 | 148 | return true; 149 | } 150 | 151 | void* NamesStore::GetAddress() 152 | { 153 | return GlobalNames; 154 | } 155 | 156 | size_t NamesStore::GetNamesNum() const 157 | { 158 | return GlobalNames->Num(); 159 | } 160 | 161 | bool NamesStore::IsValid(size_t id) const 162 | { 163 | return GlobalNames->IsValidIndex(static_cast(id)); 164 | } 165 | 166 | std::string NamesStore::GetById(size_t id) const 167 | { 168 | return GlobalNames->GetById(static_cast(id))->GetName(); 169 | } 170 | -------------------------------------------------------------------------------- /Source/jni/src/NamesStore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "UE4/GenericTypes.hpp" 6 | 7 | 8 | 9 | class NamesIterator; 10 | 11 | class NamesStore 12 | { 13 | friend NamesIterator; 14 | 15 | public: 16 | 17 | /// 18 | /// Initializes this object. 19 | /// 20 | /// true if it succeeds, false if it fails. 21 | static bool Initialize(uintptr_t a); 22 | 23 | /// Gets the address of the global names store. 24 | /// The address of the global names store. 25 | static void* GetAddress(); 26 | 27 | NamesIterator begin(); 28 | 29 | NamesIterator begin() const; 30 | 31 | NamesIterator end(); 32 | 33 | NamesIterator end() const; 34 | 35 | /// 36 | /// Gets the number of available names. 37 | /// 38 | /// The number of names. 39 | size_t GetNamesNum() const; 40 | 41 | /// 42 | /// Test if the given id is valid. 43 | /// 44 | /// The identifier. 45 | /// true if valid, false if not. 46 | bool IsValid(size_t id) const; 47 | 48 | /// 49 | /// Gets a name by id. 50 | /// 51 | /// The identifier. 52 | /// The name. 53 | std::string GetById(size_t id) const; 54 | }; 55 | 56 | struct UENameInfo 57 | { 58 | size_t Index; 59 | std::string Name; 60 | }; 61 | 62 | class NamesIterator : public std::iterator 63 | { 64 | const NamesStore& store; 65 | size_t index; 66 | 67 | public: 68 | NamesIterator(const NamesStore& store); 69 | 70 | explicit NamesIterator(const NamesStore& store, size_t index); 71 | 72 | void swap(NamesIterator& other) noexcept; 73 | 74 | NamesIterator& operator++(); 75 | 76 | NamesIterator operator++ (int); 77 | 78 | bool operator==(const NamesIterator& rhs) const; 79 | 80 | bool operator!=(const NamesIterator& rhs) const; 81 | 82 | UENameInfo operator*() const; 83 | 84 | UENameInfo operator->() const; 85 | }; 86 | -------------------------------------------------------------------------------- /Source/jni/src/ObjectsStore.cpp: -------------------------------------------------------------------------------- 1 | #include "ObjectsStore.hpp" 2 | 3 | #include "EngineClasses.hpp" 4 | 5 | 6 | ObjectsIterator ObjectsStore::begin() 7 | { 8 | return ObjectsIterator(*this, 0); 9 | } 10 | 11 | ObjectsIterator ObjectsStore::begin() const 12 | { 13 | return ObjectsIterator(*this, 0); 14 | } 15 | 16 | ObjectsIterator ObjectsStore::end() 17 | { 18 | return ObjectsIterator(*this); 19 | } 20 | 21 | ObjectsIterator ObjectsStore::end() const 22 | { 23 | return ObjectsIterator(*this); 24 | } 25 | 26 | UEClass ObjectsStore::FindClass(const std::string& name) const 27 | { 28 | for (auto obj : *this) 29 | { 30 | if (obj.GetFullName() == name) 31 | { 32 | return obj.Cast(); 33 | } 34 | } 35 | return UEClass(nullptr); 36 | } 37 | 38 | ObjectsIterator::ObjectsIterator(const ObjectsStore& _store) 39 | : store(_store), 40 | index(_store.GetObjectsNum()) 41 | { 42 | } 43 | 44 | ObjectsIterator::ObjectsIterator(const ObjectsStore& _store, size_t _index) 45 | : store(_store), 46 | index(_index), 47 | current(_store.GetById(_index)) 48 | { 49 | } 50 | 51 | ObjectsIterator::ObjectsIterator(const ObjectsIterator& other) 52 | : store(other.store), 53 | index(other.index), 54 | current(other.current) 55 | { 56 | } 57 | 58 | ObjectsIterator::ObjectsIterator(ObjectsIterator&& other) noexcept 59 | : store(other.store), 60 | index(other.index), 61 | current(other.current) 62 | { 63 | } 64 | 65 | ObjectsIterator& ObjectsIterator::operator=(const ObjectsIterator& rhs) 66 | { 67 | index = rhs.index; 68 | current = rhs.current; 69 | return *this; 70 | } 71 | 72 | void ObjectsIterator::swap(ObjectsIterator& other) noexcept 73 | { 74 | std::swap(index, other.index); 75 | std::swap(current, other.current); 76 | } 77 | 78 | ObjectsIterator& ObjectsIterator::operator++() 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 | } 119 | 120 | class FUObjectItem 121 | { 122 | public: 123 | UObject* Object; //0x0000 124 | __int32 Flags; //0x0008 125 | __int32 ClusterIndex; //0x000C 126 | __int32 SerialNumber; //0x0010 127 | char pad1[0x4]; 128 | }; 129 | 130 | class TUObjectArray 131 | { 132 | public: 133 | FUObjectItem* Objects; 134 | int32_t MaxElements; 135 | int32_t NumElements; 136 | }; 137 | 138 | class FUObjectArray 139 | { 140 | public: 141 | __int32 ObjFirstGCIndex; //0x0000 142 | __int32 ObjLastNonGCIndex; //0x0004 143 | __int32 MaxObjectsNotConsideredByGC; //0x0008 144 | __int32 OpenForDisregardForGC; //0x000C 145 | 146 | TUObjectArray ObjObjects; //0x0010 147 | }; 148 | 149 | FUObjectArray* GlobalObjects = nullptr; 150 | 151 | bool ObjectsStore::Initialize(uintptr_t GUObjectArray_Addr) 152 | { 153 | if(GUObjectArray_Addr == 0) 154 | return false; 155 | 156 | GlobalObjects = (FUObjectArray*) (GUObjectArray_Addr); 157 | 158 | return true; 159 | } 160 | 161 | void* ObjectsStore::GetAddress() 162 | { 163 | return GlobalObjects; 164 | } 165 | 166 | size_t ObjectsStore::GetObjectsNum() const 167 | { 168 | return GlobalObjects->ObjObjects.NumElements; 169 | } 170 | 171 | UEObject ObjectsStore::GetById(size_t id) const 172 | { 173 | return GlobalObjects->ObjObjects.Objects[id].Object; 174 | } 175 | -------------------------------------------------------------------------------- /Source/jni/src/ObjectsStore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "UE4/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(uintptr_t a); 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 | 78 | cache[name] = count; 79 | 80 | return count; 81 | } 82 | }; 83 | 84 | /// Holds information about an object. 85 | struct UEObjectInfo 86 | { 87 | /// Zero-based index of the object in the global objects store. 88 | size_t Index; 89 | 90 | /// The object. 91 | UEObject Object; 92 | }; 93 | 94 | /// An iterator for objects. 95 | class ObjectsIterator : public std::iterator 96 | { 97 | const ObjectsStore& store; 98 | size_t index; 99 | UEObject current; 100 | 101 | public: 102 | 103 | /// Constructor. 104 | /// The store to iterate. 105 | ObjectsIterator(const ObjectsStore& store); 106 | 107 | /// Constructor. 108 | /// The store to iterate. 109 | /// Zero-based start index. 110 | explicit ObjectsIterator(const ObjectsStore& store, size_t index); 111 | 112 | ObjectsIterator(const ObjectsIterator& other); 113 | ObjectsIterator(ObjectsIterator&& other) noexcept; 114 | 115 | ObjectsIterator& operator=(const ObjectsIterator& rhs); 116 | 117 | void swap(ObjectsIterator& other) noexcept; 118 | 119 | ObjectsIterator& operator++(); 120 | 121 | ObjectsIterator operator++ (int); 122 | 123 | bool operator==(const ObjectsIterator& rhs) const; 124 | 125 | bool operator!=(const ObjectsIterator& rhs) const; 126 | 127 | UEObject operator*() const; 128 | 129 | UEObject operator->() const; 130 | }; 131 | -------------------------------------------------------------------------------- /Source/jni/src/Package.cpp: -------------------------------------------------------------------------------- 1 | #include "Package.hpp" 2 | 3 | #include 4 | #include 5 | #include "tinyformat.h" 6 | #include "cpplinq.hpp" 7 | #include "Logger.hpp" 8 | #include "IGenerator.hpp" 9 | #include "NameValidator.hpp" 10 | #include "ObjectsStore.hpp" 11 | #include "PropertyFlags.hpp" 12 | #include "FunctionFlags.hpp" 13 | #include "PrintHelper.hpp" 14 | #include "Tools.h" 15 | 16 | uintptr_t libBaseAddr = 0; 17 | uintptr_t libEndAddr = 0; 18 | 19 | std::unordered_map Package::PackageMap; 20 | 21 | /// 22 | /// Compare two properties. 23 | /// 24 | /// The first property. 25 | /// The second property. 26 | /// true if the first property compares less, else false. 27 | bool ComparePropertyLess(const UEProperty& lhs, const UEProperty& rhs) 28 | { 29 | if (lhs.GetOffset() == rhs.GetOffset() 30 | && lhs.IsA() 31 | && rhs.IsA()) 32 | { 33 | return lhs.Cast() < rhs.Cast(); 34 | } 35 | 36 | return lhs.GetOffset() < rhs.GetOffset(); 37 | } 38 | 39 | Package::Package(const UEObject& _packageObj) 40 | : packageObj(_packageObj) 41 | { 42 | } 43 | 44 | void Package::Process(std::unordered_map& processedObjects) 45 | { 46 | for (auto obj : ObjectsStore()) 47 | { 48 | const auto package = obj.GetPackageObject(); 49 | if (packageObj == package) 50 | { 51 | if (obj.IsA()) 52 | { 53 | GenerateEnum(obj.Cast()); 54 | } 55 | else if (obj.IsA()) 56 | { 57 | GenerateConst(obj.Cast()); 58 | } 59 | else if (obj.IsA()) 60 | { 61 | GeneratePrerequisites(obj, processedObjects); 62 | } 63 | else if (obj.IsA()) 64 | { 65 | GeneratePrerequisites(obj, processedObjects); 66 | } 67 | } 68 | } 69 | } 70 | 71 | bool Package::Save(std::string path) const 72 | { 73 | extern IGenerator* generator; 74 | 75 | using namespace cpplinq; 76 | 77 | //check if package is empty (no enums, structs or classes without members) 78 | if (generator->ShouldGenerateEmptyFiles() 79 | || (from(enums) >> where([](auto&& e) { return !e.Values.empty(); }) >> any() 80 | || from(scriptStructs) >> where([](auto&& s) { return !s.Members.empty() || !s.PredefinedMethods.empty(); }) >> any() 81 | || from(classes) >> where([](auto&& c) {return !c.Members.empty() || !c.PredefinedMethods.empty() || !c.Methods.empty(); }) >> any() 82 | ) 83 | ) 84 | { 85 | SaveStructs(path); 86 | SaveClasses(path); 87 | SaveFunctions(path); 88 | 89 | return true; 90 | } 91 | 92 | //Logger::Log("skip empty Package: %s", packageObj.GetName()); 93 | 94 | return false; 95 | } 96 | 97 | bool Package::AddDependency(const UEObject& package) const 98 | { 99 | if (package != packageObj) 100 | { 101 | dependencies.insert(package); 102 | 103 | return true; 104 | } 105 | return false; 106 | } 107 | 108 | void Package::GeneratePrerequisites(const UEObject& obj, std::unordered_map& processedObjects) 109 | { 110 | if (!obj.IsValid()) 111 | { 112 | return; 113 | } 114 | 115 | const auto isClass = obj.IsA(); 116 | const auto isScriptStruct = obj.IsA(); 117 | if (!isClass && !isScriptStruct) 118 | { 119 | return; 120 | } 121 | 122 | const auto name = obj.GetName(); 123 | if (name.find("Default__") != std::string::npos 124 | || name.find("") != std::string::npos 125 | || name.find("PLACEHOLDER-CLASS") != std::string::npos) 126 | { 127 | return; 128 | } 129 | 130 | processedObjects[obj] |= false; 131 | 132 | auto classPackage = obj.GetPackageObject(); 133 | if (!classPackage.IsValid()) 134 | { 135 | return; 136 | } 137 | 138 | if (AddDependency(classPackage)) 139 | { 140 | return; 141 | } 142 | 143 | if (processedObjects[obj] == false) 144 | { 145 | processedObjects[obj] = true; 146 | 147 | auto outer = obj.GetOuter(); 148 | if (outer.IsValid() && outer != obj) 149 | { 150 | GeneratePrerequisites(outer, processedObjects); 151 | } 152 | 153 | auto structObj = obj.Cast(); 154 | 155 | auto super = structObj.GetSuper(); 156 | if (super.IsValid() && super != obj) 157 | { 158 | GeneratePrerequisites(super, processedObjects); 159 | } 160 | 161 | GenerateMemberPrerequisites(structObj.GetChildren().Cast(), processedObjects); 162 | 163 | if (isClass) 164 | { 165 | GenerateClass(obj.Cast()); 166 | } 167 | else 168 | { 169 | GenerateScriptStruct(obj.Cast()); 170 | } 171 | } 172 | } 173 | 174 | void Package::GenerateMemberPrerequisites(const UEProperty& first, std::unordered_map& processedObjects) 175 | { 176 | using namespace cpplinq; 177 | 178 | for (auto prop = first; prop.IsValid(); prop = prop.GetNext().Cast()) 179 | { 180 | const auto info = prop.GetInfo(); 181 | if (info.Type == UEProperty::PropertyType::Primitive) 182 | { 183 | if (prop.IsA()) 184 | { 185 | auto byteProperty = prop.Cast(); 186 | if (byteProperty.IsEnum()) 187 | { 188 | AddDependency(byteProperty.GetEnum().GetPackageObject()); 189 | } 190 | } 191 | else if (prop.IsA()) 192 | { 193 | auto enumProperty = prop.Cast(); 194 | AddDependency(enumProperty.GetEnum().GetPackageObject()); 195 | } 196 | } 197 | else if (info.Type == UEProperty::PropertyType::CustomStruct) 198 | { 199 | GeneratePrerequisites(prop.Cast().GetStruct(), processedObjects); 200 | } 201 | else if (info.Type == UEProperty::PropertyType::Container) 202 | { 203 | std::vector innerProperties; 204 | 205 | if (prop.IsA()) 206 | { 207 | innerProperties.push_back(prop.Cast().GetInner()); 208 | } 209 | else if (prop.IsA()) 210 | { 211 | auto mapProp = prop.Cast(); 212 | innerProperties.push_back(mapProp.GetKeyProperty()); 213 | innerProperties.push_back(mapProp.GetValueProperty()); 214 | } 215 | 216 | for (auto innerProp : from(innerProperties) 217 | >> where([](auto&& p) { return p.GetInfo().Type == UEProperty::PropertyType::CustomStruct; }) 218 | >> experimental::container()) 219 | { 220 | GeneratePrerequisites(innerProp.Cast().GetStruct(), processedObjects); 221 | } 222 | } 223 | else if (prop.IsA()) 224 | { 225 | auto function = prop.Cast(); 226 | 227 | GenerateMemberPrerequisites(function.GetChildren().Cast(), processedObjects); 228 | } 229 | } 230 | } 231 | 232 | void Package::GenerateScriptStruct(const UEScriptStruct& scriptStructObj) 233 | { 234 | extern IGenerator* generator; 235 | 236 | ScriptStruct ss; 237 | ss.Name = scriptStructObj.GetName(); 238 | ss.FullName = scriptStructObj.GetFullName(); 239 | 240 | //Logger::Log("ScriptStruct: %-100s - instance: 0x%P", ss.Name, scriptStructObj.GetAddress()); 241 | 242 | ss.NameCpp = MakeValidName(scriptStructObj.GetNameCPP()); 243 | ss.NameCppFull = "struct "; 244 | 245 | //some classes need special alignment 246 | const auto alignment = generator->GetClassAlignas(ss.FullName); 247 | if (alignment != 0) 248 | { 249 | ss.NameCppFull += tfm::format("alignas(%d) ", alignment); 250 | } 251 | 252 | ss.NameCppFull += MakeUniqueCppName(scriptStructObj); 253 | 254 | ss.Size = scriptStructObj.GetPropertySize(); 255 | ss.InheritedSize = 0; 256 | 257 | size_t offset = 0; 258 | 259 | auto super = scriptStructObj.GetSuper(); 260 | if (super.IsValid() && super != scriptStructObj) 261 | { 262 | ss.InheritedSize = offset = super.GetPropertySize(); 263 | 264 | ss.NameCppFull += " : public " + MakeUniqueCppName(super.Cast()); 265 | } 266 | 267 | std::vector properties; 268 | for (auto prop = scriptStructObj.GetChildren().Cast(); prop.IsValid(); prop = prop.GetNext().Cast()) 269 | { 270 | if (prop.GetElementSize() > 0 271 | && !prop.IsA() 272 | && !prop.IsA() 273 | && !prop.IsA() 274 | && !prop.IsA() 275 | ) 276 | { 277 | properties.push_back(prop); 278 | } 279 | } 280 | std::sort(std::begin(properties), std::end(properties), ComparePropertyLess); 281 | 282 | GenerateMembers(scriptStructObj, offset, properties, ss.Members); 283 | 284 | generator->GetPredefinedClassMethods(scriptStructObj.GetFullName(), ss.PredefinedMethods); 285 | 286 | scriptStructs.emplace_back(std::move(ss)); 287 | } 288 | 289 | void Package::GenerateEnum(const UEEnum& enumObj) 290 | { 291 | Enum e; 292 | e.Name = MakeUniqueCppName(enumObj); 293 | 294 | if (e.Name.find("Default__") != std::string::npos 295 | || e.Name.find("PLACEHOLDER-CLASS") != std::string::npos) 296 | { 297 | return; 298 | } 299 | 300 | e.FullName = enumObj.GetFullName(); 301 | 302 | std::unordered_map conflicts; 303 | for (auto&& s : enumObj.GetNames()) 304 | { 305 | const auto clean = MakeValidName(std::move(s)); 306 | 307 | const auto it = conflicts.find(clean); 308 | if (it == std::end(conflicts)) 309 | { 310 | e.Values.push_back(clean); 311 | conflicts[clean] = 1; 312 | } 313 | else 314 | { 315 | e.Values.push_back(clean + tfm::format("%02d", it->second)); 316 | conflicts[clean]++; 317 | } 318 | } 319 | 320 | enums.emplace_back(std::move(e)); 321 | } 322 | 323 | void Package::GenerateConst(const UEConst& constObj) 324 | { 325 | //auto name = MakeValidName(constObj.GetName()); 326 | auto name = MakeUniqueCppName(constObj); 327 | 328 | if (name.find("Default__") != std::string::npos 329 | || name.find("PLACEHOLDER-CLASS") != std::string::npos) 330 | { 331 | return; 332 | } 333 | 334 | constants[name] = constObj.GetValue(); 335 | } 336 | 337 | void Package::GenerateClass(const UEClass& classObj) 338 | { 339 | extern IGenerator* generator; 340 | 341 | Class c; 342 | c.Name = classObj.GetName(); 343 | c.FullName = classObj.GetFullName(); 344 | 345 | //Logger::Log("Class: %-100s - instance: 0x%P", c.Name, classObj.GetAddress()); 346 | 347 | c.NameCpp = MakeValidName(classObj.GetNameCPP()); 348 | c.NameCppFull = "class " + c.NameCpp; 349 | 350 | c.Size = classObj.GetPropertySize(); 351 | c.InheritedSize = 0; 352 | 353 | size_t offset = 0; 354 | 355 | auto super = classObj.GetSuper(); 356 | if (super.IsValid() && super != classObj) 357 | { 358 | c.InheritedSize = offset = super.GetPropertySize(); 359 | 360 | c.NameCppFull += " : public " + MakeValidName(super.GetNameCPP()); 361 | } 362 | 363 | std::vector predefinedStaticMembers; 364 | if (generator->GetPredefinedClassStaticMembers(c.FullName, predefinedStaticMembers)) 365 | { 366 | for (auto&& prop : predefinedStaticMembers) 367 | { 368 | Member p; 369 | p.Offset = 0; 370 | p.Size = 0; 371 | p.Name = prop.Name; 372 | p.Type = "static " + prop.Type; 373 | c.Members.push_back(std::move(p)); 374 | } 375 | } 376 | 377 | std::vector predefinedMembers; 378 | if (generator->GetPredefinedClassMembers(c.FullName, predefinedMembers)) 379 | { 380 | for (auto&& prop : predefinedMembers) 381 | { 382 | Member p; 383 | p.Offset = 0; 384 | p.Size = 0; 385 | p.Name = prop.Name; 386 | p.Type = prop.Type; 387 | p.Comment = "NOT AUTO-GENERATED PROPERTY"; 388 | c.Members.push_back(std::move(p)); 389 | } 390 | } 391 | else 392 | { 393 | std::vector properties; 394 | for (auto prop = classObj.GetChildren().Cast(); prop.IsValid(); prop = prop.GetNext().Cast()) 395 | { 396 | if (prop.GetElementSize() > 0 397 | && !prop.IsA() 398 | && !prop.IsA() 399 | && !prop.IsA() 400 | && !prop.IsA() 401 | && (!super.IsValid() 402 | || (super != classObj 403 | && prop.GetOffset() >= super.GetPropertySize() 404 | ) 405 | ) 406 | ) 407 | { 408 | properties.push_back(prop); 409 | } 410 | } 411 | std::sort(std::begin(properties), std::end(properties), ComparePropertyLess); 412 | 413 | GenerateMembers(classObj, offset, properties, c.Members); 414 | } 415 | 416 | generator->GetPredefinedClassMethods(c.FullName, c.PredefinedMethods); 417 | 418 | if (generator->ShouldUseStrings()) 419 | { 420 | c.PredefinedMethods.push_back(IGenerator::PredefinedMethod::Inline(tfm::format(R"( static UClass* StaticClass() 421 | { 422 | static UClass *pStaticClass = 0; 423 | if (!pStaticClass) 424 | pStaticClass = UObject::FindClass(%s); 425 | return pStaticClass; 426 | })", generator->ShouldXorStrings() ? tfm::format("_xor_(\"%s\")", c.FullName) : tfm::format("\"%s\"", c.FullName)))); 427 | } 428 | else 429 | { 430 | c.PredefinedMethods.push_back(IGenerator::PredefinedMethod::Inline(tfm::format(R"( static UClass* StaticClass() 431 | { 432 | static auto ptr = UObject::GetObjectCasted(%d); 433 | return ptr; 434 | })", classObj.GetIndex()))); 435 | } 436 | 437 | GenerateMethods(classObj, c.Methods); 438 | 439 | //search virtual functions 440 | IGenerator::VirtualFunctionPatterns patterns; 441 | if (generator->GetVirtualFunctionPatterns(c.FullName, patterns)) 442 | { 443 | if(libBaseAddr == 0 || libEndAddr == 0){ 444 | libBaseAddr = Tools::GetBaseAddress("libUE4.so"); 445 | libEndAddr = Tools::GetEndAddress("libUE4.so"); 446 | } 447 | const auto vtable = *reinterpret_cast(classObj.GetAddress()); 448 | size_t methodCount = 0; 449 | 450 | while (true) 451 | { 452 | if(!(libBaseAddr < vtable[methodCount] && libEndAddr > vtable[methodCount])) 453 | { 454 | break; 455 | } 456 | ++methodCount; 457 | } 458 | 459 | 460 | for (auto&& pattern : patterns) 461 | { 462 | Logger::Log("%s MethodCount : %d", c.FullName, methodCount); 463 | if (std::get<4>(pattern)){ 464 | c.PredefinedMethods.push_back(IGenerator::PredefinedMethod::Inline(tfm::format(std::get<3>(pattern), std::get<4>(pattern)))); 465 | } 466 | else { 467 | for (auto i = 0u; i < methodCount; ++i) 468 | { 469 | /* 470 | // TO-DO : 471 | if (vtable[i] != 0 && FindPattern(vtable[i], std::get<2>(pattern), reinterpret_cast(std::get<0>(pattern)), std::get<1>(pattern)) != -1) 472 | { 473 | c.PredefinedMethods.push_back(IGenerator::PredefinedMethod::Inline(tfm::format(std::get<3>(pattern), i))); 474 | break; 475 | } 476 | */ 477 | } 478 | } 479 | } 480 | } 481 | 482 | classes.emplace_back(std::move(c)); 483 | } 484 | 485 | Package::Member Package::CreatePadding(size_t id, size_t offset, size_t size, std::string reason) 486 | { 487 | Member ss; 488 | ss.Name = tfm::format("UnknownData%02d[0x%X]", id, size); 489 | ss.Type = "unsigned char"; 490 | ss.Offset = offset; 491 | ss.Size = size; 492 | ss.Comment = std::move(reason); 493 | return ss; 494 | } 495 | 496 | Package::Member Package::CreateBitfieldPadding(size_t id, size_t offset, std::string type, size_t bits) 497 | { 498 | Member ss; 499 | ss.Name = tfm::format("UnknownData%02d : %d", id, bits); 500 | ss.Type = std::move(type); 501 | ss.Offset = offset; 502 | ss.Size = 1; 503 | return ss; 504 | } 505 | 506 | void Package::GenerateMembers(const UEStruct& structObj, size_t offset, const std::vector& properties, std::vector& members) const 507 | { 508 | extern IGenerator* generator; 509 | 510 | std::unordered_map uniqueMemberNames; 511 | size_t unknownDataCounter = 0; 512 | UEBoolProperty previousBitfieldProperty; 513 | 514 | for (auto&& prop : properties) 515 | { 516 | if (offset < prop.GetOffset()) 517 | { 518 | previousBitfieldProperty = UEBoolProperty(); 519 | 520 | const auto size = prop.GetOffset() - offset; 521 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, size, "MISSED OFFSET")); 522 | } 523 | 524 | const auto info = prop.GetInfo(); 525 | if (info.Type != UEProperty::PropertyType::Unknown) 526 | { 527 | Member sp; 528 | sp.Offset = prop.GetOffset(); 529 | sp.Size = info.Size; 530 | 531 | sp.Type = info.CppType; 532 | sp.Name = MakeValidName(prop.GetName()); 533 | 534 | const auto it = uniqueMemberNames.find(sp.Name); 535 | if (it == std::end(uniqueMemberNames)) 536 | { 537 | uniqueMemberNames[sp.Name] = 1; 538 | } 539 | else 540 | { 541 | ++uniqueMemberNames[sp.Name]; 542 | sp.Name += tfm::format("%02d", it->second); 543 | } 544 | 545 | if (prop.GetArrayDim() > 1) 546 | { 547 | sp.Name += tfm::format("[0x%X]", prop.GetArrayDim()); 548 | } 549 | 550 | if (prop.IsA() && prop.Cast().IsBitfield()) 551 | { 552 | auto boolProp = prop.Cast(); 553 | 554 | const auto missingBits = boolProp.GetMissingBitsCount(previousBitfieldProperty); 555 | if (missingBits[1] != -1) 556 | { 557 | if (missingBits[0] > 0) 558 | { 559 | members.emplace_back(CreateBitfieldPadding(unknownDataCounter++, previousBitfieldProperty.GetOffset(), info.CppType, missingBits[0])); 560 | } 561 | if (missingBits[1] > 0) 562 | { 563 | members.emplace_back(CreateBitfieldPadding(unknownDataCounter++, sp.Offset, info.CppType, missingBits[1])); 564 | } 565 | } 566 | else if(missingBits[0] > 0) 567 | { 568 | members.emplace_back(CreateBitfieldPadding(unknownDataCounter++, sp.Offset, info.CppType, missingBits[0])); 569 | } 570 | 571 | previousBitfieldProperty = boolProp; 572 | 573 | sp.Name += " : 1"; 574 | } 575 | else 576 | { 577 | previousBitfieldProperty = UEBoolProperty(); 578 | } 579 | 580 | sp.Flags = static_cast(prop.GetPropertyFlags()); 581 | sp.FlagsString = StringifyFlags(prop.GetPropertyFlags()); 582 | 583 | members.emplace_back(std::move(sp)); 584 | 585 | const auto sizeMismatch = static_cast(prop.GetElementSize() * prop.GetArrayDim()) - static_cast(info.Size * prop.GetArrayDim()); 586 | if (sizeMismatch > 0) 587 | { 588 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, sizeMismatch, "FIX WRONG TYPE SIZE OF PREVIOUS PROPERTY")); 589 | } 590 | } 591 | else 592 | { 593 | const auto size = prop.GetElementSize() * prop.GetArrayDim(); 594 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, size, "UNKNOWN PROPERTY: " + prop.GetFullName())); 595 | } 596 | 597 | offset = prop.GetOffset() + prop.GetElementSize() * prop.GetArrayDim(); 598 | } 599 | 600 | if (offset < structObj.GetPropertySize()) 601 | { 602 | const auto size = structObj.GetPropertySize() - offset; 603 | members.emplace_back(CreatePadding(unknownDataCounter++, offset, size, "MISSED OFFSET")); 604 | } 605 | } 606 | 607 | bool Package::Method::Parameter::MakeType(UEPropertyFlags flags, Type& type) 608 | { 609 | if (flags & UEPropertyFlags::ReturnParm) 610 | { 611 | type = Type::Return; 612 | } 613 | else if (flags & UEPropertyFlags::OutParm) 614 | { 615 | //if it is a const parameter make it a default parameter 616 | if (flags & UEPropertyFlags::ConstParm) 617 | { 618 | type = Type::Default; 619 | } 620 | else 621 | { 622 | type = Type::Out; 623 | } 624 | } 625 | else if (flags & UEPropertyFlags::Parm) 626 | { 627 | type = Type::Default; 628 | } 629 | else 630 | { 631 | return false; 632 | } 633 | 634 | return true; 635 | } 636 | 637 | void Package::GenerateMethods(const UEClass& classObj, std::vector& methods) const 638 | { 639 | extern IGenerator* generator; 640 | 641 | //some classes (AnimBlueprintGenerated...) have multiple members with the same name, so filter them out 642 | std::unordered_set uniqueMethods; 643 | 644 | for (auto prop = classObj.GetChildren().Cast(); prop.IsValid(); prop = prop.GetNext().Cast()) 645 | { 646 | if (prop.IsA()) 647 | { 648 | auto function = prop.Cast(); 649 | 650 | Method m; 651 | m.Index = function.GetIndex(); 652 | m.FullName = function.GetFullName(); 653 | m.Name = MakeValidName(function.GetName()); 654 | 655 | if (uniqueMethods.find(m.FullName) != std::end(uniqueMethods)) 656 | { 657 | continue; 658 | } 659 | uniqueMethods.insert(m.FullName); 660 | 661 | m.IsNative = function.GetFunctionFlags() & UEFunctionFlags::Native; 662 | m.IsStatic = function.GetFunctionFlags() & UEFunctionFlags::Static; 663 | m.FlagsString = StringifyFlags(function.GetFunctionFlags()); 664 | 665 | std::vector> parameters; 666 | 667 | std::unordered_map unique; 668 | for (auto param = function.GetChildren().Cast(); param.IsValid(); param = param.GetNext().Cast()) 669 | { 670 | if (param.GetElementSize() == 0) 671 | { 672 | continue; 673 | } 674 | 675 | const auto info = param.GetInfo(); 676 | if (info.Type != UEProperty::PropertyType::Unknown) 677 | { 678 | using Type = Method::Parameter::Type; 679 | 680 | Method::Parameter p; 681 | 682 | if (!Method::Parameter::MakeType(param.GetPropertyFlags(), p.ParamType)) 683 | { 684 | //child isn't a parameter 685 | continue; 686 | } 687 | 688 | p.PassByReference = false; 689 | p.Name = MakeValidName(param.GetName()); 690 | 691 | const auto it = unique.find(p.Name); 692 | if (it == std::end(unique)) 693 | { 694 | unique[p.Name] = 1; 695 | } 696 | else 697 | { 698 | ++unique[p.Name]; 699 | 700 | p.Name += tfm::format("%02d", it->second); 701 | } 702 | 703 | p.FlagsString = StringifyFlags(param.GetPropertyFlags()); 704 | 705 | p.CppType = info.CppType; 706 | if (param.IsA()) 707 | { 708 | p.CppType = generator->GetOverrideType("bool"); 709 | } 710 | switch (p.ParamType) 711 | { 712 | case Type::Default: 713 | if (prop.GetArrayDim() > 1) 714 | { 715 | p.CppType = p.CppType + "*"; 716 | } 717 | else if (info.CanBeReference) 718 | { 719 | p.PassByReference = true; 720 | } 721 | break; 722 | } 723 | 724 | parameters.emplace_back(std::make_pair(prop, std::move(p))); 725 | } 726 | } 727 | 728 | std::sort(std::begin(parameters), std::end(parameters), [](auto&& lhs, auto&& rhs) { return ComparePropertyLess(lhs.first, rhs.first); }); 729 | 730 | for (auto& param : parameters) 731 | { 732 | m.Parameters.emplace_back(std::move(param.second)); 733 | } 734 | 735 | methods.emplace_back(std::move(m)); 736 | } 737 | } 738 | } 739 | 740 | void Package::SaveStructs(std::string path) const 741 | { 742 | extern IGenerator* generator; 743 | 744 | std::ofstream os(path + "/" + GenerateFileName(FileContentType::Structs, *this)); 745 | 746 | PrintFileHeader(os, true); 747 | 748 | if (!constants.empty()) 749 | { 750 | PrintSectionHeader(os, "Constants"); 751 | for (auto&& c : constants) { PrintConstant(os, c); } 752 | 753 | os << "\n"; 754 | } 755 | 756 | if (!enums.empty()) 757 | { 758 | PrintSectionHeader(os, "Enums"); 759 | for (auto&& e : enums) { PrintEnum(os, e); os << "\n"; } 760 | 761 | os << "\n"; 762 | } 763 | 764 | if (!scriptStructs.empty()) 765 | { 766 | PrintSectionHeader(os, "Script Structs"); 767 | for (auto&& s : scriptStructs) { PrintStruct(os, s); os << "\n"; } 768 | } 769 | 770 | PrintFileFooter(os); 771 | } 772 | 773 | void Package::SaveClasses(std::string path) const 774 | { 775 | extern IGenerator* generator; 776 | 777 | std::ofstream os(path + "/" + GenerateFileName(FileContentType::Classes, *this)); 778 | 779 | PrintFileHeader(os, true); 780 | 781 | if (!classes.empty()) 782 | { 783 | PrintSectionHeader(os, "Classes"); 784 | for (auto&& c : classes) { PrintClass(os, c); os << "\n"; } 785 | } 786 | 787 | PrintFileFooter(os); 788 | } 789 | 790 | void Package::SaveFunctions(std::string path) const 791 | { 792 | extern IGenerator* generator; 793 | 794 | using namespace cpplinq; 795 | 796 | if (generator->ShouldGenerateFunctionParametersFile()) 797 | { 798 | SaveFunctionParameters(path); 799 | } 800 | 801 | std::ofstream os(path + "/" + GenerateFileName(FileContentType::Functions, *this)); 802 | 803 | PrintFileHeader(os, { "\"../SDK.hpp\"" }, false); 804 | 805 | PrintSectionHeader(os, "Functions"); 806 | 807 | for (auto&& s : scriptStructs) 808 | { 809 | for (auto&& m : s.PredefinedMethods) 810 | { 811 | if (m.MethodType != IGenerator::PredefinedMethod::Type::Inline) 812 | { 813 | os << m.Body << "\n\n"; 814 | } 815 | } 816 | } 817 | 818 | for (auto&& c : classes) 819 | { 820 | for (auto&& m : c.PredefinedMethods) 821 | { 822 | if (m.MethodType != IGenerator::PredefinedMethod::Type::Inline) 823 | { 824 | os << m.Body << "\n\n"; 825 | } 826 | } 827 | 828 | for (auto&& m : c.Methods) 829 | { 830 | //Method Info 831 | os << "// " << m.FullName << "\n" 832 | << "// (" << m.FlagsString << ")\n"; 833 | if (!m.Parameters.empty()) 834 | { 835 | os << "// Parameters:\n"; 836 | for (auto&& param : m.Parameters) 837 | { 838 | tfm::format(os, "// %-30s %-30s (%s)\n", param.CppType, param.Name, param.FlagsString); 839 | } 840 | } 841 | 842 | os << "\n"; 843 | os << BuildMethodSignature(m, c, false) << "\n"; 844 | os << BuildMethodBody(c, m) << "\n\n"; 845 | } 846 | } 847 | 848 | PrintFileFooter(os); 849 | } 850 | 851 | void Package::SaveFunctionParameters(std::string path) const 852 | { 853 | using namespace cpplinq; 854 | 855 | std::ofstream os(path + "/" + GenerateFileName(FileContentType::FunctionParameters, *this)); 856 | 857 | PrintFileHeader(os, { "\"../SDK.hpp\"" }, true); 858 | 859 | PrintSectionHeader(os, "Parameters"); 860 | 861 | for (auto&& c : classes) 862 | { 863 | for (auto&& m : c.Methods) 864 | { 865 | os << "// " << m.FullName << "\n"; 866 | tfm::format(os, "struct %s_%s_Params\n{\n", c.NameCpp, m.Name); 867 | for (auto&& param : m.Parameters) 868 | { 869 | tfm::format(os, "\t%-50s %-58s// (%s)\n", param.CppType, param.Name + ";", param.FlagsString); 870 | } 871 | os << "};\n\n"; 872 | } 873 | } 874 | 875 | PrintFileFooter(os); 876 | } 877 | 878 | void Package::PrintConstant(std::ostream& os, const std::pair& c) const 879 | { 880 | tfm::format(os, "#define CONST_%-50s %s\n", c.first, c.second); 881 | } 882 | 883 | void Package::PrintEnum(std::ostream& os, const Enum& e) const 884 | { 885 | using namespace cpplinq; 886 | 887 | os << "// " << e.FullName << "\nenum class " << e.Name << " : uint8_t\n{\n"; 888 | os << (from(e.Values) 889 | >> select([](auto&& name, auto&& i) { return tfm::format("\t%-30s = %d", name, i); }) 890 | >> concatenate(",\n")) 891 | << "\n};\n\n"; 892 | } 893 | 894 | void Package::PrintStruct(std::ostream& os, const ScriptStruct& ss) const 895 | { 896 | using namespace cpplinq; 897 | 898 | os << "// " << ss.FullName << "\n// "; 899 | if (ss.InheritedSize) 900 | { 901 | os << tfm::format("0x%04X (0x%04X - 0x%04X)\n", ss.Size - ss.InheritedSize, ss.Size, ss.InheritedSize); 902 | } 903 | else 904 | { 905 | os << tfm::format("0x%04X\n", ss.Size); 906 | } 907 | 908 | os << ss.NameCppFull << "\n{\n"; 909 | 910 | //Member 911 | os << (from(ss.Members) 912 | >> select([](auto&& m) { 913 | return tfm::format("\t%-50s %-58s// 0x%04X(0x%04X)", m.Type, m.Name + ";", m.Offset, m.Size) 914 | + (!m.Comment.empty() ? " " + m.Comment : "") 915 | + (!m.FlagsString.empty() ? " (" + m.FlagsString + ")" : ""); 916 | }) 917 | >> concatenate("\n")) 918 | << "\n"; 919 | 920 | //Predefined Methods 921 | if (!ss.PredefinedMethods.empty()) 922 | { 923 | os << "\n"; 924 | for (auto&& m : ss.PredefinedMethods) 925 | { 926 | if (m.MethodType == IGenerator::PredefinedMethod::Type::Inline) 927 | { 928 | os << m.Body; 929 | } 930 | else 931 | { 932 | os << "\t" << m.Signature << ";"; 933 | } 934 | os << "\n\n"; 935 | } 936 | } 937 | 938 | os << "};\n"; 939 | } 940 | 941 | void Package::PrintClass(std::ostream& os, const Class& c) const 942 | { 943 | using namespace cpplinq; 944 | 945 | os << "// " << c.FullName << "\n// "; 946 | if (c.InheritedSize) 947 | { 948 | tfm::format(os, "0x%04X (0x%04X - 0x%04X)\n", c.Size - c.InheritedSize, c.Size, c.InheritedSize); 949 | } 950 | else 951 | { 952 | tfm::format(os, "0x%04X\n", c.Size); 953 | } 954 | 955 | os << c.NameCppFull << "\n{\npublic:\n"; 956 | 957 | //Member 958 | for (auto&& m : c.Members) 959 | { 960 | tfm::format(os, "\t%-50s %-58s// 0x%04X(0x%04X)", m.Type, m.Name + ";", m.Offset, m.Size); 961 | if (!m.Comment.empty()) 962 | { 963 | os << " " << m.Comment; 964 | } 965 | if (!m.FlagsString.empty()) 966 | { 967 | os << " (" << m.FlagsString << ")"; 968 | } 969 | os << "\n"; 970 | } 971 | 972 | //Predefined Methods 973 | if (!c.PredefinedMethods.empty()) 974 | { 975 | os << "\n"; 976 | for (auto&& m : c.PredefinedMethods) 977 | { 978 | if (m.MethodType == IGenerator::PredefinedMethod::Type::Inline) 979 | { 980 | os << m.Body; 981 | } 982 | else 983 | { 984 | os << "\t" << m.Signature << ";"; 985 | } 986 | 987 | os << "\n\n"; 988 | } 989 | } 990 | 991 | //Methods 992 | if (!c.Methods.empty()) 993 | { 994 | os << "\n"; 995 | for (auto&& m : c.Methods) 996 | { 997 | os << "\t" << BuildMethodSignature(m, {}, true) << ";\n"; 998 | } 999 | } 1000 | 1001 | os << "};\n\n"; 1002 | } 1003 | 1004 | std::string Package::BuildMethodSignature(const Method& m, const Class& c, bool inHeader) const 1005 | { 1006 | extern IGenerator* generator; 1007 | 1008 | using namespace cpplinq; 1009 | using Type = Method::Parameter::Type; 1010 | 1011 | std::ostringstream ss; 1012 | 1013 | if (m.IsStatic && inHeader && !generator->ShouldConvertStaticMethods()) 1014 | { 1015 | ss << "static "; 1016 | } 1017 | 1018 | //Return Type 1019 | auto retn = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Return; }); 1020 | if (retn >> any()) 1021 | { 1022 | ss << (retn >> first()).CppType; 1023 | } 1024 | else 1025 | { 1026 | ss << "void"; 1027 | } 1028 | ss << " "; 1029 | 1030 | if (!inHeader) 1031 | { 1032 | ss << c.NameCpp << "::"; 1033 | } 1034 | if (m.IsStatic && generator->ShouldConvertStaticMethods()) 1035 | { 1036 | ss << "STATIC_"; 1037 | } 1038 | ss << m.Name; 1039 | 1040 | //Parameters 1041 | ss << "("; 1042 | ss << (from(m.Parameters) 1043 | >> where([](auto&& param) { return param.ParamType != Type::Return; }) 1044 | >> orderby([](auto&& param) { return param.ParamType; }) 1045 | >> select([](auto&& param) { return (param.PassByReference ? "const " : "") + param.CppType + (param.PassByReference ? "& " : param.ParamType == Type::Out ? "* " : " ") + param.Name; }) 1046 | >> concatenate(", ")); 1047 | ss << ")"; 1048 | 1049 | return ss.str(); 1050 | } 1051 | 1052 | std::string Package::BuildMethodBody(const Class& c, const Method& m) const 1053 | { 1054 | extern IGenerator* generator; 1055 | 1056 | using namespace cpplinq; 1057 | using Type = Method::Parameter::Type; 1058 | 1059 | std::ostringstream ss; 1060 | 1061 | //Function Pointer 1062 | ss << "{\n\tstatic UFunction *pFunc = 0;"; 1063 | ss << "\n\tif (!pFunc)"; 1064 | ss << "\n\t\tpFunc "; 1065 | 1066 | if (generator->ShouldUseStrings()) 1067 | { 1068 | ss << " = UObject::FindObject("; 1069 | 1070 | if (generator->ShouldXorStrings()) 1071 | { 1072 | ss << "_xor_(\"" << m.FullName << "\")"; 1073 | } 1074 | else 1075 | { 1076 | ss << "\"" << m.FullName << "\""; 1077 | } 1078 | 1079 | ss << ");\n\n"; 1080 | } 1081 | else 1082 | { 1083 | ss << " = UObject::GetObjectCasted(" << m.Index << ");\n\n"; 1084 | } 1085 | 1086 | //Parameters 1087 | if (generator->ShouldGenerateFunctionParametersFile()) 1088 | { 1089 | ss << "\t" << c.NameCpp << "_" << m.Name << "_Params params;\n"; 1090 | } 1091 | else 1092 | { 1093 | ss << "\tstruct\n\t{\n"; 1094 | for (auto&& param : m.Parameters) 1095 | { 1096 | tfm::format(ss, "\t\t%-30s %s;\n", param.CppType, param.Name); 1097 | } 1098 | ss << "\t} params;\n"; 1099 | } 1100 | 1101 | auto defaultParameters = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Default; }); 1102 | if (defaultParameters >> any()) 1103 | { 1104 | for (auto&& param : defaultParameters >> experimental::container()) 1105 | { 1106 | ss << "\tparams." << param.Name << " = " << param.Name << ";\n"; 1107 | } 1108 | } 1109 | 1110 | ss << "\n"; 1111 | 1112 | //Function Call 1113 | ss << "\tauto flags = pFunc->FunctionFlags;\n"; 1114 | //ss << "\tpFunc->FunctionFlags |= 0x400;\n"; 1115 | if (m.IsNative) 1116 | { 1117 | ss << "\tpFunc->FunctionFlags |= 0x" << tfm::format("%X", static_cast>(UEFunctionFlags::Native)) << ";\n"; 1118 | } 1119 | 1120 | ss << "\n"; 1121 | 1122 | if (m.IsStatic && !generator->ShouldConvertStaticMethods()) 1123 | { 1124 | ss << "\tstatic auto defaultObj = StaticClass()->CreateDefaultObject();\n"; 1125 | ss << "\tdefaultObj->ProcessEvent(pFunc, ¶ms);\n\n"; 1126 | } 1127 | else 1128 | { 1129 | ss << "\tUObject *currentObj = (UObject *) this;\n"; 1130 | ss << "\tcurrentObj->ProcessEvent(pFunc, ¶ms);\n\n"; 1131 | } 1132 | 1133 | ss << "\tpFunc->FunctionFlags = flags;\n"; 1134 | 1135 | //Out Parameters 1136 | auto out = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Out; }); 1137 | if (out >> any()) 1138 | { 1139 | ss << "\n"; 1140 | 1141 | for (auto&& param : out >> experimental::container()) 1142 | { 1143 | ss << "\tif (" << param.Name << " != nullptr)\n"; 1144 | ss << "\t\t*" << param.Name << " = params." << param.Name << ";\n"; 1145 | } 1146 | } 1147 | 1148 | //Return Value 1149 | auto retn = from(m.Parameters) >> where([](auto&& param) { return param.ParamType == Type::Return; }); 1150 | if (retn >> any()) 1151 | { 1152 | ss << "\n\treturn params." << (retn >> first()).Name << ";\n"; 1153 | } 1154 | 1155 | ss << "}\n"; 1156 | 1157 | return ss.str(); 1158 | } 1159 | -------------------------------------------------------------------------------- /Source/jni/src/Package.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "UE4/GenericTypes.hpp" 8 | 9 | 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 | static std::unordered_map PackageMap; 19 | 20 | /// 21 | /// Constructor. 22 | /// 23 | /// The package object. 24 | Package(const UEObject& packageObj); 25 | 26 | std::string GetName() const { return packageObj.GetName(); } 27 | 28 | /// 29 | /// Process the classes the package contains. 30 | /// 31 | void Process(std::unordered_map& processedObjects); 32 | 33 | /// 34 | /// Saves the package classes as C++ code. 35 | /// Files are only generated if there is code present or the generator forces the genertion of empty files. 36 | /// 37 | /// The path to save to. 38 | /// true if files got saved, else false. 39 | bool Save(std::string path) const; 40 | 41 | private: 42 | bool AddDependency(const UEObject& package) const; 43 | 44 | /// 45 | /// Checks and generates the prerequisites of the object. 46 | /// Should be a UEClass or UEScriptStruct. 47 | /// 48 | /// The object. 49 | void GeneratePrerequisites(const UEObject& obj, std::unordered_map& processedObjects); 50 | 51 | /// 52 | /// Checks and generates the prerequisites of the members. 53 | /// 54 | /// The first member in the chain. 55 | void GenerateMemberPrerequisites(const UEProperty& first, std::unordered_map& processedObjects); 56 | 57 | /// 58 | /// Generates a script structure. 59 | /// 60 | /// The script structure object. 61 | void GenerateScriptStruct(const UEScriptStruct& scriptStructObj); 62 | 63 | /// 64 | /// Generates a constant. 65 | /// 66 | /// The constant object. 67 | void GenerateConst(const UEConst& constObj); 68 | 69 | /// 70 | /// Generates an enum. 71 | /// 72 | /// The enum object. 73 | void GenerateEnum(const UEEnum& enumObj); 74 | 75 | /// 76 | /// Generates the class. 77 | /// 78 | /// The class object. 79 | void GenerateClass(const UEClass& classObj); 80 | 81 | /// 82 | /// Writes all structs into the appropriate file. 83 | /// 84 | /// The path to save to. 85 | void SaveStructs(std::string path) const; 86 | 87 | /// 88 | /// Writes all classes into the appropriate file. 89 | /// 90 | /// The path to save to. 91 | void SaveClasses(std::string path) const; 92 | 93 | /// 94 | /// Writes all functions into the appropriate file. 95 | /// 96 | /// The path to save to. 97 | void SaveFunctions(std::string path) const; 98 | 99 | /// 100 | /// Writes all function parameters into the appropriate file. 101 | /// 102 | /// The path to save to. 103 | void SaveFunctionParameters(std::string path) const; 104 | 105 | UEObject packageObj; 106 | mutable std::unordered_set dependencies; 107 | 108 | /// 109 | /// Prints the c++ code of the constant. 110 | /// 111 | /// [in] The stream to print to. 112 | /// The constant to print. 113 | void PrintConstant(std::ostream& os, const std::pair& c) const; 114 | 115 | std::unordered_map constants; 116 | 117 | struct Enum 118 | { 119 | std::string Name; 120 | std::string FullName; 121 | std::vector Values; 122 | }; 123 | 124 | /// 125 | /// Prints the c++ code of the enum. 126 | /// 127 | /// [in] The stream to print to. 128 | /// The enum to print. 129 | void PrintEnum(std::ostream& os, const Enum& e) const; 130 | 131 | std::vector enums; 132 | 133 | struct Member 134 | { 135 | std::string Name; 136 | std::string Type; 137 | 138 | size_t Offset; 139 | size_t Size; 140 | 141 | size_t Flags; 142 | std::string FlagsString; 143 | 144 | std::string Comment; 145 | }; 146 | 147 | /// 148 | /// Generates a padding member. 149 | /// 150 | /// The unique name identifier. 151 | /// The offset. 152 | /// The size. 153 | /// The reason. 154 | /// A padding member. 155 | static Member CreatePadding(size_t id, size_t offset, size_t size, std::string reason); 156 | 157 | /// 158 | /// Generates a padding member. 159 | /// 160 | /// The unique name identifier. 161 | /// The offset. 162 | /// The size. 163 | /// The reason. 164 | /// A padding member. 165 | static Member CreateBitfieldPadding(size_t id, size_t offset, std::string type, size_t bits); 166 | 167 | /// 168 | /// Generates the members of a struct or class. 169 | /// 170 | /// The structure object. 171 | /// The start offset. 172 | /// The properties describing the members. 173 | /// [out] The members of the struct or class. 174 | void GenerateMembers(const UEStruct& structObj, size_t offset, const std::vector& properties, std::vector& members) const; 175 | 176 | struct ScriptStruct 177 | { 178 | std::string Name; 179 | std::string FullName; 180 | std::string NameCpp; 181 | std::string NameCppFull; 182 | 183 | size_t Size; 184 | size_t InheritedSize; 185 | 186 | std::vector Members; 187 | 188 | std::vector PredefinedMethods; 189 | }; 190 | 191 | /// 192 | /// Print the C++ code of the structure. 193 | /// 194 | /// [in] The stream to print to. 195 | /// The structure to print. 196 | void PrintStruct(std::ostream& os, const ScriptStruct& ss) const; 197 | 198 | std::vector scriptStructs; 199 | 200 | struct Method 201 | { 202 | struct Parameter 203 | { 204 | enum class Type 205 | { 206 | Default, 207 | Out, 208 | Return 209 | }; 210 | 211 | Type ParamType; 212 | bool PassByReference; 213 | std::string CppType; 214 | std::string Name; 215 | std::string FlagsString; 216 | 217 | /// 218 | /// Generates a valid type of the property flags. 219 | /// 220 | /// The property flags. 221 | /// [out] The parameter type. 222 | /// true if it is a valid type, else false. 223 | static bool MakeType(UEPropertyFlags flags, Type& type); 224 | }; 225 | 226 | size_t Index; 227 | std::string Name; 228 | std::string FullName; 229 | std::vector Parameters; 230 | std::string FlagsString; 231 | bool IsNative; 232 | bool IsStatic; 233 | }; 234 | 235 | /// 236 | /// Generates the methods of a class. 237 | /// 238 | /// The class object. 239 | /// [out] The methods of the class. 240 | void GenerateMethods(const UEClass& classObj, std::vector& methods) const; 241 | 242 | struct Class : ScriptStruct 243 | { 244 | std::vector VirtualFunctions; 245 | std::vector Methods; 246 | }; 247 | 248 | /// 249 | /// Builds the C++ method signature. 250 | /// 251 | /// The Method to process. 252 | /// Name of the class. 253 | /// true if the signature is used as decleration. 254 | /// The method signature. 255 | std::string BuildMethodSignature(const Method& m, const Class& c, bool inHeader) const; 256 | 257 | /// 258 | /// Builds the c++ method body. 259 | /// 260 | /// The Method to process. 261 | /// The method body. 262 | std::string BuildMethodBody(const Class& c, const Method& m) const; 263 | 264 | /// 265 | /// Print the C++ code of the class. 266 | /// 267 | /// [in] The stream to print to. 268 | /// The class to print. 269 | void PrintClass(std::ostream& os, const Class& c) const; 270 | 271 | std::vector classes; 272 | }; 273 | 274 | namespace std 275 | { 276 | template<> 277 | struct hash 278 | { 279 | size_t operator()(const Package& package) const 280 | { 281 | return std::hash()(package.packageObj.GetAddress()); 282 | } 283 | }; 284 | } 285 | 286 | inline bool operator==(const Package& lhs, const Package& rhs) { return rhs.packageObj.GetAddress() == lhs.packageObj.GetAddress(); } 287 | inline bool operator!=(const Package& lhs, const Package& rhs) { return !(lhs == rhs); } 288 | 289 | struct PackageDependencyComparer 290 | { 291 | bool operator()(const std::unique_ptr& lhs, const std::unique_ptr& rhs) const 292 | { 293 | return operator()(*lhs, *rhs); 294 | } 295 | 296 | bool operator()(const Package* lhs, const Package* rhs) const 297 | { 298 | return operator()(*lhs, *rhs); 299 | } 300 | 301 | bool operator()(const Package& lhs, const Package& rhs) const 302 | { 303 | if (rhs.dependencies.empty()) 304 | { 305 | return false; 306 | } 307 | 308 | if (std::find(std::begin(rhs.dependencies), std::end(rhs.dependencies), lhs.packageObj) != std::end(rhs.dependencies)) 309 | { 310 | return true; 311 | } 312 | 313 | for (const auto dep : rhs.dependencies) 314 | { 315 | const auto package = Package::PackageMap[dep]; 316 | if (package == nullptr) 317 | { 318 | // Missing package, should not occur... 319 | continue; 320 | } 321 | 322 | if (operator()(lhs, *package)) 323 | { 324 | return true; 325 | } 326 | } 327 | 328 | return false; 329 | } 330 | }; 331 | -------------------------------------------------------------------------------- /Source/jni/src/PrintHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintHelper.hpp" 2 | 3 | #include "tinyformat.h" 4 | 5 | #include "IGenerator.hpp" 6 | #include "Package.hpp" 7 | 8 | 9 | void PrintFileHeader(std::ostream& os, const std::vector& includes, bool isHeaderFile) 10 | { 11 | extern IGenerator* generator; 12 | 13 | if (isHeaderFile) 14 | { 15 | os << "#pragma once\n\n"; 16 | } 17 | 18 | os << tfm::format("// %s (%s) SDK by Dyno\n\n", generator->GetGameName(), generator->GetGameVersion()); 19 | //<< tfm::format("#ifdef _MSC_VER\n\t#pragma pack(push, 0x%X)\n#endif\n\n", generator->GetGlobalMemberAlignment()); 20 | 21 | if (!includes.empty()) 22 | { 23 | for (auto&& i : includes) { os << "#include " << i << "\n"; } 24 | os << "\n"; 25 | } 26 | 27 | if (!generator->GetNamespaceName().empty()) 28 | { 29 | os << "namespace " << generator->GetNamespaceName() << "\n{\n"; 30 | } 31 | } 32 | 33 | void PrintFileHeader(std::ostream& os, bool isHeaderFile) 34 | { 35 | extern IGenerator* generator; 36 | 37 | PrintFileHeader(os, std::vector(), isHeaderFile); 38 | } 39 | 40 | void PrintFileFooter(std::ostream& os) 41 | { 42 | extern IGenerator* generator; 43 | 44 | if (!generator->GetNamespaceName().empty()) 45 | { 46 | os << "}\n\n"; 47 | } 48 | 49 | //os << "#ifdef _MSC_VER\n\t#pragma pack(pop)\n#endif\n"; 50 | } 51 | 52 | void PrintSectionHeader(std::ostream& os, const char* name) 53 | { 54 | os << "//---------------------------------------------------------------------------\n" 55 | << "//" << name << "\n" 56 | << "//---------------------------------------------------------------------------\n\n"; 57 | } 58 | 59 | std::string GenerateFileName(FileContentType type, const Package& package) 60 | { 61 | extern IGenerator* generator; 62 | 63 | const char* name; 64 | switch (type) 65 | { 66 | case FileContentType::Structs: 67 | name = "%s_%s_structs.hpp"; 68 | break; 69 | case FileContentType::Classes: 70 | name = "%s_%s_classes.hpp"; 71 | break; 72 | case FileContentType::Functions: 73 | name = "%s_%s_functions.cpp"; 74 | break; 75 | case FileContentType::FunctionParameters: 76 | name = "%s_%s_parameters.hpp"; 77 | break; 78 | default: 79 | assert(false); 80 | } 81 | 82 | return tfm::format(name, generator->GetGameNameShort(), package.GetName()); 83 | } 84 | -------------------------------------------------------------------------------- /Source/jni/src/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 | -------------------------------------------------------------------------------- /Source/jni/src/Tools.cpp: -------------------------------------------------------------------------------- 1 | #include "Tools.h" 2 | 3 | #if defined(__arm__) 4 | #define process_vm_readv_syscall 376 5 | #define process_vm_writev_syscall 377 6 | #elif defined(__aarch64__) 7 | #define process_vm_readv_syscall 270 8 | #define process_vm_writev_syscall 271 9 | #elif defined(__i386__) 10 | #define process_vm_readv_syscall 347 11 | #define process_vm_writev_syscall 348 12 | #else 13 | #define process_vm_readv_syscall 310 14 | #define process_vm_writev_syscall 311 15 | #endif 16 | 17 | pid_t target_pid = -1; 18 | 19 | ssize_t process_v(pid_t __pid, const struct iovec *__local_iov, unsigned long __local_iov_count, const struct iovec *__remote_iov, unsigned long __remote_iov_count, unsigned long __flags, bool iswrite) { 20 | return syscall((iswrite ? process_vm_writev_syscall : process_vm_readv_syscall), __pid, __local_iov, __local_iov_count, __remote_iov, __remote_iov_count, __flags); 21 | } 22 | 23 | bool pvm(void *address, void *buffer, size_t size, bool write = false) { 24 | struct iovec local[1]; 25 | struct iovec remote[1]; 26 | 27 | local[0].iov_base = buffer; 28 | local[0].iov_len = size; 29 | remote[0].iov_base = address; 30 | remote[0].iov_len = size; 31 | 32 | if (target_pid == -1) { 33 | target_pid = getpid(); 34 | } 35 | 36 | ssize_t bytes = process_v(target_pid, local, 1, remote, 1, 0, write); 37 | return bytes == size; 38 | } 39 | bool Tools::Read(void *addr, void *buffer, size_t length) { 40 | return memcpy(buffer, addr, length) != 0; 41 | } 42 | 43 | bool Tools::Write(void *addr, void *buffer, size_t length) { 44 | return memcpy(addr, buffer, length) != 0; 45 | } 46 | 47 | bool Tools::ReadAddr(void *addr, void *buffer, size_t length) { 48 | unsigned long page_size = sysconf(_SC_PAGESIZE); 49 | unsigned long size = page_size * sizeof(uintptr_t); 50 | return mprotect((void *) ((uintptr_t) addr - ((uintptr_t) addr % page_size) - page_size), (size_t) size, PROT_EXEC | PROT_READ | PROT_WRITE) == 0 && memcpy(buffer, addr, length) != 0; 51 | } 52 | 53 | bool Tools::WriteAddr(void *addr, void *buffer, size_t length) { 54 | unsigned long page_size = sysconf(_SC_PAGESIZE); 55 | unsigned long size = page_size * sizeof(uintptr_t); 56 | return mprotect((void *) ((uintptr_t) addr - ((uintptr_t) addr % page_size) - page_size), (size_t) size, PROT_EXEC | PROT_READ | PROT_WRITE) == 0 && memcpy(addr, buffer, length) != 0; 57 | } 58 | 59 | bool Tools::PVM_ReadAddr(void *addr, void *buffer, size_t length) { 60 | return pvm(addr, buffer, length, false); 61 | } 62 | 63 | bool Tools::PVM_WriteAddr(void *addr, void *buffer, size_t length) { 64 | return pvm(addr, buffer, length, true); 65 | } 66 | 67 | bool Tools::IsPtrValid(void *addr) { 68 | if (!addr) { 69 | return false; 70 | } 71 | static int fd = -1; 72 | if (fd == -1) { 73 | fd = open("/dev/random", O_WRONLY); 74 | } 75 | return write(fd, addr, 4) >= 0; 76 | } 77 | 78 | uintptr_t Tools::GetBaseAddress(const char *name) { 79 | uintptr_t base = 0; 80 | char line[512]; 81 | 82 | FILE *f = fopen("/proc/self/maps", "r"); 83 | 84 | if (!f) { 85 | return 0; 86 | } 87 | 88 | while (fgets(line, sizeof line, f)) { 89 | uintptr_t tmpBase; 90 | char tmpName[256]; 91 | if (sscanf(line, "%" PRIXPTR "-%*" PRIXPTR " %*s %*s %*s %*s %s", &tmpBase, tmpName) > 0) { 92 | if (!strcmp(basename(tmpName), name)) { 93 | base = tmpBase; 94 | break; 95 | } 96 | } 97 | } 98 | 99 | fclose(f); 100 | return base; 101 | } 102 | 103 | uintptr_t Tools::GetEndAddress(const char *name) { 104 | uintptr_t end = 0; 105 | char line[512]; 106 | 107 | FILE *f = fopen("/proc/self/maps", "r"); 108 | 109 | if (!f) { 110 | return 0; 111 | } 112 | 113 | while (fgets(line, sizeof line, f)) { 114 | uintptr_t tmpEnd; 115 | char tmpName[256]; 116 | if (sscanf(line, "%*" PRIXPTR "-%" PRIXPTR " %*s %*s %*s %*s %s", &tmpEnd, tmpName) > 0) { 117 | if (!strcmp(basename(tmpName), name)) { 118 | end = tmpEnd; 119 | } else { 120 | if (end) 121 | break; 122 | } 123 | } 124 | } 125 | 126 | fclose(f); 127 | return end; 128 | } 129 | -------------------------------------------------------------------------------- /Source/jni/src/Tools.h: -------------------------------------------------------------------------------- 1 | #include "Includes.h" 2 | 3 | namespace Tools 4 | { 5 | void Hook(void *target, void *replace, void **backup); 6 | bool Read(void *addr, void *buffer, size_t length); 7 | bool Write(void *addr, void *buffer, size_t length); 8 | bool ReadAddr(void *addr, void *buffer, size_t length); 9 | bool WriteAddr(void *addr, void *buffer, size_t length); 10 | 11 | bool PVM_ReadAddr(void *addr, void *buffer, size_t length); 12 | bool PVM_WriteAddr(void *addr, void *buffer, size_t length); 13 | 14 | bool IsPtrValid(void *addr); 15 | 16 | uintptr_t GetBaseAddress(const char *name); 17 | uintptr_t GetEndAddress(const char *name); 18 | 19 | std::string RandomString(const int len); 20 | std::string GetPackageName(JNIEnv *env, jobject context); 21 | 22 | std::string CalcMD5(std::string s); 23 | std::string CalcSHA256(std::string s); 24 | } 25 | -------------------------------------------------------------------------------- /Source/jni/src/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 | } -------------------------------------------------------------------------------- /Source/jni/src/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 | -------------------------------------------------------------------------------- /Source/jni/src/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 UEClass StaticClass(); 187 | }; 188 | 189 | class UENumericProperty : public UEProperty 190 | { 191 | public: 192 | using UEProperty::UEProperty; 193 | 194 | static UEClass StaticClass(); 195 | }; 196 | 197 | class UEByteProperty : public UENumericProperty 198 | { 199 | public: 200 | using UENumericProperty::UENumericProperty; 201 | 202 | bool IsEnum() const; 203 | 204 | UEEnum GetEnum() const; 205 | 206 | UEProperty::Info GetInfo() const; 207 | 208 | static UEClass StaticClass(); 209 | }; 210 | 211 | class UEUInt16Property : public UENumericProperty 212 | { 213 | public: 214 | using UENumericProperty::UENumericProperty; 215 | 216 | UEProperty::Info GetInfo() const; 217 | 218 | static UEClass StaticClass(); 219 | }; 220 | 221 | class UEUInt32Property : public UENumericProperty 222 | { 223 | public: 224 | using UENumericProperty::UENumericProperty; 225 | 226 | UEProperty::Info GetInfo() const; 227 | 228 | static UEClass StaticClass(); 229 | }; 230 | 231 | class UEUInt64Property : public UENumericProperty 232 | { 233 | public: 234 | using UENumericProperty::UENumericProperty; 235 | 236 | UEProperty::Info GetInfo() const; 237 | 238 | static UEClass StaticClass(); 239 | }; 240 | 241 | class UEInt8Property : public UENumericProperty 242 | { 243 | public: 244 | using UENumericProperty::UENumericProperty; 245 | 246 | UEProperty::Info GetInfo() const; 247 | 248 | static UEClass StaticClass(); 249 | }; 250 | 251 | class UEInt16Property : public UENumericProperty 252 | { 253 | public: 254 | using UENumericProperty::UENumericProperty; 255 | 256 | UEProperty::Info GetInfo() const; 257 | 258 | static UEClass StaticClass(); 259 | }; 260 | 261 | class UEIntProperty : public UENumericProperty 262 | { 263 | public: 264 | using UENumericProperty::UENumericProperty; 265 | 266 | UEProperty::Info GetInfo() const; 267 | 268 | static UEClass StaticClass(); 269 | }; 270 | 271 | class UEInt64Property : public UENumericProperty 272 | { 273 | public: 274 | using UENumericProperty::UENumericProperty; 275 | 276 | UEProperty::Info GetInfo() const; 277 | 278 | static UEClass StaticClass(); 279 | }; 280 | 281 | class UEFloatProperty : public UENumericProperty 282 | { 283 | public: 284 | using UENumericProperty::UENumericProperty; 285 | 286 | UEProperty::Info GetInfo() const; 287 | 288 | static UEClass StaticClass(); 289 | }; 290 | 291 | class UEDoubleProperty : public UENumericProperty 292 | { 293 | public: 294 | using UENumericProperty::UENumericProperty; 295 | 296 | UEProperty::Info GetInfo() const; 297 | 298 | static UEClass StaticClass(); 299 | }; 300 | 301 | class UEBoolProperty : public UEProperty 302 | { 303 | public: 304 | using UEProperty::UEProperty; 305 | 306 | bool IsNativeBool() const { return GetFieldMask() == 0xFF; } 307 | 308 | bool IsBitfield() const { return !IsNativeBool(); } 309 | 310 | uint8_t GetFieldSize() const; 311 | 312 | uint8_t GetByteOffset() const; 313 | 314 | uint8_t GetByteMask() const; 315 | 316 | uint8_t GetFieldMask() const; 317 | 318 | std::array GetMissingBitsCount(const UEBoolProperty& other) const; 319 | 320 | UEProperty::Info GetInfo() const; 321 | 322 | static UEClass StaticClass(); 323 | }; 324 | 325 | inline bool operator<(const UEBoolProperty& lhs, const UEBoolProperty& rhs) 326 | { 327 | if (lhs.GetByteOffset() == rhs.GetByteOffset()) 328 | { 329 | return lhs.GetByteMask() < rhs.GetByteMask(); 330 | } 331 | return lhs.GetByteOffset() < rhs.GetByteOffset(); 332 | } 333 | 334 | class UEObjectPropertyBase : public UEProperty 335 | { 336 | public: 337 | using UEProperty::UEProperty; 338 | 339 | UEClass GetPropertyClass() const; 340 | 341 | static UEClass StaticClass(); 342 | }; 343 | 344 | class UEObjectProperty : public UEObjectPropertyBase 345 | { 346 | public: 347 | using UEObjectPropertyBase::UEObjectPropertyBase; 348 | 349 | UEProperty::Info GetInfo() const; 350 | 351 | static UEClass StaticClass(); 352 | }; 353 | 354 | class UEClassProperty : public UEObjectProperty 355 | { 356 | public: 357 | using UEObjectProperty::UEObjectProperty; 358 | 359 | UEClass GetMetaClass() const; 360 | 361 | UEProperty::Info GetInfo() const; 362 | 363 | static UEClass StaticClass(); 364 | }; 365 | 366 | class UEInterfaceProperty : public UEProperty 367 | { 368 | public: 369 | using UEProperty::UEProperty; 370 | 371 | UEClass GetInterfaceClass() const; 372 | 373 | UEProperty::Info GetInfo() const; 374 | 375 | static UEClass StaticClass(); 376 | }; 377 | 378 | class UEWeakObjectProperty : public UEObjectPropertyBase 379 | { 380 | public: 381 | using UEObjectPropertyBase::UEObjectPropertyBase; 382 | 383 | UEProperty::Info GetInfo() const; 384 | 385 | static UEClass StaticClass(); 386 | }; 387 | 388 | class UELazyObjectProperty : public UEObjectPropertyBase 389 | { 390 | public: 391 | using UEObjectPropertyBase::UEObjectPropertyBase; 392 | 393 | UEProperty::Info GetInfo() const; 394 | 395 | static UEClass StaticClass(); 396 | }; 397 | 398 | class UEAssetObjectProperty : public UEObjectPropertyBase 399 | { 400 | public: 401 | using UEObjectPropertyBase::UEObjectPropertyBase; 402 | 403 | UEProperty::Info GetInfo() const; 404 | 405 | static UEClass StaticClass(); 406 | }; 407 | 408 | class UEAssetClassProperty : public UEAssetObjectProperty 409 | { 410 | public: 411 | using UEAssetObjectProperty::UEAssetObjectProperty; 412 | 413 | UEClass GetMetaClass() const; 414 | 415 | UEProperty::Info GetInfo() const; 416 | 417 | static UEClass StaticClass(); 418 | }; 419 | 420 | class UENameProperty : public UEProperty 421 | { 422 | public: 423 | using UEProperty::UEProperty; 424 | 425 | UEProperty::Info GetInfo() const; 426 | 427 | static UEClass StaticClass(); 428 | }; 429 | 430 | class UEStructProperty : public UEProperty 431 | { 432 | public: 433 | using UEProperty::UEProperty; 434 | 435 | UEScriptStruct GetStruct() const; 436 | 437 | UEProperty::Info GetInfo() const; 438 | 439 | static UEClass StaticClass(); 440 | }; 441 | 442 | class UEStrProperty : public UEProperty 443 | { 444 | public: 445 | using UEProperty::UEProperty; 446 | 447 | UEProperty::Info GetInfo() const; 448 | 449 | static UEClass StaticClass(); 450 | }; 451 | 452 | class UETextProperty : public UEProperty 453 | { 454 | public: 455 | using UEProperty::UEProperty; 456 | 457 | UEProperty::Info GetInfo() const; 458 | 459 | static UEClass StaticClass(); 460 | }; 461 | 462 | class UEArrayProperty : public UEProperty 463 | { 464 | public: 465 | using UEProperty::UEProperty; 466 | 467 | UEProperty GetInner() const; 468 | 469 | UEProperty::Info GetInfo() const; 470 | 471 | static UEClass StaticClass(); 472 | }; 473 | 474 | class UEMapProperty : public UEProperty 475 | { 476 | public: 477 | using UEProperty::UEProperty; 478 | 479 | UEProperty GetKeyProperty() const; 480 | UEProperty GetValueProperty() const; 481 | 482 | UEProperty::Info GetInfo() const; 483 | 484 | static UEClass StaticClass(); 485 | }; 486 | 487 | class UEDelegateProperty : public UEProperty 488 | { 489 | public: 490 | using UEProperty::UEProperty; 491 | 492 | UEFunction GetSignatureFunction() const; 493 | 494 | UEProperty::Info GetInfo() const; 495 | 496 | static UEClass StaticClass(); 497 | }; 498 | 499 | class UEMulticastDelegateProperty : public UEProperty 500 | { 501 | public: 502 | using UEProperty::UEProperty; 503 | 504 | UEFunction GetSignatureFunction() const; 505 | 506 | UEProperty::Info GetInfo() const; 507 | 508 | static UEClass StaticClass(); 509 | }; 510 | 511 | class UEEnumProperty : public UEProperty 512 | { 513 | public: 514 | using UEProperty::UEProperty; 515 | 516 | UENumericProperty GetUnderlyingProperty() const; 517 | UEEnum GetEnum() const; 518 | 519 | UEProperty::Info GetInfo() const; 520 | 521 | static UEClass StaticClass(); 522 | }; 523 | 524 | template 525 | bool UEObject::IsA() const 526 | { 527 | auto cmp = T::StaticClass(); 528 | if (!cmp.IsValid()) 529 | { 530 | return false; 531 | } 532 | 533 | for (auto super = GetClass(); super.IsValid(); super = super.GetSuper().Cast()) 534 | { 535 | if (super.object == cmp.object) 536 | { 537 | return true; 538 | } 539 | } 540 | 541 | return false; 542 | } 543 | -------------------------------------------------------------------------------- /Source/jni/src/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 | } -------------------------------------------------------------------------------- /Source/jni/src/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); -------------------------------------------------------------------------------- /Source/libs/arm64-v8a/libnative-lib.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s4m33r89/UE4SDKGenerator/6f8125f03f9a7fe9ce07b19003e459ba266c7555/Source/libs/arm64-v8a/libnative-lib.so -------------------------------------------------------------------------------- /Source/ndk.cmd: -------------------------------------------------------------------------------- 1 | rmdir /libs 2 | ndk-build -------------------------------------------------------------------------------- /Source/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "build.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-3 12 | -------------------------------------------------------------------------------- /Source/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | UE4_SDK_GENERATOR 4 | 5 | -------------------------------------------------------------------------------- /Source/src/com/ue4/sdkgen/HelloJni.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.ue4.sdkgen; 17 | 18 | import android.app.Activity; 19 | import android.widget.TextView; 20 | import android.os.Bundle; 21 | 22 | 23 | public class HelloJni extends Activity 24 | { 25 | /** Called when the activity is first created. */ 26 | @Override 27 | public void onCreate(Bundle savedInstanceState) 28 | { 29 | super.onCreate(savedInstanceState); 30 | 31 | /* Create a TextView and set its content. 32 | * the text is retrieved by calling a native 33 | * function. 34 | */ 35 | TextView tv = new TextView(this); 36 | tv.setText( stringFromJNI() ); 37 | setContentView(tv); 38 | } 39 | 40 | /* A native method that is implemented by the 41 | * 'hello-jni' native library, which is packaged 42 | * with this application. 43 | */ 44 | public native String stringFromJNI(); 45 | 46 | /* This is another native method declaration that is *not* 47 | * implemented by 'hello-jni'. This is simply to show that 48 | * you can declare as many native methods in your Java code 49 | * as you want, their implementation is searched in the 50 | * currently loaded native libraries only the first time 51 | * you call them. 52 | * 53 | * Trying to call this function will result in a 54 | * java.lang.UnsatisfiedLinkError exception ! 55 | */ 56 | public native String unimplementedStringFromJNI(); 57 | 58 | /* this is used to load the 'hello-jni' library on application 59 | * startup. The library has already been unpacked into 60 | * /data/data/com.example.hellojni/lib/libhello-jni.so at 61 | * installation time by the package manager. 62 | */ 63 | static { 64 | System.loadLibrary("hello-jni"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Target/BGMI/EngineClasses.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef unsigned char uint8; 8 | typedef unsigned short int uint16; 9 | typedef unsigned int uint32; 10 | typedef unsigned long long uint64; 11 | 12 | // Signed base types. 13 | typedef signed char __int8; 14 | typedef signed short int __int16; 15 | typedef signed int __int32; 16 | typedef signed long long __int64; 17 | 18 | struct FPointer 19 | { 20 | uintptr_t Dummy; 21 | }; 22 | 23 | struct FQWord 24 | { 25 | int A; 26 | int B; 27 | }; 28 | 29 | struct FName 30 | { 31 | int32_t ComparisonIndex; 32 | int32_t Number; 33 | }; 34 | 35 | template 36 | struct TArray 37 | { 38 | friend struct FString; 39 | 40 | public: 41 | TArray() 42 | { 43 | Data = nullptr; 44 | Count = Max = 0; 45 | }; 46 | 47 | size_t Num() const 48 | { 49 | return Count; 50 | }; 51 | 52 | T& operator[](size_t i) 53 | { 54 | return Data[i]; 55 | }; 56 | 57 | const T& operator[](size_t i) const 58 | { 59 | return Data[i]; 60 | }; 61 | 62 | bool IsValidIndex(size_t i) const 63 | { 64 | return i < Num(); 65 | } 66 | 67 | private: 68 | T* Data; 69 | int32_t Count; 70 | int32_t Max; 71 | }; 72 | 73 | template 74 | class TPair 75 | { 76 | public: 77 | KeyType Key; 78 | ValueType Value; 79 | }; 80 | 81 | struct FString : public TArray 82 | { 83 | std::string ToString() const 84 | { 85 | //Add Later 86 | std::string str; 87 | return str; 88 | } 89 | }; 90 | 91 | class FScriptInterface 92 | { 93 | private: 94 | UObject* ObjectPointer; 95 | void* InterfacePointer; 96 | 97 | public: 98 | UObject* GetObject() const 99 | { 100 | return ObjectPointer; 101 | } 102 | 103 | UObject*& GetObjectRef() 104 | { 105 | return ObjectPointer; 106 | } 107 | 108 | void* GetInterface() const 109 | { 110 | return ObjectPointer != nullptr ? InterfacePointer : nullptr; 111 | } 112 | }; 113 | 114 | template 115 | class TScriptInterface : public FScriptInterface 116 | { 117 | public: 118 | InterfaceType* operator->() const 119 | { 120 | return (InterfaceType*)GetInterface(); 121 | } 122 | 123 | InterfaceType& operator*() const 124 | { 125 | return *((InterfaceType*)GetInterface()); 126 | } 127 | 128 | operator bool() const 129 | { 130 | return GetInterface() != nullptr; 131 | } 132 | }; 133 | 134 | struct FText 135 | { 136 | char UnknownData[0x18]; 137 | }; 138 | 139 | struct FWeakObjectPtr 140 | { 141 | int32_t ObjectIndex; 142 | int32_t ObjectSerialNumber; 143 | }; 144 | 145 | struct FStringAssetReference 146 | { 147 | FString AssetLongPathname; 148 | }; 149 | 150 | template 151 | class TPersistentObjectPtr 152 | { 153 | public: 154 | FWeakObjectPtr WeakPtr; 155 | int32_t TagAtLastTest; 156 | TObjectID ObjectID; 157 | }; 158 | 159 | class FAssetPtr : public TPersistentObjectPtr 160 | { 161 | 162 | }; 163 | 164 | struct FGuid 165 | { 166 | uint32_t A; 167 | uint32_t B; 168 | uint32_t C; 169 | uint32_t D; 170 | }; 171 | 172 | struct FUniqueObjectGuid 173 | { 174 | FGuid Guid; 175 | }; 176 | 177 | class FLazyObjectPtr : public TPersistentObjectPtr 178 | { 179 | 180 | }; 181 | 182 | struct FScriptDelegate 183 | { 184 | unsigned char UnknownData[16]; 185 | }; 186 | 187 | struct FScriptMulticastDelegate 188 | { 189 | unsigned char UnknownData[16]; 190 | }; 191 | 192 | class UClass; 193 | 194 | class UObject 195 | { 196 | public: 197 | FPointer VTableObject; //0 198 | int32_t ObjectFlags; //8 199 | int32_t InternalIndex; //c 200 | UClass* Class; //10 201 | FName Name; //18 202 | UObject* Outer; // 203 | }; 204 | 205 | class UField : public UObject 206 | { 207 | public: 208 | UField* Next; 209 | }; 210 | 211 | class UEnum : public UField 212 | { 213 | public: 214 | FString CppType; //0x0030 215 | TArray> Names; //0x0040 216 | __int64 CppForm; //0x0050 217 | }; 218 | 219 | class UStruct : public UField 220 | { 221 | public: 222 | UStruct* SuperField; 223 | UField* Children; 224 | int32_t PropertySize; 225 | int32_t MinAlignment; 226 | char pad_0x0048[0x28]; 227 | }; 228 | 229 | class UScriptStruct : public UStruct 230 | { 231 | public: 232 | char pad_0x0088[0x10]; //0x0088 233 | }; 234 | 235 | class UFunction : public UStruct 236 | { 237 | public: 238 | /*__int32 FunctionFlags; //0x0088 239 | __int16 RepOffset; //0x008C 240 | __int8 NumParms; //0x008E 241 | char pad_0x008F[0x1]; //0x008F 242 | __int16 ParmsSize; //0x0090 243 | __int16 ReturnValueOffset; //0x0092 244 | __int16 RPCId; //0x0094 245 | __int16 RPCResponseId; //0x0096 246 | class UProperty* FirstPropertyToInit; //0x0098 247 | UFunction* EventGraphFunction; //0x00A0 248 | __int32 EventGraphCallOffset; //0x00A8 249 | char pad_0x00AC[0x4]; //0x00AC 250 | void* Func; //0x00B0 251 | */ 252 | int32_t FunctionFlags; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 253 | int8_t NumParms; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 254 | int16_t ParmsSize; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 255 | int16_t ReturnValueOffset; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 256 | int16_t RPCId; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 257 | int16_t RPCResponseId; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 258 | char pad[0xC]; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 259 | void* Func; // 0x0000(0x0000) NOT AUTO-GENERATED PROPERTY 260 | 261 | }; 262 | 263 | class UClass : public UStruct 264 | { 265 | public: 266 | char pad_0x0088[0x170]; //0x0088 267 | }; 268 | 269 | class UProperty : public UField 270 | { 271 | public: 272 | __int32 ArrayDim; //0x0030 273 | __int32 ElementSize; //0x0034 274 | FQWord PropertyFlags; //0x0038 275 | __int32 PropertySize; //0x0040 276 | __int32 Offset; //0x0044 277 | char pad_0x0054[0x28]; //0x0048 278 | }; 279 | 280 | class UNumericProperty : public UProperty 281 | { 282 | public: 283 | 284 | }; 285 | 286 | class UByteProperty : public UNumericProperty 287 | { 288 | public: 289 | UEnum* Enum; // 0x0088 (0x04) 290 | }; 291 | 292 | class UUInt16Property : public UNumericProperty 293 | { 294 | public: 295 | 296 | }; 297 | 298 | class UUInt32Property : public UNumericProperty 299 | { 300 | public: 301 | 302 | }; 303 | 304 | class UUInt64Property : public UNumericProperty 305 | { 306 | public: 307 | 308 | }; 309 | 310 | class UInt8Property : public UNumericProperty 311 | { 312 | public: 313 | 314 | }; 315 | 316 | class UInt16Property : public UNumericProperty 317 | { 318 | public: 319 | 320 | }; 321 | 322 | class UIntProperty : public UNumericProperty 323 | { 324 | public: 325 | 326 | }; 327 | 328 | class UInt64Property : public UNumericProperty 329 | { 330 | public: 331 | 332 | }; 333 | 334 | class UFloatProperty : public UNumericProperty 335 | { 336 | public: 337 | 338 | }; 339 | 340 | class UDoubleProperty : public UNumericProperty 341 | { 342 | public: 343 | 344 | }; 345 | 346 | class UBoolProperty : public UProperty 347 | { 348 | public: 349 | uint8_t FieldSize; 350 | uint8_t ByteOffset; 351 | uint8_t ByteMask; 352 | uint8_t FieldMask; 353 | }; 354 | 355 | class UObjectPropertyBase : public UProperty 356 | { 357 | public: 358 | UClass* PropertyClass; 359 | }; 360 | 361 | class UObjectProperty : public UObjectPropertyBase 362 | { 363 | public: 364 | 365 | }; 366 | 367 | class UClassProperty : public UObjectProperty 368 | { 369 | public: 370 | UClass* MetaClass; 371 | }; 372 | 373 | class UInterfaceProperty : public UProperty 374 | { 375 | public: 376 | UClass* InterfaceClass; 377 | }; 378 | 379 | class UWeakObjectProperty : public UObjectPropertyBase 380 | { 381 | public: 382 | 383 | }; 384 | 385 | class ULazyObjectProperty : public UObjectPropertyBase 386 | { 387 | public: 388 | 389 | }; 390 | 391 | class UAssetObjectProperty : public UObjectPropertyBase 392 | { 393 | public: 394 | 395 | }; 396 | 397 | class UAssetClassProperty : public UAssetObjectProperty 398 | { 399 | public: 400 | UClass* MetaClass; 401 | }; 402 | 403 | class UNameProperty : public UProperty 404 | { 405 | public: 406 | 407 | }; 408 | 409 | class UStructProperty : public UProperty 410 | { 411 | public: 412 | UScriptStruct* Struct; 413 | }; 414 | 415 | class UStrProperty : public UProperty 416 | { 417 | public: 418 | 419 | }; 420 | 421 | class UTextProperty : public UProperty 422 | { 423 | public: 424 | 425 | }; 426 | 427 | class UArrayProperty : public UProperty 428 | { 429 | public: 430 | UProperty* Inner; 431 | }; 432 | 433 | class UMapProperty : public UProperty 434 | { 435 | public: 436 | UProperty* KeyProp; 437 | UProperty* ValueProp; 438 | }; 439 | 440 | class UDelegateProperty : public UProperty 441 | { 442 | public: 443 | UFunction* SignatureFunction; 444 | }; 445 | 446 | class UMulticastDelegateProperty : public UProperty 447 | { 448 | public: 449 | UFunction* SignatureFunction; 450 | }; 451 | 452 | class UEnumProperty : public UProperty 453 | { 454 | public: 455 | class UNumericProperty* UnderlyingProp; //0x0070 456 | class UEnum* Enum; //0x0078 457 | }; //Size: 0x0080 458 | -------------------------------------------------------------------------------- /Target/BGMI/Generator.cpp: -------------------------------------------------------------------------------- 1 | #include "IGenerator.hpp" 2 | #include "ObjectsStore.hpp" 3 | #include "NamesStore.hpp" 4 | #include "Dyno.h" 5 | 6 | class Generator : public IGenerator 7 | { 8 | public: 9 | bool Initialize(void* module) override 10 | { 11 | alignasClasses = { 12 | { "ScriptStruct CoreUObject.Plane", 16 }, 13 | { "ScriptStruct CoreUObject.Quat", 16 }, 14 | { "ScriptStruct CoreUObject.Transform", 16 }, 15 | { "ScriptStruct CoreUObject.Vector4", 16 }, 16 | 17 | { "ScriptStruct Engine.RootMotionSourceGroup", 8 } 18 | }; 19 | 20 | virtualFunctionPattern["Class CoreUObject.Object"] = { 21 | { "\x45\x33\xF6\x4D\x8B\xE0", "xxxxxx", 71, R"( inline void ProcessEvent(class UFunction* function, void* parms) 22 | { 23 | return GetVFunction(this, %d)(this, function, parms); 24 | })" 25 | ,71 } 26 | }; 27 | virtualFunctionPattern["Class CoreUObject.Class"] = { 28 | { "\x4C\x8B\xDC\x57\x48\x81\xEC", "xxxxxxx", 107, R"( inline UObject* CreateDefaultObject() 29 | { 30 | return GetVFunction(this, %d)(this); 31 | })" 32 | ,107 } 33 | }; 34 | 35 | predefinedMembers["Class CoreUObject.Object"] = { 36 | { "void*", "Vtable" }, 37 | { "int32_t", "ObjectFlags" }, 38 | { "int32_t", "InternalIndex" }, 39 | { "class UClass*", "Class" }, 40 | { "FName", "Name" }, 41 | { "class UObject*", "Outer" } 42 | }; 43 | predefinedStaticMembers["Class CoreUObject.Object"] = { 44 | { "FUObjectArray*", "GObjects" } 45 | }; 46 | predefinedMembers["Class CoreUObject.Field"] = { 47 | { "class UField*", "Next" } 48 | }; 49 | predefinedMembers["Class CoreUObject.Struct"] = { 50 | { "class UStruct*", "SuperField" }, 51 | { "class UField*", "Children" }, 52 | { "int32_t", "PropertySize" }, 53 | { "int32_t", "MinAlignment" }, 54 | { "unsigned char", "UnknownData0x0048[0x28]" } 55 | }; 56 | predefinedMembers["Class CoreUObject.Function"] = { 57 | { "int32_t", "FunctionFlags" }, 58 | //{ "int16_t", "RepOffset" }, 59 | { "int8_t", "NumParms" }, 60 | { "int16_t", "ParmsSize" }, 61 | { "int16_t", "ReturnValueOffset" }, 62 | { "int16_t", "RPCId" }, 63 | { "int16_t", "RPCResponseId" }, 64 | //{ "class UProperty*", "FirstPropertyToInit" }, 65 | //{ "class UFunction*", "EventGraphFunction" }, 66 | //{ "int32_t", "EventGraphCallOffset" }, 67 | { "unsigned char", "UnknownData0x00c[0xC]" }, 68 | { "void*", "Func" } 69 | }; 70 | 71 | predefinedMethods["ScriptStruct CoreUObject.Vector2D"] = { 72 | PredefinedMethod::Inline(R"( inline FVector2D() 73 | : X(0), Y(0) 74 | { })"), 75 | PredefinedMethod::Inline(R"( inline FVector2D(float x, float y) 76 | : X(x), 77 | Y(y) 78 | { })") 79 | }; 80 | predefinedMethods["ScriptStruct CoreUObject.LinearColor"] = { 81 | PredefinedMethod::Inline(R"( inline FLinearColor() 82 | : R(0), G(0), B(0), A(0) 83 | { })"), 84 | PredefinedMethod::Inline(R"( inline FLinearColor(float r, float g, float b, float a) 85 | : R(r), 86 | G(g), 87 | B(b), 88 | A(a) 89 | { })") 90 | }; 91 | 92 | predefinedMethods["Class CoreUObject.Object"] = { 93 | PredefinedMethod::Inline(R"( static inline TUObjectArray& GetGlobalObjects() 94 | { 95 | return GObjects->ObjObjects; 96 | })"), 97 | PredefinedMethod::Default("std::string GetName() const", R"(std::string UObject::GetName() const 98 | { 99 | std::string name(Name.GetName()); 100 | if (Name.Number > 0) 101 | { 102 | name += '_' + std::to_string(Name.Number); 103 | } 104 | 105 | auto pos = name.rfind('/'); 106 | if (pos == std::string::npos) 107 | { 108 | return name; 109 | } 110 | 111 | return name.substr(pos + 1); 112 | })"), 113 | PredefinedMethod::Default("std::string GetFullName() const", R"(std::string UObject::GetFullName() const 114 | { 115 | std::string name; 116 | 117 | if (Class != nullptr) 118 | { 119 | std::string temp; 120 | for (auto p = Outer; p; p = p->Outer) 121 | { 122 | temp = p->GetName() + "." + temp; 123 | } 124 | 125 | name = Class->GetName(); 126 | name += " "; 127 | name += temp; 128 | name += GetName(); 129 | } 130 | 131 | return name; 132 | })"), 133 | PredefinedMethod::Inline(R"( template 134 | static T* FindObject(const std::string& name) 135 | { 136 | for (int i = 0; i < GetGlobalObjects().Num(); ++i) 137 | { 138 | auto object = GetGlobalObjects().GetByIndex(i); 139 | 140 | if (object == nullptr) 141 | { 142 | continue; 143 | } 144 | 145 | if (object->GetFullName() == name) 146 | { 147 | return static_cast(object); 148 | } 149 | } 150 | return nullptr; 151 | })"), 152 | PredefinedMethod::Inline(R"( static UClass* FindClass(const std::string& name) 153 | { 154 | return FindObject(name); 155 | })"), 156 | PredefinedMethod::Inline(R"( template 157 | static T* GetObjectCasted(std::size_t index) 158 | { 159 | return static_cast(GetGlobalObjects().GetByIndex(index)); 160 | })"), 161 | PredefinedMethod::Default("bool IsA(UClass* cmp) const", R"(bool UObject::IsA(UClass* cmp) const 162 | { 163 | for (auto super = Class; super; super = static_cast(super->SuperField)) 164 | { 165 | if (super == cmp) 166 | { 167 | return true; 168 | } 169 | } 170 | 171 | return false; 172 | })") 173 | }; 174 | predefinedMethods["Class CoreUObject.Class"] = { 175 | PredefinedMethod::Inline(R"( template 176 | inline T* CreateDefaultObject() 177 | { 178 | return static_cast(CreateDefaultObject()); 179 | })") 180 | }; 181 | 182 | return true; 183 | } 184 | 185 | std::string GetGameName() const override 186 | { 187 | return gameFullName; 188 | } 189 | 190 | std::string GetGameNameShort() const override 191 | { 192 | return gameShortName; 193 | } 194 | 195 | std::string GetGameVersion() const override 196 | { 197 | return gameVersion; 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 GetBasicDeclarations() const override 211 | { 212 | return R"(template 213 | inline Fn GetVFunction(void *thiz, int idx) 214 | { 215 | auto VTable = *reinterpret_cast(const_cast(thiz)); 216 | return (Fn)(VTable[idx]); 217 | } 218 | 219 | class UObject; 220 | 221 | class FUObjectItem 222 | { 223 | public: 224 | UObject* Object; 225 | int32_t Flags; 226 | int32_t ClusterIndex; 227 | int32_t SerialNumber; 228 | 229 | enum class ObjectFlags : int32_t 230 | { 231 | None = 0, 232 | Native = 1 << 25, 233 | Async = 1 << 26, 234 | AsyncLoading = 1 << 27, 235 | Unreachable = 1 << 28, 236 | PendingKill = 1 << 29, 237 | RootSet = 1 << 30, 238 | NoStrongReference = 1 << 31 239 | }; 240 | 241 | inline bool IsUnreachable() const 242 | { 243 | return !!(Flags & static_cast>(ObjectFlags::Unreachable)); 244 | } 245 | inline bool IsPendingKill() const 246 | { 247 | return !!(Flags & static_cast>(ObjectFlags::PendingKill)); 248 | } 249 | }; 250 | 251 | class TUObjectArray 252 | { 253 | public: 254 | inline int32_t Num() const 255 | { 256 | return NumElements; 257 | } 258 | 259 | inline UObject* GetByIndex(int32_t index) const 260 | { 261 | return Objects[index].Object; 262 | } 263 | 264 | inline FUObjectItem* GetItemByIndex(int32_t index) const 265 | { 266 | if (index < NumElements) 267 | { 268 | return &Objects[index]; 269 | } 270 | return nullptr; 271 | } 272 | 273 | private: 274 | FUObjectItem* Objects; 275 | int32_t MaxElements; 276 | int32_t NumElements; 277 | }; 278 | 279 | class FUObjectArray 280 | { 281 | public: 282 | int32_t ObjFirstGCIndex; 283 | int32_t ObjLastNonGCIndex; 284 | int32_t MaxObjectsNotConsideredByGC; 285 | int32_t OpenForDisregardForGC; 286 | TUObjectArray ObjObjects; 287 | }; 288 | 289 | template 290 | struct TArray 291 | { 292 | friend struct FString; 293 | 294 | public: 295 | inline TArray() 296 | { 297 | Data = nullptr; 298 | Count = Max = 0; 299 | }; 300 | 301 | inline int Num() const 302 | { 303 | return Count; 304 | }; 305 | 306 | inline T& operator[](int i) 307 | { 308 | return Data[i]; 309 | }; 310 | 311 | inline const T& operator[](int i) const 312 | { 313 | return Data[i]; 314 | }; 315 | 316 | inline bool IsValidIndex(int i) const 317 | { 318 | return i < Num(); 319 | } 320 | 321 | private: 322 | T* Data; 323 | int32_t Count; 324 | int32_t Max; 325 | }; 326 | 327 | class FNameEntry 328 | { 329 | public: 330 | static const auto NAME_WIDE_MASK = 0x1; 331 | static const auto NAME_INDEX_SHIFT = 1; 332 | 333 | int32_t Index; 334 | #if defined(__LP64__) 335 | char pad[0x8]; 336 | #else 337 | char pad[0x4]; 338 | #endif 339 | 340 | union 341 | { 342 | char AnsiName[1024]; 343 | wchar_t WideName[1024]; 344 | }; 345 | 346 | inline const int32_t GetIndex() const 347 | { 348 | return Index >> NAME_INDEX_SHIFT; 349 | } 350 | 351 | inline bool IsWide() const 352 | { 353 | return Index & NAME_WIDE_MASK; 354 | } 355 | 356 | inline const char* GetAnsiName() const 357 | { 358 | return AnsiName; 359 | } 360 | 361 | inline const wchar_t* GetWideName() const 362 | { 363 | return WideName; 364 | } 365 | }; 366 | 367 | template 368 | class TStaticIndirectArrayThreadSafeRead 369 | { 370 | public: 371 | inline size_t Num() const 372 | { 373 | return NumElements; 374 | } 375 | 376 | inline bool IsValidIndex(int32_t index) const 377 | { 378 | return index < Num() && index > 0; 379 | } 380 | 381 | inline ElementType const* const& operator[](int32_t index) const 382 | { 383 | return *GetItemPtr(index); 384 | } 385 | 386 | private: 387 | inline ElementType const* const* GetItemPtr(int32_t Index) const 388 | { 389 | int32_t ChunkIndex = Index / ElementsPerChunk; 390 | int32_t WithinChunkIndex = Index % ElementsPerChunk; 391 | ElementType** Chunk = Chunks[ChunkIndex]; 392 | return Chunk + WithinChunkIndex; 393 | } 394 | 395 | enum 396 | { 397 | ChunkTableSize = (MaxTotalElements + ElementsPerChunk - 1) / ElementsPerChunk 398 | }; 399 | 400 | ElementType** Chunks[ChunkTableSize]; 401 | int32_t NumElements; 402 | int32_t NumChunks; 403 | }; 404 | 405 | using TNameEntryArray = TStaticIndirectArrayThreadSafeRead; 406 | 407 | struct FName 408 | { 409 | union 410 | { 411 | struct 412 | { 413 | int32_t ComparisonIndex; 414 | int32_t Number; 415 | }; 416 | }; 417 | 418 | inline FName() 419 | : ComparisonIndex(0), 420 | Number(0) 421 | { 422 | }; 423 | 424 | inline FName(int32_t i) 425 | : ComparisonIndex(i), 426 | Number(0) 427 | { 428 | }; 429 | 430 | FName(const char* nameToFind) 431 | : ComparisonIndex(0), 432 | Number(0) 433 | { 434 | static std::unordered_set cache; 435 | 436 | for (auto i : cache) 437 | { 438 | if (!std::strcmp(GetNames()[i]->GetAnsiName(), nameToFind)) 439 | { 440 | ComparisonIndex = i; 441 | 442 | return; 443 | } 444 | } 445 | 446 | for (auto i = 0; i < GetNames().Num(); ++i) 447 | { 448 | if (GetNames()[i] != nullptr) 449 | { 450 | if (!std::strcmp(GetNames()[i]->GetAnsiName(), nameToFind)) 451 | { 452 | cache.insert(i); 453 | 454 | ComparisonIndex = i; 455 | 456 | return; 457 | } 458 | } 459 | } 460 | }; 461 | 462 | static TNameEntryArray *GNames; 463 | static inline TNameEntryArray& GetNames() 464 | { 465 | return *GNames; 466 | }; 467 | 468 | inline const char* GetName() const 469 | { 470 | return GetNames()[ComparisonIndex]->GetAnsiName(); 471 | }; 472 | 473 | inline bool operator==(const FName &other) const 474 | { 475 | return ComparisonIndex == other.ComparisonIndex; 476 | }; 477 | }; 478 | 479 | struct FString : private TArray 480 | { 481 | inline FString() 482 | { 483 | } 484 | 485 | FString(const std::wstring s) 486 | { 487 | Max = Count = !s.empty() ? (s.length() * 2) + 1 : 0; 488 | if (Count) 489 | { 490 | Data = (unsigned short *)(s.data()); 491 | } 492 | } 493 | 494 | FString(const wchar_t *s) : FString(std::wstring(s)) { 495 | } 496 | 497 | FString(const wchar_t *s, int len) : FString(std::wstring(s, s + len)) { 498 | } 499 | 500 | FString(const std::string s) { 501 | std::wstring_convert> converter; 502 | std::wstring ws = converter.from_bytes(s); 503 | 504 | Max = Count = !ws.empty() ? (ws.length() * 2) + 1 : 0; 505 | if (Count) 506 | { 507 | Data = (unsigned short *)(ws.data()); 508 | } 509 | } 510 | 511 | FString(const char *s) : FString(std::string(s)) { 512 | } 513 | 514 | FString(const char *s, int len) : FString(std::string(s, s + len)) { 515 | } 516 | 517 | inline bool IsValid() const 518 | { 519 | return Data != nullptr; 520 | } 521 | 522 | inline const wchar_t* ToWString() const 523 | { 524 | wchar_t *output = new wchar_t[Count + 1]; 525 | 526 | for (int i = 0; i < Count; i++) { 527 | const char16_t uc = Data[i]; 528 | if (uc - 0xd800u >= 2048u) { 529 | output[i] = uc; 530 | } else { 531 | if ((uc & 0xfffffc00) == 0xd800 && (uc & 0xfffffc00) == 0xdc00) 532 | output[i] = (uc << 10) + Data[i] - 0x35fdc00; 533 | else 534 | output[i] = L'?'; 535 | } 536 | } 537 | 538 | output[Count] = 0; 539 | return output; 540 | } 541 | 542 | inline const char* ToString() const 543 | { 544 | std::wstring_convert,char16_t> convert; 545 | return convert.to_bytes(std::u16string(Data, Data + Count)).c_str(); 546 | } 547 | }; 548 | 549 | template 550 | class TEnumAsByte 551 | { 552 | public: 553 | inline TEnumAsByte() 554 | { 555 | } 556 | 557 | inline TEnumAsByte(TEnum _value) 558 | : value(static_cast(_value)) 559 | { 560 | } 561 | 562 | explicit inline TEnumAsByte(int32_t _value) 563 | : value(static_cast(_value)) 564 | { 565 | } 566 | 567 | explicit inline TEnumAsByte(uint8_t _value) 568 | : value(_value) 569 | { 570 | } 571 | 572 | inline operator TEnum() const 573 | { 574 | return (TEnum)value; 575 | } 576 | 577 | inline TEnum GetValue() const 578 | { 579 | return (TEnum)value; 580 | } 581 | 582 | private: 583 | uint8_t value; 584 | }; 585 | 586 | class FScriptInterface 587 | { 588 | private: 589 | UObject* ObjectPointer; 590 | void* InterfacePointer; 591 | 592 | public: 593 | inline UObject* GetObject() const 594 | { 595 | return ObjectPointer; 596 | } 597 | 598 | inline UObject*& GetObjectRef() 599 | { 600 | return ObjectPointer; 601 | } 602 | 603 | inline void* GetInterface() const 604 | { 605 | return ObjectPointer != nullptr ? InterfacePointer : nullptr; 606 | } 607 | }; 608 | 609 | template 610 | class TScriptInterface : public FScriptInterface 611 | { 612 | public: 613 | inline InterfaceType* operator->() const 614 | { 615 | return (InterfaceType*)GetInterface(); 616 | } 617 | 618 | inline InterfaceType& operator*() const 619 | { 620 | return *((InterfaceType*)GetInterface()); 621 | } 622 | 623 | inline operator bool() const 624 | { 625 | return GetInterface() != nullptr; 626 | } 627 | }; 628 | 629 | struct FText 630 | { 631 | #if defined(__LP64__) 632 | char pad[24]; 633 | #else 634 | char pad[12]; 635 | #endif 636 | }; 637 | 638 | struct FScriptDelegate 639 | { 640 | char pad[16]; 641 | }; 642 | 643 | struct FScriptMulticastDelegate 644 | { 645 | #if defined(__LP64__) 646 | char pad[16]; 647 | #else 648 | char pad[12]; 649 | #endif 650 | }; 651 | 652 | template 653 | class TMap 654 | { 655 | #if defined(__LP64__) 656 | char pad[80]; 657 | #else 658 | char pad[60]; 659 | #endif 660 | }; 661 | 662 | struct FWeakObjectPtr 663 | { 664 | public: 665 | inline bool SerialNumbersMatch(FUObjectItem* ObjectItem) const 666 | { 667 | return ObjectItem->SerialNumber == ObjectSerialNumber; 668 | } 669 | 670 | bool IsValid() const; 671 | 672 | UObject* Get() const; 673 | 674 | int32_t ObjectIndex; 675 | int32_t ObjectSerialNumber; 676 | }; 677 | 678 | template 679 | struct TWeakObjectPtr : private TWeakObjectPtrBase 680 | { 681 | public: 682 | inline T* Get() const 683 | { 684 | return (T*)TWeakObjectPtrBase::Get(); 685 | } 686 | 687 | inline T& operator*() const 688 | { 689 | return *Get(); 690 | } 691 | 692 | inline T* operator->() const 693 | { 694 | return Get(); 695 | } 696 | 697 | inline bool IsValid() const 698 | { 699 | return TWeakObjectPtrBase::IsValid(); 700 | } 701 | }; 702 | 703 | template 704 | class TAutoPointer : public TBASE 705 | { 706 | public: 707 | inline operator T*() const 708 | { 709 | return TBASE::Get(); 710 | } 711 | 712 | inline operator const T*() const 713 | { 714 | return (const T*)TBASE::Get(); 715 | } 716 | 717 | explicit inline operator bool() const 718 | { 719 | return TBASE::Get() != nullptr; 720 | } 721 | }; 722 | 723 | template 724 | class TAutoWeakObjectPtr : public TAutoPointer> 725 | { 726 | public: 727 | }; 728 | 729 | template 730 | class TPersistentObjectPtr 731 | { 732 | public: 733 | FWeakObjectPtr WeakPtr; 734 | int32_t TagAtLastTest; 735 | TObjectID ObjectID; 736 | }; 737 | 738 | struct FStringAssetReference_ 739 | { 740 | 741 | }; 742 | 743 | class FAssetPtr : public TPersistentObjectPtr 744 | { 745 | 746 | }; 747 | 748 | template 749 | class TAssetPtr : FAssetPtr 750 | { 751 | 752 | }; 753 | 754 | struct FUniqueObjectGuid_ 755 | { 756 | 757 | }; 758 | 759 | class FLazyObjectPtr : public TPersistentObjectPtr 760 | { 761 | 762 | }; 763 | 764 | template 765 | class TLazyObjectPtr : FLazyObjectPtr 766 | { 767 | 768 | };)"; 769 | } 770 | 771 | std::string GetBasicDefinitions() const override 772 | { 773 | return R"(TNameEntryArray* FName::GNames = nullptr; 774 | FUObjectArray* UObject::GUObjectArray = nullptr; 775 | //--------------------------------------------------------------------------- 776 | bool FWeakObjectPtr::IsValid() const 777 | { 778 | if (ObjectSerialNumber == 0) 779 | { 780 | return false; 781 | } 782 | if (ObjectIndex < 0) 783 | { 784 | return false; 785 | } 786 | auto ObjectItem = UObject::GetGlobalObjects().GetItemByIndex(ObjectIndex); 787 | if (!ObjectItem) 788 | { 789 | return false; 790 | } 791 | if (!SerialNumbersMatch(ObjectItem)) 792 | { 793 | return false; 794 | } 795 | return !(ObjectItem->IsUnreachable() || ObjectItem->IsPendingKill()); 796 | } 797 | //--------------------------------------------------------------------------- 798 | UObject* FWeakObjectPtr::Get() const 799 | { 800 | if (IsValid()) 801 | { 802 | auto ObjectItem = UObject::GetGlobalObjects().GetItemByIndex(ObjectIndex); 803 | if (ObjectItem) 804 | { 805 | return ObjectItem->Object; 806 | } 807 | } 808 | return nullptr; 809 | } 810 | //---------------------------------------------------------------------------)"; 811 | } 812 | }; 813 | 814 | Generator _generator; 815 | IGenerator* generator = &_generator; 816 | -------------------------------------------------------------------------------- /Target/BGMI/GenericTypes.cpp: -------------------------------------------------------------------------------- 1 | #include "../IGenerator.hpp" 2 | #include "GenericTypes.hpp" 3 | #include "../ObjectsStore.hpp" 4 | #include "../NamesStore.hpp" 5 | #include "../NameValidator.hpp" 6 | 7 | #include "../EngineClasses.hpp" 8 | 9 | void* UEObject::GetAddress() const 10 | { 11 | return object; 12 | } 13 | 14 | UEObject UEObject::GetPackageObject() const 15 | { 16 | UEObject package(nullptr); 17 | 18 | for (auto outer = GetOuter(); outer.IsValid(); outer = outer.GetOuter()) 19 | { 20 | package = outer; 21 | } 22 | 23 | return package; 24 | } 25 | 26 | std::string UEObject::GetFullName() const 27 | { 28 | if (GetClass().IsValid()) 29 | { 30 | std::string temp; 31 | 32 | for (auto outer = GetOuter(); outer.IsValid(); outer = outer.GetOuter()) 33 | { 34 | temp = outer.GetName() + "." + temp; 35 | } 36 | 37 | std::string name = GetClass().GetName(); 38 | name += " "; 39 | name += temp; 40 | name += GetName(); 41 | 42 | return name; 43 | } 44 | 45 | return std::string("(null)"); 46 | } 47 | 48 | std::string UEObject::GetNameCPP() const 49 | { 50 | std::string name; 51 | 52 | if (IsA()) 53 | { 54 | auto c = Cast(); 55 | while (c.IsValid()) 56 | { 57 | const auto className = c.GetName(); 58 | if (className == "Actor") 59 | { 60 | name += "A"; 61 | break; 62 | } 63 | if (className == "Object") 64 | { 65 | name += "U"; 66 | break; 67 | } 68 | 69 | c = c.GetSuper().Cast(); 70 | } 71 | } 72 | else 73 | { 74 | name += "F"; 75 | } 76 | 77 | name += GetName(); 78 | 79 | return name; 80 | } 81 | 82 | UEProperty::Info UEProperty::GetInfo() const 83 | { 84 | if (IsValid()) 85 | { 86 | if (IsA()) 87 | { 88 | return Cast().GetInfo(); 89 | } 90 | if (IsA()) 91 | { 92 | return Cast().GetInfo(); 93 | } 94 | if (IsA()) 95 | { 96 | return Cast().GetInfo(); 97 | } 98 | if (IsA()) 99 | { 100 | return Cast().GetInfo(); 101 | } 102 | if (IsA()) 103 | { 104 | return Cast().GetInfo(); 105 | } 106 | if (IsA()) 107 | { 108 | return Cast().GetInfo(); 109 | } 110 | if (IsA()) 111 | { 112 | return Cast().GetInfo(); 113 | } 114 | if (IsA()) 115 | { 116 | return Cast().GetInfo(); 117 | } 118 | if (IsA()) 119 | { 120 | return Cast().GetInfo(); 121 | } 122 | if (IsA()) 123 | { 124 | return Cast().GetInfo(); 125 | } 126 | if (IsA()) 127 | { 128 | return Cast().GetInfo(); 129 | } 130 | if (IsA()) 131 | { 132 | return Cast().GetInfo(); 133 | } 134 | if (IsA()) 135 | { 136 | return Cast().GetInfo(); 137 | } 138 | if (IsA()) 139 | { 140 | return Cast().GetInfo(); 141 | } 142 | if (IsA()) 143 | { 144 | return Cast().GetInfo(); 145 | } 146 | if (IsA()) 147 | { 148 | return Cast().GetInfo(); 149 | } 150 | if (IsA()) 151 | { 152 | return Cast().GetInfo(); 153 | } 154 | if (IsA()) 155 | { 156 | return Cast().GetInfo(); 157 | } 158 | if (IsA()) 159 | { 160 | return Cast().GetInfo(); 161 | } 162 | if (IsA()) 163 | { 164 | return Cast().GetInfo(); 165 | } 166 | if (IsA()) 167 | { 168 | return Cast().GetInfo(); 169 | } 170 | if (IsA()) 171 | { 172 | return Cast().GetInfo(); 173 | } 174 | if (IsA()) 175 | { 176 | return Cast().GetInfo(); 177 | } 178 | if (IsA()) 179 | { 180 | return Cast().GetInfo(); 181 | } 182 | if (IsA()) 183 | { 184 | return Cast().GetInfo(); 185 | } 186 | if (IsA()) 187 | { 188 | return Cast().GetInfo(); 189 | } 190 | if (IsA()) 191 | { 192 | return Cast().GetInfo(); 193 | } 194 | } 195 | return { PropertyType::Unknown }; 196 | } 197 | 198 | //--------------------------------------------------------------------------- 199 | //UEByteProperty 200 | //--------------------------------------------------------------------------- 201 | bool UEByteProperty::IsEnum() const 202 | { 203 | return GetEnum().IsValid(); 204 | } 205 | //--------------------------------------------------------------------------- 206 | //UEBoolProperty 207 | //--------------------------------------------------------------------------- 208 | 209 | int GetBitPosition(uint8_t value) 210 | { 211 | int i4 = !(value & 0xf) << 2; 212 | value >>= i4; 213 | 214 | int i2 = !(value & 0x3) << 1; 215 | value >>= i2; 216 | 217 | int i1 = !(value & 0x1); 218 | 219 | int i0 = (value >> i1) & 1 ? 0 : -8; 220 | 221 | return i4 + i2 + i1 + i0; 222 | } 223 | 224 | std::array UEBoolProperty::GetMissingBitsCount(const UEBoolProperty& other) const 225 | { 226 | // If there is no previous bitfield member, just calculate the missing bits. 227 | if (!other.IsValid()) 228 | { 229 | return { GetBitPosition(GetByteMask()), -1 }; 230 | } 231 | 232 | // If both bitfield member belong to the same byte, calculate the bit position difference. 233 | if (GetOffset() == other.GetOffset()) 234 | { 235 | return { GetBitPosition(GetByteMask()) - GetBitPosition(other.GetByteMask()) - 1, -1 }; 236 | } 237 | 238 | // If they have different offsets, we need two distances 239 | // |00001000|00100000| 240 | // 1. ^---^ 241 | // 2. ^--^ 242 | 243 | return { std::numeric_limits::digits - GetBitPosition(other.GetByteMask()) - 1, GetBitPosition(GetByteMask()) }; 244 | } 245 | 246 | 247 | 248 | 249 | //--------------------------------------------------------------------------- 250 | //UEObject 251 | //--------------------------------------------------------------------------- 252 | size_t UEObject::GetIndex() const 253 | { 254 | return object->InternalIndex; 255 | } 256 | //--------------------------------------------------------------------------- 257 | UEClass UEObject::GetClass() const 258 | { 259 | return UEClass(object->Class); 260 | } 261 | //--------------------------------------------------------------------------- 262 | UEObject UEObject::GetOuter() const 263 | { 264 | return UEObject(object->Outer); 265 | } 266 | //--------------------------------------------------------------------------- 267 | std::string UEObject::GetName() const 268 | { 269 | auto name = NamesStore().GetById(object->Name.ComparisonIndex); 270 | if (object->Name.Number > 0) 271 | { 272 | name += '_' + std::to_string(object->Name.Number); 273 | } 274 | 275 | auto pos = name.rfind('/'); 276 | if (pos == std::string::npos) 277 | { 278 | return name; 279 | } 280 | 281 | return name.substr(pos + 1); 282 | } 283 | //--------------------------------------------------------------------------- 284 | UEClass UEObject::StaticClass() 285 | { 286 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Object"); 287 | return c; 288 | } 289 | //--------------------------------------------------------------------------- 290 | //UEField 291 | //--------------------------------------------------------------------------- 292 | UEField UEField::GetNext() const 293 | { 294 | return UEField(static_cast(object)->Next); 295 | } 296 | //--------------------------------------------------------------------------- 297 | UEClass UEField::StaticClass() 298 | { 299 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Field"); 300 | return c; 301 | } 302 | //--------------------------------------------------------------------------- 303 | //UEEnum 304 | //--------------------------------------------------------------------------- 305 | std::vector UEEnum::GetNames() const 306 | { 307 | std::vector buffer; 308 | auto& names = static_cast(object)->Names; 309 | 310 | for (auto i = 0; i < names.Num(); ++i) 311 | { 312 | buffer.push_back(NamesStore().GetById(names[i].Key.ComparisonIndex)); 313 | } 314 | 315 | return buffer; 316 | } 317 | //--------------------------------------------------------------------------- 318 | UEClass UEEnum::StaticClass() 319 | { 320 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Enum"); 321 | return c; 322 | } 323 | //--------------------------------------------------------------------------- 324 | //UEConst 325 | //--------------------------------------------------------------------------- 326 | std::string UEConst::GetValue() const 327 | { 328 | //throw; 329 | } 330 | //--------------------------------------------------------------------------- 331 | UEClass UEConst::StaticClass() 332 | { 333 | //not supported by UE4 334 | return nullptr; 335 | } 336 | //--------------------------------------------------------------------------- 337 | //UEStruct 338 | //--------------------------------------------------------------------------- 339 | UEStruct UEStruct::GetSuper() const 340 | { 341 | return UEStruct(static_cast(object)->SuperField); 342 | } 343 | //--------------------------------------------------------------------------- 344 | UEField UEStruct::GetChildren() const 345 | { 346 | return UEField(static_cast(object)->Children); 347 | } 348 | //--------------------------------------------------------------------------- 349 | size_t UEStruct::GetPropertySize() const 350 | { 351 | return static_cast(object)->PropertySize; 352 | } 353 | //--------------------------------------------------------------------------- 354 | UEClass UEStruct::StaticClass() 355 | { 356 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Struct"); 357 | return c; 358 | } 359 | //--------------------------------------------------------------------------- 360 | //UEScriptStruct 361 | //--------------------------------------------------------------------------- 362 | UEClass UEScriptStruct::StaticClass() 363 | { 364 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ScriptStruct"); 365 | return c; 366 | } 367 | //--------------------------------------------------------------------------- 368 | //UEFunction 369 | //--------------------------------------------------------------------------- 370 | UEFunctionFlags UEFunction::GetFunctionFlags() const 371 | { 372 | return static_cast(static_cast(object)->FunctionFlags); 373 | } 374 | //--------------------------------------------------------------------------- 375 | UEClass UEFunction::StaticClass() 376 | { 377 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Function"); 378 | return c; 379 | } 380 | //--------------------------------------------------------------------------- 381 | //UEClass 382 | //--------------------------------------------------------------------------- 383 | UEClass UEClass::StaticClass() 384 | { 385 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Class"); 386 | return c; 387 | } 388 | //--------------------------------------------------------------------------- 389 | //UEProperty 390 | //--------------------------------------------------------------------------- 391 | size_t UEProperty::GetArrayDim() const 392 | { 393 | return static_cast(object)->ArrayDim; 394 | } 395 | //--------------------------------------------------------------------------- 396 | size_t UEProperty::GetElementSize() const 397 | { 398 | return static_cast(object)->ElementSize; 399 | } 400 | //--------------------------------------------------------------------------- 401 | UEPropertyFlags UEProperty::GetPropertyFlags() const 402 | { 403 | return static_cast(static_cast(object)->PropertyFlags.A); 404 | } 405 | //--------------------------------------------------------------------------- 406 | size_t UEProperty::GetOffset() const 407 | { 408 | return static_cast(object)->Offset; 409 | } 410 | //--------------------------------------------------------------------------- 411 | UEClass UEProperty::StaticClass() 412 | { 413 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Property"); 414 | return c; 415 | } 416 | //--------------------------------------------------------------------------- 417 | //UENumericProperty 418 | //--------------------------------------------------------------------------- 419 | UEClass UENumericProperty::StaticClass() 420 | { 421 | static auto c = ObjectsStore().FindClass("Class CoreUObject.NumericProperty"); 422 | return c; 423 | } 424 | //--------------------------------------------------------------------------- 425 | //UEByteProperty 426 | //--------------------------------------------------------------------------- 427 | UEEnum UEByteProperty::GetEnum() const 428 | { 429 | return UEEnum(static_cast(object)->Enum); 430 | } 431 | //--------------------------------------------------------------------------- 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | UEProperty::Info UEByteProperty::GetInfo() const 440 | { 441 | if (IsEnum()) 442 | { 443 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, "TEnumAsByte<" + MakeUniqueCppName(GetEnum()) + ">"); 444 | } 445 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, "unsigned char"); 446 | } 447 | //--------------------------------------------------------------------------- 448 | UEClass UEByteProperty::StaticClass() 449 | { 450 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ByteProperty"); 451 | return c; 452 | } 453 | //--------------------------------------------------------------------------- 454 | //UEUInt16Property 455 | //--------------------------------------------------------------------------- 456 | UEProperty::Info UEUInt16Property::GetInfo() const 457 | { 458 | return Info::Create(PropertyType::Primitive, sizeof(uint16_t), false, "uint16_t"); 459 | } 460 | //--------------------------------------------------------------------------- 461 | UEClass UEUInt16Property::StaticClass() 462 | { 463 | static auto c = ObjectsStore().FindClass("Class CoreUObject.UInt16Property"); 464 | return c; 465 | } 466 | //--------------------------------------------------------------------------- 467 | //UEUInt32Property 468 | //--------------------------------------------------------------------------- 469 | UEProperty::Info UEUInt32Property::GetInfo() const 470 | { 471 | return Info::Create(PropertyType::Primitive, sizeof(uint32_t), false, "uint32_t"); 472 | } 473 | //--------------------------------------------------------------------------- 474 | UEClass UEUInt32Property::StaticClass() 475 | { 476 | static auto c = ObjectsStore().FindClass("Class CoreUObject.UInt32Property"); 477 | return c; 478 | } 479 | //--------------------------------------------------------------------------- 480 | //UEUInt64Property 481 | //--------------------------------------------------------------------------- 482 | UEProperty::Info UEUInt64Property::GetInfo() const 483 | { 484 | return Info::Create(PropertyType::Primitive, sizeof(uint64_t), false, "uint64_t"); 485 | } 486 | //--------------------------------------------------------------------------- 487 | UEClass UEUInt64Property::StaticClass() 488 | { 489 | static auto c = ObjectsStore().FindClass("Class CoreUObject.UInt64Property"); 490 | return c; 491 | } 492 | //--------------------------------------------------------------------------- 493 | //UEInt8Property 494 | //--------------------------------------------------------------------------- 495 | UEProperty::Info UEInt8Property::GetInfo() const 496 | { 497 | return Info::Create(PropertyType::Primitive, sizeof(int8_t), false, "int8_t"); 498 | } 499 | //--------------------------------------------------------------------------- 500 | UEClass UEInt8Property::StaticClass() 501 | { 502 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Int8Property"); 503 | return c; 504 | } 505 | //--------------------------------------------------------------------------- 506 | //UEInt16Property 507 | //--------------------------------------------------------------------------- 508 | UEProperty::Info UEInt16Property::GetInfo() const 509 | { 510 | return Info::Create(PropertyType::Primitive, sizeof(int16_t), false, "int16_t"); 511 | } 512 | //--------------------------------------------------------------------------- 513 | UEClass UEInt16Property::StaticClass() 514 | { 515 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Int16Property"); 516 | return c; 517 | } 518 | //--------------------------------------------------------------------------- 519 | //UEIntProperty 520 | //--------------------------------------------------------------------------- 521 | UEProperty::Info UEIntProperty::GetInfo() const 522 | { 523 | return Info::Create(PropertyType::Primitive, sizeof(int), false, "int"); 524 | } 525 | //--------------------------------------------------------------------------- 526 | UEClass UEIntProperty::StaticClass() 527 | { 528 | static auto c = ObjectsStore().FindClass("Class CoreUObject.IntProperty"); 529 | return c; 530 | } 531 | //--------------------------------------------------------------------------- 532 | //UEInt64Property 533 | //--------------------------------------------------------------------------- 534 | UEProperty::Info UEInt64Property::GetInfo() const 535 | { 536 | return Info::Create(PropertyType::Primitive, sizeof(int64_t), false, "int64_t"); 537 | } 538 | //--------------------------------------------------------------------------- 539 | UEClass UEInt64Property::StaticClass() 540 | { 541 | static auto c = ObjectsStore().FindClass("Class CoreUObject.Int64Property"); 542 | return c; 543 | } 544 | //--------------------------------------------------------------------------- 545 | //UEFloatProperty 546 | //--------------------------------------------------------------------------- 547 | UEProperty::Info UEFloatProperty::GetInfo() const 548 | { 549 | return Info::Create(PropertyType::Primitive, sizeof(float), false, "float"); 550 | } 551 | //--------------------------------------------------------------------------- 552 | UEClass UEFloatProperty::StaticClass() 553 | { 554 | static auto c = ObjectsStore().FindClass("Class CoreUObject.FloatProperty"); 555 | return c; 556 | } 557 | //--------------------------------------------------------------------------- 558 | //UEDoubleProperty 559 | //--------------------------------------------------------------------------- 560 | UEProperty::Info UEDoubleProperty::GetInfo() const 561 | { 562 | return Info::Create(PropertyType::Primitive, sizeof(double), false, "double"); 563 | } 564 | //--------------------------------------------------------------------------- 565 | UEClass UEDoubleProperty::StaticClass() 566 | { 567 | static auto c = ObjectsStore().FindClass("Class CoreUObject.DoubleProperty"); 568 | return c; 569 | } 570 | //--------------------------------------------------------------------------- 571 | //UEBoolProperty 572 | //--------------------------------------------------------------------------- 573 | uint8_t UEBoolProperty::GetFieldSize() const 574 | { 575 | return static_cast(object)->FieldSize; 576 | } 577 | //--------------------------------------------------------------------------- 578 | uint8_t UEBoolProperty::GetByteOffset() const 579 | { 580 | return static_cast(object)->ByteOffset; 581 | } 582 | //--------------------------------------------------------------------------- 583 | uint8_t UEBoolProperty::GetByteMask() const 584 | { 585 | return static_cast(object)->ByteMask; 586 | } 587 | //--------------------------------------------------------------------------- 588 | uint8_t UEBoolProperty::GetFieldMask() const 589 | { 590 | return static_cast(object)->FieldMask; 591 | } 592 | //--------------------------------------------------------------------------- 593 | UEProperty::Info UEBoolProperty::GetInfo() const 594 | { 595 | if (IsNativeBool()) 596 | { 597 | return Info::Create(PropertyType::Primitive, sizeof(bool), false, "bool"); 598 | } 599 | return Info::Create(PropertyType::Primitive, sizeof(unsigned char), false, "unsigned char"); 600 | } 601 | //--------------------------------------------------------------------------- 602 | UEClass UEBoolProperty::StaticClass() 603 | { 604 | static auto c = ObjectsStore().FindClass("Class CoreUObject.BoolProperty"); 605 | return c; 606 | } 607 | //--------------------------------------------------------------------------- 608 | //UEObjectPropertyBase 609 | //--------------------------------------------------------------------------- 610 | UEClass UEObjectPropertyBase::GetPropertyClass() const 611 | { 612 | return UEClass(static_cast(object)->PropertyClass); 613 | } 614 | //--------------------------------------------------------------------------- 615 | UEClass UEObjectPropertyBase::StaticClass() 616 | { 617 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ObjectPropertyBase"); 618 | return c; 619 | } 620 | //--------------------------------------------------------------------------- 621 | //UEObjectProperty 622 | //--------------------------------------------------------------------------- 623 | UEProperty::Info UEObjectProperty::GetInfo() const 624 | { 625 | return Info::Create(PropertyType::Primitive, sizeof(void*), false, "class " + MakeValidName(GetPropertyClass().GetNameCPP()) + "*"); 626 | } 627 | //--------------------------------------------------------------------------- 628 | UEClass UEObjectProperty::StaticClass() 629 | { 630 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ObjectProperty"); 631 | return c; 632 | } 633 | //--------------------------------------------------------------------------- 634 | //UEClassProperty 635 | //--------------------------------------------------------------------------- 636 | UEClass UEClassProperty::GetMetaClass() const 637 | { 638 | return UEClass(static_cast(object)->MetaClass); 639 | } 640 | //--------------------------------------------------------------------------- 641 | UEProperty::Info UEClassProperty::GetInfo() const 642 | { 643 | return Info::Create(PropertyType::Primitive, sizeof(void*), false, "class " + MakeValidName(GetMetaClass().GetNameCPP()) + "*"); 644 | } 645 | //--------------------------------------------------------------------------- 646 | UEClass UEClassProperty::StaticClass() 647 | { 648 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ClassProperty"); 649 | return c; 650 | } 651 | //--------------------------------------------------------------------------- 652 | //UEInterfaceProperty 653 | //--------------------------------------------------------------------------- 654 | UEClass UEInterfaceProperty::GetInterfaceClass() const 655 | { 656 | return UEClass(static_cast(object)->InterfaceClass); 657 | } 658 | //--------------------------------------------------------------------------- 659 | UEProperty::Info UEInterfaceProperty::GetInfo() const 660 | { 661 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FScriptInterface), true, "TScriptInterface"); 662 | } 663 | //--------------------------------------------------------------------------- 664 | UEClass UEInterfaceProperty::StaticClass() 665 | { 666 | static auto c = ObjectsStore().FindClass("Class CoreUObject.InterfaceProperty"); 667 | return c; 668 | } 669 | //--------------------------------------------------------------------------- 670 | //UEWeakObjectProperty 671 | //--------------------------------------------------------------------------- 672 | UEProperty::Info UEWeakObjectProperty::GetInfo() const 673 | { 674 | return Info::Create(PropertyType::Container, sizeof(FWeakObjectPtr), false, "TWeakObjectPtr"); 675 | } 676 | //--------------------------------------------------------------------------- 677 | UEClass UEWeakObjectProperty::StaticClass() 678 | { 679 | static auto c = ObjectsStore().FindClass("Class CoreUObject.WeakObjectProperty"); 680 | return c; 681 | } 682 | //--------------------------------------------------------------------------- 683 | //UELazyObjectProperty 684 | //--------------------------------------------------------------------------- 685 | UEProperty::Info UELazyObjectProperty::GetInfo() const 686 | { 687 | return Info::Create(PropertyType::Container, sizeof(FLazyObjectPtr), false, "TLazyObjectPtr"); 688 | } 689 | //--------------------------------------------------------------------------- 690 | UEClass UELazyObjectProperty::StaticClass() 691 | { 692 | static auto c = ObjectsStore().FindClass("Class CoreUObject.LazyObjectProperty"); 693 | return c; 694 | } 695 | //--------------------------------------------------------------------------- 696 | //UEAssetObjectProperty 697 | //--------------------------------------------------------------------------- 698 | UEProperty::Info UEAssetObjectProperty::GetInfo() const 699 | { 700 | return Info::Create(PropertyType::Container, sizeof(FAssetPtr), false, "TAssetPtr"); 701 | } 702 | //--------------------------------------------------------------------------- 703 | UEClass UEAssetObjectProperty::StaticClass() 704 | { 705 | static auto c = ObjectsStore().FindClass("Class CoreUObject.AssetObjectProperty"); 706 | return c; 707 | } 708 | //--------------------------------------------------------------------------- 709 | //UEAssetClassProperty 710 | //--------------------------------------------------------------------------- 711 | UEClass UEAssetClassProperty::GetMetaClass() const 712 | { 713 | return UEClass(static_cast(object)->MetaClass); 714 | } 715 | //--------------------------------------------------------------------------- 716 | UEProperty::Info UEAssetClassProperty::GetInfo() const 717 | { 718 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, ""); 719 | } 720 | //--------------------------------------------------------------------------- 721 | UEClass UEAssetClassProperty::StaticClass() 722 | { 723 | static auto c = ObjectsStore().FindClass("Class CoreUObject.AssetClassProperty"); 724 | return c; 725 | } 726 | //--------------------------------------------------------------------------- 727 | //UENameProperty 728 | //--------------------------------------------------------------------------- 729 | UEProperty::Info UENameProperty::GetInfo() const 730 | { 731 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FName), true, "struct FName"); 732 | } 733 | //--------------------------------------------------------------------------- 734 | UEClass UENameProperty::StaticClass() 735 | { 736 | static auto c = ObjectsStore().FindClass("Class CoreUObject.NameProperty"); 737 | return c; 738 | } 739 | //--------------------------------------------------------------------------- 740 | //UEStructProperty 741 | //--------------------------------------------------------------------------- 742 | UEScriptStruct UEStructProperty::GetStruct() const 743 | { 744 | return UEScriptStruct(static_cast(object)->Struct); 745 | } 746 | //--------------------------------------------------------------------------- 747 | UEProperty::Info UEStructProperty::GetInfo() const 748 | { 749 | return Info::Create(PropertyType::CustomStruct, GetElementSize(), true, "struct " + MakeUniqueCppName(GetStruct())); 750 | } 751 | //--------------------------------------------------------------------------- 752 | UEClass UEStructProperty::StaticClass() 753 | { 754 | static auto c = ObjectsStore().FindClass("Class CoreUObject.StructProperty"); 755 | return c; 756 | } 757 | //--------------------------------------------------------------------------- 758 | //UEStrProperty 759 | //--------------------------------------------------------------------------- 760 | UEProperty::Info UEStrProperty::GetInfo() const 761 | { 762 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FString), true, "struct FString"); 763 | } 764 | //--------------------------------------------------------------------------- 765 | UEClass UEStrProperty::StaticClass() 766 | { 767 | static auto c = ObjectsStore().FindClass("Class CoreUObject.StrProperty"); 768 | return c; 769 | } 770 | //--------------------------------------------------------------------------- 771 | //UETextProperty 772 | //--------------------------------------------------------------------------- 773 | UEProperty::Info UETextProperty::GetInfo() const 774 | { 775 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FText), true, "struct FText"); 776 | } 777 | //--------------------------------------------------------------------------- 778 | UEClass UETextProperty::StaticClass() 779 | { 780 | static auto c = ObjectsStore().FindClass("Class CoreUObject.TextProperty"); 781 | return c; 782 | } 783 | //--------------------------------------------------------------------------- 784 | //UEArrayProperty 785 | //--------------------------------------------------------------------------- 786 | UEProperty UEArrayProperty::GetInner() const 787 | { 788 | return UEProperty(static_cast(object)->Inner); 789 | } 790 | //--------------------------------------------------------------------------- 791 | UEProperty::Info UEArrayProperty::GetInfo() const 792 | { 793 | auto inner = GetInner().GetInfo(); 794 | if (inner.Type != PropertyType::Unknown) 795 | { 796 | extern IGenerator* generator; 797 | 798 | return Info::Create(PropertyType::Container, sizeof(TArray), false, "TArray<" + generator->GetOverrideType(inner.CppType) + ">"); 799 | } 800 | 801 | return { PropertyType::Unknown }; 802 | } 803 | //--------------------------------------------------------------------------- 804 | UEClass UEArrayProperty::StaticClass() 805 | { 806 | static auto c = ObjectsStore().FindClass("Class CoreUObject.ArrayProperty"); 807 | return c; 808 | } 809 | //--------------------------------------------------------------------------- 810 | //UEMapProperty 811 | //--------------------------------------------------------------------------- 812 | UEProperty UEMapProperty::GetKeyProperty() const 813 | { 814 | return UEProperty(static_cast(object)->KeyProp); 815 | } 816 | //--------------------------------------------------------------------------- 817 | UEProperty UEMapProperty::GetValueProperty() const 818 | { 819 | return UEProperty(static_cast(object)->ValueProp); 820 | } 821 | //--------------------------------------------------------------------------- 822 | UEProperty::Info UEMapProperty::GetInfo() const 823 | { 824 | auto key = GetKeyProperty().GetInfo(); 825 | auto value = GetValueProperty().GetInfo(); 826 | if (key.Type != PropertyType::Unknown && value.Type != PropertyType::Unknown) 827 | { 828 | extern IGenerator* generator; 829 | 830 | return Info::Create(PropertyType::Container, 0x50, false, "TMap<" + generator->GetOverrideType(key.CppType) + ", " + generator->GetOverrideType(value.CppType) + ">"); 831 | } 832 | 833 | return { PropertyType::Unknown }; 834 | } 835 | //--------------------------------------------------------------------------- 836 | UEClass UEMapProperty::StaticClass() 837 | { 838 | static auto c = ObjectsStore().FindClass("Class CoreUObject.MapProperty"); 839 | return c; 840 | } 841 | //--------------------------------------------------------------------------- 842 | //UEDelegateProperty 843 | //--------------------------------------------------------------------------- 844 | UEFunction UEDelegateProperty::GetSignatureFunction() const 845 | { 846 | return UEFunction(static_cast(object)->SignatureFunction); 847 | } 848 | //--------------------------------------------------------------------------- 849 | UEProperty::Info UEDelegateProperty::GetInfo() const 850 | { 851 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FScriptDelegate), true, "struct FScriptDelegate"); 852 | } 853 | //--------------------------------------------------------------------------- 854 | UEClass UEDelegateProperty::StaticClass() 855 | { 856 | static auto c = ObjectsStore().FindClass("Class CoreUObject.DelegateProperty"); 857 | return c; 858 | } 859 | //--------------------------------------------------------------------------- 860 | //UEMulticastDelegateProperty 861 | //--------------------------------------------------------------------------- 862 | UEFunction UEMulticastDelegateProperty::GetSignatureFunction() const 863 | { 864 | return UEFunction(static_cast(object)->SignatureFunction); 865 | } 866 | //--------------------------------------------------------------------------- 867 | UEProperty::Info UEMulticastDelegateProperty::GetInfo() const 868 | { 869 | return Info::Create(PropertyType::PredefinedStruct, sizeof(FScriptMulticastDelegate), true, "struct FScriptMulticastDelegate"); 870 | } 871 | //--------------------------------------------------------------------------- 872 | UEClass UEMulticastDelegateProperty::StaticClass() 873 | { 874 | static auto c = ObjectsStore().FindClass("Class CoreUObject.MulticastDelegateProperty"); 875 | return c; 876 | } 877 | //--------------------------------------------------------------------------- 878 | //UEEnumProperty 879 | //--------------------------------------------------------------------------- 880 | UENumericProperty UEEnumProperty::GetUnderlyingProperty() const 881 | { 882 | return UENumericProperty(static_cast(object)->UnderlyingProp); 883 | } 884 | //--------------------------------------------------------------------------- 885 | UEEnum UEEnumProperty::GetEnum() const 886 | { 887 | return UEEnum(static_cast(object)->Enum); 888 | } 889 | //--------------------------------------------------------------------------- 890 | UEProperty::Info UEEnumProperty::GetInfo() const 891 | { 892 | return Info::Create(PropertyType::Primitive, sizeof(uint8_t), false, MakeUniqueCppName(GetEnum())); 893 | } 894 | //--------------------------------------------------------------------------- 895 | UEClass UEEnumProperty::StaticClass() 896 | { 897 | static auto c = ObjectsStore().FindClass("Class CoreUObject.EnumProperty"); 898 | return c; 899 | } 900 | //--------------------------------------------------------------------------- 901 | -------------------------------------------------------------------------------- /Target/BGMI/NamesStore.cpp: -------------------------------------------------------------------------------- 1 | #include "NamesStore.hpp" 2 | 3 | #include "EngineClasses.hpp" 4 | 5 | NamesIterator NamesStore::begin() 6 | { 7 | return NamesIterator(*this, 0); 8 | } 9 | 10 | NamesIterator NamesStore::begin() const 11 | { 12 | return NamesIterator(*this, 0); 13 | } 14 | 15 | NamesIterator NamesStore::end() 16 | { 17 | return NamesIterator(*this); 18 | } 19 | 20 | NamesIterator NamesStore::end() const 21 | { 22 | return NamesIterator(*this); 23 | } 24 | 25 | NamesIterator::NamesIterator(const NamesStore& _store) 26 | : store(_store), 27 | index(_store.GetNamesNum()) 28 | { 29 | } 30 | 31 | NamesIterator::NamesIterator(const NamesStore& _store, size_t _index) 32 | : store(_store), 33 | index(_index) 34 | { 35 | } 36 | 37 | void NamesIterator::swap(NamesIterator& other) noexcept 38 | { 39 | std::swap(index, other.index); 40 | } 41 | 42 | NamesIterator& NamesIterator::operator++() 43 | { 44 | for (++index; index < store.GetNamesNum(); ++index) 45 | { 46 | if (store.IsValid(index)) 47 | { 48 | break; 49 | } 50 | } 51 | return *this; 52 | } 53 | 54 | NamesIterator NamesIterator::operator++ (int) 55 | { 56 | auto tmp(*this); 57 | ++(*this); 58 | return tmp; 59 | } 60 | 61 | bool NamesIterator::operator==(const NamesIterator& rhs) const 62 | { 63 | return index == rhs.index; 64 | } 65 | 66 | bool NamesIterator::operator!=(const NamesIterator& rhs) const 67 | { 68 | return index != rhs.index; 69 | } 70 | 71 | UENameInfo NamesIterator::operator*() const 72 | { 73 | return { index, store.GetById(index) }; 74 | } 75 | 76 | UENameInfo NamesIterator::operator->() const 77 | { 78 | return { index, store.GetById(index) }; 79 | } 80 | 81 | class FNameEntry 82 | { 83 | public: 84 | 85 | FNameEntry* HashNext; 86 | __int32 Index; 87 | union 88 | { 89 | char AnsiName[1024]; 90 | wchar_t WideName[1024]; 91 | }; 92 | 93 | const char* GetName() const 94 | { 95 | return AnsiName; 96 | } 97 | }; 98 | 99 | template 100 | class TStaticIndirectArrayThreadSafeRead 101 | { 102 | public: 103 | int32_t Num() const 104 | { 105 | return NumElements; 106 | } 107 | 108 | bool IsValidIndex(int32_t index) const 109 | { 110 | return index >= 0 && index < Num() && GetById(index) != nullptr; 111 | } 112 | 113 | ElementType const* const& GetById(int32_t index) const 114 | { 115 | return *GetItemPtr(index); 116 | } 117 | 118 | private: 119 | ElementType const* const* GetItemPtr(int32_t Index) const 120 | { 121 | int32_t ChunkIndex = Index / ElementsPerChunk; 122 | int32_t WithinChunkIndex = Index % ElementsPerChunk; 123 | ElementType** Chunk = Chunks[ChunkIndex]; 124 | return Chunk + WithinChunkIndex; 125 | } 126 | 127 | enum 128 | { 129 | ChunkTableSize = (MaxTotalElements + ElementsPerChunk - 1) / ElementsPerChunk 130 | }; 131 | 132 | ElementType** Chunks[ChunkTableSize]; 133 | __int32 NumElements; 134 | __int32 NumChunks; 135 | }; 136 | 137 | using TNameEntryArray = TStaticIndirectArrayThreadSafeRead; 138 | 139 | TNameEntryArray* GlobalNames = nullptr; 140 | 141 | bool NamesStore::Initialize(uintptr_t GNames_Addr) 142 | { 143 | if(GNames_Addr == 0) 144 | return false; 145 | 146 | GlobalNames = (TNameEntryArray*) (GNames_Addr); 147 | 148 | return true; 149 | } 150 | 151 | void* NamesStore::GetAddress() 152 | { 153 | return GlobalNames; 154 | } 155 | 156 | size_t NamesStore::GetNamesNum() const 157 | { 158 | return GlobalNames->Num(); 159 | } 160 | 161 | bool NamesStore::IsValid(size_t id) const 162 | { 163 | return GlobalNames->IsValidIndex(static_cast(id)); 164 | } 165 | 166 | std::string NamesStore::GetById(size_t id) const 167 | { 168 | return GlobalNames->GetById(static_cast(id))->GetName(); 169 | } 170 | -------------------------------------------------------------------------------- /Target/BGMI/ObjectsStore.cpp: -------------------------------------------------------------------------------- 1 | #include "ObjectsStore.hpp" 2 | 3 | #include "EngineClasses.hpp" 4 | 5 | 6 | ObjectsIterator ObjectsStore::begin() 7 | { 8 | return ObjectsIterator(*this, 0); 9 | } 10 | 11 | ObjectsIterator ObjectsStore::begin() const 12 | { 13 | return ObjectsIterator(*this, 0); 14 | } 15 | 16 | ObjectsIterator ObjectsStore::end() 17 | { 18 | return ObjectsIterator(*this); 19 | } 20 | 21 | ObjectsIterator ObjectsStore::end() const 22 | { 23 | return ObjectsIterator(*this); 24 | } 25 | 26 | UEClass ObjectsStore::FindClass(const std::string& name) const 27 | { 28 | for (auto obj : *this) 29 | { 30 | if (obj.GetFullName() == name) 31 | { 32 | return obj.Cast(); 33 | } 34 | } 35 | return UEClass(nullptr); 36 | } 37 | 38 | ObjectsIterator::ObjectsIterator(const ObjectsStore& _store) 39 | : store(_store), 40 | index(_store.GetObjectsNum()) 41 | { 42 | } 43 | 44 | ObjectsIterator::ObjectsIterator(const ObjectsStore& _store, size_t _index) 45 | : store(_store), 46 | index(_index), 47 | current(_store.GetById(_index)) 48 | { 49 | } 50 | 51 | ObjectsIterator::ObjectsIterator(const ObjectsIterator& other) 52 | : store(other.store), 53 | index(other.index), 54 | current(other.current) 55 | { 56 | } 57 | 58 | ObjectsIterator::ObjectsIterator(ObjectsIterator&& other) noexcept 59 | : store(other.store), 60 | index(other.index), 61 | current(other.current) 62 | { 63 | } 64 | 65 | ObjectsIterator& ObjectsIterator::operator=(const ObjectsIterator& rhs) 66 | { 67 | index = rhs.index; 68 | current = rhs.current; 69 | return *this; 70 | } 71 | 72 | void ObjectsIterator::swap(ObjectsIterator& other) noexcept 73 | { 74 | std::swap(index, other.index); 75 | std::swap(current, other.current); 76 | } 77 | 78 | ObjectsIterator& ObjectsIterator::operator++() 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 | } 119 | 120 | class FUObjectItem 121 | { 122 | public: 123 | UObject* Object; //0x0000 124 | __int32 Flags; //0x0008 125 | __int32 ClusterIndex; //0x000C 126 | __int32 SerialNumber; //0x0010 127 | char pad1[0x4]; 128 | }; 129 | 130 | class TUObjectArray 131 | { 132 | public: 133 | FUObjectItem* Objects; 134 | int32_t MaxElements; 135 | int32_t NumElements; 136 | }; 137 | 138 | class FUObjectArray 139 | { 140 | public: 141 | __int32 ObjFirstGCIndex; //0x0000 142 | __int32 ObjLastNonGCIndex; //0x0004 143 | __int32 MaxObjectsNotConsideredByGC; //0x0008 144 | __int32 OpenForDisregardForGC; //0x000C 145 | 146 | TUObjectArray ObjObjects; //0x0010 147 | }; 148 | 149 | FUObjectArray* GlobalObjects = nullptr; 150 | 151 | bool ObjectsStore::Initialize(uintptr_t GUObjectArray_Addr) 152 | { 153 | if(GUObjectArray_Addr == 0) 154 | return false; 155 | 156 | GlobalObjects = (FUObjectArray*) (GUObjectArray_Addr); 157 | 158 | return true; 159 | } 160 | 161 | void* ObjectsStore::GetAddress() 162 | { 163 | return GlobalObjects; 164 | } 165 | 166 | size_t ObjectsStore::GetObjectsNum() const 167 | { 168 | return GlobalObjects->ObjObjects.NumElements; 169 | } 170 | 171 | UEObject ObjectsStore::GetById(size_t id) const 172 | { 173 | return GlobalObjects->ObjObjects.Objects[id].Object; 174 | } 175 | --------------------------------------------------------------------------------