Beispiel #1
0
        private void GenerateTtrTree(Type_0D type)
        {
            ttr_tree.Nodes.Clear();
            List <TreeNode> treeNodeStack = new List <TreeNode>();
            TypeField_0D    baseField     = type.typeFieldsEx[0];
            TreeNode        rootNode      = ttr_tree.Nodes.Add(TypeFieldToString(baseField, type));

            rootNode.Tag = baseField;
            treeNodeStack.Add(rootNode);
            for (int i = 1; i < type.typeFieldsEx.Length; i++)
            {
                TypeField_0D field      = type.typeFieldsEx[i];
                TreeNode     parentNode = treeNodeStack[field.depth - 1];
                TreeNode     node       = parentNode.Nodes.Add(TypeFieldToString(field, type));
                node.Tag = field;
                if (treeNodeStack.Count > field.depth)
                {
                    treeNodeStack[field.depth] = node;
                }
                else
                {
                    treeNodeStack.Add(node);
                }
            }
        }
        private void Ttr_list_SelectedIndexChanged(object sender, EventArgs e)
        {
            Type_0D type = file.typeTree.pTypes_Unity5[ttr_list.SelectedIndex];

            if (type.typeFieldsExCount == 0)
            {
                ClassDatabaseType cldt = cldb.classes.First(c => c.classId == type.classId);
                ttr_type.Text = cldt.name.GetString(cldb);
            }
            else
            {
                TypeField_0D baseField = type.pTypeFieldsEx[0];
                ttr_type.Text = baseField.GetTypeString(type.pStringTable);
            }
            ttr_typeid.Text   = type.classId.ToString();
            ttr_scriptid.Text = type.scriptIndex.ToString();

            if (type.unknown5 != 0 || type.unknown6 != 0 || type.unknown7 != 0 || type.unknown8 != 0)
            {
                ttr_hash.Text = $"{type.unknown5.ToString("x8")}{type.unknown6.ToString("x8")}{type.unknown7.ToString("x8")}{type.unknown8.ToString("x8")}";
            }
            else
            {
                ttr_hash.Text = "";
            }

            if (type.unknown1 != 0 || type.unknown2 != 0 || type.unknown3 != 0 || type.unknown4 != 0)
            {
                ttr_monohash.Text = $"{type.unknown1.ToString("x8")}{type.unknown2.ToString("x8")}{type.unknown3.ToString("x8")}{type.unknown4.ToString("x8")}";
            }
            else
            {
                ttr_monohash.Text = "";
            }
        }
