moved validate command into shared library.
reworked connection system to read from log file for join/quits and authenticate later with polling
This commit is contained in:
145
SharedLibraryCore/Commands/CommandProcessing.cs
Normal file
145
SharedLibraryCore/Commands/CommandProcessing.cs
Normal file
@ -0,0 +1,145 @@
|
||||
using SharedLibraryCore.Exceptions;
|
||||
using SharedLibraryCore.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Commands
|
||||
{
|
||||
public class CommandProcessing
|
||||
{
|
||||
public static async Task<Command> ValidateCommand(GameEvent E)
|
||||
{
|
||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
var Manager = E.Owner.Manager;
|
||||
|
||||
string CommandString = E.Data.Substring(1, E.Data.Length - 1).Split(' ')[0];
|
||||
E.Message = E.Data;
|
||||
|
||||
Command C = null;
|
||||
foreach (Command cmd in Manager.GetCommands())
|
||||
{
|
||||
if (cmd.Name == CommandString.ToLower() || cmd.Alias == CommandString.ToLower())
|
||||
C = cmd;
|
||||
}
|
||||
|
||||
if (C == null)
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_UNKNOWN"]);
|
||||
throw new CommandException($"{E.Origin} entered unknown command \"{CommandString}\"");
|
||||
}
|
||||
|
||||
E.Data = E.Data.RemoveWords(1);
|
||||
String[] Args = E.Data.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (E.Origin.Level < C.Permission)
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_NOACCESS"]);
|
||||
throw new CommandException($"{E.Origin} does not have access to \"{C.Name}\"");
|
||||
}
|
||||
|
||||
if (Args.Length < (C.RequiredArgumentCount))
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_MISSINGARGS"]);
|
||||
await E.Origin.Tell(C.Syntax);
|
||||
throw new CommandException($"{E.Origin} did not supply enough arguments for \"{C.Name}\"");
|
||||
}
|
||||
|
||||
if (C.RequiresTarget || Args.Length > 0)
|
||||
{
|
||||
if (!Int32.TryParse(Args[0], out int cNum))
|
||||
cNum = -1;
|
||||
|
||||
if (Args[0][0] == '@') // user specifying target by database ID
|
||||
{
|
||||
int dbID = -1;
|
||||
int.TryParse(Args[0].Substring(1, Args[0].Length - 1), out dbID);
|
||||
|
||||
var found = await Manager.GetClientService().Get(dbID);
|
||||
if (found != null)
|
||||
{
|
||||
E.Target = found.AsPlayer();
|
||||
E.Target.CurrentServer = E.Owner;
|
||||
E.Data = String.Join(" ", Args.Skip(1));
|
||||
}
|
||||
}
|
||||
|
||||
else if (Args[0].Length < 3 && cNum > -1 && cNum < E.Owner.MaxClients) // user specifying target by client num
|
||||
{
|
||||
if (E.Owner.Players[cNum] != null)
|
||||
{
|
||||
E.Target = E.Owner.Players[cNum];
|
||||
E.Data = String.Join(" ", Args.Skip(1));
|
||||
}
|
||||
}
|
||||
|
||||
List<Player> matchingPlayers;
|
||||
|
||||
if (E.Target == null && C.RequiresTarget) // Find active player including quotes (multiple words)
|
||||
{
|
||||
matchingPlayers = E.Owner.GetClientByName(E.Data.Trim());
|
||||
if (matchingPlayers.Count > 1)
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_TARGET_MULTI"]);
|
||||
throw new CommandException($"{E.Origin} had multiple players found for {C.Name}");
|
||||
}
|
||||
else if (matchingPlayers.Count == 1)
|
||||
{
|
||||
E.Target = matchingPlayers.First();
|
||||
|
||||
string escapedName = Regex.Escape(E.Target.Name);
|
||||
var reg = new Regex($"(\"{escapedName}\")|({escapedName})", RegexOptions.IgnoreCase);
|
||||
E.Data = reg.Replace(E.Data, "", 1).Trim();
|
||||
|
||||
if (E.Data.Length == 0 && C.RequiredArgumentCount > 1)
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_MISSINGARGS"]);
|
||||
await E.Origin.Tell(C.Syntax);
|
||||
throw new CommandException($"{E.Origin} did not supply enough arguments for \"{C.Name}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (E.Target == null && C.RequiresTarget) // Find active player as single word
|
||||
{
|
||||
matchingPlayers = E.Owner.GetClientByName(Args[0]);
|
||||
if (matchingPlayers.Count > 1)
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_TARGET_MULTI"]);
|
||||
foreach (var p in matchingPlayers)
|
||||
await E.Origin.Tell($"[^3{p.ClientNumber}^7] {p.Name}");
|
||||
throw new CommandException($"{E.Origin} had multiple players found for {C.Name}");
|
||||
}
|
||||
else if (matchingPlayers.Count == 1)
|
||||
{
|
||||
E.Target = matchingPlayers.First();
|
||||
|
||||
string escapedName = Regex.Escape(E.Target.Name);
|
||||
string escapedArg = Regex.Escape(Args[0]);
|
||||
var reg = new Regex($"({escapedName})|({escapedArg})", RegexOptions.IgnoreCase);
|
||||
E.Data = reg.Replace(E.Data, "", 1).Trim();
|
||||
|
||||
if ((E.Data.Trim() == E.Target.Name.ToLower().Trim() ||
|
||||
E.Data == String.Empty) &&
|
||||
C.RequiresTarget)
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_MISSINGARGS"]);
|
||||
await E.Origin.Tell(C.Syntax);
|
||||
throw new CommandException($"{E.Origin} did not supply enough arguments for \"{C.Name}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (E.Target == null && C.RequiresTarget)
|
||||
{
|
||||
await E.Origin.Tell(loc["COMMAND_TARGET_NOTFOUND"]);
|
||||
throw new CommandException($"{E.Origin} specified invalid player for \"{C.Name}\"");
|
||||
}
|
||||
}
|
||||
E.Data = E.Data.Trim();
|
||||
return C;
|
||||
}
|
||||
}
|
||||
}
|
27
SharedLibraryCore/Interfaces/IClientAuthentication.cs
Normal file
27
SharedLibraryCore/Interfaces/IClientAuthentication.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using SharedLibraryCore.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IClientAuthentication
|
||||
{
|
||||
/// <summary>
|
||||
/// request authentication when a client join event
|
||||
/// 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);
|
||||
/// <summary>
|
||||
/// get all clients that have been authenticated by the status poll
|
||||
/// </summary>
|
||||
/// <returns>list of all authenticated clients</returns>
|
||||
IList<Player> 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);
|
||||
}
|
||||
}
|
@ -13,7 +13,8 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// Add a game event event to the queue to be processed
|
||||
/// </summary>
|
||||
/// <param name="gameEvent">Game event</param>
|
||||
void AddEvent(GameEvent gameEvent);
|
||||
/// <param name="delayedExecution">don't signal that an event has been aded</param>
|
||||
void AddEvent(GameEvent gameEvent, bool delayedExecution = false);
|
||||
/// <summary>
|
||||
/// Get the next event to be processed
|
||||
/// </summary>
|
||||
|
10
SharedLibraryCore/Objects/ClientStats.cs
Normal file
10
SharedLibraryCore/Objects/ClientStats.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharedLibraryCore.Objects
|
||||
{
|
||||
class ClientStats
|
||||
{
|
||||
}
|
||||
}
|
@ -8,6 +8,13 @@ namespace SharedLibraryCore.Objects
|
||||
{
|
||||
public class Player : Database.Models.EFClient
|
||||
{
|
||||
public enum ClientState
|
||||
{
|
||||
Connecting,
|
||||
Connected,
|
||||
Disconnecting,
|
||||
}
|
||||
|
||||
public enum Permission
|
||||
{
|
||||
Banned = -1,
|
||||
@ -109,6 +116,10 @@ namespace SharedLibraryCore.Objects
|
||||
get { return _name; }
|
||||
set { _name = value; }
|
||||
}
|
||||
[NotMapped]
|
||||
public bool IsAuthenticated { get; set; }
|
||||
[NotMapped]
|
||||
public ClientState State { get; set; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
|
@ -13,6 +13,6 @@ namespace SharedLibraryCore.RCon
|
||||
}
|
||||
|
||||
public static char SeperatorChar = (char)int.Parse("0a", System.Globalization.NumberStyles.AllowHexSpecifier);
|
||||
public static readonly TimeSpan SocketTimeout = new TimeSpan(0, 0, 10);
|
||||
public static readonly TimeSpan SocketTimeout = new TimeSpan(0, 0, 5);
|
||||
}
|
||||
}
|
||||
|
@ -100,14 +100,6 @@ namespace SharedLibraryCore
|
||||
return Players.Where(p => p != null && p.Name.ToLower().Contains(pName.ToLower())).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process requested command correlating to an event
|
||||
/// </summary>
|
||||
/// <param name="E">Event parameter</param>
|
||||
/// <param name="C">Command requested from the event</param>
|
||||
/// <returns></returns>
|
||||
abstract public Task<Command> ValidateCommand(GameEvent E);
|
||||
|
||||
virtual public Task<bool> ProcessUpdatesAsync(CancellationToken cts) => (Task<bool>)Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
|
Reference in New Issue
Block a user