Common interface for Unique-collections in ruleset objects (#4788)

This commit is contained in:
SomeTroglodyte
2021-08-08 17:21:04 +02:00
committed by GitHub
parent 92d3fa65e3
commit b6ee4c0b1c
14 changed files with 81 additions and 49 deletions

View File

@ -1,6 +1,7 @@
package com.unciv.logic.city package com.unciv.logic.city
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.IHasUniques
import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
import com.unciv.models.stats.Stat import com.unciv.models.stats.Stat
@ -15,10 +16,8 @@ interface IConstruction : INamed {
fun getResourceRequirements(): HashMap<String,Int> fun getResourceRequirements(): HashMap<String,Int>
} }
interface INonPerpetualConstruction : IConstruction, INamed { interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
val hurryCostModifier: Int val hurryCostModifier: Int
val uniqueObjects: List<Unique>
val uniques: List<String>
fun getProductionCost(civInfo: CivilizationInfo): Int fun getProductionCost(civInfo: CivilizationInfo): Int
fun getStatBuyCost(cityInfo: CityInfo, stat: Stat): Int? fun getStatBuyCost(cityInfo: CityInfo, stat: Stat): Int?

View File

@ -6,11 +6,11 @@ import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText import com.unciv.ui.civilopedia.ICivilopediaText
import java.util.ArrayList import java.util.ArrayList
class Belief : INamed, ICivilopediaText { class Belief : INamed, ICivilopediaText, IHasUniques {
override var name: String = "" override var name: String = ""
var type: BeliefType = BeliefType.None var type: BeliefType = BeliefType.None
var uniques = ArrayList<String>() override var uniques = ArrayList<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } } override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
override var civilopediaText = listOf<FormattedLine>() override var civilopediaText = listOf<FormattedLine>()

View File

@ -69,11 +69,12 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText {
@Deprecated("As of 3.15.16 - replaced with 'Provides a free [buildingName] [cityFilter]'") @Deprecated("As of 3.15.16 - replaced with 'Provides a free [buildingName] [cityFilter]'")
var providesFreeBuilding: String? = null var providesFreeBuilding: String? = null
override var uniques = ArrayList<String>() override var uniques = ArrayList<String>()
var replacementTextForUniques = ""
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } } override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var replacementTextForUniques = ""
override var civilopediaText = listOf<FormattedLine>() override var civilopediaText = listOf<FormattedLine>()
fun getShortDescription(ruleset: Ruleset): String { // should fit in one line fun getShortDescription(ruleset: Ruleset): String { // should fit in one line
val infoList = mutableListOf<String>() val infoList = mutableListOf<String>()
val str = getStats(null).toString() val str = getStats(null).toString()

View File

@ -0,0 +1,9 @@
package com.unciv.models.ruleset
/**
* Common interface for all 'ruleset objects' that have Uniques, like BaseUnit, Nation, etc.
*/
interface IHasUniques {
var uniques: ArrayList<String> // Can not be a hashset as that would remove doubles
val uniqueObjects: List<Unique>
}

View File

@ -3,12 +3,9 @@
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.unciv.Constants import com.unciv.Constants
import com.unciv.logic.civilization.CityStateType import com.unciv.logic.civilization.CityStateType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
import com.unciv.models.translations.Translations
import com.unciv.models.translations.squareBraceRegex import com.unciv.models.translations.squareBraceRegex
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaText
import com.unciv.ui.civilopedia.FormattedLine import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText import com.unciv.ui.civilopedia.ICivilopediaText
import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.Fonts
@ -22,7 +19,7 @@ enum class VictoryType {
Scientific, Scientific,
} }
class Nation : INamed, ICivilopediaText { class Nation : INamed, ICivilopediaText, IHasUniques {
override lateinit var name: String override lateinit var name: String
var leaderName = "" var leaderName = ""
@ -43,8 +40,8 @@ class Nation : INamed, ICivilopediaText {
lateinit var outerColor: List<Int> lateinit var outerColor: List<Int>
var uniqueName = "" var uniqueName = ""
var uniques = HashSet<String>() override var uniques = ArrayList<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } } override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var uniqueText = "" var uniqueText = ""
var innerColor: List<Int>? = null var innerColor: List<Int>? = null
var startBias = ArrayList<String>() var startBias = ArrayList<String>()

View File

@ -2,12 +2,12 @@ package com.unciv.models.ruleset
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
open class Policy : INamed { open class Policy : INamed, IHasUniques {
lateinit var branch: PolicyBranch // not in json - added in gameBasics lateinit var branch: PolicyBranch // not in json - added in gameBasics
override lateinit var name: String override lateinit var name: String
var uniques: ArrayList<String> = ArrayList() override var uniques: ArrayList<String> = ArrayList()
val uniqueObjects:List<Unique> by lazy { uniques.map { Unique(it) } } override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var row: Int = 0 var row: Int = 0
var column: Int = 0 var column: Int = 0
var requires: ArrayList<String>? = null var requires: ArrayList<String>? = null

View File

@ -41,7 +41,7 @@ class ModOptions {
var modSize = 0 var modSize = 0
val maxXPfromBarbarians = 30 val maxXPfromBarbarians = 30
var uniques = HashSet<String>() var uniques = HashSet<String>() // No reason for now to use IHasUniques here, in that case needs to change to ArrayList
} }
class Ruleset { class Ruleset {

View File

@ -3,6 +3,7 @@ package com.unciv.models.ruleset.tech
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.IHasUniques
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.Unique
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
@ -13,14 +14,14 @@ import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.Fonts
import java.util.* import java.util.*
class Technology: INamed, ICivilopediaText { class Technology: INamed, ICivilopediaText, IHasUniques {
override lateinit var name: String override lateinit var name: String
var cost: Int = 0 var cost: Int = 0
var prerequisites = HashSet<String>() var prerequisites = HashSet<String>()
var uniques = ArrayList<String>() override var uniques = ArrayList<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } } override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var column: TechColumn? = null // The column that this tech is in the tech tree var column: TechColumn? = null // The column that this tech is in the tech tree
var row: Int = 0 var row: Int = 0

View File

@ -3,6 +3,7 @@ package com.unciv.models.ruleset.tile
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Belief import com.unciv.models.ruleset.Belief
import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.RoadStatus
import com.unciv.models.ruleset.IHasUniques
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.NamedStats import com.unciv.models.stats.NamedStats
@ -12,13 +13,13 @@ import com.unciv.ui.civilopedia.ICivilopediaText
import java.util.* import java.util.*
import kotlin.math.roundToInt import kotlin.math.roundToInt
class TileImprovement : NamedStats(), ICivilopediaText { class TileImprovement : NamedStats(), ICivilopediaText, IHasUniques {
var terrainsCanBeBuiltOn: Collection<String> = ArrayList() var terrainsCanBeBuiltOn: Collection<String> = ArrayList()
var techRequired: String? = null var techRequired: String? = null
var uniqueTo:String? = null var uniqueTo:String? = null
var uniques = ArrayList<String>() override var uniques = ArrayList<String>()
val uniqueObjects:List<Unique> by lazy { uniques.map { Unique(it) } } override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
val shortcutKey: Char? = null val shortcutKey: Char? = null
val turnsToBuild: Int = 0 // This is the base cost. val turnsToBuild: Int = 0 // This is the base cost.

View File

@ -12,20 +12,19 @@ import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
import com.unciv.models.stats.Stat import com.unciv.models.stats.Stat
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaText
import com.unciv.ui.civilopedia.FormattedLine import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText
import com.unciv.ui.utils.Fonts import com.unciv.ui.utils.Fonts
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.collections.HashSet import kotlin.collections.HashSet
import kotlin.math.pow
// This is BaseUnit because Unit is already a base Kotlin class and to avoid mixing the two up // This is BaseUnit because Unit is already a base Kotlin class and to avoid mixing the two up
/** This is the basic info of the units, as specified in Units.json, /** This is the basic info of the units, as specified in Units.json,
in contrast to MapUnit, which is a specific unit of a certain type that appears on the map */ in contrast to MapUnit, which is a specific unit of a certain type that appears on the map */
class BaseUnit : INamed, INonPerpetualConstruction, CivilopediaText() { class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
override lateinit var name: String override lateinit var name: String
var cost: Int = 0 var cost: Int = 0

View File

@ -1,5 +1,6 @@
package com.unciv.models.ruleset.unit package com.unciv.models.ruleset.unit
import com.unciv.models.ruleset.IHasUniques
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
@ -8,18 +9,18 @@ import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText import com.unciv.ui.civilopedia.ICivilopediaText
class Promotion : INamed, ICivilopediaText { class Promotion : INamed, ICivilopediaText, IHasUniques {
override lateinit var name: String override lateinit var name: String
var prerequisites = listOf<String>() var prerequisites = listOf<String>()
var effect = "" var effect = ""
var unitTypes = listOf<String>() // The json parser wouldn't agree to deserialize this as a list of UnitTypes. =( var unitTypes = listOf<String>() // The json parser wouldn't agree to deserialize this as a list of UnitTypes. =(
var uniques = ArrayList<String>() override var uniques = ArrayList<String>()
fun uniquesWithEffect() = sequence { fun uniquesWithEffect() = sequence {
if (effect.isNotEmpty()) yield(effect) if (effect.isNotEmpty()) yield(effect)
yieldAll(uniques) yieldAll(uniques)
} }
val uniqueObjects: List<Unique> by lazy { uniquesWithEffect().map { Unique(it) }.toList() } override val uniqueObjects: List<Unique> by lazy { uniquesWithEffect().map { Unique(it) }.toList() }
override var civilopediaText = listOf<FormattedLine>() override var civilopediaText = listOf<FormattedLine>()

View File

@ -31,7 +31,7 @@ class CivilopediaScreen(
* @param name From [Ruleset] object [INamed.name] * @param name From [Ruleset] object [INamed.name]
* @param description Multiline text * @param description Multiline text
* @param image Icon for button * @param image Icon for button
* @param flavour [CivilopediaText] * @param flavour [ICivilopediaText]
* @param y Y coordinate for scrolling to * @param y Y coordinate for scrolling to
* @param height Cell height * @param height Cell height
*/ */
@ -269,12 +269,10 @@ class CivilopediaScreen(
categoryToEntries[CivilopediaCategories.Tutorial] = tutorialController.getCivilopediaTutorials() categoryToEntries[CivilopediaCategories.Tutorial] = tutorialController.getCivilopediaTutorials()
.map { .map {
CivilopediaEntry( CivilopediaEntry(
it.key.replace("_", " "), it.name,
"", "",
// CivilopediaCategories.Tutorial.getImage?.invoke(it.name, imageSize) // CivilopediaCategories.Tutorial.getImage?.invoke(it.name, imageSize)
flavour = SimpleCivilopediaText( flavour = it
sequenceOf(FormattedLine(extraImage = it.key)),
it.value.asSequence(), true)
) )
} }

View File

@ -385,22 +385,23 @@ object MarkupRenderer {
} }
/** Storage class for interface [ICivilopediaText] for use as base class */ /** Storage class for interface [ICivilopediaText] for use as base class */
@Deprecated("As of 3.16.1, use ICivilopediaText directly please")
abstract class CivilopediaText : ICivilopediaText { abstract class CivilopediaText : ICivilopediaText {
override var civilopediaText = listOf<FormattedLine>() override var civilopediaText = listOf<FormattedLine>()
} }
/** Storage class for instantiation of the simplest form containing only the lines collection */ /** Storage class for instantiation of the simplest form containing only the lines collection */
class SimpleCivilopediaText(lines: List<FormattedLine>, val isComplete: Boolean = false) : CivilopediaText() { open class SimpleCivilopediaText(
init { override var civilopediaText: List<FormattedLine>,
civilopediaText = lines val isComplete: Boolean = false
} ) : ICivilopediaText {
override fun hasCivilopediaTextLines() = true
override fun replacesCivilopediaDescription() = isComplete
override fun makeLink() = ""
constructor(strings: Sequence<String>, isComplete: Boolean = false) : this( constructor(strings: Sequence<String>, isComplete: Boolean = false) : this(
strings.map { FormattedLine(it) }.toList(), isComplete) strings.map { FormattedLine(it) }.toList(), isComplete)
constructor(first: Sequence<FormattedLine>, strings: Sequence<String>, isComplete: Boolean = false) : this( constructor(first: Sequence<FormattedLine>, strings: Sequence<String>, isComplete: Boolean = false) : this(
(first + strings.map { FormattedLine(it) }).toList(), isComplete) (first + strings.map { FormattedLine(it) }).toList(), isComplete)
override fun hasCivilopediaTextLines() = true
override fun replacesCivilopediaDescription() = isComplete
override fun makeLink() = ""
} }
/** Addon common to most ruleset game objects managing civilopedia display /** Addon common to most ruleset game objects managing civilopedia display
@ -456,7 +457,7 @@ interface ICivilopediaText {
* @param ruleset The current ruleset for the Civilopedia viewer * @param ruleset The current ruleset for the Civilopedia viewer
* @return A new CivilopediaText instance containing original [civilopediaText] lines merged with those from [getCivilopediaTextHeader] and [getCivilopediaTextLines] calls. * @return A new CivilopediaText instance containing original [civilopediaText] lines merged with those from [getCivilopediaTextHeader] and [getCivilopediaTextLines] calls.
*/ */
fun assembleCivilopediaText(ruleset: Ruleset): CivilopediaText { fun assembleCivilopediaText(ruleset: Ruleset): ICivilopediaText {
val outerLines = civilopediaText.iterator() val outerLines = civilopediaText.iterator()
val newLines = sequence { val newLines = sequence {
var middleDone = false var middleDone = false

View File

@ -4,6 +4,9 @@ import com.badlogic.gdx.utils.Array
import com.unciv.JsonParser import com.unciv.JsonParser
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.models.Tutorial import com.unciv.models.Tutorial
import com.unciv.models.stats.INamed
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.SimpleCivilopediaText
import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.CameraStageBaseScreen
class TutorialController(screen: CameraStageBaseScreen) { class TutorialController(screen: CameraStageBaseScreen) {
@ -45,11 +48,33 @@ class TutorialController(screen: CameraStageBaseScreen) {
} }
} }
fun getCivilopediaTutorials(): Map<String, Array<String>> {
return tutorials.filter { Tutorial.findByName(it.key)!!.isCivilopedia }
}
private fun getTutorial(tutorial: Tutorial): Array<String> { private fun getTutorial(tutorial: Tutorial): Array<String> {
return tutorials[tutorial.value] ?: Array() return tutorials[tutorial.value] ?: Array()
} }
/** Wrapper for a Tutorial, supports INamed and ICivilopediaText,
* and already provisions for the display of an ExtraImage on top.
* @param rawName from Tutorial.value, with underscores (this wrapper replaces them with spaces)
* @param lines Array of lines exactly as stored in a TutorialController.tutorials MapEntry
*/
class CivilopediaTutorial(
rawName: String,
lines: Array<String>
) : INamed, SimpleCivilopediaText(
sequenceOf(FormattedLine(extraImage = rawName)),
lines.asSequence(),
true
) {
override var name = rawName.replace("_", " ")
}
/** Get all Tutorials intended to be displayed in the Civilopedia
* as a List of wrappers supporting INamed and ICivilopediaText
*/
fun getCivilopediaTutorials() =
tutorials.filter {
Tutorial.findByName(it.key)!!.isCivilopedia
}.map {
CivilopediaTutorial(it.key, it.value)
}
} }