From ad0cb687b7d6451790c0b684975a3037216aa44b Mon Sep 17 00:00:00 2001 From: Katie Durden Date: Tue, 4 Apr 2023 15:09:49 -0700 Subject: [PATCH] Readded `lessInfo` to many tiles related functions and other code cleanup (making argument ordering consist. --- stardew-access/Features/DynamicTiles.cs | 1192 +++++++++-------- stardew-access/Features/Radar.cs | 6 +- stardew-access/Features/ReadTile.cs | 2 +- stardew-access/Features/StaticTiles.cs | 2 +- stardew-access/Features/TileInfo.cs | 159 ++- stardew-access/Features/TileViewer.cs | 4 +- .../Patches/MiscPatches/Game1Patch.cs | 2 +- 7 files changed, 694 insertions(+), 673 deletions(-) diff --git a/stardew-access/Features/DynamicTiles.cs b/stardew-access/Features/DynamicTiles.cs index cc50483..2ea15c3 100644 --- a/stardew-access/Features/DynamicTiles.cs +++ b/stardew-access/Features/DynamicTiles.cs @@ -12,10 +12,10 @@ using System.Text.Json; namespace stardew_access.Features { - /// - /// Provides methods to locate tiles of interest in various game locations that are conditional or unpredictable (I.E. not static). - /// - /// + /// + /// Provides methods to locate tiles of interest in various game locations that are conditional or unpredictable (I.E. not static). + /// + /// /// The DynamicTiles class currently supports the following location types: /// - Beach /// - BoatTunnel @@ -111,441 +111,465 @@ namespace stardew_access.Features /// - "CaptainRoom" /// - "IslandNorthCave1" /// - "QiNutRoom" - /// - public class DynamicTiles - { - // Static instance for the singleton pattern - private static DynamicTiles? _instance; + /// + public class DynamicTiles + { + // Static instance for the singleton pattern + private static DynamicTiles? _instance; - /// - /// The singleton instance of the class. - /// - public static DynamicTiles Instance - { - get - { - _instance ??= new DynamicTiles(); - return _instance; - } - } + /// + /// The singleton instance of the class. + /// + public static DynamicTiles Instance + { + get + { + _instance ??= new DynamicTiles(); + return _instance; + } + } - // HashSet for storing which unimplemented locations have been previously logged - private static readonly HashSet loggedLocations = new(); + // HashSet for storing which unimplemented locations have been previously logged + private static readonly HashSet loggedLocations = new(); - // Dictionary of coordinates for feeding benches in barns and coops - private static readonly Dictionary FeedingBenchBounds = new() - { - { "Barn", (8, 11, 3) }, - { "Barn2", (8, 15, 3) }, - { "Big Barn", (8, 15, 3) }, - { "Barn3", (8, 19, 3) }, - { "Deluxe Barn", (8, 19, 3) }, - { "Coop", (6, 9, 3) }, - { "Coop2", (6, 13, 3) }, - { "Big Coop", (6, 13, 3) }, - { "Coop3", (6, 17, 3) }, - { "Deluxe Coop", (6, 17, 3) } - }; + // Dictionary of coordinates for feeding benches in barns and coops + private static readonly Dictionary FeedingBenchBounds = new() + { + { "Barn", (8, 11, 3) }, + { "Barn2", (8, 15, 3) }, + { "Big Barn", (8, 15, 3) }, + { "Barn3", (8, 19, 3) }, + { "Deluxe Barn", (8, 19, 3) }, + { "Coop", (6, 9, 3) }, + { "Coop2", (6, 13, 3) }, + { "Big Coop", (6, 13, 3) }, + { "Coop3", (6, 17, 3) }, + { "Deluxe Coop", (6, 17, 3) } + }; - // Dictionary to hold event info - private static readonly Dictionary> EventInteractables; + // Dictionary to hold event info + private static readonly Dictionary> EventInteractables; - /// - /// Initializes a new instance of the class. - /// Loads the event file. - /// - static DynamicTiles() - { - EventInteractables = LoadEventTiles(); - } + /// + /// Initializes a new instance of the class. + /// Loads the event file. + /// + static DynamicTiles() + { + EventInteractables = LoadEventTiles(); + } - /// - /// Loads event tiles from the "event-tiles.json" file and returns a dictionary representation of the data. - /// - /// - /// A dictionary with event names as keys and nested dictionaries as values, where nested dictionaries have - /// coordinate tuples (x, y) as keys and tile names as values. - /// - private static Dictionary> LoadEventTiles() - { - JsonElement json = LoadJsonFile("event-tiles.json"); + /// + /// Loads event tiles from the "event-tiles.json" file and returns a dictionary representation of the data. + /// + /// + /// A dictionary with event names as keys and nested dictionaries as values, where nested dictionaries have + /// coordinate tuples (x, y) as keys and tile names as values. + /// + private static Dictionary> LoadEventTiles() + { + JsonElement json = LoadJsonFile("event-tiles.json"); - if (json.ValueKind == JsonValueKind.Undefined) - { - // If the JSON couldn't be loaded or parsed, return an empty dictionary - return new Dictionary>(); - } + if (json.ValueKind == JsonValueKind.Undefined) + { + // If the JSON couldn't be loaded or parsed, return an empty dictionary + return new Dictionary>(); + } - var eventTiles = new Dictionary>(); + var eventTiles = new Dictionary>(); - // Iterate over the JSON properties to create a dictionary representation of the data - foreach (JsonProperty eventProperty in json.EnumerateObject()) - { - string eventName = eventProperty.Name; - var coordinates = new Dictionary<(int x, int y), string>(); + // Iterate over the JSON properties to create a dictionary representation of the data + foreach (JsonProperty eventProperty in json.EnumerateObject()) + { + string eventName = eventProperty.Name; + var coordinates = new Dictionary<(int x, int y), string>(); - // Iterate over the coordinate properties to create a nested dictionary with coordinate tuples as keys - foreach (JsonProperty coordinateProperty in eventProperty.Value.EnumerateObject()) - { - string[] xy = coordinateProperty.Name.Split(','); - int x = int.Parse(xy[0]); - int y = int.Parse(xy[1]); - coordinates.Add((x, y), value: coordinateProperty.Value.GetString() ?? string.Empty); - } + // Iterate over the coordinate properties to create a nested dictionary with coordinate tuples as keys + foreach (JsonProperty coordinateProperty in eventProperty.Value.EnumerateObject()) + { + string[] xy = coordinateProperty.Name.Split(','); + int x = int.Parse(xy[0]); + int y = int.Parse(xy[1]); + coordinates.Add((x, y), value: coordinateProperty.Value.GetString() ?? string.Empty); + } - eventTiles.Add(eventName, coordinates); - } + eventTiles.Add(eventName, coordinates); + } - return eventTiles; - } + return eventTiles; + } - /// - /// Retrieves information about interactables, NPCs, or other features at a given coordinate in a Beach. - /// - /// The Beach to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetBeachInfo(Beach beach, int x, int y) - { - if (MainClass.ModHelper == null) - { - return (null, null); - } - if (MainClass.ModHelper.Reflection.GetField(beach, "oldMariner").GetValue() is NPC mariner && mariner.getTileLocation() == new Vector2(x, y)) - { - return ("Old Mariner", CATEGORY.NPCs); - } - else if (x == 58 && y == 13) - { - if (!beach.bridgeFixed.Value) - { - return ("Repair Bridge", CATEGORY.Interactables); - } - else - { - return ("Bridge", CATEGORY.Bridges); - } - } + /// + /// Retrieves information about interactables, NPCs, or other features at a given coordinate in a Beach. + /// + /// The Beach to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetBeachInfo(Beach beach, int x, int y, bool lessInfo = false) + { + if (MainClass.ModHelper == null) + { + return (null, null); + } + if (MainClass.ModHelper.Reflection.GetField(beach, "oldMariner").GetValue() is NPC mariner && mariner.getTileLocation() == new Vector2(x, y)) + { + return ("Old Mariner", CATEGORY.NPCs); + } + else if (x == 58 && y == 13) + { + if (!beach.bridgeFixed.Value) + { + return ("Repair Bridge", CATEGORY.Interactables); + } + else + { + return ("Bridge", CATEGORY.Bridges); + } + } - return (null, null); - } + return (null, null); + } - /// - /// Retrieves information about interactables or other features at a given coordinate in a BoatTunnel. - /// - /// The BoatTunnel to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetBoatTunnelInfo(BoatTunnel boatTunnel, int x, int y) - { - if (boatTunnel is null) - { - throw new ArgumentNullException(nameof(boatTunnel)); - } + /// + /// Retrieves information about interactables or other features at a given coordinate in a BoatTunnel. + /// + /// The BoatTunnel to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetBoatTunnelInfo(BoatTunnel boatTunnel, int x, int y, bool lessInfo = false) + { + // Check if the player has received the specified mail or not + bool HasMail(string mail) => Game1.MasterPlayer.hasOrWillReceiveMail(mail); - if (x == 4 && y == 9) - { - return ((!Game1.MasterPlayer.hasOrWillReceiveMail("willyBoatFixed") ? "Repair " : "") + "Ticket Machine", CATEGORY.Interactables); - } - else if (x == 6 && y == 8) - { - return ((!Game1.MasterPlayer.hasOrWillReceiveMail("willyBoatHull") ? "Repair " : "") + "Boat Hull", (!Game1.MasterPlayer.hasOrWillReceiveMail("willyBoatHull") ? CATEGORY.Interactables : CATEGORY.Decor)); - } - else if (x == 8 && y == 9) - { - return ((!Game1.MasterPlayer.hasOrWillReceiveMail("willyBoatAnchor") ? "Repair " : "") + "Boat Anchor", (!Game1.MasterPlayer.hasOrWillReceiveMail("willyBoatAnchor") ? CATEGORY.Interactables : CATEGORY.Decor)); - } + // If the position matches one of the interactable elements in the boat tunnel + if ((x, y) == (4, 9) || (x, y) == (6, 8) || (x, y) == (8, 9)) + { + string mail = (x, y) switch + { + (4, 9) => "willyBoatFixed", + (6, 8) => "willyBoatHull", + (8, 9) => "willyBoatAnchor", + _ => throw new InvalidOperationException("Unexpected (x, y) values"), + }; - return (null, null); - } + string itemName = (x, y) switch + { + (4, 9) => "Ticket Machine", + (6, 8) => "Boat Hull", + (8, 9) => "Boat Anchor", + _ => throw new InvalidOperationException("Unexpected (x, y) values"), + }; - /// - /// Retrieves information about interactables or other features at a given coordinate in a CommunityCenter. - /// - /// The CommunityCenter to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetCommunityCenterInfo(CommunityCenter communityCenter, int x, int y) - { - if (communityCenter.missedRewardsChestVisible.Value && x == 22 && y == 10) - { - return ("Missed Rewards Chest", CATEGORY.Containers); - } + CATEGORY category = (x, y) == (4, 9) ? CATEGORY.Interactables : (!HasMail(mail) ? CATEGORY.Interactables : CATEGORY.Decor); - return (null, null); - } + return ((!HasMail(mail) ? "Repair " : "") + itemName, category); + } - /// - /// Gets the building information for a given position on a farm. - /// - /// The Building instance. - /// The x-coordinate of the position. - /// The y-coordinate of the position. - /// A tuple containing the name and CATEGORY of the door or building found, or (null, null) if no door or building is found. - private static (string? name, CATEGORY? category) GetBuildingInfo(Building building, int x, int y) - { - string name = building.buildingType.Value; - int buildingTileX = building.tileX.Value; - int buildingTileY = building.tileY.Value; + return (null, null); + } - // If the building is a FishPond, prepend the fish name - if (building is FishPond fishPond && fishPond.fishType.Value >= 0) - { - name = $"{Game1.objectInformation[fishPond.fishType.Value].Split('/')[4]} {name}"; - } + /// + /// Retrieves information about interactables or other features at a given coordinate in a CommunityCenter. + /// + /// The CommunityCenter to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetCommunityCenterInfo(CommunityCenter communityCenter, int x, int y, bool lessInfo = false) + { + if (communityCenter.missedRewardsChestVisible.Value && x == 22 && y == 10) + { + return ("Missed Rewards Chest", CATEGORY.Containers); + } - // Calculate differences in x and y coordinates - int offsetX = x - buildingTileX; - int offsetY = y - buildingTileY; + return (null, null); + } - // Check if the position matches the human door - if (building.humanDoor.Value.X == offsetX && building.humanDoor.Value.Y == offsetY) - { - return (name + " Door", CATEGORY.Doors); - } - // Check if the position matches the animal door - else if (building.animalDoor.Value.X == offsetX && building.animalDoor.Value.Y == offsetY) - { - return (name + " Animal Door " + ((building.animalDoorOpen.Value) ? "Opened" : "Closed"), CATEGORY.Doors); - } - // Check if the position matches the building's top-left corner - else if (offsetX == 0 && offsetY == 0) - { - return (name, CATEGORY.Buildings); - } - // Special handling for Mill buildings - else if (building is Mill) - { - // Check if the position matches the input - if (offsetX == 1 && offsetY == 1) - { - return (name + " input", CATEGORY.Buildings); - } - // Check if the position matches the output - else if (offsetX == 3 && offsetY == 1) - { - return (name + " output", CATEGORY.Buildings); - } - } + /// + /// Gets the building information for a given position on a farm. + /// + /// The Building instance. + /// The x-coordinate of the position. + /// The y-coordinate of the position. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the door or building found, or (null, null) if no door or building is found. + private static (string? name, CATEGORY? category) GetBuildingInfo(Building building, int x, int y, bool lessInfo = false) + { + string name = building.buildingType.Value; + int buildingTileX = building.tileX.Value; + int buildingTileY = building.tileY.Value; - // Return the building name for any other position within the building's area - return (name, CATEGORY.Buildings); - } + // If the building is a FishPond, prepend the fish name + if (building is FishPond fishPond && fishPond.fishType.Value >= 0) + { + name = $"{Game1.objectInformation[fishPond.fishType.Value].Split('/')[4]} {name}"; + } - /// - /// Retrieves information about interactables or other features at a given coordinate in a Farm. - /// - /// The Farm to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetFarmInfo(Farm farm, int x, int y) - { - var mainMailboxPos = farm.GetMainMailboxPosition(); - Building building = farm.getBuildingAt(new Vector2(x, y)); + // Calculate differences in x and y coordinates + int offsetX = x - buildingTileX; + int offsetY = y - buildingTileY; - if (mainMailboxPos.X == x && mainMailboxPos.Y == y) - { - return ("Mail box", CATEGORY.Interactables); - } - else if (building is not null) // Check if there is a building at the current position - { - return GetBuildingInfo(building, x, y); - } + // Check if the position matches the human door + if (building.humanDoor.Value.X == offsetX && building.humanDoor.Value.Y == offsetY) + { + return (name + " Door", CATEGORY.Doors); + } + // Check if the position matches the animal door + else if (building.animalDoor.Value.X == offsetX && building.animalDoor.Value.Y == offsetY) + { + return (name + " Animal Door " + ((building.animalDoorOpen.Value) ? "Opened" : "Closed"), CATEGORY.Doors); + } + // Check if the position matches the building's top-left corner + else if (offsetX == 0 && offsetY == 0) + { + return (name, CATEGORY.Buildings); + } + // Special handling for Mill buildings + else if (building is Mill) + { + // Check if the position matches the input + if (offsetX == 1 && offsetY == 1) + { + return (name + " input", CATEGORY.Buildings); + } + // Check if the position matches the output + else if (offsetX == 3 && offsetY == 1) + { + return (name + " output", CATEGORY.Buildings); + } + } - return (null, null); - } + // Return the building name for any other position within the building's area + return (name, CATEGORY.Buildings); + } - /// - /// Retrieves information about interactables or other features at a given coordinate in a FarmHouse. - /// - /// The FarmHouse to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetFarmHouseInfo(FarmHouse farmHouse, int x, int y) - { - if (farmHouse.upgradeLevel >= 1) - { - int kitchenX = farmHouse.getKitchenStandingSpot().X; - int kitchenY = farmHouse.getKitchenStandingSpot().Y - 1; + /// + /// Retrieves information about interactables or other features at a given coordinate in a Farm. + /// + /// The Farm to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetFarmInfo(Farm farm, int x, int y, bool lessInfo = false) + { + var mainMailboxPos = farm.GetMainMailboxPosition(); + Building building = farm.getBuildingAt(new Vector2(x, y)); - if (kitchenX == x && kitchenY == y) - { - return ("Stove", CATEGORY.Interactables); - } - else if (kitchenX + 1 == x && kitchenY == y) - { - return ("Sink", CATEGORY.Others); - } - else if (farmHouse.fridgePosition.X == x && farmHouse.fridgePosition.Y == y) - { - return ("Fridge", CATEGORY.Interactables); - } - } + if (mainMailboxPos.X == x && mainMailboxPos.Y == y) + { + return ("Mail box", CATEGORY.Interactables); + } + else if (building is not null) // Check if there is a building at the current position + { + return GetBuildingInfo(building, x, y, lessInfo); + } - return (null, null); - } + return (null, null); + } - /// - /// Retrieves information about interactables or other features at a given coordinate in a Forest. - /// - /// The Forest to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetForestInfo(Forest forest, int x, int y) - { - if (forest.travelingMerchantDay && x == 27 && y == 11) - { - return ("Travelling Cart", CATEGORY.Interactables); - } - else if (forest.log != null && x == 2 && y == 7) - { - return ("Log", CATEGORY.Interactables); - } - else if (forest.log == null && x == 0 && y == 7) - { - return ("Secret Woods Entrance", CATEGORY.Doors); - } + /// + /// Retrieves information about interactables or other features at a given coordinate in a FarmHouse. + /// + /// The FarmHouse to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetFarmHouseInfo(FarmHouse farmHouse, int x, int y, bool lessInfo = false) + { + if (farmHouse.upgradeLevel >= 1) + { + int kitchenX = farmHouse.getKitchenStandingSpot().X; + int kitchenY = farmHouse.getKitchenStandingSpot().Y - 1; - return (null, null); - } + if (kitchenX == x && kitchenY == y) + { + return ("Stove", CATEGORY.Interactables); + } + else if (kitchenX + 1 == x && kitchenY == y) + { + return ("Sink", CATEGORY.Others); + } + else if (farmHouse.fridgePosition.X == x && farmHouse.fridgePosition.Y == y) + { + return ("Fridge", CATEGORY.Interactables); + } + } - /// - /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandFarmHouse. - /// - /// The IslandFarmHouse to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetIslandFarmHouseInfo(IslandFarmHouse islandFarmHouse, int x, int y) - { - int fridgeX = islandFarmHouse.fridgePosition.X; - int fridgeY = islandFarmHouse.fridgePosition.Y; - if (fridgeX - 2 == x && fridgeY == y) - { - return ("Stove", CATEGORY.Interactables); - } - else if (fridgeX - 1 == x && fridgeY == y) - { - return ("Sink", CATEGORY.Others); - } - else if (fridgeX == x && fridgeY == y) - { - return ("Fridge", CATEGORY.Interactables); - } + return (null, null); + } - return (null, null); - } + /// + /// Retrieves information about interactables or other features at a given coordinate in a Forest. + /// + /// The Forest to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetForestInfo(Forest forest, int x, int y, bool lessInfo = false) + { + if (forest.travelingMerchantDay && x == 27 && y == 11) + { + return ("Travelling Cart", CATEGORY.Interactables); + } + else if (forest.log != null && x == 2 && y == 7) + { + return ("Log", CATEGORY.Interactables); + } + else if (forest.log == null && x == 0 && y == 7) + { + return ("Secret Woods Entrance", CATEGORY.Doors); + } - /// - /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandNorth. - /// - /// The IslandNorth to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetIslandNorthInfo(IslandNorth islandNorth, int x, int y) - { - // Check if the trader is activated and the coordinates match the trader's location - if (islandNorth.traderActivated.Value && x == 36 && y == 71) - { - return ("Island Trader", CATEGORY.Interactables); - } + return (null, null); + } - // Return (null, null) if no relevant object is found - return (null, null); - } + /// + /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandFarmHouse. + /// + /// The IslandFarmHouse to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetIslandFarmHouseInfo(IslandFarmHouse islandFarmHouse, int x, int y, bool lessInfo = false) + { + int fridgeX = islandFarmHouse.fridgePosition.X; + int fridgeY = islandFarmHouse.fridgePosition.Y; + if (fridgeX - 2 == x && fridgeY == y) + { + return ("Stove", CATEGORY.Interactables); + } + else if (fridgeX - 1 == x && fridgeY == y) + { + return ("Sink", CATEGORY.Others); + } + else if (fridgeX == x && fridgeY == y) + { + return ("Fridge", CATEGORY.Interactables); + } - /// - /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandWest. - /// - /// The IslandWest to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetIslandWestInfo(IslandWest islandWest, int x, int y) - { - // Check if the coordinates match the shipping bin's location - if ((islandWest.shippingBinPosition.X == x || (islandWest.shippingBinPosition.X + 1) == x) && islandWest.shippingBinPosition.Y == y) - { - return ("Shipping Bin", CATEGORY.Interactables); - } + return (null, null); + } - // Return (null, null) if no relevant object is found - return (null, null); - } + /// + /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandNorth. + /// + /// The IslandNorth to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetIslandNorthInfo(IslandNorth islandNorth, int x, int y, bool lessInfo = false) + { + // Check if the trader is activated and the coordinates match the trader's location + if (islandNorth.traderActivated.Value && x == 36 && y == 71) + { + return ("Island Trader", CATEGORY.Interactables); + } - /// - /// Retrieves information about tiles at a given coordinate in a VolcanoDungeon. - /// - /// The VolcanoDungeon to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name of the tile and the CATEGORY, or (null, null) if no relevant tile is found. - private static (string? name, CATEGORY? category) GetVolcanoDungeonInfo(VolcanoDungeon dungeon, int x, int y) - { - if (dungeon.IsCooledLava(x, y)) - { - return ("Cooled lava", CATEGORY.WaterTiles); - } - else if (StardewValley.Monsters.LavaLurk.IsLavaTile(dungeon, x, y)) - { - return ("Lava", CATEGORY.WaterTiles); - } + // Return (null, null) if no relevant object is found + return (null, null); + } - return (null, null); - } + /// + /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandWest. + /// + /// The IslandWest to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetIslandWestInfo(IslandWest islandWest, int x, int y, bool lessInfo = false) + { + // Check if the coordinates match the shipping bin's location + if ((islandWest.shippingBinPosition.X == x || (islandWest.shippingBinPosition.X + 1) == x) && islandWest.shippingBinPosition.Y == y) + { + return ("Shipping Bin", CATEGORY.Interactables); + } - /// - /// Retrieves information about interactables, NPCs, or other features at a given coordinate in a named IslandLocation. - /// - /// The named IslandLocation to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetNamedIslandLocationInfo(IslandLocation islandLocation, int x, int y) - { - object locationType = islandLocation is not null and IslandLocation ? islandLocation.Name ?? "Undefined Island Location" : islandLocation!.GetType(); + // Return (null, null) if no relevant object is found + return (null, null); + } - // Implement specific logic for named IslandLocations here, if necessary + /// + /// Retrieves information about tiles at a given coordinate in a VolcanoDungeon. + /// + /// The VolcanoDungeon to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name of the tile and the CATEGORY, or (null, null) if no relevant tile is found. + private static (string? name, CATEGORY? category) GetVolcanoDungeonInfo(VolcanoDungeon dungeon, int x, int y, bool lessInfo = false) + { + if (!lessInfo) + { + if (dungeon.IsCooledLava(x, y)) + { + return ("Cooled lava", CATEGORY.WaterTiles); + } + else if (StardewValley.Monsters.LavaLurk.IsLavaTile(dungeon, x, y)) + { + return ("Lava", CATEGORY.WaterTiles); + } + } - // Unimplemented locations are logged. - // Check if the location has already been logged - if (!loggedLocations.Contains(locationType)) - { - // Log the message - MainClass.DebugLog($"Called GetNamedIslandLocationInfo with unimplemented IslandLocation of type {islandLocation.GetType()} and name {islandLocation.Name}"); + return (null, null); + } - // Add the location to the HashSet to prevent logging it again - loggedLocations.Add(locationType); - } + /// + /// Retrieves information about interactables, NPCs, or other features at a given coordinate in a named IslandLocation. + /// + /// The named IslandLocation to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetNamedIslandLocationInfo(IslandLocation islandLocation, int x, int y, bool lessInfo = false) + { + object locationType = islandLocation is not null and IslandLocation ? islandLocation.Name ?? "Undefined Island Location" : islandLocation!.GetType(); - return (null, null); - } + // Implement specific logic for named IslandLocations here, if necessary - /// - /// Retrieves the name of the IslandGemBird based on its item index value. - /// - /// The IslandGemBird instance. - /// A string representing the name of the IslandGemBird. - private static String GetGemBirdName(IslandGemBird bird) - { - // Use a switch expression to return the appropriate bird name based on the item index value - return bird.itemIndex.Value switch - { - 60 => "Emerald Gem Bird", - 62 => "Aquamarine Gem Bird", - 64 => "Ruby Gem Bird", - 66 => "Amethyst Gem Bird", - 68 => "Topaz Gem Bird", - _ => "Gem Bird", // Default case for when the item index does not match any of the specified values - }; - } + // Unimplemented locations are logged. + // Check if the location has already been logged + if (!loggedLocations.Contains(locationType)) + { + // Log the message + MainClass.DebugLog($"Called GetNamedIslandLocationInfo with unimplemented IslandLocation of type {islandLocation.GetType()} and name {islandLocation.Name}"); + + // Add the location to the HashSet to prevent logging it again + loggedLocations.Add(locationType); + } + + return (null, null); + } + + /// + /// Retrieves the name of the IslandGemBird based on its item index value. + /// + /// The IslandGemBird instance. + /// A string representing the name of the IslandGemBird. + private static String GetGemBirdName(IslandGemBird bird) + { + // Use a switch expression to return the appropriate bird name based on the item index value + return bird.itemIndex.Value switch + { + 60 => "Emerald Gem Bird", + 62 => "Aquamarine Gem Bird", + 64 => "Ruby Gem Bird", + 66 => "Amethyst Gem Bird", + 68 => "Topaz Gem Bird", + _ => "Gem Bird", // Default case for when the item index does not match any of the specified values + }; + } /// /// Gets the parrot perch information at the specified tile coordinates in the given island location. @@ -564,219 +588,225 @@ namespace stardew_access.Features { string toSpeak = $"Parrot required nuts {foundPerch.requiredNuts.Value}"; - // Return appropriate string based on the current state of the parrot perch - return foundPerch.currentState.Value switch - { - StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Idle => foundPerch.IsAvailable() ? toSpeak : "Empty parrot perch", - StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.StartBuilding => "Parrots started building request", - StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Building => "Parrots building request", - StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Complete => "Request Completed", - _ => toSpeak, - }; - } + // Return appropriate string based on the current state of the parrot perch + return foundPerch.currentState.Value switch + { + StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Idle => foundPerch.IsAvailable() ? toSpeak : "Empty parrot perch", + StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.StartBuilding => "Parrots started building request", + StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Building => "Parrots building request", + StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Complete => "Request Completed", + _ => toSpeak, + }; + } // If no parrot perch was found, return null return null; } - /// - /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandLocation. - /// - /// The IslandLocation to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetIslandLocationInfo(IslandLocation islandLocation, int x, int y) - { - var nutTracker = Game1.player.team.collectedNutTracker; + /// + /// Retrieves information about interactables, NPCs, or other features at a given coordinate in an IslandLocation. + /// + /// The IslandLocation to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetIslandLocationInfo(IslandLocation islandLocation, int x, int y, bool lessInfo = false) + { + var nutTracker = Game1.player.team.collectedNutTracker; string? parrot = GetParrotPerchAtTile(islandLocation, x, y); - if (islandLocation.IsBuriedNutLocation(new Point(x, y)) && !nutTracker.ContainsKey($"Buried_{islandLocation.Name}_{x}_{y}")) - { - return ("Diggable spot", CATEGORY.Interactables); - } - else if (islandLocation.locationGemBird.Value is IslandGemBird bird && ((int)bird.position.X / Game1.tileSize) == x && ((int)bird.position.Y / Game1.tileSize) == y) - { - return (GetGemBirdName(bird), CATEGORY.NPCs); - } + if (islandLocation.IsBuriedNutLocation(new Point(x, y)) && !nutTracker.ContainsKey($"Buried_{islandLocation.Name}_{x}_{y}")) + { + return ("Diggable spot", CATEGORY.Interactables); + } + else if (islandLocation.locationGemBird.Value is IslandGemBird bird && ((int)bird.position.X / Game1.tileSize) == x && ((int)bird.position.Y / Game1.tileSize) == y) + { + return (GetGemBirdName(bird), CATEGORY.NPCs); + } else if (parrot != null) { return (parrot, CATEGORY.Buildings); } - return islandLocation switch - { - IslandNorth islandNorth => GetIslandNorthInfo(islandNorth, x, y), - IslandWest islandWest => GetIslandWestInfo(islandWest, x, y), - VolcanoDungeon dungeon => GetVolcanoDungeonInfo(dungeon, x, y), - _ => GetNamedIslandLocationInfo(islandLocation, x, y) - }; - } + return islandLocation switch + { + IslandNorth islandNorth => GetIslandNorthInfo(islandNorth, x, y, lessInfo), + IslandWest islandWest => GetIslandWestInfo(islandWest, x, y, lessInfo), + VolcanoDungeon dungeon => GetVolcanoDungeonInfo(dungeon, x, y, lessInfo), + _ => GetNamedIslandLocationInfo(islandLocation, x, y, lessInfo) + }; + } - /// - /// Retrieves the value of the "Action" property from the Buildings layer tile at the given coordinates. - /// - /// The LibraryMuseum containing the tile. - /// The x-coordinate of the tile. - /// The y-coordinate of the tile. - /// The value of the "Action" property as a string, or null if the property is not found. - private static string? GetTileActionPropertyValue(LibraryMuseum libraryMuseum, int x, int y) - { - xTile.Tiles.Tile tile = libraryMuseum.map.GetLayer("Buildings").PickTile(new xTile.Dimensions.Location(x * 64, y * 64), Game1.viewport.Size); - return tile.Properties.TryGetValue("Action", out xTile.ObjectModel.PropertyValue? value) ? value.ToString() : null; - } + /// + /// Retrieves the value of the "Action" property from the Buildings layer tile at the given coordinates. + /// + /// The LibraryMuseum containing the tile. + /// The x-coordinate of the tile. + /// The y-coordinate of the tile. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// The value of the "Action" property as a string, or null if the property is not found. + private static string? GetTileActionPropertyValue(LibraryMuseum libraryMuseum, int x, int y, bool lessInfo = false) + { + xTile.Tiles.Tile tile = libraryMuseum.map.GetLayer("Buildings").PickTile(new xTile.Dimensions.Location(x * 64, y * 64), Game1.viewport.Size); + return tile.Properties.TryGetValue("Action", out xTile.ObjectModel.PropertyValue? value) ? value.ToString() : null; + } - /// - /// Retrieves information about interactables, NPCs, or other features at a given coordinate in a LibraryMuseum. - /// - /// The LibraryMuseum to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetLibraryMuseumInfo(LibraryMuseum libraryMuseum, int x, int y) - { - if (libraryMuseum.museumPieces.TryGetValue(new Vector2(x, y), out int museumPiece)) - { - string displayName = Game1.objectInformation[museumPiece].Split('/')[0]; - return ($"{displayName} showcase", CATEGORY.Interactables); - } + /// + /// Retrieves information about interactables, NPCs, or other features at a given coordinate in a LibraryMuseum. + /// + /// The LibraryMuseum to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetLibraryMuseumInfo(LibraryMuseum libraryMuseum, int x, int y, bool lessInfo = false) + { + if (libraryMuseum.museumPieces.TryGetValue(new Vector2(x, y), out int museumPiece)) + { + string displayName = Game1.objectInformation[museumPiece].Split('/')[0]; + return ($"{displayName} showcase", CATEGORY.Interactables); + } - int booksFound = Game1.netWorldState.Value.LostBooksFound.Value; - string? action = libraryMuseum.doesTileHaveProperty(x, y, "Action", "Buildings"); - if (action != null && action.Contains("Notes")) - { - string? actionPropertyValue = GetTileActionPropertyValue(libraryMuseum, x, y); + int booksFound = Game1.netWorldState.Value.LostBooksFound.Value; + string? action = libraryMuseum.doesTileHaveProperty(x, y, "Action", "Buildings"); + if (action != null && action.Contains("Notes")) + { + string? actionPropertyValue = GetTileActionPropertyValue(libraryMuseum, x, y, lessInfo); - if (actionPropertyValue != null) - { - int which = Convert.ToInt32(actionPropertyValue.Split(' ')[1]); - if (booksFound >= which) - { - string message = Game1.content.LoadString("Strings\\Notes:" + which); - return ($"{message.Split('\n')[0]} Book", CATEGORY.Interactables); - } - return ($"Lost Book", CATEGORY.Others); - } - } + if (actionPropertyValue != null) + { + int which = Convert.ToInt32(actionPropertyValue.Split(' ')[1]); + if (booksFound >= which) + { + string message = Game1.content.LoadString("Strings\\Notes:" + which); + return ($"{message.Split('\n')[0]} Book", CATEGORY.Interactables); + } + return ($"Lost Book", CATEGORY.Others); + } + } - return (null, null); - } + return (null, null); + } - /// - /// Retrieves information about interactables or other features at a given coordinate in a Town. - /// - /// The Town to search. - /// The x-coordinate to search. - /// The y-coordinate to search. - /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. - private static (string? name, CATEGORY? category) GetTownInfo(Town town, int x, int y) - { - if (SpecialOrder.IsSpecialOrdersBoardUnlocked() && x == 62 && y == 93) - { - return ("Special quest board", CATEGORY.Interactables); - } + /// + /// Retrieves information about interactables or other features at a given coordinate in a Town. + /// + /// The Town to search. + /// The x-coordinate to search. + /// The y-coordinate to search. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple containing the name and CATEGORY of the object found, or (null, null) if no relevant object is found. + private static (string? name, CATEGORY? category) GetTownInfo(Town town, int x, int y, bool lessInfo = false) + { + if (SpecialOrder.IsSpecialOrdersBoardUnlocked() && x == 62 && y == 93) + { + return ("Special quest board", CATEGORY.Interactables); + } - return (null, null); - } + return (null, null); + } - /// - /// Gets the feeding bench information for barns and coops. - /// - /// The current GameLocation instance. - /// The x coordinate of the tile. - /// The y coordinate of the tile. - /// A tuple of (string? name, CATEGORY? category) for the feeding bench, or null if not applicable. - private static (string? name, CATEGORY? category)? GetFeedingBenchInfo(GameLocation currentLocation, int x, int y) - { - string locationName = currentLocation.Name; + /// + /// Gets the feeding bench information for barns and coops. + /// + /// The current GameLocation instance. + /// The x coordinate of the tile. + /// The y coordinate of the tile. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple of (string? name, CATEGORY? category) for the feeding bench, or null if not applicable. + private static (string? name, CATEGORY? category)? GetFeedingBenchInfo(GameLocation currentLocation, int x, int y, bool lessInfo = false) + { + string locationName = currentLocation.Name; - if (FeedingBenchBounds.TryGetValue(locationName, out var bounds) && x >= bounds.minX && x <= bounds.maxX && y == bounds.y) - { - (string? name, CATEGORY category) = TileInfo.getObjectAtTile(x, y, currentLocation, true); - return (name?.Contains("hay", StringComparison.OrdinalIgnoreCase) == true ? "Feeding Bench" : "Empty Feeding Bench", category); - } + if (FeedingBenchBounds.TryGetValue(locationName, out var bounds) && x >= bounds.minX && x <= bounds.maxX && y == bounds.y) + { + (string? name, CATEGORY category) = TileInfo.getObjectAtTile(currentLocation, x, y, true); + return (name?.Contains("hay", StringComparison.OrdinalIgnoreCase) == true ? "Feeding Bench" : "Empty Feeding Bench", category); + } - return null; - } + return null; + } - /// - /// Gets information about the current location by its name. - /// - /// The current GameLocation instance. - /// The x coordinate of the tile. - /// The y coordinate of the tile. - /// A tuple of (string? name, CATEGORY? category) for the object in the location, or null if not applicable. - private static (string? name, CATEGORY? category) GetLocationByNameInfo(GameLocation currentLocation, int x, int y) - { - object locationType = currentLocation is not null and GameLocation ? currentLocation.Name ?? "Undefined GameLocation" : currentLocation!.GetType(); string locationName = currentLocation.Name ?? ""; - if (locationName.Contains("coop", StringComparison.OrdinalIgnoreCase) || locationName.Contains("barn", StringComparison.OrdinalIgnoreCase)) - { - var feedingBenchInfo = GetFeedingBenchInfo(currentLocation, x, y); - if (feedingBenchInfo.HasValue) - { - return feedingBenchInfo.Value; - } // else if something other than feeding benches in barns and coops... - } //else if something other than barns and coops... + /// + /// Gets information about the current location by its name. + /// + /// The current GameLocation instance. + /// The x coordinate of the tile. + /// The y coordinate of the tile. + /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. + /// A tuple of (string? name, CATEGORY? category) for the object in the location, or null if not applicable. + private static (string? name, CATEGORY? category) GetLocationByNameInfo(GameLocation currentLocation, int x, int y, bool lessInfo = false) + { + object locationType = currentLocation is not null and GameLocation ? currentLocation.Name ?? "Undefined GameLocation" : currentLocation!.GetType(); string locationName = currentLocation.Name ?? ""; + if (locationName.Contains("coop", StringComparison.OrdinalIgnoreCase) || locationName.Contains("barn", StringComparison.OrdinalIgnoreCase)) + { + var feedingBenchInfo = GetFeedingBenchInfo(currentLocation, x, y); + if (feedingBenchInfo.HasValue) + { + return feedingBenchInfo.Value; + } // else if something other than feeding benches in barns and coops... + } //else if something other than barns and coops... - // Unimplemented locations are logged. - // Check if the location has already been logged - if (!loggedLocations.Contains(locationType)) - { - // Log the message - MainClass.DebugLog($"Called GetLocationByNameInfo with unimplemented GameLocation of type {currentLocation.GetType()} and name {currentLocation.Name}"); + // Unimplemented locations are logged. + // Check if the location has already been logged + if (!loggedLocations.Contains(locationType)) + { + // Log the message + MainClass.DebugLog($"Called GetLocationByNameInfo with unimplemented GameLocation of type {currentLocation.GetType()} and name {currentLocation.Name}"); - // Add the location to the HashSet to prevent logging it again - loggedLocations.Add(locationType); - } + // Add the location to the HashSet to prevent logging it again + loggedLocations.Add(locationType); + } - return (null, null); - } + return (null, null); + } - /// - /// Retrieves the dynamic tile information for the given coordinates in the specified location. - /// - /// The x-coordinate of the tile. - /// The y-coordinate of the tile. - /// The current GameLocation instance. - /// An optional boolean to return less detailed information. Defaults to false. - /// A tuple containing the name and CATEGORY of the dynamic tile, or null values if not found. - public static (string? name, CATEGORY? category) GetDynamicTileAt(int x, int y, GameLocation currentLocation, bool lessInfo = false) - { - // Check for panning spots - if (currentLocation.orePanPoint.Value != Point.Zero && currentLocation.orePanPoint.Value == new Point(x, y)) - { - return ("panning spot", CATEGORY.Interactables); - } - // Check if the current location has an event - else if (currentLocation.currentEvent is not null) - { - string eventName = currentLocation.currentEvent.FestivalName; - // Attempt to retrieve the nested dictionary for the event name from the EventInteractables dictionary - if (EventInteractables.TryGetValue(eventName, out var coordinateDictionary)) - { - // Attempt to retrieve the interactable value from the nested dictionary using the coordinates (x, y) as the key - if (coordinateDictionary.TryGetValue((x, y), value: out var interactable)) - { - // If the interactable value is found, return the corresponding category and interactable name - return (interactable, CATEGORY.Interactables); - } - } - } + /// + /// Retrieves the dynamic tile information for the given coordinates in the specified location. + /// + /// The current GameLocation instance. + /// The x-coordinate of the tile. + /// The y-coordinate of the tile. + /// An optional boolean to return less detailed information. Defaults to false. + /// A tuple containing the name and CATEGORY of the dynamic tile, or null values if not found. + public static (string? name, CATEGORY? category) GetDynamicTileAt(GameLocation currentLocation, int x, int y, bool lessInfo = false) + { + // Check for panning spots + if (currentLocation.orePanPoint.Value != Point.Zero && currentLocation.orePanPoint.Value == new Point(x, y)) + { + return ("panning spot", CATEGORY.Interactables); + } + // Check if the current location has an event + else if (currentLocation.currentEvent is not null) + { + string eventName = currentLocation.currentEvent.FestivalName; + // Attempt to retrieve the nested dictionary for the event name from the EventInteractables dictionary + if (EventInteractables.TryGetValue(eventName, out var coordinateDictionary)) + { + // Attempt to retrieve the interactable value from the nested dictionary using the coordinates (x, y) as the key + if (coordinateDictionary.TryGetValue((x, y), value: out var interactable)) + { + // If the interactable value is found, return the corresponding category and interactable name + return (interactable, CATEGORY.Interactables); + } + } + } - // Retrieve dynamic tile information based on the current location type - return currentLocation switch - { - Beach beach => GetBeachInfo(beach, x, y), - BoatTunnel boatTunnel => GetBoatTunnelInfo(boatTunnel, x, y), - CommunityCenter communityCenter => GetCommunityCenterInfo(communityCenter, x, y), - Farm farm => GetFarmInfo(farm, x, y), - FarmHouse farmHouse => GetFarmHouseInfo(farmHouse, x, y), - Forest forest => GetForestInfo(forest, x, y), - IslandFarmHouse islandFarmHouse => GetIslandFarmHouseInfo(islandFarmHouse, x, y), - IslandLocation islandLocation => GetIslandLocationInfo(islandLocation, x, y), - LibraryMuseum libraryMuseum => GetLibraryMuseumInfo(libraryMuseum, x, y), - Town town => GetTownInfo(town, x, y), - _ => GetLocationByNameInfo(currentLocation, x, y) - }; - } - } + // Retrieve dynamic tile information based on the current location type + return currentLocation switch + { + Beach beach => GetBeachInfo(beach, x, y, lessInfo), + BoatTunnel boatTunnel => GetBoatTunnelInfo(boatTunnel, x, y, lessInfo), + CommunityCenter communityCenter => GetCommunityCenterInfo(communityCenter, x, y, lessInfo), + Farm farm => GetFarmInfo(farm, x, y, lessInfo), + FarmHouse farmHouse => GetFarmHouseInfo(farmHouse, x, y, lessInfo), + Forest forest => GetForestInfo(forest, x, y, lessInfo), + IslandFarmHouse islandFarmHouse => GetIslandFarmHouseInfo(islandFarmHouse, x, y, lessInfo), + IslandLocation islandLocation => GetIslandLocationInfo(islandLocation, x, y, lessInfo), + LibraryMuseum libraryMuseum => GetLibraryMuseumInfo(libraryMuseum, x, y, lessInfo), + Town town => GetTownInfo(town, x, y, lessInfo), + _ => GetLocationByNameInfo(currentLocation, x, y, lessInfo) + }; + } + } } diff --git a/stardew-access/Features/Radar.cs b/stardew-access/Features/Radar.cs index a2752a8..eac37e8 100644 --- a/stardew-access/Features/Radar.cs +++ b/stardew-access/Features/Radar.cs @@ -160,7 +160,7 @@ namespace stardew_access.Features watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; MainClass.DebugLog($"Search init duration: {elapsedMs}"); - watch.Reset(); + watch.Reset(); watch.Start(); while (toSearch.Count > 0) { @@ -178,7 +178,7 @@ namespace stardew_access.Features { Vector2 dir = new(item.X + dirX[i], item.Y + dirY[i]); - if (!searched.Contains(dir) && (TileInfo.isWarpPointAtTile((int)dir.X, (int)dir.Y, currentLocation) || currentLocation.isTileOnMap(dir))) + if (!searched.Contains(dir) && (TileInfo.isWarpPointAtTile(currentLocation, (int)dir.X, (int)dir.Y) || currentLocation.isTileOnMap(dir))) { toSearch.Enqueue(dir); searched.Add(dir); @@ -231,7 +231,7 @@ namespace stardew_access.Features { if (currentLocation.isObjectAtTile((int)position.X, (int)position.Y)) { - (string? name, CATEGORY category) objDetails = TileInfo.getObjectAtTile((int)position.X, (int)position.Y, currentLocation); + (string? name, CATEGORY category) objDetails = TileInfo.getObjectAtTile(currentLocation, (int)position.X, (int)position.Y); string? objectName = objDetails.name; CATEGORY category = objDetails.category; StardewValley.Object obj = currentLocation.getObjectAtTile((int)position.X, (int)position.Y); diff --git a/stardew-access/Features/ReadTile.cs b/stardew-access/Features/ReadTile.cs index a5a1a11..661274c 100644 --- a/stardew-access/Features/ReadTile.cs +++ b/stardew-access/Features/ReadTile.cs @@ -90,7 +90,7 @@ namespace stardew_access.Features } var currentLocation = Game1.currentLocation; - bool isColliding = TileInfo.IsCollidingAtTile(x, y, currentLocation); + bool isColliding = TileInfo.IsCollidingAtTile(currentLocation, x, y); (string? name, string? category) info = TileInfo.getNameWithCategoryNameAtTile(tile, currentLocation); diff --git a/stardew-access/Features/StaticTiles.cs b/stardew-access/Features/StaticTiles.cs index 204d562..4b2ed15 100644 --- a/stardew-access/Features/StaticTiles.cs +++ b/stardew-access/Features/StaticTiles.cs @@ -73,7 +73,7 @@ namespace stardew_access.Features /// Additional lambda functions can be added as needed. /// private static readonly Dictionary> conditionals = new() - { + { ["Farm"] = (conditionType, uniqueModId) => { if (string.IsNullOrEmpty(uniqueModId)) diff --git a/stardew-access/Features/TileInfo.cs b/stardew-access/Features/TileInfo.cs index f572c0c..c2712df 100644 --- a/stardew-access/Features/TileInfo.cs +++ b/stardew-access/Features/TileInfo.cs @@ -11,9 +11,9 @@ namespace stardew_access.Features { public class TileInfo { - private static readonly string[] trackable_machines = { "bee house", "cask", "press", "keg", "machine", "maker", "preserves jar", "bone mill", "kiln", "crystalarium", "furnace", "geode crusher", "tapper", "lightning rod", "incubator", "wood chipper", "worm bin", "loom", "statue of endless fortune", "statue of perfection", "crab pot" }; + private static readonly string[] trackable_machines = { "bee house", "cask", "press", "keg", "machine", "maker", "preserves jar", "bone mill", "kiln", "crystalarium", "furnace", "geode crusher", "tapper", "lightning rod", "incubator", "wood chipper", "worm bin", "loom", "statue of endless fortune", "statue of perfection", "crab pot" }; private static readonly Dictionary ResourceClumpNames = new() - { + { { 600, "Large Stump" }, { 602, "Hollow Log" }, { 622, "Meteorite" }, @@ -71,7 +71,7 @@ namespace stardew_access.Features return (staticTile.name, staticTile.category); } - (string? name, CATEGORY? category) dynamicTile = DynamicTiles.GetDynamicTileAt(x, y, currentLocation, lessInfo); + (string? name, CATEGORY? category) dynamicTile = DynamicTiles.GetDynamicTileAt(currentLocation, x, y, lessInfo); if (dynamicTile.name != null) { return (dynamicTile.name, dynamicTile.category); @@ -79,16 +79,16 @@ namespace stardew_access.Features if (currentLocation.isObjectAtTile(x, y)) { - (string? name, CATEGORY? category) obj = getObjectAtTile(x, y, currentLocation, lessInfo); + (string? name, CATEGORY? category) obj = getObjectAtTile(currentLocation, x, y, lessInfo); return (obj.name, obj.category); } - if (currentLocation.isWaterTile(x, y) && !lessInfo && IsCollidingAtTile(x, y, currentLocation)) + if (currentLocation.isWaterTile(x, y) && !lessInfo && IsCollidingAtTile(currentLocation, x, y)) { return ("Water", CATEGORY.WaterTiles); } - string? resourceClump = getResourceClumpAtTile(x, y, currentLocation, lessInfo); + string? resourceClump = getResourceClumpAtTile(currentLocation, x, y, lessInfo); if (resourceClump != null) { return (resourceClump, CATEGORY.ResourceClumps); @@ -103,20 +103,20 @@ namespace stardew_access.Features } } - string? bush = GetBushAtTile(x, y, currentLocation, lessInfo); + string? bush = GetBushAtTile(currentLocation, x, y, lessInfo); if (bush != null) { return (bush, CATEGORY.Bush); } - string? door = getDoorAtTile(x, y, currentLocation); - string? warp = getWarpPointAtTile(x, y, currentLocation); + string? door = getDoorAtTile(currentLocation, x, y); + string? warp = getWarpPointAtTile(currentLocation, x, y); if (warp != null || door != null) { return (warp ?? door, CATEGORY.Doors); } - string? junimoBundle = GetJunimoBundleAt(x, y, currentLocation); + string? junimoBundle = GetJunimoBundleAt(currentLocation, x, y); if (junimoBundle != null) { return (junimoBundle, CATEGORY.JunimoBundle); @@ -150,12 +150,12 @@ namespace stardew_access.Features /// /// Gets the bush at the specified tile coordinates in the provided GameLocation. /// + /// The GameLocation instance to search for bushes. /// The x-coordinate of the tile to check. /// The y-coordinate of the tile to check. - /// The GameLocation instance to search for bushes. /// Whether to return less information about the bush. /// A string describing the bush if one is found at the specified coordinates, otherwise null. - public static string? GetBushAtTile(int x, int y, GameLocation currentLocation, bool lessInfo = false) + public static string? GetBushAtTile(GameLocation currentLocation, int x, int y, bool lessInfo = false) { Bush? bush = (Bush)currentLocation.getLargeTerrainFeatureAt(x, y); @@ -201,11 +201,11 @@ namespace stardew_access.Features /// /// Determines if there is a Junimo bundle at the specified tile coordinates in the provided GameLocation. /// + /// The GameLocation instance to search for Junimo bundles. /// The x-coordinate of the tile to check. /// The y-coordinate of the tile to check. - /// The GameLocation instance to search for Junimo bundles. /// The name of the Junimo bundle if one is found at the specified coordinates, otherwise null. - public static string? GetJunimoBundleAt(int x, int y, GameLocation currentLocation) + public static string? GetJunimoBundleAt(GameLocation currentLocation, int x, int y) { if (currentLocation is CommunityCenter communityCenter) { @@ -246,25 +246,25 @@ namespace stardew_access.Features /// /// Determines if there is a collision at the specified tile coordinates in the provided GameLocation. /// + /// The GameLocation instance to search for collisions. /// The x-coordinate of the tile to check. /// The y-coordinate of the tile to check. - /// The GameLocation instance to search for collisions. /// True if a collision is detected at the specified tile coordinates, otherwise False. - public static bool IsCollidingAtTile(int x, int y, GameLocation currentLocation) + public static bool IsCollidingAtTile(GameLocation currentLocation, int x, int y, bool lessInfo = false) { // This function highly optimized over readability because `currentLocation.isCollidingPosition` takes ~30ms on the Farm map, more on larger maps I.E. Forest. // Return the result of the logical comparison directly, inlining operations // Check if the tile is NOT a warp point and if it collides with an object or terrain feature // OR if the tile has stumps in a Woods location - return !isWarpPointAtTile(x, y, currentLocation) && + return !isWarpPointAtTile(currentLocation, x, y) && (currentLocation.isCollidingPosition(new Rectangle(x * 64 + 1, y * 64 + 1, 62, 62), Game1.viewport, true, 0, glider: false, Game1.player, pathfinding: true) || - (currentLocation is Woods woods && getStumpsInWoods(x, y, woods) is not null)); + (currentLocation is Woods woods && getStumpsInWoods(woods, x, y, lessInfo) is not null)); } /// /// Returns the Warp object at the specified tile coordinates or null if not found. /// - private static Warp? GetWarpAtTile(int x, int y, GameLocation currentLocation) + private static Warp? GetWarpAtTile(GameLocation currentLocation, int x, int y) { if (currentLocation is null) return null; @@ -281,13 +281,13 @@ namespace stardew_access.Features /// /// Returns the name of the warp point at the specified tile coordinates, or null if not found. /// - public static string? getWarpPointAtTile(int x, int y, GameLocation currentLocation) + public static string? getWarpPointAtTile(GameLocation currentLocation, int x, int y, bool lessInfo = false) { - Warp? warpPoint = GetWarpAtTile(x, y, currentLocation); + Warp? warpPoint = GetWarpAtTile(currentLocation, x, y); if (warpPoint != null) { - return $"{warpPoint.TargetName} Entrance"; + return lessInfo ? warpPoint.TargetName : $"{warpPoint.TargetName} Entrance"; } return null; @@ -296,9 +296,9 @@ namespace stardew_access.Features /// /// Returns true if there's a warp point at the specified tile coordinates, or false otherwise. /// - public static bool isWarpPointAtTile(int x, int y, GameLocation currentLocation) + public static bool isWarpPointAtTile(GameLocation currentLocation, int x, int y) { - return GetWarpAtTile(x, y, currentLocation) != null; + return GetWarpAtTile(currentLocation, x, y) != null; } /// @@ -311,7 +311,7 @@ namespace stardew_access.Features /// A string containing the farm animal's name, type, and age if a farm animal is found at the specified tile; /// null if no farm animal is found or if the location is not a Farm or an AnimalHouse. /// - public static string? getFarmAnimalAt(GameLocation? location, int x, int y) + public static string? getFarmAnimalAt(GameLocation location, int x, int y) { // Return null if the location is null or not a Farm or AnimalHouse if (location is null || !(location is Farm || location is AnimalHouse)) @@ -499,10 +499,10 @@ namespace stardew_access.Features { int treeType = tree.treeType.Value; int treeStage = tree.growthStage.Value; - string seedName = ""; + string seedName = ""; - // Handle special tree types and return their names - switch (treeType) + // Handle special tree types and return their names + switch (treeType) { case 4: case 5: @@ -522,28 +522,28 @@ namespace stardew_access.Features // Determine the tree name and growth stage description if (treeStage >= 1) { - string treeName; - switch (seedName.ToLower()) - { - case "mahogany seed": - treeName = "Mahogany"; - break; - case "acorn": - treeName = "Oak"; - break; - case "maple seed": - treeName = "Maple"; - break; - case "pine cone": - treeName = "Pine"; - break; - default: - treeName = "Coconut"; - break; - } + string treeName; + switch (seedName.ToLower()) + { + case "mahogany seed": + treeName = "Mahogany"; + break; + case "acorn": + treeName = "Oak"; + break; + case "maple seed": + treeName = "Maple"; + break; + case "pine cone": + treeName = "Pine"; + break; + default: + treeName = "Coconut"; + break; + } - // Append the growth stage description to the tree name - if (treeStage == 1) + // Append the growth stage description to the tree name + if (treeStage == 1) treeName = $"{treeName} sprout"; else if (treeStage == 2) treeName = $"{treeName} sapling"; @@ -563,12 +563,12 @@ namespace stardew_access.Features /// /// Retrieves the name and category of an object at a specific tile in the game location. /// + /// The current game location. /// The X coordinate of the tile. /// The Y coordinate of the tile. - /// The current game location. /// An optional parameter to display less information, set to false by default. /// A tuple containing the object's name and category. - public static (string? name, CATEGORY category) getObjectAtTile(int x, int y, GameLocation currentLocation, bool lessInfo = false) + public static (string? name, CATEGORY category) getObjectAtTile(GameLocation currentLocation, int x, int y, bool lessInfo = false) { (string? name, CATEGORY category) toReturn = (null, CATEGORY.Others); @@ -783,12 +783,12 @@ namespace stardew_access.Features /// /// Check if a tile with the specified index exists at the given coordinates in the specified location. /// + /// The current game location. /// The X coordinate of the tile. /// The Y coordinate of the tile. - /// The current game location. /// The target tile index to check for. /// True if a tile with the specified index exists at the given coordinates, false otherwise. - private static bool CheckTileIndex(int x, int y, GameLocation currentLocation, int targetTileIndex) + private static bool CheckTileIndex(GameLocation currentLocation, int x, int y, int targetTileIndex) { var tile = currentLocation.Map.GetLayer("Buildings").Tiles[x, y]; return tile != null && tile.TileIndex == targetTileIndex; @@ -797,70 +797,67 @@ namespace stardew_access.Features /// /// Determines if a mine down ladder is present at the specified tile location. /// + /// The current GameLocation instance. /// The x-coordinate of the tile. /// The y-coordinate of the tile. - /// The current GameLocation instance. /// True if a mine down ladder is found at the specified tile, otherwise false. - public static bool isMineDownLadderAtTile(int x, int y, GameLocation currentLocation) + public static bool isMineDownLadderAtTile(GameLocation currentLocation, int x, int y) { return currentLocation is Mine or MineShaft || currentLocation.Name == "SkullCave" - ? CheckTileIndex(x, y, currentLocation, 173) + ? CheckTileIndex(currentLocation, x, y, 173) : false; } /// /// Determines if a mine shaft is present at the specified tile location. /// + /// The current GameLocation instance. /// The x-coordinate of the tile. /// The y-coordinate of the tile. - /// The current GameLocation instance. /// True if a mine shaft is found at the specified tile, otherwise false. - public static bool isShaftAtTile(int x, int y, GameLocation currentLocation) + public static bool isShaftAtTile(GameLocation currentLocation, int x, int y) { return currentLocation is Mine or MineShaft || currentLocation.Name == "SkullCave" - ? CheckTileIndex(x, y, currentLocation, 174) + ? CheckTileIndex(currentLocation, x, y, 174) : false; } /// /// Determines if a mine up ladder is present at the specified tile location. /// + /// The current GameLocation instance. /// The x-coordinate of the tile. /// The y-coordinate of the tile. - /// The current GameLocation instance. /// True if a mine up ladder is found at the specified tile, otherwise false. - public static bool isMineUpLadderAtTile(int x, int y, GameLocation currentLocation) + public static bool isMineUpLadderAtTile(GameLocation currentLocation, int x, int y) { return currentLocation is Mine or MineShaft || currentLocation.Name == "SkullCave" - ? CheckTileIndex(x, y, currentLocation, 115) + ? CheckTileIndex(currentLocation, x, y, 115) : false; } /// /// Determines if an elevator is present at the specified tile location. /// + /// The current GameLocation instance. /// The x-coordinate of the tile. /// The y-coordinate of the tile. - /// The current GameLocation instance. /// True if an elevator is found at the specified tile, otherwise false. - public static bool isElevatorAtTile(int x, int y, GameLocation currentLocation) + public static bool isElevatorAtTile(GameLocation currentLocation, int x, int y) { return currentLocation is Mine or MineShaft || currentLocation.Name == "SkullCave" - ? CheckTileIndex(x, y, currentLocation, 112) + ? CheckTileIndex(currentLocation, x, y, 112) : false; } /// /// Gets the door information at the specified tile coordinates in the given location. /// + /// The GameLocation where the door might be found. /// The x-coordinate of the tile to check. /// The y-coordinate of the tile to check. - /// The GameLocation where the door might be found. - /// - /// A string containing the door information if a door is found at the specified tile; - /// null if no door is found. - /// - public static string? getDoorAtTile(int x, int y, GameLocation currentLocation) + /// A string containing the door information if a door is found at the specified tile; null if no door is found. + public static string? getDoorAtTile(GameLocation currentLocation, int x, int y) { // Create a Point object from the given tile coordinates Point tilePoint = new(x, y); @@ -882,19 +879,16 @@ namespace stardew_access.Features /// /// Gets the resource clump information at the specified tile coordinates in the given location. /// + /// The GameLocation where the resource clump might be found. /// The x-coordinate of the tile to check. /// The y-coordinate of the tile to check. - /// The GameLocation where the resource clump might be found. /// Optional. If true, returns information only if the tile coordinates match the resource clump's origin. Default is false. - /// - /// A string containing the resource clump information if a resource clump is found at the specified tile; - /// null if no resource clump is found. - /// - public static string? getResourceClumpAtTile(int x, int y, GameLocation currentLocation, bool lessInfo = false) + /// A string containing the resource clump information if a resource clump is found at the specified tile; null if no resource clump is found. + public static string? getResourceClumpAtTile(GameLocation currentLocation, int x, int y, bool lessInfo = false) { // Check if the current location is Woods and handle stumps in woods separately if (currentLocation is Woods woods) - return getStumpsInWoods(x, y, woods, lessInfo); + return getStumpsInWoods(woods, x, y, lessInfo); // Iterate through resource clumps in the location using a for loop for performance reasons for (int i = 0, count = currentLocation.resourceClumps.Count; i < count; i++) @@ -916,15 +910,12 @@ namespace stardew_access.Features /// /// Gets the stump information at the specified tile coordinates in the given Woods location. /// + /// The Woods location where the stump might be found. /// The x-coordinate of the tile to check. /// The y-coordinate of the tile to check. - /// The Woods location where the stump might be found. /// Optional. If true, returns information only if the tile coordinates match the stump's origin. Default is false. - /// - /// A string containing the stump information if a stump is found at the specified tile; - /// null if no stump is found. - /// - public static string? getStumpsInWoods(int x, int y, Woods woods, bool lessInfo = false) + /// A string containing the stump information if a stump is found at the specified tile; null if no stump is found. + public static string? getStumpsInWoods(Woods woods, int x, int y, bool lessInfo = false) { // Iterate through stumps in the Woods location foreach (var stump in woods.stumps) diff --git a/stardew-access/Features/TileViewer.cs b/stardew-access/Features/TileViewer.cs index 0444b56..282d0aa 100644 --- a/stardew-access/Features/TileViewer.cs +++ b/stardew-access/Features/TileViewer.cs @@ -184,7 +184,7 @@ namespace stardew_access.Features if (name == null) { // Report if a tile is empty or blocked if there is nothing on it - if (TileInfo.IsCollidingAtTile((int)tile.X, (int)tile.Y, Game1.currentLocation)) + if (TileInfo.IsCollidingAtTile(Game1.currentLocation, (int)tile.X, (int)tile.Y)) { name = "blocked"; } @@ -280,7 +280,7 @@ namespace stardew_access.Features { var currentLocation = Game1.currentLocation; // Check whether the position is a warp point, if so then return true, sometimes warp points are 1 tile off the map for example in coops and barns - if (TileInfo.isWarpPointAtTile((int)(position.X / Game1.tileSize), (int)(position.Y / Game1.tileSize), currentLocation)) return true; + if (TileInfo.isWarpPointAtTile(currentLocation, (int)(position.X / Game1.tileSize), (int)(position.Y / Game1.tileSize))) return true; //position does not take viewport into account since the entire map needs to be checked. Map map = currentLocation.map; diff --git a/stardew-access/Patches/MiscPatches/Game1Patch.cs b/stardew-access/Patches/MiscPatches/Game1Patch.cs index 4b52615..319acde 100644 --- a/stardew-access/Patches/MiscPatches/Game1Patch.cs +++ b/stardew-access/Patches/MiscPatches/Game1Patch.cs @@ -34,7 +34,7 @@ namespace stardew_access.Patches if (cueName == "grassyStep" || cueName == "sandyStep" || cueName == "snowyStep" || cueName == "stoneStep" || cueName == "thudStep" || cueName == "woodyStep") { Vector2 nextTile = CurrentPlayer.FacingTile; - if (TileInfo.IsCollidingAtTile((int)nextTile.X, (int)nextTile.Y, Game1.currentLocation)) + if (TileInfo.IsCollidingAtTile(Game1.currentLocation, (int)nextTile.X, (int)nextTile.Y)) { if (prevTile != nextTile) {