diff options
Diffstat (limited to 'src/SMAPI/Framework/Content/AssetDataForMap.cs')
-rw-r--r-- | src/SMAPI/Framework/Content/AssetDataForMap.cs | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/src/SMAPI/Framework/Content/AssetDataForMap.cs b/src/SMAPI/Framework/Content/AssetDataForMap.cs index 0425e195..133dcc6c 100644 --- a/src/SMAPI/Framework/Content/AssetDataForMap.cs +++ b/src/SMAPI/Framework/Content/AssetDataForMap.cs @@ -1,14 +1,15 @@ -#nullable disable - using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; +using StardewModdingAPI.Framework.Reflection; using StardewModdingAPI.Toolkit.Utilities; using StardewValley; using xTile; +using xTile.Dimensions; using xTile.Layers; using xTile.Tiles; +using Rectangle = Microsoft.Xna.Framework.Rectangle; namespace StardewModdingAPI.Framework.Content { @@ -16,6 +17,13 @@ namespace StardewModdingAPI.Framework.Content internal class AssetDataForMap : AssetData<Map>, IAssetDataForMap { /********* + ** Fields + *********/ + /// <summary>Simplifies access to private code.</summary> + private readonly Reflector Reflection; + + + /********* ** Public methods *********/ /// <summary>Construct an instance.</summary> @@ -24,8 +32,12 @@ namespace StardewModdingAPI.Framework.Content /// <param name="data">The content data being read.</param> /// <param name="getNormalizedPath">Normalizes an asset key to match the cache key.</param> /// <param name="onDataReplaced">A callback to invoke when the data is replaced (if any).</param> - public AssetDataForMap(string locale, IAssetName assetName, Map data, Func<string, string> getNormalizedPath, Action<Map> onDataReplaced) - : base(locale, assetName, data, getNormalizedPath, onDataReplaced) { } + /// <param name="reflection">Simplifies access to private code.</param> + public AssetDataForMap(string? locale, IAssetName assetName, Map data, Func<string, string> getNormalizedPath, Action<Map> onDataReplaced, Reflector reflection) + : base(locale, assetName, data, getNormalizedPath, onDataReplaced) + { + this.Reflection = reflection; + } /// <inheritdoc /> /// <remarks>Derived from <see cref="GameLocation.ApplyMapOverride(Map,string,Rectangle?,Rectangle?)"/> with a few changes: @@ -112,8 +124,7 @@ namespace StardewModdingAPI.Framework.Content foreach (Layer sourceLayer in source.Layers) { // get layer - Layer targetLayer = sourceToTargetLayers[sourceLayer]; - if (targetLayer == null) + if (!sourceToTargetLayers.TryGetValue(sourceLayer, out Layer? targetLayer)) { target.AddLayer(targetLayer = new Layer(sourceLayer.Id, target, target.Layers[0].LayerSize, Layer.m_tileSize)); sourceToTargetLayers[sourceLayer] = target.GetLayer(sourceLayer.Id); @@ -123,11 +134,13 @@ namespace StardewModdingAPI.Framework.Content targetLayer.Properties.CopyFrom(sourceLayer.Properties); // create new tile - Tile sourceTile = sourceLayer.Tiles[sourcePos.X, sourcePos.Y]; - Tile newTile = sourceTile != null - ? this.CreateTile(sourceTile, targetLayer, tilesheetMap[sourceTile.TileSheet]) - : null; - newTile?.Properties.CopyFrom(sourceTile.Properties); + Tile? sourceTile = sourceLayer.Tiles[sourcePos.X, sourcePos.Y]; + Tile? newTile = null; + if (sourceTile != null) + { + newTile = this.CreateTile(sourceTile, targetLayer, tilesheetMap[sourceTile.TileSheet]); + newTile?.Properties.CopyFrom(sourceTile.Properties); + } // replace tile if (newTile != null || replaceByLayer || replaceAll) @@ -137,6 +150,42 @@ namespace StardewModdingAPI.Framework.Content } } + /// <inheritdoc /> + public bool ExtendMap(Map map, int minWidth, int minHeight) + { + bool resized = false; + + // resize layers + foreach (Layer layer in map.Layers) + { + // check if resize needed + if (layer.LayerWidth >= minWidth && layer.LayerHeight >= minHeight) + continue; + resized = true; + + // build new tile matrix + int width = Math.Max(minWidth, layer.LayerWidth); + int height = Math.Max(minHeight, layer.LayerHeight); + Tile[,] tiles = new Tile[width, height]; + for (int x = 0; x < layer.LayerWidth; x++) + { + for (int y = 0; y < layer.LayerHeight; y++) + tiles[x, y] = layer.Tiles[x, y]; + } + + // update fields + this.Reflection.GetField<Tile[,]>(layer, "m_tiles").SetValue(tiles); + this.Reflection.GetField<TileArray>(layer, "m_tileArray").SetValue(new TileArray(layer, tiles)); + this.Reflection.GetField<Size>(layer, "m_layerSize").SetValue(new Size(width, height)); + } + + // resize map + if (resized) + this.Reflection.GetMethod(map, "UpdateDisplaySize").Invoke(); + + return resized; + } + /********* ** Private methods @@ -145,7 +194,7 @@ namespace StardewModdingAPI.Framework.Content /// <param name="sourceTile">The source tile to copy.</param> /// <param name="targetLayer">The target layer.</param> /// <param name="targetSheet">The target tilesheet.</param> - private Tile CreateTile(Tile sourceTile, Layer targetLayer, TileSheet targetSheet) + private Tile? CreateTile(Tile sourceTile, Layer targetLayer, TileSheet targetSheet) { switch (sourceTile) { @@ -170,7 +219,7 @@ namespace StardewModdingAPI.Framework.Content } /// <summary>Normalize a map tilesheet path for comparison. This value should *not* be used as the actual tilesheet path.</summary> /// <param name="path">The path to normalize.</param> - private string NormalizeTilesheetPathForComparison(string path) + private string NormalizeTilesheetPathForComparison(string? path) { if (string.IsNullOrWhiteSpace(path)) return string.Empty; |