示例#1
0
        /// <summary>
        /// Generates the methods of a class.
        /// </summary>
        /// <param name="classObj">The class object.</param>
        /// <returns>Return The methods of the class.</returns>
        private async Task <List <Method> > GenerateMethods(GenericTypes.UEClass classObj)
        {
            var methods = new List <Method>();

            //some classes (AnimBlueprintGenerated...) have multiple members with the same name, so filter them out
            var uniqueMethods = new List <string>();

            // prop can be UEObject, UEField, UEProperty
            for (var prop = (await classObj.GetChildren()).Cast <GenericTypes.UEField>(); prop.IsValid(); prop = await prop.GetNext())
            {
                if (!await prop.IsA <GenericTypes.UEFunction>())
                {
                    continue;
                }

                var function = prop.Cast <GenericTypes.UEFunction>();

                var m = new Method
                {
                    Index    = function.GetIndex(),
                    FullName = await function.GetFullName(),
                    Name     = Generator.GetSafeKeywordsName(NameValidator.MakeValidName(await function.GetName()))
                };

                if (uniqueMethods.Contains(m.FullName))
                {
                    continue;
                }

                uniqueMethods.Add(m.FullName);

                m.IsNative    = (await function.GetFunctionFlags()).HasFlag(UEFunctionFlags.Native);
                m.IsStatic    = (await function.GetFunctionFlags()).HasFlag(UEFunctionFlags.Static);
                m.FlagsString = FunctionFlags.StringifyFlags(await function.GetFunctionFlags());

                var parameters = new List <KeyValuePair <GenericTypes.UEProperty, Method.Parameter> >();
                var unique     = new Dictionary <string, int>();
                for (var param = (await function.GetChildren()).Cast <GenericTypes.UEProperty>(); param.IsValid(); param = (await param.GetNext()).Cast <GenericTypes.UEProperty>())
                {
                    if (await param.GetElementSize() == 0)
                    {
                        continue;
                    }

                    var info = await param.GetInfo();

                    if (info.Type == GenericTypes.UEProperty.PropertyType.Unknown)
                    {
                        continue;
                    }

                    var p = new Method.Parameter(UnrealVersion.Unreal4);

                    if (!p.MakeType(await param.GetPropertyFlags(), out p.ParamType))
                    {
                        //child isn't a parameter
                        continue;
                    }

                    p.PassByReference = false;
                    p.Name            = NameValidator.MakeValidName(await param.GetName());

                    if (!unique.ContainsKey(p.Name))
                    {
                        unique[p.Name] = 1;
                    }
                    else
                    {
                        unique[p.Name]++;
                        p.Name += unique[p.Name];
                    }

                    p.FlagsString = PropertyFlags.StringifyFlags(await param.GetPropertyFlags());
                    p.CppType     = info.CppType;

                    if (await param.IsA <GenericTypes.UEBoolProperty>())
                    {
                        p.CppType = Generator.GetOverrideType("bool");
                    }

                    if (p.ParamType == Method.Parameter.Type.Default)
                    {
                        if (await param.GetArrayDim() > 1)
                        {
                            p.CppType += "*";
                        }
                        else if (info.CanBeReference)
                        {
                            p.PassByReference = true;
                        }
                    }

                    p.Name = Generator.GetSafeKeywordsName(p.Name);
                    parameters.Add(new KeyValuePair <GenericTypes.UEProperty, Method.Parameter>(param, p));
                }

                parameters.Sort((lhs, rhs) => ComparePropertyLess(lhs.Key, rhs.Key).Result ? 0 : 1);

                foreach (var param in parameters)
                {
                    m.Parameters.Add(param.Value);
                }

                methods.Add(m);
            }

            return(methods);
        }
示例#2
0
        /// <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);
        }