@ -66,6 +66,9 @@ var private NativeActorRef votingHandlerReference;
// otherwise Acedia will alter its config
var private array<VotingHandler.MapVoteGameConfig> 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;
@ -88,7 +91,7 @@ var private const array<string> normalSynonyms;
var private const array<string> longSynonyms;
var private LoggerAPI.Definition fatNoXVotingHandler, fatBadGameConfigIndexVH;
var private LoggerAPI.Definition fatBadGameConfigIndexAdapter;
var private LoggerAPI.Definition fatBadGameConfigIndexAdapter, warnMissingMapList ;
protected function Finalizer()
{
@ -103,10 +106,10 @@ protected function Finalizer()
* Backup of replaced configs is made internally, so that they can be restored
* on map change.
*/
// TODO ADD ME!
public final function InjectIntoVotingHandler()
{
local int i;
local string nextGameModePrefix;
local GameMode nextGameMode;
local XVotingHandler votingHandler;
local array<VotingHandler.MapVoteGameConfig> newVotingHandlerConfig;
@ -121,13 +124,17 @@ public final function InjectIntoVotingHandler()
_.logger.Auto(fatNoXVotingHandler);
return;
}
pseudonimToMap = _.collections.EmptyHashTable();
votingHandlerReference = _server.unreal.ActorRef(votingHandler);
availableGameModes = class'GameMode'.static.AvailableConfigs();
for (i = 0; i < availableGameModes.length; i += 1)
{
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]));
newVotingHandlerConfig[i] = BuildVotingHandlerConfig(nextGameMode);
newVotingHandlerConfig[i] = BuildVotingHandlerConfig(nextGameMode, nextGameModePrefix);
LoadGameModeMaps(nextGameMode, nextGameModePrefix, votingHandler);
// Setup proper game mode index
if (availableGameModes[i].ToString() == targetGameMode) {
votingHandler.currentGameConfig = i;
@ -140,57 +147,134 @@ public final function InjectIntoVotingHandler()
votingHandler.gameConfig = newVotingHandlerConfig;
}
public function TrySetupMapList() {
local Text currentConfigName;
local MapList currentConfig;
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<VotingHandler.MapVoteMapList> 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);
}
if (currentConfigName != none) {
currentConfig = MapList(class'MapList'.static.GetConfigInstance(currentConfigName));
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);
}
if (currentConfig != none) {
ReplaceHandlerMaps(XVotingHandler(votingHandlerReference.Get()), currentConfig.map);
} else {
warn("currentConfig is none! Aborting!");
else {
result.Append(realName);
}
_.memory.Free(currentConfig);
_.memory.Free(currentConfigName);
_.memory.Free(mapListFeature);
_.memory.Free(nameBody);
_.memory.Free(prefix);
_.memory.Free(parser);
return result.IntoText();
}
// TODO add map reps and play count from KFMapVoteHistory.ini
public function ReplaceHandlerMaps(XVotingHandler votingHandler, array<string> maps) {
local VotingHandler.MapVoteMapList nextRecord;
local array<VotingHandler.MapVoteMapList> recordArray;
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 AppendMapsIntoHandler(
XVotingHandler votingHandler,
array<VotingHandler.MapVoteMapList> newMaps
) {
local int i;
local array<VotingHandler.MapVoteMapList> mapListCopy;
if (votingHandler == none) {
warn("votingHandler is none!");
return;
}
if (maps.length == 0) {
warn("maps.length is 0!");
if (newM aps.length == 0) {
warn("newM aps.length is 0!");
return;
}
recordArray = votingHandler.mapList;
warn(">>> recordArray.length =" $ recordArray.length);
recordArray.length = maps.length;
votingHandler.mapCount = maps.length;
nextRecord.bEnabled = true;
for (i = 0; i < maps.length; i += 1) {
nextRecord.mapName = maps[i];
recordArray[i] = nextRecord;
mapListCopy = votingHandler.mapList;
for (i = 0; i < newMaps.length; i += 1) {
mapListCopy[mapListCopy.length] = newMaps[i];
}
votingHandler.mapList = recordArray;
votingHandler.mapList = mapListCopy;
votingHandler.mapCount += newMaps.length;
}
private function VotingHandler.MapVoteGameConfig BuildVotingHandlerConfig(
GameMode gameMode)
GameMode gameMode,
string gameModePrefix)
{
local MutableText nextColoredName;
local VotingHandler.MapVoteGameConfig result;
result.gameClass = _.text.IntoString(gameMode.GetGameTypeClass());
result.prefix = _.text.IntoString(gameMode.GetMapPrefix());
result.prefix = gameModePrefix $ "-" ;
nextColoredName = gameMode
.GetTitle()
.IntoMutableText()
@ -404,6 +488,7 @@ defaultproperties
normalSynonyms(1) = "medium"
normalSynonyms(2) = "regular"
longSynonyms(0) = "long"
warnMissingMapList = (l=LOG_Warning,m="Cannot find map list `%1`.")
fatNoXVotingHandler = (l=LOG_Fatal,m="`XVotingHandler` class is missing. Make sure your server setup supports Acedia's game modes (by used voting handler derived from `XVotingHandler`).")
fatBadGameConfigIndexVH = (l=LOG_Fatal,m="`XVotingHandler`'s `currentGameConfig` variable value of %1 is out-of-bounds for `XVotingHandler.gameConfig` of length %2. Report this issue.")
fatBadGameConfigIndexAdapter = (l=LOG_Fatal,m="`XVotingHandler`'s `currentGameConfig` variable value of %1 is out-of-bounds for `VHAdapter` of length %2. Report this issue.")