using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using RainOpsMini.Helpers; using RainOpsMini.Helpers.RCON; using RainOpsMini.Models; namespace RainOpsMini.Plugins { public class WelcomePlugin : IPlugin, IDisposable { public string Name => "欢迎语插件"; public string Description => "玩家进服欢迎提示,VIP使用广播,普通玩家使用警告"; public PluginCategory Category => PluginCategory.BasicFunction; public bool IsEnabled => _config.Enabled; private WelcomeConfig _config = new WelcomeConfig(); private readonly string _configPath; private Timer? _timer; private readonly HashSet _welcomedSteamIds = new HashSet(); private readonly object _lock = new object(); public WelcomePlugin() { _configPath = Path.Combine(Environment.CurrentDirectory, "PluginConfig", "WelcomeConfig.json"); LoadConfig(); ApplyConfig(); } public object GetConfig() => _config; public void UpdateConfig(JsonElement config) { var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; _config = JsonSerializer.Deserialize(config.GetRawText(), options) ?? new WelcomeConfig(); SaveConfig(); ApplyConfig(); } public void ResetConfig() { _config = new WelcomeConfig(); SaveConfig(); ApplyConfig(); } private void LoadConfig() { if (File.Exists(_configPath)) { try { var json = File.ReadAllText(_configPath); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; _config = JsonSerializer.Deserialize(json, options) ?? new WelcomeConfig(); } catch (Exception ex) { RainOpsLog.Log($"[WelcomePlugin] Load config failed: {ex.Message}"); } } else { SaveConfig(); } } private void SaveConfig() { try { var dir = Path.GetDirectoryName(_configPath); if (dir != null && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var json = JsonSerializer.Serialize(_config, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(_configPath, json); } catch (Exception ex) { RainOpsLog.Log($"[WelcomePlugin] Save config failed: {ex.Message}"); } } private void ApplyConfig() { if (_config.Enabled) { if (_timer == null) { _timer = new Timer(CheckPlayers, null, 5000, 5000); // Check every 5 seconds } } else { _timer?.Dispose(); _timer = null; lock (_lock) { _welcomedSteamIds.Clear(); } } } private async void CheckPlayers(object? state) { try { // 拷贝一份数据,避免线程安全问题 List players; if (Program.RconCache?.Players != null) { players = new List(Program.RconCache.Players); } else { return; } if (players.Count == 0) return; var currentSteamIds = players.Select(p => p.SteamId).Where(s => !string.IsNullOrEmpty(s)).ToHashSet(); List newPlayers = new List(); lock (_lock) { // 移除已经不在服务器的玩家 _welcomedSteamIds.RemoveWhere(id => !currentSteamIds.Contains(id)); // 找出新玩家 foreach (var player in players) { if (!string.IsNullOrEmpty(player.SteamId) && !_welcomedSteamIds.Contains(player.SteamId)) { _welcomedSteamIds.Add(player.SteamId); var connectTime = RainOpsMini.Helpers.SquadGameLog.LogStorage.Instance.GetPlayerConnectTime(player.SteamId); if (connectTime != null && Math.Abs((DateTime.Now - connectTime.Value).TotalSeconds) < 3) { newPlayers.Add(player); } } } } foreach (var player in newPlayers) { await ProcessWelcome(player); } } catch (Exception ex) { RainOpsLog.Log($"[WelcomePlugin] CheckPlayers error: {ex.Message}"); } } private async Task ProcessWelcome(PlayerInfo player) { try { var vip = VipStorage.GetBySteamId(player.SteamId); bool isVip = vip != null && vip.ExpiryDate > DateTime.Now; if (isVip) { // VIP/SVIP 欢迎语 - 广播 string message = !string.IsNullOrWhiteSpace(vip!.WelcomeMessage) ? vip.WelcomeMessage : (vip.Group == "SVIP_RainOpsMini" ? _config.DefaultSvipWelcomeMessage : _config.DefaultVipWelcomeMessage); if (!string.IsNullOrWhiteSpace(message)) { message = message.Replace("{Name}", player.Name); // AdminBroadcast await Program.Client.SendCommandAsync($"AdminBroadcast {message}"); RainOpsLog.Log($"[WelcomePlugin] VIP Welcome broadcast for {player.Name}: {message}"); } } else { // 普通玩家欢迎语 - 警告 if (_config.GeneralWelcomeEnabled && !string.IsNullOrWhiteSpace(_config.GeneralWelcomeMessage)) { string message = _config.GeneralWelcomeMessage.Replace("{Name}", player.Name); // AdminWarn await Program.Client.SendCommandAsync($"AdminWarn {player.SteamId} {message}"); RainOpsLog.Log($"[WelcomePlugin] General Welcome warn for {player.Name}: {message}"); } } } catch (Exception ex) { RainOpsLog.Log($"[WelcomePlugin] ProcessWelcome error for {player.Name}: {ex.Message}"); } } public void Dispose() { _timer?.Dispose(); } } }