User: kyle wood Date: 21 Jul 26 01:26 Revision: 8c46fc74c8c2c6858fffb28de78bdffed40977fa Summary: Migrate all Groovy code to Java Fixes #2632 TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10589&personal=false Index: build.gradle.kts =================================================================== --- build.gradle.kts (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ build.gradle.kts (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -26,11 +26,9 @@ import org.jetbrains.gradle.ext.settings import org.jetbrains.gradle.ext.taskTriggers import org.jetbrains.intellij.platform.gradle.TestFrameworkType -import org.jetbrains.intellij.platform.gradle.tasks.CleanSandboxTask import org.jetbrains.intellij.platform.gradle.tasks.PrepareSandboxTask plugins { - groovy id(libs.plugins.changelog.get().pluginId) alias(libs.plugins.idea.ext) `mcdev-core` @@ -152,9 +150,6 @@ } testLibs(projects.mixinTestData) - // For non-SNAPSHOT versions (unless Jetbrains fixes this...) find the version with: - // afterEvaluate { println(intellijPlatform.productInfo.buildNumber) } - gradleToolingExtension(libs.groovy) gradleToolingExtension(libs.gradleToolingExtension) gradleToolingExtension(libs.annotations) } @@ -187,11 +182,6 @@ options.release = 8 options.compilerArgs = listOf("-Xlint:-options") } -tasks.withType().configureEach { - options.compilerArgs = listOf("-proc:none") - sourceCompatibility = "1.8" - targetCompatibility = "1.8" -} tasks.processResources { // These templates aren't allowed to be in a directory structure in the output jar @@ -262,7 +252,7 @@ } license { - val endings = listOf("java", "kt", "kts", "groovy", "gradle.kts", "xml", "properties", "html", "flex", "bnf") + val endings = listOf("java", "kt", "kts", "gradle.kts", "xml", "properties", "html", "flex", "bnf") exclude("META-INF/plugin.xml") // https://youtrack.jetbrains.com/issue/IDEA-345026 exclude("sentry-debug-meta.properties", "sentry-external-modules.txt") include(endings.map { "**/*.$it" }) Index: buildSrc/src/main/kotlin/mcdev-core.gradle.kts =================================================================== --- buildSrc/src/main/kotlin/mcdev-core.gradle.kts (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ buildSrc/src/main/kotlin/mcdev-core.gradle.kts (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -159,7 +159,7 @@ style["flex"] = HeaderStyle.BLOCK_COMMENT.format style["bnf"] = HeaderStyle.BLOCK_COMMENT.format - val endings = listOf("java", "kt", "kts", "groovy", "gradle.kts", "xml", "properties", "html", "flex", "bnf") + val endings = listOf("java", "kt", "kts", "gradle.kts", "xml", "properties", "html", "flex", "bnf") include(endings.map { "**/*.$it" }) } Index: gradle/libs.versions.toml =================================================================== --- gradle/libs.versions.toml (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ gradle/libs.versions.toml (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -53,7 +53,6 @@ # Search for com.jetbrains.intellij.gradle gradleToolingExtension = { module = "com.jetbrains.intellij.gradle:gradle-tooling-extension", version = "253.29346.138" } annotations = "org.jetbrains:annotations:26.1.0" -groovy = "org.codehaus.groovy:groovy:3.0.25" asm = { module = "org.ow2.asm:asm", version.ref = "asm" } asm-tree = { module = "org.ow2.asm:asm-tree", version.ref = "asm" } Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,57 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling - -import org.gradle.api.Project -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.ModelBuilderService - -final class McpModelFG2BuilderImpl implements ModelBuilderService { - - @Override - boolean canBuild(String modelName) { - return McpModelFG2.name == modelName - } - - @Override - Object buildAll(String modelName, Project project) { - def extension = project.extensions.findByName('minecraft') - if (extension == null) { - return null - } - - if (project.tasks.findByName("genSrgs") == null) { - return null - } - - // FG2 - def mappingFiles = project.tasks.genSrgs.outputs.files.files.collect { it.absolutePath } - return new McpModelFG2Impl(extension.version, extension.mappings, mappingFiles.toSet()) - } - - @Override - ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { - return ErrorMessageBuilder.create( - project, e, "MinecraftDev import errors" - ).withDescription("Unable to build MinecraftDev MCP project configuration") - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,37 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling - -import groovy.transform.CompileStatic - -@CompileStatic -final class McpModelFG2Impl implements McpModelFG2, Serializable { - - final String minecraftVersion - final String mcpVersion - final Set mappingFiles - - McpModelFG2Impl(String minecraftVersion, String mcpVersion, Set mappingFiles) { - this.minecraftVersion = minecraftVersion - this.mcpVersion = mcpVersion - this.mappingFiles = mappingFiles - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,83 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling - -import org.gradle.api.Project -import org.gradle.api.file.FileCollection -import org.gradle.api.provider.Provider -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.ModelBuilderService - -final class McpModelFG3BuilderImpl implements ModelBuilderService { - - @Override - boolean canBuild(String modelName) { - return McpModelFG3.name == modelName - } - - @Override - Object buildAll(String modelName, Project project) { - def extension = project.extensions.findByName('minecraft') - if (extension == null) { - return null - } - - if (!project.plugins.findPlugin("net.minecraftforge.gradle")) { - return null - } - - // FG3 userdev - def minecraftDepVersions = project.configurations.minecraft.dependencies.collect { it.version } - - // For some reason this task has had 2 different names... - def task = project.tasks.findByName("createMcpToSrg") - if (task == null) { - task = project.tasks.findByName("createMcp2Srg") - } - if (task == null) { - return null - } - - def taskOutput = task.outputs.files.singleFile - - // Cheap way to be compatible with FG5 - def mappings = extension.mappings - if (mappings instanceof Provider) { - mappings = mappings.get() - } - - def accessTransformers = extension.accessTransformers - if (accessTransformers instanceof FileCollection) { - accessTransformers = accessTransformers.asList() - } - - //noinspection GroovyAssignabilityCheck - return new McpModelFG3Impl(minecraftDepVersions, mappings, taskOutput, task.name, accessTransformers) - } - - @Override - ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { - return ErrorMessageBuilder.create( - project, e, "MinecraftDev import errors" - ).withDescription("Unable to build MinecraftDev MCP project configuration") - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,47 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling - -import groovy.transform.CompileStatic - -@CompileStatic -final class McpModelFG3Impl implements McpModelFG3, Serializable { - - final List minecraftDepVersions - final String mcpVersion - final File taskOutputLocation - final String taskName - final List accessTransformers - - McpModelFG3Impl( - final List minecraftDepVersions, - final String mcpVersion, - final File taskOutputLocation, - final String taskName, - final List accessTransformers - ) { - this.minecraftDepVersions = minecraftDepVersions - this.mcpVersion = mcpVersion - this.taskOutputLocation = taskOutputLocation - this.taskName = taskName - this.accessTransformers = accessTransformers - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,51 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom - -import org.gradle.api.Project -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.ModelBuilderService - -class ArchitecturyModelBuilderImpl implements ModelBuilderService { - boolean canBuild(String modelName) { - return ArchitecturyModel.name == modelName - } - - Object buildAll(String modelName, Project project) { - def moduleType = ArchitecturyModel.ModuleType.NONE - if (project.getPluginManager().hasPlugin('architectury-plugin')) { - if (project.configurations.findByName('transformProductionFabric') != null) { - moduleType = ArchitecturyModel.ModuleType.COMMON - } else { - moduleType = ArchitecturyModel.ModuleType.PLATFORM_SPECIFIC - } - } - - return new ArchitecturyModelImpl(moduleType) - } - - ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { - return ErrorMessageBuilder.create( - project, e, "MinecraftDev import errors" - ).withDescription("Unable to build MinecraftDev ArchitecturyLoom project configuration") - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,33 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom - -class ArchitecturyModelImpl implements ArchitecturyModel, Serializable { - private final ModuleType moduleType; - - ArchitecturyModelImpl(ModuleType moduleType) { - this.moduleType = moduleType - } - - ModuleType getModuleType() { - return moduleType - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,112 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom - -import org.gradle.api.Project -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.gradle.tooling.AbstractModelBuilderService -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.Message -import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext - -class FabricLoomModelBuilderImpl extends AbstractModelBuilderService { - - @Override - boolean canBuild(String modelName) { - return FabricLoomModel.name == modelName - } - - @Override - Object buildAll(@NotNull String modelName, @NotNull Project project, @NotNull ModelBuilderContext context) { - if (!project.plugins.hasPlugin('fabric-loom')) { - return null - } - - def loomExtension = project.extensions.getByName('loom') - - try { - return build(project, loomExtension) - } catch (GroovyRuntimeException ex) { - context.messageReporter.createMessage() - .withTitle("Minecraft Dev - Loom importing error") - .withText("An error occurred while importing Loom data, falling back to legacy import") - .withGroup("com.demonwav.mcdev") - .withKind(Message.Kind.WARNING) - .withStackTrace() - .withException(ex) - .reportMessage(project) - - // Must be using an older loom version, fallback. - return buildLegacy(project, loomExtension) - } - } - - FabricLoomModel build(Project project, Object loomExtension) { - def minecraftVersion = loomExtension.minecraftProvider.minecraftVersion() - def tinyMappings = loomExtension.hasProperty("mappingsFile") ? loomExtension.mappingsFile : null - def splitMinecraftJar = loomExtension.areEnvironmentSourceSetsSplit() - - def decompilers = [:] - - if (splitMinecraftJar) { - decompilers << ["common": getDecompilers(loomExtension, false)] - decompilers << ["client": getDecompilers(loomExtension, true)] - } else { - decompilers << ["single": getDecompilers(loomExtension, false)] - } - - //noinspection GroovyAssignabilityCheck - return new FabricLoomModelImpl(minecraftVersion, tinyMappings, decompilers, splitMinecraftJar) - } - - List getDecompilers(Object loomExtension, boolean client) { - loomExtension.decompilerOptions.collect { - def task = loomExtension.getDecompileTask(it, client) - def sourcesPath - if (task.hasProperty("outputJar")) { - // Pre 1.8 - sourcesPath = task.outputJar.get().getAsFile().getAbsolutePath() - } else { - sourcesPath = task.sourcesOutputJar.get().getAsFile().getAbsolutePath() - } - new FabricLoomModelImpl.DecompilerModelImpl(name: it.name, taskName: task.name, sourcesPath: sourcesPath) - } - } - - FabricLoomModel buildLegacy(Project project, Object loomExtension) { - def tinyMappings = loomExtension.mappingsProvider.tinyMappings.toFile().getAbsoluteFile() - def decompilers = loomExtension.decompilerOptions.collect { - def task = project.tasks.getByName('genSourcesWith' + it.name.capitalize()) - def sourcesPath = task.runtimeJar.get().getAsFile().getAbsolutePath().dropRight(4) + "-sources.jar" - new FabricLoomModelImpl.DecompilerModelImpl(name: it.name, taskName: task.name, sourcesPath: sourcesPath) - } - - //noinspection GroovyAssignabilityCheck - return new FabricLoomModelImpl(tinyMappings, ["single": decompilers], false) - } - - @Override - ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { - return ErrorMessageBuilder.create( - project, e, "MinecraftDev import errors" - ).withDescription("Unable to build MinecraftDev FabricLoom project configuration") - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,40 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom - -import groovy.transform.Immutable -import org.jetbrains.annotations.Nullable - -@Immutable(knownImmutableClasses = [File]) -class FabricLoomModelImpl implements FabricLoomModel, Serializable { - String minecraftVersion - @Nullable - File tinyMappings - Map> decompilers - boolean splitMinecraftJar - - @Immutable - static class DecompilerModelImpl implements DecompilerModel, Serializable { - String name - String taskName - String sourcesPath - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,72 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle - -import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7 -import org.gradle.api.Project -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.ModelBuilderService - -final class NeoGradle7ModelBuilderImpl implements ModelBuilderService { - - @Override - boolean canBuild(String modelName) { - return McpModelNG7.name == modelName - } - - @Override - Object buildAll(String modelName, Project project) { - def extension = project.extensions.findByName('minecraft') - if (extension == null) { - return null - } - - if (!project.plugins.findPlugin("net.neoforged.gradle.userdev")) { - return null - } - - // NG userdev - def runtimes = project.extensions.findByName('userDevRuntime').runtimes.get() - def neoforgeVersion = null - for (def entry in runtimes) { - neoforgeVersion = entry.value.specification.forgeVersion - break - } - if (neoforgeVersion == null) { - return null - } - - def mappingsFile = project.tasks.neoFormMergeMappings.output.get().asFile - - def accessTransformers = extension.accessTransformers.files.asList() - - //noinspection GroovyAssignabilityCheck - return new NeoGradle7ModelImpl(neoforgeVersion, mappingsFile, accessTransformers) - } - - @Override - ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { - return ErrorMessageBuilder.create( - project, e, "MinecraftDev import errors" - ).withDescription("Unable to build MinecraftDev MCP project configuration") - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,43 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle - - -import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7 -import groovy.transform.CompileStatic - -@CompileStatic -final class NeoGradle7ModelImpl implements McpModelNG7, Serializable { - - final String neoForgeVersion - final File mappingsFile - final List accessTransformers - - NeoGradle7ModelImpl( - final String neoForgeVersion, - final File mappingsFile, - final List accessTransformers - ) { - this.neoForgeVersion = neoForgeVersion - this.mappingsFile = mappingsFile - this.accessTransformers = accessTransformers - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,113 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev - -import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD -import org.gradle.api.InvalidUserCodeException -import org.gradle.api.Project -import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Provider -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.ModelBuilderService - -import java.nio.file.Files - -final class NeoModDevGradleModelBuilderImpl implements ModelBuilderService { - - @Override - boolean canBuild(String modelName) { - return McpModelNMD.name == modelName - } - - @Override - Object buildAll(String modelName, Project project) { - def extension = project.extensions.findByName('neoForge') - if (extension == null) { - return null - } - - if (!project.plugins.findPlugin("net.neoforged.moddev")) { - return null - } - - def neoFormVersion - try { - def neoFormVersionProp = extension.neoFormVersion - if (neoFormVersionProp instanceof String) { - neoFormVersion = neoFormVersionProp - } else if (neoFormVersionProp instanceof Provider) { - neoFormVersion = neoFormVersionProp.getOrNull() - } else { - neoFormVersion = null - } - } catch (InvalidUserCodeException ignore) { - // Happens when the NeoForm version is not set - neoFormVersion = null - } - - def neoforgeVersion - if (neoFormVersion != null) { - neoforgeVersion = null - } else { - def neoforgeVersionProp = extension.version - - if (neoforgeVersionProp instanceof String) { - neoforgeVersion = neoforgeVersionProp - } else if (neoforgeVersionProp instanceof Provider) { - neoforgeVersion = neoforgeVersionProp.getOrNull() - } else { - return null - } - } - - def accessTransformersRaw = extension.accessTransformers - List accessTransformers - if (accessTransformersRaw instanceof ListProperty) { - accessTransformers = accessTransformersRaw.get().collect { project.file(it) } - } else { - accessTransformers = accessTransformersRaw.files.files.toList() - } - - File mappingsFile = null - try { - // Hacky way to guess where the mappings file is, but I could not find a proper way to find it - def neoformDir = project.buildDir.toPath().resolve("neoForm") - mappingsFile = Files.list(neoformDir) - .map { it.resolve("config/joined.tsrg") } - .filter { Files.exists(it) } - .findFirst() - .orElse(null) - ?.toFile() - } catch (Exception ignore) { - } - - //noinspection GroovyAssignabilityCheck - return new NeoModDevGradleModelImpl(neoforgeVersion, neoFormVersion, mappingsFile, accessTransformers) - } - - @Override - ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { - return ErrorMessageBuilder.create( - project, e, "MinecraftDev import errors" - ).withDescription("Unable to build MinecraftDev MCP project configuration") - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,33 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev - -import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD -import groovy.transform.Immutable - -@Immutable(knownImmutableClasses = [File]) -final class NeoModDevGradleModelImpl implements McpModelNMD, Serializable { - - final String neoForgeVersion - final String neoFormVersion - final File mappingsFile - final List accessTransformers -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,46 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle - -import org.gradle.api.Project -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.ModelBuilderService - -class VanillaGradleModelBuilderImpl implements ModelBuilderService { - - @Override - boolean canBuild(String modelName) { - return VanillaGradleModel.name == modelName - } - - @Override - Object buildAll(String modelName, Project project) { - return new VanillaGradleModelImpl(project.plugins.hasPlugin('org.spongepowered.gradle.vanilla')) - } - - @Override - ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { - return ErrorMessageBuilder.create( - project, e, "MinecraftDev import errors" - ).withDescription("Unable to build MinecraftDev VanillaGradle project configuration") - } -} Index: src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.groovy =================================================================== --- src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) +++ src/gradle-tooling-extension/groovy/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.groovy (revision 6fb48881d9a7d2e08026a66efa3e480370fa5054) @@ -1,35 +0,0 @@ -/* - * 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 . - */ - -package com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle - -class VanillaGradleModelImpl implements VanillaGradleModel, Serializable { - - private final boolean hasVanillaGradle - - VanillaGradleModelImpl(boolean hasVanillaGradle) { - this.hasVanillaGradle = hasVanillaGradle - } - - @Override - boolean hasVanillaGradle() { - return hasVanillaGradle - } -} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,85 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.tooling.Message; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; + +public final class McpModelFG2BuilderImpl implements ModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return McpModelFG2.class.getName().equals(modelName); + } + + @Override + public Object buildAll(String modelName, Project project) { + Object extension = project.getExtensions().findByName("minecraft"); + if (extension == null) { + return null; + } + + Task genSrgs = project.getTasks().findByName("genSrgs"); + if (genSrgs == null) { + return null; + } + + try { + String version = (String) ReflectUtil.getProperty(extension, "version"); + String mappings = (String) ReflectUtil.getProperty(extension, "mappings"); + + Set files = genSrgs.getOutputs().getFiles().getFiles(); + Set mappingFiles = new HashSet<>(); + for (File file : files) { + mappingFiles.add(file.getAbsolutePath()); + } + return new McpModelFG2Impl(version, mappings, mappingFiles); + } catch (Exception e) { + return null; + } + } + + @Override + public void reportErrorMessage( + final @NotNull String modelName, + final @NotNull Project project, + final @NotNull ModelBuilderContext context, + final @NotNull Exception exception + ) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup(this) + .withKind(Message.Kind.ERROR) + .withGroup("com.demonwav.mcdev") + .withTitle("MinecraftDev: ForgeGradle import error") + .withText("Unable to build MinecraftDev ForgeGradle model for project " + project.getDisplayName()) + .withException(exception) + .reportMessage(project); + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,51 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling; + +import java.util.Set; + +final class McpModelFG2Impl implements McpModelFG2, java.io.Serializable { + + private final String minecraftVersion; + private final String mcpVersion; + private final Set mappingFiles; + + McpModelFG2Impl(String minecraftVersion, String mcpVersion, Set mappingFiles) { + this.minecraftVersion = minecraftVersion; + this.mcpVersion = mcpVersion; + this.mappingFiles = mappingFiles; + } + + @Override + public String getMinecraftVersion() { + return minecraftVersion; + } + + @Override + public String getMcpVersion() { + return mcpVersion; + } + + @Override + public Set getMappingFiles() { + return mappingFiles; + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,121 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling; + +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.file.FileCollection; +import org.gradle.api.provider.Provider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.tooling.Message; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public final class McpModelFG3BuilderImpl implements ModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return McpModelFG3.class.getName().equals(modelName); + } + + @Override + public Object buildAll(String modelName, Project project) { + Object extension = project.getExtensions().findByName("minecraft"); + if (extension == null) { + return null; + } + + if (project.getPlugins().findPlugin("net.minecraftforge.gradle") == null) { + return null; + } + + List minecraftDepVersions = new ArrayList<>(); + Configuration minecraftConfig = project.getConfigurations().findByName("minecraft"); + if (minecraftConfig != null) { + for (Dependency dep : minecraftConfig.getDependencies()) { + minecraftDepVersions.add(dep.getVersion()); + } + } + + Task task = project.getTasks().findByName("createMcpToSrg"); + if (task == null) { + task = project.getTasks().findByName("createMcp2Srg"); + } + if (task == null) { + return null; + } + + File taskOutput = task.getOutputs().getFiles().getSingleFile(); + + String mappings = null; + try { + Object mappingsObj = ReflectUtil.getProperty(extension, "mappings"); + if (mappingsObj instanceof Provider) { + mappingsObj = ((Provider) mappingsObj).get(); + } + if (mappingsObj != null) { + mappings = mappingsObj.toString(); + } + } catch (Exception ignored) { + } + + List accessTransformers = new ArrayList<>(); + try { + Object atObj = ReflectUtil.getProperty(extension, "accessTransformers"); + if (atObj instanceof FileCollection) { + accessTransformers.addAll(((FileCollection) atObj).getFiles()); + } else if (atObj instanceof Iterable) { + for (Object item : (Iterable) atObj) { + if (item instanceof File) { + accessTransformers.add((File) item); + } + } + } + } catch (Exception ignored) { + } + + return new McpModelFG3Impl(minecraftDepVersions, mappings, taskOutput, task.getName(), accessTransformers); + } + + @Override + public void reportErrorMessage( + final @NotNull String modelName, + final @NotNull Project project, + final @NotNull ModelBuilderContext context, + final @NotNull Exception exception + ) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup(this) + .withKind(Message.Kind.ERROR) + .withGroup("com.demonwav.mcdev") + .withTitle("MinecraftDev: ForgeGradle import error") + .withText("Unable to build MinecraftDev ForgeGradle model for project " + project.getDisplayName()) + .withException(exception) + .reportMessage(project); + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,72 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling; + +import java.io.File; +import java.util.List; + +final class McpModelFG3Impl implements McpModelFG3, java.io.Serializable { + + private final List minecraftDepVersions; + private final String mcpVersion; + private final File taskOutputLocation; + private final String taskName; + private final List accessTransformers; + + McpModelFG3Impl( + List minecraftDepVersions, + String mcpVersion, + File taskOutputLocation, + String taskName, + List accessTransformers + ) { + this.minecraftDepVersions = minecraftDepVersions; + this.mcpVersion = mcpVersion; + this.taskOutputLocation = taskOutputLocation; + this.taskName = taskName; + this.accessTransformers = accessTransformers; + } + + @Override + public List getMinecraftDepVersions() { + return minecraftDepVersions; + } + + @Override + public String getMcpVersion() { + return mcpVersion; + } + + @Override + public File getTaskOutputLocation() { + return taskOutputLocation; + } + + @Override + public String getTaskName() { + return taskName; + } + + @Override + public List getAccessTransformers() { + return accessTransformers; + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/ReflectUtil.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/ReflectUtil.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/ReflectUtil.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,155 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public final class ReflectUtil { + + private ReflectUtil() { + } + + public static Object getProperty(Object obj, String name) throws Exception { + if (obj == null) { + return null; + } + Class clazz = obj.getClass(); + String capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1); + + // Try getProperty() + try { + Method m = clazz.getMethod("get" + capitalized); + m.setAccessible(true); + return m.invoke(obj); + } catch (NoSuchMethodException ignored) { + } + + // Try isProperty() + try { + Method m = clazz.getMethod("is" + capitalized); + m.setAccessible(true); + return m.invoke(obj); + } catch (NoSuchMethodException ignored) { + } + + // Try property() + try { + Method m = clazz.getMethod(name); + m.setAccessible(true); + return m.invoke(obj); + } catch (NoSuchMethodException ignored) { + } + + // Try field + try { + Field f = clazz.getField(name); + f.setAccessible(true); + return f.get(obj); + } catch (NoSuchFieldException ignored) { + } + + throw new NoSuchMethodException("Could not find property or method '" + name + "' on " + clazz); + } + + public static boolean hasProperty(Object obj, String name) { + if (obj == null) { + return false; + } + Class clazz = obj.getClass(); + String capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1); + + try { + clazz.getMethod("get" + capitalized); + return true; + } catch (NoSuchMethodException ignored) { + } + + try { + clazz.getMethod("is" + capitalized); + return true; + } catch (NoSuchMethodException ignored) { + } + + try { + clazz.getMethod(name); + return true; + } catch (NoSuchMethodException ignored) { + } + + try { + clazz.getField(name); + return true; + } catch (NoSuchFieldException ignored) { + } + + return false; + } + + public static Object callMethod(Object obj, String methodName, Object... args) throws Exception { + if (obj == null) { + return null; + } + Class clazz = obj.getClass(); + Method bestMatch = null; + for (Method method : clazz.getMethods()) { + if (method.getName().equals(methodName) && method.getParameterCount() == args.length) { + if (isCompatible(method.getParameterTypes(), args)) { + bestMatch = method; + break; + } + } + } + if (bestMatch == null) { + throw new NoSuchMethodException("No compatible method " + methodName + " with " + args.length + " arguments found on " + clazz); + } + bestMatch.setAccessible(true); + return bestMatch.invoke(obj, args); + } + + private static boolean isCompatible(Class[] parameterTypes, Object[] args) { + for (int i = 0; i < parameterTypes.length; i++) { + Object arg = args[i]; + Class paramType = parameterTypes[i]; + if (arg == null) { + if (paramType.isPrimitive()) { + return false; + } + continue; + } + if (paramType.isPrimitive()) { + if (paramType == boolean.class && arg instanceof Boolean) continue; + if (paramType == int.class && arg instanceof Integer) continue; + if (paramType == long.class && arg instanceof Long) continue; + if (paramType == double.class && arg instanceof Double) continue; + if (paramType == float.class && arg instanceof Float) continue; + if (paramType == char.class && arg instanceof Character) continue; + if (paramType == byte.class && arg instanceof Byte) continue; + if (paramType == short.class && arg instanceof Short) continue; + return false; + } + if (!paramType.isInstance(arg)) { + return false; + } + } + return true; + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,67 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom; + +import org.gradle.api.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.tooling.Message; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; + +public final class ArchitecturyModelBuilderImpl implements ModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return ArchitecturyModel.class.getName().equals(modelName); + } + + @Override + public Object buildAll(String modelName, Project project) { + ArchitecturyModel.ModuleType moduleType = ArchitecturyModel.ModuleType.NONE; + if (project.getPluginManager().hasPlugin("architectury-plugin")) { + if (project.getConfigurations().findByName("transformProductionFabric") != null) { + moduleType = ArchitecturyModel.ModuleType.COMMON; + } else { + moduleType = ArchitecturyModel.ModuleType.PLATFORM_SPECIFIC; + } + } + + return new ArchitecturyModelImpl(moduleType); + } + + @Override + public void reportErrorMessage( + final @NotNull String modelName, + final @NotNull Project project, + final @NotNull ModelBuilderContext context, + final @NotNull Exception exception + ) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup(this) + .withKind(Message.Kind.ERROR) + .withGroup("com.demonwav.mcdev") + .withTitle("MinecraftDev: ArchitecturyLoom import error") + .withText("Unable to build MinecraftDev ArchitecturyLoom model for project " + project.getDisplayName()) + .withException(exception) + .reportMessage(project); + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,36 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom; + +import java.io.Serializable; + +final class ArchitecturyModelImpl implements ArchitecturyModel, Serializable { + private final ModuleType moduleType; + + ArchitecturyModelImpl(ModuleType moduleType) { + this.moduleType = moduleType; + } + + @Override + public ModuleType getModuleType() { + return moduleType; + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,187 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom; + +import com.demonwav.mcdev.platform.mcp.gradle.tooling.ReflectUtil; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.gradle.api.Project; +import org.gradle.api.provider.Provider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.tooling.AbstractModelBuilderService; +import org.jetbrains.plugins.gradle.tooling.Message; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext; + +public final class FabricLoomModelBuilderImpl extends AbstractModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return FabricLoomModel.class.getName().equals(modelName); + } + + @Override + public Object buildAll(@NotNull String modelName, @NotNull Project project, @NotNull ModelBuilderContext context) { + if (!project.getPlugins().hasPlugin("fabric-loom")) { + return null; + } + + Object loomExtension = project.getExtensions().getByName("loom"); + + try { + return build(project, loomExtension); + } catch (Exception ex) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup("com.demonwav.mcdev") + .withTitle("Minecraft Dev: Loom import error") + .withText("An error occurred while importing Loom data, falling back to legacy import") + .withKind(Message.Kind.WARNING) + .withStackTrace() + .withException(ex) + .reportMessage(project); + + try { + // Must be using an older loom version, fallback. + return buildLegacy(project, loomExtension); + } catch (Exception fallbackEx) { + // Return null if even legacy fallback fails + return null; + } + } + } + + private FabricLoomModel build(Project project, Object loomExtension) throws Exception { + Object minecraftProvider = ReflectUtil.getProperty(loomExtension, "minecraftProvider"); + String minecraftVersion = (String) ReflectUtil.callMethod(minecraftProvider, "minecraftVersion"); + + File tinyMappings = null; + if (ReflectUtil.hasProperty(loomExtension, "mappingsFile")) { + Object mappingsFileObj = ReflectUtil.getProperty(loomExtension, "mappingsFile"); + if (mappingsFileObj instanceof Provider) { + mappingsFileObj = ((Provider) mappingsFileObj).getOrNull(); + } + if (mappingsFileObj instanceof File) { + tinyMappings = (File) mappingsFileObj; + } else if (mappingsFileObj != null) { + tinyMappings = project.file(mappingsFileObj); + } + } + + boolean splitMinecraftJar = (Boolean) ReflectUtil.callMethod(loomExtension, "areEnvironmentSourceSetsSplit"); + + Map> decompilers = new HashMap<>(); + + if (splitMinecraftJar) { + decompilers.put("common", getDecompilers(loomExtension, false)); + decompilers.put("client", getDecompilers(loomExtension, true)); + } else { + decompilers.put("single", getDecompilers(loomExtension, false)); + } + + return new FabricLoomModelImpl(minecraftVersion, tinyMappings, decompilers, splitMinecraftJar); + } + + private List getDecompilers(Object loomExtension, boolean client) throws Exception { + Object decompilerOptions = ReflectUtil.getProperty(loomExtension, "decompilerOptions"); + List result = new ArrayList<>(); + if (decompilerOptions instanceof Iterable) { + for (Object option : (Iterable) decompilerOptions) { + Object task = ReflectUtil.callMethod(loomExtension, "getDecompileTask", option, client); + String sourcesPath; + if (ReflectUtil.hasProperty(task, "outputJar")) { + // Pre 1.8 + Object outputJar = ReflectUtil.getProperty(task, "outputJar"); + if (outputJar instanceof Provider) { + outputJar = ((Provider) outputJar).get(); + } + sourcesPath = ((File) ReflectUtil.callMethod(outputJar, "getAsFile")).getAbsolutePath(); + } else { + Object sourcesOutputJar = ReflectUtil.getProperty(task, "sourcesOutputJar"); + if (sourcesOutputJar instanceof Provider) { + sourcesOutputJar = ((Provider) sourcesOutputJar).get(); + } + sourcesPath = ((File) ReflectUtil.callMethod(sourcesOutputJar, "getAsFile")).getAbsolutePath(); + } + String name = (String) ReflectUtil.getProperty(option, "name"); + String taskName = (String) ReflectUtil.getProperty(task, "name"); + result.add(new FabricLoomModelImpl.DecompilerModelImpl(name, taskName, sourcesPath)); + } + } + return result; + } + + private FabricLoomModel buildLegacy(Project project, Object loomExtension) throws Exception { + Object mappingsProvider = ReflectUtil.getProperty(loomExtension, "mappingsProvider"); + Object tinyMappingsObj = ReflectUtil.getProperty(mappingsProvider, "tinyMappings"); + File tinyMappings = null; + if (tinyMappingsObj instanceof File) { + tinyMappings = ((File) tinyMappingsObj).getAbsoluteFile(); + } else if (tinyMappingsObj != null) { + tinyMappings = project.file(tinyMappingsObj).getAbsoluteFile(); + } + + Object decompilerOptions = ReflectUtil.getProperty(loomExtension, "decompilerOptions"); + List decompilers = new ArrayList<>(); + if (decompilerOptions instanceof Iterable) { + for (Object option : (Iterable) decompilerOptions) { + String optionName = (String) ReflectUtil.getProperty(option, "name"); + String capitalized = Character.toUpperCase(optionName.charAt(0)) + optionName.substring(1); + Object task = project.getTasks().getByName("genSourcesWith" + capitalized); + + Object runtimeJar = ReflectUtil.getProperty(task, "runtimeJar"); + if (runtimeJar instanceof Provider) { + runtimeJar = ((Provider) runtimeJar).get(); + } + File runtimeJarFile = (File) ReflectUtil.callMethod(runtimeJar, "getAsFile"); + String runtimeJarPath = runtimeJarFile.getAbsolutePath(); + String sourcesPath = runtimeJarPath.substring(0, runtimeJarPath.length() - 4) + "-sources.jar"; + + String taskName = (String) ReflectUtil.getProperty(task, "name"); + decompilers.add(new FabricLoomModelImpl.DecompilerModelImpl(optionName, taskName, sourcesPath)); + } + } + + Map> decompilersMap = new HashMap<>(); + decompilersMap.put("single", decompilers); + return new FabricLoomModelImpl(tinyMappings, decompilersMap, false); + } + + @Override + public void reportErrorMessage( + final @NotNull String modelName, + final @NotNull Project project, + final @NotNull ModelBuilderContext context, + final @NotNull Exception exception + ) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup(this) + .withKind(Message.Kind.ERROR) + .withGroup("com.demonwav.mcdev") + .withTitle("MinecraftDev: Loom import error") + .withText("Unable to build MinecraftDev FabricLoom model for project " + project.getDisplayName()) + .withException(exception) + .reportMessage(project); + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,104 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom; + +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +public final class FabricLoomModelImpl implements FabricLoomModel, Serializable { + + private final String minecraftVersion; + private final File tinyMappings; + private final Map> decompilers; + private final boolean splitMinecraftJar; + + public FabricLoomModelImpl( + String minecraftVersion, + @Nullable File tinyMappings, + Map> decompilers, + boolean splitMinecraftJar + ) { + this.minecraftVersion = minecraftVersion; + this.tinyMappings = tinyMappings; + this.decompilers = decompilers; + this.splitMinecraftJar = splitMinecraftJar; + } + + public FabricLoomModelImpl( + @Nullable File tinyMappings, + Map> decompilers, + boolean splitMinecraftJar + ) { + this(null, tinyMappings, decompilers, splitMinecraftJar); + } + + @Override + public String getMinecraftVersion() { + return minecraftVersion; + } + + @Override + @Nullable + public File getTinyMappings() { + return tinyMappings; + } + + @Override + public Map> getDecompilers() { + return decompilers; + } + + @Override + public boolean getSplitMinecraftJar() { + return splitMinecraftJar; + } + + public static final class DecompilerModelImpl implements DecompilerModel, Serializable { + private final String name; + private final String taskName; + private final String sourcesPath; + + public DecompilerModelImpl(String name, String taskName, String sourcesPath) { + this.name = name; + this.taskName = taskName; + this.sourcesPath = sourcesPath; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getTaskName() { + return taskName; + } + + @Override + public String getSourcesPath() { + return sourcesPath; + } + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,142 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle; + +import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7; +import com.demonwav.mcdev.platform.mcp.gradle.tooling.ReflectUtil; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; +import org.gradle.api.provider.Provider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.tooling.Message; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; + +public final class NeoGradle7ModelBuilderImpl implements ModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return McpModelNG7.class.getName().equals(modelName); + } + + @Override + public Object buildAll(String modelName, Project project) { + Object extension = project.getExtensions().findByName("minecraft"); + if (extension == null) { + return null; + } + + if (project.getPlugins().findPlugin("net.neoforged.gradle.userdev") == null) { + return null; + } + + Object userDevRuntime = project.getExtensions().findByName("userDevRuntime"); + if (userDevRuntime == null) { + return null; + } + + String neoforgeVersion = null; + try { + Object runtimesObj = ReflectUtil.getProperty(userDevRuntime, "runtimes"); + if (runtimesObj instanceof Provider) { + runtimesObj = ((Provider) runtimesObj).get(); + } + if (runtimesObj instanceof Map) { + for (Map.Entry entry : ((Map) runtimesObj).entrySet()) { + Object val = entry.getValue(); + Object spec = ReflectUtil.getProperty(val, "specification"); + Object forgeVersion = ReflectUtil.getProperty(spec, "forgeVersion"); + if (forgeVersion != null) { + neoforgeVersion = forgeVersion.toString(); + break; + } + } + } + } catch (Exception ignored) { + } + + if (neoforgeVersion == null) { + return null; + } + + Task neoFormMergeMappings = project.getTasks().findByName("neoFormMergeMappings"); + if (neoFormMergeMappings == null) { + return null; + } + + File mappingsFile = null; + try { + Object output = ReflectUtil.getProperty(neoFormMergeMappings, "output"); + if (output instanceof Provider) { + output = ((Provider) output).get(); + } + if (output instanceof File) { + mappingsFile = (File) output; + } else if (output != null) { + mappingsFile = (File) ReflectUtil.callMethod(output, "getAsFile"); + } + } catch (Exception ignored) { + } + + List accessTransformers = new ArrayList<>(); + try { + Object atObj = ReflectUtil.getProperty(extension, "accessTransformers"); + if (atObj instanceof FileCollection) { + accessTransformers.addAll(((FileCollection) atObj).getFiles()); + } else if (atObj != null) { + Object filesObj = ReflectUtil.getProperty(atObj, "files"); + if (filesObj instanceof Iterable) { + for (Object file : (Iterable) filesObj) { + if (file instanceof File) { + accessTransformers.add((File) file); + } + } + } + } + } catch (Exception ignored) { + } + + return new NeoGradle7ModelImpl(neoforgeVersion, mappingsFile, accessTransformers); + } + + @Override + public void reportErrorMessage( + final @NotNull String modelName, + final @NotNull Project project, + final @NotNull ModelBuilderContext context, + final @NotNull Exception exception + ) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup(this) + .withKind(Message.Kind.ERROR) + .withGroup("com.demonwav.mcdev") + .withTitle("MinecraftDev: NeoGradle import error") + .withText("Unable to build MinecraftDev NeoGradle model for project " + project.getDisplayName()) + .withException(exception) + .reportMessage(project); + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,58 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle; + +import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7; +import java.io.File; +import java.io.Serializable; +import java.util.List; + +final class NeoGradle7ModelImpl implements McpModelNG7, Serializable { + + private final String neoForgeVersion; + private final File mappingsFile; + private final List accessTransformers; + + NeoGradle7ModelImpl( + String neoForgeVersion, + File mappingsFile, + List accessTransformers + ) { + this.neoForgeVersion = neoForgeVersion; + this.mappingsFile = mappingsFile; + this.accessTransformers = accessTransformers; + } + + @Override + public String getNeoForgeVersion() { + return neoForgeVersion; + } + + @Override + public File getMappingsFile() { + return mappingsFile; + } + + @Override + public List getAccessTransformers() { + return accessTransformers; + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,149 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev; + +import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD; +import com.demonwav.mcdev.platform.mcp.gradle.tooling.ReflectUtil; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; +import org.gradle.api.Project; +import org.gradle.api.file.Directory; +import org.gradle.api.file.FileCollection; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.Provider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.tooling.Message; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; + +public final class NeoModDevGradleModelBuilderImpl implements ModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return McpModelNMD.class.getName().equals(modelName); + } + + @Override + public Object buildAll(String modelName, Project project) { + Object extension = project.getExtensions().findByName("neoForge"); + if (extension == null) { + return null; + } + + if (project.getPlugins().findPlugin("net.neoforged.moddev") == null) { + return null; + } + + String neoFormVersion = null; + try { + Object neoFormVersionProp = ReflectUtil.getProperty(extension, "neoFormVersion"); + if (neoFormVersionProp instanceof String) { + neoFormVersion = (String) neoFormVersionProp; + } else if (neoFormVersionProp instanceof Provider) { + neoFormVersion = (String) ((Provider) neoFormVersionProp).getOrNull(); + } + } catch (Exception ignored) { + // Happens when the NeoForm version is not set or throws + } + + String neoforgeVersion = null; + if (neoFormVersion == null) { + try { + Object neoforgeVersionProp = ReflectUtil.getProperty(extension, "version"); + if (neoforgeVersionProp instanceof String) { + neoforgeVersion = (String) neoforgeVersionProp; + } else if (neoforgeVersionProp instanceof Provider) { + neoforgeVersion = (String) ((Provider) neoforgeVersionProp).getOrNull(); + } + } catch (Exception ignored) { + } + if (neoforgeVersion == null) { + return null; + } + } + + List accessTransformers = new ArrayList<>(); + try { + Object accessTransformersRaw = ReflectUtil.getProperty(extension, "accessTransformers"); + if (accessTransformersRaw instanceof ListProperty) { + ListProperty listProperty = (ListProperty) accessTransformersRaw; + for (Object it : listProperty.get()) { + accessTransformers.add(project.file(it)); + } + } else if (accessTransformersRaw instanceof FileCollection) { + accessTransformers.addAll(((FileCollection) accessTransformersRaw).getFiles()); + } else if (accessTransformersRaw != null) { + Object filesObj = ReflectUtil.getProperty(accessTransformersRaw, "files"); + if (filesObj instanceof Iterable) { + for (Object file : (Iterable) filesObj) { + if (file instanceof File) { + accessTransformers.add((File) file); + } + } + } + } + } catch (Exception ignored) { + } + + File mappingsFile = null; + try { + Directory neoformDir = project.getLayout().getBuildDirectory().dir("neoForm").getOrNull(); + if (neoformDir != null) { + final Path neoformDirPath = neoformDir.getAsFile().toPath(); + if (Files.exists(neoformDirPath)) { + try (Stream stream = Files.list(neoformDirPath)) { + mappingsFile = stream + .map(p -> p.resolve("config/joined.tsrg")) + .filter(Files::exists) + .findFirst() + .map(Path::toFile) + .orElse(null); + } + } + } + } catch (Exception ignored) { + } + + return new NeoModDevGradleModelImpl(neoforgeVersion, neoFormVersion, mappingsFile, accessTransformers); + } + + @Override + public void reportErrorMessage( + final @NotNull String modelName, + final @NotNull Project project, + final @NotNull ModelBuilderContext context, + final @NotNull Exception exception + ) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup(this) + .withKind(Message.Kind.ERROR) + .withGroup("com.demonwav.mcdev") + .withTitle("MinecraftDev: NeoModDev import error") + .withText("Unable to build MinecraftDev NeoModDev model for project " + project.getDisplayName()) + .withException(exception) + .reportMessage(project); + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,70 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev; + +import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.Serializable; +import java.util.List; + +final class NeoModDevGradleModelImpl implements McpModelNMD, Serializable { + + private final String neoForgeVersion; + private final String neoFormVersion; + private final File mappingsFile; + private final List accessTransformers; + + NeoModDevGradleModelImpl( + String neoForgeVersion, + String neoFormVersion, + File mappingsFile, + List accessTransformers + ) { + this.neoForgeVersion = neoForgeVersion; + this.neoFormVersion = neoFormVersion; + this.mappingsFile = mappingsFile; + this.accessTransformers = accessTransformers; + } + + @Override + @Nullable + public String getNeoForgeVersion() { + return neoForgeVersion; + } + + @Override + @Nullable + public String getNeoFormVersion() { + return neoFormVersion; + } + + @Override + public File getMappingsFile() { + return mappingsFile; + } + + @Override + public List getAccessTransformers() { + return accessTransformers; + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,58 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle; + +import org.gradle.api.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.tooling.Message; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; + +public final class VanillaGradleModelBuilderImpl implements ModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return VanillaGradleModel.class.getName().equals(modelName); + } + + @Override + public Object buildAll(String modelName, Project project) { + return new VanillaGradleModelImpl(project.getPlugins().hasPlugin("org.spongepowered.gradle.vanilla")); + } + + @Override + public void reportErrorMessage( + final @NotNull String modelName, + final @NotNull Project project, + final @NotNull ModelBuilderContext context, + final @NotNull Exception exception + ) { + //noinspection UnstableApiUsage + context.getMessageReporter().createMessage() + .withGroup(this) + .withKind(Message.Kind.ERROR) + .withGroup("com.demonwav.mcdev") + .withTitle("MinecraftDev: VanillaGradle import error") + .withText("Unable to build MinecraftDev VanillaGradle model for project " + project.getDisplayName()) + .withException(exception) + .reportMessage(project); + } +} Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java =================================================================== --- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) +++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java (revision 8c46fc74c8c2c6858fffb28de78bdffed40977fa) @@ -0,0 +1,37 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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 . + */ + +package com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle; + +import java.io.Serializable; + +final class VanillaGradleModelImpl implements VanillaGradleModel, Serializable { + + private final boolean hasVanillaGradle; + + VanillaGradleModelImpl(boolean hasVanillaGradle) { + this.hasVanillaGradle = hasVanillaGradle; + } + + @Override + public boolean hasVanillaGradle() { + return hasVanillaGradle; + } +}