static LiveLinkChangeSet SerializeAndDeserialize(LiveLinkChangeSet srcChange)
    {
        var resolver = new GlobalAssetObjectResolver();

        var bytes = srcChange.Serialize();

        // Serialize Changes
        var resourcePacket = new EntityChangeSetSerialization.ResourcePacket(bytes);

        foreach (var asset in resourcePacket.GlobalObjectIds)
        {
            var manifest = ScriptableObject.CreateInstance <AssetObjectManifest>();
            AssetObjectManifestBuilder.BuildManifest(asset.AssetGUID, manifest);

            resolver.AddAsset(asset.AssetGUID, new Unity.Entities.Hash128(), manifest, null);
        }

        // Deserialize
        LiveLinkChangeSet changeSet;

        try
        {
            changeSet = LiveLinkChangeSet.Deserialize(resourcePacket, resolver);
        }
        finally
        {
            resourcePacket.Dispose();
            resolver.DisposeObjectManifests();
        }

        return(changeSet);
    }
        static void FilterBuiltinExtraResourcesObjectManifest(string manifestPath)
        {
            // Builtin Extra Resources in the editor contains a mix of Editor Only & Runtime types.
            // This is easier to filter as the type info is available to C# and we can just filter on UnityEngine vs UnityEditor
            // TODO: This will probably break someday, and we need a more reliable method for handling this.
            // TODO: Builtin Extra Resources should not contain Editor only types, there are Editor Builtin Resources for this
            var manifest = (AssetObjectManifest)UnityEditorInternal.InternalEditorUtility.LoadSerializedFileAndForget(manifestPath)[0];
            var objects  = manifest.Objects.Where(x => !x.GetType().FullName.Contains("UnityEditor")).ToArray();

            AssetObjectManifestBuilder.BuildManifest(objects, manifest);

            UnityEditorInternal.InternalEditorUtility.SaveToSerializedFileAndForget(new[] { manifest }, manifestPath, true);
        }
        static void FilterBuiltinResourcesObjectManifest(string manifestPath)
        {
            // Builtin Resources in the editor contains a mix of Editor Only & Runtime types.
            // Based on some trial an error, objects with these flags are the Runtime types.
            // TODO: This will probably break someday, and we need a more reliable method for handling this.
            // TODO: Builtin Resources should not contain Editor only types, there are Editor Builtin Resources for this
            var manifest = (AssetObjectManifest)UnityEditorInternal.InternalEditorUtility.LoadSerializedFileAndForget(manifestPath)[0];
            var objects  = manifest.Objects.Where(x => x.hideFlags == (HideFlags.HideInInspector | HideFlags.HideAndDontSave)).ToArray();

            AssetObjectManifestBuilder.BuildManifest(objects, manifest);

            UnityEditorInternal.InternalEditorUtility.SaveToSerializedFileAndForget(new[] { manifest }, manifestPath, true);
        }
        //@TODO: The asset pipeline should be building & cache the asset bundle
        public string BuildAssetBundleIfNotCached(GUID guid, out Hash128 targetHash)
        {
            //@TODO Get build target from player requesting it...
            var buildTarget = EditorUserBuildSettings.activeBuildTarget;

            targetHash = LiveLinkBuildPipeline.CalculateTargetHash(guid, buildTarget);

            // TODO: Move caching into LiveLinkBuildPipeline
            var cachePath = ResolveCachePath(targetHash);

            if (File.Exists(cachePath))
            {
                return(cachePath);
            }

            if (!Directory.Exists(cachePath))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
            }

            // Debug.Log($"Building {guid} fresh");
            // Patching only works if the ObjectManifest comes from the same GUID every time.
            // So we can't delete this file. Optimally we would control the build pipeline
            // to make it always be at a specific local identifier in file
            var manifest = ScriptableObject.CreateInstance <AssetObjectManifest>();

            AssetObjectManifestBuilder.BuildManifest(guid, manifest);
            UnityEditorInternal.InternalEditorUtility.SaveToSerializedFileAndForget(new[] { manifest }, AssetObjectManifestPath, true);

            var didSucceed = LiveLinkBuildPipeline.BuildAssetBundle(guid, $"{cachePath}", EditorUserBuildSettings.activeBuildTarget);

            if (!didSucceed)
            {
                Debug.LogError($"Failed to build asset bundle: '{guid}'");
                return(null);
            }

            return(cachePath);
        }