Fix bug with webfront spamming issues when running
Remove IW5 parser Begin implementation of dynamic parsers
This commit is contained in:
parent
08c883e0ff
commit
7a6dccc26a
@ -6,7 +6,7 @@
|
||||
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
|
||||
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
|
||||
<PackageId>RaidMax.IW4MAdmin.Application</PackageId>
|
||||
<Version>2.2.3.2</Version>
|
||||
<Version>2.2.3.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.3.2</AssemblyVersion>
|
||||
<FileVersion>2.2.3.2</FileVersion>
|
||||
<AssemblyVersion>2.2.3.3</AssemblyVersion>
|
||||
<FileVersion>2.2.3.3</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,4 +1,6 @@
|
||||
using IW4MAdmin.Application.API.Master;
|
||||
using IW4MAdmin.Application.EventParsers;
|
||||
using IW4MAdmin.Application.RconParsers;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Commands;
|
||||
using SharedLibraryCore.Configuration;
|
||||
@ -34,6 +36,13 @@ namespace IW4MAdmin.Application
|
||||
public DateTime StartTime { get; private set; }
|
||||
public string Version => Assembly.GetEntryAssembly().GetName().Version.ToString();
|
||||
|
||||
public IList<IRConParser> AdditionalRConParsers => _additionalRConParsers.ToList<IRConParser>();
|
||||
|
||||
public IList<IEventParser> AdditionalEventParsers => _additionalEventParsers.ToList<IEventParser>();
|
||||
|
||||
private readonly IList<DynamicRConParser> _additionalRConParsers;
|
||||
private readonly IList<DynamicEventParser> _additionalEventParsers;
|
||||
|
||||
static ApplicationManager Instance;
|
||||
readonly List<AsyncStatus> TaskStatuses;
|
||||
List<Command> Commands;
|
||||
@ -61,6 +70,8 @@ namespace IW4MAdmin.Application
|
||||
StartTime = DateTime.UtcNow;
|
||||
OnQuit = new ManualResetEventSlim();
|
||||
PageList = new PageList();
|
||||
_additionalEventParsers = new List<DynamicEventParser>();
|
||||
_additionalRConParsers = new List<DynamicRConParser>();
|
||||
OnServerEvent += OnGameEvent;
|
||||
OnServerEvent += EventApi.OnGameEvent;
|
||||
}
|
||||
@ -552,5 +563,9 @@ namespace IW4MAdmin.Application
|
||||
{
|
||||
return PageList;
|
||||
}
|
||||
|
||||
public IRConParser GenerateDynamicRConParser() => new DynamicRConParser();
|
||||
|
||||
public IEventParser GenerateDynamicEventParser() => new DynamicEventParser();
|
||||
}
|
||||
}
|
12
Application/EventParsers/DynamicEventParser.cs
Normal file
12
Application/EventParsers/DynamicEventParser.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using static SharedLibraryCore.Server;
|
||||
|
||||
namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
sealed internal class DynamicEventParser : IW4EventParser
|
||||
{
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
14
Application/EventParsers/DynamicEventParserConfiguration.cs
Normal file
14
Application/EventParsers/DynamicEventParserConfiguration.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using SharedLibraryCore.Interfaces;
|
||||
|
||||
namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
class DynamicEventParserConfiguration : IEventParserConfiguration
|
||||
{
|
||||
public string GameDirectory { get; set; }
|
||||
public string SayRegex { get; set; }
|
||||
public string JoinRegex { get; set; }
|
||||
public string QuitRegex { get; set; }
|
||||
public string KillRegex { get; set; }
|
||||
public string DamageRegex { get; set; }
|
||||
}
|
||||
}
|
@ -6,6 +6,9 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
class IW3EventParser : IW4EventParser
|
||||
{
|
||||
public override string GetGameDir() => "main";
|
||||
public IW3EventParser() : base()
|
||||
{
|
||||
Configuration.GameDirectory = "main";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,21 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
class IW4EventParser : IEventParser
|
||||
{
|
||||
private const string SayRegex = @"(say|sayteam);(.{1,32});([0-9]+)(.*);(.*)";
|
||||
private IEventParserConfiguration _configuration;
|
||||
|
||||
public IW4EventParser()
|
||||
{
|
||||
_configuration = new DynamicEventParserConfiguration()
|
||||
{
|
||||
GameDirectory = "userraw",
|
||||
SayRegex = "(say|sayteam);(.{1,32});([0-9]+)(.*);(.*)",
|
||||
QuitRegex = @"^(Q;)(.{1,32});([0-9]+);(.*)$",
|
||||
JoinRegex = @"^(J;)(.{1,32});([0-9]+);(.*)$",
|
||||
DamageRegex = @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$"
|
||||
};
|
||||
}
|
||||
|
||||
public IEventParserConfiguration Configuration { get => _configuration; set => _configuration = value; }
|
||||
|
||||
public virtual GameEvent GetEvent(Server server, string logLine)
|
||||
{
|
||||
@ -32,7 +46,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
|
||||
if (eventType == "say" || eventType == "sayteam")
|
||||
{
|
||||
var matchResult = Regex.Match(logLine, SayRegex);
|
||||
var matchResult = Regex.Match(logLine, _configuration.SayRegex);
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
@ -117,7 +131,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
if (!server.CustomCallback)
|
||||
{
|
||||
if (Regex.Match(eventType, @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$").Success)
|
||||
if (Regex.Match(eventType, _configuration.DamageRegex).Success)
|
||||
{
|
||||
var origin = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[5].ConvertLong());
|
||||
var target = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong());
|
||||
@ -137,7 +151,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
// join
|
||||
if (eventType == "J")
|
||||
{
|
||||
var regexMatch = Regex.Match(logLine, @"^(J;)(.{1,32});([0-9]+);(.*)$");
|
||||
var regexMatch = Regex.Match(logLine, _configuration.JoinRegex);
|
||||
if (regexMatch.Success)
|
||||
{
|
||||
return new GameEvent()
|
||||
@ -163,7 +177,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
|
||||
if (eventType == "Q")
|
||||
{
|
||||
var regexMatch = Regex.Match(logLine, @"^(Q;)(.{1,32});([0-9]+);(.*)$");
|
||||
var regexMatch = Regex.Match(logLine, _configuration.QuitRegex);
|
||||
if (regexMatch.Success)
|
||||
{
|
||||
return new GameEvent()
|
||||
@ -221,11 +235,5 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
Owner = server
|
||||
};
|
||||
}
|
||||
|
||||
// other parsers can derive from this parser so we make it virtual
|
||||
public virtual string GetGameDir()
|
||||
{
|
||||
return "userraw";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
class IW5EventParser : IW4EventParser
|
||||
{
|
||||
public override string GetGameDir()
|
||||
{
|
||||
return "logs";
|
||||
}
|
||||
|
||||
public override GameEvent GetEvent(Server server, string logLine)
|
||||
{
|
||||
string cleanedEventLine = Regex.Replace(logLine, @"[0-9]+:[0-9]+\ ", "").Trim();
|
||||
|
||||
if (cleanedEventLine.Contains("J;"))
|
||||
{
|
||||
string[] lineSplit = cleanedEventLine.Split(';');
|
||||
|
||||
int clientNum = Int32.Parse(lineSplit[2]);
|
||||
|
||||
var player = new EFClient()
|
||||
{
|
||||
NetworkId = lineSplit[1].ConvertLong(),
|
||||
ClientNumber = clientNum,
|
||||
CurrentAlias = new EFAlias()
|
||||
{
|
||||
Active = false,
|
||||
Name = lineSplit[3]
|
||||
}
|
||||
};
|
||||
|
||||
return new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.PreConnect,
|
||||
Origin = new EFClient()
|
||||
{
|
||||
ClientId = 1
|
||||
},
|
||||
Target = new EFClient()
|
||||
{
|
||||
ClientId = 1
|
||||
},
|
||||
Owner = server,
|
||||
Extra = player
|
||||
};
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return base.GetEvent(server, logLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,9 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
class T5MEventParser : IW4EventParser
|
||||
{
|
||||
public override string GetGameDir() => "v2";
|
||||
public T5MEventParser() : base()
|
||||
{
|
||||
Configuration.GameDirectory = "v2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.Objects;
|
||||
using System.IO;
|
||||
|
||||
namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
class T6MEventParser : IW4EventParser
|
||||
{
|
||||
public override string GetGameDir() => $"t6r{Path.DirectorySeparatorChar}data";
|
||||
public T6MEventParser() : base()
|
||||
{
|
||||
Configuration.GameDirectory = $"t6r{Path.DirectorySeparatorChar}data";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -669,32 +669,26 @@ namespace IW4MAdmin
|
||||
(IRConParser)new T6MRConParser() :
|
||||
new IW3RConParser();
|
||||
|
||||
if (ServerConfig.UseIW5MParser)
|
||||
{
|
||||
RconParser = new IW5MRConParser();
|
||||
}
|
||||
|
||||
var version = await this.GetDvarAsync<string>("version");
|
||||
Version = version.Value;
|
||||
GameName = Utilities.GetGame(version.Value);
|
||||
//GameName = Utilities.GetGame(version.Value);
|
||||
|
||||
if (GameName == Game.IW4)
|
||||
{
|
||||
EventParser = new IW4EventParser();
|
||||
RconParser = new IW4RConParser();
|
||||
}
|
||||
else if (GameName == Game.IW5)
|
||||
{
|
||||
EventParser = new IW5EventParser();
|
||||
}
|
||||
|
||||
else if (GameName == Game.T5M)
|
||||
{
|
||||
EventParser = new T5MEventParser();
|
||||
}
|
||||
|
||||
else if (GameName == Game.T6M)
|
||||
{
|
||||
EventParser = new T6MEventParser();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
EventParser = new IW3EventParser(); // this uses the 'main' folder for log paths
|
||||
@ -703,6 +697,9 @@ namespace IW4MAdmin
|
||||
if (GameName == Game.UKN)
|
||||
{
|
||||
Logger.WriteWarning($"Game name not recognized: {version}");
|
||||
|
||||
EventParser = Manager.AdditionalEventParsers.FirstOrDefault(_parser => (_parser as DynamicEventParser).Version == version.Value) ?? EventParser;
|
||||
RconParser = Manager.AdditionalRConParsers.FirstOrDefault(_parser => (_parser as DynamicRConParser).Version == version.Value) ?? RconParser;
|
||||
}
|
||||
|
||||
var infoResponse = await this.GetInfoAsync();
|
||||
@ -763,7 +760,7 @@ namespace IW4MAdmin
|
||||
}
|
||||
|
||||
CustomCallback = await ScriptLoaded();
|
||||
string mainPath = EventParser.GetGameDir();
|
||||
string mainPath = EventParser.Configuration.GameDirectory;
|
||||
string logPath = string.Empty;
|
||||
|
||||
LogPath = game == string.Empty ?
|
||||
|
12
Application/RconParsers/DynamicRConParser.cs
Normal file
12
Application/RconParsers/DynamicRConParser.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.RCon;
|
||||
using System;
|
||||
using static SharedLibraryCore.Server;
|
||||
|
||||
namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
sealed internal class DynamicRConParser : IW4RConParser
|
||||
{
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
13
Application/RconParsers/DynamicRConParserConfiguration.cs
Normal file
13
Application/RconParsers/DynamicRConParserConfiguration.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.RCon;
|
||||
|
||||
namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
class DynamicRConParserConfiguration : IRConParserConfiguration
|
||||
{
|
||||
public CommandPrefix CommandPrefixes { get; set; }
|
||||
public Server.Game GameName { get; set; }
|
||||
public string StatusRegex { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using SharedLibraryCore.RCon;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.RCon;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
@ -7,7 +8,9 @@ namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
class IW3RConParser : IW4RConParser
|
||||
{
|
||||
private static readonly CommandPrefix Prefixes = new CommandPrefix()
|
||||
public IW3RConParser() : base()
|
||||
{
|
||||
Configuration.CommandPrefixes = new CommandPrefix()
|
||||
{
|
||||
Tell = "tell {0} {1}",
|
||||
Say = "say {0}",
|
||||
@ -16,6 +19,7 @@ namespace IW4MAdmin.Application.RconParsers
|
||||
TempBan = "tempbanclient {0} \"{1}\""
|
||||
};
|
||||
|
||||
public override CommandPrefix GetCommandPrefixes() => Prefixes;
|
||||
Configuration.GameName = Server.Game.IW3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,16 +13,24 @@ namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
class IW4RConParser : IRConParser
|
||||
{
|
||||
private static readonly CommandPrefix Prefixes = new CommandPrefix()
|
||||
public IW4RConParser()
|
||||
{
|
||||
Configuration = new DynamicRConParserConfiguration()
|
||||
{
|
||||
CommandPrefixes = new CommandPrefix()
|
||||
{
|
||||
Tell = "tellraw {0} {1}",
|
||||
Say = "sayraw {0}",
|
||||
Kick = "clientkick {0} \"{1}\"",
|
||||
Ban = "clientkick {0} \"{1}\"",
|
||||
TempBan = "tempbanclient {0} \"{1}\""
|
||||
},
|
||||
StatusRegex = @"^( *[0-9]+) +-*([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){16}|(?:[a-z]|[0-9]){32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +([0-9]+) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}|loopback) +(-*[0-9]+) +([0-9]+) *$",
|
||||
GameName = Server.Game.IW4
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly string StatusRegex = @"^( *[0-9]+) +-*([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){16}|(?:[a-z]|[0-9]){32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +([0-9]+) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}|loopback) +(-*[0-9]+) +([0-9]+) *$";
|
||||
public IRConParserConfiguration Configuration { get; set; }
|
||||
|
||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||
{
|
||||
@ -71,11 +79,6 @@ namespace IW4MAdmin.Application.RconParsers
|
||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
||||
}
|
||||
|
||||
public virtual CommandPrefix GetCommandPrefixes()
|
||||
{
|
||||
return Prefixes;
|
||||
}
|
||||
|
||||
private List<EFClient> ClientsFromStatus(string[] Status)
|
||||
{
|
||||
List<EFClient> StatusPlayers = new List<EFClient>();
|
||||
@ -90,7 +93,7 @@ namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
String responseLine = S.Trim();
|
||||
|
||||
var regex = Regex.Match(responseLine, StatusRegex, RegexOptions.IgnoreCase);
|
||||
var regex = Regex.Match(responseLine, Configuration.StatusRegex, RegexOptions.IgnoreCase);
|
||||
|
||||
if (regex.Success)
|
||||
{
|
||||
|
@ -1,171 +0,0 @@
|
||||
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;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
|
||||
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<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)
|
||||
{
|
||||
// why can't this be real :(
|
||||
if (dvarName == "version")
|
||||
return new Dvar<T>(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<T>(dvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType("1.9", typeof(T))
|
||||
};
|
||||
|
||||
if (dvarName == "mapname")
|
||||
return new Dvar<T>(dvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType("Unknown", typeof(T))
|
||||
};
|
||||
|
||||
if (dvarName == "g_gametype")
|
||||
return new Dvar<T>(dvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType("Unknown", typeof(T))
|
||||
};
|
||||
|
||||
if (dvarName == "fs_game")
|
||||
return new Dvar<T>(dvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType("", typeof(T))
|
||||
};
|
||||
|
||||
if (dvarName == "g_logsync")
|
||||
return new Dvar<T>(dvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType(1, typeof(T))
|
||||
};
|
||||
|
||||
if (dvarName == "fs_basepath")
|
||||
return new Dvar<T>(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<T>(DvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T))
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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 EFClient()
|
||||
{
|
||||
Name = name,
|
||||
NetworkId = networkId,
|
||||
ClientNumber = clientId,
|
||||
IPAddress = ipAddress,
|
||||
Ping = Ping,
|
||||
Score = score,
|
||||
IsBot = false,
|
||||
State = EFClient.ClientState.Connecting
|
||||
};
|
||||
|
||||
StatusPlayers.Add(p);
|
||||
|
||||
if (p.IsBot)
|
||||
p.NetworkId = -p.ClientNumber;
|
||||
}
|
||||
}
|
||||
|
||||
return StatusPlayers;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +1,35 @@
|
||||
using System;
|
||||
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;
|
||||
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.Objects;
|
||||
using SharedLibraryCore.RCon;
|
||||
using SharedLibraryCore.Exceptions;
|
||||
using System.Text;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
|
||||
namespace IW4MAdmin.Application.RconParsers
|
||||
{
|
||||
public class T6MRConParser : IRConParser
|
||||
{
|
||||
private static readonly CommandPrefix Prefixes = new CommandPrefix()
|
||||
public IRConParserConfiguration Configuration { 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 CommandPrefix GetCommandPrefixes() => Prefixes;
|
||||
}
|
||||
|
||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||
{
|
||||
@ -112,7 +117,9 @@ namespace IW4MAdmin.Application.RconParsers
|
||||
};
|
||||
|
||||
if (p.IsBot)
|
||||
{
|
||||
p.NetworkId = -p.ClientNumber;
|
||||
}
|
||||
|
||||
StatusPlayers.Add(p);
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ namespace SharedLibraryCore.Configuration
|
||||
public IList<string> Rules { get; set; }
|
||||
public IList<string> AutoMessages { get; set; }
|
||||
public bool UseT6MParser { get; set; }
|
||||
public bool UseIW5MParser { get; set; }
|
||||
public string ManualLogPath { get; set; }
|
||||
public int ReservedSlotNumber { get; set; }
|
||||
|
||||
@ -36,17 +35,9 @@ namespace SharedLibraryCore.Configuration
|
||||
}
|
||||
|
||||
Password = Utilities.PromptString(loc["SETUP_SERVER_RCON"]);
|
||||
|
||||
AutoMessages = new List<string>();
|
||||
Rules = new List<string>();
|
||||
|
||||
|
||||
UseT6MParser = Utilities.PromptBool(loc["SETUP_SERVER_USET6M"]);
|
||||
if (!UseT6MParser)
|
||||
UseIW5MParser = Utilities.PromptBool(loc["SETUP_SERVER_USEIW5M"]);
|
||||
if (UseIW5MParser)
|
||||
ManualLogPath = Utilities.PromptString(loc["SETUP_SERVER_MANUALLOG"]);
|
||||
|
||||
ReservedSlotNumber = loc["SETUP_SERVER_RESERVEDSLOT"].PromptInt(null, 0, 32);
|
||||
|
||||
return this;
|
||||
|
@ -18,6 +18,6 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// Get game specific folder prefix for log files
|
||||
/// </summary>
|
||||
/// <returns>Game directory prefix</returns>
|
||||
string GetGameDir();
|
||||
IEventParserConfiguration Configuration { get; set; }
|
||||
}
|
||||
}
|
||||
|
16
SharedLibraryCore/Interfaces/IEventParserConfiguration.cs
Normal file
16
SharedLibraryCore/Interfaces/IEventParserConfiguration.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IEventParserConfiguration
|
||||
{
|
||||
string GameDirectory { get; set; }
|
||||
string SayRegex { get; set; }
|
||||
string JoinRegex { get; set; }
|
||||
string QuitRegex { get; set; }
|
||||
string KillRegex { get; set; }
|
||||
string DamageRegex { get; set; }
|
||||
}
|
||||
}
|
@ -40,6 +40,10 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IPageList GetPageList();
|
||||
IList<IRConParser> AdditionalRConParsers { get; }
|
||||
IList<IEventParser> AdditionalEventParsers { get; }
|
||||
IRConParser GenerateDynamicRConParser();
|
||||
IEventParser GenerateDynamicEventParser();
|
||||
string Version { get;}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using System.Threading.Tasks;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Objects;
|
||||
using SharedLibraryCore.RCon;
|
||||
using static SharedLibraryCore.Server;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
@ -12,6 +13,6 @@ namespace SharedLibraryCore.Interfaces
|
||||
Task<bool> SetDvarAsync(Connection connection, string dvarName, object dvarValue);
|
||||
Task<string[]> ExecuteCommandAsync(Connection connection, string command);
|
||||
Task<List<EFClient>> GetStatusAsync(Connection connection);
|
||||
CommandPrefix GetCommandPrefixes();
|
||||
IRConParserConfiguration Configuration { get; set; }
|
||||
}
|
||||
}
|
||||
|
11
SharedLibraryCore/Interfaces/IRConParserConfiguration.cs
Normal file
11
SharedLibraryCore/Interfaces/IRConParserConfiguration.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using SharedLibraryCore.RCon;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IRConParserConfiguration
|
||||
{
|
||||
CommandPrefix CommandPrefixes { get; set; }
|
||||
Server.Game GameName { get; set; }
|
||||
string StatusRegex { get; set; }
|
||||
}
|
||||
}
|
@ -461,6 +461,11 @@ namespace SharedLibraryCore.Database.Models
|
||||
|
||||
if (ipAddress != null)
|
||||
{
|
||||
if (IPAddressString == "66.150.121.184")
|
||||
{
|
||||
Kick("Your favorite servers are outdated. Please re-add the server.", autoKickClient);
|
||||
return false;
|
||||
}
|
||||
await CurrentServer.Manager.GetClientService().UpdateAlias(this);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,10 @@ namespace SharedLibraryCore.RCon
|
||||
/// <summary>
|
||||
/// interval in milliseconds to wait before sending the next RCon request
|
||||
/// </summary>
|
||||
public static readonly int FloodProtectionInterval = 635;
|
||||
public static readonly int FloodProtectionInterval = 650;
|
||||
/// <summary>
|
||||
/// how mant failed connection attempts before aborting connection
|
||||
/// </summary>
|
||||
public static readonly int AllowedConnectionFails = 3;
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,17 @@ namespace SharedLibraryCore
|
||||
this.Name = pluginObject.name;
|
||||
this.Version = (float)pluginObject.version;
|
||||
|
||||
|
||||
if (pluginObject.isParser)
|
||||
{
|
||||
await OnLoadAsync(mgr);
|
||||
IEventParser eventParser = (IEventParser)ScriptEngine.GetValue("eventParser").ToObject();
|
||||
IRConParser rconParser = (IRConParser)ScriptEngine.GetValue("rconParser").ToObject();
|
||||
Manager.AdditionalEventParsers.Add(eventParser);
|
||||
Manager.AdditionalRConParsers.Add(rconParser);
|
||||
}
|
||||
|
||||
|
||||
if (!firstRun)
|
||||
{
|
||||
await OnLoadAsync(mgr);
|
||||
|
@ -120,7 +120,7 @@ namespace SharedLibraryCore
|
||||
/// <param name="message">Message to be sent to all players</param>
|
||||
public GameEvent Broadcast(string message, EFClient sender = null)
|
||||
{
|
||||
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Say, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message}");
|
||||
string formattedMessage = String.Format(RconParser.Configuration.CommandPrefixes.Say, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message}");
|
||||
|
||||
#if DEBUG == true
|
||||
Logger.WriteVerbose(message.StripColors());
|
||||
|
@ -35,7 +35,7 @@ namespace WebfrontCore.Controllers
|
||||
Level = p.Level.ToLocalizedLevelName(),
|
||||
LevelInt = (int)p.Level
|
||||
}).ToList(),
|
||||
ChatHistory = s.ChatHistory,
|
||||
ChatHistory = s.ChatHistory.ToList(),
|
||||
PlayerHistory = s.ClientHistory.ToArray(),
|
||||
};
|
||||
return PartialView("_ClientActivity", serverInfo);
|
||||
|
@ -6,9 +6,6 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SharedLibraryCore.Database;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace WebfrontCore
|
||||
{
|
||||
@ -62,6 +59,7 @@ namespace WebfrontCore
|
||||
loggerFactory.AddDebug();
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
@{
|
||||
Layout = null;
|
||||
int half = (int)Math.Ceiling(Model.ClientCount / 2.0);
|
||||
int half = Model.ClientCount == 0 || Model.Players.Count == 0 ? 0 : (int)Math.Ceiling(Model.ClientCount / 2.0);
|
||||
}
|
||||
<div class="col-12 col-md-8 d-none d-md-block">
|
||||
@{
|
||||
@ -43,7 +43,7 @@
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
@{
|
||||
for (int i = half; i < Model.ClientCount; i++)
|
||||
for (int i = half; i < Math.Min(Model.ClientCount, Model.Players.Count); i++)
|
||||
{
|
||||
string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}";
|
||||
<span>@Html.ActionLink(Model.Players[i].Name, "ProfileAsync", "Client", new { id = Model.Players[i].ClientId }, new { @class = levelColorClass })</span><br />
|
||||
|
Loading…
Reference in New Issue
Block a user