Editor/Tools/AdvancedGameplayTools.cs
#nullable enable
using System;
using Sandbox;

namespace Editor.Mcp
{
	public static partial class SboxMcpAssistant
	{
		[McpTool("pocketknife_paint_terrain")]
		public static string PaintTerrain([Description("Terrain type: water, grass, or road")] string type, [Description("Coordinate list or bounding box string")] string bounds)
		{
			var normalized = (type ?? "").Trim().ToLowerInvariant(); var names = normalized switch { "water" => new[] { "WaterComponent", "WaterTool.WaterComponent" }, "grass" => new[] { "GrassComponent", "GrassTool.GrassComponent" }, "road" => new[] { "RoadComponent", "RoadTool.RoadComponent" }, _ => Array.Empty<string>() };
			if (names.Length == 0) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "terrain.invalid_type", $"Unsupported terrain type '{type}'. Use water, grass, or road."));
			try
			{
				var componentType = EditorRuntime.GetComponentType(names[0]) ?? EditorRuntime.GetComponentType(names[1]); if (componentType is null) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Unavailable, "terrain.dependency_missing", $"No component for '{normalized}' is loaded; nothing was painted."));
				if (string.IsNullOrWhiteSpace(bounds)) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "terrain.bounds_missing", "A non-empty bounds/coordinate expression is required."));
				var go = new GameObject(true, $"{normalized} terrain"); var component = go.Components.Create((dynamic)componentType); return McpJson.Write(ToolOutcome<object>.Degraded(new { Id = go.Id.ToString(), Type = normalized, Bounds = bounds, Component = componentType.ToString() }, "terrain.paint_api_unavailable", "The compatible component was created, but this addon does not know a safe native paint method for its bounds format."));
			}
			catch (Exception ex) { return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "terrain.paint_failed", "Terrain operation failed.", ex)); }
		}

		[McpTool("pocketknife_spawn_sandbox_entity")]
		public static string SpawnSandboxEntity([Description("Type of entity: prop, weapon, or npc")] string entityType, [Description("Path to model or prefab")] string assetPath)
		{
			var kind = (entityType ?? "").Trim().ToLowerInvariant(); if (kind is not ("prop" or "weapon" or "npc")) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "entity.invalid_type", "Entity type must be prop, weapon, or npc."));
			if (string.IsNullOrWhiteSpace(assetPath)) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "entity.asset_missing", "An asset path is required."));
			if (kind != "prop") return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Unavailable, "entity.prefab_instantiation_unavailable", $"No verified prefab factory is available for {kind}; no entity was created.", remediation: "Provide a project prefab factory or use entityType=prop with a model asset."));
			try
			{
				var model = Model.Load(assetPath); if (model is null) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Unavailable, "entity.model_not_found", $"Model '{assetPath}' could not be loaded."));
				var go = new GameObject(true, $"prop - {System.IO.Path.GetFileNameWithoutExtension(assetPath)}"); var renderer = go.Components.Create<ModelRenderer>(); renderer.Model = model; var collider = go.Components.Create<ModelCollider>(); collider.Model = model; go.Components.Create<Rigidbody>();
				return McpJson.Write(ToolOutcome<object>.Ready(new { Id = go.Id.ToString(), Type = kind, Asset = assetPath, HasRenderer = renderer.Model is not null, HasCollider = collider.Model is not null, Physics = true }));
			}
			catch (Exception ex) { return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "entity.spawn_failed", "Physics prop creation failed.", ex)); }
		}
	}
}