diff --git a/.gitignore b/.gitignore
index 7bc055e..82c0f04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
.vscode/*
+.git-old/
# User-specific files
*.rsuser
diff --git a/stardew-access/API.cs b/stardew-access/API.cs
index 902eed7..0362154 100644
--- a/stardew-access/API.cs
+++ b/stardew-access/API.cs
@@ -37,7 +37,7 @@ namespace stardew_access.ScreenReader
/// Name of the object as the first item (Item1) and category as the second item (Item2). Returns null if no object found.
public (string?, string?) GetNameWithCategoryNameAtTile(Vector2 tile)
{
- return ReadTile.getNameWithCategoryNameAtTile(tile);
+ return TileInfo.getNameWithCategoryNameAtTile(tile);
}
///
@@ -47,7 +47,7 @@ namespace stardew_access.ScreenReader
/// Name of the object. Returns null if no object found.
public string? GetNameAtTile(Vector2 tile)
{
- return ReadTile.getNameAtTile(tile);
+ return TileInfo.getNameAtTile(tile);
}
/// Speaks the text via the loaded screen reader (if any).
diff --git a/stardew-access/Features/Radar.cs b/stardew-access/Features/Radar.cs
index 62b4c27..c0b0eaa 100644
--- a/stardew-access/Features/Radar.cs
+++ b/stardew-access/Features/Radar.cs
@@ -1,7 +1,6 @@
using Microsoft.Xna.Framework;
using StardewValley;
using StardewValley.Objects;
-using StardewValley.TerrainFeatures;
namespace stardew_access.Features
{
@@ -187,7 +186,7 @@ namespace stardew_access.Features
public (bool, string?, string) CheckTile(Vector2 position)
{
- (string? name, CATEGORY? category) tileDetail = ReadTile.getNameWithCategoryAtTile(position);
+ (string? name, CATEGORY? category) tileDetail = TileInfo.getNameWithCategoryAtTile(position);
if (tileDetail.name == null)
return (false, null, CATEGORY.Others.ToString());
@@ -204,7 +203,7 @@ namespace stardew_access.Features
{
if (Game1.currentLocation.isObjectAtTile((int)position.X, (int)position.Y))
{
- (string? name, CATEGORY category) objDetails = ReadTile.getObjectAtTile((int)position.X, (int)position.Y);
+ (string? name, CATEGORY category) objDetails = TileInfo.getObjectAtTile((int)position.X, (int)position.Y);
string? objectName = objDetails.name;
CATEGORY category = objDetails.category;
StardewValley.Object obj = Game1.currentLocation.getObjectAtTile((int)position.X, (int)position.Y);
@@ -228,7 +227,7 @@ namespace stardew_access.Features
}
else
{
- (string? name, CATEGORY? category) tileDetail = ReadTile.getNameWithCategoryAtTile(position);
+ (string? name, CATEGORY? category) tileDetail = TileInfo.getNameWithCategoryAtTile(position);
if (tileDetail.name != null)
{
if (tileDetail.category == null)
diff --git a/stardew-access/Features/ReadTile.cs b/stardew-access/Features/ReadTile.cs
index 33c5931..54dcb92 100644
--- a/stardew-access/Features/ReadTile.cs
+++ b/stardew-access/Features/ReadTile.cs
@@ -1,17 +1,9 @@
using Microsoft.Xna.Framework;
using StardewModdingAPI;
using StardewValley;
-using StardewValley.Buildings;
-using StardewValley.Locations;
-using StardewValley.Objects;
-using StardewValley.TerrainFeatures;
namespace stardew_access.Features
{
- public enum MachineState
- {
- Ready, Busy, Waiting
- }
public class ReadTile
{
public static bool isReadingTile = false;
@@ -51,9 +43,9 @@ namespace stardew_access.Features
MainClass.ScreenReader.PrevTextTile = " ";
}
- bool isColliding = isCollidingAtTile(x, y);
+ bool isColliding = TileInfo.isCollidingAtTile(x, y);
- string? toSpeak = getNameAtTile(tile);
+ string? toSpeak = TileInfo.getNameAtTile(tile);
#region Narrate toSpeak
if (toSpeak != null)
@@ -81,831 +73,5 @@ namespace stardew_access.Features
MainClass.ErrorLog($"Error in Read Tile:\n{e.Message}\n{e.StackTrace}");
}
}
-
- ///Returns the name of the object at tile alongwith it's category's name
- public static (string? name, string? categoryName) getNameWithCategoryNameAtTile(Vector2 tile)
- {
- (string? name, CATEGORY? category) tileDetail = getNameWithCategoryAtTile(tile);
-
- if (tileDetail.category == null)
- tileDetail.category = CATEGORY.Others;
-
- return (tileDetail.name, tileDetail.category.ToString());
- }
-
- ///Returns the name of the object at tile
- public static string? getNameAtTile(Vector2 tile)
- {
- return getNameWithCategoryAtTile(tile).name;
- }
-
- ///Returns the name of the object at tile alongwith it's category
- public static (string? name, CATEGORY? category) getNameWithCategoryAtTile(Vector2 tile)
- {
- int x = (int)tile.X;
- int y = (int)tile.Y;
- string? toReturn = "";
- CATEGORY? category = CATEGORY.Others;
-
- bool isColliding = isCollidingAtTile(x, y);
- Dictionary> terrainFeature = Game1.currentLocation.terrainFeatures.FieldDict;
- string? door = getDoorAtTile(x, y);
- (CATEGORY? category, string? name) tileInfo = getTileInfo(x, y);
- string? junimoBundle = getJunimoBundleAt(x, y);
- string? resourceClump = getResourceClumpAtTile(x, y);
- string? farmAnimal = getFarmAnimalAt(Game1.currentLocation, x, y);
-
- if (Game1.currentLocation.isCharacterAtTile(tile) != null)
- {
- NPC npc = Game1.currentLocation.isCharacterAtTile(tile);
- toReturn = npc.displayName;
- if (npc.isVillager() || npc.CanSocialize)
- category = CATEGORY.Farmers;
- else
- category = CATEGORY.NPCs;
- }
- else if (farmAnimal != null)
- {
- toReturn = farmAnimal;
- category = CATEGORY.FarmAnimals;
- }
- else if (Game1.currentLocation.isWaterTile(x, y) && isColliding)
- {
- toReturn = "Water";
- category = CATEGORY.WaterTiles;
- }
- else if (Game1.currentLocation.isObjectAtTile(x, y))
- {
- (string? name, CATEGORY? category) obj = getObjectAtTile(x, y);
- toReturn = obj.name;
- category = obj.category;
- }
- else if (terrainFeature.ContainsKey(tile))
- {
- (string? name, CATEGORY category) tf = getTerrainFeatureAtTile(terrainFeature[tile]);
- string? terrain = tf.name;
- if (terrain != null)
- {
- toReturn = terrain;
- category = tf.category;
- }
-
- }
- else if (Game1.currentLocation.getLargeTerrainFeatureAt(x, y) != null)
- {
- toReturn = getBushAtTile(x, y);
- category = CATEGORY.Bush;
- }
- else if (resourceClump != null)
- {
- toReturn = resourceClump;
- category = CATEGORY.ResourceClumps;
- }
- else if (door != null)
- {
- toReturn = door;
- category = CATEGORY.Doors;
- }
- else if (isMineDownLadderAtTile(x, y))
- {
- toReturn = "Ladder";
- category = CATEGORY.Doors;
- }
- else if (isMineUpLadderAtTile(x, y))
- {
- toReturn = "Up Ladder";
- category = CATEGORY.Doors;
- }
- else if (isElevatorAtTile(x, y))
- {
- toReturn = "Elevator";
- category = CATEGORY.Doors;
- }
- else if (tileInfo.name != null)
- {
- toReturn = tileInfo.name;
- category = tileInfo.category;
- }
- else if (junimoBundle != null)
- {
- toReturn = junimoBundle;
- category = CATEGORY.JunimoBundle;
- }
-
- if (toReturn == "")
- return (null, category);
-
- return (toReturn, category);
- }
-
- public static string? getBushAtTile(int x, int y)
- {
- string? toReturn = null;
- Bush bush = (Bush)Game1.currentLocation.getLargeTerrainFeatureAt(x, y);
- int size = bush.size.Value;
-
- #region Check if bush is harvestable or not
- if (!bush.townBush.Value && (int)bush.tileSheetOffset.Value == 1 && bush.inBloom(Game1.GetSeasonForLocation(Game1.currentLocation), Game1.dayOfMonth))
- {
- // Taken from the game's code
- string season = ((int)bush.overrideSeason.Value == -1) ? Game1.GetSeasonForLocation(Game1.currentLocation) : Utility.getSeasonNameFromNumber(bush.overrideSeason.Value);
- int shakeOff = -1;
- if (!(season == "spring"))
- {
- if (season == "fall")
- {
- shakeOff = 410;
- }
- }
- else
- {
- shakeOff = 296;
- }
- if ((int)size == 3)
- {
- shakeOff = 815;
- }
- if ((int)size == 4)
- {
- shakeOff = 73;
- }
- if (shakeOff == -1)
- {
- return null;
- }
-
- toReturn = "Harvestable";
- }
- #endregion
-
- if (bush.townBush.Value)
- toReturn = $"{toReturn} Town Bush";
- else if (bush.greenhouseBush.Value)
- toReturn = $"{toReturn} Greenhouse Bush";
- else
- toReturn = $"{toReturn} Bush";
-
- return toReturn;
- }
-
- public static string? getJunimoBundleAt(int x, int y)
- {
- string? name = null;
- if (Game1.currentLocation is CommunityCenter communityCenter)
- {
- name = (x, y) switch
- {
- (14, 5) => "Pantry",
- (14, 23) => "Crafts Room",
- (40, 10) => "Fish Tank",
- (63, 14) => "Boiler Room",
- (55, 6) => "Vault",
- (46, 11) => "Bulletin Board",
- _ => null,
- };
- if (name != null && communityCenter.shouldNoteAppearInArea(CommunityCenter.getAreaNumberFromName(name)))
- return $"{name} bundle";
- }
- else if (Game1.currentLocation is AbandonedJojaMart)
- {
- name = (x, y) switch
- {
- (8, 8) => "Missing",
- _ => null,
- };
-
- if (name != null)
- return $"{name} bundle";
- }
-
- return null;
- }
-
- public static bool isCollidingAtTile(int x, int y)
- {
- Rectangle rect = new Rectangle(x * 64 + 1, y * 64 + 1, 62, 62);
-
- if (Game1.currentLocation.isCollidingPosition(rect, Game1.viewport, true, 0, glider: false, Game1.player, pathfinding: true))
- {
- return true;
- }
-
- if (Game1.currentLocation is Woods && getStumpsInWoods(x, y) != null)
- return true;
-
- return false;
- }
-
- public static string? getFarmAnimalAt(GameLocation? location, int x, int y, bool onlyName = false)
- {
- if (location == null)
- return null;
-
- if (location is not Farm && location is not AnimalHouse)
- return null;
-
- List? farmAnimals = null;
-
- if (location is Farm)
- farmAnimals = ((Farm)location).getAllFarmAnimals();
- else if (location is AnimalHouse)
- farmAnimals = ((AnimalHouse)location).animals.Values.ToList();
-
- if (farmAnimals == null || farmAnimals.Count <= 0)
- return null;
-
- for (int i = 0; i < farmAnimals.Count; i++)
- {
- int fx = farmAnimals[i].getTileX();
- int fy = farmAnimals[i].getTileY();
-
- if (fx.Equals(x) && fy.Equals(y))
- {
- string name = farmAnimals[i].displayName;
- int age = farmAnimals[i].age.Value;
- string type = farmAnimals[i].displayType;
-
- if (onlyName)
- return name;
-
- return $"{name}, {type}, age {age}";
- }
- }
-
- return null;
- }
-
- ///
- ///
- ///
- ///
- ///
- /// category: This is the category of the tile. Default to Furnitures.
- ///
name: This is the name of the tile. Default to null if the tile tile has nothing on it.
- public static (CATEGORY? category, string? name) getTileInfo(int x, int y)
- {
-
- int? index = null;
-
- if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
- index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
- /* Add More
- MainClass.monitor.Log(index.ToString(), LogLevel.Debug);
- */
-
- if (Game1.currentLocation is Farm)
- {
- Building building = ((Farm)Game1.currentLocation).getBuildingAt(new Vector2(x, y));
- if (building != null)
- {
- return (CATEGORY.Buildings, building.buildingType.Value);
- }
- }
-
- if (index != null)
- {
- switch (index)
- {
- case 1955:
- case 41:
- return (CATEGORY.Furnitures, "Mail Box");
- case 1003:
- return (CATEGORY.Furnitures, "Street lamp");
- case 78:
- return (CATEGORY.Furnitures, "Trash bin");
- case 617:
- return (CATEGORY.Furnitures, "Daily quest");
- case 616:
- return (CATEGORY.Furnitures, "Calender");
- }
-
- if (Game1.currentLocation is FarmHouse || Game1.currentLocation is IslandFarmHouse)
- {
- switch (index)
- {
- case 173:
- return (CATEGORY.Furnitures, "Fridge");
- case 169:
- case 170:
- case 171:
- case 172:
- return (CATEGORY.Furnitures, "Kitchen");
- }
- }
-
- }
-
- return (null, null);
- }
-
- public static (string? name, CATEGORY category) getTerrainFeatureAtTile(Netcode.NetRef terrain)
- {
- string? toReturn = null;
- CATEGORY category = CATEGORY.Others;
-
- if (terrain.Get() is HoeDirt)
- {
- category = CATEGORY.Crops;
- HoeDirt dirt = (HoeDirt)terrain.Get();
- if (dirt.crop != null)
- {
- string cropName = Game1.objectInformation[dirt.crop.indexOfHarvest.Value].Split('/')[0];
- toReturn = $"{cropName}";
-
- bool isWatered = dirt.state.Value == HoeDirt.watered;
- bool isHarvestable = dirt.readyForHarvest();
- bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer;
-
- if (isWatered)
- toReturn = "Watered " + toReturn;
-
- if (isFertilized)
- toReturn = "Fertilized " + toReturn;
-
- if (isHarvestable)
- toReturn = "Harvestable " + toReturn;
- }
- else
- {
- toReturn = "Soil";
- bool isWatered = dirt.state.Value == HoeDirt.watered;
- bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer;
-
- if (isWatered)
- toReturn = "Watered " + toReturn;
-
- if (isFertilized)
- toReturn = "Fertilized " + toReturn;
- }
- }
- else if (terrain.Get() is GiantCrop)
- {
- category = CATEGORY.Crops;
- int whichCrop = ((GiantCrop)terrain.Get()).which.Value;
- switch (whichCrop)
- {
- case 0:
- toReturn = "Cauliflower";
- break;
- case 1:
- toReturn = "Melon";
- break;
- case 2:
- toReturn = "Pumpkin";
- break;
- }
- }
- else if (terrain.Get() is CosmeticPlant)
- {
- category = CATEGORY.Furnitures;
- CosmeticPlant cosmeticPlant = (CosmeticPlant)terrain.Get();
- toReturn = cosmeticPlant.textureName().ToLower();
-
- if (toReturn.Contains("terrain"))
- toReturn.Replace("terrain", "");
-
- if (toReturn.Contains("feature"))
- toReturn.Replace("feature", "");
- }
- else if (terrain.Get() is Flooring && MainClass.Config.ReadFlooring)
- {
- category = CATEGORY.Flooring;
- Flooring flooring = (Flooring)terrain.Get();
- bool isPathway = flooring.isPathway.Get();
- bool isSteppingStone = flooring.isSteppingStone.Get();
-
- toReturn = "Flooring";
-
- if (isPathway)
- toReturn = "Pathway";
-
- if (isSteppingStone)
- toReturn = "Stepping Stone";
- }
- else if (terrain.Get() is FruitTree)
- {
- category = CATEGORY.Trees;
- toReturn = getFruitTree((FruitTree)terrain.Get());
- }
- else if (terrain.Get() is Grass)
- {
- category = CATEGORY.Debris;
- toReturn = "Grass";
- }
- else if (terrain.Get() is Tree)
- {
- category = CATEGORY.Trees;
- toReturn = getTree((Tree)terrain.Get());
- }
- else if (terrain.Get() is Quartz)
- {
- category = CATEGORY.MineItems;
- toReturn = "Quartz";
- }
-
- return (toReturn, category);
- }
-
- public static string getFruitTree(FruitTree fruitTree)
- {
- int stage = fruitTree.growthStage.Value;
- int fruitIndex = fruitTree.indexOfFruit.Get();
-
- string toReturn = Game1.objectInformation[fruitIndex].Split('/')[0];
-
- if (stage == 0)
- toReturn = $"{toReturn} seed";
- else if (stage == 1)
- toReturn = $"{toReturn} sprout";
- else if (stage == 2)
- toReturn = $"{toReturn} sapling";
- else if (stage == 3)
- toReturn = $"{toReturn} bush";
- else if (stage >= 4)
- toReturn = $"{toReturn} tree";
-
- if (fruitTree.fruitsOnTree.Value > 0)
- toReturn = $"Harvestable {toReturn}";
-
- return toReturn;
- }
-
- public static string getTree(Tree tree)
- {
- int treeType = tree.treeType.Value;
- int treeStage = tree.growthStage.Value;
- string treeName = "tree";
- string seedName = "";
-
- // Return with the name if it's one of the 3 special trees
- switch (treeType)
- {
- case 4:
- case 5:
- return "Winter Tree";
- case 6:
- return "Palm Tree";
- case 7:
- return "Mushroom Tree";
- }
-
-
- if (treeType <= 3)
- seedName = Game1.objectInformation[308 + treeType].Split('/')[0];
- else if (treeType == 8)
- seedName = Game1.objectInformation[292].Split('/')[0];
-
- if (treeStage >= 1)
- {
- 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;
- }
-
- if (treeStage == 1)
- treeName = $"{treeName} sprout";
- else if (treeStage == 2)
- treeName = $"{treeName} sapling";
- else if (treeStage == 3 || treeStage == 4)
- treeName = $"{treeName} bush";
- else if (treeStage >= 5)
- treeName = $"{treeName} tree";
-
- return treeName;
- }
-
- return seedName;
- }
-
- #region Objects
- public static (string? name, CATEGORY category) getObjectAtTile(int x, int y)
- {
- (string? name, CATEGORY category) toReturn = (null, CATEGORY.Others);
-
- StardewValley.Object obj = Game1.currentLocation.getObjectAtTile(x, y);
- int index = obj.ParentSheetIndex;
- toReturn.name = obj.DisplayName;
-
- // Get object names based on index
- (string? name, CATEGORY category) correctNameAndCategory = getCorrectNameAndCategoryFromIndex(index);
- if (correctNameAndCategory.name != null)
- toReturn = correctNameAndCategory;
-
- if (toReturn.name.ToLower().Equals("stone")) // Fix for `Busy stone`
- toReturn.category = CATEGORY.Debris;
-
- if (obj is Chest)
- {
- Chest chest = (Chest)obj;
- toReturn = (chest.DisplayName, CATEGORY.Chests);
- }
-
- if (obj is Furniture)
- toReturn.category = CATEGORY.Furnitures;
-
- if (toReturn.category == CATEGORY.Others) // Fix for `Harvestable table` and `Busy nodes`
- {
- MachineState machineState = GetMachineState(obj);
- if (machineState == MachineState.Ready)
- toReturn.name = $"Harvestable {toReturn.name}";
- else if (machineState == MachineState.Busy)
- toReturn.name = $"Busy {toReturn.name}";
- }
- return toReturn;
- }
-
- private static MachineState GetMachineState(StardewValley.Object machine)
- {
- if (machine is CrabPot crabPot)
- if (crabPot.bait.Value is not null && crabPot.heldObject.Value is null)
- return MachineState.Busy;
- return GetMachineState(machine.readyForHarvest.Value, machine.MinutesUntilReady, machine.heldObject.Value);
- }
-
- private static MachineState GetMachineState(bool readyForHarvest, int minutesUntilReady, StardewValley.Object? heldObject)
- {
- if (readyForHarvest || (heldObject is not null && minutesUntilReady <= 0))
- return MachineState.Ready;
- else if (minutesUntilReady > 0)
- return MachineState.Busy;
- else
- return MachineState.Waiting;
- }
-
- private static (string? name, CATEGORY category) getCorrectNameAndCategoryFromIndex(int index)
- {
- switch (index)
- {
- case 313:
- case 314:
- case 315:
- case 316:
- case 317:
- case 318:
- case 452:
- case 674:
- case 675:
- case 676:
- case 677:
- case 678:
- case 679:
- case 750:
- case 784:
- case 785:
- case 786:
- return ("Weed", CATEGORY.Debris);
- case 792:
- case 793:
- case 794:
- return ("Fertile weed", CATEGORY.Debris);
- case 319:
- case 320:
- case 321:
- return ("Ice crystal", CATEGORY.Debris);
- case 75:
- return ("Geode", CATEGORY.MineItems);
- case 32:
- case 34:
- case 36:
- case 38:
- case 40:
- case 42:
- case 48:
- case 50:
- case 52:
- case 54:
- case 56:
- case 58:
- return ("Coloured stone", CATEGORY.Debris);
- case 668:
- case 670:
- case 845:
- case 846:
- case 847:
- return ("Mine stone", CATEGORY.MineItems);
- case 818:
- return ("Clay stone", CATEGORY.Debris);
- case 816:
- case 817:
- return ("Fossil stone", CATEGORY.Debris);
- case 118:
- case 120:
- case 122:
- case 124:
- return ("Barrel", CATEGORY.MineItems);
- case 119:
- case 121:
- case 123:
- case 125:
- return ("Item box", CATEGORY.MineItems);
- }
-
- if (Game1.currentLocation is Mine or MineShaft)
- {
- switch (index)
- {
- case 76:
- return ("Frozen geode", CATEGORY.MineItems);
- case 77:
- return ("Magma geode", CATEGORY.MineItems);
- case 8:
- case 66:
- return ("Amethyst node", CATEGORY.MineItems);
- case 14:
- case 62:
- return ("Aquamarine node", CATEGORY.MineItems);
- case 843:
- case 844:
- return ("Cinder shard node", CATEGORY.MineItems);
- case 2:
- case 72:
- return ("Diamond node", CATEGORY.MineItems);
- case 12:
- case 60:
- return ("Emerald node", CATEGORY.MineItems);
- case 44:
- return ("Gem node", CATEGORY.MineItems);
- case 6:
- case 70:
- return ("Jade node", CATEGORY.MineItems);
- case 46:
- return ("Mystic stone", CATEGORY.MineItems);
- case 74:
- return ("Prismatic node", CATEGORY.MineItems);
- case 4:
- case 64:
- return ("Ruby node", CATEGORY.MineItems);
- case 10:
- case 68:
- return ("Topaz node", CATEGORY.MineItems);
- case 819:
- return ("Omni geode node", CATEGORY.MineItems);
- case 751:
- case 849:
- return ("Copper node", CATEGORY.MineItems);
- case 764:
- return ("Gold node", CATEGORY.MineItems);
- case 765:
- return ("Iridium node", CATEGORY.MineItems);
- case 290:
- case 850:
- return ("Iron node", CATEGORY.MineItems);
- }
- }
-
- return (null, CATEGORY.Others);
- }
- #endregion
-
- public static bool isMineDownLadderAtTile(int x, int y)
- {
- try
- {
- if (Game1.currentLocation is Mine or MineShaft)
- {
- int? index = null;
-
- if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
- index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
-
- if (index == 173 || index == 174)
- return true;
- }
- }
- catch (Exception) { }
-
- return false;
- }
-
- public static bool isMineUpLadderAtTile(int x, int y)
- {
- try
- {
- if (Game1.currentLocation is Mine or MineShaft)
- {
- int? index = null;
-
- if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
- index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
-
- if (index == 115)
- return true;
- }
- }
- catch (Exception) { }
-
- return false;
- }
-
- public static bool isElevatorAtTile(int x, int y)
- {
- try
- {
- if (Game1.currentLocation is Mine or MineShaft)
- {
- int? index = null;
-
- if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
- index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
-
- if (index == 112)
- return true;
- }
- }
- catch (Exception) { }
-
- return false;
- }
-
- public static string? getDoorAtTile(int x, int y)
- {
- Point tilePoint = new Point(x, y);
- StardewValley.Network.NetPointDictionary doorList = Game1.currentLocation.doors;
-
- for (int i = 0; i < doorList.Count(); i++)
- {
- if (doorList.ContainsKey(tilePoint))
- {
- string? doorName;
- doorList.TryGetValue(tilePoint, out doorName);
-
- if (doorName != null)
- return $"{doorName} door";
- else
- return "door";
- }
- }
-
- return null;
- }
-
- public static string? getResourceClumpAtTile(int x, int y)
- {
- if (Game1.currentLocation is Woods)
- return getStumpsInWoods(x, y);
-
- for (int i = 0; i < Game1.currentLocation.resourceClumps.Count; i++)
- {
- if (Game1.currentLocation.resourceClumps[i].occupiesTile(x, y))
- {
- int index = Game1.currentLocation.resourceClumps[i].parentSheetIndex.Value;
-
- switch (index)
- {
- case 600:
- return "Large Stump";
- case 602:
- return "Hollow Log";
- case 622:
- return "Meteorite";
- case 752:
- case 754:
- case 756:
- case 758:
- return "Mine Rock";
- case 672:
- return "Boulder";
- default:
- return "Unknown";
- }
- }
- }
-
- return null;
- }
-
- public static string? getStumpsInWoods(int x, int y)
- {
- if (Game1.currentLocation is not Woods)
- return null;
-
- if ((x == 8 || x == 9) && y == 7)
- {
- return "Old Master Cannoli";
- }
- Netcode.NetObjectList stumps = ((Woods)Game1.currentLocation).stumps;
- for (int i = 0; i < stumps.Count; i++)
- {
- if (stumps[i].occupiesTile(x, y))
- {
- return "Large Stump";
- }
- }
- return null;
- }
}
}
diff --git a/stardew-access/Features/TileInfo.cs b/stardew-access/Features/TileInfo.cs
new file mode 100644
index 0000000..1fb346f
--- /dev/null
+++ b/stardew-access/Features/TileInfo.cs
@@ -0,0 +1,876 @@
+using Microsoft.Xna.Framework;
+using StardewValley;
+using StardewValley.Buildings;
+using StardewValley.Locations;
+using StardewValley.Objects;
+using StardewValley.TerrainFeatures;
+
+namespace stardew_access.Features
+{
+ public enum MachineState
+ {
+ Ready, Busy, Waiting
+ }
+
+ public class TileInfo
+ {
+ ///Returns the name of the object at tile alongwith it's category's name
+ public static (string? name, string? categoryName) getNameWithCategoryNameAtTile(Vector2 tile)
+ {
+ (string? name, CATEGORY? category) tileDetail = getNameWithCategoryAtTile(tile);
+
+ if (tileDetail.category == null)
+ tileDetail.category = CATEGORY.Others;
+
+ return (tileDetail.name, tileDetail.category.ToString());
+ }
+
+ ///Returns the name of the object at tile
+ public static string? getNameAtTile(Vector2 tile)
+ {
+ return getNameWithCategoryAtTile(tile).name;
+ }
+
+ ///Returns the name of the object at tile alongwith it's category
+ public static (string? name, CATEGORY? category) getNameWithCategoryAtTile(Vector2 tile)
+ {
+ int x = (int)tile.X;
+ int y = (int)tile.Y;
+ string? toReturn = "";
+ CATEGORY? category = CATEGORY.Others;
+
+ bool isColliding = isCollidingAtTile(x, y);
+ Dictionary> terrainFeature = Game1.currentLocation.terrainFeatures.FieldDict;
+ string? door = getDoorAtTile(x, y);
+ (CATEGORY? category, string? name) tileInfo = getTileInfo(x, y);
+ string? junimoBundle = getJunimoBundleAt(x, y);
+ string? resourceClump = getResourceClumpAtTile(x, y);
+ string? farmAnimal = getFarmAnimalAt(Game1.currentLocation, x, y);
+ string? parrot = getParrotPerchAtTile(x, y);
+
+ if (Game1.currentLocation.isCharacterAtTile(tile) != null)
+ {
+ NPC npc = Game1.currentLocation.isCharacterAtTile(tile);
+ toReturn = npc.displayName;
+ if (npc.isVillager() || npc.CanSocialize)
+ category = CATEGORY.Farmers;
+ else
+ category = CATEGORY.NPCs;
+ }
+ else if (farmAnimal != null)
+ {
+ toReturn = farmAnimal;
+ category = CATEGORY.FarmAnimals;
+ }
+ else if (Game1.currentLocation.isWaterTile(x, y) && isColliding)
+ {
+ toReturn = "Water";
+ category = CATEGORY.WaterTiles;
+ }
+ else if (Game1.currentLocation.isObjectAtTile(x, y))
+ {
+ (string? name, CATEGORY? category) obj = getObjectAtTile(x, y);
+ toReturn = obj.name;
+ category = obj.category;
+ }
+ else if (terrainFeature.ContainsKey(tile))
+ {
+ (string? name, CATEGORY category) tf = getTerrainFeatureAtTile(terrainFeature[tile]);
+ string? terrain = tf.name;
+ if (terrain != null)
+ {
+ toReturn = terrain;
+ category = tf.category;
+ }
+
+ }
+ else if (Game1.currentLocation.getLargeTerrainFeatureAt(x, y) != null)
+ {
+ toReturn = getBushAtTile(x, y);
+ category = CATEGORY.Bush;
+ }
+ else if (resourceClump != null)
+ {
+ toReturn = resourceClump;
+ category = CATEGORY.ResourceClumps;
+ }
+ else if (door != null)
+ {
+ toReturn = door;
+ category = CATEGORY.Doors;
+ }
+ else if (isMineDownLadderAtTile(x, y))
+ {
+ toReturn = "Ladder";
+ category = CATEGORY.Doors;
+ }
+ else if (isMineUpLadderAtTile(x, y))
+ {
+ toReturn = "Up Ladder";
+ category = CATEGORY.Doors;
+ }
+ else if (isElevatorAtTile(x, y))
+ {
+ toReturn = "Elevator";
+ category = CATEGORY.Doors;
+ }
+ else if (parrot != null)
+ {
+ toReturn = parrot;
+ category = CATEGORY.Buildings;
+ }
+ else if (tileInfo.name != null)
+ {
+ toReturn = tileInfo.name;
+ category = tileInfo.category;
+ }
+ else if (junimoBundle != null)
+ {
+ toReturn = junimoBundle;
+ category = CATEGORY.JunimoBundle;
+ }
+
+ if (toReturn == "")
+ return (null, category);
+
+ return (toReturn, category);
+ }
+
+ public static string? getBushAtTile(int x, int y)
+ {
+ string? toReturn = null;
+ Bush bush = (Bush)Game1.currentLocation.getLargeTerrainFeatureAt(x, y);
+ int size = bush.size.Value;
+
+ #region Check if bush is harvestable or not
+ if (!bush.townBush.Value && (int)bush.tileSheetOffset.Value == 1 && bush.inBloom(Game1.GetSeasonForLocation(Game1.currentLocation), Game1.dayOfMonth))
+ {
+ // Taken from the game's code
+ string season = ((int)bush.overrideSeason.Value == -1) ? Game1.GetSeasonForLocation(Game1.currentLocation) : Utility.getSeasonNameFromNumber(bush.overrideSeason.Value);
+ int shakeOff = -1;
+ if (!(season == "spring"))
+ {
+ if (season == "fall")
+ {
+ shakeOff = 410;
+ }
+ }
+ else
+ {
+ shakeOff = 296;
+ }
+ if ((int)size == 3)
+ {
+ shakeOff = 815;
+ }
+ if ((int)size == 4)
+ {
+ shakeOff = 73;
+ }
+ if (shakeOff == -1)
+ {
+ return null;
+ }
+
+ toReturn = "Harvestable";
+ }
+ #endregion
+
+ if (bush.townBush.Value)
+ toReturn = $"{toReturn} Town Bush";
+ else if (bush.greenhouseBush.Value)
+ toReturn = $"{toReturn} Greenhouse Bush";
+ else
+ toReturn = $"{toReturn} Bush";
+
+ return toReturn;
+ }
+
+ public static string? getJunimoBundleAt(int x, int y)
+ {
+ string? name = null;
+ if (Game1.currentLocation is CommunityCenter communityCenter)
+ {
+ name = (x, y) switch
+ {
+ (14, 5) => "Pantry",
+ (14, 23) => "Crafts Room",
+ (40, 10) => "Fish Tank",
+ (63, 14) => "Boiler Room",
+ (55, 6) => "Vault",
+ (46, 11) => "Bulletin Board",
+ _ => null,
+ };
+ if (name != null && communityCenter.shouldNoteAppearInArea(CommunityCenter.getAreaNumberFromName(name)))
+ return $"{name} bundle";
+ }
+ else if (Game1.currentLocation is AbandonedJojaMart)
+ {
+ name = (x, y) switch
+ {
+ (8, 8) => "Missing",
+ _ => null,
+ };
+
+ if (name != null)
+ return $"{name} bundle";
+ }
+
+ return null;
+ }
+
+ public static bool isCollidingAtTile(int x, int y)
+ {
+ Rectangle rect = new Rectangle(x * 64 + 1, y * 64 + 1, 62, 62);
+
+ if (Game1.currentLocation.isCollidingPosition(rect, Game1.viewport, true, 0, glider: false, Game1.player, pathfinding: true))
+ {
+ return true;
+ }
+
+ if (Game1.currentLocation is Woods && getStumpsInWoods(x, y) != null)
+ return true;
+
+ return false;
+ }
+
+ public static string? getFarmAnimalAt(GameLocation? location, int x, int y, bool onlyName = false)
+ {
+ if (location == null)
+ return null;
+
+ if (location is not Farm && location is not AnimalHouse)
+ return null;
+
+ List? farmAnimals = null;
+
+ if (location is Farm)
+ farmAnimals = ((Farm)location).getAllFarmAnimals();
+ else if (location is AnimalHouse)
+ farmAnimals = ((AnimalHouse)location).animals.Values.ToList();
+
+ if (farmAnimals == null || farmAnimals.Count <= 0)
+ return null;
+
+ for (int i = 0; i < farmAnimals.Count; i++)
+ {
+ int fx = farmAnimals[i].getTileX();
+ int fy = farmAnimals[i].getTileY();
+
+ if (fx.Equals(x) && fy.Equals(y))
+ {
+ string name = farmAnimals[i].displayName;
+ int age = farmAnimals[i].age.Value;
+ string type = farmAnimals[i].displayType;
+
+ if (onlyName)
+ return name;
+
+ return $"{name}, {type}, age {age}";
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// category: This is the category of the tile. Default to Furnitures.
+ ///
name: This is the name of the tile. Default to null if the tile tile has nothing on it.
+ public static (CATEGORY? category, string? name) getTileInfo(int x, int y)
+ {
+
+ int? index = null;
+
+ if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
+ index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
+ /* Add More
+ MainClass.monitor.Log(index.ToString(), LogLevel.Debug);
+ */
+
+ if (Game1.currentLocation is Farm)
+ {
+ Building building = ((Farm)Game1.currentLocation).getBuildingAt(new Vector2(x, y));
+ if (building != null)
+ {
+ return (CATEGORY.Buildings, building.buildingType.Value);
+ }
+ }
+
+ if (index != null)
+ {
+ switch (index)
+ {
+ case 1955:
+ case 41:
+ return (CATEGORY.Furnitures, "Mail Box");
+ case 1003:
+ return (CATEGORY.Furnitures, "Street lamp");
+ case 78:
+ return (CATEGORY.Furnitures, "Trash bin");
+ case 617:
+ return (CATEGORY.Furnitures, "Daily quest");
+ case 616:
+ return (CATEGORY.Furnitures, "Calender");
+ }
+
+ if (Game1.currentLocation is FarmHouse || Game1.currentLocation is IslandFarmHouse)
+ {
+ switch (index)
+ {
+ case 173:
+ return (CATEGORY.Furnitures, "Fridge");
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ return (CATEGORY.Furnitures, "Kitchen");
+ }
+ }
+
+ }
+
+ return (null, null);
+ }
+
+ public static (string? name, CATEGORY category) getTerrainFeatureAtTile(Netcode.NetRef terrain)
+ {
+ string? toReturn = null;
+ CATEGORY category = CATEGORY.Others;
+
+ if (terrain.Get() is HoeDirt)
+ {
+ category = CATEGORY.Crops;
+ HoeDirt dirt = (HoeDirt)terrain.Get();
+ if (dirt.crop != null)
+ {
+ string cropName = Game1.objectInformation[dirt.crop.indexOfHarvest.Value].Split('/')[0];
+ toReturn = $"{cropName}";
+
+ bool isWatered = dirt.state.Value == HoeDirt.watered;
+ bool isHarvestable = dirt.readyForHarvest();
+ bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer;
+
+ if (isWatered)
+ toReturn = "Watered " + toReturn;
+
+ if (isFertilized)
+ toReturn = "Fertilized " + toReturn;
+
+ if (isHarvestable)
+ toReturn = "Harvestable " + toReturn;
+ }
+ else
+ {
+ toReturn = "Soil";
+ bool isWatered = dirt.state.Value == HoeDirt.watered;
+ bool isFertilized = dirt.fertilizer.Value != HoeDirt.noFertilizer;
+
+ if (isWatered)
+ toReturn = "Watered " + toReturn;
+
+ if (isFertilized)
+ toReturn = "Fertilized " + toReturn;
+ }
+ }
+ else if (terrain.Get() is GiantCrop)
+ {
+ category = CATEGORY.Crops;
+ int whichCrop = ((GiantCrop)terrain.Get()).which.Value;
+ switch (whichCrop)
+ {
+ case 0:
+ toReturn = "Cauliflower";
+ break;
+ case 1:
+ toReturn = "Melon";
+ break;
+ case 2:
+ toReturn = "Pumpkin";
+ break;
+ }
+ }
+ else if (terrain.Get() is CosmeticPlant)
+ {
+ category = CATEGORY.Furnitures;
+ CosmeticPlant cosmeticPlant = (CosmeticPlant)terrain.Get();
+ toReturn = cosmeticPlant.textureName().ToLower();
+
+ if (toReturn.Contains("terrain"))
+ toReturn.Replace("terrain", "");
+
+ if (toReturn.Contains("feature"))
+ toReturn.Replace("feature", "");
+ }
+ else if (terrain.Get() is Flooring && MainClass.Config.ReadFlooring)
+ {
+ category = CATEGORY.Flooring;
+ Flooring flooring = (Flooring)terrain.Get();
+ bool isPathway = flooring.isPathway.Get();
+ bool isSteppingStone = flooring.isSteppingStone.Get();
+
+ toReturn = "Flooring";
+
+ if (isPathway)
+ toReturn = "Pathway";
+
+ if (isSteppingStone)
+ toReturn = "Stepping Stone";
+ }
+ else if (terrain.Get() is FruitTree)
+ {
+ category = CATEGORY.Trees;
+ toReturn = getFruitTree((FruitTree)terrain.Get());
+ }
+ else if (terrain.Get() is Grass)
+ {
+ category = CATEGORY.Debris;
+ toReturn = "Grass";
+ }
+ else if (terrain.Get() is Tree)
+ {
+ category = CATEGORY.Trees;
+ toReturn = getTree((Tree)terrain.Get());
+ }
+ else if (terrain.Get() is Quartz)
+ {
+ category = CATEGORY.MineItems;
+ toReturn = "Quartz";
+ }
+
+ return (toReturn, category);
+ }
+
+ public static string getFruitTree(FruitTree fruitTree)
+ {
+ int stage = fruitTree.growthStage.Value;
+ int fruitIndex = fruitTree.indexOfFruit.Get();
+
+ string toReturn = Game1.objectInformation[fruitIndex].Split('/')[0];
+
+ if (stage == 0)
+ toReturn = $"{toReturn} seed";
+ else if (stage == 1)
+ toReturn = $"{toReturn} sprout";
+ else if (stage == 2)
+ toReturn = $"{toReturn} sapling";
+ else if (stage == 3)
+ toReturn = $"{toReturn} bush";
+ else if (stage >= 4)
+ toReturn = $"{toReturn} tree";
+
+ if (fruitTree.fruitsOnTree.Value > 0)
+ toReturn = $"Harvestable {toReturn}";
+
+ return toReturn;
+ }
+
+ public static string getTree(Tree tree)
+ {
+ int treeType = tree.treeType.Value;
+ int treeStage = tree.growthStage.Value;
+ string treeName = "tree";
+ string seedName = "";
+
+ // Return with the name if it's one of the 3 special trees
+ switch (treeType)
+ {
+ case 4:
+ case 5:
+ return "Winter Tree";
+ case 6:
+ return "Palm Tree";
+ case 7:
+ return "Mushroom Tree";
+ }
+
+
+ if (treeType <= 3)
+ seedName = Game1.objectInformation[308 + treeType].Split('/')[0];
+ else if (treeType == 8)
+ seedName = Game1.objectInformation[292].Split('/')[0];
+
+ if (treeStage >= 1)
+ {
+ 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;
+ }
+
+ if (treeStage == 1)
+ treeName = $"{treeName} sprout";
+ else if (treeStage == 2)
+ treeName = $"{treeName} sapling";
+ else if (treeStage == 3 || treeStage == 4)
+ treeName = $"{treeName} bush";
+ else if (treeStage >= 5)
+ treeName = $"{treeName} tree";
+
+ return treeName;
+ }
+
+ return seedName;
+ }
+
+ #region Objects
+ public static (string? name, CATEGORY category) getObjectAtTile(int x, int y)
+ {
+ (string? name, CATEGORY category) toReturn = (null, CATEGORY.Others);
+
+ StardewValley.Object obj = Game1.currentLocation.getObjectAtTile(x, y);
+ int index = obj.ParentSheetIndex;
+ toReturn.name = obj.DisplayName;
+
+ // Get object names based on index
+ (string? name, CATEGORY category) correctNameAndCategory = getCorrectNameAndCategoryFromIndex(index);
+ if (correctNameAndCategory.name != null)
+ toReturn = correctNameAndCategory;
+
+ if (toReturn.name.ToLower().Equals("stone")) // Fix for `Busy stone`
+ toReturn.category = CATEGORY.Debris;
+
+ if (obj is Chest)
+ {
+ Chest chest = (Chest)obj;
+ toReturn = (chest.DisplayName, CATEGORY.Chests);
+ }
+
+ if (obj is Furniture)
+ toReturn.category = CATEGORY.Furnitures;
+
+ if (toReturn.category == CATEGORY.Others) // Fix for `Harvestable table` and `Busy nodes`
+ {
+ MachineState machineState = GetMachineState(obj);
+ if (machineState == MachineState.Ready)
+ toReturn.name = $"Harvestable {toReturn.name}";
+ else if (machineState == MachineState.Busy)
+ toReturn.name = $"Busy {toReturn.name}";
+ }
+ return toReturn;
+ }
+
+ private static MachineState GetMachineState(StardewValley.Object machine)
+ {
+ if (machine is CrabPot crabPot)
+ if (crabPot.bait.Value is not null && crabPot.heldObject.Value is null)
+ return MachineState.Busy;
+ return GetMachineState(machine.readyForHarvest.Value, machine.MinutesUntilReady, machine.heldObject.Value);
+ }
+
+ private static MachineState GetMachineState(bool readyForHarvest, int minutesUntilReady, StardewValley.Object? heldObject)
+ {
+ if (readyForHarvest || (heldObject is not null && minutesUntilReady <= 0))
+ return MachineState.Ready;
+ else if (minutesUntilReady > 0)
+ return MachineState.Busy;
+ else
+ return MachineState.Waiting;
+ }
+
+ private static (string? name, CATEGORY category) getCorrectNameAndCategoryFromIndex(int index)
+ {
+ switch (index)
+ {
+ case 313:
+ case 314:
+ case 315:
+ case 316:
+ case 317:
+ case 318:
+ case 452:
+ case 674:
+ case 675:
+ case 676:
+ case 677:
+ case 678:
+ case 679:
+ case 750:
+ case 784:
+ case 785:
+ case 786:
+ return ("Weed", CATEGORY.Debris);
+ case 792:
+ case 793:
+ case 794:
+ return ("Fertile weed", CATEGORY.Debris);
+ case 319:
+ case 320:
+ case 321:
+ return ("Ice crystal", CATEGORY.Debris);
+ case 75:
+ return ("Geode", CATEGORY.MineItems);
+ case 32:
+ case 34:
+ case 36:
+ case 38:
+ case 40:
+ case 42:
+ case 48:
+ case 50:
+ case 52:
+ case 54:
+ case 56:
+ case 58:
+ return ("Coloured stone", CATEGORY.Debris);
+ case 668:
+ case 670:
+ case 845:
+ case 846:
+ case 847:
+ return ("Mine stone", CATEGORY.MineItems);
+ case 818:
+ return ("Clay stone", CATEGORY.Debris);
+ case 816:
+ case 817:
+ return ("Fossil stone", CATEGORY.Debris);
+ case 118:
+ case 120:
+ case 122:
+ case 124:
+ return ("Barrel", CATEGORY.MineItems);
+ case 119:
+ case 121:
+ case 123:
+ case 125:
+ return ("Item box", CATEGORY.MineItems);
+ }
+
+ if (Game1.currentLocation is Mine or MineShaft)
+ {
+ switch (index)
+ {
+ case 76:
+ return ("Frozen geode", CATEGORY.MineItems);
+ case 77:
+ return ("Magma geode", CATEGORY.MineItems);
+ case 8:
+ case 66:
+ return ("Amethyst node", CATEGORY.MineItems);
+ case 14:
+ case 62:
+ return ("Aquamarine node", CATEGORY.MineItems);
+ case 843:
+ case 844:
+ return ("Cinder shard node", CATEGORY.MineItems);
+ case 2:
+ case 72:
+ return ("Diamond node", CATEGORY.MineItems);
+ case 12:
+ case 60:
+ return ("Emerald node", CATEGORY.MineItems);
+ case 44:
+ return ("Gem node", CATEGORY.MineItems);
+ case 6:
+ case 70:
+ return ("Jade node", CATEGORY.MineItems);
+ case 46:
+ return ("Mystic stone", CATEGORY.MineItems);
+ case 74:
+ return ("Prismatic node", CATEGORY.MineItems);
+ case 4:
+ case 64:
+ return ("Ruby node", CATEGORY.MineItems);
+ case 10:
+ case 68:
+ return ("Topaz node", CATEGORY.MineItems);
+ case 819:
+ return ("Omni geode node", CATEGORY.MineItems);
+ case 751:
+ case 849:
+ return ("Copper node", CATEGORY.MineItems);
+ case 764:
+ return ("Gold node", CATEGORY.MineItems);
+ case 765:
+ return ("Iridium node", CATEGORY.MineItems);
+ case 290:
+ case 850:
+ return ("Iron node", CATEGORY.MineItems);
+ }
+ }
+
+ return (null, CATEGORY.Others);
+ }
+ #endregion
+
+ public static bool isMineDownLadderAtTile(int x, int y)
+ {
+ try
+ {
+ if (Game1.currentLocation is Mine or MineShaft)
+ {
+ int? index = null;
+
+ if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
+ index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
+
+ if (index == 173 || index == 174)
+ return true;
+ }
+ }
+ catch (Exception) { }
+
+ return false;
+ }
+
+ public static bool isMineUpLadderAtTile(int x, int y)
+ {
+ try
+ {
+ if (Game1.currentLocation is Mine or MineShaft)
+ {
+ int? index = null;
+
+ if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
+ index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
+
+ if (index == 115)
+ return true;
+ }
+ }
+ catch (Exception) { }
+
+ return false;
+ }
+
+ public static bool isElevatorAtTile(int x, int y)
+ {
+ try
+ {
+ if (Game1.currentLocation is Mine or MineShaft)
+ {
+ int? index = null;
+
+ if (Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y] != null)
+ index = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[x, y].TileIndex;
+
+ if (index == 112)
+ return true;
+ }
+ }
+ catch (Exception) { }
+
+ return false;
+ }
+
+ public static string? getDoorAtTile(int x, int y)
+ {
+ Point tilePoint = new Point(x, y);
+ StardewValley.Network.NetPointDictionary doorList = Game1.currentLocation.doors;
+
+ for (int i = 0; i < doorList.Count(); i++)
+ {
+ if (doorList.ContainsKey(tilePoint))
+ {
+ string? doorName;
+ doorList.TryGetValue(tilePoint, out doorName);
+
+ if (doorName != null)
+ return $"{doorName} door";
+ else
+ return "door";
+ }
+ }
+
+ return null;
+ }
+
+ public static string? getResourceClumpAtTile(int x, int y)
+ {
+ if (Game1.currentLocation is Woods)
+ return getStumpsInWoods(x, y);
+
+ for (int i = 0; i < Game1.currentLocation.resourceClumps.Count; i++)
+ {
+ if (Game1.currentLocation.resourceClumps[i].occupiesTile(x, y))
+ {
+ int index = Game1.currentLocation.resourceClumps[i].parentSheetIndex.Value;
+
+ switch (index)
+ {
+ case 600:
+ return "Large Stump";
+ case 602:
+ return "Hollow Log";
+ case 622:
+ return "Meteorite";
+ case 752:
+ case 754:
+ case 756:
+ case 758:
+ return "Mine Rock";
+ case 672:
+ return "Boulder";
+ default:
+ return "Unknown";
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static string? getStumpsInWoods(int x, int y)
+ {
+ if (Game1.currentLocation is not Woods)
+ return null;
+
+ if ((x == 8 || x == 9) && y == 7)
+ {
+ return "Old Master Cannoli";
+ }
+ Netcode.NetObjectList stumps = ((Woods)Game1.currentLocation).stumps;
+ for (int i = 0; i < stumps.Count; i++)
+ {
+ if (stumps[i].occupiesTile(x, y))
+ {
+ return "Large Stump";
+ }
+ }
+ return null;
+ }
+
+ public static string? getParrotPerchAtTile(int x, int y)
+ {
+ if (Game1.currentLocation is not IslandLocation islandLocation)
+ return null;
+
+ foreach (var perch in islandLocation.parrotUpgradePerches)
+ {
+ if (!perch.tilePosition.Value.Equals(new Point(x, y)))
+ continue;
+
+ string toSpeak = $"Parrot required nuts {perch.requiredNuts.Value}";
+
+ if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Complete)
+ return $"Request Completed";
+ else if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Idle)
+ return toSpeak;
+ else if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.StartBuilding)
+ return "Parrots started building request";
+ else if (perch.currentState == StardewValley.BellsAndWhistles.ParrotUpgradePerch.UpgradeState.Building)
+ return "Parrots building request";
+ else
+ return toSpeak;
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/stardew-access/HarmonyPatches.cs b/stardew-access/HarmonyPatches.cs
index 96e0da4..ae60975 100644
--- a/stardew-access/HarmonyPatches.cs
+++ b/stardew-access/HarmonyPatches.cs
@@ -158,12 +158,7 @@ namespace stardew_access
harmony.Patch(
original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.receiveKeyPress), new Type[] { typeof(Keys) }),
- prefix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuKeyPressPatch))
- );
-
- harmony.Patch(
- original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }),
- postfix: new HarmonyMethod(typeof(MuseumMenuPatches), nameof(MuseumMenuPatches.MuseumMenuPatch))
+ prefix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.MuseumMenuKeyPressPatch))
);
harmony.Patch(
@@ -195,11 +190,6 @@ namespace stardew_access
original: AccessTools.Method(typeof(ItemListMenu), nameof(ItemListMenu.draw), new Type[] { typeof(SpriteBatch) }),
postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.ItemListMenuPatch))
);
-
- harmony.Patch(
- original: AccessTools.Method(typeof(FieldOfficeMenu), nameof(FieldOfficeMenu.draw), new Type[] { typeof(SpriteBatch) }),
- postfix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.FieldOfficeMenuPatch))
- );
#endregion
#region Quest Patches
@@ -251,6 +241,18 @@ namespace stardew_access
#endregion
+ #region Donation Menus
+ harmony.Patch(
+ original: AccessTools.Method(typeof(MuseumMenu), nameof(MuseumMenu.draw), new Type[] { typeof(SpriteBatch) }),
+ postfix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.MuseumMenuPatch))
+ );
+
+ harmony.Patch(
+ original: AccessTools.Method(typeof(FieldOfficeMenu), nameof(FieldOfficeMenu.draw), new Type[] { typeof(SpriteBatch) }),
+ postfix: new HarmonyMethod(typeof(DonationMenuPatches), nameof(DonationMenuPatches.FieldOfficeMenuPatch))
+ );
+ #endregion
+
harmony.Patch(
original: AccessTools.Method(typeof(Game1), nameof(Game1.playSound)),
prefix: new HarmonyMethod(typeof(MenuPatches), nameof(MenuPatches.PlaySoundPatch))
diff --git a/stardew-access/Patches/DialoguePatches.cs b/stardew-access/Patches/DialoguePatches.cs
index 1228cb8..b59bbef 100644
--- a/stardew-access/Patches/DialoguePatches.cs
+++ b/stardew-access/Patches/DialoguePatches.cs
@@ -2,7 +2,6 @@
using StardewModdingAPI;
using StardewValley;
using StardewValley.Menus;
-using System.Text;
namespace stardew_access.Patches
{
@@ -197,6 +196,8 @@ namespace stardew_access.Patches
return;
else if (Game1.activeClickableMenu is FieldOfficeMenu)
return;
+ else if (Game1.activeClickableMenu is MuseumMenu)
+ return;
#endregion
string toSpeak = " ";
diff --git a/stardew-access/Patches/MuseumMenuPatches.cs b/stardew-access/Patches/DonationMenuPatches.cs
similarity index 71%
rename from stardew-access/Patches/MuseumMenuPatches.cs
rename to stardew-access/Patches/DonationMenuPatches.cs
index 6a06c65..ce244ac 100644
--- a/stardew-access/Patches/MuseumMenuPatches.cs
+++ b/stardew-access/Patches/DonationMenuPatches.cs
@@ -1,15 +1,15 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
-using StardewModdingAPI;
using StardewValley;
using StardewValley.Locations;
using StardewValley.Menus;
namespace stardew_access.Patches
{
- internal class MuseumMenuPatches
+ internal class DonationMenuPatches
{
- private static string museumQueryKey = " ";
+ internal static string museumQueryKey = " ";
+ internal static string fieldOfficeMenuQuery = " ";
private static bool isMoving = false;
private static (int x, int y)[] donationTiles =
{
@@ -29,6 +29,8 @@ namespace stardew_access.Patches
(42,16),(43,16),(44,16),(45,16),(46,16),(47,16),
};
+ #region Museum
+
internal static bool MuseumMenuKeyPressPatch()
{
try
@@ -275,5 +277,134 @@ namespace stardew_access.Patches
}
}
#endregion
+
+ #endregion
+
+ #region Field Office
+
+ internal static void FieldOfficeMenuPatch(FieldOfficeMenu __instance)
+ {
+ try
+ {
+ int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
+ string toSpeak = " ";
+
+ if (__instance.trashCan != null && __instance.trashCan.containsPoint(x, y))
+ {
+ toSpeak = "Trashcan";
+ }
+ else if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
+ {
+ toSpeak = "ok button";
+ }
+ else if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
+ {
+ toSpeak = "drop item";
+ }
+ else
+ {
+ for (int i = 0; i < __instance.inventory.inventory.Count; i++)
+ {
+ if (!__instance.inventory.inventory[i].containsPoint(x, y))
+ continue;
+
+ if (__instance.inventory.actualInventory[i] == null)
+ toSpeak = "Empty slot";
+ else
+ toSpeak = $"{__instance.inventory.actualInventory[i].Stack} {__instance.inventory.actualInventory[i].DisplayName}";
+
+ if (fieldOfficeMenuQuery != $"{toSpeak}:{i}")
+ {
+ fieldOfficeMenuQuery = $"{toSpeak}:{i}";
+ MainClass.ScreenReader.Say(toSpeak, true);
+ }
+
+ return;
+ }
+
+ for (int i = 0; i < __instance.pieceHolders.Count; i++)
+ {
+ if (!__instance.pieceHolders[i].containsPoint(x, y))
+ continue;
+
+ if (__instance.pieceHolders[i].item == null)
+ toSpeak = i switch
+ {
+ 0 => "Center skeleton slot",
+ 1 => "Center skeleton slot",
+ 2 => "Center skeleton slot",
+ 3 => "Center skeleton slot",
+ 4 => "Center skeleton slot",
+ 5 => "Center skeleton slot",
+ 6 => "Snake slot",
+ 7 => "Snake slot",
+ 8 => "Snake slot",
+ 9 => "Bat slot",
+ 10 => "Frog slot",
+ _ => "Donation slot"
+ };
+ else
+ toSpeak = $"Slot {i + 1} finished: {__instance.pieceHolders[i].item.DisplayName}";
+
+ if (__instance.heldItem != null && __instance.pieceHolders[i].item == null)
+ {
+ int highlight = getPieceIndexForDonationItem(__instance.heldItem.ParentSheetIndex);
+ if (highlight != -1 && highlight == i)
+ toSpeak += "Donatable ";
+ }
+
+ if (fieldOfficeMenuQuery != $"{toSpeak}:{i}")
+ {
+ fieldOfficeMenuQuery = $"{toSpeak}:{i}";
+ MainClass.ScreenReader.Say(toSpeak, true);
+ }
+
+ return;
+ }
+ }
+
+ if (fieldOfficeMenuQuery != toSpeak)
+ {
+ fieldOfficeMenuQuery = toSpeak;
+ MainClass.ScreenReader.Say(toSpeak, true);
+
+ if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
+ Game1.playSound("drop_item");
+ }
+ }
+ catch (System.Exception e)
+ {
+ MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
+ }
+ }
+
+ internal static int getPieceIndexForDonationItem(int itemIndex)
+ {
+ switch (itemIndex)
+ {
+ case 820:
+ return 5;
+ case 821:
+ return 4;
+ case 822:
+ return 3;
+ case 823:
+ return 0;
+ case 824:
+ return 1;
+ case 825:
+ return 8;
+ case 826:
+ return 7;
+ case 827:
+ return 9;
+ case 828:
+ return 10;
+ default:
+ return -1;
+ }
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/stardew-access/Patches/MenuPatches.cs b/stardew-access/Patches/MenuPatches.cs
index 33d0581..362c78b 100644
--- a/stardew-access/Patches/MenuPatches.cs
+++ b/stardew-access/Patches/MenuPatches.cs
@@ -20,130 +20,6 @@ namespace stardew_access.Patches
internal static string forgeMenuQuery = " ";
internal static string itemListMenuQuery = " ";
public static Vector2? prevTile = null;
- private static string fieldOfficeMenuQuery = " ";
-
- internal static void FieldOfficeMenuPatch(FieldOfficeMenu __instance)
- {
- try
- {
- int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
- string toSpeak = " ";
-
- if (__instance.trashCan != null && __instance.trashCan.containsPoint(x, y))
- {
- toSpeak = "Trashcan";
- }
- else if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
- {
- toSpeak = "ok button";
- }
- else if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
- {
- toSpeak = "drop item";
- }
- else
- {
- for (int i = 0; i < __instance.inventory.inventory.Count; i++)
- {
- if (!__instance.inventory.inventory[i].containsPoint(x, y))
- continue;
-
- if (__instance.inventory.actualInventory[i] == null)
- toSpeak = "Empty slot";
- else
- toSpeak = $"{__instance.inventory.actualInventory[i].Stack} {__instance.inventory.actualInventory[i].DisplayName}";
-
- if (fieldOfficeMenuQuery != $"{toSpeak}:{i}")
- {
- fieldOfficeMenuQuery = $"{toSpeak}:{i}";
- MainClass.ScreenReader.Say(toSpeak, true);
- }
-
- return;
- }
-
- for (int i = 0; i < __instance.pieceHolders.Count; i++)
- {
- if (!__instance.pieceHolders[i].containsPoint(x, y))
- continue;
-
- if (__instance.pieceHolders[i].item == null)
- toSpeak = i switch
- {
- 0 => "Center skeleton slot",
- 1 => "Center skeleton slot",
- 2 => "Center skeleton slot",
- 3 => "Center skeleton slot",
- 4 => "Center skeleton slot",
- 5 => "Center skeleton slot",
- 6 => "Snake slot",
- 7 => "Snake slot",
- 8 => "Snake slot",
- 9 => "Bat slot",
- 10 => "Frog slot",
- _ => "Donation slot"
- };
- else
- toSpeak = $"Slot {i + 1} finished: {__instance.pieceHolders[i].item.DisplayName}";
-
- if (__instance.heldItem != null && __instance.pieceHolders[i].item == null)
- {
- int highlight = getPieceIndexForDonationItem(__instance.heldItem.ParentSheetIndex);
- if (highlight != -1 && highlight == i)
- toSpeak += "Donatable ";
- }
-
- if (fieldOfficeMenuQuery != $"{toSpeak}:{i}")
- {
- fieldOfficeMenuQuery = $"{toSpeak}:{i}";
- MainClass.ScreenReader.Say(toSpeak, true);
- }
-
- return;
- }
- }
-
- if (fieldOfficeMenuQuery != toSpeak)
- {
- fieldOfficeMenuQuery = toSpeak;
- MainClass.ScreenReader.Say(toSpeak, true);
-
- if (__instance.dropItemInvisibleButton != null && __instance.dropItemInvisibleButton.containsPoint(x, y))
- Game1.playSound("drop_item");
- }
- }
- catch (System.Exception e)
- {
- MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
- }
- }
-
- internal static int getPieceIndexForDonationItem(int itemIndex)
- {
- switch (itemIndex)
- {
- case 820:
- return 5;
- case 821:
- return 4;
- case 822:
- return 3;
- case 823:
- return 0;
- case 824:
- return 1;
- case 825:
- return 8;
- case 826:
- return 7;
- case 827:
- return 9;
- case 828:
- return 10;
- default:
- return -1;
- }
- }
internal static void ItemListMenuPatch(ItemListMenu __instance, string ___title, int ___currentTab, int ___totalValueOfItems, List- ___itemsToList)
{
@@ -553,7 +429,7 @@ namespace stardew_access.Patches
if (cueName == "grassyStep" || cueName == "sandyStep" || cueName == "snowyStep" || cueName == "stoneStep" || cueName == "thudStep" || cueName == "woodyStep")
{
Vector2 nextTile = CurrentPlayer.getNextTile();
- if (ReadTile.isCollidingAtTile((int)nextTile.X, (int)nextTile.Y))
+ if (TileInfo.isCollidingAtTile((int)nextTile.X, (int)nextTile.Y))
{
if (prevTile != nextTile)
{
@@ -955,7 +831,11 @@ namespace stardew_access.Patches
}
else if (menu is FieldOfficeMenu)
{
- fieldOfficeMenuQuery = " ";
+ DonationMenuPatches.fieldOfficeMenuQuery = " ";
+ }
+ else if (menu is MuseumMenu)
+ {
+ DonationMenuPatches.museumQueryKey = " ";
}
else if (menu is PondQueryMenu)
{