Move T6 parser to javascript parser

This commit is contained in:
RaidMax 2019-02-03 20:47:05 -06:00
parent e6bfa408f8
commit ce02f5dd68
17 changed files with 97 additions and 192 deletions

View File

@ -6,7 +6,7 @@
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
<Version>2.2.4.2</Version>
<Version>2.2.4.3</Version>
<Authors>RaidMax</Authors>
<Company>Forever None</Company>
<Product>IW4MAdmin</Product>
@ -31,8 +31,8 @@
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
<TieredCompilation>true</TieredCompilation>
<AssemblyVersion>2.2.4.2</AssemblyVersion>
<FileVersion>2.2.4.2</FileVersion>
<AssemblyVersion>2.2.4.3</AssemblyVersion>
<FileVersion>2.2.4.3</FileVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -16,26 +16,26 @@ namespace IW4MAdmin.Application.EventParsers
GameDirectory = "userraw",
};
Configuration.Say.Pattern = @"^(say|sayteam);(.{1,32});([0-9]+)(.*);(.*)$";
Configuration.Say.Pattern = @"^(say|sayteam);(.{8,32});([0-9]+);(.+);(.*)$";
Configuration.Say.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Say.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.Say.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.Say.AddMapping(ParserRegex.GroupType.OriginName, 4);
Configuration.Say.AddMapping(ParserRegex.GroupType.Message, 5);
Configuration.Quit.Pattern = @"^(Q);(.{16,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Quit.Pattern = @"^(Q);(.{8,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Quit.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Quit.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.Quit.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.Quit.AddMapping(ParserRegex.GroupType.OriginName, 4);
Configuration.Join.Pattern = @"^(J);(.{16,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Join.Pattern = @"^(J);(.{8,32}|bot[0-9]+);([0-9]+);(.*)$";
Configuration.Join.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginNetworkId, 2);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginClientNumber, 3);
Configuration.Join.AddMapping(ParserRegex.GroupType.OriginName, 4);
Configuration.Damage.Pattern = @"^(D);([A-Fa-f0-9_]{16,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});([A-Fa-f0-9_]{16,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Damage.Pattern = @"^(D);([A-Fa-f0-9_]{8,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});([A-Fa-f0-9_]{8,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Damage.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Damage.AddMapping(ParserRegex.GroupType.TargetNetworkId, 2);
Configuration.Damage.AddMapping(ParserRegex.GroupType.TargetClientNumber, 3);
@ -50,7 +50,7 @@ namespace IW4MAdmin.Application.EventParsers
Configuration.Damage.AddMapping(ParserRegex.GroupType.MeansOfDeath, 12);
Configuration.Damage.AddMapping(ParserRegex.GroupType.HitLocation, 13);
Configuration.Kill.Pattern = @"^(K);([A-Fa-f0-9_]{16,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});([A-Fa-f0-9_]{16,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Kill.Pattern = @"^(K);([A-Fa-f0-9_]{8,32}|bot[0-9]+);(-?[0-9]+);(axis|allies|world);(.{1,24});([A-Fa-f0-9_]{8,32}|bot[0-9]+)?;-?([0-9]+);(axis|allies|world);(.{1,24})?;((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$";
Configuration.Kill.AddMapping(ParserRegex.GroupType.EventType, 1);
Configuration.Kill.AddMapping(ParserRegex.GroupType.TargetNetworkId, 2);
Configuration.Kill.AddMapping(ParserRegex.GroupType.TargetClientNumber, 3);

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace IW4MAdmin.Application.EventParsers
{
class T5MEventParser : BaseEventParser
{
public T5MEventParser() : base()
{
Configuration.GameDirectory = "v2";
}
}
}

View File

@ -1,12 +0,0 @@
using System.IO;
namespace IW4MAdmin.Application.EventParsers
{
class T6MEventParser : BaseEventParser
{
public T6MEventParser() : base()
{
Configuration.GameDirectory = $"t6r{Path.DirectorySeparatorChar}data";
}
}
}

View File

@ -389,6 +389,7 @@ namespace IW4MAdmin
var dict = (Dictionary<string, string>)E.Extra;
Gametype = dict["g_gametype"].StripColors();
Hostname = dict["sv_hostname"].StripColors();
MaxClients = Int32.Parse(dict["sv_maxclients"]);
string mapname = dict["mapname"].StripColors();
CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map()
@ -666,10 +667,10 @@ namespace IW4MAdmin
public async Task Initialize()
{
RconParser = Manager.AdditionalRConParsers
.FirstOrDefault(_parser => _parser.Version == Manager.GetApplicationSettings().Configuration().CustomParserVersion);
.FirstOrDefault(_parser => _parser.Version == ServerConfig.CustomParserVersion);
EventParser = Manager.AdditionalEventParsers
.FirstOrDefault(_parser => _parser.Version == Manager.GetApplicationSettings().Configuration().CustomParserVersion);
.FirstOrDefault(_parser => _parser.Version == ServerConfig.CustomParserVersion);
RconParser = RconParser ?? new BaseRConParser();
EventParser = EventParser ?? new BaseEventParser();
@ -680,20 +681,10 @@ namespace IW4MAdmin
Version = version.Value;
GameName = Utilities.GetGame(version?.Value);
if (GameName == Game.T5M)
{
EventParser = new T5MEventParser();
}
else if (GameName == Game.T6M)
{
EventParser = new T6MEventParser();
}
else if (version.Value.Length != 0)
if (version?.Value?.Length != 0)
{
RconParser = Manager.AdditionalRConParsers.FirstOrDefault(_parser => _parser.Version == version.Value) ?? RconParser;
EventParser = Manager.AdditionalEventParsers.First(_parser => _parser.Version == version.Value) ?? EventParser;
EventParser = Manager.AdditionalEventParsers.FirstOrDefault(_parser => _parser.Version == version.Value) ?? EventParser;
}
var infoResponse = RconParser.Configuration.CommandPrefixes.RConGetInfo != null ? await this.GetInfoAsync() : null;

View File

@ -24,7 +24,9 @@ namespace IW4MAdmin.Application.RconParsers
Kick = "clientkick {0} \"{1}\"",
Ban = "clientkick {0} \"{1}\"",
TempBan = "tempbanclient {0} \"{1}\"",
RConQuery = "ÿÿÿÿrcon {0} {1}",
RConCommand = "ÿÿÿÿrcon {0} {1}",
RConGetDvar = "ÿÿÿÿrcon {0} {1}",
RConSetDvar = "ÿÿÿÿrcon {0} set {1}",
RConGetStatus = "ÿÿÿÿgetstatus",
RConGetInfo = "ÿÿÿÿgetinfo",
RConResponse = "ÿÿÿÿprint",
@ -60,7 +62,7 @@ namespace IW4MAdmin.Application.RconParsers
public async Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName)
{
string[] lineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.DVAR, dvarName);
string[] lineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.GET_DVAR, dvarName);
string response = string.Join('\n', lineSplit.Skip(1));
if (!lineSplit[0].Contains(Configuration.CommandPrefixes.RConResponse))
@ -102,7 +104,7 @@ namespace IW4MAdmin.Application.RconParsers
public async Task<bool> SetDvarAsync(Connection connection, string dvarName, object dvarValue)
{
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
return (await connection.SendQueryAsync(StaticHelpers.QueryType.SET_DVAR, $"{dvarName} {dvarValue}")).Length > 0;
}
private List<EFClient> ClientsFromStatus(string[] Status)

View File

@ -14,5 +14,6 @@ namespace IW4MAdmin.Application.RconParsers
public Server.Game GameName { get; set; }
public ParserRegex Status { get; set; } = new ParserRegex();
public ParserRegex Dvar { get; set; } = new ParserRegex();
public bool WaitForResponse { get; set; } = true;
}
}

View File

@ -1,133 +0,0 @@
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.RCon;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace IW4MAdmin.Application.RconParsers
{
public class T6MRConParser : IRConParser
{
public IRConParserConfiguration Configuration { get; set; }
public string Version { get; set; } = "";
public T6MRConParser()
{
Configuration = new DynamicRConParserConfiguration()
{
CommandPrefixes = new CommandPrefix()
{
Tell = "tell {0} {1}",
Say = "say {0}",
Kick = "clientkick_for_reason {0} \"{1}\"",
Ban = "clientkick_for_reason {0} \"{1}\"",
TempBan = "clientkick_for_reason {0} \"{1}\""
},
GameName = Server.Game.T6M
};
}
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>()
{
Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T)),
Name = DvarName
};
}
public async Task<List<EFClient>> GetStatusAsync(Connection connection)
{
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
return ClientsFromStatus(response);
}
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;
}
private List<EFClient> ClientsFromStatus(string[] status)
{
List<EFClient> StatusPlayers = new List<EFClient>();
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);
int clientId = -1;
int Ping = -1;
Int32.TryParse(playerInfo[3], out Ping);
var regex = Regex.Match(responseLine, @"\^7.*\ +0 ");
string name = Encoding.UTF8.GetString(Encoding.Convert(Utilities.EncodingType, Encoding.UTF8, Utilities.EncodingType.GetBytes(regex.Value.Substring(0, regex.Value.Length - 2).StripColors().Trim())));
long networkId = playerInfo[4].ConvertLong();
int.TryParse(playerInfo[0], out clientId);
regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
#if DEBUG
Ping = 1;
#endif
int? ipAddress = regex.Value.Split(':')[0].ConvertToIP();
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
var p = new EFClient()
{
Name = name,
NetworkId = networkId,
ClientNumber = clientId,
IPAddress = ipAddress,
Ping = Ping,
Score = 0,
State = EFClient.ClientState.Connecting,
IsBot = ipAddress == null
};
if (p.IsBot)
{
p.NetworkId = -p.ClientNumber;
}
StatusPlayers.Add(p);
}
}
return StatusPlayers;
}
}
}

