aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalMWolfs <94038482+CalMWolfs@users.noreply.github.com>2024-06-01 20:47:08 +1000
committerGitHub <noreply@github.com>2024-06-01 12:47:08 +0200
commita20da5a79b5b05839862c8e8fd165b18368729c1 (patch)
treeef0b258d90d839867eba8c002f02e1c823b049ef
parent2698b9d13de081be2e72e63faa213a74cafb6a6b (diff)
downloadskyhanni-a20da5a79b5b05839862c8e8fd165b18368729c1.tar.gz
skyhanni-a20da5a79b5b05839862c8e8fd165b18368729c1.tar.bz2
skyhanni-a20da5a79b5b05839862c8e8fd165b18368729c1.zip
Backend: Auto load annotation (#1904)
Co-authored-by: Brady <thatgravyboat@gmail.com>
-rw-r--r--CONTRIBUTING.md3
-rw-r--r--annotation-processors/build.gradle.kts27
-rw-r--r--annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProcessor.kt68
-rw-r--r--annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProvider.kt11
-rw-r--r--annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/SkyHanniModule.kt5
-rw-r--r--annotation-processors/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider1
-rw-r--r--build.gradle.kts14
-rw-r--r--gradle.properties5
-rw-r--r--settings.gradle.kts1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt2
11 files changed, 144 insertions, 4 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6588b9a95..c66c048f5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -59,6 +59,9 @@ format like "- #821" to illustrate the dependency.
- All new classes should be written in Kotlin, with a few exceptions:
- Config files in `at.hannibal2.skyhanni.config.features`
- Mixin classes in `at.hannibal2.skyhanni.mixins.transformers`
+- New features should be made in Kotlin objects unless there is a specific reason for it not to.
+ - If the feature needs to use forge events or a repo pattern, annotate it with `@SkyHanniModule`
+ - This will automatically register it to the forge event bus and load the repo patterns
- Avoid using deprecated functions.
- These functions are marked for removal in future versions.
- If you're unsure why a function is deprecated or how to replace it, please ask for guidance.
diff --git a/annotation-processors/build.gradle.kts b/annotation-processors/build.gradle.kts
new file mode 100644
index 000000000..c091ba6e3
--- /dev/null
+++ b/annotation-processors/build.gradle.kts
@@ -0,0 +1,27 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+ idea
+ kotlin("jvm")
+ java
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation(kotlin("stdlib-jdk8"))
+ implementation("com.google.devtools.ksp:symbol-processing-api:1.8.0-1.0.8")
+}
+
+tasks.withType<JavaCompile> {
+ if (JavaVersion.current().isJava9Compatible) {
+ options.release.set(8)
+ }
+}
+
+val compileKotlin: KotlinCompile by tasks
+compileKotlin.kotlinOptions {
+ jvmTarget = "1.8"
+}
diff --git a/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProcessor.kt b/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProcessor.kt
new file mode 100644
index 000000000..bc7d262b4
--- /dev/null
+++ b/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProcessor.kt
@@ -0,0 +1,68 @@
+package at.hannibal2.skyhanni.skyhannimodule
+
+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.symbol.ClassKind
+import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSClassDeclaration
+import com.google.devtools.ksp.validate
+import java.io.OutputStreamWriter
+
+class ModuleProcessor(private val codeGenerator: CodeGenerator, private val logger: KSPLogger) : SymbolProcessor {
+
+ override fun process(resolver: Resolver): List<KSAnnotated> {
+
+ val symbols = resolver.getSymbolsWithAnnotation(SkyHanniModule::class.qualifiedName!!).toList()
+ val validSymbols = symbols.mapNotNull { validateSymbol(it) }
+
+ if (validSymbols.isNotEmpty()) {
+ generateFile(validSymbols)
+ }
+
+ return emptyList()
+ }
+
+ private fun validateSymbol(symbol: KSAnnotated): KSClassDeclaration? {
+ if (!symbol.validate()) {
+ logger.warn("Symbol is not valid: $symbol")
+ return null
+ }
+
+ if (symbol !is KSClassDeclaration) {
+ logger.error("@SkyHanniModule is only valid on class declarations", symbol)
+ return null
+ }
+
+ if (symbol.classKind != ClassKind.OBJECT) {
+ logger.error("@SkyHanniModule is only valid on kotlin objects", symbol)
+ return null
+ }
+
+ return symbol
+ }
+
+ private fun generateFile(symbols: List<KSClassDeclaration>) {
+ val dependencies = symbols.mapNotNull { it.containingFile }.toTypedArray()
+ val deps = Dependencies(true, *dependencies)
+
+ val file = codeGenerator.createNewFile(deps, "at.hannibal2.skyhanni.skyhannimodule", "LoadedModules")
+
+ OutputStreamWriter(file).use {
+ it.write("package at.hannibal2.skyhanni.skyhannimodule\n\n")
+ it.write("object LoadedModules {\n")
+ it.write(" val modules: List<Any> = listOf(\n")
+
+ symbols.forEach { symbol ->
+ it.write(" ${symbol.qualifiedName!!.asString()},\n")
+ }
+
+ it.write(" )\n")
+ it.write("}\n")
+ }
+
+ logger.warn("Generated LoadedModules file with ${symbols.size} modules")
+ }
+}
diff --git a/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProvider.kt b/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProvider.kt
new file mode 100644
index 000000000..47d03655f
--- /dev/null
+++ b/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/ModuleProvider.kt
@@ -0,0 +1,11 @@
+package at.hannibal2.skyhanni.skyhannimodule
+
+import com.google.devtools.ksp.processing.SymbolProcessor
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
+import com.google.devtools.ksp.processing.SymbolProcessorProvider
+
+class ModuleProvider : SymbolProcessorProvider {
+ override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
+ return ModuleProcessor(environment.codeGenerator, environment.logger)
+ }
+}
diff --git a/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/SkyHanniModule.kt b/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/SkyHanniModule.kt
new file mode 100644
index 000000000..cb6b0eae4
--- /dev/null
+++ b/annotation-processors/src/main/kotlin/at/hannibal2/skyhanni/skyhannimodule/SkyHanniModule.kt
@@ -0,0 +1,5 @@
+package at.hannibal2.skyhanni.skyhannimodule
+
+@Target(AnnotationTarget.CLASS)
+@Retention(AnnotationRetention.SOURCE)
+annotation class SkyHanniModule
diff --git a/annotation-processors/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/annotation-processors/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
new file mode 100644
index 000000000..5f0d42dc4
--- /dev/null
+++ b/annotation-processors/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
@@ -0,0 +1 @@
+at.hannibal2.skyhanni.skyhannimodule.ModuleProvider
diff --git a/build.gradle.kts b/build.gradle.kts
index 051bcc4f9..b481a39cf 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -11,6 +11,7 @@ plugins {
kotlin("jvm") version "1.9.0"
id("com.bnorm.power.kotlin-power-assert") version "0.13.0"
`maven-publish`
+ id("com.google.devtools.ksp") version "1.9.0-1.0.13"
id("moe.nea.shot") version "1.0.0"
}
@@ -90,6 +91,8 @@ dependencies {
headlessLwjgl(libs.headlessLwjgl)
+ compileOnly(ksp(project(":annotation-processors"))!!)
+
shadowImpl("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
isTransitive = false
}
@@ -129,6 +132,11 @@ dependencies {
implementation("net.hypixel:mod-api:0.3.1")
}
+
+ksp {
+ arg("symbolProcessor", "at.hannibal2.skyhanni.loadmodule.LoadModuleProvider")
+}
+
configurations.getByName("minecraftNamed").dependencies.forEach {
shot.applyTo(it as HasConfigurableAttributes<*>)
}
@@ -147,6 +155,12 @@ kotlin {
enableLanguageFeature("BreakContinueInInlineLambdas")
}
}
+ sourceSets.main {
+ kotlin.srcDir("build/generated/ksp/main/kotlin")
+ }
+ sourceSets.test {
+ kotlin.srcDir("build/generated/ksp/test/kotlin")
+ }
}
// Minecraft configuration:
diff --git a/gradle.properties b/gradle.properties
index 065574755..16cc55dfa 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,5 @@
loom.platform=forge
-org.gradle.jvmargs=-Xmx2g \ No newline at end of file
+org.gradle.jvmargs=-Xmx2g
+org.gradle.parallel=true
+org.gradle.caching=true
+kotlin.incremental.useClasspathSnapshot=true
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 12734a34a..8bd4de72f 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -23,4 +23,5 @@ plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version("0.6.0")
}
+include("annotation-processors")
rootProject.name = "SkyHanni"
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index 5d1bb52ad..6fd2154e8 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -14,7 +14,6 @@ import at.hannibal2.skyhanni.data.ActionBarStatsData
import at.hannibal2.skyhanni.data.BitsAPI
import at.hannibal2.skyhanni.data.BlockData
import at.hannibal2.skyhanni.data.BossbarData
-import at.hannibal2.skyhanni.data.ChatManager
import at.hannibal2.skyhanni.data.CropAccessoryData
import at.hannibal2.skyhanni.data.EntityData
import at.hannibal2.skyhanni.data.EntityMovementData
@@ -453,6 +452,7 @@ import at.hannibal2.skyhanni.features.stranded.HighlightPlaceableNpcs
import at.hannibal2.skyhanni.features.summonings.SummoningMobManager
import at.hannibal2.skyhanni.features.summonings.SummoningSoulsName
import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper
+import at.hannibal2.skyhanni.skyhannimodule.LoadedModules
import at.hannibal2.skyhanni.test.HighlightMissingRepoItems
import at.hannibal2.skyhanni.test.PacketTest
import at.hannibal2.skyhanni.test.ParkourWaypointSaver
@@ -512,9 +512,10 @@ class SkyHanniMod {
HotswapSupport.load()
- // data
loadModule(this)
- loadModule(ChatManager)
+ LoadedModules.modules.forEach { loadModule(it) }
+
+ // data
loadModule(PlayerChatManager())
loadModule(PlayerNameFormatter())
loadModule(HypixelData())
@@ -1007,9 +1008,13 @@ class SkyHanniMod {
} catch (e: Exception) {
Exception("Error reading repo data", e).printStackTrace()
}
+ loadedClasses.clear()
}
+ private val loadedClasses = mutableSetOf<Any>()
+
fun loadModule(obj: Any) {
+ if (!loadedClasses.add(obj.javaClass.name)) throw IllegalStateException("Module ${obj.javaClass.name} is already loaded")
modules.add(obj)
MinecraftForge.EVENT_BUS.register(obj)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
index 112c29f17..ef032f6fc 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
@@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.MessageSendToServerEvent
import at.hannibal2.skyhanni.events.PacketEvent
import at.hannibal2.skyhanni.features.chat.ChatFilterGui
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.IdentityCharacteristics
import at.hannibal2.skyhanni.utils.LorenzLogger
@@ -26,6 +27,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.relauncher.ReflectionHelper
import java.lang.invoke.MethodHandles
+@SkyHanniModule
object ChatManager {
private val loggerAll = LorenzLogger("chat/all")