⁠
joseph burton: Minecraft new project wizard (#1933 )
* Forge creator almost working
* Store authors and website for next time the user uses the creator
* Don't allow for dialog submission before a latent step is finished
* Fabric mod creator
* Add modid.mixins.json to Forge project creator
* Start with Architectury creator
* Fix long-running tasks that need to run after one another
* Apply website in Forge creator
* Set the correct gradle version in the Forge project creator
* Architectury should be finished but it's not working, not sure why
* Add support for custom build systems via extension points
* Sponge project creator, first maven implementation
* Remove unsupported platforms from the readme
* Add missing platforms to readme
* Replace some silly code with less silly code
* Add Spigot and Paper creators
* Add Velocity creator
* Add BungeeCord and Waterfall creator
* Delete unused code
* ktlint format
* Apply the correct JDK version depending on the platform and version
* Fix license years after merge
* Improvements and fixes to JDK selector UI
* Fix architectury template
* Fix issues with Sponge creator
* Fix IncorrectOperationException in AbstractLatentStep
* Add option to create a git repo (which also creates a gitignore)
* UI improvements
* Add a message encouraging users to report outdated templates
* Add note to project wizard outdated form warning not to request new platforms
* Paper before Spigot
* Remove dependency on TemplateMakerFabric
* Reorganize creators into multiple files and repackage some things
* Improve documentation
* Improve ergonomics for build system properties, main class name, repository, issue tracker
* Limit Sponge API version to 8 and above in dropdown box
* Prevent class name from messing up when the project name contains dots
* Forge creator almost working
* Store authors and website for next time the user uses the creator
* Don't allow for dialog submission before a latent step is finished
* Fabric mod creator
* Add modid.mixins.json to Forge project creator
* Start with Architectury creator
* Fix long-running tasks that need to run after one another
* Apply website in Forge creator
* Set the correct gradle version in the Forge project creator
* Architectury should be finished but it's not working, not sure why
* Add support for custom build systems via extension points
* Sponge project creator, first maven implementation
* Remove unsupported platforms from the readme
* Add missing platforms to readme
* Replace some silly code with less silly code
* Add Spigot and Paper creators
* Add Velocity creator
* Add BungeeCord and Waterfall creator
* Delete unused code
* ktlint format
* Apply the correct JDK version depending on the platform and version
* Fix license years after merge
* Improvements and fixes to JDK selector UI
* Fix architectury template
* Fix issues with Sponge creator
* Fix IncorrectOperationException in AbstractLatentStep
* Add option to create a git repo (which also creates a gitignore)
* UI improvements
* Add a message encouraging users to report outdated templates
* Add note to project wizard outdated form warning not to request new platforms
* Paper before Spigot
* Remove dependency on TemplateMakerFabric
* Reorganize creators into multiple files and repackage some things
* Improve documentation
* Improve ergonomics for build system properties, main class name, repository, issue tracker
* Limit Sponge API version to 8 and above in dropdown box
* Prevent class name from messing up when the project name contains dots
- /*
- * Minecraft Dev for IntelliJ
- *
- * https://minecraftdev.org
- *
- * Copyright (c) 2023 minecraft-dev
- *
- * MIT License
- */
- package com.demonwav.mcdev.platform.forge.creator
- import com.demonwav.mcdev.asset.PlatformAssets
- import com.demonwav.mcdev.creator.MinecraftModuleWizardStep
- import com.demonwav.mcdev.creator.MinecraftProjectCreator
- import com.demonwav.mcdev.creator.ValidatedField
- import com.demonwav.mcdev.creator.ValidatedFieldType.CLASS_NAME
- import com.demonwav.mcdev.creator.ValidatedFieldType.LIST
- import com.demonwav.mcdev.creator.ValidatedFieldType.NON_BLANK
- import com.demonwav.mcdev.platform.forge.version.ForgeVersion
- import com.demonwav.mcdev.platform.mcp.McpVersionPair
- import com.demonwav.mcdev.platform.mcp.version.McpVersion
- import com.demonwav.mcdev.platform.mcp.version.McpVersionEntry
- import com.demonwav.mcdev.util.License
- import com.demonwav.mcdev.util.MinecraftVersions
- import com.demonwav.mcdev.util.SemanticVersion
- import com.demonwav.mcdev.util.asyncIO
- import com.demonwav.mcdev.util.modUpdateStep
- import com.intellij.ui.CollectionComboBoxModel
- import com.intellij.ui.EnumComboBoxModel
- import java.awt.event.ActionListener
- import javax.swing.JCheckBox
- import javax.swing.JComboBox
- import javax.swing.JComponent
- import javax.swing.JLabel
- import javax.swing.JPanel
- import javax.swing.JProgressBar
- import javax.swing.JTextField
- import kotlin.math.min
- import kotlinx.coroutines.CoroutineScope
- import kotlinx.coroutines.Dispatchers
- import kotlinx.coroutines.Job
- import kotlinx.coroutines.coroutineScope
- import kotlinx.coroutines.launch
- import kotlinx.coroutines.swing.Swing
- class ForgeProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() {
- @ValidatedField(NON_BLANK)
- private lateinit var modNameField: JTextField
- @ValidatedField(NON_BLANK, CLASS_NAME)
- private lateinit var mainClassField: JTextField
- private lateinit var panel: JPanel
- private lateinit var title: JLabel
- private lateinit var descriptionField: JTextField
- @ValidatedField(LIST)
- private lateinit var authorsField: JTextField
- private lateinit var websiteField: JTextField
- private lateinit var updateUrlField: JTextField
- private lateinit var licenseBox: JComboBox<License>
- private lateinit var mixinsCheckbox: JCheckBox
- private lateinit var minecraftVersionBox: JComboBox<SemanticVersion>
- private lateinit var forgeVersionBox: JComboBox<SemanticVersion>
- private lateinit var mcpVersionBox: JComboBox<McpVersionEntry>
- private lateinit var loadingBar: JProgressBar
- private lateinit var minecraftVersionLabel: JLabel
- private lateinit var mcpWarning: JLabel
- private lateinit var errorLabel: JLabel
- private var config: ForgeProjectConfig? = null
- private data class ForgeVersions(
- var mcpVersion: McpVersion,
- var forgeVersion: ForgeVersion
- )
- private var versions: ForgeVersions? = null
- private var currentJob: Job? = null
- private val mcpBoxActionListener = ActionListener {
- mcpWarning.isVisible = (mcpVersionBox.selectedItem as? McpVersionEntry)?.isRed == true
- }
- private val forgeVersionBoxListener = ActionListener {
- val selectedVersion = forgeVersionBox.selectedItem as? SemanticVersion ?: return@ActionListener
- val supportedMixinVersion = selectedVersion >= SemanticVersion.release(31, 2, 45)
- val mcpMappingsVersion = selectedVersion <= SemanticVersion.release(37, 0, 0)
- mixinsCheckbox.isEnabled = supportedMixinVersion
- if (!supportedMixinVersion) {
- mixinsCheckbox.isSelected = false
- }
- mcpVersionBox.isEnabled = mcpMappingsVersion
- mcpWarning.isVisible = mcpMappingsVersion
- if (mcpMappingsVersion) {
- mcpBoxActionListener.actionPerformed(null)
- }
- }
- private val minecraftBoxActionListener: ActionListener = ActionListener {
- CoroutineScope(Dispatchers.Swing).launch {
- loadingBar.isIndeterminate = true
- loadingBar.isVisible = true
- updateForm()
- loadingBar.isIndeterminate = false
- loadingBar.isVisible = false
- }
- }
- init {
- mcpWarning.isVisible = false
- }
- override fun getComponent(): JComponent {
- return panel
- }
- override fun updateStep() {
- val (conf, buildSystem) = modUpdateStep<ForgeProjectConfig>(creator, modNameField) ?: return
- config = conf
- mainClassField.text = generateClassName(buildSystem, modNameField.text)
- title.icon = PlatformAssets.FORGE_ICON_2X
- title.text = "<html><font size=\"5\">Forge Settings</font></html>"
- minecraftVersionLabel.text = "Minecraft Version"
- licenseBox.model = EnumComboBoxModel(License::class.java)
- licenseBox.selectedItem = License.ALL_RIGHTS_RESERVED
- if (versions != null || currentJob?.isActive == true) {
- return
- }
- currentJob = updateVersions()
- }
- private fun setForgeVersion(data: Data) {
- forgeVersionBox.model = CollectionComboBoxModel(data.forgeVersions.subList(0, min(50, data.forgeVersions.size)))
- forgeVersionBox.selectedIndex = data.forgeSelectedIndex
- }
- private val version: SemanticVersion?
- get() = minecraftVersionBox.selectedItem as? SemanticVersion
- override fun validate(): Boolean {
- return super.validate() && !loadingBar.isVisible
- }
- override fun isStepVisible(): Boolean {
- return creator.config is ForgeProjectConfig
- }
- override fun onStepLeaving() {
- currentJob?.cancel()
- }
- override fun updateDataModel() {
- val conf = this.config ?: return
- conf.pluginName = this.modNameField.text
- conf.mainClass = this.mainClassField.text
- conf.description = this.descriptionField.text
- conf.website = this.websiteField.text
- conf.setAuthors(this.authorsField.text)
- conf.updateUrl = this.updateUrlField.text
- conf.mcVersion = this.version ?: SemanticVersion.release()
- conf.mcpVersion = if (conf.mcVersion >= MinecraftVersions.MC1_17) {
- McpVersionPair("official_" + conf.mcVersion, conf.mcVersion)
- } else {
- (this.mcpVersionBox.selectedItem as McpVersionEntry).versionPair
- }
- (this.forgeVersionBox.selectedItem as SemanticVersion).let { version ->
- val versionString = version.toString()
- val forgeVersion = this.versions?.forgeVersion ?: return@let
- conf.forgeVersionText = forgeVersion.versions.first { it.endsWith(versionString) }
- conf.forgeVersion = version
- }
- conf.mixins = mixinsCheckbox.isSelected
- conf.license = licenseBox.selectedItem as? License ?: License.ALL_RIGHTS_RESERVED
- }
- private fun mcVersionUpdate(data: Data) {
- mcpVersionBox.removeActionListener(mcpBoxActionListener)
- mcpVersionBox.model = CollectionComboBoxModel(data.mcpVersions.subList(0, min(50, data.mcpVersions.size)))
- mcpVersionBox.selectedIndex = 0
- mcpVersionBox.addActionListener(mcpBoxActionListener)
- mcpBoxActionListener.actionPerformed(null)
- forgeVersionBox.removeActionListener(forgeVersionBoxListener)
- setForgeVersion(data)
- forgeVersionBox.addActionListener(forgeVersionBoxListener)
- forgeVersionBoxListener.actionPerformed(null)
- }
- private fun updateVersions() = CoroutineScope(Dispatchers.Swing).launch {
- loadingBar.isIndeterminate = true
- loadingBar.isVisible = true
- try {
- downloadVersions()
- val data = updateForm()
- if (data != null) {
- updateMcForm(data)
- }
- } catch (e: Exception) {
- error()
- }
- loadingBar.isIndeterminate = false
- loadingBar.isVisible = false
- currentJob = null
- }
- fun error() {
- errorLabel.isVisible = true
- loadingBar.isIndeterminate = false
- loadingBar.isVisible = false
- }
- private suspend fun downloadVersions() = coroutineScope {
- val mcpVersionJob = asyncIO { McpVersion.downloadData() }
- val forgeVersionJob = asyncIO { ForgeVersion.downloadData() }
- versions = ForgeVersions(
- mcpVersionJob.await() ?: return@coroutineScope,
- forgeVersionJob.await() ?: return@coroutineScope
- )
- }
- private suspend fun updateForm(): Data? = coroutineScope {
- val vers = versions ?: return@coroutineScope null
- val selectedVersion = version ?: vers.forgeVersion.sortedMcVersions.firstOrNull() ?: return@coroutineScope null
- val mcpVersionListJob = asyncIO { vers.mcpVersion.getMcpVersionList(selectedVersion) }
- val forgeVersionsJob = asyncIO { vers.forgeVersion.getForgeVersions(selectedVersion) }
- val mcpVersionList = mcpVersionListJob.await()
- val forgeVersions = forgeVersionsJob.await()
- val data = Data(0, mcpVersionList, forgeVersions, 0)
- mcVersionUpdate(data)
- return@coroutineScope data
- }
- private fun updateMcForm(data: Data) {
- val vers = versions ?: return
- minecraftVersionBox.removeActionListener(minecraftBoxActionListener)
- minecraftVersionBox.removeAllItems()
- minecraftVersionBox.model = CollectionComboBoxModel(vers.forgeVersion.sortedMcVersions)
- minecraftVersionBox.selectedIndex = data.mcSelectedIndex
- minecraftVersionBox.addActionListener(minecraftBoxActionListener)
- }
- private data class Data(
- val mcSelectedIndex: Int,
- val mcpVersions: List<McpVersionEntry>,
- val forgeVersions: List<SemanticVersion>,
- val forgeSelectedIndex: Int
- )
- }