View File

@ -39,6 +39,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlugins", "{3F9ACC27-26DB-49FA-BCD2-50C54A49C9FA}"
ProjectSection(SolutionItems) = preProject
Plugins\ScriptPlugins\ParserIW3.js = Plugins\ScriptPlugins\ParserIW3.js
Plugins\ScriptPlugins\ParserPT6.js = Plugins\ScriptPlugins\ParserPT6.js
Plugins\ScriptPlugins\ParserTeknoMW3.js = Plugins\ScriptPlugins\ParserTeknoMW3.js
Plugins\ScriptPlugins\SharedGUIDKick.js = Plugins\ScriptPlugins\SharedGUIDKick.js
Plugins\ScriptPlugins\VPNDetection.js = Plugins\ScriptPlugins\VPNDetection.js

View File

@ -0,0 +1,49 @@
var rconParser;
var eventParser;
var plugin = {
author: 'RaidMax',
version: 0.1,
name: 'Plutoniun T6 Parser',
isParser: true,
onEventAsync: function (gameEvent, server) {
},
onLoadAsync: function (manager) {
rconParser = manager.GenerateDynamicRConParser();
eventParser = manager.GenerateDynamicEventParser();
rconParser.Configuration.CommandPrefixes.Tell = 'tell {0} {1}';
rconParser.Configuration.CommandPrefixes.Say = 'say {0}';
rconParser.Configuration.CommandPrefixes.Kick = 'clientkick_for_reason {0} "{1}"';
rconParser.Configuration.CommandPrefixes.Ban = 'clientkick_for_reason {0} "{1}"';
rconParser.Configuration.CommandPrefixes.TempBan = 'clientkick_for_reason {0} "{1}"';
rconParser.Configuration.CommandPrefixes.RConGetDvar = '\xff\xff\xff\xffrcon {0} get {1}';
rconParser.Configuration.Dvar.Pattern = '^(.+) is "(.+)?"$';
rconParser.Configuration.Dvar.AddMapping(106, 1);
rconParser.Configuration.Dvar.AddMapping(107, 2);
rconParser.Configuration.WaitForResponse = false;
rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +([0-9]+) +(.+) +((?:[A-Z]+|[0-9]+)) +((?:[A-Z]|[0-9]){8,16}) +(.{0,16}) +([0-9]+) +(\\d+\\.\\d+\\.\\d+\\.\\d+\\:-?\\d{1,5}|0+\\.0+:-?\\d{1,5}|loopback) +(-?[0-9]+) +([0-9]+) *$'
rconParser.Configuration.Status.AddMapping(100, 1);
rconParser.Configuration.Status.AddMapping(101, 2);
rconParser.Configuration.Status.AddMapping(102, 4);
rconParser.Configuration.Status.AddMapping(103, 5);
rconParser.Configuration.Status.AddMapping(104, 6);
rconParser.Configuration.Status.AddMapping(105, 8);
eventParser.Configuration.GameDirectory = 't6r\\\\data';
rconParser.Version = 'Call of Duty Multiplayer - Ship COD_T6_S MP build 1.0.44 CL(1759941) CODPCAB2 CEG Fri May 9 19:19:19 2014 win-x86 813e66d5';
eventParser.Version = 'Call of Duty Multiplayer - Ship COD_T6_S MP build 1.0.44 CL(1759941) CODPCAB2 CEG Fri May 9 19:19:19 2014 win-x86 813e66d5';
},
onUnloadAsync: function () {
},
onTickAsync: function (server) {
}
};

