public void GenerateDiff(string customMapPath, string referenceMapPath)
        {
            FormatManager formatManager = FormatManager.Instance;

            this.ModifiedMap  = formatManager.LoadMap(customMapPath);
            this.ReferenceMap = formatManager.LoadMap(referenceMapPath);

            Diff diff = new Diff();

            diff.Map = GetMapData();

            string data = JsonConvert.SerializeObject(diff, Serialization.Settings);

            File.WriteAllText("../../../TestData/diff.json", data);
        }
Beispiel #2
0
        /// <summary>Load content from the game folder or mod folder (if not already cached), and return it. When loading a <c>.png</c> file, this must be called outside the game's draw loop.</summary>
        /// <typeparam name="T">The expected data type. The main supported types are <see cref="Map"/>, <see cref="Texture2D"/>, and dictionaries; other types may be supported by the game's content pipeline.</typeparam>
        /// <param name="key">The asset key to fetch (if the <paramref name="source"/> is <see cref="ContentSource.GameContent"/>), or the local path to a content file relative to the mod folder.</param>
        /// <param name="source">Where to search for a matching content asset.</param>
        /// <exception cref="ArgumentException">The <paramref name="key"/> is empty or contains invalid characters.</exception>
        /// <exception cref="ContentLoadException">The content asset couldn't be loaded (e.g. because it doesn't exist).</exception>
        public T Load <T>(string key, ContentSource source = ContentSource.ModFolder)
        {
            SContentLoadException GetContentError(string reasonPhrase) => new SContentLoadException($"{this.ModName} failed loading content asset '{key}' from {source}: {reasonPhrase}.");

            try
            {
                this.AssertValidAssetKeyFormat(key);
                switch (source)
                {
                case ContentSource.GameContent:
                    return(this.ContentManager.Load <T>(key));

                case ContentSource.ModFolder:
                    // get file
                    FileInfo file = this.GetModFile(key);
                    if (!file.Exists)
                    {
                        throw GetContentError($"there's no matching file at path '{file.FullName}'.");
                    }

                    // get asset path
                    string assetName = this.ContentCore.GetAssetNameFromFilePath(file.FullName);

                    // try cache
                    if (this.ContentCore.IsLoaded(assetName))
                    {
                        return(this.ContentManager.Load <T>(assetName));
                    }

                    // fix map tilesheets
                    if (file.Extension.ToLower() == ".tbin")
                    {
                        // validate
                        if (typeof(T) != typeof(Map))
                        {
                            throw GetContentError($"can't read file with extension '{file.Extension}' as type '{typeof(T)}'; must be type '{typeof(Map)}'.");
                        }

                        // fetch & cache
                        FormatManager formatManager = FormatManager.Instance;
                        Map           map           = formatManager.LoadMap(file.FullName);
                        this.FixCustomTilesheetPaths(map, key);

                        // inject map
                        this.ContentManager.Inject(assetName, map);
                        return((T)(object)map);
                    }

                    // load through content manager
                    return(this.ContentManager.Load <T>(assetName));

                default:
                    throw GetContentError($"unknown content source '{source}'.");
                }
            }
            catch (Exception ex) when(!(ex is SContentLoadException))
            {
                throw new SContentLoadException($"{this.ModName} failed loading content asset '{key}' from {source}.", ex);
            }
        }
Beispiel #3
0
        /// <summary>Load an asset that has been processed by the content pipeline.</summary>
        /// <typeparam name="T">The type of asset to load.</typeparam>
        /// <param name="assetName">The asset path relative to the loader root directory, not including the <c>.xnb</c> extension.</param>
        /// <param name="language">The language code for which to load content.</param>
        /// <param name="useCache">Whether to read/write the loaded asset to the asset cache.</param>
        public override T Load <T>(string assetName, LanguageCode language, bool useCache)
        {
            assetName = this.AssertAndNormalizeAssetName(assetName);

            // disable caching
            // This is necessary to avoid assets being shared between content managers, which can
            // cause changes to an asset through one content manager affecting the same asset in
            // others (or even fresh content managers). See https://www.patreon.com/posts/27247161
            // for more background info.
            if (useCache)
            {
                throw new InvalidOperationException("Mod content managers don't support asset caching.");
            }

            // disable language handling
            // Mod files don't support automatic translation logic, so this should never happen.
            if (language != this.DefaultLanguage)
            {
                throw new InvalidOperationException("Localized assets aren't supported by the mod content manager.");
            }

            // resolve managed asset key
            {
                if (this.Coordinator.TryParseManagedAssetKey(assetName, out string contentManagerID, out string relativePath))
                {
                    if (contentManagerID != this.Name)
                    {
                        throw new SContentLoadException($"Can't load managed asset key '{assetName}' through content manager '{this.Name}' for a different mod.");
                    }
                    assetName = relativePath;
                }
            }

            // get local asset
            SContentLoadException GetContentError(string reasonPhrase) => new SContentLoadException($"Failed loading asset '{assetName}' from {this.Name}: {reasonPhrase}");

            T asset;

            try
            {
                // get file
                FileInfo file = this.GetModFile(assetName);
                if (!file.Exists)
                {
                    throw GetContentError("the specified path doesn't exist.");
                }

                // load content
                switch (file.Extension.ToLower())
                {
                // XNB file
                case ".xnb":
                {
                    asset = this.RawLoad <T>(assetName, useCache: false);
                    if (asset is Map map)
                    {
                        this.NormalizeTilesheetPaths(map);
                        this.FixCustomTilesheetPaths(map, relativeMapPath: assetName);
                    }
                }
                break;

                // unpacked data
                case ".json":
                {
                    if (!this.JsonHelper.ReadJsonFileIfExists(file.FullName, out asset))
                    {
                        throw GetContentError("the JSON file is invalid.");         // should never happen since we check for file existence above
                    }
                }
                break;

                // unpacked image
                case ".png":
                {
                    // validate
                    if (typeof(T) != typeof(Texture2D))
                    {
                        throw GetContentError($"can't read file with extension '{file.Extension}' as type '{typeof(T)}'; must be type '{typeof(Texture2D)}'.");
                    }

                    // fetch & cache
                    using FileStream stream = File.OpenRead(file.FullName);

                    Texture2D texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, stream);
                    texture = this.PremultiplyTransparency(texture);
                    asset   = (T)(object)texture;
                }
                break;

                // unpacked map
                case ".tbin":
                case ".tmx":
                {
                    // validate
                    if (typeof(T) != typeof(Map))
                    {
                        throw GetContentError($"can't read file with extension '{file.Extension}' as type '{typeof(T)}'; must be type '{typeof(Map)}'.");
                    }

                    // fetch & cache
                    FormatManager formatManager = FormatManager.Instance;
                    Map           map           = formatManager.LoadMap(file.FullName);
                    this.NormalizeTilesheetPaths(map);
                    this.FixCustomTilesheetPaths(map, relativeMapPath: assetName);
                    asset = (T)(object)map;
                }
                break;

                default:
                    throw GetContentError($"unknown file extension '{file.Extension}'; must be one of '.json', '.png', '.tbin', or '.xnb'.");
                }
            }
            catch (Exception ex) when(!(ex is SContentLoadException))
            {
                if (ex.GetInnermostException() is DllNotFoundException dllEx && dllEx.Message == "libgdiplus.dylib")
                {
                    throw GetContentError("couldn't find libgdiplus, which is needed to load mod images. Make sure Mono is installed and you're running the game through the normal launcher.");
                }
                throw new SContentLoadException($"The content manager failed loading content asset '{assetName}' from {this.Name}.", ex);
            }

            // track & return asset
            this.TrackAsset(assetName, asset, language, useCache);
            return(asset);
        }
