You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
8.3 KiB
238 lines
8.3 KiB
/** |
|
* 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 <https://www.gnu.org/licenses/>. |
|
*/ |
|
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<VotingHandler.MapVoteMapList> pseudonimMapList; |
|
var private array<VotingHandler.MapVoteMapList> realMapList; |
|
var private int gameModesSeen; |
|
|
|
var private string backupMessageMapWon; |
|
var private string backupMessageAdminMapChange; |
|
var private const string ACEDIA_MAP_FORCED_COMMAND; |
|
var private const string ACEDIA_MAP_WON_COMMAND; |
|
|
|
protected function Constructor() { |
|
pseudonimToMap = _.collections.EmptyHashTable(); |
|
} |
|
|
|
protected function Finalizer() { |
|
_server.unreal.broadcasts.OnHandleText(self).Disconnect(); |
|
_.memory.Free(votingHandlerReference); |
|
_.memory.Free(pseudonimToMap); |
|
votingHandlerReference = none; |
|
pseudonimToMap = none; |
|
pseudonimMapList.length = 0; |
|
realMapList.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<VotingHandler.MapVoteMapList> newMapsPseudonim, newMapReal; |
|
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 |
|
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; |
|
} |
|
nextRecord.mapName = mapNamePseudonim.ToString(); |
|
newMapsPseudonim[newMapsPseudonim.length] = nextRecord; |
|
nextRecord.mapName = mapNameReal.ToString(); |
|
newMapReal[newMapReal.length] = nextRecord; |
|
} |
|
AppendMaps(newMapsPseudonim, newMapReal); |
|
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<Text> usedMapLists; |
|
local MapList nextMapConfig; |
|
local array<string> 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 AppendMaps( |
|
array<VotingHandler.MapVoteMapList> newMapsPseudonim, |
|
array<VotingHandler.MapVoteMapList> newMapsReal) { |
|
local int i; |
|
local XVotingHandler votingHandler; |
|
|
|
votingHandler = GetVotingHandler(); |
|
if (votingHandler == none) { |
|
warn("votingHandler is none!"); |
|
return; |
|
} |
|
for (i = 0; i < newMapsPseudonim.length; i += 1) { |
|
pseudonimMapList[pseudonimMapList.length] = newMapsPseudonim[i]; |
|
} |
|
for (i = 0; i < newMapsReal.length; i += 1) { |
|
realMapList[realMapList.length] = newMapsReal[i]; |
|
} |
|
} |
|
|
|
public final function InjectMaps() { |
|
local XVotingHandler votingHandler; |
|
|
|
votingHandler = GetVotingHandler(); |
|
if (votingHandler != none) { |
|
votingHandler.mapList = pseudonimMapList; |
|
votingHandler.mapCount = pseudonimMapList.length; |
|
backupMessageMapWon = votingHandler.lmsgMapWon; |
|
backupMessageAdminMapChange = votingHandler.lmsgAdminMapChange; |
|
votingHandler.lmsgMapWon = ACEDIA_MAP_WON_COMMAND $ "::%mapname%"; |
|
votingHandler.lmsgAdminMapChange = ACEDIA_MAP_FORCED_COMMAND $ "::%mapname%"; |
|
_server.unreal.broadcasts.OnHandleText(self).connect = HandleMapChange; |
|
} |
|
} |
|
|
|
private function bool HandleMapChange( |
|
Actor sender, |
|
out string message, |
|
name type, |
|
bool teamMessage |
|
) { |
|
local Parser parser; |
|
local XVotingHandler votingHandler; |
|
|
|
votingHandler = GetVotingHandler(); |
|
if (sender == none) return true; |
|
if (votingHandler != sender) return true; |
|
|
|
parser = _.text.ParseString(message); |
|
parser.Match(P(ACEDIA_MAP_WON_COMMAND)); |
|
parser.Match(P("::")); |
|
if (parser.Ok()) { |
|
message = Repl(backupMessageMapWon, "%mapname%", parser.GetRemainderS()); |
|
} else { |
|
parser.Match(P(ACEDIA_MAP_FORCED_COMMAND)); |
|
parser.Match(P("::")); |
|
if (parser.Ok()) { |
|
message = Repl(backupMessageAdminMapChange, "%mapname%", parser.GetRemainderS()); |
|
} |
|
} |
|
if (parser.Ok()) { |
|
votingHandler.mapList = realMapList; |
|
votingHandler.mapCount = realMapList.length; |
|
} |
|
_.memory.Free(parser); |
|
return true; |
|
} |
|
|
|
private function XVotingHandler GetVotingHandler() { |
|
if (votingHandlerReference != none) { |
|
return XVotingHandler(votingHandlerReference.Get()); |
|
} |
|
return none; |
|
} |
|
|
|
defaultproperties { |
|
ACEDIA_MAP_FORCED_COMMAND = "ACEDIA_LAUNCHER:MAP_FORCED:DEADBEEF" |
|
ACEDIA_MAP_WON_COMMAND = "ACEDIA_LAUNCHER:MAP_WON:DEADBEEF" |
|
} |