mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-20 04:38:18 +07:00
Hoh boy so many changes to ensure the regular game works with multiplayer...
This commit is contained in:
@ -21,8 +21,8 @@ android {
|
|||||||
applicationId "com.unciv.app"
|
applicationId "com.unciv.app"
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 290
|
versionCode 292
|
||||||
versionName "2.19.9"
|
versionName "2.19.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Had to add this crap for Travis to build, it wanted to sign the app
|
// Had to add this crap for Travis to build, it wanted to sign the app
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.unciv
|
package com.unciv
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Application
|
||||||
import com.badlogic.gdx.Game
|
import com.badlogic.gdx.Game
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
@ -12,6 +13,7 @@ import com.unciv.models.metadata.GameSettings
|
|||||||
import com.unciv.ui.LanguagePickerScreen
|
import com.unciv.ui.LanguagePickerScreen
|
||||||
import com.unciv.ui.utils.ImageGetter
|
import com.unciv.ui.utils.ImageGetter
|
||||||
import com.unciv.ui.worldscreen.WorldScreen
|
import com.unciv.ui.worldscreen.WorldScreen
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class UnCivGame(val version: String) : Game() {
|
class UnCivGame(val version: String) : Game() {
|
||||||
var gameInfo: GameInfo = GameInfo()
|
var gameInfo: GameInfo = GameInfo()
|
||||||
@ -21,18 +23,25 @@ class UnCivGame(val version: String) : Game() {
|
|||||||
* This exists so that when debugging we can see the entire map.
|
* This exists so that when debugging we can see the entire map.
|
||||||
* Remember to turn this to false before commit and upload!
|
* Remember to turn this to false before commit and upload!
|
||||||
*/
|
*/
|
||||||
val viewEntireMapForDebug = false
|
var viewEntireMapForDebug = false
|
||||||
|
|
||||||
/** For when you need to test something in an advanced game and don't have time to faff around */
|
/** For when you need to test something in an advanced game and don't have time to faff around */
|
||||||
val superchargedForDebug = false
|
val superchargedForDebug = false
|
||||||
|
val mutiplayerEnabled = false
|
||||||
|
|
||||||
lateinit var worldScreen: WorldScreen
|
lateinit var worldScreen: WorldScreen
|
||||||
|
|
||||||
override fun create() {
|
override fun create() {
|
||||||
Current = this
|
Current = this
|
||||||
|
if(Gdx.app.type!= Application.ApplicationType.Desktop)
|
||||||
|
viewEntireMapForDebug=false
|
||||||
Gdx.input.setCatchKey(Input.Keys.BACK, true)
|
Gdx.input.setCatchKey(Input.Keys.BACK, true)
|
||||||
GameBasics.run { } // just to initialize the GameBasics
|
GameBasics.run { } // just to initialize the GameBasics
|
||||||
settings = GameSaver().getGeneralSettings()
|
settings = GameSaver().getGeneralSettings()
|
||||||
|
if(settings.userId=="") { // assign permanent user id
|
||||||
|
settings.userId = UUID.randomUUID().toString()
|
||||||
|
settings.save()
|
||||||
|
}
|
||||||
if (GameSaver().getSave("Autosave").exists()) {
|
if (GameSaver().getSave("Autosave").exists()) {
|
||||||
try {
|
try {
|
||||||
loadGame("Autosave")
|
loadGame("Autosave")
|
||||||
@ -45,7 +54,8 @@ class UnCivGame(val version: String) : Game() {
|
|||||||
|
|
||||||
fun loadGame(gameInfo:GameInfo){
|
fun loadGame(gameInfo:GameInfo){
|
||||||
this.gameInfo = gameInfo
|
this.gameInfo = gameInfo
|
||||||
worldScreen = WorldScreen(gameInfo.currentPlayerCiv)
|
|
||||||
|
worldScreen = WorldScreen(gameInfo.getPlayerToViewAs())
|
||||||
setWorldScreen()
|
setWorldScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +65,7 @@ class UnCivGame(val version: String) : Game() {
|
|||||||
|
|
||||||
fun startNewGame() {
|
fun startNewGame() {
|
||||||
val newGame = GameStarter().startNewGame(GameParameters().apply { difficulty="Chieftain" })
|
val newGame = GameStarter().startNewGame(GameParameters().apply { difficulty="Chieftain" })
|
||||||
gameInfo = newGame
|
loadGame(newGame)
|
||||||
|
|
||||||
worldScreen = WorldScreen(gameInfo.currentPlayerCiv)
|
|
||||||
setWorldScreen()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setWorldScreen() {
|
fun setWorldScreen() {
|
||||||
@ -80,8 +87,7 @@ class UnCivGame(val version: String) : Game() {
|
|||||||
return create()
|
return create()
|
||||||
|
|
||||||
if(::worldScreen.isInitialized) worldScreen.dispose() // I hope this will solve some of the many OuOfMemory exceptions...
|
if(::worldScreen.isInitialized) worldScreen.dispose() // I hope this will solve some of the many OuOfMemory exceptions...
|
||||||
worldScreen = WorldScreen(gameInfo.currentPlayerCiv)
|
loadGame(gameInfo)
|
||||||
setWorldScreen()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maybe this will solve the resume error on chrome OS, issue 322? Worth a shot
|
// Maybe this will solve the resume error on chrome OS, issue 322? Worth a shot
|
||||||
|
@ -2,6 +2,7 @@ package com.unciv.logic
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
|
import com.unciv.UnCivGame
|
||||||
import com.unciv.logic.automation.NextTurnAutomation
|
import com.unciv.logic.automation.NextTurnAutomation
|
||||||
import com.unciv.logic.city.CityConstructions
|
import com.unciv.logic.city.CityConstructions
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
@ -39,9 +40,17 @@ class GameInfo {
|
|||||||
toReturn.turns = turns
|
toReturn.turns = turns
|
||||||
toReturn.difficulty=difficulty
|
toReturn.difficulty=difficulty
|
||||||
toReturn.gameParameters = gameParameters
|
toReturn.gameParameters = gameParameters
|
||||||
|
toReturn.gameId = gameId
|
||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPlayerToViewAs(): CivilizationInfo {
|
||||||
|
if (!gameParameters.isOnlineMultiplayer) return currentPlayerCiv // non-online, play as human player
|
||||||
|
val userId = UnCivGame.Current.settings.userId
|
||||||
|
if (civilizations.any { it.playerId == userId}) return civilizations.first { it.playerId == userId }
|
||||||
|
else return getBarbarianCivilization()// you aren't anyone. How did you even get this game? Can you spectate?
|
||||||
|
}
|
||||||
|
|
||||||
fun getCivilization(civName:String) = civilizations.first { it.civName==civName }
|
fun getCivilization(civName:String) = civilizations.first { it.civName==civName }
|
||||||
fun getCurrentPlayerCivilization() = currentPlayerCiv
|
fun getCurrentPlayerCivilization() = currentPlayerCiv
|
||||||
fun getBarbarianCivilization() = getCivilization("Barbarians")
|
fun getBarbarianCivilization() = getCivilization("Barbarians")
|
||||||
|
@ -76,13 +76,14 @@ class CivilizationInfo {
|
|||||||
val toReturn = CivilizationInfo()
|
val toReturn = CivilizationInfo()
|
||||||
toReturn.gold = gold
|
toReturn.gold = gold
|
||||||
toReturn.playerType = playerType
|
toReturn.playerType = playerType
|
||||||
|
toReturn.playerId = playerId
|
||||||
toReturn.civName = civName
|
toReturn.civName = civName
|
||||||
toReturn.tech = tech.clone()
|
toReturn.tech = tech.clone()
|
||||||
toReturn.policies = policies.clone()
|
toReturn.policies = policies.clone()
|
||||||
toReturn.goldenAges = goldenAges.clone()
|
toReturn.goldenAges = goldenAges.clone()
|
||||||
toReturn.greatPeople = greatPeople.clone()
|
toReturn.greatPeople = greatPeople.clone()
|
||||||
toReturn.victoryManager = victoryManager.clone()
|
toReturn.victoryManager = victoryManager.clone()
|
||||||
for(diplomacyManager in diplomacy.values.map { it.clone() })
|
for (diplomacyManager in diplomacy.values.map { it.clone() })
|
||||||
toReturn.diplomacy.put(diplomacyManager.otherCivName, diplomacyManager)
|
toReturn.diplomacy.put(diplomacyManager.otherCivName, diplomacyManager)
|
||||||
toReturn.cities = cities.map { it.clone() }
|
toReturn.cities = cities.map { it.clone() }
|
||||||
|
|
||||||
|
@ -310,10 +310,10 @@ open class TileInfo {
|
|||||||
turnsToImprovement = improvement.getTurnsToBuild(civInfo)
|
turnsToImprovement = improvement.getTurnsToBuild(civInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasEnemySubmarine(): Boolean {
|
fun hasEnemySubmarine(viewingCiv:CivilizationInfo): Boolean {
|
||||||
val unitsInTile = getUnits()
|
val unitsInTile = getUnits()
|
||||||
if (unitsInTile.isEmpty()) return false
|
if (unitsInTile.isEmpty()) return false
|
||||||
if (!unitsInTile.first().civInfo.isPlayerCivilization() &&
|
if (unitsInTile.first().civInfo!=viewingCiv &&
|
||||||
unitsInTile.firstOrNull { it.isInvisible() } != null) {
|
unitsInTile.firstOrNull { it.isInvisible() } != null) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -135,44 +135,45 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getTileToMoveToThisTurn(finalDestination:TileInfo): TileInfo {
|
||||||
|
|
||||||
|
val currentTile = unit.getTile()
|
||||||
|
if (currentTile == finalDestination) return currentTile
|
||||||
|
|
||||||
|
if(unit.type.isAirUnit()){
|
||||||
|
return finalDestination // head there directly
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val distanceToTiles = getDistanceToTiles()
|
||||||
|
|
||||||
|
if (distanceToTiles.containsKey(finalDestination)) { // we should be able to get there this turn
|
||||||
|
if (canMoveTo(finalDestination))
|
||||||
|
return finalDestination
|
||||||
|
|
||||||
|
// Someone is blocking to the path to the final tile...
|
||||||
|
val destinationNeighbors = finalDestination.neighbors
|
||||||
|
if (destinationNeighbors.contains(currentTile)) // We're right nearby anyway, no need to move
|
||||||
|
return currentTile
|
||||||
|
|
||||||
|
val reachableDestinationNeighbors = destinationNeighbors
|
||||||
|
.filter { distanceToTiles.containsKey(it) && canMoveTo(it) }
|
||||||
|
if (reachableDestinationNeighbors.isEmpty()) // We can't get closer...
|
||||||
|
return currentTile
|
||||||
|
|
||||||
|
return reachableDestinationNeighbors.minBy { distanceToTiles[it]!!.totalDistance }!! // we can get a little closer
|
||||||
|
} // If the tile is far away, we need to build a path how to get there, and then take the first step
|
||||||
|
val path = getShortestPath(finalDestination)
|
||||||
|
class UnreachableDestinationException : Exception()
|
||||||
|
if (path.isEmpty()) throw UnreachableDestinationException()
|
||||||
|
return path.first()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The tile that we reached this turn
|
* @return The tile that we reached this turn
|
||||||
*/
|
*/
|
||||||
fun headTowards(destination: TileInfo): TileInfo {
|
fun headTowards(destination: TileInfo): TileInfo {
|
||||||
val currentTile = unit.getTile()
|
val destinationTileThisTurn = getTileToMoveToThisTurn(destination)
|
||||||
if (currentTile == destination) return currentTile
|
|
||||||
|
|
||||||
if(unit.type.isAirUnit()){
|
|
||||||
moveToTile(destination)
|
|
||||||
return destination
|
|
||||||
}
|
|
||||||
|
|
||||||
val distanceToTiles = getDistanceToTiles()
|
|
||||||
|
|
||||||
val destinationTileThisTurn: TileInfo
|
|
||||||
if (distanceToTiles.containsKey(destination)) { // we can get there this turn
|
|
||||||
if (canMoveTo(destination))
|
|
||||||
destinationTileThisTurn = destination
|
|
||||||
else // Someone is blocking to the path to the final tile...
|
|
||||||
{
|
|
||||||
val destinationNeighbors = destination.neighbors
|
|
||||||
if (destinationNeighbors.contains(currentTile)) // We're right nearby anyway, no need to move
|
|
||||||
return currentTile
|
|
||||||
|
|
||||||
val reachableDestinationNeighbors = destinationNeighbors
|
|
||||||
.filter { distanceToTiles.containsKey(it) && canMoveTo(it) }
|
|
||||||
if (reachableDestinationNeighbors.isEmpty()) // We can't get closer...
|
|
||||||
return currentTile
|
|
||||||
|
|
||||||
destinationTileThisTurn = reachableDestinationNeighbors.minBy { distanceToTiles[it]!!.totalDistance }!!
|
|
||||||
}
|
|
||||||
} else { // If the tile is far away, we need to build a path how to get there, and then take the first step
|
|
||||||
val path = getShortestPath(destination)
|
|
||||||
class UnreachableDestinationException : Exception()
|
|
||||||
if (path.isEmpty()) throw UnreachableDestinationException()
|
|
||||||
destinationTileThisTurn = path.first()
|
|
||||||
}
|
|
||||||
|
|
||||||
moveToTile(destinationTileThisTurn)
|
moveToTile(destinationTileThisTurn)
|
||||||
return destinationTileThisTurn
|
return destinationTileThisTurn
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.unciv.models.metadata
|
package com.unciv.models.metadata
|
||||||
|
|
||||||
import com.unciv.logic.GameSaver
|
import com.unciv.logic.GameSaver
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class GameSettings {
|
class GameSettings {
|
||||||
var showWorkedTiles: Boolean = false
|
var showWorkedTiles: Boolean = false
|
||||||
@ -20,7 +18,7 @@ class GameSettings {
|
|||||||
var autoAssignCityProduction: Boolean = true
|
var autoAssignCityProduction: Boolean = true
|
||||||
|
|
||||||
var userName:String=""
|
var userName:String=""
|
||||||
var userId = UUID.randomUUID().toString()
|
var userId = ""
|
||||||
|
|
||||||
fun save(){
|
fun save(){
|
||||||
GameSaver().setGeneralSettings(this)
|
GameSaver().setGeneralSettings(this)
|
||||||
|
@ -2,7 +2,6 @@ package com.unciv.ui.cityscreen
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
import com.unciv.UnCivGame
|
|
||||||
import com.unciv.logic.city.CityInfo
|
import com.unciv.logic.city.CityInfo
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
import com.unciv.ui.tilegroups.TileGroup
|
import com.unciv.ui.tilegroups.TileGroup
|
||||||
@ -26,12 +25,7 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo, tileSetStrin
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun update() {
|
fun update() {
|
||||||
val canSeeTile = UnCivGame.Current.viewEntireMapForDebug
|
super.update(city.civInfo,true)
|
||||||
|| city.civInfo.viewableTiles.contains(tileInfo)
|
|
||||||
val showSubmarine = UnCivGame.Current.viewEntireMapForDebug
|
|
||||||
|| city.civInfo.viewableInvisibleUnitsTiles.contains(tileInfo)
|
|
||||||
|| (!tileInfo.hasEnemySubmarine())
|
|
||||||
super.update(canSeeTile,true, showSubmarine)
|
|
||||||
|
|
||||||
// this needs to happen on update, because we can buy tiles, which changes the definition of the bought tiles...
|
// this needs to happen on update, because we can buy tiles, which changes the definition of the bought tiles...
|
||||||
when {
|
when {
|
||||||
|
@ -37,7 +37,7 @@ class MapEditorOptionsTable(mapEditorScreen: MapEditorScreen): PopupTable(mapEdi
|
|||||||
tile.roadStatus=RoadStatus.None
|
tile.roadStatus=RoadStatus.None
|
||||||
tile.setTransients()
|
tile.setTransients()
|
||||||
|
|
||||||
tileGroup.update(true,true,true)
|
tileGroup.update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
add(clearCurrentMapButton).row()
|
add(clearCurrentMapButton).row()
|
||||||
|
@ -66,13 +66,13 @@ class MapEditorScreen(): CameraStageBaseScreen(){
|
|||||||
val tileGroups = tileMap.values.map { TileGroup(it, tileSetStrings) }
|
val tileGroups = tileMap.values.map { TileGroup(it, tileSetStrings) }
|
||||||
for (tileGroup in tileGroups) {
|
for (tileGroup in tileGroups) {
|
||||||
tileGroup.showEntireMap = true
|
tileGroup.showEntireMap = true
|
||||||
tileGroup.update(true, true, true)
|
tileGroup.update()
|
||||||
tileGroup.onClick {
|
tileGroup.onClick {
|
||||||
val tileInfo = tileGroup.tileInfo
|
val tileInfo = tileGroup.tileInfo
|
||||||
|
|
||||||
tileEditorOptions.updateTileWhenClicked(tileInfo)
|
tileEditorOptions.updateTileWhenClicked(tileInfo)
|
||||||
tileGroup.tileInfo.setTransients()
|
tileGroup.tileInfo.setTransients()
|
||||||
tileGroup.update(true, true, true)
|
tileGroup.update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
val group = TileGroup(tileInfo, TileSetStrings())
|
val group = TileGroup(tileInfo, TileSetStrings())
|
||||||
group.showEntireMap=true
|
group.showEntireMap=true
|
||||||
group.forMapEditorIcon=true
|
group.forMapEditorIcon=true
|
||||||
group.update(true,true,true)
|
group.update()
|
||||||
|
|
||||||
group.onClick {
|
group.onClick {
|
||||||
clearSelection()
|
clearSelection()
|
||||||
@ -249,7 +249,7 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
|||||||
.apply {
|
.apply {
|
||||||
showEntireMap=true
|
showEntireMap=true
|
||||||
forMapEditorIcon=true
|
forMapEditorIcon=true
|
||||||
update(true,true,true)
|
update()
|
||||||
}
|
}
|
||||||
setCurrentHex(tileGroup)
|
setCurrentHex(tileGroup)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin
|
|||||||
import com.badlogic.gdx.utils.Array
|
import com.badlogic.gdx.utils.Array
|
||||||
import com.unciv.UnCivGame
|
import com.unciv.UnCivGame
|
||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
|
import com.unciv.logic.GameSaver
|
||||||
import com.unciv.logic.GameStarter
|
import com.unciv.logic.GameStarter
|
||||||
import com.unciv.logic.civilization.PlayerType
|
import com.unciv.logic.civilization.PlayerType
|
||||||
import com.unciv.models.gamebasics.tr
|
import com.unciv.models.gamebasics.tr
|
||||||
@ -66,8 +67,10 @@ class NewGameScreen: PickerScreen(){
|
|||||||
try {
|
try {
|
||||||
newGame = GameStarter().startNewGame(newGameParameters)
|
newGame = GameStarter().startNewGame(newGameParameters)
|
||||||
if (newGameParameters.isOnlineMultiplayer) {
|
if (newGameParameters.isOnlineMultiplayer) {
|
||||||
|
newGame!!.isUpToDate=true // So we don't try to download it from dropbox the second after we upload it - the file is not yet ready for loading!
|
||||||
try {
|
try {
|
||||||
OnlineMultiplayer().tryUploadGame(newGame!!)
|
OnlineMultiplayer().tryUploadGame(newGame!!)
|
||||||
|
GameSaver().autoSave(newGame!!){}
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
val cantUploadNewGamePopup = PopupTable(this)
|
val cantUploadNewGamePopup = PopupTable(this)
|
||||||
cantUploadNewGamePopup.addGoodSizedLabel("Can't upload the new game!")
|
cantUploadNewGamePopup.addGoodSizedLabel("Can't upload the new game!")
|
||||||
|
@ -6,6 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
|||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
|
||||||
import com.badlogic.gdx.utils.Array
|
import com.badlogic.gdx.utils.Array
|
||||||
|
import com.unciv.UnCivGame
|
||||||
import com.unciv.logic.MapSaver
|
import com.unciv.logic.MapSaver
|
||||||
import com.unciv.logic.map.MapType
|
import com.unciv.logic.map.MapType
|
||||||
import com.unciv.models.gamebasics.GameBasics
|
import com.unciv.models.gamebasics.GameBasics
|
||||||
@ -25,7 +26,9 @@ class NewGameScreenOptionsTable(val newGameParameters: GameParameters, val onMul
|
|||||||
addCityStatesSelectBox()
|
addCityStatesSelectBox()
|
||||||
addVictoryTypeCheckboxes()
|
addVictoryTypeCheckboxes()
|
||||||
addBarbariansCheckbox()
|
addBarbariansCheckbox()
|
||||||
//addIsOnlineMultiplayerCheckbox()
|
|
||||||
|
if(UnCivGame.Current.mutiplayerEnabled)
|
||||||
|
addIsOnlineMultiplayerCheckbox()
|
||||||
|
|
||||||
pack()
|
pack()
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ class PlayerPickerTable(val newGameScreen: NewGameScreen, val newGameParameters:
|
|||||||
val playerIdTable = Table()
|
val playerIdTable = Table()
|
||||||
playerIdTable.add("Player ID:".toLabel())
|
playerIdTable.add("Player ID:".toLabel())
|
||||||
|
|
||||||
val playerIdTextfield = TextField("", CameraStageBaseScreen.skin)
|
val playerIdTextfield = TextField(player.playerId, CameraStageBaseScreen.skin)
|
||||||
playerIdTable.add(playerIdTextfield)
|
playerIdTable.add(playerIdTextfield)
|
||||||
val errorLabel = "Not a valid user id!".toLabel().setFontColor(Color.RED)
|
val errorLabel = "Not a valid user id!".toLabel().setFontColor(Color.RED)
|
||||||
errorLabel.isVisible=false
|
errorLabel.isVisible=false
|
||||||
|
@ -185,33 +185,42 @@ open class TileGroup(var tileInfo: TileInfo, var tileSetStrings:TileSetStrings)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showMilitaryUnit(viewingCiv: CivilizationInfo) = showEntireMap
|
||||||
|
|| viewingCiv.viewableInvisibleUnitsTiles.contains(tileInfo)
|
||||||
|
|| (!tileInfo.hasEnemySubmarine(viewingCiv))
|
||||||
|
|
||||||
open fun update(isViewable: Boolean, showResourcesAndImprovements:Boolean, showSubmarine: Boolean) {
|
fun isViewable(viewingCiv: CivilizationInfo) = showEntireMap
|
||||||
|
|| viewingCiv.viewableTiles.contains(tileInfo)
|
||||||
|
|
||||||
|
open fun update(viewingCiv:CivilizationInfo?=null, showResourcesAndImprovements: Boolean=true) {
|
||||||
hideCircle()
|
hideCircle()
|
||||||
if (!showEntireMap
|
if (viewingCiv!=null && !showEntireMap
|
||||||
&& !tileInfo.tileMap.gameInfo.getCurrentPlayerCivilization().exploredTiles.contains(tileInfo.position)) {
|
&& !viewingCiv.exploredTiles.contains(tileInfo.position)) {
|
||||||
tileBaseImage.color = Color.DARK_GRAY
|
tileBaseImage.color = Color.DARK_GRAY
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val tileIsViewable = viewingCiv==null || isViewable(viewingCiv)
|
||||||
|
val showMilitaryUnit = viewingCiv==null || showMilitaryUnit(viewingCiv)
|
||||||
|
|
||||||
updateTileImage(true)
|
updateTileImage(true)
|
||||||
updateTerrainBaseImage()
|
updateTerrainBaseImage()
|
||||||
updateTerrainFeatureImage()
|
updateTerrainFeatureImage()
|
||||||
updateCityImage()
|
updateCityImage()
|
||||||
updateTileColor(isViewable)
|
updateTileColor(tileIsViewable)
|
||||||
|
|
||||||
updateResourceImage(showResourcesAndImprovements)
|
updateResourceImage(showResourcesAndImprovements)
|
||||||
updateImprovementImage(showResourcesAndImprovements)
|
updateImprovementImage(showResourcesAndImprovements)
|
||||||
|
|
||||||
|
|
||||||
civilianUnitImage = newUnitImage(tileInfo.civilianUnit, civilianUnitImage, isViewable, -20f)
|
civilianUnitImage = newUnitImage(tileInfo.civilianUnit, civilianUnitImage, tileIsViewable, -20f)
|
||||||
militaryUnitImage = newUnitImage(tileInfo.militaryUnit, militaryUnitImage, isViewable && showSubmarine, 20f)
|
militaryUnitImage = newUnitImage(tileInfo.militaryUnit, militaryUnitImage, tileIsViewable && showMilitaryUnit, 20f)
|
||||||
|
|
||||||
updateRoadImages()
|
updateRoadImages()
|
||||||
updateBorderImages()
|
updateBorderImages()
|
||||||
|
|
||||||
crosshairImage.isVisible = false
|
crosshairImage.isVisible = false
|
||||||
fogImage.isVisible = !(isViewable || showEntireMap)
|
fogImage.isVisible = !(tileIsViewable || showEntireMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTerrainBaseImage() {
|
private fun updateTerrainBaseImage() {
|
||||||
|
@ -2,6 +2,7 @@ package com.unciv.ui.tilegroups
|
|||||||
|
|
||||||
import com.unciv.UnCivGame
|
import com.unciv.UnCivGame
|
||||||
import com.unciv.logic.city.CityInfo
|
import com.unciv.logic.city.CityInfo
|
||||||
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
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
|
||||||
@ -20,21 +21,21 @@ class WorldTileGroup(internal val worldScreen: WorldScreen, tileInfo: TileInfo,
|
|||||||
unitImage?.selectUnit()
|
unitImage?.selectUnit()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(isViewable: Boolean, showSubmarine: Boolean) {
|
fun update(viewingCiv: CivilizationInfo) {
|
||||||
val city = tileInfo.getCity()
|
val city = tileInfo.getCity()
|
||||||
|
|
||||||
removePopulationIcon()
|
removePopulationIcon()
|
||||||
if (isViewable && tileInfo.isWorked() && UnCivGame.Current.settings.showWorkedTiles
|
val tileIsViewable = isViewable(viewingCiv)
|
||||||
|
if (tileIsViewable && tileInfo.isWorked() && UnCivGame.Current.settings.showWorkedTiles
|
||||||
&& city!!.civInfo.isPlayerCivilization())
|
&& city!!.civInfo.isPlayerCivilization())
|
||||||
addPopulationIcon()
|
addPopulationIcon()
|
||||||
|
|
||||||
val currentPlayerCiv = worldScreen.viewingCiv
|
val currentPlayerCiv = worldScreen.viewingCiv
|
||||||
if (UnCivGame.Current.viewEntireMapForDebug
|
if (UnCivGame.Current.viewEntireMapForDebug
|
||||||
|| currentPlayerCiv.exploredTiles.contains(tileInfo.position))
|
|| currentPlayerCiv.exploredTiles.contains(tileInfo.position))
|
||||||
updateCityButton(city, isViewable || UnCivGame.Current.viewEntireMapForDebug) // needs to be before the update so the units will be above the city button
|
updateCityButton(city, tileIsViewable || UnCivGame.Current.viewEntireMapForDebug) // needs to be before the update so the units will be above the city button
|
||||||
|
|
||||||
super.update(isViewable || UnCivGame.Current.viewEntireMapForDebug,
|
super.update(viewingCiv, UnCivGame.Current.settings.showResourcesAndImprovements)
|
||||||
UnCivGame.Current.settings.showResourcesAndImprovements, showSubmarine)
|
|
||||||
|
|
||||||
|
|
||||||
// order by z index!
|
// order by z index!
|
||||||
|
@ -32,7 +32,6 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
val tileGroups = HashMap<TileInfo, WorldTileGroup>()
|
val tileGroups = HashMap<TileInfo, WorldTileGroup>()
|
||||||
|
|
||||||
var unitActionOverlay :Actor?=null
|
var unitActionOverlay :Actor?=null
|
||||||
var removeUnitActionOverlay=false
|
|
||||||
|
|
||||||
// Used to transfer data on the "move here" button that should be created, from the side thread to the main thread
|
// Used to transfer data on the "move here" button that should be created, from the side thread to the main thread
|
||||||
class MoveHereButtonDto(val unit: MapUnit, val tileInfo: TileInfo, val turnsToGetThere: Int)
|
class MoveHereButtonDto(val unit: MapUnit, val tileInfo: TileInfo, val turnsToGetThere: Int)
|
||||||
@ -170,7 +169,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
worldScreen.bottomBar.unitTable.selectedUnit = unit
|
worldScreen.bottomBar.unitTable.selectedUnit = unit
|
||||||
worldScreen.bottomBar.unitTable.selectedCity = null
|
worldScreen.bottomBar.unitTable.selectedCity = null
|
||||||
worldScreen.shouldUpdate = true
|
worldScreen.shouldUpdate = true
|
||||||
removeUnitActionOverlay = true
|
unitActionOverlay?.remove()
|
||||||
}
|
}
|
||||||
table.add(unitGroup)
|
table.add(unitGroup)
|
||||||
}
|
}
|
||||||
@ -238,32 +237,22 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun updateTiles(civInfo: CivilizationInfo) {
|
internal fun updateTiles(viewingCiv: CivilizationInfo) {
|
||||||
if(removeUnitActionOverlay){
|
|
||||||
removeUnitActionOverlay=false
|
|
||||||
unitActionOverlay?.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
val playerViewableTilePositions = civInfo.viewableTiles.map { it.position }.toHashSet()
|
val playerViewableTilePositions = viewingCiv.viewableTiles.map { it.position }.toHashSet()
|
||||||
val playerViewableInvisibleUnitsTilePositions = civInfo.viewableInvisibleUnitsTiles.map { it.position }.toHashSet()
|
val playerViewableInvisibleUnitsTilePositions = viewingCiv.viewableInvisibleUnitsTiles.map { it.position }.toHashSet()
|
||||||
|
|
||||||
for (tileGroup in tileGroups.values){
|
for (tileGroup in tileGroups.values){
|
||||||
val canSeeTile = UnCivGame.Current.viewEntireMapForDebug
|
tileGroup.update(viewingCiv)
|
||||||
|| playerViewableTilePositions.contains(tileGroup.tileInfo.position)
|
|
||||||
|
|
||||||
val showSubmarine = UnCivGame.Current.viewEntireMapForDebug
|
|
||||||
|| playerViewableInvisibleUnitsTilePositions.contains(tileGroup.tileInfo.position)
|
|
||||||
|| (!tileGroup.tileInfo.hasEnemySubmarine())
|
|
||||||
tileGroup.update(canSeeTile, showSubmarine)
|
|
||||||
|
|
||||||
if(tileGroup.tileInfo.improvement==Constants.barbarianEncampment
|
if(tileGroup.tileInfo.improvement==Constants.barbarianEncampment
|
||||||
&& tileGroup.tileInfo.position in civInfo.exploredTiles)
|
&& tileGroup.tileInfo.position in viewingCiv.exploredTiles)
|
||||||
tileGroup.showCircle(Color.RED)
|
tileGroup.showCircle(Color.RED)
|
||||||
|
|
||||||
val unitsInTile = tileGroup.tileInfo.getUnits()
|
val unitsInTile = tileGroup.tileInfo.getUnits()
|
||||||
val canSeeEnemy = unitsInTile.isNotEmpty() && unitsInTile.first().civInfo.isAtWarWith(civInfo)
|
val canSeeEnemy = unitsInTile.isNotEmpty() && unitsInTile.first().civInfo.isAtWarWith(viewingCiv)
|
||||||
&& (showSubmarine || unitsInTile.firstOrNull {!it.isInvisible()}!=null)
|
&& tileGroup.showMilitaryUnit(viewingCiv)
|
||||||
if(canSeeTile && canSeeEnemy)
|
if(tileGroup.isViewable(viewingCiv) && canSeeEnemy)
|
||||||
tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
|
tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||||
@ -113,23 +114,36 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
|
|
||||||
update()
|
update()
|
||||||
|
|
||||||
if(gameInfo.gameParameters.isOnlineMultiplayer && !gameInfo.isUpToDate) {
|
if(gameInfo.gameParameters.isOnlineMultiplayer && !gameInfo.isUpToDate)
|
||||||
isPlayersTurn = false // until we're up to date, don't let the player do anything
|
isPlayersTurn = false // until we're up to date, don't let the player do anything
|
||||||
val loadingGamePopup = PopupTable(this)
|
if(gameInfo.gameParameters.isOnlineMultiplayer && !isPlayersTurn) {
|
||||||
loadingGamePopup.add("Loading latest game state...")
|
stage.addAction(Actions.forever(Actions.sequence(Actions.run {
|
||||||
loadingGamePopup.open()
|
loadLatestMultiplayerState()
|
||||||
thread {
|
}, Actions.delay(10f)))) // delay is in seconds
|
||||||
try {
|
}
|
||||||
val latestGame = OnlineMultiplayer().tryDownloadGame(gameInfo.gameId)
|
}
|
||||||
latestGame.isUpToDate=true
|
|
||||||
game.loadGame(latestGame)
|
fun loadLatestMultiplayerState(){
|
||||||
} catch (ex: Exception) {
|
val loadingGamePopup = PopupTable(this)
|
||||||
|
loadingGamePopup.add("Loading latest game state...")
|
||||||
|
loadingGamePopup.open()
|
||||||
|
thread {
|
||||||
|
try {
|
||||||
|
val latestGame = OnlineMultiplayer().tryDownloadGame(gameInfo.gameId)
|
||||||
|
if(gameInfo.isUpToDate && gameInfo.currentPlayer==latestGame.currentPlayer) { // we were trying to download this to see when it's our turn...nothing changed
|
||||||
loadingGamePopup.close()
|
loadingGamePopup.close()
|
||||||
val couldntDownloadLatestGame = PopupTable(this)
|
return@thread
|
||||||
couldntDownloadLatestGame.addGoodSizedLabel("Couldn't download the latest game state!")
|
|
||||||
couldntDownloadLatestGame.addCloseButton()
|
|
||||||
couldntDownloadLatestGame.open()
|
|
||||||
}
|
}
|
||||||
|
latestGame.isUpToDate=true
|
||||||
|
// Since we're making a screen this needs to run from the man thread which has a GL context
|
||||||
|
Gdx.app.postRunnable { game.loadGame(latestGame) }
|
||||||
|
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
loadingGamePopup.close()
|
||||||
|
val couldntDownloadLatestGame = PopupTable(this)
|
||||||
|
couldntDownloadLatestGame.addGoodSizedLabel("Couldn't download the latest game state!")
|
||||||
|
couldntDownloadLatestGame.addCloseButton()
|
||||||
|
couldntDownloadLatestGame.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,23 +152,13 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
// That way, not only do we save a lot of unnecessary updates, we also ensure that all updates are called from the main GL thread
|
// That way, not only do we save a lot of unnecessary updates, we also ensure that all updates are called from the main GL thread
|
||||||
// and we don't get any silly concurrency problems!
|
// and we don't get any silly concurrency problems!
|
||||||
private fun update() {
|
private 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()
|
|
||||||
gameClone.setTransients()
|
|
||||||
val cloneCivilization = gameClone.getCurrentPlayerCivilization()
|
|
||||||
thread {
|
|
||||||
gameInfo.civilizations.forEach { it.setCitiesConnectedToCapitalTransients() }
|
|
||||||
}
|
|
||||||
|
|
||||||
displayTutorialsOnUpdate(cloneCivilization, gameClone)
|
|
||||||
|
|
||||||
|
displayTutorialsOnUpdate(viewingCiv, gameInfo)
|
||||||
|
|
||||||
bottomBar.update(tileMapHolder.selectedTile) // has to come before tilemapholder update because the tilemapholder actions depend on the selected unit!
|
bottomBar.update(tileMapHolder.selectedTile) // has to come before tilemapholder update because the tilemapholder actions depend on the selected unit!
|
||||||
battleTable.update()
|
battleTable.update()
|
||||||
|
|
||||||
minimapWrapper.update(cloneCivilization)
|
minimapWrapper.update(viewingCiv)
|
||||||
minimapWrapper.y = bottomBar.height // couldn't be bothered to create a separate val for minimap wrapper
|
minimapWrapper.y = bottomBar.height // couldn't be bothered to create a separate val for minimap wrapper
|
||||||
|
|
||||||
unitActionsTable.update(bottomBar.unitTable.selectedUnit)
|
unitActionsTable.update(bottomBar.unitTable.selectedUnit)
|
||||||
@ -165,12 +169,12 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
// it causes a bug when we move a unit to an unexplored tile (for instance a cavalry unit which can move far)
|
// it causes a bug when we move a unit to an unexplored tile (for instance a cavalry unit which can move far)
|
||||||
tileMapHolder.updateTiles(viewingCiv)
|
tileMapHolder.updateTiles(viewingCiv)
|
||||||
|
|
||||||
topBar.update(cloneCivilization)
|
topBar.update(viewingCiv)
|
||||||
|
|
||||||
updateTechButton(cloneCivilization)
|
updateTechButton(viewingCiv)
|
||||||
techPolicyandVictoryHolder.pack()
|
techPolicyandVictoryHolder.pack()
|
||||||
techPolicyandVictoryHolder.setPosition(10f, topBar.y - techPolicyandVictoryHolder.height - 5f)
|
techPolicyandVictoryHolder.setPosition(10f, topBar.y - techPolicyandVictoryHolder.height - 5f)
|
||||||
updateDiplomacyButton(cloneCivilization)
|
updateDiplomacyButton(viewingCiv)
|
||||||
|
|
||||||
notificationsScroll.update(viewingCiv.notifications)
|
notificationsScroll.update(viewingCiv.notifications)
|
||||||
notificationsScroll.setPosition(stage.width - notificationsScroll.width - 5f,
|
notificationsScroll.setPosition(stage.width - notificationsScroll.width - 5f,
|
||||||
@ -309,7 +313,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
shouldUpdate = true
|
shouldUpdate = true
|
||||||
|
|
||||||
|
|
||||||
thread {
|
thread { // on a separate thread so the user can explore their world while we're passing the turn
|
||||||
val gameInfoClone = gameInfo.clone()
|
val gameInfoClone = gameInfo.clone()
|
||||||
gameInfoClone.setTransients()
|
gameInfoClone.setTransients()
|
||||||
try {
|
try {
|
||||||
@ -342,7 +346,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
Gdx.app.postRunnable {
|
Gdx.app.postRunnable {
|
||||||
|
|
||||||
fun createNewWorldScreen(){
|
fun createNewWorldScreen(){
|
||||||
val newWorldScreen = WorldScreen(gameInfoClone.currentPlayerCiv)
|
val newWorldScreen = WorldScreen(gameInfoClone.getPlayerToViewAs())
|
||||||
newWorldScreen.tileMapHolder.scrollX = tileMapHolder.scrollX
|
newWorldScreen.tileMapHolder.scrollX = tileMapHolder.scrollX
|
||||||
newWorldScreen.tileMapHolder.scrollY = tileMapHolder.scrollY
|
newWorldScreen.tileMapHolder.scrollY = tileMapHolder.scrollY
|
||||||
newWorldScreen.tileMapHolder.scaleX = tileMapHolder.scaleX
|
newWorldScreen.tileMapHolder.scaleX = tileMapHolder.scaleX
|
||||||
|
@ -167,7 +167,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
|||||||
attackButton.onClick {
|
attackButton.onClick {
|
||||||
try {
|
try {
|
||||||
battle.moveAndAttack(attacker, attackableEnemy)
|
battle.moveAndAttack(attacker, attackableEnemy)
|
||||||
worldScreen.tileMapHolder.removeUnitActionOverlay = true // the overlay was one of attacking
|
worldScreen.tileMapHolder.unitActionOverlay?.remove() // the overlay was one of attacking
|
||||||
worldScreen.shouldUpdate = true
|
worldScreen.shouldUpdate = true
|
||||||
}
|
}
|
||||||
catch (ex:Exception){
|
catch (ex:Exception){
|
||||||
|
@ -58,9 +58,10 @@ class DropBox(){
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uploadFile(fileName: String, data: String){
|
fun uploadFile(fileName: String, data: String, overwrite:Boolean=false){
|
||||||
|
val overwriteModeString = if(!overwrite) "" else ""","mode":{".tag":"overwrite"}"""
|
||||||
val response = dropboxApi("https://content.dropboxapi.com/2/files/upload",
|
val response = dropboxApi("https://content.dropboxapi.com/2/files/upload",
|
||||||
data,"application/octet-stream","{\"path\":\"$fileName\"}")
|
data,"application/octet-stream", """{"path":"$fileName"$overwriteModeString}""")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,11 +81,11 @@ class OnlineMultiplayer(){
|
|||||||
|
|
||||||
fun tryUploadGame(gameInfo: GameInfo){
|
fun tryUploadGame(gameInfo: GameInfo){
|
||||||
val zippedGameInfo = Gzip.zip(GameSaver().json().toJson(gameInfo))
|
val zippedGameInfo = Gzip.zip(GameSaver().json().toJson(gameInfo))
|
||||||
DropBox().uploadFile(getGameLocation(gameInfo.gameId),zippedGameInfo)
|
DropBox().uploadFile(getGameLocation(gameInfo.gameId),zippedGameInfo,true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryDownloadGame(gameId: String): GameInfo {
|
fun tryDownloadGame(gameId: String): GameInfo {
|
||||||
val zippedGameInfo = DropBox().downloadFile(gameId)
|
val zippedGameInfo = DropBox().downloadFile(getGameLocation(gameId))
|
||||||
return GameSaver().gameInfoFromString(Gzip.unzip(zippedGameInfo))
|
return GameSaver().gameInfoFromString(Gzip.unzip(zippedGameInfo))
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -53,10 +53,11 @@ class WorldScreenMenuTable(val worldScreen: WorldScreen) : PopupTable(worldScree
|
|||||||
addButton("Start new game".tr()){ UnCivGame.Current.screen = NewGameScreen() }
|
addButton("Start new game".tr()){ UnCivGame.Current.screen = NewGameScreen() }
|
||||||
|
|
||||||
if(worldScreen.gameInfo.gameParameters.isOnlineMultiplayer){
|
if(worldScreen.gameInfo.gameParameters.isOnlineMultiplayer){
|
||||||
addButton("Copy game ID to clipboard".tr()){ Gdx.app.clipboard.contents = worldScreen.gameInfo.gameId }
|
addButton("Copy game ID".tr()){ Gdx.app.clipboard.contents = worldScreen.gameInfo.gameId }
|
||||||
}
|
}
|
||||||
|
|
||||||
// addJoinMultiplayerButton()
|
if(UnCivGame.Current.mutiplayerEnabled)
|
||||||
|
addJoinMultiplayerButton()
|
||||||
|
|
||||||
addButton("Victory status".tr()) { UnCivGame.Current.screen = VictoryScreen() }
|
addButton("Victory status".tr()) { UnCivGame.Current.screen = VictoryScreen() }
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.unciv.ui.worldscreen.unit
|
package com.unciv.ui.worldscreen.unit
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
|
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
|
||||||
@ -39,7 +40,7 @@ class UnitContextMenu(val tileMapHolder: TileMapHolder, val selectedUnit: MapUni
|
|||||||
addButton(icon, label) {
|
addButton(icon, label) {
|
||||||
selectedUnit.mapUnitAction = action
|
selectedUnit.mapUnitAction = action
|
||||||
selectedUnit.mapUnitAction?.doPreTurnAction()
|
selectedUnit.mapUnitAction?.doPreTurnAction()
|
||||||
tileMapHolder.removeUnitActionOverlay = true
|
tileMapHolder.unitActionOverlay?.remove()
|
||||||
tileMapHolder.worldScreen.shouldUpdate = true
|
tileMapHolder.worldScreen.shouldUpdate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,28 +58,32 @@ class UnitContextMenu(val tileMapHolder: TileMapHolder, val selectedUnit: MapUni
|
|||||||
fun onMoveButtonClick() {
|
fun onMoveButtonClick() {
|
||||||
// this can take a long time, because of the unit-to-tile calculation needed, so we put it in a different thread
|
// this can take a long time, because of the unit-to-tile calculation needed, so we put it in a different thread
|
||||||
thread {
|
thread {
|
||||||
if (selectedUnit.movement.canReach(targetTile)) {
|
// these are the heavy parts, finding where we want to go
|
||||||
|
if (!selectedUnit.movement.canReach(targetTile)) return@thread // can't move here
|
||||||
|
val tileToMoveTo = selectedUnit.movement.getTileToMoveToThisTurn(targetTile)
|
||||||
|
|
||||||
|
Gdx.app.postRunnable {
|
||||||
try {
|
try {
|
||||||
// Because this is darned concurrent (as it MUST be to avoid ANRs),
|
// Because this is darned concurrent (as it MUST be to avoid ANRs),
|
||||||
// there are edge cases where the canReach is true,
|
// there are edge cases where the canReach is true,
|
||||||
// but until it reaches the headTowards the board has changed and so the headTowards fails.
|
// but until it reaches the headTowards the board has changed and so the headTowards fails.
|
||||||
// I can't think of any way to avoid this,
|
// I can't think of any way to avoid this,
|
||||||
// but it's so rare and edge-case-y that ignoring its failure is actually acceptable, hence the empty catch
|
// but it's so rare and edge-case-y that ignoring its failure is actually acceptable, hence the empty catch
|
||||||
selectedUnit.movement.headTowards(targetTile)
|
selectedUnit.movement.moveToTile(tileToMoveTo)
|
||||||
Sounds.play("whoosh")
|
Sounds.play("whoosh")
|
||||||
if (selectedUnit.currentTile != targetTile)
|
if (selectedUnit.currentTile != targetTile)
|
||||||
selectedUnit.action = "moveTo " + targetTile.position.x.toInt() + "," + targetTile.position.y.toInt()
|
selectedUnit.action = "moveTo " + targetTile.position.x.toInt() + "," + targetTile.position.y.toInt()
|
||||||
if(selectedUnit.currentMovement>0){
|
if (selectedUnit.currentMovement > 0) {
|
||||||
tileMapHolder.worldScreen.bottomBar.unitTable.selectedUnit=selectedUnit
|
tileMapHolder.worldScreen.bottomBar.unitTable.selectedUnit = selectedUnit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we don't update it directly because we're on a different thread; instead, we tell it to update itself
|
||||||
|
tileMapHolder.worldScreen.shouldUpdate = true
|
||||||
|
tileMapHolder.unitActionOverlay?.remove()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we don't update it directly because we're on a different thread; instead, we tell it to update itself
|
|
||||||
tileMapHolder.worldScreen.shouldUpdate = true
|
|
||||||
|
|
||||||
tileMapHolder.removeUnitActionOverlay=true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user