Exemple #1
0
        public void AddReplacer(byte[] data, int type, ushort monoType, bool isAsset)
        {
            int            id       = isAsset ? assetId : sceneId;
            AssetsReplacer replacer = new AssetsReplacerFromMemory(0, id, type, monoType, data);

            if (IsAsset(type))
            {
                assetReplacers.Add(replacer);
            }
            else if (type == 0x72)
            {
                sceneMonoReplacers.Add(replacer);
            }
            else
            {
                sceneReplacers.Add(replacer);
            }
            if (isAsset)
            {
                assetId++;
            }
            else
            {
                sceneId++;
            }
        }
Exemple #2
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);
        }
    }
Exemple #3
0
        public async Task <bool> BatchImport(Window win, AssetWorkspace workspace, List <AssetContainer> selection)
        {
            OpenFolderDialog ofd = new OpenFolderDialog();

            ofd.Title = "Select import directory";

            string dir = await ofd.ShowAsync(win);

            if (dir != null && dir != string.Empty)
            {
                ImportBatch            dialog     = new ImportBatch(workspace, selection, dir, ".png");
                List <ImportBatchInfo> batchInfos = await dialog.ShowDialog <List <ImportBatchInfo> >(win);

                foreach (ImportBatchInfo batchInfo in batchInfos)
                {
                    AssetContainer cont = batchInfo.cont;

                    AssetTypeValueField baseField = workspace.GetBaseField(cont);

                    string file = batchInfo.importFile;

                    byte[] byteData = File.ReadAllBytes(file);
                    baseField.Get("m_Script").GetValue().Set(byteData);

                    byte[] savedAsset = baseField.WriteToByteArray();

                    var replacer = new AssetsReplacerFromMemory(
                        0, cont.PathId, (int)cont.ClassId, cont.MonoId, savedAsset);

                    workspace.AddReplacer(cont.FileInstance, replacer, new MemoryStream(savedAsset));
                }
                return(true);
            }
            return(false);
        }
Exemple #4
0
        //replaces the PPtr entries in each asset with the new pathId
        //(.Key with .Value in the references dictionary) and fixes some
        //specific problems with assets like GameObject or Texture2D
        //(stored in sceneReplacers and assetReplacers)
        public void ReplaceReferences(AssetsFileInstance inst, AssetFileInfoEx inf, long pathId)
        {
            AssetTypeValueField baseField = am.GetATI(inst.file, inf).GetBaseField();

            FixAssetPre(inst, baseField, inf);
            ReplaceReferencesRecurse(inst, baseField, inf);
            FixAssetPost(inst, baseField, inf);

            byte[] baseFieldData;
            using (MemoryStream ms = new MemoryStream())
                using (AssetsFileWriter w = new AssetsFileWriter(ms))
                {
                    w.bigEndian = false;
                    baseField.Write(w);
                    baseFieldData = ms.ToArray();
                }
            AssetsReplacer replacer = new AssetsReplacerFromMemory(0, pathId, (int)inf.curFileType, 0xFFFF, baseFieldData);

            if (IsAsset(inf))
            {
                assetReplacers.Add(replacer);
            }
            else if (inf.curFileType == 0x72)
            {
                sceneMonoReplacers.Add(replacer);
            }
            else
            {
                sceneReplacers.Add(replacer);
            }
        }
Exemple #5
0
        public void AddReplacer(byte[] data, int type, ushort monoType)
        {
            AssetsReplacer replacer = new AssetsReplacerFromMemory(0, sceneId, type, monoType, data);

            if (type != 0x72)
            {
                sceneReplacers.Add(replacer);
            }
            sceneId++;
        }
Exemple #6
0
        public void ReplaceReferences(AssetsFileInstance inst, AssetFileInfoEx inf, long pathId)
        {
            AssetTypeValueField baseField = am.GetATI(inst.file, inf).GetBaseField();

            ReplaceReferencesRecurse(inst, baseField, inf);
            //FixAsset(baseField, inf);
            byte[]         baseFieldData = baseField.WriteToByteArray();
            AssetsReplacer replacer      = new AssetsReplacerFromMemory(0, pathId, (int)inf.curFileType, 0xFFFF, baseFieldData);

            if (inf.curFileType != 0x72)
            {
                sceneReplacers.Add(replacer);
            }
        }
        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);
        }
