mirror of
https://gitee.com/xiarenalofs/squad-rain-ops-mini.git
synced 2026-08-06 13:26:25 +08:00
209 lines
7.3 KiB
C#
209 lines
7.3 KiB
C#
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<string> _welcomedSteamIds = new HashSet<string>();
|
||
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<WelcomeConfig>(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<WelcomeConfig>(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<PlayerInfo> players;
|
||
if (Program.RconCache?.Players != null)
|
||
{
|
||
players = new List<PlayerInfo>(Program.RconCache.Players);
|
||
}
|
||
else
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (players.Count == 0) return;
|
||
|
||
var currentSteamIds = players.Select(p => p.SteamId).Where(s => !string.IsNullOrEmpty(s)).ToHashSet();
|
||
|
||
List<PlayerInfo> newPlayers = new List<PlayerInfo>();
|
||
|
||
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 <Message>
|
||
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 <SteamId> <Message>
|
||
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();
|
||
}
|
||
}
|
||
}
|