Map editor2.2 (#6641)

* Readability overloads for `getComplexRuleset`

* Enable loading maps containing missing ruleset objects with fix and message

* Fix bungled `noMapsAvailable` and follow minor criticism
This commit is contained in:
SomeTroglodyte
2022-04-30 22:58:03 +02:00
committed by GitHub
parent 940306432f
commit 52586a2101
12 changed files with 49 additions and 27 deletions

View File

@ -492,6 +492,8 @@ Invalid map: Area ([area]) does not match saved dimensions ([dimensions]). =
The dimensions have now been fixed for you. = The dimensions have now been fixed for you. =
River generation failed! = River generation failed! =
Please don't use step 'Landmass' with map type 'Empty', create a new empty map instead. = Please don't use step 'Landmass' with map type 'Empty', create a new empty map instead. =
This map has errors: =
The incompatible elements have been removed. =
## Map/Tool names ## Map/Tool names
My new map = My new map =
@ -1183,6 +1185,8 @@ Base terrain [terrain] does not exist in ruleset! =
Terrain feature [feature] does not exist in ruleset! = Terrain feature [feature] does not exist in ruleset! =
Resource [resource] does not exist in ruleset! = Resource [resource] does not exist in ruleset! =
Improvement [improvement] does not exist in ruleset! = Improvement [improvement] does not exist in ruleset! =
Nation [nation] does not exist in ruleset! =
Natural Wonder [naturalWonder] does not exist in ruleset! =
# Civilopedia difficulty levels # Civilopedia difficulty levels
Player settings = Player settings =

View File

@ -393,7 +393,7 @@ class GameInfo {
gameParameters.mods = LinkedHashSet(gameParameters.mods.filter { it != baseRulesetInMods }) gameParameters.mods = LinkedHashSet(gameParameters.mods.filter { it != baseRulesetInMods })
} }
ruleSet = RulesetCache.getComplexRuleset(gameParameters.mods, gameParameters.baseRuleset) ruleSet = RulesetCache.getComplexRuleset(gameParameters)
// any mod the saved game lists that is currently not installed causes null pointer // any mod the saved game lists that is currently not installed causes null pointer
// exceptions in this routine unless it contained no new objects or was very simple. // exceptions in this routine unless it contained no new objects or was very simple.

View File

