public static AssetTypeValueField GetMonoBaseFieldCached(this AssetsManager am, AssetsFileInstance inst, AssetFileInfoEx info, string managedPath, List <string> fileNames, Dictionary <AssetID, long> aidToPid) { AssetsFile file = inst.file; ushort scriptIndex = file.typeTree.pTypes_Unity5[info.curFileTypeOrIndex].scriptIndex; if (scriptIndex != 0xFFFF && inst.templateFieldCache.ContainsKey(scriptIndex)) { AssetTypeTemplateField baseTemplateField = inst.templateFieldCache[scriptIndex]; AssetTypeInstance baseAti = new AssetTypeInstance(baseTemplateField, file.reader, false, info.absoluteFilePos); return(baseAti.GetBaseField()); } else { AssetTypeTemplateField baseField = new AssetTypeTemplateField(); baseField.FromClassDatabase(am.classFile, AssetHelper.FindAssetClassByID(am.classFile, info.curFileType), 0); AssetTypeInstance mainAti = new AssetTypeInstance(baseField, file.reader, false, info.absoluteFilePos); if (file.typeTree.pTypes_Unity5[info.curFileTypeOrIndex].scriptIndex != 0xFFFF) { AssetTypeValueField m_Script = mainAti.GetBaseField().Get("m_Script"); int m_ScriptFileId = m_Script.Get("m_FileID").GetValue().AsInt(); long m_ScriptPathId = m_Script.Get("m_PathID").GetValue().AsInt64(); AssetID id = new AssetID(fileNames[-m_ScriptFileId], m_ScriptPathId); long m_ScriptRealPathId = aidToPid[id]; AssetTypeInstance scriptAti = am.GetExtAsset(inst, 0, m_ScriptRealPathId).instance; string scriptName = scriptAti.GetBaseField().Get("m_Name").GetValue().AsString(); string assemblyName = scriptAti.GetBaseField().Get("m_AssemblyName").GetValue().AsString(); string assemblyPath = Path.Combine(managedPath, assemblyName); Console.WriteLine("checking " + scriptName + " in " + assemblyName + " from id " + info.index); if (File.Exists(assemblyPath)) { MonoClass mc = new MonoClass(); mc.Read(scriptName, assemblyPath, inst.file.header.format); AssetTypeTemplateField[] monoTemplateFields = mc.children; AssetTypeTemplateField[] templateField = baseField.children.Concat(monoTemplateFields).ToArray(); baseField.children = templateField; baseField.childrenCount = (uint)baseField.children.Length; mainAti = new AssetTypeInstance(baseField, file.reader, false, info.absoluteFilePos); } } AssetTypeValueField baseValueField = mainAti.GetBaseField(); inst.templateFieldCache[scriptIndex] = baseValueField.templateField; return(baseValueField); } }
private AssetTypeTemplateField[] TryDeserializeMono(AssetTypeInstance ati, AssetsManager am, string rootDir) { AssetTypeInstance scriptAti = am.GetExtAsset(curFile, ati.GetBaseField().Get("m_Script")).instance; string scriptName = scriptAti.GetBaseField().Get("m_Name").GetValue().AsString(); string assemblyName = scriptAti.GetBaseField().Get("m_AssemblyName").GetValue().AsString(); string assemblyPath = Path.Combine(rootDir, "Managed", assemblyName); if (File.Exists(assemblyPath)) { MonoClass mc = new MonoClass(); mc.Read(scriptName, assemblyPath); return(mc.children); } else { return(null); } }
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); }