diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 4bea75fc5..f16218461 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -759,14 +759,20 @@ namespace IW4MAdmin.Application return PageList; } - public IRConParser GenerateDynamicRConParser() + public IRConParser GenerateDynamicRConParser(string name) { - return new DynamicRConParser(); + return new DynamicRConParser() + { + Name = name + }; } - public IEventParser GenerateDynamicEventParser() + public IEventParser GenerateDynamicEventParser(string name) { - return new DynamicEventParser(); + return new DynamicEventParser() + { + Name = name + }; } public async Task> ExecuteSharedDatabaseOperation(string operationName) diff --git a/Application/EventParsers/BaseEventParser.cs b/Application/EventParsers/BaseEventParser.cs index 71962056c..3d0bc746b 100644 --- a/Application/EventParsers/BaseEventParser.cs +++ b/Application/EventParsers/BaseEventParser.cs @@ -2,7 +2,6 @@ using SharedLibraryCore.Database.Models; using SharedLibraryCore.Interfaces; using System; -using System.Linq; using System.Text.RegularExpressions; using static SharedLibraryCore.Server; @@ -75,6 +74,8 @@ namespace IW4MAdmin.Application.EventParsers public string URLProtocolFormat { get; set; } = "CoD://{{ip}}:{{port}}"; + public string Name { get; set; } = "Call of Duty"; + public virtual GameEvent GenerateGameEvent(string logLine) { logLine = Regex.Replace(logLine, @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim(); diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index e1d57fe51..b16349cbb 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -63,6 +63,7 @@ namespace IW4MAdmin.Application.RconParsers public virtual string Version { get; set; } = "CoD"; public Game GameName { get; set; } = Game.COD; public bool CanGenerateLogPath { get; set; } = true; + public string Name { get; set; } = "Call of Duty"; public async Task ExecuteCommandAsync(Connection connection, string command) { diff --git a/GameFiles/IW4x/userraw/_commands.gsc b/GameFiles/IW4x/userraw/_commands.gsc index 25994f543..0c80cb336 100644 --- a/GameFiles/IW4x/userraw/_commands.gsc +++ b/GameFiles/IW4x/userraw/_commands.gsc @@ -5,166 +5,49 @@ init() { -/* - SetDvarIfUninitialized("sv_team_balance_assignments", ""); - SetDvarIfUninitialized("sv_iw4madmin_serverid", 0); - SetDvarIfUninitialized("sv_iw4madmin_apiurl", "http://127.0.0.1:1624/api/gsc/"); - level.apiUrl = GetDvar("sv_iw4madmin_apiurl"); + SetDvarIfUninitialized( "sv_iw4madmin_command", "" ); level thread WaitForCommand(); - level thread onPlayerConnect(); - level thread onPlayerDisconnect(); -*/ -} - -onPlayerConnect() -{ - for(;;) - { - level waittill( "connected", player ); - player thread onJoinedTeam(); - } -} - -onPlayerDisconnect() -{ - for(;;) - { - level waittill( "disconnected", player ); - logPrint("player disconnected\n"); - level.players[0] SetTeamBalanceAssignments(true); - } -} - -onJoinedTeam() -{ - self endon("disconnect"); - - for(;;) - { - self waittill( "joined_team" ); - self SetTeamBalanceAssignments(false); - } -} - -SetTeamBalanceAssignments(isDisconnect) -{ - assignments = GetDvar("sv_team_balance_assignments"); - dc = ""; - if (isDisconnect) - { - dc = "&isDisconnect=true"; - } - url = level.apiUrl + "GetTeamAssignments/" + self.guid + "/?teams=" + assignments + dc + "&serverId=" + GetDvar("sv_iw4madmin_serverid"); - newAssignments = GetHttpString(url); - SetDvar("sv_team_balance_assignments", newAssignments.data); - - if (newAssignments.success) - { - BalanceTeams(strtok(newAssignments.data, ",")); - } } WaitForCommand() { + level endon( "game_ended" ); + for(;;) { - commandInfo = strtok(getDvar("sv_iw4madmin_command"), ";"); + commandInfo = strtok( getDvar("sv_iw4madmin_command"), ";" ); command = commandInfo[0]; - commandArgs = strtok(commandInfo[1], ","); - - switch(command) + + switch( command ) { - case "balance": - BalanceTeams(commandArgs); - break; case "alert": - //clientId alertType sound message - SendAlert(commandArgs[0], commandArgs[1], commandArgs[2], commandArgs[3]); + //clientId alertType sound message + SendAlert( commandInfo[1], commandInfo[2], commandInfo[3], commandInfo[4] ); + break; + case "killplayer": + // clientId + KillPlayer( commandInfo[1], commandInfo[2] ); break; } - setDvar("sv_iw4madmin_command", ""); - wait(1); + setDvar( "sv_iw4madmin_command", "" ); + wait( 1 ); } } -SendAlert(clientId, alertType, sound, message) +SendAlert( clientId, alertType, sound, message ) { - client = getPlayerFromClientNum(clientId); - - client thread playLeaderDialogOnPlayer(sound, client.team); - client playLocalSound(sound); - client iPrintLnBold("^1" + alertType + ": ^3" + message); + client = getPlayerFromClientNum( int( clientId ) ); + client thread playLeaderDialogOnPlayer( sound, client.team ); + client playLocalSound( sound ); + client iPrintLnBold( "^1" + alertType + ": ^3" + message ); } -GetHttpString(url) +KillPlayer( targetId, originId) { - response = spawnStruct(); - response.success = false; - response.data = undefined; + target = getPlayerFromClientNum( int( targetId ) ); + target suicide(); + origin = getPlayerFromClientNum( int( originId ) ); - logPrint("Making request to " + url + "\n"); - request = httpGet(url); - request waittill("done", success, data); - - if(success != 0){ - logPrint("Request succeeded\n"); - response.success = true; - response.data = data; - } - - else - { - logPrint("Request failed\n"); - } - - return response; -} - -BalanceTeams(commandArgs) -{ - if (level.teamBased) - { - printOnPlayers("^5Balancing Teams..."); - - for (i = 0; i < commandArgs.size; i+= 2) - { - teamNum = int(commandArgs[i+1]); - clientNum = int(commandArgs[i]); - - //printOnPlayers("[" + teamNum + "," + clientNum + "]"); - - if (teamNum == 2) - { - newTeam = "allies"; - } - else - { - newTeam = "axis"; - } - - player = getPlayerFromClientNum(clientNum); - - //if (!isPlayer(player)) - // continue; - - switch (newTeam) - { - case "axis": - if (player.team != "axis") - { - //printOnPlayers("moving " + player.name + " to axis"); - player[[level.axis]](); - } - break; - case "allies": - if (player.team != "allies") - { - //printOnPlayers("moving " + player.name + " to allies"); - player[[level.allies]](); - } - break; - } - } - } + iPrintLnBold("^1" + origin.name + " ^7killed ^5" + target.name); } \ No newline at end of file diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index 352215090..eeebf6fa6 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -288,6 +288,7 @@ Global {B72DEBFB-9D48-4076-8FF5-1FD72A830845}.Release|x86.ActiveCfg = Release|Any CPU {B72DEBFB-9D48-4076-8FF5-1FD72A830845}.Release|x86.Build.0 = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C706CE5-A206-4E46-8712-F8C48D526091}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -295,6 +296,7 @@ Global {6C706CE5-A206-4E46-8712-F8C48D526091}.Debug|x86.ActiveCfg = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Debug|x86.Build.0 = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Prerelease|Any CPU.ActiveCfg = Prerelease|Any CPU + {6C706CE5-A206-4E46-8712-F8C48D526091}.Prerelease|Any CPU.Build.0 = Prerelease|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Prerelease|Mixed Platforms.ActiveCfg = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Prerelease|Mixed Platforms.Build.0 = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Prerelease|x64.ActiveCfg = Debug|Any CPU @@ -302,6 +304,7 @@ Global {6C706CE5-A206-4E46-8712-F8C48D526091}.Prerelease|x86.ActiveCfg = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Prerelease|x86.Build.0 = Debug|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|Any CPU.Build.0 = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|Mixed Platforms.Build.0 = Release|Any CPU {6C706CE5-A206-4E46-8712-F8C48D526091}.Release|x64.ActiveCfg = Release|Any CPU diff --git a/Master/master/templates/index.html b/Master/master/templates/index.html index 0e9d9e08a..d23fe2956 100644 --- a/Master/master/templates/index.html +++ b/Master/master/templates/index.html @@ -2,7 +2,7 @@ {% block content %}
-
+
{{history_graph|safe}}
@@ -15,10 +15,6 @@ — {{server_count}} servers
- -
-
-
{% endblock %} diff --git a/Plugins/IW4ScriptCommands/CommandInfo.cs b/Plugins/IW4ScriptCommands/CommandInfo.cs deleted file mode 100644 index d7e76be63..000000000 --- a/Plugins/IW4ScriptCommands/CommandInfo.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace IW4ScriptCommands -{ - class CommandInfo - { - public string Command { get; set; } - public int ClientNumber { get; set; } - public List CommandArguments { get; set; } = new List(); - public override string ToString() => $"{Command};{ClientNumber},{string.Join(',', CommandArguments)}"; - } -} diff --git a/Plugins/IW4ScriptCommands/Commands/Balance.cs b/Plugins/IW4ScriptCommands/Commands/Balance.cs deleted file mode 100644 index 9931d34bc..000000000 --- a/Plugins/IW4ScriptCommands/Commands/Balance.cs +++ /dev/null @@ -1,201 +0,0 @@ -/* -using SharedLibraryCore; -using SharedLibraryCore.Database.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace IW4ScriptCommands.Commands -{ - class Balance - { - private class TeamAssignment - { - public IW4MAdmin.Plugins.Stats.IW4Info.Team CurrentTeam { get; set; } - public int Num { get; set; } - public IW4MAdmin.Plugins.Stats.Models.EFClientStatistics Stats { get; set; } - } - - 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.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.EndPoint) - }) - .ToList(); - - // at least one team is full so we can't balance - if (scriptClientTeams.Count(ct => ct.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Axis) >= Math.Floor(server.MaxClients / 2.0) - || scriptClientTeams.Count(ct => ct.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Allies) >= Math.Floor(server.MaxClients / 2.0)) - { - // E.Origin?.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BALANCE_FAIL"]); - return string.Empty; - } - - List teamAssignments = new List(); - - var _c = server.GetClientsAsList(); - if (isDisconnect && client != null) - { - _c = _c.Where(c => c.ClientNumber != client.ClientNumber).ToList(); - } - - var activeClients = _c.Select(c => new TeamAssignment() - { - Num = c.ClientNumber, - Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, server.EndPoint), - CurrentTeam = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, server.EndPoint).Team - }) - .Where(c => scriptClientTeams.FirstOrDefault(sc => sc.Num == c.Num)?.CurrentTeam != IW4MAdmin.Plugins.Stats.IW4Info.Team.Spectator) - .Where(c => c.CurrentTeam != scriptClientTeams.FirstOrDefault(p => p.Num == c.Num)?.CurrentTeam) - .OrderByDescending(c => c.Stats.Performance) - .ToList(); - - var alliesTeam = scriptClientTeams - .Where(c => c.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Allies) - .Where(c => activeClients.Count(t => t.Num == c.Num) == 0) - .ToList(); - - var axisTeam = scriptClientTeams - .Where(c => c.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Axis) - .Where(c => activeClients.Count(t => t.Num == c.Num) == 0) - .ToList(); - - while (activeClients.Count() > 0) - { - int teamSizeDifference = alliesTeam.Count - axisTeam.Count; - double performanceDisparity = alliesTeam.Count > 0 ? alliesTeam.Average(t => t.Stats.Performance) : 0 - - axisTeam.Count > 0 ? axisTeam.Average(t => t.Stats.Performance) : 0; - - if (teamSizeDifference == 0) - { - if (performanceDisparity == 0) - { - alliesTeam.Add(activeClients.First()); - activeClients.RemoveAt(0); - } - else - { - if (performanceDisparity > 0) - { - axisTeam.Add(activeClients.First()); - activeClients.RemoveAt(0); - } - else - { - alliesTeam.Add(activeClients.First()); - activeClients.RemoveAt(0); - } - } - } - else if (teamSizeDifference > 0) - { - if (performanceDisparity > 0) - { - axisTeam.Add(activeClients.First()); - activeClients.RemoveAt(0); - } - - else - { - axisTeam.Add(activeClients.Last()); - activeClients.RemoveAt(activeClients.Count - 1); - } - } - else - { - if (performanceDisparity > 0) - { - alliesTeam.Add(activeClients.First()); - activeClients.RemoveAt(0); - } - - else - { - alliesTeam.Add(activeClients.Last()); - activeClients.RemoveAt(activeClients.Count - 1); - } - } - } - - alliesTeam = alliesTeam.OrderByDescending(t => t.Stats.Performance) - .ToList(); - - axisTeam = axisTeam.OrderByDescending(t => t.Stats.Performance) - .ToList(); - - while (Math.Abs(alliesTeam.Count - axisTeam.Count) > 1) - { - int teamSizeDifference = alliesTeam.Count - axisTeam.Count; - double performanceDisparity = alliesTeam.Count > 0 ? alliesTeam.Average(t => t.Stats.Performance) : 0 - - axisTeam.Count > 0 ? axisTeam.Average(t => t.Stats.Performance) : 0; - - if (teamSizeDifference > 0) - { - if (performanceDisparity > 0) - { - axisTeam.Add(alliesTeam.First()); - alliesTeam.RemoveAt(0); - } - - else - { - axisTeam.Add(alliesTeam.Last()); - alliesTeam.RemoveAt(axisTeam.Count - 1); - } - } - - else - { - if (performanceDisparity > 0) - { - alliesTeam.Add(axisTeam.Last()); - axisTeam.RemoveAt(axisTeam.Count - 1); - } - - else - { - alliesTeam.Add(axisTeam.First()); - axisTeam.RemoveAt(0); - } - } - } - - foreach (var assignment in alliesTeam) - { - teamAssignments.Add($"{assignment.Num},2"); - assignment.Stats.Team = IW4MAdmin.Plugins.Stats.IW4Info.Team.Allies; - } - - foreach (var assignment in axisTeam) - { - teamAssignments.Add($"{assignment.Num},3"); - assignment.Stats.Team = IW4MAdmin.Plugins.Stats.IW4Info.Team.Axis; - } - - //if (alliesTeam.Count(ac => scriptClientTeams.First(sc => sc.Num == ac.Num).CurrentTeam != ac.CurrentTeam) == 0 && - // axisTeam.Count(ac => scriptClientTeams.First(sc => sc.Num == ac.Num).CurrentTeam != ac.CurrentTeam) == 0) - //{ - // //E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BALANCE_FAIL_BALANCED"]); - // return string.Empty; - //} - - //if (E.Origin?.Level > Player.Permission.Administrator) - //{ - // E.Origin.Tell($"Allies Elo: {(alliesTeam.Count > 0 ? alliesTeam.Average(t => t.Stats.Performance) : 0)}"); - // E.Origin.Tell($"Axis Elo: {(axisTeam.Count > 0 ? axisTeam.Average(t => t.Stats.Performance) : 0)}"); - //} - - //E.Origin.Tell("Balance command sent"); - string args = string.Join(",", teamAssignments); - return args; - } - } -} -*/ \ No newline at end of file diff --git a/Plugins/IW4ScriptCommands/Commands/KillPlayerCommand.cs b/Plugins/IW4ScriptCommands/Commands/KillPlayerCommand.cs new file mode 100644 index 000000000..d8fe0ebe7 --- /dev/null +++ b/Plugins/IW4ScriptCommands/Commands/KillPlayerCommand.cs @@ -0,0 +1,34 @@ +using SharedLibraryCore; +using SharedLibraryCore.Database.Models; +using System.Threading.Tasks; + +namespace IW4ScriptCommands.Commands +{ + /// + /// Example script command + /// + public class KillPlayerCommand : Command + { + public KillPlayerCommand() : base("killplayer", "kill a player", "kp", EFClient.Permission.Administrator, true, new[] + { + new CommandArgument() + { + Name = "player", + Required = true + } + }) + { } + + public override async Task ExecuteAsync(GameEvent E) + { + var cmd = new ScriptCommand() + { + CommandName = "killplayer", + ClientNumber = E.Target.ClientNumber, + CommandArguments = new[] { E.Origin.ClientNumber.ToString() } + }; + + await cmd.Execute(E.Owner); + } + } +} diff --git a/Plugins/IW4ScriptCommands/GscApiController.cs b/Plugins/IW4ScriptCommands/GscApiController.cs index f5b3a4312..2642b68cb 100644 --- a/Plugins/IW4ScriptCommands/GscApiController.cs +++ b/Plugins/IW4ScriptCommands/GscApiController.cs @@ -1,17 +1,24 @@ -/*using IW4ScriptCommands.Commands; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using SharedLibraryCore; -using System; -using System.Collections.Generic; +using SharedLibraryCore.Interfaces; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace WebfrontCore.Controllers.API { [Route("api/gsc/[action]")] - public class GscApiController : ApiController + public class GscApiController : BaseController { + public GscApiController(IManager manager) : base(manager) + { + + } + + /// + /// grabs basic info about the client from IW4MAdmin + /// + /// + /// [HttpGet("{networkId}")] public IActionResult ClientInfo(string networkId) { @@ -32,23 +39,5 @@ namespace WebfrontCore.Controllers.API return Content(""); } - - [HttpGet("{networkId}")] - public IActionResult GetTeamAssignments(string networkId, int serverId, string teams = "", bool isDisconnect = false) - { - return Unauthorized(); - - var client = Manager.GetActiveClients() - .FirstOrDefault(c => c.NetworkId == networkId.ConvertGuidToLong()); - - var server = Manager.GetServers().First(c => c.EndPoint == serverId); - - teams = teams ?? string.Empty; - - string assignments = Balance.GetTeamAssignments(client, isDisconnect, server, teams); - - return Content(assignments); - } } } -*/ \ No newline at end of file diff --git a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj index 35d5bd5c1..5597b8497 100644 --- a/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj +++ b/Plugins/IW4ScriptCommands/IW4ScriptCommands.csproj @@ -10,12 +10,11 @@ - - false - - - false - + + + + + diff --git a/Plugins/IW4ScriptCommands/Plugin.cs b/Plugins/IW4ScriptCommands/Plugin.cs index c21313d60..23091568a 100644 --- a/Plugins/IW4ScriptCommands/Plugin.cs +++ b/Plugins/IW4ScriptCommands/Plugin.cs @@ -1,13 +1,10 @@ -/*using SharedLibraryCore; +using SharedLibraryCore; using SharedLibraryCore.Interfaces; -using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace IW4ScriptCommands { - class Plugin : IPlugin + public class Plugin : IPlugin { public string Name => "IW4 Script Commands"; @@ -15,29 +12,29 @@ namespace IW4ScriptCommands public string Author => "RaidMax"; - public Task OnEventAsync(GameEvent E, Server S) + public async Task OnEventAsync(GameEvent E, Server S) { if (E.Type == GameEvent.EventType.Start) { - return S.SetDvarAsync("sv_iw4madmin_serverid", S.EndPoint); + await S.SetDvarAsync("sv_iw4madmin_serverid", S.EndPoint); } if (E.Type == GameEvent.EventType.Warn) { - return S.SetDvarAsync("sv_iw4madmin_command", new CommandInfo() + var cmd = new ScriptCommand() { ClientNumber = E.Target.ClientNumber, - Command = "alert", - CommandArguments = new List() + CommandName = "alert", + CommandArguments = new[] { "Warning", "ui_mp_nukebomb_timer", E.Data } - }.ToString()); + }; + // notifies the player ingame of the warning + await cmd.Execute(S); } - - return Task.CompletedTask; } public Task OnLoadAsync(IManager manager) => Task.CompletedTask; @@ -47,4 +44,3 @@ namespace IW4ScriptCommands public Task OnUnloadAsync() => Task.CompletedTask; } } -*/ \ No newline at end of file diff --git a/Plugins/IW4ScriptCommands/ScriptCommand.cs b/Plugins/IW4ScriptCommands/ScriptCommand.cs new file mode 100644 index 000000000..5b2e494bb --- /dev/null +++ b/Plugins/IW4ScriptCommands/ScriptCommand.cs @@ -0,0 +1,36 @@ +using SharedLibraryCore; +using System.Linq; +using System.Threading.Tasks; + +namespace IW4ScriptCommands +{ + /// + /// Contains basic properties for command information read by gsc + /// + class ScriptCommand + { + /// + /// Name of the command to execute + /// + public string CommandName { get; set; } + + /// + /// Target client number + /// + public int ClientNumber { get; set; } + + /// + /// Arguments for the script function itself + /// + public string[] CommandArguments { get; set; } = new string[0]; + + public override string ToString() => string.Join(";", new[] { CommandName, ClientNumber.ToString() }.Concat(CommandArguments).Select(_arg => _arg.Replace(";", ""))); + + /// + /// Executes the command + /// + /// server to execute the command on + /// + public async Task Execute(Server server) => await server.SetDvarAsync("sv_iw4madmin_command", ToString()); + } +} diff --git a/Plugins/ScriptPlugins/ParserCoD4x.js b/Plugins/ScriptPlugins/ParserCoD4x.js index d61670187..9b12a6aca 100644 --- a/Plugins/ScriptPlugins/ParserCoD4x.js +++ b/Plugins/ScriptPlugins/ParserCoD4x.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'FrenchFry, RaidMax', - version: 0.5, + version: 0.6, name: 'CoD4x Parser', isParser: true, @@ -11,8 +11,8 @@ var plugin = { }, onLoadAsync: function (manager) { - rconParser = manager.GenerateDynamicRConParser(); - eventParser = manager.GenerateDynamicEventParser(); + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){16,32}|(?:[a-z]|[0-9]){32}|bot[0-9]+) ([0-9+]) *(.{0,32}) +([0-9]+) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback) +(-*[0-9]+) +([0-9]+) *$' rconParser.Configuration.Status.AddMapping(104, 6); // RConName diff --git a/Plugins/ScriptPlugins/ParserIW4x.js b/Plugins/ScriptPlugins/ParserIW4x.js index 70f683b2d..3be55cb38 100644 --- a/Plugins/ScriptPlugins/ParserIW4x.js +++ b/Plugins/ScriptPlugins/ParserIW4x.js @@ -3,16 +3,16 @@ var eventParser; var plugin = { author: 'RaidMax', - version: 0.3, - name: 'IW4 Parser', + version: 0.4, + name: 'IW4x Parser', isParser: true, onEventAsync: function (gameEvent, server) { }, onLoadAsync: function (manager) { - rconParser = manager.GenerateDynamicRConParser(); - eventParser = manager.GenerateDynamicEventParser(); + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); rconParser.Configuration.CommandPrefixes.Tell = 'tellraw {0} {1}'; rconParser.Configuration.CommandPrefixes.Say = 'sayraw {0}'; diff --git a/Plugins/ScriptPlugins/ParserPT6.js b/Plugins/ScriptPlugins/ParserPT6.js index f9ecf53ab..2f3c8670b 100644 --- a/Plugins/ScriptPlugins/ParserPT6.js +++ b/Plugins/ScriptPlugins/ParserPT6.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax, Xerxes', - version: 0.5, + version: 0.6, name: 'Plutonium T6 Parser', isParser: true, @@ -11,8 +11,8 @@ var plugin = { }, onLoadAsync: function (manager) { - rconParser = manager.GenerateDynamicRConParser(); - eventParser = manager.GenerateDynamicEventParser(); + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); rconParser.Configuration.CommandPrefixes.Tell = 'tell {0} {1}'; rconParser.Configuration.CommandPrefixes.Say = 'say {0}'; diff --git a/Plugins/ScriptPlugins/ParserRektT5M.js b/Plugins/ScriptPlugins/ParserRektT5M.js index 40774e767..aa1e441a3 100644 --- a/Plugins/ScriptPlugins/ParserRektT5M.js +++ b/Plugins/ScriptPlugins/ParserRektT5M.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax', - version: 0.1, + version: 0.2, name: 'RektT5m Parser', isParser: true, @@ -11,12 +11,12 @@ var plugin = { }, onLoadAsync: function (manager) { - rconParser = manager.GenerateDynamicRConParser(); - eventParser = manager.GenerateDynamicEventParser(); + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); eventParser.Configuration.GameDirectory = 'data'; - rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xff\1print'; + rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xff\x01print'; rconParser.Configuration.CommandPrefixes.Tell = 'tell {0} {1}'; rconParser.Configuration.CommandPrefixes.RConGetInfo = undefined; diff --git a/Plugins/ScriptPlugins/ParserTeknoMW3.js b/Plugins/ScriptPlugins/ParserTeknoMW3.js index f78e97f54..793c8fff0 100644 --- a/Plugins/ScriptPlugins/ParserTeknoMW3.js +++ b/Plugins/ScriptPlugins/ParserTeknoMW3.js @@ -3,7 +3,7 @@ var eventParser; var plugin = { author: 'RaidMax', - version: 0.2, + version: 0.3, name: 'Tekno MW3 Parser', isParser: true, @@ -11,8 +11,8 @@ var plugin = { }, onLoadAsync: function (manager) { - rconParser = manager.GenerateDynamicRConParser(); - eventParser = manager.GenerateDynamicEventParser(); + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[A-Z]|[0-9]){16,32})\t +(.{0,16}) +([0-9]+) +(\\d+\\.\\d+\\.\\d+\\.\\d+\\:-?\\d{1,5}|0+\\.0+\\:-?\\d{1,5}|loopback) *$'; rconParser.Configuration.Status.AddMapping(104, 5); // RConName diff --git a/SharedLibraryCore/Configuration/ServerConfiguration.cs b/SharedLibraryCore/Configuration/ServerConfiguration.cs index f00e0ec4e..097ee62ab 100644 --- a/SharedLibraryCore/Configuration/ServerConfiguration.cs +++ b/SharedLibraryCore/Configuration/ServerConfiguration.cs @@ -58,7 +58,7 @@ namespace SharedLibraryCore.Configuration public void ModifyParsers() { var loc = Utilities.CurrentLocalization.LocalizationIndex; - var parserVersions = rconParsers.Select(_parser => _parser.Version).ToArray(); + var parserVersions = rconParsers.Select(_parser => _parser.Name).ToArray(); var selection = Utilities.PromptSelection($"{loc["SETUP_SERVER_RCON_PARSER_VERSION"]} ({IPAddress}:{Port})", $"{loc["SETUP_PROMPT_DEFAULT"]} (Call of Duty)", null, parserVersions); if (selection.Item1 >= 0) diff --git a/SharedLibraryCore/Interfaces/IEventParser.cs b/SharedLibraryCore/Interfaces/IEventParser.cs index fc12944e6..733b4de1c 100644 --- a/SharedLibraryCore/Interfaces/IEventParser.cs +++ b/SharedLibraryCore/Interfaces/IEventParser.cs @@ -31,5 +31,10 @@ namespace SharedLibraryCore.Interfaces /// specifies the connect URI used to join game servers via web browser /// string URLProtocolFormat { get; set; } + + /// + /// Specifies the text name of the game the parser is for + /// + string Name { get; set; } } } diff --git a/SharedLibraryCore/Interfaces/IManager.cs b/SharedLibraryCore/Interfaces/IManager.cs index dbd0167c2..b970a0905 100644 --- a/SharedLibraryCore/Interfaces/IManager.cs +++ b/SharedLibraryCore/Interfaces/IManager.cs @@ -6,7 +6,6 @@ using System.Reflection; using SharedLibraryCore.Database.Models; using System.Threading; using System.Collections; -using static SharedLibraryCore.GameEvent; namespace SharedLibraryCore.Interfaces { @@ -48,8 +47,20 @@ namespace SharedLibraryCore.Interfaces Task> ExecuteSharedDatabaseOperation(string operationName); void RegisterSharedDatabaseOperation(Task operation, string operationName); IMiddlewareActionHandler MiddlewareActionHandler { get; } - IRConParser GenerateDynamicRConParser(); - IEventParser GenerateDynamicEventParser(); + + /// + /// generates an rcon parser that can be configured by script plugins + /// + /// name of the RCon parser + /// new rcon parser instance + IRConParser GenerateDynamicRConParser(string name); + + /// + /// Generates an event parser that can be configured by script plugins + /// + /// name of the event parser + /// new event parser instance + IEventParser GenerateDynamicEventParser(string name); string Version { get;} ITokenAuthentication TokenAuthenticator { get; } string ExternalIPAddress { get; } diff --git a/SharedLibraryCore/Interfaces/IRConParser.cs b/SharedLibraryCore/Interfaces/IRConParser.cs index e7b2060db..916dca84a 100644 --- a/SharedLibraryCore/Interfaces/IRConParser.cs +++ b/SharedLibraryCore/Interfaces/IRConParser.cs @@ -61,5 +61,10 @@ namespace SharedLibraryCore.Interfaces /// of fs_game, fs_basepath, g_log /// bool CanGenerateLogPath { get; set; } + + /// + /// Specifies the name of the parser + /// + string Name { get; set; } } } diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index a0d37bc71..bd3efa8a2 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -28,7 +28,7 @@ namespace SharedLibraryCore.Services if (existingAliases.Count > 0) { - linkId = existingAliases.First().LinkId; + linkId = existingAliases.OrderBy(_alias => _alias.LinkId).First().LinkId; entity.CurrentServer.Logger.WriteDebug($"[create] client with new GUID {entity} has existing link {linkId}"); @@ -50,7 +50,6 @@ namespace SharedLibraryCore.Services NetworkId = entity.NetworkId }; - entity.CurrentServer.Logger.WriteDebug($"[create] adding {entity} to context"); context.Clients.Add(client);