public static PropertyCollection getDefaultStructValue(string className, bool stripTransients)
 {
     if (Structs.ContainsKey(className))
     {
         bool      immutable = UnrealObjectInfo.isImmutable(className, MEGame.ME3);
         ClassInfo info      = Structs[className];
         try
         {
             string filepath = (Path.Combine(ME3Directory.gamePath, @"BIOGame\" + info.pccPath));
             if (File.Exists(info.pccPath))
             {
                 filepath = info.pccPath; //Used for dynamic lookup
             }
             using (ME3Package importPCC = MEPackageHandler.OpenME3Package(filepath))
             {
                 byte[] buff;
                 //Plane and CoverReference inherit from other structs, meaning they don't have default values (who knows why)
                 //thus, I have hardcoded what those default values should be
                 if (className == "Plane")
                 {
                     buff = PlaneDefault;
                 }
                 else if (className == "CoverReference")
                 {
                     buff = CoverReferenceDefault;
                 }
                 else
                 {
                     var exportToRead = importPCC.Exports[info.exportIndex];
                     buff = exportToRead.Data.Skip(0x24).ToArray();
                 }
                 PropertyCollection props = PropertyCollection.ReadProps(importPCC, new MemoryStream(buff), className);
                 if (stripTransients)
                 {
                     List <UProperty> toRemove = new List <UProperty>();
                     foreach (var prop in props)
                     {
                         //remove transient props
                         if (info.properties.TryGetValue(prop.Name, out PropertyInfo propInfo))
                         {
                             if (propInfo.transient)
                             {
                                 toRemove.Add(prop);
                             }
                         }
                         //if (!info.properties.ContainsKey(prop.Name) && info.baseClass == "Class")
                         //{
                         //    toRemove.Add(prop);
                         //}
                     }
                     foreach (var prop in toRemove)
                     {
                         Debug.WriteLine($"ME3: Get Default Struct value ({className}) - removing transient prop: {prop.Name}");
                         props.Remove(prop);
                     }
                 }
                 return(props);
             }
         }
         catch
         {
             return(null);
         }
     }
     return(null);
 }
Пример #2
0
        public static void ImportProperty(IMEPackage pcc, IMEPackage importpcc, Property p, string className, MemoryStream m, bool inStruct = false)
        {
            string name    = importpcc.getNameEntry(p.Name);
            int    idxname = pcc.FindNameOrAdd(name);

            m.Write(BitConverter.GetBytes(idxname), 0, 4);
            m.Write(new byte[4], 0, 4);
            if (name == "None")
            {
                return;
            }
            string type    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 8));
            int    idxtype = pcc.FindNameOrAdd(type);

            m.Write(BitConverter.GetBytes(idxtype), 0, 4);
            m.Write(new byte[4], 0, 4);
            string          name2;
            int             idxname2;
            int             size, count, pos;
            List <Property> Props;

            switch (type)
            {
            case "IntProperty":
            case "FloatProperty":
            case "ObjectProperty":
            case "StringRefProperty":
                m.Write(BitConverter.GetBytes(4), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(p.Value.IntValue), 0, 4);
                break;

            case "NameProperty":
                m.Write(BitConverter.GetBytes(8), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                //preserve index or whatever the second part of a namereference is
                m.Write(p.raw, 28, 4);
                break;

            case "BoolProperty":
                m.Write(new byte[8], 0, 8);
                m.WriteByte((byte)p.Value.IntValue);
                if (pcc.Game != MEGame.ME3)
                {
                    m.Write(new byte[3], 0, 3);
                }
                break;

            case "BioMask4Property":
                m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.WriteByte((byte)p.Value.IntValue);
                break;

            case "ByteProperty":
                m.Write(BitConverter.GetBytes(p.Size), 0, 4);
                m.Write(new byte[4], 0, 4);
                if (pcc.Game == MEGame.ME3)
                {
                    name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                    idxname2 = pcc.FindNameOrAdd(name2);
                    m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                if (p.Size != 1)
                {
                    m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(importpcc.getNameEntry(p.Value.IntValue))), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                else
                {
                    m.WriteByte(Convert.ToByte(p.Value.IntValue));
                }
                break;

            case "DelegateProperty":
                size = BitConverter.ToInt32(p.raw, 16);
                if (size == 0xC)
                {
                    name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28));
                    idxname2 = pcc.FindNameOrAdd(name2);
                    m.Write(BitConverter.GetBytes(0xC), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                }
                else
                {
                    m.Write(BitConverter.GetBytes(size), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    for (int i = 0; i < size; i++)
                    {
                        m.WriteByte(p.raw[24 + i]);
                    }
                }
                break;

            case "StrProperty":
                name2 = p.Value.StringValue;
                if (p.Value.StringValue.Length > 0)
                {
                    name2 += '\0';
                }
                if (p.Value.len < 0)
                {
                    //unicode
                    m.Write(BitConverter.GetBytes(4 + name2.Length * 2), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(-name2.Length), 0, 4);
                    foreach (char c in name2)
                    {
                        m.WriteByte((byte)c);
                        m.WriteByte(0);
                    }
                }
                else
                {
                    //ascii
                    m.Write(BitConverter.GetBytes(4 + name2.Length), 0, 4);
                    m.Write(new byte[4], 0, 4);
                    m.Write(BitConverter.GetBytes(name2.Length), 0, 4);
                    foreach (char c in name2)
                    {
                        m.WriteByte((byte)c);
                    }
                }
                break;

            case "StructProperty":
                size     = BitConverter.ToInt32(p.raw, 16);
                name2    = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 24));
                idxname2 = pcc.FindNameOrAdd(name2);
                pos      = 32;
                Props    = new List <Property>();
                try
                {
                    Props = ReadProp(importpcc, p.raw, pos);
                }
                catch (Exception)
                {
                }
                m.Write(BitConverter.GetBytes(size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(idxname2), 0, 4);
                m.Write(new byte[4], 0, 4);
                if (Props.Count == 0 || Props[0].TypeVal == PropertyType.Unknown)
                {
                    for (int i = 0; i < size; i++)
                    {
                        m.WriteByte(p.raw[32 + i]);
                    }
                }
                else
                {
                    foreach (Property pp in Props)
                    {
                        ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                }
                break;

            case "ArrayProperty":
                size  = BitConverter.ToInt32(p.raw, 16);
                count = BitConverter.ToInt32(p.raw, 24);
                PropertyInfo info      = ME3UnrealObjectInfo.getPropertyInfo(className, name, inStruct);
                ArrayType    arrayType = ME3UnrealObjectInfo.getArrayType(info);
                pos = 28;
                List <Property> AllProps = new List <Property>();

                if (arrayType == ArrayType.Struct)
                {
                    for (int i = 0; i < count; i++)
                    {
                        Props = new List <Property>();
                        try
                        {
                            Props = ReadProp(importpcc, p.raw, pos);
                        }
                        catch (Exception)
                        {
                        }
                        AllProps.AddRange(Props);
                        if (Props.Count != 0)
                        {
                            pos = Props[Props.Count - 1].offend;
                        }
                    }
                }
                m.Write(BitConverter.GetBytes(size), 0, 4);
                m.Write(new byte[4], 0, 4);
                m.Write(BitConverter.GetBytes(count), 0, 4);
                if (AllProps.Count != 0 && (info == null || !UnrealObjectInfo.isImmutable(info.reference, pcc.Game)))
                {
                    foreach (Property pp in AllProps)
                    {
                        ImportProperty(pcc, importpcc, pp, className, m, inStruct);
                    }
                }
                else if (arrayType == ArrayType.Name)
                {
                    for (int i = 0; i < count; i++)
                    {
                        string s = importpcc.getNameEntry(BitConverter.ToInt32(p.raw, 28 + i * 8));
                        m.Write(BitConverter.GetBytes(pcc.FindNameOrAdd(s)), 0, 4);
                        //preserve index or whatever the second part of a namereference is
                        m.Write(p.raw, 32 + i * 8, 4);
                    }
                }
                else
                {
                    m.Write(p.raw, 28, size - 4);
                }
                break;

            default:
                throw new Exception(type);
            }
        }
 public static byte[] getDefaultClassValue(ME3Package pcc, string className, bool fullProps = false)
 {
     if (Structs.ContainsKey(className))
     {
         bool      immutable = UnrealObjectInfo.isImmutable(className, MEGame.ME3);
         ClassInfo info      = Structs[className];
         try
         {
             string filepath = (Path.Combine(ME3Directory.gamePath, @"BIOGame\" + info.pccPath));
             if (File.Exists(info.pccPath))
             {
                 filepath = info.pccPath; //Used for dynamic lookup
             }
             using (ME3Package importPCC = MEPackageHandler.OpenME3Package(filepath))
             {
                 byte[] buff;
                 //Plane and CoverReference inherit from other structs, meaning they don't have default values (who knows why)
                 //thus, I have hardcoded what those default values should be
                 if (className == "Plane")
                 {
                     buff = PlaneDefault;
                 }
                 else if (className == "CoverReference")
                 {
                     buff = CoverReferenceDefault;
                 }
                 else
                 {
                     buff = importPCC.Exports[info.exportIndex].Data.Skip(0x24).ToArray();
                 }
                 List <PropertyReader.Property> Props = PropertyReader.ReadProp(importPCC, buff, 0);
                 MemoryStream m = new MemoryStream();
                 foreach (PropertyReader.Property p in Props)
                 {
                     string propName = importPCC.getNameEntry(p.Name);
                     //check if property is transient, if so, skip (neither of the structs that inherit have transient props)
                     if (info.properties.ContainsKey(propName) || propName == "None" || info.baseClass != "Class")
                     {
                         if (immutable && !fullProps)
                         {
                             PropertyReader.ImportImmutableProperty(pcc, importPCC, p, className, m, true);
                         }
                         else
                         {
                             PropertyReader.ImportProperty(pcc, importPCC, p, className, m, true);
                         }
                     }
                 }
                 return(m.ToArray());
             }
         }
         catch (Exception)
         {
             return(null);
         }
     }
     else if (Classes.ContainsKey(className))
     {
         ClassInfo info = Structs[className];
         try
         {
             string filepath = (Path.Combine(ME3Directory.gamePath, @"BIOGame\" + info.pccPath));
             if (File.Exists(info.pccPath))
             {
                 filepath = info.pccPath; //Used for dynamic lookup
             }
             using (ME3Package importPCC = MEPackageHandler.OpenME3Package(filepath))
             {
                 IExportEntry entry = pcc.Exports[info.exportIndex + 1];
                 List <PropertyReader.Property> Props = PropertyReader.getPropList(entry);
                 MemoryStream m = new MemoryStream(entry.DataSize - 4);
                 foreach (PropertyReader.Property p in Props)
                 {
                     if (!info.properties.ContainsKey(importPCC.getNameEntry(p.Name)))
                     {
                         //property is transient
                         continue;
                     }
                     PropertyReader.ImportProperty(pcc, importPCC, p, className, m);
                 }
                 return(m.ToArray());
             }
         }
         catch (Exception)
         {
             return(null);
         }
     }
     return(null);
 }