├── .gitattributes
├── README.md
├── GloryOfEfficiency
├── assets
│ ├── icon_ladder.png
│ ├── icon_monster.png
│ └── icon_pickaxe.png
├── packages.config
├── ModCheckers
│ └── ModChecker.cs
├── OptionsElements
│ ├── EmptyLabel.cs
│ ├── MenuTab.cs
│ ├── LabelComponent.cs
│ ├── OptionsElementWithLabel.cs
│ ├── ColorBox.cs
│ ├── ModifiedCheckBox.cs
│ ├── ButtonWithLabel.cs
│ ├── ModifiedSlider.cs
│ ├── ModifiedClickListener.cs
│ └── ModifiedInputListener.cs
├── manifest.json
├── Utils
│ ├── CustomAnimalConfigHolder.cs
│ ├── Logger.cs
│ └── ConfigHolder.cs
├── Configs
│ ├── CustomAnimalTool.cs
│ └── ConfigCustomAnimalTool.cs
├── EventHandler
│ ├── MenuEvents.cs
│ ├── SaveEvents.cs
│ ├── EventHolder.cs
│ ├── InputEvents.cs
│ ├── GraphicsEvents.cs
│ ├── ArtifactSpotDigger.cs
│ └── UpdateEvents.cs
├── Automation
│ ├── WateringCanRefiller.cs
│ ├── TrashCanScavenger.cs
│ ├── MailAutomation.cs
│ ├── InventoryAutomation.cs
│ ├── CollectibleCollector.cs
│ ├── FoodAutomation.cs
│ ├── MachineOperator.cs
│ ├── FarmCleaner.cs
│ ├── FlowerColorUnifier.cs
│ └── AnimalAutomation.cs
├── Huds
│ ├── PausedHud.cs
│ ├── FpsCounter.cs
│ ├── ShippingEstimationInfoBox.cs
│ ├── MineHud.cs
│ ├── MineIcons.cs
│ ├── GiftInformationTooltip.cs
│ └── FishInformationHud.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Core
│ ├── InstanceHolder.cs
│ ├── ConfigLimitation.cs
│ ├── ModEntry.cs
│ └── Config.cs
├── GloryOfEfficiency.csproj
├── Misc
│ └── IdlePause.cs
├── Harmony
│ └── HarmonyPatcher.cs
├── i18n
│ ├── zh.json
│ ├── de.json
│ ├── es.json
│ ├── ja.json
│ ├── ko.json
│ ├── ru.json
│ ├── default.json
│ └── pt.json
└── Menus
│ └── RegisterFlowerMenu.cs
├── global.json
├── testplan.txt
├── GloryOfEfficiency.sln
└── .gitignore
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nexus page (You can download mod releases there)
2 | https://www.nexusmods.com/stardewvalley/mods/25996
3 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/assets/icon_ladder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hackswell/GloryOfEfficiency/HEAD/GloryOfEfficiency/assets/icon_ladder.png
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "6.0.0",
4 | "rollForward": "latestMajor",
5 | "allowPrerelease": false
6 | }
7 | }
--------------------------------------------------------------------------------
/GloryOfEfficiency/assets/icon_monster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hackswell/GloryOfEfficiency/HEAD/GloryOfEfficiency/assets/icon_monster.png
--------------------------------------------------------------------------------
/GloryOfEfficiency/assets/icon_pickaxe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hackswell/GloryOfEfficiency/HEAD/GloryOfEfficiency/assets/icon_pickaxe.png
--------------------------------------------------------------------------------
/GloryOfEfficiency/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/ModCheckers/ModChecker.cs:
--------------------------------------------------------------------------------
1 | using StardewModdingAPI;
2 |
3 | namespace GloryOfEfficiency.ModCheckers
4 | {
5 | public class ModChecker
6 | {
7 | public static bool IsCoGLoaded(IModHelper helper) => helper.ModRegistry.IsLoaded("punyo.CasksOnGround");
8 | public static bool IsCaLoaded(IModHelper helper) => helper.ModRegistry.IsLoaded("CasksAnywhere");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/EmptyLabel.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework.Graphics;
2 | using StardewValley.Menus;
3 |
4 | namespace GloryOfEfficiency.OptionsElements
5 | {
6 | internal class EmptyLabel : LabelComponent
7 | {
8 | public EmptyLabel() : base("") { }
9 | public override void draw(SpriteBatch b, int slotX, int slotY, IClickableMenu context = null) {}
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "Author": "hackswell",
3 | "Description": "Adds many useful functions to make gameplay more efficient. Forked from pomepome/JoysOfEfficiency on GitHub",
4 | "EntryDll": "GloryOfEfficiency.dll",
5 | "MinimumApiVersion": "4.0",
6 | "Name": "GloryOfEfficiency",
7 | "UniqueID": "hackswell.GloryOfEfficiency",
8 | "UpdateKeys": [ "Nexus:25996" ],
9 | "Version": "1.0.1"
10 | }
11 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Utils/CustomAnimalConfigHolder.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Configs;
2 |
3 | namespace GloryOfEfficiency.Utils
4 | {
5 | internal class CustomAnimalConfigHolder : ConfigHolder
6 | {
7 | public CustomAnimalConfigHolder(string filePath) : base(filePath)
8 | {
9 | }
10 |
11 | protected override ConfigCustomAnimalTool GetNewInstance()
12 | {
13 | return new ConfigCustomAnimalTool();
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Configs/CustomAnimalTool.cs:
--------------------------------------------------------------------------------
1 | namespace GloryOfEfficiency.Configs
2 | {
3 | class CustomAnimalTool
4 | {
5 | public string Name { get; set; }
6 | public ToolType ToolType { get; set; }
7 |
8 | public CustomAnimalTool(string name, ToolType toolType)
9 | {
10 | Name = name;
11 | ToolType = toolType;
12 | }
13 | }
14 |
15 | public enum ToolType
16 | {
17 | None,
18 | Bucket,
19 | Shears
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/MenuTab.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using StardewValley.Menus;
3 |
4 | namespace GloryOfEfficiency.OptionsElements
5 | {
6 | internal class MenuTab
7 | {
8 | private readonly List _optionsElements = new List();
9 |
10 | public void AddOptionsElement(OptionsElement element)
11 | {
12 | _optionsElements.Add(element);
13 | }
14 |
15 | public List GetElements()
16 | {
17 | return new List(_optionsElements);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/LabelComponent.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 |
6 | namespace GloryOfEfficiency.OptionsElements
7 | {
8 | internal class LabelComponent : OptionsElement
9 | {
10 | public LabelComponent(string label) : base(label, -1, -1, 9 * Game1.pixelZoom, 9 * Game1.pixelZoom, 0) { }
11 |
12 | public override void draw(SpriteBatch b, int slotX, int slotY, IClickableMenu context = null)
13 | {
14 | Utility.drawTextWithShadow(b, $" {label}", Game1.dialogueFont, new Vector2(slotX, slotY), Color.Black);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/OptionsElementWithLabel.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Utils;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewValley.Menus;
4 |
5 | namespace GloryOfEfficiency.OptionsElements
6 | {
7 | public abstract class OptionsElementWithLabel : OptionsElement
8 | {
9 | protected OptionsElementWithLabel(string label, int x, int y, int width, int height, int whichOption = -1)
10 | : base(label, x, y, width, height, whichOption) { }
11 |
12 | private int GetOffsetLabel()
13 | {
14 | return Util.IsAndroid() ? bounds.Width + 8 : 0;
15 | }
16 |
17 | public override void draw(SpriteBatch b, int slotX, int slotY, IClickableMenu context = null)
18 | {
19 | base.draw(b, slotX + GetOffsetLabel(), slotY, context);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/EventHandler/MenuEvents.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Automation;
2 | using GloryOfEfficiency.Core;
3 | using StardewModdingAPI.Events;
4 | using StardewValley.Menus;
5 |
6 | namespace GloryOfEfficiency.EventHandler
7 | {
8 | internal class MenuEvents
9 | {
10 | private static Config Conf => InstanceHolder.Config;
11 | public void OnMenuChanged(object sender, MenuChangedEventArgs args)
12 | {
13 | if (Conf.AutoLootTreasures && args.NewMenu is ItemGrabMenu menu)
14 | {
15 | //Opened ItemGrabMenu
16 | InventoryAutomation.LootAllAcceptableItems(menu);
17 | }
18 |
19 | if (Conf.CollectLetterAttachmentsAndQuests && args.NewMenu is LetterViewerMenu letter)
20 | {
21 | MailAutomation.CollectMailAttachmentsAndQuests(letter);
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/WateringCanRefiller.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Core;
2 | using GloryOfEfficiency.Utils;
3 | using StardewValley;
4 | using StardewValley.Tools;
5 |
6 | namespace GloryOfEfficiency.Automation
7 | {
8 | internal class WateringCanRefiller
9 | {
10 | private static Config Config => InstanceHolder.Config;
11 | public static void RefillWateringCan()
12 | {
13 | WateringCan can = Util.FindToolFromInventory(Config.FindCanFromInventory);
14 | if (can == null || can.WaterLeft >= can.waterCanMax ||
15 | !Util.IsThereAnyWaterNear(Game1.player.currentLocation, Game1.player.Tile))
16 | {
17 | return;
18 | }
19 | can.WaterLeft = can.waterCanMax;
20 | Game1.playSound("slosh");
21 | DelayedAction.playSoundAfterDelay("glug", 250);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Utils/Logger.cs:
--------------------------------------------------------------------------------
1 | using StardewModdingAPI;
2 |
3 | namespace GloryOfEfficiency.Utils
4 | {
5 | public class Logger
6 | {
7 | public static IMonitor Monitor
8 | {
9 | get; private set;
10 | }
11 |
12 | public static void Init(IMonitor monitor)
13 | {
14 | Monitor = monitor;
15 | }
16 |
17 | private string Name { get; }
18 | public Logger(string loggerName)
19 | {
20 | Name = loggerName;
21 | }
22 |
23 | public void Log(string text, LogLevel level = LogLevel.Trace)
24 | {
25 | Monitor.Log($"[{Name}]{text}", level);
26 | }
27 |
28 | public void Info(string text, LogLevel level = LogLevel.Info)
29 | {
30 | Monitor.Log($"[{Name}]{text}", level);
31 | }
32 |
33 | public void Error(string text)
34 | {
35 | Log(text, LogLevel.Error);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/EventHandler/SaveEvents.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GloryOfEfficiency.Automation;
3 | using GloryOfEfficiency.Core;
4 | using GloryOfEfficiency.Misc;
5 | using StardewModdingAPI;
6 |
7 | namespace GloryOfEfficiency.EventHandler
8 | {
9 | internal class SaveEvents
10 | {
11 | private static Config Conf => InstanceHolder.Config;
12 |
13 | public void OnBeforeSave(object sender, EventArgs args)
14 | {
15 | if (!Context.IsWorldReady || !Conf.AutoAnimalDoor)
16 | {
17 | return;
18 | }
19 | AnimalAutomation.LetAnimalsInHome();
20 | AnimalAutomation.AutoCloseAnimalDoor();
21 | }
22 |
23 | public void OnDayStarted(object sender, EventArgs args)
24 | {
25 | if (!Context.IsWorldReady || !Conf.AutoAnimalDoor)
26 | {
27 | return;
28 | }
29 | AnimalAutomation.AutoOpenAnimalDoor();
30 | UpdateEvents.DayEnded = false;
31 | IdlePause.OnDataLoaded();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Huds/PausedHud.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Core;
2 | using GloryOfEfficiency.Utils;
3 | using Microsoft.Xna.Framework;
4 | using Microsoft.Xna.Framework.Graphics;
5 | using StardewModdingAPI;
6 | using StardewValley;
7 |
8 | namespace GloryOfEfficiency.Huds
9 | {
10 | internal class PausedHud
11 | {
12 | private static ITranslationHelper Translation => InstanceHolder.Translation;
13 | public static void DrawPausedHud()
14 | {
15 | SpriteFont font = Game1.dialogueFont;
16 | string text = Translation.Get("hud.paused");
17 | Vector2 stringSize = font.MeasureString(text);
18 | int x = InstanceHolder.Config.PauseNotificationX;
19 | int y = InstanceHolder.Config.PauseNotificationY;
20 | int width = 16 + (int)stringSize.X + 16;
21 | int height = 16 + (int)stringSize.Y + 16;
22 |
23 | Util.DrawWindow(x, y, width, height);
24 | Utility.drawTextWithShadow(Game1.spriteBatch, text, font, new Vector2(x + 16, y + 16 + 8), Color.Black);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
5 | // アセンブリに関連付けられている情報を変更するには、
6 | // これらの属性値を変更してください。
7 | [assembly: AssemblyTitle("GloryOfEfficiency")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("GloryOfEfficiency")]
12 | [assembly: AssemblyCopyright("Copyright yakminepunyo© 2018, Copyright Hackswell© 2024")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから
17 | // 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、
18 | // その型の ComVisible 属性を true に設定してください。
19 | [assembly: ComVisible(false)]
20 |
21 | // このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります
22 | [assembly: Guid("0302444c-4190-4c5d-a873-a1f80267961a")]
23 |
24 | // アセンブリのバージョン情報は次の 4 つの値で構成されています:
25 | //
26 | // メジャー バージョン
27 | // マイナー バージョン
28 | // ビルド番号
29 | // Revision
30 | //
31 | // すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます
32 | // 以下のように '*' を使用します:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/EventHandler/EventHolder.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Huds;
2 | using StardewModdingAPI.Events;
3 |
4 | namespace GloryOfEfficiency.EventHandler
5 | {
6 | internal class EventHolder
7 | {
8 | public static UpdateEvents Update { get;} = new UpdateEvents();
9 | public static GraphicsEvents Graphics { get; } = new GraphicsEvents();
10 | public static SaveEvents Save { get; } = new SaveEvents();
11 | public static MenuEvents Menu { get; } = new MenuEvents();
12 | public static InputEvents Input { get; } = new InputEvents();
13 |
14 | public static void RegisterEvents(IModEvents events)
15 | {
16 | events.Input.ButtonPressed += Input.OnButtonPressed;
17 |
18 | events.GameLoop.UpdateTicked += Update.OnGameUpdateEvent;
19 | events.GameLoop.Saving += Save.OnBeforeSave;
20 | events.GameLoop.DayStarted += Save.OnDayStarted;
21 |
22 | events.Display.RenderingHud += Graphics.OnRenderHud;
23 | events.Display.RenderedActiveMenu += Graphics.OnPostRenderGui;
24 | events.Display.MenuChanged += Menu.OnMenuChanged;
25 | events.Display.RenderingHud += FpsCounter.OnHudDraw;
26 | events.Display.RenderedHud += FpsCounter.PostHudDraw;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Utils/ConfigHolder.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Text.Json;
3 |
4 | namespace GloryOfEfficiency.Utils
5 | {
6 | public abstract class ConfigHolder
7 | {
8 | private readonly string _configFileName;
9 |
10 | public T Entry { get; private set; }
11 |
12 | private static Logger Logger = new Logger("ConfigHolder");
13 |
14 | protected ConfigHolder(string filePath)
15 | {
16 | _configFileName = filePath;
17 | Load();
18 | Save();
19 | }
20 |
21 | protected void Load()
22 | {
23 | if (!File.Exists(_configFileName))
24 | {
25 | Entry = GetNewInstance();
26 | return;
27 | }
28 |
29 | Logger.Log("Loaded "+ _configFileName);
30 |
31 | string jsonContent = File.ReadAllText(_configFileName);
32 | Entry = JsonSerializer.Deserialize(jsonContent);
33 | }
34 |
35 | public void Save()
36 | {
37 | string jsonContent = JsonSerializer.Serialize(Entry);
38 | File.WriteAllText(_configFileName, jsonContent);
39 | Logger.Log("Saved " + Path.GetFullPath(_configFileName));
40 | }
41 |
42 | protected abstract T GetNewInstance();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/testplan.txt:
--------------------------------------------------------------------------------
1 | *** APPARENTLY WORKING ***
2 | --------------------------
3 | +[Fence Gate Automation]
4 |
5 | +[Farm Cleaner]
6 | +[Watering Can Refiller]
7 | +[Harvest Automation]
8 | +Autofill watering can
9 | +Water nearby crops
10 | +Harvest nearby crops
11 | +Does NOT harvest crops on exclusion list
12 | +Destroy dead crops
13 | +Shake trees / fruit trees
14 |
15 | +[MachineOperator]
16 | +Auto pull
17 | +Auto push
18 |
19 | +[Animal Automation]
20 | +Pet nearby animals
21 | +Pet nearby pets
22 | +Auto shear/milk
23 |
24 | +[Gift Information Tooltip]
25 |
26 | +Balanced Mode [every 1s for balanced, super fast otherwise]
27 |
28 | +[Mine HUD]
29 |
30 | +[Trash can Scavenger]
31 |
32 | +[Collectible Collector]
33 | +Seed Spots auto digger
34 | +Artifact auto digger
35 | +Collect nearby collectibles
36 |
37 | +[Shipping Estimator]
38 |
39 | O[Fishing]
40 | OFishing Probabilities Box [O Farm, +Mines, O Submarine, O Witch's Swamp, +EverywhereElse]
41 | +Fish Info HUD
42 | Autofisher
43 | Auto-reeling
44 | AFK
45 | Treasure
46 |
47 | *** UNTESTED ***
48 | ----------------
49 |
50 | [Idle Pause] -- UNTESTED
51 |
52 | [Food Automation] -- UNTESTED
53 | Auto eat
54 |
55 | [Inventory Automation] -- UNTESTED
56 | Treasure Auto-grab
57 |
58 | [Flower Color Unifier] -- UNTESTED
59 | Unify Flower Colors
60 |
61 | [Mail Automation] -- UNTESTED
62 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Huds/FpsCounter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GloryOfEfficiency.Core;
3 | using GloryOfEfficiency.Utils;
4 | using StardewModdingAPI.Events;
5 | using StardewValley;
6 |
7 | namespace GloryOfEfficiency.Huds
8 | {
9 | internal class FpsCounter
10 | {
11 | private static double _fps;
12 |
13 | private static int _lastMilliseconds = Environment.TickCount;
14 |
15 | private static int _frameCounter;
16 |
17 | public static void OnHudDraw(object sender, RenderingHudEventArgs args)
18 | {
19 | _frameCounter++;
20 | if (_frameCounter != 50)
21 | {
22 | return;
23 | }
24 |
25 | int current = Environment.TickCount;
26 | int delta = current - _lastMilliseconds;
27 | _fps = (1000.0 * _frameCounter / delta);
28 | _frameCounter = 0;
29 | _lastMilliseconds = Environment.TickCount;
30 | }
31 |
32 | public static void PostHudDraw(object sender, RenderedHudEventArgs args)
33 | {
34 | if (ModEntry.DebugMode)
35 | {
36 | Draw();
37 | }
38 | }
39 |
40 | public static void Draw()
41 | {
42 | string fpsString = $"{_fps:f1}fps";
43 | Util.DrawSimpleTextbox(Game1.spriteBatch, fpsString, 0, 0, Game1.smallFont, null);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/EventHandler/InputEvents.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Automation;
2 | using GloryOfEfficiency.Core;
3 | using GloryOfEfficiency.Menus;
4 | using StardewModdingAPI;
5 | using StardewModdingAPI.Events;
6 | using StardewValley;
7 |
8 | namespace GloryOfEfficiency.EventHandler
9 | {
10 | internal class InputEvents
11 | {
12 | private static Config Conf => InstanceHolder.Config;
13 | public void OnButtonPressed(object sender, ButtonPressedEventArgs args)
14 | {
15 | if (!Context.IsWorldReady)
16 | {
17 | return;
18 | }
19 | if (args.Button == Conf.ToggleAfkFishing)
20 | {
21 | AutoFisher.ToggleAfkFishing();
22 | }
23 | if (!Context.IsPlayerFree || Game1.activeClickableMenu != null)
24 | {
25 | return;
26 | }
27 | if (args.Button == Conf.ButtonShowMenu)
28 | {
29 | //Open Up Menu
30 | GoEMenu.OpenMenu();
31 | }
32 | else if (args.Button == Conf.ButtonToggleBlackList)
33 | {
34 | HarvestAutomation.ToggleBlacklistUnderCursor();
35 | }
36 | else if (args.Button == Conf.ButtonToggleFlowerColorUnification)
37 | {
38 | FlowerColorUnifier.ToggleFlowerColorUnification();
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/TrashCanScavenger.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Core;
2 | using Microsoft.Xna.Framework;
3 | using StardewValley;
4 | using StardewValley.Locations;
5 | using xTile.Layers;
6 |
7 | namespace GloryOfEfficiency.Automation
8 | {
9 | internal class TrashCanScavenger
10 | {
11 | private static Config Config => InstanceHolder.Config;
12 |
13 | public static void ScavengeTrashCan()
14 | {
15 | if (!(Game1.currentLocation is Town town))
16 | {
17 | return;
18 | }
19 |
20 | Farmer player = Game1.player;
21 | GameLocation currLocation = Game1.currentLocation;
22 | int radius = InstanceHolder.Config.BalancedMode ? 1 : InstanceHolder.Config.ScavengingRadius;
23 | for (int dy = -radius; dy <= radius; dy++)
24 | {
25 | for (int dx = -radius; dx <= radius; dx++)
26 | {
27 | int x = player.TilePoint.X + dx;
28 | int y = player.TilePoint.Y + dy;
29 | if (currLocation.doesTileHaveProperty(x, y, "Action", "Buildings").StartsWith("Garbage"))
30 | {
31 | string whichGarbage = currLocation.doesTileHaveProperty(x, y, "Action", "Buildings").Split(' ')[1];
32 | town.CheckGarbage(whichGarbage, new Vector2(x, y), Game1.player, true, Config.GarbageDisgustsNPCs);
33 | }
34 | }
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/GloryOfEfficiency.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 17
3 | VisualStudioVersion = 17.9.34714.143
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GloryOfEfficiency", "GloryOfEfficiency\GloryOfEfficiency.csproj", "{0302444C-4190-4C5D-A873-A1F80267961A}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Debug|x86 = Debug|x86
11 | Release|Any CPU = Release|Any CPU
12 | Release|x86 = Release|x86
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {0302444C-4190-4C5D-A873-A1F80267961A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
16 | {0302444C-4190-4C5D-A873-A1F80267961A}.Debug|Any CPU.Build.0 = Debug|Any CPU
17 | {0302444C-4190-4C5D-A873-A1F80267961A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
18 | {0302444C-4190-4C5D-A873-A1F80267961A}.Debug|x86.ActiveCfg = Debug|Any CPU
19 | {0302444C-4190-4C5D-A873-A1F80267961A}.Debug|x86.Build.0 = Debug|Any CPU
20 | {0302444C-4190-4C5D-A873-A1F80267961A}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {0302444C-4190-4C5D-A873-A1F80267961A}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {0302444C-4190-4C5D-A873-A1F80267961A}.Release|x86.ActiveCfg = Release|Any CPU
23 | {0302444C-4190-4C5D-A873-A1F80267961A}.Release|x86.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {0264D5EB-D267-4DE6-890C-8A5B4896283E}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Core/InstanceHolder.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Utils;
2 | using StardewModdingAPI;
3 | using StardewValley;
4 |
5 | namespace GloryOfEfficiency.Core
6 | {
7 | ///
8 | /// This class holds mod and config instance and exposes some useful methods.
9 | ///
10 | internal class InstanceHolder
11 | {
12 | private static ModEntry ModInstance { get; set; }
13 |
14 | public static Config Config { get; private set; }
15 | private static IModHelper Helper => ModInstance.Helper;
16 | public static ITranslationHelper Translation => Helper.Translation;
17 | public static Multiplayer Multiplayer => Game1.Multiplayer;
18 |
19 | public static InputState Input => Game1.input;
20 |
21 | public static CustomAnimalConfigHolder CustomAnimalTool;
22 |
23 | ///
24 | /// Sets mod's entry point and configuration instance.
25 | ///
26 | /// the mod instance
27 | /// the configuration instance
28 | public static void Init(ModEntry modInstance)
29 | {
30 | ModInstance = modInstance;
31 | Config = LoadConfig();
32 | CustomAnimalTool = new CustomAnimalConfigHolder(modInstance.GetFilePath("customAnimalTools.json"));
33 | }
34 |
35 | ///
36 | /// Writes settings to '(ModFolder)/config.json'.
37 | ///
38 |
39 | public static void WriteConfig()
40 | {
41 | Helper?.WriteConfig(Config);
42 | }
43 |
44 | public static Config LoadConfig()
45 | {
46 | return Helper != null ? Config = Helper.ReadConfig() : new Config();
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Configs/ConfigCustomAnimalTool.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using GloryOfEfficiency.Core;
3 | using StardewValley;
4 | using StardewValley.Tools;
5 |
6 | namespace GloryOfEfficiency.Configs
7 | {
8 | class ConfigCustomAnimalTool
9 | {
10 |
11 | public List CustomAnimalTools { get; set; }= new List();
12 |
13 | public static ToolType GetToolType(Tool tool)
14 | {
15 | switch (tool)
16 | {
17 | case MilkPail _:
18 | return ToolType.Bucket;
19 | case Shears _:
20 | return ToolType.Shears;
21 | }
22 |
23 | return ToolType.None;
24 | }
25 |
26 | public bool AddCustomTool(string name, Tool tool)
27 | {
28 | ToolType type = GetToolType(tool);
29 | if (type == ToolType.None)
30 | {
31 | return false;
32 | }
33 |
34 | if (CustomAnimalTools.Exists(c => c.Name == name))
35 | {
36 | return false;
37 | }
38 | CustomAnimalTools.Add(new CustomAnimalTool(name, type));
39 | InstanceHolder.CustomAnimalTool.Save();
40 | return true;
41 | }
42 |
43 | public void RemoveCustomTool(string name)
44 | {
45 | if (!CustomAnimalTools.Exists(c => c.Name == name))
46 | {
47 | return;
48 | }
49 |
50 | CustomAnimalTools.RemoveAll(c => c.Name == name);
51 | InstanceHolder.CustomAnimalTool.Save();
52 | }
53 |
54 | public bool Contains(string name)
55 | {
56 | return CustomAnimalTools.Exists(c => c.Name == name);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Core/ConfigLimitation.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Utils;
2 |
3 | namespace GloryOfEfficiency.Core
4 | {
5 | internal class ConfigLimitation
6 | {
7 | private static Config Conf => InstanceHolder.Config;
8 | public static void LimitConfigValues()
9 | {
10 | if (Conf.DisableConfigLimitation)
11 | {
12 | return;
13 | }
14 | Conf.CpuThresholdFishing = Util.Cap(Conf.CpuThresholdFishing, 0, 0.5f);
15 | Conf.HealthToEatRatio = Util.Cap(Conf.HealthToEatRatio, 0.1f, 0.8f);
16 | Conf.StaminaToEatRatio = Util.Cap(Conf.StaminaToEatRatio, 0.1f, 0.8f);
17 | Conf.ThrowPower = Util.Cap(Conf.ThrowPower, 0.0f, 1.0f);
18 | Conf.AutoCollectRadius = (int)Util.Cap(Conf.AutoCollectRadius, 1, 3);
19 | Conf.AutoHarvestRadius = (int)Util.Cap(Conf.AutoHarvestRadius, 1, 3);
20 | Conf.AutoPetRadius = (int)Util.Cap(Conf.AutoPetRadius, 1, 3);
21 | Conf.AutoWaterRadius = (int)Util.Cap(Conf.AutoWaterRadius, 1, 3);
22 | Conf.AutoDigRadius = (int)Util.Cap(Conf.AutoDigRadius, 1, 3);
23 | Conf.AutoShakeRadius = (int)Util.Cap(Conf.AutoShakeRadius, 1, 3);
24 | Conf.MachineRadius = (int)Util.Cap(Conf.MachineRadius, 1, 3);
25 | Conf.IdleTimeout = (int)Util.Cap(Conf.IdleTimeout, 1, 300);
26 | Conf.ScavengingRadius = (int)Util.Cap(Conf.ScavengingRadius, 1, 3);
27 | Conf.AnimalHarvestRadius = (int)Util.Cap(Conf.AnimalHarvestRadius, 1, 3);
28 | Conf.TrialOfExamine = (int)Util.Cap(Conf.TrialOfExamine, 1, 50);
29 | Conf.RadiusFarmCleanup = (int)Util.Cap(Conf.RadiusFarmCleanup, 1, 3);
30 | Conf.ThresholdStaminaPercentage = (int)Util.Cap(Conf.ThresholdStaminaPercentage, 10f, 60f);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/ColorBox.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Utils;
2 | using Microsoft.Xna.Framework;
3 | using Microsoft.Xna.Framework.Graphics;
4 | using StardewValley.Menus;
5 |
6 | namespace GloryOfEfficiency.OptionsElements
7 | {
8 | internal class ColorBox : OptionsElement
9 | {
10 | //Color of the inner box.
11 | private Color _color;
12 |
13 | public ColorBox(string name, int which, Color color, int width = 128, int height = 128)
14 | : base(name, -1, -1, width, height, which)
15 | {
16 | _color = color;
17 | }
18 |
19 | public override void draw(SpriteBatch b, int slotX, int slotY, IClickableMenu context = null)
20 | {
21 | slotX += 32;
22 |
23 | Util.DrawWindow(slotX, slotY, bounds.Width, bounds.Height); //Draw outer frame.
24 | Util.DrawColoredBox(
25 | b,
26 | slotX + 12, slotY + 12,
27 | bounds.Width - 24, bounds.Height - 24,
28 | _color); //Draw inner box.
29 | }
30 |
31 | ///
32 | /// Sets color of the inner box.
33 | ///
34 | /// The color you want to change.
35 | public void SetColor(Color c)
36 | {
37 | SetColor(c.R, c.G, c.B);
38 | }
39 |
40 | ///
41 | /// Sets color of the inner box.
42 | ///
43 | /// The red value you want to change.
44 | /// The green value you want to change.
45 | /// The blue value you want to change.
46 | public void SetColor(int r, int g, int b)
47 | {
48 | _color.R = (byte) r;
49 | _color.G = (byte) g;
50 | _color.B = (byte) b;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/ModifiedCheckBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GloryOfEfficiency.Core;
3 | using Microsoft.Xna.Framework;
4 | using Microsoft.Xna.Framework.Graphics;
5 | using StardewValley;
6 | using StardewValley.Menus;
7 |
8 | namespace GloryOfEfficiency.OptionsElements
9 | {
10 | internal class ModifiedCheckBox : OptionsElementWithLabel
11 | {
12 |
13 | private bool IsChecked { get; set; }
14 | private readonly Action _valueChanged;
15 | private readonly Func _isDisabled;
16 | public ModifiedCheckBox(string label, int which, bool initial, Action callback = null, Func isDisabled = null) : base(label, -1, -1, 9 * Game1.pixelZoom, 9 * Game1.pixelZoom, 0)
17 | {
18 | this.label = InstanceHolder.Translation.Get($"options.{label}");
19 | IsChecked = initial;
20 | _valueChanged = callback;
21 | whichOption = which;
22 | _isDisabled = isDisabled ?? (i => false);
23 | }
24 |
25 | public override void receiveLeftClick(int x, int y)
26 | {
27 | if(greyedOut)
28 | {
29 | return;
30 | }
31 | Game1.playSound("drumkit6");
32 | base.receiveLeftClick(x, y);
33 | IsChecked = !IsChecked;
34 | _valueChanged?.Invoke(whichOption, IsChecked);
35 | }
36 |
37 | public override void draw(SpriteBatch spriteBatch, int slotX, int slotY, IClickableMenu context = null)
38 | {
39 | greyedOut = _isDisabled(whichOption);
40 | spriteBatch.Draw(Game1.mouseCursors, new Vector2(slotX + bounds.X, slotY + bounds.Y), IsChecked ? OptionsCheckbox.sourceRectChecked : OptionsCheckbox.sourceRectUnchecked, Color.White * (greyedOut ? 0.33f : 1f), 0.0f, Vector2.Zero, Game1.pixelZoom, SpriteEffects.None, 0.4f);
41 | base.draw(spriteBatch, slotX, slotY);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/EventHandler/GraphicsEvents.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Automation;
2 | using GloryOfEfficiency.Core;
3 | using GloryOfEfficiency.Huds;
4 | using GloryOfEfficiency.Misc;
5 | using StardewModdingAPI.Events;
6 | using StardewValley;
7 | using StardewValley.Locations;
8 | using StardewValley.Menus;
9 | using StardewValley.Tools;
10 |
11 | namespace GloryOfEfficiency.EventHandler
12 | {
13 | internal class GraphicsEvents
14 | {
15 | private static Config Conf => InstanceHolder.Config;
16 |
17 | public void OnRenderHud(object sender, RenderingHudEventArgs args)
18 | {
19 | if (Game1.currentLocation is MineShaft shaft && Conf.MineInfoGui)
20 | {
21 | MineHud.DrawMineGui(shaft);
22 | }
23 | if (Conf.GiftInformation)
24 | {
25 | GiftInformationTooltip.DrawTooltip();
26 | }
27 | if (Game1.player.CurrentTool is FishingRod rod && rod.isFishing)
28 | {
29 | FishingProbabilitiesBox.PrintFishingInfo();
30 | }
31 | if (Conf.PauseWhenIdle)
32 | {
33 | IdlePause.DrawHud();
34 | }
35 | }
36 |
37 | public void OnPostRenderGui(object sender, RenderedActiveMenuEventArgs args)
38 | {
39 | if (Game1.activeClickableMenu is BobberBar bar)
40 | {
41 | if (Conf.FishingInfo)
42 | {
43 | FishInformationHud.DrawFishingInfoBox(Game1.spriteBatch, bar, Game1.dialogueFont);
44 | }
45 | if (Conf.AutoFishing)
46 | {
47 | AutoFisher.AutoFishing(bar);
48 | }
49 | }
50 | if (Conf.EstimateShippingPrice && Game1.activeClickableMenu is ItemGrabMenu menu)
51 | {
52 | ShippingEstimationInfoBox.DrawShippingPrice(menu, Game1.dialogueFont);
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/ButtonWithLabel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GloryOfEfficiency.Core;
3 | using Microsoft.Xna.Framework;
4 | using Microsoft.Xna.Framework.Graphics;
5 | using StardewValley;
6 | using StardewValley.Menus;
7 |
8 | namespace GloryOfEfficiency.OptionsElements
9 | {
10 | internal class ButtonWithLabel : OptionsElement
11 | {
12 | private Rectangle _buttonRect = Rectangle.Empty;
13 |
14 | private readonly Action _onButtonPressed;
15 | private readonly Func _isDisabled;
16 |
17 | public ButtonWithLabel(string label, int which,
18 | Action onButtonPressed = null, Func isDisabled = null)
19 | : base(label, -1, -1, 9 * Game1.pixelZoom, 9 * Game1.pixelZoom, which)
20 | {
21 | this.label = InstanceHolder.Translation.Get($"options.{label}");
22 | _onButtonPressed = onButtonPressed ?? (i => { });
23 | _isDisabled = isDisabled ?? (i => false);
24 | }
25 |
26 | public override void receiveLeftClick(int x, int y)
27 | {
28 | base.receiveLeftClick(x, y);
29 |
30 | if (x >= _buttonRect.Left && x <= _buttonRect.Right)
31 | {
32 | _onButtonPressed(whichOption);
33 | }
34 | }
35 |
36 | public override void draw(SpriteBatch b, int slotX, int slotY, IClickableMenu context = null)
37 | {
38 | string text = label;
39 | Vector2 size = Game1.dialogueFont.MeasureString(text);
40 | b.DrawString(Game1.dialogueFont, text, new Vector2(slotX + 16, slotY + 8), Color.Black, 0, new Vector2(), 1f, SpriteEffects.None, 1.0f);
41 |
42 | int x = slotX + (int)size.X + 24;
43 |
44 | _buttonRect = new Rectangle(x, slotY + 8, 90, 45);
45 | bounds = new Rectangle(0, 0, (int) size.X + _buttonRect.Width + _buttonRect.Width / 2, _buttonRect.Height + _buttonRect.Height / 2);
46 |
47 | b.Draw(Game1.mouseCursors, _buttonRect, new Rectangle(294, 428, 21, 11), Color.White * (_isDisabled(whichOption) ? 0.66f : 1.0f), 0, Vector2.Zero, SpriteEffects.None, 1.0f);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Huds/ShippingEstimationInfoBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using GloryOfEfficiency.Core;
4 | using GloryOfEfficiency.Utils;
5 | using Microsoft.Xna.Framework;
6 | using Microsoft.Xna.Framework.Graphics;
7 | using StardewModdingAPI;
8 | using StardewValley;
9 | using StardewValley.Menus;
10 |
11 | namespace GloryOfEfficiency.Huds
12 | {
13 | internal class ShippingEstimationInfoBox
14 | {
15 | private static Config Config => InstanceHolder.Config;
16 | private static ITranslationHelper Translation => InstanceHolder.Translation;
17 | public static void DrawShippingPrice(IClickableMenu menu, SpriteFont font)
18 | {
19 | if (!(menu is ItemGrabMenu grabMenu) || !(grabMenu.shippingBin || IsCaShippingBinMenu(grabMenu)))
20 | {
21 | return;
22 | }
23 | int shippingPrice = Game1.getFarm().getShippingBin(Game1.player).Sum(item => GetTruePrice(item) / 2 * item.Stack);
24 | string title = Translation.Get("estimatedprice.title");
25 | string text = $" {shippingPrice}G";
26 | Vector2 sizeTitle = font.MeasureString(title) * 1.2f;
27 | Vector2 sizeText = font.MeasureString(text) * 1.2f;
28 | int width = Math.Max((int)sizeTitle.X, (int)sizeText.X) + 32;
29 | int height = 16 + (int)sizeTitle.Y + 8 + (int)sizeText.Y + 16;
30 | Vector2 basePos = new Vector2(Config.PriceBoxCoordinates.X, Config.PriceBoxCoordinates.Y);
31 |
32 | Util.DrawWindow((int)basePos.X, (int)basePos.Y, width, height);
33 | Utility.drawTextWithShadow(Game1.spriteBatch, title, font, basePos + new Vector2(16, 16), Color.Black, 1.2f);
34 | Utility.drawTextWithShadow(Game1.spriteBatch, text, font, basePos + new Vector2(16, 16 + (int)sizeTitle.Y + 8), Color.Black, 1.2f);
35 | }
36 |
37 | public static bool IsCaShippingBinMenu(ItemGrabMenu menu)
38 | {
39 | return !menu.reverseGrab && menu.showReceivingMenu && menu.context is Farm;
40 | }
41 |
42 | public static int GetTruePrice(Item item)
43 | {
44 | if (item == null)
45 | {
46 | return 0;
47 | }
48 | return item is StardewValley.Object obj ? obj.sellToStorePrice() * 2 : item.salePrice();
49 | }
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/MailAutomation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using GloryOfEfficiency.Utils;
4 | using StardewValley;
5 | using StardewValley.Menus;
6 | using StardewValley.Quests;
7 |
8 | namespace GloryOfEfficiency.Automation
9 | {
10 | internal class MailAutomation
11 | {
12 | private static readonly Logger Logger = new Logger("MailAutomation");
13 |
14 | public static void CollectMailAttachmentsAndQuests(LetterViewerMenu menu)
15 | {
16 | String questId = menu.questID;
17 |
18 | if (menu.itemsLeftToGrab())
19 | {
20 | foreach (ClickableComponent component in menu.itemsToGrab.ToArray())
21 | {
22 | if (component.item == null || !CanPlayerAcceptsItemPartially(component.item))
23 | {
24 | continue;
25 | }
26 |
27 | int stack = component.item.Stack;
28 | Game1.playSound("coin");
29 | int remain = Util.AddItemIntoInventory(component.item);
30 |
31 | Logger.Log($"You collected {component.item.DisplayName}{(stack - remain > 1 ? " x" + (stack - remain) : "")}.");
32 | if (remain == 0)
33 | {
34 | component.item = null;
35 | }
36 | else
37 | {
38 | component.item.Stack = remain;
39 | }
40 | }
41 | }
42 |
43 | if (questId == null)
44 | {
45 | return;
46 | }
47 |
48 | Logger.Log($"You started Quest: '{Quest.getQuestFromId(questId).questTitle}'.");
49 | Game1.player.addQuest(questId);
50 | Game1.playSound("newArtifact");
51 | menu.questID = null;
52 | }
53 |
54 | private static bool CanPlayerAcceptsItemPartially(Item item)
55 | {
56 | if (Game1.player.Items.Contains(null) || Game1.player.Items.Count < Game1.player.MaxItems)
57 | {
58 | // Inventory includes at least one free space.
59 | return true;
60 | }
61 |
62 | return Game1.player.Items.Any(stack => stack.canStackWith(item) && stack.Stack < stack.maximumStackSize());
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // このコードはツールによって生成されました。
4 | // ランタイム バージョン:4.0.30319.42000
5 | //
6 | // このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
7 | // コードが再生成されるときに損失したりします。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | using System.CodeDom.Compiler;
12 | using System.ComponentModel;
13 | using System.Diagnostics;
14 | using System.Diagnostics.CodeAnalysis;
15 | using System.Globalization;
16 | using System.Resources;
17 | using System.Runtime.CompilerServices;
18 |
19 | namespace GloryOfEfficiency.Properties {
20 | ///
21 | /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。
22 | ///
23 | // このクラスは StronglyTypedResourceBuilder クラスが ResGen
24 | // または Visual Studio のようなツールを使用して自動生成されました。
25 | // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に
26 | // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。
27 | [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
28 | [DebuggerNonUserCode()]
29 | [CompilerGenerated()]
30 | internal class Resources {
31 |
32 | private static ResourceManager resourceMan;
33 |
34 | private static CultureInfo resourceCulture;
35 |
36 | [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
37 | internal Resources() {
38 | }
39 |
40 | ///
41 | /// このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。
42 | ///
43 | [EditorBrowsable(EditorBrowsableState.Advanced)]
44 | internal static ResourceManager ResourceManager {
45 | get {
46 | if (ReferenceEquals(resourceMan, null)) {
47 | ResourceManager temp = new ResourceManager("GloryOfEfficiency.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// すべてについて、現在のスレッドの CurrentUICulture プロパティをオーバーライドします
56 | /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。
57 | ///
58 | [EditorBrowsable(EditorBrowsableState.Advanced)]
59 | internal static CultureInfo Culture {
60 | get {
61 | return resourceCulture;
62 | }
63 | set {
64 | resourceCulture = value;
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/EventHandler/ArtifactSpotDigger.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Core;
2 | using GloryOfEfficiency.Utils;
3 | using Microsoft.Xna.Framework;
4 | using StardewValley;
5 | using StardewValley.TerrainFeatures;
6 | using StardewValley.Tools;
7 |
8 | namespace GloryOfEfficiency.EventHandler
9 | {
10 | internal class ArtifactSpotDigger
11 | {
12 | private static Config Config => InstanceHolder.Config;
13 | private static readonly Logger Logger = new Logger("ArtifactSpotDigger");
14 | private static Farmer player = Game1.player;
15 |
16 | public static void DigNearbyArtifactSpots()
17 | {
18 | int radius = Config.AutoDigRadius;
19 | Hoe hoe = Util.FindToolFromInventory(player, InstanceHolder.Config.FindHoeFromInventory);
20 | if (hoe == null)
21 | {
22 | return;
23 | }
24 |
25 | bool flag = false;
26 | GameLocation location = player.currentLocation;
27 | for (int i = -radius; i <= radius; i++)
28 | {
29 | for (int j = -radius; j <= radius; j++)
30 | {
31 | Point currPos = player.TilePoint;
32 | int x = currPos.X + i;
33 | int y = currPos.Y + j;
34 | Vector2 loc = new Vector2(x, y);
35 | if (!location.Objects.ContainsKey(loc) || location.isTileHoeDirt(loc))
36 | {
37 | continue;
38 | }
39 |
40 | string spotName = location.Objects[loc].name;
41 | if (spotName == "Seed Spot" || spotName == "Artifact Spot")
42 | {
43 | Logger.Log($"{spotName}: {location.Objects[loc].name} at [{loc.X},{loc.Y}]");
44 |
45 | // Hackswell: location.digUpArtifactSpot() works fine... except with Farm Type Manager Mod.
46 | // Just easier to do everything the following way... =shurg=
47 | //
48 | // Liberated this from Pathoschild's "TractorMod"
49 | player.lastClick = (loc * Game1.tileSize) + new Vector2(Game1.tileSize / 2f);
50 | hoe.swingTicker++;
51 | hoe.DoFunction(location, (int)player.lastClick.X, (int)player.lastClick.Y, 0, player);
52 | flag = true;
53 | }
54 | }
55 | }
56 |
57 | if (flag)
58 | {
59 | Game1.playSound("hoeHit");
60 | }
61 | }
62 |
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/GloryOfEfficiency.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | net6.0
6 | Library
7 | Properties
8 | GloryOfEfficiency
9 | GloryOfEfficiency
10 | 512
11 | 1.0.0
12 |
13 |
14 | true
15 | full
16 | false
17 | bin\Debug\
18 | DEBUG;TRACE
19 | prompt
20 | 3
21 |
22 |
23 | true
24 | pdbonly
25 | true
26 | bin\Release\
27 | TRACE
28 | prompt
29 | 3
30 |
31 |
32 | Always
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | PreserveNewest
49 |
50 |
51 |
52 |
53 | PreserveNewest
54 |
55 |
56 | PreserveNewest
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Misc/IdlePause.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Core;
2 | using GloryOfEfficiency.Huds;
3 | using GloryOfEfficiency.Utils;
4 | using StardewValley;
5 | using static StardewValley.Game1;
6 |
7 | namespace GloryOfEfficiency.Misc
8 | {
9 | internal class IdlePause
10 | {
11 | private static Config Conf => InstanceHolder.Config;
12 | private static double TimeoutCounter { get; set; }
13 | private static bool Paused { get; set; }
14 | private static int LastTimeOfDay { get; set; }
15 |
16 | private static int _lastItemIndex;
17 |
18 | private static readonly Logger Logger = new Logger("IdlePause");
19 |
20 | public static void OnTickUpdate()
21 | {
22 | if (Conf.PauseWhenIdle)
23 | {
24 | if (IsPlayerIdle())
25 | {
26 | TimeoutCounter += Game1.currentGameTime.ElapsedGameTime.TotalMilliseconds;
27 | if (TimeoutCounter > Conf.IdleTimeout * 1000)
28 | {
29 | if (!Paused)
30 | {
31 | Logger.Log("Paused game");
32 | Paused = true;
33 | }
34 |
35 | Game1.timeOfDay = LastTimeOfDay;
36 | }
37 | }
38 | else
39 | {
40 | if (Paused)
41 | {
42 | Paused = false;
43 | Logger.Log("Resumed game");
44 | }
45 |
46 | TimeoutCounter = 0;
47 | LastTimeOfDay = Game1.timeOfDay;
48 | }
49 | }
50 | else
51 | {
52 | Paused = false;
53 | }
54 | }
55 |
56 | public static void OnDataLoaded()
57 | {
58 | LastTimeOfDay = Game1.timeOfDay;
59 | }
60 |
61 | public static void DrawHud()
62 | {
63 | if (Paused)
64 | {
65 | PausedHud.DrawPausedHud();
66 | }
67 | }
68 |
69 | private static bool IsPlayerIdle()
70 | {
71 | if (paused || !shouldTimePass())
72 | {
73 | //When game is paused or time is stopped already. it's not idle.
74 | return false;
75 | }
76 |
77 | if (player.CurrentToolIndex != _lastItemIndex)
78 | {
79 | //When tool index changed, it's not idle.
80 | _lastItemIndex = player.CurrentToolIndex;
81 | return false;
82 | }
83 |
84 | if (player.isMoving() || player.UsingTool)
85 | {
86 | //When player is moving or is using tools, it's not idle of cause.
87 | return false;
88 | }
89 |
90 | return true;
91 | }
92 |
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Huds/MineHud.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using GloryOfEfficiency.Core;
4 | using Microsoft.Xna.Framework;
5 | using StardewModdingAPI;
6 | using StardewValley;
7 | using StardewValley.Locations;
8 | using StardewValley.Monsters;
9 |
10 | namespace GloryOfEfficiency.Huds
11 | {
12 | internal class MineHud
13 | {
14 | private static ITranslationHelper Translation => InstanceHolder.Translation;
15 |
16 | private static readonly MineIcons Icons = new MineIcons();
17 | private static List _lastMonsters = new List();
18 |
19 | public static Monster LastKilledMonster { get; private set; }
20 |
21 | public static void DrawMineGui(MineShaft shaft)
22 | {
23 | int stonesLeft = CountActualStones(shaft);
24 | Vector2 ladderPos = FindLadder(shaft);
25 | bool ladder = ladderPos != Vector2.Zero;
26 |
27 | List currentMonsters = shaft.characters.OfType().ToList();
28 | foreach (Monster mon in _lastMonsters)
29 | {
30 | if (!currentMonsters.Contains(mon) && mon.Name != "ignoreMe")
31 | {
32 | LastKilledMonster = mon;
33 | }
34 | }
35 | _lastMonsters = currentMonsters.ToList();
36 | string tallyStr = null;
37 | string ladderStr = null;
38 | if (LastKilledMonster != null)
39 | {
40 | int kills = Game1.stats.getMonstersKilled(LastKilledMonster.Name);
41 | tallyStr = string.Format(Translation.Get("monsters.tally"), LastKilledMonster.displayName, kills);
42 | }
43 |
44 | string stonesStr;
45 | if (stonesLeft == 0)
46 | {
47 | stonesStr = Translation.Get("stones.none");
48 | }
49 | else
50 | {
51 | bool single = stonesLeft == 1;
52 | stonesStr = single ? Translation.Get("stones.one") : string.Format(Translation.Get("stones.many"), stonesLeft);
53 | }
54 | if (ladder)
55 | {
56 | ladderStr = Translation.Get("ladder");
57 | }
58 | Icons.Draw(stonesStr, tallyStr, ladderStr);
59 |
60 | }
61 | private static int CountActualStones(GameLocation shaft)
62 | {
63 | return shaft.Objects.Pairs.Count(kv => kv.Value.Name.Contains("Stone"));
64 | }
65 | private static Vector2 FindLadder(GameLocation shaft)
66 | {
67 | for (int i = 0; i < shaft.Map.GetLayer("Buildings").LayerWidth; i++)
68 | {
69 | for (int j = 0; j < shaft.Map.GetLayer("Buildings").LayerHeight; j++)
70 | {
71 | int index = shaft.getTileIndexAt(new Point(i, j), "Buildings");
72 | Vector2 loc = new Vector2(i, j);
73 | if (shaft.Objects.ContainsKey(loc) || shaft.terrainFeatures.ContainsKey(loc))
74 | {
75 | continue;
76 | }
77 |
78 | if (index == 171 || index == 173 || index == 174)
79 | {
80 | return loc;
81 | }
82 | }
83 | }
84 | return Vector2.Zero;
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/InventoryAutomation.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Huds;
2 | using GloryOfEfficiency.Utils;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 |
6 | namespace GloryOfEfficiency.Automation
7 | {
8 | internal class InventoryAutomation
9 | {
10 | private static readonly Logger Logger = new Logger("InventoryAutomation");
11 |
12 | public static void LootAllAcceptableItems(ItemGrabMenu menu, bool skipCheck = false)
13 | {
14 | if (!skipCheck)
15 | {
16 | if (menu.shippingBin || ShippingEstimationInfoBox.IsCaShippingBinMenu(menu))
17 | {
18 | Logger.Log("Won't do anything to shipping bin");
19 | return;
20 | }
21 |
22 | if (menu.reverseGrab)
23 | {
24 | Logger.Log("You can't get item from this menu.");
25 | return;
26 | }
27 |
28 | if (menu.source == ItemGrabMenu.source_chest)
29 | {
30 | Logger.Log("Won't do anything to chest player placed");
31 | return;
32 | }
33 |
34 | if (menu.showReceivingMenu && menu.source == ItemGrabMenu.source_none)
35 | {
36 | Logger.Log("showReceivingMenu true but is not gift or fishing chest.");
37 | return;
38 | }
39 | }
40 |
41 | for (int i = menu.ItemsToGrabMenu.actualInventory.Count - 1; i >= 0; i--)
42 | {
43 | if (i >= menu.ItemsToGrabMenu.actualInventory.Count)
44 | {
45 | continue;
46 | }
47 |
48 | Item item = menu.ItemsToGrabMenu.actualInventory[i];
49 | int oldStack = item.Stack;
50 | int remain = Util.AddItemIntoInventory(item);
51 | int taken = oldStack - remain;
52 | if (taken > 0)
53 | {
54 | Logger.Log($"You looted {item.DisplayName}{(taken == 1 ? "" : " x" + taken)}.");
55 | }
56 |
57 | if (remain == 0)
58 | {
59 | menu.ItemsToGrabMenu.actualInventory.Remove(item);
60 | continue;
61 | }
62 |
63 | menu.ItemsToGrabMenu.actualInventory[i].Stack = remain;
64 | }
65 | }
66 |
67 | public static void TryCloseItemGrabMenu(ItemGrabMenu menu)
68 | {
69 | if (!menu.areAllItemsTaken() || menu.heldItem != null)
70 | {
71 | return;
72 | }
73 |
74 | if (menu.shippingBin || ShippingEstimationInfoBox.IsCaShippingBinMenu(menu))
75 | {
76 | //It's a shipping bin.
77 | return;
78 | }
79 |
80 | if (menu.context is Event && menu.essential)
81 | {
82 | // You should not emergency close in events (it may stop the dialogue).
83 | return;
84 | }
85 |
86 | switch (menu.source)
87 | {
88 | case ItemGrabMenu.source_chest:
89 | case ItemGrabMenu.source_none when menu.context == null:
90 | return; // It's a chest.
91 | }
92 |
93 | menu.exitThisMenu();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/ModifiedSlider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GloryOfEfficiency.Core;
3 | using Microsoft.Xna.Framework;
4 | using Microsoft.Xna.Framework.Graphics;
5 | using StardewValley;
6 | using StardewValley.Menus;
7 |
8 | namespace GloryOfEfficiency.OptionsElements
9 | {
10 | internal class ModifiedSlider : OptionsElementWithLabel
11 | {
12 | private readonly string _label;
13 |
14 | private readonly Action _setValue;
15 |
16 | private readonly int _maxValue;
17 | private readonly int _minValue;
18 |
19 | private int _value;
20 |
21 | private readonly Func _isDisabled;
22 |
23 | private readonly Func _format;
24 |
25 | public ModifiedSlider(string label, int which, int initialValue, int minValue, int maxValue, Action setValue, Func disabled = null, Func format = null, int width = 64)
26 | : base(label, -1, -1, width * Game1.pixelZoom, 6 * Game1.pixelZoom, 0)
27 | {
28 | whichOption = which;
29 | _label = InstanceHolder.Translation.Get($"options.{label}");
30 | _value = initialValue - minValue;
31 | _minValue = minValue;
32 | _maxValue = maxValue - minValue;
33 | _setValue = setValue ?? ((i, j) => { });
34 | _isDisabled = disabled ?? (() => false);
35 | _format = format ?? ((i, value) => value.ToString());
36 | }
37 |
38 | public override void leftClickHeld(int x, int y)
39 | {
40 | if (greyedOut)
41 | return;
42 |
43 | base.leftClickHeld(x, y);
44 | int oldValue = _value;
45 | _value = x >= bounds.X
46 | ? (x <= bounds.Right - 10 * Game1.pixelZoom
47 | ? (int) ((x - bounds.X) / (bounds.Width - 10d * Game1.pixelZoom) * _maxValue)
48 | : _maxValue)
49 | : 0;
50 | if (_value != oldValue)
51 | {
52 | _setValue?.Invoke(whichOption, _value + _minValue);
53 | }
54 |
55 | }
56 |
57 | public override void receiveLeftClick(int x, int y)
58 | {
59 | if (greyedOut)
60 | return;
61 | base.receiveLeftClick(x, y);
62 | leftClickHeld(x, y);
63 | }
64 |
65 | public override void leftClickReleased(int x, int y)
66 | {
67 | _setValue?.Invoke(whichOption, _value + _minValue);
68 | }
69 |
70 | public override void draw(SpriteBatch spriteBatch, int slotX, int slotY, IClickableMenu context = null)
71 | {
72 | label = _label.Contains("{0}")
73 | ? string.Format(_label, _format(whichOption, _value + _minValue))
74 | : $"{_label}: {_format(whichOption, _value + _minValue)}";
75 |
76 | greyedOut = _isDisabled();
77 |
78 | base.draw(spriteBatch, slotX, slotY - ((int)Game1.dialogueFont.MeasureString(label).Y - bounds.Height) / 2, context);
79 | IClickableMenu.drawTextureBox(spriteBatch, Game1.mouseCursors, OptionsSlider.sliderBGSource, slotX + bounds.X, slotY + bounds.Y, bounds.Width, bounds.Height, Color.White * (greyedOut ? 0.33f : 1.0f), Game1.pixelZoom, false);
80 | spriteBatch.Draw(Game1.mouseCursors, new Vector2(slotX + bounds.X + (bounds.Width - 10 * Game1.pixelZoom) * (_value / (float)_maxValue), slotY + bounds.Y), OptionsSlider.sliderButtonRect, Color.White * (greyedOut ? 0.66f : 1.0f), 0.0f, Vector2.Zero, Game1.pixelZoom, SpriteEffects.None, 0.9f);
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Core/ModEntry.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using GloryOfEfficiency.Automation;
3 | using GloryOfEfficiency.EventHandler;
4 | using GloryOfEfficiency.Harmony;
5 | using GloryOfEfficiency.Huds;
6 | using GloryOfEfficiency.ModCheckers;
7 | using GloryOfEfficiency.Utils;
8 | using Microsoft.Xna.Framework;
9 | using StardewModdingAPI;
10 | using StardewModdingAPI.Events;
11 | using StardewValley;
12 |
13 | namespace GloryOfEfficiency.Core
14 | {
15 | using Player = Farmer;
16 |
17 | ///
18 | /// This class is a representation of the mod itself.
19 | ///
20 | internal class ModEntry : Mod
21 | {
22 | public static bool IsCoGOn { get; private set; }
23 | public static bool IsCaOn { get; private set; }
24 | private static Config Conf => InstanceHolder.Config;
25 | public static bool DebugMode { get; private set; }
26 |
27 | private static readonly Logger Logger = new Logger("Main");
28 |
29 | ///
30 | /// Called firstly when SMAPI finished loading of the mod.
31 | ///
32 | ///
33 | public override void Entry(IModHelper helper)
34 | {
35 | // Initialize Logger
36 | Logger.Init(Monitor);
37 |
38 | // Initialize InstanceHolder.
39 | InstanceHolder.Init(this);
40 |
41 | // Register events.
42 | EventHolder.RegisterEvents(Helper.Events);
43 |
44 | // Limit config values.
45 | ConfigLimitation.LimitConfigValues();
46 |
47 | // Registration commands.
48 | Helper.ConsoleCommands.Add("goedebug", "Debug command for GoE", OnDebugCommand);
49 | Helper.ConsoleCommands.Add("goerelcon", "Reloading config command for GoE", OnReloadConfigCommand);
50 | Helper.Events.GameLoop.GameLaunched += OnGameLaunched;
51 |
52 | // Check mod compatibilities.
53 | if(ModChecker.IsCoGLoaded(helper))
54 | {
55 | Logger.Log("CasksOnGround detected.");
56 | IsCoGOn = true;
57 | }
58 |
59 | if (ModChecker.IsCaLoaded(helper))
60 | {
61 | Logger.Log("CasksAnywhere detected.");
62 | IsCaOn = true;
63 | }
64 |
65 | // Do patching stuff
66 | if (!Conf.SafeMode)
67 | {
68 | HarmonyPatcher.DoPatching();
69 | }
70 | else
71 | {
72 | Logger.Log("Bypassing patching...");
73 | }
74 |
75 | helper.WriteConfig(Conf);
76 |
77 | if (Conf.DontEatThat)
78 | {
79 | Logger.Log($"Don't Eat That(tm) is enabled!");
80 | Helper.Events.Input.ButtonPressed += FoodAutomation.ButtonPressed;
81 | }
82 |
83 | MineIcons.Init(helper);
84 | }
85 |
86 | private static void OnReloadConfigCommand(string name, string[] args)
87 | {
88 | // Loads configuration from file.
89 | InstanceHolder.LoadConfig();
90 | if (Conf.DontEatThat)
91 | {
92 | Logger.Log($"Don't Eat That(tm) is enabled!");
93 | FoodAutomation.InitDontEat();
94 | }
95 | Logger.Log("Reloaded JoE's config.");
96 | }
97 |
98 | private static void OnGameLaunched(object sender, GameLaunchedEventArgs e)
99 | {
100 | if (Conf.DontEatThat)
101 | {
102 | Logger.Log($"Don't Eat That(tm) is enabled!");
103 | FoodAutomation.InitDontEat();
104 | }
105 | }
106 |
107 | private static void OnDebugCommand(string name, string[] args)
108 | {
109 | DebugMode = !DebugMode;
110 | }
111 |
112 | public string GetFilePath(string fileName)
113 | {
114 | return Path.Combine(Helper.DirectoryPath, fileName);
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Huds/MineIcons.cs:
--------------------------------------------------------------------------------
1 | using GloryOfEfficiency.Utils;
2 | using Microsoft.Xna.Framework;
3 | using Microsoft.Xna.Framework.Graphics;
4 | using StardewModdingAPI;
5 | using StardewValley;
6 | using StardewValley.Menus;
7 |
8 | namespace GloryOfEfficiency.Huds
9 | {
10 | public class MineIcons
11 | {
12 | private static Logger _logger = new Logger("MineIcons");
13 |
14 | private static Texture2D _iconPickaxe;
15 | private static Texture2D _iconMonster;
16 | private static Texture2D _iconLadder;
17 |
18 | private static int OffsetX => (Util.IsAndroid() ? 128 : 0);
19 |
20 | public static void Init(IModHelper helper)
21 | {
22 | _iconPickaxe = helper.ModContent.Load("assets/icon_pickaxe.png");
23 | _iconMonster = helper.ModContent.Load("assets/icon_monster.png");
24 | _iconLadder = helper.ModContent.Load("assets/icon_ladder.png");
25 | int x = 16 + OffsetX;
26 |
27 | _logger.Log($"x:{x}");
28 | }
29 |
30 | public void Draw(string stoneStr, string monsterStr, string ladderStr)
31 | {
32 | SpriteBatch batch = Game1.spriteBatch;
33 |
34 | bool redrawCursor = false;
35 | string displayText = "";
36 |
37 | Point mousePos = new Point(Game1.getMouseX(), Game1.getMouseY());
38 |
39 | int y = 96;
40 | int x = 16 + OffsetX;
41 | {
42 | IClickableMenu.drawTextureBox(batch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), x - 16, y - 16, 40 + 32, 40 + 32, Color.White);
43 | batch.Draw(_iconPickaxe, new Vector2(x, y), null, Color.White, 0.0f, Vector2.Zero, 2.5f, SpriteEffects.None, 0.9f);
44 | Rectangle rect = new Rectangle(x, y, 40, 40);
45 | if (rect.Contains(mousePos))
46 | {
47 | displayText = stoneStr;
48 | redrawCursor = true;
49 | }
50 |
51 | x += 80;
52 | }
53 | if (monsterStr != null)
54 | {
55 | IClickableMenu.drawTextureBox(batch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), x - 16, y - 16, 40 + 32, 40 + 32, Color.White);
56 | batch.Draw(_iconMonster, new Vector2(x, y), null, Color.White, 0.0f, Vector2.Zero, 2.5f, SpriteEffects.None, 0.9f);
57 | Rectangle rect = new Rectangle(x, y, 40, 40);
58 | if (rect.Contains(mousePos))
59 | {
60 | displayText = monsterStr;
61 | redrawCursor = true;
62 | }
63 |
64 | x += 80;
65 | }
66 | if (ladderStr != null)
67 | {
68 | IClickableMenu.drawTextureBox(batch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), x-16, y-16, 40 + 32, 40 + 32, Color.White);
69 | batch.Draw(_iconLadder, new Vector2(x, y), null, Color.White, 0.0f, Vector2.Zero, 2.5f, SpriteEffects.None, 0.9f);
70 | Rectangle rect = new Rectangle(x, y, 40, 40);
71 | if (rect.Contains(mousePos))
72 | {
73 | displayText = ladderStr;
74 | redrawCursor = true;
75 | }
76 | }
77 |
78 | if (displayText != "")
79 | {
80 | Util.DrawSimpleTextbox(batch, displayText, Game1.dialogueFont, this, true, isTips: true);
81 | }
82 |
83 | if(redrawCursor)
84 | DrawCursor(batch);
85 | }
86 |
87 | public static void DrawCursor(SpriteBatch batch)
88 | {
89 | if (!Game1.options.hardwareCursor && !Game1.options.gamepadControls)
90 | {
91 | batch.Draw(Game1.mouseCursors, new Vector2(Game1.getMouseX(), Game1.getMouseY()), Game1.getSourceRectForStandardTileSheet(Game1.mouseCursors, Game1.options.gamepadControls ? 44 : 0, 16, 16), Color.White, 0f, Vector2.Zero, Game1.pixelZoom + Game1.dialogueButtonScale / 150f, SpriteEffects.None, 1f);
92 | }
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Harmony/HarmonyPatcher.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 | using System;
3 | using System.Linq.Expressions;
4 | using System.Reflection;
5 | using GloryOfEfficiency.Utils;
6 | using HarmonyLib;
7 | using StardewModdingAPI;
8 | using StardewValley;
9 | using SVObject = StardewValley.Object;
10 |
11 | namespace GloryOfEfficiency.Harmony
12 | {
13 | internal class HarmonyPatcher
14 | {
15 | private static HarmonyLib.Harmony harmony = new HarmonyLib.Harmony("com.hackswell.goe");
16 |
17 | private static readonly Logger Logger = new Logger("GoE HarmonyPatcher");
18 |
19 | public static void DoPatching()
20 | {
21 | harmony.PatchAll();
22 | }
23 | /*
24 | ///
25 | /// Patches for FTM's burial spot.
26 | ///
27 | internal static class FTMArtifactSpotPatch
28 | {
29 | #region delegates
30 | private static readonly Lazy?> isBuriedItem = new(() =>
31 | {
32 | Type? buriedItem = AccessTools.TypeByName("FarmTypeManager.ModEntry+BuriedItems");
33 | if (buriedItem is null)
34 | {
35 | return null;
36 | }
37 |
38 | ParameterExpression? obj = Expression.Parameter(typeof(SVObject), "obj");
39 | TypeBinaryExpression? express = Expression.TypeIs(obj, buriedItem);
40 | return Expression.Lambda>(express, obj).Compile();
41 | });
42 |
43 | ///
44 | /// Gets whether an item is a MoreGrassStarter grass starter.
45 | ///
46 | internal static Func? IsBuriedItem => isBuriedItem.Value;
47 | #endregion
48 |
49 | ///
50 | /// Applies the patches for this class.
51 | ///
52 | /// My harmony instance.
53 | internal static void ApplyPatch(HarmonyLib.Harmony harmony)
54 | {
55 | Type? buriedItem = AccessTools.TypeByName("FarmTypeManager.ModEntry+BuriedItems");
56 | if (buriedItem is null)
57 | {
58 | Logger.Log($"Farm Type Manager's buried items may not behave correctly if dug up with the tool.", LogLevel.Error);
59 | return;
60 | }
61 |
62 | try
63 | {
64 | harmony.Patch(
65 | original: buriedItem.GetMethod("performToolAction", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy),
66 | prefix: new HarmonyMethod(typeof(FTMArtifactSpotPatch).GetMethod(nameof(Prefix), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy)));
67 | }
68 | catch (Exception ex)
69 | {
70 | Logger.Log($"Failed to patch FTM to support artifact spots.\n\n{ex}", LogLevel.Error);
71 | }
72 | }
73 |
74 | private static bool Prefix(SVObject __instance, Tool t, GameLocation location, ref bool __result)
75 | {
76 | // Until I know if we need the Prefix() method or not...
77 | // We don't have a ShovelTool in this mod...
78 | //if (t is not ShovelTool shovel)
79 | //return true;
80 |
81 | try
82 | {
83 | __result = true;
84 | MethodInfo method = __instance.GetType().GetMethod("releaseContents", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
85 |
86 | method.Invoke(__instance, new[] { location });
87 |
88 | if (!location.terrainFeatures.ContainsKey(__instance.TileLocation))
89 | {
90 | location.makeHoeDirt(__instance.TileLocation);
91 | }
92 | location.playSound("hoeHit");
93 | return false;
94 | }
95 | catch (Exception ex)
96 | {
97 | Logger.Log($"Failed while trying to use tool on FTM artifact spot:\n\n{ex}", LogLevel.Error);
98 | }
99 |
100 | return true;
101 |
102 |
103 | }
104 | }
105 | */
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | text/microsoft-resx
91 |
92 |
93 | 1.3
94 |
95 |
96 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
97 |
98 |
99 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
100 |
101 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/CollectibleCollector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using GloryOfEfficiency.Core;
4 | using GloryOfEfficiency.Utils;
5 | using Microsoft.Xna.Framework;
6 | using StardewValley;
7 | using StardewValley.TerrainFeatures;
8 | using StardewValley.Tools;
9 | using SVObject = StardewValley.Object;
10 |
11 | namespace GloryOfEfficiency.Automation
12 | {
13 | internal class CollectibleCollector
14 | {
15 | private static Config Config => InstanceHolder.Config;
16 | private static readonly Logger Logger = new Logger("CollectibleCollector");
17 |
18 | public static void CollectNearbyCollectibles(GameLocation location)
19 | {
20 | int reach = Config.BalancedMode ? 1 : Config.AutoCollectRadius;
21 | foreach (SVObject obj in Util.GetObjectsWithin(reach))
22 | if (obj.IsSpawnedObject || obj.isAnimalProduct())
23 | CollectObj(location, obj);
24 |
25 | Hoe hoe = Util.FindToolFromInventory(true);
26 | if (hoe == null) return;
27 | foreach (KeyValuePair kv in Util.GetFeaturesWithin(reach))
28 | if (IsGinger(kv.Value.crop))
29 | CollectGinger(location, kv.Key, kv.Value);
30 | }
31 | private static void CollectObj(GameLocation loc, SVObject obj)
32 | {
33 | Farmer who = Game1.player;
34 |
35 | Vector2 vector = Util.GetLocationOf(loc, obj);
36 |
37 | if ((int)vector.X == -1 && (int)vector.Y == -1) return;
38 | if (obj.questItem.Value) return;
39 |
40 | int quality = obj.Quality;
41 | Random random = new Random((int)Game1.uniqueIDForThisGame / 2 + (int)Game1.stats.DaysPlayed + (int)vector.X + (int)vector.Y * 777);
42 |
43 | if (who.professions.Contains(16) && obj.isForage())
44 | {
45 | obj.Quality = 4;
46 | }
47 |
48 | else if (obj.isForage())
49 | {
50 | if (random.NextDouble() < who.ForagingLevel / 30f)
51 | {
52 | obj.Quality = 2;
53 | }
54 | else if (random.NextDouble() < who.ForagingLevel / 15f)
55 | {
56 | obj.Quality = 1;
57 | }
58 | }
59 |
60 | if (who.couldInventoryAcceptThisItem(obj))
61 | {
62 | Logger.Log($"picked up {obj.DisplayName} at [{vector.X},{vector.Y}]");
63 | if (who.IsLocalPlayer)
64 | {
65 | loc.localSound("pickUpItem");
66 | DelayedAction.playSoundAfterDelay("coin", 300);
67 | }
68 |
69 | if (!who.isRidingHorse() && !who.ridingMineElevator)
70 | {
71 | who.animateOnce(279 + who.FacingDirection);
72 | }
73 |
74 | if (!loc.isFarmBuildingInterior())
75 | {
76 | if (obj.isForage())
77 | {
78 | who.gainExperience(2, 7);
79 | }
80 | }
81 | else
82 | {
83 | who.gainExperience(0, 5);
84 | }
85 |
86 | who.addItemToInventoryBool(obj.getOne());
87 | Game1.stats.ItemsForaged++;
88 | if (who.professions.Contains(13) && random.NextDouble() < 0.2 && !obj.questItem.Value && who.couldInventoryAcceptThisItem(obj) && !loc.isFarmBuildingInterior())
89 | {
90 | who.addItemToInventoryBool(obj.getOne());
91 | who.gainExperience(2, 7);
92 | }
93 | loc.Objects.Remove(vector);
94 | return;
95 | }
96 | obj.Quality = quality;
97 | }
98 |
99 | private static bool IsGinger(Crop crop)
100 | {
101 | return crop != null && crop.forageCrop.Value && crop.whichForageCrop.Value == Crop.forageCrop_ginger.ToString();
102 | }
103 |
104 | private static void CollectGinger(GameLocation loc, Vector2 pos, HoeDirt dirt)
105 | {
106 | Farmer who = Game1.player;
107 | float stamina = 2 - who.FarmingLevel * 0.1f;
108 | if (who.Stamina < stamina)
109 | {
110 | return;
111 | }
112 |
113 | if (dirt.crop.hitWithHoe((int)pos.X, (int)pos.Y, loc,dirt))
114 | {
115 | who.Stamina -= stamina;
116 | dirt.destroyCrop(true);
117 | }
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Huds/GiftInformationTooltip.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Text;
4 | using GloryOfEfficiency.Core;
5 | using GloryOfEfficiency.Utils;
6 | using Microsoft.Xna.Framework;
7 | using StardewModdingAPI;
8 | using StardewValley;
9 |
10 | namespace GloryOfEfficiency.Huds
11 | {
12 | public class GiftInformationTooltip
13 | {
14 |
15 | private static bool _unableToGift;
16 | private static string _hoverText;
17 |
18 | public static void UpdateTooltip()
19 | {
20 | _hoverText = null;
21 | if (!Context.IsPlayerFree)
22 | {
23 | return;
24 | }
25 | Farmer player = Game1.player;
26 | _unableToGift = false;
27 | if (Game1.player.CurrentItem == null || !player.CurrentItem.canBeGivenAsGift() || player.currentLocation == null || player.currentLocation.characters.Count == 0)
28 | {
29 | return;
30 | }
31 |
32 | List npcList = player.currentLocation.characters.Where(a => a != null && a.IsVillager).ToList();
33 | foreach (NPC npc in npcList)
34 | {
35 | Rectangle npcRect = new Rectangle(
36 | (int)npc.position.X,
37 | (int)(npc.position.Y - npc.Sprite.getHeight() - Game1.tileSize / 1.5f),
38 | (int)(npc.Sprite.getWidth() * 3 + npc.Sprite.getWidth() / 1.5f),
39 | (int)(npc.Sprite.getHeight() * 3.5f)
40 | );
41 |
42 | if (!npcRect.Contains(
43 | Game1.getMouseX() + Game1.viewport.X,
44 | Game1.getMouseY() + Game1.viewport.Y))
45 | {
46 | continue;
47 | }
48 |
49 | //Mouse hovered on the NPC
50 | StringBuilder key = new StringBuilder("taste.");
51 | if (player.friendshipData.ContainsKey(npc.Name) && Game1.NPCGiftTastes.ContainsKey(npc.Name))
52 | {
53 | Friendship friendship = player.friendshipData[npc.Name];
54 | if (friendship.GiftsThisWeek >= 2 && !IsNpcMarriedWithPlayer(npc, player))
55 | {
56 | key.Append("gavetwogifts.");
57 | _unableToGift = true;
58 | }
59 | else if (friendship.GiftsToday > 0)
60 | {
61 | //Day restriction
62 | key.Append("gavetoday.");
63 | _unableToGift = true;
64 | }
65 | else if (npc.tryToReceiveActiveObject(player, probe: true))
66 | {
67 | switch (npc.getGiftTasteForThisItem(player.CurrentItem))
68 | {
69 | case 0:
70 | key.Append("love.");
71 | break;
72 | case 2:
73 | key.Append("like.");
74 | break;
75 | case 4:
76 | key.Append("dislike.");
77 | break;
78 | case 6:
79 | key.Append("hate.");
80 | break;
81 | default:
82 | key.Append("neutral.");
83 | break;
84 | }
85 | }
86 | else
87 | {
88 | return;
89 | }
90 | }
91 | switch (npc.Gender)
92 | {
93 | case Gender.Female:
94 | key.Append("female");
95 | break;
96 | default:
97 | key.Append("male");
98 | break;
99 | }
100 | _hoverText = InstanceHolder.Translation.Get(key.ToString());
101 | }
102 | }
103 |
104 | internal static void DrawTooltip()
105 | {
106 | if (Context.IsPlayerFree && !string.IsNullOrEmpty(_hoverText) && Game1.player.CurrentItem != null)
107 | {
108 | Util.DrawSimpleTextbox(Game1.spriteBatch, _hoverText, Game1.dialogueFont,null, false, _unableToGift ? null : Game1.player.CurrentItem);
109 | }
110 | }
111 |
112 | private static bool IsNpcMarriedWithPlayer(NPC npc, Farmer player)
113 | {
114 | return npc.isMarried() && npc.getSpouse().UniqueMultiplayerID == player.UniqueMultiplayerID;
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/i18n/zh.json:
--------------------------------------------------------------------------------
1 | {
2 | "button.awaiting": "按键分配...",
3 | "button.conflict": "你按下的键有冲突",
4 | "button.esc": "按 Esc 取消",
5 |
6 | "estimatedprice.title": "预估价格",
7 |
8 | "fishinfo.quality": "品质: ",
9 | "fishinfo.size": "尺寸: {0} 厘米",
10 | "fishinfo.species": "品种: {0}",
11 | "fishinfo.treasure.appear": "宝箱出现了!",
12 | "fishinfo.treasure.caught": "获得了宝箱!",
13 | "fishinfo.treasure.incoming": "宝箱在 {0:f1} 秒后出现。",
14 | "fishinfo.price": "出售价格:{0}G",
15 |
16 | "hud.paused": "游戏暂停",
17 |
18 | "ladder": "梯子出现了!",
19 |
20 | "location.awaiting": "单击某处以指定所需的位置。",
21 |
22 | "monsters.tally": "{0}:{1} 击杀",
23 |
24 | "options.AnimalHarvestRadius": "搜索动物的地图格半径",
25 | "options.AutoAnimalDoor": "自动开启/关闭畜棚门",
26 | "options.AutoCollectCollectibles": "自动收集附近藏品",
27 | "options.AutoCollectRadius": "自动收集范围",
28 | "options.AutoDepositIngredient": "自动投放持有材料至机器",
29 | "options.AutoDestroyDeadCrops": "自动收割附近枯萎作物",
30 | "options.AutoDigArtifactSpot": "自动挖掘附近人工痕迹",
31 | "options.AutoDigRadius": "自动挖掘范围",
32 | "options.AutoEat": "自动在低状态下进食",
33 | "options.AutoFishing": "自动进行钓鱼",
34 | "options.AutoGate": "自动开启/关闭门",
35 | "options.AutoHarvest": "自动收获成熟作物",
36 | "options.AutoHarvestRadius": "自动收获范围",
37 | "options.AutoLootTreasures": "自动获取宝箱中所有可接受的物品",
38 | "options.AutoPetNearbyAnimals": "自动抚摸附近动物",
39 | "options.AutoPetNearbyPets": "自动抚摸附近宠物",
40 | "options.AutoPetRadius": "自动抚摸范围",
41 | "options.AutoPickUpTrash": "自动搜索附近的垃圾桶",
42 | "options.AutoPullMachineResult": "自动收集机器产物",
43 | "options.AutoReelRod": "自动拉起鱼竿",
44 | "options.AutoRefillWateringCan": "自动填充水壶(附近有水时)",
45 | "options.AutoShakeFruitedPlants": "自动摇晃附近果树",
46 | "options.AutoShakeRadius": "自动摇晃范围",
47 | "options.AutoShearingAndMilking": "自动剪羊毛/挤奶",
48 | "options.AutoWaterNearbyCrops": "自动浇水",
49 | "options.AutoWaterRadius": "自动浇水范围",
50 | "options.BalancedMode": "切换平衡模式",
51 | "options.CloseTreasureWhenAllLooted": "拿完东西后自动关闭宝箱",
52 | "options.CollectLetterAttachmentsAndQuests": "自动收取信封附件和接取任务",
53 | "options.CPUThresholdFishing": "智能操作状态条频繁度",
54 | "options.CraftingFromChests": "用附近箱子中物品制造物品",
55 | "options.EstimateShippingPrice": "预估物品价格",
56 | "options.FilterBackgroundInMenu": "配置菜单之外的颜色变暗",
57 | "options.FindCanFromInventory": "从背包中自动寻找水壶",
58 | "options.FindHoeFromInventory": "从背包中自动寻找锄头",
59 | "options.FishInfo": "显示钓鱼信息",
60 | "options.FishingInfo": "显示钓鱼信息",
61 | "options.FishingProbabilitiesInfo": "显示鱼的上竿几率",
62 | "options.FishingTackleInfo": "绘制当前的鱼饵和浮标",
63 | "options.TackleBoxAttach": "将钓具盒连接到鱼类概率盒",
64 | "options.TackleBoxLocation": "信息框的左上角坐标",
65 | "options.ProbBoxMaxFish": "每列的鱼数",
66 | "options.GiftInformation": "显示礼物提示",
67 | "options.HealthToEatRatio": "自动进食阈值(生命值)",
68 | "options.IdleTimeout": "暂停游戏的空闲超时",
69 | "options.KeyShowMenu": "显示设置菜单按键",
70 | "options.KeyToggleBlackList": "切换收获黑名单按键",
71 | "options.MachineRadius": "寻找机器范围",
72 | "options.MineInfoGui": "显示矿洞信息图标",
73 | "options.MuchFasterBiting": "快速进食",
74 | "options.PauseWhenIdle": "闲置时暂停",
75 | "options.ProbBoxLocation": "信息框的左上角坐标",
76 | "options.MorePreciseProbabilities": "计算更精确的概率",
77 | "options.TrialOfExamine": "计算概率数",
78 | "options.ProtectNectarProducingFlower": "保护蜂箱附近的花",
79 | "options.RadiusCraftingFromChests": "寻找箱子范围",
80 | "options.ScavengingRadius": "垃圾桶搜索范围",
81 | "options.StaminaToEatRatio": "自动进食阈值(体力值)",
82 | "options.UnifyFlowerColors": "将花的颜色统一",
83 | "options.ShowMousePositionWhenAssigningLocation": "分配坐标时显示鼠标位置",
84 | "options.ButtonToggleFlowerColorUnification": "注册/取消注册花朵颜色以实现统一",
85 | "options.RadiusFarmCleanup": "清洁农场的地图格半径",
86 | "options.CutWeeds": "切杂草(镰刀)",
87 | "options.BreakRocks": "打破小石头(镐)",
88 | "options.ChopTwigs": "砍树枝(斧头)",
89 | "options.PriceBoxCoordinates": "信息框的左上角坐标",
90 |
91 | "options.ThrowPower": "鱼钩投掷力度",
92 | "options.ThresholdStaminaPersentage": "停止钓鱼的体力值",
93 |
94 | "options.ToggleAFKFishing": "切换 AFK 钓鱼模式",
95 |
96 | "hud.afk.passedout": "已停止钓鱼,因为你昏过去了。",
97 | "hud.afk.on": "AFK 钓鱼模式开启",
98 | "hud.afk.off": "AFK 钓鱼模式关闭",
99 | "hud.afk.tired": "已停止钓鱼,因为你累了。",
100 |
101 | "options.flower": "花:{0}",
102 | "options.R": "R",
103 | "options.G": "G",
104 | "options.B": "B",
105 | "options.previewColor": "预览颜色:",
106 | "options.register": "注册",
107 |
108 | "flower.register": "{0}的颜色将统一",
109 | "flower.unregister": "{0}的颜色将不再统一",
110 | "flower.vanilla": "不能取消注册原版的花。",
111 |
112 | "quality.gold": "金",
113 | "quality.iridium": "铱",
114 | "quality.normal": "一般",
115 | "quality.silver": "银",
116 | "stones.many": "这层还有 {0} 块石头",
117 | "stones.none": "这层没有石头",
118 | "stones.one": "这层还有一块石头",
119 | "tab.automation": "自动化",
120 | "tab.cheats": "作弊",
121 | "tab.controls": "控制",
122 | "tab.misc": "杂项",
123 | "tab.UIs": "用户界面",
124 | "taste.dislike.female": "她不喜欢这个礼物",
125 | "taste.dislike.male": "他不喜欢这个礼物",
126 | "taste.gavetoday.female": "今天你给过她礼物了",
127 | "taste.gavetoday.male": "今天你给过他礼物了",
128 | "taste.gavetwogifts.female": "这周你给过她两次礼物了",
129 | "taste.gavetwogifts.male": "这周你给过他两次礼物了",
130 | "taste.hate.female": "她不喜欢这个礼物",
131 | "taste.hate.male": "他不喜欢这个礼物",
132 | "taste.like.female": "她喜欢这个礼物",
133 | "taste.like.male": "他喜欢这个礼物",
134 | "taste.love.female": "她最爱这个礼物",
135 | "taste.love.male": "他最爱这个礼物",
136 | "taste.neutral.female": "她对这份礼物持中立态度",
137 | "taste.neutral.male": "他对这份礼物持中立态度"
138 | }
139 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/FoodAutomation.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using GloryOfEfficiency.Core;
4 | using GloryOfEfficiency.Utils;
5 | using StardewModdingAPI;
6 | using StardewValley;
7 | using StardewValley.Tools;
8 | using StardewModdingAPI.Events;
9 | using StardewValley.GameData.Objects;
10 | using SVObject = StardewValley.Object;
11 |
12 | namespace GloryOfEfficiency.Automation
13 | {
14 | internal class FoodAutomation
15 | {
16 | private static Config Config => InstanceHolder.Config;
17 | private static readonly Logger Logger = new Logger("FoodAutomation");
18 | private static HashSet _dontEat = new HashSet();
19 |
20 | public static void TryToEatIfNeeded(Farmer player)
21 | {
22 | if (player.isEating || Game1.activeClickableMenu != null)
23 | {
24 | return;
25 | }
26 |
27 | if (player.CurrentTool != null && player.CurrentTool is FishingRod rod)
28 | {
29 | if (rod.inUse() && !player.UsingTool)
30 | {
31 | return;
32 | }
33 | }
34 |
35 | if (!(player.Stamina <= player.MaxStamina * Config.StaminaToEatRatio) &&
36 | !(player.health <= player.maxHealth * Config.HealthToEatRatio))
37 | {
38 | return;
39 | }
40 |
41 | SVObject itemToEat = null;
42 | foreach (SVObject item in player.Items.OfType())
43 | {
44 | if (item.Edibility <= 0)
45 | continue;
46 |
47 | //It's a edible item
48 | if (itemToEat == null ||
49 | itemToEat.Edibility / itemToEat.salePrice() < item.Edibility / item.salePrice())
50 | {
51 | //Found good edibility per price or just first food
52 | itemToEat = item;
53 | }
54 | }
55 |
56 | if (itemToEat == null)
57 | {
58 | return;
59 | }
60 |
61 | player.eatObject(itemToEat);
62 | itemToEat.Stack--;
63 | if (itemToEat.Stack == 0)
64 | {
65 | player.removeItemFromInventory(itemToEat);
66 | }
67 | }
68 |
69 |
70 | // Don't Eat This mod copied and update here! Liberated from Pyrohead37.
71 | public static void InitDontEat()
72 | {
73 | _dontEat.Clear();
74 | // public const int artisanGoodsCategory = -26;
75 | // public const int ingredientsCategory = -25;
76 | // public const int meatCategory = -14;
77 | // public const int flowersCategory = -80;
78 | // public const int FruitsCategory = -79;
79 | // public const int VegetableCategory = -75;
80 | // public const int FishCategory = -4;
81 | // public const int EggCategory = -5;
82 | // public const int MilkCategory = -6;
83 | // public const int CookingCategory = -7;
84 | // public const int inedible = -300;
85 | // public const int GreensCategory = -81;
86 |
87 | // Go through all game objects and add any that are in our DontEatCategories first
88 | foreach (KeyValuePair item in Game1.objectData)
89 | {
90 | string itemName = item.Value.Name;
91 | int itemEdibility = item.Value.Edibility;
92 | int itemCategory = item.Value.Category;
93 | string categoryName = Object.GetCategoryDisplayName(itemCategory);
94 |
95 | if (itemEdibility == -300) { continue; }
96 | if (Config.DontEatCategories.Contains(categoryName))
97 | {
98 | _dontEat.Add(itemName);
99 | Logger.Log($"Adding from Category [{item.Key}] {itemName} to the diet\t({categoryName})");
100 | }
101 | }
102 |
103 | // Add individual items from DontEat list
104 | foreach (var item in Config.DontEat)
105 | {
106 | _dontEat.Add(item);
107 | Logger.Log($"Adding from DontEat {item} to the diet\t");
108 | }
109 |
110 | // REMOVE any items in the DoEat list! This must be last!
111 | foreach (var item in Config.DoEat)
112 | {
113 | _dontEat.Remove(item);
114 | Logger.Log($"REMOVING from DontEat {item}\t(DoEat exception)");
115 | }
116 |
117 | _dontEat.TrimExcess();
118 | }
119 |
120 | public static void ButtonPressed(object sender, ButtonPressedEventArgs e)
121 | {
122 | SVObject activePlayerItem = Game1.player.ActiveObject;
123 |
124 | if (Config.DontEatThat && Context.IsWorldReady && e.Button.IsActionButton() && activePlayerItem != null)
125 | {
126 | string itemName = activePlayerItem.DisplayName;
127 |
128 | // Logger.Log($"Testing item {itemName} for dontEatability");
129 | if (_dontEat.Contains(itemName))
130 | {
131 | activePlayerItem.Edibility = -300;
132 | Logger.Log($"Don't eat that {activePlayerItem.DisplayName}! Spoofing inedibility.");
133 | }
134 | }
135 | }
136 | }
137 |
138 |
139 | }
140 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/OptionsElements/ModifiedClickListener.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GloryOfEfficiency.Core;
3 | using GloryOfEfficiency.Utils;
4 | using Microsoft.Xna.Framework;
5 | using Microsoft.Xna.Framework.Graphics;
6 | using Microsoft.Xna.Framework.Input;
7 | using StardewModdingAPI;
8 | using StardewValley;
9 | using StardewValley.Menus;
10 |
11 | namespace GloryOfEfficiency.OptionsElements
12 | {
13 | internal class ModifiedClickListener : OptionsElement
14 | {
15 | private bool _isListening;
16 | private Point _point;
17 |
18 | private readonly Action _onStartListening;
19 | private readonly Action _onSomewhereClicked;
20 | private Rectangle _buttonRect;
21 |
22 | private bool _isSuppressed;
23 |
24 | private static readonly SpriteFont Font = Game1.dialogueFont;
25 |
26 | private readonly ITranslationHelper _translation;
27 | private readonly IClickableMenu _menu;
28 |
29 | public ModifiedClickListener(IClickableMenu parent ,string label, int which, int initialX, int initialY, ITranslationHelper translationHelper, Action onSomewhereClicked, Action onStartListening = null) : base(label, -1, -1, 9 * Game1.pixelZoom, 9 * Game1.pixelZoom, 0)
30 | {
31 | this.label = InstanceHolder.Translation.Get($"options.{label}");
32 | _point = new Point(initialX, initialY);
33 | _onSomewhereClicked = onSomewhereClicked;
34 | _translation = translationHelper;
35 | _onStartListening = onStartListening ?? ((i,obj) => { });
36 | whichOption = which;
37 | _menu = parent;
38 | }
39 |
40 | public override void draw(SpriteBatch b, int slotX, int slotY, IClickableMenu context = null)
41 | {
42 | string text = $"{label}: [{_point.X},{_point.Y}]";
43 | Vector2 size = Game1.dialogueFont.MeasureString(text);
44 | b.DrawString(Game1.dialogueFont, text, new Vector2(slotX+16, slotY + 8), Color.Black, 0, new Vector2(), 1f, SpriteEffects.None, 1.0f);
45 |
46 | int x = slotX + (int)size.X + 24;
47 |
48 | _buttonRect = new Rectangle(x, slotY, 90, 45);
49 | bounds = new Rectangle(0, 0, (int)size.X + _buttonRect.Width, _buttonRect.Height);
50 |
51 | b.Draw(Game1.mouseCursors, _buttonRect, new Rectangle(294, 428, 21, 11), Color.White, 0, Vector2.Zero, SpriteEffects.None, 1.0f);
52 | }
53 |
54 | public override void receiveLeftClick(int x, int y)
55 | {
56 | if (_isSuppressed)
57 | {
58 | return;
59 | }
60 | base.receiveLeftClick(x, y);
61 | if (_isListening)
62 | {
63 | _isListening = false;
64 | _point = new Point(x, y);
65 | _onSomewhereClicked(whichOption, new Point(x, y));
66 | return;
67 | }
68 |
69 | x += _menu.xPositionOnScreen;
70 | y += _buttonRect.Height / 2;
71 | if (x >= _buttonRect.Left && x <= _buttonRect.Right)
72 | {
73 | _isSuppressed = true;
74 | _onStartListening(whichOption, this);
75 | _isListening = true;
76 | }
77 | }
78 |
79 | public override void receiveKeyPress(Keys key)
80 | {
81 | if (_isListening && key.HasFlag(Keys.Escape))
82 | {
83 | _isListening = false;
84 | _onSomewhereClicked(-1, Point.Zero);
85 | }
86 | base.receiveKeyPress(key);
87 | }
88 |
89 | public override void leftClickReleased(int x, int y)
90 | {
91 | base.leftClickReleased(x, y);
92 | if (_isSuppressed)
93 | {
94 | _isSuppressed = false;
95 | }
96 | }
97 |
98 | public void DrawStrings(SpriteBatch batch, int x, int y)
99 | {
100 | x += 16;
101 | y += 16;
102 | {
103 | Vector2 size = Font.MeasureString(_translation.Get("location.awaiting"));
104 | batch.DrawString(Font, _translation.Get("location.awaiting"), new Vector2(x, y), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);
105 | y += (int)size.Y + 8;
106 |
107 | batch.DrawString(Font, _translation.Get("button.esc"), new Vector2(x, y), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);
108 |
109 | if (InstanceHolder.Config.ShowMousePositionWhenAssigningLocation)
110 | {
111 | Util.DrawSimpleTextbox(batch, $"[{Game1.getMouseX()},{Game1.getMouseY()}]", Game1.dialogueFont, this);
112 | }
113 | }
114 | }
115 |
116 | public Point GetListeningMessageWindowSize()
117 | {
118 | int x = 32;
119 | int y = 16;
120 |
121 | {
122 | Vector2 size = Font.MeasureString(_translation.Get("location.awaiting"));
123 | x += (int)size.X;
124 | y += (int)size.Y;
125 | }
126 | {
127 | Vector2 size = Font.MeasureString(_translation.Get("button.esc"));
128 | if(size.X + 16 > x)
129 | {
130 | x = (int)size.X + 16;
131 | }
132 | y += (int)size.Y + 16;
133 | }
134 |
135 | return new Point(x, y);
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "button.awaiting": "Drücke eine Taste für die Zuweisung...",
3 | "button.conflict": "Die Taste, die gedrückt wurde, ist bereits belegt",
4 | "button.esc": " Drücke Esc um abzubrechen",
5 | "estimatedprice.title": "Geschätzter Versandpreis",
6 | "fishinfo.quality": "Qualität: ",
7 | "fishinfo.size": "Größe: {0}cm",
8 | "fishinfo.species": "Art: {0}",
9 | "fishinfo.treasure.appear": "Schatz erschienen!",
10 | "fishinfo.treasure.caught": "Schatz gefangen!",
11 | "fishinfo.treasure.incoming": "Schatz erscheint in {0:f1}s.",
12 | "hud.paused": "Pausierte das Spiel",
13 | "ladder": "Leiter ist erschienen!",
14 | "monsters.tally": "{0}: {1} Tötungen",
15 | "options.AutoAnimalDoor": "Öffnet/Schließt die Stalltore automatisch",
16 | "options.AutoCollectCollectibles": "Automatisches Einsammeln der sammelbaren Dinge",
17 | "options.AutoCollectRadius": "Wie viele Felder weit gesammelt wird",
18 | "options.AutoDepositIngredient": "Automatisches Befüllen von Maschinen mit dem ausgewählten Gegenstand",
19 | "options.AutoDestroyDeadCrops": "Automatische Vernichtung verrotterter Pflanzen ",
20 | "options.AutoDigArtifactSpot": "Automatisches Graben bei nahem Artifaktstellen",
21 | "options.AutoDigRadius": "Wie viele Felder weit gegraben wird",
22 | "options.AutoEat": "Automatisches Essen",
23 | "options.AutoFishing": "Automatisches Fisch-Minigame durch die KI",
24 | "options.AutoGate": "Öffnet & Schließt Tore automatisch",
25 | "options.AutoHarvest": "Automatische Ernte",
26 | "options.AutoHarvestRadius": "Wie viele Felder weit geerntet werden",
27 | "options.AutoPetNearbyAnimals": "Automatisches Streicheln der Tiere in deiner Nähe",
28 | "options.AutoPetNearbyPets": "Automatisches Streicheln naher Tiere",
29 | "options.AutoPetRadius": "Wie viele Felder für das Streicheln erkannt werden",
30 | "options.AutoPickUpTrash": "Beute-Mülltonnen in der Nähe",
31 | "options.AutoPullMachineResult": "Automatisches Einholen von Maschinenerzeugnissen",
32 | "options.AutoReelRod": "Automatische Angeleinholung",
33 | "options.AutoRefillWateringCan": "Automatisches Auffüllen der Giesskanne",
34 | "options.AutoShakeFruitedPlants": "Automatisches Schütteln der nächsten Obstpflanzen",
35 | "options.AutoShakeRadius": "Wie viele Felder weit geschüttelt wird",
36 | "options.AutoWaterNearbyCrops": "Automatische Bewässerung",
37 | "options.AutoWaterRadius": "Wie viele Felder sollen bewässert werden",
38 | "options.BalancedMode": "Aktiviere den ausgeglichenen Modus",
39 | "options.CavernFloorIntervalToSave": "Der Minenfortschritt wird alle {0} Etagen gespeichert",
40 | "options.CPUThresholdFishing": "Wie oft die KI beim Fischen agiert",
41 | "options.CraftingFromChests": "Basteln mit Gegenständen in nahegelegenen Truhen",
42 | "options.EstimateShippingPrice": "Schätzen Sie den Preis der versandte Produkte",
43 | "options.FindCanFromInventory": "Finde im Inventar automatisch die Gießkanne",
44 | "options.FindHoeFromInventory": "Finde die Hake im Inventar",
45 | "options.FishInfo": "Zeige stets die Infobox fürs Fischen",
46 | "options.FishingInfo": "Zeigt die Infobox beim Fischen",
47 | "options.FishingProbabilitiesInfo": "Zeige die Wahrscheinlichkeit der Fische",
48 | "options.FishingTackleInfo": "Ziehen Sie aktuelle Köder und Bobber",
49 | "options.TackleBoxAttach": "Befestigen Sie die Angelbox an der Fischwahrscheinlichkeitsbox",
50 | "options.TackleBoxLocation": "Koordinaten oben links für das Informationsfeld",
51 | "options.ProbBoxMaxFish": "Anzahl der Fische pro Spalte",
52 | "options.GiftInformation": "Zeige den Tooltip für Geschenke",
53 | "options.HealthToEatRatio": "Automatisches Essen, um Gesundheit aufzufüllent",
54 | "options.IdleTimeout": "Leerlauf-Timeout für das Pausieren des Spiels",
55 | "options.KeyShowMenu": "Taste, um das Einstellungs-Menü zu zeigen",
56 | "options.KeyToggleBlackList": "Taste um harvest blacklist",
57 | "options.MachineRadius": "Wie viele Felder weit eingeholt wird",
58 | "options.MineInfoGui": "Zeigt Icons der Mine",
59 | "options.MuchFasterBiting": "Verkürzt die Einholzeit auf sofort",
60 | "options.PauseWhenIdle": "Pause im Leerlauf",
61 | "options.ProtectNectarProducingFlower": "Nehme Blumen nahe eines Bienenhauses davon aus",
62 | "options.RadiusCraftingFromChests": "Kacheln zum Auffinden von Truhen",
63 | "options.SaveSkullCavernLevel": "Sichere den Schädelhölenfortschritt",
64 | "options.ScavengingRadius": "How far tiles to search trash can",
65 | "options.StaminaToEatRatio": "Automatisches Essen, um Ausdauer aufzufüllenr",
66 | "options.UnifyFlowerColors": "Vereinheitlichung der Farben von Blumen",
67 | "quality.gold": "Gold",
68 | "quality.iridium": "Iridium",
69 | "quality.normal": "Normal",
70 | "quality.silver": "Silber",
71 | "stones.many": "Es gibt {0} Steine in dieser Etage",
72 | "stones.none": "Es gibt keinen Stein auf dieser Etage",
73 | "stones.one": "Auf diese Etage gibt es noch einen Stein",
74 | "tab.automation": "Automation",
75 | "tab.cheats": "Cheats",
76 | "tab.controls": "Einstellungen",
77 | "tab.misc": "Sonstiges",
78 | "tab.UIs": "Benutzer-Schnittstellen",
79 | "taste.dislike.female": "Sie mag dieses Geschenk nicht",
80 | "taste.dislike.male": "Er mag dieses Geschenk nicht",
81 | "taste.hate.female": "Sie hasst dieses Geschenk",
82 | "taste.hate.male": "Er hasst dieses Geschenk",
83 | "taste.like.female": "Sie mag dieses Geschenk",
84 | "taste.like.male": "Er mag dieses Geschenk",
85 | "taste.love.female": "Sie liebt dieses Geschenk",
86 | "taste.love.male": "Er liebt dieses Geschenk",
87 | "taste.neutral.female": "Sie steht diesem Geschenk neutral gegenüber",
88 | "taste.neutral.male": "Er steht diesem Geschenk neutral gegenüber"
89 | }
--------------------------------------------------------------------------------
/GloryOfEfficiency/i18n/es.json:
--------------------------------------------------------------------------------
1 | {
2 | "button.awaiting": "Presione la tecla para asignar...",
3 | "button.conflict": "La tecla presionada está en conflicto",
4 | "button.esc": "Presione la tecla Esc para cancelar",
5 | "estimatedprice.title": "Precio estimado de envío",
6 | "fishinfo.quality": "Calidad: ",
7 | "fishinfo.size": "Tamaño: {0}cm",
8 | "fishinfo.species": "Especie: {0:f1}",
9 | "fishinfo.treasure.appear": "¡Apareció el tesoro!",
10 | "fishinfo.treasure.caught": "Tesoro capturado!",
11 | "fishinfo.treasure.incoming": "Tesoro es entrante en {0:f1}s.",
12 | "hud.paused": "Pausó el juego",
13 | "ladder": "¡Ha aparecido la escalera!",
14 | "monsters.tally": "{0}: {1} muertes",
15 | "options.AutoAnimalDoor": "Abrir/cerrar la puerta de los animales automáticamente",
16 | "options.AutoCollectCollectibles": "Colecciona objetos de colección en las cercanías",
17 | "options.AutoCollectRadius": "Azulejos para coleccionar",
18 | "options.AutoDepositIngredient": "Deposite el ingrediente que aferró a las máquinas",
19 | "options.AutoDepositSeedMaker": "\tDeposite el ingrediente en los Seed Makers",
20 | "options.AutoDestroyDeadCrops": "Destruir las cosechas muertas cercanas",
21 | "options.AutoDigArtifactSpot": "Cavando un artefacto cercano",
22 | "options.AutoDigRadius": "Baldosas para excavación",
23 | "options.AutoEat": "Auto-comer algo si está en apuros",
24 | "options.AutoFishing": "Minijuego automático de pesca",
25 | "options.AutoGate": "Abrir/cerrar automáticamente las puertas de la valla",
26 | "options.AutoHarvest": "Cultivos autocosechados",
27 | "options.AutoHarvestRadius": "azulejos para cosechar",
28 | "options.AutoLootTreasures": "Auto Loot de la caja del tesoro",
29 | "options.AutoPetNearbyAnimals": "Auto acariciar animales cerca",
30 | "options.AutoPetNearbyPets": "Acariciar cerca de mascota",
31 | "options.AutoPetRadius": "Azulejos para encontrar animales",
32 | "options.AutoPickUpTrash": "Saquear los botes de basura cercanos",
33 | "options.AutoPullMachineResult": "Tirar de los resultados de las máquinas",
34 | "options.AutoReelRod": "Auto devanado cuando los peces mordisquean",
35 | "options.AutoRefillWateringCan": "Rellenar la regadera cerca del agua",
36 | "options.AutoShakeFruitedPlants": "Agitar las plantas frutales cercanas",
37 | "options.AutoShakeRadius": "Aazulejos para agitar",
38 | "options.AutoWaterNearbyCrops": "Riego automático a cultivos",
39 | "options.AutoWaterRadius": "Baldosas para regar",
40 | "options.BalancedMode": "Alternar el modo balanceado",
41 | "options.EveryNthTick": "Actualizar cada N Ticks",
42 | "options.CloseTreasureWhenAllLooted": "Cerrar la caja del tesoro cuando haya robado todo",
43 | "options.CPUThresholdFishing": "Con qué frecuencia AI opera la barra",
44 | "options.CraftingFromChests": "Artesanías de los cofres cercanos",
45 | "options.EstimateShippingPrice": "Mostrar el precio de los productos enviados",
46 | "options.FindCanFromInventory": "Buscar regadera en el inventario",
47 | "options.FindHoeFromInventory": "Buscar azada en el inventario",
48 | "options.FishInfo": "Dibujar información de peces",
49 | "options.FishingInfo": "Dibujar el cuadro de información de pesca",
50 | "options.FishingProbabilitiesInfo": "Dibujar probabilidades de pesca",
51 | "options.FishingTackleInfo": "Dibujar cebos y bobbers actuales",
52 | "options.TackleBoxAttach": "Adjunte la caja de aparejos a la caja de probabilidades de pescar.",
53 | "options.TackleBoxLocation": "Coordenadas superior izquierda para el cuadro de información.",
54 | "options.ProbBoxMaxFish": "Número de peces por columna",
55 | "options.GiftInformation": "Mostrar información de regalos",
56 | "options.HealthToEatRatio": "Salud para comer auto",
57 | "options.IdleTimeout": "Tiempo de espera para pausar el juego",
58 | "options.KeyShowMenu": "Tecla para mostrar el menú de ajustes",
59 | "options.KeyToggleBlackList": "Tecla para activar la lista negra de cosecha",
60 | "options.MachineRadius": "Azulejos para encontrar máquinas",
61 | "options.MineInfoGui": "Dibujar la mina Información Iconos",
62 | "options.MuchFasterBiting": "Reduce el tiempo de mordisqueo a inmediato",
63 | "options.PauseWhenIdle": "Pausa el juego cuando está inactivo",
64 | "options.ProtectNectarProducingFlower": "Proteger las flores cerca de las casas de las abejas",
65 | "options.RadiusCraftingFromChests": "Baldosas para encontrar cofres",
66 | "options.ScavengingRadius": "Qué tan lejos las baldosas para buscarlo",
67 | "options.StaminaToEatRatio": "Resistencia para comer auto",
68 | "options.UnifyFlowerColors": "Unificar los colores de las flores",
69 | "options.DontEatThat": "Habilitar 'No Comas Eso(tm)'",
70 | "quality.gold": "Oro",
71 | "quality.iridium": "Iridium",
72 | "quality.normal": "Normal",
73 | "quality.silver": "Plata",
74 | "stones.many": "Hay {0} piedras en este piso",
75 | "stones.none": "No hay ninguna piedra a la izquierda en este piso",
76 | "stones.one": "Hay una piedra en este piso",
77 | "tab.automation": "Automatización",
78 | "tab.cheats": "Trucos",
79 | "tab.controls": "Controles",
80 | "tab.UIs": "Interfaces de usuario",
81 | "taste.dislike.female": "No le gusta este regalo",
82 | "taste.dislike.male": "No le gusta este regalo",
83 | "taste.hate.female": "Ella odia este regalo",
84 | "taste.hate.male": "Él odia este regalo",
85 | "taste.like.female": "Ella le gusta este regalo",
86 | "taste.like.male": "Él le gusta este regalo",
87 | "taste.love.female": "Ella ama este regalo",
88 | "taste.love.male": "Él ama este regalo",
89 | "taste.neutral.female": "Ella tiene un sentimiento neutral acerca de este regalo",
90 | "taste.neutral.male": "Él tiene un sentimiento neutral acerca de este regalo"
91 | }
92 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/i18n/ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "button.awaiting": "割り当てるキーかボタンを押してください...",
3 | "button.conflict": "そのキーかボタンはすでに割り当てられています",
4 | "button.esc": "Escキーを押すとキャンセルできます",
5 | "location.awaiting": "座標をマウスカーソルで指定してクリックしてください",
6 |
7 | "estimatedprice.title": "出荷額",
8 |
9 | "fishinfo.quality": "品質: ",
10 | "fishinfo.size": "大きさ: {0}センチ",
11 | "fishinfo.species": "種: {0}",
12 | "fishinfo.treasure.appear": "宝箱が出現した",
13 | "fishinfo.treasure.caught": "宝物をゲットした",
14 | "fishinfo.treasure.incoming": "{0:f1}秒後に宝箱が出現する",
15 | "fishinfo.price": "売値:{0}G",
16 |
17 | "hud.paused": "一時停止中",
18 |
19 | "ladder": "はしごが出現した!",
20 | "monsters.tally": "{0}: {1}匹",
21 |
22 | "options.AnimalHarvestRadius": "動物を探す範囲",
23 | "options.AutoAnimalDoor": "動物のドアを自動で開閉",
24 | "options.AutoCollectCollectibles": "周りの収集物を採取",
25 | "options.AutoCollectRadius": "採取の範囲",
26 | "options.AutoDepositIngredient": "手に持った原料を機械に預ける",
27 | "options.AutoDestroyDeadCrops": "枯れた作物を破壊する",
28 | "options.AutoDigArtifactSpot": "遺物を自動で掘る",
29 | "options.AutoDigRadius": "掘る範囲",
30 | "options.AutoEat": "ピンチの時に自動で食べる",
31 | "options.AutoFishing": "自動釣り",
32 | "options.AutoGate": "ゲートを自動で開閉する",
33 | "options.AutoHarvest": "自動収穫",
34 | "options.AutoHarvestRadius": "収穫する範囲",
35 | "options.AutoLootTreasures": "宝箱の中身を自動取得",
36 | "options.AutoPetNearbyAnimals": "周りの動物をなでる",
37 | "options.AutoPetNearbyPets": "ペットをなでる",
38 | "options.AutoPetRadius": "なでる距離",
39 | "options.AutoPickUpTrash": "近くのゴミ箱を自動で漁る",
40 | "options.AutoPullMachineResult": "生成物を機械から取り出す",
41 | "options.AutoReelRod": "かかったときに自動で引く",
42 | "options.AutoRefillWateringCan": "じょうろに自動で水をいれる",
43 | "options.AutoShakeFruitedPlants": "自動で結実した植物を揺らす",
44 | "options.AutoShakeRadius": "揺らす範囲",
45 | "options.AutoShearingAndMilking": "収穫可能な牛や羊から自動で採取を行う",
46 | "options.AutoWaterNearbyCrops": "作物に自動で水やり",
47 | "options.AutoWaterRadius": "水やりの範囲",
48 | "options.BalancedMode": "バランスモード",
49 | "options.CavernFloorIntervalToSave": "保存するフロア間隔",
50 | "options.CloseTreasureWhenAllLooted": "宝物を全て回収したときに画面を閉じる",
51 | "options.CollectLetterAttachmentsAndQuests": "手紙に添付されたクエストやアイテムを自動取得する",
52 | "options.CPUThresholdFishing": "COMがどれほど操作するか",
53 | "options.CraftingFromChests": "クラフティングにチェストの中身を使える",
54 | "options.EstimateShippingPrice": "推定出荷額を表示",
55 | "options.FilterBackgroundInMenu": "メニュー画面の外側を暗くする",
56 | "options.FindCanFromInventory": "じょうろをインベントリから探す",
57 | "options.FindHoeFromInventory": "クワをインベントリから探す",
58 | "options.FishingInfo": "釣りの情報を表示",
59 | "options.FishingProbabilitiesInfo": "釣りの確率を表示",
60 | "options.FishingTackleInfo": "現在のベイトと浮きを描く",
61 | "options.TackleBoxAttach": "タックルボックスを魚の確率ボックスに取り付ける",
62 | "options.TackleBoxLocation": "情報ボックスの左上の座標",
63 | "options.ProbBoxMaxFish": "列ごとの魚の数",
64 | "options.GiftInformation": "贈り物情報を表示",
65 | "options.HealthToEatRatio": "体力しきい値",
66 | "options.IdleTimeout": "一時停止までの時間",
67 | "options.KeyShowMenu": "設定メニューを表示",
68 | "options.KeyToggleBlackList": "ブラックリストの切り替え",
69 | "options.MachineRadius": "機械の範囲",
70 | "options.MineInfoGui": "鉱山の情報を表示",
71 | "options.MuchFasterBiting": "とても速くかかる",
72 | "options.PauseWhenIdle": "放置でゲームを一時停止する",
73 | "options.ProbBoxLocation": "情報ウィンドウの左上座標",
74 | "options.ProtectNectarProducingFlower": "はちみつを生産している花を保護",
75 | "options.RadiusCraftingFromChests": "チェストを探す距離",
76 | "options.ScavengingRadius": "ゴミ箱を漁る範囲",
77 | "options.StaminaToEatRatio": "スタミナしきい値",
78 | "options.UnifyFlowerColors": "花の色を統一する",
79 | "options.ShowMousePositionWhenAssigningLocation": "座標指定時にマウス座標を表示",
80 | "options.MorePreciseProbabilities": "より正確な確率を計算",
81 | "options.TrialOfExamine": "確率の計算試行回数",
82 | "options.ButtonToggleFlowerColorUnification": "花の色の登録/登録解除",
83 | "options.RadiusFarmCleanup": "掃除の範囲",
84 | "options.CutWeeds": "雑草刈り(鎌が必要)",
85 | "options.BreakRocks": "岩砕き(ツルハシが必要)",
86 | "options.ChopTwigs": "小枝刈り(斧が必要)",
87 | "options.PriceBoxCoordinates": "情報ウィンドウの左上座標",
88 |
89 | "options.ThrowPower": "浮きを投げる強さ",
90 | "options.ThresholdStaminaPersentage": "釣りを止めるスタミナの割合",
91 | "options.ToggleAFKFishing": "自動釣りモードの切り替え",
92 |
93 | "hud.afk.passedout": "気絶したので釣りを止めた。",
94 | "hud.afk.on": "自動釣りモード開始。",
95 | "hud.afk.off": "自動釣りモード停止。",
96 | "hud.afk.tired": "疲れてきたので釣りを止めた。",
97 |
98 | //RegisterFlowerMenu strings
99 | "options.flower": "花:{0}",
100 | "options.R": "赤",
101 | "options.G": "緑",
102 | "options.B": "青",
103 | "options.previewColor": "色のプレビュー:",
104 | "options.register": "登録",
105 |
106 | //Flower Color Unification register/unregister
107 | "flower.register": "{0}の色は統一されます",
108 | "flower.unregister": "{0}の色は統一されません",
109 | "flower.vanilla": "バニラの花を登録解除することはできません",
110 |
111 |
112 | "quality.gold": "金",
113 | "quality.iridium": "イリジウム",
114 | "quality.normal": "普通",
115 | "quality.silver": "銀",
116 | "stones.many": "この階に石は{0}個ある",
117 | "stones.none": "この階に石は残っていない",
118 | "stones.one": "この階に石は一つだけある",
119 | "tab.automation": "自動化",
120 | "tab.cheats": "チート",
121 | "tab.controls": "コントロール",
122 | "tab.misc": "その他",
123 | "tab.UIs": "ユーザーインターフェース",
124 | "taste.dislike.female": "彼女はこの贈り物が嫌いみたいだ",
125 | "taste.dislike.male": "彼はこの贈り物が嫌いみたいだ",
126 | "taste.gavetoday.female": "今日は彼女に贈り物を渡している",
127 | "taste.gavetoday.male": "今日は彼に贈り物を渡している",
128 | "taste.gavetwogifts.female": "今週彼女に2回贈り物を渡している",
129 | "taste.gavetwogifts.male": "今週彼に2回贈り物を渡している",
130 | "taste.hate.female": "彼女はこの贈り物が大嫌いみたいだ",
131 | "taste.hate.male": "彼はこの贈り物が大嫌いみたいだ",
132 | "taste.like.female": "彼女はこの贈り物が好きみたいだ",
133 | "taste.like.male": "彼はこの贈り物が好きみたいだ",
134 | "taste.love.female": "彼女はこの贈り物が大好きみたいだ",
135 | "taste.love.male": "彼はこの贈り物が大好きみたいだ",
136 | "taste.neutral.female": "彼女はこの贈り物をなんとも思っていない",
137 | "taste.neutral.male": "彼はこの贈り物をなんとも思っていない"
138 | }
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/MachineOperator.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using GloryOfEfficiency.Core;
3 | using GloryOfEfficiency.Utils;
4 | using Microsoft.Xna.Framework;
5 | using StardewValley;
6 | using StardewValley.Locations;
7 | using StardewValley.Objects;
8 | using SVObject = StardewValley.Object;
9 | using static StardewValley.Game1;
10 |
11 | namespace GloryOfEfficiency.Automation
12 | {
13 | internal class MachineOperator
14 | {
15 | private static readonly Logger Logger = new Logger("MachineOperator");
16 |
17 | public static void DepositIngredientsToMachines()
18 | {
19 | Farmer player = Game1.player;
20 | if (player.CurrentItem == null || !(player.CurrentItem is SVObject item))
21 | {
22 | return;
23 | }
24 |
25 | foreach (SVObject obj in Util.GetObjectsWithin(InstanceHolder.Config.MachineRadius).Where(IsObjectMachine))
26 | {
27 | Vector2 loc = Util.GetLocationOf(currentLocation, obj);
28 | if (obj.heldObject.Value != null)
29 | continue;
30 |
31 | if (obj.Name == "Keg" && item.ParentSheetIndex == 433 && item.Stack < 5)
32 | {
33 | // You don't have enough beans.
34 | Logger.Log($"Trying to deposit {item.Name} into KEG: {obj.Name}. Not enough beans!");
35 | return;
36 | }
37 |
38 | bool accepted = obj.Name == "Furnace" ? CanFurnaceAcceptItem(item, player) : Utility.isThereAnObjectHereWhichAcceptsThisItem(currentLocation, item, (int)loc.X * tileSize, (int)loc.Y * tileSize);
39 | Logger.Log($"Trying to deposit ({accepted}) {item.Name} into machine: {obj.Name}");
40 | if (obj is Cask)
41 | {
42 | if (ModEntry.IsCoGOn || ModEntry.IsCaOn)
43 | {
44 | if (obj.performObjectDropInAction(item, true, player))
45 | {
46 | obj.heldObject.Value = null;
47 | accepted = true;
48 | }
49 | }
50 | else if (currentLocation is not Cellar && accepted)
51 | {
52 | accepted = false;
53 | }
54 | }
55 | else if (obj.Name == "Crab Pot")
56 | {
57 | if (item.Name == "Bait" || item.Name == "Magic Bait")
58 | {
59 | accepted = true;
60 | Logger.Log($"\tCrab Pot and {item.Name} are now ACCEPTED.");
61 | }
62 | }
63 | else if (obj.Name == "Seed Maker" && InstanceHolder.Config.AutoDepositSeedMaker == false)
64 | {
65 | continue;
66 | }
67 |
68 | if (!accepted)
69 | continue;
70 |
71 | // performObjectDropInAction but only if it's currently empty
72 | if (obj.performObjectDropInAction(item, false, player, true))
73 | {
74 | player.reduceActiveItemByOne();
75 | Logger.Log($"Item {obj} MANUALLY consuming {item.Name}");
76 | } else {
77 | Logger.Log($"Item {obj} should have already consumed {item.Name}");
78 | }
79 | Logger.Log($"DONE dropping {item.Name} into {obj}.");
80 |
81 | return;
82 | }
83 | }
84 |
85 | public static void PullMachineResult()
86 | {
87 | Farmer player = Game1.player;
88 | foreach (SVObject obj in Util.GetObjectsWithin(InstanceHolder.Config.MachineRadius).Where(IsObjectMachine))
89 | {
90 | // Nothing in the machine...
91 | if (obj.heldObject.Value == null)
92 | {
93 | continue;
94 | }
95 | else if (!obj.readyForHarvest.Value)
96 | {
97 | Logger.Log($"Time until {obj.Name} ready for collecting item {obj.heldObject.Value.Name}: {obj.MinutesUntilReady} game minutes.");
98 | continue;
99 | }
100 |
101 | Item item = obj.heldObject.Value;
102 | if (player.couldInventoryAcceptThisItem(item))
103 | obj.checkForAction(player);
104 | }
105 | }
106 |
107 | private static bool CanFurnaceAcceptItem(Item item, Farmer player)
108 | {
109 | Logger.Log($"{player.Items.ContainsId(Object.coalQID)} ** {item.Stack} ** {item.ParentSheetIndex}");
110 |
111 | // Minimum of one coal in inventory
112 | if (! player.Items.ContainsId(Object.coalQID, 1))
113 | return false;
114 |
115 | switch (item.Name)
116 | {
117 | // One item per coal...
118 | case "Clay":
119 | case "Quartz":
120 | case "Fire Quartz":
121 | break;
122 |
123 | // Five items per coal...
124 | case "Copper Ore":
125 | case "Iron Ore":
126 | case "Gold Ore":
127 | case "Iridium Ore":
128 | case "Radioactive Ore":
129 | if (item.Stack < 5)
130 | return false;
131 | break;
132 |
133 | default:
134 | return false;
135 | }
136 | return true;
137 | }
138 |
139 | private static bool IsObjectMachine(SVObject obj)
140 | {
141 | if (InstanceHolder.Config.MachineTypes.Contains(obj.Name))
142 | {
143 | return true;
144 | }
145 | return false;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/GloryOfEfficiency/i18n/ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "button.awaiting": "할당하려면 키 또는 버튼을 누르십시오.",
3 | "button.conflict": "누른 키 또는 버튼이 충돌합니다.",
4 | "button.esc": "Esc 키를 눌러 취소",
5 |
6 | "estimatedprice.title": "예상 판매 금액",
7 |
8 | "fishinfo.quality": "품질: ",
9 | "fishinfo.size": "크기: {0}인치",
10 | "fishinfo.species": "종: {0}",
11 | "fishinfo.treasure.appear": "보물이 나타났습니다!",
12 | "fishinfo.treasure.caught": "보물이 잡혔습니다!",
13 | "fishinfo.treasure.incoming": "보물이 {0 : f1}에 수신됩니다.",
14 | "fishinfo.price": "판매 가격:{0}골드",
15 |
16 | "hud.paused": "게임이 일시 정지 되었습니다.",
17 |
18 | "ladder": "사다리가 나타났습니다!",
19 |
20 | "location.awaiting": "원하는 위치를 지정하려면 아무곳이나 클릭하십시오.",
21 |
22 | "monsters.tally": "{0}: {1}킬",
23 |
24 | "options.AnimalHarvestRadius": "동물 검색을 위한 타일 반경",
25 | "options.AutoAnimalDoor": "동물 우리 문 자동 열기/닫기",
26 | "options.AutoCollectCollectibles": "근처 수집품 자동 수집",
27 | "options.AutoCollectRadius": "자동 수집 할 수 있는 타일 반경",
28 | "options.AutoDepositIngredient": "기계에 사용되는 재료 선택시 자동 넣기",
29 | "options.AutoDestroyDeadCrops": "근처 죽은 작물을 자동으로 파괴",
30 | "options.AutoDigArtifactSpot": "근처 아티팩트 스팟 자동 수집",
31 | "options.AutoDigRadius": "자동 수집 할 수 있는 타일 반경",
32 | "options.AutoEat": "위급시 자동 먹기",
33 | "options.AutoFishing": "자동 낚시 미니 게임",
34 | "options.AutoGate": "울타리 문 자동 열기/닫기",
35 | "options.AutoHarvest": "재배 작물 자동 수확",
36 | "options.AutoHarvestRadius": "수확 할 수 있는 타일 반경",
37 | "options.AutoLootTreasures": "보물 상자에 있는 모든 아이템 자동 수집",
38 | "options.AutoPetNearbyAnimals": "근처 동물 자동 쓰다듬기",
39 | "options.AutoPetNearbyPets": "근처 펫 자동 쓰다듬기",
40 | "options.AutoPetRadius": "동물을 찾을 수 있는 타일 반경",
41 | "options.AutoPickUpTrash": "주변 쓰레기통을 뒤집니다.",
42 | "options.AutoPullMachineResult": "기계에서 자동 수집",
43 | "options.AutoReelRod": "물고기 잡혔을 때 자동 감기",
44 | "options.AutoRefillWateringCan": "근처 물이 있을 때 물뿌리개 자동 보충",
45 | "options.AutoShakeFruitedPlants": "근처 과일 나무 자동 수확",
46 | "options.AutoShakeRadius": "자동 수집 할 수 있는 타일 반경",
47 | "options.AutoShearingAndMilking": "다 자란 양 / 소 - 자동 털 깎기 / 자동 착유 ",
48 | "options.AutoWaterNearbyCrops": "작물 자동 물주기",
49 | "options.AutoWaterRadius": "물 줄 수 있는 타일 반경",
50 | "options.BalancedMode": "밸런스 모드 켜기 (타일 반경)",
51 | "options.CloseTreasureWhenAllLooted": "모든 아이템 수집하면 보물 상자 닫기",
52 | "options.CollectLetterAttachmentsAndQuests": "메일에 첨부된 퀘스트 또는 아이템을 자동 수락",
53 | "options.CPUThresholdFishing": "낚시 바 움직임 빈도",
54 | "options.CraftingFromChests": "가장 가까운 상자에 있는 아이템을 사용하여 제작",
55 | "options.EstimateShippingPrice": "배송 가격 표시",
56 | "options.FilterBackgroundInMenu": "구성 메뉴 외부가 어둡게 표시됨",
57 | "options.FindCanFromInventory": "가방에서 물 뿌리개 찾기",
58 | "options.FindHoeFromInventory": "가방에서 호미 찾기",
59 | "options.FishInfo": "물고기 정보 상자 보기",
60 | "options.FishingInfo": "물고기 정보 상자 보기",
61 | "options.FishingProbabilitiesInfo": "낚시 확률 표시",
62 | "options.FishingTackleInfo": "현재 미끼와 찌 그리기",
63 | "options.TackleBoxAttach": "물고기 확률 상자에 태클 상자를 부착합니다.",
64 | "options.TackleBoxLocation": "정보 상자의 왼쪽 상단 좌표",
65 | "options.ProbBoxMaxFish": "열당 물고기 수",
66 | "options.GiftInformation": "선물 정보 표시 (선물할 것을 선택 후 NPC 위로 가져 가면 정보 표시)",
67 | "options.HealthToEatRatio": "자동 먹기 체력 최대치 값",
68 | "options.IdleTimeout": "게임 일시 정지를 위한 유휴 초과 시간",
69 | "options.KeyShowMenu": "설정 메뉴 단축키 ",
70 | "options.KeyToggleBlackList": "수확 블랙리스트 설정 단축키 ",
71 | "options.MachineRadius": "기계를 찾을 수 있는 타일 반경",
72 | "options.MineInfoGui": "광산 정보 아이콘 표시",
73 | "options.MuchFasterBiting": "먹는 시간 즉시 단축",
74 | "options.PauseWhenIdle": "유휴 상태 일때 일시 중지",
75 | "options.ProbBoxLocation": "정보 박스 왼쪽 상단으로 조정",
76 | "options.MorePreciseProbabilities": "더 정확한 확률 계산",
77 | "options.TrialOfExamine": "계산 확률 수",
78 | "options.ProtectNectarProducingFlower": "벌집 근처 꽃 보호",
79 | "options.RadiusCraftingFromChests": "상자를 찾을 수 있는 타일 반경",
80 | "options.ScavengingRadius": "사용 가능한 타일 반경",
81 | "options.StaminaToEatRatio": "자동 먹기 기력 최대치 값",
82 | "options.UnifyFlowerColors": "꽃 색상 통일하기",
83 | "options.ShowMousePositionWhenAssigningLocation": "좌표를 지정할 때 마우스에 좌표 표시",
84 | "options.ButtonToggleFlowerColorUnification": "꽃 색상 통일 변경/해제 단축키 ",
85 | "options.RadiusFarmCleanup": "농장 청소를 위한 타일 반경",
86 | "options.CutWeeds": "잡초 자르기 (낫 변경시)",
87 | "options.BreakRocks": "작은 바위 깨기 (곡괭이 변경시)",
88 | "options.ChopTwigs": "나무 가지 치기 (도끼 변경시)",
89 | "options.PriceBoxCoordinates": "정보 상자의 왼쪽 상단 좌표",
90 |
91 | "options.ThrowPower": "찌 던지는 힘",
92 | "options.ThresholdStaminaPersentage": "낚시를 멈추기 위한 체력 최대치",
93 |
94 | "options.ToggleAFKFishing": "AFK 낚시 모드 전환",
95 |
96 | "hud.afk.passedout": "기절했기 때문에 낚시가 중단되었습니다.",
97 | "hud.afk.on": "AFK 낚시가 활성화되었습니다.",
98 | "hud.afk.off": "AFK 낚시가 비활성화되었습니다.",
99 | "hud.afk.tired": "피곤해서 낚시가 중단되었습니다.",
100 |
101 | "options.flower": "꽃:{0}",
102 | "options.R": "R",
103 | "options.G": "G",
104 | "options.B": "B",
105 | "options.previewColor": "미리보기 색상:",
106 | "options.register": "기록",
107 |
108 | "flower.register": "{0}의 색상이 통일됩니다.",
109 | "flower.unregister": "{0}의 색상은 더 이상 통일되지 않습니다.",
110 | "flower.vanilla": "바닐라 꽃은 등록을 취소 할 수 없습니다.",
111 |
112 | "quality.gold": "골드",
113 | "quality.iridium": "이리듐",
114 | "quality.normal": "보통",
115 | "quality.silver": "실버",
116 | "stones.many": "이 층에는 {0}개의 돌이 있습니다.",
117 | "stones.none": "이 층에는 돌이 없습니다.",
118 | "stones.one": "이 층에 돌이 있습니다.",
119 | "tab.automation": "자동화",
120 | "tab.cheats": "요령",
121 | "tab.controls": "컨트롤",
122 | "tab.misc": "기타",
123 | "tab.UIs": "사용자 설정",
124 | "taste.dislike.female": "그녀는 이 선물을 매우 싫어합니다.",
125 | "taste.dislike.male": "그는 이 선물을 매우 싫어합니다.",
126 | "taste.gavetoday.female": "오늘 그녀에게 선물을 주었습니다.",
127 | "taste.gavetoday.male": "오늘 그에게 선물을 주었습니다.",
128 | "taste.gavetwogifts.female": "이번 주에 그녀에게 두 번 선물을 주었습니다.",
129 | "taste.gavetwogifts.male": "이번 주에 그에게 두 번 선물을 주었습니다.",
130 | "taste.hate.female": "그녀는 이 선물을 싫어합니다.",
131 | "taste.hate.male": "그는 이 선물을 싫어합니다.",
132 | "taste.like.female": "그녀는 이 선물을 좋아합니다.",
133 | "taste.like.male": "그는 이 선물을 좋아합니다.",
134 | "taste.love.female": "그녀는 이 선물을 매우 좋아합니다.",
135 | "taste.love.male": "그는 이 선물을 매우 좋아합니다.",
136 | "taste.neutral.female": "그녀는 이 선물에 대해 중립적인 감정을 가지고 있습니다.",
137 | "taste.neutral.male": "그는 이 선물에 대해 중립적인 감정을 가지고 있습니다."
138 | }
--------------------------------------------------------------------------------
/GloryOfEfficiency/Automation/FarmCleaner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using GloryOfEfficiency.Core;
4 | using GloryOfEfficiency.Utils;
5 | using Microsoft.Xna.Framework;
6 | using StardewValley;
7 | using StardewValley.Locations;
8 | using StardewValley.Tools;
9 | using Object = StardewValley.Object;
10 |
11 | namespace GloryOfEfficiency.Automation
12 | {
13 | internal class FarmCleaner
14 | {
15 | private static Multiplayer Multiplayer => InstanceHolder.Multiplayer;
16 | private static Config Config => InstanceHolder.Config;
17 |
18 | private static readonly Logger Logger = new Logger("FarmCleaner");
19 |
20 | public static void OnNthTickUpdate()
21 | {
22 | GameLocation farm = Game1.currentLocation;
23 | if (!(farm is Farm || farm is IslandWest))
24 | {
25 | return;
26 | }
27 |
28 | Tool tool = Game1.player.CurrentTool;
29 | if (tool == null)
30 | {
31 | return;
32 | }
33 |
34 | List