Fix bug with webfront spamming issues when running

Remove IW5 parser
Begin implementation of dynamic parsers
This commit is contained in:
RaidMax 2019-01-26 20:33:37 -06:00
parent 08c883e0ff
commit 7a6dccc26a
29 changed files with 223 additions and 325 deletions

View File

@ -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>

View File

@ -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();
}
}

View 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; }
}
}

View 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; }
}
}

View File

@ -6,6 +6,9 @@ namespace IW4MAdmin.Application.EventParsers
{
class IW3EventParser : IW4EventParser
{
public override string GetGameDir() => "main";
public IW3EventParser() : base()
{
Configuration.GameDirectory = "main";
}
}
}

View File

@ -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";
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -6,6 +6,9 @@ namespace IW4MAdmin.Application.EventParsers
{
class T5MEventParser : IW4EventParser
{
public override string GetGameDir() => "v2";
public T5MEventParser() : base()
{
Configuration.GameDirectory = "v2";
}
}
}

View File

@ -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";
}
}
}

View File

@ -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 ?

View 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; }
}
}

View 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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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)
{

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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; }
}
}

View 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; }
}
}

View File

@ -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;}
}
}

View File

@ -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; }
}
}

View 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; }
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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());

View File

@ -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);

View File

@ -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");

View File

@ -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 />