/********* ** Private methods *********/ /// <summary>Try to apply a map overlay patch.</summary> /// <param name="source">The source map to overlay.</param> /// <param name="targetAsset">The target map to overlay.</param> /// <param name="error">An error indicating why applying the patch failed, if applicable.</param> /// <returns>Returns whether applying the patch succeeded.</returns> private bool TryApplyMapPatch(Map source, IAssetDataForMap targetAsset, out string error) { Map target = targetAsset.Data; // read data Rectangle mapBounds = this.GetMapArea(source); if (!this.TryReadArea(this.FromArea, 0, 0, mapBounds.Width, mapBounds.Height, out Rectangle sourceArea, out error)) { return(this.Fail($"the source area is invalid: {error}.", out error)); } if (!this.TryReadArea(this.ToArea, 0, 0, sourceArea.Width, sourceArea.Height, out Rectangle targetArea, out error)) { return(this.Fail($"the target area is invalid: {error}.", out error)); } // validate area values string sourceAreaLabel = this.FromArea != null ? $"{nameof(this.FromArea)}" : "source map"; string targetAreaLabel = this.ToArea != null ? $"{nameof(this.ToArea)}" : "target map"; Point sourceMapSize = new Point(source.Layers.Max(p => p.LayerWidth), source.Layers.Max(p => p.LayerHeight)); if (!this.TryValidateArea(sourceArea, sourceMapSize, "source", out error)) { return(this.Fail(error, out error)); } if (!this.TryValidateArea(targetArea, null, "target", out error)) { return(this.Fail(error, out error)); } if (sourceArea.Width != targetArea.Width || sourceArea.Height != targetArea.Height) { return(this.Fail($"{sourceAreaLabel} size (Width:{sourceArea.Width}, Height:{sourceArea.Height}) doesn't match {targetAreaLabel} size (Width:{targetArea.Width}, Height:{targetArea.Height}).", out error)); } // apply source map this.ExtendMap(target, minWidth: targetArea.Right, minHeight: targetArea.Bottom); targetAsset.PatchMap(source: source, sourceArea: sourceArea, targetArea: targetArea); error = null; return(true); }
/********* ** Private methods *********/ /// <inheritdoc cref="IContentEvents.AssetRequested"/> /// <param name="sender">The event sender.</param> /// <param name="e">The event data.</param> private void OnAssetRequested(object?sender, AssetRequestedEventArgs e) { // add farm type if (e.NameWithoutLocale.IsEquivalentTo("Data/AdditionalFarms")) { e.Edit(editor => { var data = editor.GetData <List <ModFarmType> >(); data.Add(new() { ID = this.ModManifest.UniqueID, TooltipStringPath = "Strings/UI:Pathoschild_BeachFarm_Description", MapName = "Pathoschild_SmallBeachFarm" }); }); } // add farm description else if (e.NameWithoutLocale.IsEquivalentTo("Strings/UI")) { e.Edit(editor => { var data = editor.AsDictionary <string, string>().Data; data["Pathoschild_BeachFarm_Description"] = $"{I18n.Farm_Name()}_{I18n.Farm_Description()}"; }); } // load map else if (e.NameWithoutLocale.IsEquivalentTo("Maps/Pathoschild_SmallBeachFarm")) { e.LoadFrom( () => { // load map Map map = this.Helper.ModContent.Load <Map>("assets/farm.tmx"); IAssetDataForMap editor = this.Helper.ModContent.GetPatchHelper(map).AsMap(); TileSheet outdoorTilesheet = map.GetTileSheet("untitled tile sheet"); Layer buildingsLayer = map.GetLayer("Buildings"); Layer backLayer = map.GetLayer("Back"); // add islands if (this.Config.EnableIslands) { Map islands = this.Helper.ModContent.Load <Map>("assets/overlay_islands.tmx"); Size size = islands.GetSizeInTiles(); editor.PatchMap(source: islands, targetArea: new Rectangle(0, 26, size.Width, size.Height)); } // add campfire if (this.Config.AddCampfire) { buildingsLayer.Tiles[65, 23] = new StaticTile(buildingsLayer, map.GetTileSheet("zbeach"), BlendMode.Alpha, 157); // driftwood pile buildingsLayer.Tiles[64, 22] = new StaticTile(buildingsLayer, outdoorTilesheet, BlendMode.Alpha, 242); // campfire } // remove shipping bin path if (!this.Config.ShippingBinPath) { for (int x = 71; x <= 72; x++) { for (int y = 14; y <= 15; y++) { backLayer.Tiles[x, y] = new StaticTile(backLayer, outdoorTilesheet, BlendMode.Alpha, 175); // grass tile } } } // add fishing pier if (this.Config.AddFishingPier) { // load overlay Map pier = this.Helper.ModContent.Load <Map>("assets/overlay_pier.tmx"); Size size = pier.GetSizeInTiles(); // get target position Point position = this.Config.CustomFishingPierPosition; if (position == Point.Zero) { position = new Point(70, 26); } // remove building tiles which block movement on the pier { var pierBack = pier.GetLayer("Back"); for (int x = 0; x < size.Width; x++) { for (int y = 0; y < size.Height; y++) { if (pierBack.Tiles[x, y] is not null) { buildingsLayer.Tiles[position.X + x, position.Y + y] = null; } } } } // apply overlay editor.PatchMap(source: pier, targetArea: new Rectangle(position.X, position.Y, size.Width, size.Height)); } // apply tilesheet recolors foreach (TileSheet tilesheet in map.TileSheets) { IAssetName imageSource = this.Helper.GameContent.ParseAssetName(tilesheet.ImageSource); if (imageSource.StartsWith($"{this.TilesheetsPath}/_default/")) { tilesheet.ImageSource = PathUtilities.NormalizeAssetName($"{this.FakeAssetPrefix}/{Path.GetFileNameWithoutExtension(tilesheet.ImageSource)}"); } } return(map); }, AssetLoadPriority.Exclusive ); } // load tilesheet else if (e.NameWithoutLocale.StartsWith(this.FakeAssetPrefix)) { e.LoadFrom( () => { string filename = Path.GetFileName(e.NameWithoutLocale.Name); if (!Path.HasExtension(filename)) { filename += ".png"; } // get relative path to load string?relativePath = new DirectoryInfo(this.GetFullPath(this.TilesheetsPath)) .EnumerateDirectories() .FirstOrDefault(p => p.Name != "_default" && this.Helper.ModRegistry.IsLoaded(p.Name)) ?.Name; relativePath = Path.Combine(this.TilesheetsPath, relativePath ?? "_default", filename); // load asset Texture2D tilesheet = this.Helper.ModContent.Load <Texture2D>(relativePath); return(tilesheet); }, AssetLoadPriority.Exclusive ); } }