Skip to content

Commit e23ddbd

Browse files
authored
NeoForge support (#2196)
* NeoForged support * 2024 license * Add Parchment mappings * Fix NeoGradle integration * License * Fix ktlint error * Allow using parchment mappings for older versions * Address reviews * Quote mod_id placeholder in mods.toml template See 59677b8
1 parent 47053d6 commit e23ddbd

File tree

63 files changed

+2607
-50
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2607
-50
lines changed

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ Supported Platforms
137137
- [![Sponge Icon](src/main/resources/assets/icons/platform/Sponge_dark.png?raw=true) **Sponge**](https://www.spongepowered.org/)
138138
- [![Architectury Icon](src/main/resources/assets/icons/platform/Architectury.png?raw=true) **Architectury**](https://github.com/architectury/architectury-api)
139139
- [![Forge Icon](src/main/resources/assets/icons/platform/Forge.png?raw=true) **Minecraft Forge**](https://forums.minecraftforge.net/)
140+
- <a href="https://neoforged.net/"><img src="src/main/resources/assets/icons/platform/NeoForge.png?raw=true" width="16" height="16"/> <b>Neoforge</b><a/>
140141
- [![Fabric Icon](src/main/resources/assets/icons/platform/Fabric.png?raw=true) **Fabric**](https://fabricmc.net)
141142
- [![Mixins Icon](src/main/resources/assets/icons/platform/Mixins_dark.png?raw=true) **Mixins**](https://github.com/SpongePowered/Mixin)
142143
- [![BungeeCord Icon](src/main/resources/assets/icons/platform/BungeeCord.png?raw=true) **BungeeCord**](https://www.spigotmc.org/wiki/bungeecord/) ([![Waterfall Icon](src/main/resources/assets/icons/platform/Waterfall.png?raw=true) Waterfall](https://github.com/PaperMC/Waterfall))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle
22+
23+
import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7
24+
import org.gradle.api.Project
25+
import org.jetbrains.annotations.NotNull
26+
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
27+
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
28+
29+
final class NeoGradle7ModelBuilderImpl implements ModelBuilderService {
30+
31+
@Override
32+
boolean canBuild(String modelName) {
33+
return McpModelNG7.name == modelName
34+
}
35+
36+
@Override
37+
Object buildAll(String modelName, Project project) {
38+
def extension = project.extensions.findByName('minecraft')
39+
if (extension == null) {
40+
return null
41+
}
42+
43+
if (!project.plugins.findPlugin("net.neoforged.gradle.userdev")) {
44+
return null
45+
}
46+
47+
// NG userdev
48+
def runtimes = project.extensions.findByName('userDevRuntime').runtimes.get()
49+
def neoforgeVersion = null
50+
for (def entry in runtimes) {
51+
neoforgeVersion = entry.value.specification.forgeVersion
52+
break
53+
}
54+
if (neoforgeVersion == null) {
55+
return null
56+
}
57+
58+
def mappingsFile = project.tasks.neoFormMergeMappings.output.get().asFile
59+
60+
def accessTransformers = extension.accessTransformers.files.asList()
61+
62+
//noinspection GroovyAssignabilityCheck
63+
return new NeoGradle7ModelImpl(neoforgeVersion, mappingsFile, accessTransformers)
64+
}
65+
66+
@Override
67+
ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
68+
return ErrorMessageBuilder.create(
69+
project, e, "MinecraftDev import errors"
70+
).withDescription("Unable to build MinecraftDev MCP project configuration")
71+
}
72+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle
22+
23+
24+
import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7
25+
import groovy.transform.CompileStatic
26+
27+
@CompileStatic
28+
final class NeoGradle7ModelImpl implements McpModelNG7, Serializable {
29+
30+
final String neoForgeVersion
31+
final File mappingsFile
32+
final List<File> accessTransformers
33+
34+
NeoGradle7ModelImpl(
35+
final String neoForgeVersion,
36+
final File mappingsFile,
37+
final List<File> accessTransformers
38+
) {
39+
this.neoForgeVersion = neoForgeVersion
40+
this.mappingsFile = mappingsFile
41+
this.accessTransformers = accessTransformers
42+
}
43+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mcp.gradle.tooling;
22+
23+
import java.io.File;
24+
import java.util.List;
25+
26+
public interface McpModelNG7 {
27+
String getNeoForgeVersion();
28+
File getMappingsFile();
29+
List<File> getAccessTransformers();
30+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom.ArchitecturyModelBuilderImpl
22
com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom.FabricLoomModelBuilderImpl
3+
com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle.NeoGradle7ModelBuilderImpl
34
com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle.VanillaGradleModelBuilderImpl
45
com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG2BuilderImpl
56
com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG3BuilderImpl

src/main/kotlin/asset/PlatformAssets.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
package com.demonwav.mcdev.asset
2222

23+
import com.intellij.util.IconUtil
24+
2325
@Suppress("unused")
2426
object PlatformAssets : Assets() {
2527
val MINECRAFT_ICON = loadIcon("/assets/icons/platform/Minecraft.png")
@@ -62,6 +64,9 @@ object PlatformAssets : Assets() {
6264
val MIXIN_ICON_DARK = loadIcon("/assets/icons/platform/Mixins_dark.png")
6365
val MIXIN_ICON_2X_DARK = loadIcon("/assets/icons/platform/Mixins@2x_dark.png")
6466

67+
val NEOFORGE_ICON = IconUtil.scale(loadIcon("/assets/icons/platform/NeoForge.png"), null, 0.125f)
68+
val NEOFORGE_ICON_2X = IconUtil.scale(loadIcon("/assets/icons/platform/NeoForge.png"), null, 0.25f)
69+
6570
val MCP_ICON = loadIcon("/assets/icons/platform/MCP.png")
6671
val MCP_ICON_2X = loadIcon("/assets/icons/platform/[email protected]")
6772
val MCP_ICON_DARK = loadIcon("/assets/icons/platform/MCP_dark.png")
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.creator
22+
23+
import com.demonwav.mcdev.asset.MCDevBundle
24+
import com.demonwav.mcdev.creator.step.AbstractMcVersionChainStep
25+
import com.demonwav.mcdev.util.SemanticVersion
26+
import com.intellij.icons.AllIcons
27+
import com.intellij.ide.wizard.AbstractNewProjectWizardStep
28+
import com.intellij.ide.wizard.NewProjectWizardStep
29+
import com.intellij.openapi.observable.properties.ObservableMutableProperty
30+
import com.intellij.openapi.observable.util.and
31+
import com.intellij.openapi.observable.util.bindBooleanStorage
32+
import com.intellij.openapi.observable.util.not
33+
import com.intellij.openapi.project.Project
34+
import com.intellij.openapi.util.Key
35+
import com.intellij.ui.content.AlertIcon
36+
import com.intellij.ui.dsl.builder.Panel
37+
import com.intellij.ui.dsl.builder.bindItem
38+
import com.intellij.ui.dsl.builder.bindSelected
39+
import com.intellij.util.application
40+
import com.intellij.util.ui.AsyncProcessIcon
41+
import javax.swing.DefaultComboBoxModel
42+
import kotlinx.coroutines.Dispatchers
43+
import kotlinx.coroutines.runBlocking
44+
import kotlinx.coroutines.swing.Swing
45+
import kotlinx.coroutines.withContext
46+
47+
class ParchmentStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) {
48+
49+
val useParchmentProperty = propertyGraph.property(false)
50+
.bindBooleanStorage("${javaClass.name}.useParchment")
51+
var useParchment by useParchmentProperty
52+
53+
val parchmentVersionProperty = propertyGraph.property<ParchmentVersion?>(null)
54+
var parchmentVersion by parchmentVersionProperty
55+
56+
val parchmentVersionsProperty = propertyGraph.property<List<ParchmentVersion>>(emptyList())
57+
var parchmentVersions by parchmentVersionsProperty
58+
59+
val loadingVersionsProperty = propertyGraph.property(false)
60+
var loadingVersions by loadingVersionsProperty
61+
62+
val hasParchmentVersionProperty = propertyGraph.property(false)
63+
var hasParchmentVersion by hasParchmentVersionProperty
64+
65+
val includeOlderMcVersionsProperty = propertyGraph.property(false)
66+
.bindBooleanStorage("${javaClass.name}.includeOlderMcVersions")
67+
var includeOlderMcVersions by includeOlderMcVersionsProperty
68+
69+
val includeSnapshotsVersionsProperty = propertyGraph.property(false)
70+
.bindBooleanStorage("${javaClass.name}.includeSnapshotsVersions")
71+
var includeSnapshotsVersions by includeSnapshotsVersionsProperty
72+
73+
private val parchmentVersionsModel = DefaultComboBoxModel<ParchmentVersion>(emptyArray())
74+
private val mcVersionProperty: ObservableMutableProperty<SemanticVersion>
75+
76+
init {
77+
storeToData()
78+
@Suppress("UNCHECKED_CAST")
79+
mcVersionProperty = findStep<AbstractMcVersionChainStep>().getVersionProperty(0)
80+
as ObservableMutableProperty<SemanticVersion>
81+
mcVersionProperty.afterChange { updateVersionsModel() }
82+
83+
includeOlderMcVersionsProperty.afterChange { updateVersionsModel() }
84+
includeSnapshotsVersionsProperty.afterChange { updateVersionsModel() }
85+
86+
downloadVersions()
87+
}
88+
89+
private fun updateVersionsModel() {
90+
val mcVersion = mcVersionProperty.get()
91+
val versions = parchmentVersions.filter { version ->
92+
if (!includeOlderMcVersions && version.mcVersion < mcVersion) {
93+
return@filter false
94+
}
95+
96+
if (!includeSnapshotsVersions && version.parchmentVersion.contains("-SNAPSHOT")) {
97+
return@filter false
98+
}
99+
100+
return@filter true
101+
}
102+
103+
hasParchmentVersion = versions.isNotEmpty()
104+
105+
parchmentVersionsModel.removeAllElements()
106+
parchmentVersionsModel.addAll(versions)
107+
108+
parchmentVersionsModel.selectedItem = versions.firstOrNull { !it.parchmentVersion.contains('-') }
109+
?: versions.firstOrNull()
110+
111+
loadingVersions = false
112+
}
113+
114+
private fun downloadVersions() {
115+
loadingVersions = true
116+
parchmentVersionsModel.removeAllElements()
117+
application.executeOnPooledThread {
118+
runBlocking {
119+
val versions = ParchmentVersion.downloadData()
120+
withContext(Dispatchers.Swing) {
121+
parchmentVersions = versions
122+
updateVersionsModel()
123+
}
124+
}
125+
}
126+
}
127+
128+
override fun setupUI(builder: Panel) {
129+
with(builder) {
130+
row(MCDevBundle("creator.ui.parchment.label")) {
131+
checkBox("")
132+
.bindSelected(useParchmentProperty)
133+
134+
comboBox(parchmentVersionsModel)
135+
.enabledIf(useParchmentProperty and hasParchmentVersionProperty)
136+
.bindItem(parchmentVersionProperty)
137+
138+
cell(AsyncProcessIcon("$javaClass.parchmentVersions"))
139+
.visibleIf(loadingVersionsProperty)
140+
141+
label(MCDevBundle("creator.ui.parchment.no_version.message"))
142+
.visibleIf(hasParchmentVersionProperty.not() and loadingVersionsProperty.not())
143+
.applyToComponent { icon = AlertIcon(AllIcons.General.Warning) }
144+
}
145+
146+
row(MCDevBundle("creator.ui.parchment.include.label")) {
147+
checkBox(MCDevBundle("creator.ui.parchment.include.old_mc.label"))
148+
.enabledIf(useParchmentProperty)
149+
.bindSelected(includeOlderMcVersionsProperty)
150+
checkBox(MCDevBundle("creator.ui.parchment.include.snapshots.label"))
151+
.enabledIf(useParchmentProperty)
152+
.bindSelected(includeSnapshotsVersionsProperty)
153+
}
154+
}
155+
156+
super.setupUI(builder)
157+
}
158+
159+
override fun setupProject(project: Project) {
160+
data.putUserData(USE_KEY, useParchment)
161+
data.putUserData(VERSION_KEY, parchmentVersion)
162+
}
163+
164+
companion object {
165+
val USE_KEY = Key.create<Boolean>("${ParchmentStep::class.java.name}.useParchment")
166+
val VERSION_KEY = Key.create<ParchmentVersion>("${ParchmentStep::class.java}.parchmentVersion")
167+
}
168+
}

0 commit comments

Comments
 (0)