Exemple #8
0
        public async Task <bool> SingleImport(Window win, AssetWorkspace workspace, List <AssetContainer> selection)
        {
            AssetContainer cont = selection[0];

            OpenFileDialog ofd = new OpenFileDialog();

            AssetTypeValueField baseField = workspace.GetBaseField(cont);

            ofd.Title   = "Open text file";
            ofd.Filters = new List <FileDialogFilter>()
            {
                new FileDialogFilter()
                {
                    Name = "TXT file", Extensions = new List <string>()
                    {
                        "txt"
                    }
                }
            };

            string[] fileList = await ofd.ShowAsync(win);

            if (fileList.Length == 0)
            {
                return(false);
            }

            string file = fileList[0];

            if (file != null && file != string.Empty)
            {
                byte[] byteData = File.ReadAllBytes(file);
                baseField.Get("m_Script").GetValue().Set(byteData);

                byte[] savedAsset = baseField.WriteToByteArray();

                var replacer = new AssetsReplacerFromMemory(
                    0, cont.PathId, (int)cont.ClassId, cont.MonoId, savedAsset);

                workspace.AddReplacer(cont.FileInstance, replacer, new MemoryStream(savedAsset));
            }
            return(false);
        }
Exemple #9
0
        public async Task <bool> ExecutePlugin(Window win, AssetWorkspace workspace, List <AssetContainer> selection)
        {
            for (int i = 0; i < selection.Count; i++)
            {
                selection[i] = new AssetContainer(selection[i], TextureHelper.GetByteArrayTexture(workspace, selection[i]));
            }

            OpenFolderDialog ofd = new OpenFolderDialog();

            ofd.Title = "Select import directory";

            string dir = await ofd.ShowAsync(win);

            if (dir != null && dir != string.Empty)
            {
                ImportBatch            dialog     = new ImportBatch(workspace, selection, dir, ".png");
                List <ImportBatchInfo> batchInfos = await dialog.ShowDialog <List <ImportBatchInfo> >(win);

                bool success = await ImportTextures(win, batchInfos);

                if (success)
                {
                    //some of the assets may not get modified, but
                    //uabe still makes replacers for those anyway
                    foreach (AssetContainer cont in selection)
                    {
                        byte[] savedAsset = cont.TypeInstance.WriteToByteArray();

                        var replacer = new AssetsReplacerFromMemory(
                            0, cont.PathId, (int)cont.ClassId, cont.MonoId, savedAsset);

                        workspace.AddReplacer(cont.FileInstance, replacer, new MemoryStream(savedAsset));
                    }
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            return(false);
        }
Exemple #10
0
        public async Task <bool> ExecutePlugin(Window win, AssetWorkspace workspace, List <AssetContainer> selection)
        {
            AssetContainer cont = selection[0];

            AssetTypeValueField texBaseField = TextureHelper.GetByteArrayTexture(workspace, cont).GetBaseField();
            TextureFile         texFile      = TextureFile.ReadTextureFile(texBaseField);
            EditDialog          dialog       = new EditDialog(texFile.m_Name, texFile, texBaseField);
            bool saved = await dialog.ShowDialog <bool>(win);

            if (saved)
            {
                byte[] savedAsset = texBaseField.WriteToByteArray();

                var replacer = new AssetsReplacerFromMemory(
                    0, cont.PathId, (int)cont.ClassId, cont.MonoId, savedAsset);

                workspace.AddReplacer(cont.FileInstance, replacer, new MemoryStream(savedAsset));
                return(true);
            }
            return(false);
        }
Exemple #11
0
        public async Task <bool> ExecutePlugin(Window win, AssetWorkspace workspace, List <AssetExternal> selection)
        {
            AssetExternal       tex          = selection[0];
            AssetTypeValueField texBaseField = tex.instance.GetBaseField();
            TextureFile         texFile      = TextureFile.ReadTextureFile(texBaseField);
            EditDialog          dialog       = new EditDialog(texFile.m_Name, texFile, texBaseField);
            bool saved = await dialog.ShowDialog <bool>(win);

            if (saved)
            {
                byte[] savedAsset = texBaseField.WriteToByteArray();

                var replacer = new AssetsReplacerFromMemory(
                    0, tex.info.index, (int)tex.info.curFileType,
                    AssetHelper.GetScriptIndex(tex.file.file, tex.info), savedAsset);

                workspace.AddReplacer(tex.file, replacer, new MemoryStream(savedAsset));
                return(true);
            }
            return(false);
        }
Exemple #12
0
        private static object ParseReplacer(AssetsFileReader reader, bool prefReplacersInMemory)
        {
            short replacerType = reader.ReadInt16();
            byte  fileType     = reader.ReadByte();

            if (fileType == 0) //BundleReplacer
            {
                string oldName                  = reader.ReadCountStringInt16();
                string newName                  = reader.ReadCountStringInt16();
                bool   hasSerializedData        = reader.ReadByte() != 0; //guess
                long   replacerCount            = reader.ReadInt64();
                List <AssetsReplacer> replacers = new List <AssetsReplacer>();
                for (int i = 0; i < replacerCount; i++)
                {
                    AssetsReplacer assetReplacer = (AssetsReplacer)ParseReplacer(reader, prefReplacersInMemory);
                    replacers.Add(assetReplacer);
                }

                if (replacerType == 4) //BundleReplacerFromAssets
                {
                    //we have to null the assetsfile here and call init later
                    BundleReplacer replacer = new BundleReplacerFromAssets(oldName, newName, null, replacers, 0);
                    return(replacer);
                }
            }
            else if (fileType == 1)                         //AssetsReplacer
            {
                byte   unknown01       = reader.ReadByte(); //always 1
                int    fileId          = reader.ReadInt32();
                long   pathId          = reader.ReadInt64();
                int    classId         = reader.ReadInt32();
                ushort monoScriptIndex = reader.ReadUInt16();

                List <AssetPPtr> preloadDependencies = new List <AssetPPtr>();
                int preloadDependencyCount           = reader.ReadInt32();
                for (int i = 0; i < preloadDependencyCount; i++)
                {
                    AssetPPtr pptr = new AssetPPtr(reader.ReadInt32(), reader.ReadInt64());
                    preloadDependencies.Add(pptr);
                }

                if (replacerType == 0) //remover
                {
                    AssetsReplacer replacer = new AssetsRemover(fileId, pathId, classId, monoScriptIndex);
                    if (preloadDependencyCount != 0)
                    {
                        replacer.SetPreloadDependencies(preloadDependencies);
                    }

                    return(replacer);
                }
                else if (replacerType == 2) //adder/replacer?
                {
                    Hash128?          propertiesHash = null;
                    Hash128?          scriptHash     = null;
                    ClassDatabaseFile?classData      = null;
                    AssetsReplacer    replacer;

                    bool flag1 = reader.ReadByte() != 0; //no idea, couldn't get it to be 1
                    if (flag1)
                    {
                        throw new NotSupportedException("you just found a file with the mysterious flag1 set, send the file to nes");
                    }

                    bool flag2 = reader.ReadByte() != 0; //has properties hash
                    if (flag2)
                    {
                        propertiesHash = new Hash128(reader);
                    }

                    bool flag3 = reader.ReadByte() != 0; //has script hash
                    if (flag3)
                    {
                        scriptHash = new Hash128(reader);
                    }

                    bool flag4 = reader.ReadByte() != 0; //has cldb
                    if (flag4)
                    {
                        classData = new ClassDatabaseFile();
                        classData.Read(reader);
                    }

                    long bufLength = reader.ReadInt64();
                    if (prefReplacersInMemory)
                    {
                        byte[] buf = reader.ReadBytes((int)bufLength);
                        replacer = new AssetsReplacerFromMemory(fileId, pathId, classId, monoScriptIndex, buf);
                    }
                    else
                    {
                        replacer = new AssetsReplacerFromStream(fileId, pathId, classId, monoScriptIndex, reader.BaseStream, reader.Position, bufLength);
                    }

                    if (propertiesHash != null)
                    {
                        replacer.SetPropertiesHash(propertiesHash.Value);
                    }
                    if (scriptHash != null)
                    {
                        replacer.SetScriptIDHash(scriptHash.Value);
                    }
                    if (scriptHash != null)
                    {
                        replacer.SetTypeInfo(classData, null, false); //idk what the last two are supposed to do
                    }
                    if (preloadDependencyCount != 0)
                    {
                        replacer.SetPreloadDependencies(preloadDependencies);
                    }

                    return(replacer);
                }
            }
            return(null);
        }
Exemple #13
0
        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);
        }