View File

@ -28,7 +28,6 @@ namespace SharedLibraryCore.Configuration
public string Id { get; set; }
public List<ServerConfiguration> Servers { get; set; }
public int AutoMessagePeriod { get; set; }
public string CustomParserVersion { get; set; }
public List<string> AutoMessages { get; set; }
public List<string> GlobalRules { get; set; }
public List<MapConfiguration> Maps { get; set; }

View File

@ -13,6 +13,7 @@ namespace SharedLibraryCore.Configuration
public IList<string> AutoMessages { get; set; }
public bool UseT6MParser { get; set; }
public string ManualLogPath { get; set; }
public string CustomParserVersion { get; set; }
public int ReservedSlotNumber { get; set; }
public IBaseConfiguration Generate()

View File

@ -20,5 +20,10 @@ namespace SharedLibraryCore.Interfaces
/// stores the regex info for parsing get DVAR responses
/// </summary>
ParserRegex Dvar { get; set; }
/// <summary>
/// indicates if the application should wait for response from server
/// when executing a command
/// </summary>
bool WaitForResponse { get; set; }
}
}

View File

@ -434,7 +434,7 @@ namespace SharedLibraryCore.Database.Models
// reserved slots stuff
// todo: bots don't seem to honor party_maxplayers/sv_maxclients
if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged())) < CurrentServer.ServerConfig.ReservedSlotNumber &&
if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged() && !_client.IsBot)) < CurrentServer.ServerConfig.ReservedSlotNumber &&
!this.IsPrivileged() &&
CurrentServer.GetClientsAsList().Count <= CurrentServer.MaxClients &&
CurrentServer.MaxClients != 0)