@ -43,7 +43,7 @@ object GameStarter {
gameSetupInfo.gameParameters.baseRuleset = RulesetCache.getVanillaRuleset().name gameSetupInfo.gameParameters.baseRuleset = RulesetCache.getVanillaRuleset().name
gameInfo.gameParameters = gameSetupInfo.gameParameters gameInfo.gameParameters = gameSetupInfo.gameParameters
val ruleset = RulesetCache.getComplexRuleset(gameInfo.gameParameters.mods, gameInfo.gameParameters.baseRuleset) val ruleset = RulesetCache.getComplexRuleset(gameInfo.gameParameters)
val mapGen = MapGenerator(ruleset) val mapGen = MapGenerator(ruleset)
if (gameSetupInfo.mapParameters.name != "") runAndMeasure("loadMap") { if (gameSetupInfo.mapParameters.name != "") runAndMeasure("loadMap") {

View File

@ -7,9 +7,11 @@ import com.unciv.Constants
import com.unciv.JsonParser import com.unciv.JsonParser
import com.unciv.logic.BackwardCompatibility.updateDeprecations import com.unciv.logic.BackwardCompatibility.updateDeprecations
import com.unciv.logic.UncivShowableException import com.unciv.logic.UncivShowableException
import com.unciv.logic.map.MapParameters
import com.unciv.models.Counter import com.unciv.models.Counter
import com.unciv.models.ModConstants import com.unciv.models.ModConstants
import com.unciv.models.metadata.BaseRuleset import com.unciv.models.metadata.BaseRuleset
import com.unciv.models.metadata.GameParameters
import com.unciv.models.ruleset.tech.TechColumn import com.unciv.models.ruleset.tech.TechColumn
import com.unciv.models.ruleset.tech.Technology import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.ruleset.tile.Terrain import com.unciv.models.ruleset.tile.Terrain
@ -910,9 +912,18 @@ object RulesetCache : HashMap<String,Ruleset>() {
) )
} }
/** Creates a combined [Ruleset] from a list of mods contained in [parameters]. */
fun getComplexRuleset(parameters: MapParameters) =
getComplexRuleset(parameters.mods, parameters.baseRuleset)
/** Creates a combined [Ruleset] from a list of mods contained in [parameters]. */
fun getComplexRuleset(parameters: GameParameters) =
getComplexRuleset(parameters.mods, parameters.baseRuleset)
/** /**
* Creates a combined [Ruleset] from a list of mods. If no baseRuleset is listed in [mods], * Creates a combined [Ruleset] from a list of mods.
* then the vanilla Ruleset is included automatically. * If no baseRuleset is passed in [optionalBaseRuleset] (or a non-existing one), then the vanilla Ruleset is included automatically.
* Any mods in the [mods] parameter marked as base ruleset (or not loaded in [RulesetCache]) are ignored.
*/ */
fun getComplexRuleset(mods: LinkedHashSet<String>, optionalBaseRuleset: String? = null): Ruleset { fun getComplexRuleset(mods: LinkedHashSet<String>, optionalBaseRuleset: String? = null): Ruleset {
val newRuleset = Ruleset() val newRuleset = Ruleset()

View File

@ -25,5 +25,5 @@ import com.unciv.ui.utils.*
@Deprecated("As of 4.0.x") @Deprecated("As of 4.0.x")
class GameParametersScreen(var mapEditorScreen: MapEditorScreen): IPreviousScreen, PickerScreen(disableScroll = true) { class GameParametersScreen(var mapEditorScreen: MapEditorScreen): IPreviousScreen, PickerScreen(disableScroll = true) {
override var gameSetupInfo = GameSetupInfo(mapParameters = mapEditorScreen.newMapParameters) override var gameSetupInfo = GameSetupInfo(mapParameters = mapEditorScreen.newMapParameters)
override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods, gameSetupInfo.gameParameters.baseRuleset) override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters)
} }

View File

@ -62,7 +62,7 @@ class MapEditorEditTab(
Improvements("Improvements", 'i', "OtherIcons/Improvements", { parent, ruleset -> MapEditorEditImprovementsTab(parent, ruleset) }), Improvements("Improvements", 'i', "OtherIcons/Improvements", { parent, ruleset -> MapEditorEditImprovementsTab(parent, ruleset) }),
Rivers("Rivers", 'v', "OtherIcons/Star", { parent, ruleset -> MapEditorEditRiversTab(parent, ruleset) }), Rivers("Rivers", 'v', "OtherIcons/Star", { parent, ruleset -> MapEditorEditRiversTab(parent, ruleset) }),
StartingLocations("Starting locations", 's', "OtherIcons/Nations", { parent, ruleset -> MapEditorEditStartsTab(parent, ruleset) }), StartingLocations("Starting locations", 's', "OtherIcons/Nations", { parent, ruleset -> MapEditorEditStartsTab(parent, ruleset) }),
Units("Units", 'u', "OtherIcons/Shield", { parent, ruleset -> MapEditorEditUnitsTab(parent, ruleset) }), // Units("Units", 'u', "OtherIcons/Shield", { parent, ruleset -> MapEditorEditUnitsTab(parent, ruleset) }),
} }
init { init {

View File

@ -93,13 +93,13 @@ class MapEditorFilesTable(
layout() layout()
} }
fun noMapsAvailable(includeMods: Boolean = false): Boolean { fun noMapsAvailable(): Boolean {
if (MapSaver.getMaps().any()) return true if (MapSaver.getMaps().any()) return false
if (!includeMods) return false if (!includeMods) return true
for (modFolder in RulesetCache.values.mapNotNull { it.folderLocation }) { for (modFolder in RulesetCache.values.mapNotNull { it.folderLocation }) {
val mapsFolder = modFolder.child(MapSaver.mapsFolder) val mapsFolder = modFolder.child(MapSaver.mapsFolder)
if (mapsFolder.exists() && mapsFolder.list().any()) return true if (mapsFolder.exists() && mapsFolder.list().any()) return false
} }
return false return true
} }
} }

