Editor/Tools/AssetEditorTools.cs
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Sandbox;

namespace Editor.Mcp
{
	public static partial class SboxMcpAssistant
	{
		[McpTool("pocketknife_open_in_hammer")]
		public static string OpenInHammer([Description("Path to .vmap file")] string mapPath) => EditorDocumentOpen("hammer", mapPath);

		[McpTool("pocketknife_edit_material")]
		public static string EditMaterial([Description("Path to .vmat file")] string materialPath) => EditorDocumentOpen("material", materialPath);

		[McpTool("pocketknife_create_sound_event")]
		public static string CreateSoundEvent([Description("Name of the new .sound file")] string soundName, [Description("Path to raw audio asset")] string audioPath, [Description("Volume from 0 to 1")] float volume = 1f)
		{
			try
			{
				if (!ToolGuard.IsValidName(soundName) || soundName.Contains('/') || soundName.Contains('\\')) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "sound.invalid_name", "Sound name must be a single safe file name."));
				if (volume < 0 || volume > 1) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "sound.invalid_volume", "Volume must be between 0 and 1."));
				if (string.IsNullOrWhiteSpace(audioPath)) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "sound.audio_missing", "An audio asset path is required."));
				var root = Project.Current?.GetRootPath(); if (string.IsNullOrWhiteSpace(root)) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Unavailable, "project.not_active", "No active project is available."));
				var path = Path.Combine(root, "sounds", soundName.EndsWith(".sound", StringComparison.OrdinalIgnoreCase) ? soundName : soundName + ".sound"); Directory.CreateDirectory(Path.GetDirectoryName(path)!);
				var json = new { UI = false, Volume = volume.ToString(System.Globalization.CultureInfo.InvariantCulture), VolumeRandom = 0, Pitch = "1", PitchRandom = 0, DistanceMax = 2000, Sounds = new[] { ToolGuard.Normalize(audioPath) } }; File.WriteAllText(path, JsonSerializer.Serialize(json, new JsonSerializerOptions { WriteIndented = true }));
				if (!File.Exists(path)) return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "sound.verify_failed", "The sound file was not created."));
				var refreshed = EditorRuntime.Trigger("assets.refresh_all"); return McpJson.Write(refreshed ? ToolOutcome<object>.Ready(new { Path = path, Audio = audioPath, Volume = volume, Refreshed = true }) : ToolOutcome<object>.Degraded(new { Path = path, Audio = audioPath, Volume = volume, Refreshed = false }, "asset.refresh_unavailable", "The sound asset was written, but the editor action dispatcher was unavailable."));
			}
			catch (Exception ex) { return McpJson.Write(ToolOutcome<object>.Failure(null, ToolStatus.Failed, "sound.create_failed", "Sound event creation failed.", ex)); }
		}


	}
}