abstracting rcon parsing and event parsing
changed Event to GameEvent finally fixed the stats NaN check ip for bans consolidated console, profile, and logout into dropdown make sure game is iw4 before using :^ in say fix pm not showing from name if in web console show time left of temban on profile
This commit is contained in:
parent
827e69f70a
commit
4caa4655e2
@ -28,9 +28,9 @@ namespace IW4MAdmin.Application.API
|
|||||||
|
|
||||||
public Queue<EventInfo> GetEvents() => Events;
|
public Queue<EventInfo> GetEvents() => Events;
|
||||||
|
|
||||||
public void OnServerEvent(object sender, Event E)
|
public void OnServerEvent(object sender, GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Type == Event.GType.Say && E.Origin.Level < Player.Permission.Trusted)
|
if (E.Type == GameEvent.EventType.Say && E.Origin.Level < Player.Permission.Trusted)
|
||||||
{
|
{
|
||||||
bool flaggedMessage = false;
|
bool flaggedMessage = false;
|
||||||
foreach (string msg in FlaggedMessageContains)
|
foreach (string msg in FlaggedMessageContains)
|
||||||
@ -62,7 +62,7 @@ namespace IW4MAdmin.Application.API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.Report)
|
if (E.Type == GameEvent.EventType.Report)
|
||||||
{
|
{
|
||||||
Events.Enqueue(new EventInfo(
|
Events.Enqueue(new EventInfo(
|
||||||
EventInfo.EventType.ALERT,
|
EventInfo.EventType.ALERT,
|
||||||
|
108
Application/EventParsers/IW4EventParser.cs
Normal file
108
Application/EventParsers/IW4EventParser.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SharedLibraryCore;
|
||||||
|
using SharedLibraryCore.Interfaces;
|
||||||
|
using SharedLibraryCore.Objects;
|
||||||
|
|
||||||
|
namespace Application.EventParsers
|
||||||
|
{
|
||||||
|
class IW4EventParser : IEventParser
|
||||||
|
{
|
||||||
|
public GameEvent GetEvent(Server server, string logLine)
|
||||||
|
{
|
||||||
|
string[] lineSplit = logLine.Split(';');
|
||||||
|
string cleanedEventLine = Regex.Replace(lineSplit[0], @"[0-9]+:[0-9]+\ ", "");
|
||||||
|
|
||||||
|
if (cleanedEventLine[0] == 'K')
|
||||||
|
{
|
||||||
|
if (!server.CustomCallback)
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Script,
|
||||||
|
Data = logLine,
|
||||||
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
|
||||||
|
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineSplit[0].Substring(lineSplit[0].Length - 3).Trim() == "say")
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Say,
|
||||||
|
Data = lineSplit[4].Replace("\x15", ""),
|
||||||
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
|
Owner = server,
|
||||||
|
Message = lineSplit[4]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanedEventLine.Contains("ScriptKill"))
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Script,
|
||||||
|
Data = logLine,
|
||||||
|
Origin = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong()),
|
||||||
|
Target = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[2].ConvertLong()),
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanedEventLine.Contains("ExitLevel"))
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.MapEnd,
|
||||||
|
Data = lineSplit[0],
|
||||||
|
Origin = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Target = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanedEventLine.Contains("InitGame"))
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.MapChange,
|
||||||
|
Data = lineSplit[0],
|
||||||
|
Origin = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Target = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Unknown,
|
||||||
|
Origin = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Target = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
Application/EventParsers/T6MEventParser.cs
Normal file
92
Application/EventParsers/T6MEventParser.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SharedLibraryCore;
|
||||||
|
using SharedLibraryCore.Interfaces;
|
||||||
|
using SharedLibraryCore.Objects;
|
||||||
|
|
||||||
|
namespace Application.EventParsers
|
||||||
|
{
|
||||||
|
class T6MEventParser : IEventParser
|
||||||
|
{
|
||||||
|
public GameEvent GetEvent(Server server, string logLine)
|
||||||
|
{
|
||||||
|
string[] lineSplit = logLine.Split(';');
|
||||||
|
string cleanedEventName = Regex.Replace(lineSplit[0], @" +[0-9]+:[0-9]+ +", "");
|
||||||
|
|
||||||
|
if (cleanedEventName[0] == 'K')
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Script,
|
||||||
|
Data = logLine,
|
||||||
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
|
||||||
|
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanedEventName == "say")
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Say,
|
||||||
|
Data = lineSplit[4],
|
||||||
|
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
|
||||||
|
Owner = server,
|
||||||
|
Message = lineSplit[4]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanedEventName.Contains("ShutdownGame"))
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.MapEnd,
|
||||||
|
Data = lineSplit[0],
|
||||||
|
Origin = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Target = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanedEventName.Contains("InitGame"))
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.MapChange,
|
||||||
|
Data = lineSplit[0],
|
||||||
|
Origin = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Target = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Unknown,
|
||||||
|
Origin = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Target = new Player()
|
||||||
|
{
|
||||||
|
ClientId = 1
|
||||||
|
},
|
||||||
|
Owner = server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@ namespace IW4MAdmin.Application
|
|||||||
ServerManager = ApplicationManager.GetInstance();
|
ServerManager = ApplicationManager.GetInstance();
|
||||||
ServerManager.Init().Wait();
|
ServerManager.Init().Wait();
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run((Action)(() =>
|
||||||
{
|
{
|
||||||
String userInput;
|
String userInput;
|
||||||
Player Origin = ServerManager.GetClientService().Get(1).Result.AsPlayer();
|
Player Origin = ServerManager.GetClientService().Get(1).Result.AsPlayer();
|
||||||
@ -54,12 +54,12 @@ namespace IW4MAdmin.Application
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Origin.CurrentServer = ServerManager.Servers[0];
|
Origin.CurrentServer = ServerManager.Servers[0];
|
||||||
Event E = new Event(Event.GType.Say, userInput, Origin, null, ServerManager.Servers[0]);
|
GameEvent E = new GameEvent((GameEvent.EventType)GameEvent.EventType.Say, userInput, Origin, null, ServerManager.Servers[0]);
|
||||||
ServerManager.Servers[0].ExecuteEvent(E);
|
ServerManager.Servers[0].ExecuteEvent(E);
|
||||||
Console.Write('>');
|
Console.Write('>');
|
||||||
|
|
||||||
} while (ServerManager.Running);
|
} while (ServerManager.Running);
|
||||||
});
|
}));
|
||||||
|
|
||||||
Task.Run(() => WebfrontCore.Program.Init(ServerManager));
|
Task.Run(() => WebfrontCore.Program.Init(ServerManager));
|
||||||
ServerManager.Start();
|
ServerManager.Start();
|
||||||
|
@ -28,7 +28,7 @@ namespace IW4MAdmin.Application
|
|||||||
public Dictionary<int, Player> PrivilegedClients { get; set; }
|
public Dictionary<int, Player> PrivilegedClients { get; set; }
|
||||||
public ILogger Logger { get; private set; }
|
public ILogger Logger { get; private set; }
|
||||||
public bool Running { get; private set; }
|
public bool Running { get; private set; }
|
||||||
public EventHandler<Event> ServerEventOccurred { get; private set; }
|
public EventHandler<GameEvent> ServerEventOccurred { get; private set; }
|
||||||
|
|
||||||
static ApplicationManager Instance;
|
static ApplicationManager Instance;
|
||||||
List<AsyncStatus> TaskStatuses;
|
List<AsyncStatus> TaskStatuses;
|
||||||
|
@ -12,8 +12,17 @@ using SharedLibraryCore.Exceptions;
|
|||||||
|
|
||||||
namespace Application.RconParsers
|
namespace Application.RconParsers
|
||||||
{
|
{
|
||||||
class IW4Parser : IRConParser
|
class IW4RConParser : IRConParser
|
||||||
{
|
{
|
||||||
|
private static CommandPrefix Prefixes = new CommandPrefix()
|
||||||
|
{
|
||||||
|
Tell = "tellraw {0} {1}",
|
||||||
|
Say = "sayraw {0}",
|
||||||
|
Kick = "clientkick {0} \"{1}\"",
|
||||||
|
Ban = "clientkick {0} \"{1}\"",
|
||||||
|
TempBan = "tempbanclient {0} \"{1}\""
|
||||||
|
};
|
||||||
|
|
||||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||||
{
|
{
|
||||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command)).Skip(1).ToArray();
|
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command)).Skip(1).ToArray();
|
||||||
@ -60,6 +69,8 @@ namespace Application.RconParsers
|
|||||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandPrefix GetCommandPrefixes() => Prefixes;
|
||||||
|
|
||||||
private List<Player> ClientsFromStatus(string[] Status)
|
private List<Player> ClientsFromStatus(string[] Status)
|
||||||
{
|
{
|
||||||
List<Player> StatusPlayers = new List<Player>();
|
List<Player> StatusPlayers = new List<Player>();
|
||||||
@ -68,7 +79,7 @@ namespace Application.RconParsers
|
|||||||
{
|
{
|
||||||
String responseLine = S.Trim();
|
String responseLine = S.Trim();
|
||||||
|
|
||||||
if (Regex.Matches(responseLine, @"\d+$", RegexOptions.IgnoreCase).Count > 0 && responseLine.Length > 72) // its a client line!
|
if (Regex.Matches(responseLine, @"^\d+", RegexOptions.IgnoreCase).Count > 0)
|
||||||
{
|
{
|
||||||
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
int cID = -1;
|
int cID = -1;
|
@ -12,8 +12,19 @@ using System.Text;
|
|||||||
|
|
||||||
namespace Application.RconParsers
|
namespace Application.RconParsers
|
||||||
{
|
{
|
||||||
public class T6MParser : IRConParser
|
public class T6MRConParser : IRConParser
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||||
{
|
{
|
||||||
await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command, false);
|
await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command, false);
|
||||||
@ -69,19 +80,20 @@ namespace Application.RconParsers
|
|||||||
|
|
||||||
foreach (string statusLine in status)
|
foreach (string statusLine in status)
|
||||||
{
|
{
|
||||||
String responseLine = statusLine.Trim();
|
String responseLine = statusLine;
|
||||||
|
|
||||||
if (Regex.Matches(responseLine, @"\d+$", RegexOptions.IgnoreCase).Count > 0 && responseLine.Length > 72) // its a client line!
|
if (Regex.Matches(responseLine, @"^\d+", RegexOptions.IgnoreCase).Count > 0) // its a client line!
|
||||||
{
|
{
|
||||||
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
int clientId = -1;
|
int clientId = -1;
|
||||||
int Ping = -1;
|
int Ping = -1;
|
||||||
|
|
||||||
Int32.TryParse(playerInfo[3], out Ping);
|
Int32.TryParse(playerInfo[3], out Ping);
|
||||||
string name = Encoding.UTF8.GetString(Encoding.Convert(Encoding.UTF7, Encoding.UTF8, Encoding.UTF7.GetBytes(responseLine.Substring(50, 15).StripColors().Trim())));
|
var regex = Regex.Match(responseLine, @"\^7.*\ +0 ");
|
||||||
|
string name = Encoding.UTF8.GetString(Encoding.Convert(Encoding.UTF7, Encoding.UTF8, Encoding.UTF7.GetBytes(regex.Value.Substring(0, regex.Value.Length - 2).StripColors().Trim())));
|
||||||
long networkId = playerInfo[4].ConvertLong();
|
long networkId = playerInfo[4].ConvertLong();
|
||||||
int.TryParse(playerInfo[0], out clientId);
|
int.TryParse(playerInfo[0], out clientId);
|
||||||
var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Ping = 1;
|
Ping = 1;
|
||||||
#endif
|
#endif
|
@ -15,6 +15,7 @@ using SharedLibraryCore.Configuration;
|
|||||||
|
|
||||||
using IW4MAdmin.Application.Misc;
|
using IW4MAdmin.Application.Misc;
|
||||||
using Application.RconParsers;
|
using Application.RconParsers;
|
||||||
|
using Application.EventParsers;
|
||||||
|
|
||||||
namespace IW4MAdmin
|
namespace IW4MAdmin
|
||||||
{
|
{
|
||||||
@ -59,19 +60,20 @@ namespace IW4MAdmin
|
|||||||
Players[polledPlayer.ClientNumber].Score = polledPlayer.Score;
|
Players[polledPlayer.ClientNumber].Score = polledPlayer.Score;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (polledPlayer.Name.Length < 3)
|
if (polledPlayer.Name.Length < 3)
|
||||||
{
|
{
|
||||||
Logger.WriteDebug($"Kicking {polledPlayer} because their name is too short");
|
Logger.WriteDebug($"Kicking {polledPlayer} because their name is too short");
|
||||||
await this.ExecuteCommandAsync($"clientkick {polledPlayer.ClientNumber} \"Your name must contain atleast 3 characters.\"");
|
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, "Your name must contain atleast 3 characters.");
|
||||||
|
await this.ExecuteCommandAsync(formattedKick);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Players.FirstOrDefault(p => p != null && p.Name == polledPlayer.Name) != null)
|
if (Players.FirstOrDefault(p => p != null && p.Name == polledPlayer.Name) != null)
|
||||||
{
|
{
|
||||||
Logger.WriteDebug($"Kicking {polledPlayer} because their name is already in use");
|
Logger.WriteDebug($"Kicking {polledPlayer} because their name is already in use");
|
||||||
await this.ExecuteCommandAsync($"clientkick {polledPlayer.ClientNumber} \"Your name is being used by someone else.\"");
|
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, "Your name is being used by someone else.");
|
||||||
|
await this.ExecuteCommandAsync(formattedKick);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,14 +82,16 @@ namespace IW4MAdmin
|
|||||||
polledPlayer.Name == "CHEATER")
|
polledPlayer.Name == "CHEATER")
|
||||||
{
|
{
|
||||||
Logger.WriteDebug($"Kicking {polledPlayer} because their name is generic");
|
Logger.WriteDebug($"Kicking {polledPlayer} because their name is generic");
|
||||||
await this.ExecuteCommandAsync($"clientkick {polledPlayer.ClientNumber} \"Please change your name using /name.\"");
|
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, "Please change your name using /name.");
|
||||||
|
await this.ExecuteCommandAsync(formattedKick);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (polledPlayer.Name.Where(c => Char.IsControl(c)).Count() > 0)
|
if (polledPlayer.Name.Where(c => Char.IsControl(c)).Count() > 0)
|
||||||
{
|
{
|
||||||
Logger.WriteDebug($"Kicking {polledPlayer} because their contains control characters");
|
Logger.WriteDebug($"Kicking {polledPlayer} because their contains control characters");
|
||||||
await this.ExecuteCommandAsync($"clientkick {polledPlayer.ClientNumber} \"Your name cannot contain control characters.\"");
|
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, "Your name cannot contain control characters.");
|
||||||
|
await this.ExecuteCommandAsync(formattedKick);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +149,7 @@ namespace IW4MAdmin
|
|||||||
player.CurrentServer = this;
|
player.CurrentServer = this;
|
||||||
Players[player.ClientNumber] = player;
|
Players[player.ClientNumber] = player;
|
||||||
|
|
||||||
var activePenalties = await Manager.GetPenaltyService().GetActivePenaltiesAsync(player.AliasLinkId);
|
var activePenalties = await Manager.GetPenaltyService().GetActivePenaltiesAsync(player.AliasLinkId, player.IPAddress);
|
||||||
var currentBan = activePenalties.FirstOrDefault(b => b.Expires > DateTime.UtcNow);
|
var currentBan = activePenalties.FirstOrDefault(b => b.Expires > DateTime.UtcNow);
|
||||||
|
|
||||||
if (currentBan != null)
|
if (currentBan != null)
|
||||||
@ -155,7 +159,10 @@ namespace IW4MAdmin
|
|||||||
autoKickClient.CurrentServer = this;
|
autoKickClient.CurrentServer = this;
|
||||||
|
|
||||||
if (currentBan.Type == Penalty.PenaltyType.TempBan)
|
if (currentBan.Type == Penalty.PenaltyType.TempBan)
|
||||||
await this.ExecuteCommandAsync($"clientkick {player.ClientNumber} \"You are temporarily banned. ({(currentBan.Expires - DateTime.UtcNow).TimeSpanText()} left)\"");
|
{
|
||||||
|
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, $"You are temporarily banned. ({(currentBan.Expires - DateTime.UtcNow).TimeSpanText()} left)");
|
||||||
|
await this.ExecuteCommandAsync(formattedKick);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
await player.Kick($"Previously banned for {currentBan.Offense}", autoKickClient);
|
await player.Kick($"Previously banned for {currentBan.Offense}", autoKickClient);
|
||||||
|
|
||||||
@ -166,7 +173,7 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
Logger.WriteInfo($"Client {player} connecting...");
|
Logger.WriteInfo($"Client {player} connecting...");
|
||||||
|
|
||||||
await ExecuteEvent(new Event(Event.GType.Connect, "", player, null, this));
|
await ExecuteEvent(new GameEvent(GameEvent.EventType.Connect, "", player, null, this));
|
||||||
|
|
||||||
|
|
||||||
if (!Manager.GetApplicationSettings().Configuration().EnableClientVPNs &&
|
if (!Manager.GetApplicationSettings().Configuration().EnableClientVPNs &&
|
||||||
@ -194,7 +201,7 @@ namespace IW4MAdmin
|
|||||||
Player Leaving = Players[cNum];
|
Player Leaving = Players[cNum];
|
||||||
Logger.WriteInfo($"Client {Leaving} disconnecting...");
|
Logger.WriteInfo($"Client {Leaving} disconnecting...");
|
||||||
|
|
||||||
await ExecuteEvent(new Event(Event.GType.Disconnect, "", Leaving, null, this));
|
await ExecuteEvent(new GameEvent(GameEvent.EventType.Disconnect, "", Leaving, null, this));
|
||||||
|
|
||||||
Leaving.TotalConnectionTime += (int)(DateTime.UtcNow - Leaving.ConnectionTime).TotalSeconds;
|
Leaving.TotalConnectionTime += (int)(DateTime.UtcNow - Leaving.ConnectionTime).TotalSeconds;
|
||||||
Leaving.LastConnection = DateTime.UtcNow;
|
Leaving.LastConnection = DateTime.UtcNow;
|
||||||
@ -203,34 +210,9 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Another version of client from line, written for the line created by a kill or death event
|
|
||||||
override public Player ParseClientFromString(String[] L, int cIDPos)
|
|
||||||
{
|
|
||||||
if (L.Length < cIDPos)
|
|
||||||
{
|
|
||||||
Logger.WriteError("Line sent for client creation is not long enough!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pID = -2; // apparently falling = -1 cID so i can't use it now
|
|
||||||
int.TryParse(L[cIDPos].Trim(), out pID);
|
|
||||||
|
|
||||||
if (pID == -1) // special case similar to mod_suicide
|
|
||||||
int.TryParse(L[2], out pID);
|
|
||||||
|
|
||||||
if (pID < 0 || pID > 17)
|
|
||||||
{
|
|
||||||
Logger.WriteError("Event player index " + pID + " is out of bounds!");
|
|
||||||
Logger.WriteDebug("Offending line -- " + String.Join(";", L));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Players[pID];
|
|
||||||
}
|
|
||||||
|
|
||||||
//Process requested command correlating to an event
|
//Process requested command correlating to an event
|
||||||
// todo: this needs to be removed out of here
|
// todo: this needs to be removed out of here
|
||||||
override public async Task<Command> ValidateCommand(Event E)
|
override public async Task<Command> ValidateCommand(GameEvent E)
|
||||||
{
|
{
|
||||||
string CommandString = E.Data.Substring(1, E.Data.Length - 1).Split(' ')[0];
|
string CommandString = E.Data.Substring(1, E.Data.Length - 1).Split(' ')[0];
|
||||||
E.Message = E.Data;
|
E.Message = E.Data;
|
||||||
@ -368,7 +350,7 @@ namespace IW4MAdmin
|
|||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task ExecuteEvent(Event E)
|
public override async Task ExecuteEvent(GameEvent E)
|
||||||
{
|
{
|
||||||
if (Throttled)
|
if (Throttled)
|
||||||
return;
|
return;
|
||||||
@ -457,7 +439,7 @@ namespace IW4MAdmin
|
|||||||
// first start
|
// first start
|
||||||
if (firstRun)
|
if (firstRun)
|
||||||
{
|
{
|
||||||
await ExecuteEvent(new Event(Event.GType.Start, "Server started", null, null, this));
|
await ExecuteEvent(new GameEvent(GameEvent.EventType.Start, "Server started", null, null, this));
|
||||||
firstRun = false;
|
firstRun = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,8 +528,7 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string[] game_event = lines[count].Split(';');
|
GameEvent event_ = EventParser.GetEvent(this, lines[count]);
|
||||||
Event event_ = Event.ParseEventString(game_event, this);
|
|
||||||
if (event_ != null)
|
if (event_ != null)
|
||||||
{
|
{
|
||||||
if (event_.Origin == null)
|
if (event_.Origin == null)
|
||||||
@ -590,7 +571,8 @@ namespace IW4MAdmin
|
|||||||
|
|
||||||
public async Task Initialize()
|
public async Task Initialize()
|
||||||
{
|
{
|
||||||
RconParser = ServerConfig.UseT6MParser ? (IRConParser)new T6MParser() : new IW4Parser();
|
RconParser = ServerConfig.UseT6MParser ? (IRConParser)new T6MRConParser() : new IW4RConParser();
|
||||||
|
EventParser = ServerConfig.UseT6MParser ? (IEventParser)new T6MEventParser() : new IW4EventParser();
|
||||||
|
|
||||||
var version = await this.GetDvarAsync<string>("version");
|
var version = await this.GetDvarAsync<string>("version");
|
||||||
GameName = Utilities.GetGame(version.Value);
|
GameName = Utilities.GetGame(version.Value);
|
||||||
@ -666,7 +648,9 @@ namespace IW4MAdmin
|
|||||||
mainPath = (GameName == Game.T5M) ? "rzodemo" : mainPath;
|
mainPath = (GameName == Game.T5M) ? "rzodemo" : mainPath;
|
||||||
// patch for T6M:PLUTONIUM
|
// patch for T6M:PLUTONIUM
|
||||||
mainPath = (GameName == Game.T6M) ? $"t6r{Path.DirectorySeparatorChar}data" : mainPath;
|
mainPath = (GameName == Game.T6M) ? $"t6r{Path.DirectorySeparatorChar}data" : mainPath;
|
||||||
|
#if DEBUG
|
||||||
|
basepath.Value = @"\\192.168.88.253\Call of Duty Black Ops II";
|
||||||
|
#endif
|
||||||
string logPath = (game.Value == "" || onelog?.Value == 1) ?
|
string logPath = (game.Value == "" || onelog?.Value == 1) ?
|
||||||
$"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{mainPath}{Path.DirectorySeparatorChar}{logfile.Value}" :
|
$"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{mainPath}{Path.DirectorySeparatorChar}{logfile.Value}" :
|
||||||
$"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game.Value.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile.Value}";
|
$"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{game.Value.Replace('/', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{logfile.Value}";
|
||||||
@ -692,9 +676,9 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Process any server event
|
//Process any server event
|
||||||
override protected async Task ProcessEvent(Event E)
|
override protected async Task ProcessEvent(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Type == Event.GType.Connect)
|
if (E.Type == GameEvent.EventType.Connect)
|
||||||
{
|
{
|
||||||
ChatHistory.Add(new ChatInfo()
|
ChatHistory.Add(new ChatInfo()
|
||||||
{
|
{
|
||||||
@ -707,7 +691,7 @@ namespace IW4MAdmin
|
|||||||
await E.Origin.Tell($"There are ^5{Reports.Count} ^7recent reports");
|
await E.Origin.Tell($"There are ^5{Reports.Count} ^7recent reports");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (E.Type == Event.GType.Disconnect)
|
else if (E.Type == GameEvent.EventType.Disconnect)
|
||||||
{
|
{
|
||||||
ChatHistory.Add(new ChatInfo()
|
ChatHistory.Add(new ChatInfo()
|
||||||
{
|
{
|
||||||
@ -717,12 +701,12 @@ namespace IW4MAdmin
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (E.Type == Event.GType.Script)
|
else if (E.Type == GameEvent.EventType.Script)
|
||||||
{
|
{
|
||||||
await ExecuteEvent(new Event(Event.GType.Kill, E.Data, E.Origin, E.Target, this));
|
await ExecuteEvent(new GameEvent(GameEvent.EventType.Kill, E.Data, E.Origin, E.Target, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.Say && E.Data.Length >= 2)
|
if (E.Type == GameEvent.EventType.Say && E.Data.Length >= 2)
|
||||||
{
|
{
|
||||||
if (E.Data.Substring(0, 1) == "!" || E.Data.Substring(0, 1) == "@" || E.Origin.Level == Player.Permission.Console)
|
if (E.Data.Substring(0, 1) == "!" || E.Data.Substring(0, 1) == "@" || E.Origin.Level == Player.Permission.Console)
|
||||||
{
|
{
|
||||||
@ -776,7 +760,7 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.MapChange)
|
if (E.Type == GameEvent.EventType.MapChange)
|
||||||
{
|
{
|
||||||
Logger.WriteInfo($"New map loaded - {ClientNum} active players");
|
Logger.WriteInfo($"New map loaded - {ClientNum} active players");
|
||||||
|
|
||||||
@ -788,7 +772,7 @@ namespace IW4MAdmin
|
|||||||
CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname };
|
CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map() { Alias = mapname, Name = mapname };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.MapEnd)
|
if (E.Type == GameEvent.EventType.MapEnd)
|
||||||
{
|
{
|
||||||
Logger.WriteInfo("Game ending...");
|
Logger.WriteInfo("Game ending...");
|
||||||
}
|
}
|
||||||
@ -821,7 +805,10 @@ namespace IW4MAdmin
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Target.Warnings >= 4)
|
if (Target.Warnings >= 4)
|
||||||
|
{
|
||||||
await Target.Kick("Too many warnings!", (await Manager.GetClientService().Get(1)).AsPlayer());
|
await Target.Kick("Too many warnings!", (await Manager.GetClientService().Get(1)).AsPlayer());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Target.Warnings++;
|
Target.Warnings++;
|
||||||
String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", Target.Warnings, Target.Name, Reason);
|
String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", Target.Warnings, Target.Name, Reason);
|
||||||
@ -859,7 +846,10 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
else
|
else
|
||||||
await Target.CurrentServer.ExecuteCommandAsync($"clientkick {Target.ClientNumber} \"Player Kicked: ^5{Reason}^7\"");
|
{
|
||||||
|
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, Target.ClientNumber, $"You were Kicked - ^5{Reason}^7");
|
||||||
|
await Target.CurrentServer.ExecuteCommandAsync(formattedKick);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@ -897,7 +887,10 @@ namespace IW4MAdmin
|
|||||||
}
|
}
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
else
|
else
|
||||||
await Target.CurrentServer.ExecuteCommandAsync($"clientkick {Target.ClientNumber } \"^7Player Temporarily Banned: ^5{ Reason }\"");
|
{
|
||||||
|
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, Target.ClientNumber, $"^7You're Temporarily Banned - ^5{Reason}");
|
||||||
|
await Target.CurrentServer.ExecuteCommandAsync(formattedKick);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
await Target.CurrentServer.RemovePlayer(Target.ClientNumber);
|
await Target.CurrentServer.RemovePlayer(Target.ClientNumber);
|
||||||
#endif
|
#endif
|
||||||
@ -941,7 +934,8 @@ namespace IW4MAdmin
|
|||||||
// this is set only because they're still in the server.
|
// this is set only because they're still in the server.
|
||||||
Target.Level = Player.Permission.Banned;
|
Target.Level = Player.Permission.Banned;
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
await Target.CurrentServer.ExecuteCommandAsync($"clientkick {Target.ClientNumber} \"Player Banned: ^5{Message} ^7(appeal at {Website}) ^7\"");
|
string formattedString = String.Format(RconParser.GetCommandPrefixes().Kick, Target.ClientNumber, $"You're Banned - ^5{Message} ^7(appeal at {Website})^7");
|
||||||
|
await Target.CurrentServer.ExecuteCommandAsync(formattedString);
|
||||||
#else
|
#else
|
||||||
await Target.CurrentServer.RemovePlayer(Target.ClientNumber);
|
await Target.CurrentServer.RemovePlayer(Target.ClientNumber);
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,12 +22,12 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
IManager Manager;
|
IManager Manager;
|
||||||
Task CompletedTask = Task.FromResult(false);
|
Task CompletedTask = Task.FromResult(false);
|
||||||
|
|
||||||
public async Task OnEventAsync(Event E, Server S)
|
public async Task OnEventAsync(GameEvent E, Server S)
|
||||||
{
|
{
|
||||||
if (!Settings.Configuration().EnableProfanityDeterment)
|
if (!Settings.Configuration().EnableProfanityDeterment)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (E.Type == Event.GType.Connect)
|
if (E.Type == GameEvent.EventType.Connect)
|
||||||
{
|
{
|
||||||
if (!ProfanityCounts.TryAdd(E.Origin.ClientId, new Tracking(E.Origin)))
|
if (!ProfanityCounts.TryAdd(E.Origin.ClientId, new Tracking(E.Origin)))
|
||||||
{
|
{
|
||||||
@ -36,7 +36,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.Disconnect)
|
if (E.Type == GameEvent.EventType.Disconnect)
|
||||||
{
|
{
|
||||||
if (!ProfanityCounts.TryRemove(E.Origin.ClientId, out Tracking old))
|
if (!ProfanityCounts.TryRemove(E.Origin.ClientId, out Tracking old))
|
||||||
{
|
{
|
||||||
@ -44,7 +44,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == Event.GType.Say)
|
if (E.Type == GameEvent.EventType.Say)
|
||||||
{
|
{
|
||||||
var objectionalWords = Settings.Configuration().OffensiveWords;
|
var objectionalWords = Settings.Configuration().OffensiveWords;
|
||||||
bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Data.ToLower().Contains(w)) != null;
|
bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Data.ToLower().Contains(w)) != null;
|
||||||
|
@ -68,7 +68,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
double newAverage = (previousAverage * (hitLoc.HitCount - 1) + angle) / hitLoc.HitCount;
|
double newAverage = (previousAverage * (hitLoc.HitCount - 1) + angle) / hitLoc.HitCount;
|
||||||
hitLoc.HitOffsetAverage = (float)newAverage;
|
hitLoc.HitOffsetAverage = (float)newAverage;
|
||||||
|
|
||||||
if (hitLoc.HitOffsetAverage == float.NaN)
|
if (double.IsNaN(hitLoc.HitOffsetAverage))
|
||||||
{
|
{
|
||||||
Log.WriteWarning("[Detection::ProcessKill] HitOffsetAvgerage NaN");
|
Log.WriteWarning("[Detection::ProcessKill] HitOffsetAvgerage NaN");
|
||||||
Log.WriteDebug($"{previousAverage}-{hitLoc.HitCount}-{hitLoc}-{newAverage}");
|
Log.WriteDebug($"{previousAverage}-{hitLoc.HitCount}-{hitLoc}-{newAverage}");
|
||||||
@ -269,7 +269,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
|
|
||||||
public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats)
|
public DetectionPenaltyResult ProcessTotalRatio(EFClientStatistics stats)
|
||||||
{
|
{
|
||||||
int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.left_arm_upper).HitCount;
|
int totalChestKills = stats.HitLocations.Single(c => c.Location == IW4Info.HitLocation.torso_upper).HitCount;
|
||||||
|
|
||||||
if (totalChestKills >= 60)
|
if (totalChestKills >= 60)
|
||||||
{
|
{
|
||||||
@ -279,7 +279,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
|||||||
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(2), lerpAmount) + marginOfError;
|
double chestAbdomenRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(3.0), Thresholds.ChestAbdomenRatioThresholdHighSample(2), lerpAmount) + marginOfError;
|
||||||
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(4.0), Thresholds.ChestAbdomenRatioThresholdHighSample(4.0), lerpAmount) + marginOfError;
|
double chestAbdomenLerpValueForBan = Thresholds.Lerp(Thresholds.ChestAbdomenRatioThresholdHighSample(4.0), Thresholds.ChestAbdomenRatioThresholdHighSample(4.0), lerpAmount) + marginOfError;
|
||||||
|
|
||||||
double currentChestAbdomenRatio = stats.HitLocations.Single(hl => hl.Location == IW4Info.HitLocation.torso_upper).HitCount /
|
double currentChestAbdomenRatio = totalChestKills /
|
||||||
stats.HitLocations.Single(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount;
|
stats.HitLocations.Single(hl => hl.Location == IW4Info.HitLocation.torso_lower).HitCount;
|
||||||
|
|
||||||
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
if (currentChestAbdomenRatio > chestAbdomenRatioLerpValueForFlag)
|
||||||
|
@ -13,7 +13,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
|
|||||||
{
|
{
|
||||||
public ResetStats() : base("resetstats", "reset your stats to factory-new", "rs", Player.Permission.User, false) { }
|
public ResetStats() : base("resetstats", "reset your stats to factory-new", "rs", Player.Permission.User, false) { }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Origin.ClientNumber >= 0)
|
if (E.Origin.ClientNumber >= 0)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
|
|||||||
{
|
{
|
||||||
public TopStats() : base("topstats", "view the top 5 players on this server", "ts", Player.Permission.User, false) { }
|
public TopStats() : base("topstats", "view the top 5 players on this server", "ts", Player.Permission.User, false) { }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
var statsSvc = new GenericRepository<EFClientStatistics>();
|
var statsSvc = new GenericRepository<EFClientStatistics>();
|
||||||
int serverId = E.Owner.GetHashCode();
|
int serverId = E.Owner.GetHashCode();
|
||||||
|
@ -22,7 +22,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Target?.ClientNumber < 0)
|
if (E.Target?.ClientNumber < 0)
|
||||||
{
|
{
|
||||||
|
@ -193,7 +193,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue2);
|
detectionStats.TryRemove(pl.ClientId, out Cheat.Detection removedValue2);
|
||||||
|
|
||||||
// sync their stats before they leave
|
// sync their stats before they leave
|
||||||
UpdateStats(clientStats);
|
clientStats = UpdateStats(clientStats);
|
||||||
|
|
||||||
// todo: should this be saved every disconnect?
|
// todo: should this be saved every disconnect?
|
||||||
statsSvc.ClientStatSvc.Update(clientStats);
|
statsSvc.ClientStatSvc.Update(clientStats);
|
||||||
@ -211,12 +211,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads)
|
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads)
|
||||||
{
|
{
|
||||||
var statsSvc = ContextThreads[serverId];
|
var statsSvc = ContextThreads[serverId];
|
||||||
|
|
||||||
|
|
||||||
Vector3 vDeathOrigin = null;
|
Vector3 vDeathOrigin = null;
|
||||||
Vector3 vKillOrigin = null;
|
Vector3 vKillOrigin = null;
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vDeathOrigin = Vector3.Parse(deathOrigin);
|
vDeathOrigin = Vector3.Parse(deathOrigin);
|
||||||
@ -295,7 +292,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
if (attacker.Level != Player.Permission.User)
|
if (attacker.Level != Player.Permission.User)
|
||||||
break;
|
break;
|
||||||
var flagCmd = new CFlag();
|
var flagCmd = new CFlag();
|
||||||
await flagCmd.ExecuteAsync(new Event(Event.GType.Flag, $"{(int)penalty.Bone}-{Math.Round(penalty.RatioAmount, 2).ToString()}@{penalty.KillCount}", new Player()
|
await flagCmd.ExecuteAsync(new GameEvent(GameEvent.EventType.Flag, $"{(int)penalty.Bone}-{Math.Round(penalty.RatioAmount, 2).ToString()}@{penalty.KillCount}", new Player()
|
||||||
{
|
{
|
||||||
ClientId = 1,
|
ClientId = 1,
|
||||||
Level = Player.Permission.Console,
|
Level = Player.Permission.Console,
|
||||||
@ -356,12 +353,20 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
await attacker.Tell(streakMessage);
|
await attacker.Tell(streakMessage);
|
||||||
|
|
||||||
// fixme: why?
|
// fixme: why?
|
||||||
if (victimStats.SPM == double.NaN || victimStats.Skill == double.NaN)
|
if (double.IsNaN(victimStats.SPM) || double.IsNaN(victimStats.Skill))
|
||||||
{
|
{
|
||||||
|
Log.WriteDebug($"[StatManager::AddStandardKill] victim SPM/SKILL {victimStats.SPM} {victimStats.Skill}");
|
||||||
victimStats.SPM = 0.0;
|
victimStats.SPM = 0.0;
|
||||||
victimStats.Skill = 0.0;
|
victimStats.Skill = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (double.IsNaN(attackerStats.SPM) || double.IsNaN(attackerStats.Skill))
|
||||||
|
{
|
||||||
|
Log.WriteDebug($"[StatManager::AddStandardKill] attacker SPM/SKILL {victimStats.SPM} {victimStats.Skill}");
|
||||||
|
attackerStats.SPM = 0.0;
|
||||||
|
attackerStats.Skill = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
// todo: do we want to save this immediately?
|
// todo: do we want to save this immediately?
|
||||||
var statsSvc = ContextThreads[serverId];
|
var statsSvc = ContextThreads[serverId];
|
||||||
statsSvc.ClientStatSvc.Update(attackerStats);
|
statsSvc.ClientStatSvc.Update(attackerStats);
|
||||||
@ -393,7 +398,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
victimStats.KillStreak = 0;
|
victimStats.KillStreak = 0;
|
||||||
|
|
||||||
// process the attacker's stats after the kills
|
// process the attacker's stats after the kills
|
||||||
UpdateStats(attackerStats);
|
attackerStats = UpdateStats(attackerStats);
|
||||||
|
|
||||||
// update after calculation
|
// update after calculation
|
||||||
attackerStats.TimePlayed += (int)(DateTime.UtcNow - attackerStats.LastActive).TotalSeconds;
|
attackerStats.TimePlayed += (int)(DateTime.UtcNow - attackerStats.LastActive).TotalSeconds;
|
||||||
@ -410,7 +415,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
private EFClientStatistics UpdateStats(EFClientStatistics clientStats)
|
private EFClientStatistics UpdateStats(EFClientStatistics clientStats)
|
||||||
{
|
{
|
||||||
// prevent NaN or inactive time lowering SPM
|
// prevent NaN or inactive time lowering SPM
|
||||||
if ((DateTime.UtcNow - clientStats.LastStatCalculation).TotalSeconds / 60.0 < 0.1 ||
|
if ((DateTime.UtcNow - clientStats.LastStatCalculation).TotalSeconds / 60.0 < 0.01 ||
|
||||||
(DateTime.UtcNow - clientStats.LastActive).TotalSeconds / 60.0 > 3 ||
|
(DateTime.UtcNow - clientStats.LastActive).TotalSeconds / 60.0 > 3 ||
|
||||||
clientStats.SessionScore < 1)
|
clientStats.SessionScore < 1)
|
||||||
return clientStats;
|
return clientStats;
|
||||||
@ -439,13 +444,11 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
|
|
||||||
// calculate the new weight against average times the weight against play time
|
// calculate the new weight against average times the weight against play time
|
||||||
clientStats.SPM = (killSPM * SPMAgainstPlayWeight) + (clientStats.SPM * (1 - SPMAgainstPlayWeight));
|
clientStats.SPM = (killSPM * SPMAgainstPlayWeight) + (clientStats.SPM * (1 - SPMAgainstPlayWeight));
|
||||||
|
|
||||||
clientStats.SPM = Math.Round(clientStats.SPM, 3);
|
clientStats.SPM = Math.Round(clientStats.SPM, 3);
|
||||||
|
|
||||||
clientStats.Skill = Math.Round((clientStats.SPM * KDRWeight), 3);
|
clientStats.Skill = Math.Round((clientStats.SPM * KDRWeight), 3);
|
||||||
|
|
||||||
// fixme: how does this happen?
|
// fixme: how does this happen?
|
||||||
if (clientStats.SPM == double.NaN || clientStats.Skill == double.NaN)
|
if (double.IsNaN(clientStats.SPM) || double.IsNaN(clientStats.Skill))
|
||||||
{
|
{
|
||||||
Log.WriteWarning("[StatManager::UpdateStats] clientStats SPM/Skill NaN");
|
Log.WriteWarning("[StatManager::UpdateStats] clientStats SPM/Skill NaN");
|
||||||
Log.WriteDebug($"{killSPM}-{KDRWeight}-{totalPlayTime}-{SPMAgainstPlayWeight}-{clientStats.SPM}-{clientStats.Skill}-{scoreDifference}");
|
Log.WriteDebug($"{killSPM}-{KDRWeight}-{totalPlayTime}-{SPMAgainstPlayWeight}-{clientStats.SPM}-{clientStats.Skill}-{scoreDifference}");
|
||||||
|
@ -28,50 +28,50 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
private IManager ServerManager;
|
private IManager ServerManager;
|
||||||
public static BaseConfigurationHandler<StatsConfiguration> Config { get; private set; }
|
public static BaseConfigurationHandler<StatsConfiguration> Config { get; private set; }
|
||||||
|
|
||||||
public async Task OnEventAsync(Event E, Server S)
|
public async Task OnEventAsync(GameEvent E, Server S)
|
||||||
{
|
{
|
||||||
switch (E.Type)
|
switch (E.Type)
|
||||||
{
|
{
|
||||||
case Event.GType.Start:
|
case GameEvent.EventType.Start:
|
||||||
Manager.AddServer(S);
|
Manager.AddServer(S);
|
||||||
break;
|
break;
|
||||||
case Event.GType.Stop:
|
case GameEvent.EventType.Stop:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Connect:
|
case GameEvent.EventType.Connect:
|
||||||
await Manager.AddPlayer(E.Origin);
|
await Manager.AddPlayer(E.Origin);
|
||||||
break;
|
break;
|
||||||
case Event.GType.Disconnect:
|
case GameEvent.EventType.Disconnect:
|
||||||
await Manager.RemovePlayer(E.Origin);
|
await Manager.RemovePlayer(E.Origin);
|
||||||
break;
|
break;
|
||||||
case Event.GType.Say:
|
case GameEvent.EventType.Say:
|
||||||
if (E.Data != string.Empty && E.Data.Trim().Length > 0 && E.Message.Trim()[0] != '!' && E.Origin.ClientId > 1)
|
if (E.Data != string.Empty && E.Data.Trim().Length > 0 && E.Message.Trim()[0] != '!' && E.Origin.ClientId > 1)
|
||||||
await Manager.AddMessageAsync(E.Origin.ClientId, E.Owner.GetHashCode(), E.Data);
|
await Manager.AddMessageAsync(E.Origin.ClientId, E.Owner.GetHashCode(), E.Data);
|
||||||
break;
|
break;
|
||||||
case Event.GType.MapChange:
|
case GameEvent.EventType.MapChange:
|
||||||
Manager.ResetKillstreaks(S.GetHashCode());
|
Manager.ResetKillstreaks(S.GetHashCode());
|
||||||
await Manager.Sync(S);
|
await Manager.Sync(S);
|
||||||
break;
|
break;
|
||||||
case Event.GType.MapEnd:
|
case GameEvent.EventType.MapEnd:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Broadcast:
|
case GameEvent.EventType.Broadcast:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Tell:
|
case GameEvent.EventType.Tell:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Kick:
|
case GameEvent.EventType.Kick:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Ban:
|
case GameEvent.EventType.Ban:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Remote:
|
case GameEvent.EventType.Remote:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Unknown:
|
case GameEvent.EventType.Unknown:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Report:
|
case GameEvent.EventType.Report:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Flag:
|
case GameEvent.EventType.Flag:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Script:
|
case GameEvent.EventType.Script:
|
||||||
break;
|
break;
|
||||||
case Event.GType.Kill:
|
case GameEvent.EventType.Kill:
|
||||||
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
||||||
if (killInfo.Length >= 9 && killInfo[0].Contains("ScriptKill") && E.Owner.CustomCallback)
|
if (killInfo.Length >= 9 && killInfo[0].Contains("ScriptKill") && E.Owner.CustomCallback)
|
||||||
await Manager.AddScriptKill(E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
await Manager.AddScriptKill(E.Origin, E.Target, S.GetHashCode(), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
||||||
@ -79,7 +79,7 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
else if (!E.Owner.CustomCallback)
|
else if (!E.Owner.CustomCallback)
|
||||||
await Manager.AddStandardKill(E.Origin, E.Target);
|
await Manager.AddStandardKill(E.Origin, E.Target);
|
||||||
break;
|
break;
|
||||||
case Event.GType.Death:
|
case GameEvent.EventType.Death:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@ using SharedLibraryCore;
|
|||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
using SharedLibraryCore.Objects;
|
using SharedLibraryCore.Objects;
|
||||||
using SharedLibraryCore.Configuration;
|
using SharedLibraryCore.Configuration;
|
||||||
|
using SharedLibraryCore.Services;
|
||||||
|
using SharedLibraryCore.Database.Models;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace IW4MAdmin.Plugins.Welcome
|
namespace IW4MAdmin.Plugins.Welcome
|
||||||
{
|
{
|
||||||
@ -73,9 +76,9 @@ namespace IW4MAdmin.Plugins.Welcome
|
|||||||
|
|
||||||
public Task OnTickAsync(Server S) => Utilities.CompletedTask;
|
public Task OnTickAsync(Server S) => Utilities.CompletedTask;
|
||||||
|
|
||||||
public async Task OnEventAsync(Event E, Server S)
|
public async Task OnEventAsync(GameEvent E, Server S)
|
||||||
{
|
{
|
||||||
if (E.Type == Event.GType.Connect)
|
if (E.Type == GameEvent.EventType.Connect)
|
||||||
{
|
{
|
||||||
Player newPlayer = E.Origin;
|
Player newPlayer = E.Origin;
|
||||||
if (newPlayer.Level >= Player.Permission.Trusted && !E.Origin.Masked)
|
if (newPlayer.Level >= Player.Permission.Trusted && !E.Origin.Masked)
|
||||||
@ -84,7 +87,10 @@ namespace IW4MAdmin.Plugins.Welcome
|
|||||||
await newPlayer.Tell(ProcessAnnouncement(Config.Configuration().UserWelcomeMessage, newPlayer));
|
await newPlayer.Tell(ProcessAnnouncement(Config.Configuration().UserWelcomeMessage, newPlayer));
|
||||||
|
|
||||||
if (newPlayer.Level == Player.Permission.Flagged)
|
if (newPlayer.Level == Player.Permission.Flagged)
|
||||||
await E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name} ^7has joined!");
|
{
|
||||||
|
var penalty = await new GenericRepository<EFPenalty>().FindAsync(p => p.OffenderId == newPlayer.ClientId && p.Type == Penalty.PenaltyType.Flag);
|
||||||
|
await E.Owner.ToAdmins($"^1NOTICE: ^7Flagged player ^5{newPlayer.Name} ^7({penalty.FirstOrDefault()?.Offense}) has joined!");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
await E.Owner.Broadcast(ProcessAnnouncement(Config.Configuration().UserAnnouncementMessage, newPlayer));
|
await E.Owner.Broadcast(ProcessAnnouncement(Config.Configuration().UserAnnouncementMessage, newPlayer));
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace SharedLibraryCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Execute the command
|
//Execute the command
|
||||||
abstract public Task ExecuteAsync(Event E);
|
abstract public Task ExecuteAsync(GameEvent E);
|
||||||
|
|
||||||
public String Name { get; private set; }
|
public String Name { get; private set; }
|
||||||
public String Description { get; private set; }
|
public String Description { get; private set; }
|
||||||
|
@ -18,7 +18,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("quit", "quit IW4MAdmin", "q", Player.Permission.Owner, false)
|
base("quit", "quit IW4MAdmin", "q", Player.Permission.Owner, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override Task ExecuteAsync(Event E)
|
public override Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
return Task.Run(() => { E.Owner.Manager.Stop(); });
|
return Task.Run(() => { E.Owner.Manager.Stop(); });
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("owner", "claim ownership of the server", "o", Player.Permission.User, false)
|
base("owner", "claim ownership of the server", "o", Player.Permission.User, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if ((await (E.Owner.Manager.GetClientService() as Services.ClientService).GetOwners()).Count == 0)
|
if ((await (E.Owner.Manager.GetClientService() as Services.ClientService).GetOwners()).Count == 0)
|
||||||
{
|
{
|
||||||
@ -61,7 +61,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Origin.Level <= E.Target.Level)
|
if (E.Origin.Level <= E.Target.Level)
|
||||||
await E.Origin.Tell($"You do not have the required privileges to warn {E.Target.Name}");
|
await E.Origin.Tell($"You do not have the required privileges to warn {E.Target.Name}");
|
||||||
@ -83,7 +83,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
E.Target.Warnings = 0;
|
E.Target.Warnings = 0;
|
||||||
String Message = String.Format("All warning cleared for {0}", E.Target.Name);
|
String Message = String.Format("All warning cleared for {0}", E.Target.Name);
|
||||||
@ -109,11 +109,11 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Origin.Level > E.Target.Level)
|
if (E.Origin.Level > E.Target.Level)
|
||||||
{
|
{
|
||||||
await E.Owner.ExecuteEvent(new Event(Event.GType.Kick, E.Data, E.Origin, E.Target, E.Owner));
|
await E.Owner.ExecuteEvent(new GameEvent(GameEvent.EventType.Kick, E.Data, E.Origin, E.Target, E.Owner));
|
||||||
await E.Target.Kick(E.Data, E.Origin);
|
await E.Target.Kick(E.Data, E.Origin);
|
||||||
await E.Origin.Tell($"^5{E.Target} ^7has been kicked");
|
await E.Origin.Tell($"^5{E.Target} ^7has been kicked");
|
||||||
}
|
}
|
||||||
@ -135,9 +135,9 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
await E.Owner.Broadcast($"^:{E.Origin.Name} - ^6{E.Data}^7");
|
await E.Owner.Broadcast($"{(E.Owner.GameName == Server.Game.IW4 ? "^:" : "")}{E.Origin.Name} - ^6{E.Data}^7");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
String Message = Utilities.RemoveWords(E.Data, 1).Trim();
|
String Message = Utilities.RemoveWords(E.Data, 1).Trim();
|
||||||
var length = E.Data.Split(' ')[0].ToLower().ParseTimespan();
|
var length = E.Data.Split(' ')[0].ToLower().ParseTimespan();
|
||||||
@ -199,7 +199,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Origin.Level > E.Target.Level)
|
if (E.Origin.Level > E.Target.Level)
|
||||||
{
|
{
|
||||||
@ -229,10 +229,10 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
var penalties = await E.Owner.Manager.GetPenaltyService().GetActivePenaltiesAsync(E.Target.AliasLinkId);
|
var penalties = await E.Owner.Manager.GetPenaltyService().GetActivePenaltiesAsync(E.Target.AliasLinkId);
|
||||||
if (penalties.Where(p => p.Type == Penalty.PenaltyType.Ban).FirstOrDefault() != null)
|
if (penalties.Where(p => p.Type == Penalty.PenaltyType.Ban || p.Type == Penalty.PenaltyType.TempBan).FirstOrDefault() != null)
|
||||||
{
|
{
|
||||||
await E.Owner.Unban(E.Data, E.Target, E.Origin);
|
await E.Owner.Unban(E.Data, E.Target, E.Origin);
|
||||||
await E.Origin.Tell($"Successfully unbanned {E.Target}");
|
await E.Origin.Tell($"Successfully unbanned {E.Target}");
|
||||||
@ -250,7 +250,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("whoami", "give information about yourself.", "who", Player.Permission.User, false)
|
base("whoami", "give information about yourself.", "who", Player.Permission.User, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientNumber, E.Origin.NetworkId, E.Origin.ClientId, Utilities.ConvertLevelToColor(E.Origin.Level), E.Origin.IPAddressString);
|
String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientNumber, E.Origin.NetworkId, E.Origin.ClientId, Utilities.ConvertLevelToColor(E.Origin.Level), E.Origin.IPAddressString);
|
||||||
await E.Origin.Tell(You);
|
await E.Origin.Tell(You);
|
||||||
@ -263,7 +263,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("list", "list active clients", "l", Player.Permission.Moderator, false)
|
base("list", "list active clients", "l", Player.Permission.Moderator, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
StringBuilder playerList = new StringBuilder();
|
StringBuilder playerList = new StringBuilder();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@ -305,7 +305,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
String cmd = E.Data.Trim();
|
String cmd = E.Data.Trim();
|
||||||
|
|
||||||
@ -361,7 +361,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("fastrestart", "fast restart current map", "fr", Player.Permission.Moderator, false)
|
base("fastrestart", "fast restart current map", "fr", Player.Permission.Moderator, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
await E.Owner.ExecuteCommandAsync("fast_restart");
|
await E.Owner.ExecuteCommandAsync("fast_restart");
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("maprotate", "cycle to the next map in rotation", "mr", Player.Permission.Administrator, false)
|
base("maprotate", "cycle to the next map in rotation", "mr", Player.Permission.Administrator, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (!E.Origin.Masked)
|
if (!E.Origin.Masked)
|
||||||
await E.Owner.Broadcast($"Map rotating in ^55 ^7seconds [^5{E.Origin.Name}^7]");
|
await E.Owner.Broadcast($"Map rotating in ^55 ^7seconds [^5{E.Origin.Name}^7]");
|
||||||
@ -407,7 +407,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Target == E.Origin)
|
if (E.Target == E.Origin)
|
||||||
{
|
{
|
||||||
@ -481,7 +481,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("usage", "get current application memory usage", "us", Player.Permission.Moderator, false)
|
base("usage", "get current application memory usage", "us", Player.Permission.Moderator, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
await E.Origin.Tell("IW4M Admin is using " + Math.Round(((System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 2048f) / 1200f), 1) + "MB");
|
await E.Origin.Tell("IW4M Admin is using " + Math.Round(((System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 2048f) / 1200f), 1) + "MB");
|
||||||
}
|
}
|
||||||
@ -493,7 +493,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("uptime", "get current application running time", "up", Player.Permission.Moderator, false)
|
base("uptime", "get current application running time", "up", Player.Permission.Moderator, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
TimeSpan uptime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime;
|
TimeSpan uptime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime;
|
||||||
await E.Origin.Tell(String.Format("IW4M Admin has been up for {0} days, {1} hours, and {2} minutes", uptime.Days, uptime.Hours, uptime.Minutes));
|
await E.Origin.Tell(String.Format("IW4M Admin has been up for {0} days, {1} hours, and {2} minutes", uptime.Days, uptime.Hours, uptime.Minutes));
|
||||||
@ -506,7 +506,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("admins", "list currently connected admins", "a", Player.Permission.User, false)
|
base("admins", "list currently connected admins", "a", Player.Permission.User, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
int numOnline = 0;
|
int numOnline = 0;
|
||||||
for (int i = 0; i < E.Owner.Players.Count; i++)
|
for (int i = 0; i < E.Owner.Players.Count; i++)
|
||||||
@ -540,7 +540,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
string newMap = E.Data.Trim().ToLower();
|
string newMap = E.Data.Trim().ToLower();
|
||||||
foreach (Map m in E.Owner.Maps)
|
foreach (Map m in E.Owner.Maps)
|
||||||
@ -573,7 +573,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
IList<EFClient> db_players = (await (E.Owner.Manager.GetClientService() as ClientService)
|
IList<EFClient> db_players = (await (E.Owner.Manager.GetClientService() as ClientService)
|
||||||
.GetClientByName(E.Data))
|
.GetClientByName(E.Data))
|
||||||
@ -603,7 +603,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("rules", "list server rules", "r", Player.Permission.User, false)
|
base("rules", "list server rules", "r", Player.Permission.User, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules?.Count < 1 &&
|
if (E.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules?.Count < 1 &&
|
||||||
E.Owner.ServerConfig.Rules?.Count < 1)
|
E.Owner.ServerConfig.Rules?.Count < 1)
|
||||||
@ -650,7 +650,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
await E.Target.Tell($"^1{E.Origin.Name} ^3[PM]^7 - {E.Data}");
|
await E.Target.Tell($"^1{E.Origin.Name} ^3[PM]^7 - {E.Data}");
|
||||||
await E.Origin.Tell($"To ^3{E.Target.Name} ^7-> {E.Data}");
|
await E.Origin.Tell($"To ^3{E.Target.Name} ^7-> {E.Data}");
|
||||||
@ -675,7 +675,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
// todo: move unflag to seperate command
|
// todo: move unflag to seperate command
|
||||||
if (E.Target.Level >= E.Origin.Level)
|
if (E.Target.Level >= E.Origin.Level)
|
||||||
@ -708,7 +708,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
};
|
};
|
||||||
|
|
||||||
await E.Owner.Manager.GetPenaltyService().Create(newPenalty);
|
await E.Owner.Manager.GetPenaltyService().Create(newPenalty);
|
||||||
await E.Owner.ExecuteEvent(new Event(Event.GType.Flag, E.Data, E.Origin, E.Target, E.Owner));
|
await E.Owner.ExecuteEvent(new GameEvent(GameEvent.EventType.Flag, E.Data, E.Origin, E.Target, E.Owner));
|
||||||
await E.Origin.Tell($"You have flagged ^5{E.Target.Name}");
|
await E.Origin.Tell($"You have flagged ^5{E.Target.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,7 +733,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Data.ToLower().Contains("camp"))
|
if (E.Data.ToLower().Contains("camp"))
|
||||||
{
|
{
|
||||||
@ -762,7 +762,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
E.Owner.Reports.Add(new Report(E.Target, E.Origin, E.Data));
|
E.Owner.Reports.Add(new Report(E.Target, E.Origin, E.Data));
|
||||||
|
|
||||||
await E.Origin.Tell($"Thank you for your report, an administrator has been notified");
|
await E.Origin.Tell($"Thank you for your report, an administrator has been notified");
|
||||||
await E.Owner.ExecuteEvent(new Event(Event.GType.Report, E.Data, E.Origin, E.Target, E.Owner));
|
await E.Owner.ExecuteEvent(new GameEvent(GameEvent.EventType.Report, E.Data, E.Origin, E.Target, E.Owner));
|
||||||
await E.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", E.Origin.Name, E.Target.Name, E.Data));
|
await E.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", E.Origin.Name, E.Target.Name, E.Data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -780,7 +780,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Data != null && E.Data.ToLower().Contains("clear"))
|
if (E.Data != null && E.Data.ToLower().Contains("clear"))
|
||||||
{
|
{
|
||||||
@ -806,7 +806,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("mask", "hide your presence as an administrator", "hide", Player.Permission.Moderator, false)
|
base("mask", "hide your presence as an administrator", "hide", Player.Permission.Moderator, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Origin.Masked)
|
if (E.Origin.Masked)
|
||||||
{
|
{
|
||||||
@ -836,7 +836,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
var B = await E.Owner.Manager.GetPenaltyService().GetClientPenaltiesAsync(E.Target.ClientId);
|
var B = await E.Owner.Manager.GetPenaltyService().GetClientPenaltiesAsync(E.Target.ClientId);
|
||||||
|
|
||||||
@ -865,7 +865,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
StringBuilder message = new StringBuilder();
|
StringBuilder message = new StringBuilder();
|
||||||
var names = new List<string>(E.Target.AliasLink.Children.Select(a => a.Name));
|
var names = new List<string>(E.Target.AliasLink.Children.Select(a => a.Name));
|
||||||
@ -897,7 +897,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
var Response = await E.Owner.ExecuteCommandAsync(E.Data.Trim());
|
var Response = await E.Owner.ExecuteCommandAsync(E.Data.Trim());
|
||||||
foreach (string S in Response)
|
foreach (string S in Response)
|
||||||
@ -913,7 +913,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("plugins", "view all loaded plugins", "p", Player.Permission.Administrator, false)
|
base("plugins", "view all loaded plugins", "p", Player.Permission.Administrator, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
await E.Origin.Tell("^5Loaded Plugins:");
|
await E.Origin.Tell("^5Loaded Plugins:");
|
||||||
foreach (var P in Plugins.PluginImporter.ActivePlugins)
|
foreach (var P in Plugins.PluginImporter.ActivePlugins)
|
||||||
@ -929,7 +929,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
base("getexternalip", "view your external IP address", "ip", Player.Permission.User, false)
|
base("getexternalip", "view your external IP address", "ip", Player.Permission.User, false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
await E.Origin.Tell($"Your external IP is ^5{E.Origin.IPAddressString}");
|
await E.Origin.Tell($"Your external IP is ^5{E.Origin.IPAddressString}");
|
||||||
}
|
}
|
||||||
@ -947,7 +947,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
int inactiveDays = 30;
|
int inactiveDays = 30;
|
||||||
|
|
||||||
@ -997,7 +997,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
})
|
})
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Data.Length < 5)
|
if (E.Data.Length < 5)
|
||||||
{
|
{
|
||||||
@ -1024,7 +1024,7 @@ namespace SharedLibraryCore.Commands
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task ExecuteAsync(Event E)
|
public override async Task ExecuteAsync(GameEvent E)
|
||||||
{
|
{
|
||||||
var gameserverProcesses = System.Diagnostics.Process.GetProcessesByName("iw4x");
|
var gameserverProcesses = System.Diagnostics.Process.GetProcessesByName("iw4x");
|
||||||
var currentProcess = gameserverProcesses.FirstOrDefault(g => g.MainWindowTitle.Contains(E.Owner.Hostname));
|
var currentProcess = gameserverProcesses.FirstOrDefault(g => g.MainWindowTitle.Contains(E.Owner.Hostname));
|
||||||
|
@ -7,9 +7,9 @@ using SharedLibraryCore.Objects;
|
|||||||
|
|
||||||
namespace SharedLibraryCore
|
namespace SharedLibraryCore
|
||||||
{
|
{
|
||||||
public class Event
|
public class GameEvent
|
||||||
{
|
{
|
||||||
public enum GType
|
public enum EventType
|
||||||
{
|
{
|
||||||
//FROM SERVER
|
//FROM SERVER
|
||||||
Start,
|
Start,
|
||||||
@ -38,7 +38,7 @@ namespace SharedLibraryCore
|
|||||||
Death,
|
Death,
|
||||||
}
|
}
|
||||||
|
|
||||||
public Event(GType t, string d, Player O, Player T, Server S)
|
public GameEvent(EventType t, string d, Player O, Player T, Server S)
|
||||||
{
|
{
|
||||||
Type = t;
|
Type = t;
|
||||||
Data = d?.Trim();
|
Data = d?.Trim();
|
||||||
@ -47,59 +47,10 @@ namespace SharedLibraryCore
|
|||||||
Owner = S;
|
Owner = S;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Event ParseEventString(String[] line, Server SV)
|
public GameEvent() { }
|
||||||
{
|
|
||||||
#if DEBUG == false
|
|
||||||
try
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
string removeTime = Regex.Replace(line[0], @"[0-9]+:[0-9]+\ ", "");
|
|
||||||
|
|
||||||
if (removeTime[0] == 'K')
|
|
||||||
{
|
|
||||||
StringBuilder Data = new StringBuilder();
|
|
||||||
if (line.Length > 9)
|
|
||||||
{
|
|
||||||
for (int i = 9; i < line.Length; i++)
|
|
||||||
Data.Append(line[i] + ";");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SV.CustomCallback)
|
|
||||||
return new Event(GType.Script, Data.ToString(), SV.ParseClientFromString(line, 6), SV.ParseClientFromString(line, 2), SV);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0].Substring(line[0].Length - 3).Trim() == "say")
|
|
||||||
{
|
|
||||||
Regex rgx = new Regex("[^a-zA-Z0-9 -! -_]");
|
|
||||||
string message = rgx.Replace(line[4], "");
|
|
||||||
return new Event(GType.Say, message.StripColors(), SV.ParseClientFromString(line, 2), null, SV) { Message = message };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (removeTime.Contains("ScriptKill"))
|
|
||||||
{
|
|
||||||
return new Event(GType.Script, String.Join(";", line), SV.Players.First(p => p != null && p.NetworkId == line[1].ConvertLong()), SV.Players.First(p => p != null && p.NetworkId == line[2].ConvertLong()), SV);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (removeTime.Contains("ExitLevel"))
|
|
||||||
return new Event(GType.MapEnd, line[0], new Player() { ClientId = 1 }, null, SV);
|
|
||||||
|
|
||||||
if (removeTime.Contains("InitGame"))
|
|
||||||
return new Event(GType.MapChange, line[0], new Player() { ClientId = 1 }, null, SV);
|
|
||||||
|
|
||||||
|
|
||||||
return null;
|
public EventType Type;
|
||||||
}
|
|
||||||
#if DEBUG == false
|
|
||||||
catch (Exception E)
|
|
||||||
{
|
|
||||||
SV.Manager.GetLogger().WriteError("Error requesting event " + E.Message);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public GType Type;
|
|
||||||
public string Data; // Data is usually the message sent by player
|
public string Data; // Data is usually the message sent by player
|
||||||
public string Message;
|
public string Message;
|
||||||
public Player Origin;
|
public Player Origin;
|
||||||
|
@ -5,7 +5,7 @@ namespace SharedLibraryCore.Interfaces
|
|||||||
{
|
{
|
||||||
public interface IEventApi
|
public interface IEventApi
|
||||||
{
|
{
|
||||||
void OnServerEvent(object sender, Event E);
|
void OnServerEvent(object sender, GameEvent E);
|
||||||
Queue<EventInfo> GetEvents();
|
Queue<EventInfo> GetEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
SharedLibraryCore/Interfaces/IEventParser.cs
Normal file
11
SharedLibraryCore/Interfaces/IEventParser.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Interfaces
|
||||||
|
{
|
||||||
|
public interface IEventParser
|
||||||
|
{
|
||||||
|
GameEvent GetEvent(Server server, string logLine);
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ namespace SharedLibraryCore.Interfaces
|
|||||||
{
|
{
|
||||||
Task OnLoadAsync(IManager manager);
|
Task OnLoadAsync(IManager manager);
|
||||||
Task OnUnloadAsync();
|
Task OnUnloadAsync();
|
||||||
Task OnEventAsync(Event E, Server S);
|
Task OnEventAsync(GameEvent E, Server S);
|
||||||
Task OnTickAsync(Server S);
|
Task OnTickAsync(Server S);
|
||||||
|
|
||||||
//for logging purposes
|
//for logging purposes
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
using SharedLibraryCore.Objects;
|
using System.Collections.Generic;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using SharedLibraryCore.Objects;
|
||||||
|
using SharedLibraryCore.RCon;
|
||||||
|
|
||||||
namespace SharedLibraryCore.Interfaces
|
namespace SharedLibraryCore.Interfaces
|
||||||
{
|
{
|
||||||
public interface IRConParser
|
public interface IRConParser
|
||||||
{
|
{
|
||||||
Task<Dvar<T>> GetDvarAsync<T>(RCon.Connection connection, string dvarName);
|
Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName);
|
||||||
Task<bool> SetDvarAsync(RCon.Connection connection, string dvarName, object dvarValue);
|
Task<bool> SetDvarAsync(Connection connection, string dvarName, object dvarValue);
|
||||||
Task<string[]> ExecuteCommandAsync(RCon.Connection connection, string command);
|
Task<string[]> ExecuteCommandAsync(Connection connection, string command);
|
||||||
Task<List<Player>> GetStatusAsync(RCon.Connection connection);
|
Task<List<Player>> GetStatusAsync(Connection connection);
|
||||||
|
CommandPrefix GetCommandPrefixes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
SharedLibraryCore/RCon/CommandPrefix.cs
Normal file
17
SharedLibraryCore/RCon/CommandPrefix.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.RCon
|
||||||
|
{
|
||||||
|
public class CommandPrefix
|
||||||
|
{
|
||||||
|
public string Tell { get; set; }
|
||||||
|
public string Say { get; set; }
|
||||||
|
public string Set { get; set; }
|
||||||
|
public string Kick { get; set; }
|
||||||
|
public string Ban { get; set; }
|
||||||
|
public string Unban { get; set; }
|
||||||
|
public string TempBan { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -79,13 +79,6 @@ namespace SharedLibraryCore
|
|||||||
/// <returns>true if removal succeded, false otherwise</returns>
|
/// <returns>true if removal succeded, false otherwise</returns>
|
||||||
abstract public Task RemovePlayer(int cNum);
|
abstract public Task RemovePlayer(int cNum);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the player from the server's list by line from game long
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="L">Game log line containing event</param>
|
|
||||||
/// <param name="cIDPos">Position in the line where the cliet ID is written</param>
|
|
||||||
/// <returns>Matching player if found</returns>
|
|
||||||
abstract public Player ParseClientFromString(String[] L, int cIDPos);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a player by name
|
/// Get a player by name
|
||||||
@ -113,7 +106,7 @@ namespace SharedLibraryCore
|
|||||||
/// <param name="E">Event parameter</param>
|
/// <param name="E">Event parameter</param>
|
||||||
/// <param name="C">Command requested from the event</param>
|
/// <param name="C">Command requested from the event</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
abstract public Task<Command> ValidateCommand(Event E);
|
abstract public Task<Command> ValidateCommand(GameEvent E);
|
||||||
|
|
||||||
virtual public Task<bool> ProcessUpdatesAsync(CancellationToken cts)
|
virtual public Task<bool> ProcessUpdatesAsync(CancellationToken cts)
|
||||||
{
|
{
|
||||||
@ -125,8 +118,8 @@ namespace SharedLibraryCore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="E">Event</param>
|
/// <param name="E">Event</param>
|
||||||
/// <returns>True on sucess</returns>
|
/// <returns>True on sucess</returns>
|
||||||
abstract protected Task ProcessEvent(Event E);
|
abstract protected Task ProcessEvent(GameEvent E);
|
||||||
abstract public Task ExecuteEvent(Event E);
|
abstract public Task ExecuteEvent(GameEvent E);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a message to all players
|
/// Send a message to all players
|
||||||
@ -134,10 +127,9 @@ namespace SharedLibraryCore
|
|||||||
/// <param name="Message">Message to be sent to all players</param>
|
/// <param name="Message">Message to be sent to all players</param>
|
||||||
public async Task Broadcast(String Message)
|
public async Task Broadcast(String Message)
|
||||||
{
|
{
|
||||||
|
|
||||||
string sayCommand = (GameName == Game.IW4) ? "sayraw" : "say";
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
await this.ExecuteCommandAsync($"{sayCommand} {(CustomSayEnabled ? CustomSayName : "")} {Message}");
|
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Say, Message);
|
||||||
|
await this.ExecuteCommandAsync(formattedMessage);
|
||||||
#else
|
#else
|
||||||
Logger.WriteVerbose(Message.StripColors());
|
Logger.WriteVerbose(Message.StripColors());
|
||||||
await Utilities.CompletedTask;
|
await Utilities.CompletedTask;
|
||||||
@ -151,11 +143,11 @@ namespace SharedLibraryCore
|
|||||||
/// <param name="Target">Player to send message to</param>
|
/// <param name="Target">Player to send message to</param>
|
||||||
public async Task Tell(String Message, Player Target)
|
public async Task Tell(String Message, Player Target)
|
||||||
{
|
{
|
||||||
string tellCommand = (GameName == Game.IW4) ? "tellraw" : "tell";
|
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
|
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Tell, Target.ClientNumber, Message);
|
||||||
if (Target.ClientNumber > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console)
|
if (Target.ClientNumber > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console)
|
||||||
await this.ExecuteCommandAsync($"{tellCommand} {Target.ClientNumber} {(CustomSayEnabled ? CustomSayName : "")} {Message}^7");
|
await this.ExecuteCommandAsync(formattedMessage);
|
||||||
#else
|
#else
|
||||||
Logger.WriteVerbose($"{Target.ClientNumber}->{Message.StripColors()}");
|
Logger.WriteVerbose($"{Target.ClientNumber}->{Message.StripColors()}");
|
||||||
await Utilities.CompletedTask;
|
await Utilities.CompletedTask;
|
||||||
@ -286,8 +278,8 @@ namespace SharedLibraryCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
public Interfaces.IManager Manager { get; protected set; }
|
public IManager Manager { get; protected set; }
|
||||||
public Interfaces.ILogger Logger { get; private set; }
|
public ILogger Logger { get; private set; }
|
||||||
public ServerConfiguration ServerConfig { get; private set; }
|
public ServerConfiguration ServerConfig { get; private set; }
|
||||||
public List<Map> Maps { get; protected set; }
|
public List<Map> Maps { get; protected set; }
|
||||||
public List<Report> Reports { get; set; }
|
public List<Report> Reports { get; set; }
|
||||||
@ -315,6 +307,7 @@ namespace SharedLibraryCore
|
|||||||
public string WorkingDirectory { get; protected set; }
|
public string WorkingDirectory { get; protected set; }
|
||||||
public RCon.Connection RemoteConnection { get; protected set; }
|
public RCon.Connection RemoteConnection { get; protected set; }
|
||||||
public IRConParser RconParser { get; protected set; }
|
public IRConParser RconParser { get; protected set; }
|
||||||
|
public IEventParser EventParser { get; set; }
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
protected string IP;
|
protected string IP;
|
||||||
|
@ -139,6 +139,7 @@ namespace SharedLibraryCore.Services
|
|||||||
|
|
||||||
if (victim)
|
if (victim)
|
||||||
{
|
{
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
var iqPenalties = from penalty in context.Penalties.AsNoTracking()
|
var iqPenalties = from penalty in context.Penalties.AsNoTracking()
|
||||||
where penalty.OffenderId == clientId
|
where penalty.OffenderId == clientId
|
||||||
join victimClient in context.Clients.AsNoTracking()
|
join victimClient in context.Clients.AsNoTracking()
|
||||||
@ -160,13 +161,22 @@ namespace SharedLibraryCore.Services
|
|||||||
PunisherName = punisherAlias.Name,
|
PunisherName = punisherAlias.Name,
|
||||||
PunisherId = penalty.PunisherId,
|
PunisherId = penalty.PunisherId,
|
||||||
Offense = penalty.Offense,
|
Offense = penalty.Offense,
|
||||||
Type = penalty.Type.ToString()
|
Type = penalty.Type.ToString(),
|
||||||
|
TimeRemaining = now > penalty.Expires ? "" : penalty.Expires.ToString()
|
||||||
},
|
},
|
||||||
When = penalty.When,
|
When = penalty.When,
|
||||||
Sensitive = penalty.Type == Objects.Penalty.PenaltyType.Flag
|
Sensitive = penalty.Type == Objects.Penalty.PenaltyType.Flag
|
||||||
};
|
};
|
||||||
// fixme: is this good and fast?
|
// fixme: is this good and fast?
|
||||||
return await iqPenalties.ToListAsync();
|
var list = await iqPenalties.ToListAsync();
|
||||||
|
list.ForEach(p =>
|
||||||
|
{
|
||||||
|
var pi = ((PenaltyInfo)p.Value);
|
||||||
|
if (pi.TimeRemaining.Length > 0)
|
||||||
|
pi.TimeRemaining = (DateTime.Parse(((PenaltyInfo)p.Value).TimeRemaining) - now).TimeSpanText();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -204,17 +214,26 @@ namespace SharedLibraryCore.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<EFPenalty>> GetActivePenaltiesAsync(int aliasId)
|
public async Task<List<EFPenalty>> GetActivePenaltiesAsync(int aliasId, int ip = 0)
|
||||||
{
|
{
|
||||||
using (var context = new DatabaseContext())
|
using (var context = new DatabaseContext())
|
||||||
{
|
{
|
||||||
var iqPenalties = from link in context.AliasLinks
|
var iqPenalties = await (from link in context.AliasLinks
|
||||||
where link.AliasLinkId == aliasId
|
where link.AliasLinkId == aliasId
|
||||||
join penalty in context.Penalties
|
join penalty in context.Penalties
|
||||||
on link.AliasLinkId equals penalty.LinkId
|
on link.AliasLinkId equals penalty.LinkId
|
||||||
where penalty.Active
|
where penalty.Active
|
||||||
select penalty;
|
select penalty).ToListAsync();
|
||||||
return await iqPenalties.ToListAsync();
|
if (ip != 0)
|
||||||
|
{
|
||||||
|
iqPenalties.AddRange(await (from alias in context.Aliases
|
||||||
|
where alias.IPAddress == ip
|
||||||
|
join penalty in context.Penalties
|
||||||
|
on alias.LinkId equals penalty.LinkId
|
||||||
|
where penalty.Active
|
||||||
|
select penalty).ToListAsync());
|
||||||
|
}
|
||||||
|
return iqPenalties;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,6 +355,17 @@ namespace SharedLibraryCore
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int ClientIdFromString(String[] lineSplit, int cIDPos)
|
||||||
|
{
|
||||||
|
int pID = -2; // apparently falling = -1 cID so i can't use it now
|
||||||
|
int.TryParse(lineSplit[cIDPos].Trim(), out pID);
|
||||||
|
|
||||||
|
if (pID == -1) // special case similar to mod_suicide
|
||||||
|
int.TryParse(lineSplit[2], out pID);
|
||||||
|
|
||||||
|
return pID;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<Dvar<T>> GetDvarAsync<T>(this Server server, string dvarName) => await server.RconParser.GetDvarAsync<T>(server.RemoteConnection, dvarName);
|
public static async Task<Dvar<T>> GetDvarAsync<T>(this Server server, string dvarName) => await server.RconParser.GetDvarAsync<T>(server.RemoteConnection, dvarName);
|
||||||
|
|
||||||
public static async Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => await server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
|
public static async Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => await server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
|
||||||
|
@ -29,8 +29,6 @@ namespace WebfrontCore.Controllers
|
|||||||
|
|
||||||
if (HttpContext.Connection.RemoteIpAddress.ToString() != "127.0.0.1")
|
if (HttpContext.Connection.RemoteIpAddress.ToString() != "127.0.0.1")
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
User.ClientId = Convert.ToInt32(base.User.Claims.First(c => c.Type == ClaimTypes.Sid).Value);
|
User.ClientId = Convert.ToInt32(base.User.Claims.First(c => c.Type == ClaimTypes.Sid).Value);
|
||||||
|
@ -34,10 +34,16 @@ namespace WebfrontCore.Controllers
|
|||||||
{
|
{
|
||||||
ClientId = User.ClientId,
|
ClientId = User.ClientId,
|
||||||
Level = User.Level,
|
Level = User.Level,
|
||||||
CurrentServer = server
|
CurrentServer = server,
|
||||||
|
CurrentAlias = new Alias() { Name = User.Name }
|
||||||
|
};
|
||||||
|
var remoteEvent = new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Say,
|
||||||
|
Data = command,
|
||||||
|
Origin = client,
|
||||||
|
Owner = server
|
||||||
};
|
};
|
||||||
|
|
||||||
var remoteEvent = new Event(Event.GType.Say, command, client, null, server);
|
|
||||||
|
|
||||||
await server.ExecuteEvent(remoteEvent);
|
await server.ExecuteEvent(remoteEvent);
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
using SharedLibraryCore.Dtos;
|
using SharedLibraryCore.Dtos;
|
||||||
|
using SharedLibraryCore.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace WebfrontCore.ViewComponents
|
namespace WebfrontCore.ViewComponents
|
||||||
@ -12,22 +13,6 @@ namespace WebfrontCore.ViewComponents
|
|||||||
{
|
{
|
||||||
public async Task<IViewComponentResult> InvokeAsync(int offset)
|
public async Task<IViewComponentResult> InvokeAsync(int offset)
|
||||||
{
|
{
|
||||||
int ip = HttpContext.Connection.RemoteIpAddress
|
|
||||||
.ToString().ConvertToIP();
|
|
||||||
|
|
||||||
bool authed = false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// var a = IW4MAdmin.ApplicationManager.GetInstance()
|
|
||||||
//.PrivilegedClients[HttpContext.Connection.RemoteIpAddress.ToString().ConvertToIP()];
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (KeyNotFoundException)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var penalties = await Program.Manager.GetPenaltyService().GetRecentPenalties(15, offset);
|
var penalties = await Program.Manager.GetPenaltyService().GetRecentPenalties(15, offset);
|
||||||
var penaltiesDto = penalties.Select(p => new PenaltyInfo()
|
var penaltiesDto = penalties.Select(p => new PenaltyInfo()
|
||||||
{
|
{
|
||||||
@ -40,10 +25,11 @@ namespace WebfrontCore.ViewComponents
|
|||||||
Type = p.Type.ToString(),
|
Type = p.Type.ToString(),
|
||||||
TimePunished = Utilities.GetTimePassed(p.When, false),
|
TimePunished = Utilities.GetTimePassed(p.When, false),
|
||||||
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : Utilities.TimeSpanText(p.Expires - DateTime.UtcNow),
|
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : Utilities.TimeSpanText(p.Expires - DateTime.UtcNow),
|
||||||
Sensitive = p.Type == SharedLibraryCore.Objects.Penalty.PenaltyType.Flag
|
Sensitive = p.Type == Penalty.PenaltyType.Flag
|
||||||
});
|
});
|
||||||
|
|
||||||
penaltiesDto = authed ? penaltiesDto.ToList() : penaltiesDto.Where(p => !p.Sensitive).ToList();
|
bool authorized = User.Identity.IsAuthenticated;
|
||||||
|
penaltiesDto = authorized ? penaltiesDto.ToList() : penaltiesDto.Where(p => !p.Sensitive).ToList();
|
||||||
|
|
||||||
return View("_List", penaltiesDto);
|
return View("_List", penaltiesDto);
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,36 @@
|
|||||||
<li class="nav-item text-center text-md-left">@Html.ActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-link" })</li>
|
<li class="nav-item text-center text-md-left">@Html.ActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-link" })</li>
|
||||||
<li class="nav-item text-center text-md-left">@Html.ActionLink("Penalties", "List", "Penalty", new { area = "" }, new { @class = "nav-link" })</li>
|
<li class="nav-item text-center text-md-left">@Html.ActionLink("Penalties", "List", "Penalty", new { area = "" }, new { @class = "nav-link" })</li>
|
||||||
<li class="nav-item text-center text-md-left">@Html.ActionLink("Admins", "PrivilegedAsync", "Client", new { area = "" }, new { @class = "nav-link" })</li>
|
<li class="nav-item text-center text-md-left">@Html.ActionLink("Admins", "PrivilegedAsync", "Client", new { area = "" }, new { @class = "nav-link" })</li>
|
||||||
<li class="nav-item text-center text-md-left">@Html.ActionLink("Console", "Index", "Console", new { area = "" }, new { @class = "nav-link" })</li>
|
<li class="nav-item text-center text-md-left"></li>
|
||||||
@if (!string.IsNullOrEmpty(ViewBag.DiscordLink))
|
@if (!string.IsNullOrEmpty(ViewBag.DiscordLink))
|
||||||
{
|
{
|
||||||
<li class="nav-item text-center text-md-left"><a href="@ViewBag.DiscordLink" class="nav-link" target="_blank">Discord</a></li>
|
<li class="nav-item text-center text-md-left"><a href="@ViewBag.DiscordLink" class="nav-link" target="_blank">Discord</a></li>
|
||||||
}
|
}
|
||||||
@if (ViewBag.Authorized)
|
@if (ViewBag.Authorized)
|
||||||
{
|
{
|
||||||
<li class="nav-item text-center text-md-left">@Html.ActionLink("Logout", "LogoutAsync", "Account", new { area = "" }, new { @class = "nav-link" })</li>
|
<li class="nav-link dropdown text-center text-md-left p-0">
|
||||||
<li class="nav-item text-center text-md-left">@Html.ActionLink("", "ProfileAsync", "Client", new { id = ViewBag.User.ClientId }, new { @class = "nav-link oi oi-person oi-fix-navbar w-100", title = "Client Profile" })</li>
|
<a href="#" class="nav-link oi oi-person dropdown-toggle oi-fix-navbar w-100" id="account_dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></a>
|
||||||
|
|
||||||
|
<div class="dropdown-menu p-0" aria-labelledby="account_dropdown">
|
||||||
|
@Html.ActionLink("Console", "Index", "Console", new { area = "" }, new
|
||||||
|
{
|
||||||
|
@class = "dropdown-item bg-dark text-muted text-center text-md-left",
|
||||||
|
title = "Web Console"
|
||||||
|
})
|
||||||
|
@Html.ActionLink("Profile", "ProfileAsync", "Client", new { id = ViewBag.User.ClientId }, new
|
||||||
|
{
|
||||||
|
@class = "dropdown-item bg-dark text-muted text-center text-md-left",
|
||||||
|
title = "Client Profile",
|
||||||
|
})
|
||||||
|
@Html.ActionLink("Logout", "LogoutAsync", "Account", new { area = "" }, new
|
||||||
|
{
|
||||||
|
@class = "dropdown-item bg-dark text-muted text-center text-md-left",
|
||||||
|
title = "Logout of account"
|
||||||
|
})
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item text-center text-md-left"></li>
|
||||||
|
<li class="nav-item text-center text-md-left"></li>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -135,3 +135,8 @@ form * {
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
-webkit-box-shadow: none;
|
-webkit-box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
border-bottom: 1px solid $secondary;
|
||||||
|
margin-top: -3px;
|
||||||
|
}
|
||||||
|
@ -13,7 +13,7 @@ function loadMorePenalties() {
|
|||||||
offset += 15;
|
offset += 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($('#penalty_table').length == 1) {
|
if ($('#penalty_table').length === 1) {
|
||||||
/*
|
/*
|
||||||
https://stackoverflow.com/questions/19731730/jquery-js-detect-users-scroll-attempt-without-any-window-overflow-to-scroll
|
https://stackoverflow.com/questions/19731730/jquery-js-detect-users-scroll-attempt-without-any-window-overflow-to-scroll
|
||||||
*/
|
*/
|
||||||
|
@ -168,7 +168,10 @@ function loadMeta(meta) {
|
|||||||
// it's a penalty
|
// it's a penalty
|
||||||
if (meta.class.includes("Penalty")) {
|
if (meta.class.includes("Penalty")) {
|
||||||
if (meta.value.punisherId !== clientInfo.clientId) {
|
if (meta.value.punisherId !== clientInfo.clientId) {
|
||||||
eventString = `<div><span class="penalties-color-${meta.value.type.toLowerCase()}">${penaltyToName(meta.value.type)}</span> by <span class="text-highlight"> <a class="link-inverse" href="${meta.value.punisherId}">${meta.value.punisherName}</a></span > for <span style="color: white; ">${meta.value.offense}</span></div>`;
|
const timeRemaining = meta.value.type == 'TempBan' && meta.value.timeRemaining.length > 0 ?
|
||||||
|
`(${meta.value.timeRemaining} remaining)` :
|
||||||
|
'';
|
||||||
|
eventString = `<div><span class="penalties-color-${meta.value.type.toLowerCase()}">${penaltyToName(meta.value.type)}</span> by <span class="text-highlight"> <a class="link-inverse" href="${meta.value.punisherId}">${meta.value.punisherName}</a></span > for <span style="color: white; ">${meta.value.offense}</span><span class="text-muted"> ${timeRemaining}</span></div>`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
eventString = `<div><span class="penalties-color-${meta.value.type.toLowerCase()}">${penaltyToName(meta.value.type)} </span> <span class="text-highlight"><a class="link-inverse" href="${meta.value.offenderId}"> ${meta.value.offenderName}</a></span > for <span style="color: white; ">${meta.value.offense}</span></div>`;
|
eventString = `<div><span class="penalties-color-${meta.value.type.toLowerCase()}">${penaltyToName(meta.value.type)} </span> <span class="text-highlight"><a class="link-inverse" href="${meta.value.offenderId}"> ${meta.value.offenderName}</a></span > for <span style="color: white; ">${meta.value.offense}</span></div>`;
|
||||||
|
Loading…
Reference in New Issue
Block a user