public ME3FaceFXAnimSet(IMEPackage Pcc, IExportEntry Entry) { pcc = Pcc; export = Entry; List<PropertyReader.Property> props = PropertyReader.getPropList(export); int start = props[props.Count - 1].offend + 4; SerializingContainer Container = new SerializingContainer(new MemoryStream(export.Data.Skip(start).ToArray())); Container.isLoading = true; Serialize(Container); }
protected SObj(int idx, IMEPackage p) { pcc = p; index = idx; export = pcc.getExport(index); comment = new SText(GetComment(), commentColor, false); comment.X = 0; comment.Y = 0 - comment.Height; comment.Pickable = false; this.AddChild(comment); this.Pickable = true; }
public static void WriteDelegateProperty(this Stream stream, IMEPackage pcc, string propName, int unk, NameReference value) { stream.WritePropHeader(pcc, propName, PropertyType.DelegateProperty, 12); stream.WriteValueS32(unk); stream.WriteValueS32(pcc.FindNameOrAdd(value.Name)); stream.WriteValueS32(value.count); }
public static void WriteNoneProperty(this EndianWriter stream, IMEPackage pcc) { //Debug.WriteLine("Writing none property at 0x" + stream.Position.ToString("X6")); stream.WriteNameReference("None", pcc); }
public static void WriteStringProperty(this Stream stream, IMEPackage pcc, string propName, string value) { int strLen = value.Length + 1; if (pcc.Game == MEGame.ME3) { stream.WritePropHeader(pcc, propName, PropertyType.StrProperty, (strLen * 2) + 4); stream.WriteValueS32(-strLen); stream.WriteStringUnicode(value); } else { stream.WritePropHeader(pcc, propName, PropertyType.StrProperty, strLen + 4); stream.WriteValueS32(strLen); stream.WriteStringASCII(value); } }
public SAction(int idx, float x, float y, IMEPackage p, GraphEditor grapheditor) : base(idx, p, grapheditor) { GetVarLinks(); GetOutputLinks(); originalX = x; originalY = y; }
protected SBox(int idx, IMEPackage p, GraphEditor grapheditor) : base(idx, p, grapheditor) { }
public static List<Property> ReadProp(IMEPackage pcc, byte[] raw, int start) { Property p; PropertyValue v; int sname; List<Property> result = new List<Property>(); int pos = start; if(raw.Length - pos < 8) return result; int name = (int)BitConverter.ToInt64(raw, pos); if (!pcc.isName(name)) return result; string t = pcc.getNameEntry(name); p = new Property(); p.Name = name; if (t == "None") { p.TypeVal = PropertyType.None; p.offsetval = pos; p.Size = 8; p.Value = new PropertyValue(); p.raw = BitConverter.GetBytes((long)name); p.offend = pos + 8; result.Add(p); return result; } int type = (int)BitConverter.ToInt64(raw, pos + 8); p.Size = BitConverter.ToInt32(raw, pos + 16); if (!pcc.isName(type) || p.Size < 0 || p.Size >= raw.Length) return result; string tp = pcc.getNameEntry(type); switch (tp) { case "DelegateProperty": p.TypeVal = PropertyType.DelegateProperty; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = BitConverter.ToInt32(raw, pos + 28); v.len = p.Size; v.Array = new List<PropertyValue>(); pos += 24; for (int i = 0; i < p.Size; i++) { PropertyValue v2 = new PropertyValue(); if(pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "ArrayProperty": int count = BitConverter.ToInt32(raw, pos + 24); p.TypeVal = PropertyType.ArrayProperty; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = p.Size - 4; count = v.len;//TODO can be other objects too v.Array = new List<PropertyValue>(); pos += 28; for (int i = 0; i < count; i++) { PropertyValue v2 = new PropertyValue(); if(pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos ++; } p.Value = v; break; case "StrProperty": count = BitConverter.ToInt32(raw, pos + 24); p.TypeVal = PropertyType.StrProperty; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = type; v.len = count; pos += 28; string s = ""; if (count < 0) { count *= -1; for (int i = 1; i < count; i++) { s += (char)raw[pos]; pos += 2; } pos += 2; } else if (count > 0) { for (int i = 1; i < count; i++) { s += (char)raw[pos]; pos++; } pos++; } v.StringValue = s; p.Value = v; break; case "StructProperty": sname = BitConverter.ToInt32(raw, pos + 24); p.TypeVal = PropertyType.StructProperty; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = sname; v.len = p.Size; v.Array = new List<PropertyValue>(); pos += 32; for (int i = 0; i < p.Size; i++) { PropertyValue v2 = new PropertyValue(); if (pos < raw.Length) v2.IntValue = raw[pos]; v.Array.Add(v2); pos++; } p.Value = v; break; case "BioMask4Property": p.TypeVal = PropertyType.ByteProperty; p.offsetval = pos + 24; v = new PropertyValue(); v.len = p.Size; pos += 24; v.IntValue = raw[pos]; pos += p.Size; p.Value = v; break; case "ByteProperty": sname = BitConverter.ToInt32(raw, pos + 24); p.TypeVal = PropertyType.ByteProperty; v = new PropertyValue(); v.len = p.Size; if (pcc.Game == MEGame.ME3) { p.offsetval = pos + 32; v.StringValue = pcc.getNameEntry(sname); pos += 32; if (p.Size == 8) { v.IntValue = BitConverter.ToInt32(raw, pos); } else { v.IntValue = raw[pos]; } pos += p.Size; } else { p.offsetval = pos + 24; if (p.Size != 1) { v.StringValue = pcc.getNameEntry(sname); v.IntValue = sname; pos += 32; } else { v.StringValue = ""; v.IntValue = raw[pos + 24]; pos += 25; } } p.Value = v; break; case "FloatProperty": sname = BitConverter.ToInt32(raw, pos + 24); p.TypeVal = PropertyType.FloatProperty; p.offsetval = pos + 24; v = new PropertyValue(); v.FloatValue = BitConverter.ToSingle(raw, pos + 24); v.len = p.Size; pos += 28; p.Value = v; break; case "BoolProperty": p = new Property(); p.Name = name; p.TypeVal = PropertyType.BoolProperty; p.offsetval = pos + 24; v = new PropertyValue(); v.IntValue = raw[pos + 24]; if (pcc.Game == MEGame.ME3) { v.len = 1; } else { v.len = 4; } pos += v.len + 24; p.Value = v; break; default: p.TypeVal = getType(pcc,type); p.offsetval = pos + 24; p.Value = ReadValue(pcc, raw, pos + 24, type); pos += p.Value.len + 24; break; } p.raw = new byte[pos - start]; p.offend = pos; if(pos < raw.Length) for (int i = 0; i < pos - start; i++) p.raw[i] = raw[start + i]; result.Add(p); if(pos!=start) result.AddRange(ReadProp(pcc, raw, pos)); return result; }
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 + '\0'; if (p.Value.len < 0) { 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 { 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 || !ME3UnrealObjectInfo.isImmutable(info.reference))) { 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); } }
/// <summary> /// Ports an export into a package. Checks if the export already exists, and if it does, returns that instead. /// </summary> /// <param name="targetPackage">The target package to port into.</param> /// <param name="sourceExport">The source export to port over, including all dependencies and references.</param> /// <param name="targetLink">The target link UIndex. Only used if createParentPackages is false.</param> /// <param name="createParentPackages">If the export should be ported in the same way as it was cooked into the package natively, e.g. create the parent package paths. The export must directly sit under a Package or an exception will be thrown.</param> /// <param name="ensureMemoryUniqueness">If this object is an instance, such as a sequence object, and should be made memory-unique so it is properly used</param> /// <returns></returns> public static ExportEntry PortExportIntoPackage(IMEPackage targetPackage, ExportEntry sourceExport, int targetLink = 0, bool createParentPackages = true, bool ensureMemoryUniqueness = false, bool useMemorySafeImport = false, PackageCache cache = null) { #if DEBUG // in preprocessor to prevent this from running in release mode if (sourceExport.FileRef.FilePath != null && targetPackage.FilePath != null) { Debug.WriteLine($"Porting {sourceExport.InstancedFullPath} from {Path.GetFileName(sourceExport.FileRef.FilePath)} into {Path.GetFileName(targetPackage.FilePath)}"); } #endif var existing = targetPackage.FindExport(sourceExport.InstancedFullPath); if (existing != null) { return(existing); } // Create parent hierarchy IEntry newParent = null; if (createParentPackages) { List <IEntry> parents = new List <IEntry>(); var parent = sourceExport.Parent; while (parent != null) { if (parent.ClassName != "Package") { throw new Exception("Parent is not package!"); } parents.Add(parent); parent = parent.Parent; } // Create the parents parents.Reverse(); foreach (var p in parents) { var sourceFullPath = p.InstancedFullPath; var matchingParent = targetPackage.FindEntry(sourceFullPath); if (matchingParent != null) { newParent = matchingParent; continue; } newParent = ExportCreator.CreatePackageExport(targetPackage, p.ObjectName, newParent); } } else { newParent = targetPackage.GetEntry(targetLink); } IEntry newEntry; if (!useMemorySafeImport) { Dictionary <IEntry, IEntry> crossPCCObjectMap = new Dictionary <IEntry, IEntry>(); // Not sure what this is used for these days. Should probably just be part of the method var relinkResults = EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneAllDependencies, sourceExport, targetPackage, newParent, true, out newEntry, crossPCCObjectMap); if (relinkResults.Any()) { Debugger.Break(); } } else { // Memory safe, fixes upstream var relinkedResults = EntryExporter.ExportExportToPackage(sourceExport, targetPackage, out newEntry, MERFileSystem.GetGlobalCache(), cache); if (relinkedResults.Any()) { Debugger.Break(); } } #if DEBUG //(sourceExport.FileRef as MEPackage).CompareToPackageDetailed(targetPackage); #endif // Helps ensure we don't have memory duplicates if (ensureMemoryUniqueness) { newEntry.ObjectName = targetPackage.GetNextIndexedName(newEntry.ObjectName); } return(newEntry as ExportEntry); }
public void LoadME3Package(string s) { pcc?.Release(wpfWindow: this); Pcc = MEPackageHandler.OpenME3Package(s, wpfWindow: this); }
/// <summary> /// Copies the inputstream to the outputstream, for the specified amount of bytes /// </summary> /// <param name="input">Stream to copy from</param> /// <param name="output">Stream to copy to</param> /// <param name="bytes">The number of bytes to copy</param> //public static void CopyToEx(this Stream input, Stream output, int bytes) //{ // var buffer = new byte[32768]; // int read; // while (bytes > 0 && // (read = input.Read(buffer, 0, Math.Min(buffer.Length, bytes))) > 0) // { // output.Write(buffer, 0, read); // bytes -= read; // } //} public static NameReference ReadNameReference(this Stream stream, IMEPackage pcc) { return(new NameReference(pcc.getNameEntry(stream.ReadInt32()), stream.ReadInt32())); }
public static void WriteNameReference(this Stream stream, NameReference name, IMEPackage pcc) { stream.WriteInt32(pcc.FindNameOrAdd(name.Name)); stream.WriteInt32(name.Number); }
public ImportEntry(IMEPackage pccFile) { FileRef = pccFile; Header = new byte[byteSize]; }
public static void WriteDelegateProperty(this EndianWriter stream, IMEPackage pcc, NameReference propName, ScriptDelegate value, int staticArrayIndex) { stream.WritePropHeader(pcc, propName, PropertyType.DelegateProperty, 12, staticArrayIndex); stream.WriteInt32(value.Object); stream.WriteNameReference(value.FunctionName, pcc); }
public static void WriteArrayProperty(this EndianWriter stream, IMEPackage pcc, NameReference propName, int count, Func <Stream> func, int staticArrayIndex) { stream.WriteArrayProperty(pcc, propName, count, func(), staticArrayIndex); }
public static Property getPropOrNull(IMEPackage pcc, byte[] data, int start, string propName) { List<Property> props = ReadProp(pcc, data, start); foreach (Property prop in props) { if (pcc.getNameEntry(prop.Name) == propName) { return prop; } } return null; }
public static PropertyCollection RemoveIncompatibleProperties(IMEPackage sourcePcc, PropertyCollection props, string typeName, MEGame newGame) { var infoProps = UnrealObjectInfo.GetAllProperties(newGame, typeName); infoProps.KeyComparer = StringComparer.OrdinalIgnoreCase; var newProps = new PropertyCollection(); foreach (Property prop in props) { if (infoProps.ContainsKey(prop.Name)) { switch (prop) { case ArrayProperty <DelegateProperty> adp: //don't think these exist? if they do, delete them break; case ArrayProperty <EnumProperty> aep: if (UnrealObjectInfo.GetEnumValues(newGame, aep.Reference) is List <NameReference> enumValues) { foreach (EnumProperty enumProperty in aep) { if (!enumValues.Contains(enumProperty.Value)) { enumProperty.Value = enumValues.First(); //hope that the first value is a reasonable default } } newProps.Add(aep); } break; case ArrayProperty <ObjectProperty> asp: for (int i = asp.Count - 1; i >= 0; i--) { if (asp[i].Value == 0 || sourcePcc.GetEntry(asp[i].Value) is IEntry entry && !entry.FullPath.StartsWith(UnrealPackageFile.TrashPackageName)) { continue; } //delete if it references a trashed entry or if value is invalid asp.RemoveAt(i); } newProps.Add(asp); break; case ArrayProperty <StructProperty> asp: if (UnrealObjectInfo.GetStructs(newGame).ContainsKey(asp.Reference)) { if (HasIncompatibleImmutabilities(asp.Reference, out bool newImmutability)) { break; } foreach (StructProperty structProperty in asp) { structProperty.Properties = RemoveIncompatibleProperties(sourcePcc, structProperty.Properties, structProperty.StructType, newGame); structProperty.IsImmutable = newImmutability; } newProps.Add(asp); } break; case DelegateProperty delegateProperty: //script related, so just delete it. break; case EnumProperty enumProperty: if (UnrealObjectInfo.GetEnumValues(newGame, enumProperty.EnumType) is List <NameReference> values) { if (!values.Contains(enumProperty.Value)) { enumProperty.Value = values.First(); //hope that the first value is a reasonable default } newProps.Add(enumProperty); } break; case ObjectProperty objectProperty: { if (objectProperty.Value == 0 || sourcePcc.GetEntry(objectProperty.Value) is IEntry entry && !entry.FullPath.StartsWith(UnrealPackageFile.TrashPackageName)) { newProps.Add(objectProperty); } break; } case StructProperty structProperty: string structType = structProperty.StructType; if (UnrealObjectInfo.GetStructs(newGame).ContainsKey(structType)) { if (HasIncompatibleImmutabilities(structType, out bool newImmutability)) { break; } structProperty.Properties = RemoveIncompatibleProperties(sourcePcc, structProperty.Properties, structType, newGame); structProperty.IsImmutable = newImmutability; newProps.Add(structProperty); } break; default: newProps.Add(prop); break; } } } return(newProps); bool HasIncompatibleImmutabilities(string structType, out bool newImmutability) { bool sourceIsImmutable = UnrealObjectInfo.IsImmutable(structType, sourcePcc.Game); newImmutability = UnrealObjectInfo.IsImmutable(structType, newGame); if (sourceIsImmutable && newImmutability && !UnrealObjectInfo.GetClassOrStructInfo(sourcePcc.Game, structType).properties .SequenceEqual(UnrealObjectInfo.GetClassOrStructInfo(newGame, structType).properties)) { //both immutable, but have different properties return(true); } if (!sourceIsImmutable && newImmutability) { //can't easily guarantee it will have have all neccesary properties return(true); } return(false); } }
public static CustomProperty PropertyToGrid(Property p, IMEPackage pcc) { string cat = p.TypeVal.ToString(); CustomProperty pg; NameProp pp; switch (p.TypeVal) { case PropertyType.BoolProperty : pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, (p.Value.IntValue == 1), typeof(bool), false, true); break; case PropertyType.FloatProperty: pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, p.Value.FloatValue, typeof(float), false, true); break; case PropertyType.ByteProperty: if (p.Size != 8) { pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, (byte)p.Value.IntValue, typeof(byte), false, true); } else { pp = new NameProp(); pp.name = pcc.getNameEntry(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, pp, typeof(NameProp), false, true); } break; case PropertyType.NameProperty: pp = new NameProp(); pp.name = pcc.getNameEntry(p.Value.IntValue); pp.nameindex = p.Value.IntValue; pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, pp, typeof(NameProp), false, true); break; case PropertyType.ObjectProperty: ObjectProp ppo = new ObjectProp(); ppo.objectName = pcc.getObjectName(p.Value.IntValue); ppo.index = p.Value.IntValue; pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, ppo, typeof(ObjectProp), false, true); break; case PropertyType.StrProperty: pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, p.Value.StringValue, typeof(string), false, true); break; case PropertyType.ArrayProperty: pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, BitConverter.ToInt32(p.raw,24) + " elements", typeof(string), false, true); break; case PropertyType.StructProperty: string structType = pcc.getNameEntry(p.Value.IntValue); if(structType == "Color") { ColorProp cp = new ColorProp(); cp.name = structType; cp.nameindex = p.Value.IntValue; System.Drawing.Color color = System.Drawing.Color.FromArgb(BitConverter.ToInt32(p.raw, 32)); cp.Alpha = color.A; cp.Red = color.R; cp.Green = color.G; cp.Blue = color.B; pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, cp, typeof(ColorProp), false, true); } else if (structType == "Vector") { VectorProp vp = new VectorProp(); vp.name = structType; vp.nameindex = p.Value.IntValue; vp.X = BitConverter.ToSingle(p.raw, 32); vp.Y = BitConverter.ToSingle(p.raw, 36); vp.Z = BitConverter.ToSingle(p.raw, 40); pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, vp, typeof(VectorProp), false, true); } else if (structType == "Rotator") { RotatorProp rp = new RotatorProp(); rp.name = structType; rp.nameindex = p.Value.IntValue; rp.Pitch = BitConverter.ToInt32(p.raw, 32) * 360f / 65536f; rp.Yaw = BitConverter.ToInt32(p.raw, 36) * 360f / 65536f; rp.Roll = BitConverter.ToInt32(p.raw, 40) * 360f / 65536f; pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, rp, typeof(RotatorProp), false, true); } else if (structType == "LinearColor") { LinearColorProp lcp = new LinearColorProp(); lcp.name = structType; lcp.nameindex = p.Value.IntValue; lcp.Red = BitConverter.ToSingle(p.raw, 32); lcp.Green = BitConverter.ToSingle(p.raw, 36); lcp.Blue = BitConverter.ToSingle(p.raw, 40); lcp.Alpha = BitConverter.ToSingle(p.raw, 44); pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, lcp, typeof(VectorProp), false, true); } else { StructProp ppp = new StructProp(); ppp.name = structType; ppp.nameindex = p.Value.IntValue; byte[] buf = new byte[p.Value.Array.Count()]; for (int i = 0; i < p.Value.Array.Count(); i++) buf[i] = (byte)p.Value.Array[i].IntValue; List<int> buf2 = new List<int>(); for (int i = 0; i < p.Value.Array.Count() / 4; i++) buf2.Add(BitConverter.ToInt32(buf ,i * 4)); ppp.data = buf2.ToArray(); pg = new CustomProperty(pcc.getNameEntry(p.Name), cat, ppp, typeof(StructProp), false, true); } break; default: pg = new CustomProperty(pcc.getNameEntry(p.Name),cat,p.Value.IntValue,typeof(int),false,true); break; } return pg; }
private static PropertyInfo getProperty(ExportEntry entry) { IMEPackage pcc = entry.FileRef; string reference = null; PropertyType type; switch (entry.ClassName) { case "IntProperty": type = PropertyType.IntProperty; break; case "StringRefProperty": type = PropertyType.StringRefProperty; break; case "FloatProperty": type = PropertyType.FloatProperty; break; case "BoolProperty": type = PropertyType.BoolProperty; break; case "StrProperty": type = PropertyType.StrProperty; break; case "NameProperty": type = PropertyType.NameProperty; break; case "DelegateProperty": type = PropertyType.DelegateProperty; break; case "ObjectProperty": case "ClassProperty": case "ComponentProperty": type = PropertyType.ObjectProperty; reference = pcc.getObjectName(BitConverter.ToInt32(entry.Data, entry.Data.Length - 4)); break; case "StructProperty": type = PropertyType.StructProperty; reference = pcc.getObjectName(BitConverter.ToInt32(entry.Data, entry.Data.Length - 4)); break; case "BioMask4Property": case "ByteProperty": type = PropertyType.ByteProperty; reference = pcc.getObjectName(BitConverter.ToInt32(entry.Data, entry.Data.Length - 4)); break; case "ArrayProperty": type = PropertyType.ArrayProperty; PropertyInfo arrayTypeProp = getProperty(pcc.getUExport(BitConverter.ToInt32(entry.Data, 44))); if (arrayTypeProp != null) { switch (arrayTypeProp.Type) { case PropertyType.ObjectProperty: case PropertyType.StructProperty: case PropertyType.ArrayProperty: reference = arrayTypeProp.Reference; break; case PropertyType.ByteProperty: if (arrayTypeProp.Reference == "Class") { reference = arrayTypeProp.Type.ToString(); } else { reference = arrayTypeProp.Reference; } break; case PropertyType.IntProperty: case PropertyType.FloatProperty: case PropertyType.NameProperty: case PropertyType.BoolProperty: case PropertyType.StrProperty: case PropertyType.StringRefProperty: case PropertyType.DelegateProperty: reference = arrayTypeProp.Type.ToString(); break; case PropertyType.None: case PropertyType.Unknown: default: Debugger.Break(); return(null); } } else { return(null); } break; case "InterfaceProperty": default: return(null); } bool transient = ((UnrealFlags.EPropertyFlags)BitConverter.ToUInt64(entry.Data, 24)).HasFlag(UnrealFlags.EPropertyFlags.Transient); return(new PropertyInfo(type, reference, transient)); }
static PropertyValue ReadValue(IMEPackage pcc, byte[] raw, int start, int type) { PropertyValue v = new PropertyValue(); switch (pcc.getNameEntry(type)) { case "IntProperty": case "ObjectProperty": case "StringRefProperty": v.IntValue = BitConverter.ToInt32(raw, start); v.len = 4; break; case "NameProperty": v.IntValue = BitConverter.ToInt32(raw, start); var nameRef = new NameReference(); nameRef.Name = pcc.getNameEntry(v.IntValue); nameRef.count = BitConverter.ToInt32(raw, start + 4); if (nameRef.count > 0) nameRef.Name += "_" + (nameRef.count - 1); v.NameValue = nameRef; v.StringValue = nameRef.Name; v.len = 8; break; } return v; }
/// <summary> /// Attempts to relink unreal binary data to object pointers if they are part of the clone tree. /// It's gonna be an ugly mess. /// </summary> /// <param name="importpcc">PCC being imported from</param> private List <string> relinkBinaryObjects(IMEPackage importpcc) { List <string> relinkFailedReport = new List <string>(); foreach (KeyValuePair <int, int> entry in crossPCCObjectMap) { if (entry.Key > 0) { IExportEntry exp = pcc.getExport(entry.Value); byte[] binarydata = exp.getBinaryData(); if (binarydata.Length > 0) { //has binary data //This is temporary until I find a more permanent style for relinking binary try { switch (exp.ClassName) { case "WwiseEvent": { int count = BitConverter.ToInt32(binarydata, 0); for (int i = 0; i < count; i++) { int originalValue = BitConverter.ToInt32(binarydata, 4 + (i * 4)); int currentObjectRef = unrealIndexToME3ExpIndexing(originalValue); //count + i * intsize int mapped; bool isMapped = crossPCCObjectMap.TryGetValue(currentObjectRef, out mapped); if (isMapped) { mapped = me3ExpIndexingToUnreal(mapped, originalValue < 0); //if the value is 0, it would have an error anyways. Debug.WriteLine("Binary relink hit for WwiseEvent Export " + exp.UIndex + " 0x" + (4 + (i * 4)).ToString("X6") + " " + originalValue + " -> " + (mapped + 1)); WriteMem(4 + (i * 4), binarydata, BitConverter.GetBytes(mapped)); int newValue = BitConverter.ToInt32(binarydata, 4 + (i * 4)); Debug.WriteLine(originalValue + " -> " + newValue); } else { Debug.WriteLine("Binary relink missed WwiseEvent Export " + exp.UIndex + " 0x" + (4 + (i * 4)).ToString("X6") + " " + originalValue); relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: WwiseEvent referenced WwiseStream " + originalValue + " is not in the mapping tree and could not be relinked"); } } exp.setBinaryData(binarydata); } break; case "Class": { if (exp.FileRef.Game != importpcc.Game) { //Cannot relink against a different game. continue; } IExportEntry importingExp = importpcc.getExport(entry.Key); if (importingExp.ClassName != "Class") { continue; //the class was not actually set, so this is not really class. } //This is going to be pretty ugly try { byte[] newdata = importpcc.Exports[entry.Key].Data; //may need to rewrite first unreal header byte[] data = importpcc.Exports[entry.Key].Data; int offset = 0; int unrealExportIndex = BitConverter.ToInt32(data, offset); offset += 4; int superclassIndex = BitConverter.ToInt32(data, offset); if (superclassIndex < 0) { //its an import ImportEntry superclassImportEntry = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(superclassIndex))]; ImportEntry newSuperclassValue = getOrAddCrossImport(superclassImportEntry.GetFullPath, importpcc, exp.FileRef); WriteMem(offset, newdata, BitConverter.GetBytes(newSuperclassValue.UIndex)); } else { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Superclass is an export in the source package and was not relinked."); } int unknown1 = BitConverter.ToInt32(data, offset); offset += 4; int classObjTree = BitConverter.ToInt32(data, offset); //Don't know if I need to do this. offset += 4; //I am not sure what these mean. However if Pt1&2 are 33/25, the following bytes that follow are extended. int headerUnknown1 = BitConverter.ToInt32(data, offset); Int64 ignoreMask = BitConverter.ToInt64(data, offset); offset += 8; Int16 labelOffset = BitConverter.ToInt16(data, offset); offset += 2; int skipAmount = 0x6; //Find end of script block. Seems to be 10 FF's. while (offset + skipAmount + 10 < data.Length) { //Debug.WriteLine("Cheecking at 0x"+(offset + skipAmount + 10).ToString("X4")); bool isEnd = true; for (int i = 0; i < 10; i++) { byte b = data[offset + skipAmount + i]; if (b != 0xFF) { isEnd = false; break; } } if (isEnd) { break; } else { skipAmount++; } } int offsetEnd = offset + skipAmount + 10; offset += skipAmount + 10; //heuristic to find end of script uint stateMask = BitConverter.ToUInt32(data, offset); offset += 4; int localFunctionsTableCount = BitConverter.ToInt32(data, offset); offset += 4; bool isMapped; for (int i = 0; i < localFunctionsTableCount; i++) { int nameTableIndex = BitConverter.ToInt32(data, offset); int nameIndex = BitConverter.ToInt32(data, offset + 4); NameReference importingName = importpcc.getNameEntry(nameTableIndex); int newFuncName = exp.FileRef.FindNameOrAdd(importingName); WriteMem(offset, newdata, BitConverter.GetBytes(newFuncName)); offset += 8; int functionObjectIndex = unrealIndexToME3ExpIndexing(BitConverter.ToInt32(data, offset)); int mapped; isMapped = crossPCCObjectMap.TryGetValue(functionObjectIndex, out mapped); if (isMapped) { mapped = me3ExpIndexingToUnreal(mapped, functionObjectIndex < 0); //if the value is 0, it would have an error anyways. WriteMem(offset, newdata, BitConverter.GetBytes(mapped)); } else { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Local function[" + i + "] could not be remapped during porting: " + functionObjectIndex + " is not in the mapping tree and could not be relinked"); } offset += 4; } int classMask = BitConverter.ToInt32(data, offset); offset += 4; if (importpcc.Game != MEGame.ME3) { offset += 1; //seems to be a blank byte here } int coreReference = BitConverter.ToInt32(data, offset); if (coreReference < 0) { //its an import ImportEntry outerclassReferenceImport = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(coreReference))]; ImportEntry outerclassNewImport = getOrAddCrossImport(outerclassReferenceImport.GetFullPath, importpcc, exp.FileRef); WriteMem(offset, newdata, BitConverter.GetBytes(outerclassNewImport.UIndex)); } else { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Outerclass is an export in the original package, not relinked."); } offset += 4; if (importpcc.Game == MEGame.ME3) { offset = ClassParser_RelinkComponentsTable(importpcc, exp, relinkFailedReport, ref newdata, offset); offset = ClassParser_ReadImplementsTable(importpcc, exp, relinkFailedReport, ref newdata, offset); int postComponentsNoneNameIndex = BitConverter.ToInt32(data, offset); int postComponentNoneIndex = BitConverter.ToInt32(data, offset + 4); string postCompName = importpcc.getNameEntry(postComponentsNoneNameIndex); //This appears to be unused in ME3, it is always None it seems. int newFuncName = exp.FileRef.FindNameOrAdd(postCompName); WriteMem(offset, newdata, BitConverter.GetBytes(newFuncName)); offset += 8; int unknown4 = BitConverter.ToInt32(data, offset); offset += 4; } else { offset = ClassParser_ReadImplementsTable(importpcc, exp, relinkFailedReport, ref data, offset); offset = ClassParser_RelinkComponentsTable(importpcc, exp, relinkFailedReport, ref data, offset); int me12unknownend1 = BitConverter.ToInt32(data, offset); offset += 4; int me12unknownend2 = BitConverter.ToInt32(data, offset); offset += 4; } int defaultsClassLink = unrealIndexToME3ExpIndexing(BitConverter.ToInt32(data, offset)); int defClassLink; isMapped = crossPCCObjectMap.TryGetValue(defaultsClassLink, out defClassLink); if (isMapped) { defClassLink = me3ExpIndexingToUnreal(defClassLink, defaultsClassLink < 0); //if the value is 0, it would have an error anyways. WriteMem(offset, newdata, BitConverter.GetBytes(defClassLink)); } else { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: DefaultsClassLink cannot be currently automatically relinked by Binary Relinker. Please manually set this in Binary Editor"); } offset += 4; if (importpcc.Game == MEGame.ME3) { int functionsTableCount = BitConverter.ToInt32(data, offset); offset += 4; for (int i = 0; i < functionsTableCount; i++) { int functionsTableIndex = unrealIndexToME3ExpIndexing(BitConverter.ToInt32(data, offset)); int mapped; isMapped = crossPCCObjectMap.TryGetValue(functionsTableIndex, out mapped); if (isMapped) { mapped = me3ExpIndexingToUnreal(mapped, functionsTableIndex < 0); //if the value is 0, it would have an error anyways. WriteMem(offset, newdata, BitConverter.GetBytes(mapped)); } else { if (functionsTableIndex < 0) { ImportEntry functionObjIndex = importpcc.Imports[Math.Abs(functionsTableIndex)]; ImportEntry newFunctionObjIndex = getOrAddCrossImport(functionObjIndex.GetFullPath, importpcc, exp.FileRef); WriteMem(offset, newdata, BitConverter.GetBytes(newFunctionObjIndex.UIndex)); } else { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Full Functions List function[" + i + "] could not be remapped during porting: " + functionsTableIndex + " is not in the mapping tree and could not be relinked"); } } offset += 4; } } exp.Data = newdata; } catch (Exception ex) { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Exception relinking: " + ex.Message); } } break; default: continue; } } catch (Exception e) { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relinking failed: " + e.Message); } //Run an interpreter pass over it - we will find objectleafnodes and attempt to update the same offset in the destination file. //BinaryInterpreter binaryrelinkInterpreter = new ME3Explorer.BinaryInterpreter(importpcc, importpcc.Exports[entry.Key], pcc, pcc.Exports[entry.Value], crossPCCObjectMapping); } } } return(relinkFailedReport); }
private void importImport(IMEPackage importpcc, int n, int link) { ImportEntry imp = importpcc.getImport(n); ImportEntry nimp = new ImportEntry(pcc, imp.header); nimp.idxLink = link; nimp.idxClassName = pcc.FindNameOrAdd(importpcc.getNameEntry(imp.idxClassName)); nimp.idxObjectName = pcc.FindNameOrAdd(importpcc.getNameEntry(imp.idxObjectName)); nimp.idxPackageFile = pcc.FindNameOrAdd(importpcc.getNameEntry(imp.idxPackageFile)); pcc.addImport(nimp); }
public InterpCurve(IMEPackage _pcc, PropertyReader.Property p) { pcc = _pcc; Curves = new ObservableCollection<Curve>(); Name = pcc.getNameEntry(p.Name); curveType = (CurveType)Enum.Parse(typeof(CurveType), pcc.getNameEntry(p.Value.IntValue)); float InVal = 0f; CurveMode InterpMode = CurveMode.CIM_Linear; var points = PropertyReader.ReadStructArrayProp(pcc, PropertyReader.getPropOrNull(pcc, p.raw, 32, "Points")); switch (curveType) { case CurveType.InterpCurveQuat: throw new NotImplementedException($"InterpCurveQuat has not been implemented yet."); case CurveType.InterpCurveFloat: float OutVal = 0f; float ArriveTangent = 0f; float LeaveTangent = 0f; LinkedList<CurvePoint> vals = new LinkedList<CurvePoint>(); foreach (var point in points) { foreach (var prop in point) { switch (pcc.getNameEntry(prop.Name)) { case "InVal": InVal = BitConverter.ToSingle(prop.raw, 24); break; case "OutVal": OutVal = BitConverter.ToSingle(prop.raw, 24); break; case "ArriveTangent": ArriveTangent = BitConverter.ToSingle(prop.raw, 24); break; case "LeaveTangent": LeaveTangent = BitConverter.ToSingle(prop.raw, 24); break; case "InterpMode": InterpMode = (CurveMode)Enum.Parse(typeof(CurveMode), pcc.getNameEntry(prop.Value.IntValue)); break; default: break; } } vals.AddLast(new CurvePoint(InVal, OutVal, ArriveTangent, LeaveTangent, InterpMode)); } Curves.Add(new Curve("X", vals)); break; case CurveType.InterpCurveVector: Vector OutValVec = new Vector(0, 0, 0); Vector ArriveTangentVec = new Vector(0, 0, 0); Vector LeaveTangentVec = new Vector(0, 0, 0); LinkedList<CurvePoint> x = new LinkedList<CurvePoint>(); LinkedList<CurvePoint> y = new LinkedList<CurvePoint>(); LinkedList<CurvePoint> z = new LinkedList<CurvePoint>(); foreach (var point in points) { foreach (var prop in point) { switch (pcc.getNameEntry(prop.Name)) { case "InVal": InVal = BitConverter.ToSingle(prop.raw, 24); break; case "OutVal": OutValVec = GetVector(prop); break; case "ArriveTangent": ArriveTangentVec = GetVector(prop); break; case "LeaveTangent": LeaveTangentVec = GetVector(prop); break; case "InterpMode": InterpMode = (CurveMode)Enum.Parse(typeof(CurveMode), pcc.getNameEntry(prop.Value.IntValue)); break; default: break; } } x.AddLast(new CurvePoint(InVal, OutValVec.X, ArriveTangentVec.X, LeaveTangentVec.X, InterpMode)); y.AddLast(new CurvePoint(InVal, OutValVec.Y, ArriveTangentVec.Y, LeaveTangentVec.Y, InterpMode)); z.AddLast(new CurvePoint(InVal, OutValVec.Z, ArriveTangentVec.Z, LeaveTangentVec.Z, InterpMode)); } if (Name == "EulerTrack") { Curves.Add(new Curve("Roll", x)); Curves.Add(new Curve("Pitch", y)); Curves.Add(new Curve("Yaw", z)); } else { Curves.Add(new Curve("X", x)); Curves.Add(new Curve("Y", y)); Curves.Add(new Curve("Z", z)); } break; case CurveType.InterpCurveVector2D: throw new NotImplementedException($"InterpCurveVector2D has not been implemented yet."); case CurveType.InterpCurveTwoVectors: throw new NotImplementedException($"InterpCurveTwoVectors has not been implemented yet."); case CurveType.InterpCurveLinearColor: throw new NotImplementedException($"InterpCurveLinearColor has not been implemented yet."); default: break; } foreach (var curve in Curves) { curve.SharedValueChanged += Curve_SharedValueChanged; curve.ListModified += Curve_ListModified; } }
public SVar(int idx, float x, float y, IMEPackage p, GraphEditor grapheditor) : base(idx, p, grapheditor) { string s = export.ObjectName; s = s.Replace("BioSeqVar_", ""); s = s.Replace("SFXSeqVar_", ""); s = s.Replace("SeqVar_", ""); type = getType(s); float w = 60; float h = 60; shape = PPath.CreateEllipse(0, 0, w, h); outlinePen = new Pen(getColor(type)); shape.Pen = outlinePen; shape.Brush = nodeBrush; shape.Pickable = false; this.AddChild(shape); this.Bounds = new RectangleF(0, 0, w, h); val = new SText(GetValue()); val.Pickable = false; val.TextAlignment = StringAlignment.Center; val.X = w / 2 - val.Width / 2; val.Y = h / 2 - val.Height / 2; this.AddChild(val); var props = export.GetProperties(); foreach (var prop in props) { if (prop.Name == "VarName" || prop.Name == "varName") { SText VarName = new SText((prop as NameProperty).Value, Color.Red, false); VarName.Pickable = false; VarName.TextAlignment = StringAlignment.Center; VarName.X = w / 2 - VarName.Width / 2; VarName.Y = h; this.AddChild(VarName); break; } } this.TranslateBy(x, y); this.MouseEnter += OnMouseEnter; this.MouseLeave += OnMouseLeave; }
//call this method to regenerate ME1ObjectInfo.json //Takes a long time (10 to 20 minutes maybe?). Application will be completely unresponsive during that time. public static void generateInfo(string outpath) { Classes = new Dictionary <string, ClassInfo>(); Structs = new Dictionary <string, ClassInfo>(); Enums = new Dictionary <string, List <NameReference> >(); SequenceObjects = new Dictionary <string, SequenceObjectInfo>(); foreach (string file in MELoadedFiles.GetOfficialFiles(MEGame.ME1)) { if (Path.GetExtension(file) == ".upk" || Path.GetExtension(file) == ".sfm" || Path.GetExtension(file) == ".u") { Debug.WriteLine($"File: {file}"); using IMEPackage pcc = MEPackageHandler.OpenME1Package(file); for (int j = 1; j <= pcc.ExportCount; j++) { ExportEntry exportEntry = pcc.GetUExport(j); string className = exportEntry.ClassName; if (className == "Enum") { generateEnumValues(exportEntry); } else if (className == "Class") { string objectName = exportEntry.ObjectName; Debug.WriteLine($"Generating information for {objectName}"); if (!Classes.ContainsKey(objectName)) { Classes.Add(objectName, generateClassInfo(exportEntry)); } } else if (className == "ScriptStruct") { string objectName = exportEntry.ObjectName; if (!Structs.ContainsKey(exportEntry.ObjectName)) { Structs.Add(objectName, generateClassInfo(exportEntry, isStruct: true)); } } else if (exportEntry.IsA("SequenceObject")) { if (!SequenceObjects.TryGetValue(className, out SequenceObjectInfo seqObjInfo)) { seqObjInfo = new SequenceObjectInfo(); SequenceObjects.Add(className, seqObjInfo); } int objInstanceVersion = exportEntry.GetProperty <IntProperty>("ObjInstanceVersion"); if (objInstanceVersion > seqObjInfo.ObjInstanceVersion) { seqObjInfo.ObjInstanceVersion = objInstanceVersion; } } } } } //CUSTOM ADDITIONS Classes["LightMapTexture2D"] = new ClassInfo { baseClass = "Texture2D", exportIndex = 0, pccPath = UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName }; Classes["StaticMesh"] = new ClassInfo { baseClass = "Object", exportIndex = 0, pccPath = UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName, properties = { new KeyValuePair <string, PropertyInfo>("UseSimpleRigidBodyCollision", new PropertyInfo(PropertyType.BoolProperty)), new KeyValuePair <string, PropertyInfo>("UseSimpleLineCollision", new PropertyInfo(PropertyType.BoolProperty)), new KeyValuePair <string, PropertyInfo>("UseSimpleBoxCollision", new PropertyInfo(PropertyType.BoolProperty)), new KeyValuePair <string, PropertyInfo>("ForceDoubleSidedShadowVolumes", new PropertyInfo(PropertyType.BoolProperty)), new KeyValuePair <string, PropertyInfo>("BodySetup", new PropertyInfo(PropertyType.ObjectProperty, "RB_BodySetup")), new KeyValuePair <string, PropertyInfo>("LODDistanceRatio", new PropertyInfo(PropertyType.FloatProperty)), new KeyValuePair <string, PropertyInfo>("LightMapCoordinateIndex", new PropertyInfo(PropertyType.IntProperty)), new KeyValuePair <string, PropertyInfo>("LightMapResolution", new PropertyInfo(PropertyType.IntProperty)), new KeyValuePair <string, PropertyInfo>("SoundCue", new PropertyInfo(PropertyType.ObjectProperty, "SoundCue")), } }; File.WriteAllText(outpath, JsonConvert.SerializeObject(new { SequenceObjects, Classes, Structs, Enums }, Formatting.Indented)); }
private int ClassParser_RelinkComponentsTable(IMEPackage importpcc, IExportEntry exp, List <string> relinkFailedReport, ref byte[] data, int offset) { if (importpcc.Game == MEGame.ME3) { int componentTableNameIndex = BitConverter.ToInt32(data, offset); int componentTableIndex = BitConverter.ToInt32(data, offset + 4); NameReference importingName = importpcc.getNameEntry(componentTableNameIndex); int newComponentTableName = exp.FileRef.FindNameOrAdd(importingName); WriteMem(offset, data, BitConverter.GetBytes(newComponentTableName)); offset += 8; int componentTableCount = BitConverter.ToInt32(data, offset); offset += 4; for (int i = 0; i < componentTableCount; i++) { int nameTableIndex = BitConverter.ToInt32(data, offset); int nameIndex = BitConverter.ToInt32(data, offset + 4); importingName = importpcc.getNameEntry(nameTableIndex); int componentName = exp.FileRef.FindNameOrAdd(importingName); WriteMem(offset, data, BitConverter.GetBytes(componentName)); offset += 8; int componentObjectIndex = BitConverter.ToInt32(data, offset); int mapped; bool isMapped = crossPCCObjectMap.TryGetValue(componentObjectIndex, out mapped); if (isMapped) { mapped = me3ExpIndexingToUnreal(mapped, componentObjectIndex < 0); //if the value is 0, it would have an error anyways. WriteMem(offset, data, BitConverter.GetBytes(mapped)); } else { if (componentObjectIndex < 0) { ImportEntry componentObjectImport = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(componentObjectIndex))]; ImportEntry newComponentObjectImport = getOrAddCrossImport(componentObjectImport.GetFullPath, importpcc, exp.FileRef); WriteMem(offset, data, BitConverter.GetBytes(newComponentObjectImport.UIndex)); } else if (componentObjectIndex > 0) //we do not remap on 0 here in binary land { relinkFailedReport.Add(exp.Index + " " + exp.GetFullPath + " binary relink error: Component[" + i + "] could not be remapped during porting: " + componentObjectIndex + " is not in the mapping tree"); } } offset += 4; } } else { int componentTableCount = BitConverter.ToInt32(data, offset); offset += 4; for (int i = 0; i < componentTableCount; i++) { int nameTableIndex = BitConverter.ToInt32(data, offset); int nameIndex = BitConverter.ToInt32(data, offset + 4); offset += 8; int componentObjectIndex = BitConverter.ToInt32(data, offset); if (componentObjectIndex != 0) { int mapped; bool isMapped = crossPCCObjectMap.TryGetValue(componentObjectIndex, out mapped); if (isMapped) { mapped = me3ExpIndexingToUnreal(mapped, componentObjectIndex < 0); //if the value is 0, it would have an error anyways. WriteMem(offset, data, BitConverter.GetBytes(mapped)); } else { if (componentObjectIndex < 0) { ImportEntry componentObjectImport = importpcc.Imports[Math.Abs(unrealIndexToME3ExpIndexing(componentObjectIndex))]; ImportEntry newComponentObjectImport = getOrAddCrossImport(componentObjectImport.GetFullPath, importpcc, exp.FileRef); WriteMem(offset, data, BitConverter.GetBytes(newComponentObjectImport.UIndex)); } else { relinkFailedReport.Add("Binary Class Component[" + i + "] could not be remapped during porting: " + componentObjectIndex + " is not in the mapping tree"); } } } offset += 4; } } return(offset); }
public static IEntry GetEntry(Window owner, IMEPackage pcc, SupportedTypes supportedInputTypes, string directionsText = null) { var dlg = new EntrySelector(owner, pcc, supportedInputTypes, directionsText); return(dlg.ShowDialog() == true ? dlg.ChosenEntry : null); }
public static void propGridPropertyValueChanged(PropertyValueChangedEventArgs e, int n, IMEPackage pcc) { string name = e.ChangedItem.Label; GridItem parent = e.ChangedItem.Parent; //if (parent != null) name = parent.Label; if (parent.Label == "data") { GridItem parent2 = parent.Parent; if (parent2 != null) name = parent2.Label; } Type parentVal = null; if (parent.Value != null) { parentVal = parent.Value.GetType(); } if (name == "nameindex" || name == "index" || parentVal == typeof(ColorProp) || parentVal == typeof(VectorProp) || parentVal == typeof(Unreal.RotatorProp) || parentVal == typeof(Unreal.LinearColorProp)) { name = parent.Label; } IExportEntry ent = pcc.getExport(n); byte[] data = ent.Data; List<PropertyReader.Property> p = PropertyReader.getPropList(ent); int m = -1; for (int i = 0; i < p.Count; i++) if (pcc.getNameEntry(p[i].Name) == name) m = i; if (m == -1) return; byte[] buff2; switch (p[m].TypeVal) { case PropertyType.BoolProperty: byte res = 0; if ((bool)e.ChangedItem.Value == true) res = 1; data[p[m].offsetval] = res; break; case PropertyType.FloatProperty: buff2 = BitConverter.GetBytes((float)e.ChangedItem.Value); for (int i = 0; i < 4; i++) data[p[m].offsetval + i] = buff2[i]; break; case PropertyType.IntProperty: case PropertyType.StringRefProperty: int newv = Convert.ToInt32(e.ChangedItem.Value); int oldv = Convert.ToInt32(e.OldValue); buff2 = BitConverter.GetBytes(newv); for (int i = 0; i < 4; i++) data[p[m].offsetval + i] = buff2[i]; break; case PropertyType.StrProperty: string s = Convert.ToString(e.ChangedItem.Value); int stringMultiplier = 1; int oldLength = BitConverter.ToInt32(data, p[m].offsetval); if (oldLength < 0) { stringMultiplier = 2; oldLength *= -2; } int oldSize = 4 + oldLength; List<byte> stringBuff = new List<byte>(s.Length * stringMultiplier); if (stringMultiplier == 2) { for (int j = 0; j < s.Length; j++) { stringBuff.AddRange(BitConverter.GetBytes(s[j])); } stringBuff.Add(0); } else { for (int j = 0; j < s.Length; j++) { stringBuff.Add(BitConverter.GetBytes(s[j])[0]); } } stringBuff.Add(0); buff2 = BitConverter.GetBytes((s.Length + 1) * stringMultiplier + 4); for (int j = 0; j < 4; j++) data[p[m].offsetval - 8 + j] = buff2[j]; buff2 = BitConverter.GetBytes((s.Length + 1) * stringMultiplier == 1 ? 1 : -1); for (int j = 0; j < 4; j++) data[p[m].offsetval + j] = buff2[j]; buff2 = new byte[data.Length - oldLength + stringBuff.Count]; int startLength = p[m].offsetval + 4; int startLength2 = startLength + oldLength; for (int i = 0; i < startLength; i++) { buff2[i] = data[i]; } for (int i = 0; i < stringBuff.Count; i++) { buff2[i + startLength] = stringBuff[i]; } startLength += stringBuff.Count; for (int i = 0; i < data.Length - startLength2; i++) { buff2[i + startLength] = data[i + startLength2]; } data = buff2; break; case PropertyType.StructProperty: if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(ColorProp)) { switch (e.ChangedItem.Label) { case "Alpha": data[p[m].offsetval + 11] = Convert.ToByte(e.ChangedItem.Value); break; case "Red": data[p[m].offsetval + 10] = Convert.ToByte(e.ChangedItem.Value); break; case "Green": data[p[m].offsetval + 9] = Convert.ToByte(e.ChangedItem.Value); break; case "Blue": data[p[m].offsetval + 8] = Convert.ToByte(e.ChangedItem.Value); break; default: break; } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(VectorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "X": offset = 8; break; case "Y": offset = 12; break; case "Z": offset = 16; break; default: break; } if (offset != 0) { buff2 = BitConverter.GetBytes(Convert.ToSingle(e.ChangedItem.Value)); for (int i = 0; i < 4; i++) data[p[m].offsetval + offset + i] = buff2[i]; } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(Unreal.RotatorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "Pitch": offset = 8; break; case "Yaw": offset = 12; break; case "Roll": offset = 16; break; default: break; } if (offset != 0) { int val = Convert.ToInt32(Convert.ToSingle(e.ChangedItem.Value) * 65536f / 360f); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) data[p[m].offsetval + offset + i] = buff2[i]; } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(Unreal.LinearColorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "Red": offset = 8; break; case "Green": offset = 12; break; case "Blue": offset = 16; break; case "Alpha": offset = 20; break; default: break; } if (offset != 0) { buff2 = BitConverter.GetBytes(Convert.ToSingle(e.ChangedItem.Value)); for (int i = 0; i < 4; i++) data[p[m].offsetval + offset + i] = buff2[i]; } } else if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); if (e.ChangedItem.Label == "nameindex") { int val1 = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val1); for (int i = 0; i < 4; i++) data[p[m].offsetval + i] = buff2[i]; } else { string sidx = e.ChangedItem.Label.Replace("[", ""); sidx = sidx.Replace("]", ""); int index = Convert.ToInt32(sidx); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) data[p[m].offsetval + i + index * 4 + 8] = buff2[i]; } } break; case PropertyType.ByteProperty: case PropertyType.NameProperty: if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) data[p[m].offsetval + i] = buff2[i]; } break; case PropertyType.ObjectProperty: if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) data[p[m].offsetval + i] = buff2[i]; } break; default: return; } ent.Data = data; }
/// <summary> /// Adds an import from the importingPCC to the destinationPCC with the specified importFullName, or returns the existing one if it can be found. /// This method will look at importingPCC's import upstream chain and check for the most downstream one's existence in destinationPCC, /// including if none can be founc (in which case the entire upstream is copied). It will then create new imports to match the remaining /// downstream ones and return the originally named import, however now located in destinationPCC. /// </summary> /// <param name="importFullName">GetFullPath() of an import from ImportingPCC</param> /// <param name="importingPCC">PCC to import imports from</param> /// <param name="destinationPCC">PCC to add imports to</param> /// <returns></returns> private ImportEntry getOrAddCrossImport(string importFullName, IMEPackage importingPCC, IMEPackage destinationPCC, int?forcedLinkIdx = null) { //This code is kind of ugly, sorry. //see if this import exists locally foreach (ImportEntry imp in destinationPCC.Imports) { if (imp.GetFullPath == importFullName) { return(imp); } } //Import doesn't exist, so we're gonna need to add it //But first we need to figure out what needs to be added upstream as links //Search upstream until we find something, or we can't get any more upstreams ImportEntry mostdownstreamimport = null; string[] importParts = importFullName.Split('.'); if (!forcedLinkIdx.HasValue) { List <int> upstreamLinks = new List <int>(); //0 = top level, 1 = next level... n = what we wanted to import int upstreamCount = 1; ImportEntry upstreamImport = null; //get number of required upstream imports that do not yet exist while (upstreamCount < importParts.Count()) { string upstream = String.Join(".", importParts, 0, importParts.Count() - upstreamCount); foreach (ImportEntry imp in destinationPCC.Imports) { if (imp.GetFullPath == upstream) { upstreamImport = imp; break; } } if (upstreamImport != null) { //We found an upsteam import that already exists break; } upstreamCount++; } IExportEntry donorUpstreamExport = null; if (upstreamImport == null) { //We have to import the entire upstream chain string fullobjectname = importParts[0]; ImportEntry donorTopLevelImport = null; foreach (ImportEntry imp in importingPCC.Imports) //importing side info we will move to our dest pcc { if (imp.GetFullPath == fullobjectname) { donorTopLevelImport = imp; break; } } if (donorTopLevelImport == null) { //This is issue KinkoJiro had. It is aborting relinking at this step. Will need to find a way to //work with exports as parents for imports which will block it. //Update: This has been partially implemented. Debug.WriteLine("No upstream import was found in the source file. It's probably an export: " + importFullName); foreach (IExportEntry exp in destinationPCC.Exports) //importing side info we will move to our dest pcc { //Console.WriteLine(exp.GetFullPath); if (exp.GetFullPath == fullobjectname) { // = imp; //We will need to find a way to cross map this as this will block cross import mapping unless these exports already exist. Debug.WriteLine("FOUND UPSTREAM, AS EXPORT!"); KFreonLib.Debugging.DebugOutput.StartDebugger("Package Editor Relinker"); KFreonLib.Debugging.DebugOutput.PrintLn("Error: Upstream item that is required is an export in the pcc to import from: " + fullobjectname); donorUpstreamExport = exp; upstreamCount--; //level 1 now from the top down //Create new import with this as higher IDK break; } } if (donorUpstreamExport == null) { Debug.WriteLine("An error has occured. Could not find an upstream import or export for relinking: " + fullobjectname + " from " + pcc.FileName); return(null); } } if (donorUpstreamExport == null) { //Create new toplevel import and set that as the most downstream one. (top = bottom at this point) int downstreamPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(donorTopLevelImport.PackageFile)); int downstreamClassName = destinationPCC.FindNameOrAdd(donorTopLevelImport.ClassName); int downstreamName = destinationPCC.FindNameOrAdd(fullobjectname); mostdownstreamimport = new ImportEntry(destinationPCC); // mostdownstreamimport.idxLink = downstreamLinkIdx; ?? mostdownstreamimport.idxClassName = downstreamClassName; mostdownstreamimport.idxObjectName = downstreamName; mostdownstreamimport.idxPackageFile = downstreamPackageFile; destinationPCC.addImport(mostdownstreamimport); //Add new top level downstream import upstreamImport = mostdownstreamimport; upstreamCount--; //level 1 now from the top down //return null; } } //Have an upstream import, now we need to add downstream imports. while (upstreamCount > 0) { upstreamCount--; string fullobjectname = String.Join(".", importParts, 0, importParts.Count() - upstreamCount); ImportEntry donorImport = null; //Get or create names for creating import and get upstream linkIdx int downstreamName = destinationPCC.FindNameOrAdd(importParts[importParts.Count() - upstreamCount - 1]); foreach (ImportEntry imp in importingPCC.Imports) //importing side info we will move to our dest pcc { if (imp.GetFullPath == fullobjectname) { donorImport = imp; break; } } if (donorImport == null) { throw new Exception("No suitable upstream import was found for porting - this may be an export in the source file that is referenced as a parent or dependency. You should import this object and its parents first. " + fullobjectname + "(as part of " + importFullName + ")"); } int downstreamPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(donorImport.PackageFile)); int downstreamClassName = destinationPCC.FindNameOrAdd(donorImport.ClassName); mostdownstreamimport = new ImportEntry(destinationPCC); mostdownstreamimport.idxLink = donorUpstreamExport == null ? upstreamImport.UIndex : donorUpstreamExport.UIndex; mostdownstreamimport.idxClassName = downstreamClassName; mostdownstreamimport.idxObjectName = downstreamName; mostdownstreamimport.idxPackageFile = downstreamPackageFile; destinationPCC.addImport(mostdownstreamimport); upstreamImport = mostdownstreamimport; } } else { //get importing import ImportEntry importingImport = importingPCC.Imports.FirstOrDefault(x => x.GetFullPath == importFullName); //this shouldn't be null mostdownstreamimport = new ImportEntry(destinationPCC); mostdownstreamimport.idxLink = forcedLinkIdx.Value; mostdownstreamimport.idxClassName = destinationPCC.FindNameOrAdd(importingImport.ClassName); mostdownstreamimport.idxObjectName = destinationPCC.FindNameOrAdd(importingImport.ObjectName); mostdownstreamimport.idxPackageFile = destinationPCC.FindNameOrAdd(Path.GetFileNameWithoutExtension(importingImport.PackageFile)); destinationPCC.addImport(mostdownstreamimport); } return(mostdownstreamimport); }
public static void WriteArrayProperty(this Stream stream, IMEPackage pcc, string propName, int count, Func<MemoryStream> func) { stream.WriteArrayProperty(pcc, propName, count, func()); }
private string relinkObjectProperty(IMEPackage importingPCC, IMEPackage destinationPCC, ObjectProperty objProperty, List <KeyValuePair <int, int> > crossPCCObjectMappingList) { if (objProperty.Value == 0) { return(null); //do not relink 0 } if (importingPCC == destinationPCC && objProperty.Value < 0) { return(null); //do not relink same-pcc imports. } int sourceObjReference = objProperty.Value; if (sourceObjReference > 0) { sourceObjReference--; //make 0 based for mapping. } if (sourceObjReference < 0) { sourceObjReference++; //make 0 based for mapping. } //if (objProperty.Name != null) //{ // Debug.WriteLine(objProperty.Name); //} KeyValuePair <int, int> mapping = crossPCCObjectMappingList.Where(pair => pair.Key == sourceObjReference).FirstOrDefault(); var defaultKVP = default(KeyValuePair <int, int>); //struct comparison if (!mapping.Equals(defaultKVP)) { //relink int newval = 0; if (mapping.Value > 0) { newval = mapping.Value + 1; //reincrement } else if (mapping.Value < 0) { newval = mapping.Value - 1; //redecrement } objProperty.Value = (newval); IEntry entry = destinationPCC.getEntry(newval); string s = ""; if (entry != null) { s = entry.GetFullPath; } Debug.WriteLine("Relink hit: " + sourceObjReference + objProperty.Name + ": " + s); } else if (objProperty.Value < 0) //It's an unmapped import { //objProperty is currently pointing to importingPCC as that is where we read the properties from int n = objProperty.Value; int origvalue = n; int importZeroIndex = Math.Abs(n) - 1; //Debug.WriteLine("Relink miss, attempting JIT relink on " + n + " " + rootNode.Text); if (n < 0 && importZeroIndex < importingPCC.ImportCount) { //Get the original import ImportEntry origImport = importingPCC.getImport(importZeroIndex); string origImportFullName = origImport.GetFullPath; //Debug.WriteLine("We should import " + origImport.GetFullPath); ImportEntry crossImport = null; string linkFailedDueToError = null; try { crossImport = getOrAddCrossImport(origImportFullName, importingPCC, destinationPCC); } catch (Exception e) { //Error during relink KFreonLib.Debugging.DebugOutput.StartDebugger("PCC Relinker"); DebugOutput.PrintLn("Exception occured during relink: "); DebugOutput.PrintLn(ExceptionHandlerDialogWPF.FlattenException(e)); DebugOutput.PrintLn("You may want to consider discarding this sessions' changes as relinking was not able to properly finish."); linkFailedDueToError = e.Message; } if (crossImport != null) { //cache item. Imports are stored +1, Exports-1. Someday I will go back and make this just 0 indexed crossPCCObjectMappingList.Add(new KeyValuePair <int, int>(sourceObjReference, crossImport.UIndex + 1)); //add to mapping to speed up future relinks objProperty.Value = crossImport.UIndex; Debug.WriteLine("Relink hit: Dynamic CrossImport for " + origvalue + " " + importingPCC.getEntry(origvalue).GetFullPath + " -> " + objProperty.Value); } else { if (linkFailedDueToError != null) { Debug.WriteLine("Relink failed: CrossImport porting failed for " + objProperty.Name + " " + objProperty.Value + ": " + importingPCC.getEntry(origvalue).GetFullPath); return("Relink failed for " + objProperty.Name + " " + objProperty.Value + ": " + linkFailedDueToError); } else if (destinationPCC.getEntry(objProperty.Value) != null) { Debug.WriteLine("Relink failed: CrossImport porting failed for " + objProperty.Name + " " + objProperty.Value + ": " + importingPCC.getEntry(origvalue).GetFullPath); return("Relink failed: CrossImport porting failed for " + objProperty.Name + " " + objProperty.Value + " " + destinationPCC.getEntry(objProperty.Value).GetFullPath); } else { return("Relink failed: New export does not exist - this is probably a bug in cross import code for " + objProperty.Name + " " + objProperty.Value); } } } } else { string path = importingPCC.getEntry(objProperty.Value) != null?importingPCC.getEntry(objProperty.Value).GetFullPath : "Entry not found: " + objProperty.Value; Debug.WriteLine("Relink failed: " + objProperty.Name + " " + objProperty.Value + " " + path); return("Relink failed: " + objProperty.Name + " " + objProperty.Value + " " + path); } return(null); }
public static void WriteStringRefProperty(this Stream stream, IMEPackage pcc, string propName, int value) { stream.WritePropHeader(pcc, propName, PropertyType.StringRefProperty, 4); stream.WriteValueS32(value); }
public override void WriteTo(Stream ms, IMEPackage pcc, int fileOffset) { ms.WriteFromBuffer(data); }
public static void WriteStructPropVector(this Stream stream, IMEPackage pcc, string propName, float x, float y, float z) { MemoryStream m = new MemoryStream(12); m.WriteValueF32(x); m.WriteValueF32(y); m.WriteValueF32(z); stream.WriteStructProperty(pcc, propName, "Vector", m.ToArray()); }
public override byte[] ToArray(IMEPackage pcc, int fileOffset = 0) { return(data); }
public static string PropertyToText(Property p, IMEPackage pcc) { string s = ""; s = "Name: " + pcc.getNameEntry(p.Name); s += " Type: " + TypeToString((int)p.TypeVal); s += " Size: " + p.Size; switch (p.TypeVal) { case PropertyType.StructProperty: s += " \"" + pcc.getNameEntry (p.Value.IntValue) + "\" with " + p.Value.Array.Count + " bytes"; break; case PropertyType.IntProperty: case PropertyType.ObjectProperty: case PropertyType.StringRefProperty : s += " Value: " + p.Value.IntValue; break; case PropertyType.BoolProperty: s += " Value: " + (p.raw[24] == 1); break; case PropertyType.FloatProperty: s += " Value: " + p.Value.FloatValue; break; case PropertyType.NameProperty: s += " " + pcc.getNameEntry(p.Value.IntValue); break; case PropertyType.ByteProperty: s += " Value: \"" + p.Value.StringValue + "\" with \"" + pcc.getNameEntry(p.Value.IntValue) + "\""; break; case PropertyType.ArrayProperty: s += " bytes"; //Value: " + p.Value.Array.Count.ToString() + " Elements"; break; case PropertyType.StrProperty: if (p.Value.StringValue.Length == 0) break; s += " Value: " + p.Value.StringValue; break; } return s; }
public static void propGridPropertyValueChanged(PropertyValueChangedEventArgs e, int n, IMEPackage pcc) { string name = e.ChangedItem.Label; GridItem parent = e.ChangedItem.Parent; //if (parent != null) name = parent.Label; if (parent.Label == "data") { GridItem parent2 = parent.Parent; if (parent2 != null) { name = parent2.Label; } } Type parentVal = null; if (parent.Value != null) { parentVal = parent.Value.GetType(); } if (name == "nameindex" || name == "index" || parentVal == typeof(ColorProp) || parentVal == typeof(VectorProp) || parentVal == typeof(Unreal.RotatorProp) || parentVal == typeof(Unreal.LinearColorProp)) { name = parent.Label; } IExportEntry ent = pcc.getExport(n); byte[] data = ent.Data; List <PropertyReader.Property> p = PropertyReader.getPropList(ent); int m = -1; for (int i = 0; i < p.Count; i++) { if (pcc.getNameEntry(p[i].Name) == name) { m = i; } } if (m == -1) { return; } byte[] buff2; switch (p[m].TypeVal) { case PropertyType.BoolProperty: byte res = 0; if ((bool)e.ChangedItem.Value == true) { res = 1; } data[p[m].offsetval] = res; break; case PropertyType.FloatProperty: buff2 = BitConverter.GetBytes((float)e.ChangedItem.Value); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } break; case PropertyType.IntProperty: case PropertyType.StringRefProperty: int newv = Convert.ToInt32(e.ChangedItem.Value); int oldv = Convert.ToInt32(e.OldValue); buff2 = BitConverter.GetBytes(newv); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } break; case PropertyType.StrProperty: string s = Convert.ToString(e.ChangedItem.Value); int stringMultiplier = 1; int oldLength = BitConverter.ToInt32(data, p[m].offsetval); if (oldLength < 0) { stringMultiplier = 2; oldLength *= -2; } int oldSize = 4 + oldLength; List <byte> stringBuff = new List <byte>(s.Length * stringMultiplier); if (stringMultiplier == 2) { for (int j = 0; j < s.Length; j++) { stringBuff.AddRange(BitConverter.GetBytes(s[j])); } stringBuff.Add(0); } else { for (int j = 0; j < s.Length; j++) { stringBuff.Add(BitConverter.GetBytes(s[j])[0]); } } stringBuff.Add(0); buff2 = BitConverter.GetBytes((s.Length + 1) * stringMultiplier + 4); for (int j = 0; j < 4; j++) { data[p[m].offsetval - 8 + j] = buff2[j]; } buff2 = BitConverter.GetBytes((s.Length + 1) * stringMultiplier == 1 ? 1 : -1); for (int j = 0; j < 4; j++) { data[p[m].offsetval + j] = buff2[j]; } buff2 = new byte[data.Length - oldLength + stringBuff.Count]; int startLength = p[m].offsetval + 4; int startLength2 = startLength + oldLength; for (int i = 0; i < startLength; i++) { buff2[i] = data[i]; } for (int i = 0; i < stringBuff.Count; i++) { buff2[i + startLength] = stringBuff[i]; } startLength += stringBuff.Count; for (int i = 0; i < data.Length - startLength2; i++) { buff2[i + startLength] = data[i + startLength2]; } data = buff2; break; case PropertyType.StructProperty: if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(ColorProp)) { switch (e.ChangedItem.Label) { case "Alpha": data[p[m].offsetval + 11] = Convert.ToByte(e.ChangedItem.Value); break; case "Red": data[p[m].offsetval + 10] = Convert.ToByte(e.ChangedItem.Value); break; case "Green": data[p[m].offsetval + 9] = Convert.ToByte(e.ChangedItem.Value); break; case "Blue": data[p[m].offsetval + 8] = Convert.ToByte(e.ChangedItem.Value); break; default: break; } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(VectorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "X": offset = 8; break; case "Y": offset = 12; break; case "Z": offset = 16; break; default: break; } if (offset != 0) { buff2 = BitConverter.GetBytes(Convert.ToSingle(e.ChangedItem.Value)); for (int i = 0; i < 4; i++) { data[p[m].offsetval + offset + i] = buff2[i]; } } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(Unreal.RotatorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "Pitch": offset = 8; break; case "Yaw": offset = 12; break; case "Roll": offset = 16; break; default: break; } if (offset != 0) { int val = Convert.ToSingle(e.ChangedItem.Value).ToUnrealRotationUnits(); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + offset + i] = buff2[i]; } } } else if (e.ChangedItem.Label != "nameindex" && parentVal == typeof(Unreal.LinearColorProp)) { int offset = 0; switch (e.ChangedItem.Label) { case "Red": offset = 8; break; case "Green": offset = 12; break; case "Blue": offset = 16; break; case "Alpha": offset = 20; break; default: break; } if (offset != 0) { buff2 = BitConverter.GetBytes(Convert.ToSingle(e.ChangedItem.Value)); for (int i = 0; i < 4; i++) { data[p[m].offsetval + offset + i] = buff2[i]; } } } else if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); if (e.ChangedItem.Label == "nameindex") { int val1 = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val1); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } } else { string sidx = e.ChangedItem.Label.Replace("[", ""); sidx = sidx.Replace("]", ""); int index = Convert.ToInt32(sidx); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i + index * 4 + 8] = buff2[i]; } } } break; case PropertyType.ByteProperty: case PropertyType.NameProperty: if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } } break; case PropertyType.ObjectProperty: if (e.ChangedItem.Value is int) { int val = Convert.ToInt32(e.ChangedItem.Value); buff2 = BitConverter.GetBytes(val); for (int i = 0; i < 4; i++) { data[p[m].offsetval + i] = buff2[i]; } } break; default: return; } ent.Data = data; }
public static List<List<Property>> ReadStructArrayProp(IMEPackage pcc, Property p) { List<List<Property>> res = new List<List<Property>>(); int pos = 28; int linkCount = BitConverter.ToInt32(p.raw, 24); for (int i = 0; i < linkCount; i++) { List<Property> p2 = ReadProp(pcc, p.raw, pos); for (int j = 0; j < p2.Count(); j++) { pos += p2[j].raw.Length; } res.Add(p2); } return res; }
public static Dictionary <IEntry, List <string> > FindUsagesOfName(this IMEPackage pcc, string name) { var result = new Dictionary <IEntry, List <string> >(); foreach (ExportEntry exp in pcc.Exports) { try { //find header references if (exp.ObjectName.Name == name) { result.AddToListAt(exp, "Header: Object Name"); } if (exp.HasComponentMap && exp.ComponentMap.Any(kvp => kvp.Key.Name == name)) { result.AddToListAt(exp, "Header: ComponentMap"); } if ((!exp.IsDefaultObject && exp.IsOrInheritsFrom("Component") || pcc.Game == MEGame.UDK && exp.ClassName.EndsWith("Component")) && exp.ParentFullPath.Contains("Default__") && exp.DataSize >= 12 && BitConverter.ToInt32(exp.Data, 4) is int nameIdx && pcc.IsName(nameIdx) && pcc.GetNameEntry(nameIdx) == name) { result.AddToListAt(exp, "Component TemplateName (0x4)"); } //find property references findPropertyReferences(exp.GetProperties(), exp, false, "Property: "); //find binary references if (!exp.IsDefaultObject && ObjectBinary.From(exp) is { } objBin) { if (objBin is BioStage bioStage) { if (bioStage.length > 0 && name == "m_aCameraList") { result.AddToListAt(exp, "(Binary prop: m_aCameraList name)"); } int i = 0; foreach ((NameReference key, PropertyCollection props) in bioStage.CameraList) { if (key.Name == name) { result.AddToListAt(exp, $"(Binary prop: m_aCameraList[{i}])"); } findPropertyReferences(props, exp, false, "Binary prop: m_aCameraList[{i}]."); ++i; } } else if (objBin is UScriptStruct scriptStruct) { findPropertyReferences(scriptStruct.Defaults, exp, false, "Binary Property:"); } else { List <(NameReference, string)> names = objBin.GetNames(exp.FileRef.Game); foreach ((NameReference nameRef, string propName) in names) { if (nameRef.Name == name) { result.AddToListAt(exp, $"(Binary prop: {propName})"); } } } } } catch { result.AddToListAt(exp, "Exception occured while reading this export!"); } } foreach (ImportEntry import in pcc.Imports) { try { if (import.ObjectName.Name == name) { result.AddToListAt(import, "ObjectName"); } if (import.PackageFile == name) { result.AddToListAt(import, "PackageFile"); } if (import.ClassName == name) { result.AddToListAt(import, "Class"); } } catch (Exception e) { result.AddToListAt(import, "Exception occured while reading this import!"); } } return(result); void findPropertyReferences(PropertyCollection props, ExportEntry exp, bool isInImmutable = false, string prefix = "") { foreach (UProperty prop in props) { if (!isInImmutable && prop.Name.Name == name) { result.AddToListAt(exp, $"{prefix}{prop.Name} name"); } switch (prop) { case NameProperty nameProperty: if (nameProperty.Value.Name == name) { result.AddToListAt(exp, $"{prefix}{nameProperty.Name} value"); } break; case DelegateProperty delegateProperty: if (delegateProperty.Value.FunctionName.Name == name) { result.AddToListAt(exp, $"{prefix}{delegateProperty.Name} function name"); } break; case EnumProperty enumProperty: if (pcc.Game >= MEGame.ME3 && !isInImmutable && enumProperty.EnumType.Name == name) { result.AddToListAt(exp, $"{prefix}{enumProperty.Name} enum type"); } if (enumProperty.Value.Name == name) { result.AddToListAt(exp, $"{prefix}{enumProperty.Name} enum value"); } break; case StructProperty structProperty: if (!isInImmutable && structProperty.StructType == name) { result.AddToListAt(exp, $"{prefix}{structProperty.Name} struct type"); } findPropertyReferences(structProperty.Properties, exp, structProperty.IsImmutable, $"{prefix}{structProperty.Name}: "); break; case ArrayProperty <NameProperty> arrayProperty: for (int i = 0; i < arrayProperty.Count; i++) { NameProperty nameProp = arrayProperty[i]; if (nameProp.Value.Name == name) { result.AddToListAt(exp, $"{prefix}{arrayProperty.Name}[{i}]"); } } break; case ArrayProperty <EnumProperty> arrayProperty: for (int i = 0; i < arrayProperty.Count; i++) { EnumProperty enumProp = arrayProperty[i]; if (enumProp.Value.Name == name) { result.AddToListAt(exp, $"{prefix}{arrayProperty.Name}[{i}]"); } } break; case ArrayProperty <StructProperty> arrayProperty: for (int i = 0; i < arrayProperty.Count; i++) { StructProperty structProp = arrayProperty[i]; findPropertyReferences(structProp.Properties, exp, structProp.IsImmutable, $"{prefix}{arrayProperty.Name}[{i}]."); } break; } } } }
static PropertyType getType(IMEPackage pcc, int type) { switch (pcc.getNameEntry(type)) { case "None": return PropertyType.None; case "StructProperty": return PropertyType.StructProperty; case "IntProperty": return PropertyType.IntProperty; case "FloatProperty": return PropertyType.FloatProperty; case "ObjectProperty": return PropertyType.ObjectProperty; case "NameProperty": return PropertyType.NameProperty; case "BoolProperty": return PropertyType.BoolProperty; case "ByteProperty": return PropertyType.ByteProperty; case "ArrayProperty": return PropertyType.ArrayProperty; case "DelegateProperty": return PropertyType.DelegateProperty; case "StrProperty": return PropertyType.StrProperty; case "StringRefProperty": return PropertyType.StringRefProperty; default: return PropertyType.Unknown; } }
public PathNode_Dynamic(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { shape.Brush = dynamicPathnodefindingNodeBrush; }
public static int detectStart(IMEPackage pcc, byte[] raw, ulong flags) { if ((flags & (ulong)UnrealFlags.EObjectFlags.HasStack) != 0) { if (pcc.Game != MEGame.ME3) { return 32; } return 30; } int result = 8; int test1 = BitConverter.ToInt32(raw, 4); int test2 = BitConverter.ToInt32(raw, 8); if (pcc.isName(test1) && test2 == 0) result = 4; if (pcc.isName(test1) && pcc.isName(test2) && test2 != 0) result = 8; return result; }
public CoverLink(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { }
private bool importTree(TreeNode sourceNode, IMEPackage importpcc, int n) { int nextIndex; int index; foreach (TreeNode node in sourceNode.Nodes) { index = Convert.ToInt32(node.Name); if (index >= 0) { if (!importExport(importpcc, index, n)) { return false; } nextIndex = pcc.ExportCount; } else { importImport(importpcc, -index - 1, n); nextIndex = -pcc.ImportCount; } if (node.Nodes.Count > 0) { if (!importTree(node, importpcc, nextIndex)) { return false; } } } return true; }
public SFXNav_JumpDownNode(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { }
private bool importExport(IMEPackage importpcc, int n, int link) { IExportEntry ex = importpcc.getExport(n); IExportEntry nex = null; switch (pcc.Game) { case MEGame.ME1: nex = new ME1ExportEntry(pcc as ME1Package); break; case MEGame.ME2: nex = new ME2ExportEntry(pcc as ME2Package); break; case MEGame.ME3: nex = new ME3ExportEntry(pcc as ME3Package); break; } byte[] idata = ex.Data; PropertyCollection props = ex.GetProperties(); int start = ex.GetPropertyStart(); int end = props.endOffset; MemoryStream res = new MemoryStream(); if ((importpcc.getExport(n).ObjectFlags & (ulong)UnrealFlags.EObjectFlags.HasStack) != 0) { byte[] stackdummy = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //Lets hope for the best :D 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,}; if (pcc.Game != MEGame.ME3) { stackdummy = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,}; } res.Write(stackdummy, 0, stackdummy.Length); } else { res.Write(new byte[start], 0, start); } //store copy of names list in case something goes wrong List<string> names = pcc.Names.ToList(); try { props.WriteTo(res, pcc); } catch (Exception exception) { //restore namelist pcc.setNames(names); MessageBox.Show("Error occured while trying to import " + ex.ObjectName + " : " + exception.Message); return false; } if (importpcc.Game == MEGame.ME3 && importpcc.getObjectName(ex.idxClass) == "SkeletalMesh") { SkeletalMesh skl = new SkeletalMesh(importpcc as ME3Package, n); SkeletalMesh.BoneStruct bone; for (int i = 0; i < skl.Bones.Count; i++) { bone = skl.Bones[i]; string s = importpcc.getNameEntry(bone.Name); bone.Name = pcc.FindNameOrAdd(s); skl.Bones[i] = bone; } SkeletalMesh.TailNamesStruct tailName; for (int i = 0; i < skl.TailNames.Count; i++) { tailName = skl.TailNames[i]; string s = importpcc.getNameEntry(tailName.Name); tailName.Name = pcc.FindNameOrAdd(s); skl.TailNames[i] = tailName; } SerializingContainer container = new SerializingContainer(res); container.isLoading = false; skl.Serialize(container); } else { res.Write(idata, end, idata.Length - end); } nex.setHeader((byte[])ex.header.Clone()); nex.Data = res.ToArray(); nex.idxObjectName = pcc.FindNameOrAdd(importpcc.getNameEntry(ex.idxObjectName)); nex.idxLink = link; nex.idxArchtype = nex.idxClass = nex.idxClassParent = 0; pcc.addExport(nex); return true; }
public SFXNav_LeapNodeHumanoid(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { }
public SAction(int idx, float x, float y, IMEPackage p) : base(idx, p) { GetVarLinks(); GetOutputLinks(); originalX = x; originalY = y; }
public PendingNode(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { }
public SFrame(int idx, float x, float y, IMEPackage p, GraphEditor grapheditor) : base(idx, p, grapheditor) { string s = export.ObjectName; float w = 0; float h = 0; var props = export.GetProperties(); foreach (var prop in props) { if (prop.Name == "SizeX") { w = (prop as IntProperty); } if (prop.Name == "SizeY") { h = (prop as IntProperty); } } MakeTitleBox(s); shape = PPath.CreateRectangle(0, -titleBox.Height, w, h + titleBox.Height); outlinePen = new Pen(Color.Black); shape.Pen = outlinePen; shape.Brush = new SolidBrush(Color.Transparent); shape.Pickable = false; this.AddChild(shape); titleBox.TranslateBy(0, -titleBox.Height); this.AddChild(titleBox); comment.Y -= titleBox.Height; this.Bounds = new RectangleF(0, -titleBox.Height, titleBox.Width, titleBox.Height); this.TranslateBy(x, y); }
public SFXDynamicCoverSlotMarker(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { shape.Brush = dynamicPathfindingNodeBrush; }
protected SBox(int idx, IMEPackage p) : base(idx, p) { }
public MantleMarker(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { }
public SEvent(int idx, float x, float y, IMEPackage p, GraphEditor grapheditor) : base(idx, p, grapheditor) { outlinePen = new Pen(Color.FromArgb(214, 30, 28)); string s = export.ObjectName; s = s.Replace("BioSeqEvt_", ""); s = s.Replace("SFXSeqEvt_", ""); s = s.Replace("SeqEvt_", ""); s = s.Replace("SeqEvent_", ""); float starty = 0; float w = 15; float midW = 0; varLinkBox = new PPath(); GetVarLinks(); for (int i = 0; i < Varlinks.Count; i++) { string d = ""; foreach (int l in Varlinks[i].Links) d = d + "#" + l + ","; d = d.Remove(d.Length - 1); SText t2 = new SText( d + "\n" + Varlinks[i].Desc); t2.X = w; t2.Y = 0; w += t2.Width + 20; t2.Pickable = false; Varlinks[i].node.TranslateBy(t2.X + t2.Width / 2, t2.Y + t2.Height); t2.AddChild(Varlinks[i].node); varLinkBox.AddChild(t2); } if(Varlinks.Count != 0) varLinkBox.AddRectangle(0, 0, w, varLinkBox[0].Height); varLinkBox.Pickable = false; varLinkBox.Pen = outlinePen; varLinkBox.Brush = nodeBrush; GetOutputLinks(); outLinkBox = new PPath(); for (int i = 0; i < Outlinks.Count(); i++) { SText t2 = new SText(Outlinks[i].Desc); if(t2.Width + 10 > midW) midW = t2.Width + 10; //t2.TextAlignment = StringAlignment.Far; //t2.ConstrainWidthToTextWidth = false; t2.X = 0 - t2.Width; t2.Y = starty + 3; starty += t2.Height + 6; t2.Pickable = false; Outlinks[i].node.TranslateBy(0, t2.Y + t2.Height / 2); t2.AddChild(Outlinks[i].node); outLinkBox.AddChild(t2); } outLinkBox.AddPolygon(new PointF[] { new PointF(0, 0), new PointF(0, starty), new PointF(-0.5f*midW, starty+30), new PointF(0 - midW, starty), new PointF(0 - midW, 0), new PointF(midW/-2, -30) }); outLinkBox.Pickable = false; outLinkBox.Pen = outlinePen; outLinkBox.Brush = nodeBrush; var props = export.GetProperties(); foreach (var prop in props) { if (prop.Name.Name.Contains("EventName") || prop.Name == "sScriptName") s += "\n\"" + (prop as NameProperty) + "\""; else if (prop.Name == "InputLabel" || prop.Name == "sEvent") s += "\n\"" + (prop as StrProperty) + "\""; } float tW = GetTitleBox(s, w); if (tW > w) { if (midW > tW) { w = midW; titleBox.Width = w; } else { w = tW; } varLinkBox.Width = w; } float h = titleBox.Height + 1; outLinkBox.TranslateBy(titleBox.Width/2 + midW/2, h + 30); h += outLinkBox.Height + 1; varLinkBox.TranslateBy(0, h); h += varLinkBox.Height; this.bounds = new RectangleF(0, 0, w, h); this.AddChild(titleBox); this.AddChild(varLinkBox); this.AddChild(outLinkBox); this.TranslateBy(x, y); }
}; //Bottom part of H public SFXNav_HarvesterMoveNode(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { }
public TreeNode FindSequences(IMEPackage pcc, int index, bool wantFullName = false) { TreeNode ret = new TreeNode("#" + index + ": " + (wantFullName ? pcc.getExport(index).GetFullPath : pcc.getExport(index).ObjectName)); ret.Name = index.ToString(); var seqObjs = pcc.getExport(index).GetProperty<ArrayProperty<ObjectProperty>>("SequenceObjects"); if (seqObjs != null) { IExportEntry exportEntry; foreach (ObjectProperty seqObj in seqObjs) { exportEntry = pcc.getExport(seqObj.Value - 1); if (exportEntry.ClassName == "Sequence" || exportEntry.ClassName.StartsWith("PrefabSequence")) { TreeNode t = FindSequences(pcc, seqObj.Value - 1, false); ret.Nodes.Add(t); } else if (exportEntry.ClassName == "SequenceReference") { var propSequenceReference = exportEntry.GetProperty<ObjectProperty>("oSequenceReference"); if (propSequenceReference != null) { TreeNode t = FindSequences(pcc, propSequenceReference.Value - 1, false); ret.Nodes.Add(t); } } } } return ret; }
public SFXNav_LargeMantleNode(int idx, float x, float y, IMEPackage p, PathingGraphEditor grapheditor) : base(idx, x, y, p, grapheditor) { }
public static void WriteArrayProperty(this Stream stream, IMEPackage pcc, string propName, int count, MemoryStream value) { stream.WritePropHeader(pcc, propName, PropertyType.ArrayProperty, 4 + (int)value.Length); stream.WriteValueS32(count); stream.WriteStream(value); }
public static PropertyCollection getDefaultStructValue(string className, bool stripTransients) { bool isImmutable = UnrealObjectInfo.IsImmutable(className, MEGame.ME1); if (Structs.ContainsKey(className)) { ClassInfo info = Structs[className]; try { PropertyCollection structProps = new PropertyCollection(); ClassInfo tempInfo = info; while (tempInfo != null) { foreach ((string propName, PropertyInfo propInfo) in tempInfo.properties) { if (stripTransients && propInfo.Transient) { continue; } if (getDefaultProperty(propName, propInfo, stripTransients, isImmutable) is Property uProp) { structProps.Add(uProp); } } if (!Structs.TryGetValue(tempInfo.baseClass, out tempInfo)) { tempInfo = null; } } structProps.Add(new NoneProperty()); string filepath = null; if (ME1Directory.BioGamePath != null) { filepath = Path.Combine(ME1Directory.BioGamePath, info.pccPath); } Stream loadStream = null; if (File.Exists(info.pccPath)) //dynamic lookup (relative path) { filepath = info.pccPath; loadStream = new MemoryStream(File.ReadAllBytes(info.pccPath)); } else if (info.pccPath == UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName) { filepath = "GAMERESOURCES_ME1"; //used for cache loadStream = Utilities.LoadFileFromCompressedResource("GameResources.zip", CoreLib.CustomResourceFileName(MEGame.ME1)); // should this be ME3 (it was originally before corelib move) } else if (filepath != null && File.Exists(filepath)) { loadStream = new MemoryStream(File.ReadAllBytes(filepath)); } #if AZURE else if (MiniGameFilesPath != null && File.Exists(Path.Combine(MiniGameFilesPath, info.pccPath))) { filepath = Path.Combine(MiniGameFilesPath, info.pccPath); // Load from test minigame folder. This is only really useful on azure where we don't have access to // games loadStream = new MemoryStream(File.ReadAllBytes(filepath)); } #endif if (loadStream == null) { filepath = Path.Combine(ME1Directory.DefaultGamePath, info.pccPath); //for files from ME1 DLC if (File.Exists(filepath)) { loadStream = new MemoryStream(File.ReadAllBytes(filepath)); } } if (loadStream != null) { using (IMEPackage importPCC = MEPackageHandler.OpenMEPackageFromStream(loadStream, filepath, useSharedPackageCache: true)) { var exportToRead = importPCC.GetUExport(info.exportIndex); byte[] buff = exportToRead.Data.Skip(0x30).ToArray(); PropertyCollection defaults = PropertyCollection.ReadProps(exportToRead, new MemoryStream(buff), className); foreach (var prop in defaults) { structProps.TryReplaceProp(prop); } } } return(structProps); } catch { return(null); } } return(null); }