Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
root = true

[*.{kt,kts}]
max_line_length=120
ij_kotlin_imports_layout=*
indent_size = 4
indent_style = space
max_line_length = 120
ij_kotlin_imports_layout = *
ij_kotlin_name_count_to_use_star_import = 2147483647
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
insert_final_newline = true
2 changes: 1 addition & 1 deletion src/main/kotlin/creator/custom/TemplateDescriptor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ data class TemplateDescriptor(

companion object {

const val FORMAT_VERSION = 1
const val FORMAT_VERSION = 2
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.creator.custom.derivation

import com.demonwav.mcdev.creator.custom.PropertyDerivation
import com.demonwav.mcdev.creator.custom.TemplateValidationReporter
import com.demonwav.mcdev.creator.custom.types.CreatorProperty
import com.demonwav.mcdev.util.MinecraftVersions
import com.demonwav.mcdev.util.SemanticVersion

class ExtractPaperApiVersionPropertyDerivation : ExtractVersionMajorMinorPropertyDerivation() {

override fun derive(parentValues: List<Any?>): Any? {
val from = parentValues[0] as SemanticVersion
if (from >= MinecraftVersions.MC1_20_5) {
return from
}

return super.derive(parentValues);
}

companion object : PropertyDerivationFactory {

override fun create(
reporter: TemplateValidationReporter,
parents: List<CreatorProperty<*>?>?,
derivation: PropertyDerivation
): PreparedDerivation? {
if (parents.isNullOrEmpty()) {
reporter.error("Expected a parent")
return null
}

if (!parents[0]!!.acceptsType(SemanticVersion::class.java)) {
reporter.error("First parent must produce a semantic version")
return null
}

return ExtractPaperApiVersionPropertyDerivation()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import com.demonwav.mcdev.creator.custom.TemplateValidationReporter
import com.demonwav.mcdev.creator.custom.types.CreatorProperty
import com.demonwav.mcdev.util.SemanticVersion

class ExtractVersionMajorMinorPropertyDerivation : PreparedDerivation {
open class ExtractVersionMajorMinorPropertyDerivation : PreparedDerivation {

override fun derive(parentValues: List<Any?>): Any? {
val from = parentValues[0] as SemanticVersion
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/creator/custom/model/StringList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ data class StringList(val values: List<String>) : List<String> by values {
@JvmOverloads
fun toString(separator: String, prefix: String = "", postfix: String = ""): String =
values.joinToString(separator, prefix, postfix)

fun toStringQuoted(): String =
values.joinToString(", ", transform = { '"' + it + '"' })
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class MavenArtifactVersionCreatorProperty(
var versionFilter: (SemanticVersion) -> Boolean = { true }

override val graphProperty: GraphProperty<SemanticVersion> = graph.property(SemanticVersion(emptyList()))
private val versionsProperty = graph.property<Collection<SemanticVersion>>(emptyList())
private val versionsProperty = graph.property<Set<SemanticVersion>>(emptySet())
private val loadingVersionsProperty = graph.property(true)
private val loadingVersionsStatusProperty = graph.property("")

Expand Down Expand Up @@ -127,7 +127,7 @@ class MavenArtifactVersionCreatorProperty(
descriptor.limit ?: 50
) { result ->
result.onSuccess { versions ->
versionsProperty.set(versions)
versionsProperty.set(versions.toSet())
loadingVersionsProperty.set(false)
}.onFailure { exception ->
loadingVersionsStatusProperty.set(exception.message ?: exception.javaClass.simpleName)
Expand Down
129 changes: 129 additions & 0 deletions src/main/kotlin/creator/custom/types/PaperVersionCreatorProperty.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2025 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.creator.custom.types

import com.demonwav.mcdev.creator.custom.CreatorContext
import com.demonwav.mcdev.creator.custom.TemplatePropertyDescriptor
import com.demonwav.mcdev.creator.custom.TemplateValidationReporter
import com.demonwav.mcdev.update.PluginUtil
import com.demonwav.mcdev.util.MinecraftVersions
import com.demonwav.mcdev.util.SemanticVersion
import com.intellij.ui.ComboboxSpeedSearch
import com.intellij.ui.JBColor
import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.builder.bindItem
import com.intellij.ui.dsl.builder.bindText
import com.intellij.util.ui.AsyncProcessIcon
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive

open class PaperVersionCreatorProperty(
descriptor: TemplatePropertyDescriptor,
context: CreatorContext
) : SemanticVersionCreatorProperty(descriptor, context) {

@OptIn(DelicateCoroutinesApi::class)
companion object {
private var paperVersions: List<SemanticVersion>? = null

suspend fun getPaperVersions(): List<SemanticVersion> {
paperVersions?.let { return it }

val client = HttpClient()
val response = client.get("https://fill.papermc.io/v3/projects/paper", block = {
this.header("User-Agent", "minecraft-dev/${PluginUtil.pluginVersion} (https://github.com/minecraft-dev/MinecraftDev)")
})
if (response.status.isSuccess()) {
val element = Json.parseToJsonElement(response.bodyAsText())
val result = element.jsonObject["versions"]?.jsonObject?.values
?.asSequence()
?.flatMap { it.jsonArray }
?.map { it.jsonPrimitive.content }
?.mapNotNull { SemanticVersion.tryParse(it) }
// only release versions
?.filter { ver -> ver.parts.all { it is SemanticVersion.Companion.VersionPart.ReleasePart } }
// nothing lower than 1.18.2 should be selectable
?.filter { it >= MinecraftVersions.MC1_18_2 }
?.toList()
?.sortedDescending()

if (result != null) {
paperVersions = result
return result
}
}

return emptyList()
}
}

private val versionsProperty = graph.property<Set<SemanticVersion>>(emptySet())
private val loadingVersionsProperty = graph.property(true)
private val loadingVersionsStatusProperty = graph.property("")

override fun buildUi(panel: Panel) {
panel.row(descriptor.translatedLabel) {
val combobox = comboBox(versionsProperty.get())
.bindItem(graphProperty)
.enabled(descriptor.editable != false)
.also { ComboboxSpeedSearch.installOn(it.component) }

cell(AsyncProcessIcon(makeStorageKey("progress")))
.visibleIf(loadingVersionsProperty)
label("").applyToComponent { foreground = JBColor.RED }
.bindText(loadingVersionsStatusProperty)
.visibleIf(loadingVersionsProperty)

versionsProperty.afterChange { versions ->
combobox.component.removeAllItems()
for (version in versions) {
combobox.component.addItem(version)
}
}
}.propertyVisibility()
}

override fun setupProperty(reporter: TemplateValidationReporter) {
super.setupProperty(reporter)
val scope = context.childScope("PaperVersionCreatorProperty")
scope.launch(Dispatchers.Default) {
val result = getPaperVersions()
versionsProperty.set(result.toSet())
loadingVersionsProperty.set(false)
}
}

class Factory : CreatorPropertyFactory {
override fun create(
descriptor: TemplatePropertyDescriptor,
context: CreatorContext
): CreatorProperty<*> = PaperVersionCreatorProperty(descriptor, context)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.demonwav.mcdev.creator.custom.CreatorContext
import com.demonwav.mcdev.creator.custom.PropertyDerivation
import com.demonwav.mcdev.creator.custom.TemplatePropertyDescriptor
import com.demonwav.mcdev.creator.custom.TemplateValidationReporter
import com.demonwav.mcdev.creator.custom.derivation.ExtractPaperApiVersionPropertyDerivation
import com.demonwav.mcdev.creator.custom.derivation.ExtractVersionMajorMinorPropertyDerivation
import com.demonwav.mcdev.creator.custom.derivation.PreparedDerivation
import com.demonwav.mcdev.creator.custom.derivation.SelectPropertyDerivation
Expand Down Expand Up @@ -64,6 +65,11 @@ open class SemanticVersionCreatorProperty(
ExtractVersionMajorMinorPropertyDerivation.create(reporter, parents, derives)
}

"extractPaperApiVersion" -> {
val parents = collectDerivationParents(reporter)
ExtractPaperApiVersionPropertyDerivation.create(reporter, parents, derives)
}

null -> {
SelectPropertyDerivation.create(reporter, emptyList(), derives)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ abstract class SimpleCreatorProperty<T>(
isSelected: Boolean,
cellHasFocus: Boolean
): Component {
val label = options!![value] ?: value.toString()
val label = options?.get(value) ?: value.toString()
return super.getListCellRendererComponent(list, label, index, isSelected, cellHasFocus)
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@
<creatorPropertyType
implementation="com.demonwav.mcdev.creator.custom.types.NeoForgeVersionsCreatorProperty$Factory"
type="neoforge_versions"/>
<creatorPropertyType
implementation="com.demonwav.mcdev.creator.custom.types.PaperVersionCreatorProperty$Factory"
type="paper_versions"/>
<creatorPropertyType implementation="com.demonwav.mcdev.creator.custom.types.ParchmentCreatorProperty$Factory"
type="parchment"/>
<creatorPropertyType
Expand Down
16 changes: 16 additions & 0 deletions src/main/resources/messages/MinecraftDevelopment.properties
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@ creator.ui.use_fabricapi.label=Use Fabric API
creator.ui.spongeapi_version.label=Sponge Version\:
creator.ui.velocity_version.label=Velocity Version\:
creator.ui.versions_download.label=Downloading versions...
creator.ui.use_version_catalog.label=Use Gradle version catalog\:
creator.ui.include_plugin_bootstrap.label=Include plugin bootstrap file\:
creator.ui.use_gremlin.label=Use gremlin for dependency resolution\:
creator.ui.gremlin_version.label=gremlin version\:
creator.ui.include_plugin_loader.label=Include plugin loader file\:
creator.ui.java_plugin_loader.label=Generate the plugin loader in Java\:
creator.ui.use_resource_factory_plugin.label=Use the resource-factory Gradle plugin\:
creator.ui.resource_factory_version.label=resource-factory version\:
creator.ui.use_paperweight_userdev.label=Use the paperweight-userdev Gradle plugin\:
creator.ui.paperweight_version.label=paperweight-userdev version\:
creator.ui.include_shadow_plugin.label=Include the shadow Gradle plugin\:
creator.ui.shadow_version.label=shadow version\:
creator.ui.include_run_paper_plugin.label=Include the run-paper Gradle plugin\:
creator.ui.run_paper_version.label=run-paper version\:
creator.ui.accept_eula.label=Add eula-agree runServer JVM flag\:
creator.ui.accept_eula.warning=By using this feature, you agree to the <a href='https://www.minecraft.net/en-us/eula'>Minecraft EULA</a>.

creator.ui.warn.no_yarn_to_mc_match=Unable to match Yarn versions to Minecraft version
creator.ui.warn.no_fabricapi_to_mc_match=Unable to match API versions to Minecraft version
Expand Down