using Discord.WebSocket; using MinecraftDiscordBot.Commands; using MinecraftDiscordBot.Models; using Newtonsoft.Json; namespace MinecraftDiscordBot.Services; public class PlayerDetectorService : CommandRouter { private readonly ITaskWaitSource _taskSource; public PlayerDetectorService(ITaskWaitSource taskSource) => _taskSource = taskSource; public override string HelpTextPrefix => "!pd "; public override Task FallbackHandler(SocketUserMessage message, string method, string[] parameters, CancellationToken ct) => throw new ReplyException($"The player detector cannot do '{method}'!"); private Task Method(string methodName, Func parser, CancellationToken ct, Dictionary? parameters = null) => RootCommandService.Method(_taskSource, methodName, parser, ct, parameters); public Task GetOnlinePlayersAsync(CancellationToken ct) => Method("getonline", RootCommandService.Deserialize(), ct); public async Task GetPlayerPosition(string username, CancellationToken ct) => (await FindPlayerAsync(username, ct)) ?? throw new ReplyException($"User '{username}' is not online!"); private Task FindPlayerAsync(string username, CancellationToken ct) => Method("whereis", i => JsonConvert.DeserializeObject(i), ct, new() { ["username"] = username }); [CommandHandler("getonline", HelpText = "Get a list of online players.")] public async Task HandleOnlinePlayers(SocketUserMessage message, string[] parameters, CancellationToken ct) => ResponseType.AsString($"The following players are currently online:\n{string.Join("\n", await GetOnlinePlayersAsync(ct))}"); [CommandHandler("whereis", HelpText = "Find a player in the world.")] public async Task HandleFindPlayers(SocketUserMessage message, string[] parameters, CancellationToken ct) { if (parameters is not { Length: 1 }) throw new ReplyException($"Give me only one username!"); var username = parameters[0]; var player = await FindPlayerAsync(username, ct); if (player is null) throw new ReplyException($"{username} is currently offline!"); return ResponseType.AsString($"{username} is at coordinates {player.X} {player.Y} {player.Z} in dimension {player.Dimension}."); } }