Many UI updates are now done on the clone, so we won't get concurrency exceptions
This commit is contained in:
parent
ce00fd43e0
commit
86464ccdb0
8 changed files with 73 additions and 47 deletions
|
@ -41,8 +41,8 @@ class NewGameScreen: PickerScreen(){
|
|||
private fun getUniqueLabel(nation: Nation): CharSequence? {
|
||||
for (building in GameBasics.Buildings.values)
|
||||
if (building.uniqueTo == nation.name) {
|
||||
var text = building.name + " - {replaces} " + building.replaces + "\n"
|
||||
val originalBuilding = GameBasics.Buildings[building.replaces]!!
|
||||
var text = building.name.tr() + " - {replaces} " + building.replaces!!.tr() + "\n"
|
||||
val originalBuilding = GameBasics.Buildings[building.replaces!!]!!
|
||||
val originalBuildingStatMap = originalBuilding.toHashMap()
|
||||
for (stat in building.toHashMap())
|
||||
if (stat.value != originalBuildingStatMap[stat.key])
|
||||
|
@ -54,8 +54,8 @@ class NewGameScreen: PickerScreen(){
|
|||
|
||||
for (unit in GameBasics.Units.values)
|
||||
if (unit.uniqueTo == nation.name) {
|
||||
var text = unit.name + " - {replaces} " + unit.replaces + "\n"
|
||||
val originalUnit = GameBasics.Units[unit.replaces]!!
|
||||
var text = unit.name.tr() + " - {replaces} " + unit.replaces!!.tr() + "\n"
|
||||
val originalUnit = GameBasics.Units[unit.replaces!!]!!
|
||||
if (unit.strength != originalUnit.strength)
|
||||
text += "{Combat strength} " + unit.strength + " vs " + originalUnit.strength + "\n"
|
||||
if (unit.rangedStrength!= originalUnit.rangedStrength)
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image
|
|||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.logic.HexMath
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.ui.utils.ImageGetter
|
||||
import com.unciv.ui.utils.addClickListener
|
||||
|
@ -67,11 +68,10 @@ class Minimap(val tileMapHolder: TileMapHolder) : ScrollPane(null){
|
|||
return true
|
||||
}
|
||||
})
|
||||
update()
|
||||
}
|
||||
|
||||
fun update(){
|
||||
val exploredTiles = tileMapHolder.worldScreen.civInfo.exploredTiles
|
||||
fun update(cloneCivilization: CivilizationInfo) {
|
||||
val exploredTiles = cloneCivilization.exploredTiles
|
||||
for(tileInfo in tileMapHolder.tileMap.values) {
|
||||
val RGB = tileInfo.getBaseTerrain().RGB!!
|
||||
val hex = tileImages[tileInfo]!!
|
||||
|
|
|
@ -8,14 +8,14 @@ import com.unciv.logic.civilization.Notification
|
|||
import com.unciv.ui.utils.*
|
||||
import kotlin.math.min
|
||||
|
||||
class NotificationsScroll(private val notifications: List<Notification>, internal val worldScreen: WorldScreen) : ScrollPane(null) {
|
||||
class NotificationsScroll(internal val worldScreen: WorldScreen) : ScrollPane(null) {
|
||||
private var notificationsTable = Table()
|
||||
|
||||
init {
|
||||
widget = notificationsTable
|
||||
}
|
||||
|
||||
internal fun update() {
|
||||
internal fun update(notifications: MutableList<Notification>) {
|
||||
notificationsTable.clearChildren()
|
||||
for (notification in notifications) {
|
||||
val label = Label(notification.text.tr(), CameraStageBaseScreen.skin).setFontColor(Color.BLACK)
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.unciv.ui.worldscreen
|
|||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||
|
@ -15,12 +16,15 @@ import com.unciv.logic.map.TileMap
|
|||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
import com.unciv.ui.tilegroups.WorldTileGroup
|
||||
import com.unciv.ui.utils.addClickListener
|
||||
import com.unciv.ui.utils.center
|
||||
import com.unciv.ui.utils.colorFromRGB
|
||||
|
||||
class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap, internal val civInfo: CivilizationInfo) : ScrollPane(null) {
|
||||
class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap: TileMap) : ScrollPane(null) {
|
||||
internal var selectedTile: TileInfo? = null
|
||||
val tileGroups = HashMap<TileInfo, WorldTileGroup>()
|
||||
|
||||
var overlayActor :Actor?=null
|
||||
|
||||
internal fun addTiles() {
|
||||
val allTiles = Group()
|
||||
val groupPadding = 300f // This is so that no tile will be stuck "on the side" and be unreachable or difficult to reach
|
||||
|
@ -35,7 +39,22 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||
|
||||
group.addClickListener {
|
||||
worldScreen.displayTutorials("TileClicked")
|
||||
if(overlayActor!=null) overlayActor!!.remove()
|
||||
selectedTile = tileInfo
|
||||
|
||||
// val selectedUnit = worldScreen.bottomBar.unitTable.selectedUnit
|
||||
// if(selectedUnit!=null && selectedUnit.getTile()!=tileInfo
|
||||
// && selectedUnit.canMoveTo(tileInfo) && selectedUnit.movementAlgs().canReach(tileInfo)) {
|
||||
// val size = 40f
|
||||
// val moveHereGroup = Group().apply { width = size;height = size; }
|
||||
// moveHereGroup.addActor(ImageGetter.getImage("OtherIcons/Circle").apply { width = size; height = size })
|
||||
// moveHereGroup.addActor(ImageGetter.getStatIcon("Movement").apply { width = size / 2; height = size / 2; center(moveHereGroup) })
|
||||
// if(selectedUnit.currentMovement>0)
|
||||
// moveHereGroup.addClickListener { selectedUnit.movementAlgs().headTowards(tileInfo);worldScreen.update() }
|
||||
// else moveHereGroup.color.a=0.5f
|
||||
// addAboveGroup(group, moveHereGroup).apply { width = size; height = size }
|
||||
// }
|
||||
|
||||
worldScreen.bottomBar.unitTable.tileSelected(tileInfo)
|
||||
worldScreen.update()
|
||||
}
|
||||
|
@ -69,7 +88,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||
setSize(worldScreen.stage.width, worldScreen.stage.height)
|
||||
addListener(object : ActorGestureListener() {
|
||||
var lastScale = 1f
|
||||
internal var lastInitialDistance = 0f
|
||||
var lastInitialDistance = 0f
|
||||
|
||||
override fun zoom(event: InputEvent?, initialDistance: Float, distance: Float) {
|
||||
if (lastInitialDistance != initialDistance) {
|
||||
|
@ -87,14 +106,23 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||
layout() // Fit the scroll pane to the contents - otherwise, setScroll won't work!
|
||||
}
|
||||
|
||||
internal fun updateTiles() {
|
||||
val playerViewableTiles = civInfo.getViewableTiles().toHashSet()
|
||||
private fun addAboveGroup(group:Group, actor: Actor) {
|
||||
actor.center(group)
|
||||
actor.x+=group.x
|
||||
actor.y+=group.y+group.height
|
||||
group.parent.addActor(actor)
|
||||
actor.toFront()
|
||||
overlayActor=actor
|
||||
}
|
||||
|
||||
internal fun updateTiles(civInfo: CivilizationInfo) {
|
||||
val playerViewableTilePositions = civInfo.getViewableTiles().map { it.position }.toHashSet()
|
||||
|
||||
for (WG in tileGroups.values){
|
||||
WG.update(playerViewableTiles.contains(WG.tileInfo))
|
||||
WG.update(playerViewableTilePositions.contains(WG.tileInfo.position))
|
||||
val unitsInTile = WG.tileInfo.getUnits()
|
||||
if((playerViewableTiles.contains(WG.tileInfo) || UnCivGame.Current.viewEntireMapForDebug)
|
||||
&& unitsInTile.isNotEmpty() && unitsInTile.first().civInfo!=civInfo)
|
||||
if((playerViewableTilePositions.contains(WG.tileInfo.position) || UnCivGame.Current.viewEntireMapForDebug)
|
||||
&& unitsInTile.isNotEmpty() && !unitsInTile.first().civInfo.isPlayerCivilization())
|
||||
WG.showCircle(Color.RED)
|
||||
} // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
|
||||
|
||||
|
@ -116,7 +144,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||
for (tile in attackableTiles.filter {
|
||||
it.getUnits().isNotEmpty()
|
||||
&& it.getUnits().first().owner != unit.owner
|
||||
&& (playerViewableTiles.contains(it) || UnCivGame.Current.viewEntireMapForDebug)}) {
|
||||
&& (playerViewableTilePositions.contains(it.position) || UnCivGame.Current.viewEntireMapForDebug)}) {
|
||||
if(unit.baseUnit().unitType== UnitType.Civilian) tileGroups[tile]!!.hideCircle()
|
||||
else {
|
||||
tileGroups[tile]!!.showCircle(colorFromRGB(237, 41, 57))
|
||||
|
|
|
@ -22,7 +22,7 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
val gameInfo = game.gameInfo
|
||||
internal val civInfo: CivilizationInfo = gameInfo.getPlayerCivilization()
|
||||
|
||||
val tileMapHolder: TileMapHolder = TileMapHolder(this, gameInfo.tileMap, civInfo)
|
||||
val tileMapHolder: TileMapHolder = TileMapHolder(this, gameInfo.tileMap)
|
||||
val minimap = Minimap(tileMapHolder)
|
||||
|
||||
internal var buttonScale = 0.9f
|
||||
|
@ -42,7 +42,7 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
|
||||
nextTurnButton.setPosition(stage.width - nextTurnButton.width - 10f,
|
||||
topBar.y - nextTurnButton.height - 10f)
|
||||
notificationsScroll = NotificationsScroll(gameInfo.notifications, this)
|
||||
notificationsScroll = NotificationsScroll(this)
|
||||
notificationsScroll.width = stage.width/3
|
||||
minimap.setSize(stage.width/5,stage.height/5)
|
||||
minimap.x = stage.width - minimap.width
|
||||
|
@ -83,8 +83,11 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
|
||||
|
||||
fun update() {
|
||||
// many of the display functions will be called with the game clone and not the actual game,
|
||||
// because that's guaranteed to stay the exact same and so we won't get any concurrent modification exceptions
|
||||
|
||||
val gameClone = gameInfo.clone()
|
||||
// so we don't get a concurrent modification exception, we clone the entire game (yes really, it's actually very fast)
|
||||
val cloneCivilization = gameClone.getPlayerCivilization()
|
||||
kotlin.concurrent.thread {
|
||||
civInfo.happiness = gameClone.getPlayerCivilization().getHappinessForNextTurn().values.sum().toInt()
|
||||
}
|
||||
|
@ -101,27 +104,27 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
}
|
||||
|
||||
if(!UnCivGame.Current.settings.tutorialsShown.contains("EnemyCityNeedsConqueringWithMeleeUnit")) {
|
||||
for (enemyCity in civInfo.diplomacy.values.filter { it.diplomaticStatus == DiplomaticStatus.War }
|
||||
for (enemyCity in cloneCivilization.diplomacy.values.filter { it.diplomaticStatus == DiplomaticStatus.War }
|
||||
.map { it.otherCiv() }.flatMap { it.cities }) {
|
||||
if (enemyCity.health == 1 && enemyCity.getCenterTile().getTilesInDistance(2)
|
||||
.any { it.getUnits().any { unit -> unit.civInfo == civInfo } })
|
||||
.any { it.getUnits().any { unit -> unit.civInfo == cloneCivilization } })
|
||||
displayTutorials("EnemyCityNeedsConqueringWithMeleeUnit")
|
||||
}
|
||||
}
|
||||
|
||||
updateTechButton()
|
||||
updateDiplomacyButton()
|
||||
updateTechButton(cloneCivilization)
|
||||
updateDiplomacyButton(cloneCivilization)
|
||||
|
||||
bottomBar.update(tileMapHolder.selectedTile) // has to come before tilemapholder update because the tilemapholder actions depend on the selected unit!
|
||||
minimap.update()
|
||||
minimap.update(cloneCivilization)
|
||||
minimap.y = bottomBar.height
|
||||
|
||||
unitActionsTable.update(bottomBar.unitTable.selectedUnit)
|
||||
unitActionsTable.y = bottomBar.height
|
||||
|
||||
tileMapHolder.updateTiles()
|
||||
topBar.update()
|
||||
notificationsScroll.update()
|
||||
tileMapHolder.updateTiles(cloneCivilization)
|
||||
topBar.update(cloneCivilization)
|
||||
notificationsScroll.update(gameClone.notifications)
|
||||
notificationsScroll.width = stage.width/3
|
||||
notificationsScroll.setPosition(stage.width - notificationsScroll.width - 5f,
|
||||
nextTurnButton.y - notificationsScroll.height - 5f)
|
||||
|
@ -130,7 +133,7 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
else if(civInfo.greatPeople.freeGreatPeople>0) game.screen = GreatPersonPickerScreen()
|
||||
}
|
||||
|
||||
private fun updateDiplomacyButton() {
|
||||
private fun updateDiplomacyButton(civInfo: CivilizationInfo) {
|
||||
diplomacyButtonWrapper.clear()
|
||||
if(civInfo.diplomacy.values.map { it.otherCiv() }
|
||||
.filterNot { it.isDefeated() || it.isPlayerCivilization() || it.isBarbarianCivilization() }
|
||||
|
@ -144,7 +147,7 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
diplomacyButtonWrapper.y = techButton.y -20 - diplomacyButtonWrapper.height
|
||||
}
|
||||
|
||||
private fun updateTechButton() {
|
||||
private fun updateTechButton(civInfo: CivilizationInfo) {
|
||||
techButton.isVisible = civInfo.cities.isNotEmpty()
|
||||
|
||||
if (civInfo.tech.currentTechnology() == null)
|
||||
|
|
|
@ -103,9 +103,7 @@ class WorldScreenTopBar(val screen: WorldScreen) : Table() {
|
|||
}
|
||||
|
||||
|
||||
internal fun update() {
|
||||
val civInfo = screen.civInfo
|
||||
|
||||
internal fun update(civInfo: CivilizationInfo) {
|
||||
val revealedStrategicResources = GameBasics.TileResources.values
|
||||
.filter { it.resourceType == ResourceType.Strategic } // && }
|
||||
val civResources = civInfo.getCivResources()
|
||||
|
|
|
@ -18,7 +18,6 @@ class WorldScreenDisplayOptionsTable() : PopupTable(){
|
|||
val settings = UnCivGame.Current.settings
|
||||
settings.save()
|
||||
clear()
|
||||
val tileMapHolder = UnCivGame.Current.worldScreen.tileMapHolder
|
||||
|
||||
if (settings.showWorkedTiles) addButton("{Hide} {worked tiles}") { settings.showWorkedTiles = false; update() }
|
||||
else addButton("{Show} {worked tiles}") { settings.showWorkedTiles = true; update() }
|
||||
|
@ -64,6 +63,6 @@ class WorldScreenDisplayOptionsTable() : PopupTable(){
|
|||
|
||||
pack() // Needed to show the background.
|
||||
center(UnCivGame.Current.worldScreen.stage)
|
||||
tileMapHolder.updateTiles()
|
||||
UnCivGame.Current.worldScreen.update()
|
||||
}
|
||||
}
|
|
@ -2,22 +2,20 @@ package com.unciv.game.desktop;
|
|||
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.tools.texturepacker.TexturePacker;
|
||||
import com.unciv.UnCivGame;
|
||||
|
||||
class DesktopLauncher {
|
||||
public static void main (String[] arg) {
|
||||
|
||||
TexturePacker.Settings settings = new TexturePacker.Settings();
|
||||
settings.maxWidth = 2048;
|
||||
settings.maxHeight = 2048;
|
||||
settings.combineSubdirectories=true;
|
||||
|
||||
// This is so they don't look all pixelated
|
||||
settings.filterMag = Texture.TextureFilter.MipMapLinearLinear;
|
||||
settings.filterMin = Texture.TextureFilter.MipMapLinearLinear;
|
||||
TexturePacker.process(settings, "../images", ".", "game");
|
||||
//
|
||||
// TexturePacker.Settings settings = new TexturePacker.Settings();
|
||||
// settings.maxWidth = 2048;
|
||||
// settings.maxHeight = 2048;
|
||||
// settings.combineSubdirectories=true;
|
||||
//
|
||||
// // This is so they don't look all pixelated
|
||||
// settings.filterMag = Texture.TextureFilter.MipMapLinearLinear;
|
||||
// settings.filterMin = Texture.TextureFilter.MipMapLinearLinear;
|
||||
// TexturePacker.process(settings, "../images", ".", "game");
|
||||
|
||||
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
|
||||
new LwjglApplication(new UnCivGame(), config);
|
||||
|
|
Loading…
Reference in a new issue