summaryrefslogtreecommitdiff
path: root/src/SMAPI.Mods.ConsoleCommands
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI.Mods.ConsoleCommands')
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs246
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/ModEntry.cs2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj2
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/manifest.json4
14 files changed, 261 insertions, 13 deletions
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs
index 3ad1e168..10007b42 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs
@@ -9,7 +9,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands
internal class ArgumentParser : IReadOnlyList<string>
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>The command name for errors.</summary>
private readonly string CommandName;
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs
index 37f4719e..263e126c 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs
@@ -10,7 +10,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
internal class AddCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>Provides methods for searching and constructing items.</summary>
private readonly ItemRepository Items = new ItemRepository();
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs
index 34f1760c..a835455e 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs
@@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
internal class ListItemTypesCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>Provides methods for searching and constructing items.</summary>
private readonly ItemRepository Items = new ItemRepository();
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs
index 942a50b8..5b52e9a2 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs
@@ -9,7 +9,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
internal class ListItemsCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>Provides methods for searching and constructing items.</summary>
private readonly ItemRepository Items = new ItemRepository();
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs
index 2e8f6630..1abb82b5 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs
@@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
internal class SetHealthCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>Whether to keep the player's health at its maximum.</summary>
private bool InfiniteHealth;
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs
index 3fc504b1..ad11cc66 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs
@@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
internal class SetMoneyCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>Whether to keep the player's money at a set value.</summary>
private bool InfiniteMoney;
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs
index 866c3d22..009cb1de 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs
@@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player
internal class SetStaminaCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>Whether to keep the player's stamina at its maximum.</summary>
private bool InfiniteStamina;
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs
new file mode 100644
index 00000000..c769b622
--- /dev/null
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs
@@ -0,0 +1,246 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using StardewValley;
+using StardewValley.Locations;
+using StardewValley.Objects;
+using StardewValley.TerrainFeatures;
+using SObject = StardewValley.Object;
+
+namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
+{
+ /// <summary>A command which clears in-game objects.</summary>
+ internal class ClearCommand : TrainerCommand
+ {
+ /*********
+ ** Fields
+ *********/
+ /// <summary>The valid types that can be cleared.</summary>
+ private readonly string[] ValidTypes = { "debris", "fruit-trees", "grass", "trees", "everything" };
+
+ /// <summary>The resource clump IDs to consider debris.</summary>
+ private readonly int[] DebrisClumps = { ResourceClump.stumpIndex, ResourceClump.hollowLogIndex, ResourceClump.meteoriteIndex, ResourceClump.boulderIndex };
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ public ClearCommand()
+ : base(
+ name: "world_clear",
+ description: "Clears in-game entities in a given location.\n\n"
+ + "Usage: world_clear <location> <object type>\n"
+ + "- location: the location name for which to clear objects (like Farm), or 'current' for the current location.\n"
+ + " - object type: the type of object clear. You can specify 'debris' (stones/twigs/weeds and dead crops), 'grass', and 'trees' / 'fruit-trees'. You can also specify 'everything', which includes things not removed by the other types (like furniture or resource clumps)."
+ )
+ { }
+
+ /// <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)
+ {
+ // check context
+ if (!Context.IsWorldReady)
+ {
+ monitor.Log("You need to load a save to use this command.", LogLevel.Error);
+ return;
+ }
+
+ // parse arguments
+ if (!args.TryGet(0, "location", out string locationName, required: true))
+ return;
+ if (!args.TryGet(1, "object type", out string type, required: true, oneOf: this.ValidTypes))
+ return;
+
+ // get target location
+ GameLocation location = Game1.locations.FirstOrDefault(p => p.Name != null && p.Name.Equals(locationName, StringComparison.InvariantCultureIgnoreCase));
+ if (location == null && locationName == "current")
+ location = Game1.currentLocation;
+ if (location == null)
+ {
+ string[] locationNames = (from loc in Game1.locations where !string.IsNullOrWhiteSpace(loc.Name) orderby loc.Name select loc.Name).ToArray();
+ monitor.Log($"Could not find a location with that name. Must be one of [{string.Join(", ", locationNames)}].", LogLevel.Error);
+ return;
+ }
+
+ // apply
+ switch (type)
+ {
+ case "debris":
+ {
+ int removed = 0;
+ foreach (var pair in location.terrainFeatures.Pairs.ToArray())
+ {
+ TerrainFeature feature = pair.Value;
+ if (feature is HoeDirt dirt && dirt.crop?.dead == true)
+ {
+ dirt.crop = null;
+ removed++;
+ }
+ }
+
+ removed +=
+ this.RemoveObjects(location, obj => obj.Name.ToLower().Contains("weed") || obj.Name == "Twig" || obj.Name == "Stone")
+ + this.RemoveResourceClumps(location, clump => this.DebrisClumps.Contains(clump.parentSheetIndex.Value));
+
+ monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info);
+ break;
+ }
+
+ case "fruit-trees":
+ {
+ int removed = this.RemoveTerrainFeatures(location, feature => feature is FruitTree);
+ monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info);
+ break;
+ }
+
+ case "grass":
+ {
+ int removed = this.RemoveTerrainFeatures(location, feature => feature is Grass);
+ monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info);
+ break;
+ }
+
+ case "trees":
+ {
+ int removed = this.RemoveTerrainFeatures(location, feature => feature is Tree);
+ monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info);
+ break;
+ }
+
+ case "everything":
+ {
+ int removed =
+ this.RemoveFurniture(location, p => true)
+ + this.RemoveObjects(location, p => true)
+ + this.RemoveTerrainFeatures(location, p => true)
+ + this.RemoveLargeTerrainFeatures(location, p => true)
+ + this.RemoveResourceClumps(location, p => true);
+ monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info);
+ break;
+ }
+
+ default:
+ monitor.Log($"Unknown type '{type}'. Must be one [{string.Join(", ", this.ValidTypes)}].", LogLevel.Error);
+ break;
+ }
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Remove objects from a location matching a lambda.</summary>
+ /// <param name="location">The location to search.</param>
+ /// <param name="shouldRemove">Whether an entity should be removed.</param>
+ /// <returns>Returns the number of removed entities.</returns>
+ private int RemoveObjects(GameLocation location, Func<SObject, bool> shouldRemove)
+ {
+ int removed = 0;
+
+ foreach (var pair in location.Objects.Pairs.ToArray())
+ {
+ if (shouldRemove(pair.Value))
+ {
+ location.Objects.Remove(pair.Key);
+ removed++;
+ }
+ }
+
+ return removed;
+ }
+
+ /// <summary>Remove terrain features from a location matching a lambda.</summary>
+ /// <param name="location">The location to search.</param>
+ /// <param name="shouldRemove">Whether an entity should be removed.</param>
+ /// <returns>Returns the number of removed entities.</returns>
+ private int RemoveTerrainFeatures(GameLocation location, Func<TerrainFeature, bool> shouldRemove)
+ {
+ int removed = 0;
+
+ foreach (var pair in location.terrainFeatures.Pairs.ToArray())
+ {
+ if (shouldRemove(pair.Value))
+ {
+ location.terrainFeatures.Remove(pair.Key);
+ removed++;
+ }
+ }
+
+ return removed;
+ }
+
+ /// <summary>Remove large terrain features from a location matching a lambda.</summary>
+ /// <param name="location">The location to search.</param>
+ /// <param name="shouldRemove">Whether an entity should be removed.</param>
+ /// <returns>Returns the number of removed entities.</returns>
+ private int RemoveLargeTerrainFeatures(GameLocation location, Func<LargeTerrainFeature, bool> shouldRemove)
+ {
+ int removed = 0;
+
+ foreach (LargeTerrainFeature feature in location.largeTerrainFeatures.ToArray())
+ {
+ if (shouldRemove(feature))
+ {
+ location.largeTerrainFeatures.Remove(feature);
+ removed++;
+ }
+ }
+
+ return removed;
+ }
+
+ /// <summary>Remove resource clumps from a location matching a lambda.</summary>
+ /// <param name="location">The location to search.</param>
+ /// <param name="shouldRemove">Whether an entity should be removed.</param>
+ /// <returns>Returns the number of removed entities.</returns>
+ private int RemoveResourceClumps(GameLocation location, Func<ResourceClump, bool> shouldRemove)
+ {
+ int removed = 0;
+
+ // get resource clumps
+ IList<ResourceClump> resourceClumps =
+ (location as Farm)?.resourceClumps
+ ?? (IList<ResourceClump>)(location as Woods)?.stumps
+ ?? new List<ResourceClump>();
+
+ // remove matching clumps
+ foreach (var clump in resourceClumps.ToArray())
+ {
+ if (shouldRemove(clump))
+ {
+ resourceClumps.Remove(clump);
+ removed++;
+ }
+ }
+
+ return removed;
+ }
+
+ /// <summary>Remove furniture from a location matching a lambda.</summary>
+ /// <param name="location">The location to search.</param>
+ /// <param name="shouldRemove">Whether an entity should be removed.</param>
+ /// <returns>Returns the number of removed entities.</returns>
+ private int RemoveFurniture(GameLocation location, Func<Furniture, bool> shouldRemove)
+ {
+ int removed = 0;
+
+ if (location is DecoratableLocation decoratableLocation)
+ {
+ foreach (Furniture furniture in decoratableLocation.furniture.ToArray())
+ {
+ if (shouldRemove(furniture))
+ {
+ decoratableLocation.furniture.Remove(furniture);
+ removed++;
+ }
+ }
+ }
+
+ return removed;
+ }
+ }
+}
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs
index 2627b714..6a7ab162 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs
@@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
internal class FreezeTimeCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>The time of day at which to freeze time.</summary>
internal static int FrozenTime;
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs
index b5db9c0d..0615afe7 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs
@@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World
internal class SetSeasonCommand : TrainerCommand
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>The valid season names.</summary>
private readonly string[] ValidSeasons = { "winter", "spring", "summer", "fall" };
diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs
index f4a38403..fc631826 100644
--- a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs
@@ -12,7 +12,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework
internal class ItemRepository
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>The custom ID offset for items don't have a unique ID in the game.</summary>
private readonly int CustomIDOffset = 1000;
diff --git a/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs b/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs
index 30951064..77dace26 100644
--- a/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs
+++ b/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs
@@ -10,7 +10,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands
public class ModEntry : Mod
{
/*********
- ** Properties
+ ** Fields
*********/
/// <summary>The commands to handle.</summary>
private ITrainerCommand[] Commands;
diff --git a/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj b/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj
index d1f16e41..2c958dbc 100644
--- a/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj
+++ b/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj
@@ -11,6 +11,7 @@
<AssemblyName>ConsoleCommands</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
+ <LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
@@ -62,6 +63,7 @@
<Compile Include="Framework\Commands\TrainerCommand.cs" />
<Compile Include="Framework\Commands\World\SetMineLevelCommand.cs" />
<Compile Include="Framework\Commands\World\DownMineLevelCommand.cs" />
+ <Compile Include="Framework\Commands\World\ClearCommand.cs" />
<Compile Include="Framework\Commands\World\SetYearCommand.cs" />
<Compile Include="Framework\Commands\World\SetSeasonCommand.cs" />
<Compile Include="Framework\Commands\World\SetDayCommand.cs" />
diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json
index 541d1045..3e7001d5 100644
--- a/src/SMAPI.Mods.ConsoleCommands/manifest.json
+++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Console Commands",
"Author": "SMAPI",
- "Version": "2.9.3",
+ "Version": "2.10.0",
"Description": "Adds SMAPI console commands that let you manipulate the game.",
"UniqueID": "SMAPI.ConsoleCommands",
"EntryDll": "ConsoleCommands.dll",
- "MinimumApiVersion": "2.9.3"
+ "MinimumApiVersion": "2.10.0"
}