started work on getting the restart functionality in the gamelogserver

fix bug with unbanned players still showing as banned via lock icon
move player based stuff into client class
finally renamed Player to EFClient via partial class
don't try to run this build because it's in between stages
This commit is contained in:
RaidMax 2018-11-05 21:01:29 -06:00
parent d9d548ea18
commit ed83c4c011
65 changed files with 864 additions and 743 deletions

2
.gitignore vendored
View File

@ -230,3 +230,5 @@ bootstrap-custom.min.css
/DiscordWebhook/config.dev.json
/GameLogServer/env
launchSettings.json
/VpnDetectionPrivate.js
/Plugins/ScriptPlugins/VpnDetectionPrivate.js

View File

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

View File

@ -1,4 +1,5 @@
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
@ -9,16 +10,16 @@ namespace IW4MAdmin.Application.Core
{
class ClientAuthentication : IClientAuthentication
{
private Queue<Player> ClientAuthenticationQueue;
private Dictionary<long, Player> AuthenticatedClients;
private Queue<EFClient> ClientAuthenticationQueue;
private Dictionary<long, EFClient> AuthenticatedClients;
public ClientAuthentication()
{
ClientAuthenticationQueue = new Queue<Player>();
AuthenticatedClients = new Dictionary<long, Player>();
ClientAuthenticationQueue = new Queue<EFClient>();
AuthenticatedClients = new Dictionary<long, EFClient>();
}
public void AuthenticateClients(IList<Player> clients)
public void AuthenticateClients(IList<EFClient> clients)
{
// we need to un-auth all the clients that have disconnected
var clientNetworkIds = clients.Select(c => c.NetworkId);
@ -33,10 +34,10 @@ namespace IW4MAdmin.Application.Core
foreach (var client in clients)
{
// they've not been authenticated
if (!AuthenticatedClients.TryGetValue(client.NetworkId, out Player value))
if (!AuthenticatedClients.TryGetValue(client.NetworkId, out EFClient value))
{
// authenticate them
client.State = Player.ClientState.Authenticated;
client.State = EFClient.ClientState.Authenticated;
AuthenticatedClients.Add(client.NetworkId, client);
}
else
@ -54,16 +55,16 @@ namespace IW4MAdmin.Application.Core
// grab each client that's connected via log
var clientToAuthenticate = ClientAuthenticationQueue.Dequeue();
// if they're not already authed, auth them
if (!AuthenticatedClients.TryGetValue(clientToAuthenticate.NetworkId, out Player value))
if (!AuthenticatedClients.TryGetValue(clientToAuthenticate.NetworkId, out EFClient value))
{
// authenticate them
clientToAuthenticate.State = Player.ClientState.Authenticated;
clientToAuthenticate.State = EFClient.ClientState.Authenticated;
AuthenticatedClients.Add(clientToAuthenticate.NetworkId, clientToAuthenticate);
}
}
}
public IList<Player> GetAuthenticatedClients()
public IList<EFClient> GetAuthenticatedClients()
{
if (AuthenticatedClients.Values.Count > 18)
{
@ -74,7 +75,7 @@ namespace IW4MAdmin.Application.Core
return AuthenticatedClients.Values.ToList();
}
public void RequestClientAuthentication(Player client)
public void RequestClientAuthentication(EFClient client)
{
ClientAuthenticationQueue.Enqueue(client);
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
@ -20,7 +21,7 @@ namespace IW4MAdmin.Application.EventParsers
if (eventType == "JoinTeam")
{
var origin = server.GetPlayersAsList().FirstOrDefault(c => c.NetworkId == lineSplit[1].ConvertLong());
var origin = server.GetClientsAsList().FirstOrDefault(c => c.NetworkId == lineSplit[1].ConvertLong());
return new GameEvent()
{
@ -41,7 +42,7 @@ namespace IW4MAdmin.Application.EventParsers
.Replace("\x15", "")
.Trim();
var origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2));
var origin = server.GetClientsAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2));
if (message[0] == '!' || message[0] == '@')
{
@ -70,8 +71,8 @@ namespace IW4MAdmin.Application.EventParsers
{
if (!server.CustomCallback)
{
var origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6));
var target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2));
var origin = server.GetClientsAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6));
var target = server.GetClientsAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2));
return new GameEvent()
{
@ -86,8 +87,8 @@ namespace IW4MAdmin.Application.EventParsers
if (eventType == "ScriptKill")
{
var origin = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong());
var target = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[2].ConvertLong());
var origin = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong());
var target = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[2].ConvertLong());
return new GameEvent()
{
Type = GameEvent.EventType.ScriptKill,
@ -100,8 +101,8 @@ namespace IW4MAdmin.Application.EventParsers
if (eventType == "ScriptDamage")
{
var origin = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong());
var target = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[2].ConvertLong());
var origin = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong());
var target = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[2].ConvertLong());
return new GameEvent()
{
@ -120,8 +121,8 @@ namespace IW4MAdmin.Application.EventParsers
{
if (Regex.Match(eventType, @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$").Success)
{
var origin = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[5].ConvertLong());
var target = server.GetPlayersAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong());
var origin = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[5].ConvertLong());
var target = server.GetClientsAsList().First(c => c.NetworkId == lineSplit[1].ConvertLong());
return new GameEvent()
{
@ -146,12 +147,12 @@ namespace IW4MAdmin.Application.EventParsers
Type = GameEvent.EventType.Join,
Data = logLine,
Owner = server,
Origin = new Player()
Origin = new EFClient()
{
Name = regexMatch.Groups[4].ToString().StripColors(),
NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString()),
State = Player.ClientState.Connecting,
State = EFClient.ClientState.Connecting,
CurrentServer = server
}
};
@ -185,11 +186,11 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.MapEnd,
Data = lineSplit[0],
Origin = new Player()
Origin = new EFClient()
{
ClientId = 1
},
Target = new Player()
Target = new EFClient()
{
ClientId = 1
},
@ -205,14 +206,8 @@ namespace IW4MAdmin.Application.EventParsers
{
Type = GameEvent.EventType.MapChange,
Data = lineSplit[0],
Origin = new Player()
{
ClientId = 1
},
Target = new Player()
{
ClientId = 1
},
Origin = Utilities.IW4MAdminClient(server),
Target = Utilities.IW4MAdminClient(server),
Owner = server,
Extra = dump.DictionaryFromKeyValue()
};
@ -221,14 +216,8 @@ namespace IW4MAdmin.Application.EventParsers
return new GameEvent()
{
Type = GameEvent.EventType.Unknown,
Origin = new Player()
{
ClientId = 1
},
Target = new Player()
{
ClientId = 1
},
Origin = Utilities.IW4MAdminClient(server),
Target = Utilities.IW4MAdminClient(server),
Owner = server
};
}

View File

