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 UProperty uProp) { structProps.Add(uProp); } } if (!Structs.TryGetValue(tempInfo.baseClass, out tempInfo)) { tempInfo = null; } } structProps.Add(new NoneProperty()); string filepath = Path.Combine(ME1Directory.gamePath, "BioGame", info.pccPath); if (File.Exists(info.pccPath)) { filepath = info.pccPath; //Used for dynamic lookup } if (File.Exists(filepath)) { IMEPackage importPCC = MEPackageHandler.OpenME1Package(filepath); 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); }
public static UProperty getDefaultProperty(string propName, PropertyInfo propInfo, bool stripTransients = true, bool isImmutable = false) { switch (propInfo.Type) { case PropertyType.IntProperty: return(new IntProperty(0, propName)); case PropertyType.FloatProperty: return(new FloatProperty(0f, propName)); case PropertyType.DelegateProperty: return(new DelegateProperty(0, "None")); case PropertyType.ObjectProperty: return(new ObjectProperty(0, propName)); case PropertyType.NameProperty: return(new NameProperty("None", propName)); case PropertyType.BoolProperty: return(new BoolProperty(false, propName)); case PropertyType.ByteProperty when propInfo.IsEnumProp(): return(new EnumProperty(propInfo.Reference, MEGame.ME2, propName)); case PropertyType.ByteProperty: return(new ByteProperty(0, propName)); case PropertyType.StrProperty: return(new StrProperty("", propName)); case PropertyType.StringRefProperty: return(new StringRefProperty(propName)); case PropertyType.BioMask4Property: return(new BioMask4Property(0, propName)); case PropertyType.ArrayProperty: switch (getArrayType(propInfo)) { case ArrayType.Object: return(new ArrayProperty <ObjectProperty>(propName)); case ArrayType.Name: return(new ArrayProperty <NameProperty>(propName)); case ArrayType.Enum: return(new ArrayProperty <EnumProperty>(propName)); case ArrayType.Struct: return(new ArrayProperty <StructProperty>(propName)); case ArrayType.Bool: return(new ArrayProperty <BoolProperty>(propName)); case ArrayType.String: return(new ArrayProperty <StrProperty>(propName)); case ArrayType.Float: return(new ArrayProperty <FloatProperty>(propName)); case ArrayType.Int: return(new ArrayProperty <IntProperty>(propName)); case ArrayType.Byte: return(new ImmutableByteArrayProperty(propName)); default: return(null); } case PropertyType.StructProperty: isImmutable = isImmutable || UnrealObjectInfo.IsImmutable(propInfo.Reference, MEGame.ME2); return(new StructProperty(propInfo.Reference, getDefaultStructValue(propInfo.Reference, stripTransients), propName, isImmutable)); case PropertyType.None: case PropertyType.Unknown: default: return(null); } }
public static PropertyCollection RemoveIncompatibleProperties(IMEPackage sourcePcc, PropertyCollection props, string typeName, MEGame newGame) { var infoProps = UnrealObjectInfo.GetAllProperties(newGame, typeName); var newProps = new PropertyCollection(); foreach (UProperty 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.GetFullPath.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.GetFullPath.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 PropertyCollection getDefaultStructValue(string className, bool stripTransients) { bool isImmutable = UnrealObjectInfo.IsImmutable(className, MEGame.ME2); 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 (ME2Directory.BioGamePath != null) { filepath = Path.Combine(ME2Directory.BioGamePath, info.pccPath); } Stream loadStream = null; if (File.Exists(info.pccPath)) { filepath = info.pccPath; loadStream = new MemoryStream(File.ReadAllBytes(info.pccPath)); } else if (info.pccPath == UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName) { filepath = "GAMERESOURCES_ME2"; loadStream = Utilities.LoadFileFromCompressedResource("GameResources.zip", CoreLib.CustomResourceFileName(MEGame.ME2)); } 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))) { // Load from test minigame folder. This is only really useful on azure where we don't have access to // games filepath = Path.Combine(MiniGameFilesPath, info.pccPath); loadStream = new MemoryStream(File.ReadAllBytes(filepath)); } #endif 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); }