User: rednesto Date: 29 Apr 23 20:05 Revision: 0ce517e06c34acd371a59bf3c3aceb28644fa892 Summary: Merge branch '2022.3' into 2023.1 # Conflicts: # src/main/kotlin/insight/ColorUtil.kt TeamCity URL: https://ci.mcdev.io/viewModification.html?tab=vcsModificationFiles&modId=8471&personal=false Index: gradle.properties =================================================================== --- gradle.properties (revision dae0cecb8265a1667faaf51894670e892ce83d71) +++ gradle.properties (revision 0ce517e06c34acd371a59bf3c3aceb28644fa892) @@ -14,7 +14,7 @@ ideaVersion = 2023.1 ideaVersionName = 2023.1 -coreVersion = 1.6.3 +coreVersion = 1.6.4 downloadIdeaSources = true pluginTomlVersion = 231.8109.1 Index: src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt =================================================================== --- src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt (revision dae0cecb8265a1667faaf51894670e892ce83d71) +++ src/main/kotlin/creator/step/FixedAssetsNewProjectWizardStep.kt (revision 0ce517e06c34acd371a59bf3c3aceb28644fa892) @@ -72,6 +72,10 @@ setupAssets(project) WriteAction.runAndWait { + if (project.isDisposed) { + return@runAndWait + } + val generatedFiles = mutableSetOf() for (asset in assets) { generateFile(asset)?.let { generatedFiles += it } @@ -86,7 +90,7 @@ fun runWhenCreated(project: Project, action: () -> Unit) { if (ApplicationManager.getApplication().isUnitTestMode) { action() - } else { + } else if (!project.isDisposed) { StartupManager.getInstance(project).runAfterOpened { ApplicationManager.getApplication().invokeLater(action, project.disposed) } Index: src/main/kotlin/facet/MinecraftFacetDetector.kt =================================================================== --- src/main/kotlin/facet/MinecraftFacetDetector.kt (revision dae0cecb8265a1667faaf51894670e892ce83d71) +++ src/main/kotlin/facet/MinecraftFacetDetector.kt (revision 0ce517e06c34acd371a59bf3c3aceb28644fa892) @@ -75,21 +75,23 @@ private fun checkNoFacet(module: Module) { val platforms = autoDetectTypes(module).ifEmpty { return } - val facetManager = FacetManager.getInstance(module) - val configuration = MinecraftFacetConfiguration() - configuration.state.autoDetectTypes.addAll(platforms) - - val facetType = MinecraftFacet.facetTypeOrNull ?: return - val facet = facetManager.createFacet(facetType, "Minecraft", configuration, null) runWriteTaskLater { // Only add the new facet if there isn't a Minecraft facet already - double check here since this // task may run much later - if (module.isDisposed || facet.isDisposed) { + if (module.isDisposed) { // Module may be disposed before we run return@runWriteTaskLater } - if (facetManager.getFacetByType(MinecraftFacet.ID) == null) { + + val facetType = MinecraftFacet.facetTypeOrNull + ?: return@runWriteTaskLater + + val facetManager = FacetManager.getInstance(module) - val model = facetManager.createModifiableModel() + val model = facetManager.createModifiableModel() + if (model.getFacetByType(MinecraftFacet.ID) == null) { + val configuration = MinecraftFacetConfiguration() + configuration.state.autoDetectTypes.addAll(platforms) + val facet = facetManager.createFacet(facetType, "Minecraft", configuration, null) model.addFacet(facet) model.commit() } Index: src/main/kotlin/insight/ColorUtil.kt =================================================================== --- src/main/kotlin/insight/ColorUtil.kt (revision dae0cecb8265a1667faaf51894670e892ce83d71) +++ src/main/kotlin/insight/ColorUtil.kt (revision 0ce517e06c34acd371a59bf3c3aceb28644fa892) @@ -8,12 +8,14 @@ * MIT License */ +@file:Suppress("UseJBColor") package com.demonwav.mcdev.insight import com.demonwav.mcdev.facet.MinecraftFacet import com.demonwav.mcdev.platform.AbstractModule import com.demonwav.mcdev.platform.AbstractModuleType import com.demonwav.mcdev.util.findModule +import com.demonwav.mcdev.util.runCatchingKtIdeaExceptions import com.demonwav.mcdev.util.runWriteAction import com.intellij.openapi.module.ModuleUtilCore import com.intellij.psi.JVMElementFactories @@ -52,7 +54,7 @@ return null } - val referencedElement = expression.resolveToUElement() + val referencedElement = runCatchingKtIdeaExceptions { expression.resolveToUElement() } if (referencedElement is UField) { val referencedFieldInitializer = referencedElement.uastInitializer if (referencedFieldInitializer is UReferenceExpression) { @@ -104,7 +106,7 @@ return findColorFromCallExpression(methodExpression, vectorClasses) } - var referencedElement = (uastParent as? UResolvable)?.resolveToUElement() + var referencedElement = runCatchingKtIdeaExceptions { (uastParent as? UResolvable)?.resolveToUElement() } while (referencedElement is UField) { val referencedFieldInitializer: UExpression? = referencedElement.uastInitializer if (referencedFieldInitializer is UCallExpression) { @@ -121,7 +123,7 @@ return referenceNameElement.findColor(moduleType, className, vectorClasses, maxDepth, depth + 1) } else if (referenceNameElement is UResolvable) { // The expression is complex, so we resolve it. If it is a field we're on for another round - referencedElement = referenceNameElement.resolveToUElement() + referencedElement = runCatchingKtIdeaExceptions { referenceNameElement.resolveToUElement() } continue } } @@ -143,7 +145,7 @@ return when { // Single Integer Argument - types.size == 1 && types[0] == PsiTypes.intType() -> + types.size == 1 -> colorFromSingleArgument(arguments[0])?.let { it to arguments[0] } // Triple Integer Argument types.size == 3 && types.all { it == PsiTypes.intType() } -> @@ -163,8 +165,30 @@ } private fun colorFromSingleArgument(expression: UExpression): Color? { - return Color(expression.evaluate() as? Int ?: return null) + return when (val paramVal = expression.evaluate()) { + is Int -> Color(paramVal as? Int ?: return null) + is String -> { + if (paramVal.startsWith("#")) { + val hexString = paramVal.substring(1) + when (hexString.length) { + 6 -> hexString.toIntOrNull(16)?.let(::Color) + 3 -> { + val hexInt = hexString.toIntOrNull(16) + ?: return null + val r = (hexInt and 0xf00) shr 8 or (hexInt and 0xf00) shr 4 + val g = (hexInt and 0x0f0) shr 4 or (hexInt and 0x0f0) + val b = (hexInt and 0x00f) shl 4 or (hexInt and 0x00f) + Color(r, g, b) -} + } + else -> null + } + } else { + null + } + } + else -> null + } +} private fun colorFromThreeArguments(expressions: List): Color? { fun normalize(value: Any?): Int? = when (value) { @@ -189,10 +213,17 @@ return colorFromThreeArguments(newExpression.valueArguments) } -fun UElement.setColor(color: String) { +fun UElement.setColor(color: String, isStringLiteral: Boolean = false) { val sourcePsi = this.sourcePsi ?: return sourcePsi.containingFile.runWriteAction { val project = sourcePsi.project + if (isStringLiteral) { + val literal = generationPlugin?.getElementFactory(project)?.createStringLiteralExpression(color, sourcePsi) + ?: return@runWriteAction + this.replace(literal) + return@runWriteAction + } + val parent = this.uastParent val newColorRef = generationPlugin?.getElementFactory(project)?.createQualifiedReference(color, sourcePsi) ?: return@runWriteAction @@ -241,3 +272,22 @@ b.sourcePsi?.replace(literalExpressionThree) } } + +fun UCallExpression.setColorHSV(h: Float, s: Float, v: Float) { + val sourcePsi = this.sourcePsi ?: return + sourcePsi.containingFile.runWriteAction { + val hExpr = this.valueArguments[0] + val sExpr = this.valueArguments[1] + val vExpr = this.valueArguments[2] + + val factory = JVMElementFactories.requireFactory(sourcePsi.language, sourcePsi.project) + + val literalExpressionOne = factory.createExpressionFromText(h.toString() + "f", null) + val literalExpressionTwo = factory.createExpressionFromText(s.toString() + "f", null) + val literalExpressionThree = factory.createExpressionFromText(v.toString() + "f", null) + + hExpr.sourcePsi?.replace(literalExpressionOne) + sExpr.sourcePsi?.replace(literalExpressionTwo) + vExpr.sourcePsi?.replace(literalExpressionThree) + } +} Index: src/main/kotlin/platform/adventure/color/AdventureColorUtil.kt =================================================================== --- src/main/kotlin/platform/adventure/color/AdventureColorUtil.kt (revision dae0cecb8265a1667faaf51894670e892ce83d71) +++ src/main/kotlin/platform/adventure/color/AdventureColorUtil.kt (revision 0ce517e06c34acd371a59bf3c3aceb28644fa892) @@ -14,10 +14,78 @@ import com.demonwav.mcdev.platform.adventure.AdventureConstants import com.demonwav.mcdev.platform.adventure.AdventureModuleType import com.intellij.psi.PsiElement +import com.intellij.psi.PsiTypes import java.awt.Color +import kotlin.math.roundToInt +import org.jetbrains.uast.UCallExpression import org.jetbrains.uast.UElement +import org.jetbrains.uast.UExpression import org.jetbrains.uast.UIdentifier +import org.jetbrains.uast.UQualifiedReferenceExpression +import org.jetbrains.uast.getParentOfType import org.jetbrains.uast.toUElementOfType -fun PsiElement.findAdventureColor(): Pair? = - this.toUElementOfType()?.findColor(AdventureModuleType, AdventureConstants.TEXT_COLOR_CLASS, null) +fun PsiElement.findAdventureColor(): Pair? { + val identifier = this.toUElementOfType() + ?: return null + + if (identifier.name == "hsvLike") { + val call = identifier.getParentOfType() + ?: return null + + if (call.resolve()?.containingClass?.qualifiedName != "net.kyori.adventure.util.HSVLike") { + return null + } + + val params = call.valueArguments + val h = params.getOrNull(0)?.evaluate() as? Float ?: return null + val s = params.getOrNull(1)?.evaluate() as? Float ?: return null + val v = params.getOrNull(2)?.evaluate() as? Float ?: return null + return Color.getHSBColor(h, s, v) to call + } + + if (identifier.name == "lerp") { + val call = identifier.getParentOfType() + ?: return null + + if (call.resolve()?.containingClass?.qualifiedName != "net.kyori.adventure.text.format.TextColor") { + return null + } + + val params = call.valueArguments + val t = params.getOrNull(0)?.evaluate() as? Float ?: return null + val (a, _) = params.getOrNull(1)?.findAdventureColor() ?: return null + val (b, _) = params.getOrNull(2)?.findAdventureColor() ?: return null + val clampedT = t.coerceIn(0f, 1f) + @Suppress("UseJBColor") + val color = Color( + (a.red + clampedT * (b.red - a.red)).roundToInt(), + (a.green + clampedT * (b.green - a.green)).roundToInt(), + (a.blue + clampedT * (b.blue - a.blue)).roundToInt() + ) + return color to call + } + + if (identifier.name == "color") { + val call = identifier.getParentOfType() + ?: return null + + if (call.resolve()?.containingClass?.qualifiedName != "net.kyori.adventure.text.format.TextColor") { + return null + } + + val params = call.valueArguments + if (params.size == 1 && params[0].getExpressionType() != PsiTypes.intType()) { + return params[0].findAdventureColor() + } + } + + return identifier.findColor(AdventureModuleType, AdventureConstants.TEXT_COLOR_CLASS, null) + ?: identifier.findColor(AdventureModuleType, "net.kyori.adventure.util.HSVLike", null) +} + +fun UExpression.findAdventureColor(): Pair? = when (this) { + is UCallExpression -> this.methodIdentifier?.sourcePsi?.findAdventureColor() + is UQualifiedReferenceExpression -> this.referenceNameElement?.sourcePsi?.findAdventureColor() + else -> null +} Index: src/main/kotlin/platform/bukkit/creator/bukkit-platforms.kt =================================================================== --- src/main/kotlin/platform/bukkit/creator/bukkit-platforms.kt (revision dae0cecb8265a1667faaf51894670e892ce83d71) +++ src/main/kotlin/platform/bukkit/creator/bukkit-platforms.kt (revision 0ce517e06c34acd371a59bf3c3aceb28644fa892) @@ -13,8 +13,14 @@ import com.demonwav.mcdev.creator.buildsystem.BuildDependency import com.demonwav.mcdev.creator.buildsystem.BuildRepository import com.demonwav.mcdev.platform.PlatformType +import com.demonwav.mcdev.util.MinecraftTemplates import com.demonwav.mcdev.util.MinecraftVersions import com.demonwav.mcdev.util.SemanticVersion +import com.intellij.openapi.observable.util.bindBooleanStorage +import com.intellij.openapi.ui.validation.AFTER_GRAPH_PROPAGATION +import com.intellij.openapi.ui.validation.WHEN_GRAPH_PROPAGATION_FINISHED +import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.bindSelected class SpigotPlatformStep(parent: BukkitPlatformStep) : AbstractBukkitPlatformStep(parent, PlatformType.SPIGOT) { override fun getRepositories(mcVersion: SemanticVersion) = listOf( @@ -38,6 +44,10 @@ ), ) + override fun getManifest(): Pair { + return "src/main/resources/plugin.yml" to MinecraftTemplates.BUKKIT_PLUGIN_YML_TEMPLATE + } + class Factory : BukkitPlatformStep.Factory { override val name = "Spigot" @@ -46,6 +56,23 @@ } class PaperPlatformStep(parent: BukkitPlatformStep) : AbstractBukkitPlatformStep(parent, PlatformType.PAPER) { + + private val usePaperManifestProperty = propertyGraph.property(false) + .bindBooleanStorage("${javaClass.name}.usePaperManifest") + + private val usePaperManifest by usePaperManifestProperty + + override fun setupUI(builder: Panel) { + super.setupUI(builder) + with(builder) { + row("Paper manifest:") { + checkBox("Use paper-plugin.yml") + .bindSelected(usePaperManifestProperty) + .validationRequestor(WHEN_GRAPH_PROPAGATION_FINISHED(propertyGraph)) + } + } + } + override fun getRepositories(mcVersion: SemanticVersion) = listOf( BuildRepository( "papermc-repo", @@ -73,6 +100,14 @@ ) } + override fun getManifest(): Pair { + if (usePaperManifest) { + return "src/main/resources/paper-plugin.yml" to MinecraftTemplates.PAPER_PLUGIN_YML_TEMPLATE + } + + return "src/main/resources/plugin.yml" to MinecraftTemplates.BUKKIT_PLUGIN_YML_TEMPLATE + } + class Factory : BukkitPlatformStep.Factory { override val name = "Paper" Index: src/main/kotlin/util/utils.kt =================================================================== --- src/main/kotlin/util/utils.kt (revision dae0cecb8265a1667faaf51894670e892ce83d71) +++ src/main/kotlin/util/utils.kt (revision 0ce517e06c34acd371a59bf3c3aceb28644fa892) @@ -354,3 +354,13 @@ // put the whole class name in as a string (easier to refactor, etc.) @Suppress("NOTHING_TO_INLINE") // In order for this to work this function must be `inline` inline fun loggerForTopLevel() = Logger.getInstance(MethodHandles.lookup().lookupClass()) + +inline fun runCatchingKtIdeaExceptions(action: () -> T): T? = try { + action() +} catch (e: Exception) { + if (e.javaClass.name == "org.jetbrains.kotlin.idea.caches.resolve.KotlinIdeaResolutionException") { + null + } else { + throw e + } +}