using System; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Text; using SharedLibraryCore; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Objects; using SharedLibraryCore.RCon; using SharedLibraryCore.Exceptions; namespace IW4MAdmin.Application.RconParsers { public class IW5MRConParser : IRConParser { private static readonly CommandPrefix Prefixes = new CommandPrefix() { Tell = "tell {0} {1}", Say = "say {0}", Kick = "dropClient {0} \"{1}\"", Ban = "dropClient {0} \"{1}\"", TempBan = "dropClient {0} \"{1}\"" }; public CommandPrefix GetCommandPrefixes() => Prefixes; public async Task ExecuteCommandAsync(Connection connection, string command) { await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command, false); return new string[] { "Command Executed" }; } public async Task> GetDvarAsync(Connection connection, string dvarName) { // why can't this be real :( if (dvarName == "version") return new Dvar(dvarName) { Value = (T)Convert.ChangeType("IW5 MP 1.9 build 461 Fri Sep 14 00:04:28 2012 win-x86", typeof(T)) }; if (dvarName == "shortversion") return new Dvar(dvarName) { Value = (T)Convert.ChangeType("1.9", typeof(T)) }; if (dvarName == "mapname") return new Dvar(dvarName) { Value = (T)Convert.ChangeType("Unknown", typeof(T)) }; if (dvarName == "g_gametype") return new Dvar(dvarName) { Value = (T)Convert.ChangeType("Unknown", typeof(T)) }; if (dvarName == "fs_game") return new Dvar(dvarName) { Value = (T)Convert.ChangeType("", typeof(T)) }; if (dvarName == "g_logsync") return new Dvar(dvarName) { Value = (T)Convert.ChangeType(1, typeof(T)) }; if (dvarName == "fs_basepath") return new Dvar(dvarName) { Value = (T)Convert.ChangeType("", typeof(T)) }; string[] LineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.DVAR, dvarName); if (LineSplit.Length < 4) { var e = new DvarException($"DVAR \"{dvarName}\" does not exist"); e.Data["dvar_name"] = dvarName; throw e; } string[] ValueSplit = LineSplit[1].Split(new char[] { '"' }); if (ValueSplit.Length == 0) { var e = new DvarException($"DVAR \"{dvarName}\" does not exist"); e.Data["dvar_name"] = dvarName; throw e; } string DvarName = dvarName; string DvarCurrentValue = Regex.Replace(ValueSplit[3].StripColors(), @"\^[0-9]", ""); return new Dvar(DvarName) { Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T)) }; } public async Task> GetStatusAsync(Connection connection) { string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status"); return ClientsFromStatus(response); } public async Task SetDvarAsync(Connection connection, string dvarName, object dvarValue) { // T6M doesn't respond with anything when a value is set, so we can only hope for the best :c await connection.SendQueryAsync(StaticHelpers.QueryType.DVAR, $"set {dvarName} {dvarValue}", false); return true; } private List ClientsFromStatus(string[] status) { List StatusPlayers = new List(); foreach (string statusLine in status) { String responseLine = statusLine; if (Regex.Matches(responseLine, @"^ *\d+", RegexOptions.IgnoreCase).Count > 0) // its a client line! { String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // this happens when the client is in a zombie state if (playerInfo.Length < 5) continue; int clientId = -1; int Ping = -1; Int32.TryParse(playerInfo[2], out Ping); string name = Encoding.UTF8.GetString(Encoding.Convert(Utilities.EncodingType, Encoding.UTF8, Utilities.EncodingType.GetBytes(responseLine.Substring(23, 15).StripColors().Trim()))); long networkId = 0;//playerInfo[4].ConvertLong(); int.TryParse(playerInfo[0], out clientId); var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}"); int ipAddress = regex.Value.Split(':')[0].ConvertToIP(); regex = Regex.Match(responseLine, @" +(\d+ +){3}"); int score = Int32.Parse(regex.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries)[0]); var p = new Player() { Name = name, NetworkId = networkId, ClientNumber = clientId, IPAddress = ipAddress, Ping = Ping, Score = score, IsBot = false, State = Player.ClientState.Connecting }; StatusPlayers.Add(p); if (p.IsBot) p.NetworkId = -p.ClientNumber; } } return StatusPlayers; } } }