Add @Subscribe annotation
[no changelog]
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,6 +8,7 @@
|
|||||||
/build/
|
/build/
|
||||||
/buildSrc/.gradle
|
/buildSrc/.gradle
|
||||||
/buildSrc/build/
|
/buildSrc/build/
|
||||||
|
/*/build
|
||||||
|
|
||||||
# Ignore Gradle GUI config
|
# Ignore Gradle GUI config
|
||||||
gradle-app.setting
|
gradle-app.setting
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|||||||
plugins {
|
plugins {
|
||||||
java
|
java
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
id("com.google.devtools.ksp") version "1.9.23-1.0.20"
|
||||||
kotlin("jvm") version "1.9.23"
|
kotlin("jvm") version "1.9.23"
|
||||||
kotlin("plugin.serialization") version "1.9.23"
|
kotlin("plugin.serialization") version "1.9.23"
|
||||||
// id("com.bnorm.power.kotlin-power-assert") version "0.13.0"
|
// id("com.bnorm.power.kotlin-power-assert") version "0.13.0"
|
||||||
@@ -170,6 +171,9 @@ dependencies {
|
|||||||
|
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
|
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
|
||||||
|
|
||||||
|
implementation(project(":symbols"))
|
||||||
|
ksp(project(":symbols"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
@@ -193,8 +197,8 @@ loom {
|
|||||||
parseEnvFile(file(".env")).forEach { (t, u) ->
|
parseEnvFile(file(".env")).forEach { (t, u) ->
|
||||||
environmentVariable(t, u)
|
environmentVariable(t, u)
|
||||||
}
|
}
|
||||||
parseEnvFile(file(".properties")).forEach{ (t, u) ->
|
parseEnvFile(file(".properties")).forEach { (t, u) ->
|
||||||
property(t,u)
|
property(t, u)
|
||||||
}
|
}
|
||||||
vmArg("-ea")
|
vmArg("-ea")
|
||||||
vmArg("-XX:+AllowEnhancedClassRedefinition")
|
vmArg("-XX:+AllowEnhancedClassRedefinition")
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
@@ -28,3 +32,4 @@ pluginManagement {
|
|||||||
|
|
||||||
rootProject.name = "Firmament"
|
rootProject.name = "Firmament"
|
||||||
|
|
||||||
|
include("symbols")
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.events.subscription
|
||||||
|
|
||||||
|
import moe.nea.firmament.events.FirmamentEvent
|
||||||
|
import moe.nea.firmament.events.FirmamentEventBus
|
||||||
|
|
||||||
|
interface SubscriptionOwner
|
||||||
|
|
||||||
|
data class Subscription<T : FirmamentEvent>(
|
||||||
|
val owner: SubscriptionOwner,
|
||||||
|
val invoke: (T) -> Unit,
|
||||||
|
val eventBus: FirmamentEventBus<T>,
|
||||||
|
)
|
||||||
@@ -10,7 +10,10 @@ package moe.nea.firmament.features
|
|||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.annotations.generated.AllSubscriptions
|
||||||
import moe.nea.firmament.events.FeaturesInitializedEvent
|
import moe.nea.firmament.events.FeaturesInitializedEvent
|
||||||
|
import moe.nea.firmament.events.FirmamentEvent
|
||||||
|
import moe.nea.firmament.events.subscription.Subscription
|
||||||
import moe.nea.firmament.features.chat.AutoCompletions
|
import moe.nea.firmament.features.chat.AutoCompletions
|
||||||
import moe.nea.firmament.features.chat.ChatLinks
|
import moe.nea.firmament.features.chat.ChatLinks
|
||||||
import moe.nea.firmament.features.chat.QuickCommands
|
import moe.nea.firmament.features.chat.QuickCommands
|
||||||
@@ -80,11 +83,26 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
|
|||||||
loadFeature(DebugView)
|
loadFeature(DebugView)
|
||||||
}
|
}
|
||||||
allFeatures.forEach { it.config }
|
allFeatures.forEach { it.config }
|
||||||
|
subscribeEvents()
|
||||||
FeaturesInitializedEvent.publish(FeaturesInitializedEvent(allFeatures.toList()))
|
FeaturesInitializedEvent.publish(FeaturesInitializedEvent(allFeatures.toList()))
|
||||||
hasAutoloaded = true
|
hasAutoloaded = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun subscribeEvents() {
|
||||||
|
AllSubscriptions.provideSubscriptions {
|
||||||
|
subscribeSingleEvent(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : FirmamentEvent> subscribeSingleEvent(it: Subscription<T>) {
|
||||||
|
if (it.owner in features.values) { // TODO: better check here, somehow. probably implement some interface method
|
||||||
|
it.eventBus.subscribe(false, it.invoke) // TODO: pass through receivesCancelled from the annotation
|
||||||
|
} else {
|
||||||
|
Firmament.logger.error("Ignoring event listener for ${it.eventBus} in ${it.owner}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun loadFeature(feature: FirmamentFeature) {
|
fun loadFeature(feature: FirmamentFeature) {
|
||||||
synchronized(features) {
|
synchronized(features) {
|
||||||
if (feature.identifier in features) {
|
if (feature.identifier in features) {
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package moe.nea.firmament.features
|
package moe.nea.firmament.features
|
||||||
|
|
||||||
|
import moe.nea.firmament.events.subscription.SubscriptionOwner
|
||||||
import moe.nea.firmament.gui.config.ManagedConfig
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
|
|
||||||
interface FirmamentFeature {
|
interface FirmamentFeature : SubscriptionOwner {
|
||||||
val identifier: String
|
val identifier: String
|
||||||
val defaultEnabled: Boolean
|
val defaultEnabled: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
@@ -7,6 +8,7 @@
|
|||||||
package moe.nea.firmament.features.inventory
|
package moe.nea.firmament.features.inventory
|
||||||
|
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
import moe.nea.firmament.events.ItemTooltipEvent
|
import moe.nea.firmament.events.ItemTooltipEvent
|
||||||
import moe.nea.firmament.features.FirmamentFeature
|
import moe.nea.firmament.features.FirmamentFeature
|
||||||
import moe.nea.firmament.gui.config.ManagedConfig
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
@@ -26,9 +28,12 @@ object PriceData : FirmamentFeature {
|
|||||||
override val config get() = TConfig
|
override val config get() = TConfig
|
||||||
|
|
||||||
override fun onLoad() {
|
override fun onLoad() {
|
||||||
ItemTooltipEvent.subscribe {
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun function(it: ItemTooltipEvent) {
|
||||||
if (!TConfig.tooltipEnabled && !TConfig.enableKeybinding.isPressed()) {
|
if (!TConfig.tooltipEnabled && !TConfig.enableKeybinding.isPressed()) {
|
||||||
return@subscribe
|
return
|
||||||
}
|
}
|
||||||
val sbId = it.stack.skyBlockId
|
val sbId = it.stack.skyBlockId
|
||||||
val bazaarData = HypixelStaticData.bazaarData[sbId]
|
val bazaarData = HypixelStaticData.bazaarData[sbId]
|
||||||
@@ -36,17 +41,19 @@ object PriceData : FirmamentFeature {
|
|||||||
if (bazaarData != null) {
|
if (bazaarData != null) {
|
||||||
it.lines.add(Text.literal(""))
|
it.lines.add(Text.literal(""))
|
||||||
it.lines.add(
|
it.lines.add(
|
||||||
Text.stringifiedTranslatable("firmament.tooltip.bazaar.sell-order", FirmFormatters.formatCurrency(bazaarData.quickStatus.sellPrice, 1))
|
Text.stringifiedTranslatable("firmament.tooltip.bazaar.sell-order",
|
||||||
|
FirmFormatters.formatCurrency(bazaarData.quickStatus.sellPrice, 1))
|
||||||
)
|
)
|
||||||
it.lines.add(
|
it.lines.add(
|
||||||
Text.stringifiedTranslatable("firmament.tooltip.bazaar.buy-order", FirmFormatters.formatCurrency(bazaarData.quickStatus.buyPrice, 1))
|
Text.stringifiedTranslatable("firmament.tooltip.bazaar.buy-order",
|
||||||
|
FirmFormatters.formatCurrency(bazaarData.quickStatus.buyPrice, 1))
|
||||||
)
|
)
|
||||||
} else if (lowestBin != null) {
|
} else if (lowestBin != null) {
|
||||||
it.lines.add(Text.literal(""))
|
it.lines.add(Text.literal(""))
|
||||||
it.lines.add(
|
it.lines.add(
|
||||||
Text.stringifiedTranslatable("firmament.tooltip.ah.lowestbin", FirmFormatters.formatCurrency(lowestBin, 1))
|
Text.stringifiedTranslatable("firmament.tooltip.ah.lowestbin",
|
||||||
|
FirmFormatters.formatCurrency(lowestBin, 1))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import net.minecraft.entity.player.PlayerInventory
|
|||||||
import net.minecraft.screen.GenericContainerScreenHandler
|
import net.minecraft.screen.GenericContainerScreenHandler
|
||||||
import net.minecraft.screen.slot.SlotActionType
|
import net.minecraft.screen.slot.SlotActionType
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
||||||
import moe.nea.firmament.events.IsSlotProtectedEvent
|
import moe.nea.firmament.events.IsSlotProtectedEvent
|
||||||
import moe.nea.firmament.events.SlotRenderEvents
|
import moe.nea.firmament.events.SlotRenderEvents
|
||||||
@@ -166,7 +167,10 @@ object SlotLocking : FirmamentFeature {
|
|||||||
event.protectSilent()
|
event.protectSilent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SlotRenderEvents.After.subscribe {
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun function(it: SlotRenderEvents.After) {
|
||||||
val isSlotLocked = it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())
|
val isSlotLocked = it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())
|
||||||
val isUUIDLocked = (it.slot.stack?.skyblockUUID) in (lockedUUIDs ?: setOf())
|
val isUUIDLocked = (it.slot.stack?.skyblockUUID) in (lockedUUIDs ?: setOf())
|
||||||
if (isSlotLocked || isUUIDLocked) {
|
if (isSlotLocked || isUUIDLocked) {
|
||||||
@@ -190,5 +194,4 @@ object SlotLocking : FirmamentFeature {
|
|||||||
RenderSystem.enableDepthTest()
|
RenderSystem.enableDepthTest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
19
symbols/build.gradle.kts
Normal file
19
symbols/build.gradle.kts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("com.google.devtools.ksp")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.1.0")
|
||||||
|
implementation("com.google.auto.service:auto-service-annotations:1.1.1")
|
||||||
|
implementation("com.google.devtools.ksp:symbol-processing-api:1.9.23-1.0.20")
|
||||||
|
}
|
||||||
12
symbols/src/main/kotlin/Subscribe.kt
Normal file
12
symbols/src/main/kotlin/Subscribe.kt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.annotations
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class Subscribe
|
||||||
|
|
||||||
116
symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt
Normal file
116
symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.annotations.process
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService
|
||||||
|
import com.google.devtools.ksp.processing.CodeGenerator
|
||||||
|
import com.google.devtools.ksp.processing.Dependencies
|
||||||
|
import com.google.devtools.ksp.processing.KSPLogger
|
||||||
|
import com.google.devtools.ksp.processing.Resolver
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||||
|
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||||
|
import com.google.devtools.ksp.symbol.ClassKind
|
||||||
|
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||||
|
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||||
|
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
|
||||||
|
import com.google.devtools.ksp.symbol.KSType
|
||||||
|
import com.google.devtools.ksp.symbol.Nullability
|
||||||
|
import com.google.devtools.ksp.validate
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
|
||||||
|
class SubscribeAnnotationProcessor(
|
||||||
|
val logger: KSPLogger,
|
||||||
|
val codeGenerator: CodeGenerator,
|
||||||
|
) : SymbolProcessor {
|
||||||
|
override fun finish() {
|
||||||
|
val dependencies = Dependencies(
|
||||||
|
aggregating = true,
|
||||||
|
*subscriptions.mapTo(mutableSetOf()) { it.parent.containingFile!! }.toTypedArray())
|
||||||
|
val subscriptionsFile =
|
||||||
|
codeGenerator
|
||||||
|
.createNewFile(dependencies, "moe.nea.firmament.annotations.generated", "AllSubscriptions")
|
||||||
|
.bufferedWriter()
|
||||||
|
subscriptionsFile.apply {
|
||||||
|
appendLine("// This file is @generated by SubscribeAnnotationProcessor at ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(
|
||||||
|
Date())}")
|
||||||
|
appendLine("// Do not edit")
|
||||||
|
appendLine("package moe.nea.firmament.annotations.generated")
|
||||||
|
appendLine()
|
||||||
|
appendLine("import moe.nea.firmament.events.subscription.*")
|
||||||
|
appendLine()
|
||||||
|
appendLine("object AllSubscriptions {")
|
||||||
|
appendLine(" fun provideSubscriptions(addSubscription: (Subscription<*>) -> Unit) {")
|
||||||
|
for (subscription in subscriptions) {
|
||||||
|
val owner = subscription.parent.qualifiedName!!.asString()
|
||||||
|
val method = subscription.child.simpleName.asString()
|
||||||
|
val type = subscription.type.declaration.qualifiedName!!.asString()
|
||||||
|
appendLine(" addSubscription(Subscription<$type>(")
|
||||||
|
appendLine(" ${owner},")
|
||||||
|
appendLine(" ${owner}::${method},")
|
||||||
|
appendLine(" ${type}))")
|
||||||
|
}
|
||||||
|
appendLine(" }")
|
||||||
|
appendLine("}")
|
||||||
|
}
|
||||||
|
subscriptionsFile.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Subscription(
|
||||||
|
val parent: KSClassDeclaration,
|
||||||
|
val child: KSFunctionDeclaration,
|
||||||
|
val type: KSType,
|
||||||
|
)
|
||||||
|
|
||||||
|
val subscriptions = mutableListOf<Subscription>()
|
||||||
|
|
||||||
|
fun processCandidates(list: List<KSAnnotated>) {
|
||||||
|
for (element in list) {
|
||||||
|
if (element !is KSFunctionDeclaration) {
|
||||||
|
logger.error("@Subscribe annotation on a not-function", element)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.isAbstract) {
|
||||||
|
logger.error("@Subscribe annotation on an abstract function", element)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val parent = element.parentDeclaration
|
||||||
|
if (parent !is KSClassDeclaration || parent.isCompanionObject || parent.classKind != ClassKind.OBJECT) {
|
||||||
|
logger.error("@Subscribe on a non-object", element)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val param = element.parameters.singleOrNull()
|
||||||
|
if (param == null) {
|
||||||
|
logger.error("@Subscribe annotated functions need to take exactly one parameter", element)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val type = param.type.resolve()
|
||||||
|
if (type.nullability != Nullability.NOT_NULL) {
|
||||||
|
logger.error("@Subscribe annotated functions cannot take a nullable event", element)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
subscriptions.add(Subscription(parent, element, type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||||
|
val candidates = resolver.getSymbolsWithAnnotation(Subscribe::class.qualifiedName!!).toList()
|
||||||
|
val valid = candidates.filter { it.validate() }
|
||||||
|
val invalid = candidates.filter { !it.validate() }
|
||||||
|
processCandidates(valid)
|
||||||
|
return invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoService(SymbolProcessorProvider::class)
|
||||||
|
class SubscribeAnnotationProcessorProvider : SymbolProcessorProvider {
|
||||||
|
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
|
||||||
|
return SubscribeAnnotationProcessor(environment.logger, environment.codeGenerator)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user