From 19ffce4a2f8a0caddfab0460f8955027b4f3f2d2 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 00:54:55 +0200 Subject: [PATCH 01/20] Search for Mixin classes with $ in the name Fixes #2069 --- .../kotlin/util/reference/ClassNameReferenceProvider.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt b/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt index efbbde967..b15058417 100644 --- a/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt +++ b/src/main/kotlin/util/reference/ClassNameReferenceProvider.kt @@ -52,6 +52,12 @@ abstract class ClassNameReferenceProvider : PackageNameReferenceProvider() { return classes.mapToArray(::PsiElementResolveResult) } + // The dollar sign can also be used in normal class names + val classesWithDollarSign = facade.findClasses(qualifiedName, element.resolveScope) + if (classesWithDollarSign.isNotEmpty()) { + return classesWithDollarSign.mapToArray(::PsiElementResolveResult) + } + return super.resolve(actualName, element, facade) } From 2ddc23e42c36d1fbeab715377c9b0537156a4dfb Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 11:51:52 +0200 Subject: [PATCH 02/20] Also install JDK 11 for Gradle tooling ext --- .github/workflows/publish.yml | 4 +++- .github/workflows/test.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f932aa844..f58ca5f03 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,7 +13,9 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 17 + java-version: | + 11 + 17 - uses: actions/cache@v3 with: path: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6959f5b0..691a83b70 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,9 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 17 + java-version: | + 11 + 17 - uses: actions/cache@v3 with: path: | From efa2b72f8dbd37b3ec1b72978567eb5c2d201f49 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 13:00:26 +0200 Subject: [PATCH 03/20] Skip some creation steps if project is not opened Fixes minecraft-dev/mcdev-error-report#862 Fixes minecraft-dev/mcdev-error-report#832 Fixes minecraft-dev/mcdev-error-report#735 Fixes minecraft-dev/mcdev-error-report#716 Fixes minecraft-dev/mcdev-error-report#717 --- src/main/kotlin/creator/buildsystem/gradle-steps.kt | 9 ++++++++- src/main/kotlin/creator/buildsystem/maven-steps.kt | 7 +++++-- src/main/kotlin/creator/creator-utils.kt | 11 +++++++++++ .../kotlin/creator/step/AbstractReformatFilesStep.kt | 6 ++++++ src/main/resources/META-INF/plugin.xml | 1 + 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/creator/buildsystem/gradle-steps.kt b/src/main/kotlin/creator/buildsystem/gradle-steps.kt index 54577b5df..a19f46a16 100644 --- a/src/main/kotlin/creator/buildsystem/gradle-steps.kt +++ b/src/main/kotlin/creator/buildsystem/gradle-steps.kt @@ -22,6 +22,7 @@ package com.demonwav.mcdev.creator.buildsystem import com.demonwav.mcdev.creator.addTemplates import com.demonwav.mcdev.creator.findStep +import com.demonwav.mcdev.creator.notifyCreatedProjectNotOpened import com.demonwav.mcdev.creator.step.AbstractLongRunningStep import com.demonwav.mcdev.creator.step.AbstractReformatFilesStep import com.demonwav.mcdev.creator.step.FixedAssetsNewProjectWizardStep @@ -123,7 +124,8 @@ abstract class AbstractPatchGradleFilesStep(parent: NewProjectWizardStep) : Abst override fun perform(project: Project) { invokeAndWait { - if (project.isDisposed) { + if (project.isDisposed || !project.isInitialized) { + notifyCreatedProjectNotOpened() return@invokeAndWait } @@ -195,6 +197,11 @@ open class GradleImportStep(parent: NewProjectWizardStep) : AbstractLongRunningS open val additionalRunTasks = emptyList() override fun perform(project: Project) { + if (!project.isInitialized) { + notifyCreatedProjectNotOpened() + return + } + val rootDirectory = Path.of(context.projectFileDirectory) val buildSystemProps = findStep>() diff --git a/src/main/kotlin/creator/buildsystem/maven-steps.kt b/src/main/kotlin/creator/buildsystem/maven-steps.kt index f2a9932b6..294c928e1 100644 --- a/src/main/kotlin/creator/buildsystem/maven-steps.kt +++ b/src/main/kotlin/creator/buildsystem/maven-steps.kt @@ -22,6 +22,7 @@ package com.demonwav.mcdev.creator.buildsystem import com.demonwav.mcdev.creator.findStep import com.demonwav.mcdev.creator.getVersionJson +import com.demonwav.mcdev.creator.notifyCreatedProjectNotOpened import com.demonwav.mcdev.creator.step.AbstractLongRunningStep import com.demonwav.mcdev.creator.step.AbstractModNameStep import com.demonwav.mcdev.creator.step.AbstractReformatFilesStep @@ -125,7 +126,8 @@ abstract class AbstractPatchPomStep(parent: NewProjectWizardStep) : AbstractLong override fun perform(project: Project) { invokeAndWait { - if (project.isDisposed) { + if (project.isDisposed || !project.isInitialized) { + notifyCreatedProjectNotOpened() return@invokeAndWait } @@ -172,7 +174,8 @@ class MavenImportStep(parent: NewProjectWizardStep) : AbstractLongRunningStep(pa val pomFile = VfsUtil.findFile(Path.of(context.projectFileDirectory).resolve("pom.xml"), true) ?: return val promise = invokeAndWait { - if (project.isDisposed) { + if (project.isDisposed || !project.isInitialized) { + notifyCreatedProjectNotOpened() return@invokeAndWait null } MavenImportingManager.getInstance(project).linkAndImportFile(pomFile) diff --git a/src/main/kotlin/creator/creator-utils.kt b/src/main/kotlin/creator/creator-utils.kt index 38af05308..fdf4e38c9 100644 --- a/src/main/kotlin/creator/creator-utils.kt +++ b/src/main/kotlin/creator/creator-utils.kt @@ -29,6 +29,8 @@ import com.intellij.ide.starters.local.GeneratorTemplateFile import com.intellij.ide.wizard.AbstractNewProjectWizardStep import com.intellij.ide.wizard.GitNewProjectWizardData import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.notification.Notification +import com.intellij.notification.NotificationType import com.intellij.openapi.observable.properties.ObservableMutableProperty import com.intellij.openapi.observable.properties.ObservableProperty import com.intellij.openapi.project.Project @@ -149,3 +151,12 @@ fun ObservableMutableProperty.updateWhenChanged(dependency: ObservablePro } class EmptyStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) + +fun notifyCreatedProjectNotOpened() { + Notification( + "Minecraft project creator", + "Created project must be opened", + "Generated files might be incomplete and the project might be broken.", + NotificationType.ERROR, + ).notify(null) +} diff --git a/src/main/kotlin/creator/step/AbstractReformatFilesStep.kt b/src/main/kotlin/creator/step/AbstractReformatFilesStep.kt index 89221bea0..b97e7e3b5 100644 --- a/src/main/kotlin/creator/step/AbstractReformatFilesStep.kt +++ b/src/main/kotlin/creator/step/AbstractReformatFilesStep.kt @@ -20,6 +20,7 @@ package com.demonwav.mcdev.creator.step +import com.demonwav.mcdev.creator.notifyCreatedProjectNotOpened import com.intellij.codeInsight.actions.ReformatCodeProcessor import com.intellij.ide.wizard.NewProjectWizardStep import com.intellij.openapi.application.ReadAction @@ -56,6 +57,11 @@ abstract class AbstractReformatFilesStep(parent: NewProjectWizardStep) : Abstrac NonProjectFileWritingAccessProvider.disableChecksDuring { WriteCommandAction.writeCommandAction(project, *files).withGlobalUndo().run { + if (project.isDisposed || !project.isInitialized) { + notifyCreatedProjectNotOpened() + return@run + } + ReformatCodeProcessor(project, files, null, false).run() } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index a81c5a941..170242432 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -171,6 +171,7 @@ + From b070670f2e3d625bade5adf3d541ccef50be7be7 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 14:28:01 +0200 Subject: [PATCH 04/20] Attempt to fix lost userdata before NBT editor is created Fixes minecraft-dev/mcdev-error-report#1062 --- .../nbt/editor/NbtFileEditorProvider.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt b/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt index 21ea39ae4..6c9ce5423 100644 --- a/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt +++ b/src/main/kotlin/nbt/editor/NbtFileEditorProvider.kt @@ -48,6 +48,7 @@ import com.intellij.openapi.util.Key import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import com.intellij.psi.codeStyle.CodeStyleManager +import com.intellij.ui.EditorNotifications import com.intellij.ui.components.JBLoadingPanel import com.intellij.util.IncorrectOperationException import java.awt.BorderLayout @@ -92,6 +93,7 @@ private class NbtFileEditor( private var editor: FileEditor? = null private val editorCheckedDisposable = Disposer.newCheckedDisposable() private val component = JPanel(BorderLayout()) + private val tempUserData = mutableMapOf() init { val loading = JBLoadingPanel(null, this) @@ -123,10 +125,16 @@ private class NbtFileEditor( Disposer.dispose(this) return@let } + tempUserData.forEach { (k, v) -> + @Suppress("UNCHECKED_CAST") + editor.putUserData(k as Key, v) + } + tempUserData.clear() invokeLater { component.add(toolbar.panel, BorderLayout.NORTH) component.add(editor.component, BorderLayout.CENTER) } + EditorNotifications.getInstance(project).updateAllNotifications() } // This can be null if the file is too big to be parsed as a psi file @@ -178,12 +186,22 @@ private class NbtFileEditor( override fun getComponent() = component override fun getPreferredFocusedComponent() = editor.exec { preferredFocusedComponent } - override fun getUserData(key: Key) = editor.exec { getUserData(key) } + override fun getUserData(key: Key): T? { + if (editor == null) { + @Suppress("UNCHECKED_CAST") + return tempUserData[key] as? T + } + return editor.exec { getUserData(key) } + } override fun selectNotify() { editor.exec { selectNotify() } } override fun putUserData(key: Key, value: T?) { + if (editor == null) { + tempUserData[key] = value + return + } editor.exec { putUserData(key, value) } } From e685e8e9c661598ef78e3f17a3ab5805d823c866 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 15:20:12 +0200 Subject: [PATCH 05/20] Do not update groupId based on main class name change Prevents some kind of recursive update that does not appear in the UI for some reason Fixes #1985 --- src/main/kotlin/creator/step/MainClassStep.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/kotlin/creator/step/MainClassStep.kt b/src/main/kotlin/creator/step/MainClassStep.kt index f0ee9bddb..89db049a3 100644 --- a/src/main/kotlin/creator/step/MainClassStep.kt +++ b/src/main/kotlin/creator/step/MainClassStep.kt @@ -64,8 +64,6 @@ class MainClassStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep whenStepAvailable> { buildSystemStep -> classNameProperty.updateWhenChanged(buildSystemStep.groupIdProperty, ::suggestMainClassName) classNameProperty.updateWhenChanged(buildSystemStep.artifactIdProperty, ::suggestMainClassName) - - buildSystemStep.groupIdProperty.updateWhenChanged(classNameProperty, ::suggestGroupId) } whenStepAvailable { modNameStep -> classNameProperty.updateWhenChanged(modNameStep.nameProperty, ::suggestMainClassName) From f2f3b1c9dace3985c194b061b2e9761c6ca875d9 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 18:26:14 +0200 Subject: [PATCH 06/20] Add separate field for mod/plugin ID Fixes #2007 Fixes #2039 Fixes #2047 --- src/main/kotlin/creator/step/ModIdStep.kt | 104 ++++++++++++++++++ .../architectury/creator/asset-steps.kt | 13 ++- .../architectury/creator/gradle-steps.kt | 3 + .../platform/architectury/creator/ui-steps.kt | 2 + .../platform/fabric/creator/asset-steps.kt | 10 +- .../platform/fabric/creator/ui-steps.kt | 2 + .../platform/forge/creator/asset-steps.kt | 10 +- .../platform/forge/creator/gradle-steps.kt | 10 +- .../kotlin/platform/forge/creator/ui-steps.kt | 2 + .../platform/sponge/creator/gradle-steps.kt | 4 +- .../platform/sponge/creator/maven-steps.kt | 6 +- .../platform/sponge/creator/ui-steps.kt | 2 + .../platform/velocity/creator/asset-steps.kt | 4 +- .../platform/velocity/creator/ui-steps.kt | 2 + .../architectury_common_main_class.java.ft | 4 +- .../architectury_fabric_mod.json.ft | 6 +- .../architectury_forge_build.gradle.ft | 6 +- .../architectury_forge_mods.toml.ft | 8 +- .../j2ee/fabric/fabric_mod.json.ft | 6 +- .../forge/Forge (1.13+) gradle.properties.ft | 2 +- .../forge/Forge (1.16+) Main Class.java.ft | 4 +- .../forge/Forge (1.17+) Main Class.java.ft | 4 +- .../forge/Forge (1.18+) Main Class.java.ft | 4 +- .../forge/Forge (1.19+) Main Class.java.ft | 10 +- .../forge/Forge (1.19.3+) Main Class.java.ft | 10 +- .../forge/Forge (1.20+) Main Class.java.ft | 10 +- .../j2ee/forge/Forge Mixins Config.json.ft | 2 +- .../fileTemplates/j2ee/forge/mods.toml.ft | 2 +- .../fileTemplates/j2ee/forge/pack.mcmeta.ft | 2 +- 29 files changed, 193 insertions(+), 61 deletions(-) create mode 100644 src/main/kotlin/creator/step/ModIdStep.kt diff --git a/src/main/kotlin/creator/step/ModIdStep.kt b/src/main/kotlin/creator/step/ModIdStep.kt new file mode 100644 index 000000000..d40819de1 --- /dev/null +++ b/src/main/kotlin/creator/step/ModIdStep.kt @@ -0,0 +1,104 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2023 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.creator.step + +import com.demonwav.mcdev.creator.storeToData +import com.intellij.ide.wizard.AbstractNewProjectWizardStep +import com.intellij.ide.wizard.NewProjectWizardBaseData +import com.intellij.ide.wizard.NewProjectWizardStep +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.validation.AFTER_GRAPH_PROPAGATION +import com.intellij.openapi.ui.validation.CHECK_NON_EMPTY +import com.intellij.openapi.ui.validation.and +import com.intellij.openapi.ui.validation.validationErrorIf +import com.intellij.openapi.util.Key +import com.intellij.ui.dsl.builder.COLUMNS_MEDIUM +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindText +import com.intellij.ui.dsl.builder.columns +import com.intellij.ui.dsl.builder.textValidation + +private val validModIdRegex = "[a-z][a-z0-9-_]{1,63}".toRegex() +private val invalidModIdRegex = "[^a-z0-9-_]+".toRegex() + +private val validForgeModIdRegex = "[a-z][a-z0-9_]{1,63}".toRegex() +private val invalidForgeModIdRegex = "[^a-z0-9_]+".toRegex() + +abstract class AbstractModIdStep( + parent: NewProjectWizardStep, + private val validRegex: Regex = validModIdRegex, + private val invalidRegex: Regex = invalidModIdRegex +) : AbstractNewProjectWizardStep(parent) { + private val baseData = data.getUserData(NewProjectWizardBaseData.KEY) + ?: throw IllegalStateException("Mod id step created without base step") + val idProperty = propertyGraph.lazyProperty(::suggestId) + var id by idProperty + + private val idValidation = validationErrorIf("Id must match $validRegex") { !it.matches(validRegex) } + + init { + idProperty.dependsOn(baseData.nameProperty, ::suggestId) + storeToData() + } + + fun suggestId(): String { + val sanitized = baseData.name.lowercase().replace(invalidRegex, "_") + if (sanitized.length > 64) { + return sanitized.substring(0, 64) + } + return sanitized + } + + abstract val label: String + + override fun setupUI(builder: Panel) { + with(builder) { + row(label) { + textField() + .bindText(idProperty) + .columns(COLUMNS_MEDIUM) + .validationRequestor(AFTER_GRAPH_PROPAGATION(propertyGraph)) + .textValidation(CHECK_NON_EMPTY and idValidation) + } + } + } + + override fun setupProject(project: Project) { + data.putUserData(KEY, id) + } + + companion object { + val KEY = Key.create("${AbstractModIdStep::class.java.name}.id") + } +} + +class ModIdStep(parent: NewProjectWizardStep) : AbstractModIdStep(parent) { + override val label = "Mod Id:" +} + +class ForgeStyleModIdStep(parent: NewProjectWizardStep) : + AbstractModIdStep(parent, validForgeModIdRegex, invalidForgeModIdRegex) { + override val label = "Mod Id:" +} + +class PluginIdStep(parent: NewProjectWizardStep) : AbstractModIdStep(parent) { + override val label = "Plugin Id:" +} diff --git a/src/main/kotlin/platform/architectury/creator/asset-steps.kt b/src/main/kotlin/platform/architectury/creator/asset-steps.kt index 9e06cdd00..60184ce5a 100644 --- a/src/main/kotlin/platform/architectury/creator/asset-steps.kt +++ b/src/main/kotlin/platform/architectury/creator/asset-steps.kt @@ -29,6 +29,7 @@ import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport import com.demonwav.mcdev.creator.findStep import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModIdStep import com.demonwav.mcdev.creator.step.AbstractModNameStep import com.demonwav.mcdev.creator.step.AbstractReformatFilesStep import com.demonwav.mcdev.creator.step.AuthorsStep @@ -74,7 +75,8 @@ class ArchitecturyProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongR val buildSystemProps = findStep>() val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false val javaVersion = findStep().preferredJdk.ordinal - val packageName = "${buildSystemProps.groupId.toPackageName()}.${buildSystemProps.artifactId.toPackageName()}" + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return + val packageName = "${buildSystemProps.groupId.toPackageName()}.${modId.toPackageName()}" val mcVersion = data.getUserData(ArchitecturyVersionChainStep.MC_VERSION_KEY) ?: return val modName = data.getUserData(AbstractModNameStep.KEY) ?: return val forgeVersion = data.getUserData(ArchitecturyVersionChainStep.FORGE_VERSION_KEY) ?: return @@ -114,6 +116,7 @@ class ArchitecturyProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongR "PACK_COMMENT" to packDescriptor.comment, "PACKAGE_NAME" to packageName, "JAVA_VERSION" to javaVersion, + "MOD_ID" to modId, "MOD_NAME" to modName, "DISPLAY_TEST" to hasDisplayTestInManifest, "FORGE_SPEC_VERSION" to forgeVersion.parts[0].versionString, @@ -160,9 +163,9 @@ class ArchitecturyProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongR assets.addTemplateProperties( "MIXINS" to "true", ) - val commonMixinsFile = "common/src/main/resources/${buildSystemProps.artifactId}-common.mixins.json" - val forgeMixinsFile = "forge/src/main/resources/${buildSystemProps.artifactId}.mixins.json" - val fabricMixinsFile = "fabric/src/main/resources/${buildSystemProps.artifactId}.mixins.json" + val commonMixinsFile = "common/src/main/resources/$modId-common.mixins.json" + val forgeMixinsFile = "forge/src/main/resources/$modId.mixins.json" + val fabricMixinsFile = "fabric/src/main/resources/$modId.mixins.json" assets.addTemplates( project, commonMixinsFile to MinecraftTemplates.ARCHITECTURY_COMMON_MIXINS_JSON_TEMPLATE, @@ -194,6 +197,7 @@ abstract class ArchitecturyMainClassStep( override fun setupAssets(project: Project) { val buildSystemProps = findStep>() + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return val modName = data.getUserData(AbstractModNameStep.KEY) ?: return val useArchApi = data.getUserData(ArchitecturyVersionChainStep.ARCHITECTURY_API_VERSION_KEY) != null @@ -203,6 +207,7 @@ abstract class ArchitecturyMainClassStep( "PACKAGE_NAME" to packageName, "CLASS_NAME" to className, "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_ID" to modId, "MOD_NAME" to modName, "MOD_VERSION" to buildSystemProps.version, "ARCHITECTURY_PACKAGE" to architecturyPackage, diff --git a/src/main/kotlin/platform/architectury/creator/gradle-steps.kt b/src/main/kotlin/platform/architectury/creator/gradle-steps.kt index 52ce7ab41..26084c5eb 100644 --- a/src/main/kotlin/platform/architectury/creator/gradle-steps.kt +++ b/src/main/kotlin/platform/architectury/creator/gradle-steps.kt @@ -33,6 +33,7 @@ import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties import com.demonwav.mcdev.creator.findStep import com.demonwav.mcdev.creator.gitEnabled import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModIdStep import com.demonwav.mcdev.creator.step.AbstractModNameStep import com.demonwav.mcdev.creator.step.NewProjectWizardChainStep.Companion.nextStep import com.demonwav.mcdev.util.MinecraftTemplates @@ -67,6 +68,7 @@ class ArchitecturyGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRu data.putUserData(GRADLE_VERSION_KEY, SemanticVersion.release(7, 6, 1)) val buildSystemProps = findStep>() + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return val modName = data.getUserData(AbstractModNameStep.KEY) ?: return val mcVersion = data.getUserData(ArchitecturyVersionChainStep.MC_VERSION_KEY) ?: return val forgeVersion = data.getUserData(ArchitecturyVersionChainStep.FORGE_VERSION_KEY) ?: return @@ -78,6 +80,7 @@ class ArchitecturyGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRu assets.addTemplateProperties( "GROUP_ID" to buildSystemProps.groupId, "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_ID" to modId, "MOD_NAME" to modName, "VERSION" to buildSystemProps.version, "MC_VERSION" to mcVersion, diff --git a/src/main/kotlin/platform/architectury/creator/ui-steps.kt b/src/main/kotlin/platform/architectury/creator/ui-steps.kt index e986d165d..4b7f31a0a 100644 --- a/src/main/kotlin/platform/architectury/creator/ui-steps.kt +++ b/src/main/kotlin/platform/architectury/creator/ui-steps.kt @@ -26,6 +26,7 @@ import com.demonwav.mcdev.creator.step.AbstractLatentStep import com.demonwav.mcdev.creator.step.AbstractMcVersionChainStep import com.demonwav.mcdev.creator.step.AuthorsStep import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.ForgeStyleModIdStep import com.demonwav.mcdev.creator.step.IssueTrackerStep import com.demonwav.mcdev.creator.step.LicenseStep import com.demonwav.mcdev.creator.step.ModNameStep @@ -75,6 +76,7 @@ class ArchitecturyPlatformStep(parent: ModPlatformStep) : AbstractLatentStep>() + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false val javaVersion = findStep().preferredJdk.ordinal if (useMixins) { val packageName = - "${buildSystemProps.groupId.toPackageName()}.${buildSystemProps.artifactId.toPackageName()}.mixin" + "${buildSystemProps.groupId.toPackageName()}.${modId.toPackageName()}.mixin" assets.addTemplateProperties( "PACKAGE_NAME" to packageName, "JAVA_VERSION" to javaVersion, ) - val mixinsJsonFile = "src/main/resources/${buildSystemProps.artifactId}.mixins.json" + val mixinsJsonFile = "src/main/resources/$modId.mixins.json" assets.addTemplates(project, mixinsJsonFile to FABRIC_MIXINS_JSON_TEMPLATE) } @@ -107,6 +109,7 @@ class FabricSmartModeFilesStep(parent: NewProjectWizardStep) : AbstractLongRunni override fun setupAssets(project: Project) { val buildSystemProps = findStep>() + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return val modName = data.getUserData(AbstractModNameStep.KEY) ?: return val description = data.getUserData(DescriptionStep.KEY) ?: "" val envName = when (data.getUserData(FabricEnvironmentStep.KEY) ?: Side.NONE) { @@ -121,7 +124,7 @@ class FabricSmartModeFilesStep(parent: NewProjectWizardStep) : AbstractLongRunni val apiVersion = data.getUserData(FabricVersionChainStep.API_VERSION_KEY) val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false - val packageName = "${buildSystemProps.groupId.toPackageName()}.${buildSystemProps.artifactId.toPackageName()}" + val packageName = "${buildSystemProps.groupId.toPackageName()}.${modId.toPackageName()}" val mainClassName = "$packageName.${modName.toJavaClassName()}" val clientClassName = "$packageName.client.${modName.toJavaClassName()}Client" entryPoints = listOf( @@ -131,6 +134,7 @@ class FabricSmartModeFilesStep(parent: NewProjectWizardStep) : AbstractLongRunni assets.addTemplateProperties( "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_ID" to modId, "MOD_NAME" to StringUtil.escapeStringCharacters(modName), "MOD_DESCRIPTION" to StringUtil.escapeStringCharacters(description), "MOD_ENVIRONMENT" to envName, diff --git a/src/main/kotlin/platform/fabric/creator/ui-steps.kt b/src/main/kotlin/platform/fabric/creator/ui-steps.kt index d91b4a380..91b0abb3f 100644 --- a/src/main/kotlin/platform/fabric/creator/ui-steps.kt +++ b/src/main/kotlin/platform/fabric/creator/ui-steps.kt @@ -27,6 +27,7 @@ import com.demonwav.mcdev.creator.step.AbstractMcVersionChainStep import com.demonwav.mcdev.creator.step.AuthorsStep import com.demonwav.mcdev.creator.step.DescriptionStep import com.demonwav.mcdev.creator.step.LicenseStep +import com.demonwav.mcdev.creator.step.ModIdStep import com.demonwav.mcdev.creator.step.ModNameStep import com.demonwav.mcdev.creator.step.NewProjectWizardChainStep.Companion.nextStep import com.demonwav.mcdev.creator.step.RepositoryStep @@ -75,6 +76,7 @@ class FabricPlatformStep( return FabricVersionChainStep(this, fabricVersions, apiVersions) .nextStep(::FabricEnvironmentStep) .nextStep(::UseMixinsStep) + .nextStep(::ModIdStep) .nextStep(::ModNameStep) .nextStep(::LicenseStep) .nextStep(::FabricOptionalSettingsStep) diff --git a/src/main/kotlin/platform/forge/creator/asset-steps.kt b/src/main/kotlin/platform/forge/creator/asset-steps.kt index 038d449c4..55882dd60 100644 --- a/src/main/kotlin/platform/forge/creator/asset-steps.kt +++ b/src/main/kotlin/platform/forge/creator/asset-steps.kt @@ -29,6 +29,7 @@ import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport import com.demonwav.mcdev.creator.findStep import com.demonwav.mcdev.creator.splitPackage import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModIdStep import com.demonwav.mcdev.creator.step.AbstractModNameStep import com.demonwav.mcdev.creator.step.AbstractReformatFilesStep import com.demonwav.mcdev.creator.step.AuthorsStep @@ -56,6 +57,7 @@ class ForgeProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningA val mainClass = data.getUserData(MainClassStep.KEY) ?: return val (mainPackageName, mainClassName) = splitPackage(mainClass) val buildSystemProps = findStep>() + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return val modName = data.getUserData(AbstractModNameStep.KEY) ?: return val license = data.getUserData(LicenseStep.KEY) ?: return val description = data.getUserData(DescriptionStep.KEY) ?: "" @@ -78,6 +80,7 @@ class ForgeProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningA "PACKAGE_NAME" to mainPackageName, "CLASS_NAME" to mainClassName, "ARTIFACT_ID" to buildSystemProps.artifactId, + "MOD_ID" to modId, "MOD_NAME" to modName, "MOD_VERSION" to buildSystemProps.version, "DISPLAY_TEST" to (forgeVersion >= ForgeConstants.DISPLAY_TEST_MANIFEST_VERSION), @@ -144,12 +147,13 @@ class ForgeMixinsJsonStep(parent: NewProjectWizardStep) : AbstractLongRunningAss override fun setupAssets(project: Project) { val useMixins = data.getUserData(UseMixinsStep.KEY) ?: false if (useMixins) { + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return val buildSystemProps = findStep>() assets.addTemplateProperties( - "PACKAGE_NAME" to "${buildSystemProps.groupId}.${buildSystemProps.artifactId}.mixin", - "ARTIFACT_ID" to buildSystemProps.artifactId, + "PACKAGE_NAME" to "${buildSystemProps.groupId}.$modId.mixin", + "MOD_ID" to buildSystemProps.artifactId, ) - val mixinsJsonFile = "src/main/resources/${buildSystemProps.artifactId}.mixins.json" + val mixinsJsonFile = "src/main/resources/$modId.mixins.json" assets.addTemplates(project, mixinsJsonFile to MinecraftTemplates.FORGE_MIXINS_JSON_TEMPLATE) } } diff --git a/src/main/kotlin/platform/forge/creator/gradle-steps.kt b/src/main/kotlin/platform/forge/creator/gradle-steps.kt index 8668e9121..fbbf07ca2 100644 --- a/src/main/kotlin/platform/forge/creator/gradle-steps.kt +++ b/src/main/kotlin/platform/forge/creator/gradle-steps.kt @@ -33,6 +33,7 @@ import com.demonwav.mcdev.creator.buildsystem.addGradleWrapperProperties import com.demonwav.mcdev.creator.findStep import com.demonwav.mcdev.creator.gitEnabled import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModIdStep import com.demonwav.mcdev.creator.step.AbstractModNameStep import com.demonwav.mcdev.creator.step.AuthorsStep import com.demonwav.mcdev.creator.step.DescriptionStep @@ -47,7 +48,6 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VfsUtil import com.intellij.util.lang.JavaVersion -import java.util.Locale private val fg6WrapperVersion = SemanticVersion.release(8, 1, 1) @@ -68,14 +68,11 @@ class ForgeGradleSupport : BuildSystemSupport { class ForgeGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAssetsStep(parent) { override val description = "Creating Gradle files" - private fun transformModName(modName: String): String { - return modName.lowercase(Locale.ENGLISH).replace(" ", "") - } - override fun setupAssets(project: Project) { val mcVersion = data.getUserData(ForgeVersionChainStep.MC_VERSION_KEY) ?: return val forgeVersion = data.getUserData(ForgeVersionChainStep.FORGE_VERSION_KEY) ?: return - val modName = transformModName(data.getUserData(AbstractModNameStep.KEY) ?: return) + val modId = data.getUserData(AbstractModIdStep.KEY) ?: return + val modName = data.getUserData(AbstractModNameStep.KEY) ?: return val buildSystemProps = findStep>() val javaVersion = context.projectJdk.versionString?.let(JavaVersion::parse) val authors = data.getUserData(AuthorsStep.KEY) ?: emptyList() @@ -92,6 +89,7 @@ class ForgeGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningAs data.putUserData(GRADLE_VERSION_KEY, fg6WrapperVersion) assets.addTemplateProperties( + "MOD_ID" to modId, "MOD_NAME" to modName, "MC_VERSION" to mcVersion, "MC_NEXT_VERSION" to mcNextVersion, diff --git a/src/main/kotlin/platform/forge/creator/ui-steps.kt b/src/main/kotlin/platform/forge/creator/ui-steps.kt index 10d54c0f8..e58cb3089 100644 --- a/src/main/kotlin/platform/forge/creator/ui-steps.kt +++ b/src/main/kotlin/platform/forge/creator/ui-steps.kt @@ -26,6 +26,7 @@ import com.demonwav.mcdev.creator.step.AbstractLatentStep import com.demonwav.mcdev.creator.step.AbstractMcVersionChainStep import com.demonwav.mcdev.creator.step.AuthorsStep import com.demonwav.mcdev.creator.step.DescriptionStep +import com.demonwav.mcdev.creator.step.ForgeStyleModIdStep import com.demonwav.mcdev.creator.step.LicenseStep import com.demonwav.mcdev.creator.step.MainClassStep import com.demonwav.mcdev.creator.step.ModNameStep @@ -53,6 +54,7 @@ class ForgePlatformStep(parent: ModPlatformStep) : AbstractLatentStep().preferredJdk.ordinal val spongeVersion = data.getUserData(SpongeApiVersionStep.KEY) ?: return val license = data.getUserData(LicenseStep.KEY) ?: return + val pluginId = data.getUserData(AbstractModIdStep.KEY) ?: return val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return val mainClass = data.getUserData(MainClassStep.KEY) ?: return val description = data.getUserData(DescriptionStep.KEY) ?: "" @@ -78,7 +80,7 @@ class SpongeGradleFilesStep(parent: NewProjectWizardStep) : AbstractLongRunningA assets.addTemplateProperties( "GROUP_ID" to buildSystemProps.groupId, "ARTIFACT_ID" to buildSystemProps.artifactId, - "PLUGIN_ID" to buildSystemProps.artifactId, + "PLUGIN_ID" to pluginId, "PLUGIN_VERSION" to buildSystemProps.version, "JAVA_VERSION" to javaVersion, "SPONGEAPI_VERSION" to spongeVersion, diff --git a/src/main/kotlin/platform/sponge/creator/maven-steps.kt b/src/main/kotlin/platform/sponge/creator/maven-steps.kt index 5d776dc48..0fe77de6c 100644 --- a/src/main/kotlin/platform/sponge/creator/maven-steps.kt +++ b/src/main/kotlin/platform/sponge/creator/maven-steps.kt @@ -28,7 +28,6 @@ import com.demonwav.mcdev.creator.addTemplates import com.demonwav.mcdev.creator.buildsystem.AbstractPatchPomStep import com.demonwav.mcdev.creator.buildsystem.BuildDependency import com.demonwav.mcdev.creator.buildsystem.BuildRepository -import com.demonwav.mcdev.creator.buildsystem.BuildSystemPropertiesStep import com.demonwav.mcdev.creator.buildsystem.BuildSystemSupport import com.demonwav.mcdev.creator.buildsystem.BuildSystemType import com.demonwav.mcdev.creator.buildsystem.MavenImportStep @@ -37,6 +36,7 @@ import com.demonwav.mcdev.creator.buildsystem.addDefaultMavenProperties import com.demonwav.mcdev.creator.findStep import com.demonwav.mcdev.creator.gitEnabled import com.demonwav.mcdev.creator.step.AbstractLongRunningAssetsStep +import com.demonwav.mcdev.creator.step.AbstractModIdStep import com.demonwav.mcdev.creator.step.AbstractModNameStep import com.demonwav.mcdev.creator.step.AuthorsStep import com.demonwav.mcdev.creator.step.DependStep @@ -82,10 +82,10 @@ class SpongeMavenProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRu override val description = "Creating Maven project files" override fun setupAssets(project: Project) { - val buildSystemProps = findStep>() val mainClass = data.getUserData(MainClassStep.KEY) ?: return val spongeApiVersion = data.getUserData(SpongeApiVersionStep.KEY) ?: return val license = data.getUserData(LicenseStep.KEY) ?: return + val pluginId = data.getUserData(AbstractModIdStep.KEY) ?: return val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return val description = data.getUserData(DescriptionStep.KEY) ?: "" val website = data.getUserData(WebsiteStep.KEY) ?: "" @@ -93,7 +93,7 @@ class SpongeMavenProjectFilesStep(parent: NewProjectWizardStep) : AbstractLongRu val dependencies = data.getUserData(DependStep.KEY) ?: emptyList() assets.addTemplateProperties( - "PLUGIN_ID" to buildSystemProps.artifactId, + "PLUGIN_ID" to pluginId, "VERSION_PLACEHOLDER" to "\${version}", "SPONGEAPI_VERSION" to spongeApiVersion, "LICENSE" to license.id, diff --git a/src/main/kotlin/platform/sponge/creator/ui-steps.kt b/src/main/kotlin/platform/sponge/creator/ui-steps.kt index e29e092e5..a67662e2e 100644 --- a/src/main/kotlin/platform/sponge/creator/ui-steps.kt +++ b/src/main/kotlin/platform/sponge/creator/ui-steps.kt @@ -32,6 +32,7 @@ import com.demonwav.mcdev.creator.step.DescriptionStep import com.demonwav.mcdev.creator.step.LicenseStep import com.demonwav.mcdev.creator.step.MainClassStep import com.demonwav.mcdev.creator.step.NewProjectWizardChainStep.Companion.nextStep +import com.demonwav.mcdev.creator.step.PluginIdStep import com.demonwav.mcdev.creator.step.PluginNameStep import com.demonwav.mcdev.creator.step.WebsiteStep import com.demonwav.mcdev.platform.sponge.SpongeVersion @@ -52,6 +53,7 @@ class SpongePlatformStep(parent: PluginPlatformStep) : AbstractLatentStep>() + val pluginId = data.getUserData(AbstractModIdStep.KEY) ?: return val pluginName = data.getUserData(AbstractModNameStep.KEY) ?: return val mainClassName = data.getUserData(MainClassStep.KEY) ?: return val mainClassFile = "${context.projectFileDirectory}/src/main/java/${mainClassName.replace('.', '/')}.java" @@ -111,7 +113,7 @@ class VelocityModifyMainClassStep( val psiClass = mainClassPsi.classes[0] val annotation = buildString { append("@Plugin(") - append("\nid = ${literal(buildSystemProps.artifactId)}") + append("\nid = ${literal(pluginId)}") append(",\nname = ${literal(pluginName)}") if (isGradle) { diff --git a/src/main/kotlin/platform/velocity/creator/ui-steps.kt b/src/main/kotlin/platform/velocity/creator/ui-steps.kt index 374ba1769..de3cbb3ae 100644 --- a/src/main/kotlin/platform/velocity/creator/ui-steps.kt +++ b/src/main/kotlin/platform/velocity/creator/ui-steps.kt @@ -33,6 +33,7 @@ import com.demonwav.mcdev.creator.step.DependStep import com.demonwav.mcdev.creator.step.DescriptionStep import com.demonwav.mcdev.creator.step.MainClassStep import com.demonwav.mcdev.creator.step.NewProjectWizardChainStep.Companion.nextStep +import com.demonwav.mcdev.creator.step.PluginIdStep import com.demonwav.mcdev.creator.step.PluginNameStep import com.demonwav.mcdev.creator.step.WebsiteStep import com.demonwav.mcdev.platform.PlatformType @@ -59,6 +60,7 @@ class VelocityPlatformStep(parent: PluginPlatformStep) : AbstractLatentStep { LOGGER.info("Hello world from the MDK"); return "Hello world";}); + InterModComms.sendTo("${MOD_ID}", "helloworld", () -> { LOGGER.info("Hello world from the MDK"); return "Hello world";}); } private void processIMC(final InterModProcessEvent event) { diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.17+) Main Class.java.ft b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.17+) Main Class.java.ft index ed7e8ab02..4e31c0de6 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.17+) Main Class.java.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.17+) Main Class.java.ft @@ -18,7 +18,7 @@ import org.apache.logging.log4j.Logger; import java.util.stream.Collectors; // The value here should match an entry in the META-INF/mods.toml file -@Mod("${ARTIFACT_ID}") +@Mod("${MOD_ID}") public class ${CLASS_NAME} { // Directly reference a log4j logger. @@ -44,7 +44,7 @@ public class ${CLASS_NAME} { private void enqueueIMC(final InterModEnqueueEvent event) { // some example code to dispatch IMC to another mod - InterModComms.sendTo("${ARTIFACT_ID}", "helloworld", () -> { LOGGER.info("Hello world from the MDK"); return "Hello world";}); + InterModComms.sendTo("${MOD_ID}", "helloworld", () -> { LOGGER.info("Hello world from the MDK"); return "Hello world";}); } private void processIMC(final InterModProcessEvent event) { diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.18+) Main Class.java.ft b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.18+) Main Class.java.ft index 9031f15d9..be352a3a1 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.18+) Main Class.java.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.18+) Main Class.java.ft @@ -18,7 +18,7 @@ import org.slf4j.Logger; import java.util.stream.Collectors; // The value here should match an entry in the META-INF/mods.toml file -@Mod("${ARTIFACT_ID}") +@Mod("${MOD_ID}") public class ${CLASS_NAME} { // Directly reference a slf4j logger @@ -44,7 +44,7 @@ public class ${CLASS_NAME} { private void enqueueIMC(final InterModEnqueueEvent event) { // Some example code to dispatch IMC to another mod - InterModComms.sendTo("${ARTIFACT_ID}", "helloworld", () -> { LOGGER.info("Hello world from the MDK"); return "Hello world";}); + InterModComms.sendTo("${MOD_ID}", "helloworld", () -> { LOGGER.info("Hello world from the MDK"); return "Hello world";}); } private void processIMC(final InterModProcessEvent event) { diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19+) Main Class.java.ft b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19+) Main Class.java.ft index da7921740..de4c70d7d 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19+) Main Class.java.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19+) Main Class.java.ft @@ -31,17 +31,17 @@ import org.slf4j.Logger; public class ${CLASS_NAME} { // Define mod id in a common place for everything to reference - public static final String MODID = "${ARTIFACT_ID}"; + public static final String MODID = "${MOD_ID}"; // Directly reference a slf4j logger private static final Logger LOGGER = LogUtils.getLogger(); - // Create a Deferred Register to hold Blocks which will all be registered under the "${ARTIFACT_ID}" namespace + // Create a Deferred Register to hold Blocks which will all be registered under the "${MOD_ID}" namespace public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID); - // Create a Deferred Register to hold Items which will all be registered under the "${ARTIFACT_ID}" namespace + // Create a Deferred Register to hold Items which will all be registered under the "${MOD_ID}" namespace public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); - // Creates a new Block with the id "${ARTIFACT_ID}:example_block", combining the namespace and path + // Creates a new Block with the id "${MOD_ID}:example_block", combining the namespace and path public static final RegistryObject EXAMPLE_BLOCK = BLOCKS.register("example_block", () -> new Block(BlockBehaviour.Properties.of(Material.STONE))); - // Creates a new BlockItem with the id "${ARTIFACT_ID}:example_block", combining the namespace and path + // Creates a new BlockItem with the id "${MOD_ID}:example_block", combining the namespace and path public static final RegistryObject EXAMPLE_BLOCK_ITEM = ITEMS.register("example_block", () -> new BlockItem(EXAMPLE_BLOCK.get(), new Item.Properties().tab(CreativeModeTab.TAB_BUILDING_BLOCKS))); public ${CLASS_NAME}() { diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19.3+) Main Class.java.ft b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19.3+) Main Class.java.ft index 3fed7ca56..66310807a 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19.3+) Main Class.java.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.19.3+) Main Class.java.ft @@ -29,17 +29,17 @@ import org.slf4j.Logger; public class ${CLASS_NAME} { // Define mod id in a common place for everything to reference - public static final String MODID = "${ARTIFACT_ID}"; + public static final String MODID = "${MOD_ID}"; // Directly reference a slf4j logger private static final Logger LOGGER = LogUtils.getLogger(); - // Create a Deferred Register to hold Blocks which will all be registered under the "${ARTIFACT_ID}" namespace + // Create a Deferred Register to hold Blocks which will all be registered under the "${MOD_ID}" namespace public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID); - // Create a Deferred Register to hold Items which will all be registered under the "${ARTIFACT_ID}" namespace + // Create a Deferred Register to hold Items which will all be registered under the "${MOD_ID}" namespace public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); - // Creates a new Block with the id "${ARTIFACT_ID}:example_block", combining the namespace and path + // Creates a new Block with the id "${MOD_ID}:example_block", combining the namespace and path public static final RegistryObject EXAMPLE_BLOCK = BLOCKS.register("example_block", () -> new Block(BlockBehaviour.Properties.of(Material.STONE))); - // Creates a new BlockItem with the id "${ARTIFACT_ID}:example_block", combining the namespace and path + // Creates a new BlockItem with the id "${MOD_ID}:example_block", combining the namespace and path public static final RegistryObject EXAMPLE_BLOCK_ITEM = ITEMS.register("example_block", () -> new BlockItem(EXAMPLE_BLOCK.get(), new Item.Properties())); public ${CLASS_NAME}() { diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.20+) Main Class.java.ft b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.20+) Main Class.java.ft index af36d796e..8d7c4f392 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge (1.20+) Main Class.java.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/Forge (1.20+) Main Class.java.ft @@ -34,19 +34,19 @@ import org.slf4j.Logger; public class ${CLASS_NAME} { // Define mod id in a common place for everything to reference - public static final String MODID = "${ARTIFACT_ID}"; + public static final String MODID = "${MOD_ID}"; // Directly reference a slf4j logger private static final Logger LOGGER = LogUtils.getLogger(); - // Create a Deferred Register to hold Blocks which will all be registered under the "${ARTIFACT_ID}" namespace + // Create a Deferred Register to hold Blocks which will all be registered under the "${MOD_ID}" namespace public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID); - // Create a Deferred Register to hold Items which will all be registered under the "${ARTIFACT_ID}" namespace + // Create a Deferred Register to hold Items which will all be registered under the "${MOD_ID}" namespace public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); // Create a Deferred Register to hold CreativeModeTabs which will all be registered under the "examplemod" namespace public static final DeferredRegister CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID); - // Creates a new Block with the id "${ARTIFACT_ID}:example_block", combining the namespace and path + // Creates a new Block with the id "${MOD_ID}:example_block", combining the namespace and path public static final RegistryObject EXAMPLE_BLOCK = BLOCKS.register("example_block", () -> new Block(BlockBehaviour.Properties.of().mapColor(MapColor.STONE))); - // Creates a new BlockItem with the id "${ARTIFACT_ID}:example_block", combining the namespace and path + // Creates a new BlockItem with the id "${MOD_ID}:example_block", combining the namespace and path public static final RegistryObject EXAMPLE_BLOCK_ITEM = ITEMS.register("example_block", () -> new BlockItem(EXAMPLE_BLOCK.get(), new Item.Properties())); // Creates a new food item with the id "examplemod:example_id", nutrition 1 and saturation 2 diff --git a/src/main/resources/fileTemplates/j2ee/forge/Forge Mixins Config.json.ft b/src/main/resources/fileTemplates/j2ee/forge/Forge Mixins Config.json.ft index f975f7194..7e2aeffb1 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/Forge Mixins Config.json.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/Forge Mixins Config.json.ft @@ -3,7 +3,7 @@ "minVersion": "0.8", "package": "${PACKAGE_NAME}", "compatibilityLevel": "JAVA_8", - "refmap": "${ARTIFACT_ID}.refmap.json", + "refmap": "${MOD_ID}.refmap.json", "mixins": [ ], "client": [ diff --git a/src/main/resources/fileTemplates/j2ee/forge/mods.toml.ft b/src/main/resources/fileTemplates/j2ee/forge/mods.toml.ft index b2f73fe39..9e796114a 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/mods.toml.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/mods.toml.ft @@ -33,7 +33,7 @@ displayURL="${WEBSITE}" #optional #displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional #end # A file name (in the root of the mod JAR) containing a logo for display -#logoFile="${ARTIFACT_ID}.png" #optional +#logoFile="${MOD_ID}.png" #optional # A text field displayed in the mod UI #credits="Thanks for this example mod goes to Java" #optional # A text field displayed in the mod UI diff --git a/src/main/resources/fileTemplates/j2ee/forge/pack.mcmeta.ft b/src/main/resources/fileTemplates/j2ee/forge/pack.mcmeta.ft index 8a20b0d15..6f3c35d6a 100644 --- a/src/main/resources/fileTemplates/j2ee/forge/pack.mcmeta.ft +++ b/src/main/resources/fileTemplates/j2ee/forge/pack.mcmeta.ft @@ -1,6 +1,6 @@ { "pack": { - "description": "${ARTIFACT_ID} resources", + "description": "${MOD_ID} resources", #if (${PACK_COMMENT} != "") "pack_format": ${PACK_FORMAT}, "_comment": "${PACK_COMMENT}" From 9537e32bc0a1df07fd13e1685c567e5b7dbbf7ef Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 19:18:21 +0200 Subject: [PATCH 07/20] Detect Architectury patched Mixin dependency Fixes #1895 --- .../mixin/framework/MixinPresentationProvider.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/platform/mixin/framework/MixinPresentationProvider.kt b/src/main/kotlin/platform/mixin/framework/MixinPresentationProvider.kt index 34f36851e..cd022af95 100644 --- a/src/main/kotlin/platform/mixin/framework/MixinPresentationProvider.kt +++ b/src/main/kotlin/platform/mixin/framework/MixinPresentationProvider.kt @@ -31,17 +31,20 @@ import java.util.jar.Attributes.Name.IMPLEMENTATION_VERSION class MixinPresentationProvider : LibraryPresentationProvider(MIXIN_LIBRARY_KIND) { + private val hintFilePath = "META-INF/services/org.spongepowered.asm.service.IMixinService" + override fun getIcon(properties: LibraryVersionProperties?) = PlatformAssets.MIXIN_ICON override fun detect(classesRoots: List): LibraryVersionProperties? { for (classesRoot in classesRoots) { - val manifest = classesRoot.manifest ?: continue - if (manifest["Agent-Class"] != MixinConstants.Classes.MIXIN_AGENT) { + val manifest = classesRoot.manifest + if (manifest?.get("Agent-Class") != MixinConstants.Classes.MIXIN_AGENT && + classesRoot.findFileByRelativePath(hintFilePath) == null + ) { continue } - val version = manifest[IMPLEMENTATION_VERSION] ?: continue - return LibraryVersionProperties(version) + return LibraryVersionProperties(manifest?.get(IMPLEMENTATION_VERSION)) } return null } From 31c927bd012aa3c1d54aa136eec8ae52f4ac4212 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 9 Jul 2023 21:03:59 +0200 Subject: [PATCH 08/20] Significantly improve robustness of Forge mods search Fixes #2052 --- .../reference/ModsTomlReferenceContributor.kt | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt b/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt index 1287fc418..e1ad1ccb2 100644 --- a/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt +++ b/src/main/kotlin/toml/platform/forge/reference/ModsTomlReferenceContributor.kt @@ -25,12 +25,12 @@ import com.demonwav.mcdev.toml.inDependenciesHeaderId import com.demonwav.mcdev.toml.inModsTomlValueWithKey import com.demonwav.mcdev.toml.stringValue import com.demonwav.mcdev.util.childrenOfType +import com.demonwav.mcdev.util.constantStringValue import com.demonwav.mcdev.util.findModule import com.demonwav.mcdev.util.mapFirstNotNull -import com.intellij.openapi.progress.ProgressManager -import com.intellij.openapi.progress.util.ProgressIndicatorBase +import com.intellij.codeInsight.completion.JavaLookupElementBuilder +import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.openapi.project.rootManager -import com.intellij.openapi.util.Computable import com.intellij.openapi.util.Condition import com.intellij.openapi.util.TextRange import com.intellij.psi.JavaPsiFacade @@ -42,16 +42,11 @@ import com.intellij.psi.PsiReferenceContributor import com.intellij.psi.PsiReferenceProvider import com.intellij.psi.PsiReferenceRegistrar import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.searches.ReferencesSearch +import com.intellij.psi.search.searches.AnnotatedElementsSearch +import com.intellij.util.ArrayUtil import com.intellij.util.ProcessingContext import kotlin.math.max import org.jetbrains.jps.model.java.JavaResourceRootType -import org.jetbrains.uast.UAnnotation -import org.jetbrains.uast.evaluateString -import org.jetbrains.uast.getContainingUClass -import org.jetbrains.uast.getParentOfType -import org.jetbrains.uast.toUElement import org.toml.lang.psi.TomlArrayTable import org.toml.lang.psi.TomlKeySegment import org.toml.lang.psi.TomlPsiFactory @@ -132,26 +127,39 @@ class ModsTomlModIdReference(element: TomlValue) : val modId: String? = element.stringValue() override fun resolve(): PsiElement? { - if (modId == null) { + if (modId.isNullOrBlank()) { return null } - val module = element.findModule() ?: return null - val scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false) + + val scope = element.resolveScope + if (modId == "minecraft") { + return JavaPsiFacade.getInstance(element.project) + .findClass("net.minecraftforge.fml.mclanguageprovider.MinecraftModContainer", scope) + } + val modAnnotation = JavaPsiFacade.getInstance(element.project).findClass(ForgeConstants.MOD_ANNOTATION, scope) ?: return null - val refScope = GlobalSearchScope.moduleScope(module) - return ProgressManager.getInstance().runProcess( - Computable { - ReferencesSearch.search(modAnnotation, refScope, true).mapFirstNotNull { ref -> - ProgressManager.checkCanceled() - ref.element.toUElement()?.getParentOfType() - ?.takeIf { - it.qualifiedName == ForgeConstants.MOD_ANNOTATION && - it.findAttributeValue("value")?.evaluateString() == modId - }?.getContainingUClass()?.sourcePsi + return AnnotatedElementsSearch.searchPsiClasses(modAnnotation, scope).mapFirstNotNull { modClass -> + modClass.getAnnotation(ForgeConstants.MOD_ANNOTATION) + ?.takeIf { + val id = it.findAttributeValue("value")?.constantStringValue + id == modId } - }, - ProgressIndicatorBase() - ) + } + } + + override fun getVariants(): Array { + val scope = element.resolveScope + val modAnnotation = JavaPsiFacade.getInstance(element.project).findClass(ForgeConstants.MOD_ANNOTATION, scope) + ?: return ArrayUtil.EMPTY_OBJECT_ARRAY + val modIds = mutableListOf(LookupElementBuilder.create("minecraft")) + return AnnotatedElementsSearch.searchPsiClasses(modAnnotation, scope).mapNotNullTo(modIds) { modClass -> + val modId = modClass.getAnnotation(ForgeConstants.MOD_ANNOTATION) + ?.findAttributeValue("value") + ?.constantStringValue + ?: return@mapNotNullTo null + + JavaLookupElementBuilder.forClass(modClass, modId, true) + }.toTypedArray() } } From 6c0bb4f497848691c2347289261c750722940b19 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Mon, 10 Jul 2023 11:21:16 +0200 Subject: [PATCH 09/20] Intercept KTIJ exceptions in two more places Fixes minecraft-dev/mcdev-error-report#1065 Fixes minecraft-dev/mcdev-error-report#526 --- src/main/kotlin/insight/ListenerEventAnnotator.kt | 10 ++++++---- .../sponge/reference/SpongeReferenceContributor.kt | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/insight/ListenerEventAnnotator.kt b/src/main/kotlin/insight/ListenerEventAnnotator.kt index cbd3b8c22..0e2c2e663 100644 --- a/src/main/kotlin/insight/ListenerEventAnnotator.kt +++ b/src/main/kotlin/insight/ListenerEventAnnotator.kt @@ -22,6 +22,7 @@ package com.demonwav.mcdev.insight import com.demonwav.mcdev.MinecraftSettings import com.demonwav.mcdev.facet.MinecraftFacet +import com.demonwav.mcdev.util.runCatchingKtIdeaExceptions import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.Annotator import com.intellij.lang.annotation.HighlightSeverity @@ -53,10 +54,11 @@ class ListenerEventAnnotator : Annotator { return } - val method: UMethod = element.toUElement()?.uastParent as? UMethod - ?: element.getUastParentOfType() - ?.getParentOfType()?.uastParent as? UMethod // Be sure to be on the type of a parameter - ?: return + val method: UMethod = runCatchingKtIdeaExceptions { + element.toUElement()?.uastParent as? UMethod + ?: element.getUastParentOfType() + ?.getParentOfType()?.uastParent as? UMethod // Be sure to be on the type of a parameter + } ?: return if (method.javaPsi.hasModifierProperty(PsiModifier.ABSTRACT)) { // I don't think any implementation allows for abstract return diff --git a/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt b/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt index 84f83b248..3d67a14bd 100644 --- a/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt +++ b/src/main/kotlin/platform/sponge/reference/SpongeReferenceContributor.kt @@ -22,6 +22,7 @@ package com.demonwav.mcdev.platform.sponge.reference import com.demonwav.mcdev.insight.uastEventListener import com.demonwav.mcdev.platform.sponge.util.SpongeConstants +import com.demonwav.mcdev.util.runCatchingKtIdeaExceptions import com.intellij.codeInsight.completion.JavaLookupElementBuilder import com.intellij.patterns.PlatformPatterns import com.intellij.psi.CommonClassNames @@ -98,7 +99,7 @@ private class GetterReference(element: PsiLanguageInjectionHost) : PsiReferenceB private object GetterAnnotationFilter : ElementFilter { override fun isAcceptable(element: Any, context: PsiElement?): Boolean { val type = context.toUElement() ?: return false - val annotation = type.getParentOfType() ?: return false + val annotation = runCatchingKtIdeaExceptions { type.getParentOfType() } ?: return false return annotation.qualifiedName == SpongeConstants.GETTER_ANNOTATION } From 52872c2f62b56c8a795e6c9f8a249f0a114cff7c Mon Sep 17 00:00:00 2001 From: RedNesto Date: Mon, 10 Jul 2023 14:19:51 +0200 Subject: [PATCH 10/20] Fix Ktlint errors --- src/main/kotlin/insight/ListenerEventAnnotator.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/insight/ListenerEventAnnotator.kt b/src/main/kotlin/insight/ListenerEventAnnotator.kt index 0e2c2e663..591e8f212 100644 --- a/src/main/kotlin/insight/ListenerEventAnnotator.kt +++ b/src/main/kotlin/insight/ListenerEventAnnotator.kt @@ -55,9 +55,9 @@ class ListenerEventAnnotator : Annotator { } val method: UMethod = runCatchingKtIdeaExceptions { - element.toUElement()?.uastParent as? UMethod - ?: element.getUastParentOfType() - ?.getParentOfType()?.uastParent as? UMethod // Be sure to be on the type of a parameter + element.toUElement()?.uastParent as? UMethod + ?: element.getUastParentOfType() + ?.getParentOfType()?.uastParent as? UMethod // Be sure to be on the type of a parameter } ?: return if (method.javaPsi.hasModifierProperty(PsiModifier.ABSTRACT)) { // I don't think any implementation allows for abstract From 9ea1e404264046b08ea70b0d09e70fd1b70edff1 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sat, 15 Jul 2023 21:24:43 +0200 Subject: [PATCH 11/20] Check canNavigate() before calling navigate() Fixes minecraft-dev/mcdev-error-report#905 --- src/main/kotlin/insight/ListenerLineMarkerProvider.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/insight/ListenerLineMarkerProvider.kt b/src/main/kotlin/insight/ListenerLineMarkerProvider.kt index cc9351d68..8b72a91e2 100644 --- a/src/main/kotlin/insight/ListenerLineMarkerProvider.kt +++ b/src/main/kotlin/insight/ListenerLineMarkerProvider.kt @@ -76,7 +76,9 @@ class ListenerLineMarkerProvider : LineMarkerProviderDescriptor() { return GutterIconNavigationHandler handler@{ _, element -> val (eventClass, _) = element.toUElementOfType()?.uastEventListener ?: return@handler FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.declaration") - eventClass.navigate(true) + if (eventClass.canNavigate()) { + eventClass.navigate(true) + } } } From ea427f844a94df607d0f355fb932e40f98814406 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 16:40:06 +0200 Subject: [PATCH 12/20] Do not cast to PsiLiteralExpression Created expressions aren't always PsiLiteralExpression Fixes minecraft-dev/mcdev-error-report#218 --- src/main/kotlin/util/psi-utils.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/util/psi-utils.kt b/src/main/kotlin/util/psi-utils.kt index 1396bcaad..8fa5149eb 100644 --- a/src/main/kotlin/util/psi-utils.kt +++ b/src/main/kotlin/util/psi-utils.kt @@ -42,9 +42,9 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementFactory import com.intellij.psi.PsiElementResolveResult import com.intellij.psi.PsiEllipsisType +import com.intellij.psi.PsiExpression import com.intellij.psi.PsiFile import com.intellij.psi.PsiKeyword -import com.intellij.psi.PsiLiteralExpression import com.intellij.psi.PsiMember import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethodReferenceExpression @@ -282,7 +282,7 @@ val PsiMethodReferenceExpression.hasSyntheticMethod: Boolean val PsiClass.psiType: PsiType get() = PsiTypesUtil.getClassType(this) -fun PsiElementFactory.createLiteralExpression(constant: Any?): PsiLiteralExpression { +fun PsiElementFactory.createLiteralExpression(constant: Any?): PsiExpression { return when (constant) { null -> createExpressionFromText("null", null) is Boolean, is Double, is Int -> createExpressionFromText(constant.toString(), null) @@ -292,5 +292,5 @@ fun PsiElementFactory.createLiteralExpression(constant: Any?): PsiLiteralExpress is String -> createExpressionFromText("\"${StringUtil.escapeStringCharacters(constant)}\"", null) else -> throw IncorrectOperationException("Unsupported literal type: ${constant.javaClass.name}") - } as PsiLiteralExpression + } } From 152abf41a45014c351f14dae843050749be8df06 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 16:42:06 +0200 Subject: [PATCH 13/20] Recognize ModifyConstant injections without Constant supplied In this case Mixin filters the constants based on the method's return type. --- .../mixin/handlers/ModifyConstantHandler.kt | 94 ++++++++++++++++-- .../injectionPoint/ConstantInjectionPoint.kt | 99 +++++++++++++++---- 2 files changed, 167 insertions(+), 26 deletions(-) diff --git a/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt b/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt index c65c7f3f3..29855274d 100644 --- a/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt +++ b/src/main/kotlin/platform/mixin/handlers/ModifyConstantHandler.kt @@ -38,9 +38,11 @@ import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiElement import com.intellij.psi.PsiEnumConstant import com.intellij.psi.PsiManager +import com.intellij.psi.PsiMethod import com.intellij.psi.PsiReferenceExpression import com.intellij.psi.PsiType import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.util.parentOfType import org.objectweb.asm.Opcodes import org.objectweb.asm.Type import org.objectweb.asm.tree.AbstractInsnNode @@ -141,7 +143,28 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { targetClass: ClassNode, targetMethod: MethodNode, ): List? { - val constantInfos = getConstantInfos(annotation) ?: return null + val constantInfos = getConstantInfos(annotation) + if (constantInfos == null) { + val method = annotation.parentOfType() + ?: return emptyList() + val returnType = method.returnType + ?: return emptyList() + val constantParamName = method.parameterList.getParameter(0)?.name ?: "constant" + return listOf( + MethodSignature( + listOf( + ParameterGroup(listOf(sanitizedParameter(returnType, constantParamName))), + ParameterGroup( + collectTargetMethodParameters(annotation.project, targetClass, targetMethod), + isVarargs = true, + required = ParameterGroup.RequiredLevel.OPTIONAL, + ), + ), + returnType, + ) + ) + } + val psiManager = PsiManager.getInstance(annotation.project) return constantInfos.asSequence().map { when (it.constantInfo.constant) { @@ -174,8 +197,6 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { targetClass: ClassNode, targetMethod: MethodNode, ): List { - val constantInfos = getConstantInfos(annotation) ?: return emptyList() - val targetElement = targetMethod.findSourceElement( targetClass, annotation.project, @@ -183,6 +204,31 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { canDecompile = true, ) ?: return emptyList() + val constantInfos = getConstantInfos(annotation) + if (constantInfos == null) { + val returnType = annotation.parentOfType()?.returnType + ?: return emptyList() + + val collectVisitor = ConstantInjectionPoint.MyCollectVisitor( + annotation.project, + CollectVisitor.Mode.MATCH_ALL, + null, + Type.getType(returnType.descriptor) + ) + collectVisitor.visit(targetMethod) + val bytecodeResults = collectVisitor.result + + val navigationVisitor = ConstantInjectionPoint.MyNavigationVisitor( + null, + Type.getType(returnType.descriptor) + ) + targetElement.accept(navigationVisitor) + + return bytecodeResults.asSequence().mapNotNull { bytecodeResult -> + navigationVisitor.result.getOrNull(bytecodeResult.index) + }.sortedBy { it.textOffset }.toList() + } + val constantInjectionPoint = InjectionPoint.byAtCode("CONSTANT") as? ConstantInjectionPoint ?: return emptyList() @@ -215,7 +261,21 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { targetMethod: MethodNode, mode: CollectVisitor.Mode, ): List> { - val constantInfos = getConstantInfos(annotation) ?: return emptyList() + val constantInfos = getConstantInfos(annotation) + if (constantInfos == null) { + val returnType = annotation.parentOfType()?.returnType + ?: return emptyList() + + val collectVisitor = ConstantInjectionPoint.MyCollectVisitor( + annotation.project, + mode, + null, + Type.getType(returnType.descriptor) + ) + collectVisitor.visit(targetMethod) + return collectVisitor.result.sortedBy { targetMethod.instructions.indexOf(it.insn) } + } + val constantInjectionPoint = InjectionPoint.byAtCode("CONSTANT") as? ConstantInjectionPoint ?: return emptyList() return constantInfos.asSequence().flatMap { modifyConstantInfo -> @@ -239,10 +299,28 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { targetClass: ClassNode, targetMethod: MethodNode, ): InsnResolutionInfo.Failure? { - val constantInfos = getConstantInfos(annotation) ?: return InsnResolutionInfo.Failure() + val constantInfos = getConstantInfos(annotation) + if (constantInfos == null) { + val returnType = annotation.parentOfType()?.returnType + ?: return InsnResolutionInfo.Failure() + + val collectVisitor = ConstantInjectionPoint.MyCollectVisitor( + annotation.project, + CollectVisitor.Mode.MATCH_FIRST, + null, + Type.getType(returnType.descriptor) + ) + collectVisitor.visit(targetMethod) + return if (collectVisitor.result.isEmpty()) { + InsnResolutionInfo.Failure(collectVisitor.filterToBlame) + } else { + null + } + } + val constantInjectionPoint = InjectionPoint.byAtCode("CONSTANT") as? ConstantInjectionPoint ?: return null - return constantInfos.asSequence().mapNotNull { modifyConstantInfo -> + return constantInfos.firstNotNullOfOrNull { modifyConstantInfo -> val collectVisitor = ConstantInjectionPoint.MyCollectVisitor( annotation.project, CollectVisitor.Mode.MATCH_FIRST, @@ -255,11 +333,11 @@ class ModifyConstantHandler : InjectorAnnotationHandler() { ) collectVisitor.visit(targetMethod) if (collectVisitor.result.isEmpty()) { - collectVisitor.filterToBlame + InsnResolutionInfo.Failure(collectVisitor.filterToBlame) } else { null } - }.firstOrNull()?.let(InsnResolutionInfo::Failure) + } } override fun isInsnAllowed(insn: AbstractInsnNode): Boolean { diff --git a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt index c67d1fcb0..91f8aa0b4 100644 --- a/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt +++ b/src/main/kotlin/platform/mixin/handlers/injectionPoint/ConstantInjectionPoint.kt @@ -27,6 +27,7 @@ import com.demonwav.mcdev.util.descriptor import com.demonwav.mcdev.util.ifNotBlank import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.openapi.project.Project +import com.intellij.psi.CommonClassNames import com.intellij.psi.JavaPsiFacade import com.intellij.psi.JavaTokenType import com.intellij.psi.PsiAnnotation @@ -103,9 +104,8 @@ class ConstantInjectionPoint : InjectionPoint() { at: PsiAnnotation, target: MixinSelector?, targetClass: PsiClass, - ): NavigationVisitor? { - val constantInfo = getConstantInfo(at) ?: return null - return MyNavigationVisitor(constantInfo) + ): NavigationVisitor { + return MyNavigationVisitor(getConstantInfo(at)) } override fun doCreateCollectVisitor( @@ -113,9 +113,8 @@ class ConstantInjectionPoint : InjectionPoint() { target: MixinSelector?, targetClass: ClassNode, mode: CollectVisitor.Mode, - ): CollectVisitor? { - val constantInfo = getConstantInfo(at) ?: return null - return MyCollectVisitor(at.project, mode, constantInfo) + ): CollectVisitor { + return MyCollectVisitor(at.project, mode, getConstantInfo(at)) } override fun createLookup( @@ -135,7 +134,8 @@ class ConstantInjectionPoint : InjectionPoint() { } class MyNavigationVisitor( - private val constantInfo: ConstantInfo, + private val constantInfo: ConstantInfo?, + private val expectedType: Type? = null, ) : NavigationVisitor() { override fun visitForeachStatement(statement: PsiForeachStatement) { if (statement.iteratedValue?.type is PsiArrayType) { @@ -169,10 +169,35 @@ class ConstantInjectionPoint : InjectionPoint() { } private fun visitConstant(element: PsiElement, value: Any?) { - if (value != constantInfo.constant) { + if (constantInfo != null && value != constantInfo.constant) { return } + if (expectedType != null && value != null) { + // First check if we expect any String literal + if (value is String && + (expectedType.sort != Type.OBJECT || expectedType.className != CommonClassNames.JAVA_LANG_STRING) + ) { + return + } + + // then check if we expect any class literal + if (value is Type && ( + expectedType.sort != Type.ARRAY && expectedType.sort != Type.OBJECT || + expectedType.className != CommonClassNames.JAVA_LANG_CLASS + ) + ) { + return + } + + // otherwise we expect a primitive literal + if (expectedType.sort in Type.BOOLEAN..Type.DOUBLE && + value::class.javaPrimitiveType?.let(Type::getType) != expectedType + ) { + return + } + } + val parent = PsiUtil.skipParenthesizedExprUp(element.parent) // check for expandZeroConditions @@ -189,7 +214,11 @@ class ConstantInjectionPoint : InjectionPoint() { JavaTokenType.GE -> Opcodes.IFGE else -> null } - if (opcode != null && !constantInfo.expandConditions.any { opcode in it.opcodes }) { + if (opcode != null && ( + constantInfo == null || + !constantInfo.expandConditions.any { opcode in it.opcodes } + ) + ) { return } } @@ -207,10 +236,10 @@ class ConstantInjectionPoint : InjectionPoint() { class MyCollectVisitor( private val project: Project, mode: Mode, - private val constantInfo: ConstantInfo, + private val constantInfo: ConstantInfo?, + private val expectedType: Type? = null, ) : CollectVisitor(mode) { override fun accept(methodNode: MethodNode) { - val elementFactory = JavaPsiFacade.getElementFactory(project) methodNode.instructions?.iterator()?.forEachRemaining { insn -> val constant = when (insn) { is InsnNode -> when (insn.opcode) { @@ -225,13 +254,15 @@ class ConstantInjectionPoint : InjectionPoint() { Opcodes.ACONST_NULL -> null else -> return@forEachRemaining } + is IntInsnNode -> when (insn.opcode) { Opcodes.BIPUSH, Opcodes.SIPUSH -> insn.operand else -> return@forEachRemaining } + is LdcInsnNode -> insn.cst is JumpInsnNode -> { - if (!constantInfo.expandConditions.any { insn.opcode in it.opcodes }) { + if (constantInfo == null || !constantInfo.expandConditions.any { insn.opcode in it.opcodes }) { return@forEachRemaining } var lastInsn = insn.previous @@ -251,16 +282,48 @@ class ConstantInjectionPoint : InjectionPoint() { } 0 } + else -> return@forEachRemaining } - if (constant == constantInfo.constant) { - val literal = if (constant is Type) { - elementFactory.createExpressionFromText("${constant.className}.class", null) - } else { - elementFactory.createLiteralExpression(constant) + + if (constantInfo != null && constant != constantInfo.constant) { + return@forEachRemaining + } + + if (expectedType != null && constant != null) { + // First check if we expect any String literal + if (constant is String && ( + expectedType.sort != Type.OBJECT || + expectedType.className != CommonClassNames.JAVA_LANG_STRING + ) + ) { + return@forEachRemaining } - addResult(insn, literal) + + // then check if we expect any class literal + if (constant is Type && ( + expectedType.sort != Type.ARRAY && expectedType.sort != Type.OBJECT || + expectedType.className != CommonClassNames.JAVA_LANG_CLASS + ) + ) { + return@forEachRemaining + } + + // otherwise we expect a primitive literal + if (expectedType.sort in Type.BOOLEAN..Type.DOUBLE && + constant::class.javaPrimitiveType?.let(Type::getType) != expectedType + ) { + return@forEachRemaining + } + } + + val elementFactory = JavaPsiFacade.getElementFactory(project) + val literal = if (constant is Type) { + elementFactory.createExpressionFromText("${constant.className}.class", null) + } else { + elementFactory.createLiteralExpression(constant) } + addResult(insn, literal) } } } From bf256202050a98b8afa2495aea17685e02e406c2 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 16:59:49 +0200 Subject: [PATCH 14/20] Fix minecraft-dev/mcdev-error-report#1071 --- src/main/kotlin/platform/mixin/util/AsmUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/platform/mixin/util/AsmUtil.kt b/src/main/kotlin/platform/mixin/util/AsmUtil.kt index 23148c0fb..60ae2497f 100644 --- a/src/main/kotlin/platform/mixin/util/AsmUtil.kt +++ b/src/main/kotlin/platform/mixin/util/AsmUtil.kt @@ -719,7 +719,7 @@ fun MethodNode.findOrConstructSourceMethod( val simpleName = clazz?.name?.substringAfterLast('/') if (simpleName != null) { name = simpleName.substringAfterLast('$') - while (!name[0].isJavaIdentifierStart()) { + while (name.isNotEmpty() && !name[0].isJavaIdentifierStart()) { val dollarIndex = simpleName.lastIndexOf('$', simpleName.length - name.length - 2) if (dollarIndex == -1) { name = simpleName From 1a8c6c1c255c6aa395a41b28fdda1a9bceb65eb4 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 17:41:38 +0200 Subject: [PATCH 15/20] Do not replace dollar signs when followed by a digit Fixes minecraft-dev/mcdev-error-report#205 --- src/main/kotlin/platform/mixin/util/AsmUtil.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/platform/mixin/util/AsmUtil.kt b/src/main/kotlin/platform/mixin/util/AsmUtil.kt index 60ae2497f..79fc0b310 100644 --- a/src/main/kotlin/platform/mixin/util/AsmUtil.kt +++ b/src/main/kotlin/platform/mixin/util/AsmUtil.kt @@ -128,7 +128,8 @@ private fun hasModifier(access: Int, @PsiModifier.ModifierConstant modifier: Str } fun Type.toPsiType(elementFactory: PsiElementFactory, context: PsiElement? = null): PsiType { - return elementFactory.createTypeFromText(className.replace('$', '.'), context) + val javaClassName = className.replace("(\\$)(\\D)".toRegex()) { "." + it.groupValues[2] } + return elementFactory.createTypeFromText(javaClassName, context) } private fun hasAccess(access: Int, flag: Int) = (access and flag) != 0 From 14b015e45adcd1297e341cb9d3e15a379265db97 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 20:07:28 +0200 Subject: [PATCH 16/20] Fix Find Mixins TW not showing up --- src/main/kotlin/platform/mixin/action/FindMixinsAction.kt | 4 ---- src/main/resources/META-INF/plugin.xml | 6 ++++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt b/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt index ecbf4026e..a36e708d5 100644 --- a/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt +++ b/src/main/kotlin/platform/mixin/action/FindMixinsAction.kt @@ -52,10 +52,6 @@ class FindMixinsAction : AnAction() { class TWFactory : ToolWindowFactory { override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) { } - - override fun shouldBeAvailable(project: Project): Boolean { - return false - } } companion object { diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 170242432..55a992c34 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -426,8 +426,10 @@ order="before javaSkipAutopopupInStrings"/> - + From ad173127db8943e60a184e98fd97d8df36e71082 Mon Sep 17 00:00:00 2001 From: Dayo Date: Mon, 17 Jul 2023 05:00:34 +0900 Subject: [PATCH 17/20] Resolve deprecation warning (#2024) --- .../j2ee/architectury/architectury_common_build.gradle.ft | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/fileTemplates/j2ee/architectury/architectury_common_build.gradle.ft b/src/main/resources/fileTemplates/j2ee/architectury/architectury_common_build.gradle.ft index bd659acdc..564b15aa0 100644 --- a/src/main/resources/fileTemplates/j2ee/architectury/architectury_common_build.gradle.ft +++ b/src/main/resources/fileTemplates/j2ee/architectury/architectury_common_build.gradle.ft @@ -9,7 +9,7 @@ dependencies { } architectury { - common() + common("fabric", "forge") } publishing { @@ -24,4 +24,4 @@ publishing { repositories { // Add repositories to publish to here. } -} \ No newline at end of file +} From c15638a28f6daeb351cd91caf3ab9b4594b4432d Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 22:34:19 +0200 Subject: [PATCH 18/20] Run Fabric scope enlarger filter in smart mode --- .../fabric/reference/FabricClientUseScopeEnlarger.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt b/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt index 124f60688..7a659360c 100644 --- a/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt +++ b/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt @@ -23,6 +23,8 @@ package com.demonwav.mcdev.platform.fabric.reference import com.demonwav.mcdev.platform.fabric.util.FabricConstants import com.demonwav.mcdev.platform.mcp.fabricloom.FabricLoomData import com.demonwav.mcdev.util.findModule +import com.intellij.openapi.project.DumbService +import com.intellij.openapi.util.Computable import com.intellij.psi.PsiElement import com.intellij.psi.search.FilenameIndex import com.intellij.psi.search.GlobalSearchScope @@ -41,8 +43,10 @@ class FabricClientUseScopeEnlarger : UseScopeEnlarger() { if (loomData.splitMinecraftJar) { return GlobalSearchScope.filesScope(element.project) { - val moduleWithDeps = GlobalSearchScope.moduleWithDependenciesScope(module) - FilenameIndex.getVirtualFilesByName(FabricConstants.FABRIC_MOD_JSON, moduleWithDeps) + DumbService.getInstance(module.project).runReadActionInSmartMode(Computable { + val moduleWithDeps = GlobalSearchScope.moduleWithDependenciesScope(module) + FilenameIndex.getVirtualFilesByName(FabricConstants.FABRIC_MOD_JSON, moduleWithDeps) + }) } } From a0ca0da5dda34b2abd0456bc9e1063f51d0730e5 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 22:41:31 +0200 Subject: [PATCH 19/20] Fix Ktlint error --- .../fabric/reference/FabricClientUseScopeEnlarger.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt b/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt index 7a659360c..5372d6286 100644 --- a/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt +++ b/src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt @@ -43,10 +43,12 @@ class FabricClientUseScopeEnlarger : UseScopeEnlarger() { if (loomData.splitMinecraftJar) { return GlobalSearchScope.filesScope(element.project) { - DumbService.getInstance(module.project).runReadActionInSmartMode(Computable { - val moduleWithDeps = GlobalSearchScope.moduleWithDependenciesScope(module) - FilenameIndex.getVirtualFilesByName(FabricConstants.FABRIC_MOD_JSON, moduleWithDeps) - }) + DumbService.getInstance(module.project).runReadActionInSmartMode( + Computable { + val moduleWithDeps = GlobalSearchScope.moduleWithDependenciesScope(module) + FilenameIndex.getVirtualFilesByName(FabricConstants.FABRIC_MOD_JSON, moduleWithDeps) + } + ) } } From 2888acffa5cec4d2bc17720bc26da5598de5ff10 Mon Sep 17 00:00:00 2001 From: RedNesto Date: Sun, 16 Jul 2023 22:50:45 +0200 Subject: [PATCH 20/20] Version 1.6.8 --- gradle.properties | 2 +- readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 95ce02f2b..bfdb5039c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,7 +24,7 @@ kotlin.code.style=official ideaVersion = 2022.2 ideaVersionName = 2022.2 -coreVersion = 1.6.7 +coreVersion = 1.6.8 downloadIdeaSources = true pluginTomlVersion = 222.3345.108 diff --git a/readme.md b/readme.md index 2206971aa..cf8c35126 100644 --- a/readme.md +++ b/readme.md @@ -35,7 +35,7 @@ Minecraft Development for IntelliJ -Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.6.7-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327) +Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.6.8-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327) ----------------------