public static ObjectBinary From(ExportEntry export) { if (export.IsDefaultObject) { //DefaultObjects don't have binary return(null); } string className = export.ClassName; if (export.IsOrInheritsFrom("BioPawn")) { //way, waaay too many subclasses of BioPawn to put in the switch statement, so we take care of it here className = "BioPawn"; } switch (className) { case "BioStage": return(From <BioStage>(export)); case "Level": return(From <Level>(export)); case "World": return(From <World>(export)); case "Model": return(From <Model>(export)); case "Polys": return(From <Polys>(export)); case "DecalMaterial": case "Material": return(From <Material>(export)); case "MaterialInstanceConstant": case "MaterialInstanceTimeVarying": if (export.GetProperty <BoolProperty>("bHasStaticPermutationResource")?.Value == true) { return(From <MaterialInstance>(export)); } return(Array.Empty <byte>()); case "FracturedStaticMesh": return(From <FracturedStaticMesh>(export)); case "StaticMesh": return(From <StaticMesh>(export)); case "SkeletalMesh": return(From <SkeletalMesh>(export)); case "CoverMeshComponent": case "InteractiveFoliageComponent": case "SplineMeshComponent": case "FracturedStaticMeshComponent": case "StaticMeshComponent": return(From <StaticMeshComponent>(export)); case "DecalComponent": return(From <DecalComponent>(export)); case "Terrain": return(From <Terrain>(export)); case "TerrainComponent": return(From <TerrainComponent>(export)); case "FluidSurfaceComponent": return(From <FluidSurfaceComponent>(export)); case "ModelComponent": return(From <ModelComponent>(export)); case "BioDynamicAnimSet": return(From <BioDynamicAnimSet>(export)); case "BioPawn": return(From <BioPawn>(export)); case "PrefabInstance": return(From <PrefabInstance>(export)); case "Class": return(From <UClass>(export)); case "State": return(From <UState>(export)); case "Function": return(From <UFunction>(export)); case "Enum": return(From <UEnum>(export)); case "Const": return(From <UConst>(export)); case "ScriptStruct": return(From <UScriptStruct>(export)); case "IntProperty": case "BoolProperty": case "FloatProperty": case "NameProperty": case "StrProperty": case "StringRefProperty": return(From <UValueProperty>(export)); case "ByteProperty": case "ObjectProperty": case "ComponentProperty": case "InterfaceProperty": case "ArrayProperty": case "StructProperty": case "BioMask4Property": return(From <UReferenceProperty>(export)); case "MapProperty": case "ClassProperty": case "DelegateProperty": return(From <UTwoReferenceProperty>(export)); case "ShaderCache": return(From <ShaderCache>(export)); default: return(null); } }
//call this method to regenerate ME2ObjectInfo.json //Takes a long time (10 minutes maybe?). Application will be completely unresponsive during that time. public static void generateInfo() { var NewClasses = new Dictionary <string, ClassInfo>(); var NewStructs = new Dictionary <string, ClassInfo>(); var NewEnums = new Dictionary <string, List <NameReference> >(); var NewSequenceObjects = new Dictionary <string, SequenceObjectInfo>(); foreach (string filePath in MELoadedFiles.GetOfficialFiles(MEGame.ME2)) { if (Path.GetExtension(filePath) == ".pcc") { using IMEPackage pcc = MEPackageHandler.OpenME2Package(filePath); for (int j = 1; j <= pcc.ExportCount; j++) { ExportEntry exportEntry = pcc.GetUExport(j); string className = exportEntry.ClassName; if (className == "Enum") { generateEnumValues(exportEntry, NewEnums); } else if (className == "Class") { string objectName = exportEntry.ObjectName; if (!NewClasses.ContainsKey(objectName)) { NewClasses.Add(objectName, generateClassInfo(exportEntry)); } } else if (className == "ScriptStruct") { string objectName = exportEntry.ObjectName; if (!NewStructs.ContainsKey(objectName)) { NewStructs.Add(objectName, generateClassInfo(exportEntry, isStruct: true)); } } else if (exportEntry.IsOrInheritsFrom("SequenceObject")) { if (!NewSequenceObjects.TryGetValue(className, out SequenceObjectInfo seqObjInfo)) { seqObjInfo = new SequenceObjectInfo(); NewSequenceObjects.Add(className, seqObjInfo); } int objInstanceVersion = exportEntry.GetProperty <IntProperty>("ObjInstanceVersion"); if (objInstanceVersion > seqObjInfo.ObjInstanceVersion) { seqObjInfo.ObjInstanceVersion = objInstanceVersion; } } } //Debug.WriteLine("Releasing " + pcc.FileName); } } //CUSTOM ADDITIONS try { NewClasses.Add("LightMapTexture2D", new ClassInfo { baseClass = "Texture2D", exportIndex = 0, pccPath = UnrealObjectInfo.Me3ExplorerCustomNativeAdditionsName }); NewClasses["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>("UseFullPrecisionUVs", 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)), } }; } catch (Exception) { } //SFXPhysicalMaterialDecals missing items ClassInfo sfxpmd = NewClasses["SFXPhysicalMaterialDecals"]; string[] decalComponentArrays = { "HeavyPistol", "AutoPistol", "HandCannon", "SMG", "Shotgun", "HeavyShotgun", "FlakGun", "AssaultRifle", "Needler", "Machinegun", "SniperRifle", "AntiMatRifle", "MassCannon", "ParticleBeam" }; foreach (string decal in decalComponentArrays) { sfxpmd.properties.Add(decal, new PropertyInfo(PropertyType.ArrayProperty, "DecalComponent")); } NewClasses["SFXWeapon"].properties.Add("InstantHitDamageTypes", new PropertyInfo(PropertyType.ArrayProperty, "Class")); File.WriteAllText(jsonPath, JsonConvert.SerializeObject(new { SequenceObjects = NewSequenceObjects, Classes = NewClasses, Structs = NewStructs, Enums = NewEnums }, Formatting.Indented)); }
//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() { 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.IsOrInheritsFrom("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(jsonPath, JsonConvert.SerializeObject(new { SequenceObjects, Classes, Structs, Enums }, Formatting.Indented)); }