public static void GenerateDiffFile(AssetsManager am, AssetsFileInstance inst, AssetsFileInstance newInst, HKWEMeta meta) { EditorUtility.DisplayProgressBar("HKEdit", "Reading dependencies...", 0.5f); am.UpdateDependencies(); Dictionary <AssetID, AssetID> newToOldIds = new Dictionary <AssetID, AssetID>(); AssetsFileTable newTable = newInst.table; List <AssetFileInfoEx> initialGameObjects = newTable.GetAssetsOfType(0x01); for (int i = 0; i < initialGameObjects.Count; i++) { if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Finding diff IDs... (step 1/3)", (float)i / initialGameObjects.Count); } AssetFileInfoEx inf = initialGameObjects[i]; AssetTypeValueField baseField = am.GetATI(newInst.file, inf).GetBaseField(); AssetTypeValueField editDifferMono = GetEDMono(am, newInst, baseField); EditDifferData diff = new EditDifferData() { fileId = editDifferMono.Get("fileId").GetValue().AsInt(), pathId = editDifferMono.Get("pathId").GetValue().AsInt64(), origPathId = editDifferMono.Get("origPathId").GetValue().AsInt64(), newAsset = editDifferMono.Get("newAsset").GetValue().AsBool() }; } }
static void PatchVR(string gameManagersBackupPath, string gameManagersPath, string classDataPath) { Console.WriteLine("Patching globalgamemanagers..."); Console.WriteLine($"Using classData file from path '{classDataPath}'"); AssetsManager am = new AssetsManager(); am.LoadClassPackage(classDataPath); AssetsFileInstance ggm = am.LoadAssetsFile(gameManagersBackupPath, false); AssetsFile ggmFile = ggm.file; AssetsFileTable ggmTable = ggm.table; am.LoadClassDatabaseFromPackage(ggmFile.typeTree.unityVersion); List <AssetsReplacer> replacers = new List <AssetsReplacer>(); AssetFileInfoEx buildSettings = ggmTable.GetAssetInfo(11); AssetTypeValueField buildSettingsBase = am.GetATI(ggmFile, buildSettings).GetBaseField(); AssetTypeValueField enabledVRDevices = buildSettingsBase.Get("enabledVRDevices").Get("Array"); AssetTypeTemplateField stringTemplate = enabledVRDevices.templateField.children[1]; AssetTypeValueField[] vrDevicesList = new AssetTypeValueField[] { StringField("OpenVR", stringTemplate) }; enabledVRDevices.SetChildrenList(vrDevicesList); replacers.Add(new AssetsReplacerFromMemory(0, buildSettings.index, (int)buildSettings.curFileType, 0xffff, buildSettingsBase.WriteToByteArray())); using (AssetsFileWriter writer = new AssetsFileWriter(File.OpenWrite(gameManagersPath))) { ggmFile.Write(writer, 0, replacers, 0); } }
public Dependency(string name, Stream file, AssetsFile af, AssetsFileTable aft) { this.name = name; this.file = file; this.af = af; this.aft = aft; }
public AssetsFileInstance(FileStream stream, string root) { path = stream.Name; name = Path.Combine(root, Path.GetFileName(path)); file = new AssetsFile(new AssetsFileReader(stream)); table = new AssetsFileTable(file); dependencies.AddRange( Enumerable.Range(0, file.dependencies.dependencyCount) .Select(d => (AssetsFileInstance)null) ); }
public AssetsFileInstance(Stream stream, string filePath, string root) { this.stream = stream; path = Path.GetFullPath(filePath); name = Path.Combine(root, Path.GetFileName(path)); file = new AssetsFile(new AssetsFileReader(stream)); table = new AssetsFileTable(file); dependencies.AddRange( Enumerable.Range(0, (int)file.dependencies.dependencyCount) .Select(d => (AssetsFileInstance)null) ); }
public static ResourceAssets Parse() { ResourceAssets resourceAssets = new ResourceAssets(); using (FileStream resStream = new FileStream(FindPath(), FileMode.Open)) using (AssetsFileReader resReader = new AssetsFileReader(resStream)) { AssetsFile resourcesFile = new AssetsFile(resReader); AssetsFileTable resourcesFileTable = new AssetsFileTable(resourcesFile); foreach (AssetFileInfoEx afi in resourcesFileTable.pAssetFileInfo) { if (afi.curFileType == TEXT_CLASS_ID) { resourcesFile.reader.Position = afi.absoluteFilePos; string assetName = resourcesFile.reader.ReadCountStringInt32(); if (assetName == "EntityDistributions") { resourcesFile.reader.Align(); resourceAssets.LootDistributionsJson = resourcesFile.reader.ReadCountStringInt32().Replace("\\n", ""); } } else if (afi.curFileType == MONOBEHAVIOUR_CLASS_ID) { resourcesFile.reader.Position = afi.absoluteFilePos; resourcesFile.reader.Position += 28; string assetName = resourcesFile.reader.ReadCountStringInt32(); if (assetName == "WorldEntityData") { resourcesFile.reader.Align(); uint size = resourcesFile.reader.ReadUInt32(); WorldEntityInfo wei; for (int i = 0; i < size; i++) { wei = new WorldEntityInfo(); wei.classId = resourcesFile.reader.ReadCountStringInt32(); wei.techType = (TechType)resourcesFile.reader.ReadInt32(); wei.slotType = (EntitySlot.Type)resourcesFile.reader.ReadInt32(); wei.prefabZUp = resourcesFile.reader.ReadBoolean(); resourcesFile.reader.Align(); wei.cellLevel = (LargeWorldEntity.CellLevel)resourcesFile.reader.ReadInt32(); wei.localScale = new UnityEngine.Vector3(resourcesFile.reader.ReadSingle(), resourcesFile.reader.ReadSingle(), resourcesFile.reader.ReadSingle()); resourceAssets.WorldEntitiesByClassId.Add(wei.classId, wei); } } } } } Validate.IsTrue(resourceAssets.WorldEntitiesByClassId.Count > 0); Validate.IsTrue(resourceAssets.LootDistributionsJson != ""); return(resourceAssets); }
public static List <AssetFileInfoEx> GetAssetsOfType(this AssetsFileTable table, int typeId) { List <AssetFileInfoEx> infos = new List <AssetFileInfoEx>(); foreach (AssetFileInfoEx info in table.pAssetFileInfo) { if (info.curFileType == typeId) { infos.Add(info); } } return(infos); }
private static string GetAssetNameFast(int fileId, long pathId, AssetsFileInstance inst) { if (pathId == 0) { return(""); } AssetsFile file = null; AssetsFileTable table = null; if (fileId == 0) { file = inst.file; table = inst.table; } else { AssetsFileInstance dep = inst.dependencies[fileId - 1]; file = dep.file; table = dep.table; } AssetFileInfoEx inf = table.getAssetInfo((ulong)pathId); AssetsFileReader reader = file.reader; if (allowed.Contains(inf.curFileType)) { reader.Position = inf.absoluteFilePos; return(reader.ReadCountStringInt32()); } if (inf.curFileType == 0x1) { reader.Position = inf.absoluteFilePos; int size = reader.ReadInt32(); reader.Position += (ulong)(size * 12); reader.Position += 4; return(reader.ReadCountStringInt32()); } else if (inf.curFileType == 0x72) { reader.Position = inf.absoluteFilePos; reader.Position += 28; string name = reader.ReadCountStringInt32(); if (name != "") { return(name); } } return(""); }
private static void ParseAssetManifest(string basePath, string fileName, ResourceAssets resourceAssets) { string path = Path.Combine(basePath, fileName).Replace("resources/", "Resources/"); if (parsedManifests.Contains(path)) { return; } Dictionary <int, string> relativeFileIdToPath = new Dictionary <int, string>(); using (FileStream resStream = new FileStream(path, FileMode.Open, FileAccess.Read)) using (AssetsFileReader reader = new AssetsFileReader(resStream)) { AssetsFile file = new AssetsFile(reader); AssetsFileTable resourcesFileTable = new AssetsFileTable(file); parsedManifests.Add(path); relativeFileIdToPath.Add(0, path); int fileId = 1; foreach (AssetsFileDependency dependency in file.dependencies.dependencies) { relativeFileIdToPath.Add(fileId++, Path.Combine(basePath, dependency.assetPath)); } foreach (AssetsFileDependency dependency in file.dependencies.dependencies) { ParseAssetManifest(basePath, dependency.assetPath, resourceAssets); } foreach (AssetFileInfoEx assetFileInfo in resourcesFileTable.assetFileInfo) { reader.Position = assetFileInfo.absoluteFilePos; AssetIdentifier identifier = new AssetIdentifier(path, assetFileInfo.index); AssetParser assetParser; if (assetParsersByClassId.TryGetValue(assetFileInfo.curFileType, out assetParser)) { assetParser.Parse(identifier, reader, resourceAssets, relativeFileIdToPath); } assetIdentifierToClassId.Add(identifier, assetFileInfo.curFileType); } } }
public void LoadAssets(Stream stream, string directory) { file = stream; initialFile = new AssetsFile(new AssetsFileReader(file)); initialTable = new AssetsFileTable(initialFile); for (int i = 0; i < initialFile.dependencies.dependencyCount; i++) { Dependency assetDependency; string depName = initialFile.dependencies.pDependencies[i].assetPath; FileStream depFile = new FileStream(directory + "\\" + depName.Replace("library/", "Resources\\"), FileMode.Open, FileAccess.Read, FileShare.Read); AssetsFile depAssetsFile = new AssetsFile(new AssetsFileReader(depFile)); AssetsFileTable depAssetsFileTable = new AssetsFileTable(depAssetsFile); assetDependency = new Dependency(depName, depFile, depAssetsFile, depAssetsFileTable); dependencies.Add(assetDependency); } }
static void Main(string[] args) { byte[] b = File.ReadAllBytes(@"resources.assets"); int Reader = AssetsFileReader.CreateAssetsReaderFromMemory(b, (uint)b.Length, true); AssetsFile assetsFile = new AssetsFile(AssetsFileReader.AssetsReaderFromMemory, Reader); AssetsFileTable assetsFileTable = new AssetsFileTable(assetsFile, true); for (int i = 0; i < assetsFileTable.AssetFileInfoCount; ++i) { AssetFileInfoEx Asset = assetsFileTable.GetAssetInfo((ulong)i); if (Asset == null) { continue; } Console.WriteLine(Asset.NameString); } }
// All dependencies are stored in the root resource.assets file. The order they // are listed corresponds to the fileId order. We store this value, so we can // fetch the fileId of different assets to build AssetIdentifiers. private static void CalculateDependencyFileIds(string basePath, string fileName) { string path = Path.Combine(basePath, fileName); using (FileStream resStream = new FileStream(path, FileMode.Open, FileAccess.Read)) using (AssetsFileReader reader = new AssetsFileReader(resStream)) { AssetsFile file = new AssetsFile(reader); AssetsFileTable resourcesFileTable = new AssetsFileTable(file); int fileId = 1; foreach (AssetsFileDependency dependency in file.dependencies.dependencies) { fileIdByResourcePath.Add(dependency.assetPath, fileId); fileId++; } } }
private static void ParseAssetManifest(string basePath, string fileName, int fileId, ResourceAssets resourceAssets) { fileName = fileName.Replace("resources/", "Resources/"); if (parsedManifests.Contains(fileName)) { return; } parsedManifests.Add(fileName); string path = Path.Combine(basePath, fileName); using (FileStream resStream = new FileStream(path, FileMode.Open, FileAccess.Read)) using (AssetsFileReader reader = new AssetsFileReader(resStream)) { AssetsFile file = new AssetsFile(reader); AssetsFileTable resourcesFileTable = new AssetsFileTable(file); foreach (AssetsFileDependency dependency in file.dependencies.dependencies) { int dependencyFileId = fileIdByResourcePath[dependency.assetPath]; ParseAssetManifest(basePath, dependency.assetPath, dependencyFileId, resourceAssets); } foreach (AssetFileInfoEx assetFileInfo in resourcesFileTable.assetFileInfo) { reader.Position = assetFileInfo.absoluteFilePos; AssetIdentifier identifier = new AssetIdentifier(fileId, assetFileInfo.index); AssetParser assetParser; if (assetParsersByClassId.TryGetValue(assetFileInfo.curFileType, out assetParser)) { assetParser.Parse(identifier, reader, resourceAssets); } assetIdentifierToClassId.Add(identifier, assetFileInfo.curFileType); } } }
public List <AssetInfo> LoadAllFSMsFromFile(string path) { curFile = am.LoadAssetsFile(path, true); am.UpdateDependencies(); am.LoadClassDatabaseFromPackage(curFile.file.typeTree.unityVersion); AssetsFile file = curFile.file; AssetsFileTable table = curFile.table; //we read manually with binaryreader to speed up reading, but sometimes the dataVersion field won't exist //so here we read the template manually to see whether it exists and back up a bit if it doesn't string assemblyPath = Path.Combine(Path.GetDirectoryName(curFile.path), "Managed", "PlayMaker.dll"); MonoDeserializer deserializer = new MonoDeserializer(); deserializer.Read("PlayMakerFSM", MonoDeserializer.GetAssemblyWithDependencies(assemblyPath), file.header.format); bool hasDataField = deserializer.children[0].children[0].name == "dataVersion"; return(GetFSMInfos(file, table, hasDataField)); }
public static AssetFileInfoEx GetAssetInfo(this AssetsFileTable table, string name, uint typeId, bool caseSensitive = true) { if (!caseSensitive) { name = name.ToLower(); } for (int i = 0; i < table.assetFileInfo.Length; i++) { AssetFileInfoEx info = table.assetFileInfo[i]; string infoName = GetAssetNameFastNaive(table.file, info); if (!caseSensitive) { infoName = infoName.ToLower(); } if (info.curFileType == typeId && infoName == name) { return(info); } } return(null); }
public static void GenerateLevelFiles(AssetsManager am, AssetsFileInstance inst) { EditorUtility.DisplayProgressBar("HKEdit", "Reading dependencies...", 0.5f); am.UpdateDependencies(); //quicker asset id lookup for (int i = 0; i < am.files.Count; i++) { AssetsFileInstance afi = am.files[i]; if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Generating QLTs...", (float)i / am.files.Count); } afi.table.GenerateQuickLookupTree(); } ClassDatabaseFile cldb = am.classFile; AssetsFileTable table = inst.table; ReferenceCrawler crawler = new ReferenceCrawler(am); List <AssetFileInfoEx> initialGameObjects = table.GetAssetsOfType(0x01); for (int i = 0; i < initialGameObjects.Count; i++) { if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Recursing GameObject dependencies... (step 1/3)", (float)i / initialGameObjects.Count); } AssetFileInfoEx inf = initialGameObjects[i]; crawler.AddReference(new AssetID(inst.path, (long)inf.index), false); crawler.FindReferences(inst, inf); } Dictionary <AssetID, AssetID> glblToLcl = crawler.references; List <Type_0D> types = new List <Type_0D>(); List <string> typeNames = new List <string>(); Dictionary <string, AssetsFileInstance> fileToInst = am.files.ToDictionary(d => d.path); int j = 0; foreach (KeyValuePair <AssetID, AssetID> id in glblToLcl) { if (j % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Rewiring asset pointers... (step 2/3)", (float)j / glblToLcl.Count); } AssetsFileInstance depInst = fileToInst[id.Key.fileName]; AssetFileInfoEx depInf = depInst.table.getAssetInfo((ulong)id.Key.pathId); ClassDatabaseType clType = AssetHelper.FindAssetClassByID(cldb, depInf.curFileType); string clName = clType.name.GetString(cldb); if (!typeNames.Contains(clName)) { Type_0D type0d = C2T5.Cldb2TypeTree(cldb, clName); type0d.classId = (int)depInf.curFileType; types.Add(type0d); typeNames.Add(clName); } crawler.ReplaceReferences(depInst, depInf, id.Value.pathId); j++; } EditorUtility.DisplayProgressBar("HKEdit", "Saving scene... (step 3/3)", 1f); types.Add(CreateEditDifferTypeTree(cldb)); List <Type_0D> assetTypes = new List <Type_0D>() { C2T5.Cldb2TypeTree(cldb, 0x1c), C2T5.Cldb2TypeTree(cldb, 0x30), C2T5.Cldb2TypeTree(cldb, 0x53) }; string origFileName = Path.GetFileNameWithoutExtension(inst.path); string sceneGuid = CreateMD5(origFileName); string ExportedScenes = Path.Combine("Assets", "ExportedScenes"); //circumvents "!BeginsWithCaseInsensitive(file.pathName, AssetDatabase::kAssetsPathWithSlash)' assertion string ExportedScenesData = "ExportedScenesData"; CreateMetaFile(sceneGuid, Path.Combine(ExportedScenes, origFileName + ".unity.meta")); AssetsFile sceneFile = new AssetsFile(new AssetsFileReader(new MemoryStream(BundleCreator.CreateBlankAssets(ver, types)))); AssetsFile assetFile = new AssetsFile(new AssetsFileReader(new MemoryStream(BundleCreator.CreateBlankAssets(ver, assetTypes)))); byte[] sceneFileData; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; //unity editor won't load whole assets files by guid, so we have to use hardcoded paths sceneFile.dependencies.pDependencies = new AssetsFileDependency[] { CreateDependency(ExportedScenesData + "/" + origFileName + "-data.assets"), CreateScriptDependency(Constants.editDifferMsEditorScriptHash, Constants.editDifferLsEditorScriptHash) }; sceneFile.dependencies.dependencyCount = 2; sceneFile.preloadTable.items = new AssetPPtr[] { new AssetPPtr(2, 11500000) }; sceneFile.preloadTable.len = 1; sceneFile.Write(w, 0, crawler.sceneReplacers.Concat(crawler.sceneMonoReplacers).ToArray(), 0); sceneFileData = ms.ToArray(); } byte[] assetFileData; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; assetFile.Write(w, 0, crawler.assetReplacers.ToArray(), 0); assetFileData = ms.ToArray(); } File.WriteAllBytes(Path.Combine(ExportedScenes, origFileName + ".unity"), sceneFileData); File.WriteAllBytes(Path.Combine(ExportedScenesData, origFileName + "-data.assets"), assetFileData); File.WriteAllText(Path.Combine(ExportedScenesData, origFileName + ".metadata"), CreateHKWEMetaFile(am, inst)); EditorUtility.ClearProgressBar(); }
public void LoadFSM(AssetsManager am, AssetInfo info, string folderPath) { //risky but would technically work AssetsFileInstance assetsFileInstance = am.files.First(); AssetsFile assetsFile = assetsFileInstance.file; AssetsFileTable assetsTable = assetsFileInstance.table; AssetFileInfoEx afi = assetsTable.getAssetInfo(info.id); AssetTypeValueField baseField = Util.GetMonoBaseField(am, assetsFile, afi, folderPath); AssetTypeValueField fsm = baseField.Get("fsm"); AssetTypeValueField states = fsm.Get("states"); dataVersion = fsm.Get("dataVersion").GetValue().AsInt(); for (int i = 0; i < states.GetValue().AsArray().size; i++) { AssetTypeValueField state = states.Get((uint)i); string name = state.Get("name").GetValue().AsString(); AssetTypeValueField rect = state.Get("position"); float x = Mathf.Floor(rect.Get("x").GetValue().AsFloat()); float y = Mathf.Floor(rect.Get("y").GetValue().AsFloat()); float width = Mathf.Floor(rect.Get("width").GetValue().AsFloat()); float height = Mathf.Floor(rect.Get("height").GetValue().AsFloat()); HandleElement rectElem = new HandleElement(HandleType.Rectangle, new Vector2(x, y), new Vector2(x + width, y + height), new Color(0.5f, 0.5f, 0.5f, 0.7f)); elements.Add(rectElem); elements.Add(new HandleElement(HandleType.Label, new Vector2(x + (width / 2), y + 3), (int)width, name)); AssetTypeValueField transitions = state.Get("transitions"); uint transitionCount = transitions.GetValue().AsArray().size; FsmTransition[] dotNetTransitions = new FsmTransition[transitionCount]; for (int j = 0; j < transitionCount; j++) { dotNetTransitions[j] = new FsmTransition(transitions.Get((uint)j)); string transitionName = dotNetTransitions[j].fsmEvent.name; elements.Add(new HandleElement(HandleType.Label, new Vector2(x + (width / 2), y + 3 + ((j + 1) * 16)), (int)width, transitionName)); } Node node = new Node(name, new Rect(x, y, width, height), dotNetTransitions, rectElem); nodes.Add(node); //AssetTypeValueField transitions = state.Get("transitions"); //uint transitionCount = transitions.GetValue().AsArray().size; //FsmTransition[] dotNetTransitions = new FsmTransition[transitionCount]; //for (int j = 0; j < transitionCount; j++) //{ // dotNetTransitions[j] = new FsmTransition(transitions.Get((uint)j)); //} //Node node = new Node(state, name, dotNetRect, dotNetTransitions); //nodes.Add(node); //node.grid.MouseLeftButtonDown += (object sender, MouseButtonEventArgs e) => //{ // foreach (Node node2 in nodes) // { // node2.Selected = false; // } // node.Selected = true; // SidebarData(node); //}; // //graphCanvas.Children.Add(node.grid); } foreach (Node node in nodes) { if (node.transitions.Length > 0) { float yPos = 25; foreach (FsmTransition trans in node.transitions) { Node endNode = nodes.Where(n => n.text == trans.toState).FirstOrDefault(); if (endNode != null) { bool isLeft, dummy; Vector2 start = ComputeLocation(node, endNode, yPos, out isLeft); Vector2 end = ComputeLocation(endNode, node, 10, out dummy); Vector2 startMiddle, endMiddle; float dist = 70; if (!isLeft) { startMiddle = new Vector2(start.x - dist, start.y); endMiddle = new Vector2(end.x + dist, end.y); } else { startMiddle = new Vector2(start.x + dist, start.y); endMiddle = new Vector2(end.x - dist, end.y); } elements.Insert(0, new HandleElement(HandleType.ArrowLine, start, end, startMiddle, endMiddle)); } else { System.Diagnostics.Debug.WriteLine(node.text + " failed to connect to " + trans.toState); } yPos += 16; } } } }
public static byte[] CreateBundleFromLevel(AssetsManager am, /*byte[] data,*/ AssetsFileInstance inst, string sceneName, DiffFile diffFile, string bunPath) { AssetsFile file = inst.file; AssetsFileTable table = inst.table; string folderName = Path.GetDirectoryName(inst.path); //string sceneName = Path.GetFileNameWithoutExtension(inst.path) + "_mod"; List <AssetsReplacer> assetsSA = new List <AssetsReplacer>(); List <AssetFileInfoEx> infos = table.pAssetFileInfo.ToList(); //List<int> typeIds = new List<int>(); //foreach (AssetFileInfoEx info in infos) //{ // int typeId = (int)info.curFileType; // if (!typeIds.Contains(typeId) && typeId != 0x72) // typeIds.Add(typeId); //} assetsSA.Add(PreloadData.CreatePreloadData(1)); assetsSA.Add(BundleMeta.CreateBundleInformation(sceneName, 2)); //todo: pull from original assets file, cldb is not always update to date List <Type_0D> types = new List <Type_0D>(); //foreach (int typeId in typeIds) //{ // types.Add(C2T5.Cldb2TypeTree(am.classFile, typeId)); //} List <Type_0D> typesSA = new List <Type_0D> { C2T5.Cldb2TypeTree(am.classFile, 0x96), //PreloadData C2T5.Cldb2TypeTree(am.classFile, 0x8E) //AssetBundle }; const string ver = "2017.4.10f1"; List <AssetsReplacer> replacers = new List <AssetsReplacer>(); //UnityEngine.Debug.Log("HKWE DM " + diffFile.magic); //UnityEngine.Debug.Log("HKWE GC " + diffFile.changes.Count + diffFile.adds.Count + diffFile.removes.Count); //AssetsReplacerFromMemory mem = MoveTest.RunMoveTest(table.getAssetInfo(2642), am.GetATI(file, table.getAssetInfo(2642)).GetBaseField(), 2642) as AssetsReplacerFromMemory; foreach (GameObjectChange goChange in diffFile.changes) { //UnityEngine.Debug.Log("HKWE GO " + goChange.pathId); foreach (ComponentChangeOrAdd compChange in goChange.changes) { AssetFileInfoEx goInfo = table.getAssetInfo((ulong)goChange.pathId); AssetTypeValueField goBaseField = am.GetATI(file, goInfo).GetBaseField(); AssetTypeValueField compPptr = goBaseField.Get("m_Component").Get("Array")[(uint)compChange.componentIndex].Get("component"); AssetsManager.AssetExternal compExt = am.GetExtAsset(inst, compPptr); AssetFileInfoEx compInfo = compExt.info; AssetTypeValueField compBaseField = compExt.instance.GetBaseField(); //UnityEngine.Debug.Log("HKWE LR " + compInfo.index); AssetsReplacer imAlreadyReplacer = ComponentDiffReplacer.DiffComponent(compInfo, compBaseField, am.classFile, compChange, compInfo.index); replacers.Add(imAlreadyReplacer); } } AssetsManager amBun = new AssetsManager(); //we create a new manager because the two filenames will probably conflict amBun.classFile = am.classFile; //we can just reuse the classfile which is kinda hacky AssetsFileInstance bunInst = amBun.LoadAssetsFile(new MemoryStream(GetBundleData(bunPath, 0)), "HKWEDiffs", false); //placeholder path since we have no deps //rearrange the pathids immediately after the //last one from the level to keep unity happy ulong levelLargestPathID = 0; foreach (AssetFileInfoEx inf in table.pAssetFileInfo) { if (inf.index > levelLargestPathID) { levelLargestPathID = inf.index; } } ReferenceCrawler.ReorderIds(amBun, bunInst, levelLargestPathID + 1); byte[] bunSAInst = GetBundleData(bunPath, 1); //HashSet<ulong> addedDeps = new HashSet<ulong>(); foreach (AssetFileInfoEx inf in bunInst.table.pAssetFileInfo) { replacers.Add(MakeReplacer(inf.index, am, bunInst, inst, inf, bunSAInst, types)); } //foreach (GameObjectInfo inf in diffFile.infos) //{ // Debug.Log("7"); // ulong bunPathId = GetBundlePathId(amBun, bunInst, inf); // // AssetFileInfoEx objInf = bunInst.table.getAssetInfo(bunPathId); // replacers.Add(MakeReplacer(bunPathId, am, bunInst, inst, objInf, bunSAInst, types)); // // List<ulong> deps = ReferenceCrawler.CrawlPPtrs(amBun, bunInst, bunPathId); // foreach (ulong dep in deps) // { // if (!addedDeps.Contains(dep)) // { // addedDeps.Add(dep); // AssetFileInfoEx depInf = bunInst.table.getAssetInfo(dep); // //if (depInf.curFileType == 0x01 || depInf.curFileType == 0x04 || depInf.curFileType == 0xD4 || depInf.curFileType == 0x15 || depInf.curFileType == 0xD5) // //{ // // continue; // //} // replacers.Add(MakeReplacer(dep, am, bunInst, inst, depInf, bunSAInst, types)); // } // } // ////its possible to get a collision but very unlikely since unity already randomizes ids which are 8 bytes long // ////there's nothing here to test if a collision would be created so just hope that you don't win the lottery // //ulong bunPathId = GetBundlePathId(amBun, bunInst, inf); // ////AssetFileInfoEx afInf = bunInst.table.getAssetInfo(bunPathId); // ////replacers.Add(MakeReplacer(bunPathId, afInf, bunInst.stream)); // //List<ulong> deps = ReferenceCrawler.CrawlPPtrs(am, bunInst, bunPathId); // ////if (info.curFileType == 0x01 || info.curFileType == 0x04 || info.curFileType == 0xD4) // ////{ // //// continue; // ////} // //foreach (ulong dep in deps) // //{ // // AssetFileInfoEx depInf = bunInst.table.getAssetInfo(dep); // // //MakeReplacer(dep, am, bunInst, inst, depInf, bunSAInst, types); // // AssetsReplacerFromMemory ar = MakeReplacer(dep, am, bunInst, inst, depInf, bunSAInst, types); // // //todo- I guess this was just for testing purposes to block out everything, remove this at some point // // if (depInf.curFileType == 0x01 || depInf.curFileType == 0x04 || depInf.curFileType == 0xD4 || depInf.curFileType == 0x15 || depInf.curFileType == 0xD5) //depInf.curFileType == 0x1C // // { // // continue; // // } // // replacers.Add(ar); // //} //} byte[] data = null; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { //file.typeTree.hasTypeTree = true; //so we don't have to calculate hashes //foreach (Type_0D type in file.typeTree.pTypes_Unity5) //{ // if (!types.Any(t => t.classId == type.classId)) // { // types.Insert(0, C2T5.Cldb2TypeTree(am.classFile, type.classId)); // } //} file.typeTree.pTypes_Unity5 = file.typeTree.pTypes_Unity5.Concat(types.ToArray()).ToArray(); //file.typeTree.pTypes_Unity5 = types.ToArray(); file.typeTree.fieldCount = (uint)file.typeTree.pTypes_Unity5.Length; //file.typeTree.fieldCount = (uint)types.Count; file.Write(writer, 0, replacers.ToArray(), 0); data = ms.ToArray(); } //File.WriteAllBytes("_bundlefinal1.unity3d", data); byte[] blankDataSA = BundleCreator.CreateBlankAssets(ver, typesSA); AssetsFile blankFileSA = new AssetsFile(new AssetsFileReader(new MemoryStream(blankDataSA))); byte[] dataSA = null; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { blankFileSA.Write(writer, 0, assetsSA.ToArray(), 0); dataSA = ms.ToArray(); } using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { AssetsBundleFile bundle = BundleCreator.CreateBlankBundle(ver, data.Length, dataSA.Length, sceneName); bundle.Write(writer); writer.Write(dataSA); writer.Write(data); return(ms.ToArray()); } }
public HKSave(string path, string diff) { LoadProgress("Load Scene", "Generating diff...", 0); am = new AssetsManager(); assetsFileInstance = am.LoadAssetsFile(diff, false); assetsFile = assetsFileInstance.file; assetsTable = assetsFileInstance.table; am.LoadClassPackage(Path.Combine(Application.dataPath, "cldb.dat")); //FileStream stream = File.Open(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); //BinaryWriter writer = new BinaryWriter(stream); GameObject[] sceneObjs = GameObject.FindObjectsOfType <GameObject>(); List <GameObjectAdd> addList = new List <GameObjectAdd>(); List <GameObjectRemove> removeList = new List <GameObjectRemove>(); List <GameObjectChange> changeList = new List <GameObjectChange>(); List <GameObject> newGameObjects = new List <GameObject>(); List <GameObjectInfo> newGoInfos = new List <GameObjectInfo>(); int i = 0; foreach (GameObject obj in sceneObjs) { LoadProgress("Load Scene", "Generating diff...", ((float)i / sceneObjs.Length) * 100f); EditDiffer differ = obj.GetComponent <EditDiffer>(); if (differ != null) { if (!differ.newAsset) { List <ComponentChangeOrAdd> changes = new List <ComponentChangeOrAdd>(); List <ComponentRemove> removes = new List <ComponentRemove>(); ulong origPathId = differ.pathId; CompareTransform(obj, origPathId, changes); if (changes.Count > 0 || removes.Count > 0) { changeList.Add(new GameObjectChange() { pathId = (long)origPathId, changes = changes, removes = removes }); } } else { //bool parentIsNew = false; ulong parentPathId = ulong.MaxValue; if (obj.transform.parent == null) { parentPathId = 0; } else { EditDiffer ed = obj.transform.parent.gameObject.GetComponent <EditDiffer>(); if (ed != null) { parentPathId = ed.pathId; //if (ed.newAsset) //{ // parentIsNew = true; //} } else { Debug.LogWarning("editdiff missing from " + obj.name + "'s parent"); } } bool newAsset = differ.origPathId == 0; //when a new asset was created *not* by cloning addList.Add(new GameObjectAdd() { pathId = differ.pathId, parentId = parentPathId, goNew = newAsset }); newGameObjects.Add(obj); if (newAsset) { newGoInfos.Add(new GameObjectInfo(obj.name, differ.fileId, differ.origPathId, differ.pathId)); } } } i++; } LoadProgress("Create Diff Bundle", 0); CreateBundle(path, addList, removeList, changeList, newGameObjects, newGoInfos); EditorUtility.ClearProgressBar(); EditorUtility.DisplayDialog("HKEdit", "Diff saved. Because of a Unity bug, please clear and reopen the map to continue working. All errors shown after save are normal.", "OK"); //stream.Close(); }
public HKScene(string path, AssetsManager ami = null) { EditorUtility.DisplayProgressBar("HKEdit", "Wiping scene...", 0); GameObject[] sceneRoots = SceneManager.GetActiveScene().GetRootGameObjects(); foreach (GameObject rootObj in sceneRoots) { UnityEngine.Object.DestroyImmediate(rootObj); } EditorUtility.DisplayProgressBar("HKEdit", "Loading level file", 0); diffFile = path; string folderName = Path.GetDirectoryName(path); if (ami != null) { am = ami; } else { am = new AssetsManager(); } if (am.classFile == null) { am.LoadClassPackage(Path.Combine(Application.dataPath, "cldb.dat")); } assetsFileInstance = am.LoadAssetsFile(path, false); assetsFile = assetsFileInstance.file; assetsTable = assetsFileInstance.table; EditorUtility.DisplayProgressBar("HKEdit", "Loading dependencies", 0); //i dunno what this does but it should fix dependency issues am.LoadAssetsFile(path, true); EditorUtility.DisplayProgressBar("HKEdit", "Loading dependencies refs", 50); am.UpdateDependencies(); spriteLoader = new SpriteLoader(); byte[] bundleData = Loader.CreateBundleFromLevel(am, assetsFileInstance); EditorUtility.DisplayProgressBar("HKEdit", "Loading bundle", 0); bundle = AssetBundle.LoadFromMemory(bundleData); EditorUtility.DisplayProgressBar("HKEdit", "Loading scene", 50); //File.WriteAllBytes("hkwedebug.unity3d", bundleData); //assetMap = GetAssetMap(am, bundle); string[] names = bundle.GetAllAssetNames(); bundleAssets = bundle.LoadAllAssets(); int index = 0; foreach (string fileName in names) { string withoutExt = fileName.Substring(0, fileName.Length - 4); string assetName = withoutExt.Split('/')[0]; long pathId = long.Parse(withoutExt.Split('/')[1]); if (assetName == "" && pathId == 0) { index++; continue; } assetMap.Add(new AssetID(assetName, pathId), index); index++; } EditDiffer.usedIds.Clear(); int i = 0; foreach (AssetFileInfoEx info in assetsTable.pAssetFileInfo) { EditorUtility.DisplayProgressBar("HKEdit", "Creating GameObjects", i / (float)assetsTable.pAssetFileInfo.Length); if (info.curFileType == GAMEOBJECT) { RecurseGameObjects(info, true); } EditDiffer.usedIds.Add(info.index); i++; } EditorUtility.ClearProgressBar(); }
private bool GetDataFiles(out string lootDistributions, out Dictionary <string, WorldEntityInfo> worldEntityData) { lootDistributions = ""; worldEntityData = new Dictionary <string, WorldEntityInfo>(); string resourcesPath = ""; Optional <string> steamPath = SteamFinder.FindSteamGamePath(264710, "Subnautica"); string gameResourcesPath = ""; if (!steamPath.IsEmpty()) { gameResourcesPath = Path.Combine(steamPath.Get(), "Subnautica_Data/resources.assets"); } if (File.Exists(gameResourcesPath)) { resourcesPath = gameResourcesPath; } else if (File.Exists("../resources.assets")) { resourcesPath = Path.GetFullPath("../resources.assets"); } else if (File.Exists("resources.assets")) { resourcesPath = Path.GetFullPath("resources.assets"); } else { throw new FileNotFoundException("Make sure resources.assets is in current or parent directory and readable."); } using (FileStream resStream = new FileStream(resourcesPath, FileMode.Open)) using (AssetsFileReader resReader = new AssetsFileReader(resStream)) { AssetsFile resourcesFile = new AssetsFile(resReader); AssetsFileTable resourcesFileTable = new AssetsFileTable(resourcesFile); foreach (AssetFileInfoEx afi in resourcesFileTable.pAssetFileInfo) { if (afi.curFileType == TEXT_CLASS_ID) { resourcesFile.reader.Position = afi.absoluteFilePos; string assetName = resourcesFile.reader.ReadCountStringInt32(); if (assetName == "EntityDistributions") { resourcesFile.reader.Align(); lootDistributions = resourcesFile.reader.ReadCountStringInt32().Replace("\\n", ""); } } else if (afi.curFileType == MONOBEHAVIOUR_CLASS_ID) { resourcesFile.reader.Position = afi.absoluteFilePos; resourcesFile.reader.Position += 28; string assetName = resourcesFile.reader.ReadCountStringInt32(); if (assetName == "WorldEntityData") { resourcesFile.reader.Align(); uint size = resourcesFile.reader.ReadUInt32(); WorldEntityInfo wei; for (int i = 0; i < size; i++) { wei = new WorldEntityInfo(); wei.classId = resourcesFile.reader.ReadCountStringInt32(); wei.techType = (TechType)resourcesFile.reader.ReadInt32(); wei.slotType = (EntitySlot.Type)resourcesFile.reader.ReadInt32(); wei.prefabZUp = resourcesFile.reader.ReadBoolean(); resourcesFile.reader.Align(); wei.cellLevel = (LargeWorldEntity.CellLevel)resourcesFile.reader.ReadInt32(); wei.localScale = new UnityEngine.Vector3(resourcesFile.reader.ReadSingle(), resourcesFile.reader.ReadSingle(), resourcesFile.reader.ReadSingle()); worldEntityData.Add(wei.classId, wei); } } } } } return(true); }
private List <AssetInfo> GetFSMInfos(AssetsFile file, AssetsFileTable table, bool hasDataField) { List <AssetInfo> assetInfos = new List <AssetInfo>(); uint assetCount = table.assetFileInfoCount; uint fsmTypeId = 0; foreach (AssetFileInfoEx info in table.assetFileInfo) { bool isMono = false; if (fsmTypeId == 0) { ushort monoType; if (file.header.format <= 0x10) { monoType = info.scriptIndex; } else { monoType = file.typeTree.unity5Types[info.curFileTypeOrIndex].scriptIndex; } if (monoType != 0xFFFF) { isMono = true; } } else if (info.curFileType == fsmTypeId) { isMono = true; } if (isMono) { AssetTypeInstance monoAti = am.GetATI(file, info); AssetExternal ext = am.GetExtAsset(curFile, monoAti.GetBaseField().Get("m_Script")); AssetTypeInstance scriptAti = am.GetExtAsset(curFile, monoAti.GetBaseField().Get("m_Script")).instance; AssetTypeInstance goAti = am.GetExtAsset(curFile, monoAti.GetBaseField().Get("m_GameObject")).instance; if (goAti == null) //found a scriptable object, oops { fsmTypeId = 0; continue; } string m_Name = goAti.GetBaseField().Get("m_Name").GetValue().AsString(); string m_ClassName = scriptAti.GetBaseField().Get("m_ClassName").GetValue().AsString(); if (m_ClassName == "PlayMakerFSM") { if (fsmTypeId == 0) { fsmTypeId = info.curFileType; } AssetsFileReader reader = file.reader; long oldPos = reader.BaseStream.Position; reader.BaseStream.Position = info.absoluteFilePos; reader.BaseStream.Position += 28; uint length = reader.ReadUInt32(); reader.ReadBytes((int)length); reader.Align(); reader.BaseStream.Position += 16; if (!hasDataField) { reader.BaseStream.Position -= 4; } uint length2 = reader.ReadUInt32(); string fsmName = Encoding.UTF8.GetString(reader.ReadBytes((int)length2)); reader.BaseStream.Position = oldPos; assetInfos.Add(new AssetInfo() { id = info.index, size = info.curFileSize, name = m_Name + "-" + fsmName }); } } } assetInfos.Sort((x, y) => x.name.CompareTo(y.name)); return(assetInfos); }
public static byte[] CreateBundleFromLevel(AssetsManager am, AssetsFileInstance inst) { AssetsFile file = inst.file; AssetsFileTable table = inst.table; string folderName = Path.GetDirectoryName(inst.path); ulong pathId = 2; List <AssetsReplacer> assets = new List <AssetsReplacer>(); Dictionary <AssetID, ulong> assetMap = new Dictionary <AssetID, ulong>(); //get all sprites int i = 0; List <AssetFileInfoEx> infos = table.GetAssetsOfType(0xD4); List <ulong> spriteIds = new List <ulong>(); foreach (AssetFileInfoEx info in infos) { //honestly this is a really trash way to do this //we have a better scene exporter but it would //take some work to fix it up and block certain assets EditorUtility.DisplayProgressBar("HKEdit", "Creating scene bundle", i / (float)infos.Count); AssetTypeValueField baseField = GetBaseField(am, file, info); AssetTypeValueField m_Sprite = baseField.Get("m_Sprite"); AssetFileInfoEx spriteInfo = am.GetExtAsset(inst, m_Sprite, true).info; AssetsFileInstance spriteInst; if (m_Sprite.Get("m_FileID").GetValue().AsInt() == 0) { spriteInst = inst; } else { spriteInst = inst.dependencies[m_Sprite.Get("m_FileID").GetValue().AsInt() - 1]; } int spriteFileId = m_Sprite.Get("m_FileID").GetValue().AsInt(); long spritePathId = m_Sprite.Get("m_PathID").GetValue().AsInt64(); if (assetMap.ContainsKey(new AssetID(Path.GetFileName(spriteInst.path), spritePathId)) || (spriteFileId == 0 && spritePathId == 0)) { i++; continue; } AssetTypeValueField spriteBaseField = GetBaseField(am, spriteInst.file, spriteInfo); AssetTypeValueField m_RD = spriteBaseField.Get("m_RD"); AssetTypeValueField texture = m_RD.Get("texture"); AssetTypeValueField alphaTexture = m_RD.Get("alphaTexture"); AssetsFileInstance textureInst, alphaTextureInst; if (texture.Get("m_FileID").GetValue().AsInt() == 0) { textureInst = spriteInst; } else { textureInst = spriteInst.dependencies[texture.Get("m_FileID").GetValue().AsInt() - 1]; } if (alphaTexture.Get("m_FileID").GetValue().AsInt() == 0) { alphaTextureInst = spriteInst; } else { alphaTextureInst = spriteInst.dependencies[alphaTexture.Get("m_FileID").GetValue().AsInt() - 1]; } AssetTypeInstance textureAti = am.GetExtAsset(spriteInst, texture, false).instance; AssetTypeInstance alphaTextureAti = am.GetExtAsset(spriteInst, alphaTexture, false).instance; ulong textureId = 0, alphaTextureId = 0; if (textureAti != null) { AssetID id = new AssetID(Path.GetFileName(textureInst.path), texture.Get("m_PathID").GetValue().AsInt64()); if (!assetMap.ContainsKey(id)) { textureId = pathId; assetMap.Add(id, pathId); assets.Add(TextureConverter.ConvertTexture(textureAti.GetBaseField(), pathId++, folderName)); } else { textureId = assetMap[id]; } } if (alphaTextureAti != null) { AssetID id = new AssetID(Path.GetFileName(alphaTextureInst.path), alphaTexture.Get("m_PathID").GetValue().AsInt64()); if (!assetMap.ContainsKey(id)) { alphaTextureId = pathId; assetMap.Add(id, pathId); assets.Add(TextureConverter.ConvertTexture(alphaTextureAti.GetBaseField(), pathId++, folderName)); } else { alphaTextureId = assetMap[id]; } } AssetTypeValueField m_Materials = baseField.Get("m_Materials").Get("Array"); if (m_Materials.GetValue().AsArray().size > 0) { AssetTypeValueField material = baseField.Get("m_Materials").Get("Array")[0]; AssetsFileInstance materialInst; int materialFileId = material.Get("m_FileID").GetValue().AsInt(); if (materialFileId == 0) { materialInst = inst; } else { materialInst = inst.dependencies[materialFileId - 1]; } AssetID materialId = new AssetID(Path.GetFileName(materialInst.path), material.Get("m_PathID").GetValue().AsInt64()); if (!assetMap.ContainsKey(materialId)) { AssetTypeValueField materialBaseField = am.GetExtAsset(inst, material).instance.GetBaseField(); AssetTypeValueField shader = materialBaseField.Get("m_Shader"); ulong shaderPathId = RecurseShaderDependencies(am, materialInst, pathId, shader, assets, assetMap, out pathId); assetMap.Add(materialId, pathId); assets.Add(MaterialConverter.ConvertMaterial(materialBaseField, pathId++, shaderPathId)); } } assetMap.Add(new AssetID(Path.GetFileName(spriteInst.path), spritePathId), pathId); spriteIds.Add(pathId); assets.Add(SpriteConverter.ConvertSprite(spriteBaseField, pathId++, textureId, alphaTextureId)); i++; } assetMap.Add(new AssetID(0), pathId); assets.Add(HeaderInformation.CreateHeaderInformation(assetMap, pathId++)); assets.Insert(0, BundleMeta.CreateBundleInformation(assetMap, spriteIds, 1)); //assets.Add(BundleMeta.CreateBundleInformation(assetMap, 1)); //todo: pull from original assets file, cldb is not always update to date List <Type_0D> types = new List <Type_0D> { FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0x8E)), //AssetBundle FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0x1C)), //Texture2D FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0x31)), //TextAsset FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0xD4)), //SpriteRenderer FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0xD5)), //Sprite //FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0x31)), //TextAsset FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0x15)), //Material FixTypeTree(C2T5.Cldb2TypeTree(am.classFile, 0x30)) //Shader }; const string ver = "2017.4.10f1"; //const string ver = "2018.2.1f1"; byte[] blankData = BundleCreator.CreateBlankAssets(ver, types); AssetsFile blankFile = new AssetsFile(new AssetsFileReader(new MemoryStream(blankData))); byte[] data = null; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { blankFile.WriteFix(writer, 0, assets.ToArray(), 0); data = ms.ToArray(); } EditorUtility.DisplayProgressBar("HKEdit", "Creating bundle", 1); using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { BundleCreator.CreateBlankBundle(ver, data.Length).Write(writer, data); return(ms.ToArray()); } }
public static void ShowOpenFileDialog() { string path = EditorUtility.OpenFilePanel("Open level file", "", ""); if (path.Length != 0) { HKSelect window = GetWindow <HKSelect>(); window.am = new AssetsManager(); AssetsFileInstance assetsFileInstance = window.am.LoadAssetsFile(path, true); //might work with false AssetsFile assetsFile = assetsFileInstance.file; AssetsFileTable assetsTable = assetsFileInstance.table; window.am.LoadClassPackage(Path.Combine(Application.dataPath, "cldb.dat")); window.folderPath = Path.GetDirectoryName(path); Stream assetStream = assetsFileInstance.stream; List <AssetInfo> assetInfos = new List <AssetInfo>(); uint fsmTypeId = 0; foreach (AssetFileInfoEx info in assetsTable.pAssetFileInfo) { bool isMono = false; if (fsmTypeId == 0) { ushort monoType = assetsFile.typeTree.pTypes_Unity5[info.curFileTypeOrIndex].scriptIndex; if (monoType != 0xFFFF) { isMono = true; } } else if (info.curFileType == fsmTypeId) { isMono = true; } if (isMono) { AssetTypeInstance monoAti = window.am.GetATI(assetsFile, info); AssetTypeInstance scriptAti = window.am.GetExtAsset(assetsFileInstance, monoAti.GetBaseField().Get("m_Script")).instance; AssetTypeInstance goAti = window.am.GetExtAsset(assetsFileInstance, monoAti.GetBaseField().Get("m_GameObject")).instance; if (goAti == null) //found a scriptable object, oops { fsmTypeId = 0; continue; } string m_Name = goAti.GetBaseField().Get("m_Name").GetValue().AsString(); string m_ClassName = scriptAti.GetBaseField().Get("m_ClassName").GetValue().AsString(); if (m_ClassName == "PlayMakerFSM") { if (fsmTypeId == 0) { fsmTypeId = info.curFileType; } BinaryReader reader = new BinaryReader(assetStream); long oldPos = assetStream.Position; reader.BaseStream.Position = (long)info.absoluteFilePos; reader.BaseStream.Position += 28; uint length = reader.ReadUInt32(); reader.ReadBytes((int)length); long pad = 4 - (reader.BaseStream.Position % 4); if (pad != 4) { reader.BaseStream.Position += pad; } reader.BaseStream.Position += 16; uint length2 = reader.ReadUInt32(); string fsmName = Encoding.ASCII.GetString(reader.ReadBytes((int)length2)); reader.BaseStream.Position = oldPos; assetInfos.Add(new AssetInfo() { id = info.index, size = info.curFileSize, name = m_Name + "-" + fsmName }); } } } assetInfos.Sort((x, y) => x.name.CompareTo(y.name)); window.assetInfos = assetInfos; window.strings = assetInfos.Select(i => i.name).ToArray(); } }
public static byte[] CreateBundleFromLevel(AssetsManager am, AssetsFileInstance inst) { EditorUtility.DisplayProgressBar("HKEdit", "Reading Files...", 0f); am.UpdateDependencies(); //quicker asset id lookup for (int i = 0; i < am.files.Count; i++) { AssetsFileInstance afi = am.files[i]; EditorUtility.DisplayProgressBar("HKEdit", "Generating QLTs", (float)i / am.files.Count); afi.table.GenerateQuickLookupTree(); } //setup AssetsFile file = inst.file; AssetsFileTable table = inst.table; string folderName = Path.GetDirectoryName(inst.path); List <AssetFileInfoEx> infos = table.pAssetFileInfo.ToList(); List <string> fileNames = new List <string>(); Dictionary <AssetID, byte[]> deps = new Dictionary <AssetID, byte[]>(); fileNames.Add(inst.name); //add own ids to list so we don't reread them foreach (AssetFileInfoEx info in infos) { if (info.curFileType != 1) { continue; } AssetID id = new AssetID(inst.name, (long)info.index); deps.Add(id, null); } //look through each field in each asset in this file for (int i = 0; i < infos.Count; i++) { AssetFileInfoEx info = infos[i]; if (info.curFileType != 1) { continue; } EditorUtility.DisplayProgressBar("HKEdit", "Crawling PPtrs", (float)i / infos.Count); ReferenceCrawler.CrawlPPtrs(am, inst, info.index, fileNames, deps); } //add typetree data for dependencies long curId = 1; List <Type_0D> types = new List <Type_0D>(); List <string> typeNames = new List <string>(); List <AssetsReplacer> assets = new List <AssetsReplacer>(); Dictionary <string, AssetsFileInstance> insts = new Dictionary <string, AssetsFileInstance>(); //asset id is our custom id that uses filename/pathid instead of fileid/pathid //asset id to path id Dictionary <AssetID, long> aidToPid = new Dictionary <AssetID, long>(); //script id to mono id Dictionary <ScriptID, ushort> sidToMid = new Dictionary <ScriptID, ushort>(); uint lastId = 0; ushort nextMonoId = 0; int depCount = 0; foreach (KeyValuePair <AssetID, byte[]> dep in deps) { EditorUtility.DisplayProgressBar("HKEdit", "Fixing Dependencies", (float)depCount / deps.Keys.Count); AssetID id = dep.Key; byte[] assetData = dep.Value; AssetsFileInstance afInst = null; if (insts.ContainsKey(id.fileName)) { afInst = insts[id.fileName]; } else { afInst = am.files.First(f => f.name == id.fileName); } if (afInst == null) { continue; } AssetFileInfoEx inf = afInst.table.getAssetInfo((ulong)id.pathId); if (lastId != inf.curFileType) { lastId = inf.curFileType; } ClassDatabaseType clType = AssetHelper.FindAssetClassByID(am.classFile, inf.curFileType); string clName = clType.name.GetString(am.classFile); ushort monoIndex = 0xFFFF; if (inf.curFileType != 0x72) { if (!typeNames.Contains(clName)) { Type_0D type0d = C2T5.Cldb2TypeTree(am.classFile, clName); type0d.classId = (int)inf.curFileType; //? types.Add(type0d); typeNames.Add(clName); } } else { //unused for now AssetTypeValueField baseField = am.GetATI(afInst.file, inf).GetBaseField(); AssetTypeValueField m_Script = baseField.Get("m_Script"); AssetTypeValueField scriptBaseField = am.GetExtAsset(afInst, m_Script).instance.GetBaseField(); string m_ClassName = scriptBaseField.Get("m_ClassName").GetValue().AsString(); string m_Namespace = scriptBaseField.Get("m_Namespace").GetValue().AsString(); string m_AssemblyName = scriptBaseField.Get("m_AssemblyName").GetValue().AsString(); ScriptID sid = new ScriptID(m_ClassName, m_Namespace, m_AssemblyName); if (!sidToMid.ContainsKey(sid)) { MonoClass mc = new MonoClass(); mc.Read(m_ClassName, Path.Combine(Path.Combine(Path.GetDirectoryName(inst.path), "Managed"), m_AssemblyName), afInst.file.header.format); Type_0D type0d = C2T5.Cldb2TypeTree(am.classFile, clName); TemplateFieldToType0D typeConverter = new TemplateFieldToType0D(); TypeField_0D[] monoFields = typeConverter.TemplateToTypeField(mc.children, type0d); type0d.pStringTable = typeConverter.stringTable; type0d.stringTableLen = (uint)type0d.pStringTable.Length; type0d.scriptIndex = nextMonoId; type0d.pTypeFieldsEx = type0d.pTypeFieldsEx.Concat(monoFields).ToArray(); type0d.typeFieldsExCount = (uint)type0d.pTypeFieldsEx.Length; types.Add(type0d); sidToMid.Add(sid, nextMonoId); nextMonoId++; } monoIndex = sidToMid[sid]; } aidToPid.Add(id, curId); AssetsReplacer rep = new AssetsReplacerFromMemory(0, (ulong)curId, (int)inf.curFileType, monoIndex, assetData); assets.Add(rep); curId++; depCount++; } byte[] blankData = BundleCreator.CreateBlankAssets(ver, types); AssetsFile blankFile = new AssetsFile(new AssetsFileReader(new MemoryStream(blankData))); EditorUtility.DisplayProgressBar("HKEdit", "Writing first file...", 0f); byte[] data = null; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { blankFile.Write(writer, 0, assets.ToArray(), 0); data = ms.ToArray(); } //File.WriteAllBytes("debug.assets", data); MemoryStream msn = new MemoryStream(data); AssetsManager amn = new AssetsManager(); amn.classFile = am.classFile; AssetsFileInstance instn = amn.LoadAssetsFile(msn, ((FileStream)inst.file.reader.BaseStream).Name, false); instn.table.GenerateQuickLookupTree(); deps.Clear(); List <AssetsReplacer> assetsn = new List <AssetsReplacer>(); //gameobject id to mono id Dictionary <long, long> gidToMid = new Dictionary <long, long>(); long nextBehaviourId = (long)instn.table.pAssetFileInfo.Max(i => i.index) + 1; CreateEditDifferTypeTree(amn.classFile, instn); CreateSceneMetadataTypeTree(amn.classFile, instn); Random rand = new Random(); rand.Next(); foreach (KeyValuePair <AssetID, long> kvp in aidToPid) { AssetFileInfoEx inf = instn.table.getAssetInfo((ulong)kvp.Value); if (inf.curFileType == 0x01) { gidToMid.Add(kvp.Value, nextBehaviourId); assetsn.Add(CreateEditDifferMonoBehaviour(kvp.Value, kvp.Key, nextBehaviourId++, rand)); } } for (int i = 0; i < instn.table.pAssetFileInfo.Length; i++) { AssetFileInfoEx inf = instn.table.pAssetFileInfo[i]; EditorUtility.DisplayProgressBar("HKEdit", "Crawling PPtrs", (float)i / instn.table.pAssetFileInfo.Length); ReferenceCrawler.CrawlReplacePPtrs(amn, instn, inf.index, fileNames, deps, aidToPid, gidToMid); } //add monoscript assets to preload table to make unity happy List <AssetPPtr> preloadPptrs = new List <AssetPPtr>(); preloadPptrs.Add(new AssetPPtr(1, 11500000)); preloadPptrs.Add(new AssetPPtr(2, 11500000)); foreach (KeyValuePair <AssetID, byte[]> dep in deps) { AssetID id = dep.Key; byte[] assetData = dep.Value; long pid = id.pathId; if (pid == 1) { assetData = AddMetadataMonobehaviour(assetData, nextBehaviourId); } AssetFileInfoEx inf = instn.table.getAssetInfo((ulong)pid); ushort monoId = instn.file.typeTree.pTypes_Unity5[inf.curFileTypeOrIndex].scriptIndex; assetsn.Add(new AssetsReplacerFromMemory(0, (ulong)pid, (int)inf.curFileType, monoId, assetData)); if (inf.curFileType == 0x73) { preloadPptrs.Add(new AssetPPtr(0, (ulong)pid)); } } List <long> usedIds = assetsn.Select(a => (long)a.GetPathID()).ToList(); //will break if no gameobjects but I don't really care at this point assetsn.Add(CreateSceneMetadataMonoBehaviour(1, nextBehaviourId++, inst.name, usedIds)); instn.file.preloadTable.items = preloadPptrs.ToArray(); instn.file.preloadTable.len = (uint)instn.file.preloadTable.items.Length; //add dependencies to monobehaviours List <AssetsFileDependency> fileDeps = new List <AssetsFileDependency>(); AddScriptDependency(fileDeps, Constants.editDifferMsEditorScriptHash, Constants.editDifferLsEditorScriptHash); AddScriptDependency(fileDeps, Constants.sceneMetadataMsEditorScriptHash, Constants.sceneMetadataLsEditorScriptHash); instn.file.dependencies.pDependencies = fileDeps.ToArray(); instn.file.dependencies.dependencyCount = (uint)fileDeps.Count; EditorUtility.DisplayProgressBar("HKEdit", "Writing second file...", 0f); byte[] datan = null; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { instn.file.Write(writer, 0, assetsn.ToArray(), 0); datan = ms.ToArray(); } EditorUtility.ClearProgressBar(); return(datan); }
public static void GenerateDiffFile(AssetsManager am, AssetsFileInstance origInst, AssetsFileInstance newInst, HKWEMeta meta) { EditorUtility.DisplayProgressBar("HKEdit", "Reading dependencies...", 0.5f); am.UpdateDependencies(); DiffData result = new DiffData() { goChanges = new List <GameObjectChange>(), goAdditions = new List <GameObjectAddition>() }; Dictionary <EditDifferData, long> differToNewId = new Dictionary <EditDifferData, long>(); Dictionary <long, EditDifferData> origIdToDiffer = new Dictionary <long, EditDifferData>(); List <EditDifferData> differData = new List <EditDifferData>(); AssetsFileTable newTable = newInst.table; List <AssetFileInfoEx> newGos = newTable.GetAssetsOfType(0x01); for (int i = 0; i < newGos.Count; i++) { if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Finding diff IDs... (step 1/3)", (float)i / newGos.Count); } AssetFileInfoEx inf = newGos[i]; AssetTypeValueField baseField = am.GetATI(newInst.file, inf).GetBaseField(); AssetTypeValueField editDifferMono = GetEDMono(am, newInst, baseField); EditDifferData diff = new EditDifferData() { fileId = editDifferMono.Get("fileId").GetValue().AsInt(), pathId = editDifferMono.Get("pathId").GetValue().AsInt64(), origPathId = editDifferMono.Get("origPathId").GetValue().AsInt64(), newAsset = editDifferMono.Get("newAsset").GetValue().AsBool() }; origIdToDiffer[diff.origPathId] = diff; differData.Add(diff); } ////////////////////////// AssetsFileTable origTable = origInst.table; List <AssetFileInfoEx> origGos = origTable.GetAssetsOfType(0x01); List <long> origDeletIds = new List <long>(); int nextBundleId = 1; // == delete changes == // for (int i = 0; i < origGos.Count; i++) { if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Checking for deletes... (step 2/3)", (float)i / origGos.Count); } AssetFileInfoEx inf = newGos[i]; if (!differData.Any(d => d.origPathId == inf.index)) { GameObjectChange change = new GameObjectChange { flags = GameObjectChangeFlags.Deleted }; result.goChanges.Add(change); origDeletIds.Add(inf.index); } } // == add changes == // for (int i = 0; i < differData.Count; i++) { if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Checking for additions... (step 2/3)", (float)i / differData.Count); } EditDifferData dat = differData[i]; if (dat.newAsset) { ReferenceCrawlerBundle crawler = new ReferenceCrawlerBundle(am); long newPathId = differToNewId[dat]; AssetFileInfoEx inf = newInst.table.GetAssetInfo(newPathId); crawler.SetReferences(newInst, inf); GameObjectAddition addition = new GameObjectAddition { bundleId = nextBundleId, parentId = dat.pathId, dependencies = new List <GameObjectAdditionDependency>() }; nextBundleId++; foreach (KeyValuePair <AssetID, AssetID> goRef in crawler.references) { addition.dependencies.Add(new GameObjectAdditionDependency { parentId = goRef.Key.pathId, bundleId = goRef.Value.pathId }); } result.goAdditions.Add(addition); } else { ReferenceCrawlerBundle crawler = new ReferenceCrawlerBundle(am); long newPathId = differToNewId[dat]; AssetFileInfoEx inf = newInst.table.GetAssetInfo(newPathId); crawler.SetReferences(newInst, inf); } } }
private void LoadFSMs(string path) { string folderName = Path.GetDirectoryName(path); curFile = am.LoadAssetsFile(path, true); am.UpdateDependencies(); AssetsFile file = curFile.file; AssetsFileTable table = curFile.table; List <AssetInfo> assetInfos = new List <AssetInfo>(); uint assetCount = table.assetFileInfoCount; uint fsmTypeId = 0; foreach (AssetFileInfoEx info in table.pAssetFileInfo) { bool isMono = false; if (fsmTypeId == 0) { ushort monoType = file.typeTree.pTypes_Unity5[info.curFileTypeOrIndex].scriptIndex; if (monoType != 0xFFFF) { isMono = true; } } else if (info.curFileType == fsmTypeId) { isMono = true; } if (isMono) { AssetTypeInstance monoAti = am.GetATI(file, info); AssetTypeInstance scriptAti = am.GetExtAsset(curFile, monoAti.GetBaseField().Get("m_Script")).instance; AssetTypeInstance goAti = am.GetExtAsset(curFile, monoAti.GetBaseField().Get("m_GameObject")).instance; if (goAti == null) //found a scriptable object, oops { fsmTypeId = 0; continue; } string m_Name = goAti.GetBaseField().Get("m_Name").GetValue().AsString(); string m_ClassName = scriptAti.GetBaseField().Get("m_ClassName").GetValue().AsString(); if (m_ClassName == "PlayMakerFSM") { if (fsmTypeId == 0) { fsmTypeId = info.curFileType; } BinaryReader reader = file.reader; long oldPos = reader.BaseStream.Position; reader.BaseStream.Position = (long)info.absoluteFilePos; reader.BaseStream.Position += 28; uint length = reader.ReadUInt32(); reader.ReadBytes((int)length); long pad = 4 - (reader.BaseStream.Position % 4); if (pad != 4) { reader.BaseStream.Position += pad; } reader.BaseStream.Position += 16; uint length2 = reader.ReadUInt32(); string fsmName = Encoding.ASCII.GetString(reader.ReadBytes((int)length2)); reader.BaseStream.Position = oldPos; assetInfos.Add(new AssetInfo() { id = info.index, size = info.curFileSize, name = m_Name + "-" + fsmName }); } } } assetInfos.Sort((x, y) => x.name.CompareTo(y.name)); FSMSelector selector = new FSMSelector(assetInfos); selector.ShowDialog(); //todo separate into separate method(s) if (selector.selectedID == -1) { return; } AssetFileInfoEx afi = table.getAssetInfo((ulong)selector.selectedID); string tabName = assetInfos.FirstOrDefault(i => i.id == (ulong)selector.selectedID).name; TabItem tab = new TabItem { //Name = tabName.Replace(" ","").Replace("-","_").Replace("(","_").Replace(")","_"), Header = tabName }; ignoreChangeEvent = true; fsmTabControl.Items.Add(tab); fsmTabControl.SelectedItem = tab; ignoreChangeEvent = false; SaveAndClearNodes(); mt.Matrix = Matrix.Identity; currentTab++; AssetTypeValueField baseField = am.GetMonoBaseFieldCached(curFile, afi, Path.Combine(Path.GetDirectoryName(curFile.path), "Managed")); //from uabe //ClassDatabaseType cldt = AssetHelper.FindAssetClassByID(am.classFile, afi.curFileType); //AssetTypeTemplateField pBaseField = new AssetTypeTemplateField(); //pBaseField.FromClassDatabase(am.classFile, cldt, 0); //AssetTypeInstance mainAti = new AssetTypeInstance(1, new[] { pBaseField }, file.reader, false, afi.absoluteFilePos); //AssetTypeTemplateField[] desMonos; //desMonos = TryDeserializeMono(mainAti, am, folderName); //if (desMonos != null) //{ // AssetTypeTemplateField[] templateField = pBaseField.children.Concat(desMonos).ToArray(); // pBaseField.children = templateField; // pBaseField.childrenCount = (uint)pBaseField.children.Length; // // mainAti = new AssetTypeInstance(1, new[] { pBaseField }, file.reader, false, afi.absoluteFilePos); //} //AssetTypeValueField baseField = mainAti.GetBaseField(); AssetTypeValueField fsm = baseField.Get("fsm"); AssetTypeValueField states = fsm.Get("states"); AssetTypeValueField globalTransitions = fsm.Get("globalTransitions"); dataVersion = fsm.Get("dataVersion").GetValue().AsInt(); for (int i = 0; i < states.GetValue().AsArray().size; i++) { AssetTypeValueField state = states.Get((uint)i); //move all of this into node string name = state.Get("name").GetValue().AsString(); AssetTypeValueField rect = state.Get("position"); Rect dotNetRect = new Rect(rect.Get("x").GetValue().AsFloat(), rect.Get("y").GetValue().AsFloat(), rect.Get("width").GetValue().AsFloat(), rect.Get("height").GetValue().AsFloat()); AssetTypeValueField transitions = state.Get("transitions"); uint transitionCount = transitions.GetValue().AsArray().size; FsmTransition[] dotNetTransitions = new FsmTransition[transitionCount]; for (int j = 0; j < transitionCount; j++) { dotNetTransitions[j] = new FsmTransition(transitions.Get((uint)j)); } Node node = new Node(state, name, dotNetRect, dotNetTransitions); nodes.Add(node); node.grid.MouseLeftButtonDown += (object sender, MouseButtonEventArgs e) => { foreach (Node node2 in nodes) { node2.Selected = false; } node.Selected = true; SidebarData(node, curFile); }; graphCanvas.Children.Add(node.grid); } for (int i = 0; i < globalTransitions.GetValue().AsArray().size; i++) { AssetTypeValueField transition = globalTransitions.Get((uint)i); FsmTransition dotNetTransition = new FsmTransition(transition); Node toNode = nodes.FirstOrDefault(n => n.name == dotNetTransition.toState); if (toNode == null) { System.Diagnostics.Debug.WriteLine("transition " + dotNetTransition.fsmEvent.name + " going to non-existant node " + dotNetTransition.toState); } else { Rect rect = new Rect( toNode.Transform.X, toNode.Transform.Y - 50, toNode.Transform.Width, 18); if (toNode != null) { Node node = new Node(null, dotNetTransition.fsmEvent.name, rect, new[] { dotNetTransition }); nodes.Add(node); graphCanvas.Children.Add(node.grid); } } } foreach (Node node in nodes) { if (node.transitions.Length <= 0) { continue; } float yPos = 24; foreach (FsmTransition trans in node.transitions) { Node endNode = nodes.FirstOrDefault(n => n.name == trans.toState); if (endNode != null) { Point start, end, startMiddle, endMiddle; if (node.state != null) { start = ComputeLocation(node, endNode, yPos, out bool isLeftStart); end = ComputeLocation(endNode, node, 10, out bool isLeftEnd); double dist = 70; if (isLeftStart == isLeftEnd) { dist *= 0.5; } if (!isLeftStart) { startMiddle = new Point(start.X - dist, start.Y); } else { startMiddle = new Point(start.X + dist, start.Y); } if (!isLeftEnd) { endMiddle = new Point(end.X - dist, end.Y); } else { endMiddle = new Point(end.X + dist, end.Y); } } else { start = new Point(node.Transform.X + node.Transform.Width / 2, node.Transform.Y + node.Transform.Height); end = new Point(endNode.Transform.X + endNode.Transform.Width / 2, endNode.Transform.Y); startMiddle = new Point(start.X, start.Y + 1); endMiddle = new Point(end.X, end.Y - 1); } CurvedArrow arrow = new CurvedArrow() { Points = new PointCollection(new List <Point>() { start, startMiddle, endMiddle, end }), StrokeThickness = 2, Stroke = Brushes.Black, Fill = Brushes.Black, IsHitTestVisible = true }; arrow.MouseEnter += (object sender, MouseEventArgs e) => { arrow.Stroke = Brushes.LightGray; arrow.Fill = Brushes.LightGray; }; arrow.MouseLeave += (object sender, MouseEventArgs e) => { arrow.Stroke = Brushes.Black; arrow.Fill = Brushes.Black; }; Panel.SetZIndex(arrow, -1); graphCanvas.Children.Add(arrow); } else { System.Diagnostics.Debug.WriteLine(node.name + " failed to connect to " + trans.toState); } yPos += 16; } } AssetTypeValueField events = fsm.Get("events"); for (int i = 0; i < events.GetValue().AsArray().size; i++) { AssetTypeValueField @event = events.Get((uint)i); string name = @event.Get("name").GetValue().AsString(); bool isSystemEvent = @event.Get("isSystemEvent").GetValue().AsBool(); bool isGlobal = @event.Get("isGlobal").GetValue().AsBool(); eventList.Children.Add(CreateSidebarRow(name, isSystemEvent, isGlobal)); } AssetTypeValueField variables = fsm.Get("variables"); AssetTypeValueField floatVariables = variables.Get("floatVariables"); AssetTypeValueField intVariables = variables.Get("intVariables"); AssetTypeValueField boolVariables = variables.Get("boolVariables"); AssetTypeValueField stringVariables = variables.Get("stringVariables"); AssetTypeValueField vector2Variables = variables.Get("vector2Variables"); AssetTypeValueField vector3Variables = variables.Get("vector3Variables"); AssetTypeValueField colorVariables = variables.Get("colorVariables"); AssetTypeValueField rectVariables = variables.Get("rectVariables"); AssetTypeValueField quaternionVariables = variables.Get("quaternionVariables"); AssetTypeValueField gameObjectVariables = variables.Get("gameObjectVariables"); AssetTypeValueField objectVariables = variables.Get("objectVariables"); AssetTypeValueField materialVariables = variables.Get("materialVariables"); AssetTypeValueField textureVariables = variables.Get("textureVariables"); AssetTypeValueField arrayVariables = variables.Get("arrayVariables"); AssetTypeValueField enumVariables = variables.Get("enumVariables"); variableList.Children.Add(CreateSidebarHeader("Floats")); for (int i = 0; i < floatVariables.GetValue().AsArray().size; i++) { string name = floatVariables.Get((uint)i).Get("name").GetValue().AsString(); string value = floatVariables.Get((uint)i).Get("value").GetValue().AsFloat().ToString(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("Ints")); for (int i = 0; i < intVariables.GetValue().AsArray().size; i++) { string name = intVariables.Get((uint)i).Get("name").GetValue().AsString(); string value = intVariables.Get((uint)i).Get("value").GetValue().AsInt().ToString(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("Bools")); for (int i = 0; i < boolVariables.GetValue().AsArray().size; i++) { string name = boolVariables.Get((uint)i).Get("name").GetValue().AsString(); string value = boolVariables.Get((uint)i).Get("value").GetValue().AsBool().ToString().ToLower(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("Strings")); for (int i = 0; i < stringVariables.GetValue().AsArray().size; i++) { string name = stringVariables.Get((uint)i).Get("name").GetValue().AsString(); string value = stringVariables.Get((uint)i).Get("value").GetValue().AsString(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("Vector2s")); for (int i = 0; i < vector2Variables.GetValue().AsArray().size; i++) { string name = vector2Variables.Get((uint)i).Get("name").GetValue().AsString(); AssetTypeValueField vector2 = vector2Variables.Get((uint)i).Get("value"); string value = vector2.Get("x").GetValue().AsFloat().ToString() + ", "; value += vector2.Get("y").GetValue().AsFloat().ToString(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("Vector3s")); for (int i = 0; i < vector3Variables.GetValue().AsArray().size; i++) { string name = vector3Variables.Get((uint)i).Get("name").GetValue().AsString(); AssetTypeValueField vector3 = vector3Variables.Get((uint)i).Get("value"); string value = vector3.Get("x").GetValue().AsFloat().ToString() + ", "; value += vector3.Get("x").GetValue().AsFloat().ToString() + ", "; value += vector3.Get("z").GetValue().AsFloat().ToString(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("Colors")); for (int i = 0; i < colorVariables.GetValue().AsArray().size; i++) { string name = colorVariables.Get((uint)i).Get("name").GetValue().AsString(); AssetTypeValueField color = colorVariables.Get((uint)i).Get("value"); string value = ((int)(color.Get("r").GetValue().AsFloat()) * 255).ToString("X2"); value += ((int)(color.Get("g").GetValue().AsFloat()) * 255).ToString("X2"); value += ((int)(color.Get("b").GetValue().AsFloat()) * 255).ToString("X2"); value += ((int)(color.Get("a").GetValue().AsFloat()) * 255).ToString("X2"); Grid sidebarRow = CreateSidebarRow(name, value); TextBox textBox = sidebarRow.Children.OfType <TextBox>().FirstOrDefault(); textBox.BorderBrush = (SolidColorBrush)(new BrushConverter().ConvertFrom("#" + value)); variableList.Children.Add(sidebarRow); } variableList.Children.Add(CreateSidebarHeader("Rects")); for (int i = 0; i < rectVariables.GetValue().AsArray().size; i++) { string name = rectVariables.Get((uint)i).Get("name").GetValue().AsString(); AssetTypeValueField rect = rectVariables.Get((uint)i).Get("value"); string value = rect.Get("x").GetValue().AsFloat().ToString() + ", "; value += rect.Get("y").GetValue().AsFloat().ToString() + ", "; value += rect.Get("width").GetValue().AsFloat().ToString() + ", "; value += rect.Get("height").GetValue().AsFloat().ToString(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("Quaternions")); for (int i = 0; i < quaternionVariables.GetValue().AsArray().size; i++) { string name = quaternionVariables.Get((uint)i).Get("name").GetValue().AsString(); AssetTypeValueField rect = quaternionVariables.Get((uint)i).Get("value"); string value = rect.Get("x").GetValue().AsFloat().ToString() + ", "; value += rect.Get("y").GetValue().AsFloat().ToString() + ", "; value += rect.Get("z").GetValue().AsFloat().ToString() + ", "; value += rect.Get("w").GetValue().AsFloat().ToString(); variableList.Children.Add(CreateSidebarRow(name, value)); } variableList.Children.Add(CreateSidebarHeader("GameObjects")); for (int i = 0; i < gameObjectVariables.GetValue().AsArray().size; i++) { string name = gameObjectVariables.Get((uint)i).Get("name").GetValue().AsString(); AssetTypeValueField gameObject = gameObjectVariables.Get((uint)i).Get("value"); int m_FileID = gameObject.Get("m_FileID").GetValue().AsInt(); long m_PathID = gameObject.Get("m_PathID").GetValue().AsInt64(); string value; if (m_PathID != 0) { value = $"[{m_FileID},{m_PathID}]"; } else { value = ""; } variableList.Children.Add(CreateSidebarRow(name, value)); } }
public static void GenerateDiffFile(AssetsManager am, AssetsFileInstance buildInst, AssetsFileInstance sceneInst, HKWEMeta meta) { EditorUtility.DisplayProgressBar("HKEdit", "Reading dependencies...", 0.5f); am.UpdateDependencies(); ClassDatabaseFile cldb = am.classFile; DiffData result = new DiffData() { goChanges = new List <GameObjectChange>(), goAdditions = new List <GameObjectAddition>() }; Dictionary <EditDifferData, long> differToSceneId = new Dictionary <EditDifferData, long>(); Dictionary <long, EditDifferData> buildIdToDiffer = new Dictionary <long, EditDifferData>(); List <EditDifferData> differData = new List <EditDifferData>(); AssetsFileTable sceneTable = sceneInst.table; List <AssetFileInfoEx> sceneGos = sceneTable.GetAssetsOfType(0x01); for (int i = 0; i < sceneGos.Count; i++) { if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Finding diff IDs... (step 1/3)", (float)i / sceneGos.Count); } AssetFileInfoEx inf = sceneGos[i]; AssetTypeValueField baseField = am.GetATI(sceneInst.file, inf).GetBaseField(); AssetTypeValueField editDifferMono = GetEDMono(am, sceneInst, baseField); EditDifferData diff = new EditDifferData() { fileId = editDifferMono.Get("fileId").GetValue().AsInt(), pathId = editDifferMono.Get("pathId").GetValue().AsInt64(), origPathId = editDifferMono.Get("origPathId").GetValue().AsInt64(), newAsset = editDifferMono.Get("newAsset").GetValue().AsBool() }; buildIdToDiffer[diff.origPathId] = diff; differToSceneId[diff] = inf.index; differData.Add(diff); } ////////////////////////// AssetsFileTable origTable = buildInst.table; List <AssetFileInfoEx> origGos = origTable.GetAssetsOfType(0x01); List <long> origDeletIds = new List <long>(); //int nextBundleId = 1; //// == delete changes == // //for (int i = 0; i < origGos.Count; i++) //{ // if (i % 100 == 0) // EditorUtility.DisplayProgressBar("HKEdit", "Checking for deletes... (step 2/3)", (float)i / origGos.Count); // AssetFileInfoEx inf = sceneGos[i]; // if (!differData.Any(d => d.origPathId == inf.index)) // { // GameObjectChange change = new GameObjectChange // { // flags = GameObjectChangeFlags.Deleted // }; // result.goChanges.Add(change); // origDeletIds.Add(inf.index); // } //} // == add changes == // //to get this working in a built game, we need //built assets (ie pngs -> texture2d) the problem //is there's no easy way to direct unity to do that //without loading the scene and using unity's api //but we can pull out assets into a prefab and build //the prefab but there are problems with duplicate //dependencies being copied, so we pack them all //into one place so that doesn't happen //(for reference, in hkwe1, each gameobject got //its own prefab) //find dependencies ReferenceCrawlerBundle createdCrawler = new ReferenceCrawlerBundle(am); //assets created by the user in the ditor ReferenceCrawlerBundle existingCrawler = new ReferenceCrawlerBundle(am); //assets that already existed in the scene for (int i = 0; i < differData.Count; i++) { if (i % 100 == 0) { EditorUtility.DisplayProgressBar("HKEdit", "Checking for additions... (step 2/3)", (float)i / differData.Count); } EditDifferData dat = differData[i]; if (dat.newAsset) { long sceneId = differToSceneId[dat]; AssetFileInfoEx inf = sceneInst.table.GetAssetInfo(sceneId); createdCrawler.SetReferences(sceneInst, inf); GameObjectAddition addition = new GameObjectAddition { bundleId = createdCrawler.GetNextId(), //? sceneId = dat.pathId, dependencies = new List <GameObjectAdditionDependency>() }; //nextBundleId++; foreach (KeyValuePair <AssetID, AssetID> goRef in createdCrawler.references) { addition.dependencies.Add(new GameObjectAdditionDependency { sceneId = goRef.Key.pathId, bundleId = goRef.Value.pathId }); } result.goAdditions.Add(addition); } else { long newPathId = differToSceneId[dat]; AssetFileInfoEx inf = sceneInst.table.GetAssetInfo(newPathId); existingCrawler.SetReferences(sceneInst, inf); } } //load up all created assets into a prefab List <Type_0D> types = new List <Type_0D>(); List <string> typeNames = new List <string>(); foreach (AssetsReplacer rep in createdCrawler.sceneReplacers) { ClassDatabaseType clType = AssetHelper.FindAssetClassByID(cldb, (uint)rep.GetClassID()); string clName = clType.name.GetString(cldb); if (!typeNames.Contains(clName)) { Type_0D type0d = C2T5.Cldb2TypeTree(cldb, clName); type0d.classId = clType.classId; types.Add(type0d); typeNames.Add(clName); } } List <AssetsReplacer> replacers = new List <AssetsReplacer>(); replacers.Add(CreatePrefabAsset(2)); //better hope id 2 is a gameobject replacers.AddRange(createdCrawler.sceneReplacers); AssetsFile createdFile = new AssetsFile(new AssetsFileReader(new MemoryStream(BundleCreator.CreateBlankAssets(ver, types)))); byte[] data; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(ms)) { createdFile.Write(writer, 0, replacers, 0); data = ms.ToArray(); } }