View File

@ -13,7 +13,9 @@ namespace SharedLibraryCore.RCon
public string Ban { get; set; }
public string Unban { get; set; }
public string TempBan { get; set; }
public string RConQuery { get; set; }
public string RConCommand { get; set; }
public string RConGetDvar { get; set; }
public string RConSetDvar { get; set; }
public string RConGetStatus { get; set; }
public string RConGetInfo { get; set; }
public string RConResponse { get; set; }

View File

@ -45,7 +45,7 @@ namespace SharedLibraryCore.RCon
Config = config;
}
public async Task<string[]> SendQueryAsync(StaticHelpers.QueryType type, string parameters = "", bool waitForResponse = true)
public async Task<string[]> SendQueryAsync(StaticHelpers.QueryType type, string parameters = "")
{
if (!ActiveQueries.ContainsKey(this.Endpoint))
{
@ -75,18 +75,26 @@ namespace SharedLibraryCore.RCon
#endif
byte[] payload = null;
bool waitForResponse = Config.WaitForResponse;
switch (type)
{
case StaticHelpers.QueryType.DVAR:
case StaticHelpers.QueryType.GET_DVAR:
waitForResponse |= true;
payload = (string.Format(Config.CommandPrefixes.RConGetDvar, RConPassword, parameters + '\0')).Select(Convert.ToByte).ToArray();
break;
case StaticHelpers.QueryType.SET_DVAR:
payload = (string.Format(Config.CommandPrefixes.RConSetDvar, RConPassword, parameters + '\0')).Select(Convert.ToByte).ToArray();
break;
case StaticHelpers.QueryType.COMMAND:
payload = Utilities.EncodingType
.GetBytes(string.Format(Config.CommandPrefixes.RConQuery, RConPassword, parameters + '\0'));
payload = (string.Format(Config.CommandPrefixes.RConCommand, RConPassword, parameters + '\0')).Select(Convert.ToByte).ToArray();
break;
case StaticHelpers.QueryType.GET_STATUS:
waitForResponse |= true;
payload = (Config.CommandPrefixes.RConGetStatus + '\0').Select(Convert.ToByte).ToArray();
break;
case StaticHelpers.QueryType.GET_INFO:
waitForResponse |= true;
payload = (Config.CommandPrefixes.RConGetInfo + '\0').Select(Convert.ToByte).ToArray();
break;
}

View File

@ -24,7 +24,12 @@ namespace SharedLibraryCore.RCon
/// retrieve the value of a DVAR
/// RCon password is required
/// </summary>
DVAR,
GET_DVAR,
/// <summary>
/// set the value of a DVAR
/// RCon password is required
/// </summary>
SET_DVAR,
/// <summary>
/// execute a command
/// RCon password is required