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