View File

@ -103,7 +103,7 @@ class MapEditorGenerateTab(
try { try {
val (newRuleset, generator) = if (step > MapGeneratorSteps.Landmass) null to null val (newRuleset, generator) = if (step > MapGeneratorSteps.Landmass) null to null
else { else {
val newRuleset = RulesetCache.getComplexRuleset(mapParameters.mods, mapParameters.baseRuleset) val newRuleset = RulesetCache.getComplexRuleset(mapParameters)
newRuleset to MapGenerator(newRuleset) newRuleset to MapGenerator(newRuleset)
} }
when (step) { when (step) {

View File

@ -100,8 +100,8 @@ class MapEditorLoadTab(
val newBaseRuleset = map.mapParameters.mods.filter { it !in missingMods }.firstOrNull { RulesetCache[it]!!.modOptions.isBaseRuleset } val newBaseRuleset = map.mapParameters.mods.filter { it !in missingMods }.firstOrNull { RulesetCache[it]!!.modOptions.isBaseRuleset }
if (newBaseRuleset != null) map.mapParameters.baseRuleset = newBaseRuleset if (newBaseRuleset != null) map.mapParameters.baseRuleset = newBaseRuleset
// //
if (map.mapParameters.baseRuleset !in RulesetCache) missingMods += map.mapParameters.baseRuleset if (map.mapParameters.baseRuleset !in RulesetCache) missingMods += map.mapParameters.baseRuleset
if (missingMods.isNotEmpty()) { if (missingMods.isNotEmpty()) {
Gdx.app.postRunnable { Gdx.app.postRunnable {
needPopup = false needPopup = false
@ -118,7 +118,17 @@ class MapEditorLoadTab(
map.mapParameters.mods -= modBaseRuleset map.mapParameters.mods -= modBaseRuleset
} }
editorScreen.loadMap(map) val ruleset = RulesetCache.getComplexRuleset(map.mapParameters)
val rulesetIncompatibilities = map.getRulesetIncompatibility(ruleset)
if (rulesetIncompatibilities.isNotEmpty()) {
map.removeMissingTerrainModReferences(ruleset)
val message = "{This map has errors:}\n\n".tr() +
rulesetIncompatibilities.sorted().joinToString("\n") { it.tr() } +
"\n\n{The incompatible elements have been removed.}"
ToastPopup(message, editorScreen, 4000L)
}
editorScreen.loadMap(map, ruleset)
needPopup = false needPopup = false
popup?.close() popup?.close()
} catch (ex: Throwable) { } catch (ex: Throwable) {

View File

@ -20,7 +20,7 @@ import com.unciv.ui.utils.*
//todo normalize properly //todo normalize properly
//todo functional Tab for Units //todo functional Tab for Units (empty Tab is prepared but commented out in MapEditorEditTab.AllEditSubTabs)
//todo copy/paste tile areas? (As tool tab, brush sized, floodfill forbidden, tab displays copied area) //todo copy/paste tile areas? (As tool tab, brush sized, floodfill forbidden, tab displays copied area)
//todo Synergy with Civilopedia for drawing loose tiles / terrain icons //todo Synergy with Civilopedia for drawing loose tiles / terrain icons
//todo left-align everything so a half-open drawer is more useful //todo left-align everything so a half-open drawer is more useful
@ -38,7 +38,6 @@ import com.unciv.ui.utils.*
//todo "random nation" starting location (maybe no new internal representation = all major nations) //todo "random nation" starting location (maybe no new internal representation = all major nations)
//todo Nat Wonder step generator: Needs tweaks to avoid placing duplicates or wonders too close together //todo Nat Wonder step generator: Needs tweaks to avoid placing duplicates or wonders too close together
//todo Music? Different suffix? Off? 20% Volume? //todo Music? Different suffix? Off? 20% Volume?
//todo Unciv Europe Map Example - does not load due to "Gold / Gold ore": Solve problem that multiple errors are not shown nicely, and re-enable fixing the map and displaying it
//todo See #6610 - re-layout after the map size dropdown changes to custom and new widgets are inserted - can reach "Create" only by dragging the _header_ of the sub-TabbedPager //todo See #6610 - re-layout after the map size dropdown changes to custom and new widgets are inserted - can reach "Create" only by dragging the _header_ of the sub-TabbedPager
class MapEditorScreen(map: TileMap? = null): BaseScreen() { class MapEditorScreen(map: TileMap? = null): BaseScreen() {
@ -76,8 +75,7 @@ class MapEditorScreen(map: TileMap? = null): BaseScreen() {
mapParameters.mapSize = MapSizeNew(MapSize.Tiny) mapParameters.mapSize = MapSizeNew(MapSize.Tiny)
} }
} else { } else {
ruleset = map.ruleset ?: ruleset = map.ruleset ?: RulesetCache.getComplexRuleset(map.mapParameters)
RulesetCache.getComplexRuleset(map.mapParameters.mods, map.mapParameters.baseRuleset)
tileMap = map tileMap = map
} }
@ -148,8 +146,7 @@ class MapEditorScreen(map: TileMap? = null): BaseScreen() {
mapHolder.remove() mapHolder.remove()
tileMap = map tileMap = map
checkAndFixMapSize() checkAndFixMapSize()
ruleset = newRuleset ?: ruleset = newRuleset ?: RulesetCache.getComplexRuleset(map.mapParameters)
RulesetCache.getComplexRuleset(map.mapParameters.mods, map.mapParameters.baseRuleset)
mapHolder = newMapHolder() mapHolder = newMapHolder()
isDirty = false isDirty = false
Gdx.input.inputProcessor = stage Gdx.input.inputProcessor = stage

View File

@ -252,7 +252,7 @@ class GameOptionsTable(
fun reloadRuleset() { fun reloadRuleset() {
ruleset.clear() ruleset.clear()
val newRuleset = RulesetCache.getComplexRuleset(gameParameters.mods, gameParameters.baseRuleset) val newRuleset = RulesetCache.getComplexRuleset(gameParameters)
ruleset.add(newRuleset) ruleset.add(newRuleset)
ruleset.mods += gameParameters.baseRuleset ruleset.mods += gameParameters.baseRuleset
ruleset.mods += gameParameters.mods ruleset.mods += gameParameters.mods

View File

@ -33,7 +33,7 @@ class NewGameScreen(
): IPreviousScreen, PickerScreen() { ): IPreviousScreen, PickerScreen() {
override val gameSetupInfo = _gameSetupInfo ?: GameSetupInfo.fromSettings() override val gameSetupInfo = _gameSetupInfo ?: GameSetupInfo.fromSettings()
override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods, gameSetupInfo.gameParameters.baseRuleset) // needs to be set because the GameOptionsTable etc. depend on this override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters) // needs to be set because the GameOptionsTable etc. depend on this
private val newGameOptionsTable: GameOptionsTable private val newGameOptionsTable: GameOptionsTable
private val playerPickerTable: PlayerPickerTable private val playerPickerTable: PlayerPickerTable
private val mapOptionsTable: MapOptionsTable private val mapOptionsTable: MapOptionsTable
@ -256,7 +256,7 @@ class NewGameScreen(
fun updateRuleset() { fun updateRuleset() {
ruleset.clear() ruleset.clear()
ruleset.add(RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters.mods, gameSetupInfo.gameParameters.baseRuleset)) ruleset.add(RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters))
ImageGetter.setNewRuleset(ruleset) ImageGetter.setNewRuleset(ruleset)
game.musicController.setModList(gameSetupInfo.gameParameters.getModsAndBaseRuleset()) game.musicController.setModList(gameSetupInfo.gameParameters.getModsAndBaseRuleset())
} }