@ -1,4 +1,5 @@
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using System;
@ -23,7 +24,7 @@ namespace IW4MAdmin.Application.EventParsers
int clientNum = Int32.Parse(lineSplit[2]);
var player = new Player()
var player = new EFClient()
{
NetworkId = lineSplit[1].ConvertLong(),
ClientNumber = clientNum,
@ -33,11 +34,11 @@ namespace IW4MAdmin.Application.EventParsers
return new GameEvent()
{
Type = GameEvent.EventType.Join,
Origin = new Player()
Origin = new EFClient()
{
ClientId = 1
},
Target = new Player()
Target = new EFClient()
{
ClientId = 1
},

View File

@ -110,7 +110,7 @@ namespace IW4MAdmin.Application
var consoleTask = Task.Run(async () =>
{
String userInput;
Player Origin = Utilities.IW4MAdminClient(ServerManager.Servers[0]);
var Origin = Utilities.IW4MAdminClient(ServerManager.Servers[0]);
do
{

View File

@ -19,6 +19,7 @@ using SharedLibraryCore.Events;
using IW4MAdmin.Application.API.Master;
using IW4MAdmin.Application.Migration;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Application
{
@ -26,7 +27,7 @@ namespace IW4MAdmin.Application
{
private List<Server> _servers;
public List<Server> Servers => _servers.OrderByDescending(s => s.ClientNum).ToList();
public Dictionary<int, Player> PrivilegedClients { get; set; }
public Dictionary<int, EFClient> PrivilegedClients { get; set; }
public ILogger Logger => GetLogger(0);
public bool Running { get; private set; }
public bool IsInitialized { get; private set; }
@ -60,7 +61,7 @@ namespace IW4MAdmin.Application
ClientSvc = new ClientService();
AliasSvc = new AliasService();
PenaltySvc = new PenaltyService();
PrivilegedClients = new Dictionary<int, Player>();
PrivilegedClients = new Dictionary<int, EFClient>();
ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
StartTime = DateTime.UtcNow;
OnQuit = new ManualResetEventSlim();
@ -144,7 +145,7 @@ namespace IW4MAdmin.Application
if (e.Target != null)
{
// update the target incase they left or have newer info
e.Target = newEvent.Owner.GetPlayersAsList()
e.Target = newEvent.Owner.GetClientsAsList()
.FirstOrDefault(p => p.NetworkId == e.Target.NetworkId);
// we have to throw out the event because they left
if (e.Target == null)
@ -285,7 +286,7 @@ namespace IW4MAdmin.Application
}
// todo: optimize this (or replace it)
var ipList = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted))
var ipList = (await ClientSvc.Find(c => c.Level > EFClient.Permission.Trusted))
.Select(c => new
{
c.Password,
@ -299,7 +300,7 @@ namespace IW4MAdmin.Application
{
try
{
PrivilegedClients.Add(a.ClientId, new Player()
PrivilegedClients.Add(a.ClientId, new EFClient()
{
Name = a.Name,
ClientId = a.ClientId,
@ -593,13 +594,13 @@ namespace IW4MAdmin.Application
return MessageTokens;
}
public IList<Player> GetActiveClients() => _servers.SelectMany(s => s.Players).Where(p => p != null).ToList();
public IList<EFClient> GetActiveClients() => _servers.SelectMany(s => s.Clients).Where(p => p != null).ToList();
public ClientService GetClientService() => ClientSvc;
public AliasService GetAliasService() => AliasSvc;
public PenaltyService GetPenaltyService() => PenaltySvc;
public IConfigurationHandler<ApplicationConfiguration> GetApplicationSettings() => ConfigHandler;
public IDictionary<int, Player> GetPrivilegedClients() => PrivilegedClients;
public IDictionary<int, EFClient> GetPrivilegedClients() => PrivilegedClients;
public bool ShutdownRequested() => !Running;
public IEventHandler GetEventHandler() => Handler;

View File

@ -9,6 +9,7 @@ using SharedLibraryCore.Objects;
using SharedLibraryCore;
using SharedLibraryCore.RCon;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Application.RconParsers
{
@ -61,7 +62,7 @@ namespace IW4MAdmin.Application.RconParsers
};
}
public async Task<List<Player>> GetStatusAsync(Connection connection)
public async Task<List<EFClient>> GetStatusAsync(Connection connection)
{
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
return ClientsFromStatus(response);
@ -74,9 +75,9 @@ namespace IW4MAdmin.Application.RconParsers
public virtual CommandPrefix GetCommandPrefixes() => Prefixes;
private List<Player> ClientsFromStatus(string[] Status)
private List<EFClient> ClientsFromStatus(string[] Status)
{
List<Player> StatusPlayers = new List<Player>();
List<EFClient> StatusPlayers = new List<EFClient>();
if (Status.Length < 4)
throw new ServerException("Unexpected status response received");
@ -106,7 +107,7 @@ namespace IW4MAdmin.Application.RconParsers
string name = regex.Groups[5].Value.StripColors().Trim();
int ip = regex.Groups[7].Value.Split(':')[0].ConvertToIP();
Player P = new Player()
var P = new EFClient()
{
Name = name,
NetworkId = networkId,
@ -115,7 +116,7 @@ namespace IW4MAdmin.Application.RconParsers
Ping = ping,
Score = score,
IsBot = ip == 0,
State = Player.ClientState.Connecting
State = EFClient.ClientState.Connecting
};
StatusPlayers.Add(P);
}

View File

@ -9,6 +9,7 @@ using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using SharedLibraryCore.RCon;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Application.RconParsers
{
@ -105,7 +106,7 @@ namespace IW4MAdmin.Application.RconParsers
};
}
public async Task<List<Player>> GetStatusAsync(Connection connection)
public async Task<List<EFClient>> GetStatusAsync(Connection connection)
{
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
return ClientsFromStatus(response);
@ -118,9 +119,9 @@ namespace IW4MAdmin.Application.RconParsers
return true;
}
private List<Player> ClientsFromStatus(string[] status)
private List<EFClient> ClientsFromStatus(string[] status)
{
List<Player> StatusPlayers = new List<Player>();
List<EFClient> StatusPlayers = new List<EFClient>();
foreach (string statusLine in status)
{
@ -145,7 +146,7 @@ namespace IW4MAdmin.Application.RconParsers
regex = Regex.Match(responseLine, @" +(\d+ +){3}");
int score = Int32.Parse(regex.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries)[0]);
var p = new Player()
var p = new EFClient()
{
Name = name,
NetworkId = networkId,
@ -154,7 +155,7 @@ namespace IW4MAdmin.Application.RconParsers
Ping = Ping,
Score = score,
IsBot = false,
State = Player.ClientState.Connecting
State = EFClient.ClientState.Connecting
};
StatusPlayers.Add(p);

View File

@ -9,6 +9,7 @@ using SharedLibraryCore.Objects;
using SharedLibraryCore.RCon;
using SharedLibraryCore.Exceptions;
using System.Text;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Application.RconParsers
{
@ -60,7 +61,7 @@ namespace IW4MAdmin.Application.RconParsers
};
}
public async Task<List<Player>> GetStatusAsync(Connection connection)
public async Task<List<EFClient>> GetStatusAsync(Connection connection)
{
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
return ClientsFromStatus(response);
@ -73,9 +74,9 @@ namespace IW4MAdmin.Application.RconParsers
return true;
}
private List<Player> ClientsFromStatus(string[] status)
private List<EFClient> ClientsFromStatus(string[] status)
{
List<Player> StatusPlayers = new List<Player>();
List<EFClient> StatusPlayers = new List<EFClient>();
foreach (string statusLine in status)
{
@ -98,7 +99,7 @@ namespace IW4MAdmin.Application.RconParsers
#endif
int ipAddress = regex.Value.Split(':')[0].ConvertToIP();
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
var p = new Player()
var p = new EFClient()
{
Name = name,
NetworkId = networkId,
@ -106,7 +107,7 @@ namespace IW4MAdmin.Application.RconParsers
IPAddress = ipAddress,
Ping = Ping,
Score = 0,
State = Player.ClientState.Connecting,
State = EFClient.ClientState.Connecting,
IsBot = networkId == 0
};

View File

@ -1,24 +1,22 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using IW4MAdmin.Application.EventParsers;
using IW4MAdmin.Application.IO;
using IW4MAdmin.Application.RconParsers;
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Localization;
using IW4MAdmin.Application.RconParsers;
using IW4MAdmin.Application.EventParsers;
using IW4MAdmin.Application.IO;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace IW4MAdmin
{
@ -58,234 +56,101 @@ namespace IW4MAdmin
return Id;
}
public async Task OnPlayerJoined(Player logClient)
public async Task OnClientJoined(EFClient polledClient)
{
var existingClient = Players[logClient.ClientNumber];
var existingClient = Clients[polledClient.ClientNumber];
if (existingClient == null ||
(existingClient.NetworkId != logClient.NetworkId &&
existingClient.State != Player.ClientState.Connected))
if (existingClient != null)
{
Logger.WriteDebug($"Log detected {logClient} joining");
Players[logClient.ClientNumber] = logClient;
await existingClient.OnJoin(polledClient.IPAddress);
}
}
await Task.CompletedTask;
}
override public async Task<bool> AddPlayer(Player polledPlayer)
override public async Task OnClientConnected(EFClient clientFromLog)
{
if ((polledPlayer.Ping == 999 && !polledPlayer.IsBot) ||
polledPlayer.Ping < 1 ||
polledPlayer.ClientNumber < 0)
{
return false;
}
// set this when they are waiting for authentication
if (Players[polledPlayer.ClientNumber] == null &&
polledPlayer.State == Player.ClientState.Connecting)
{
Players[polledPlayer.ClientNumber] = polledPlayer;
return false;
}
#if !DEBUG
if (polledPlayer.Name.Length < 3)
{
Logger.WriteDebug($"Kicking {polledPlayer} because their name is too short");
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, loc["SERVER_KICK_MINNAME"]);
await this.ExecuteCommandAsync(formattedKick);
return false;
}
if (Players.FirstOrDefault(p => p != null && p.Name == polledPlayer.Name && p.NetworkId != polledPlayer.NetworkId) != null)
{
Logger.WriteDebug($"Kicking {polledPlayer} because their name is already in use");
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, loc["SERVER_KICK_NAME_INUSE"]);
await this.ExecuteCommandAsync(formattedKick);
return false;
}
if (polledPlayer.Name == "Unknown Soldier" ||
polledPlayer.Name == "UnknownSoldier" ||
polledPlayer.Name == "CHEATER")
{
Logger.WriteDebug($"Kicking {polledPlayer} because their name is generic");
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, loc["SERVER_KICK_GENERICNAME"]);
await this.ExecuteCommandAsync(formattedKick);
return false;
}
if (polledPlayer.Name.Where(c => Char.IsControl(c)).Count() > 0)
{
Logger.WriteDebug($"Kicking {polledPlayer} because their name contains control characters");
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, loc["SERVER_KICK_CONTROLCHARS"]);
await this.ExecuteCommandAsync(formattedKick);
return false;
}
#endif
Logger.WriteDebug($"Client slot #{polledPlayer.ClientNumber} now reserved");
Logger.WriteDebug($"Client slot #{clientFromLog.ClientNumber} now reserved");
try
{
Player player = null;
var client = await Manager.GetClientService().GetUnique(polledPlayer.NetworkId);
EFClient client = await Manager.GetClientService().GetUnique(clientFromLog.NetworkId);
// first time client is connecting to server
if (client == null)
{
Logger.WriteDebug($"Client {polledPlayer} first time connecting");
player = (await Manager.GetClientService().Create(polledPlayer)).AsPlayer();
Logger.WriteDebug($"Client {clientFromLog} first time connecting");
client = await Manager.GetClientService().Create(clientFromLog);
}
// client has connected in the past
else
{
client.LastConnection = DateTime.UtcNow;
client.Connections += 1;
var existingAlias = client.AliasLink.Children
.FirstOrDefault(a => a.Name == polledPlayer.Name && a.IPAddress == polledPlayer.IPAddress);
.FirstOrDefault(a => a.Name == clientFromLog.Name);
if (existingAlias == null)
{
Logger.WriteDebug($"Client {polledPlayer} has connected previously under a different ip/name");
Logger.WriteDebug($"Client {clientFromLog} has connected previously under a different ip/name");
client.CurrentAlias = new EFAlias()
{
IPAddress = polledPlayer.IPAddress,
Name = polledPlayer.Name,
// this gets updated on client join
IPAddress = clientFromLog.IPAddress,
Name = clientFromLog.Name,
};
// we need to update their new ip and name to the virtual property
client.Name = polledPlayer.Name;
client.IPAddress = polledPlayer.IPAddress;
}
else
{
client.CurrentAlias = existingAlias;
client.CurrentAliasId = existingAlias.AliasId;
client.Name = existingAlias.Name;
client.IPAddress = existingAlias.IPAddress;
}
await Manager.GetClientService().Update(client);
player = client.AsPlayer();
}
// reserved slots stuff
if ((MaxClients - ClientNum) < ServerConfig.ReservedSlotNumber &&
!player.IsPrivileged())
{
Logger.WriteDebug($"Kicking {polledPlayer} their spot is reserved");
string formattedKick = String.Format(RconParser.GetCommandPrefixes().Kick, polledPlayer.ClientNumber, loc["SERVER_KICK_SLOT_IS_RESERVED"]);
await this.ExecuteCommandAsync(formattedKick);
return false;
}
Logger.WriteInfo($"Client {player} connected...");
Logger.WriteInfo($"Client {client} connected...");
// Do the player specific stuff
player.ClientNumber = polledPlayer.ClientNumber;
player.IsBot = polledPlayer.IsBot;
player.Score = polledPlayer.Score;
player.CurrentServer = this;
client.ClientNumber = clientFromLog.ClientNumber;
client.IsBot = clientFromLog.IsBot;
client.Score = clientFromLog.Score;
client.Ping = clientFromLog.Ping;
client.CurrentServer = this;
player.DelayedEvents = (Players[player.ClientNumber]?.DelayedEvents) ?? new Queue<GameEvent>();
Players[player.ClientNumber] = player;
Clients[client.ClientNumber] = client;
client.OnConnect();
var activePenalties = await Manager.GetPenaltyService().GetActivePenaltiesAsync(player.AliasLinkId, player.IPAddress);
var currentBan = activePenalties.FirstOrDefault(p => p.Type == Penalty.PenaltyType.Ban || p.Type == Penalty.PenaltyType.TempBan);
var currentAutoFlag = activePenalties.Where(p => p.Type == Penalty.PenaltyType.Flag && p.PunisherId == 1)
.Where(p => p.Active)
.OrderByDescending(p => p.When)
.FirstOrDefault();
// remove their auto flag status after a week
if (player.Level == Player.Permission.Flagged &&
currentAutoFlag != null &&
(DateTime.Now - currentAutoFlag.When).TotalDays > 7)
{
player.Level = Player.Permission.User;
}
if (currentBan != null)
{
Logger.WriteInfo($"Banned client {player} trying to connect...");
var autoKickClient = Utilities.IW4MAdminClient(this);
// the player is permanently banned
if (currentBan.Type == Penalty.PenaltyType.Ban)
{
// don't store the kick message
string formattedKick = String.Format(
RconParser.GetCommandPrefixes().Kick,
polledPlayer.ClientNumber,
$"{loc["SERVER_BAN_PREV"]} {currentBan.Offense} ({loc["SERVER_BAN_APPEAL"]} {Website})");
await this.ExecuteCommandAsync(formattedKick);
}
else
{
string formattedKick = String.Format(
RconParser.GetCommandPrefixes().Kick,
polledPlayer.ClientNumber,
$"{loc["SERVER_TB_REMAIN"]} ({(currentBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})");
await this.ExecuteCommandAsync(formattedKick);
}
// reban the "evading" guid
if (player.Level != Player.Permission.Banned && currentBan.Type == Penalty.PenaltyType.Ban)
{
// hack: re apply the automated offense to the reban
if (currentBan.AutomatedOffense != null)
{
autoKickClient.AdministeredPenalties.Add(new EFPenalty() { AutomatedOffense = currentBan.AutomatedOffense });
}
player.Ban($"{currentBan.Offense}", autoKickClient);
}
// they didn't fully connect so empty their slot
Players[player.ClientNumber] = null;
return false;
}
player.State = Player.ClientState.Connected;
return true;
client.State = EFClient.ClientState.Connected;
}
catch (Exception ex)
{
Logger.WriteError($"{loc["SERVER_ERROR_ADDPLAYER"]} {polledPlayer.Name}::{polledPlayer.NetworkId}");
Logger.WriteError($"{loc["SERVER_ERROR_ADDPLAYER"]} {clientFromLog.Name}::{clientFromLog.NetworkId}");
Logger.WriteDebug(ex.Message);
Logger.WriteDebug(ex.StackTrace);
return false;
}
}
//Remove player by CLIENT NUMBER
override public async Task RemovePlayer(int cNum)
override public async Task RemoveClient(int cNum)
{
if (cNum >= 0 && Players[cNum] != null)
if (cNum >= 0 && Clients[cNum] != null)
{
Player Leaving = Players[cNum];
EFClient Leaving = Clients[cNum];
// occurs when the player disconnects via log before being authenticated by RCon
if (Leaving.State != Player.ClientState.Connected)
if (Leaving.State != EFClient.ClientState.Connected)
{
Players[cNum] = null;
Clients[cNum] = null;
}
else
{
Logger.WriteInfo($"Client {Leaving} [{Leaving.State.ToString().ToLower()}] disconnecting...");
Leaving.State = Player.ClientState.Disconnecting;
Leaving.State = EFClient.ClientState.Disconnecting;
Leaving.TotalConnectionTime += Leaving.ConnectionLength;
Leaving.LastConnection = DateTime.UtcNow;
await Manager.GetClientService().Update(Leaving);
Players[cNum] = null;
Clients[cNum] = null;
}
}
}
@ -340,7 +205,7 @@ namespace IW4MAdmin
if (E.Type == GameEvent.EventType.Command &&
E.Extra != null &&
(canExecuteCommand ||
E.Origin?.Level == Player.Permission.Console))
E.Origin?.Level == EFClient.Permission.Console))
{
await (((Command)E.Extra).ExecuteAsync(E));
}
@ -355,25 +220,17 @@ namespace IW4MAdmin
{
if (E.Type == GameEvent.EventType.Connect)
{
E.Origin.State = Player.ClientState.Authenticated;
// add them to the server
if (!await AddPlayer(E.Origin))
{
E.Origin.State = Player.ClientState.Connecting;
Logger.WriteDebug("client didn't pass authentication, so we are discontinuing event");
return false;
}
// hack: makes the event propgate with the correct info
E.Origin = Players[E.Origin.ClientNumber];
E.Origin.State = EFClient.ClientState.Authenticated;
await OnClientConnected(E.Origin);
ChatHistory.Add(new ChatInfo()
{
Name = E.Origin?.Name ?? "ERROR!",
Name = E.Origin.Name,
Message = "CONNECTED",
Time = DateTime.UtcNow
});
if (E.Origin.Level > Player.Permission.Moderator)
if (E.Origin.Level > EFClient.Permission.Moderator)
{
E.Origin.Tell(string.Format(loc["SERVER_REPORT_COUNT"], E.Owner.Reports.Count));
}
@ -381,7 +238,7 @@ namespace IW4MAdmin
else if (E.Type == GameEvent.EventType.Join)
{
await OnPlayerJoined(E.Origin);
await OnClientJoined(E.Origin);
}
else if (E.Type == GameEvent.EventType.Flag)
@ -446,11 +303,11 @@ namespace IW4MAdmin
else if (E.Type == GameEvent.EventType.Quit)
{
var origin = Players.FirstOrDefault(p => p != null && p.NetworkId == E.Origin.NetworkId);
var origin = Clients.FirstOrDefault(p => p != null && p.NetworkId == E.Origin.NetworkId);
if (origin != null &&
// we only want to forward the event if they are connected.
origin.State == Player.ClientState.Connected &&
origin.State == EFClient.ClientState.Connected &&
// make sure we don't get the disconnect event from every time the game ends
origin.ConnectionLength < Manager.GetApplicationSettings().Configuration().RConPollRate)
{
@ -465,9 +322,9 @@ namespace IW4MAdmin
}
else if (origin != null &&
origin.State != Player.ClientState.Connected)
origin.State != EFClient.ClientState.Connected)
{
await RemovePlayer(origin.ClientNumber);
await RemoveClient(origin.ClientNumber);
}
}
@ -481,9 +338,9 @@ namespace IW4MAdmin
});
var currentState = E.Origin.State;
await RemovePlayer(E.Origin.ClientNumber);
await RemoveClient(E.Origin.ClientNumber);
if (currentState != Player.ClientState.Connected)
if (currentState != EFClient.ClientState.Connected)
{
throw new ServerException("Disconnecting player was not in a connected state");
}
@ -569,12 +426,16 @@ namespace IW4MAdmin
}
while (ChatHistory.Count > Math.Ceiling((double)ClientNum / 2))
{
ChatHistory.RemoveAt(0);
}
// the last client hasn't fully disconnected yet
// so there will still be at least 1 client left
if (ClientNum < 2)
{
ChatHistory.Clear();
}
return true;
}
@ -585,12 +446,12 @@ namespace IW4MAdmin
/// array index 1 = disconnecting clients
/// </summary>
/// <returns></returns>
async Task<IList<Player>[]> PollPlayersAsync()
async Task<IList<EFClient>[]> PollPlayersAsync()
{
#if DEBUG
var now = DateTime.Now;
#endif
var currentClients = GetPlayersAsList();
var currentClients = GetClientsAsList();
var polledClients = (await this.GetStatusAsync()).AsEnumerable();
if (this.Manager.GetApplicationSettings().Configuration().IgnoreBots)
{
@ -604,15 +465,15 @@ namespace IW4MAdmin
foreach (var client in polledClients)
{
// todo: move out somehwere
var existingClient = Players[client.ClientNumber] ?? client;
var existingClient = Clients[client.ClientNumber] ?? client;
existingClient.Ping = client.Ping;
existingClient.Score = client.Score;
}
var disconnectingClients = currentClients.Except(polledClients);
var connectingClients = polledClients.Except(currentClients.Where(c => c.State == Player.ClientState.Connected));
var connectingClients = polledClients.Except(currentClients.Where(c => c.State == EFClient.ClientState.Connected));
return new List<Player>[] { connectingClients.ToList(), disconnectingClients.ToList() };
return new List<EFClient>[] { connectingClients.ToList(), disconnectingClients.ToList() };
}
DateTime start = DateTime.Now;
@ -626,12 +487,14 @@ namespace IW4MAdmin
if (Manager.ShutdownRequested())
{
// todo: fix up disconnect
//for (int i = 0; i < Players.Count; i++)
// await RemovePlayer(i);
//for (int i = 0; i < EFClients.Count; i++)
// await RemoveClient(i);
foreach (var plugin in SharedLibraryCore.Plugins.PluginImporter.ActivePlugins)
{
await plugin.OnUnloadAsync();
}
}
// only check every 2 minutes if the server doesn't seem to be responding
/* if ((DateTime.Now - LastPoll).TotalMinutes < 0.5 && ConnectionErrors >= 1)
@ -644,7 +507,7 @@ namespace IW4MAdmin
foreach (var disconnectingClient in polledClients[1])
{
if (disconnectingClient.State == Player.ClientState.Disconnecting)
if (disconnectingClient.State == EFClient.ClientState.Disconnecting)
{
continue;
}
@ -669,8 +532,8 @@ namespace IW4MAdmin
foreach (var client in polledClients[0])
{
// this prevents duplicate events from being sent to the event api
if (GetPlayersAsList().Count(c => c.NetworkId == client.NetworkId &&
c.State == Player.ClientState.Connected) != 0)
if (GetClientsAsList().Count(c => c.NetworkId == client.NetworkId &&
c.State == EFClient.ClientState.Connected) != 0)
{
continue;
}
@ -730,9 +593,12 @@ namespace IW4MAdmin
// update the player history
if ((lastCount - playerCountStart).TotalMinutes >= SharedLibraryCore.Helpers.PlayerHistory.UpdateInterval)
{
while (PlayerHistory.Count > ((60 / SharedLibraryCore.Helpers.PlayerHistory.UpdateInterval) * 12)) // 12 times a hour for 12 hours
PlayerHistory.Dequeue();
PlayerHistory.Enqueue(new SharedLibraryCore.Helpers.PlayerHistory(ClientNum));
while (ClientHistory.Count > ((60 / SharedLibraryCore.Helpers.PlayerHistory.UpdateInterval) * 12)) // 12 times a hour for 12 hours
{
ClientHistory.Dequeue();
}
ClientHistory.Enqueue(new SharedLibraryCore.Helpers.PlayerHistory(ClientNum));
playerCountStart = DateTime.Now;
}
@ -782,7 +648,9 @@ namespace IW4MAdmin
new IW3RConParser();
if (ServerConfig.UseIW5MParser)
{
RconParser = new IW5MRConParser();
}
var version = await this.GetDvarAsync<string>("version");
GameName = Utilities.GetGame(version.Value);
@ -793,16 +661,26 @@ namespace IW4MAdmin
RconParser = new IW4RConParser();
}
else if (GameName == Game.IW5)
{
EventParser = new IW5EventParser();
}
else if (GameName == Game.T5M)
{
EventParser = new T5MEventParser();
}
else if (GameName == Game.T6M)
{
EventParser = new T6MEventParser();
}
else
{
EventParser = new IW3EventParser(); // this uses the 'main' folder for log paths
}
if (GameName == Game.UKN)
{
Logger.WriteWarning($"Game name not recognized: {version}");
}
var infoResponse = await this.GetInfoAsync();
// this is normally slow, but I'm only doing it because different games have different prefixes
@ -906,7 +784,7 @@ namespace IW4MAdmin
#endif
}
protected override async Task Warn(String Reason, Player Target, Player Origin)
protected override async Task Warn(String Reason, EFClient Target, EFClient Origin)
{
// ensure player gets warned if command not performed on them in game
if (Target.ClientNumber < 0)
@ -948,7 +826,7 @@ namespace IW4MAdmin
await Manager.GetPenaltyService().Create(newPenalty);
}
protected override async Task Kick(String Reason, Player Target, Player Origin)
protected override async Task Kick(String Reason, EFClient Target, EFClient Origin)
{
// ensure player gets kicked if command not performed on them in game
if (Target.ClientNumber < 0)
@ -971,7 +849,7 @@ namespace IW4MAdmin
#endif
#if DEBUG
await Target.CurrentServer.RemovePlayer(Target.ClientNumber);
await Target.CurrentServer.RemoveClient(Target.ClientNumber);
#endif
var newPenalty = new Penalty()
@ -988,7 +866,7 @@ namespace IW4MAdmin
await Manager.GetPenaltyService().Create(newPenalty);
}
protected override async Task TempBan(String Reason, TimeSpan length, Player Target, Player Origin)
protected override async Task TempBan(String Reason, TimeSpan length, EFClient Target, EFClient Origin)
{
// ensure player gets banned if command not performed on them in game
if (Target.ClientNumber < 0)
@ -1009,7 +887,7 @@ namespace IW4MAdmin
await Target.CurrentServer.ExecuteCommandAsync(formattedKick);
}
#else
await Target.CurrentServer.RemovePlayer(Target.ClientNumber);
await Target.CurrentServer.RemoveClient(Target.ClientNumber);
#endif
Penalty newPenalty = new Penalty()
@ -1027,15 +905,15 @@ namespace IW4MAdmin
await Manager.GetPenaltyService().Create(newPenalty);
}
override protected async Task Ban(String Message, Player Target, Player Origin)
override protected async Task Ban(String Message, EFClient Target, EFClient Origin)
{
// ensure player gets banned if command not performed on them in game
if (Target.ClientNumber < 0)
{
Player ingameClient = null;
EFClient ingameClient = null;
ingameClient = Manager.GetServers()
.Select(s => s.GetPlayersAsList())
.Select(s => s.GetClientsAsList())
.FirstOrDefault(l => l.FirstOrDefault(c => c.ClientId == Target.ClientId) != null)
?.First(c => c.ClientId == Target.ClientId);
@ -1049,13 +927,13 @@ namespace IW4MAdmin
else
{
// this is set only because they're still in the server.
Target.Level = Player.Permission.Banned;
Target.Level = EFClient.Permission.Banned;
#if !DEBUG
string formattedString = String.Format(RconParser.GetCommandPrefixes().Kick, Target.ClientNumber, $"{loc["SERVER_BAN_TEXT"]} - ^5{Message} ^7({loc["SERVER_BAN_APPEAL"]} {Website})^7");
await Target.CurrentServer.ExecuteCommandAsync(formattedString);
#else
await Target.CurrentServer.RemovePlayer(Target.ClientNumber);
await Target.CurrentServer.RemoveClient(Target.ClientNumber);
#endif
}
@ -1077,7 +955,7 @@ namespace IW4MAdmin
Manager.GetPrivilegedClients().Remove(Target.ClientId);
}
override public async Task Unban(string reason, Player Target, Player Origin)
override public async Task Unban(string reason, EFClient Target, EFClient Origin)
{
var unbanPenalty = new Penalty()
{

View File

@ -27,6 +27,11 @@
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Prerelease' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<OutputPath>bin\Prerelease\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="DiscordWebhook.py" />
</ItemGroup>

View File

@ -27,10 +27,16 @@
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Prerelease' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<OutputPath>bin\Prerelease\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="GameLogServer\log_reader.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="GameLogServer\restart_resource.py" />
<Compile Include="GameLogServer\server.py">
<SubType>Code</SubType>
</Compile>

View File

@ -0,0 +1,29 @@
from flask_restful import Resource
from flask import request
import requests
import os
import subprocess
import re
def get_pid_of_server_windows(port):
process = subprocess.Popen('netstat -aon', shell=True, stdout=subprocess.PIPE)
output = process.communicate()[0]
matches = re.search(' *(UDP) +([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}):'+ str(port) + ' +[^\w]*([0-9]+)', output.decode('utf-8'))
if matches is not None:
return matches.group(3)
else:
return 0
class RestartResource(Resource):
def get(self):
try:
response = requests.get('http://' + request.remote_addr + ':1624/api/restartapproved')
if response.status_code == 200:
pid = get_pid_of_server_windows(response.json()['port'])
subprocess.check_output("Taskkill /PID %s /F" % pid)
else:
return {}, 400
except Exception as e:
print(e)
return {}, 500
return {}, 200

View File

@ -1,9 +1,11 @@
from flask import Flask
from flask_restful import Api
from .log_resource import LogResource
from .restart_resource import RestartResource
app = Flask(__name__)
def init():
api = Api(app)
api.add_resource(LogResource, '/log/<string:path>')
api.add_resource(RestartResource, '/restart')

View File

@ -1,4 +1,3 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
@ -41,6 +40,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlug
ProjectSection(SolutionItems) = preProject
Plugins\ScriptPlugins\SharedGUIDKick.js = Plugins\ScriptPlugins\SharedGUIDKick.js
Plugins\ScriptPlugins\VPNDetection.js = Plugins\ScriptPlugins\VPNDetection.js
Plugins\ScriptPlugins\VpnDetectionPrivate.js = Plugins\ScriptPlugins\VpnDetectionPrivate.js
EndProjectSection
EndProject
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "GameLogServer", "GameLogServer\GameLogServer.pyproj", "{42EFDA12-10D3-4C40-A210-9483520116BC}"

View File

@ -17,7 +17,7 @@
<SuppressCollectPythonCloudServiceFiles>true</SuppressCollectPythonCloudServiceFiles>
<Name>Master</Name>
<RootNamespace>Master</RootNamespace>
<InterpreterId>MSBuild|dev_env|$(MSBuildProjectFullPath)</InterpreterId>
<InterpreterId>MSBuild|env|X:\IW4MAdmin\GameLogServer\GameLogServer.pyproj</InterpreterId>
<IsWindowsApplication>False</IsWindowsApplication>
<PythonRunWebServerCommand>
</PythonRunWebServerCommand>
@ -111,23 +111,15 @@
<Folder Include="master\templates\" />
</ItemGroup>
<ItemGroup>
<None Include="FolderProfile.pubxml" />
<Content Include="master\config\master.json" />
<Content Include="master\templates\serverlist.html" />
<None Include="Release.pubxml" />
<Content Include="requirements.txt" />
<Content Include="master\templates\index.html" />
<Content Include="master\templates\layout.html" />
</ItemGroup>
<ItemGroup>
<Interpreter Include="dev_env\">
<Id>dev_env</Id>
<Version>3.6</Version>
<Description>dev_env (Python 3.6 (64-bit))</Description>
<InterpreterPath>Scripts\python.exe</InterpreterPath>
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
<Architecture>X64</Architecture>
</Interpreter>
<InterpreterReference Include="MSBuild|env|X:\IW4MAdmin\GameLogServer\GameLogServer.pyproj" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.Web.targets" />
<!-- Specify pre- and post-build commands in the BeforeBuild and

View File

@ -1,6 +1,6 @@
aniso8601==3.0.0
aniso8601==3.0.2
click==6.7
Flask==0.12.2
Flask==1.0.2
Flask-JWT==0.3.2
Flask-JWT-Extended==3.8.1
Flask-RESTful==0.3.6
@ -8,9 +8,15 @@ itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
marshmallow==3.0.0b8
pip==9.0.1
pip==9.0.3
PyJWT==1.4.2
pytz==2018.4
pytz==2018.5
setuptools==39.0.1
six==1.11.0
Werkzeug==0.14.1
certifi==2018.10.15
chardet==3.0.4
idna==2.7
psutil==5.4.8
requests==2.20.0
urllib3==1.24

View File

@ -1,4 +1,5 @@
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
@ -17,15 +18,15 @@ namespace IW4ScriptCommands.Commands
public IW4MAdmin.Plugins.Stats.Models.EFClientStatistics Stats { get; set; }
}
public static string GetTeamAssignments(Player client, bool isDisconnect, Server server, string teamsString = "")
public static string GetTeamAssignments(EFClient client, bool isDisconnect, Server server, string teamsString = "")
{
var scriptClientTeams = teamsString.Split(';', StringSplitOptions.RemoveEmptyEntries)
.Select(c => c.Split(','))
.Select(c => new TeamAssignment()
{
CurrentTeam = (IW4MAdmin.Plugins.Stats.IW4Info.Team)Enum.Parse(typeof(IW4MAdmin.Plugins.Stats.IW4Info.Team), c[1]),
Num = server.GetPlayersAsList().FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0]))?.ClientNumber ?? -1,
Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(server.Players.FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0])).ClientId, server.GetHashCode())
Num = server.GetClientsAsList().FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0]))?.ClientNumber ?? -1,
Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(server.Clients.FirstOrDefault(p => p.ClientNumber == Int32.Parse(c[0])).ClientId, server.GetHashCode())
})
.ToList();
@ -39,7 +40,7 @@ namespace IW4ScriptCommands.Commands
List<string> teamAssignments = new List<string>();
var _c = server.GetPlayersAsList();
var _c = server.GetClientsAsList();
if (isDisconnect && client != null)
{
_c = _c.Where(c => c.ClientNumber != client.ClientNumber).ToList();

View File

@ -6,6 +6,7 @@
<RuntimeFrameworkVersion>2.1.5</RuntimeFrameworkVersion>
<ApplicationIcon />
<StartupObject />
<Configurations>Debug;Release;Prerelease</Configurations>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -1,4 +1,5 @@
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
@ -8,7 +9,7 @@ namespace IW4MAdmin.Plugins.Login.Commands
{
public class CLogin : Command
{
public CLogin() : base("login", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_LOGIN_COMMANDS_LOGIN_DESC"], "li", Player.Permission.Trusted, false, new CommandArgument[]
public CLogin() : base("login", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_LOGIN_COMMANDS_LOGIN_DESC"], "li", EFClient.Permission.Trusted, false, new CommandArgument[]
{
new CommandArgument()
{

View File

@ -3,6 +3,7 @@ using System.Reflection;
using System.Threading.Tasks;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
@ -38,11 +39,11 @@ namespace IW4MAdmin.Plugins.Login
if (E.Type == GameEvent.EventType.Command)
{
if (E.Origin.Level < Player.Permission.Moderator ||
E.Origin.Level == Player.Permission.Console)
if (E.Origin.Level < EFClient.Permission.Moderator ||
E.Origin.Level == EFClient.Permission.Console)
return Task.CompletedTask;
E.Owner.Manager.GetPrivilegedClients().TryGetValue(E.Origin.ClientId, out Player client);
E.Owner.Manager.GetPrivilegedClients().TryGetValue(E.Origin.ClientId, out EFClient client);
if (((Command)E.Extra).Name == new SharedLibraryCore.Commands.CSetPassword().Name &&
client?.Password == null)

View File

@ -5,6 +5,7 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
@ -48,7 +49,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
if (containsObjectionalWord)
{
E.Origin.Kick(Settings.Configuration().ProfanityKickMessage, new Player()
E.Origin.Kick(Settings.Configuration().ProfanityKickMessage, new EFClient()
{
ClientId = 1,
CurrentServer = E.Owner
@ -85,7 +86,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
var clientProfanity = ProfanityCounts[E.Origin.ClientId];
if (clientProfanity.Infringements >= Settings.Configuration().KickAfterInfringementCount)
{
clientProfanity.Client.Kick(Settings.Configuration().ProfanityKickMessage, new Player()
clientProfanity.Client.Kick(Settings.Configuration().ProfanityKickMessage, new EFClient()
{
ClientId = 1,
CurrentServer = E.Owner
@ -96,7 +97,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
{
clientProfanity.Infringements++;
clientProfanity.Client.Warn(Settings.Configuration().ProfanityWarningMessage, new Player()
clientProfanity.Client.Warn(Settings.Configuration().ProfanityWarningMessage, new EFClient()
{
ClientId = 1,
CurrentServer = E.Owner

View File

@ -1,16 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
namespace IW4MAdmin.Plugins.ProfanityDeterment
{
class Tracking
{
public Player Client { get; private set; }
public EFClient Client { get; private set; }
public int Infringements { get; set; }
public Tracking(Player client)
public Tracking(EFClient client)
{
Client = client;
Infringements = 0;

View File

@ -1,7 +1,7 @@
using SharedLibraryCore.Helpers;
using IW4MAdmin.Plugins.Stats.Models;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using IW4MAdmin.Plugins.Stats.Models;
using System;
using System.Collections.Generic;
using System.Linq;
@ -20,7 +20,9 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
};
public ChangeTracking<EFACSnapshot> Tracker { get; private set; }
public const int QUEUE_COUNT = 10;
public List<EFClientKill> QueuedHits { get; set; }
int Kills;
int HitCount;
Dictionary<IW4Info.HitLocation, int> HitLocationCount;
@ -37,10 +39,14 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
Log = log;
HitLocationCount = new Dictionary<IW4Info.HitLocation, int>();
foreach (var loc in Enum.GetValues(typeof(IW4Info.HitLocation)))
{
HitLocationCount.Add((IW4Info.HitLocation)loc, 0);
}
ClientStats = clientStats;
Strain = new Strain();
Tracker = new ChangeTracking<EFACSnapshot>();
QueuedHits = new List<EFClientKill>();
}
/// <summary>
@ -56,10 +62,12 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
hit.HitLoc == IW4Info.HitLocation.none || hit.TimeOffset - LastOffset < 0 ||
// hack: prevents false positives
(LastWeapon != hit.Weapon && (hit.TimeOffset - LastOffset) == 50))
{
return new DetectionPenaltyResult()
{
ClientPenalty = Penalty.PenaltyType.Any,
};
}
DetectionPenaltyResult result = null;
LastWeapon = hit.Weapon;
@ -141,7 +149,6 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
ClientStats.MaxStrain = currentStrain;
}
// flag
if (currentStrain > Thresholds.MaxStrainFlag)
{
@ -201,7 +208,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
var sb = new StringBuilder();
foreach (var kvp in HitLocationCount)
{
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
}
Log.WriteDebug(sb.ToString());
result = new DetectionPenaltyResult()
@ -222,7 +232,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
var sb = new StringBuilder();
foreach (var kvp in HitLocationCount)
{
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
}
Log.WriteDebug(sb.ToString());
result = new DetectionPenaltyResult()
@ -251,7 +264,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}");
var sb = new StringBuilder();
foreach (var kvp in HitLocationCount)
{
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
}
Log.WriteDebug(sb.ToString());
result = new DetectionPenaltyResult()
@ -272,7 +288,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}");
var sb = new StringBuilder();
foreach (var kvp in HitLocationCount)
{
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
}
Log.WriteDebug(sb.ToString());
result = new DetectionPenaltyResult()
@ -306,15 +325,15 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestHits >= Thresholds.MediumSampleMinKills + 30)
{
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**");
Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**Chest Hits: {chestHits}");
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
var sb = new StringBuilder();
foreach (var kvp in HitLocationCount)
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
Log.WriteDebug(sb.ToString());
//Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**");
//Log.WriteDebug($"ClientId: {hit.AttackerId}");
//Log.WriteDebug($"**Chest Hits: {chestHits}");
//Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
//Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
//var sb = new StringBuilder();
//foreach (var kvp in HitLocationCount)
// sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
//Log.WriteDebug(sb.ToString());
result = new DetectionPenaltyResult()
{
@ -327,16 +346,15 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
}
else
{
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**");
Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**Chest Hits: {chestHits}");
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
var sb = new StringBuilder();
foreach (var kvp in HitLocationCount)
sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
Log.WriteDebug(sb.ToString());
// Log.WriteDebug($"ThresholdReached: {AboveThresholdCount}");
//Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**");
//Log.WriteDebug($"ClientId: {hit.AttackerId}");
//Log.WriteDebug($"**Chest Hits: {chestHits}");
//Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
//Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
//var sb = new StringBuilder();
//foreach (var kvp in HitLocationCount)
// sb.Append($"HitLocation: {kvp.Key} -> {kvp.Value}\r\n");
//Log.WriteDebug(sb.ToString());
result = new DetectionPenaltyResult()
{
@ -407,15 +425,15 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan)
{
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**");
Log.WriteDebug($"ClientId: {stats.ClientId}");
Log.WriteDebug($"**Total Chest Hits: {totalChestHits}");
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
var sb = new StringBuilder();
foreach (var location in stats.HitLocations)
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
Log.WriteDebug(sb.ToString());
//Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Ban**");
//Log.WriteDebug($"ClientId: {stats.ClientId}");
//Log.WriteDebug($"**Total Chest Hits: {totalChestHits}");
//Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
//Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
//var sb = new StringBuilder();
//foreach (var location in stats.HitLocations)
// sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
//Log.WriteDebug(sb.ToString());
return new DetectionPenaltyResult()
{
@ -428,15 +446,15 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
}
else
{
Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**");
Log.WriteDebug($"ClientId: {stats.ClientId}");
Log.WriteDebug($"**Total Chest Hits: {totalChestHits}");
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
var sb = new StringBuilder();
foreach (var location in stats.HitLocations)
sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
Log.WriteDebug(sb.ToString());
//Log.WriteDebug("**Maximum Lifetime Chest/Abdomen Ratio Reached For Flag**");
//Log.WriteDebug($"ClientId: {stats.ClientId}");
//Log.WriteDebug($"**Total Chest Hits: {totalChestHits}");
//Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
//Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
//var sb = new StringBuilder();
//foreach (var location in stats.HitLocations)
// sb.Append($"HitLocation: {location.Location} -> {location.HitCount}\r\n");
//Log.WriteDebug(sb.ToString());
return new DetectionPenaltyResult()
{

View File

@ -23,18 +23,15 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
double decayFactor = GetDecay(deltaTime);
CurrentStrain *= decayFactor;
#if DEBUG
Console.WriteLine($"Decay Factor = {decayFactor} ");
#endif
double[] distance = Helpers.Extensions.AngleStuff(newAngle, LastAngle);
LastDistance = distance[0] + distance[1];
#if DEBUG == true
Console.WriteLine($"Last Distance = {LastDistance}");
Console.WriteLine($"Angle Between = {LastDistance}");
Console.WriteLine($"Distance From Target = {killDistance}");
Console.WriteLine($"Time Offset = {deltaTime}");
Console.WriteLine($"Decay Factor = {decayFactor} ");
#endif
// this happens on first kill
if ((distance[0] == 0 && distance[1] == 0) ||
deltaTime == 0 ||

View File

@ -8,6 +8,7 @@ using SharedLibraryCore.Objects;
using IW4MAdmin.Plugins.Stats.Models;
using SharedLibraryCore.Database;
using System.Collections.Generic;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Plugins.Stats.Commands
{
@ -34,7 +35,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
join alias in db.Aliases
on client.CurrentAliasId equals alias.AliasId
where stats.ServerId == serverId
where client.Level != Player.Permission.Banned
where client.Level != EFClient.Permission.Banned
where client.LastConnection >= thirtyDaysAgo
orderby stats.Kills descending
select new
@ -55,7 +56,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
return mostPlayed;
}
public MostPlayed() : base("mostplayed", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_MOSTPLAYED_DESC"], "mp", Player.Permission.User, false) { }
public MostPlayed() : base("mostplayed", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_MOSTPLAYED_DESC"], "mp", EFClient.Permission.User, false) { }
public override async Task ExecuteAsync(GameEvent E)
{

View File

@ -8,12 +8,13 @@ using System.Text;
using System.Threading.Tasks;
using SharedLibraryCore.Database;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Plugins.Stats.Commands
{
public class ResetStats : Command
{
public ResetStats() : base("resetstats", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_RESET_DESC"], "rs", Player.Permission.User, false) { }
public ResetStats() : base("resetstats", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_RESET_DESC"], "rs", EFClient.Permission.User, false) { }
public override async Task ExecuteAsync(GameEvent E)
{

View File

@ -9,6 +9,7 @@ using SharedLibraryCore.Services;
using IW4MAdmin.Plugins.Stats.Models;
using SharedLibraryCore.Database;
using System.Collections.Generic;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Plugins.Stats.Commands
{
@ -33,7 +34,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
on client.CurrentAliasId equals alias.AliasId
where stats.ServerId == serverId
where stats.TimePlayed >= Plugin.Config.Configuration().TopPlayersMinPlayTime
where client.Level != Player.Permission.Banned
where client.Level != EFClient.Permission.Banned
where client.LastConnection >= fifteenDaysAgo
orderby stats.Performance descending
select new
@ -66,7 +67,7 @@ namespace IW4MAdmin.Plugins.Stats.Commands
return topStatsText;
}
public TopStats() : base("topstats", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_TOP_DESC"], "ts", Player.Permission.User, false) { }
public TopStats() : base("topstats", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_TOP_DESC"], "ts", EFClient.Permission.User, false) { }
public override async Task ExecuteAsync(GameEvent E)
{

View File

@ -10,12 +10,13 @@ using System.Threading.Tasks;
using SharedLibraryCore.Database;
using Microsoft.EntityFrameworkCore;
using IW4MAdmin.Plugins.Stats.Helpers;
using SharedLibraryCore.Database.Models;
namespace IW4MAdmin.Plugins.Stats.Commands
{
public class CViewStats : Command
{
public CViewStats() : base("stats", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_VIEW_DESC"], "xlrstats", Player.Permission.User, false, new CommandArgument[]
public CViewStats() : base("stats", Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_VIEW_DESC"], "xlrstats", EFClient.Permission.User, false, new CommandArgument[]
{
new CommandArgument()
{

View File

@ -1,23 +1,21 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IW4MAdmin.Plugins.Stats.Cheat;
using IW4MAdmin.Plugins.Stats.Models;
using IW4MAdmin.Plugins.Stats.Web.Dtos;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using SharedLibraryCore.Commands;
using IW4MAdmin.Plugins.Stats.Models;
using System.Text.RegularExpressions;
using IW4MAdmin.Plugins.Stats.Web.Dtos;
using SharedLibraryCore.Database;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Services;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace IW4MAdmin.Plugins.Stats.Helpers
{
@ -40,14 +38,17 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
OnProcessingSensitive = new SemaphoreSlim(1, 1);
}
public EFClientStatistics GetClientStats(int clientId, int serverId) => Servers[serverId].PlayerStats[clientId];
public EFClientStatistics GetClientStats(int clientId, int serverId)
{
return Servers[serverId].PlayerStats[clientId];
}
public static Expression<Func<EFRating, bool>> GetRankingFunc(int? serverId = null)
{
var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15);
return (r) => r.ServerId == serverId &&
r.When > fifteenDaysAgo &&
r.RatingHistory.Client.Level != Player.Permission.Banned &&
r.RatingHistory.Client.Level != EFClient.Permission.Banned &&
r.Newest &&
r.ActivityAmount >= Plugin.Config.Configuration().TopPlayersMinPlayTime;
}
@ -235,7 +236,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
/// </summary>
/// <param name="pl">Player to add/retrieve stats for</param>
/// <returns>EFClientStatistic of specified player</returns>
public async Task<EFClientStatistics> AddPlayer(Player pl)
public async Task<EFClientStatistics> AddPlayer(EFClient pl)
{
await OnProcessingSensitive.WaitAsync();
@ -373,7 +374,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
/// </summary>
/// <param name="pl">Disconnecting client</param>
/// <returns></returns>
public async Task RemovePlayer(Player pl)
public async Task RemovePlayer(EFClient pl)
{
Log.WriteInfo($"Removing {pl} from stats");
@ -432,7 +433,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
/// Process stats for kill event
/// </summary>
/// <returns></returns>
public async Task AddScriptHit(bool isDamage, DateTime time, Player attacker, Player victim, int serverId, string map, string hitLoc, string type,
public async Task AddScriptHit(bool isDamage, DateTime time, EFClient attacker, EFClient victim, int serverId, string map, string hitLoc, string type,
string damage, string weapon, string killOrigin, string deathOrigin, string viewAngles, string offset, string isKillstreakKill, string Ads,
string fraction, string visibilityPercentage, string snapAngles)
{
@ -548,7 +549,22 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
if (Plugin.Config.Configuration().EnableAntiCheat)
{
ApplyPenalty(clientDetection.ProcessHit(hit, isDamage), clientDetection, attacker, ctx);
if (clientDetection.QueuedHits.Count > Detection.QUEUE_COUNT)
{
while (clientDetection.QueuedHits.Count > 0)
{
clientDetection.QueuedHits = clientDetection.QueuedHits.OrderBy(_hits => _hits.TimeOffset).ToList();
var oldestHit = clientDetection.QueuedHits.First();
clientDetection.QueuedHits.RemoveAt(0);
ApplyPenalty(clientDetection.ProcessHit(oldestHit, isDamage), clientDetection, attacker, ctx);
}
}
else
{
clientDetection.QueuedHits.Add(hit);
}
ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), clientDetection, attacker, ctx);
}
@ -567,16 +583,16 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}
}
void ApplyPenalty(Cheat.DetectionPenaltyResult penalty, Cheat.Detection clientDetection, Player attacker, DatabaseContext ctx)
void ApplyPenalty(Cheat.DetectionPenaltyResult penalty, Cheat.Detection clientDetection, EFClient attacker, DatabaseContext ctx)
{
switch (penalty.ClientPenalty)
{
case Penalty.PenaltyType.Ban:
if (attacker.Level == Player.Permission.Banned)
if (attacker.Level == EFClient.Permission.Banned)
{
break;
}
attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new Player()
attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new EFClient()
{
ClientId = 1,
AdministeredPenalties = new List<EFPenalty>()
@ -588,7 +604,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
$"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}",
}
},
Level = Player.Permission.Console,
Level = EFClient.Permission.Console,
CurrentServer = attacker.CurrentServer
});
if (clientDetection.Tracker.HasChanges)
@ -597,7 +613,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}
break;
case Penalty.PenaltyType.Flag:
if (attacker.Level != Player.Permission.User)
if (attacker.Level != EFClient.Permission.User)
{
break;
}
@ -606,10 +622,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
$"{penalty.Type}-{(int)penalty.Location}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}" :
$"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}";
attacker.Flag(flagReason, new Player()
attacker.Flag(flagReason, new EFClient()
{
ClientId = 1,
Level = Player.Permission.Console,
Level = EFClient.Permission.Console,
CurrentServer = attacker.CurrentServer,
});
@ -677,7 +693,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}
}
public async Task AddStandardKill(Player attacker, Player victim)
public async Task AddStandardKill(EFClient attacker, EFClient victim)
{
int serverId = attacker.CurrentServer.GetHashCode();
@ -712,10 +728,14 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
// this happens when the round has changed
if (attackerStats.SessionScore == 0)
{
attackerStats.LastScore = 0;
}
if (victimStats.SessionScore == 0)
{
victimStats.LastScore = 0;
}
attackerStats.SessionScore = attacker.Score;
victimStats.SessionScore = victim.Score;
@ -780,7 +800,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
/// <param name="client">client to update</param>
/// <param name="clientStats">stats of client that is being updated</param>
/// <returns></returns>
private async Task UpdateStatHistory(Player client, EFClientStatistics clientStats)
private async Task UpdateStatHistory(EFClient client, EFClientStatistics clientStats)
{
int currentSessionTime = (int)(DateTime.UtcNow - client.LastConnection).TotalSeconds;
@ -1158,7 +1178,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
{
// the web users can have no account
if (clientId < 1)
{
return;
}
using (var ctx = new DatabaseContext(disableTracking: true))
{

View File

@ -1,6 +1,7 @@
using IW4MAdmin.Application;
using SharedLibraryCore;
using SharedLibraryCore.Commands;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
@ -25,7 +26,7 @@ namespace Tests
[Fact]
public void SetAdditionalPropertyShouldSucceed()
{
var client = new Player();
var client = new EFClient();
int newProp = 5;
client.SetAdditionalProperty("NewProp", newProp);
}
@ -33,7 +34,7 @@ namespace Tests
[Fact]
public void GetAdditionalPropertyShouldSucceed()
{
var client = new Player();
var client = new EFClient();
int newProp = 5;
client.SetAdditionalProperty("NewProp", newProp);
@ -48,11 +49,11 @@ namespace Tests
Thread.Sleep(100);
}
var client = Manager.Servers.First().GetPlayersAsList().FirstOrDefault();
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to warn");
var warnEvent = client.Warn("test warn", new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
var warnEvent = client.Warn("test warn", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
warnEvent.OnProcessed.Wait();
Assert.True((client.Warnings == 1 ||
@ -60,19 +61,19 @@ namespace Tests
Manager.GetPenaltyService().GetClientPenaltiesAsync(client.ClientId).Result.Count(p => p.Type == Penalty.PenaltyType.Warning) == 1,
"warning did not get applied");
warnEvent = client.Warn("test warn", new Player() { ClientId = 1, Level = Player.Permission.Banned, CurrentServer = client.CurrentServer });
warnEvent = client.Warn("test warn", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
warnEvent.OnProcessed.Wait();
Assert.True(warnEvent.FailReason == GameEvent.EventFailReason.Permission &&
client.Warnings == 1, "warning was applied without proper permissions");
// warn clear
var warnClearEvent = client.WarnClear(new Player { ClientId = 1, Level = Player.Permission.Banned, CurrentServer = client.CurrentServer });
var warnClearEvent = client.WarnClear(new EFClient { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
Assert.True(warnClearEvent.FailReason == GameEvent.EventFailReason.Permission &&
client.Warnings == 1, "warning was removed without proper permissions");
warnClearEvent = client.WarnClear(new Player { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
warnClearEvent = client.WarnClear(new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
Assert.True(!warnClearEvent.Failed && client.Warnings == 0, "warning was not cleared");
}
@ -85,11 +86,11 @@ namespace Tests
Thread.Sleep(100);
}
var client = Manager.Servers.First().GetPlayersAsList().FirstOrDefault();
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to report");
// fail
var player = new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer };
var player = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer };
player.SetAdditionalProperty("_reportCount", 3);
var reportEvent = client.Report("test report", player);
reportEvent.OnProcessed.Wait(TestTimeout);
@ -98,14 +99,14 @@ namespace Tests
client.CurrentServer.Reports.Count(r => r.Target.NetworkId == client.NetworkId) == 0, $"too many reports were applied [{reportEvent.FailReason.ToString()}]");
// succeed
reportEvent = client.Report("test report", new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
reportEvent = client.Report("test report", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
reportEvent.OnProcessed.Wait(TestTimeout);
Assert.True(!reportEvent.Failed &&
client.CurrentServer.Reports.Count(r => r.Target.NetworkId == client.NetworkId) == 1, $"report was not applied [{reportEvent.FailReason.ToString()}]");
// fail
reportEvent = client.Report("test report", new Player() { ClientId = 1, NetworkId = 1, Level = Player.Permission.Banned, CurrentServer = client.CurrentServer });
reportEvent = client.Report("test report", new EFClient() { ClientId = 1, NetworkId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
Assert.True(reportEvent.FailReason == GameEvent.EventFailReason.Permission &&
client.CurrentServer.Reports.Count(r => r.Target.NetworkId == client.NetworkId) == 1,
@ -118,7 +119,7 @@ namespace Tests
client.CurrentServer.Reports.Count(r => r.Target.NetworkId == client.NetworkId) == 1, $"report was applied to self");
// fail
reportEvent = client.Report("test report", new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
reportEvent = client.Report("test report", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
Assert.True(reportEvent.FailReason == GameEvent.EventFailReason.Exception &&
client.CurrentServer.Reports.Count(r => r.Target.NetworkId == client.NetworkId) == 1, $"duplicate report was applied");
@ -132,42 +133,42 @@ namespace Tests
Thread.Sleep(100);
}
var client = Manager.Servers.First().GetPlayersAsList().FirstOrDefault();
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to flag");
var flagEvent = client.Flag("test flag", new Player { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
var flagEvent = client.Flag("test flag", new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
flagEvent.OnProcessed.Wait();
// succeed
Assert.True(!flagEvent.Failed &&
client.Level == Player.Permission.Flagged, $"player is not flagged [{flagEvent.FailReason.ToString()}]");
client.Level == EFClient.Permission.Flagged, $"player is not flagged [{flagEvent.FailReason.ToString()}]");
Assert.False(client.ReceivedPenalties.FirstOrDefault(p => p.Offense == "test flag") == null, "flag was not applied");
flagEvent = client.Flag("test flag", new Player { ClientId = 1, Level = Player.Permission.Banned, CurrentServer = client.CurrentServer });
flagEvent = client.Flag("test flag", new EFClient { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
flagEvent.OnProcessed.Wait();
// fail
Assert.True(client.ReceivedPenalties.Count == 1, "flag was applied without permisions");
flagEvent = client.Flag("test flag", new Player { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
flagEvent = client.Flag("test flag", new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
flagEvent.OnProcessed.Wait();
// fail
Assert.True(client.ReceivedPenalties.Count == 1, "duplicate flag was applied");
var unflagEvent = client.Unflag("test unflag", new Player { ClientId = 1, Level = Player.Permission.Banned, CurrentServer = client.CurrentServer });
var unflagEvent = client.Unflag("test unflag", new EFClient { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
unflagEvent.OnProcessed.Wait();
// fail
Assert.False(client.Level == Player.Permission.User, "user was unflagged without permissions");
Assert.False(client.Level == EFClient.Permission.User, "user was unflagged without permissions");
unflagEvent = client.Unflag("test unflag", new Player { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
unflagEvent = client.Unflag("test unflag", new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
unflagEvent.OnProcessed.Wait();
// succeed
Assert.True(client.Level == Player.Permission.User, "user was not unflagged");
Assert.True(client.Level == EFClient.Permission.User, "user was not unflagged");
unflagEvent = client.Unflag("test unflag", new Player { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
unflagEvent = client.Unflag("test unflag", new EFClient { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
unflagEvent.OnProcessed.Wait();
// succeed
@ -182,18 +183,18 @@ namespace Tests
Thread.Sleep(100);
}
var client = Manager.Servers.First().GetPlayersAsList().FirstOrDefault();
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to kick");
var kickEvent = client.Kick("test kick", new Player() { ClientId = 1, Level = Player.Permission.Banned, CurrentServer = client.CurrentServer });
var kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Banned, CurrentServer = client.CurrentServer });
kickEvent.OnProcessed.Wait();
Assert.True(kickEvent.FailReason == GameEvent.EventFailReason.Permission, "client was kicked without permission");
kickEvent = client.Kick("test kick", new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer });
kickEvent = client.Kick("test kick", new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer });
kickEvent.OnProcessed.Wait();
Assert.True(Manager.Servers.First().GetPlayersAsList().FirstOrDefault(c => c.NetworkId == client.NetworkId) == null, "client was not kicked");
Assert.True(Manager.Servers.First().GetClientsAsList().FirstOrDefault(c => c.NetworkId == client.NetworkId) == null, "client was not kicked");
}
[Fact]
@ -204,13 +205,13 @@ namespace Tests
Thread.Sleep(100);
}
var client = Manager.Servers.First().GetPlayersAsList().FirstOrDefault();
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to tempban");
var tbCommand = new CTempBan();
tbCommand.ExecuteAsync(new GameEvent()
{
Origin = new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer },
Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer },
Target = client,
Data = "5days test tempban",
Type = GameEvent.EventType.Command,
@ -229,13 +230,13 @@ namespace Tests
Thread.Sleep(100);
}
var client = Manager.Servers.First().GetPlayersAsList().FirstOrDefault();
var client = Manager.Servers.First().GetClientsAsList().FirstOrDefault();
Assert.False(client == null, "no client found to ban");
var banCommand = new CBan();
banCommand.ExecuteAsync(new GameEvent()
{
Origin = new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer },
Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer },
Target = client,
Data = "test ban",
Type = GameEvent.EventType.Command,
@ -248,8 +249,8 @@ namespace Tests
var unbanCommand = new CUnban();
unbanCommand.ExecuteAsync(new GameEvent()
{
Origin = new Player() { ClientId = 1, Level = Player.Permission.Console, CurrentServer = client.CurrentServer },
Target = Manager.GetClientService().Find(c => c.NetworkId == client.NetworkId).Result.First().AsPlayer(),
Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer },
Target = Manager.GetClientService().Find(c => c.NetworkId == client.NetworkId).Result.First().AsEFClient(),
Data = "test unban",
Type = GameEvent.EventType.Command,
Owner = client.CurrentServer

View File

@ -1,5 +1,6 @@
using IW4MAdmin.Application;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Objects;
using System;
@ -53,7 +54,7 @@ namespace Tests
var e = new GameEvent()
{
Type = GameEvent.EventType.Join,
Origin = new Player()
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,
@ -78,7 +79,7 @@ namespace Tests
var e = new GameEvent()
{
Type = GameEvent.EventType.Disconnect,
Origin = new Player()
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,
@ -113,7 +114,7 @@ namespace Tests
var e = new GameEvent()
{
Type = GameEvent.EventType.Connect,
Origin = new Player()
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,
@ -134,7 +135,7 @@ namespace Tests
waiters.Dequeue().OnProcessed.Wait();
}
int actualClientNum = server.GetPlayersAsList().Count(p => p.State == Player.ClientState.Connected);
int actualClientNum = server.GetClientsAsList().Count(p => p.State == EFClient.ClientState.Connected);
Assert.True(actualClientNum == clientNum, $"client connected states don't match [{actualClientNum}:{clientNum}");
for (int i = clientIndexStart; i < clientNum + clientIndexStart; i++)
@ -142,7 +143,7 @@ namespace Tests
var e = new GameEvent()
{
Type = GameEvent.EventType.Disconnect,
Origin = new Player()
Origin = new EFClient()
{
Name = $"Player{i}",
NetworkId = i,

View File

@ -1,5 +1,6 @@
using IW4MAdmin.Application;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
using Xunit;
@ -21,7 +22,7 @@ namespace Tests
var e = new GameEvent()
{
Type = GameEvent.EventType.Connect,
Origin = new Player()
Origin = new EFClient()
{
Name = $"Player1",
NetworkId = 1,
@ -33,7 +34,7 @@ namespace Tests
Manager.GetEventHandler().AddEvent(e);
e.OnProcessed.Wait();
var client = Manager.GetServers()[0].Players[0];
var client = Manager.GetServers()[0].Clients[0];
e = new GameEvent()
{

View File

@ -13,12 +13,13 @@ using Microsoft.EntityFrameworkCore;
using System.Net;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
using static SharedLibraryCore.Database.Models.EFClient;
namespace IW4MAdmin.Plugins.Welcome
{
public class Plugin : IPlugin
{
String TimesConnected(Player P)
String TimesConnected(EFClient P)
{
int connection = P.Connections;
String Prefix = String.Empty;
@ -85,13 +86,13 @@ namespace IW4MAdmin.Plugins.Welcome
{
if (E.Type == GameEvent.EventType.Connect)
{
Player newPlayer = E.Origin;
if (newPlayer.Level >= Player.Permission.Trusted && !E.Origin.Masked)
EFClient newPlayer = E.Origin;
if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked)
E.Owner.Broadcast(await ProcessAnnouncement(Config.Configuration().PrivilegedAnnouncementMessage, newPlayer));
newPlayer.Tell(await ProcessAnnouncement(Config.Configuration().UserWelcomeMessage, newPlayer));
if (newPlayer.Level == Player.Permission.Flagged)
if (newPlayer.Level == Permission.Flagged)
{
string penaltyReason;
@ -111,7 +112,7 @@ namespace IW4MAdmin.Plugins.Welcome
}
}
private async Task<string> ProcessAnnouncement(string msg, Player joining)
private async Task<string> ProcessAnnouncement(string msg, EFClient joining)
{
msg = msg.Replace("{{ClientName}}", joining.Name);
msg = msg.Replace("{{ClientLevel}}", Utilities.ConvertLevelToColor(joining.Level, joining.ClientPermission.Name));

View File

@ -1,8 +1,8 @@
dotnet publish WebfrontCore/WebfrontCore.csproj -c Prerelease -o C:\Projects\IW4M-Admin\Publish\WindowsPrerelease
dotnet publish Application/Application.csproj -c Prerelease -o C:\Projects\IW4M-Admin\Publish\WindowsPrerelease
dotnet publish GameLogServer/GameLogServer.pyproj -c Release -o C:\Projects\IW4M-Admin\Publish\WindowsPrerelease\GameLogServer
dotnet publish WebfrontCore/WebfrontCore.csproj -c Prerelease -o X:\IW4MAdmin\Publish\WindowsPrerelease
dotnet publish Application/Application.csproj -c Prerelease -o X:\IW4MAdmin\Publish\WindowsPrerelease
dotnet publish GameLogServer/GameLogServer.pyproj -c Release -o X:\IW4MAdmin\Publish\WindowsPrerelease\GameLogServer
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat"
msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=FolderProfile /p:DeployOnBuild=true /p:PublishProfileRootFolder=C:\Projects\IW4M-Admin\GameLogServer\
msbuild DiscordWebhook/DiscordWebhook.pyproj /p:PublishProfile=FolderProfile /p:DeployOnBuild=true /p:PublishProfileRootFolder=C:\Projects\IW4M-Admin\DiscordWebhook\
cd "C:\Projects\IW4M-Admin\DEPLOY\"
msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=FolderProfile /p:DeployOnBuild=true /p:PublishProfileRootFolder=X:\IW4MAdmin\GameLogServer\
msbuild DiscordWebhook/DiscordWebhook.pyproj /p:PublishProfile=FolderProfile /p:DeployOnBuild=true /p:PublishProfileRootFolder=X:\IW4MAdmin\DiscordWebhook\
cd "X:\IW4MAdmin\DEPLOY\"
PowerShell ".\upload_prerelease.ps1"

View File

@ -1,8 +1,8 @@
dotnet publish WebfrontCore/WebfrontCore.csproj -c Release -o C:\Projects\IW4M-Admin\Publish\Windows
dotnet publish Application/Application.csproj -c Release -o C:\Projects\IW4M-Admin\Publish\Windows
dotnet publish GameLogServer/GameLogServer.pyproj -c Release -o C:\Projects\IW4M-Admin\Publish\Windows\GameLogServer
dotnet publish WebfrontCore/WebfrontCore.csproj -c Release -o X:\IW4MAdmin\Publish\Windows
dotnet publish Application/Application.csproj -c Release -o X:\IW4MAdmin\Publish\Windows
dotnet publish GameLogServer/GameLogServer.pyproj -c Release -o X:\IW4MAdmin\Publish\Windows\GameLogServer
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat"
msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=Stable /p:DeployOnBuild=true /p:PublishProfileRootFolder=C:\Projects\IW4M-Admin\GameLogServer\
msbuild DiscordWebhook/DiscordWebhook.pyproj /p:PublishProfile=Stable /p:DeployOnBuild=true /p:PublishProfileRootFolder=C:\Projects\IW4M-Admin\DiscordWebhook\
cd "C:\Projects\IW4M-Admin\DEPLOY\"
msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=Stable /p:DeployOnBuild=true /p:PublishProfileRootFolder=X:\IW4MAdmin\GameLogServer\
msbuild DiscordWebhook/DiscordWebhook.pyproj /p:PublishProfile=Stable /p:DeployOnBuild=true /p:PublishProfileRootFolder=X:\IW4MAdmin\DiscordWebhook\
cd "X:\IW4MAdmin\DEPLOY\"
PowerShell ".\upload_release.ps1"

View File

@ -1,7 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
namespace SharedLibraryCore
@ -14,7 +14,7 @@ namespace SharedLibraryCore
public abstract class Command
{
public Command(String commandName, String commandDescription, String commandAlias, Player.Permission requiredPermission, bool requiresTarget, CommandArgument[] param = null)
public Command(String commandName, String commandDescription, String commandAlias, EFClient.Permission requiredPermission, bool requiresTarget, CommandArgument[] param = null)
{
Name = commandName;
Description = commandDescription;
@ -33,7 +33,7 @@ namespace SharedLibraryCore
public String Alias { get; private set; }
public int RequiredArgumentCount => Arguments.Count(c => c.Required);
public bool RequiresTarget { get; private set; }
public Player.Permission Permission { get; private set; }
public EFClient.Permission Permission { get; private set; }
public CommandArgument[] Arguments { get; private set; }
}
}

View File

@ -1,4 +1,5 @@
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
@ -60,7 +61,7 @@ namespace SharedLibraryCore.Commands
var found = await Manager.GetClientService().Get(dbID);
if (found != null)
{
E.Target = found.AsPlayer();
E.Target = found;
E.Target.CurrentServer = E.Owner;
E.Data = String.Join(" ", Args.Skip(1));
}
@ -68,14 +69,14 @@ namespace SharedLibraryCore.Commands
else if (Args[0].Length < 3 && cNum > -1 && cNum < E.Owner.MaxClients) // user specifying target by client num
{
if (E.Owner.Players[cNum] != null)
if (E.Owner.Clients[cNum] != null)
{
E.Target = E.Owner.Players[cNum];
E.Target = E.Owner.Clients[cNum];
E.Data = String.Join(" ", Args.Skip(1));
}
}
List<Player> matchingPlayers;
List<EFClient> matchingPlayers;
if (E.Target == null && C.RequiresTarget) // Find active player including quotes (multiple words)
{

View File

@ -12,14 +12,13 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static SharedLibraryCore.RCon.StaticHelpers;
namespace SharedLibraryCore.Commands
{
public class CQuit : Command
{
public CQuit() :
base("quit", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_QUIT_DESC"], "q", Player.Permission.Owner, false)
base("quit", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_QUIT_DESC"], "q", EFClient.Permission.Owner, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@ -31,14 +30,14 @@ namespace SharedLibraryCore.Commands
public class COwner : Command
{
public COwner() :
base("owner", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_DESC"], "iamgod", Player.Permission.User, false)
base("owner", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_DESC"], "iamgod", EFClient.Permission.User, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
{
if ((await (E.Owner.Manager.GetClientService() as ClientService).GetOwners()).Count == 0)
{
E.Origin.Level = Player.Permission.Owner;
E.Origin.Level = EFClient.Permission.Owner;
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_SUCCESS"]);
// so setpassword/login works
E.Owner.Manager.GetPrivilegedClients().Add(E.Origin.ClientId, E.Origin);
@ -54,7 +53,7 @@ namespace SharedLibraryCore.Commands
public class CWarn : Command
{
public CWarn() :
base("warn", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARN_DESC"], "w", Player.Permission.Trusted, true, new CommandArgument[]
base("warn", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARN_DESC"], "w", EFClient.Permission.Trusted, true, new CommandArgument[]
{
new CommandArgument()
{
@ -83,7 +82,7 @@ namespace SharedLibraryCore.Commands
public class CWarnClear : Command
{
public CWarnClear() :
base("warnclear", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARNCLEAR_DESC"], "wc", Player.Permission.Trusted, true, new CommandArgument[]
base("warnclear", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARNCLEAR_DESC"], "wc", EFClient.Permission.Trusted, true, new CommandArgument[]
{
new CommandArgument()
{
@ -107,7 +106,7 @@ namespace SharedLibraryCore.Commands
public class CKick : Command
{
public CKick() :
base("kick", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_DESC"], "k", Player.Permission.Moderator, true, new CommandArgument[]
base("kick", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_DESC"], "k", EFClient.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
@ -133,7 +132,7 @@ namespace SharedLibraryCore.Commands
public class CSay : Command
{
public CSay() :
base("say", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SAY_DESC"], "s", Player.Permission.Moderator, false, new CommandArgument[]
base("say", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SAY_DESC"], "s", EFClient.Permission.Moderator, false, new CommandArgument[]
{
new CommandArgument()
{
@ -153,7 +152,7 @@ namespace SharedLibraryCore.Commands
public class CTempBan : Command
{
public CTempBan() :
base("tempban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_DESC"], "tb", Player.Permission.Administrator, true, new CommandArgument[]
base("tempban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_DESC"], "tb", EFClient.Permission.Administrator, true, new CommandArgument[]
{
new CommandArgument()
{
@ -201,7 +200,7 @@ namespace SharedLibraryCore.Commands
public class CBan : Command
{
public CBan() :
base("ban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_DESC"], "b", Player.Permission.SeniorAdmin, true, new CommandArgument[]
base("ban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_DESC"], "b", EFClient.Permission.SeniorAdmin, true, new CommandArgument[]
{
new CommandArgument()
{
@ -227,7 +226,7 @@ namespace SharedLibraryCore.Commands
public class CUnban : Command
{
public CUnban() :
base("unban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_DESC"], "ub", Player.Permission.SeniorAdmin, true, new CommandArgument[]
base("unban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_DESC"], "ub", EFClient.Permission.SeniorAdmin, true, new CommandArgument[]
{
new CommandArgument()
{
@ -260,7 +259,7 @@ namespace SharedLibraryCore.Commands
public class CWhoAmI : Command
{
public CWhoAmI() :
base("whoami", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WHO_DESC"], "who", Player.Permission.User, false)
base("whoami", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WHO_DESC"], "who", EFClient.Permission.User, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@ -275,27 +274,33 @@ namespace SharedLibraryCore.Commands
public class CList : Command
{
public CList() :
base("list", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_LIST_DESC"], "l", Player.Permission.Moderator, false)
base("list", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_LIST_DESC"], "l", EFClient.Permission.Moderator, false)
{ }
public override Task ExecuteAsync(GameEvent E)
{
StringBuilder playerList = new StringBuilder();
int count = 0;
for (int i = 0; i < E.Owner.Players.Count; i++)
for (int i = 0; i < E.Owner.Clients.Count; i++)
{
var P = E.Owner.Players[i];
var P = E.Owner.Clients[i];
if (P == null)
{
continue;
}
// todo: fix spacing
// todo: make this better :)
if (P.Masked)
playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(Player.Permission.User, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - Player.Permission.User.ToString().Length));
{
playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor( EFClient.Permission.User, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces( EFClient.Permission.SeniorAdmin.ToString().Length - EFClient.Permission.User.ToString().Length));
}
else
playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length));
{
playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces( EFClient.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length));
}
if (count == 2 || E.Owner.GetPlayersAsList().Count == 1)
if (count == 2 || E.Owner.GetClientsAsList().Count == 1)
{
E.Origin.Tell(playerList.ToString());
count = 0;
@ -320,7 +325,7 @@ namespace SharedLibraryCore.Commands
public class CHelp : Command
{
public CHelp() :
base("help", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_HELP_DESC"], "h", Player.Permission.User, false, new CommandArgument[]
base("help", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_HELP_DESC"], "h", EFClient.Permission.User, false, new CommandArgument[]
{
new CommandArgument()
{
@ -385,7 +390,7 @@ namespace SharedLibraryCore.Commands
public class CFastRestart : Command
{
public CFastRestart() :
base("fastrestart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FASTRESTART_DESC"], "fr", Player.Permission.Moderator, false)
base("fastrestart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FASTRESTART_DESC"], "fr", EFClient.Permission.Moderator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@ -401,7 +406,7 @@ namespace SharedLibraryCore.Commands
public class CMapRotate : Command
{
public CMapRotate() :
base("maprotate", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAPROTATE_DESC"], "mr", Player.Permission.Administrator, false)
base("maprotate", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAPROTATE_DESC"], "mr", EFClient.Permission.Administrator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@ -418,7 +423,7 @@ namespace SharedLibraryCore.Commands
public class CSetLevel : Command
{
public CSetLevel() :
base("setlevel", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_DESC"], "sl", Player.Permission.Moderator, true, new CommandArgument[]
base("setlevel", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_DESC"], "sl", EFClient.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
@ -441,17 +446,17 @@ namespace SharedLibraryCore.Commands
return;
}
Player.Permission oldPerm = E.Target.Level;
Player.Permission newPerm = Utilities.MatchPermission(E.Data);
EFClient.Permission oldPerm = E.Target.Level;
EFClient.Permission newPerm = Utilities.MatchPermission(E.Data);
if (newPerm == Player.Permission.Owner &&
if (newPerm == EFClient.Permission.Owner &&
!E.Owner.Manager.GetApplicationSettings().Configuration().EnableMultipleOwners)
{
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_OWNER"]);
return;
}
if (E.Origin.Level < Player.Permission.Owner &&
if (E.Origin.Level < EFClient.Permission.Owner &&
!E.Owner.Manager.GetApplicationSettings().Configuration().EnableSteppedHierarchy)
{
E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} ^5{E.Target.Name}");
@ -460,14 +465,14 @@ namespace SharedLibraryCore.Commands
if (newPerm >= E.Origin.Level)
{
if (E.Origin.Level < Player.Permission.Owner)
if (E.Origin.Level < EFClient.Permission.Owner)
{
E.Origin.Tell(string.Format(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_LEVELTOOHIGH"], E.Target.Name, (E.Origin.Level - 1).ToString()));
return;
}
}
else if (newPerm > Player.Permission.Banned)
else if (newPerm > EFClient.Permission.Banned)
{
var ActiveClient = E.Owner.Manager.GetActiveClients()
.FirstOrDefault(p => p.NetworkId == E.Target.NetworkId);
@ -530,7 +535,7 @@ namespace SharedLibraryCore.Commands
public class CUsage : Command
{
public CUsage() :
base("usage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_USAGE_DESC"], "us", Player.Permission.Moderator, false)
base("usage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_USAGE_DESC"], "us", EFClient.Permission.Moderator, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@ -543,7 +548,7 @@ namespace SharedLibraryCore.Commands
public class CUptime : Command
{
public CUptime() :
base("uptime", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UPTIME_DESC"], "up", Player.Permission.Moderator, false)
base("uptime", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UPTIME_DESC"], "up", EFClient.Permission.Moderator, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@ -558,13 +563,13 @@ namespace SharedLibraryCore.Commands
public class CListAdmins : Command
{
public CListAdmins() :
base("admins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ADMINS_DESC"], "a", Player.Permission.User, false)
base("admins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ADMINS_DESC"], "a", EFClient.Permission.User, false)
{ }
public static string OnlineAdmins(Server S)
{
var onlineAdmins = S.GetPlayersAsList()
.Where(p => p.Level > Player.Permission.Flagged)
var onlineAdmins = S.GetClientsAsList()
.Where(p => p.Level > EFClient.Permission.Flagged)
.Where(p => !p.Masked)
.Select(p => $"[^3{Utilities.ConvertLevelToColor(p.Level, p.ClientPermission.Name)}^7] {p.Name}");
@ -587,7 +592,7 @@ namespace SharedLibraryCore.Commands
public class CLoadMap : Command
{
public CLoadMap() :
base("map", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_DESC"], "m", Player.Permission.Administrator, false, new CommandArgument[]
base("map", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_DESC"], "m", EFClient.Permission.Administrator, false, new CommandArgument[]
{
new CommandArgument()
{
@ -620,7 +625,7 @@ namespace SharedLibraryCore.Commands
public class CFindPlayer : Command
{
public CFindPlayer() :
base("find", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FIND_DESC"], "f", Player.Permission.Administrator, false, new CommandArgument[]
base("find", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FIND_DESC"], "f", EFClient.Permission.Administrator, false, new CommandArgument[]
{
new CommandArgument()
{
@ -664,7 +669,7 @@ namespace SharedLibraryCore.Commands
public class CListRules : Command
{
public CListRules() :
base("rules", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RULES_DESC"], "r", Player.Permission.User, false)
base("rules", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RULES_DESC"], "r", EFClient.Permission.User, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@ -682,7 +687,9 @@ namespace SharedLibraryCore.Commands
var rules = new List<string>();
rules.AddRange(E.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules);
if (E.Owner.ServerConfig.Rules != null)
{
rules.AddRange(E.Owner.ServerConfig.Rules);
}
foreach (string r in rules)
{
@ -697,7 +704,7 @@ namespace SharedLibraryCore.Commands
public class CPrivateMessage : Command
{
public CPrivateMessage() :
base("privatemessage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PM_DESC"], "pm", Player.Permission.User, true, new CommandArgument[]
base("privatemessage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PM_DESC"], "pm", EFClient.Permission.User, true, new CommandArgument[]
{
new CommandArgument()
{
@ -724,7 +731,7 @@ namespace SharedLibraryCore.Commands
public class CFlag : Command
{
public CFlag() :
base("flag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_DESC"], "fp", Player.Permission.Moderator, true, new CommandArgument[]
base("flag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_DESC"], "fp", EFClient.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
@ -766,7 +773,7 @@ namespace SharedLibraryCore.Commands
public class CUnflag : Command
{
public CUnflag() :
base("unflag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_DESC"], "uf", Player.Permission.Moderator, true, new CommandArgument[]
base("unflag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_DESC"], "uf", EFClient.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
@ -804,7 +811,7 @@ namespace SharedLibraryCore.Commands
public class CReport : Command
{
public CReport() :
base("report", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_DESC"], "rep", Player.Permission.User, true, new CommandArgument[]
base("report", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_DESC"], "rep", EFClient.Permission.User, true, new CommandArgument[]
{
new CommandArgument()
{
@ -875,7 +882,7 @@ namespace SharedLibraryCore.Commands
public class CListReports : Command
{
public CListReports() :
base("reports", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORTS_DESC"], "reps", Player.Permission.Moderator, false, new CommandArgument[]
base("reports", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORTS_DESC"], "reps", EFClient.Permission.Moderator, false, new CommandArgument[]
{
new CommandArgument()
{
@ -912,7 +919,7 @@ namespace SharedLibraryCore.Commands
public class CMask : Command
{
public CMask() :
base("mask", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MASK_DESC"], "hide", Player.Permission.Moderator, false)
base("mask", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MASK_DESC"], "hide", EFClient.Permission.Moderator, false)
{ }
public override async Task ExecuteAsync(GameEvent E)
@ -935,7 +942,7 @@ namespace SharedLibraryCore.Commands
public class CListBanInfo : Command
{
public CListBanInfo() :
base("baninfo", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_DESC"], "bi", Player.Permission.Moderator, true, new CommandArgument[]
base("baninfo", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_DESC"], "bi", EFClient.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
@ -968,7 +975,7 @@ namespace SharedLibraryCore.Commands
public class CListAlias : Command
{
public CListAlias() :
base("alias", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ALIAS_DESC"], "known", Player.Permission.Moderator, true, new CommandArgument[]
base("alias", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ALIAS_DESC"], "known", EFClient.Permission.Moderator, true, new CommandArgument[]
{
new CommandArgument()
{
@ -1002,7 +1009,7 @@ namespace SharedLibraryCore.Commands
public class CExecuteRCON : Command
{
public CExecuteRCON() :
base("rcon", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RCON_DESC"], "rcon", Player.Permission.Owner, false, new CommandArgument[]
base("rcon", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RCON_DESC"], "rcon", EFClient.Permission.Owner, false, new CommandArgument[]
{
new CommandArgument()
{
@ -1016,16 +1023,21 @@ namespace SharedLibraryCore.Commands
{
var Response = await E.Owner.ExecuteCommandAsync(E.Data.Trim());
foreach (string S in Response)
{
E.Origin.Tell(S.StripColors());
}
if (Response.Length == 0)
{
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RCON_SUCCESS"]);
}
}
}
public class CPlugins : Command
{
public CPlugins() :
base("plugins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PLUGINS_DESC"], "p", Player.Permission.Administrator, false)
base("plugins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PLUGINS_DESC"], "p", EFClient.Permission.Administrator, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@ -1042,7 +1054,7 @@ namespace SharedLibraryCore.Commands
public class CIP : Command
{
public CIP() :
base("getexternalip", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_IP_DESC"], "ip", Player.Permission.User, false)
base("getexternalip", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_IP_DESC"], "ip", EFClient.Permission.User, false)
{ }
public override Task ExecuteAsync(GameEvent E)
@ -1054,7 +1066,7 @@ namespace SharedLibraryCore.Commands
public class CPruneAdmins : Command
{
public CPruneAdmins() : base("prune", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_DESC"], "pa", Player.Permission.Owner, false, new CommandArgument[]
public CPruneAdmins() : base("prune", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_DESC"], "pa", EFClient.Permission.Owner, false, new CommandArgument[]
{
new CommandArgument()
{
@ -1074,9 +1086,11 @@ namespace SharedLibraryCore.Commands
{
inactiveDays = Int32.Parse(E.Data);
if (inactiveDays < 1)
{
throw new FormatException();
}
}
}
catch (FormatException)
{
@ -1091,10 +1105,10 @@ namespace SharedLibraryCore.Commands
{
var lastActive = DateTime.UtcNow.AddDays(-inactiveDays);
inactiveUsers = await context.Clients
.Where(c => c.Level > Player.Permission.Flagged && c.Level <= Player.Permission.Moderator)
.Where(c => c.Level > EFClient.Permission.Flagged && c.Level <= EFClient.Permission.Moderator)
.Where(c => c.LastConnection < lastActive)
.ToListAsync();
inactiveUsers.ForEach(c => c.Level = Player.Permission.User);
inactiveUsers.ForEach(c => c.Level = EFClient.Permission.User);
await context.SaveChangesAsync();
}
E.Origin.Tell($"^5{inactiveUsers.Count} ^7{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_SUCCESS"]}");
@ -1103,7 +1117,7 @@ namespace SharedLibraryCore.Commands
public class CSetPassword : Command
{
public CSetPassword() : base("setpassword", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETPASSWORD_DESC"], "sp", Player.Permission.Moderator, false, new CommandArgument[]
public CSetPassword() : base("setpassword", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETPASSWORD_DESC"], "sp", EFClient.Permission.Moderator, false, new CommandArgument[]
{
new CommandArgument()
{
@ -1137,11 +1151,22 @@ namespace SharedLibraryCore.Commands
public class CKillServer : Command
{
public CKillServer() : base("killserver", "kill the game server", "kill", Player.Permission.Administrator, false)
public CKillServer() : base("killserver", "kill the game server", "kill", EFClient.Permission.Administrator, false)
{
}
public override async Task ExecuteAsync(GameEvent E)
{
if (E.Owner.ServerConfig.ManualLogPath != null)
{
using (var wc = new WebClient())
{
E.Owner.RestartRequested = true;
var response = await wc.DownloadStringTaskAsync(new Uri($"{E.Owner.ServerConfig.ManualLogPath}/restart"));
}
}
else
{
var gameserverProcesses = System.Diagnostics.Process.GetProcessesByName("iw4x");
@ -1203,11 +1228,12 @@ namespace SharedLibraryCore.Commands
return;
}
}
}
public class CPing : Command
{
public CPing() : base("ping", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_DESC"], "pi", Player.Permission.User, false, new CommandArgument[]
public CPing() : base("ping", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_DESC"], "pi", EFClient.Permission.User, false, new CommandArgument[]
{
new CommandArgument()
{
@ -1222,17 +1248,25 @@ namespace SharedLibraryCore.Commands
if (E.Message.IsBroadcastCommand())
{
if (E.Target == null)
{
E.Owner.Broadcast($"{E.Origin.Name}'s {Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_TARGET"]} ^5{E.Origin.Ping}^7ms");
}
else
{
E.Owner.Broadcast($"{E.Target.Name}'s {Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_TARGET"]} ^5{E.Target.Ping}^7ms");
}
}
else
{
if (E.Target == null)
{
E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_SELF"]} ^5{E.Origin.Ping}^7ms");
}
else
{
E.Origin.Tell($"{E.Target.Name}'s {Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_TARGET"]} ^5{E.Target.Ping}^7ms");
}
}
return Task.CompletedTask;
}
@ -1240,7 +1274,7 @@ namespace SharedLibraryCore.Commands
public class CSetGravatar : Command
{
public CSetGravatar() : base("setgravatar", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_DESC"], "sg", Player.Permission.User, false, new CommandArgument[]
public CSetGravatar() : base("setgravatar", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_DESC"], "sg", EFClient.Permission.User, false, new CommandArgument[]
{
new CommandArgument()
{
@ -1304,7 +1338,7 @@ namespace SharedLibraryCore.Commands
/// </summary>
public class CNextMap : Command
{
public CNextMap() : base("nextmap", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_DESC"], "nm", Player.Permission.User, false) { }
public CNextMap() : base("nextmap", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_DESC"], "nm", EFClient.Permission.User, false) { }
public static async Task<string> GetNextMap(Server s)
{
string mapRotation = (await s.GetDvarAsync<string>("sv_mapRotation")).Value.ToLower();

View File

@ -3,6 +3,7 @@ using SharedLibraryCore.Database.Models;
using System;
using System.Linq;
using System.Threading.Tasks;
using static SharedLibraryCore.Database.Models.EFClient;
namespace SharedLibraryCore.Database
{
@ -47,7 +48,7 @@ namespace SharedLibraryCore.Database
Connections = 0,
FirstConnection = DateTime.UtcNow,
LastConnection = DateTime.UtcNow,
Level = Objects.Player.Permission.Console,
Level = Permission.Console,
Masked = true,
NetworkId = 0,
AliasLinkId = 1,

View File

@ -1,17 +1,13 @@
using System;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Database.Models;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Data.Sqlite;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore.Metadata;
using Npgsql;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace SharedLibraryCore.Database
{
@ -26,6 +22,7 @@ namespace SharedLibraryCore.Database
static string _ConnectionString;
static string _provider;
private static string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins\";
public DatabaseContext(DbContextOptions<DatabaseContext> opt) : base(opt) { }
@ -57,7 +54,7 @@ namespace SharedLibraryCore.Database
$"{Path.DirectorySeparatorChar}{currentPath}" :
currentPath;
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = $"{currentPath}{Path.DirectorySeparatorChar}Database{Path.DirectorySeparatorChar}Database.db" };
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = Path.Join(currentPath, "Database", "Database.db") };
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);
@ -126,23 +123,11 @@ namespace SharedLibraryCore.Database
// adapted from
// https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/
IEnumerable<string> directoryFiles;
string pluginDir = Path.Join(Utilities.OperatingDirectory, "Plugins");
IEnumerable<string> directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll"));
string pluginDir = $@"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}Debug{Path.DirectorySeparatorChar}netcoreapp2.1{Path.DirectorySeparatorChar}Plugins";
if (!Directory.Exists(pluginDir))
{
pluginDir = Path.Join(Environment.CurrentDirectory, "Plugins");
if (!Directory.Exists(pluginDir))
{
pluginDir = Path.Join(Utilities.OperatingDirectory, "Plugins");
}
}
directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll"));
#if DEBUG == TRUE
foreach (string dllPath in Directory.GetFiles(@"C:\Projects\IW4M-Admin\Application\bin\Debug\netcoreapp2.1\Plugins").Where(f => f.EndsWith(".dll")))
foreach (string dllPath in Directory.GetFiles(_migrationPluginDirectory).Where(f => f.EndsWith(".dll")))
#else
foreach (string dllPath in directoryFiles)
#endif
@ -163,7 +148,9 @@ namespace SharedLibraryCore.Database
.Select(c => (IModelConfiguration)Activator.CreateInstance(c));
foreach (var configurable in configurations)
{
configurable.Configure(modelBuilder);
}
foreach (var type in library.ExportedTypes)
{

View File

@ -5,7 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace SharedLibraryCore.Database.Models
{
public class EFClient : SharedEntity
public partial class EFClient : SharedEntity
{
[Key]
public int ClientId { get; set; }
@ -25,7 +25,7 @@ namespace SharedLibraryCore.Database.Models
[ForeignKey("AliasLinkId")]
public virtual EFAliasLink AliasLink { get; set; }
[Required]
public Objects.Player.Permission Level { get; set; }
public Permission Level { get; set; }
[Required]
public int CurrentAliasId { get; set; }
@ -57,11 +57,5 @@ namespace SharedLibraryCore.Database.Models
public virtual ICollection<EFPenalty> ReceivedPenalties { get; set; }
public virtual ICollection<EFPenalty> AdministeredPenalties { get; set; }
public EFClient()
{
ReceivedPenalties = new List<EFPenalty>();
AdministeredPenalties = new List<EFPenalty>();
}
}
}

View File

@ -1,17 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static SharedLibraryCore.Objects.Player;
namespace SharedLibraryCore.Dtos
namespace SharedLibraryCore.Dtos
{
public class ClientInfo
{
public string Name { get; set; }
public int ClientId { get; set; }
public int LinkId { get; set; }
public Permission Level { get; set; }
public Database.Models.EFClient.Permission Level { get; set; }
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
namespace SharedLibraryCore
@ -50,11 +51,11 @@ namespace SharedLibraryCore
/// </summary>
Stop,
/// <summary>
/// a client was detecting as connecting via RCon
/// a client was detecting as connecting via log
/// </summary>
Connect,
/// <summary>
/// a client was detecting joining via log
/// a client was detecting joining by RCon
/// </summary>
Join,
/// <summary>
@ -170,8 +171,8 @@ namespace SharedLibraryCore
public EventType Type;
public string Data; // Data is usually the message sent by player
public string Message;
public Player Origin;
public Player Target;
public EFClient Origin;
public EFClient Target;
public Server Owner;
public Boolean Remote = false;
public object Extra { get; set; }
@ -200,7 +201,7 @@ namespace SharedLibraryCore
public static bool ShouldOriginEventBeDelayed(GameEvent queuedEvent)
{
return queuedEvent.Origin != null &&
(queuedEvent.Origin.State != Player.ClientState.Connected &&
(queuedEvent.Origin.State != EFClient.ClientState.Connected &&
// we want to allow join and quit events
queuedEvent.Type != EventType.Connect &&
queuedEvent.Type != EventType.Join &&
@ -219,7 +220,7 @@ namespace SharedLibraryCore
public static bool ShouldTargetEventBeDelayed(GameEvent queuedEvent)
{
return (queuedEvent.Target != null && queuedEvent.Target.ClientNumber != -1) &&
(queuedEvent.Target.State != Player.ClientState.Connected &&
(queuedEvent.Target.State != EFClient.ClientState.Connected &&
queuedEvent.Target.NetworkId != 0 &&
queuedEvent.Origin?.ClientId != 1);
}

View File

@ -1,4 +1,5 @@
using SharedLibraryCore.Objects;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
using System.Text;
@ -12,16 +13,16 @@ namespace SharedLibraryCore.Interfaces
/// occurs in the log, as no IP is given
/// </summary>
/// <param name="client">client that has joined from the log</param>
void RequestClientAuthentication(Player client);
void RequestClientAuthentication(EFClient client);
/// <summary>
/// get all clients that have been authenticated by the status poll
/// </summary>
/// <returns>list of all authenticated clients</returns>
IList<Player> GetAuthenticatedClients();
IList<EFClient> GetAuthenticatedClients();
/// <summary>
/// authenticate a list of clients from status poll
/// </summary>
/// <param name="clients">list of clients to authenticate</param>
void AuthenticateClients(IList<Player> clients);
void AuthenticateClients(IList<EFClient> clients);
}
}

View File

@ -5,6 +5,7 @@ using SharedLibraryCore.Objects;
using SharedLibraryCore.Services;
using SharedLibraryCore.Configuration;
using System.Reflection;
using SharedLibraryCore.Database.Models;
namespace SharedLibraryCore.Interfaces
{
@ -17,12 +18,12 @@ namespace SharedLibraryCore.Interfaces
IList<Server> GetServers();
IList<Command> GetCommands();
IList<Helpers.MessageToken> GetMessageTokens();
IList<Player> GetActiveClients();
IList<EFClient> GetActiveClients();
IConfigurationHandler<ApplicationConfiguration> GetApplicationSettings();
ClientService GetClientService();
AliasService GetAliasService();
PenaltyService GetPenaltyService();
IDictionary<int, Player> GetPrivilegedClients();
IDictionary<int, EFClient> GetPrivilegedClients();
/// <summary>
/// Get the event handlers
/// </summary>

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
using SharedLibraryCore.RCon;
@ -10,7 +11,7 @@ namespace SharedLibraryCore.Interfaces
Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName);
Task<bool> SetDvarAsync(Connection connection, string dvarName, object dvarValue);
Task<string[]> ExecuteCommandAsync(Connection connection, string command);
Task<List<Player>> GetStatusAsync(Connection connection);
Task<List<EFClient>> GetStatusAsync(Connection connection);
CommandPrefix GetCommandPrefixes();
}
}

View File

@ -1,13 +1,14 @@
using System;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Objects;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace SharedLibraryCore.Objects
namespace SharedLibraryCore.Database.Models
{
public class Player : Database.Models.EFClient
public partial class EFClient
{
public enum ClientState
{
@ -76,7 +77,7 @@ namespace SharedLibraryCore.Objects
Console = 8
}
public Player()
public EFClient()
{
ConnectionTime = DateTime.UtcNow;
ClientNumber = -1;
@ -87,7 +88,10 @@ namespace SharedLibraryCore.Objects
};
}
public override string ToString() => $"{Name}::{NetworkId}";
public override string ToString()
{
return $"{Name}::{NetworkId}";
}
/// <summary>
/// send a message directly to the connected client
@ -113,7 +117,7 @@ namespace SharedLibraryCore.Objects
/// </summary>
/// <param name="warnReason">reason for warn</param>
/// <param name="sender">client performing the warn</param>
public GameEvent Warn(String warnReason, Player sender)
public GameEvent Warn(String warnReason, EFClient sender)
{
var e = new GameEvent()
{
@ -146,7 +150,7 @@ namespace SharedLibraryCore.Objects
/// </summary>
/// <param name="sender">client performing the warn clear</param>
/// <returns></returns>
public GameEvent WarnClear(Player sender)
public GameEvent WarnClear(EFClient sender)
{
var e = new GameEvent()
{
@ -175,7 +179,7 @@ namespace SharedLibraryCore.Objects
/// <param name="reportReason">reason for the report</param>
/// <param name="sender">client performing the report</param>
/// <returns></returns>
public GameEvent Report(string reportReason, Player sender)
public GameEvent Report(string reportReason, EFClient sender)
{
var e = new GameEvent()
{
@ -221,7 +225,7 @@ namespace SharedLibraryCore.Objects
/// <param name="flagReason">reason for flagging</param>
/// <param name="sender">client performing the flag</param>
/// <returns>game event for the flag</returns>
public GameEvent Flag(string flagReason, Player sender)
public GameEvent Flag(string flagReason, EFClient sender)
{
var e = new GameEvent()
{
@ -238,14 +242,14 @@ namespace SharedLibraryCore.Objects
e.FailReason = GameEvent.EventFailReason.Permission;
}
else if (this.Level == Player.Permission.Flagged)
else if (this.Level == Permission.Flagged)
{
e.FailReason = GameEvent.EventFailReason.Invalid;
}
else
{
this.Level = Player.Permission.Flagged;
this.Level = Permission.Flagged;
}
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
@ -258,7 +262,7 @@ namespace SharedLibraryCore.Objects
/// <param name="unflagReason">reason to unflag a player for</param>
/// <param name="sender">client performing the unflag</param>
/// <returns>game event for the un flug</returns>
public GameEvent Unflag(string unflagReason, Player sender)
public GameEvent Unflag(string unflagReason, EFClient sender)
{
var e = new GameEvent()
{
@ -275,7 +279,7 @@ namespace SharedLibraryCore.Objects
e.FailReason = GameEvent.EventFailReason.Permission;
}
else if (this.Level != Player.Permission.Flagged)
else if (this.Level != EFClient.Permission.Flagged)
{
e.FailReason = GameEvent.EventFailReason.Invalid;
}
@ -294,7 +298,7 @@ namespace SharedLibraryCore.Objects
/// </summary>
/// <param name="kickReason">reason to kick for</param>
/// <param name="sender">client performing the kick</param>
public GameEvent Kick(String kickReason, Player sender)
public GameEvent Kick(String kickReason, EFClient sender)
{
var e = new GameEvent()
{
@ -322,7 +326,7 @@ namespace SharedLibraryCore.Objects
/// <param name="tempbanReason">reason for the temp ban</param>
/// <param name="banLength">how long the temp ban lasts</param>
/// <param name="sender">client performing the tempban</param>
public GameEvent TempBan(String tempbanReason, TimeSpan banLength, Player sender)
public GameEvent TempBan(String tempbanReason, TimeSpan banLength, EFClient sender)
{
var e = new GameEvent()
{
@ -350,7 +354,7 @@ namespace SharedLibraryCore.Objects
/// </summary>
/// <param name="banReason">reason for the ban</param>
/// <param name="sender">client performing the ban</param>
public GameEvent Ban(String banReason, Player sender)
public GameEvent Ban(String banReason, EFClient sender)
{
var e = new GameEvent()
{
@ -378,7 +382,7 @@ namespace SharedLibraryCore.Objects
/// <param name="unbanReason">reason for the unban</param>
/// <param name="sender">client performing the unban</param>
/// <returns></returns>
public GameEvent Unban(String unbanReason, Player sender)
public GameEvent Unban(String unbanReason, EFClient sender)
{
var e = new GameEvent()
{
@ -400,10 +404,119 @@ namespace SharedLibraryCore.Objects
return e;
}
/// <summary>
/// Handles any client related logic on connection
/// </summary>
public void OnConnect()
{
var loc = Utilities.CurrentLocalization.LocalizationIndex;
//#if !DEBUG
if (Name.Length < 3)
{
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short");
Kick(loc["SERVER_KICK_MINNAME"], Utilities.IW4MAdminClient(CurrentServer));
return;
}
if (Name == "Unknown Soldier" ||
Name == "UnknownSoldier" ||
Name == "CHEATER")
{
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is generic");
Kick(loc["SERVER_KICK_GENERICNAME"], Utilities.IW4MAdminClient(CurrentServer));
return;
}
if (Name.Where(c => char.IsControl(c)).Count() > 0)
{
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name contains control characters");
Kick(loc["SERVER_KICK_CONTROLCHARS"], Utilities.IW4MAdminClient(CurrentServer));
return;
}
// reserved slots stuff
if ((CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged()) - CurrentServer.MaxClients) < CurrentServer.ServerConfig.ReservedSlotNumber &&
!this.IsPrivileged())
{
CurrentServer.Logger.WriteDebug($"Kicking {this} their spot is reserved");
Kick(loc["SERVER_KICK_SLOT_IS_RESERVED"], Utilities.IW4MAdminClient(CurrentServer));
return;
}
LastConnection = DateTime.UtcNow;
Connections += 1;
//#endif
}
public async Task OnJoin(int ipAddress)
{
// todo: fix this up
CurrentAlias.IPAddress = IPAddress;
await CurrentServer.Manager.GetClientService().Update(this);
var loc = Utilities.CurrentLocalization.LocalizationIndex;
var activePenalties = await CurrentServer.Manager.GetPenaltyService().GetActivePenaltiesAsync(AliasLinkId, ipAddress);
var currentBan = activePenalties.FirstOrDefault(p => p.Type == Penalty.PenaltyType.Ban || p.Type == Penalty.PenaltyType.TempBan);
var currentAutoFlag = activePenalties.Where(p => p.Type == Penalty.PenaltyType.Flag && p.PunisherId == 1)
.Where(p => p.Active)
.OrderByDescending(p => p.When)
.FirstOrDefault();
// remove their auto flag status after a week
if (Level == Permission.Flagged &&
currentAutoFlag != null &&
(DateTime.UtcNow - currentAutoFlag.When).TotalDays > 7)
{
Level = Permission.User;
}
if (currentBan != null)
{
CurrentServer.Logger.WriteInfo($"Banned client {this} trying to join...");
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
// reban the "evading" guid
if (Level != Permission.Banned &&
currentBan.Type == Penalty.PenaltyType.Ban)
{
// hack: re apply the automated offense to the reban
if (currentBan.AutomatedOffense != null)
{
autoKickClient.AdministeredPenalties.Add(new EFPenalty()
{
AutomatedOffense = currentBan.AutomatedOffense
});
}
Ban($"{currentBan.Offense}", autoKickClient);
}
// the player is permanently banned
else if (currentBan.Type == Penalty.PenaltyType.Ban)
{
Kick($"{loc["SERVER_BAN_PREV"]} {currentBan.Offense} ({loc["SERVER_BAN_APPEAL"]} {CurrentServer.Website})", autoKickClient);
}
else
{
//string formattedKick = String.Format(
// RconParser.GetCommandPrefixes().Kick,
// polledPlayer.ClientNumber,
// $"{loc["SERVER_TB_REMAIN"]} ({(currentBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})");
//await this.ExecuteCommandAsync(formattedKick);
}
}
}
[NotMapped]
Dictionary<string, object> _additionalProperties;
public T GetAdditionalProperty<T>(string name) => _additionalProperties.ContainsKey(name) ? (T)_additionalProperties[name] : default(T);
public T GetAdditionalProperty<T>(string name)
{
return _additionalProperties.ContainsKey(name) ? (T)_additionalProperties[name] : default(T);
}
public void SetAdditionalProperty(string name, object value)
{
@ -433,18 +546,18 @@ namespace SharedLibraryCore.Objects
public int Score { get; set; }
[NotMapped]
public bool IsBot { get; set; }
private int _ipaddress;
public override int IPAddress
{
get { return _ipaddress; }
set { _ipaddress = value; }
}
private string _name;
public override string Name
{
get { return _name; }
set { _name = value; }
}
//private int _ipaddress;
//public override int IPAddress
//{
// get => _ipaddress;
// set => _ipaddress = value;
//}
//private string _name;
//public override string Name
//{
// get => _name;
// set => _name = value;
//}
[NotMapped]
public ClientState State { get; set; }
[NotMapped]
@ -460,9 +573,12 @@ namespace SharedLibraryCore.Objects
public override bool Equals(object obj)
{
return ((Player)obj).NetworkId == this.NetworkId;
return ((EFClient)obj).NetworkId == this.NetworkId;
}
public override int GetHashCode() => (int)NetworkId;
public override int GetHashCode()
{
return (int)NetworkId;
}
}
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using static SharedLibraryCore.Objects.Player;
using static SharedLibraryCore.Database.Models.EFClient;
namespace SharedLibraryCore.Objects
{

View File

@ -1,4 +1,5 @@
using System;
using SharedLibraryCore.Database.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -8,8 +9,8 @@ namespace SharedLibraryCore.Objects
{
public class Report
{
public Player Target { get; set; }
public Player Origin { get; set; }
public String Reason { get; set; }
public EFClient Target { get; set; }
public EFClient Origin { get; set; }
public string Reason { get; set; }
}
}

View File

@ -137,12 +137,9 @@ namespace SharedLibraryCore.RCon
throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_NOTSET"]);
}
Log.WriteInfo(responseString);
string[] splitResponse = responseString.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Trim()).ToArray();
return splitResponse;
}
private async Task<byte[]> SendPayloadAsync(byte[] payload, bool waitForResponse)

View File

@ -1,4 +1,5 @@
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
@ -71,7 +72,7 @@ namespace SharedLibraryCore
cfg.AllowClr(new[]
{
typeof(System.Net.Http.HttpClient).Assembly,
typeof(Objects.Player).Assembly,
typeof(EFClient).Assembly,
})
.CatchClrExceptions());

View File

@ -9,6 +9,7 @@ using SharedLibraryCore.Objects;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Database.Models;
namespace SharedLibraryCore
{
@ -37,9 +38,9 @@ namespace SharedLibraryCore
ServerConfig = config;
RemoteConnection = new RCon.Connection(IP, Port, Password, Logger);
Players = new List<Player>(new Player[18]);
Clients = new List<EFClient>(new EFClient[18]);
Reports = new List<Report>();
PlayerHistory = new Queue<PlayerHistory>();
ClientHistory = new Queue<PlayerHistory>();
ChatHistory = new List<ChatInfo>();
NextMessage = 0;
CustomSayEnabled = Manager.GetApplicationSettings().Configuration().EnableCustomSayName;
@ -61,32 +62,32 @@ namespace SharedLibraryCore
}
//Returns list of all current players
public List<Player> GetPlayersAsList()
public List<EFClient> GetClientsAsList()
{
return Players.FindAll(x => x != null);
return Clients.FindAll(x => x != null);
}
/// <summary>
/// Add a player to the server's player list
/// </summary>
/// <param name="P">Player pulled from memory reading</param>
/// <param name="P">EFClient pulled from memory reading</param>
/// <returns>True if player added sucessfully, false otherwise</returns>
abstract public Task<bool> AddPlayer(Player P);
abstract public Task OnClientConnected(EFClient P);
/// <summary>
/// Remove player by client number
/// </summary>
/// <param name="cNum">Client ID of player to be removed</param>
/// <returns>true if removal succeded, false otherwise</returns>
abstract public Task RemovePlayer(int cNum);
abstract public Task RemoveClient(int cNum);
/// <summary>
/// Get a player by name
/// </summary>
/// <param name="pName">Player name to search for</param>
/// <param name="pName">EFClient name to search for</param>
/// <returns>Matching player if found</returns>
public List<Player> GetClientByName(String pName)
public List<EFClient> GetClientByName(String pName)
{
string[] QuoteSplit = pName.Split('"');
bool literal = false;
@ -96,9 +97,9 @@ namespace SharedLibraryCore
literal = true;
}
if (literal)
return Players.Where(p => p != null && p.Name.ToLower().Equals(pName.ToLower())).ToList();
return Clients.Where(p => p != null && p.Name.ToLower().Equals(pName.ToLower())).ToList();
return Players.Where(p => p != null && p.Name.ToLower().Contains(pName.ToLower())).ToList();
return Clients.Where(p => p != null && p.Name.ToLower().Contains(pName.ToLower())).ToList();
}
virtual public Task<bool> ProcessUpdatesAsync(CancellationToken cts) => (Task<bool>)Task.CompletedTask;
@ -115,7 +116,7 @@ namespace SharedLibraryCore
/// Send a message to all players
/// </summary>
/// <param name="message">Message to be sent to all players</param>
public GameEvent Broadcast(string message, Player sender = null)
public GameEvent Broadcast(string message, EFClient sender = null)
{
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Say, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message}");
@ -139,19 +140,19 @@ namespace SharedLibraryCore
/// Send a message to a particular players
/// </summary>
/// <param name="Message">Message to send</param>
/// <param name="Target">Player to send message to</param>
protected async Task Tell(String Message, Player Target)
/// <param name="Target">EFClient to send message to</param>
protected async Task Tell(String Message, EFClient Target)
{
#if !DEBUG
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Tell, Target.ClientNumber, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{Message}");
if (Target.ClientNumber > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console)
if (Target.ClientNumber > -1 && Message.Length > 0 && Target.Level != EFClient.Permission.Console)
await this.ExecuteCommandAsync(formattedMessage);
#else
Logger.WriteVerbose($"{Target.ClientNumber}->{Message.StripColors()}");
await Task.CompletedTask;
#endif
if (Target.Level == Player.Permission.Console)
if (Target.Level == EFClient.Permission.Console)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(Message.StripColors());
@ -179,7 +180,7 @@ namespace SharedLibraryCore
/// <param name="message">Message to send out</param>
public void ToAdmins(String message)
{
foreach (var client in GetPlayersAsList().Where(c => c.Level > Player.Permission.Flagged))
foreach (var client in GetClientsAsList().Where(c => c.Level > EFClient.Permission.Flagged))
{
client.Tell(message);
}
@ -189,15 +190,15 @@ namespace SharedLibraryCore
/// Kick a player from the server
/// </summary>
/// <param name="Reason">Reason for kicking</param>
/// <param name="Target">Player to kick</param>
abstract protected Task Kick(String Reason, Player Target, Player Origin);
/// <param name="Target">EFClient to kick</param>
abstract protected Task Kick(String Reason, EFClient Target, EFClient Origin);
/// <summary>
/// Temporarily ban a player ( default 1 hour ) from the server
/// </summary>
/// <param name="Reason">Reason for banning the player</param>
/// <param name="Target">The player to ban</param>
abstract protected Task TempBan(String Reason, TimeSpan length, Player Target, Player Origin);
abstract protected Task TempBan(String Reason, TimeSpan length, EFClient Target, EFClient Origin);
/// <summary>
/// Perm ban a player from the server
@ -205,9 +206,9 @@ namespace SharedLibraryCore
/// <param name="Reason">The reason for the ban</param>
/// <param name="Target">The person to ban</param>
/// <param name="Origin">The person who banned the target</param>
abstract protected Task Ban(String Reason, Player Target, Player Origin);
abstract protected Task Ban(String Reason, EFClient Target, EFClient Origin);
abstract protected Task Warn(String Reason, Player Target, Player Origin);
abstract protected Task Warn(String Reason, EFClient Target, EFClient Origin);
/// <summary>
/// Unban a player by npID / GUID
@ -215,7 +216,7 @@ namespace SharedLibraryCore
/// <param name="npID">npID of the player</param>
/// <param name="Target">I don't remember what this is for</param>
/// <returns></returns>
abstract public Task Unban(string reason, Player Target, Player Origin);
abstract public Task Unban(string reason, EFClient Target, EFClient Origin);
/// <summary>
/// Change the current searver map
@ -284,7 +285,7 @@ namespace SharedLibraryCore
public List<Map> Maps { get; protected set; }
public List<Report> Reports { get; set; }
public List<ChatInfo> ChatHistory { get; protected set; }
public Queue<PlayerHistory> PlayerHistory { get; private set; }
public Queue<PlayerHistory> ClientHistory { get; private set; }
public Game GameName { get; protected set; }
// Info
@ -296,11 +297,11 @@ namespace SharedLibraryCore
{
get
{
return Players.Where(p => p != null).Count();
return Clients.Where(p => p != null).Count();
}
}
public int MaxClients { get; protected set; }
public List<Player> Players { get; protected set; }
public List<EFClient> Clients { get; protected set; }
public string Password { get; private set; }
public bool Throttled { get; protected set; }
public bool CustomCallback { get; protected set; }
@ -309,6 +310,7 @@ namespace SharedLibraryCore
public IRConParser RconParser { get; protected set; }
public IEventParser EventParser { get; set; }
public string LogPath { get; protected set; }
public bool RestartRequested { get; set; }
// Internal
protected string IP;

View File

@ -10,6 +10,7 @@ using System.Linq.Expressions;
using SharedLibraryCore.Objects;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Dtos;
using static SharedLibraryCore.Database.Models.EFClient;
namespace SharedLibraryCore.Services
{
@ -60,8 +61,8 @@ namespace SharedLibraryCore.Services
Level = hasExistingAlias ?
(await context.Clients.Where(c => c.AliasLinkId == existingAlias.LinkId)
.OrderByDescending(c => c.Level)
.FirstOrDefaultAsync())?.Level ?? Player.Permission.User :
Player.Permission.User,
.FirstOrDefaultAsync())?.Level ?? Permission.User :
Permission.User,
FirstConnection = DateTime.UtcNow,
Connections = 1,
LastConnection = DateTime.UtcNow,
@ -228,7 +229,7 @@ namespace SharedLibraryCore.Services
{
using (var context = new DatabaseContext())
return await context.Clients
.Where(c => c.Level == Player.Permission.Owner)
.Where(c => c.Level == Permission.Owner)
.ToListAsync();
}
@ -237,7 +238,7 @@ namespace SharedLibraryCore.Services
using (var context = new DatabaseContext(disableTracking: true))
{
var iqClients = from client in context.Clients
where client.Level >= Player.Permission.Trusted
where client.Level >= Permission.Trusted
where client.Active
select new ClientInfo()
{

View File

@ -8,6 +8,7 @@ using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Objects;
using static SharedLibraryCore.Database.Models.EFClient;
namespace SharedLibraryCore.Services
{
@ -35,7 +36,7 @@ namespace SharedLibraryCore.Services
{
await context.Clients
.Where(c => c.AliasLinkId == addedEntity.LinkId)
.ForEachAsync(c => c.Level = Objects.Player.Permission.Banned);
.ForEachAsync(c => c.Level = Permission.Banned);
}
// make flags propogate to all aliases
@ -43,7 +44,7 @@ namespace SharedLibraryCore.Services
{
await context.Clients
.Where(c => c.AliasLinkId == addedEntity.LinkId)
.ForEachAsync(c => c.Level = Objects.Player.Permission.Flagged);
.ForEachAsync(c => c.Level = Permission.Flagged);
}
context.Penalties.Add(addedEntity);
@ -221,10 +222,12 @@ namespace SharedLibraryCore.Services
var iqPenalties = context.Penalties
.Where(p => p.LinkId == linkId ||
p.Link.Children.Any(a => a.IPAddress == ip))
.Where(p => p.Type == Penalty.PenaltyType.TempBan ||
p.Type == Penalty.PenaltyType.Ban ||
p.Type == Penalty.PenaltyType.Flag)
.Where(p => p.Active)
.Where(p => p.Expires == null || p.Expires > now);
#if DEBUG == true
var penaltiesSql = iqPenalties.ToSql();
#endif
@ -256,7 +259,7 @@ namespace SharedLibraryCore.Services
{
await internalContext.Clients
.Where(c => c.AliasLinkId == p.LinkId)
.ForEachAsync(c => c.Level = Player.Permission.User);
.ForEachAsync(c => c.Level = EFClient.Permission.User);
await internalContext.SaveChangesAsync();
}
}

View File

@ -15,6 +15,7 @@ using System.Diagnostics;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using SharedLibraryCore.Database.Models;
namespace SharedLibraryCore
{
@ -27,12 +28,13 @@ namespace SharedLibraryCore
#endif
public static Encoding EncodingType;
public static Localization.Layout CurrentLocalization = new Localization.Layout(new Dictionary<string, string>());
public static Player IW4MAdminClient(Server server = null) => new Player()
public static EFClient IW4MAdminClient(Server server = null) => new EFClient()
{
ClientId = 1,
State = Player.ClientState.Connected,
Level = Player.Permission.Console,
CurrentServer = server
State = EFClient.ClientState.Connected,
Level = EFClient.Permission.Console,
CurrentServer = server,
Name = "IW4MAdmin"
};
public static string HttpRequest(string location, string header, string headerValue)
@ -98,16 +100,16 @@ namespace SharedLibraryCore
return sb.ToString();
}
public static Player.Permission MatchPermission(String str)
public static EFClient.Permission MatchPermission(String str)
{
String lookingFor = str.ToLower();
for (Player.Permission Perm = Player.Permission.User; Perm < Player.Permission.Console; Perm++)
for (EFClient.Permission Perm = EFClient.Permission.User; Perm < EFClient.Permission.Console; Perm++)
if (lookingFor.Contains(Perm.ToString().ToLower())
|| lookingFor.Contains(CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{Perm.ToString().ToUpper()}"].ToLower()))
return Perm;
return Player.Permission.Banned;
return EFClient.Permission.Banned;
}
/// <summary>
@ -131,25 +133,25 @@ namespace SharedLibraryCore
/// </summary>
/// <param name="level">Specified player level</param>
/// <returns></returns>
public static String ConvertLevelToColor(Player.Permission level, string localizedLevel)
public static String ConvertLevelToColor(EFClient.Permission level, string localizedLevel)
{
char colorCode = '6';
// todo: maybe make this game independant?
switch (level)
{
case Player.Permission.Banned:
case EFClient.Permission.Banned:
colorCode = '1';
break;
case Player.Permission.Flagged:
case EFClient.Permission.Flagged:
colorCode = '9';
break;
case Player.Permission.Owner:
case EFClient.Permission.Owner:
colorCode = '5';
break;
case Player.Permission.User:
case EFClient.Permission.User:
colorCode = '2';
break;
case Player.Permission.Trusted:
case EFClient.Permission.Trusted:
colorCode = '3';
break;
default:
@ -159,7 +161,7 @@ namespace SharedLibraryCore
return $"^{colorCode}{localizedLevel ?? level.ToString()}";
}
public static string ToLocalizedLevelName(this Player.Permission perm) => CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{perm.ToString().ToUpper()}"];
public static string ToLocalizedLevelName(this EFClient.Permission perm) => CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{perm.ToString().ToUpper()}"];
public static String ProcessMessageToken(this Server server, IList<Helpers.MessageToken> tokens, String str)
{
@ -392,9 +394,9 @@ namespace SharedLibraryCore
return "unknown";
}
public static Player AsPlayer(this Database.Models.EFClient client)
public static EFClient AsEFClient(this Database.Models.EFClient client)
{
return client == null ? null : new Player()
return client == null ? null : new EFClient()
{
Active = client.Active,
AliasLink = client.AliasLink,
@ -419,7 +421,7 @@ namespace SharedLibraryCore
};
}
public static bool IsPrivileged(this Player p) => p.Level > Player.Permission.User;
public static bool IsPrivileged(this EFClient p) => p.Level > EFClient.Permission.User;
public static bool PromptBool(string question)
{
@ -524,7 +526,7 @@ namespace SharedLibraryCore
public static async Task<string[]> ExecuteCommandAsync(this Server server, string commandName) => await server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
public static Task<List<Player>> GetStatusAsync(this Server server) => server.RconParser.GetStatusAsync(server.RemoteConnection);
public static Task<List<EFClient>> GetStatusAsync(this Server server) => server.RconParser.GetStatusAsync(server.RemoteConnection);
public static async Task<Dictionary<string, string>> GetInfoAsync(this Server server)
{

View File

@ -1,16 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using SharedLibraryCore.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebfrontCore.Controllers.API
{
public class ApiController : BaseController
{
public IActionResult Index() => Ok($"IW4MAdmin API");
public IActionResult Index()
{
return Ok($"IW4MAdmin API");
}
[HttpGet]
public IActionResult Event(bool shouldConsume = true)
@ -28,12 +28,12 @@ namespace WebfrontCore.Controllers.API
Id = server.GetHashCode(),
Name = server.Hostname,
MaxPlayers = server.MaxClients,
CurrentPlayers = server.GetPlayersAsList().Count,
CurrentPlayers = server.GetClientsAsList().Count,
Map = server.CurrentMap,
GameMode = server.Gametype,
Port = server.GetPort(),
Game = server.GameName.ToString(),
Players = server.GetPlayersAsList()
Players = server.GetClientsAsList()
.Select(player => new
{
player.Name,
@ -53,5 +53,23 @@ namespace WebfrontCore.Controllers.API
return Json(serverInfo);
}
[HttpGet]
public IActionResult RestartApproved()
{
var serverToRestart = Manager.GetServers().FirstOrDefault(_server => _server.RestartRequested);
if (serverToRestart != null)
{
serverToRestart.RestartRequested = false;
}
return serverToRestart != null ?
(IActionResult)Json(new
{
port = serverToRestart.GetPort()
}) :
Unauthorized();
}
}
}

View File

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using WebfrontCore.ViewModels;
using static SharedLibraryCore.Objects.Player;
using static SharedLibraryCore.Database.Models.EFClient;
namespace WebfrontCore.Controllers
{

View File

@ -46,7 +46,7 @@ namespace WebfrontCore.Controllers
Client = Client ?? new EFClient()
{
ClientId = -1,
Level = Player.Permission.User,
Level = EFClient.Permission.User,
CurrentAlias = new EFAlias() { Name = "Web Console Guest" }
};
@ -55,7 +55,7 @@ namespace WebfrontCore.Controllers
try
{
Client.ClientId = Convert.ToInt32(base.User.Claims.First(c => c.Type == ClaimTypes.Sid).Value);
Client.Level = (Player.Permission)Enum.Parse(typeof(Player.Permission), User.Claims.First(c => c.Type == ClaimTypes.Role).Value);
Client.Level = (EFClient.Permission)Enum.Parse(typeof(EFClient.Permission), User.Claims.First(c => c.Type == ClaimTypes.Role).Value);
Client.CurrentAlias = new EFAlias() { Name = User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value };
var stillExists = Manager.GetPrivilegedClients()[Client.ClientId];
@ -81,7 +81,7 @@ namespace WebfrontCore.Controllers
else
{
Client.ClientId = 1;
Client.Level = Player.Permission.Console;
Client.Level = EFClient.Permission.Console;
Client.CurrentAlias = new EFAlias() { Name = "IW4MAdmin" };
}

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Services;
using System;
@ -63,7 +64,7 @@ namespace WebfrontCore.Controllers
var administeredPenaltiesMeta = await Manager.GetPenaltyService()
.ReadGetClientPenaltiesAsync(client.ClientId, false);
if (Authorized && client.Level > SharedLibraryCore.Objects.Player.Permission.Trusted)
if (Authorized && client.Level > EFClient.Permission.Trusted)
clientDto.Meta.Add(new ProfileMeta()
{
Key = Localization["WEBFRONT_CLIENT_META_MASKED"],
@ -122,7 +123,7 @@ namespace WebfrontCore.Controllers
.OrderByDescending(a => a.Level)
.GroupBy(a => a.LinkId).Select(a => a.First());
var adminsDict = new Dictionary<SharedLibraryCore.Objects.Player.Permission, IList<ClientInfo>>();
var adminsDict = new Dictionary<EFClient.Permission, IList<ClientInfo>>();
foreach (var admin in admins)
{

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Objects;
using System;
@ -29,7 +30,7 @@ namespace WebfrontCore.Controllers
public async Task<IActionResult> ExecuteAsync(int serverId, string command)
{
var server = Manager.GetServers().First(s => s.GetHashCode() == serverId);
var client = new Player()
var client = new EFClient()
{
ClientId = Client.ClientId,
Level = Client.Level,

View File

@ -27,7 +27,7 @@ namespace WebfrontCore.Controllers
ClientCount = s.ClientNum,
MaxClients = s.MaxClients,
GameType = s.Gametype,
Players = s.GetPlayersAsList()
Players = s.GetClientsAsList()
.Select(p => new PlayerInfo
{
Name = p.Name,
@ -36,7 +36,7 @@ namespace WebfrontCore.Controllers
LevelInt = (int)p.Level
}).ToList(),
ChatHistory = s.ChatHistory,
PlayerHistory = s.PlayerHistory.ToArray(),
PlayerHistory = s.ClientHistory.ToArray(),
};
return PartialView("_ClientActivity", serverInfo);
}

View File

@ -19,8 +19,8 @@ namespace WebfrontCore.ViewComponents
ClientCount = s.ClientNum,
MaxClients = s.MaxClients,
GameType = s.Gametype,
PlayerHistory = s.PlayerHistory.ToArray(),
Players = s.GetPlayersAsList()
PlayerHistory = s.ClientHistory.ToArray(),
Players = s.GetClientsAsList()
.Select(p => new PlayerInfo()
{
Name = p.Name,

View File

@ -1,5 +1,6 @@
Version 2.3:
-added configuration option to ignore bots
-updated anticheat slightly
Version 2.2:
-upgraded projects to .NET 2.1