From a0daa6be4ca29a061187d2c1b424e601345e8198 Mon Sep 17 00:00:00 2001 From: Alexander Korolyov <49795502+alkorolyov@users.noreply.github.com> Date: Tue, 14 Jul 2020 17:17:37 +0200 Subject: [PATCH] Add mod compatibility for extended map editor (#2840) * Add mod compatibility for extended map editor * fix crashes when loading scenario with mods enabled * update imagegetter ruleset when loading scenario * reload ruleset on new scenrio * Fixed crash when units/improvements from the missing mods present in the map editor. * removeMissingModReferences - better name --- .../ui/mapeditor/GameParametersScreen.kt | 12 +++++---- .../com/unciv/ui/mapeditor/MapEditorScreen.kt | 14 +++++----- .../ui/mapeditor/TileEditorOptionsTable.kt | 26 +++++++++---------- .../ui/newgamescreen/GameOptionsTable.kt | 1 - .../unciv/ui/newgamescreen/MapOptionsTable.kt | 8 ++++-- .../unciv/ui/newgamescreen/NewGameScreen.kt | 8 ++++++ .../ui/newgamescreen/PlayerPickerTable.kt | 15 +++++------ core/src/com/unciv/ui/tilegroups/TileGroup.kt | 14 ++++++++++ 8 files changed, 63 insertions(+), 35 deletions(-) diff --git a/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt b/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt index 05b7bdfdf2..90d4733429 100644 --- a/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/GameParametersScreen.kt @@ -3,6 +3,7 @@ package com.unciv.ui.mapeditor import com.unciv.UncivGame import com.unciv.logic.map.Scenario import com.unciv.models.ruleset.Ruleset +import com.unciv.models.ruleset.RulesetCache import com.unciv.ui.newgamescreen.GameOptionsTable import com.unciv.ui.newgamescreen.GameSetupInfo import com.unciv.ui.newgamescreen.PlayerPickerTable @@ -17,10 +18,10 @@ import com.unciv.ui.utils.* * @param [mapEditorScreen] previous screen from map editor. */ class GameParametersScreen(var mapEditorScreen: MapEditorScreen): IPreviousScreen, PickerScreen() { - override var gameSetupInfo: GameSetupInfo = mapEditorScreen.gameSetupInfo - override var ruleset: Ruleset = mapEditorScreen.ruleset - var playerPickerTable = PlayerPickerTable(this, this.gameSetupInfo.gameParameters) - var gameOptionsTable = GameOptionsTable(mapEditorScreen) { desiredCiv: String -> playerPickerTable.update(desiredCiv) } + override var gameSetupInfo = mapEditorScreen.gameSetupInfo.clone() + override var ruleset = RulesetCache.getComplexRuleset(gameSetupInfo.gameParameters) + var playerPickerTable = PlayerPickerTable(this, gameSetupInfo.gameParameters) + var gameOptionsTable = GameOptionsTable(this) { desiredCiv: String -> playerPickerTable.update(desiredCiv) } init { @@ -34,7 +35,8 @@ class GameParametersScreen(var mapEditorScreen: MapEditorScreen): IPreviousScree rightSideButton.onClick { mapEditorScreen.gameSetupInfo = gameSetupInfo mapEditorScreen.scenario = Scenario(mapEditorScreen.tileMap, mapEditorScreen.gameSetupInfo.gameParameters) - mapEditorScreen.ruleset = ruleset //TODO: figure out whether it is necessary + mapEditorScreen.ruleset.clear() + mapEditorScreen.ruleset.add(ruleset) mapEditorScreen.tileEditorOptions.update() mapEditorScreen.mapHolder.updateTileGroups() UncivGame.Current.setScreen(mapEditorScreen) diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt index 9353fa1f5b..1c9b5a23f5 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorScreen.kt @@ -18,17 +18,14 @@ import com.unciv.ui.newgamescreen.GameSetupInfo import com.unciv.ui.newgamescreen.IPreviousScreen import com.unciv.ui.utils.* -class MapEditorScreen(): IPreviousScreen, CameraStageBaseScreen() { - // need for compatibility with PickerScreen - override fun setRightSideButtonEnabled(boolean: Boolean) {} - +class MapEditorScreen(): CameraStageBaseScreen() { var mapName = "" var tileMap = TileMap() var scenarioName = "" // when loading map: mapName is taken as default for scenarioName var scenario: Scenario? = null // main indicator whether scenario information is present - override var ruleset = RulesetCache.getBaseRuleset() + var ruleset = RulesetCache.getBaseRuleset() - override var gameSetupInfo = GameSetupInfo() + var gameSetupInfo = GameSetupInfo() lateinit var mapHolder: EditorMapHolder lateinit var tileEditorOptions: TileEditorOptionsTable @@ -63,7 +60,12 @@ class MapEditorScreen(): IPreviousScreen, CameraStageBaseScreen() { mapName = scenarioName this.scenario = scenario this.scenarioName = scenarioName + gameSetupInfo.gameParameters = scenario.gameParameters + + ruleset = RulesetCache.getComplexRuleset(scenario.gameParameters) + ImageGetter.ruleset = ruleset + ImageGetter.setTextureRegionDrawables() initialize() } diff --git a/core/src/com/unciv/ui/mapeditor/TileEditorOptionsTable.kt b/core/src/com/unciv/ui/mapeditor/TileEditorOptionsTable.kt index 49a4dea5b6..f853577a45 100644 --- a/core/src/com/unciv/ui/mapeditor/TileEditorOptionsTable.kt +++ b/core/src/com/unciv/ui/mapeditor/TileEditorOptionsTable.kt @@ -3,10 +3,8 @@ package com.unciv.ui.mapeditor import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.Group -import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.ui.Slider import com.badlogic.gdx.scenes.scene2d.ui.Table -import com.badlogic.gdx.utils.Align import com.unciv.Constants import com.unciv.UncivGame import com.unciv.logic.civilization.CivilizationInfo @@ -18,7 +16,6 @@ import com.unciv.models.metadata.Player import com.unciv.models.ruleset.Nation import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.TerrainType -import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.translations.tr import com.unciv.ui.tilegroups.TileGroup import com.unciv.ui.tilegroups.TileSetStrings @@ -226,23 +223,26 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera val nationsTable = Table() - // default player - barbarians - var currentPlayer = "" - var currentNation: Nation? = ruleset.nations.values.firstOrNull{ it.isBarbarian() } - + // default player - first MajorCiv player + val defaultPlayer = gameParameters.players.first{ + it.chosenCiv != Constants.spectator && it.chosenCiv != Constants.random + } + var currentPlayer = getPlayerIndexString(defaultPlayer) + var currentNation: Nation = ruleset.nations[defaultPlayer.chosenCiv]!! var currentUnit = ruleset.units.values.first() fun setUnitTileAction(){ - if (currentNation == null) return - val unitImage = ImageGetter.getUnitIcon(currentUnit.name, currentNation!!.getInnerColor()) - .surroundWithCircle(40f).apply { color=currentNation!!.getOuterColor() } - setCurrentHex(unitImage, currentUnit.name.tr()+ " - $currentPlayer ("+currentNation!!.name.tr()+")") + val unitImage = ImageGetter.getUnitIcon(currentUnit.name, currentNation.getInnerColor()) + .surroundWithCircle(40f*0.9f).apply { circle.color=currentNation.getOuterColor() } + .surroundWithCircle(40f, false).apply { circle.color=currentNation.getInnerColor() } + + setCurrentHex(unitImage, currentUnit.name.tr()+ " - $currentPlayer ("+currentNation.name.tr()+")") tileAction = { val unit = MapUnit() unit.baseUnit = currentUnit unit.name = currentUnit.name - unit.owner = currentNation!!.name - unit.civInfo = CivilizationInfo(currentNation!!.name).apply { nation=currentNation!! } // needed for the unit icon to render correctly + unit.owner = currentNation.name + unit.civInfo = CivilizationInfo(currentNation.name).apply { nation=currentNation } // needed for the unit icon to render correctly unit.updateUniques() if (unit.movement.canMoveTo(it)) { when { diff --git a/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt b/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt index 4da740aba7..caa7d4ffb0 100644 --- a/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt +++ b/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt @@ -170,7 +170,6 @@ class GameOptionsTable(previousScreen: IPreviousScreen, val updatePlayerPickerTa val modRulesets = RulesetCache.values.filter { it.name != "" } if (modRulesets.isEmpty()) return - add("Mods:".toLabel(fontSize = 24)).padTop(16f).colspan(2).row() val modCheckboxTable = Table().apply { defaults().pad(5f) } for (mod in modRulesets) { diff --git a/core/src/com/unciv/ui/newgamescreen/MapOptionsTable.kt b/core/src/com/unciv/ui/newgamescreen/MapOptionsTable.kt index 5974d4c997..2d38e9ce1b 100644 --- a/core/src/com/unciv/ui/newgamescreen/MapOptionsTable.kt +++ b/core/src/com/unciv/ui/newgamescreen/MapOptionsTable.kt @@ -103,8 +103,12 @@ class MapOptionsTable(val newGameScreen: NewGameScreen): Table() { scenarioFileSelectBox.onChange { mapParameters.name = scenarioFileSelectBox.selected!! val scenario = MapSaver.loadScenario(mapParameters.name) - newGameScreen.gameSetupInfo.gameParameters = scenario.gameParameters - newGameScreen.updateTables() + newGameScreen.apply { + gameSetupInfo.gameParameters = scenario.gameParameters + newGameOptionsTable.gameParameters = scenario.gameParameters + newGameOptionsTable.reloadRuleset() + updateTables() + } } return scenarioFileSelectBox } diff --git a/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt b/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt index 1ae1448966..2d0a5de534 100644 --- a/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt +++ b/core/src/com/unciv/ui/newgamescreen/NewGameScreen.kt @@ -23,6 +23,14 @@ class GameSetupInfo(var gameId:String, var gameParameters: GameParameters, var m constructor() : this("", GameParameters(), MapParameters()) constructor(gameInfo: GameInfo) : this("", gameInfo.gameParameters.clone(), gameInfo.tileMap.mapParameters) constructor(gameParameters: GameParameters, mapParameters: MapParameters) : this("", gameParameters, mapParameters) + + fun clone(): GameSetupInfo { + val toReturn = GameSetupInfo() + toReturn.gameId = this.gameId + toReturn.gameParameters = this.gameParameters + toReturn.mapParameters = this.mapParameters + return toReturn + } } class NewGameScreen(previousScreen:CameraStageBaseScreen, _gameSetupInfo: GameSetupInfo?=null): IPreviousScreen, PickerScreen() { diff --git a/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt b/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt index 2f1f7ee324..410c1b2547 100644 --- a/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt +++ b/core/src/com/unciv/ui/newgamescreen/PlayerPickerTable.kt @@ -78,7 +78,7 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters: val availableCiv = getAvailablePlayerCivs().firstOrNull { !it.isSpectator() } if (availableCiv != null) player = Player(availableCiv.name) // Spectators only Humans - else player = Player("Spectator").apply { playerType = PlayerType.Human } + else player = Player(Constants.spectator).apply { playerType = PlayerType.Human } } gameParameters.players.add(player) update() @@ -89,13 +89,12 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters: } /** - * If new mod removes nations already chosen by some player - * sets first civilization available in the ruleset + * Reassigns removed mod references to random civilization */ private fun reassignRemovedModReferences() { for (player in gameParameters.players) { if (!previousScreen.ruleset.nations.containsKey(player.chosenCiv)) - player.chosenCiv = "Random" + player.chosenCiv = Constants.random } } @@ -107,7 +106,7 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters: // No auto-select if desiredCiv already used if (gameParameters.players.any { it.chosenCiv == desiredCiv }) return // Do auto-select, silently no-op if no suitable slot (human with 'random' choice) - gameParameters.players.firstOrNull { it.chosenCiv == "Random" && it.playerType == PlayerType.Human }?.chosenCiv = desiredCiv + gameParameters.players.firstOrNull { it.chosenCiv == Constants.random && it.playerType == PlayerType.Human }?.chosenCiv = desiredCiv } /** @@ -190,7 +189,7 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters: */ private fun getNationTable(player: Player): Table { val nationTable = Table() - val nationImage = if (player.chosenCiv == "Random") "?".toLabel(Color.WHITE, 25) + val nationImage = if (player.chosenCiv == Constants.random) "?".toLabel(Color.WHITE, 25) .apply { this.setAlignment(Align.center) } .surroundWithCircle(36f).apply { circle.color = Color.BLACK } .surroundWithCircle(40f, false).apply { circle.color = Color.WHITE } @@ -221,10 +220,10 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters: .apply { this.setAlignment(Align.center) } .surroundWithCircle(45f).apply { circle.color = Color.BLACK } .surroundWithCircle(50f, false).apply { circle.color = Color.WHITE }).pad(10f) - randomPlayerTable.add("Random".toLabel()) + randomPlayerTable.add(Constants.random.toLabel()) randomPlayerTable.touchable = Touchable.enabled randomPlayerTable.onClick { - player.chosenCiv = "Random" + player.chosenCiv = Constants.random nationsPopup.close() update() } diff --git a/core/src/com/unciv/ui/tilegroups/TileGroup.kt b/core/src/com/unciv/ui/tilegroups/TileGroup.kt index ee66068293..c71d8c4490 100644 --- a/core/src/com/unciv/ui/tilegroups/TileGroup.kt +++ b/core/src/com/unciv/ui/tilegroups/TileGroup.kt @@ -297,6 +297,8 @@ open class TileGroup(var tileInfo: TileInfo, var tileSetStrings:TileSetStrings) val tileIsViewable = viewingCiv == null || isViewable(viewingCiv) val showMilitaryUnit = viewingCiv == null || showMilitaryUnit(viewingCiv) + removeMissingModReferences() + updateTileImage(viewingCiv) updateRivers(tileInfo.hasBottomRightRiver, tileInfo.hasBottomRiver, tileInfo.hasBottomLeftRiver) updateTerrainBaseImage() @@ -318,6 +320,18 @@ open class TileGroup(var tileInfo: TileInfo, var tileSetStrings:TileSetStrings) fogImage.isVisible = !(tileIsViewable || showEntireMap) } + private fun removeMissingModReferences() { + val improvementName = tileInfo.improvement + if(improvementName != null && improvementName.startsWith("StartingLocation ")){ + val nationName = improvementName.removePrefix("StartingLocation ") + if (!tileInfo.ruleset.nations.containsKey(nationName)) + tileInfo.improvement = null + } + + for (unit in tileInfo.getUnits()) + if (!tileInfo.ruleset.nations.containsKey(unit.owner)) unit.removeFromTile() + } + private fun updateTerrainBaseImage() { if (tileInfo.baseTerrain == baseTerrain) return baseTerrain = tileInfo.baseTerrain