mirror of
https://gitee.com/xiarenalofs/squad-rain-ops-mini.git
synced 2026-08-09 06:35:58 +08:00
164 lines
7.3 KiB
C#
164 lines
7.3 KiB
C#
using System.Text.RegularExpressions;
|
|
using RainOpsMini.Models;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using RainOpsMini.Helpers.RCON;
|
|
|
|
namespace RainOpsMini
|
|
{
|
|
public static class RconParser
|
|
{
|
|
// Team ID: 1 (1st Infantry Division)
|
|
private static readonly Regex TeamHeaderRegex = new Regex(@"Team ID:\s*(\d+)\s*\(", RegexOptions.Compiled);
|
|
|
|
// ID: 1 | Name: Squad 1 | Size: 5 | Locked: False | Creator Name: lanyu | Creator Online IDs: EOS: 00020148e4944a0a9ca3ddd4c703b5e0 steam: 76561198296558085
|
|
private static readonly Regex SquadRegex = new Regex(@"ID:\s*(\d+)\s*\|\s*Name:\s*(.+?)\s*\|\s*Size:\s*(\d+)\s*\|\s*Locked:\s*(\w+)\s*\|\s*Creator Name:\s*(.+?)\s*\|\s*Creator Online IDs:\s*EOS:\s*(\w+)\s*steam:\s*(\d+)", RegexOptions.Compiled);
|
|
|
|
// ID: 40 | Online IDs: EOS: 00026c77c7fc494fa0ab3a337382826f steam: 76561199065911668 | Name: ANDRUHA | Team ID: 1 | Squad ID: N/A | Is Leader: False | Role: USA_Rifleman_01
|
|
private static readonly Regex PlayerRegex = new Regex(@"ID:\s*(\d+)\s*\|\s*Online IDs:\s*EOS:\s*(\w+)\s*steam:\s*(\d+)\s*\|\s*Name:\s*(.+?)\s*\|\s*Team ID:\s*(\d+)\s*\|\s*Squad ID:\s*(.+?)\s*\|\s*Is Leader:\s*(\w+)\s*\|\s*Role:\s*(.+)", RegexOptions.Compiled);
|
|
|
|
// [ChatAll] [Online IDs:EOS: 0002236691c54d00b82bcf1b04a27761 steam: 76561199735605536] [hina] 澶ф : cj
|
|
// [ChatAll] [Online IDs:EOS: 00026937662e43e593caf18bebdbeb2a steam: 76561199402993315] Rain鍦ㄤ笅鐝?: 00
|
|
// Improved Regex to handle both [Name] Message and Name : Message formats
|
|
private static readonly Regex ChatRegex = new Regex(@"\[(ChatAll|ChatTeam|ChatSquad|ChatAdmin|ChatGame)\]\s*\[Online IDs:?\s*EOS:\s*(\w+)\s*steam:\s*(\d+)\]\s*(?:\[(.+?)\]\s*(.*)|(.+?)\s*:\s*(.*))", RegexOptions.Compiled);
|
|
|
|
public static ChatMessage? ParseChatMessage(string rconOutput)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(rconOutput)) return null;
|
|
|
|
var match = ChatRegex.Match(rconOutput);
|
|
if (match.Success)
|
|
{
|
|
// Group 4/5 are for [Name] Message format
|
|
// Group 6/7 are for Name : Message format
|
|
string name = match.Groups[4].Success ? match.Groups[4].Value : match.Groups[6].Value;
|
|
string message = match.Groups[4].Success ? match.Groups[5].Value : match.Groups[7].Value;
|
|
|
|
return new ChatMessage
|
|
{
|
|
Type = match.Groups[1].Value,
|
|
EosId = match.Groups[2].Value,
|
|
SteamId = match.Groups[3].Value,
|
|
Name = name?.Trim() ?? "Unknown",
|
|
Message = message?.Trim() ?? "",
|
|
Timestamp = DateTime.Now
|
|
};
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static ServerInfoResponse? ParseServerInfo(string rconOutput)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(rconOutput)) return null;
|
|
|
|
// ShowServerInfo might return raw JSON string, sometimes wrapped in quotes or with other text
|
|
// We'll try to find the JSON object part: starts with { and ends with }
|
|
int startIndex = rconOutput.IndexOf('{');
|
|
int endIndex = rconOutput.LastIndexOf('}');
|
|
|
|
if (startIndex >= 0 && endIndex > startIndex)
|
|
{
|
|
string json = rconOutput.Substring(startIndex, endIndex - startIndex + 1);
|
|
try
|
|
{
|
|
var options = new JsonSerializerOptions
|
|
{
|
|
PropertyNameCaseInsensitive = true,
|
|
NumberHandling = JsonNumberHandling.AllowReadingFromString
|
|
};
|
|
var info = JsonSerializer.Deserialize<ServerInfoResponse>(json, options);
|
|
|
|
// Fallback for PlayTime_I if not in JSON (it is usually there, but just in case)
|
|
// Actually standard ShowServerInfo returns JSON with PLAYTIME_I field.
|
|
|
|
return info;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
RainOpsMini.Helpers.RainOpsLog.Log($"[Error] Failed to parse ServerInfo JSON: {ex.Message}");
|
|
// Optional: Print json snippet for debugging
|
|
// RainOpsMini.Helpers.RainOpsLog.Log($"[Debug] JSON: {json}");
|
|
return null;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static List<SquadInfo> ParseSquads(string rconOutput)
|
|
{
|
|
var squads = new List<SquadInfo>();
|
|
if (string.IsNullOrWhiteSpace(rconOutput)) return squads;
|
|
|
|
var lines = rconOutput.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
|
int currentTeamId = 0;
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
var teamMatch = TeamHeaderRegex.Match(line);
|
|
if (teamMatch.Success)
|
|
{
|
|
if (int.TryParse(teamMatch.Groups[1].Value, out int tid))
|
|
{
|
|
currentTeamId = tid;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
var squadMatch = SquadRegex.Match(line);
|
|
if (squadMatch.Success)
|
|
{
|
|
var squad = new SquadInfo
|
|
{
|
|
TeamId = currentTeamId,
|
|
Id = int.Parse(squadMatch.Groups[1].Value),
|
|
Name = squadMatch.Groups[2].Value.Trim(),
|
|
Size = int.Parse(squadMatch.Groups[3].Value),
|
|
Locked = bool.Parse(squadMatch.Groups[4].Value),
|
|
CreatorName = squadMatch.Groups[5].Value.Trim(),
|
|
CreatorEosId = squadMatch.Groups[6].Value,
|
|
CreatorSteamId = squadMatch.Groups[7].Value
|
|
};
|
|
squads.Add(squad);
|
|
}
|
|
}
|
|
return squads;
|
|
}
|
|
|
|
public static List<PlayerInfo> ParsePlayers(string rconOutput)
|
|
{
|
|
var players = new List<PlayerInfo>();
|
|
if (string.IsNullOrWhiteSpace(rconOutput)) return players;
|
|
|
|
var lines = rconOutput.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
var match = PlayerRegex.Match(line);
|
|
if (match.Success)
|
|
{
|
|
var player = new PlayerInfo
|
|
{
|
|
Id = int.Parse(match.Groups[1].Value),
|
|
EosId = match.Groups[2].Value,
|
|
SteamId = match.Groups[3].Value,
|
|
Name = match.Groups[4].Value.Trim(),
|
|
TeamId = int.Parse(match.Groups[5].Value),
|
|
IsLeader = bool.Parse(match.Groups[7].Value),
|
|
Role = match.Groups[8].Value.Trim()
|
|
};
|
|
|
|
string squadIdStr = match.Groups[6].Value.Trim();
|
|
if (squadIdStr != "N/A" && int.TryParse(squadIdStr, out int sid))
|
|
{
|
|
player.SquadId = sid;
|
|
}
|
|
|
|
players.Add(player);
|
|
}
|
|
}
|
|
return players;
|
|
}
|
|
}
|
|
}
|
|
|