From efc131c863c8a75613b811639202784cfc35c07f Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Mon, 13 Apr 2020 11:08:59 +0300 Subject: [PATCH] Preserve mod order in ruleset and game parameters --- core/src/com/unciv/logic/GameStarter.kt | 46 +++++++++---------- .../unciv/models/metadata/GameParameters.kt | 24 +++++----- core/src/com/unciv/models/ruleset/Ruleset.kt | 29 ++++++------ 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/core/src/com/unciv/logic/GameStarter.kt b/core/src/com/unciv/logic/GameStarter.kt index 3942cc36..a7bdd653 100644 --- a/core/src/com/unciv/logic/GameStarter.kt +++ b/core/src/com/unciv/logic/GameStarter.kt @@ -19,7 +19,7 @@ object GameStarter { gameInfo.gameParameters = newGameParameters val ruleset = RulesetCache.getComplexRuleset(newGameParameters.mods) - if(mapParameters.name != "") + if (mapParameters.name != "") gameInfo.tileMap = MapSaver.loadMap(mapParameters.name) else gameInfo.tileMap = MapGenerator(ruleset).generateMap(mapParameters) gameInfo.tileMap.mapParameters = mapParameters @@ -35,7 +35,7 @@ object GameStarter { gameInfo.setTransients() // needs to be before placeBarbarianUnit because it depends on the tilemap having its gameinfo set // Add Civ Technologies - for (civInfo in gameInfo.civilizations.filter {!it.isBarbarian()}) { + for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian() }) { if (!civInfo.isPlayerCivilization()) for (tech in gameInfo.getDifficulty().aiFreeTechs) @@ -100,9 +100,9 @@ object GameStarter { gameInfo.tileMap) // remove starting locations one we're done - for(tile in gameInfo.tileMap.values){ - if(tile.improvement!=null && tile.improvement!!.startsWith("StartingLocation ")) - tile.improvement=null + for (tile in gameInfo.tileMap.values) { + if (tile.improvement != null && tile.improvement!!.startsWith("StartingLocation ")) + tile.improvement = null } // For later starting eras, or for civs like Polynesia with a different Warrior, we need different starting units @@ -131,42 +131,42 @@ object GameStarter { } - private fun getStartingLocations(civs:List, tileMap: TileMap): HashMap { + private fun getStartingLocations(civs: List, tileMap: TileMap): HashMap { var landTiles = tileMap.values .filter { it.isLand && !it.getBaseTerrain().impassable } val landTilesInBigEnoughGroup = ArrayList() - while(landTiles.any()){ - val bfs = BFS(landTiles.random()){it.isLand && !it.getBaseTerrain().impassable} + while (landTiles.any()) { + val bfs = BFS(landTiles.random()) { it.isLand && !it.getBaseTerrain().impassable } bfs.stepToEnd() val tilesInGroup = bfs.tilesReached.keys landTiles = landTiles.filter { it !in tilesInGroup } - if(tilesInGroup.size > 20) // is this a good number? I dunno, but it's easy enough to change later on + if (tilesInGroup.size > 20) // is this a good number? I dunno, but it's easy enough to change later on landTilesInBigEnoughGroup.addAll(tilesInGroup) } val tilesWithStartingLocations = tileMap.values - .filter { it.improvement!=null && it.improvement!!.startsWith("StartingLocation ") } + .filter { it.improvement != null && it.improvement!!.startsWith("StartingLocation ") } - val civsOrderedByAvailableLocations = civs.sortedBy {civ -> + val civsOrderedByAvailableLocations = civs.sortedBy { civ -> when { - tilesWithStartingLocations.any { it.improvement=="StartingLocation "+civ.civName } -> 1 // harshest requirements + tilesWithStartingLocations.any { it.improvement == "StartingLocation " + civ.civName } -> 1 // harshest requirements civ.nation.startBias.isNotEmpty() -> 2 // less harsh else -> 3 } // no requirements } - for(minimumDistanceBetweenStartingLocations in tileMap.tileMatrix.size/3 downTo 0){ + for (minimumDistanceBetweenStartingLocations in tileMap.tileMatrix.size / 3 downTo 0) { val freeTiles = landTilesInBigEnoughGroup - .filter { vectorIsAtLeastNTilesAwayFromEdge(it.position,minimumDistanceBetweenStartingLocations,tileMap)} + .filter { vectorIsAtLeastNTilesAwayFromEdge(it.position, minimumDistanceBetweenStartingLocations, tileMap) } .toMutableList() - val startingLocations = HashMap() + val startingLocations = HashMap() - for(civ in civsOrderedByAvailableLocations){ - var startingLocation:TileInfo - val presetStartingLocation = tilesWithStartingLocations.firstOrNull { it.improvement=="StartingLocation "+civ.civName } - if(presetStartingLocation!=null) startingLocation = presetStartingLocation + for (civ in civsOrderedByAvailableLocations) { + var startingLocation: TileInfo + val presetStartingLocation = tilesWithStartingLocations.firstOrNull { it.improvement == "StartingLocation " + civ.civName } + if (presetStartingLocation != null) startingLocation = presetStartingLocation else { if (freeTiles.isEmpty()) break // we failed to get all the starting tiles with this minimum distance var preferredTiles = freeTiles.toList() @@ -182,21 +182,21 @@ object GameStarter { startingLocation = if (preferredTiles.isNotEmpty()) preferredTiles.random() else freeTiles.random() } startingLocations[civ] = startingLocation - freeTiles.removeAll(tileMap.getTilesInDistance(startingLocation.position,minimumDistanceBetweenStartingLocations)) + freeTiles.removeAll(tileMap.getTilesInDistance(startingLocation.position, minimumDistanceBetweenStartingLocations)) } - if(startingLocations.size < civs.size) continue // let's try again with less minimum distance! + if (startingLocations.size < civs.size) continue // let's try again with less minimum distance! return startingLocations } throw Exception("Didn't manage to get starting tiles even with distance of 1?") } - private fun vectorIsAtLeastNTilesAwayFromEdge(vector: Vector2, n:Int, tileMap: TileMap): Boolean { + private fun vectorIsAtLeastNTilesAwayFromEdge(vector: Vector2, n: Int, tileMap: TileMap): Boolean { // Since all maps are HEXAGONAL, the easiest way of checking if a tile is n steps away from the // edge is checking the distance to the CENTER POINT // Can't believe we used a dumb way of calculating this before! val hexagonalRadius = -tileMap.leftX val distanceFromCenter = HexMath.getDistance(vector, Vector2.Zero) - return hexagonalRadius-distanceFromCenter >= n + return hexagonalRadius - distanceFromCenter >= n } } \ No newline at end of file diff --git a/core/src/com/unciv/models/metadata/GameParameters.kt b/core/src/com/unciv/models/metadata/GameParameters.kt index 33244f78..067da731 100644 --- a/core/src/com/unciv/models/metadata/GameParameters.kt +++ b/core/src/com/unciv/models/metadata/GameParameters.kt @@ -21,20 +21,20 @@ class GameParameters { // Default values are the default new game var startingEra = TechEra.Ancient var isOnlineMultiplayer = false - var mods = HashSet() + var mods = LinkedHashSet() fun clone(): GameParameters { - val parameters=GameParameters() - parameters.difficulty=difficulty - parameters.gameSpeed=gameSpeed - parameters.players= ArrayList(players) - parameters.numberOfCityStates=numberOfCityStates - parameters.noBarbarians=noBarbarians - parameters.oneCityChallenge=oneCityChallenge - parameters.victoryTypes= ArrayList(victoryTypes) - parameters.startingEra=startingEra - parameters.isOnlineMultiplayer=isOnlineMultiplayer - parameters.mods= HashSet(mods) + val parameters = GameParameters() + parameters.difficulty = difficulty + parameters.gameSpeed = gameSpeed + parameters.players = ArrayList(players) + parameters.numberOfCityStates = numberOfCityStates + parameters.noBarbarians = noBarbarians + parameters.oneCityChallenge = oneCityChallenge + parameters.victoryTypes = ArrayList(victoryTypes) + parameters.startingEra = startingEra + parameters.isOnlineMultiplayer = isOnlineMultiplayer + parameters.mods = LinkedHashSet(mods) return parameters } } \ No newline at end of file diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index efff4653..8755eab9 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -29,7 +29,7 @@ class Ruleset() { val nations = LinkedHashMap() val policyBranches = LinkedHashMap() val difficulties = LinkedHashMap() - val mods = HashSet() + val mods = LinkedHashSet() fun clone(): Ruleset { val newRuleset = Ruleset() @@ -146,35 +146,34 @@ class Ruleset() { /** Loading mods is expensive, so let's only do it once and * save all of the loaded rulesets somewhere for later use * */ -object RulesetCache :HashMap(){ - fun loadRulesets(){ +object RulesetCache :HashMap() { + fun loadRulesets() { this[""] = Ruleset().apply { load(Gdx.files.internal("jsons")) } - for(modFolder in Gdx.files.local("mods").list()){ + for (modFolder in Gdx.files.local("mods").list()) { if (modFolder.name().startsWith('.')) continue - try{ + try { val modRuleset = Ruleset() modRuleset.load(modFolder.child("jsons")) modRuleset.name = modFolder.name() this[modRuleset.name] = modRuleset - println ("Mod loaded successfully: " + modRuleset.name) - } - catch (ex:Exception){ - println ("Exception loading mod '${modFolder.name()}':") - println (" ${ex.localizedMessage}") - println (" (Source file ${ex.stackTrace[0].fileName} line ${ex.stackTrace[0].lineNumber})") + println("Mod loaded successfully: " + modRuleset.name) + } catch (ex: Exception) { + println("Exception loading mod '${modFolder.name()}':") + println(" ${ex.localizedMessage}") + println(" (Source file ${ex.stackTrace[0].fileName} line ${ex.stackTrace[0].lineNumber})") } } } fun getBaseRuleset() = this[""]!! - fun getComplexRuleset(mods:Collection): Ruleset { + fun getComplexRuleset(mods: Collection): Ruleset { val newRuleset = Ruleset() - for(mod in mods) - if(containsKey(mod)) { + for (mod in mods) + if (containsKey(mod)) { newRuleset.add(this[mod]!!) - newRuleset.mods+=mod + newRuleset.mods += mod } newRuleset.add(getBaseRuleset()) return newRuleset