From 413570d0d42c4330e4b2551e2bce13700719f447 Mon Sep 17 00:00:00 2001 From: Diamante Date: Sat, 22 Mar 2025 15:30:23 +0100 Subject: [PATCH 1/5] chore: fix T5 parser for the upcoming update (#358) * chore: fix T5 parser for the upcoming update * chore: add credits * chore: fix credits for consistency elsewhere... Since I'm already here * fix credits here * andn here --- Plugins/ScriptPlugins/ParserBOIII.js | 2 +- Plugins/ScriptPlugins/ParserH1MOD.js | 2 +- Plugins/ScriptPlugins/ParserH2MMOD.js | 2 +- Plugins/ScriptPlugins/ParserPlutoniumT5.js | 18 +++++------------- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Plugins/ScriptPlugins/ParserBOIII.js b/Plugins/ScriptPlugins/ParserBOIII.js index b10b180f..8efa6803 100644 --- a/Plugins/ScriptPlugins/ParserBOIII.js +++ b/Plugins/ScriptPlugins/ParserBOIII.js @@ -2,7 +2,7 @@ var rconParser; var eventParser; var plugin = { - author: 'Diamante', + author: 'diamante0018', version: 0.3, name: 'BOIII Parser', isParser: true, diff --git a/Plugins/ScriptPlugins/ParserH1MOD.js b/Plugins/ScriptPlugins/ParserH1MOD.js index 722e1c5a..dc532727 100644 --- a/Plugins/ScriptPlugins/ParserH1MOD.js +++ b/Plugins/ScriptPlugins/ParserH1MOD.js @@ -2,7 +2,7 @@ var rconParser; var eventParser; var plugin = { - author: 'fed, diamante', + author: 'alice, diamante0018', version: 0.2, name: 'H1-Mod Parser', isParser: true, diff --git a/Plugins/ScriptPlugins/ParserH2MMOD.js b/Plugins/ScriptPlugins/ParserH2MMOD.js index 894e9f99..7c19cbd7 100644 --- a/Plugins/ScriptPlugins/ParserH2MMOD.js +++ b/Plugins/ScriptPlugins/ParserH2MMOD.js @@ -2,7 +2,7 @@ var rconParser; var eventParser; var plugin = { - author: "fed, diamante", + author: "alice, diamante0018", version: 0.2, name: "H2M-Mod Parser", isParser: true, diff --git a/Plugins/ScriptPlugins/ParserPlutoniumT5.js b/Plugins/ScriptPlugins/ParserPlutoniumT5.js index b681ce70..9d1d2fe5 100644 --- a/Plugins/ScriptPlugins/ParserPlutoniumT5.js +++ b/Plugins/ScriptPlugins/ParserPlutoniumT5.js @@ -2,9 +2,9 @@ var rconParser; var eventParser; var plugin = { - author: 'RaidMax', - version: 0.2, - name: 'Plutonium T5 Parser', + author: 'RaidMax, diamante0018, ineedbots', + version: 0.3, + name: 'Plutonium T5 Parser (2025)', isParser: true, onEventAsync: function (gameEvent, server) { @@ -13,22 +13,14 @@ var plugin = { onLoadAsync: function (manager) { rconParser = manager.GenerateDynamicRConParser(this.name); eventParser = manager.GenerateDynamicEventParser(this.name); - eventParser.Configuration.GameDirectory = ''; + eventParser.Configuration.GameDirectory = 'main'; rconParser.Configuration.DefaultInstallationDirectoryHint = '{LocalAppData}/Plutonium/storage/t5'; rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint\n'; rconParser.Configuration.Dvar.Pattern = '^(?:\\^7)?\\"(.+)\\" is: \\"(.+)?\\" default: \\"(.+)?\\"\\n?(?:latched: \\"(.+)?\\"\\n)?\\w*(.+)*$'; rconParser.Configuration.CommandPrefixes.Tell = 'tell {0} {1}'; - rconParser.Configuration.CommandPrefixes.RConGetInfo = undefined; rconParser.Configuration.GuidNumberStyle = 7; // Integer - rconParser.Configuration.DefaultRConPort = 3074; - rconParser.Configuration.OverrideDvarNameMapping.Add('fs_homepath', 'fs_basegame'); - rconParser.Configuration.CanGenerateLogPath = false; - - rconParser.Configuration.OverrideCommandTimeouts.Clear(); - rconParser.Configuration.OverrideCommandTimeouts.Add('map', 0); - rconParser.Configuration.OverrideCommandTimeouts.Add('map_rotate', 0); - rconParser.Configuration.OverrideCommandTimeouts.Add('fast_restart', 0); + rconParser.Configuration.DefaultRConPort = 28960; rconParser.Version = 'Call of Duty Multiplayer - Ship COD_T5_S MP build 7.0.189 CL(1022875) CODPCAB-V64 CEG Wed Nov 02 18:02:23 2011 win-x86'; rconParser.GameName = 6; // T5 From 081c522b960909f7f3148df2bdbeb4764900b991 Mon Sep 17 00:00:00 2001 From: m Date: Mon, 14 Apr 2025 22:34:22 -0400 Subject: [PATCH 2/5] add iw7-mod RCON support (#361) * create iw7-mod parser * iw7 default settings & enum stuff * add zm maps to defaultsettings --- Application/DefaultSettings.json | 234 ++++++++++++++++++++++++++ Data/Models/Reference.cs | 3 +- IW4MAdmin.sln | 1 + Plugins/ScriptPlugins/ParserIW7MOD.js | 43 +++++ Plugins/ScriptPlugins/ServerBanner.js | 3 + SharedLibraryCore/Server.cs | 3 +- 6 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 Plugins/ScriptPlugins/ParserIW7MOD.js diff --git a/Application/DefaultSettings.json b/Application/DefaultSettings.json index 12e0a8f9..ee1b78a8 100644 --- a/Application/DefaultSettings.json +++ b/Application/DefaultSettings.json @@ -723,6 +723,83 @@ "Alias": "Team Deathmatch" } ] + }, + { + "Game": "IW7", + "Gametypes": [ + { + "Name": "war", + "Alias": "Team Deathmatch" + }, + { + "Name": "front", + "Alias": "Frontline" + }, + { + "Name": "dom", + "Alias": "Domination" + }, + { + "Name": "sd", + "Alias": "Search and Destroy" + }, + { + "Name": "conf", + "Alias": "Kill Confirmed" + }, + { + "Name": "dm", + "Alias": "Free For All" + }, + { + "Name": "koth", + "Alias": "Hardpoint" + }, + { + "Name": "tdef", + "Alias": "Defender" + }, + { + "Name": "ball", + "Alias": "Uplink" + }, + { + "Name": "dd", + "Alias": "Demolition" + }, + { + "Name": "ctf", + "Alias": "Capture The Flag" + }, + { + "Name": "sr", + "Alias": "Search and Rescue" + }, + { + "Name": "siege", + "Alias": "Reinforce" + }, + { + "Name": "grind", + "Alias": "Grind" + }, + { + "Name": "infect", + "Alias": "Infected" + }, + { + "Name": "gun", + "Alias": "Gun Game" + }, + { + "Name": "grnd", + "Alias": "Drop Zone" + }, + { + "Name": "zombies", + "Alias": "Zombies" + } + ] } ], "Maps": [ @@ -2601,6 +2678,163 @@ "Alias": "Sirocco" } ] + }, + { + "Game": "IW7", + "Maps": [ + { + "Alias": "Frontier", + "Name": "mp_frontier" + }, + { + "Alias": "Dominion", + "Name": "mp_afghan" + }, + { + "Alias": "Depot 22", + "Name": "mp_depot" + }, + { + "Alias": "Excess", + "Name": "mp_flip" + }, + { + "Alias": "Renaissance", + "Name": "mp_geneva" + }, + { + "Alias": "Renaissance (Free)", + "Name": "mp_renaissance2" + }, + { + "Alias": "Heartland", + "Name": "mp_hawkwar" + }, + { + "Alias": "Scrap", + "Name": "mp_junk" + }, + { + "Alias": "Archive", + "Name": "mp_mansion" + }, + { + "Alias": "Turista", + "Name": "mp_marsoasis" + }, + { + "Alias": "Turista (Summer)", + "Name": "mp_turista2" + }, + { + "Alias": "Neon", + "Name": "mp_neon" + }, + { + "Alias": "Bermuda", + "Name": "mp_nova" + }, + { + "Alias": "Permafrost", + "Name": "mp_overflow" + }, + { + "Alias": "Permafrost (Free)", + "Name": "mp_permafrost2" + }, + { + "Alias": "Ember", + "Name": "mp_paris" + }, + { + "Alias": "Fore", + "Name": "mp_pixel" + }, + { + "Alias": "Noir", + "Name": "mp_prime" + }, + { + "Alias": "Carnage", + "Name": "mp_rally" + }, + { + "Alias": "Carnage (Free)", + "Name": "mp_carnage2" + }, + { + "Alias": "Breakout", + "Name": "mp_parkour" + }, + { + "Alias": "Frost", + "Name": "mp_proto" + }, + { + "Alias": "Crusher", + "Name": "mp_quarry" + }, + { + "Alias": "Retaliation", + "Name": "mp_riot" + }, + { + "Alias": "Skydock", + "Name": "mp_rivet" + }, + { + "Alias": "Terminal", + "Name": "mp_skyway" + }, + { + "Alias": "Mayday", + "Name": "mp_breakneck" + }, + { + "Alias": "Altitude", + "Name": "mp_codphish" + }, + { + "Alias": "Grounded", + "Name": "mp_desert" + }, + { + "Alias": "Scorch", + "Name": "mp_divide" + }, + { + "Alias": "Genesis", + "Name": "mp_dome_iw" + }, + { + "Alias": "Throwback", + "Name": "mp_fallen" + }, + { + "Alias": "Precinct", + "Name": "mp_metropolis" + }, + { + "Alias": "Zombies in Spaceland", + "Name": "cp_zmb" + }, + { + "Alias": "Shaolin Shuffle", + "Name": "cp_disco" + }, + { + "Alias": "The Beast From Beyond", + "Name": "cp_final" + }, + { + "Alias": "Rave in the Redwoods", + "Name": "cp_rave" + }, + { + "Alias": "Radioactive Thing", + "Name": "cp_town" + } + ] } ], "GameStrings": { diff --git a/Data/Models/Reference.cs b/Data/Models/Reference.cs index 51e98753..70224fd2 100644 --- a/Data/Models/Reference.cs +++ b/Data/Models/Reference.cs @@ -18,7 +18,8 @@ CSGO = 10, H1 = 11, L4D2 = 12, - H2M = 13 + H2M = 13, + IW7 = 14 } public enum ConnectionType diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index ec2209b5..9f49da74 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -53,6 +53,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlug Plugins\ScriptPlugins\ParserL4D2SM.js = Plugins\ScriptPlugins\ParserL4D2SM.js Plugins\ScriptPlugins\ParserPlutoniumT6.js = Plugins\ScriptPlugins\ParserPlutoniumT6.js Plugins\ScriptPlugins\ParserH2MMOD.js = Plugins\ScriptPlugins\ParserH2MMOD.js + Plugins\ScriptPlugins\ParserIW7MOD.js = Plugins\ScriptPlugins\ParserIW7MOD.js EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutomessageFeed", "Plugins\AutomessageFeed\AutomessageFeed.csproj", "{F5815359-CFC7-44B4-9A3B-C04BACAD5836}" diff --git a/Plugins/ScriptPlugins/ParserIW7MOD.js b/Plugins/ScriptPlugins/ParserIW7MOD.js new file mode 100644 index 00000000..66ecd833 --- /dev/null +++ b/Plugins/ScriptPlugins/ParserIW7MOD.js @@ -0,0 +1,43 @@ +var rconParser; +var eventParser; + +var plugin = { + author: 'mjkzy', + version: 0.1, + name: 'IW7-Mod Parser', + isParser: true, + + onEventAsync: function(gameEvent, server) {}, + + onLoadAsync: function(manager) { + rconParser = manager.GenerateDynamicRConParser(this.name); + eventParser = manager.GenerateDynamicEventParser(this.name); + + rconParser.Configuration.CommandPrefixes.Kick = 'kickClient {0} "{1}"'; + rconParser.Configuration.CommandPrefixes.Ban = 'kickClient {0} "{1}"'; + rconParser.Configuration.CommandPrefixes.TempBan = 'kickClient {0} "{1}"'; + rconParser.Configuration.CommandPrefixes.Tell = 'tellraw {0} "{1}"'; + rconParser.Configuration.CommandPrefixes.Say = 'sayraw "{0}"'; + rconParser.Configuration.CommandPrefixes.RConResponse = '\xff\xff\xff\xffprint'; + rconParser.Configuration.Dvar.Pattern = '^ *\\"(.+)\\" is: \\"(.+)?\\" default: \\"(.+)?\\"'; + rconParser.Configuration.Status.Pattern = '^ *([0-9]+) +-?([0-9]+) +(Yes|No) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +(\\d+\\.\\d+\\.\\d+.\\d+\\:-*\\d{1,5}|0+.0+:-*\\d{1,5}|loopback|unknown|bot) +(-*[0-9]+) *$'; + rconParser.Configuration.StatusHeader.Pattern = 'num +score +bot +ping +guid +name +address +qport *'; + rconParser.Configuration.Status.AddMapping(102, 4); + rconParser.Configuration.Status.AddMapping(103, 5); + rconParser.Configuration.Status.AddMapping(104, 6); + rconParser.Configuration.WaitForResponse = false; + rconParser.Configuration.DefaultRConPort = 27016; + + eventParser.Configuration.GameDirectory = ''; + eventParser.Configuration.LocalizeText = '\x1f'; + + rconParser.Version = 'IW7 6.23 build 1435251 Tue Apr 17 18:34:00 2018 win64'; + rconParser.GameName = 14; // IW7 + eventParser.Version = 'IW7 6.23 build 1435251 Tue Apr 17 18:34:00 2018 win64'; + eventParser.GameName = 14; // IW7 + }, + + onUnloadAsync: function() {}, + + onTickAsync: function(server) {} +}; diff --git a/Plugins/ScriptPlugins/ServerBanner.js b/Plugins/ScriptPlugins/ServerBanner.js index 710d3cce..f80dfa02 100644 --- a/Plugins/ScriptPlugins/ServerBanner.js +++ b/Plugins/ScriptPlugins/ServerBanner.js @@ -127,6 +127,9 @@ const plugin = { 'h2m': { right: colorLeft }, + 'iw7': { + right: colorLeft + } }; const servers = plugin.manager.servers; diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 5be70f27..5a9d99c8 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -37,7 +37,8 @@ namespace SharedLibraryCore CSGO = 10, H1 = 11, L4D2 = 12, - H2M = 13 + H2M = 13, + IW7 = 14 } // only here for performance From 072e6da4d1ca80ecbd8a66ca29e5fe0107e73e78 Mon Sep 17 00:00:00 2001 From: Amos Date: Mon, 12 May 2025 01:13:41 +0100 Subject: [PATCH 3/5] Utilise Minutes in TempBan for under 1 hour bans. (#362) * Update tempban command to use minutes instead of hours The duration calculation for tempbans now uses minutes rather than hours for greater precision. This change ensures better alignment with user expectations and configurations in smaller timeframes. * Update regex patterns to enforce stricter input validation Adjusted regex in `ParseTimespan` and `TempBanCommand` to ensure input starts with 1-5 numeric characters, improving validation. This prevents malformed user inputs and enhances overall command reliability. * \w includes digits. Who knew. --- SharedLibraryCore/Commands/NativeCommands.cs | 2 +- SharedLibraryCore/Utilities.cs | 2 +- WebfrontCore/Controllers/ActionController.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index ae2879c6..e04e695d 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -229,7 +229,7 @@ namespace SharedLibraryCore.Commands /// public class TempBanCommand : Command { - private static readonly string TempBanRegex = @"([0-9]+\w+)\ (.+)"; + private static readonly string TempBanRegex = @"^([0-9]{1,5}\p{L}+)\ (.+)"; private readonly ApplicationConfiguration _appConfig; public TempBanCommand(ApplicationConfiguration appConfig, CommandConfiguration config, diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index ee47a773..08166367 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -510,7 +510,7 @@ namespace SharedLibraryCore public static TimeSpan ParseTimespan(this string input) { - var expressionMatch = Regex.Match(input, @"([0-9]+)(\w+)"); + var expressionMatch = Regex.Match(input, @"^([0-9]{1,5})(\p{L}+)"); if (!expressionMatch.Success) // fallback to default tempban length of 1 hour { diff --git a/WebfrontCore/Controllers/ActionController.cs b/WebfrontCore/Controllers/ActionController.cs index 338e62fa..8e8d761d 100644 --- a/WebfrontCore/Controllers/ActionController.cs +++ b/WebfrontCore/Controllers/ActionController.cs @@ -312,8 +312,8 @@ namespace WebfrontCore.Controllers else { var durationSpan = _appConfig.BanDurations[duration - 1]; - var durationValue = durationSpan.TotalHours.ToString(CultureInfo.InvariantCulture) + - Localization["GLOBAL_TIME_HOURS"][0]; + var durationValue = durationSpan.TotalMinutes.ToString(CultureInfo.InvariantCulture) + + Localization["GLOBAL_TIME_MINUTES"][0]; command = $"{_appConfig.CommandPrefix}{_tempbanCommandName} @{targetId} {durationValue} {fallthroughReason}"; } From 604aba628d025948f99577c72ae2f4898ebece96 Mon Sep 17 00:00:00 2001 From: HGM Date: Sun, 11 May 2025 23:45:17 +0100 Subject: [PATCH 4/5] Added maps for H2M Nightshade DLC Updated to add new H2M MW3 Nightshade DLC Maps --- Application/DefaultSettings.json | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Application/DefaultSettings.json b/Application/DefaultSettings.json index ee1b78a8..b2d2ea3a 100644 --- a/Application/DefaultSettings.json +++ b/Application/DefaultSettings.json @@ -2531,6 +2531,42 @@ { "Alias": "Wasteland", "Name": "mp_brecourt" + }, + { + "Alias": "Dome", + "Name": "mp_dome" + }, + { + "Alias": "Bootleg", + "Name": "mp_bootleg" + }, + { + "Alias": "Fallen", + "Name": "mp_lambeth" + }, + { + "Alias": "Hardhat", + "Name": "mp_hardhat" + }, + { + "Alias": "Lockdown", + "Name": "mp_alpha" + }, + { + "Alias": "Mission", + "Name": "mp_bravo" + }, + { + "Alias": "Resistance", + "Name": "mp_paris" + }, + { + "Alias": "Underground", + "Name": "mp_underground" + }, + { + "Alias": "Erosion", + "Name": "mp_courtyard_ss" } ] }, From 3e186ca07aefff9c9ace7e54d97a9bc6dd8b53a7 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 24 May 2025 15:36:24 -0500 Subject: [PATCH 5/5] Add ResolvedExternalIPAddress to API and Master Communication (#365) * Feature: Add ResolvedExternalIPAddress to API and Master Communication This commit introduces the `ResolvedExternalIPAddress` property to enhance IP address reporting. 1. **Server API (`WebfrontCore/Controllers/API/Server.cs`):** The `ResolvedExternalIPAddress` property has been added to the JSON responses for the `/api/server` endpoints. This property is nullable and contains the IPv4 string value of the manager's external IP address if the server's resolved IP endpoint is an internal address. Otherwise, it is null. 2. **Master Server Communication (`MasterCommunication.cs` and `ApiServer.cs`):** - The `ApiServer` DTO (in `Application/API/Master/ApiServer.cs`) now includes the `ResolvedExternalIPAddress` property (serialized as `resolved_external_ip_address`). - The `UploadStatus` method in `Application/Misc/MasterCommunication.cs` now populates this property for each server being reported to the master server, using the same logic (external IP if server's own resolved IP is internal). This provides more comprehensive IP address information both through the web API and to the master server. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- Application/API/Master/ApiServer.cs | 2 ++ Application/Misc/MasterCommunication.cs | 3 ++- SharedLibraryCore/Dtos/ServerInfo.cs | 1 + WebfrontCore/Controllers/API/Server.cs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Application/API/Master/ApiServer.cs b/Application/API/Master/ApiServer.cs index 4c2fe3ca..212c149c 100644 --- a/Application/API/Master/ApiServer.cs +++ b/Application/API/Master/ApiServer.cs @@ -24,5 +24,7 @@ namespace IW4MAdmin.Application.API.Master public int ClientNum { get; set; } [JsonPropertyName("maxclientnum")] public int MaxClientNum { get; set; } + [JsonPropertyName("resolved_external_ip_address")] + public string? ResolvedExternalIPAddress { get; set; } } } diff --git a/Application/Misc/MasterCommunication.cs b/Application/Misc/MasterCommunication.cs index 86adc1a6..5b537411 100644 --- a/Application/Misc/MasterCommunication.cs +++ b/Application/Misc/MasterCommunication.cs @@ -149,7 +149,8 @@ namespace IW4MAdmin.Application.Misc MaxClientNum = s.MaxClients, Id = s.EndPoint, Port = (short)s.ListenPort, - IPAddress = s.ListenAddress + IPAddress = s.ListenAddress, + ResolvedExternalIPAddress = s.ResolvedIpEndPoint.Address.IsInternal() ? _manager.ExternalIPAddress : null }).ToList(), WebfrontUrl = _appConfig.WebfrontUrl }; diff --git a/SharedLibraryCore/Dtos/ServerInfo.cs b/SharedLibraryCore/Dtos/ServerInfo.cs index 5b4c304c..3b3a0125 100644 --- a/SharedLibraryCore/Dtos/ServerInfo.cs +++ b/SharedLibraryCore/Dtos/ServerInfo.cs @@ -25,6 +25,7 @@ namespace SharedLibraryCore.Dtos public string IPAddress { get; set; } public string ExternalIPAddress { get; set; } public bool IsPasswordProtected { get; set; } + public string? ResolvedExternalIPAddress { get; set; } public string Endpoint => $"{IPAddress}:{Port}"; public double? LobbyZScore diff --git a/WebfrontCore/Controllers/API/Server.cs b/WebfrontCore/Controllers/API/Server.cs index 519744fa..83e76701 100644 --- a/WebfrontCore/Controllers/API/Server.cs +++ b/WebfrontCore/Controllers/API/Server.cs @@ -39,6 +39,7 @@ namespace WebfrontCore.Controllers.API name = server.GametypeName }, Parser = server.RconParser.Name, + ResolvedExternalIPAddress = server.ResolvedIpEndPoint.Address.IsInternal() ? Manager.ExternalIPAddress : null, })); } @@ -68,6 +69,7 @@ namespace WebfrontCore.Controllers.API name = foundServer.GametypeName }, Parser = foundServer.RconParser.Name, + ResolvedExternalIPAddress = foundServer.ResolvedIpEndPoint.Address.IsInternal() ? Manager.ExternalIPAddress : null }); }