Profanity deterrent kick players with offensive names
status parsing with Regex in IW4 is much cleaner fixed tempban not always kicking made plugin event tasks parallel
This commit is contained in:
parent
35e7f57156
commit
3a463be7f8
@ -192,6 +192,9 @@
|
||||
"GLOBAL_ERROR": "Error",
|
||||
"GLOBAL_WARNING": "Warning",
|
||||
"GLOBAL_INFO": "Info",
|
||||
"GLOBAL_VERBOSE": "Verbose"
|
||||
"GLOBAL_VERBOSE": "Verbose",
|
||||
|
||||
"MANAGER_CONSOLE_NOSERV": "No servers are currently being monitored",
|
||||
"SERVER_PLUGIN_ERROR": "A plugin generated an error"
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@
|
||||
"SERVER_WARNLIMT_REACHED": "Слишком много предупреждений",
|
||||
"SERVER_WARNING": "Предупреждение",
|
||||
"SERVER_WEBSITE_GENERIC": "веб-сайт этого сервера",
|
||||
"BROADCAST_ONLINE": "^5IW4MADMIN ^7сейчас ^В СЕТИ",
|
||||
"BROADCAST_ONLINE": "^5IW4MADMIN ^7сейчас СЕТИ",
|
||||
"BROADCAST_OFFLINE": "IW4MAdmin отключается",
|
||||
"COMMAND_HELP_SYNTAX": "синтаксис:",
|
||||
"COMMAND_HELP_OPTIONAL": "опционально",
|
||||
|
@ -23,6 +23,11 @@ namespace Application.Misc
|
||||
string response = await RequestClient.GetStringAsync($"http://v2.api.iphub.info/ip/{ip}");
|
||||
var responseJson = JsonConvert.DeserializeObject<JObject>(response);
|
||||
int blockType = Convert.ToInt32(responseJson["block"]);
|
||||
if (responseJson.ContainsKey("isp"))
|
||||
{
|
||||
if (responseJson["isp"].ToString() == "TSF-IP-CORE")
|
||||
return true;
|
||||
}
|
||||
return blockType == 1;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ namespace Application.RconParsers
|
||||
Ban = "clientkick {0} \"{1}\"",
|
||||
TempBan = "tempbanclient {0} \"{1}\""
|
||||
};
|
||||
|
||||
|
||||
private static string StatusRegex = @"^( *[0-9]+) +([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){16}|bot[0-9]+) +(.{0,20}) +([0-9]+) +(\d+\.\d+\.\d+.\d+\:\d{1,5}|0+.0+:\d{1,5}) +(-*[0-9]+) +([0-9]+) *$";
|
||||
|
||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||
{
|
||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command)).Skip(1).ToArray();
|
||||
@ -82,30 +84,33 @@ namespace Application.RconParsers
|
||||
{
|
||||
String responseLine = S.Trim();
|
||||
|
||||
if (Regex.Matches(responseLine, @" *^\d+", RegexOptions.IgnoreCase).Count > 0)
|
||||
var regex = Regex.Match(responseLine, StatusRegex, RegexOptions.IgnoreCase);
|
||||
if (regex.Success)
|
||||
{
|
||||
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (playerInfo.Length < 4)
|
||||
continue;
|
||||
int cID = -1;
|
||||
int Ping = -1;
|
||||
Int32.TryParse(playerInfo[2], out Ping);
|
||||
String cName = Encoding.UTF8.GetString(Encoding.Convert(Utilities.EncodingType, Encoding.UTF8, Utilities.EncodingType.GetBytes(responseLine.Substring(46, 18).StripColors().Trim())));
|
||||
long npID = Regex.Match(responseLine, @"([a-z]|[0-9]){16}|bot[0-9]+", RegexOptions.IgnoreCase).Value.ConvertLong();
|
||||
int.TryParse(playerInfo[0], out cID);
|
||||
var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
||||
int cIP = regex.Value.Split(':')[0].ConvertToIP();
|
||||
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
|
||||
int score = Int32.Parse(regex.Value.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1]);
|
||||
int clientNumber = int.Parse(regex.Groups[1].Value);
|
||||
int score = int.Parse(regex.Groups[2].Value);
|
||||
|
||||
int ping = 999;
|
||||
|
||||
// their state can be CNCT, ZMBI etc
|
||||
if (regex.Groups[3].Value.Length <= 3)
|
||||
{
|
||||
ping = int.Parse(regex.Groups[3].Value);
|
||||
}
|
||||
|
||||
long networkId = regex.Groups[4].Value.ConvertLong();
|
||||
string name = regex.Groups[5].Value.StripColors().Trim();
|
||||
int ip = regex.Groups[7].Value.Split(':')[0].ConvertToIP();
|
||||
|
||||
Player P = new Player()
|
||||
{
|
||||
Name = cName,
|
||||
NetworkId = npID,
|
||||
ClientNumber = cID,
|
||||
IPAddress = cIP,
|
||||
Ping = Ping,
|
||||
Name = name,
|
||||
NetworkId = networkId,
|
||||
ClientNumber = clientNumber,
|
||||
IPAddress = ip,
|
||||
Ping = ping,
|
||||
Score = score,
|
||||
IsBot = cIP == 0
|
||||
IsBot = ip == 0
|
||||
};
|
||||
|
||||
StatusPlayers.Add(P);
|
||||
|
@ -178,6 +178,9 @@ namespace IW4MAdmin
|
||||
|
||||
if (player.Level != Player.Permission.Banned && currentBan.Type == Penalty.PenaltyType.Ban)
|
||||
await player.Ban($"{loc["SERVER_BAN_PREV"]} {currentBan.Offense}", autoKickClient);
|
||||
|
||||
// they didn't fully connect so empty their slot
|
||||
Players[player.ClientNumber] = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -186,7 +189,7 @@ namespace IW4MAdmin
|
||||
var e = new GameEvent(GameEvent.EventType.Connect, "", player, null, this);
|
||||
Manager.GetEventHandler().AddEvent(e);
|
||||
|
||||
// e.OnProcessed.Wait();
|
||||
e.OnProcessed.Wait();
|
||||
|
||||
if (!Manager.GetApplicationSettings().Configuration().EnableClientVPNs &&
|
||||
await VPNCheck.UsingVPN(player.IPAddressString, Manager.GetApplicationSettings().Configuration().IPHubAPIKey))
|
||||
@ -362,14 +365,15 @@ namespace IW4MAdmin
|
||||
await ProcessEvent(E);
|
||||
Manager.GetEventApi().OnServerEvent(this, E);
|
||||
|
||||
foreach (IPlugin P in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
||||
// this allows us to catch exceptions but still run it parallel
|
||||
async Task pluginHandlingAsync(Task onEvent, string pluginName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (cts.IsCancellationRequested)
|
||||
break;
|
||||
return;
|
||||
|
||||
await P.OnEventAsync(E, this);
|
||||
await onEvent;
|
||||
}
|
||||
|
||||
// this happens if a plugin (login) wants to stop commands from executing
|
||||
@ -381,7 +385,7 @@ namespace IW4MAdmin
|
||||
|
||||
catch (Exception Except)
|
||||
{
|
||||
Logger.WriteError(String.Format("The plugin \"{0}\" generated an error. ( see log )", P.Name));
|
||||
Logger.WriteError($"{loc["SERVER_PLUGIN_ERROR"]} [{pluginName}]");
|
||||
Logger.WriteDebug(String.Format("Error Message: {0}", Except.Message));
|
||||
Logger.WriteDebug(String.Format("Error Trace: {0}", Except.StackTrace));
|
||||
while (Except.InnerException != null)
|
||||
@ -389,11 +393,15 @@ namespace IW4MAdmin
|
||||
Except = Except.InnerException;
|
||||
Logger.WriteDebug($"Inner exception: {Except.Message}");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var pluginTasks = SharedLibraryCore.Plugins.PluginImporter.ActivePlugins.
|
||||
Select(p => pluginHandlingAsync(p.OnEventAsync(E, this), p.Name));
|
||||
|
||||
// execute all the plugin updates simultaneously
|
||||
await Task.WhenAll(pluginTasks);
|
||||
|
||||
// hack: this prevents commands from getting executing that 'shouldn't' be
|
||||
if (E.Type == GameEvent.EventType.Command &&
|
||||
E.Extra != null &&
|
||||
@ -402,7 +410,6 @@ namespace IW4MAdmin
|
||||
{
|
||||
await (((Command)E.Extra).ExecuteAsync(E));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -599,27 +606,35 @@ namespace IW4MAdmin
|
||||
|
||||
override public async Task<bool> ProcessUpdatesAsync(CancellationToken cts)
|
||||
{
|
||||
// this isn't really used anymore
|
||||
this.cts = cts;
|
||||
|
||||
try
|
||||
{
|
||||
if (Manager.ShutdownRequested())
|
||||
{
|
||||
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
||||
await plugin.OnUnloadAsync();
|
||||
|
||||
for (int i = 0; i < Players.Count; i++)
|
||||
await RemovePlayer(i);
|
||||
}
|
||||
|
||||
// only check every 2 minutes if the server doesn't seem to be responding
|
||||
if ((DateTime.Now - LastPoll).TotalMinutes < 2 && ConnectionErrors >= 1)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
// trying to reduce the polling rate as every 450ms is unnecessary
|
||||
if ((DateTime.Now - LastPoll).TotalSeconds >= 10)
|
||||
{
|
||||
int polledPlayerCount = await PollPlayersAsync();
|
||||
int polledPlayerCount = await PollPlayersAsync();
|
||||
|
||||
if (ConnectionErrors > 0)
|
||||
{
|
||||
Logger.WriteVerbose($"{loc["MANAGER_CONNECTION_REST"]} {IP}:{Port}");
|
||||
Throttled = false;
|
||||
}
|
||||
ConnectionErrors = 0;
|
||||
LastPoll = DateTime.Now;
|
||||
if (ConnectionErrors > 0)
|
||||
{
|
||||
Logger.WriteVerbose($"{loc["MANAGER_CONNECTION_REST"]} {IP}:{Port}");
|
||||
Throttled = false;
|
||||
}
|
||||
ConnectionErrors = 0;
|
||||
LastPoll = DateTime.Now;
|
||||
}
|
||||
|
||||
catch (NetworkException e)
|
||||
@ -637,6 +652,8 @@ namespace IW4MAdmin
|
||||
LastMessage = DateTime.Now - start;
|
||||
lastCount = DateTime.Now;
|
||||
|
||||
// todo: re-enable on tick
|
||||
/*
|
||||
if ((DateTime.Now - tickTime).TotalMilliseconds >= 1000)
|
||||
{
|
||||
foreach (var Plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
||||
@ -647,8 +664,9 @@ namespace IW4MAdmin
|
||||
await Plugin.OnTickAsync(this);
|
||||
}
|
||||
tickTime = DateTime.Now;
|
||||
}
|
||||
}*/
|
||||
|
||||
// update the player history
|
||||
if ((lastCount - playerCountStart).TotalMinutes >= SharedLibraryCore.Helpers.PlayerHistory.UpdateInterval)
|
||||
{
|
||||
while (PlayerHistory.Count > ((60 / SharedLibraryCore.Helpers.PlayerHistory.UpdateInterval) * 12)) // 12 times a hour for 12 hours
|
||||
@ -657,6 +675,7 @@ namespace IW4MAdmin
|
||||
playerCountStart = DateTime.Now;
|
||||
}
|
||||
|
||||
// send out broadcast messages
|
||||
if (LastMessage.TotalSeconds > Manager.GetApplicationSettings().Configuration().AutoMessagePeriod
|
||||
&& BroadcastMessages.Count > 0
|
||||
&& ClientNum > 0)
|
||||
@ -666,14 +685,6 @@ namespace IW4MAdmin
|
||||
start = DateTime.Now;
|
||||
}
|
||||
|
||||
if (Manager.ShutdownRequested())
|
||||
{
|
||||
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
|
||||
await plugin.OnUnloadAsync();
|
||||
|
||||
for (int i = 0; i < Players.Count; i++)
|
||||
await RemovePlayer(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,16 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
||||
S.Logger.WriteWarning("Could not add client to profanity tracking");
|
||||
}
|
||||
|
||||
var objectionalWords = Settings.Configuration().OffensiveWords;
|
||||
bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Origin.Name.ToLower().Contains(w)) != null;
|
||||
|
||||
if (containsObjectionalWord)
|
||||
{
|
||||
await E.Origin.Kick(Settings.Configuration().ProfanityKickMessage, new Player()
|
||||
{
|
||||
ClientId = 1
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (E.Type == GameEvent.EventType.Disconnect)
|
||||
|
@ -467,6 +467,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
|
||||
// calculate the new weight against average times the weight against play time
|
||||
clientStats.SPM = (killSPM * SPMAgainstPlayWeight) + (clientStats.SPM * (1 - SPMAgainstPlayWeight));
|
||||
|
||||
if (clientStats.SPM < 0)
|
||||
{
|
||||
Log.WriteWarning("[StatManager:UpdateStats] clientStats SPM < 0");
|
||||
Log.WriteDebug($"{scoreDifference}-{clientStats.RoundScore} - {clientStats.LastScore} - {clientStats.SessionScore}");
|
||||
clientStats.SPM = 0;
|
||||
}
|
||||
|
||||
clientStats.SPM = Math.Round(clientStats.SPM, 3);
|
||||
clientStats.Skill = Math.Round((clientStats.SPM * KDRWeight), 3);
|
||||
|
||||
|
@ -37,6 +37,7 @@ namespace WebfrontCore.Controllers
|
||||
CurrentServer = server,
|
||||
Name = Client.Name
|
||||
};
|
||||
|
||||
var remoteEvent = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Say,
|
||||
|
Loading…
Reference in New Issue
Block a user