add initial CS:GO support
This commit is contained in:
@ -11,20 +11,20 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// </summary>
|
||||
public enum GroupType
|
||||
{
|
||||
EventType,
|
||||
OriginNetworkId,
|
||||
TargetNetworkId,
|
||||
OriginClientNumber,
|
||||
TargetClientNumber,
|
||||
OriginName,
|
||||
TargetName,
|
||||
OriginTeam,
|
||||
TargetTeam,
|
||||
Weapon,
|
||||
Damage,
|
||||
MeansOfDeath,
|
||||
HitLocation,
|
||||
Message,
|
||||
EventType = 0,
|
||||
OriginNetworkId = 1,
|
||||
TargetNetworkId = 2,
|
||||
OriginClientNumber = 3,
|
||||
TargetClientNumber = 4,
|
||||
OriginName = 5,
|
||||
TargetName = 6,
|
||||
OriginTeam = 7,
|
||||
TargetTeam = 8,
|
||||
Weapon = 9,
|
||||
Damage = 10,
|
||||
MeansOfDeath = 11,
|
||||
HitLocation = 12,
|
||||
Message = 13,
|
||||
RConClientNumber = 100,
|
||||
RConScore = 101,
|
||||
RConPing = 102,
|
||||
@ -38,6 +38,8 @@ namespace SharedLibraryCore.Interfaces
|
||||
RConDvarDomain = 110,
|
||||
RConStatusMap = 111,
|
||||
RConStatusGametype = 112,
|
||||
RConStatusHostname = 113,
|
||||
RConStatusMaxPlayers = 114,
|
||||
AdditionalGroup = 200
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,16 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// </summary>
|
||||
ParserRegex Time { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// stores the regex information for the map change game log
|
||||
/// </summary>
|
||||
ParserRegex MapChange { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores the regex information for the map end game log
|
||||
/// </summary>
|
||||
ParserRegex MapEnd { get; }
|
||||
|
||||
/// <summary>
|
||||
/// indicates the format expected for parsed guids
|
||||
/// </summary>
|
||||
|
@ -11,7 +11,8 @@
|
||||
/// <param name="ipAddress">ip address of the server</param>
|
||||
/// <param name="port">port of the server</param>
|
||||
/// <param name="password"> password of the server</param>
|
||||
/// <param name="rconEngine">engine to create the rcon connection to</param>
|
||||
/// <returns>instance of rcon connection</returns>
|
||||
IRConConnection CreateConnection(string ipAddress, int port, string password);
|
||||
IRConConnection CreateConnection(string ipAddress, int port, string password, string rconEngine);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using static SharedLibraryCore.Server;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
@ -39,8 +37,8 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// get the list of connected clients from status response
|
||||
/// </summary>
|
||||
/// <param name="connection">RCon connection to use</param>
|
||||
/// <returns>list of clients, current map, and current gametype</returns>
|
||||
Task<(List<EFClient>, string, string)> GetStatusAsync(IRConConnection connection);
|
||||
/// <returns><see cref="IStatusResponse"/></returns>
|
||||
Task<IStatusResponse> GetStatusAsync(IRConConnection connection);
|
||||
|
||||
/// <summary>
|
||||
/// stores the RCon configuration
|
||||
@ -50,23 +48,29 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// <summary>
|
||||
/// stores the game/client specific version (usually the value of the "version" DVAR)
|
||||
/// </summary>
|
||||
string Version { get; set; }
|
||||
string Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// specifies the game name (usually the internal studio iteration ie: IW4, T5 etc...)
|
||||
/// </summary>
|
||||
Game GameName { get; set; }
|
||||
Game GameName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// indicates if the game supports generating a log path from DVAR retrieval
|
||||
/// of fs_game, fs_basepath, g_log
|
||||
/// </summary>
|
||||
bool CanGenerateLogPath { get; set; }
|
||||
bool CanGenerateLogPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// specifies the name of the parser
|
||||
/// </summary>
|
||||
string Name { get; set; }
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// specifies the type of rcon engine
|
||||
/// eg: COD, Source
|
||||
/// </summary>
|
||||
string RConEngine { get; }
|
||||
|
||||
/// <summary>
|
||||
/// retrieves the value of given dvar key if it exists in the override dict
|
||||
|
@ -9,59 +9,69 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// <summary>
|
||||
/// stores the command format for console commands
|
||||
/// </summary>
|
||||
CommandPrefix CommandPrefixes { get; set; }
|
||||
CommandPrefix CommandPrefixes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores the regex info for parsing get status response
|
||||
/// </summary>
|
||||
ParserRegex Status { get; set; }
|
||||
ParserRegex Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores regex info for parsing the map line from rcon status response
|
||||
/// </summary>
|
||||
ParserRegex MapStatus { get; set; }
|
||||
ParserRegex MapStatus { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores regex info for parsing the gametype line from rcon status response
|
||||
/// </summary>
|
||||
ParserRegex GametypeStatus { get; set; }
|
||||
ParserRegex GametypeStatus { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores regex info for parsing hostname line from rcon status response
|
||||
/// </summary>
|
||||
ParserRegex HostnameStatus { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores regex info for parsing max players line from rcon status response
|
||||
/// </summary>
|
||||
ParserRegex MaxPlayersStatus { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores the regex info for parsing get DVAR responses
|
||||
/// </summary>
|
||||
ParserRegex Dvar { get; set; }
|
||||
ParserRegex Dvar { get; }
|
||||
|
||||
/// <summary>
|
||||
/// stores the regex info for parsing the header of a status response
|
||||
/// </summary>
|
||||
ParserRegex StatusHeader { get; set; }
|
||||
ParserRegex StatusHeader { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the expected response message from rcon when the server is not running
|
||||
/// </summary>
|
||||
string ServerNotRunningResponse { get; set; }
|
||||
string ServerNotRunningResponse { get; }
|
||||
|
||||
/// <summary>
|
||||
/// indicates if the application should wait for response from server
|
||||
/// when executing a command
|
||||
/// </summary>
|
||||
bool WaitForResponse { get; set; }
|
||||
bool WaitForResponse { get; }
|
||||
|
||||
/// <summary>
|
||||
/// indicates the format expected for parsed guids
|
||||
/// </summary>
|
||||
NumberStyles GuidNumberStyle { get; set; }
|
||||
NumberStyles GuidNumberStyle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// specifies simple mappings for dvar names in scenarios where the needed
|
||||
/// information is not stored in a traditional dvar name
|
||||
/// </summary>
|
||||
IDictionary<string, string> OverrideDvarNameMapping { get; set; }
|
||||
IDictionary<string, string> OverrideDvarNameMapping { get; }
|
||||
|
||||
/// <summary>
|
||||
/// specifies the default dvar values for games that don't support certain dvars
|
||||
/// </summary>
|
||||
IDictionary<string, string> DefaultDvarValues { get; set; }
|
||||
IDictionary<string, string> DefaultDvarValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// specifies how many lines can be used for ingame notice
|
||||
@ -71,11 +81,11 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// <summary>
|
||||
/// specifies how many characters can be displayed per notice line
|
||||
/// </summary>
|
||||
int NoticeMaxCharactersPerLine { get; set; }
|
||||
int NoticeMaxCharactersPerLine { get; }
|
||||
|
||||
/// <summary>
|
||||
/// specifies the characters used to split a line
|
||||
/// </summary>
|
||||
string NoticeLineSeparator { get; set; }
|
||||
string NoticeLineSeparator { get; }
|
||||
}
|
||||
}
|
||||
|
35
SharedLibraryCore/Interfaces/IStatusResponse.cs
Normal file
35
SharedLibraryCore/Interfaces/IStatusResponse.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using SharedLibraryCore.Database.Models;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// describes the collection of data returned from a status query
|
||||
/// </summary>
|
||||
public interface IStatusResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// name of the map
|
||||
/// </summary>
|
||||
string Map { get; }
|
||||
|
||||
/// <summary>
|
||||
/// gametype/mode
|
||||
/// </summary>
|
||||
string GameType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// server name
|
||||
/// </summary>
|
||||
string Hostname { get; }
|
||||
|
||||
/// <summary>
|
||||
/// max number of players
|
||||
/// </summary>
|
||||
int? MaxClients { get; }
|
||||
|
||||
/// <summary>
|
||||
/// active clients
|
||||
/// </summary>
|
||||
EFClient[] Clients { get; }
|
||||
}
|
||||
}
|
@ -29,7 +29,8 @@ namespace SharedLibraryCore
|
||||
T5 = 6,
|
||||
T6 = 7,
|
||||
T7 = 8,
|
||||
SHG1 = 9
|
||||
SHG1 = 9,
|
||||
CSGO = 10
|
||||
}
|
||||
|
||||
public Server(ILogger<Server> logger, SharedLibraryCore.Interfaces.ILogger deprecatedLogger,
|
||||
@ -42,7 +43,6 @@ namespace SharedLibraryCore
|
||||
Manager = mgr;
|
||||
Logger = deprecatedLogger;
|
||||
ServerConfig = config;
|
||||
RemoteConnection = rconConnectionFactory.CreateConnection(IP, Port, Password);
|
||||
EventProcessing = new SemaphoreSlim(1, 1);
|
||||
Clients = new List<EFClient>(new EFClient[64]);
|
||||
Reports = new List<Report>();
|
||||
@ -52,6 +52,7 @@ namespace SharedLibraryCore
|
||||
CustomSayEnabled = Manager.GetApplicationSettings().Configuration().EnableCustomSayName;
|
||||
CustomSayName = Manager.GetApplicationSettings().Configuration().CustomSayName;
|
||||
this.gameLogReaderFactory = gameLogReaderFactory;
|
||||
RConConnectionFactory = rconConnectionFactory;
|
||||
ServerLogger = logger;
|
||||
InitializeTokens();
|
||||
InitializeAutoMessages();
|
||||
@ -158,24 +159,28 @@ namespace SharedLibraryCore
|
||||
/// Send a message to a particular players
|
||||
/// </summary>
|
||||
/// <param name="message">Message to send</param>
|
||||
/// <param name="target">EFClient to send message to</param>
|
||||
protected async Task Tell(string message, EFClient target)
|
||||
/// <param name="targetClient">EFClient to send message to</param>
|
||||
protected async Task Tell(string message, EFClient targetClient)
|
||||
{
|
||||
if (!Utilities.IsDevelopment)
|
||||
{
|
||||
var temporalClientId = targetClient.GetAdditionalProperty<string>("ConnectionClientId");
|
||||
var parsedClientId = string.IsNullOrEmpty(temporalClientId) ? (int?)null : int.Parse(temporalClientId);
|
||||
var clientNumber = parsedClientId ?? targetClient.ClientNumber;
|
||||
|
||||
var formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell,
|
||||
target.ClientNumber,
|
||||
clientNumber,
|
||||
$"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}");
|
||||
if (target.ClientNumber > -1 && message.Length > 0 && target.Level != EFClient.Permission.Console)
|
||||
if (targetClient.ClientNumber > -1 && message.Length > 0 && targetClient.Level != EFClient.Permission.Console)
|
||||
await this.ExecuteCommandAsync(formattedMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerLogger.LogDebug("Tell[{clientNumber}]->{message}", target.ClientNumber, message.StripColors());
|
||||
ServerLogger.LogDebug("Tell[{clientNumber}]->{message}", targetClient.ClientNumber, message.StripColors());
|
||||
}
|
||||
|
||||
|
||||
if (target.Level == EFClient.Permission.Console)
|
||||
if (targetClient.Level == EFClient.Permission.Console)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
using (LogContext.PushProperty("Server", ToString()))
|
||||
@ -340,6 +345,7 @@ namespace SharedLibraryCore
|
||||
protected DateTime LastPoll;
|
||||
protected ManualResetEventSlim OnRemoteCommandResponse;
|
||||
protected IGameLogReaderFactory gameLogReaderFactory;
|
||||
protected IRConConnectionFactory RConConnectionFactory;
|
||||
|
||||
// only here for performance
|
||||
private readonly bool CustomSayEnabled;
|
||||
|
@ -44,7 +44,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.10" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="RaidMax.IW4MAdmin.Data" Version="1.0.0" />
|
||||
<PackageReference Include="RaidMax.IW4MAdmin.Data" Version="1.0.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
|
||||
<PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
@ -322,6 +322,8 @@ namespace SharedLibraryCore
|
||||
/// <returns></returns>
|
||||
public static long ConvertGuidToLong(this string str, NumberStyles numberStyle, long? fallback = null)
|
||||
{
|
||||
// added for source games that provide the steam ID
|
||||
str = str.Replace("STEAM_1", "").Replace(":", "");
|
||||
str = str.Substring(0, Math.Min(str.Length, 19));
|
||||
var parsableAsNumber = Regex.Match(str, @"([A-F]|[a-f]|[0-9])+").Value;
|
||||
|
||||
@ -732,7 +734,7 @@ namespace SharedLibraryCore
|
||||
return await server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
|
||||
}
|
||||
|
||||
public static Task<(List<EFClient>, string, string)> GetStatusAsync(this Server server)
|
||||
public static Task<IStatusResponse> GetStatusAsync(this Server server)
|
||||
{
|
||||
return server.RconParser.GetStatusAsync(server.RemoteConnection);
|
||||
}
|
||||
|
Reference in New Issue
Block a user