mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-27 08:09:21 +07:00
Two extension features for custom maps (#11443)
* Fix apparent bug removing starting locations * Remove StartingLocation legacy support (when they were TileImprovements) * Starting locations get a "usage" controlling new game "select players" * Maps get a description map creators can use to pass info to their users * Fix bad fix from last PR preventing then map preview of the initial selection to show in some cases * Wrap all those setProgrammaticChangeEvents calls * Fix None/Normal discrepancy
This commit is contained in:
@ -544,6 +544,8 @@ An overlay image is incompatible with world wrap and was deactivated. =
|
||||
Choose a Wesnoth map file =
|
||||
That map is invalid! =
|
||||
("[code]" does not conform to TerrainCodesWML) =
|
||||
Use for new game "Select players" button: =
|
||||
Enter a description for the users of this map =
|
||||
|
||||
## Map/Tool names
|
||||
My new map =
|
||||
@ -571,6 +573,7 @@ Spawn river from/to =
|
||||
Bottom left river =
|
||||
Bottom right river =
|
||||
Bottom river =
|
||||
Player =
|
||||
|
||||
# Multiplayer
|
||||
|
||||
|
@ -29,18 +29,6 @@ import kotlin.math.abs
|
||||
* @param initialCapacity Passed to constructor of [tileList]
|
||||
*/
|
||||
class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
||||
companion object {
|
||||
/** Legacy way to store starting locations - now this is used only in [translateStartingLocationsFromMap] */
|
||||
const val startingLocationPrefix = "StartingLocation "
|
||||
|
||||
/**
|
||||
* To be backwards compatible, a json without a startingLocations element will be recognized by an entry with this marker
|
||||
* New saved maps will never have this marker and will always have a serialized startingLocations list even if empty.
|
||||
* New saved maps will also never have "StartingLocation" improvements, these are converted on load in [setTransients].
|
||||
*/
|
||||
private const val legacyMarker = " Legacy "
|
||||
}
|
||||
|
||||
//region Fields, Serialized
|
||||
|
||||
var mapParameters = MapParameters()
|
||||
@ -51,8 +39,29 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
||||
* @param position [Vector2] of the location
|
||||
* @param nation Name of the nation
|
||||
*/
|
||||
private data class StartingLocation(val position: Vector2 = Vector2.Zero, val nation: String = "") : IsPartOfGameInfoSerialization
|
||||
private val startingLocations = arrayListOf(StartingLocation(Vector2.Zero, legacyMarker))
|
||||
data class StartingLocation(
|
||||
val position: Vector2 = Vector2.Zero,
|
||||
val nation: String = "",
|
||||
val usage: Usage = Usage.default // default for maps saved pior to this feature
|
||||
) : IsPartOfGameInfoSerialization {
|
||||
/** How a starting location may be used when the map is loaded for a new game */
|
||||
enum class Usage(val label: String) {
|
||||
/** Starting location only */
|
||||
Normal("None"),
|
||||
/** Use for "Select players from starting locations" */
|
||||
Player("Player"),
|
||||
/** Use as first Human player */
|
||||
Human("Human")
|
||||
;
|
||||
companion object {
|
||||
val default get() = Player
|
||||
}
|
||||
}
|
||||
}
|
||||
val startingLocations = arrayListOf<StartingLocation>()
|
||||
|
||||
/** Optional freeform text a mod map creator can set for their "customers" */
|
||||
var description = ""
|
||||
|
||||
//endregion
|
||||
//region Fields, Transient
|
||||
@ -179,6 +188,8 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
||||
toReturn.startingLocations.clear()
|
||||
toReturn.startingLocations.ensureCapacity(startingLocations.size)
|
||||
toReturn.startingLocations.addAll(startingLocations)
|
||||
|
||||
toReturn.description = description
|
||||
toReturn.tileUniqueMapCache = tileUniqueMapCache
|
||||
|
||||
return toReturn
|
||||
@ -635,45 +646,33 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize startingLocations transients, including legacy support (maps saved with placeholder improvements)
|
||||
* Initialize startingLocations transients
|
||||
*/
|
||||
fun setStartingLocationsTransients() {
|
||||
if (startingLocations.size == 1 && startingLocations[0].nation == legacyMarker)
|
||||
return translateStartingLocationsFromMap()
|
||||
startingLocationsByNation.clear()
|
||||
for ((position, nationName) in startingLocations) {
|
||||
startingLocationsByNation.addToMapOfSets(nationName, get(position))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan and remove placeholder improvements from map and build startingLocations from them
|
||||
*/
|
||||
private fun translateStartingLocationsFromMap() {
|
||||
startingLocations.clear()
|
||||
tileList.asSequence()
|
||||
.filter { it.improvement?.startsWith(startingLocationPrefix) == true }
|
||||
.map { it to StartingLocation(it.position, it.improvement!!.removePrefix(startingLocationPrefix)) }
|
||||
.sortedBy { it.second.nation } // vanity, or to make diffs between un-gzipped map files easier
|
||||
.forEach { (tile, startingLocation) ->
|
||||
tile.removeImprovement()
|
||||
startingLocations.add(startingLocation)
|
||||
}
|
||||
setStartingLocationsTransients()
|
||||
}
|
||||
|
||||
/** Adds a starting position, maintaining the transients
|
||||
*
|
||||
* Note: Will not replace an existing StartingLocation to update its [usage]
|
||||
* @return true if the starting position was not already stored as per [Collection]'s add */
|
||||
fun addStartingLocation(nationName: String, tile: Tile): Boolean {
|
||||
fun addStartingLocation(
|
||||
nationName: String,
|
||||
tile: Tile,
|
||||
usage: StartingLocation.Usage = StartingLocation.Usage.Player
|
||||
): Boolean {
|
||||
if (startingLocationsByNation.contains(nationName, tile)) return false
|
||||
startingLocations.add(StartingLocation(tile.position, nationName))
|
||||
startingLocations.add(StartingLocation(tile.position, nationName, usage))
|
||||
return startingLocationsByNation.addToMapOfSets(nationName, tile)
|
||||
}
|
||||
|
||||
/** Removes a starting position, maintaining the transients
|
||||
* @return true if the starting position was removed as per [Collection]'s remove */
|
||||
fun removeStartingLocation(nationName: String, tile: Tile): Boolean {
|
||||
if (startingLocationsByNation.contains(nationName, tile)) return false
|
||||
if (!startingLocationsByNation.contains(nationName, tile)) return false
|
||||
startingLocations.remove(StartingLocation(tile.position, nationName))
|
||||
return startingLocationsByNation[nationName]!!.remove(tile)
|
||||
// we do not clean up an empty startingLocationsByNation[nationName] set - not worth it
|
||||
@ -755,6 +754,13 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
||||
class Preview {
|
||||
val mapParameters = MapParameters()
|
||||
private val startingLocations = arrayListOf<StartingLocation>()
|
||||
fun getDeclaredNations() = startingLocations.asSequence().map { it.nation }.distinct()
|
||||
fun getDeclaredNations() = startingLocations.asSequence()
|
||||
.filter { it.usage != StartingLocation.Usage.Normal }
|
||||
.map { it.nation }
|
||||
.distinct()
|
||||
fun getNationsForHumanPlayer() = startingLocations.asSequence()
|
||||
.filter { it.usage == StartingLocation.Usage.Human }
|
||||
.map { it.nation }
|
||||
.distinct()
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,11 @@ import com.unciv.models.metadata.BaseRuleset
|
||||
import com.unciv.models.metadata.GameSetupInfo
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.input.KeyCharAndCode
|
||||
import com.unciv.ui.components.input.KeyShortcutDispatcherVeto
|
||||
import com.unciv.ui.components.input.KeyboardPanningListener
|
||||
import com.unciv.ui.components.input.onChange
|
||||
import com.unciv.ui.components.tilegroups.TileGroup
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.images.ImageWithCustomSize
|
||||
@ -83,6 +85,7 @@ class MapEditorScreen(map: TileMap? = null) : BaseScreen(), RecreateOnResize {
|
||||
val tabs: MapEditorMainTabs
|
||||
var tileClickHandler: ((tile: Tile)->Unit)? = null
|
||||
private var zoomController: ZoomButtonPair? = null
|
||||
val descriptionTextField = UncivTextField.create("Enter a description for the users of this map")
|
||||
|
||||
private val highlightedTileGroups = mutableListOf<TileGroup>()
|
||||
|
||||
@ -98,10 +101,12 @@ class MapEditorScreen(map: TileMap? = null) : BaseScreen(), RecreateOnResize {
|
||||
} else {
|
||||
ruleset = map.ruleset ?: RulesetCache.getComplexRuleset(map.mapParameters)
|
||||
tileMap = map
|
||||
descriptionTextField.text = map.description
|
||||
}
|
||||
|
||||
mapHolder = newMapHolder() // will set up ImageGetter and translations, and all dirty flags
|
||||
isDirty = false
|
||||
descriptionTextField.onChange { isDirty = true }
|
||||
|
||||
tabs = MapEditorMainTabs(this)
|
||||
MapEditorToolsDrawer(tabs, stage, mapHolder)
|
||||
@ -212,6 +217,7 @@ class MapEditorScreen(map: TileMap? = null) : BaseScreen(), RecreateOnResize {
|
||||
clearOverlayImages()
|
||||
mapHolder.remove()
|
||||
tileMap = map
|
||||
descriptionTextField.text = map.description
|
||||
ruleset = newRuleset ?: RulesetCache.getComplexRuleset(map.mapParameters)
|
||||
mapHolder = newMapHolder()
|
||||
isDirty = false
|
||||
|
@ -2,9 +2,12 @@ package com.unciv.ui.screens.mapeditorscreen.tabs
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.logic.map.tile.RoadStatus
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
@ -269,6 +272,7 @@ class MapEditorEditStartsTab(
|
||||
private val ruleset: Ruleset
|
||||
): Table(BaseScreen.skin), IMapEditorEditSubTabs {
|
||||
private val collator = UncivGame.Current.settings.getCollatorFromLocale()
|
||||
private val usageOptionGroup = ButtonGroup<CheckBox>()
|
||||
|
||||
init {
|
||||
top()
|
||||
@ -287,6 +291,8 @@ class MapEditorEditStartsTab(
|
||||
}
|
||||
} }).padBottom(0f).row()
|
||||
|
||||
addUsage()
|
||||
|
||||
// Create the nation list with the spectator nation included, and shown/interpreted as "Any Civ" starting location.
|
||||
// We use Nation/Spectator because it hasn't been used yet and we need an icon within the Nation.
|
||||
add(
|
||||
@ -297,10 +303,13 @@ class MapEditorEditStartsTab(
|
||||
UncivGame.Current.musicController.chooseTrack(it, MusicMood.Theme, MusicTrackChooserFlags.setSpecific)
|
||||
val icon = "Nation/$it"
|
||||
val pediaLink = if (it == Constants.spectator) "" else icon
|
||||
val isMajorCiv = ruleset.nations[it]?.isMajorCiv ?: false
|
||||
val selectedUsage = if (isMajorCiv) TileMap.StartingLocation.Usage.values()[usageOptionGroup.checkedIndex]
|
||||
else TileMap.StartingLocation.Usage.Normal
|
||||
editTab.setBrush(BrushHandlerType.Direct, it.spectatorToAnyCiv(), icon, pediaLink) { tile ->
|
||||
// toggle the starting location here, note this allows
|
||||
// both multiple locations per nation and multiple nations per tile
|
||||
if (!tile.tileMap.addStartingLocation(it, tile))
|
||||
if (!tile.tileMap.addStartingLocation(it, tile, selectedUsage))
|
||||
tile.tileMap.removeStartingLocation(it, tile)
|
||||
}
|
||||
}
|
||||
@ -318,6 +327,20 @@ class MapEditorEditStartsTab(
|
||||
FormattedLine("[${it.name.spectatorToAnyCiv()}] starting location", link = it.name, icon = "Nation/${it.name}", size = 24)
|
||||
}.asIterable()
|
||||
|
||||
private fun addUsage() {
|
||||
val table = Table()
|
||||
table.defaults().pad(5f)
|
||||
table.add("Use for new game \"Select players\" button:".toLabel()).colspan(3).row()
|
||||
val defaultUsage = TileMap.StartingLocation.Usage.default
|
||||
for (usage in TileMap.StartingLocation.Usage.values()) {
|
||||
val checkBox = CheckBox(usage.label.tr(), skin)
|
||||
table.add(checkBox)
|
||||
usageOptionGroup.add(checkBox)
|
||||
checkBox.isChecked = usage == defaultUsage
|
||||
}
|
||||
add(table).row()
|
||||
}
|
||||
|
||||
override fun isDisabled() = allowedNations().none()
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,6 @@ import com.unciv.logic.files.MapSaver
|
||||
import com.unciv.logic.map.MapGeneratedMainType
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.widgets.AutoScrollPane
|
||||
import com.unciv.ui.components.widgets.TabbedPager
|
||||
import com.unciv.ui.components.UncivTextField
|
||||
import com.unciv.ui.components.extensions.isEnabled
|
||||
import com.unciv.ui.components.extensions.toTextButton
|
||||
@ -19,6 +17,8 @@ import com.unciv.ui.components.input.keyShortcuts
|
||||
import com.unciv.ui.components.input.onActivation
|
||||
import com.unciv.ui.components.input.onChange
|
||||
import com.unciv.ui.components.input.onClick
|
||||
import com.unciv.ui.components.widgets.AutoScrollPane
|
||||
import com.unciv.ui.components.widgets.TabbedPager
|
||||
import com.unciv.ui.popups.ConfirmPopup
|
||||
import com.unciv.ui.popups.Popup
|
||||
import com.unciv.ui.popups.ToastPopup
|
||||
@ -89,6 +89,7 @@ class MapEditorSaveTab(
|
||||
if (mapNameTextField.text.isBlank()) return
|
||||
editorScreen.tileMap.mapParameters.name = mapNameTextField.text
|
||||
editorScreen.tileMap.mapParameters.type = MapGeneratedMainType.custom
|
||||
editorScreen.tileMap.description = editorScreen.descriptionTextField.text
|
||||
setSaveButton(false)
|
||||
editorScreen.startBackgroundJob("MapSaver", false) { saverThread() }
|
||||
}
|
||||
|
@ -101,6 +101,8 @@ class MapEditorViewTab(
|
||||
val statsLabel = WrappableLabel(statsText, labelWidth)
|
||||
add(statsLabel.apply { wrap = true }).row()
|
||||
|
||||
add(editorScreen.descriptionTextField).growX().row()
|
||||
|
||||
// Map editor must not touch tileMap.naturalWonders as it is a by lazy immutable list,
|
||||
// and we wouldn't be able to fix it when the natural wonders change
|
||||
if (editorScreen.naturalWondersNeedRefresh) {
|
||||
@ -191,8 +193,7 @@ class MapEditorViewTab(
|
||||
lines += FormattedLine(stats.toString())
|
||||
}
|
||||
|
||||
val nations = tile.tileMap.getTileStartingLocations(tile)
|
||||
.joinToString { it.name.tr() }
|
||||
val nations = tile.tileMap.getTileStartingLocationSummary(tile)
|
||||
if (nations.isNotEmpty()) {
|
||||
lines += FormattedLine()
|
||||
lines += FormattedLine("Starting location(s): [$nations]")
|
||||
@ -257,11 +258,12 @@ class MapEditorViewTab(
|
||||
tileClickHandler(tile)
|
||||
}
|
||||
|
||||
private fun TileMap.getTileStartingLocations(tile: Tile?) =
|
||||
startingLocationsByNation.asSequence()
|
||||
.filter { tile == null || tile in it.value }
|
||||
.mapNotNull { ruleset!!.nations[it.key] }
|
||||
.sortedWith(compareBy<Nation>{ it.isCityState }.thenBy(collator) { it.name.tr(hideIcons = true) })
|
||||
private fun TileMap.getTileStartingLocationSummary(tile: Tile) =
|
||||
startingLocations.asSequence()
|
||||
.filter { it.position == tile.position }
|
||||
.mapNotNull { if (it.nation in ruleset!!.nations) ruleset!!.nations[it.nation]!! to it.usage else null }
|
||||
.sortedWith(compareBy<Pair<Nation,TileMap.StartingLocation.Usage>>{ it.first.isCityState }.thenBy(collator) { it.first.name.tr(hideIcons = true) })
|
||||
.joinToString { "{${it.first.name}} ({${it.second.label}})".tr() }
|
||||
|
||||
private fun TileMap.getStartingLocationSummary() =
|
||||
startingLocationsByNation.asSequence()
|
||||
|
@ -7,6 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.Group
|
||||
import com.badlogic.gdx.scenes.scene2d.actions.Actions
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Cell
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Container
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
@ -39,6 +40,12 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.isActive
|
||||
|
||||
private inline fun <T> SelectBox<T>.withoutChangeEvents(block: SelectBox<T>.() -> Unit) {
|
||||
selection.setProgrammaticChangeEvents(false)
|
||||
block()
|
||||
selection.setProgrammaticChangeEvents(true)
|
||||
}
|
||||
|
||||
class MapFileSelectTable(
|
||||
private val newGameScreen: NewGameScreen,
|
||||
private val mapParameters: MapParameters
|
||||
@ -49,9 +56,12 @@ class MapFileSelectTable(
|
||||
private val useNationsFromMapButton = "Select players from starting locations".toTextButton(AnimatedMenuPopup.SmallButtonStyle())
|
||||
private val useNationsButtonCell: Cell<Actor?>
|
||||
private var mapNations = emptyList<Nation>()
|
||||
private var mapHumanPick: String? = null
|
||||
private val miniMapWrapper = Container<Group?>()
|
||||
private var mapPreviewJob: Job? = null
|
||||
private var preselectedName = mapParameters.name
|
||||
private val descriptionLabel = "".toLabel()
|
||||
private val descriptionLabelCell: Cell<Label>
|
||||
|
||||
// The SelectBox auto displays the text a object.toString(), which on the FileHandle itself includes the folder path.
|
||||
// So we wrap it in another object with a custom toString()
|
||||
@ -85,6 +95,9 @@ class MapFileSelectTable(
|
||||
useNationsButtonCell = add().pad(0f)
|
||||
row()
|
||||
|
||||
descriptionLabelCell = add(descriptionLabel)
|
||||
descriptionLabelCell.height(0f).row()
|
||||
|
||||
add(miniMapWrapper)
|
||||
.pad(15f)
|
||||
.maxWidth(columnWidth - 20f)
|
||||
@ -126,7 +139,7 @@ class MapFileSelectTable(
|
||||
loadingIcon.hide {
|
||||
loadingIcon.remove()
|
||||
}
|
||||
onCategorySelectBoxChange() // re-sort lower SelectBox
|
||||
onCategorySelectBoxChange() // re-sort lower SelectBox, and trigger map selection (mod select, description and preview)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,19 +158,19 @@ class MapFileSelectTable(
|
||||
compareBy<String?> { it != sortToTop }
|
||||
.thenBy(collator) { it }
|
||||
).toGdxArray()
|
||||
mapCategorySelectBox.selection.setProgrammaticChangeEvents(false)
|
||||
mapCategorySelectBox.items = newItems
|
||||
mapCategorySelectBox.selected = select
|
||||
mapCategorySelectBox.selection.setProgrammaticChangeEvents(true)
|
||||
mapCategorySelectBox.withoutChangeEvents {
|
||||
items = newItems
|
||||
selected = select
|
||||
}
|
||||
}
|
||||
|
||||
if (mapCategorySelectBox.selected != categoryName) return
|
||||
|
||||
// .. but add the maps themselves as they come
|
||||
mapFileSelectBox.selection.setProgrammaticChangeEvents(false)
|
||||
mapFileSelectBox.items.add(mapWrapper)
|
||||
mapFileSelectBox.items = mapFileSelectBox.items // Call setItems so SelectBox sees the change
|
||||
mapFileSelectBox.selection.setProgrammaticChangeEvents(true)
|
||||
mapFileSelectBox.withoutChangeEvents {
|
||||
items.add(mapWrapper)
|
||||
setItems(items) // Call setItems so SelectBox sees the change
|
||||
}
|
||||
}
|
||||
|
||||
private val firstMap: FileHandle? by lazy {
|
||||
@ -205,12 +218,17 @@ class MapFileSelectTable(
|
||||
|
||||
// avoid the overhead of doing a full updateRuleset + updateTables + startMapPreview
|
||||
// (all expensive) for something that will be overthrown momentarily
|
||||
mapFileSelectBox.selection.setProgrammaticChangeEvents(false)
|
||||
mapFileSelectBox.items = mapFiles
|
||||
// Now, we want this ON because the event removes map selections which are pulling mods
|
||||
// that trip updateRuleset - so that code should still be active for the pre-selection
|
||||
mapFileSelectBox.selection.setProgrammaticChangeEvents(true)
|
||||
mapFileSelectBox.selected = selectedItem
|
||||
mapFileSelectBox.withoutChangeEvents {
|
||||
items = mapFiles
|
||||
selected = selectedItem
|
||||
}
|
||||
|
||||
// Now, we want this to *always* run even when setting mapFileSelectBox.selected would
|
||||
// not have fired the event (which it won't if the selection is already as asked).
|
||||
// Reasons:
|
||||
// * Mods that trip validation in updateRuleset
|
||||
// * Update description and minimap preview
|
||||
onFileSelectBoxChange()
|
||||
// In the event described above, we now have: mapFileSelectBox.selected != selectedItem
|
||||
// Do NOT try to put back the "bad" preselection!
|
||||
}
|
||||
@ -227,12 +245,18 @@ class MapFileSelectTable(
|
||||
?: selection.mapPreview.mapParameters.baseRuleset
|
||||
val success = newGameScreen.tryUpdateRuleset(updateUI = true)
|
||||
|
||||
mapNations = if (success)
|
||||
selection.mapPreview.getDeclaredNations()
|
||||
if (success) {
|
||||
mapNations = selection.mapPreview.getDeclaredNations()
|
||||
.mapNotNull { newGameScreen.ruleset.nations[it] }
|
||||
.filter { it.isMajorCiv }
|
||||
.toList()
|
||||
else emptyList()
|
||||
mapHumanPick = selection.mapPreview.getNationsForHumanPlayer()
|
||||
.filter { newGameScreen.ruleset.nations[it]?.isMajorCiv == true }
|
||||
.toList().randomOrNull()
|
||||
} else {
|
||||
mapNations = emptyList()
|
||||
mapHumanPick = null
|
||||
}
|
||||
|
||||
if (mapNations.isEmpty()) {
|
||||
useNationsButtonCell.setActor(null)
|
||||
@ -272,8 +296,10 @@ class MapFileSelectTable(
|
||||
// ReplayMap still paints outside its bounds - so we subtract padding and a little extra
|
||||
val size = (columnWidth - 40f).coerceAtMost(500f)
|
||||
val miniMap = LoadMapPreview(map, size, size)
|
||||
val description = map.description
|
||||
if (!isActive) return@run
|
||||
Concurrency.runOnGLThread {
|
||||
showDescription(description)
|
||||
showMinimap(miniMap)
|
||||
}
|
||||
} catch (_: Throwable) {}
|
||||
@ -299,6 +325,13 @@ class MapFileSelectTable(
|
||||
miniMapWrapper.addAction(Actions.fadeIn(0.2f))
|
||||
}
|
||||
|
||||
private fun showDescription(text: String) {
|
||||
descriptionLabel.setText(text)
|
||||
descriptionLabelCell
|
||||
.height(if (text.isEmpty()) 0f else descriptionLabel.prefHeight)
|
||||
.padTop(if (text.isEmpty()) 0f else 10f)
|
||||
}
|
||||
|
||||
private fun hideMiniMap() {
|
||||
if (miniMapWrapper.actor !is LoadMapPreview) return
|
||||
miniMapWrapper.clearActions()
|
||||
@ -321,13 +354,12 @@ class MapFileSelectTable(
|
||||
useNationsFromMapButton.disable()
|
||||
val players = newGameScreen.playerPickerTable.gameParameters.players
|
||||
players.clear()
|
||||
val pickForHuman = mapNations.random().name
|
||||
mapNations.asSequence()
|
||||
.map { it.name to it.name.tr(hideIcons = true) } // Sort by translation but keep untranslated name
|
||||
.sortedWith(
|
||||
compareBy<Pair<String, String>>{ it.first != pickForHuman }
|
||||
compareBy<Pair<String, String>>{ it.first != mapHumanPick }
|
||||
.thenBy(collator) { it.second }
|
||||
).map { Player(it.first, if (it.first == pickForHuman) PlayerType.Human else PlayerType.AI) }
|
||||
).map { Player(it.first, if (it.first == mapHumanPick) PlayerType.Human else PlayerType.AI) }
|
||||
.toCollection(players)
|
||||
newGameScreen.playerPickerTable.update()
|
||||
}
|
||||
|
Reference in New Issue
Block a user