public static bool GetVirtualFunctionPatterns(string name, ref VirtualFunctionPatterns patterns) { if (!_virtualFunctionPattern.ContainsKey(name)) { return(false); } patterns = _virtualFunctionPattern[name]; return(true); }
/// <summary> /// Generates the class. /// </summary> /// <param name="classObj">The class object.</param> private async Task GenerateClass(GenericTypes.UEClass classObj) { var c = new Class { Name = await classObj.GetName(), FullName = await classObj.GetFullName() }; var logTask = Logger.Log($"Class: {await GetName() + "." + c.Name,-85} - instance: 0x{classObj.GetAddress().ToInt64():X8}"); c.NameCpp = NameValidator.MakeValidName(await classObj.GetNameCpp()); c.NameCppFull = $"class {c.NameCpp}"; c.Size = await classObj.GetPropertySize(); c.InheritedSize = 0; int offset = 0; var super = await classObj.GetSuper(); if (super.IsValid() && super != classObj) { c.InheritedSize = offset = await super.GetPropertySize(); c.NameCppFull += $" : public {NameValidator.MakeValidName(await super.GetNameCpp())}"; } var predefinedStaticMembers = new List <PredefinedMember>(); if (Generator.GetPredefinedClassStaticMembers(c.FullName, ref predefinedStaticMembers)) { foreach (var prop in predefinedStaticMembers) { var p = new Member { Offset = 0, Size = 0, Name = prop.Name, Type = prop.Type, IsStatic = true }; c.Members.Add(p); } } var predefinedMembers = new List <PredefinedMember>(); if (Generator.GetPredefinedClassMembers(c.FullName, ref predefinedMembers)) { foreach (var prop in predefinedMembers) { var p = new Member { Offset = 0, Size = 0, Name = prop.Name, Type = prop.Type, IsStatic = false, Comment = "NOT AUTO-GENERATED PROPERTY" }; c.Members.Add(p); } } else { var properties = new List <GenericTypes.UEProperty>(); for (var prop = (await classObj.GetChildren()).Cast <GenericTypes.UEProperty>(); prop.IsValid(); prop = (await prop.GetNext()).Cast <GenericTypes.UEProperty>()) { var elementSizeT = prop.GetElementSize(); var isScriptStruct = prop.IsA <GenericTypes.UEScriptStruct>(); var isFunction = prop.IsA <GenericTypes.UEFunction>(); var isEnum = prop.IsA <GenericTypes.UEEnum>(); var isConst = prop.IsA <GenericTypes.UEConst>(); if (await elementSizeT > 0 && !await isScriptStruct && !await isFunction && !await isEnum && !await isConst && (!super.IsValid() || (super != classObj && await prop.GetOffset() >= await super.GetPropertySize()))) { properties.Add(prop); } } // As C# sort not same as C++ version, that's not work // Anyway after some testes it's not needed !! // properties.Sort((x, y) => ComparePropertyLess(x, y).Result ? 0 : 1); c.Members = await GenerateMembers(classObj, offset, properties); } Generator.GetPredefinedClassMethods(c.FullName, ref c.PredefinedMethods); if (Generator.SdkType == SdkType.External) { // ToDO: Add external Read/Write here for external } else { if (Generator.ShouldUseStrings) { string classStr = Generator.ShouldXorStrings ? $"_xor_(\"{c.FullName}\")" : $"\"{c.FullName}\""; c.PredefinedMethods.Add(PredefinedMethod.Inline($@" static UClass* StaticClass() {{ static auto ptr = UObject::FindClass({classStr}); return ptr; }}" ) ); } else { c.PredefinedMethods.Add(PredefinedMethod.Inline($@" static UClass* StaticClass() {{ static auto ptr = UObject::GetObjectCasted<UClass>({classObj.GetIndex()}); return ptr; }}" ) ); } c.Methods = await GenerateMethods(classObj); //search virtual functions var patterns = new VirtualFunctionPatterns(); if (Generator.GetVirtualFunctionPatterns(c.FullName, ref patterns)) { int ptrSize = Utils.GamePointerSize(); IntPtr vTableAddress = classObj.Object.VfTable; var vTable = new List <IntPtr>(); int methodCount = 0; while (methodCount < 150) { // Dereference Pointer IntPtr vAddress = Utils.MemObj.ReadAddress(vTableAddress + (methodCount * ptrSize)); // Check valid address int res = Win32.VirtualQueryEx(Utils.MemObj.ProcessHandle, vAddress, out var info, (uint)Marshal.SizeOf <Win32.MemoryBasicInformation>()); if (res == 0 || info.Protect.HasFlag(Win32.MemoryProtection.PageNoAccess)) { break; } vTable.Add(vAddress); methodCount++; } foreach (var(pattern, funcStr) in patterns) { for (int i = 0; i < methodCount; i++) { if (vTable[i].IsNull()) { continue; } var scanResult = await PatternScanner.FindPattern(Utils.MemObj, vTable[i], vTable[i] + 0x300, new List <PatternScanner.Pattern> { pattern }, true); if (!scanResult.ContainsKey(pattern.Name) || scanResult[pattern.Name].Empty()) { continue; } c.PredefinedMethods.Add(PredefinedMethod.Inline($@"{funcStr.Replace("%d", i.ToString())}")); break; } } } } // Wait logger await logTask; Classes.Add(c); }