private void LoadGGM(AssetsFileInstance mainFile) { //swap this with resources so we can actually see ggm assets foreach (AssetFileInfoEx info in mainFile.table.pAssetFileInfo) { ClassDatabaseType type = AssetHelper.FindAssetClassByID(helper.classFile, info.curFileType); if (type.name.GetString(helper.classFile) == "ResourceManager") { AssetTypeInstance inst = helper.GetATI(mainFile.file, info); AssetTypeValueField baseField = inst.GetBaseField(); AssetTypeValueField m_Container = baseField.Get("m_Container").Get("Array"); //Dictionary<string, AssetDetails> paths = new Dictionary<string, AssetDetails>(); List <AssetDetails> assets = new List <AssetDetails>(); for (uint i = 0; i < m_Container.GetValue().AsArray().size; i++) { AssetTypeValueField item = m_Container[i]; string path = item.Get("first").GetValue().AsString(); AssetTypeValueField pointerField = item.Get("second"); uint fileID = (uint)pointerField.Get("m_FileID").GetValue().AsInt(); ulong pathID = (ulong)pointerField.Get("m_PathID").GetValue().AsInt64(); //paths[path] = new AssetDetails(new AssetPPtr(fileID, pathID)); assets.Add(new AssetDetails(new AssetPPtr(fileID, pathID), AssetIcon.Unknown, path)); } rootDir = new FSDirectory(); //rootDir.Create(paths); rootDir.Create(assets); ChangeDirectory(""); helper.UpdateDependencies(); CheckResourcesInfo(); return; } } }
private void LoadResources(AssetsFileInstance ggm) { foreach (AssetFileInfoEx info in ggm.table.assetFileInfo) { ClassDatabaseType type = AssetHelper.FindAssetClassByID(helper.classFile, info.curFileType); if (type.name.GetString(helper.classFile) == "ResourceManager") { AssetTypeInstance inst = helper.GetATI(ggm.file, info); AssetTypeValueField baseField = inst.GetBaseField(); AssetTypeValueField m_Container = baseField.Get("m_Container").Get("Array"); List <AssetDetails> assets = new List <AssetDetails>(); for (int i = 0; i < m_Container.GetValue().AsArray().size; i++) { AssetTypeValueField item = m_Container[i]; string path = item.Get("first").GetValue().AsString(); AssetTypeValueField pointerField = item.Get("second"); //paths[path] = new AssetDetails(new AssetPPtr(fileID, pathID)); AssetExternal assetExt = helper.GetExtAsset(ggm, pointerField, true); AssetFileInfoEx assetInfo = assetExt.info; ClassDatabaseType assetType = AssetHelper.FindAssetClassByID(helper.classFile, assetInfo.curFileType); if (assetType == null) { continue; } string assetTypeName = assetType.name.GetString(helper.classFile); string assetName = AssetInfo.GetAssetNameFast(assetInfo, helper.classFile, assetType, assetExt.file); if (path.Contains("/")) { if (path.Substring(path.LastIndexOf('/') + 1) == assetName.ToLower()) { path = path.Substring(0, path.LastIndexOf('/') + 1) + assetName; } } else { if (path == assetName.ToLower()) { path = path.Substring(0, path.LastIndexOf('/') + 1) + assetName; } } assets.Add(new AssetDetails(new AssetPPtr(0, assetInfo.index), GetIconForName(assetTypeName), path, assetTypeName, (int)assetInfo.curFileSize)); } rootDir = new FSDirectory(); //rootDir.Create(paths); rootDir.Create(assets); ChangeDirectory(""); helper.UpdateDependencies(); CheckResourcesInfo(); return; } } }
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); } }
private static void ReplacePointers(AssetsFileInstance file, AssetFileInfoEx info, long pathId) { var baseField = am.GetATI(file.file, info).GetBaseField(); FindNestedPointers(file, baseField, info, true); FinalizeAsset(file, baseField, info); byte[] baseFieldData; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; // Copy all data from base field into byte array baseField.Write(w); baseFieldData = ms.ToArray(); } AssetsReplacer replacer = new AssetsReplacerFromMemory(0, (ulong)pathId, (int)info.curFileType, 0xFFFF, baseFieldData); if (IsAsset(info)) { assetReplacers.Add(replacer); } //else if (info.curFileType == 0x73) monoReplacers.Add(replacer); else { sceneReplacers.Add(replacer); } }
private static List <ulong> CrawlPPtrs(AssetsManager am, AssetsFileInstance inst, ulong startingId, List <ulong> depIds) { AssetFileInfoEx info = inst.table.getAssetInfo(startingId); AssetTypeValueField baseField = am.GetATI(inst.file, info).GetBaseField(); RecurseType(am, inst, baseField, depIds, 0); return(depIds); }
private static AssetsReplacerFromMemory MakeReplacer(ulong pathId, AssetsManager am, AssetsFileInstance file, AssetsFileInstance srcFile, AssetFileInfoEx inf, byte[] saData, List <Type_0D> types) { byte[] data = new byte[inf.curFileSize]; //UnityEngine.Debug.Log("making rep for " + inf.absoluteFilePos + " => " + (inf.absoluteFilePos+inf.curFileSize) + " of " + file.stream.Length); int typeId = file.file.typeTree.pTypes_Unity5[inf.curFileTypeOrIndex].classId; if (!types.Any(t => t.classId == typeId) && !srcFile.file.typeTree.pTypes_Unity5.Any(t => t.classId == typeId)) { if (!Hashes.hashes.ContainsKey(typeId)) { throw new NotImplementedException("hash not in hashtable, please add it!"); } types.Add(new Type_0D() { classId = typeId, unknown16_1 = 0, scriptIndex = 0xFFFF, unknown1 = 0, unknown2 = 0, unknown3 = 0, unknown4 = 0, unknown5 = Hashes.hashes[typeId][0], unknown6 = Hashes.hashes[typeId][1], unknown7 = Hashes.hashes[typeId][2], unknown8 = Hashes.hashes[typeId][3] }); //types.Add(C2T5.Cldb2TypeTree(am.classFile, typeId)); } switch (typeId) { case 0x1C: data = FixTexture2D(am.GetATI(file.file, inf).GetBaseField(), saData); break; case 0x15: data = FixMaterial(srcFile.file, am.GetATI(file.file, inf).GetBaseField(), saData); break; default: file.stream.Position = (int)inf.absoluteFilePos; file.stream.Read(data, 0, (int)inf.curFileSize); break; } return(new AssetsReplacerFromMemory(0, pathId, typeId, 0xFFFF, data)); }
private void button1_Click(object sender, EventArgs e) { if (startedScanning) { return; } listBox1.Items.Clear(); startedScanning = true; loadingBar.Maximum = details.Count; if (textBox1.Text == "") { return; } long searchNum = long.Parse(textBox1.Text); BackgroundWorker bw = new BackgroundWorker(); bw.WorkerReportsProgress = true; bw.DoWork += delegate(object s, DoWorkEventArgs ev) { for (int i = 0; i < details.Count; i++) { AssetDetails ad = details[i]; if (ad.fileID != 0 && !checkBox1.Checked) { continue; } if (ad.typeName == "GameObject") { AssetTypeInstance gameObjectAti = manager.GetATI(manager.GetStream(ad.fileID), manager.GetInfo(ad.fileID, ad.pathID)); AssetTypeValueField components = gameObjectAti.GetBaseField().Get("m_Component").Get("Array"); for (uint j = 0; j < components.GetValue().AsArray().size; j++) { int fileId = components.Get(j).Get("component").Get("m_FileID").GetValue().AsInt(); long pathId = components.Get(j).Get("component").Get("m_PathID").GetValue().AsInt64(); if (pathId == searchNum) { bw.ReportProgress(i, gameObjectAti.GetBaseField().Get("m_Name").GetValue().AsString() + "(" + ad.fileID + "/" + ad.pathID + ")"); } } bw.ReportProgress(i); } } startedScanning = false; }; bw.ProgressChanged += delegate(object s, ProgressChangedEventArgs ev) { loadingBar.Value = ev.ProgressPercentage; if (ev.UserState != null) { listBox1.Items.Add(ev.UserState); } }; bw.RunWorkerAsync(); }
public static AssetExternal GetExtAsset(this AssetsManager am, AssetsFileInstance relativeTo, int fileId, long pathId, bool onlyGetInfo = false) { AssetExternal ext = new AssetExternal(); if (fileId == 0 && pathId == 0) { ext.info = null; ext.instance = null; ext.file = null; } else if (fileId != 0) { AssetsFileInstance dep = relativeTo.dependencies[fileId - 1]; ext.info = dep.table.GetAssetInfo(pathId); if (!onlyGetInfo) { ext.instance = am.GetATI(dep.file, ext.info); } else { ext.instance = null; } ext.file = dep; } else { ext.info = relativeTo.table.GetAssetInfo(pathId); if (!onlyGetInfo) { ext.instance = am.GetATI(relativeTo.file, ext.info); } else { ext.instance = null; } ext.file = relativeTo; } return(ext); }
public static void CrawlReplacePPtrs(AssetsManager am, AssetsFileInstance inst, ulong startingId, List <string> fileNames, Dictionary <AssetID, byte[]> depIds, Dictionary <AssetID, long> aidToPid, Dictionary <long, long> gidToMid) { AssetFileInfoEx info = inst.table.getAssetInfo(startingId); AssetTypeValueField baseField; if (info.curFileType == 0x72) { baseField = am.GetMonoBaseFieldCached(inst, info, Path.Combine(Path.GetDirectoryName(inst.path), "Managed"), fileNames, aidToPid); } else { baseField = am.GetATI(inst.file, info).GetBaseField(); } RecurseTypeReplace(am, inst, info, baseField, fileNames, depIds, aidToPid, gidToMid, 0); }
private void ImportAssets() { var inf = currentFile.table.GetAssetInfo("MyBoringAsset"); var baseField = helper.GetATI(currentFile.file, inf).GetBaseField(); baseField.Get("m_Name") .GetValue() .Set("MyCoolAsset"); var newGoBytes = baseField.WriteToByteArray(); //AssetsReplacerFromMemory's monoScriptIndex should always be 0xFFFF unless it's a MonoBehaviour var repl = new AssetsReplacerFromMemory(0, inf.index, (int)inf.curFileType, 0xFFFF, newGoBytes); var writer = new AssetsFileWriter(File.OpenWrite("resources-modified.assets")); currentFile.file.Write(writer, 1, new AssetsReplacer[] { repl }.ToList(), 1); }
public static AssetTypeValueField GetField(long id, out string className) { className = ""; string path = DirctoryPath; AssetsManager helper = AssetsManager; ClassDatabaseFile classFile = helper.classFile; AssetsFileInstance correctAti = AssetsFileInstance; AssetFileInfoEx info = correctAti.table.GetAssetInfo(id); if (info == null) { Console.WriteLine($"path_id:{id} is not found,maybe in other file"); return(null); } ClassDatabaseType classType = AssetHelper.FindAssetClassByID(classFile, info.curFileType); string typeName = classType.name.GetString(classFile); AssetTypeValueField baseField = helper.GetATI(correctAti.file, info).GetBaseField(); className = AssetHelper.FindAssetClassByID(helper.classFile, info.curFileType) .name.GetString(helper.classFile); AssetTypeValueField targetBaseField = baseField; if (className == "MonoBehaviour") { if (AssetUtils.AllDependenciesLoaded(helper, correctAti)) { className += $"--{GetClassName(helper, correctAti, targetBaseField)}--{targetBaseField[3].value.AsString().TrimEnd('\0')}--"; string managedPath = Path.Combine(Path.GetDirectoryName(correctAti.path), "Managed"); if (Directory.Exists(managedPath)) { targetBaseField = helper.GetMonoBaseFieldCached(correctAti, info, managedPath); } } else { MessageBox.Show("Can't display MonoBehaviour data until dependencies are loaded", "Assets View"); return(null); } } else { className += "--"; } return(targetBaseField); }
internal static void ChangeDisableUnityAudio(string path, bool newValue, QModGame game) { if (game != QModGame.Subnautica && game != QModGame.BelowZero) { throw new ArgumentException("Neither Subnautica nor Below Zero detected!"); } AssetsManager am = new AssetsManager(); AssetsFileInstance afi = am.LoadAssetsFile(path, false); if (game == QModGame.Subnautica) { am.LoadClassDatabase("cldb.dat"); } else { am.LoadClassDatabase("cldb2018.dat"); } AssetFileInfoEx audioInfo = afi.table.getAssetInfo(4); AssetTypeInstance audioAti = am.GetATI(afi.file, audioInfo); AssetTypeValueField audioBaseField = audioAti.GetBaseField(); audioBaseField.Get("m_DisableAudio").GetValue().Set(newValue); byte[] audioAsset; using (MemoryStream memStream = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(memStream)) { writer.bigEndian = false; audioBaseField.Write(writer); audioAsset = memStream.ToArray(); } List <AssetsReplacer> rep = new List <AssetsReplacer>() { new AssetsReplacerFromMemory(0, 4, 0x0B, 0xFFFF, audioAsset) }; using (MemoryStream memStream = new MemoryStream()) using (AssetsFileWriter writer = new AssetsFileWriter(memStream)) { afi.file.Write(writer, 0, rep.ToArray(), 0); afi.stream.Close(); File.WriteAllBytes(path, memStream.ToArray()); } }
private static string GetLevelName(AssetsManager am, int index) { AssetsFileInstance inst = am.files.FirstOrDefault(f => f.name == "globalgamemanagers"); if (inst == null) { return(string.Empty); } AssetFileInfoEx bsInf = inst.table.GetAssetsOfType(0x8D).FirstOrDefault(); //BuildSettings if (bsInf == null) { return(string.Empty); } AssetTypeValueField bsBaseField = am.GetATI(inst.file, bsInf).GetBaseField(); AssetTypeValueField scenes = bsBaseField.Get("scenes").Get("Array"); return(scenes[(uint)index].GetValue().AsString()); }
public static void OpenSceneByName() { AssetsManager am = new AssetsManager(); am.LoadClassPackage(Path.Combine(Application.dataPath, "cldb.dat")); string gameDataPath = GetGamePath(); AssetsFileInstance inst = am.LoadAssetsFile(Path.Combine(gameDataPath, "globalgamemanagers"), false); AssetFileInfoEx buildSettings = inst.table.getAssetInfo(11); List <string> scenes = new List <string>(); AssetTypeValueField baseField = am.GetATI(inst.file, buildSettings).GetBaseField(); AssetTypeValueField sceneArray = baseField.Get("scenes").Get("Array"); for (uint i = 0; i < sceneArray.GetValue().AsArray().size; i++) { scenes.Add(sceneArray[i].GetValue().AsString() + "[" + i + "]"); } SceneSelector sel = SceneSelector.ShowDialog(am, scenes, gameDataPath); }
public IList <AssetsToolsAsset> GetAssets() { var assets = new List <AssetsToolsAsset>(); foreach (var info in assetsFile.table.assetFileInfo) { var type = AssetHelper.FindAssetClassByID(manager.classFile, info.curFileType); if (type == null) { continue; } var typeName = type.name.GetString(manager.classFile); var assetName = AssetHelper.GetAssetNameFast(assetsFile.file, manager.classFile, info); var baseField = manager.GetATI(assetsFile.file, info).GetBaseField(); assets.Add(new AssetsToolsAsset(info, typeName, assetName, baseField)); } return(assets); }
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(); } }
private static void LoadScene() { am = new AssetsManager(); am.LoadClassPackage("cldb.dat"); am.useTemplateFieldCache = true; am.updateAfterLoad = false; hkDir = Util.SteamHelper.GetHollowKnightDataPath(); var globalgamemanagers = am.LoadAssetsFile(Path.Combine(hkDir, "globalgamemanagers"), false); var buildSettings = globalgamemanagers.table.getAssetInfo(11); var baseField = am.GetATI(globalgamemanagers.file, buildSettings).GetBaseField(); var scenesArray = baseField.Get("scenes").Get("Array"); // TODO: Allow level to be selected const int level = 0; var levelName = scenesArray[level].GetValue().AsString().Substring(14); levelName = levelName.Substring(0, levelName.Length - 6); progressBarTitle = "Loading Scene #" + level + ": " + levelName; if (ShouldCancel("Checking workspace", 0.2f)) { return; } if (!baseField.Get("m_Version").GetValue().AsString().Equals(Application.unityVersion)) { EditorUtility.ClearProgressBar(); EditorUtility.DisplayDialog("Incorrect Unity version!", " You are using " + Application.unityVersion + " but the assets are compiled for version " + baseField.Get("m_Version").GetValue().AsString(), "Ok"); return; } unityVersion = Application.unityVersion; if (!Directory.Exists(scenesDir)) { Directory.CreateDirectory(scenesDir); } if (!Directory.Exists(dataDir)) { Directory.CreateDirectory(dataDir); } var metaFilePath = Path.Combine(scenesDir, "level" + level + ".unity.meta"); var sceneFilePath = Path.Combine(scenesDir, "level" + level + ".unity"); var assetsFilePath = Path.Combine(dataDir, "level" + level + ".assets"); if (File.Exists(sceneFilePath)) { if (EditorUtility.DisplayDialog("Overwrite scene?", "" + " You have already exported this scene. Would you like to overwrite it or open the existing scene? ", "Open Existing", "Overwrite")) { if (ShouldCancel("Opening Scene", 0.5f)) { return; } EditorSceneManager.OpenScene(sceneFilePath); EditorUtility.ClearProgressBar(); return; } else { File.Delete(sceneFilePath); } } if (File.Exists(metaFilePath)) { File.Delete(metaFilePath); } if (File.Exists(assetsFilePath)) { File.Delete(assetsFilePath); } curSceneId = 1; curAssetId = 1; pointers = new Dictionary <AssetID, AssetID>(); sceneReplacers = new List <AssetsReplacer>(); assetReplacers = new List <AssetsReplacer>(); monoReplacers = new List <AssetsReplacer>(); if (ShouldCancel("Reading level file", 0.5f)) { return; } var scenePath = Path.Combine(Util.SteamHelper.GetHollowKnightDataPath(), "level" + level); var scene = am.LoadAssetsFile(scenePath, true); if (ShouldCancel("Updating Dependencies", 0.8f)) { return; } am.UpdateDependencies(); for (var i = 0; i < am.files.Count; i++) { if (i % 100 == 0 && ShouldCancel("Generating QLTs", (float)i / am.files.Count)) { return; } am.files[i].table.GenerateQuickLookupTree(); } var table = scene.table; var gameObjects = table.GetAssetsOfType(0x01); var gameObjectBaseFields = new Dictionary <AssetFileInfoEx, AssetTypeValueField>(); var c = 0; for (c = 0; c < gameObjects.Count; c++) { if (c % 100 == 0 && ShouldCancel("Finding initial GameObjects", (float)c / gameObjects.Count)) { return; } var gameObjectInfo = gameObjects[c]; var gameObjectBaseField = am.GetATI(scene.file, gameObjectInfo).GetBaseField(); AddPointer(new AssetID(scene.path, (long)gameObjectInfo.index), false); gameObjectBaseFields.Add(gameObjectInfo, gameObjectBaseField); } c = 0; foreach (var pair in gameObjectBaseFields) { if (c % 100 == 0 && ShouldCancel("Recursing GameObject dependencies", (float)c / gameObjectBaseFields.Count)) { return; } FindNestedPointers(scene, pair.Value, pair.Key, false); c++; } var types = new List <Type_0D>(); var typeNames = new List <string>(); var fileToInst = am.files.ToDictionary(d => d.path); var j = 0; foreach (var pair in pointers) { if (j % 100 == 0 && ShouldCancel("Rewiring asset pointers", (float)j / pointers.Count)) { return; } var file = fileToInst[pair.Key.fileName]; var info = file.table.getAssetInfo((ulong)pair.Key.pathId); var assetClass = AssetHelper.FindAssetClassByID(am.classFile, info.curFileType); var assetName = assetClass.name.GetString(am.classFile); if (!typeNames.Contains(assetName)) { var type0d = C2T5.Cldb2TypeTree(am.classFile, assetName); type0d.classId = (int)info.curFileType; types.Add(type0d); typeNames.Add(assetName); } ReplacePointers(file, info, pair.Value.pathId); j++; } if (ShouldCancel("Saving scene", 1)) { return; } List <Type_0D> assetTypes = new List <Type_0D>() { C2T5.Cldb2TypeTree(am.classFile, 0x1c), // audioclip C2T5.Cldb2TypeTree(am.classFile, 0x30), // shader C2T5.Cldb2TypeTree(am.classFile, 0x53) // texture2d }; var sceneGuid = Util.UnityHelper.CreateMD5(levelName); UnityHelper.CreateMetaFile(sceneGuid, metaFilePath); var sceneFile = new AssetsFile(new AssetsFileReader(new MemoryStream(BundleCreator.CreateBlankAssets(unityVersion, types)))); var assetFile = new AssetsFile(new AssetsFileReader(new MemoryStream(BundleCreator.CreateBlankAssets(unityVersion, assetTypes)))); byte[] sceneFileData; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; sceneFile.dependencies.pDependencies = new AssetsFileDependency[] { UnityHelper.CreateDependency(assetsFilePath), }; sceneFile.dependencies.dependencyCount = 1; sceneFile.preloadTable.items = new AssetPPtr[] {}; sceneFile.preloadTable.len = 0; sceneFile.Write(w, 0, sceneReplacers.Concat(monoReplacers).ToArray(), 0); sceneFileData = ms.ToArray(); } byte[] assetFileData; using (var ms = new MemoryStream()) using (var w = new AssetsFileWriter(ms)) { w.bigEndian = false; assetFile.Write(w, 0, assetReplacers.ToArray(), 0); assetFileData = ms.ToArray(); } File.WriteAllBytes(sceneFilePath, sceneFileData); File.WriteAllBytes(assetsFilePath, assetFileData); if (ShouldCancel("Refreshing Assets", 0.95f)) { return; } AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); }
private static bool EnableVROptions(string path) { AssetsManager assetsManager = new AssetsManager(); AssetsFileInstance assetsFileInstance = assetsManager.LoadAssetsFile(path, false, ""); assetsManager.LoadClassDatabase(Path.Combine(VREnabler.VRPatcherPath, "cldb.dat")); int num = 0; while ((long)num < (long)((ulong)assetsFileInstance.table.assetFileInfoCount)) { try { AssetFileInfoEx assetInfo = assetsFileInstance.table.GetAssetInfo((long)num); AssetTypeInstance ati = assetsManager.GetATI(assetsFileInstance.file, assetInfo, false); AssetTypeValueField assetTypeValueField = (ati != null) ? ati.GetBaseField(0) : null; AssetTypeValueField assetTypeValueField2 = (assetTypeValueField != null) ? assetTypeValueField.Get("enabledVRDevices") : null; if (assetTypeValueField2 != null) { AssetTypeValueField assetTypeValueField3 = assetTypeValueField2.Get("Array"); if (assetTypeValueField3 != null) { AssetTypeValueField assetTypeValueField4 = ValueBuilder.DefaultValueFieldFromArrayTemplate(assetTypeValueField3); assetTypeValueField4.GetValue().Set("Oculus"); AssetTypeValueField assetTypeValueField5 = ValueBuilder.DefaultValueFieldFromArrayTemplate(assetTypeValueField3); assetTypeValueField5.GetValue().Set("OpenVR"); AssetTypeValueField assetTypeValueField6 = ValueBuilder.DefaultValueFieldFromArrayTemplate(assetTypeValueField3); assetTypeValueField6.GetValue().Set("None"); assetTypeValueField3.SetChildrenList(new AssetTypeValueField[] { assetTypeValueField6, assetTypeValueField4, assetTypeValueField5 }); byte[] array; using (MemoryStream memoryStream = new MemoryStream()) { using (AssetsFileWriter assetsFileWriter = new AssetsFileWriter(memoryStream)) { assetsFileWriter.bigEndian = false; AssetWriters.Write(assetTypeValueField, assetsFileWriter, 0); array = memoryStream.ToArray(); } } List <AssetsReplacer> list = new List <AssetsReplacer> { new AssetsReplacerFromMemory(0, (long)num, (int)assetInfo.curFileType, ushort.MaxValue, array) }; using (MemoryStream memoryStream2 = new MemoryStream()) { using (AssetsFileWriter assetsFileWriter2 = new AssetsFileWriter(memoryStream2)) { assetsFileInstance.file.Write(assetsFileWriter2, 0UL, list, 0U, null); assetsFileInstance.stream.Close(); File.WriteAllBytes(path, memoryStream2.ToArray()); } } return(true); } } } catch { } num++; } VREnabler.Logger.LogError("VR enable location not found!"); return(false); }
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); }
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 AssetTypeValueField GetBaseField(AssetsManager am, AssetsFile file, AssetFileInfoEx info) { AssetTypeInstance ati = am.GetATI(file, info); return(ati.GetBaseField()); }
private void button1_Click(object sender, EventArgs e) { if (startedScanning || finishedScanning) { return; } startedScanning = true; loadingBar.Maximum = details.Count; Dictionary <ulong, string> monos = new Dictionary <ulong, string>(); BackgroundWorker bw = new BackgroundWorker(); bw.WorkerReportsProgress = true; bw.DoWork += delegate(object s, DoWorkEventArgs ev) { for (int i = 0; i < details.Count; i++) { AssetDetails ad = details[i]; if (ad.fileID != 0 && !checkBox1.Checked) { continue; } string text = null; if (ad.typeName == "MonoBehaviour") { if (ad.name != "MonoBehaviour") { text = ad.name + " (" + ad.fileID + "/" + ad.pathID + ")"; } else { AssetTypeInstance behaviourAti = manager.GetATI(manager.GetStream(ad.fileID), manager.GetInfo(ad.fileID, ad.pathID)); AssetTypeInstance scriptAti = manager.GetExtAsset(behaviourAti.GetBaseField().Get("m_Script")).instance; string scriptName = scriptAti.GetBaseField().Get("m_Name").GetValue().AsString(); text = scriptName + " (" + ad.fileID + "/" + ad.pathID + ")"; } monos.Add(ad.pathID, text); } bw.ReportProgress(i); } for (int i = 0; i < details.Count; i++) { AssetDetails ad = details[i]; if (ad.fileID != 0 && !checkBox1.Checked) { continue; } if (ad.typeName == "GameObject") { AssetTypeInstance gameObjectAti = manager.GetATI(manager.GetStream(ad.fileID), manager.GetInfo(ad.fileID, ad.pathID)); AssetTypeValueField components = gameObjectAti.GetBaseField().Get("m_Component").Get("Array"); for (uint j = 0; j < components.GetValue().AsArray().size; j++) { long id = components.Get(j).Get("component").Get("m_PathID").GetValue().AsInt64(); if (monos.ContainsKey((ulong)id)) { monos[(ulong)id] += " -> " + gameObjectAti.GetBaseField().Get("m_Name").GetValue().AsString() + "(" + ad.fileID + "/" + ad.pathID + ")"; } } bw.ReportProgress(i); } } foreach (string str in monos.Values) { bw.ReportProgress(details.Count, str); } startedScanning = false; finishedScanning = true; }; bw.ProgressChanged += delegate(object s, ProgressChangedEventArgs ev) { loadingBar.Value = ev.ProgressPercentage; if (ev.UserState != null) { listBox1.Items.Add(ev.UserState); } }; bw.RunWorkerAsync(); }
//fast transform compare since most //changes will probably be transforms private void CompareTransform(GameObject obj, ulong origPathId, List <ComponentChangeOrAdd> changes) { Transform objTransform = obj.transform; AssetFileInfoEx goInfo = assetsTable.getAssetInfo(origPathId); AssetTypeInstance goInstance = am.GetATI(assetsFile, goInfo); AssetTypeValueField transformPPtr = goInstance.GetBaseField() .Get("m_Component") .Get("Array")[0] .Get("component"); AssetTypeInstance tfmInfo = am.GetExtAsset(assetsFileInstance, transformPPtr).instance; AssetTypeValueField tfmBaseField = tfmInfo.GetBaseField(); AssetTypeValueField m_LocalPosition = tfmBaseField.Get("m_LocalPosition"); AssetTypeValueField m_LocalRotation = tfmBaseField.Get("m_LocalRotation"); AssetTypeValueField m_LocalScale = tfmBaseField.Get("m_LocalScale"); Vector3 localPosition = new Vector3( m_LocalPosition.Get("x").GetValue().AsFloat(), m_LocalPosition.Get("y").GetValue().AsFloat(), m_LocalPosition.Get("z").GetValue().AsFloat() ); Quaternion localRotation = new Quaternion( m_LocalRotation.Get("x").GetValue().AsFloat(), m_LocalRotation.Get("y").GetValue().AsFloat(), m_LocalRotation.Get("z").GetValue().AsFloat(), m_LocalRotation.Get("w").GetValue().AsFloat() ); Vector3 localScale = new Vector3( m_LocalScale.Get("x").GetValue().AsFloat(), m_LocalScale.Get("y").GetValue().AsFloat(), m_LocalScale.Get("z").GetValue().AsFloat() ); if (objTransform.localPosition != localPosition || objTransform.localRotation != localRotation || objTransform.localScale != localScale) { List <FieldChange> fieldChanges = new List <FieldChange>(); if (localPosition.x != objTransform.localPosition.x) { fieldChanges.Add(new FieldChange("m_LocalPosition/x", objTransform.localPosition.x)); } if (localPosition.y != objTransform.localPosition.y) { fieldChanges.Add(new FieldChange("m_LocalPosition/y", objTransform.localPosition.y)); } if (localPosition.z != objTransform.localPosition.z) { fieldChanges.Add(new FieldChange("m_LocalPosition/z", objTransform.localPosition.z)); } if (localRotation.w != objTransform.localRotation.w) { fieldChanges.Add(new FieldChange("m_LocalRotation/w", objTransform.localRotation.w)); } if (localRotation.x != objTransform.localRotation.x) { fieldChanges.Add(new FieldChange("m_LocalRotation/x", objTransform.localRotation.x)); } if (localRotation.y != objTransform.localRotation.y) { fieldChanges.Add(new FieldChange("m_LocalRotation/y", objTransform.localRotation.y)); } if (localRotation.z != objTransform.localRotation.z) { fieldChanges.Add(new FieldChange("m_LocalRotation/z", objTransform.localRotation.z)); } if (localScale.x != objTransform.localScale.x) { fieldChanges.Add(new FieldChange("m_LocalScale/x", objTransform.localScale.x)); } if (localScale.y != objTransform.localScale.y) { fieldChanges.Add(new FieldChange("m_LocalScale/y", objTransform.localScale.y)); } if (localScale.z != objTransform.localScale.z) { fieldChanges.Add(new FieldChange("m_LocalScale/z", objTransform.localScale.z)); } changes.Add(new ComponentChangeOrAdd() { isNewComponent = false, componentIndex = 0, componentType = "Transform", changes = fieldChanges }); //Debug.Log("diffing " + obj.name + "'s transform"); } }
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 GameObject RecurseGameObjects(AssetFileInfoEx info, bool topRoot, bool hideOnCreation = false) { AssetTypeValueField gameObject = am.GetATI(assetsFile, info).GetBaseField(); string name = gameObject.Get("m_Name").GetValue().AsString(); AssetTypeValueField m_Component = gameObject.Get("m_Component").Get("Array"); AssetsManager.AssetExternal transformComponent = am.GetExtAsset(assetsFileInstance, m_Component[0].Get("component")); AssetTypeValueField transform = transformComponent.instance.GetBaseField(); if (name == "TileMap Render Data" || name == "Template-TileMap (1) Render Data") //should be .EndsWith(" Render Data") { return(TilemapRenderData(transform, name)); } if (topRoot && transform.Get("m_Father").Get("m_PathID").GetValue().AsInt64() != 0) { return(null); } if (!topRoot && transform.Get("m_Father").Get("m_PathID").GetValue().AsInt64() == 0) { return(null); } GameObject gameObjectInstance = new GameObject(name); //if this object or parent object is mask bool isMask = hideOnCreation; int m_Tag = (ushort)gameObject.Get("m_Tag").GetValue().AsUInt(); if (m_Tag >= 20000) { int tagIndex = m_Tag - 20000; gameObjectInstance.tag = UnityEditorInternal.InternalEditorUtility.tags[tagIndex]; } else if (m_Tag != 0) { string[] tags = new[] { "Respawn", "Finished", "EditorOnly", "MainCamera", "Player", "GameController" }; gameObjectInstance.tag = tags[m_Tag - 1]; } gameObjectInstance.layer = (int)gameObject.Get("m_Layer").GetValue().AsUInt(); EditDiffer differ = gameObjectInstance.AddComponent <EditDiffer>(); differ.fileId = 0; differ.pathId = info.index; differ.origPathId = differ.pathId; Transform transformInstance = gameObjectInstance.transform; AssetTypeValueField m_LocalPosition = transform.Get("m_LocalPosition"); AssetTypeValueField m_LocalRotation = transform.Get("m_LocalRotation"); AssetTypeValueField m_LocalScale = transform.Get("m_LocalScale"); Vector3 localPosition = GetVector3(m_LocalPosition); Quaternion localRotation = GetQuaternion(m_LocalRotation); Vector3 localScale = GetVector3(m_LocalScale); for (uint i = 1; i < m_Component.GetValue().AsArray().size; i++) { //faster to check for only info but also keeps us from reading //particle systems which tend to update literally every minor update //if we end up needing more types we can use typetree2cldb on an editor file AssetsManager.AssetExternal component = am.GetExtAsset(assetsFileInstance, m_Component[i].Get("component"), true); if (component.info.curFileType == SPRITERENDERER) { component = am.GetExtAsset(assetsFileInstance, m_Component[i].Get("component")); AssetTypeValueField baseField = component.instance.GetBaseField(); AssetTypeValueField m_Sprite = baseField.Get("m_Sprite"); int fileId = m_Sprite.Get("m_FileID").GetValue().AsInt(); long pathId = m_Sprite.Get("m_PathID").GetValue().AsInt64(); AssetsManager.AssetExternal sprite = am.GetExtAsset(assetsFileInstance, m_Sprite); if (sprite.info == null) //spriterenderer with no sprite lol { continue; } AssetsFileInstance spriteInst; if (m_Sprite.Get("m_FileID").GetValue().AsInt() == 0) { spriteInst = assetsFileInstance; } else { spriteInst = assetsFileInstance.dependencies[m_Sprite.Get("m_FileID").GetValue().AsInt() - 1]; } Sprite spriteInstance = bundleAssets[assetMap[new AssetID(Path.GetFileName(spriteInst.path), pathId)]] as Sprite; SpriteRenderer sr = gameObjectInstance.AddComponent <SpriteRenderer>(); string[] sortingLayers = new[] { "Default", "Far BG 2", "Far BG 1", "Mid BG", "Immediate BG", "Actors", "Player", "Tiles", "MID Dressing", "Immediate FG", "Far FG", "Vignette", "Over", "HUD" }; sr.sortingLayerName = sortingLayers[baseField.Get("m_SortingLayer").GetValue().AsInt()]; sr.sortingOrder = baseField.Get("m_SortingOrder").GetValue().AsInt(); sr.sprite = spriteInstance; AssetTypeValueField m_Materials = baseField.Get("m_Materials").Get("Array"); if (m_Materials.GetValue().AsArray().size > 0) { AssetTypeValueField m_Material = m_Materials[0]; int matFileId = m_Material.Get("m_FileID").GetValue().AsInt(); long matPathId = m_Material.Get("m_PathID").GetValue().AsInt64(); AssetsFileInstance materialInst; if (m_Material.Get("m_FileID").GetValue().AsInt() == 0) { materialInst = assetsFileInstance; } else { materialInst = assetsFileInstance.dependencies[matFileId - 1]; } if (assetMap.ContainsKey(new AssetID(Path.GetFileName(materialInst.path), matPathId))) { Material mat = bundleAssets[assetMap[new AssetID(Path.GetFileName(materialInst.path), matPathId)]] as Material; if (mat.shader.name != "Sprites/Lit") //honestly this shader confuses me. it is the only shader { //with no code and only references the generic material sr.material = mat; } //else //{ // mat.shader = sr.sharedMaterial.shader; // sr.sharedMaterial = mat; //} if (mat.shader.name == "Hollow Knight/Grass-Default" || mat.shader.name == "Hollow Knight/Grass-Diffuse") { sr.sharedMaterial.SetFloat("_SwayAmount", 0f); //stops grass animation } } //else //{ // Debug.Log("failed to find " + Path.GetFileName(materialInst.path) + "/" + matPathId + ".dat"); //} } } if (component.info.curFileType == MONOBEHAVIOUR) { component = am.GetExtAsset(assetsFileInstance, m_Component[i].Get("component")); AssetTypeValueField baseField = component.instance.GetBaseField(); int monoTypeId = assetsFileInstance.file.typeTree.pTypes_Unity5[component.info.curFileTypeOrIndex].scriptIndex; if (!monoBehaviourIds.ContainsKey(monoTypeId)) { //map out the monobehaviour script indexes to their name for fast lookup AssetTypeValueField m_Script = baseField.Get("m_Script"); AssetsManager.AssetExternal script = am.GetExtAsset(assetsFileInstance, m_Script); string scriptName = script.instance.GetBaseField().Get("m_Name").GetValue().AsString(); monoBehaviourIds[monoTypeId] = scriptName; } if (monoBehaviourIds[monoTypeId] == "tk2dSprite") { string managedPath = Path.Combine(Path.GetDirectoryName(assetsFileInstance.path), "Managed"); baseField = am.GetMonoBaseFieldCached(assetsFileInstance, component.info, managedPath); AssetTypeValueField collection = baseField.Get("collection"); int _spriteId = baseField.Get("_spriteId").GetValue().AsInt(); int fileId = collection.Get("m_FileID").GetValue().AsInt(); //long pathId = collection.Get("m_PathID").GetValue().AsInt64(); AssetsManager.AssetExternal sprite = am.GetExtAsset(assetsFileInstance, collection); if (sprite.info == null) { continue; } AssetsFileInstance spriteFileInstance = assetsFileInstance.dependencies[fileId - 1]; AssetTypeValueField spriteBaseField = am.GetMonoBaseFieldCached(spriteFileInstance, sprite.info, managedPath); //this is a bad hack but it works for some reason so here it is //the reason the pivot is being set and not the actual position //is so we don't modify the values on the transform component Texture2D image = spriteLoader.LoadTK2dSpriteNative(am, spriteBaseField, spriteFileInstance, _spriteId); AssetTypeValueField boundsData = spriteBaseField.Get("spriteDefinitions")[(uint)_spriteId].Get("boundsData")[0]; float xOff = boundsData.Get("x").GetValue().AsFloat() * 100; float yOff = boundsData.Get("y").GetValue().AsFloat() * 100; Vector2 offset = new Vector2((image.width / 2f - xOff) / image.width, (image.height / 2f - yOff) / image.height); Sprite spriteInstance = Sprite.Create(image, new Rect(0, 0, image.width, image.height), offset, 100f); SpriteRenderer sr = gameObjectInstance.AddComponent <SpriteRenderer>(); sr.sortingLayerName = "Default"; sr.sortingOrder = 0; sr.sprite = spriteInstance; } else if (monoBehaviourIds[monoTypeId] == "PlayMakerFSM") { //string managedPath = Path.Combine(Path.GetDirectoryName(assetsFileInstance.path), "Managed"); //baseField = am.GetMonoBaseFieldCached(assetsFileInstance, component.info, managedPath); string fsmName = ReadFSMName(component.info, assetsFileInstance.file.reader);//baseField.Get("fsm").Get("name").GetValue().AsString(); if (fsmName == "remasker" || fsmName == "unmasker" || fsmName == "remasker_inverse" || fsmName == "Remove") { isMask = true; } } } } transformInstance.localScale = localScale; transformInstance.localPosition = localPosition; transformInstance.localRotation = localRotation; Renderer ren = gameObjectInstance.GetComponent <Renderer>(); if (isMask && ren != null) { ren.enabled = false; } AssetTypeValueField childrenArray = transform.Get("m_Children").Get("Array"); uint childrenCount = childrenArray.GetValue().AsArray().size; for (uint i = 0; i < childrenCount; i++) { AssetTypeValueField childTf = am.GetExtAsset(assetsFileInstance, childrenArray[i]).instance.GetBaseField(); AssetFileInfoEx childGo = am.GetExtAsset(assetsFileInstance, childTf.Get("m_GameObject")).info; RecurseGameObjects(childGo, false, isMask).transform.SetParent(transformInstance, false); } return(gameObjectInstance); }
private void automaticallyToolStripMenuItem_Click(object sender, EventArgs e) { if (!File.Exists("pathinfo.txt")) { DialogResult res = MessageBox.Show("pathinfo.txt does not exist, would you like to create it?", "sse-adv", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { res = MessageBox.Show("are you using steam?", "sse-adv", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { File.WriteAllLines("pathinfo.txt", new[] { "steam", "appid", "game title", "game data folder name" }); MessageBox.Show("please fill in the values in pathinfo.txt with your game info", "sse-adv"); return; } else { string newGameDataPath = SelectFolder("select game's _data path"); if (newGameDataPath != string.Empty) { File.WriteAllLines("pathinfo.txt", new[] { "path", newGameDataPath }); } else { return; } } } else { return; } } string[] pathInfoCfg = File.ReadAllLines("pathinfo.txt"); string gameDataPath; if (pathInfoCfg[0] == "steam") { int appId = int.Parse(pathInfoCfg[1]); string gameName = pathInfoCfg[2]; string dataFolderName = pathInfoCfg[3]; gameDataPath = Path.Combine(SteamHelper.FindSteamGamePath(appId, gameName), dataFolderName); } else if (pathInfoCfg[0] == "path") { gameDataPath = pathInfoCfg[1]; } else { MessageBox.Show("pathinfo.txt invalid", "sse-adv"); return; } if (string.IsNullOrEmpty(gameDataPath)) { return; } AssetsFileInstance inst = am.LoadAssetsFile(Path.Combine(gameDataPath, "globalgamemanagers"), false); am.LoadClassDatabaseFromPackage(inst.file.typeTree.unityVersion); AssetFileInfoEx buildSettings = inst.table.GetAssetInfo(11); List <string> scenes = new List <string>(); AssetTypeValueField baseField = am.GetATI(inst.file, buildSettings).GetBaseField(); AssetTypeValueField sceneArray = baseField.Get("scenes").Get("Array"); for (int i = 0; i < sceneArray.GetValue().AsArray().size; i++) { scenes.Add(sceneArray[i].GetValue().AsString()); } sceneselect sel = new sceneselect(scenes); sel.ShowDialog(); if (sel.selectedFile != string.Empty) { OpenFile(Path.Combine(gameDataPath, sel.selectedFile)); } }
//creates a lookup where assets from different built game files //with different fileIds and pathIds can be converted to a list //of pathIds in order with fileId 0 or 1 depending on the asset type //(stored in the references dictionary) public void SetReferences(AssetsFileInstance inst, AssetFileInfoEx inf) { AssetTypeValueField baseField = am.GetATI(inst.file, inf).GetBaseField(); SetReferencesRecurse(inst, baseField); }
//this is going to be a slow operation, so it's probably best to move //this to a post process action after unity has built the bundle public static void ReorderIds(AssetsManager am, AssetsFileInstance inst, ulong idOffset) { List <ulong> oldIds = new List <ulong>(); List <ulong> tempIds = new List <ulong>(); Dictionary <ulong, ulong> oldToTemp = new Dictionary <ulong, ulong>(); Dictionary <ulong, ulong> tempToNew = new Dictionary <ulong, ulong>(); Dictionary <ulong, byte[]> tempData = new Dictionary <ulong, byte[]>(); Dictionary <ulong, byte[]> newData = new Dictionary <ulong, byte[]>(); //move 1: //move everything to the end of where it will go to //prevent from hitting collisions with their own ids foreach (AssetFileInfoEx inf in inst.table.pAssetFileInfo) { oldIds.Add(inf.index); } ulong nextId = idOffset + inst.table.assetFileInfoCount; foreach (AssetFileInfoEx inf in inst.table.pAssetFileInfo) { if (InClassBlacklist(inf.curFileType)) { continue; } ulong repId = nextId++; while (oldIds.Contains(repId)) { repId = nextId++; } tempIds.Add(repId); oldToTemp[inf.index] = repId; } foreach (AssetFileInfoEx inf in inst.table.pAssetFileInfo) { if (InClassBlacklist(inf.curFileType)) { continue; } AssetTypeValueField baseField = am.GetATI(inst.file, inf).GetBaseField(); List <ulong> depIds = new List <ulong>(); depIds.Add(inf.index); RecurseTypeReplace(am, inst, baseField, depIds, 0, oldToTemp); using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; baseField.Write(w); tempData[inf.index] = ms.ToArray(); } } //update everything to a new assets file with the first move List <AssetsReplacer> reps = new List <AssetsReplacer>(); foreach (AssetFileInfoEx inf in inst.table.pAssetFileInfo) { reps.Add(new AssetsRemover(0, inf.index, (int)inf.curFileType)); if (InClassBlacklist(inf.curFileType)) { continue; } reps.Add(new AssetsReplacerFromMemory(0, oldToTemp[inf.index], (int)inf.curFileType, 0xFFFF, tempData[inf.index])); } byte[] firstMoveBytes; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; inst.file.Write(w, 0, reps.ToArray(), 0); firstMoveBytes = ms.ToArray(); } //File.WriteAllBytes("_bundletest1.unity3d", firstMoveBytes); //load our modifications (btw super hacky and slow) inst.stream = new MemoryStream(firstMoveBytes); inst.file = new AssetsFile(new AssetsFileReader(inst.stream)); inst.table = new AssetsFileTable(inst.file); //move 2: //move the assets right after the existing ones nextId = idOffset; foreach (AssetFileInfoEx inf in inst.table.pAssetFileInfo) { if (InClassBlacklist(inf.curFileType)) { continue; } ulong repId = nextId++; tempToNew[inf.index] = repId; } foreach (AssetFileInfoEx inf in inst.table.pAssetFileInfo) { AssetTypeValueField baseField = am.GetATI(inst.file, inf).GetBaseField(); List <ulong> depIds = new List <ulong>(); depIds.Add(inf.index); RecurseTypeReplace(am, inst, baseField, depIds, 0, tempToNew); using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; baseField.Write(w); newData[inf.index] = ms.ToArray(); } } reps.Clear(); foreach (AssetFileInfoEx inf in inst.table.pAssetFileInfo) { reps.Add(new AssetsRemover(0, inf.index, (int)inf.curFileType)); reps.Add(new AssetsReplacerFromMemory(0, tempToNew[inf.index], (int)inf.curFileType, 0xFFFF, newData[inf.index])); } byte[] secondMoveBytes; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter w = new AssetsFileWriter(ms)) { w.bigEndian = false; inst.file.Write(w, 0, reps.ToArray(), 0); secondMoveBytes = ms.ToArray(); } //File.WriteAllBytes("_bundletest2.unity3d", secondMoveBytes); inst.stream = new MemoryStream(secondMoveBytes); inst.file = new AssetsFile(new AssetsFileReader(inst.stream)); inst.table = new AssetsFileTable(inst.file); Debug.Log("done"); }
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); } } }