From 41bd1314b9908267218ef42d48269c5839167fb6 Mon Sep 17 00:00:00 2001 From: yairm210 Date: Sun, 14 Jul 2024 11:47:02 +0300 Subject: [PATCH] Mod CI step 1 - allow running Unciv as a cli tool for linting etc --- core/src/com/unciv/models/ruleset/Ruleset.kt | 4 ++-- .../com/unciv/app/desktop/ConsoleLauncher.kt | 10 +++++++--- .../src/com/unciv/app/desktop/DesktopGame.kt | 20 +++++++++++++++++++ .../com/unciv/app/desktop/DesktopLauncher.kt | 7 +++++-- .../src/com/unciv/app/desktop/ImagePacker.kt | 2 +- docs/Modders/.pages | 1 + docs/Modders/CI-automation.md | 7 +++++++ 7 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 docs/Modders/CI-automation.md diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index 1a2514963b..710af48c05 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -89,7 +89,7 @@ class Ruleset { val tileRemovals by lazy { tileImprovements.values.filter { it.name.startsWith(Constants.remove) } } val nonRoadTileRemovals by lazy { tileRemovals.filter { rulesetImprovement -> - RoadStatus.values().none { it.removeAction == rulesetImprovement.name } } } + RoadStatus.entries.toTypedArray().none { it.removeAction == rulesetImprovement.name } } } /** Contains all happiness levels that moving *from* them, to one *below* them, can change uniques that apply */ val allHappinessLevelsThatAffectUniques by lazy { @@ -244,7 +244,7 @@ class Ruleset { fun allICivilopediaText(): Sequence = allRulesetObjects() + events.values + events.values.flatMap { it.choices } - internal fun load(folderHandle: FileHandle) { + fun load(folderHandle: FileHandle) { // Note: Most files are loaded using createHashmap, which sets originRuleset automatically. // For other files containing IRulesetObject's we'll have to remember to do so manually - e.g. Tech. val modOptionsFile = folderHandle.child("ModOptions.json") diff --git a/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt b/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt index 142093c16c..5c4553c51c 100644 --- a/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt +++ b/desktop/src/com/unciv/app/desktop/ConsoleLauncher.kt @@ -16,7 +16,6 @@ import com.unciv.models.ruleset.nation.Nation import com.unciv.models.skins.SkinCache import com.unciv.models.tilesets.TileSetCache import com.unciv.utils.Log -import java.util.LinkedHashSet import kotlin.time.ExperimentalTime internal object ConsoleLauncher { @@ -39,7 +38,12 @@ internal object ConsoleLauncher { TileSetCache.loadTileSetConfigs(true) SkinCache.loadSkinConfigs(true) - val ruleset = RulesetCache[BaseRuleset.Civ_V_GnK.fullName]!! + runSimulation() + } + + @ExperimentalTime + private fun runSimulation() { + val ruleset = RulesetCache[BaseRuleset.Civ_V_GnK.fullName]!! ruleset.nations[simulationCiv1] = Nation().apply { name = simulationCiv1 } ruleset.nations[simulationCiv2] = Nation().apply { name = simulationCiv2 } @@ -52,7 +56,7 @@ internal object ConsoleLauncher { UncivGame.Current.gameInfo = newGame - val simulation = Simulation(newGame,10,4) + val simulation = Simulation(newGame, 10, 4) simulation.start() } diff --git a/desktop/src/com/unciv/app/desktop/DesktopGame.kt b/desktop/src/com/unciv/app/desktop/DesktopGame.kt index f6b764a6bc..e7d3786c3c 100644 --- a/desktop/src/com/unciv/app/desktop/DesktopGame.kt +++ b/desktop/src/com/unciv/app/desktop/DesktopGame.kt @@ -3,11 +3,16 @@ package com.unciv.app.desktop import com.badlogic.gdx.Gdx import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration import com.unciv.UncivGame +import com.unciv.models.ruleset.Ruleset +import com.unciv.models.ruleset.validation.RulesetErrorSeverity +import com.unciv.models.ruleset.validation.RulesetValidator +import kotlin.system.exitProcess class DesktopGame(config: Lwjgl3ApplicationConfiguration) : UncivGame() { private var discordUpdater = DiscordUpdater() private val windowListener = UncivWindowListener() + var isModCi = false init { config.setWindowListener(windowListener) @@ -33,6 +38,21 @@ class DesktopGame(config: Lwjgl3ApplicationConfiguration) : UncivGame() { discordUpdater.startUpdates() } + override fun create() { + // The uniques checker requires the file system to be seet up, which happens after lwjgw initializes it + if (isModCi) { + ImagePacker.packImagesPerMod(".", ".") + val ruleset = Ruleset() + ruleset.folderLocation = Gdx.files.local("jsons") + ruleset.load(ruleset.folderLocation!!) + val errors = RulesetValidator(ruleset).getErrorList(true) + println(errors.getErrorText(true)) + exitProcess(if (errors.any { it.errorSeverityToReport == RulesetErrorSeverity.Error }) 1 else 0) + } + + super.create() + } + override fun installAudioHooks() { (Gdx.app as HardenGdxAudio).installHooks( musicController.getAudioLoopCallback(), diff --git a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt index 87355716ee..cf96a8a2f0 100644 --- a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt +++ b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt @@ -37,7 +37,7 @@ internal object DesktopLauncher { // For more info see https://github.com/yairm210/Unciv/pull/3202 and https://github.com/LWJGL/lwjgl/issues/119 System.setProperty("org.lwjgl.opengl.Display.allowSoftwareOpenGL", "true") - val isRunFromJAR = DesktopLauncher.javaClass.`package`.specificationVersion != null + val isRunFromJAR = true//DesktopLauncher.javaClass.`package`.specificationVersion != null ImagePacker.packImages(isRunFromJAR) val config = Lwjgl3ApplicationConfiguration() @@ -68,8 +68,11 @@ internal object DesktopLauncher { UiElementDocsWriter().write() } + val desktopGame = DesktopGame(config) + if (arg.isNotEmpty() && arg[0] == "mod-ci") desktopGame.isModCi = true + // HardenGdxAudio extends Lwjgl3Application, and the Lwjgl3Application constructor runs as long as the game runs - HardenGdxAudio(DesktopGame(config), config) + HardenGdxAudio(desktopGame, config) exitProcess(0) } } diff --git a/desktop/src/com/unciv/app/desktop/ImagePacker.kt b/desktop/src/com/unciv/app/desktop/ImagePacker.kt index e24790b44c..7bc6a8a5a6 100644 --- a/desktop/src/com/unciv/app/desktop/ImagePacker.kt +++ b/desktop/src/com/unciv/app/desktop/ImagePacker.kt @@ -104,7 +104,7 @@ internal object ImagePacker { } // Scan multiple image folders and generate an atlas for each - if outdated - private fun packImagesPerMod(input: String, output: String, defaultSettings: TexturePacker.Settings) { + fun packImagesPerMod(input: String, output: String, defaultSettings: TexturePacker.Settings = getDefaultSettings()) { val baseDir = File(input) if (!File(baseDir, imagesPathBase).exists() && !File(baseDir, existCheck2).exists()) return // So we don't run this from within a fat JAR val atlasList = mutableListOf() diff --git a/docs/Modders/.pages b/docs/Modders/.pages index 1a2c1ed426..55eb3b7ab4 100644 --- a/docs/Modders/.pages +++ b/docs/Modders/.pages @@ -10,3 +10,4 @@ nav: - uniques.md - Type-checking.md - Scenarios.md + - CI-automation.md diff --git a/docs/Modders/CI-automation.md b/docs/Modders/CI-automation.md new file mode 100644 index 0000000000..133113df32 --- /dev/null +++ b/docs/Modders/CI-automation.md @@ -0,0 +1,7 @@ +# AI automation + +Unciv contains built-in capabilities for packing images and autoupdating uniques. +You can use Unciv as a command-line tool by running it with the command + +`java -jar /Unciv.jar mod-ci` +