static string PostProcessBundle(BuiltAssetBundle bundle, Dictionary <string, string> assemblyReplacements) { Debug.Log($"Post Processing Bundle -> {bundle.File}"); var am = new AssetsManager(); am.LoadClassPackage("Assets\\WeaverCore\\Libraries\\classdata.tpk"); var bun = am.LoadBundleFile(bundle.File.FullName); //load the first entry in the bundle (hopefully the one we want) var assetsFileData = BundleHelper.LoadAssetDataFromBundle(bun.file, 0); var assetsFileName = bun.file.bundleInf6.dirInf[0].name; //name of the first entry in the bundle //I have a new update coming, but in the current release, assetsmanager //will only load from file, not from the AssetsFile class. so we just //put it into memory and load from that... var assetsFileInst = am.LoadAssetsFile(new MemoryStream(assetsFileData), "dummypath", false); var assetsFileTable = assetsFileInst.table; //load cldb from classdata.tpk am.LoadClassDatabaseFromPackage(assetsFileInst.file.typeTree.unityVersion); List <BundleReplacer> bundleReplacers = new List <BundleReplacer>(); List <AssetsReplacer> assetReplacers = new List <AssetsReplacer>(); foreach (var info in assetsFileTable.assetFileInfo) { //If object is a MonoScript, change the script's "m_AssemblyName" from "Assembly-CSharp" to name of mod assembly if (info.curFileType == 0x73) { //MonoDeserializer.GetMonoBaseField var monoScriptInst = am.GetTypeInstance(assetsFileInst.file, info).GetBaseField(); var m_AssemblyNameValue = monoScriptInst.Get("m_AssemblyName").GetValue(); foreach (var testAsm in assemblyReplacements) { var assemblyName = m_AssemblyNameValue.AsString(); if (assemblyName.Contains(testAsm.Key)) { var newAsmName = assemblyName.Replace(testAsm.Key, testAsm.Value); //change m_AssemblyName field m_AssemblyNameValue.Set(newAsmName); //rewrite the asset and add it to the pending list of changes //Debug.Log($"Replacing in Monoscript {assemblyName} -> {newAsmName}"); assetReplacers.Add(new AssetsReplacerFromMemory(0, info.index, (int)info.curFileType, 0xffff, monoScriptInst.WriteToByteArray())); break; } } } //If the object is a MonoBehaviour #if !REWRITE_REGISTRIES else if (info.curFileType == 0x72) { AssetTypeValueField monoBehaviourInst = null; try { monoBehaviourInst = am.GetTypeInstance(assetsFileInst, info).GetBaseField(); } catch (Exception e) { Debug.LogError("An exception occured when reading a MonoBehaviour, skipping"); foreach (var field in info.GetType().GetFields()) { Debug.LogError($"{field.Name} = {field.GetValue(info)}"); } Debug.LogException(e); continue; } // /*try * { * monoBehaviourInst = MonoDeserializer.GetMonoBaseField(am, assetsFileInst, info, new DirectoryInfo("Library\\ScriptAssemblies").FullName); * } * catch (Exception) * { * continue; * }*/ //If this MonoBehaviour has a field called "modAssemblyName", then it's a Registry object //If MonoBehaviour is a registry, replace the "modAssemblyName" variable from "Assembly-CSharp" if (!monoBehaviourInst.Get("modAssemblyName").IsDummy()) { var modAsmNameVal = monoBehaviourInst.Get("modAssemblyName").GetValue(); foreach (var replacement in assemblyReplacements) { if (modAsmNameVal.AsString() == replacement.Key) { modAsmNameVal.Set(replacement.Value); Debug.Log($"Replacing Registry Assembly From {replacement.Key} to {replacement.Value}"); assetReplacers.Add(new AssetsReplacerFromMemory(0, info.index, (int)info.curFileType, AssetHelper.GetScriptIndex(assetsFileInst.file, info), monoBehaviourInst.WriteToByteArray())); break; } } } } #endif } //rewrite the assets file back to memory byte[] modifiedAssetsFileBytes; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter aw = new AssetsFileWriter(ms)) { aw.bigEndian = false; assetsFileInst.file.Write(aw, 0, assetReplacers, 0); modifiedAssetsFileBytes = ms.ToArray(); } //adding the assets file to the pending list of changes for the bundle bundleReplacers.Add(new BundleReplacerFromMemory(assetsFileName, assetsFileName, true, modifiedAssetsFileBytes, modifiedAssetsFileBytes.Length)); byte[] modifiedBundleBytes; using (MemoryStream ms = new MemoryStream()) using (AssetsFileWriter aw = new AssetsFileWriter(ms)) { bun.file.Write(aw, bundleReplacers); modifiedBundleBytes = ms.ToArray(); } using (MemoryStream mbms = new MemoryStream(modifiedBundleBytes)) using (AssetsFileReader ar = new AssetsFileReader(mbms)) { AssetBundleFile modifiedBundle = new AssetBundleFile(); modifiedBundle.Read(ar); //recompress the bundle and write it (this is optional of course) using (FileStream ms = File.OpenWrite(bundle.File.FullName + ".edit")) using (AssetsFileWriter aw = new AssetsFileWriter(ms)) { bun.file.Pack(modifiedBundle.reader, aw, AssetBundleCompressionType.LZ4); } } return(bundle.File.FullName + ".edit"); }
public static AssetsReplacer CreateAssetReplacer(AssetsFile file, AssetFileInfoEx info, byte[] data) { return(new AssetsReplacerFromMemory(0, info.index, (int)info.curFileType, AssetHelper.GetScriptIndex(file, info), data)); }