Performance: Viewable tiles are now a transient list in civInfo
This commit is contained in:
parent
bf4d9b609d
commit
d7ddd85c32
14 changed files with 46 additions and 39 deletions
|
@ -60,7 +60,7 @@ class GameInfo {
|
|||
|
||||
player.startTurn()
|
||||
|
||||
val enemyUnitsCloseToTerritory = player.getViewableTiles()
|
||||
val enemyUnitsCloseToTerritory = player.viewableTiles
|
||||
.filter {
|
||||
it.militaryUnit != null && it.militaryUnit!!.civInfo != player
|
||||
&& player.isAtWarWith(it.militaryUnit!!.civInfo)
|
||||
|
@ -80,7 +80,7 @@ class GameInfo {
|
|||
if (tileToPlace == null) {
|
||||
// Barbarians will only spawn in places that no one can see
|
||||
val allViewableTiles = civilizations.filterNot { it.isBarbarianCivilization() }
|
||||
.flatMap { it.getViewableTiles() }.toHashSet()
|
||||
.flatMap { it.viewableTiles }.toHashSet()
|
||||
val viableTiles = tileMap.values.filterNot { allViewableTiles.contains(it) || it.militaryUnit != null || it.civilianUnit != null }
|
||||
if (viableTiles.isEmpty()) return // no place for more barbs =(
|
||||
tile = viableTiles.getRandom()
|
||||
|
@ -92,10 +92,10 @@ class GameInfo {
|
|||
tileMap.gameInfo = this
|
||||
tileMap.setTransients()
|
||||
|
||||
for (civInfo in civilizations) {
|
||||
civInfo.gameInfo = this
|
||||
civInfo.setTransients()
|
||||
}
|
||||
// this is separated into 2 loops because when we activate updateViewableTiles in civ.setTransients,
|
||||
// we try to find new civs, and we check if civ is barbarian, which we can't know unless the gameInfo is already set.
|
||||
for (civInfo in civilizations) civInfo.gameInfo = this
|
||||
for (civInfo in civilizations) civInfo.setTransients()
|
||||
|
||||
for (civInfo in civilizations) {
|
||||
// we have to remove hydro plants from all cities BEFORE we update a single one,
|
||||
|
|
|
@ -146,7 +146,7 @@ class UnitAutomation{
|
|||
class AttackableTile(val tileToAttackFrom:TileInfo, val tileToAttack:TileInfo)
|
||||
|
||||
fun getAttackableEnemies(unit: MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>): ArrayList<AttackableTile> {
|
||||
val tilesWithEnemies = unit.civInfo.getViewableTiles()
|
||||
val tilesWithEnemies = unit.civInfo.viewableTiles
|
||||
.filter { containsAttackableEnemy(it,unit) }
|
||||
|
||||
val rangeOfAttack = unit.getRange()
|
||||
|
|
|
@ -95,6 +95,8 @@ class CityExpansionManager {
|
|||
for(unit in tileInfo.getUnits())
|
||||
if(!unit.civInfo.canEnterTiles(cityInfo.civInfo))
|
||||
unit.movementAlgs().teleportToClosestMoveableTile()
|
||||
|
||||
cityInfo.civInfo.updateViewableTiles()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class CityInfo {
|
|||
constructor() // for json parsing, we need to have a default constructor
|
||||
constructor(civInfo: CivilizationInfo, cityLocation: Vector2) {
|
||||
this.civInfo = civInfo
|
||||
this.location = cityLocation
|
||||
setTransients()
|
||||
|
||||
// Since cities can be captures between civilizations,
|
||||
|
@ -48,7 +49,6 @@ class CityInfo {
|
|||
else name = civInfo.getNation().cities.map { "Newer $it" }.first{ !allExistingCityNames.contains(it) }
|
||||
}
|
||||
|
||||
this.location = cityLocation
|
||||
civInfo.cities = civInfo.cities.toMutableList().apply { add(this@CityInfo) }
|
||||
if(civInfo == civInfo.gameInfo.getPlayerCivilization())
|
||||
civInfo.addNotification("[$name] has been founded!", cityLocation, Color.PURPLE)
|
||||
|
|
|
@ -26,6 +26,7 @@ import kotlin.math.roundToInt
|
|||
class CivilizationInfo {
|
||||
@Transient lateinit var gameInfo: GameInfo
|
||||
@Transient var units=ArrayList<MapUnit>()
|
||||
@Transient var viewableTiles = HashSet<TileInfo>()
|
||||
|
||||
var gold = 0
|
||||
var happiness = 15
|
||||
|
@ -203,25 +204,26 @@ class CivilizationInfo {
|
|||
return units.toList() // to avoid comodification problems (ie concurrency again...)
|
||||
}
|
||||
|
||||
fun getViewableTiles(): List<TileInfo> {
|
||||
var viewablePositions = emptyList<TileInfo>()
|
||||
viewablePositions += cities.flatMap { it.getTiles() }
|
||||
.flatMap { it.neighbors } // tiles adjacent to city tiles
|
||||
viewablePositions += getCivUnits()
|
||||
.flatMap { it.getViewableTiles()} // Tiles within 2 tiles of units
|
||||
viewablePositions.map { it.position }.filterNot { exploredTiles.contains(it) }.toCollection(exploredTiles)
|
||||
|
||||
val viewedCivs = viewablePositions
|
||||
.flatMap { it.getUnits().map { u->u.civInfo }.union(listOf(it.getOwner())) }
|
||||
.filterNotNull().filterNot { it==this || it.isBarbarianCivilization() }
|
||||
fun updateViewableTiles() {
|
||||
viewableTiles.clear()
|
||||
viewableTiles.addAll(cities.flatMap { it.getTiles() }.flatMap { it.neighbors }) // tiles adjacent to city tiles
|
||||
viewableTiles.addAll(getCivUnits().flatMap { it.getViewableTiles()})
|
||||
|
||||
// updating the viewable tiles also affects the explored tiles, obvs
|
||||
viewableTiles.asSequence().map { it.position }
|
||||
.filterNot { exploredTiles.contains(it) }.toCollection(exploredTiles)
|
||||
|
||||
val viewedCivs = viewableTiles
|
||||
.flatMap { it.getUnits().map { unit->unit.civInfo }.union(listOf(it.getOwner())) }
|
||||
// we can meet a civ either by meeting its unit, or its tile
|
||||
.asSequence().filterNotNull().filterNot { it==this || it.isBarbarianCivilization() }
|
||||
|
||||
for(otherCiv in viewedCivs)
|
||||
if(!diplomacy.containsKey(otherCiv.civName)){
|
||||
meetCivilization(otherCiv)
|
||||
addNotification("We have encountered [${otherCiv.civName}]!".tr(),null, Color.GOLD)
|
||||
}
|
||||
|
||||
return viewablePositions.distinct()
|
||||
}
|
||||
|
||||
fun meetCivilization(otherCiv: CivilizationInfo) {
|
||||
|
@ -254,7 +256,6 @@ class CivilizationInfo {
|
|||
|
||||
//region state-changing functions
|
||||
fun setTransients() {
|
||||
if(civName=="") civName="Babylon" // this is because it used to be a default but now it isn't so we can change it.
|
||||
goldenAges.civInfo = this
|
||||
policies.civInfo = this
|
||||
if(policies.adoptedPolicies.size>0 && policies.numberOfAdoptedPolicies == 0)
|
||||
|
@ -263,16 +264,13 @@ class CivilizationInfo {
|
|||
tech.civInfo = this
|
||||
diplomacy.values.forEach { it.civInfo=this}
|
||||
|
||||
for (unit in gameInfo.tileMap.values.flatMap { it.getUnits() }.filter { it.owner==civName }) {
|
||||
unit.assignOwner(this)
|
||||
unit.setTransients()
|
||||
}
|
||||
|
||||
for (cityInfo in cities) {
|
||||
cityInfo.civInfo = this // must be before the city's setTransients because it depends on the tilemap, that comes from the civInfo
|
||||
cityInfo.setTransients()
|
||||
}
|
||||
setCitiesConnectedToCapitalTransients()
|
||||
updateViewableTiles()
|
||||
}
|
||||
|
||||
fun endTurn() {
|
||||
|
@ -320,7 +318,7 @@ class CivilizationInfo {
|
|||
}
|
||||
|
||||
fun startTurn(){
|
||||
getViewableTiles() // adds explored tiles so that the units will be able to perform automated actions better
|
||||
updateViewableTiles() // adds explored tiles so that the units will be able to perform automated actions better
|
||||
setCitiesConnectedToCapitalTransients()
|
||||
for (city in cities)
|
||||
city.cityStats.update()
|
||||
|
|
|
@ -314,6 +314,7 @@ class MapUnit {
|
|||
currentTile = tile
|
||||
if(tile.improvement=="Ancient ruins" && !civInfo.isBarbarianCivilization())
|
||||
getAncientRuinBonus()
|
||||
civInfo.updateViewableTiles()
|
||||
}
|
||||
|
||||
private fun getAncientRuinBonus() {
|
||||
|
|
|
@ -200,7 +200,7 @@ open class TileInfo {
|
|||
|
||||
override fun toString(): String {
|
||||
val SB = StringBuilder()
|
||||
val isViewableToPlayer = UnCivGame.Current.gameInfo.getPlayerCivilization().getViewableTiles().contains(this)
|
||||
val isViewableToPlayer = UnCivGame.Current.gameInfo.getPlayerCivilization().viewableTiles.contains(this)
|
||||
|| UnCivGame.Current.viewEntireMapForDebug
|
||||
|
||||
if (isCityCenter()) {
|
||||
|
|
|
@ -117,6 +117,11 @@ class TileMap {
|
|||
tileInfo.tileMap = this
|
||||
if(tileInfo.militaryUnit!=null) tileInfo.militaryUnit!!.currentTile = tileInfo
|
||||
if(tileInfo.civilianUnit!=null) tileInfo.civilianUnit!!.currentTile = tileInfo
|
||||
|
||||
for (unit in tileInfo.getUnits()) {
|
||||
unit.assignOwner(gameInfo.civilizations.first { it.civName == unit.owner })
|
||||
unit.setTransients()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class UnitPromotions{
|
|||
promotions.add(promotionName)
|
||||
numberOfPromotions++
|
||||
unit.updateUniques()
|
||||
unit.civInfo.updateViewableTiles() // some promotions give the unit bonus sight
|
||||
}
|
||||
|
||||
fun getAvailablePromotions(): List<Promotion> {
|
||||
|
|
|
@ -331,17 +331,19 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
|
|||
return newImage
|
||||
}
|
||||
|
||||
fun getBackgroundImageForUnit(unit: MapUnit):Image{
|
||||
return when {
|
||||
unit.isEmbarked() -> ImageGetter.getImage("OtherIcons/Banner")
|
||||
unit.isFortified() -> ImageGetter.getImage("OtherIcons/Shield.png")
|
||||
else -> ImageGetter.getImage("OtherIcons/Circle.png")
|
||||
}
|
||||
}
|
||||
|
||||
fun getUnitImage(unit: MapUnit, size: Float): Group {
|
||||
val unitBaseImage = ImageGetter.getUnitIcon(unit.name, unit.civInfo.getNation().getSecondaryColor())
|
||||
.apply { setSize(size*0.75f, size*0.75f) }
|
||||
|
||||
val background =
|
||||
when {
|
||||
unit.isEmbarked() -> ImageGetter.getImage("OtherIcons/Banner")
|
||||
unit.isFortified() -> ImageGetter.getImage("OtherIcons/Shield.png")
|
||||
else -> ImageGetter.getImage("OtherIcons/Circle.png")
|
||||
}
|
||||
val background = getBackgroundImageForUnit(unit)
|
||||
background.apply {
|
||||
this.color = unit.civInfo.getNation().getColor()
|
||||
setSize(size, size)
|
||||
|
|
|
@ -5,7 +5,6 @@ import com.unciv.logic.city.CityInfo
|
|||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||
import com.unciv.ui.utils.ImageGetter
|
||||
import com.unciv.ui.utils.center
|
||||
|
||||
|
||||
|
@ -13,8 +12,7 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
|
|||
var cityButton: CityButton? = null
|
||||
|
||||
fun addWhiteHaloAroundUnit(unit: MapUnit) {
|
||||
val whiteHalo = if(unit.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png")
|
||||
else ImageGetter.getImage("OtherIcons/Circle.png")
|
||||
val whiteHalo = getBackgroundImageForUnit(unit)
|
||||
whiteHalo.setSize(30f,30f)
|
||||
val unitImage = if(unit.type.isCivilian()) civilianUnitImage
|
||||
else militaryUnitImage
|
||||
|
|
|
@ -145,7 +145,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||
}
|
||||
|
||||
internal fun updateTiles(civInfo: CivilizationInfo) {
|
||||
val playerViewableTilePositions = civInfo.getViewableTiles().map { it.position }.toHashSet()
|
||||
val playerViewableTilePositions = civInfo.viewableTiles.map { it.position }.toHashSet()
|
||||
|
||||
cityButtonOverlays.forEach{it.remove()}
|
||||
cityButtonOverlays.clear()
|
||||
|
|
|
@ -265,7 +265,7 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
val shownTutorials = UnCivGame.Current.settings.tutorialsShown
|
||||
displayTutorials("NextTurn")
|
||||
if("BarbarianEncountered" !in shownTutorials
|
||||
&& civInfo.getViewableTiles().any { it.getUnits().any { unit -> unit.civInfo.isBarbarianCivilization() } })
|
||||
&& civInfo.viewableTiles.any { it.getUnits().any { unit -> unit.civInfo.isBarbarianCivilization() } })
|
||||
displayTutorials("BarbarianEncountered")
|
||||
if(civInfo.cities.size > 2) displayTutorials("SecondCity")
|
||||
if(civInfo.happiness<0) displayTutorials("Unhappiness")
|
||||
|
|
|
@ -127,7 +127,7 @@ class WorldScreenTopBar(val screen: WorldScreen) : Table() {
|
|||
else -> 2020+(turns-440)/2
|
||||
}
|
||||
|
||||
turnsLabel.setText("Turn".tr()+" " + civInfo.gameInfo.turns + " | "+ abs(year)+(if (year<0) " BE" else " AD"))
|
||||
turnsLabel.setText("Turn".tr()+" " + civInfo.gameInfo.turns + " | "+ abs(year)+(if (year<0) " BC" else " AD"))
|
||||
|
||||
val nextTurnStats = civInfo.getStatsForNextTurn()
|
||||
val goldPerTurn = "(" + (if (nextTurnStats.gold > 0) "+" else "") + Math.round(nextTurnStats.gold) + ")"
|
||||
|
|
Loading…
Reference in a new issue