/// <summary> /// Gets the type of an array /// </summary> /// <param name="game">What game we are looking info for</param> /// <param name="propName">Name of the array property</param> /// <param name="className">Name of the class that should contain the information. If contained in a struct, this will be the name of the struct type</param> /// <param name="parsingEntry">Entry that is being parsed. Used for dynamic lookup if it's not in the DB</param> /// <returns></returns> public static ArrayType GetArrayType(Mod.MEGame game, string propName, string className, IEntry parsingEntry = null) { switch (game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.getArrayType(className, propName, export: parsingEntry as ExportEntry)); case Mod.MEGame.ME2: var res2 = ME2UnrealObjectInfo.getArrayType(className, propName, export: parsingEntry as ExportEntry); #if DEBUG //For debugging only! if (res2 == ArrayType.Int && ME2UnrealObjectInfo.ArrayTypeLookupJustFailed) { ME2UnrealObjectInfo.ArrayTypeLookupJustFailed = false; Debug.WriteLine("[ME2] Array type lookup failed for " + propName + " in class " + className + " in export " + parsingEntry.FileRef.GetEntryString(parsingEntry.UIndex)); } #endif return(res2); case Mod.MEGame.ME3: var res = ME3UnrealObjectInfo.getArrayType(className, propName, export: parsingEntry as ExportEntry); #if DEBUG //For debugging only! if (res == ArrayType.Int && ME3UnrealObjectInfo.ArrayTypeLookupJustFailed) { Debug.WriteLine("[ME3] Array type lookup failed for " + propName + " in class " + className + " in export " + parsingEntry.FileRef.GetEntryString(parsingEntry.UIndex)); ME3UnrealObjectInfo.ArrayTypeLookupJustFailed = false; } #endif return(res); } return(ArrayType.Int); }
/// <summary> /// Gets property information for a property by name & containing class or struct name /// </summary> /// <param name="game">Game to lookup informatino from</param> /// <param name="propname">Name of property information to look up</param> /// <param name="containingClassOrStructName">Name of containing class or struct name</param> /// <param name="nonVanillaClassInfo">Dynamically built property info</param> /// <returns></returns> public static PropertyInfo GetPropertyInfo(MEGame game, string propname, string containingClassOrStructName, ClassInfo nonVanillaClassInfo = null) { bool inStruct = false; PropertyInfo p = null; switch (game) { case MEGame.ME1: p = ME1UnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct, nonVanillaClassInfo); break; case MEGame.ME2: p = ME2UnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct, nonVanillaClassInfo); break; case MEGame.ME3: case MEGame.UDK: p = ME3UnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct, nonVanillaClassInfo); if (p == null && game == MEGame.UDK) { p = UDKUnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct, nonVanillaClassInfo); } break; } if (p == null) { inStruct = true; switch (game) { case MEGame.ME1: p = ME1UnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct); break; case MEGame.ME2: p = ME2UnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct); break; case MEGame.ME3: p = ME3UnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct); break; case MEGame.UDK: p = ME3UnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct); if (p == null && game == MEGame.UDK) { p = UDKUnrealObjectInfo.getPropertyInfo(containingClassOrStructName, propname, inStruct, nonVanillaClassInfo); } break; } } return(p); }
public static string GetEnumType(MEGame game, string propName, string typeName) { switch (game) { case MEGame.ME1: return(ME1UnrealObjectInfo.getEnumTypefromProp(typeName, propName)); case MEGame.ME2: return(ME2UnrealObjectInfo.getEnumTypefromProp(typeName, propName)); case MEGame.ME3: return(ME3UnrealObjectInfo.getEnumTypefromProp(typeName, propName)); } return(null); }
public static ArrayType GetArrayType(MEGame game, string propName, string typeName) { switch (game) { case MEGame.ME1: return(ME1UnrealObjectInfo.getArrayType(typeName, propName)); case MEGame.ME2: return(ME2UnrealObjectInfo.getArrayType(typeName, propName)); case MEGame.ME3: return(ME3UnrealObjectInfo.getArrayType(typeName, propName)); } return(ArrayType.Int); }
public static List <NameReference> GetEnumValues(Mod.MEGame game, string enumName, bool includeNone = false) { switch (game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.getEnumValues(enumName, includeNone)); case Mod.MEGame.ME2: return(ME2UnrealObjectInfo.getEnumValues(enumName, includeNone)); case Mod.MEGame.ME3: return(ME3UnrealObjectInfo.getEnumValues(enumName, includeNone)); } return(null); }
/// <summary> /// Gets the default values for a struct /// </summary> /// <param name="game">Game to pull info from</param> /// <param name="typeName">Struct type name</param> /// <param name="stripTransients">Strip transients from the struct</param> /// <returns></returns> internal static PropertyCollection getDefaultStructValue(Mod.MEGame game, string typeName, bool stripTransients) { switch (game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.getDefaultStructValue(typeName, stripTransients)); case Mod.MEGame.ME2: return(ME2UnrealObjectInfo.getDefaultStructValue(typeName, stripTransients)); case Mod.MEGame.ME3: return(ME3UnrealObjectInfo.getDefaultStructValue(typeName, stripTransients)); } return(null); }
public static ClassInfo generateClassInfo(ExportEntry export, bool isStruct = false) { switch (export.FileRef.Game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.generateClassInfo(export, isStruct)); case Mod.MEGame.ME2: return(ME2UnrealObjectInfo.generateClassInfo(export, isStruct)); case Mod.MEGame.ME3: return(ME3UnrealObjectInfo.generateClassInfo(export, isStruct)); } return(null); }
public static string GetEnumType(Mod.MEGame game, string propName, string typeName, ClassInfo nonVanillaClassInfo = null) { switch (game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.getEnumTypefromProp(typeName, propName, nonVanillaClassInfo: nonVanillaClassInfo)); case Mod.MEGame.ME2: return(ME2UnrealObjectInfo.getEnumTypefromProp(typeName, propName, nonVanillaClassInfo: nonVanillaClassInfo)); case Mod.MEGame.ME3: var enumType = ME3UnrealObjectInfo.getEnumTypefromProp(typeName, propName); return(enumType); } return(null); }
public static UProperty getDefaultProperty(Mod.MEGame game, string propName, PropertyInfo propInfo, bool stripTransients = true, bool isImmutable = false) { switch (game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.getDefaultProperty(propName, propInfo, stripTransients, isImmutable)); case Mod.MEGame.ME2: return(ME2UnrealObjectInfo.getDefaultProperty(propName, propInfo, stripTransients, isImmutable)); case Mod.MEGame.ME3: return(ME3UnrealObjectInfo.getDefaultProperty(propName, propInfo, stripTransients, isImmutable)); } return(null); }
public static bool inheritsFrom(this IExportEntry entry, string baseClass) { if (entry.FileRef.Game == MEGame.ME1) { return(ME1UnrealObjectInfo.inheritsFrom(entry as ME1ExportEntry, baseClass)); } else if (entry.FileRef.Game == MEGame.ME2) { return(ME2UnrealObjectInfo.inheritsFrom(entry as ME2ExportEntry, baseClass)); } else if (entry.FileRef.Game == MEGame.ME3) { return(ME3UnrealObjectInfo.inheritsFrom(entry as ME3ExportEntry, baseClass)); } return(false); }
public static bool InheritsFrom(this IEntry entry, string baseClass) { switch (entry.FileRef.Game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.InheritsFrom(entry.ClassName, baseClass)); case Mod.MEGame.ME2: return(ME2UnrealObjectInfo.InheritsFrom(entry.ClassName, baseClass)); case Mod.MEGame.ME3: return(ME3UnrealObjectInfo.InheritsFrom(entry.ClassName, baseClass)); default: return(false); } }
public static bool IsImmutable(string structType, Mod.MEGame game) { switch (game) { case Mod.MEGame.ME1: return(ME1UnrealObjectInfo.IsImmutableStruct(structType)); case Mod.MEGame.ME2: return(ME2UnrealObjectInfo.IsImmutableStruct(structType)); case Mod.MEGame.ME3: return(ME3UnrealObjectInfo.IsImmutableStruct(structType)); default: return(false); } }
public static void loadfromJSON() { if (!loaded) { try { var blob = JsonConvert.DeserializeAnonymousType(ME3UnrealObjectInfo.LoadEmbeddedJSONText(MEGame.ME3), new { Classes, Structs, Enums }); Classes = blob.Classes; Structs = blob.Structs; Enums = blob.Enums; loaded = true; } catch (Exception e) { } } }
public static bool inheritsFrom(this IEntry entry, string baseClass) { switch (entry.FileRef.Game) { case MEGame.ME1: return(ME1UnrealObjectInfo.inheritsFrom(entry, baseClass)); case MEGame.ME2: return(ME2UnrealObjectInfo.inheritsFrom(entry, baseClass)); case MEGame.ME3: case MEGame.UDK: //use me3? return(ME3UnrealObjectInfo.inheritsFrom(entry, baseClass)); default: return(false); } }
public static ArrayType getArrayType(string className, string propName, bool inStruct = false, IExportEntry export = null) { PropertyInfo p = getPropertyInfo(className, propName, inStruct); if (p == null) { p = getPropertyInfo(className, propName, !inStruct); } if (p == null && export != null && export.ClassName != "Class" && export.idxClass > 0) { export = export.FileRef.Exports[export.idxClass - 1]; //make sure you get actual class ClassInfo currentInfo; switch (export.FileRef.Game) { case MEGame.ME1: currentInfo = ME1Explorer.Unreal.ME1UnrealObjectInfo.generateClassInfo(export); break; case MEGame.ME2: currentInfo = ME2Explorer.Unreal.ME2UnrealObjectInfo.generateClassInfo(export); break; case MEGame.ME3: default: currentInfo = ME3UnrealObjectInfo.generateClassInfo(export); break; } currentInfo.baseClass = export.ClassParent; p = getPropertyInfo(className, propName, inStruct, currentInfo); if (p == null) { p = getPropertyInfo(className, propName, !inStruct, currentInfo); } if (p == null) { //getting property info failed return(ArrayType.Int); } } return(getArrayType(p)); }
public static PropertyInfo GetPropertyInfo(MEGame game, string propname, string typeName) { bool inStruct = false; PropertyInfo p = null; switch (game) { case MEGame.ME1: p = ME1UnrealObjectInfo.getPropertyInfo(typeName, propname, inStruct); break; case MEGame.ME2: p = ME2UnrealObjectInfo.getPropertyInfo(typeName, propname, inStruct); break; case MEGame.ME3: p = ME3UnrealObjectInfo.getPropertyInfo(typeName, propname, inStruct); break; } if (p == null) { inStruct = true; switch (game) { case MEGame.ME1: p = ME1UnrealObjectInfo.getPropertyInfo(typeName, propname, inStruct); break; case MEGame.ME2: p = ME2UnrealObjectInfo.getPropertyInfo(typeName, propname, inStruct); break; case MEGame.ME3: p = ME3UnrealObjectInfo.getPropertyInfo(typeName, propname, inStruct); break; } } return(p); }
public static PropertyCollection ReadSpecialStruct(IMEPackage pcc, MemoryStream stream, string structType, int size) { PropertyCollection props = new PropertyCollection(); if (pcc.Game == MEGame.ME3) { if (ME3UnrealObjectInfo.Structs.ContainsKey(structType)) { PropertyCollection defaultProps; //memoize if (defaultStructValues.ContainsKey(structType)) { defaultProps = defaultStructValues[structType]; } else { defaultProps = ME3UnrealObjectInfo.getDefaultStructValue(structType); if (defaultProps == null) { props.Add(new UnknownProperty(stream, size)); return(props); } defaultStructValues.Add(structType, defaultProps); } for (int i = 0; i < defaultProps.Count; i++) { UProperty uProperty = ReadSpecialStructProp(pcc, stream, defaultProps[i], structType); if (uProperty.PropType != PropertyType.None) { props.Add(uProperty); } } return(props); } } //TODO: implement getDefaultClassValue() for ME1 and ME2 so this isn't needed if (structType == "Rotator") { string[] labels = { "Pitch", "Yaw", "Roll" }; for (int i = 0; i < 3; i++) { props.Add(new IntProperty(stream, labels[i])); } } else if (structType == "Vector2d" || structType == "RwVector2") { string[] labels = { "X", "Y" }; for (int i = 0; i < 2; i++) { props.Add(new FloatProperty(stream, labels[i])); } } else if (structType == "Vector" || structType == "RwVector3") { string[] labels = { "X", "Y", "Z" }; for (int i = 0; i < 3; i++) { props.Add(new FloatProperty(stream, labels[i])); } } else if (structType == "Color") { string[] labels = { "B", "G", "R", "A" }; for (int i = 0; i < 4; i++) { props.Add(new ByteProperty(stream, labels[i])); } } else if (structType == "LinearColor") { string[] labels = { "R", "G", "B", "A" }; for (int i = 0; i < 4; i++) { props.Add(new FloatProperty(stream, labels[i])); } } //uses EndsWith to support RwQuat, RwVector4, and RwPlane else if (structType.EndsWith("Quat") || structType.EndsWith("Vector4") || structType.EndsWith("Plane")) { string[] labels = { "X", "Y", "Z", "W" }; for (int i = 0; i < 4; i++) { props.Add(new FloatProperty(stream, labels[i])); } } else if (structType == "TwoVectors") { string[] labels = { "X", "Y", "Z", "X", "Y", "Z" }; for (int i = 0; i < 6; i++) { props.Add(new FloatProperty(stream, labels[i])); } } else if (structType == "Matrix" || structType == "RwMatrix44") { string[] labels = { "X Plane", "Y Plane", "Z Plane", "W Plane" }; string[] labels2 = { "X", "Y", "Z", "W" }; for (int i = 0; i < 4; i++) { PropertyCollection structProps = new PropertyCollection(); for (int j = 0; j < 4; j++) { structProps.Add(new FloatProperty(stream, labels2[j])); } props.Add(new StructProperty("Plane", structProps, labels[i], true)); } } else if (structType == "Guid") { string[] labels = { "A", "B", "C", "D" }; for (int i = 0; i < 4; i++) { props.Add(new IntProperty(stream, labels[i])); } } else if (structType == "IntPoint") { string[] labels = { "X", "Y" }; for (int i = 0; i < 2; i++) { props.Add(new IntProperty(stream, labels[i])); } } else if (structType == "Box" || structType == "BioRwBox") { string[] labels = { "Min", "Max" }; string[] labels2 = { "X", "Y", "Z" }; for (int i = 0; i < 2; i++) { PropertyCollection structProps = new PropertyCollection(); for (int j = 0; j < 3; j++) { structProps.Add(new FloatProperty(stream, labels2[j])); } props.Add(new StructProperty("Vector", structProps, labels[i], true)); } props.Add(new ByteProperty(stream, "IsValid")); } else { props.Add(new UnknownProperty(stream, size)); } return(props); }
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 PropertyCollection ReadProps(IMEPackage pcc, MemoryStream stream, string typeName) { PropertyCollection props = new PropertyCollection(); long startPosition = stream.Position; while (stream.Position + 8 <= stream.Length) { int nameIdx = stream.ReadValueS32(); if (!pcc.isName(nameIdx)) { stream.Seek(-4, SeekOrigin.Current); break; } string name = pcc.getNameEntry(nameIdx); if (name == "None") { props.Add(new NoneProperty { PropType = PropertyType.None }); stream.Seek(4, SeekOrigin.Current); break; } NameReference nameRef = new NameReference { Name = name, count = stream.ReadValueS32() }; int typeIdx = stream.ReadValueS32(); stream.Seek(4, SeekOrigin.Current); int size = stream.ReadValueS32(); if (!pcc.isName(typeIdx) || size < 0 || size > stream.Length - stream.Position) { stream.Seek(-16, SeekOrigin.Current); break; } stream.Seek(4, SeekOrigin.Current); PropertyType type; if (!Enum.TryParse(pcc.getNameEntry(typeIdx), out type)) { type = PropertyType.Unknown; } switch (type) { case PropertyType.StructProperty: string structType = pcc.getNameEntry(stream.ReadValueS32()); stream.Seek(4, SeekOrigin.Current); if (ME3UnrealObjectInfo.isImmutable(structType)) { PropertyCollection structProps = ReadSpecialStruct(pcc, stream, structType, size); props.Add(new StructProperty(structType, structProps, nameRef, true)); } else { PropertyCollection structProps = ReadProps(pcc, stream, structType); props.Add(new StructProperty(structType, structProps, nameRef)); } break; case PropertyType.IntProperty: props.Add(new IntProperty(stream, nameRef)); break; case PropertyType.FloatProperty: props.Add(new FloatProperty(stream, nameRef)); break; case PropertyType.ObjectProperty: props.Add(new ObjectProperty(stream, nameRef)); break; case PropertyType.NameProperty: props.Add(new NameProperty(stream, pcc, nameRef)); break; case PropertyType.BoolProperty: props.Add(new BoolProperty(stream, pcc.Game, nameRef)); break; case PropertyType.BioMask4Property: props.Add(new BioMask4Property(stream, nameRef)); break; case PropertyType.ByteProperty: { if (size != 1) { NameReference enumType = new NameReference(); if (pcc.Game == MEGame.ME3) { enumType.Name = pcc.getNameEntry(stream.ReadValueS32()); enumType.count = stream.ReadValueS32(); } else { enumType.Name = UnrealObjectInfo.GetEnumType(pcc.Game, name, typeName); } props.Add(new EnumProperty(stream, pcc, enumType, nameRef)); } else { if (pcc.Game == MEGame.ME3) { stream.Seek(8, SeekOrigin.Current); } props.Add(new ByteProperty(stream, nameRef)); } } break; case PropertyType.ArrayProperty: { props.Add(ReadArrayProperty(stream, pcc, typeName, nameRef)); } break; case PropertyType.StrProperty: { props.Add(new StrProperty(stream, nameRef)); } break; case PropertyType.StringRefProperty: props.Add(new StringRefProperty(stream, nameRef)); break; case PropertyType.DelegateProperty: props.Add(new DelegateProperty(stream, pcc, nameRef)); break; case PropertyType.Unknown: { props.Add(new UnknownProperty(stream, size, pcc.getNameEntry(typeIdx), nameRef)); } break; case PropertyType.None: default: break; } } if (props.Count > 0) { if (props[props.Count - 1].PropType != PropertyType.None) { stream.Seek(startPosition, SeekOrigin.Begin); return(new PropertyCollection { endOffset = (int)stream.Position }); } //remove None Property props.RemoveAt(props.Count - 1); } props.endOffset = (int)stream.Position; return(props); }
public static UProperty ReadArrayProperty(MemoryStream stream, IMEPackage pcc, string enclosingType, NameReference name, bool IsInImmutable = false) { long arrayOffset = IsInImmutable ? stream.Position : stream.Position - 24; ArrayType arrayType = UnrealObjectInfo.GetArrayType(pcc.Game, name, enclosingType); int count = stream.ReadValueS32(); switch (arrayType) { case ArrayType.Object: { var props = new List <ObjectProperty>(); for (int i = 0; i < count; i++) { props.Add(new ObjectProperty(stream)); } return(new ArrayProperty <ObjectProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.Name: { var props = new List <NameProperty>(); for (int i = 0; i < count; i++) { props.Add(new NameProperty(stream, pcc)); } return(new ArrayProperty <NameProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.Enum: { var props = new List <EnumProperty>(); NameReference enumType = new NameReference { Name = UnrealObjectInfo.GetEnumType(pcc.Game, name, enclosingType) }; for (int i = 0; i < count; i++) { props.Add(new EnumProperty(stream, pcc, enumType)); } return(new ArrayProperty <EnumProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.Struct: { var props = new List <StructProperty>(); string arrayStructType = UnrealObjectInfo.GetPropertyInfo(pcc.Game, name, enclosingType)?.reference; if (IsInImmutable || ME3UnrealObjectInfo.isImmutable(arrayStructType)) { int arraySize = 0; if (!IsInImmutable) { stream.Seek(-16, SeekOrigin.Current); arraySize = stream.ReadValueS32(); stream.Seek(12, SeekOrigin.Current); } for (int i = 0; i < count; i++) { long offset = stream.Position; PropertyCollection structProps = ReadSpecialStruct(pcc, stream, arrayStructType, arraySize / count); StructProperty structP = new StructProperty(arrayStructType, structProps, isImmutable: true); structP.Offset = offset; props.Add(structP); } } else { for (int i = 0; i < count; i++) { long structOffset = stream.Position; PropertyCollection structProps = ReadProps(pcc, stream, arrayStructType); StructProperty structP = new StructProperty(arrayStructType, structProps); structP.Offset = structOffset; props.Add(structP); } } return(new ArrayProperty <StructProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.Bool: { var props = new List <BoolProperty>(); for (int i = 0; i < count; i++) { props.Add(new BoolProperty(stream, pcc.Game)); } return(new ArrayProperty <BoolProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.String: { var props = new List <StrProperty>(); for (int i = 0; i < count; i++) { props.Add(new StrProperty(stream)); } return(new ArrayProperty <StrProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.Float: { var props = new List <FloatProperty>(); for (int i = 0; i < count; i++) { props.Add(new FloatProperty(stream)); } return(new ArrayProperty <FloatProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.Byte: { var props = new List <ByteProperty>(); for (int i = 0; i < count; i++) { props.Add(new ByteProperty(stream)); } return(new ArrayProperty <ByteProperty>(arrayOffset, props, arrayType, name)); } case ArrayType.Int: default: { var props = new List <IntProperty>(); for (int i = 0; i < count; i++) { props.Add(new IntProperty(stream)); } return(new ArrayProperty <IntProperty>(arrayOffset, props, arrayType, name)); } } }
public static PropertyCollection ReadProps(IMEPackage pcc, MemoryStream stream, string typeName, bool includeNoneProperty = false) { //Uncomment this for debugging property engine /*DebugOutput.StartDebugger("Property Engine ReadProps() for "+typeName); * if (pcc.FileName == "C:\\Users\\Dev\\Downloads\\ME2_Placeables.upk") * { * //Debugger.Break(); * }*/ PropertyCollection props = new PropertyCollection(); long startPosition = stream.Position; while (stream.Position + 8 <= stream.Length) { int nameIdx = stream.ReadValueS32(); if (!pcc.isName(nameIdx)) { stream.Seek(-4, SeekOrigin.Current); break; } string name = pcc.getNameEntry(nameIdx); if (name == "None") { props.Add(new NoneProperty(stream, "None")); stream.Seek(4, SeekOrigin.Current); break; } NameReference nameRef = new NameReference { Name = name, Number = stream.ReadValueS32() }; int typeIdx = stream.ReadValueS32(); stream.Seek(4, SeekOrigin.Current); int size = stream.ReadValueS32(); if (!pcc.isName(typeIdx) || size < 0 || size > stream.Length - stream.Position) { stream.Seek(-16, SeekOrigin.Current); break; } stream.Seek(4, SeekOrigin.Current); PropertyType type; string namev = pcc.getNameEntry(typeIdx); if (Enum.IsDefined(typeof(PropertyType), namev)) { Enum.TryParse(namev, out type); } else { type = PropertyType.Unknown; } switch (type) { case PropertyType.StructProperty: string structType = pcc.getNameEntry(stream.ReadValueS32()); stream.Seek(4, SeekOrigin.Current); if (ME3UnrealObjectInfo.isImmutable(structType)) { PropertyCollection structProps = ReadSpecialStruct(pcc, stream, structType, size); var structprop = new StructProperty(structType, structProps, nameRef, true); structprop.Offset = stream.Position - 4; props.Add(structprop); } else { PropertyCollection structProps = ReadProps(pcc, stream, structType, includeNoneProperty); var structprop = new StructProperty(structType, structProps, nameRef); structprop.Offset = stream.Position - 4; props.Add(structprop); } break; case PropertyType.IntProperty: props.Add(new IntProperty(stream, nameRef)); break; case PropertyType.FloatProperty: props.Add(new FloatProperty(stream, nameRef)); break; case PropertyType.ObjectProperty: props.Add(new ObjectProperty(stream, nameRef)); break; case PropertyType.NameProperty: props.Add(new NameProperty(stream, pcc, nameRef)); break; case PropertyType.BoolProperty: props.Add(new BoolProperty(stream, pcc.Game, nameRef)); break; case PropertyType.BioMask4Property: props.Add(new BioMask4Property(stream, nameRef)); break; case PropertyType.ByteProperty: { if (size != 1) { NameReference enumType = new NameReference(); if (pcc.Game == MEGame.ME3) { enumType.Name = pcc.getNameEntry(stream.ReadValueS32()); enumType.Number = stream.ReadValueS32(); } else { enumType.Name = UnrealObjectInfo.GetEnumType(pcc.Game, name, typeName); } props.Add(new EnumProperty(stream, pcc, enumType, nameRef)); } else { if (pcc.Game == MEGame.ME3) { stream.Seek(8, SeekOrigin.Current); } props.Add(new ByteProperty(stream, nameRef)); } } break; case PropertyType.ArrayProperty: { props.Add(ReadArrayProperty(stream, pcc, typeName, nameRef)); } break; case PropertyType.StrProperty: { props.Add(new StrProperty(stream, nameRef)); } break; case PropertyType.StringRefProperty: props.Add(new StringRefProperty(stream, nameRef)); break; case PropertyType.DelegateProperty: props.Add(new DelegateProperty(stream, pcc, nameRef)); break; case PropertyType.Unknown: { props.Add(new UnknownProperty(stream, size, pcc.getNameEntry(typeIdx), nameRef)); } break; case PropertyType.None: if (includeNoneProperty) { props.Add(new NoneProperty(stream, "None")); } break; default: break; } } if (props.Count > 0) { //error reading props. if (props[props.Count - 1].PropType != PropertyType.None) { stream.Seek(startPosition, SeekOrigin.Begin); return(new PropertyCollection { endOffset = (int)stream.Position }); } //remove None Property if (!includeNoneProperty) { props.RemoveAt(props.Count - 1); } } props.endOffset = (int)stream.Position; return(props); }