using System.Collections.Generic; using UnityEngine; /// /// Console command for inspecting and validating the SCore farming managers. /// /// Commands: /// scf count — print registered counts for farm plots and crop plants /// scf validate — remove stale entries from both managers and report /// scf listplots [range] — list all registered farm plot positions (optional: within range of player) /// scf listcrops [range] — list all registered crop plant positions (optional: within range of player) /// public class ConsoleCmdFarming : ConsoleCmdAbstract { public override bool IsExecuteOnClient => true; public override string[] getCommands() => new[] { "scorefarming", "scf" }; public override string getDescription() => "SCore: Inspect and validate farming plot/crop registries."; public override string getHelp() => "Usage:\n" + " scf count — show registered farm plot and crop counts\n" + " scf validate — remove stale entries from both managers\n" + " scf listplots [range] — list all registered farm plot positions\n" + " scf listcrops [range] — list all registered crop plant positions\n"; public override void Execute(List _params, CommandSenderInfo _senderInfo) { var console = SingletonMonoBehaviour.Instance; if (_params.Count == 0) { Output(console, getHelp()); return; } switch (_params[0].ToLower()) { case "count": ExecuteCount(console); break; case "validate": ExecuteValidate(console); break; case "listplots": ExecuteListPlots(console, _params); break; case "listcrops": ExecuteListCrops(console, _params); break; default: Output(console, $"Unknown sub-command '{_params[0]}'. Run 'scf' for help."); break; } } // ----------------------------------------------------------------------- private static void ExecuteCount(SdtdConsole console) { var plots = FarmPlotManager.Instance.GetAll(); var crops = CropManager.Instance.GetAll(); Output(console, $"Farm plots registered : {plots.Count}"); Output(console, $"Crop plants registered: {crops.Count}"); } private static void ExecuteValidate(SdtdConsole console) { int removedPlots = FarmPlotManager.Instance.Validate(); int removedCrops = CropManager.Instance.Validate(); Output(console, $"Validation complete."); Output(console, $" Stale farm plots removed : {removedPlots}"); Output(console, $" Stale crop plants removed: {removedCrops}"); // Print updated counts Output(console, $" Farm plots remaining : {FarmPlotManager.Instance.GetAll().Count}"); Output(console, $" Crop plants remaining: {CropManager.Instance.GetAll().Count}"); } private static void ExecuteListPlots(SdtdConsole console, List _params) { float range = ParseRange(_params, console); var playerPos = GetPlayerPos(); var plots = FarmPlotManager.Instance.GetAll(); var world = GameManager.Instance.World; int shown = 0; foreach (var plot in plots) { var pos = plot.GetBlockPos(); if (range > 0f && Vector3.Distance(playerPos, pos) > range) continue; bool hasWater = plot.HasWater(); bool hasPlant = plot.HasPlant(); bool isEmpty = plot.IsEmpty(); bool isDead = plot.IsDeadPlant(); bool visited = plot.Visited; // Collect crop block names stacked above this plot (up to 4 blocks up). var cropBlocks = new System.Text.StringBuilder(); for (int dy = 1; dy <= 4; dy++) { var above = world.GetBlock(pos + new Vector3i(0, dy, 0)); if (above.isair) break; if (dy > 1) cropBlocks.Append(", "); cropBlocks.Append($"Y+{dy}={above.Block.GetBlockName()}"); } string cropInfo = cropBlocks.Length > 0 ? $" crops=[{cropBlocks}]" : string.Empty; Output(console, $" {pos} water={hasWater} plant={hasPlant} empty={isEmpty} dead={isDead} visited={visited}{cropInfo}"); shown++; } Output(console, range > 0f ? $"Listed {shown} of {plots.Count} farm plots within {range} blocks." : $"Listed {shown} farm plots total."); } private static void ExecuteListCrops(SdtdConsole console, List _params) { float range = ParseRange(_params, console); var playerPos = GetPlayerPos(); var crops = CropManager.Instance.GetAll(); var world = GameManager.Instance.World; int shown = 0; foreach (var pos in crops) { if (range > 0f && Vector3.Distance(playerPos, pos) > range) continue; var block = world.GetBlock(pos); string blockName = block.isair ? "(air — stale)" : block.Block.GetBlockName(); // Find the farm plot block below this crop (search down up to 4 blocks). string plotInfo = string.Empty; for (int dy = 1; dy <= 4; dy++) { var below = world.GetBlock(pos - new Vector3i(0, dy, 0)); if (below.Block is BlockFarmPlotSDX) { plotInfo = $" plot={pos - new Vector3i(0, dy, 0)} (Y-{dy})"; break; } if (!below.isair) break; // hit a non-plot, non-air block — stop searching } Output(console, $" {pos} block={blockName}{plotInfo}"); shown++; } Output(console, range > 0f ? $"Listed {shown} of {crops.Count} crop plants within {range} blocks." : $"Listed {shown} crop plants total."); } // ----------------------------------------------------------------------- private static void Output(SdtdConsole console, string msg) { console.Output(msg); Log.Out($"[ConsoleCmdFarming] {msg}"); } private static float ParseRange(List _params, SdtdConsole console) { if (_params.Count < 2) return 0f; if (float.TryParse(_params[1], out float r)) return r; Output(console, $"Invalid range '{_params[1]}', showing all."); return 0f; } private static Vector3 GetPlayerPos() { var player = GameManager.Instance.World?.GetPrimaryPlayer(); return player != null ? player.position : Vector3.zero; } }