Beispiel #3
0
        private static void CreateSceneMetadataTypeTree(ClassDatabaseFile cldb, AssetsFileInstance inst)
        {
            Type_0D type = C2T5.Cldb2TypeTree(cldb, 0x72);

            type.scriptIndex = 0x0001;
            type.unknown1    = Constants.sceneMetadataScriptNEHash[0];
            type.unknown2    = Constants.sceneMetadataScriptNEHash[1];
            type.unknown3    = Constants.sceneMetadataScriptNEHash[2];
            type.unknown4    = Constants.sceneMetadataScriptNEHash[3];

            TypeTreeEditor editor    = new TypeTreeEditor(type);
            TypeField_0D   baseField = type.pTypeFieldsEx[0];

            uint sceneName = editor.AddField(baseField, editor.CreateTypeField("string", "sceneName", 1, uint.MaxValue, 0, false, false, Flags.AnyChildUsesAlignBytesFlag));
            uint Array     = editor.AddField(editor.type.pTypeFieldsEx[sceneName], editor.CreateTypeField("Array", "Array", 2, uint.MaxValue, 0, true, true, Flags.HideInEditorMask));

            editor.AddField(editor.type.pTypeFieldsEx[Array], editor.CreateTypeField("int", "size", 3, 4, 0, false, false, Flags.HideInEditorMask));
            editor.AddField(editor.type.pTypeFieldsEx[Array], editor.CreateTypeField("char", "data", 3, 1, 0, false, false, Flags.HideInEditorMask));
            uint usedIds = editor.AddField(baseField, editor.CreateTypeField("vector", "usedIds", 1, uint.MaxValue, 0, false, false, Flags.AnyChildUsesAlignBytesFlag));
            uint Array2  = editor.AddField(editor.type.pTypeFieldsEx[usedIds], editor.CreateTypeField("Array", "Array", 2, uint.MaxValue, 0, true, true));

            editor.AddField(editor.type.pTypeFieldsEx[Array2], editor.CreateTypeField("int", "size", 3, 4, 0, false));
            editor.AddField(editor.type.pTypeFieldsEx[Array2], editor.CreateTypeField("SInt64", "data", 3, 8, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("int", "hkweVersion", 1, 4, 0, false));
            type = editor.SaveType();

            inst.file.typeTree.pTypes_Unity5 = inst.file.typeTree.pTypes_Unity5.Concat(new Type_0D[] { type }).ToArray();
            inst.file.typeTree.fieldCount++;
        }
Beispiel #4
0
        /////////////////////////////////////////////////////////

        private static Type_0D CreateEditDifferTypeTree(ClassDatabaseFile cldb)
        {
            Type_0D type = C2T5.Cldb2TypeTree(cldb, 0x72);

            type.scriptIndex = 0x0000;
            type.unknown1    = Constants.editDifferScriptNEHash[0];
            type.unknown2    = Constants.editDifferScriptNEHash[1];
            type.unknown3    = Constants.editDifferScriptNEHash[2];
            type.unknown4    = Constants.editDifferScriptNEHash[3];

            TypeTreeEditor editor    = new TypeTreeEditor(type);
            TypeField_0D   baseField = type.pTypeFieldsEx[0];

            editor.AddField(baseField, editor.CreateTypeField("unsigned int", "fileId", 1, 4, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("UInt64", "pathId", 1, 8, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("UInt64", "origPathId", 1, 8, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("UInt8", "newAsset", 1, 1, 0, true));
            uint componentIds = editor.AddField(baseField, editor.CreateTypeField("vector", "componentIds", 1, uint.MaxValue, 0, false, false, Flags.AnyChildUsesAlignBytesFlag));
            uint Array        = editor.AddField(editor.type.pTypeFieldsEx[componentIds], editor.CreateTypeField("Array", "Array", 2, uint.MaxValue, 0, true, true));

            editor.AddField(editor.type.pTypeFieldsEx[Array], editor.CreateTypeField("int", "size", 3, 4, 0, false));
            editor.AddField(editor.type.pTypeFieldsEx[Array], editor.CreateTypeField("SInt64", "data", 3, 8, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("int", "instanceId", 1, 4, 0, false));

            type = editor.SaveType();
            return(type);
        }
Beispiel #5
0
        private void XRefsDialog_Load(object sender, EventArgs e)
        {
            List <AssetID> xrefs = map.GetXRefs(id);

            if (xrefs == null)
            {
                xrefList.Items.Add("[no xrefs]");
            }
            else
            {
                foreach (AssetID id in xrefs)
                {
                    int instIndex = am.files.FindIndex(f => Path.GetFileName(f.path).ToLower() == Path.GetFileName(id.fileName).ToLower());
                    if (instIndex != -1)
                    {
                        AssetsFileInstance xrefInst = am.files[instIndex];
                        AssetsFile         xrefFile = xrefInst.file;
                        AssetFileInfoEx    xrefInf  = xrefInst.table.GetAssetInfo(id.pathID);
                        uint fixedId     = AssetHelper.FixAudioID(xrefInf.curFileType);
                        bool hasTypeTree = xrefFile.typeTree.hasTypeTree;

                        string assetName = AssetHelper.GetAssetNameFast(xrefFile, am.classFile, xrefInf);
                        string typeName;
                        if (hasTypeTree)
                        {
                            Type_0D xrefType = AssetHelper.FindTypeTreeTypeByID(xrefFile.typeTree, fixedId);
                            typeName = xrefType.typeFieldsEx[0].GetTypeString(xrefType.stringTable);
                        }
                        else
                        {
                            ClassDatabaseType xrefType = AssetHelper.FindAssetClassByID(am.classFile, fixedId);
                            typeName = xrefType.name.GetString(am.classFile);
                        }
                        xrefList.Items.Add(new ListBoxInfo($"{id.fileName} {id.pathID} ({typeName} {assetName})", id));
                    }
                    else
                    {
                        xrefList.Items.Add(new ListBoxInfo($"{id.fileName} {id.pathID}", id));
                    }
                }
            }
        }
Beispiel #6
0
        public uint   _fmt;      //not stored here in the .assets file, the variable is just to remember the .assets file version

        public ulong Read(ulong absFilePos, AssetsFileReader reader, uint version, bool bigEndian)
        {
            unityVersion  = reader.ReadNullTerminated();
            this.version  = reader.ReadUInt32();
            hasTypeTree   = reader.ReadBoolean();
            fieldCount    = reader.ReadUInt32();
            pTypes_Unity5 = new Type_0D[fieldCount];
            for (int i = 0; i < fieldCount; i++)
            {
                Type_0D type0d = new Type_0D();
                type0d.Read(hasTypeTree, reader.Position, reader, version, version, bigEndian);
                pTypes_Unity5[i] = type0d;
            }
            if (version < 0x0E)
            {
                dwUnknown = reader.ReadUInt24();
            }
            _fmt = version; //-todo: figure out what the heck this is for. if ver = -1 on write does it set it to default or something?
            return(reader.Position);
        }//Minimum AssetsFile format : 6
Beispiel #7
0
 public ulong Read(ulong absFilePos, AssetsFileReader reader, uint version, bool bigEndian)
 {
     unityVersion  = reader.ReadNullTerminated();
     this.version  = reader.ReadUInt32();
     hasTypeTree   = reader.ReadBoolean();
     fieldCount    = reader.ReadUInt32();
     pTypes_Unity5 = new Type_0D[fieldCount];
     for (int i = 0; i < fieldCount; i++)
     {
         Type_0D type0d = new Type_0D();
         type0d.Read(hasTypeTree, reader.Position, reader, version, version, bigEndian);
         pTypes_Unity5[i] = type0d;
     }
     if (version < 0x0E)
     {
         dwUnknown = reader.ReadUInt32();
     }
     _fmt = version;
     return(reader.Position);
 }
Beispiel #8
0
        private void Ttr_list_SelectedIndexChanged(object sender, EventArgs e)
        {
            TypeTree typeTree = file.typeTree;
            Type_0D  type     = typeTree.unity5Types[ttr_list.SelectedIndex];

            if (type.typeFieldsExCount == 0)
            {
                ClassDatabaseType cldt = cldb.classes.First(c => c.classId == type.classId);
                ttr_type.Text = cldt.name.GetString(cldb);
            }
            else
            {
                TypeField_0D baseField = type.typeFieldsEx[0];
                ttr_type.Text = baseField.GetTypeString(type.stringTable);
            }
            ttr_typeid.Text   = type.classId.ToString();
            ttr_scriptid.Text = type.scriptIndex.ToString();

            if (type.typeHash1 != 0 || type.typeHash2 != 0 || type.typeHash3 != 0 || type.typeHash4 != 0)
            {
                ttr_hash.Text = $"{type.typeHash1.ToString("x8")}{type.typeHash2.ToString("x8")}{type.typeHash3.ToString("x8")}{type.typeHash4.ToString("x8")}";
            }
            else
            {
                ttr_hash.Text = "";
            }

            if (type.scriptHash1 != 0 || type.scriptHash2 != 0 || type.scriptHash3 != 0 || type.scriptHash4 != 0)
            {
                ttr_monohash.Text = $"{type.scriptHash1.ToString("x8")}{type.scriptHash2.ToString("x8")}{type.scriptHash3.ToString("x8")}{type.scriptHash4.ToString("x8")}";
            }
            else
            {
                ttr_monohash.Text = "";
            }

            if (typeTree.hasTypeTree)
            {
                GenerateTtrTree(type);
            }
        }
Beispiel #9
0
        public AssetTypeTemplateField GetTemplateField(AssetsFile file, uint type, ushort scriptIndex)
        {
            uint fixedId = AssetHelper.FixAudioID(type);
            bool hasTypeTree = file.typeTree.hasTypeTree;

            AssetTypeTemplateField baseField = new AssetTypeTemplateField();
            if (hasTypeTree)
            {
                Type_0D type0d = Extensions.FindTypeTreeTypeByID(file.typeTree, fixedId, scriptIndex);

                if (type0d != null && type0d.typeFieldsExCount > 0)
                    baseField.From0D(type0d, 0);
                else //fallback to cldb
                    baseField.FromClassDatabase(am.classFile, AssetHelper.FindAssetClassByID(am.classFile, fixedId), 0);
            }
            else
            {
                baseField.FromClassDatabase(am.classFile, AssetHelper.FindAssetClassByID(am.classFile, fixedId), 0);
            }

            return baseField;
        }
Beispiel #10
0
        private static Type_0D CreateTk2dEmuTypeTree(ClassDatabaseFile cldb)
        {
            Type_0D type = C2T5.Cldb2TypeTree(cldb, 0x72);

            type.scriptIndex = 0x0001;
            type.scriptHash1 = Constants.tk2dEmuScriptNEHash[0];
            type.scriptHash2 = Constants.tk2dEmuScriptNEHash[1];
            type.scriptHash3 = Constants.tk2dEmuScriptNEHash[2];
            type.scriptHash4 = Constants.tk2dEmuScriptNEHash[3];

            TypeTreeEditor editor    = new TypeTreeEditor(type);
            TypeField_0D   baseField = type.typeFieldsEx[0];

            uint vertices = editor.AddField(baseField, editor.CreateTypeField("vector", "vertices", 1, -1, 0, false, false, Flags.AnyChildUsesAlignBytesFlag));
            uint Array    = editor.AddField(editor.type.typeFieldsEx[vertices], editor.CreateTypeField("Array", "Array", 2, -1, 0, true, true));

            editor.AddField(editor.type.typeFieldsEx[Array], editor.CreateTypeField("int", "size", 3, 4, 0, false));
            uint data = editor.AddField(editor.type.typeFieldsEx[Array], editor.CreateTypeField("Vector3", "data", 3, -1, 0, false));

            editor.AddField(editor.type.typeFieldsEx[data], editor.CreateTypeField("float", "x", 4, 4, 0, false));
            editor.AddField(editor.type.typeFieldsEx[data], editor.CreateTypeField("float", "y", 4, 4, 0, false));
            editor.AddField(editor.type.typeFieldsEx[data], editor.CreateTypeField("float", "z", 4, 4, 0, false));
            uint uvs = editor.AddField(baseField, editor.CreateTypeField("vector", "uvs", 1, -1, 0, false, false, Flags.AnyChildUsesAlignBytesFlag));

            Array = editor.AddField(editor.type.typeFieldsEx[uvs], editor.CreateTypeField("Array", "Array", 2, -1, 0, true, true));
            editor.AddField(editor.type.typeFieldsEx[Array], editor.CreateTypeField("int", "size", 3, 4, 0, false));
            data = editor.AddField(editor.type.typeFieldsEx[Array], editor.CreateTypeField("Vector2", "data", 3, -1, 0, false));
            editor.AddField(editor.type.typeFieldsEx[data], editor.CreateTypeField("float", "x", 4, 4, 0, false));
            editor.AddField(editor.type.typeFieldsEx[data], editor.CreateTypeField("float", "y", 4, 4, 0, false));
            uint indices = editor.AddField(baseField, editor.CreateTypeField("vector", "indices", 1, -1, 0, false, false, Flags.AnyChildUsesAlignBytesFlag));

            Array = editor.AddField(editor.type.typeFieldsEx[indices], editor.CreateTypeField("Array", "Array", 2, -1, 0, true, true));
            editor.AddField(editor.type.typeFieldsEx[Array], editor.CreateTypeField("int", "size", 3, 4, 0, false));
            editor.AddField(editor.type.typeFieldsEx[Array], editor.CreateTypeField("int", "data", 3, 4, 0, false));

            type = editor.SaveType();
            return(type);
        }
Beispiel #11
0
        /////////////////////////////////////////////////////////

        private static void CreateEditDifferTypeTree(ClassDatabaseFile cldb, AssetsFileInstance inst)
        {
            Type_0D type = C2T5.Cldb2TypeTree(cldb, 0x72);

            type.scriptIndex = 0x0000;
            type.unknown1    = Constants.editDifferScriptNEHash[0];
            type.unknown2    = Constants.editDifferScriptNEHash[1];
            type.unknown3    = Constants.editDifferScriptNEHash[2];
            type.unknown4    = Constants.editDifferScriptNEHash[3];

            TypeTreeEditor editor    = new TypeTreeEditor(type);
            TypeField_0D   baseField = type.pTypeFieldsEx[0];

            editor.AddField(baseField, editor.CreateTypeField("unsigned int", "fileId", 1, 4, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("UInt64", "pathId", 1, 8, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("UInt64", "origPathId", 1, 8, 0, false));
            editor.AddField(baseField, editor.CreateTypeField("UInt8", "newAsset", 1, 1, 0, true));
            editor.AddField(baseField, editor.CreateTypeField("int", "instanceId", 1, 4, 0, false));
            type = editor.SaveType();

            inst.file.typeTree.pTypes_Unity5 = inst.file.typeTree.pTypes_Unity5.Concat(new Type_0D[] { type }).ToArray();
            inst.file.typeTree.fieldCount++;
        }
Beispiel #12
0
 public static Type_0D FixTypeTree(Type_0D tt)
 {
     //if basefield isn't 3, unity won't load the bundle
     tt.pTypeFieldsEx[0].version = 3;
     return(tt);
 }
Beispiel #13
0
 public TypeField_0D[] TemplateToTypeField(AssetTypeTemplateField[] fields, Type_0D stringTableType)
 {
     return(TemplateToTypeField(fields, stringTableType.pStringTable));
 }
Beispiel #14
0
        public static Type_0D Cldb2TypeTree(ClassDatabaseFile classes, int id)
        {
            ClassDatabaseType type   = classes.classes.Where(c => c.classId == id).First();
            Type_0D           type0d = new Type_0D()
            {
                classId           = type.classId,
                typeFieldsExCount = (uint)type.fields.Count,
                scriptIndex       = 0xFFFF,
                unknown16_1       = 0,
                scriptHash1       = 0,
                scriptHash2       = 0,
                scriptHash3       = 0,
                scriptHash4       = 0,
                typeHash1         = 0,
                typeHash2         = 0,
                typeHash3         = 0,
                typeHash4         = 0
            };
            string stringTable = "";
            Dictionary <string, uint> strTableList = new Dictionary <string, uint>();
            Dictionary <string, uint> defTableList = new Dictionary <string, uint>();

            uint strTablePos = 0;
            uint defTablePos = 0;

            string[] defaultTable = Type_0D.strTable.Split('\0');
            foreach (string entry in defaultTable)
            {
                if (entry != "")
                {
                    defTableList.Add(entry, defTablePos);
                    defTablePos += (uint)entry.Length + 1;
                }
            }

            List <TypeField_0D> field0ds = new List <TypeField_0D>();

            for (int i = 0; i < type.fields.Count; i++)
            {
                ClassDatabaseTypeField field = type.fields[i];
                string fieldName             = field.fieldName.GetString(classes);
                string typeName     = field.typeName.GetString(classes);
                uint   fieldNamePos = 0xFFFFFFFF;
                uint   typeNamePos  = 0xFFFFFFFF;

                if (strTableList.ContainsKey(fieldName))
                {
                    fieldNamePos = strTableList[fieldName];
                }
                else if (defTableList.ContainsKey(fieldName))
                {
                    fieldNamePos = defTableList[fieldName] + 0x80000000;
                }
                else
                {
                    fieldNamePos = strTablePos;
                    strTableList.Add(fieldName, strTablePos);
                    strTablePos += (uint)fieldName.Length + 1;
                }

                if (strTableList.ContainsKey(typeName))
                {
                    typeNamePos = strTableList[typeName];
                }
                else if (defTableList.ContainsKey(typeName))
                {
                    typeNamePos = defTableList[typeName] + 0x80000000;
                }
                else
                {
                    typeNamePos = strTablePos;
                    strTableList.Add(typeName, strTablePos);
                    strTablePos += (uint)typeName.Length + 1;
                }

                field0ds.Add(new TypeField_0D()
                {
                    depth            = field.depth,
                    flags            = field.flags2,
                    index            = (uint)i,
                    isArray          = field.isArray,
                    nameStringOffset = fieldNamePos,
                    size             = field.size,
                    typeStringOffset = typeNamePos,
                    version          = field.version
                });
            }

            List <KeyValuePair <string, uint> > sortedStrTableList = strTableList.OrderBy(n => n.Value).ToList();

            foreach (KeyValuePair <string, uint> entry in sortedStrTableList)
            {
                stringTable += entry.Key + '\0';
            }

            type0d.stringTable    = stringTable;
            type0d.stringTableLen = (uint)stringTable.Length;
            type0d.typeFieldsEx   = field0ds.ToArray();
            return(type0d);
        }
Beispiel #15
0
        public static string GetAssetNameFast(AssetsFile file, ClassDatabaseFile cldb, AssetFileInfoEx info)
        {
            ClassDatabaseType type   = FindAssetClassByID(cldb, info.curFileType);
            AssetsFileReader  reader = file.reader;

            if (file.typeTree.hasTypeTree)
            {
                Type_0D ttType     = file.typeTree.unity5Types[info.curFileTypeOrIndex];
                string  ttTypeName = ttType.typeFieldsEx[0].GetTypeString(ttType.stringTable);
                if (ttType.typeFieldsEx.Length == 0)
                {
                    return(type.name.GetString(cldb));                                 //fallback to cldb
                }
                if (ttType.typeFieldsEx.Length > 1 && ttType.typeFieldsEx[1].GetNameString(ttType.stringTable) == "m_Name")
                {
                    reader.Position = info.absoluteFilePos;
                    return(reader.ReadCountStringInt32());
                }
                //todo, use the typetree since we have it already, there could be extra fields
                else if (ttTypeName == "GameObject")
                {
                    reader.Position = info.absoluteFilePos;
                    int size          = reader.ReadInt32();
                    int componentSize = file.header.format > 0x10 ? 0x0c : 0x10;
                    reader.Position += size * componentSize;
                    reader.Position += 0x04;
                    return(reader.ReadCountStringInt32());
                }
                else if (ttTypeName == "MonoBehaviour")
                {
                    reader.Position  = info.absoluteFilePos;
                    reader.Position += 0x1c;
                    string name = reader.ReadCountStringInt32();
                    if (name != "")
                    {
                        return(name);
                    }
                }
                return(ttTypeName);
            }

            string typeName = type.name.GetString(cldb);

            if (type.fields.Count == 0)
            {
                return(type.name.GetString(cldb));
            }
            if (type.fields.Count > 1 && type.fields[1].fieldName.GetString(cldb) == "m_Name")
            {
                reader.Position = info.absoluteFilePos;
                return(reader.ReadCountStringInt32());
            }
            else if (typeName == "GameObject")
            {
                reader.Position = info.absoluteFilePos;
                int size          = reader.ReadInt32();
                int componentSize = file.header.format > 0x10 ? 0x0c : 0x10;
                reader.Position += size * componentSize;
                reader.Position += 0x04;
                return(reader.ReadCountStringInt32());
            }
            else if (typeName == "MonoBehaviour")
            {
                reader.Position  = info.absoluteFilePos;
                reader.Position += 0x1c;
                string name = reader.ReadCountStringInt32();
                if (name != "")
                {
                    return(name);
                }
            }
            return(typeName);
        }
 public TypeTreeEditor(Type_0D type)
 {
     NullToDict(strTableList, ref strTablePos, type.stringTable);
     NullToDict(defTableList, ref defTablePos, Type_0D.strTable);
     this.type = type;
 }
Beispiel #17
0
        private ObservableCollection <AssetInfoDataGridItem> MakeDataGridItems()
        {
            dataGridItems = new ObservableCollection <AssetInfoDataGridItem>();

            bool usingTypeTree = assetsFile.file.typeTree.hasTypeTree;

            foreach (AssetFileInfoEx info in assetsFile.table.assetFileInfo)
            {
                string name;
                string container;
                string type;
                int    fileId;
                long   pathId;
                int    size;
                string modified;

                ClassDatabaseType cldbType = AssetHelper.FindAssetClassByID(am.classFile, info.curFileType);
                name      = AssetHelper.GetAssetNameFast(assetsFile.file, am.classFile, info); //handles both cldb and typetree
                container = string.Empty;
                fileId    = 0;
                pathId    = info.index;
                size      = (int)info.curFileSize;
                modified  = "";

                if (usingTypeTree)
                {
                    Type_0D ttType = assetsFile.file.typeTree.unity5Types[info.curFileTypeOrIndex];
                    if (ttType.typeFieldsEx.Length != 0)
                    {
                        type = ttType.typeFieldsEx[0].GetTypeString(ttType.stringTable);
                    }
                    else
                    {
                        if (cldbType != null)
                        {
                            type = cldbType.name.GetString(am.classFile);
                        }
                        else
                        {
                            type = $"0x{info.curFileType:X8}";
                        }
                    }
                }
                else
                {
                    if (cldbType != null)
                    {
                        type = cldbType.name.GetString(am.classFile);
                    }
                    else
                    {
                        type = $"0x{info.curFileType:X8}";
                    }
                }

                if (info.curFileType == 0x01)
                {
                    name = $"GameObject {name}";
                }
                if (name == string.Empty)
                {
                    name = "Unnamed asset";
                }

                var item = new AssetInfoDataGridItem()
                {
                    Name      = name,
                    Container = container,
                    Type      = type,
                    TypeID    = info.curFileType,
                    FileID    = fileId,
                    PathID    = pathId,
                    Size      = size,
                    Modified  = modified
                };

                dataGridItems.Add(item);
            }
            return(dataGridItems);
        }
Beispiel #18
0
        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();
                }
        }
Beispiel #19
0
        private string TypeFieldToString(TypeField_0D field, Type_0D type)
        {
            string stringTable = type.stringTable;

            return($"{field.GetTypeString(stringTable)} {field.GetNameString(stringTable)}");
        }
Beispiel #20
0
        public static Type_0D Cldb2TypeTree(ClassDatabaseFile classes, int id)
        {
            ClassDatabaseType type   = classes.classes.Where(c => c.classId == id).First();
            Type_0D           type0d = new Type_0D()
            {
                classId           = type.classId,
                typeFieldsExCount = (uint)type.fields.Count,
                scriptIndex       = 0xFFFF,
                unknown16_1       = 0,
                unknown1          = 0,
                unknown2          = 0,
                unknown3          = 0,
                unknown4          = 0,
                unknown5          = 0,
                unknown6          = 0,
                unknown7          = 0,
                unknown8          = 0
            };
            string stringTable           = "";
            List <TypeField_0D> field0ds = new List <TypeField_0D>();

            for (int i = 0; i < type.fields.Count; i++)
            {
                ClassDatabaseTypeField field = type.fields[i];
                string fieldName             = field.fieldName.GetString(classes) + '\0';
                string typeName     = field.typeName.GetString(classes) + '\0';
                uint   fieldNamePos = 0xFFFFFFFF;
                uint   typeNamePos  = 0xFFFFFFFF;

                if (stringTable.Contains(fieldName))
                {
                    fieldNamePos = (uint)stringTable.IndexOf(fieldName);
                }
                else if (Type_0D.strTable.Contains(fieldName))
                {
                    fieldNamePos = (uint)Type_0D.strTable.IndexOf(fieldName) + 0x80000000;
                }
                else
                {
                    fieldNamePos = (uint)stringTable.Length;
                    stringTable += fieldName;
                }

                if (stringTable.Contains(typeName))
                {
                    typeNamePos = (uint)stringTable.IndexOf(typeName);
                }
                else if (Type_0D.strTable.Contains(typeName))
                {
                    typeNamePos = (uint)Type_0D.strTable.IndexOf(typeName) + 0x80000000;
                }
                else
                {
                    typeNamePos  = (uint)stringTable.Length;
                    stringTable += typeName;
                }

                field0ds.Add(new TypeField_0D()
                {
                    depth            = field.depth,
                    flags            = field.flags2,
                    index            = (uint)i,
                    isArray          = field.isArray == 1 ? true : false,
                    nameStringOffset = fieldNamePos,
                    size             = field.size,
                    typeStringOffset = typeNamePos,
                    version          = field.version
                });
            }

            type0d.pStringTable   = stringTable;
            type0d.stringTableLen = (uint)stringTable.Length;
            type0d.pTypeFieldsEx  = field0ds.ToArray();
            return(type0d);
        }
Beispiel #21
0
        //AssetsFile
        public static ulong WriteFix(this AssetsFile file, AssetsFileWriter writer, ulong filePos, AssetsReplacer[] pReplacers, uint fileID, ClassDatabaseFile typeMeta = null)
        {
            file.header.Write(writer.Position, writer);

            for (int i = 0; i < pReplacers.Length; i++)
            {
                AssetsReplacer replacer = pReplacers[i];
                if (!file.typeTree.pTypes_Unity5.Any(t => t.classId == replacer.GetClassID()))
                {
                    Type_0D type = new Type_0D()
                    {
                        classId           = replacer.GetClassID(),
                        unknown16_1       = 0,
                        scriptIndex       = 0xFFFF,
                        unknown5          = 0,
                        unknown6          = 0,
                        unknown7          = 0,
                        unknown8          = 0,
                        typeFieldsExCount = 0,
                        stringTableLen    = 0,
                        pStringTable      = ""
                    };
                    file.typeTree.pTypes_Unity5.Concat(new Type_0D[] { type });
                }
            }
            file.typeTree.Write(writer.Position, writer, file.header.format);

            int initialSize  = (int)(AssetFileInfo.GetSize(file.header.format) * file.AssetCount);
            int newSize      = (int)(AssetFileInfo.GetSize(file.header.format) * (file.AssetCount + pReplacers.Length));
            int appendedSize = newSize - initialSize;

            file.reader.Position = file.AssetTablePos;

            List <AssetFileInfo>  originalAssetInfos = new List <AssetFileInfo>();
            List <AssetFileInfo>  assetInfos         = new List <AssetFileInfo>();
            List <AssetsReplacer> currentReplacers   = pReplacers.ToList();
            uint currentOffset = 0;

            //-write all original assets, modify sizes if needed and skip those to be removed
            for (int i = 0; i < file.AssetCount; i++)
            {
                AssetFileInfo info = new AssetFileInfo();
                info.Read(file.header.format, file.reader.Position, file.reader, file.reader.bigEndian);
                originalAssetInfos.Add(info);
                AssetsReplacer replacer = currentReplacers.FirstOrDefault(n => n.GetPathID() == info.index);
                if (replacer != null)
                {
                    currentReplacers.Remove(replacer);
                    if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                    {
                        int classIndex = Array.FindIndex(file.typeTree.pTypes_Unity5, t => t.classId == replacer.GetClassID());
                        info = new AssetFileInfo()
                        {
                            index               = replacer.GetPathID(),
                            offs_curFile        = currentOffset,
                            curFileSize         = (uint)replacer.GetSize(),
                            curFileTypeOrIndex  = (uint)classIndex,
                            inheritedUnityClass = (ushort)replacer.GetClassID(), //-what is this
                            scriptIndex         = replacer.GetMonoScriptID(),
                            unknown1            = 0
                        };
                    }
                    else if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_Remove)
                    {
                        continue;
                    }
                }
                currentOffset += info.curFileSize;
                uint pad = 8 - (currentOffset % 8);
                if (pad != 8)
                {
                    currentOffset += pad;
                }

                assetInfos.Add(info);
            }

            //-write new assets
            while (currentReplacers.Count > 0)
            {
                AssetsReplacer replacer = currentReplacers.First();
                if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                {
                    int           classIndex = Array.FindIndex(file.typeTree.pTypes_Unity5, t => t.classId == replacer.GetClassID());
                    AssetFileInfo info       = new AssetFileInfo()
                    {
                        index               = replacer.GetPathID(),
                        offs_curFile        = currentOffset,
                        curFileSize         = (uint)replacer.GetSize(),
                        curFileTypeOrIndex  = (uint)classIndex,
                        inheritedUnityClass = (ushort)replacer.GetClassID(),
                        scriptIndex         = replacer.GetMonoScriptID(),
                        unknown1            = 0
                    };
                    currentOffset += info.curFileSize;
                    uint pad = 8 - (currentOffset % 8);
                    if (pad != 8)
                    {
                        currentOffset += pad;
                    }

                    assetInfos.Add(info);
                }
                currentReplacers.Remove(replacer);
            }

            writer.Write(assetInfos.Count);
            writer.Align();
            for (int i = 0; i < assetInfos.Count; i++)
            {
                assetInfos[i].Write(file.header.format, writer.Position, writer);
            }

            file.preloadTable.Write(writer.Position, writer, file.header.format);

            file.dependencies.Write(writer.Position, writer, file.header.format);

            uint metadataSize = (uint)writer.Position - 0x13;

            //-for padding only. if all initial data before assetData is more than 0x1000, this is skipped
            while (writer.Position < 0x1000 /*header.offs_firstFile*/)
            {
                writer.Write((byte)0x00);
            }

            writer.Align16();

            uint offs_firstFile = (uint)writer.Position;

            for (int i = 0; i < assetInfos.Count; i++)
            {
                AssetFileInfo  info     = assetInfos[i];
                AssetsReplacer replacer = pReplacers.FirstOrDefault(n => n.GetPathID() == info.index);
                if (replacer != null)
                {
                    if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_AddOrModify)
                    {
                        replacer.Write(writer.Position, writer);
                        writer.Align8();
                    }
                    else if (replacer.GetReplacementType() == AssetsReplacementType.AssetsReplacement_Remove)
                    {
                        continue;
                    }
                }
                else
                {
                    AssetFileInfo originalInfo = originalAssetInfos.FirstOrDefault(n => n.index == info.index);
                    if (originalInfo != null)
                    {
                        file.reader.Position = file.header.offs_firstFile + originalInfo.offs_curFile;
                        byte[] assetData = file.reader.ReadBytes((int)originalInfo.curFileSize);
                        writer.Write(assetData);
                        writer.Align8();
                    }
                }
            }

            file.header.offs_firstFile = offs_firstFile;

            ulong fileSizeMarker = writer.Position;

            file.reader.Position = file.header.offs_firstFile;

            writer.Position          = 0;
            file.header.metadataSize = metadataSize;
            file.header.fileSize     = (uint)fileSizeMarker;
            file.header.Write(writer.Position, writer);
            return(writer.Position);
        }
Beispiel #22
0
        public static void GenerateLevelFiles(AssetsManager am, AssetsFileInstance inst)
        {
            EditorUtility.DisplayProgressBar("HKEdit", "Reading dependencies...", 0.5f);
            am.UpdateDependencies();

            //quicker asset id lookup
            for (int i = 0; i < am.files.Count; i++)
            {
                AssetsFileInstance afi = am.files[i];
                if (i % 100 == 0)
                {
                    EditorUtility.DisplayProgressBar("HKEdit", "Generating QLTs...", (float)i / am.files.Count);
                }
                afi.table.GenerateQuickLookupTree();
            }

            ClassDatabaseFile cldb  = am.classFile;
            AssetsFileTable   table = inst.table;

            ReferenceCrawler crawler = new ReferenceCrawler(am);

            List <AssetFileInfoEx> initialGameObjects = table.GetAssetsOfType(0x01);

            for (int i = 0; i < initialGameObjects.Count; i++)
            {
                if (i % 100 == 0)
                {
                    EditorUtility.DisplayProgressBar("HKEdit", "Recursing GameObject dependencies... (step 1/3)", (float)i / initialGameObjects.Count);
                }
                AssetFileInfoEx inf = initialGameObjects[i];
                crawler.AddReference(new AssetID(inst.path, (long)inf.index), false);
                crawler.FindReferences(inst, inf);
            }

            Dictionary <AssetID, AssetID> glblToLcl = crawler.references;

            List <Type_0D> types     = new List <Type_0D>();
            List <string>  typeNames = new List <string>();

            Dictionary <string, AssetsFileInstance> fileToInst = am.files.ToDictionary(d => d.path);
            int j = 0;

            foreach (KeyValuePair <AssetID, AssetID> id in glblToLcl)
            {
                if (j % 100 == 0)
                {
                    EditorUtility.DisplayProgressBar("HKEdit", "Rewiring asset pointers... (step 2/3)", (float)j / glblToLcl.Count);
                }
                AssetsFileInstance depInst = fileToInst[id.Key.fileName];
                AssetFileInfoEx    depInf  = depInst.table.getAssetInfo((ulong)id.Key.pathId);

                ClassDatabaseType clType = AssetHelper.FindAssetClassByID(cldb, depInf.curFileType);
                string            clName = clType.name.GetString(cldb);
                if (!typeNames.Contains(clName))
                {
                    Type_0D type0d = C2T5.Cldb2TypeTree(cldb, clName);
                    type0d.classId = (int)depInf.curFileType;
                    types.Add(type0d);
                    typeNames.Add(clName);
                }

                crawler.ReplaceReferences(depInst, depInf, id.Value.pathId);
                j++;
            }

            EditorUtility.DisplayProgressBar("HKEdit", "Saving scene... (step 3/3)", 1f);

            types.Add(CreateEditDifferTypeTree(cldb));

            List <Type_0D> assetTypes = new List <Type_0D>()
            {
                C2T5.Cldb2TypeTree(cldb, 0x1c),
                C2T5.Cldb2TypeTree(cldb, 0x30),
                C2T5.Cldb2TypeTree(cldb, 0x53)
            };

            string origFileName = Path.GetFileNameWithoutExtension(inst.path);

            string sceneGuid = CreateMD5(origFileName);

            string ExportedScenes = Path.Combine("Assets", "ExportedScenes");
            //circumvents "!BeginsWithCaseInsensitive(file.pathName, AssetDatabase::kAssetsPathWithSlash)' assertion
            string ExportedScenesData = "ExportedScenesData";

            CreateMetaFile(sceneGuid, Path.Combine(ExportedScenes, origFileName + ".unity.meta"));

            AssetsFile sceneFile = new AssetsFile(new AssetsFileReader(new MemoryStream(BundleCreator.CreateBlankAssets(ver, types))));
            AssetsFile assetFile = new AssetsFile(new AssetsFileReader(new MemoryStream(BundleCreator.CreateBlankAssets(ver, assetTypes))));

            byte[] sceneFileData;
            using (MemoryStream ms = new MemoryStream())
                using (AssetsFileWriter w = new AssetsFileWriter(ms))
                {
                    w.bigEndian = false;
                    //unity editor won't load whole assets files by guid, so we have to use hardcoded paths
                    sceneFile.dependencies.pDependencies = new AssetsFileDependency[]
                    {
                        CreateDependency(ExportedScenesData + "/" + origFileName + "-data.assets"),
                        CreateScriptDependency(Constants.editDifferMsEditorScriptHash, Constants.editDifferLsEditorScriptHash)
                    };
                    sceneFile.dependencies.dependencyCount = 2;
                    sceneFile.preloadTable.items           = new AssetPPtr[]
                    {
                        new AssetPPtr(2, 11500000)
                    };
                    sceneFile.preloadTable.len = 1;
                    sceneFile.Write(w, 0, crawler.sceneReplacers.Concat(crawler.sceneMonoReplacers).ToArray(), 0);
                    sceneFileData = ms.ToArray();
                }
            byte[] assetFileData;
            using (MemoryStream ms = new MemoryStream())
                using (AssetsFileWriter w = new AssetsFileWriter(ms))
                {
                    w.bigEndian = false;
                    assetFile.Write(w, 0, crawler.assetReplacers.ToArray(), 0);
                    assetFileData = ms.ToArray();
                }

            File.WriteAllBytes(Path.Combine(ExportedScenes, origFileName + ".unity"), sceneFileData);
            File.WriteAllBytes(Path.Combine(ExportedScenesData, origFileName + "-data.assets"), assetFileData);
            File.WriteAllText(Path.Combine(ExportedScenesData, origFileName + ".metadata"), CreateHKWEMetaFile(am, inst));

            EditorUtility.ClearProgressBar();
        }
Beispiel #23
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);
        }