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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 81 additions and 49 deletions

View File

@ -1,6 +1,7 @@
package com.unciv.logic.city
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.IHasUniques
import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.INamed
import com.unciv.models.stats.Stat
@ -15,10 +16,8 @@ interface IConstruction : INamed {
fun getResourceRequirements(): HashMap<String,Int>
}
interface INonPerpetualConstruction : IConstruction, INamed {
interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
val hurryCostModifier: Int
val uniqueObjects: List<Unique>
val uniques: List<String>
fun getProductionCost(civInfo: CivilizationInfo): 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 java.util.ArrayList
class Belief : INamed, ICivilopediaText {
class Belief : INamed, ICivilopediaText, IHasUniques {
override var name: String = ""
var type: BeliefType = BeliefType.None
var uniques = ArrayList<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
override var uniques = ArrayList<String>()
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
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]'")
var providesFreeBuilding: String? = null
override var uniques = ArrayList<String>()
var replacementTextForUniques = ""
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var replacementTextForUniques = ""
override var civilopediaText = listOf<FormattedLine>()
fun getShortDescription(ruleset: Ruleset): String { // should fit in one line
val infoList = mutableListOf<String>()
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.unciv.Constants
import com.unciv.logic.civilization.CityStateType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.stats.INamed
import com.unciv.models.translations.Translations
import com.unciv.models.translations.squareBraceRegex
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaText
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText
import com.unciv.ui.utils.Fonts
@ -22,7 +19,7 @@ enum class VictoryType {
Scientific,
}
class Nation : INamed, ICivilopediaText {
class Nation : INamed, ICivilopediaText, IHasUniques {
override lateinit var name: String
var leaderName = ""
@ -43,8 +40,8 @@ class Nation : INamed, ICivilopediaText {
lateinit var outerColor: List<Int>
var uniqueName = ""
var uniques = HashSet<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
override var uniques = ArrayList<String>()
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var uniqueText = ""
var innerColor: List<Int>? = null
var startBias = ArrayList<String>()

View File

@ -2,12 +2,12 @@ package com.unciv.models.ruleset
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
override lateinit var name: String
var uniques: ArrayList<String> = ArrayList()
val uniqueObjects:List<Unique> by lazy { uniques.map { Unique(it) } }
override var uniques: ArrayList<String> = ArrayList()
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
var row: Int = 0
var column: Int = 0
var requires: ArrayList<String>? = null

View File

@ -41,7 +41,7 @@ class ModOptions {
var modSize = 0
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 {

View File

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

View File

@ -3,6 +3,7 @@ package com.unciv.models.ruleset.tile
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Belief
import com.unciv.logic.map.RoadStatus
import com.unciv.models.ruleset.IHasUniques
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.NamedStats
@ -12,13 +13,13 @@ import com.unciv.ui.civilopedia.ICivilopediaText
import java.util.*
import kotlin.math.roundToInt
class TileImprovement : NamedStats(), ICivilopediaText {
class TileImprovement : NamedStats(), ICivilopediaText, IHasUniques {
var terrainsCanBeBuiltOn: Collection<String> = ArrayList()
var techRequired: String? = null
var uniqueTo:String? = null
var uniques = ArrayList<String>()
val uniqueObjects:List<Unique> by lazy { uniques.map { Unique(it) } }
override var uniques = ArrayList<String>()
override val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
val shortcutKey: Char? = null
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.Stat
import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaText
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText
import com.unciv.ui.utils.Fonts
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
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 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 */
class BaseUnit : INamed, INonPerpetualConstruction, CivilopediaText() {
class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
override lateinit var name: String
var cost: Int = 0

View File

@ -1,5 +1,6 @@
package com.unciv.models.ruleset.unit
import com.unciv.models.ruleset.IHasUniques
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.stats.INamed
@ -8,18 +9,18 @@ import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.civilopedia.ICivilopediaText
class Promotion : INamed, ICivilopediaText {
class Promotion : INamed, ICivilopediaText, IHasUniques {
override lateinit var name: String
var prerequisites = listOf<String>()
var effect = ""
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 {
if (effect.isNotEmpty()) yield(effect)
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>()

View File

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

View File

@ -258,7 +258,7 @@ class FormattedLine (
var iconCount = 0
val iconSize = max(minIconSize, fontSize * 1.5f)
if (linkType != LinkType.None && !noLinkImages) {
table.add( ImageGetter.getImage(linkImage) ).size(iconSize).padRight(iconPad)
table.add(ImageGetter.getImage(linkImage)).size(iconSize).padRight(iconPad)
iconCount++
}
if (!noLinkImages)
@ -385,22 +385,23 @@ object MarkupRenderer {
}
/** Storage class for interface [ICivilopediaText] for use as base class */
@Deprecated("As of 3.16.1, use ICivilopediaText directly please")
abstract class CivilopediaText : ICivilopediaText {
override var civilopediaText = listOf<FormattedLine>()
}
/** Storage class for instantiation of the simplest form containing only the lines collection */
class SimpleCivilopediaText(lines: List<FormattedLine>, val isComplete: Boolean = false) : CivilopediaText() {
init {
civilopediaText = lines
}
override fun hasCivilopediaTextLines() = true
override fun replacesCivilopediaDescription() = isComplete
override fun makeLink() = ""
open class SimpleCivilopediaText(
override var civilopediaText: List<FormattedLine>,
val isComplete: Boolean = false
) : ICivilopediaText {
constructor(strings: Sequence<String>, isComplete: Boolean = false) : this(
strings.map { FormattedLine(it) }.toList(), isComplete)
constructor(first: Sequence<FormattedLine>, strings: Sequence<String>, isComplete: Boolean = false) : this(
(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
@ -424,7 +425,7 @@ interface ICivilopediaText {
* @return A [FormattedLine] that will be inserted on top
*/
fun getCivilopediaTextHeader(): FormattedLine? =
if (this is INamed) FormattedLine(name, icon=makeLink(), header = 2)
if (this is INamed) FormattedLine(name, icon = makeLink(), header = 2)
else null
/** Generate automatic lines from object metadata.
@ -456,7 +457,7 @@ interface ICivilopediaText {
* @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.
*/
fun assembleCivilopediaText(ruleset: Ruleset): CivilopediaText {
fun assembleCivilopediaText(ruleset: Ruleset): ICivilopediaText {
val outerLines = civilopediaText.iterator()
val newLines = sequence {
var middleDone = false

View File

@ -4,6 +4,9 @@ import com.badlogic.gdx.utils.Array
import com.unciv.JsonParser
import com.unciv.UncivGame
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
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> {
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)
}
}