2018-04-11 18:24:21 -04:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
using SharedLibraryCore;
|
|
|
|
|
using SharedLibraryCore.Interfaces;
|
|
|
|
|
using SharedLibraryCore.Objects;
|
|
|
|
|
using SharedLibraryCore.RCon;
|
|
|
|
|
using SharedLibraryCore.Exceptions;
|
|
|
|
|
using System.Text;
|
2018-04-15 21:27:43 -04:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net.Http;
|
2018-04-11 18:24:21 -04:00
|
|
|
|
|
|
|
|
|
namespace Application.RconParsers
|
|
|
|
|
{
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public class T6MRConParser : IRConParser
|
2018-04-11 18:24:21 -04:00
|
|
|
|
{
|
2018-04-15 21:27:43 -04:00
|
|
|
|
class T6MResponse
|
|
|
|
|
{
|
|
|
|
|
public class SInfo
|
|
|
|
|
{
|
|
|
|
|
public short Com_maxclients { get; set; }
|
|
|
|
|
public string Game { get; set; }
|
|
|
|
|
public string Gametype { get; set; }
|
|
|
|
|
public string Mapname { get; set; }
|
|
|
|
|
public short NumBots { get; set; }
|
|
|
|
|
public short NumClients { get; set; }
|
|
|
|
|
public short Round { get; set; }
|
|
|
|
|
public string Sv_hostname { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class PInfo
|
|
|
|
|
{
|
|
|
|
|
public short Assists { get; set; }
|
|
|
|
|
public string Clan { get; set; }
|
|
|
|
|
public short Deaths { get; set; }
|
|
|
|
|
public short Downs { get; set; }
|
|
|
|
|
public short Headshots { get; set; }
|
|
|
|
|
public short Id { get; set; }
|
|
|
|
|
public bool IsBot { get; set; }
|
|
|
|
|
public short Kills { get; set; }
|
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
public short Ping { get; set; }
|
|
|
|
|
public short Revives { get; set; }
|
|
|
|
|
public int Score { get; set; }
|
|
|
|
|
public long Xuid { get; set; }
|
|
|
|
|
public string Ip { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SInfo Info { get; set; }
|
|
|
|
|
public PInfo[] Players { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
private static CommandPrefix Prefixes = new CommandPrefix()
|
|
|
|
|
{
|
|
|
|
|
Tell = "tell {0} {1}",
|
|
|
|
|
Say = "say {0}",
|
|
|
|
|
Kick = "clientKick {0}",
|
|
|
|
|
Ban = "clientKick {0}",
|
|
|
|
|
TempBan = "clientKick {0}"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public CommandPrefix GetCommandPrefixes() => Prefixes;
|
|
|
|
|
|
2018-04-11 18:24:21 -04:00
|
|
|
|
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
|
|
|
|
{
|
|
|
|
|
await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command, false);
|
|
|
|
|
return new string[] { "Command Executed" };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName)
|
|
|
|
|
{
|
|
|
|
|
string[] LineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"get {dvarName}");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (LineSplit.Length < 2)
|
|
|
|
|
{
|
|
|
|
|
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[1], @"\^[0-9]", "");
|
|
|
|
|
|
|
|
|
|
return new Dvar<T>(DvarName)
|
|
|
|
|
{
|
|
|
|
|
Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T))
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<List<Player>> GetStatusAsync(Connection connection)
|
|
|
|
|
{
|
|
|
|
|
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
|
|
|
|
|
return ClientsFromStatus(response);
|
2018-04-15 21:27:43 -04:00
|
|
|
|
|
|
|
|
|
//return ClientsFromResponse(connection);
|
2018-04-11 18:24:21 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<bool> 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;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-15 21:27:43 -04:00
|
|
|
|
private async Task<List<Player>> ClientsFromResponse(Connection conn)
|
|
|
|
|
{
|
|
|
|
|
using (var client = new HttpClient())
|
|
|
|
|
{
|
|
|
|
|
client.BaseAddress = new Uri($"http://{conn.Endpoint.Address}:{conn.Endpoint.Port}/");
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var parameters = new FormUrlEncodedContent(new[]
|
|
|
|
|
{
|
|
|
|
|
new KeyValuePair<string, string>("rcon_password", conn.RConPassword)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var serverResponse = await client.PostAsync("/info", parameters);
|
|
|
|
|
var serverResponseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<T6MResponse>(await serverResponse.Content.ReadAsStringAsync());
|
|
|
|
|
|
|
|
|
|
return serverResponseObject.Players.Select(p => new Player()
|
|
|
|
|
{
|
|
|
|
|
Name = p.Name,
|
|
|
|
|
NetworkId = p.Xuid,
|
|
|
|
|
ClientNumber = p.Id,
|
|
|
|
|
IPAddress = p.Ip.Split(':')[0].ConvertToIP(),
|
|
|
|
|
Ping = p.Ping,
|
|
|
|
|
Score = p.Score,
|
|
|
|
|
IsBot = p.IsBot,
|
|
|
|
|
}).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (HttpRequestException e)
|
|
|
|
|
{
|
|
|
|
|
throw new NetworkException(e.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-11 18:24:21 -04:00
|
|
|
|
private List<Player> ClientsFromStatus(string[] status)
|
|
|
|
|
{
|
|
|
|
|
List<Player> StatusPlayers = new List<Player>();
|
|
|
|
|
|
|
|
|
|
foreach (string statusLine in status)
|
|
|
|
|
{
|
2018-04-13 02:32:30 -04:00
|
|
|
|
String responseLine = statusLine;
|
2018-04-11 18:24:21 -04:00
|
|
|
|
|
2018-04-14 00:51:38 -04:00
|
|
|
|
if (Regex.Matches(responseLine, @"^ *\d+", RegexOptions.IgnoreCase).Count > 0) // its a client line!
|
2018-04-11 18:24:21 -04:00
|
|
|
|
{
|
|
|
|
|
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
int clientId = -1;
|
|
|
|
|
int Ping = -1;
|
|
|
|
|
|
|
|
|
|
Int32.TryParse(playerInfo[3], out Ping);
|
2018-04-13 02:32:30 -04:00
|
|
|
|
var regex = Regex.Match(responseLine, @"\^7.*\ +0 ");
|
2018-04-21 18:18:20 -04:00
|
|
|
|
string name = Encoding.UTF8.GetString(Encoding.Convert(Utilities.EncodingType, Encoding.UTF8, Utilities.EncodingType.GetBytes(regex.Value.Substring(0, regex.Value.Length - 2).StripColors().Trim())));
|
2018-04-11 18:24:21 -04:00
|
|
|
|
long networkId = playerInfo[4].ConvertLong();
|
|
|
|
|
int.TryParse(playerInfo[0], out clientId);
|
2018-04-13 02:32:30 -04:00
|
|
|
|
regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
2018-04-11 18:24:21 -04:00
|
|
|
|
#if DEBUG
|
|
|
|
|
Ping = 1;
|
|
|
|
|
#endif
|
|
|
|
|
int ipAddress = regex.Value.Split(':')[0].ConvertToIP();
|
|
|
|
|
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
|
2018-04-21 18:18:20 -04:00
|
|
|
|
int score = 0;
|
|
|
|
|
// todo: fix this when T6M score is valid ;)
|
|
|
|
|
//int score = Int32.Parse(playerInfo[1]);
|
2018-04-28 01:22:18 -04:00
|
|
|
|
var p = new Player()
|
2018-04-11 18:24:21 -04:00
|
|
|
|
{
|
|
|
|
|
Name = name,
|
|
|
|
|
NetworkId = networkId,
|
|
|
|
|
ClientNumber = clientId,
|
|
|
|
|
IPAddress = ipAddress,
|
|
|
|
|
Ping = Ping,
|
2018-04-21 18:18:20 -04:00
|
|
|
|
Score = score,
|
2018-04-24 18:01:27 -04:00
|
|
|
|
IsBot = networkId == 0
|
2018-04-28 01:22:18 -04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (p.IsBot)
|
|
|
|
|
p.NetworkId = -p.ClientNumber;
|
|
|
|
|
|
|
|
|
|
StatusPlayers.Add(p);
|
2018-04-11 18:24:21 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return StatusPlayers;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|