Exemple #1
0
    private static void LoadScene()
    {
        am = new AssetsManager();
        am.LoadClassPackage("cldb.dat");
        am.useTemplateFieldCache = true;
        am.updateAfterLoad       = false;

        hkDir = Util.SteamHelper.GetHollowKnightDataPath();

        var globalgamemanagers = am.LoadAssetsFile(Path.Combine(hkDir, "globalgamemanagers"), false);
        var buildSettings      = globalgamemanagers.table.getAssetInfo(11);

        var baseField = am.GetATI(globalgamemanagers.file, buildSettings).GetBaseField();

        var scenesArray = baseField.Get("scenes").Get("Array");

        // TODO: Allow level to be selected
        const int level = 0;

        var levelName = scenesArray[level].GetValue().AsString().Substring(14);

        levelName = levelName.Substring(0, levelName.Length - 6);

        progressBarTitle = "Loading Scene #" + level + ": " + levelName;

        if (ShouldCancel("Checking workspace", 0.2f))
        {
            return;
        }

        if (!baseField.Get("m_Version").GetValue().AsString().Equals(Application.unityVersion))
        {
            EditorUtility.ClearProgressBar();
            EditorUtility.DisplayDialog("Incorrect Unity version!", " You are using " +
                                        Application.unityVersion + " but the assets are compiled for version " +
                                        baseField.Get("m_Version").GetValue().AsString(), "Ok");
            return;
        }

        unityVersion = Application.unityVersion;

        if (!Directory.Exists(scenesDir))
        {
            Directory.CreateDirectory(scenesDir);
        }

        if (!Directory.Exists(dataDir))
        {
            Directory.CreateDirectory(dataDir);
        }

        var metaFilePath   = Path.Combine(scenesDir, "level" + level + ".unity.meta");
        var sceneFilePath  = Path.Combine(scenesDir, "level" + level + ".unity");
        var assetsFilePath = Path.Combine(dataDir, "level" + level + ".assets");

        if (File.Exists(sceneFilePath))
        {
            if (EditorUtility.DisplayDialog("Overwrite scene?", "" +
                                            " You have already exported this scene. Would you like to overwrite it or open the existing scene? ",
                                            "Open Existing", "Overwrite"))
            {
                if (ShouldCancel("Opening Scene", 0.5f))
                {
                    return;
                }
                EditorSceneManager.OpenScene(sceneFilePath);
                EditorUtility.ClearProgressBar();
                return;
            }
            else
            {
                File.Delete(sceneFilePath);
            }
        }

        if (File.Exists(metaFilePath))
        {
            File.Delete(metaFilePath);
        }
        if (File.Exists(assetsFilePath))
        {
            File.Delete(assetsFilePath);
        }

        curSceneId = 1;
        curAssetId = 1;

        pointers       = new Dictionary <AssetID, AssetID>();
        sceneReplacers = new List <AssetsReplacer>();
        assetReplacers = new List <AssetsReplacer>();
        monoReplacers  = new List <AssetsReplacer>();

        if (ShouldCancel("Reading level file", 0.5f))
        {
            return;
        }
        var scenePath = Path.Combine(Util.SteamHelper.GetHollowKnightDataPath(), "level" + level);
        var scene     = am.LoadAssetsFile(scenePath, true);

        if (ShouldCancel("Updating Dependencies", 0.8f))
        {
            return;
        }
        am.UpdateDependencies();

        for (var i = 0; i < am.files.Count; i++)
        {
            if (i % 100 == 0 && ShouldCancel("Generating QLTs", (float)i / am.files.Count))
            {
                return;
            }
            am.files[i].table.GenerateQuickLookupTree();
        }

        var table                = scene.table;
        var gameObjects          = table.GetAssetsOfType(0x01);
        var gameObjectBaseFields = new Dictionary <AssetFileInfoEx, AssetTypeValueField>();

        var c = 0;

        for (c = 0; c < gameObjects.Count; c++)
        {
            if (c % 100 == 0 && ShouldCancel("Finding initial GameObjects", (float)c / gameObjects.Count))
            {
                return;
            }

            var gameObjectInfo      = gameObjects[c];
            var gameObjectBaseField = am.GetATI(scene.file, gameObjectInfo).GetBaseField();

            AddPointer(new AssetID(scene.path, (long)gameObjectInfo.index), false);
            gameObjectBaseFields.Add(gameObjectInfo, gameObjectBaseField);
        }
        c = 0;

        foreach (var pair in gameObjectBaseFields)
        {
            if (c % 100 == 0 && ShouldCancel("Recursing GameObject dependencies", (float)c / gameObjectBaseFields.Count))
            {
                return;
            }
            FindNestedPointers(scene, pair.Value, pair.Key, false);
            c++;
        }

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

        var fileToInst = am.files.ToDictionary(d => d.path);
        var j          = 0;

        foreach (var pair in pointers)
        {
            if (j % 100 == 0 && ShouldCancel("Rewiring asset pointers", (float)j / pointers.Count))
            {
                return;
            }

            var file = fileToInst[pair.Key.fileName];
            var info = file.table.getAssetInfo((ulong)pair.Key.pathId);

            var assetClass = AssetHelper.FindAssetClassByID(am.classFile, info.curFileType);
            var assetName  = assetClass.name.GetString(am.classFile);

            if (!typeNames.Contains(assetName))
            {
                var type0d = C2T5.Cldb2TypeTree(am.classFile, assetName);
                type0d.classId = (int)info.curFileType;
                types.Add(type0d);
                typeNames.Add(assetName);
            }

            ReplacePointers(file, info, pair.Value.pathId);
            j++;
        }

        if (ShouldCancel("Saving scene", 1))
        {
            return;
        }

        List <Type_0D> assetTypes = new List <Type_0D>()
        {
            C2T5.Cldb2TypeTree(am.classFile, 0x1c), // audioclip
            C2T5.Cldb2TypeTree(am.classFile, 0x30), // shader
            C2T5.Cldb2TypeTree(am.classFile, 0x53)  // texture2d
        };

        var sceneGuid = Util.UnityHelper.CreateMD5(levelName);

        UnityHelper.CreateMetaFile(sceneGuid, metaFilePath);

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

        byte[] sceneFileData;
        using (MemoryStream ms = new MemoryStream())
            using (AssetsFileWriter w = new AssetsFileWriter(ms))
            {
                w.bigEndian = false;
                sceneFile.dependencies.pDependencies = new AssetsFileDependency[]
                {
                    UnityHelper.CreateDependency(assetsFilePath),
                };
                sceneFile.dependencies.dependencyCount = 1;

                sceneFile.preloadTable.items = new AssetPPtr[] {};
                sceneFile.preloadTable.len   = 0;

                sceneFile.Write(w, 0, sceneReplacers.Concat(monoReplacers).ToArray(), 0);
                sceneFileData = ms.ToArray();
            }
        byte[] assetFileData;
        using (var ms = new MemoryStream())
            using (var w = new AssetsFileWriter(ms))
            {
                w.bigEndian = false;
                assetFile.Write(w, 0, assetReplacers.ToArray(), 0);
                assetFileData = ms.ToArray();
            }

        File.WriteAllBytes(sceneFilePath, sceneFileData);
        File.WriteAllBytes(assetsFilePath, assetFileData);

        if (ShouldCancel("Refreshing Assets", 0.95f))
        {
            return;
        }
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }