From 8c5a60dccd3fa892b3022086db65feb610fce799 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 8 Mar 2023 13:13:30 +0700 Subject: [PATCH] Refactor map replacement to be done by separate object --- sources/MapList/MapTool.uc | 187 ++++++++++++++++++++++++++++++++ sources/VotingHandlerAdapter.uc | 132 ++-------------------- 2 files changed, 194 insertions(+), 125 deletions(-) create mode 100644 sources/MapList/MapTool.uc diff --git a/sources/MapList/MapTool.uc b/sources/MapList/MapTool.uc new file mode 100644 index 0000000..a1d8dc8 --- /dev/null +++ b/sources/MapList/MapTool.uc @@ -0,0 +1,187 @@ +/** + * Copyright 2023 Anton Tarasenko + *------------------------------------------------------------------------------ + * This file is part of Acedia. + * + * Acedia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + * + * Acedia is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Acedia. If not, see . + */ +class MapTool extends AcediaObject; + +// Finding voting handler is not cheap, so only do it once and then store it. +var private NativeActorRef votingHandlerReference; +// Maps map pseudonims we've used in voting handler to real map names +var private HashTable pseudonimToMap; +var private array outputMapList; +var private int gameModesSeen; + +protected function Constructor() { + pseudonimToMap = _.collections.EmptyHashTable(); +} + +protected function Finalizer() { + _.memory.Free(votingHandlerReference); + _.memory.Free(pseudonimToMap); + votingHandlerReference = none; + pseudonimToMap = none; + outputMapList.length = 0; + gameModesSeen = 0; +} + +public function bool Initialize(NativeActorRef initVotingHandlerReference) { + if (initVotingHandlerReference == none) return false; + if (XVotingHandler(initVotingHandlerReference.Get()) == none) return false; + + initVotingHandlerReference.NewRef(); + votingHandlerReference = initVotingHandlerReference; + return true; +} + +public function string LoadGameModeMaps(GameMode gameMode) { + local int i; + local XVotingHandler votingHandler; + local ArrayList gameModeMaps; + local Text mapNameReal, mapNamePseudonim; + local VotingHandler.MapHistoryInfo nextMapInfo; + local VotingHandler.MapVoteMapList nextRecord; + local array newMaps; + local string gameModePrefix; + + votingHandler = GetVotingHandler(); + if (votingHandler == none) { + return "!!!"; + } + gameModePrefix = ("KF" $ gameModesSeen); + nextRecord.bEnabled = true; + gameModeMaps = GetAllGameModeMaps(gameMode); + for (i = 0; i < gameModeMaps.GetLength(); i += 1) { + // Make a pseudonim to map connection + mapNameReal = gameModeMaps.GetText(i); + mapNamePseudonim = MakeMapPseudonim(mapNameReal, gameModePrefix); + pseudonimToMap.SetItem(mapNamePseudonim, mapNameReal); + // Setup `VotingHandler.MapVoteMapList` struct for next map + nextRecord.mapName = mapNamePseudonim.ToString(); + if (votingHandler.history != none) { + nextMapInfo = votingHandler.history.GetMapHistory(mapNameReal.ToString()); + nextRecord.playCount = nextMapInfo.p; + nextRecord.sequence = nextMapInfo.s; + } else { + nextRecord.playCount = 0; + nextRecord.sequence = 0; + } + newMaps[newMaps.length] = nextRecord; + } + AppendMapsIntoHandler(newMaps); + gameModesSeen += 1; + return gameModePrefix; +} + +private function Text MakeMapPseudonim(Text realName, string gameModePrefix) { + local Parser parser; + local MutableText prefix, nameBody; + local MutableText result; + + result = _.text.FromStringM(gameModePrefix); + result.Append(P("-")); + parser = realName.Parse(); + parser.MUntil(prefix, _.text.GetCharacter("-")); + parser.Match(P("-")); + if (parser.Ok()) { + nameBody = parser.GetRemainderM(); + result.Append(nameBody); + } + else { + result.Append(realName); + } + _.memory.Free(nameBody); + _.memory.Free(prefix); + _.memory.Free(parser); + return result.IntoText(); +} + +private function ArrayList GetAllGameModeMaps(GameMode gameMode) { + local int i, j; + local HashTable uniqueMapSet; + local ArrayList result; + local array usedMapLists; + local MapList nextMapConfig; + local array nextMapArray; + local Text nextMapName, lowerMapName; + + uniqueMapSet = _.collections.EmptyHashTable(); // to quickly make sure we add each map only once + result = _.collections.EmptyArrayList(); + usedMapLists = gameMode.GetIncludedMapLists(); + for (i = 0; i < usedMapLists.length; i += 1) { + // Get maps from `MapList` config + nextMapConfig = MapList(class'MapList'.static.GetConfigInstance(usedMapLists[i])); + nextMapArray.length = 0; + if (nextMapConfig != none) { + nextMapArray = nextMapConfig.map; + } else { + //_.logger.Auto(warnMissingMapList).Arg(usedMapLists[i].Copy()); + } + _.memory.Free(nextMapConfig); + // Add maps we haven't yet added from other lists + for (j = 0; j < nextMapArray.length; j += 1) { + nextMapName = _.text.FromString(nextMapArray[j]); + lowerMapName = nextMapName.LowerCopy(); + if (!uniqueMapSet.HasKey(lowerMapName)) { + uniqueMapSet.SetItem(lowerMapName, none); + result.AddItem(nextMapName); + } + _.memory.Free(lowerMapName); + _.memory.Free(nextMapName); + } + } + _.memory.Free(uniqueMapSet); + _.memory.FreeMany(usedMapLists); + return result; +} + +private function AppendMapsIntoHandler(array newMaps) { + local int i; + local XVotingHandler votingHandler; + + votingHandler = GetVotingHandler(); + if (votingHandler == none) { + warn("votingHandler is none!"); + return; + } + if (newMaps.length == 0) { + warn("newMaps.length is 0!"); + return; + } + for (i = 0; i < newMaps.length; i += 1) { + outputMapList[outputMapList.length] = newMaps[i]; + } +} + +public final function InjectMaps() { + local XVotingHandler votingHandler; + + votingHandler = GetVotingHandler(); + if (votingHandler != none) { + votingHandler.mapList = outputMapList; + votingHandler.mapCount = outputMapList.length; + } +} + +private function XVotingHandler GetVotingHandler() { + if (votingHandlerReference != none) { + return XVotingHandler(votingHandlerReference.Get()); + } + return none; +} + +defaultproperties { +} \ No newline at end of file diff --git a/sources/VotingHandlerAdapter.uc b/sources/VotingHandlerAdapter.uc index b2936c7..e338685 100644 --- a/sources/VotingHandlerAdapter.uc +++ b/sources/VotingHandlerAdapter.uc @@ -66,9 +66,6 @@ var private NativeActorRef votingHandlerReference; // otherwise Acedia will alter its config var private array backupVotingHandlerConfig; -// Maps map pseudonims we've used in voting handler to real map names -var private HashTable pseudonimToMap; - // Setting value of this flag to `true` indicates that map switching just // occurred and we need to recover some information from the previous map. var private config bool isServerTraveling; @@ -113,6 +110,7 @@ public final function InjectIntoVotingHandler() local GameMode nextGameMode; local XVotingHandler votingHandler; local array newVotingHandlerConfig; + local MapTool mapTool; if (votingHandlerReference != none) { return; @@ -124,17 +122,17 @@ public final function InjectIntoVotingHandler() _.logger.Auto(fatNoXVotingHandler); return; } - pseudonimToMap = _.collections.EmptyHashTable(); votingHandlerReference = _server.unreal.ActorRef(votingHandler); + mapTool = MapTool(_.memory.Allocate(class'MapTool')); + mapTool.Initialize(votingHandlerReference); //TODO check return value availableGameModes = class'GameMode'.static.AvailableConfigs(); votingHandler.mapCount = 0; votingHandler.mapList.length = 0; for (i = 0; i < availableGameModes.length; i += 1) { - nextGameModePrefix = "GM" $ i; nextGameMode = GameMode(class'GameMode'.static .GetConfigInstance(availableGameModes[i])); + nextGameModePrefix = mapTool.LoadGameModeMaps(nextGameMode); newVotingHandlerConfig[i] = BuildVotingHandlerConfig(nextGameMode, nextGameModePrefix); - LoadGameModeMaps(nextGameMode, nextGameModePrefix, votingHandler); // Setup proper game mode index if (availableGameModes[i].ToString() == targetGameMode) { votingHandler.currentGameConfig = i; @@ -142,128 +140,12 @@ public final function InjectIntoVotingHandler() // Report omitted mutators / server options nextGameMode.ReportBadMutatorNames(); nextGameMode.ReportBadOptions(); + _.memory.Free(nextGameMode); } backupVotingHandlerConfig = votingHandler.gameConfig; votingHandler.gameConfig = newVotingHandlerConfig; -} - -private function LoadGameModeMaps( - GameMode gameMode, - string gameModePrefix, - XVotingHandler votingHandler -) { - local int i; - local ArrayList gameModeMaps; - local Text mapNameReal, mapNamePseudonim; - local VotingHandler.MapHistoryInfo nextMapInfo; - local VotingHandler.MapVoteMapList nextRecord; - local array newMaps; - - nextRecord.bEnabled = true; - gameModeMaps = GetAllGameModeMaps(gameMode); - for (i = 0; i < gameModeMaps.GetLength(); i += 1) { - // Make a pseudonim to map connection - mapNameReal = gameModeMaps.GetText(i); - mapNamePseudonim = MakeMapPseudonim(mapNameReal, gameModePrefix); - pseudonimToMap.SetItem(mapNamePseudonim, mapNameReal); - // Setup `VotingHandler.MapVoteMapList` struct for next map - nextRecord.mapName = mapNamePseudonim.ToString(); - if (votingHandler.history != none) { - nextMapInfo = votingHandler.history.GetMapHistory(nextRecord.mapName); - nextRecord.playCount = nextMapInfo.p; - nextRecord.sequence = nextMapInfo.s; - } else { - nextRecord.playCount = 0; - nextRecord.sequence = 0; - } - newMaps[newMaps.length] = nextRecord; - } - AppendMapsIntoHandler(votingHandler, newMaps); -} - -private function Text MakeMapPseudonim(Text realName, string gameModePrefix) { - local Parser parser; - local MutableText prefix, nameBody; - local MutableText result; - - result = _.text.FromStringM(gameModePrefix); - result.Append(P("-")); - parser = realName.Parse(); - parser.MUntil(prefix, _.text.GetCharacter("-")); - parser.Match(P("-")); - if (parser.Ok()) { - nameBody = parser.GetRemainderM(); - result.Append(nameBody); - } - else { - result.Append(realName); - } - _.memory.Free(nameBody); - _.memory.Free(prefix); - _.memory.Free(parser); - return result.IntoText(); -} - -private function ArrayList GetAllGameModeMaps(GameMode gameMode) { - local int i, j; - local HashTable uniqueMapSet; - local ArrayList result; - local array usedMapLists; - local MapList nextMapConfig; - local array nextMapArray; - local Text nextMapName, lowerMapName; - - uniqueMapSet = _.collections.EmptyHashTable(); // to quickly make sure we add each map only once - result = _.collections.EmptyArrayList(); - usedMapLists = gameMode.GetIncludedMapLists(); - for (i = 0; i < usedMapLists.length; i += 1) { - // Get maps from `MapList` config - nextMapConfig = MapList(class'MapList'.static.GetConfigInstance(usedMapLists[i])); - nextMapArray.length = 0; - if (nextMapConfig != none) { - nextMapArray = nextMapConfig.map; - } else { - _.logger.Auto(warnMissingMapList).Arg(usedMapLists[i].Copy()); - } - _.memory.Free(nextMapConfig); - // Add maps we haven't yet added from other lists - for (j = 0; j < nextMapArray.length; j += 1) { - nextMapName = _.text.FromString(nextMapArray[j]); - lowerMapName = nextMapName.LowerCopy(); - if (!uniqueMapSet.HasKey(lowerMapName)) { - uniqueMapSet.SetItem(lowerMapName, none); - result.AddItem(nextMapName); - } - _.memory.Free(lowerMapName); - _.memory.Free(nextMapName); - } - } - _.memory.Free(uniqueMapSet); - _.memory.FreeMany(usedMapLists); - return result; -} - -private function AppendMapsIntoHandler( - XVotingHandler votingHandler, - array newMaps -) { - local int i; - local array mapListCopy; - - if (votingHandler == none) { - warn("votingHandler is none!"); - return; - } - if (newMaps.length == 0) { - warn("newMaps.length is 0!"); - return; - } - mapListCopy = votingHandler.mapList; - for (i = 0; i < newMaps.length; i += 1) { - mapListCopy[mapListCopy.length] = newMaps[i]; - } - votingHandler.mapList = mapListCopy; - votingHandler.mapCount += newMaps.length; + mapTool.InjectMaps(); + _.memory.Free(mapTool); } private function VotingHandler.MapVoteGameConfig BuildVotingHandlerConfig(