Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions SharedLibraryCore/Commands/NativeCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,31 +1187,57 @@ public NextMapCommand(CommandConfiguration config, ITranslationLookup translatio

public static async Task<string> GetNextMap(Server s, ITranslationLookup lookup)
{
// FIRST: Try sv_maprotationcurrent (GSManager style)
var currentRotation = await s.GetDvarAsync<string>("sv_maprotationcurrent", token: s.Manager.CancellationToken);

if (!string.IsNullOrEmpty(currentRotation?.Value))
{
// Parse format: "gametype sd map mp_bloc ..."
var pattern = @"^\s*(?:gametype\s+([a-z]+)\s+)?map\s+([a-z0-9_.-]+)\s*(.*)$";
var match = Regex.Match(currentRotation.Value.ToLower(), pattern, RegexOptions.IgnoreCase);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wether or not to use regex to parse the map rotation is a question I'll leave to the maintainers
(the clients do not waste resources using regex: see iw4x-client map rotation.cpp, it's just easier to split the string by spaces and read the first token pair for map ).
Anyhow, you are already ignoring the case with the regex function so calling tolower() is a wasteful operation.


if (match.Success)
{
var gsNextMapName = match.Groups[2].Value;
var gsNextGametype = !string.IsNullOrEmpty(match.Groups[1].Value)
? match.Groups[1].Value
: s.Gametype;

var gsNextMap = s.Maps.FirstOrDefault(m =>
m.Name.Equals(gsNextMapName, StringComparison.InvariantCultureIgnoreCase)) ??
new Map { Alias = gsNextMapName, Name = gsNextMapName };

return lookup["COMMANDS_NEXTMAP_SUCCESS"].FormatExt(
gsNextMap.Alias,
Utilities.GetLocalizedGametype(gsNextGametype));
}
}

// SECOND: Original iw4madmin logic (fallback)
var mapRotation = (await s.GetDvarAsync<string>("sv_mapRotation", token: s.Manager.CancellationToken)).Value?.ToLower() ?? "";
var regexMatches = Regex.Matches(mapRotation,
@"((?:gametype|exec) +(?:([a-z]{1,4})(?:.cfg)?))? *map ([a-z|_|\d]+)", RegexOptions.IgnoreCase)
.ToList();

// find the current map in the rotation
var currentMap = regexMatches.Where(m => m.Groups[3].ToString() == s.CurrentMap.Name);
var lastMap = regexMatches.LastOrDefault();
Map nextMap = null;

// no maprotation at all
if (regexMatches.Count() == 0)
{
return lookup["COMMANDS_NEXTMAP_SUCCESS"]
.FormatExt(s.CurrentMap.Alias, Utilities.GetLocalizedGametype(s.Gametype));
}

// find the current map in the rotation
var currentMap = regexMatches.Where(m => m.Groups[3].ToString() == s.CurrentMap.Name);
var lastMap = regexMatches.LastOrDefault();
Map nextMap = null;

// the current map is not in rotation
if (currentMap.Count() == 0)
{
return lookup["COMMANDS_NEXTMAP_NOT_IN_ROTATION"];
}

// there's duplicate maps in rotation

if (currentMap.Count() > 1)
{
// gametype has been manually specified
Expand All @@ -1222,8 +1248,6 @@ public static async Task<string> GetNextMap(Server s, ITranslationLookup lookup)
{
currentMap = duplicateMaps.Where(m => m.Groups[2].ToString() == s.Gametype);
}

// else we just have to assume it's the first one
}

// if the current map is the last map, the next map is the first map
Expand Down