diff --git a/release-notes.md b/release-notes.md
index d157c06a..81d770f0 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -8,6 +8,7 @@ For players:
* Simplified log filename.
* Simplified error messages when a mod can't be loaded.
* Simple nested mod folders are now recognised by SMAPI (e.g. `ModName-1.0\ModName\manifest.json`).
+* Improved TrainerMod command handling & feedback.
* Fixed game's debug output being shown in the console for all users.
* Fixed the game-outdated error not pausing before exit.
* Fixed installer errors for some players when deleting files.
diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs
index 18a83e32..07857512 100644
--- a/src/StardewModdingAPI/Program.cs
+++ b/src/StardewModdingAPI/Program.cs
@@ -554,7 +554,10 @@ namespace StardewModdingAPI
this.Monitor.Log($"{result.Name}: {result.Documentation}\n(Added by {result.ModName}.)", LogLevel.Info);
}
else
- this.Monitor.Log("Commands: " + string.Join(", ", this.CommandManager.GetAll().Select(p => p.Name)), LogLevel.Info);
+ {
+ this.Monitor.Log("The following commands are registered: " + string.Join(", ", this.CommandManager.GetAll().Select(p => p.Name)) + ".", LogLevel.Info);
+ this.Monitor.Log("For more information about a command, type 'help command_name'.", LogLevel.Info);
+ }
}
/// Show a 'press any key to exit' message, and exit when they press a key.
diff --git a/src/TrainerMod/TrainerMod.cs b/src/TrainerMod/TrainerMod.cs
index 1298c5cd..b89cbf5c 100644
--- a/src/TrainerMod/TrainerMod.cs
+++ b/src/TrainerMod/TrainerMod.cs
@@ -94,7 +94,7 @@ namespace TrainerMod
.Add("player_setlevel", "Sets the player's specified skill to the specified value.\n\nUsage: player_setlevel \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).", this.HandleCommand)
.Add("player_setspeed", "Sets the player's speed to the specified value?\n\nUsage: player_setspeed \n- value: an integer amount (0 is normal).", this.HandleCommand)
- .Add("player_changecolour", "Sets the colour of a player feature.\n\nUsage: player_changecolor \n- target: what to change (one of 'hair', 'eyes', or 'pants').\n- colour: a colour value in RGB format, like (255,255,255).", this.HandleCommand)
+ .Add("player_changecolor", "Sets the color of a player feature.\n\nUsage: player_changecolor \n- target: what to change (one of 'hair', 'eyes', or 'pants').\n- color: a color value in RGB format, like (255,255,255).", this.HandleCommand)
.Add("player_changestyle", "Sets the style of a player feature.\n\nUsage: player_changecolor .\n- target: what to change (one of 'hair', 'shirt', 'skin', 'acc', 'shoe', 'swim', or 'gender').\n- value: the integer style ID.", this.HandleCommand)
.Add("player_additem", $"Gives the player an item.\n\nUsage: player_additem [count] [quality]\n- item: the item ID (use the 'list_items' command to see a list).\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).", this.HandleCommand)
@@ -104,7 +104,7 @@ namespace TrainerMod
.Add("list_items", "Lists and searches items in the game data.\n\nUsage: list_items [search]\n- search (optional): an arbitrary search string to filter by.", this.HandleCommand)
.Add("world_settime", "Sets the time to the specified value.\n\nUsage: world_settime \n- value: the target time in military time (like 0600 for 6am and 1800 for 6pm)", this.HandleCommand)
- .Add("world_freezetime", "Freezes or resumes time.\n\nUsage: world_freezetime [value]\n- value: one of 0 (resume), 1 (freeze) or blank (toggle).", this.HandleCommand)
+ .Add("world_freezetime", "Freezes or resumes time.\n\nUsage: world_freezetime [value]\n- value: one of 0 (resume), 1 (freeze), or blank (toggle).", this.HandleCommand)
.Add("world_setday", "Sets the day to the specified value.\n\nUsage: world_setday .\n- value: the target day (a number from 1 to 28).", this.HandleCommand)
.Add("world_setseason", "Sets the season to the specified value.\n\nUsage: world_setseason \n- value: the target season (one of 'spring', 'summer', 'fall', 'winter').", this.HandleCommand)
.Add("world_downminelevel", "Goes down one mine level?", this.HandleCommand)
@@ -115,21 +115,23 @@ namespace TrainerMod
}
/// Handle a TrainerMod command.
- /// The command name.
+ /// The command name.
/// The command arguments.
- private void HandleCommand(string name, string[] args)
+ private void HandleCommand(string command, string[] args)
{
- switch (name)
+ switch (command)
{
case "type":
- this.Monitor.Log($"[Int32: {int.MinValue} - {int.MaxValue}], [Int64: {long.MinValue} - {long.MaxValue}], [String: \"raw text\"], [Colour: r,g,b (EG: 128, 32, 255)]", LogLevel.Info);
+ this.Monitor.Log($"[Int32: {int.MinValue} - {int.MaxValue}], [Int64: {long.MinValue} - {long.MaxValue}], [String: \"raw text\"], [Color: r,g,b (EG: 128, 32, 255)]", LogLevel.Info);
break;
case "save":
+ this.Monitor.Log("Saving the game...", LogLevel.Info);
SaveGame.Save();
break;
case "load":
+ this.Monitor.Log("Triggering load menu...", LogLevel.Info);
Game1.hasLoadedGame = false;
Game1.activeClickableMenu = new LoadGameMenu();
break;
@@ -145,17 +147,19 @@ namespace TrainerMod
{
case "player":
Game1.player.Name = args[1];
+ this.Monitor.Log($"OK, your player's name is now {Game1.player.Name}.", LogLevel.Info);
break;
case "farm":
Game1.player.farmName = args[1];
+ this.Monitor.Log($"OK, your farm's name is now {Game1.player.Name}.", LogLevel.Info);
break;
}
}
else
- this.LogObjectInvalid();
+ this.LogArgumentsInvalid(command);
}
else
- this.LogObjectValueNotSpecified();
+ this.Monitor.Log($"Your name is currently '{Game1.player.Name}'. Type 'help player_setname' for usage.", LogLevel.Info);
break;
case "player_setmoney":
@@ -163,7 +167,10 @@ namespace TrainerMod
{
string amountStr = args[0];
if (amountStr == "inf")
+ {
this.InfiniteMoney = true;
+ this.Monitor.Log("OK, you now have infinite money.", LogLevel.Info);
+ }
else
{
this.InfiniteMoney = false;
@@ -171,14 +178,14 @@ namespace TrainerMod
if (int.TryParse(amountStr, out amount))
{
Game1.player.Money = amount;
- this.Monitor.Log($"Set {Game1.player.Name}'s money to {Game1.player.Money}", LogLevel.Info);
+ this.Monitor.Log($"OK, you now have {Game1.player.Money} gold.", LogLevel.Info);
}
else
- this.LogValueNotInt32();
+ this.LogArgumentNotInt(command);
}
}
else
- this.LogValueNotSpecified();
+ this.Monitor.Log($"You currently have {(this.InfiniteMoney ? "infinite" : Game1.player.Money.ToString())} gold. Specify a value to change it.", LogLevel.Info);
break;
case "player_setstamina":
@@ -186,7 +193,10 @@ namespace TrainerMod
{
string amountStr = args[0];
if (amountStr == "inf")
+ {
this.InfiniteStamina = true;
+ this.Monitor.Log("OK, you now have infinite stamina.", LogLevel.Info);
+ }
else
{
this.InfiniteStamina = false;
@@ -194,14 +204,14 @@ namespace TrainerMod
if (int.TryParse(amountStr, out amount))
{
Game1.player.Stamina = amount;
- this.Monitor.Log($"Set {Game1.player.Name}'s stamina to {Game1.player.Stamina}", LogLevel.Info);
+ this.Monitor.Log($"OK, you now have {Game1.player.Stamina} stamina.", LogLevel.Info);
}
else
- this.LogValueNotInt32();
+ this.LogArgumentNotInt(command);
}
}
else
- this.Monitor.Log($"{Game1.player.Name}'s stamina is {Game1.player.Stamina}", LogLevel.Info);
+ this.Monitor.Log($"You currently have {(this.InfiniteStamina ? "infinite" : Game1.player.Stamina.ToString())} stamina. Specify a value to change it.", LogLevel.Info);
break;
case "player_setmaxstamina":
@@ -211,13 +221,13 @@ namespace TrainerMod
if (int.TryParse(args[0], out amount))
{
Game1.player.MaxStamina = amount;
- this.Monitor.Log($"Set {Game1.player.Name}'s max stamina to {Game1.player.MaxStamina}", LogLevel.Info);
+ this.Monitor.Log($"OK, you now have {Game1.player.MaxStamina} max stamina.", LogLevel.Info);
}
else
- this.LogValueNotInt32();
+ this.LogArgumentNotInt(command);
}
else
- this.Monitor.Log($"{Game1.player.Name}'s maxstamina is {Game1.player.MaxStamina}", LogLevel.Info);
+ this.Monitor.Log($"You currently have {Game1.player.MaxStamina} max stamina. Specify a value to change it.", LogLevel.Info);
break;
case "player_setlevel":
@@ -234,32 +244,38 @@ namespace TrainerMod
{
case "luck":
Game1.player.LuckLevel = level;
+ this.Monitor.Log($"OK, your luck skill is now {Game1.player.LuckLevel}.", LogLevel.Info);
break;
case "mining":
Game1.player.MiningLevel = level;
+ this.Monitor.Log($"OK, your mining skill is now {Game1.player.MiningLevel}.", LogLevel.Info);
break;
case "combat":
Game1.player.CombatLevel = level;
+ this.Monitor.Log($"OK, your combat skill is now {Game1.player.CombatLevel}.", LogLevel.Info);
break;
case "farming":
Game1.player.FarmingLevel = level;
+ this.Monitor.Log($"OK, your farming skill is now {Game1.player.FarmingLevel}.", LogLevel.Info);
break;
case "fishing":
Game1.player.FishingLevel = level;
+ this.Monitor.Log($"OK, your fishing skill is now {Game1.player.FishingLevel}.", LogLevel.Info);
break;
case "foraging":
Game1.player.ForagingLevel = level;
+ this.Monitor.Log($"OK, your foraging skill is now {Game1.player.ForagingLevel}.", LogLevel.Info);
break;
}
}
else
- this.LogValueNotInt32();
+ this.LogArgumentNotInt(command);
}
else
- this.Monitor.Log(" is invalid", LogLevel.Error);
+ this.LogUsageError("That isn't a valid skill.", command);
}
else
- this.Monitor.Log(" and must be specified", LogLevel.Error);
+ this.LogArgumentsInvalid(command);
break;
case "player_setspeed":
@@ -269,16 +285,16 @@ namespace TrainerMod
if (amountStr.IsInt())
{
Game1.player.addedSpeed = amountStr.ToInt();
- this.Monitor.Log($"Set {Game1.player.Name}'s added speed to {Game1.player.addedSpeed}", LogLevel.Info);
+ this.Monitor.Log($"OK, your added speed is now {Game1.player.addedSpeed}.", LogLevel.Info);
}
else
- this.LogValueNotInt32();
+ this.LogArgumentNotInt(command);
}
else
- this.LogValueNotSpecified();
+ this.Monitor.Log($"You currently have {Game1.player.addedSpeed} added speed. Specify a value to change it.", LogLevel.Info);
break;
- case "player_changecolour":
+ case "player_changecolor":
if (args.Length > 1)
{
string target = args[0];
@@ -293,23 +309,26 @@ namespace TrainerMod
{
case "hair":
Game1.player.hairstyleColor = color;
+ this.Monitor.Log("OK, your hair color is updated.", LogLevel.Info);
break;
case "eyes":
Game1.player.changeEyeColor(color);
+ this.Monitor.Log("OK, your eye color is updated.", LogLevel.Info);
break;
case "pants":
Game1.player.pantsColor = color;
+ this.Monitor.Log("OK, your pants color is updated.", LogLevel.Info);
break;
}
}
else
- this.Monitor.Log(" is invalid", LogLevel.Error);
+ this.LogUsageError("The color should be an RBG value like '255,150,0'.", command);
}
else
- this.LogObjectInvalid();
+ this.LogArgumentsInvalid(command);
}
else
- this.Monitor.Log("