Index: binaries/data/mods/public/gui/common/color.js =================================================================== --- binaries/data/mods/public/gui/common/color.js +++ binaries/data/mods/public/gui/common/color.js @@ -158,3 +158,11 @@ "[/color]" }); } + +/** + * Adds grey font if savegame/replay is not compatible. + */ +function compatibilityColor(text, isCompatible) +{ + return isCompatible ? text : '[color="96 96 96"]' + text + '[/color]'; +} Index: binaries/data/mods/public/gui/common/functions_utility_loadsave.js =================================================================== --- binaries/data/mods/public/gui/common/functions_utility_loadsave.js +++ binaries/data/mods/public/gui/common/functions_utility_loadsave.js @@ -3,25 +3,28 @@ return b.metadata.time - a.metadata.time; } -function generateLabel(metadata, engineInfo) +function isCompatibleSavegame(metadata, engineInfo) { - let dateTimeString = Engine.FormatMillisecondsIntoDateStringLocal(metadata.time*1000, translate("yyyy-MM-dd HH:mm:ss")); - let dateString = sprintf(translate("\\[%(date)s]"), { "date": dateTimeString }); + return engineInfo && hasSameSavegameVersion(metadata, engineInfo) && + hasSameEngineVersion(metadata, engineInfo) & hasSameMods(metadata, engineInfo); +} - if (engineInfo) - { - if (!hasSameSavegameVersion(metadata, engineInfo) || !hasSameEngineVersion(metadata, engineInfo)) - dateString = "[color=\"red\"]" + dateString + "[/color]"; - else if (!hasSameMods(metadata, engineInfo)) - dateString = "[color=\"orange\"]" + dateString + "[/color]"; - } +function generateSavegameDateString(metadata, engineInfo) +{ + let dateString = Engine.FormatMillisecondsIntoDateStringLocal(metadata.time * 1000, translate("yyyy-MM-dd HH:mm:ss")); + if (!isCompatibleSavegame(metadata, engineInfo)) + dateString = compatibilityColor(dateString); + return dateString; +} +function generateSavegameLabel(metadata, engineInfo) +{ return sprintf( metadata.description ? translate("%(dateString)s %(map)s - %(description)s") : translate("%(dateString)s %(map)s"), { - "dateString": dateString, + "dateString": generateSavegameDateString(metadata, engineInfo), "map": metadata.initAttributes.map, "description": metadata.description || "" } Index: binaries/data/mods/public/gui/replaymenu/replay_menu.js =================================================================== --- binaries/data/mods/public/gui/replaymenu/replay_menu.js +++ binaries/data/mods/public/gui/replaymenu/replay_menu.js @@ -212,12 +212,12 @@ let works = replay.isCompatible; return { "directories": replay.directory, - "months": greyout(getReplayDateTime(replay), works), - "popCaps": greyout(translatePopulationCapacity(replay.attribs.settings.PopulationCap), works), - "mapNames": greyout(getReplayMapName(replay), works), - "mapSizes": greyout(translateMapSize(replay.attribs.settings.Size), works), - "durations": greyout(getReplayDuration(replay), works), - "playerNames": greyout(getReplayPlayernames(replay), works) + "months": compatibilityColor(getReplayDateTime(replay), works), + "popCaps": compatibilityColor(translatePopulationCapacity(replay.attribs.settings.PopulationCap), works), + "mapNames": compatibilityColor(getReplayMapName(replay), works), + "mapSizes": compatibilityColor(translateMapSize(replay.attribs.settings.Size), works), + "durations": compatibilityColor(getReplayDuration(replay), works), + "playerNames": compatibilityColor(getReplayPlayernames(replay), works) }; }); @@ -287,14 +287,6 @@ } /** - * Adds grey font if replay is not compatible. - */ -function greyout(text, isCompatible) -{ - return isCompatible ? text : '[color="96 96 96"]' + text + '[/color]'; -} - -/** * Returns a human-readable version of the replay date. */ function getReplayDateTime(replay) Index: binaries/data/mods/public/gui/savedgames/load.js =================================================================== --- binaries/data/mods/public/gui/savedgames/load.js +++ binaries/data/mods/public/gui/savedgames/load.js @@ -7,30 +7,88 @@ function init() { + let savedGames = Engine.GetSavedGames(); + + // Get current game version and loaded mods + let engineInfo = Engine.GetEngineInfo(); + + if (Engine.GetGUIObjectByName("compatibilityFilter").checked) + savedGames = savedGames.filter(game => isCompatibleSavegame(game.metadata, engineInfo)); + let gameSelection = Engine.GetGUIObjectByName("gameSelection"); - let savedGames = Engine.GetSavedGames().sort(sortDecreasingDate); gameSelection.enabled = !!savedGames.length; - if (!savedGames.length) + Engine.GetGUIObjectByName("gameSelectionFeedback").hidden = !!savedGames.length; + + let selectedGameId = gameSelection.list_data[gameSelection.selected]; + + // Save metadata for the detailed view + g_SavedGamesMetadata = savedGames.map(game => { - gameSelection.list = [translate("No saved games found")]; - gameSelection.selected = -1; - return; - } + game.metadata.id = game.id; + return game.metadata; + }); - // Get current game version and loaded mods - let engineInfo = Engine.GetEngineInfo(); + const sortKey = gameSelection.selected_column; + const sortOrder = gameSelection.selected_column_order; + g_SavedGamesMetadata = g_SavedGamesMetadata.sort((a, b) => + { + let cmpA, cmpB; + switch (sortKey) + { + case 'date': + cmpA = +a.time; + cmpB = +b.time; + break; + case 'mapName': + cmpA = translate(a.initAttributes.settings.Name); + cmpB = translate(b.initAttributes.settings.Name); + break; + case 'mapType': + cmpA = translateMapType(a.initAttributes.mapType); + cmpB = translateMapType(b.initAttributes.mapType); + break; + case 'description': + cmpA = a.description; + cmpB = b.description; + break; + } + + if (cmpA < cmpB) + return -sortOrder; + else if (cmpA > cmpB) + return +sortOrder; + + return 0; + }); + + let list = g_SavedGamesMetadata.map(metadata => { + let isCompatible = isCompatibleSavegame(metadata, engineInfo); + return { + "date": generateSavegameDateString(metadata, engineInfo), + "mapName": compatibilityColor(translate(metadata.initAttributes.settings.Name), isCompatible), + "mapType": compatibilityColor(translateMapType(metadata.initAttributes.mapType), isCompatible), + "description": compatibilityColor(metadata.description, isCompatible) + }; + }); - g_SavedGamesMetadata = savedGames.map(game => game.metadata); + if (list.length) + list = prepareForDropdown(list); - gameSelection.list = savedGames.map(game => generateLabel(game.metadata, engineInfo)); - gameSelection.list_data = savedGames.map(game => game.id); + gameSelection.list_date = list.date || []; + gameSelection.list_mapName = list.mapName || []; + gameSelection.list_mapType = list.mapType || []; + gameSelection.list_description = list.description || []; + + // Change these last, otherwise crash + gameSelection.list = g_SavedGamesMetadata.map(metadata => generateSavegameLabel(metadata, engineInfo)); + gameSelection.list_data = g_SavedGamesMetadata.map(metadata => metadata.id); - if (gameSelection.selected == -1) + if (gameSelection.selected == -1 && savedGames.length) gameSelection.selected = 0; - else if (gameSelection.selected >= savedGames.length) // happens when deleting the last saved game - gameSelection.selected = savedGames.length - 1; + else if (gameSelection.selected >= g_SavedGamesMetadata.length) // happens when deleting the last saved game + gameSelection.selected = g_SavedGamesMetadata.length - 1; else - selectionChanged(); + gameSelection.selected = g_SavedGamesMetadata.findIndex(metadata => metadata.id == selectedGameId); Engine.GetGUIObjectByName("deleteGameButton").tooltip = deleteTooltip(); } Index: binaries/data/mods/public/gui/savedgames/load.xml =================================================================== --- binaries/data/mods/public/gui/savedgames/load.xml +++ binaries/data/mods/public/gui/savedgames/load.xml @@ -14,15 +14,47 @@ - + Load Game - - + + selectionChanged(); + init(); + loadGame(); + + + Date / Time + + + + Map Type + + + + Map Name + + + + Description + + + + @@ -42,7 +74,18 @@ - + + + init(); + + + + Filter compatible saved games + + + + + @@ -76,7 +119,7 @@ - + Index: binaries/data/mods/public/gui/savedgames/save.js =================================================================== --- binaries/data/mods/public/gui/savedgames/save.js +++ binaries/data/mods/public/gui/savedgames/save.js @@ -36,7 +36,7 @@ for (let game of savedGames) g_Descriptions[game.id] = game.metadata.description || ""; - gameSelection.list = savedGames.map(game => generateLabel(game.metadata)); + gameSelection.list = savedGames.map(game => generateSavegameLabel(game.metadata)); gameSelection.list_data = savedGames.map(game => game.id); gameSelection.selected = -1;