// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using MUnique.OpenMU.GameLogic.CastleSiege; using MUnique.OpenMU.GameLogic.PlugIns.PeriodicTasks; using MUnique.OpenMU.GameLogic.Views; using MUnique.OpenMU.Interfaces; using MUnique.OpenMU.PlugIns; /// /// Sets the Castle Siege weekly auto-schedule. GM only. Times are UTC. /// Usage: /csschedule (show) | /csschedule Sunday 20:00 | /csschedule Sunday,Wednesday 20:00 | /csschedule clear. /// [Guid("A1B2C3D4-0006-4E5F-9A0B-CA5710000006")] [PlugIn] [Display(Name = "Castle Siege Schedule", Description = "GM command: /csschedule [ | clear]")] [ChatCommandHelp(Command, CharacterStatus.GameMaster)] public class CastleSiegeScheduleChatCommandPlugIn : IChatCommandPlugIn { private const string Command = "/csschedule"; /// public string Key => Command; /// public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster; /// public async ValueTask HandleCommandAsync(Player player, string command) { var context = CastleSiegeEventPlugIn.TryGetContext(player.GameContext); if (context is null) { await ShowAsync(player, "Castle Siege plugin not active.").ConfigureAwait(false); return; } var parts = command.Split(' ', StringSplitOptions.RemoveEmptyEntries); // "/csschedule" -> show current schedule. if (parts.Length == 1) { await ShowAsync(player, Describe(context)).ConfigureAwait(false); return; } // "/csschedule clear" -> disable auto-start. if (parts.Length == 2 && string.Equals(parts[1], "clear", StringComparison.OrdinalIgnoreCase)) { context.SetSchedule(Array.Empty(), null); await ShowAsync(player, "Castle Siege auto-schedule cleared (manual start only).").ConfigureAwait(false); return; } if (parts.Length < 3) { await ShowAsync(player, "Usage: /csschedule | /csschedule clear").ConfigureAwait(false); return; } var days = new List(); foreach (var token in parts[1].Split(',', StringSplitOptions.RemoveEmptyEntries)) { if (!Enum.TryParse(token, true, out var day)) { await ShowAsync(player, $"Unknown day '{token}'. Use e.g. Sunday, Monday, Tuesday...").ConfigureAwait(false); return; } days.Add(day); } if (!TimeOnly.TryParse(parts[2], CultureInfo.InvariantCulture, out var time)) { await ShowAsync(player, $"Invalid time '{parts[2]}'. Use 24h HH:mm (UTC).").ConfigureAwait(false); return; } context.SetSchedule(days, time); await ShowAsync(player, $"{Describe(context)} Server UTC now: {DateTime.UtcNow:ddd HH:mm}.").ConfigureAwait(false); } private static string Describe(CastleSiegeContext context) { var config = context.Configuration; if (config.RegistrationOpenTimes.Count == 0) { return "Castle Siege auto-schedule: (none). Set with /csschedule ."; } var days = config.RegistrationOpenDays.Count > 0 ? string.Join(",", config.RegistrationOpenDays) : "every day"; var times = string.Join(",", config.RegistrationOpenTimes.Select(t => t.ToString("HH\\:mm"))); return $"Castle Siege auto-schedule: {days} at {times} UTC (reg {config.RegistrationDuration:g} -> prep {config.PreparationDuration:g} -> war {config.SiegeDuration:g})."; } private static ValueTask ShowAsync(Player player, string text) => player.InvokeViewPlugInAsync(p => p.ShowMessageAsync(text, MessageType.BlueNormal)); }