summaryrefslogtreecommitdiff
path: root/src/SMAPI.Mods.ConsoleCommands/Framework/Commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI.Mods.ConsoleCommands/Framework/Commands')
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs90
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs8
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetLevelCommand.cs91
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs4
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetSpeedCommand.cs30
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStyleCommand.cs4
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs4
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs4
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs5
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetTimeCommand.cs34
10 files changed, 111 insertions, 163 deletions
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs
index a6f42b98..37f4719e 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs
@@ -15,14 +15,16 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
/// <summary>Provides methods for searching and constructing items.</summary>
private readonly ItemRepository Items = new ItemRepository();
+ /// <summary>The type names recognised by this command.</summary>
+ private readonly string[] ValidTypes = Enum.GetNames(typeof(ItemType)).Concat(new[] { "Name" }).ToArray();
+
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
public AddCommand()
- : base("player_add", AddCommand.GetDescription())
- { }
+ : base("player_add", AddCommand.GetDescription()) { }
/// <summary>Handle the command.</summary>
/// <param name="monitor">Writes messages to the console and log file.</param>
@@ -30,35 +32,34 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
/// <param name="args">The command arguments.</param>
public override void Handle(IMonitor monitor, string command, ArgumentParser args)
{
- // read arguments
- if (!args.TryGet(0, "item type", out string rawType, oneOf: Enum.GetNames(typeof(ItemType))))
+ // validate
+ if (!Context.IsWorldReady)
+ {
+ monitor.Log("You need to load a save to use this command.", LogLevel.Error);
return;
- if (!args.TryGetInt(1, "item ID", out int id, min: 0))
+ }
+
+ // read arguments
+ if (!args.TryGet(0, "item type", out string type, oneOf: this.ValidTypes))
return;
if (!args.TryGetInt(2, "count", out int count, min: 1, required: false))
count = 1;
if (!args.TryGetInt(3, "quality", out int quality, min: Object.lowQuality, max: Object.bestQuality, required: false))
quality = Object.lowQuality;
- ItemType type = (ItemType)Enum.Parse(typeof(ItemType), rawType, ignoreCase: true);
// find matching item
- SearchableItem match = this.Items.GetAll().FirstOrDefault(p => p.Type == type && p.ID == id);
+ SearchableItem match = Enum.TryParse(type, true, out ItemType itemType)
+ ? this.FindItemByID(monitor, args, itemType)
+ : this.FindItemByName(monitor, args);
if (match == null)
- {
- monitor.Log($"There's no {type} item with ID {id}.", LogLevel.Error);
return;
- }
// apply count
match.Item.Stack = count;
// apply quality
if (match.Item is Object obj)
-#if STARDEW_VALLEY_1_3
obj.Quality = quality;
-#else
- obj.quality = quality;
-#endif
else if (match.Item is Tool tool)
tool.UpgradeLevel = quality;
@@ -67,9 +68,60 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
monitor.Log($"OK, added {match.Name} ({match.Type} #{match.ID}) to your inventory.", LogLevel.Info);
}
+
/*********
** Private methods
*********/
+ /// <summary>Get a matching item by its ID.</summary>
+ /// <param name="monitor">Writes messages to the console and log file.</param>
+ /// <param name="args">The command arguments.</param>
+ /// <param name="type">The item type.</param>
+ private SearchableItem FindItemByID(IMonitor monitor, ArgumentParser args, ItemType type)
+ {
+ // read arguments
+ if (!args.TryGetInt(1, "item ID", out int id, min: 0))
+ return null;
+
+ // find matching item
+ SearchableItem item = this.Items.GetAll().FirstOrDefault(p => p.Type == type && p.ID == id);
+ if (item == null)
+ monitor.Log($"There's no {type} item with ID {id}.", LogLevel.Error);
+ return item;
+ }
+
+ /// <summary>Get a matching item by its name.</summary>
+ /// <param name="monitor">Writes messages to the console and log file.</param>
+ /// <param name="args">The command arguments.</param>
+ private SearchableItem FindItemByName(IMonitor monitor, ArgumentParser args)
+ {
+ // read arguments
+ if (!args.TryGet(1, "item name", out string name))
+ return null;
+
+ // find matching items
+ SearchableItem[] matches = this.Items.GetAll().Where(p => p.NameContains(name)).ToArray();
+ if (!matches.Any())
+ {
+ monitor.Log($"There's no item with name '{name}'. You can use the 'list_items [name]' command to search for items.", LogLevel.Error);
+ return null;
+ }
+
+ // handle single exact match
+ SearchableItem[] exactMatches = matches.Where(p => p.NameEquivalentTo(name)).ToArray();
+ if (exactMatches.Length == 1)
+ return exactMatches[0];
+
+ // handle ambiguous results
+ string options = this.GetTableString(
+ data: matches,
+ header: new[] { "type", "name", "command" },
+ getRow: item => new[] { item.Type.ToString(), item.DisplayName, $"player_add {item.Type} {item.ID}" }
+ );
+ monitor.Log($"There's no item with name '{name}'. Do you mean one of these?\n\n{options}", LogLevel.Info);
+ return null;
+ }
+
+ /// <summary>Get the command description.</summary>
private static string GetDescription()
{
string[] typeValues = Enum.GetNames(typeof(ItemType));
@@ -81,8 +133,14 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
+ "- count (optional): how many of the item to give.\n"
+ $"- quality (optional): one of {Object.lowQuality} (normal), {Object.medQuality} (silver), {Object.highQuality} (gold), or {Object.bestQuality} (iridium).\n"
+ "\n"
- + "This example adds the galaxy sword to your inventory:\n"
- + " player_add weapon 4";
+ + "Usage: player_add name \"<name>\" [count] [quality]\n"
+ + "- name: the item name to search (use the 'list_items' command to see a list). This will add the item immediately if it's an exact match, else show a table of matching items.\n"
+ + "- count (optional): how many of the item to give.\n"
+ + $"- quality (optional): one of {Object.lowQuality} (normal), {Object.medQuality} (silver), {Object.highQuality} (gold), or {Object.bestQuality} (iridium).\n"
+ + "\n"
+ + "These examples both add the galaxy sword to your inventory:\n"
+ + " player_add weapon 4\n"
+ + " player_add name \"Galaxy Sword\"";
}
}
}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs
index aa4fd105..f0815ef6 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetColorCommand.cs
@@ -36,11 +36,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
switch (target)
{
case "hair":
-#if STARDEW_VALLEY_1_3
Game1.player.hairstyleColor.Value = color;
-#else
- Game1.player.hairstyleColor = color;
-#endif
monitor.Log("OK, your hair color is updated.", LogLevel.Info);
break;
@@ -50,11 +46,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
break;
case "pants":
-#if STARDEW_VALLEY_1_3
Game1.player.pantsColor.Value = color;
-#else
- Game1.player.pantsColor = color;
-#endif
monitor.Log("OK, your pants color is updated.", LogLevel.Info);
break;
}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetLevelCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetLevelCommand.cs
deleted file mode 100644
index 68891267..00000000
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetLevelCommand.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using System.Collections.Generic;
-using StardewValley;
-using SFarmer = StardewValley.Farmer;
-
-namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
-{
- /// <summary>A command which edits the player's current level for a skill.</summary>
- internal class SetLevelCommand : TrainerCommand
- {
- /*********
- ** Properties
- *********/
- /// <summary>The experience points needed to reach each level.</summary>
- /// <remarks>Derived from <see cref="SFarmer.checkForLevelGain"/>.</remarks>
- private readonly IDictionary<int, int> LevelExp = new Dictionary<int, int>
- {
- [0] = 0,
- [1] = 100,
- [2] = 380,
- [3] = 770,
- [4] = 1300,
- [5] = 2150,
- [6] = 3300,
- [7] = 4800,
- [8] = 6900,
- [9] = 10000,
- [10] = 15000
- };
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Construct an instance.</summary>
- public SetLevelCommand()
- : base("player_setlevel", "Sets the player's specified skill to the specified value.\n\nUsage: player_setlevel <skill> <value>\n- skill: the skill to set (one of 'luck', 'mining', 'combat', 'farming', 'fishing', or 'foraging').\n- value: the target level (a number from 1 to 10).") { }
-
- /// <summary>Handle the command.</summary>
- /// <param name="monitor">Writes messages to the console and log file.</param>
- /// <param name="command">The command name.</param>
- /// <param name="args">The command arguments.</param>
- public override void Handle(IMonitor monitor, string command, ArgumentParser args)
- {
- // validate
- if (!args.TryGet(0, "skill", out string skill, oneOf: new[] { "luck", "mining", "combat", "farming", "fishing", "foraging" }))
- return;
- if (!args.TryGetInt(1, "level", out int level, min: 0, max: 10))
- return;
-
- // handle
- switch (skill)
- {
- case "luck":
- Game1.player.LuckLevel = level;
- Game1.player.experiencePoints[SFarmer.luckSkill] = this.LevelExp[level];
- monitor.Log($"OK, your luck skill is now {Game1.player.LuckLevel}.", LogLevel.Info);
- break;
-
- case "mining":
- Game1.player.MiningLevel = level;
- Game1.player.experiencePoints[SFarmer.miningSkill] = this.LevelExp[level];
- monitor.Log($"OK, your mining skill is now {Game1.player.MiningLevel}.", LogLevel.Info);
- break;
-
- case "combat":
- Game1.player.CombatLevel = level;
- Game1.player.experiencePoints[SFarmer.combatSkill] = this.LevelExp[level];
- monitor.Log($"OK, your combat skill is now {Game1.player.CombatLevel}.", LogLevel.Info);
- break;
-
- case "farming":
- Game1.player.FarmingLevel = level;
- Game1.player.experiencePoints[SFarmer.farmingSkill] = this.LevelExp[level];
- monitor.Log($"OK, your farming skill is now {Game1.player.FarmingLevel}.", LogLevel.Info);
- break;
-
- case "fishing":
- Game1.player.FishingLevel = level;
- Game1.player.experiencePoints[SFarmer.fishingSkill] = this.LevelExp[level];
- monitor.Log($"OK, your fishing skill is now {Game1.player.FishingLevel}.", LogLevel.Info);
- break;
-
- case "foraging":
- Game1.player.ForagingLevel = level;
- Game1.player.experiencePoints[SFarmer.foragingSkill] = this.LevelExp[level];
- monitor.Log($"OK, your foraging skill is now {Game1.player.ForagingLevel}.", LogLevel.Info);
- break;
- }
- }
- }
-}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs
index 71e17f71..e8cb0584 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetNameCommand.cs
@@ -39,11 +39,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
case "farm":
if (!string.IsNullOrWhiteSpace(name))
{
-#if STARDEW_VALLEY_1_3
Game1.player.farmName.Value = args[1];
-#else
- Game1.player.farmName = args[1];
-#endif
monitor.Log($"OK, your farm's name is now {Game1.player.farmName}.", LogLevel.Info);
}
else
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetSpeedCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetSpeedCommand.cs
deleted file mode 100644
index e9693540..00000000
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetSpeedCommand.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using StardewValley;
-
-namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
-{
- /// <summary>A command which edits the player's current added speed.</summary>
- internal class SetSpeedCommand : TrainerCommand
- {
- /*********
- ** Public methods
- *********/
- /// <summary>Construct an instance.</summary>
- public SetSpeedCommand()
- : base("player_setspeed", "Sets the player's added speed to the specified value.\n\nUsage: player_setspeed <value>\n- value: an integer amount (0 is normal).") { }
-
- /// <summary>Handle the command.</summary>
- /// <param name="monitor">Writes messages to the console and log file.</param>
- /// <param name="command">The command name.</param>
- /// <param name="args">The command arguments.</param>
- public override void Handle(IMonitor monitor, string command, ArgumentParser args)
- {
- // parse arguments
- if (!args.TryGetInt(0, "added speed", out int amount, min: 0))
- return;
-
- // handle
- Game1.player.addedSpeed = amount;
- monitor.Log($"OK, your added speed is now {Game1.player.addedSpeed}.", LogLevel.Info);
- }
- }
-}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStyleCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStyleCommand.cs
index b59be2e5..31f4107d 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStyleCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStyleCommand.cs
@@ -1,4 +1,4 @@
-using StardewValley;
+using StardewValley;
namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
{
@@ -10,7 +10,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
*********/
/// <summary>Construct an instance.</summary>
public SetStyleCommand()
- : base("player_changestyle", "Sets the style of a player feature.\n\nUsage: player_changecolor <target> <value>.\n- target: what to change (one of 'hair', 'shirt', 'skin', 'acc', 'shoe', 'swim', or 'gender').\n- value: the integer style ID.") { }
+ : base("player_changestyle", "Sets the style of a player feature.\n\nUsage: player_changestyle <target> <value>.\n- target: what to change (one of 'hair', 'shirt', 'skin', 'acc', 'shoe', 'swim', or 'gender').\n- value: the integer style ID.") { }
/// <summary>Handle the command.</summary>
/// <param name="monitor">Writes messages to the console and log file.</param>
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs
index c83c3b07..2cec0fd3 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/DownMineLevelCommand.cs
@@ -21,11 +21,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
{
int level = (Game1.currentLocation as MineShaft)?.mineLevel ?? 0;
monitor.Log($"OK, warping you to mine level {level + 1}.", LogLevel.Info);
-#if STARDEW_VALLEY_1_3
Game1.enterMine(level + 1);
-#else
- Game1.enterMine(false, level + 1, "");
-#endif
}
}
}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs
index 5947af1a..b4f6d5b3 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetMineLevelCommand.cs
@@ -26,11 +26,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
// handle
level = Math.Max(1, level);
monitor.Log($"OK, warping you to mine level {level}.", LogLevel.Info);
-#if STARDEW_VALLEY_1_3
Game1.enterMine(level);
-#else
- Game1.enterMine(true, level, "");
-#endif
}
}
}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs
index 897d052f..b5db9c0d 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
@@ -38,7 +38,8 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
return;
// handle
- Game1.currentSeason = season;
+ Game1.currentSeason = season.ToLower();
+ Game1.setGraphicsForSeason();
monitor.Log($"OK, the date is now {Game1.currentSeason} {Game1.dayOfMonth}.", LogLevel.Info);
}
}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetTimeCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetTimeCommand.cs
index d6c71387..7644ee46 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetTimeCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetTimeCommand.cs
@@ -1,4 +1,5 @@
-using System.Linq;
+using System;
+using System.Linq;
using StardewValley;
namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
@@ -31,9 +32,38 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
return;
// handle
- Game1.timeOfDay = time;
+ this.SafelySetTime(time);
FreezeTimeCommand.FrozenTime = Game1.timeOfDay;
monitor.Log($"OK, the time is now {Game1.timeOfDay.ToString().PadLeft(4, '0')}.", LogLevel.Info);
}
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Safely transition to the given time, allowing NPCs to update their schedule.</summary>
+ /// <param name="time">The time of day.</param>
+ private void SafelySetTime(int time)
+ {
+ // define conversion between game time and TimeSpan
+ TimeSpan ToTimeSpan(int value) => new TimeSpan(0, value / 100, value % 100, 0);
+ int FromTimeSpan(TimeSpan span) => (int)((span.Hours * 100) + span.Minutes);
+
+ // transition to new time
+ int intervals = (int)((ToTimeSpan(time) - ToTimeSpan(Game1.timeOfDay)).TotalMinutes / 10);
+ if (intervals > 0)
+ {
+ for (int i = 0; i < intervals; i++)
+ Game1.performTenMinuteClockUpdate();
+ }
+ else if (intervals < 0)
+ {
+ for (int i = 0; i > intervals; i--)
+ {
+ Game1.timeOfDay = FromTimeSpan(ToTimeSpan(Game1.timeOfDay).Subtract(TimeSpan.FromMinutes(20))); // offset 20 mins so game updates to next interval
+ Game1.performTenMinuteClockUpdate();
+ }
+ }
+ }
}
}