Beispiel #4
0
        /// <summary>Load content from the game folder or mod folder (if not already cached), and return it. When loading a <c>.png</c> file, this must be called outside the game's draw loop.</summary>
        /// <typeparam name="T">The expected data type. The main supported types are <see cref="Texture2D"/> and dictionaries; other types may be supported by the game's content pipeline.</typeparam>
        /// <param name="key">The asset key to fetch (if the <paramref name="source"/> is <see cref="ContentSource.GameContent"/>), or the local path to a content file relative to the mod folder.</param>
        /// <param name="source">Where to search for a matching content asset.</param>
        /// <exception cref="ArgumentException">The <paramref name="key"/> is empty or contains invalid characters.</exception>
        /// <exception cref="ContentLoadException">The content asset couldn't be loaded (e.g. because it doesn't exist).</exception>
        public T Load <T>(string key, ContentSource source = ContentSource.ModFolder)
        {
            SContentLoadException GetContentError(string reasonPhrase) => new SContentLoadException($"{this.ModName} failed loading content asset '{key}' from {source}: {reasonPhrase}.");

            this.AssertValidAssetKeyFormat(key);
            try
            {
                switch (source)
                {
                case ContentSource.GameContent:
                    return(this.ContentManager.Load <T>(key));

                case ContentSource.ModFolder:
                    // get file
                    FileInfo file = this.GetModFile(key);
                    if (!file.Exists)
                    {
                        throw GetContentError($"there's no matching file at path '{file.FullName}'.");
                    }

                    // get asset path
                    string assetPath = this.GetModAssetPath(key, file.FullName);

                    // try cache
                    if (this.ContentManager.IsLoaded(assetPath))
                    {
                        return(this.ContentManager.Load <T>(assetPath));
                    }

                    // load content
                    switch (file.Extension.ToLower())
                    {
                    // XNB file
                    case ".xnb":
                    {
                        T asset = this.ContentManager.Load <T>(assetPath);
                        if (asset is Map)
                        {
                            this.FixLocalMapTilesheets(asset as Map, key);
                        }
                        return(asset);
                    }

                    // unpacked map
                    case ".tbin":
                    {
                        // validate
                        if (typeof(T) != typeof(Map))
                        {
                            throw GetContentError($"can't read file with extension '{file.Extension}' as type '{typeof(T)}'; must be type '{typeof(Map)}'.");
                        }

                        // fetch & cache
                        FormatManager formatManager = FormatManager.Instance;
                        Map           map           = formatManager.LoadMap(file.FullName);
                        this.FixLocalMapTilesheets(map, key);

                        // inject map
                        this.ContentManager.Inject(assetPath, map);
                        return((T)(object)map);
                    }

                    // unpacked image
                    case ".png":
                        // validate
                        if (typeof(T) != typeof(Texture2D))
                        {
                            throw GetContentError($"can't read file with extension '{file.Extension}' as type '{typeof(T)}'; must be type '{typeof(Texture2D)}'.");
                        }

                        // fetch & cache
                        using (FileStream stream = File.OpenRead(file.FullName))
                        {
                            Texture2D texture = Texture2D.FromStream(Game1.graphics.GraphicsDevice, stream);
                            texture = this.PremultiplyTransparency(texture);
                            this.ContentManager.Inject(assetPath, texture);
                            return((T)(object)texture);
                        }

                    default:
                        throw GetContentError($"unknown file extension '{file.Extension}'; must be one of '.png', '.tbin', or '.xnb'.");
                    }

                default:
                    throw GetContentError($"unknown content source '{source}'.");
                }
            }
            catch (Exception ex) when(!(ex is SContentLoadException))
            {
                throw new SContentLoadException($"{this.ModName} failed loading content asset '{key}' from {source}.", ex);
            }
        }