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); }
/// <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); } }
/// <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); }
/// <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); } }