From de98500a3a69062e544e133a48a91722891fe458 Mon Sep 17 00:00:00 2001 From: Username404 Date: Tue, 18 May 2021 22:14:35 +0200 Subject: [PATCH] Begin adding a macro system --- build.gradle.kts | 20 ++++++++++++++---- common/build.gradle.kts | 1 - .../snowygui/config/Configuration.kt | 21 +++++++++++++++++++ .../snowygui/gui/feature/ButtonImpl.kt | 12 ++++++++--- .../snowygui/gui/feature/ButtonInfo.kt | 3 +++ .../username404/snowygui/gui/feature/Macro.kt | 11 ++++++++++ .../username404/snowygui/fabric/FabricInit.kt | 2 +- forge/build.gradle.kts | 5 ++++- .../username404/snowygui/forge/ForgeInit.kt | 6 ++++-- gradle.properties | 1 + 10 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 common/src/main/kotlin/fr/username404/snowygui/gui/feature/Macro.kt diff --git a/build.gradle.kts b/build.gradle.kts index a4d51e3..e9011f1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,6 +11,7 @@ buildscript { plugins { kotlin("jvm") version "1.5.0" + kotlin("plugin.serialization") version "1.5.0" id("com.github.johnrengelman.shadow") version "6.1.0" apply false id("architectury-plugin") version "[3.0.100, 3.3[" id("dev.architectury.loom") version "0.7.2.110" apply false @@ -31,7 +32,6 @@ val kotlinX: String = "org.jetbrains.kotlinx" subprojects { group = rootProject.group.toString() lateinit var mappingsDep: Dependency - apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "dev.architectury.loom") apply(plugin = "com.github.johnrengelman.shadow") val shadowC by configurations.creating @@ -46,7 +46,7 @@ subprojects { keep("class $group.snowygui.fabric.**") keep("class $group.snowygui.forge.**") keepnames("class $group.snowygui.Snowy") - keep("class $group.snowygui.gui.feature.** { public static *** INSTANCE; }") + keep("class $group.snowygui.gui.feature.* { public static *** INSTANCE; }") keepclassmembers("class $group.snowygui.** { public protected ; }") keepattributes("*Annotation*, Signature, InnerClasses, EnclosingMethod, MethodParameters, Synthetic, Exceptions") obfuscationdictionary("$dictionariesDir/dictionary.txt") @@ -55,8 +55,15 @@ subprojects { flattenpackagehierarchy("$group.snowygui") allowaccessmodification() adaptclassstrings() - dontnote("$group.**") - dontwarn("java.**") + "$group.**".also { dontnote(it); dontwarn(it) } + + // kotlinx-serialization related configuration: + dontnote("kotlinx.serialization.AnnotationsKt") + keepclasseswithmembers("class kotlinx.serialization.json.** { kotlinx.serialization.KSerializer serializer(...); }") + keep(mapOf("includedescriptorclasses" to true), "class $group.snowygui.**$\$serializer { * ; }") + keepclassmembers("class $group.snowygui.** { *** Companion; }") + keepclasseswithmembers("class $group.snowygui.** { kotlinx.serialization.KSerializer serializer(...); }") + val homeDir = System.getProperty("java.home") as String libraryjars(configurations.compileClasspath.get().filter { file -> listOf( @@ -111,13 +118,18 @@ allprojects { } **/ apply(plugin = "java") + apply(plugin = "org.jetbrains.kotlin.jvm") + apply(plugin = "org.jetbrains.kotlin.plugin.serialization") apply(plugin = "architectury-plugin") java { sourceCompatibility = JavaVersion.VERSION_11 } + val serializationVer: String by rootProject dependencies { implementation(kotlin("stdlib-jdk8", kotlinVer)) implementation(kotlin("reflect", kotlinVer)) + implementation("$kotlinX:kotlinx-serialization-core:$serializationVer") + implementation("$kotlinX:kotlinx-serialization-json:$serializationVer") annotationProcessor("com.github.bsideup.jabel:jabel-javac-plugin:0.3.0") { listOf("byte-buddy", "byte-buddy-agent").forEach { exclude(module = it) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 1795a83..d655510 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,6 +1,5 @@ architectury { common(); injectInjectables = false } dependencies { modImplementation("net.fabricmc:fabric-loader:${rootProject.property("fabric_loader_version")}") - implementation(kotlin("reflect")) } diff --git a/common/src/main/kotlin/fr/username404/snowygui/config/Configuration.kt b/common/src/main/kotlin/fr/username404/snowygui/config/Configuration.kt index dc92b23..062789f 100644 --- a/common/src/main/kotlin/fr/username404/snowygui/config/Configuration.kt +++ b/common/src/main/kotlin/fr/username404/snowygui/config/Configuration.kt @@ -8,15 +8,21 @@ import com.typesafe.config.ConfigValueFactory import fr.username404.snowygui.ClickGui import fr.username404.snowygui.Snowy import fr.username404.snowygui.gui.feature.ButtonImpl +import fr.username404.snowygui.gui.feature.Macro import io.github.config4k.extract import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import net.minecraft.client.Minecraft import java.io.File +import java.nio.charset.Charset object Configuration { private val file: File = File(Minecraft.getInstance().gameDirectory.absolutePath + File.separator + "snowy.conf") + private val macroFile: File = File(Minecraft.getInstance().gameDirectory.absolutePath + File.separator + "snowy-macros.json") private suspend fun writeConfig(c: Config) = coroutineScope { launch { file.writeText( @@ -67,6 +73,12 @@ object Configuration { val enabledFeatures: MutableMap = if (obtained.hasPath("enabledFeatures")) { obtained.extract("enabledFeatures") } else mutableMapOf() + val macros: MutableSet = run { + if (!macroFile.exists()) macroFile.createNewFile() + macroFile.readLines(Charset.forName("UTF-8")).map { + Json.decodeFromString(it) + }.toMutableSet() + } init { Runtime.getRuntime().addShutdownHook( Thread { @@ -80,6 +92,15 @@ object Configuration { } ) } + macros.map { Json.encodeToString(it) }.forEachIndexed { index, s -> + with(macroFile) { + "$s\n".let { + if (index == 0) { + writeText(it) + } else appendText(it) + } + } + } writeConfig(obtained.withValue("enabledFeatures", ConfigValueFactory.fromMap(enabledFeatures))).join() // TODO Fix formatting of enabledFeatures } } diff --git a/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonImpl.kt b/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonImpl.kt index 88f38a3..58a5130 100644 --- a/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonImpl.kt +++ b/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonImpl.kt @@ -18,6 +18,11 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) { fun initialize() { done = true Snowy.annotatedButtons.forEach { // Initializes every button + fun addToButtons(buttonImpl: ButtonImpl) { + ClickGui.components.filterIsInstance().find { box -> + box.name!!.key == buttonImpl.info.parent.translationKey + }?.buttons!!.add(buttonImpl) + } ((try { it.getConstructor().newInstance() } catch (e: NoSuchMethodException) { @@ -30,9 +35,10 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) { } } } - ClickGui.components.filterIsInstance().find { box -> - box.name!!.key == impl.info.parent.translationKey - }?.buttons!!.add(impl) + addToButtons(impl) + } + Configuration.macros.forEach { macro -> + addToButtons(macro) } } } diff --git a/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonInfo.kt b/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonInfo.kt index df8f5ee..a938e7b 100644 --- a/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonInfo.kt +++ b/common/src/main/kotlin/fr/username404/snowygui/gui/feature/ButtonInfo.kt @@ -4,6 +4,9 @@ import fr.username404.snowygui.ClickGui import fr.username404.snowygui.gui.elements.ClickBox import net.minecraft.network.chat.TranslatableComponent +/** + * Should be used on classes/objects extending [ButtonImpl] +**/ @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) annotation class ButtonInfo( diff --git a/common/src/main/kotlin/fr/username404/snowygui/gui/feature/Macro.kt b/common/src/main/kotlin/fr/username404/snowygui/gui/feature/Macro.kt new file mode 100644 index 0000000..3553984 --- /dev/null +++ b/common/src/main/kotlin/fr/username404/snowygui/gui/feature/Macro.kt @@ -0,0 +1,11 @@ +package fr.username404.snowygui.gui.feature + +import net.minecraft.client.Minecraft +import kotlinx.serialization.* +import fr.username404.snowygui.gui.feature.ButtonInfo.Companion.Type + +@Serializable +@ButtonInfo(Category.MACROS, kind = Type.CLICK) +data class Macro(private val command: String): ButtonImpl() { + override fun execAction() = Minecraft.getInstance().player!!.chat("/$command") +} \ No newline at end of file diff --git a/fabric/src/main/kotlin/fr/username404/snowygui/fabric/FabricInit.kt b/fabric/src/main/kotlin/fr/username404/snowygui/fabric/FabricInit.kt index 024899e..9d6433a 100644 --- a/fabric/src/main/kotlin/fr/username404/snowygui/fabric/FabricInit.kt +++ b/fabric/src/main/kotlin/fr/username404/snowygui/fabric/FabricInit.kt @@ -29,6 +29,6 @@ class FabricInit: Snowy(), ClientModInitializer { .setUrls(ClasspathHelper.forPackage(FeaturePackage)) .setScanners(SubTypesScanner(false), TypeAnnotationsScanner()) .useParallelExecutor() - ).getTypesAnnotatedWith(ButtonInfo::class.java) + ).getTypesAnnotatedWith(ButtonInfo::class.java).filterNot { it.kotlin.isAbstract || it.kotlin.isData; }.toSet() } } \ No newline at end of file diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 85503e3..2b67623 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -2,12 +2,15 @@ architectury { platformSetupLoomIde(); forge() } repositories { maven(url = "https://thedarkcolour.github.io/KotlinForForge/") } + +val serializationVer: String by rootProject dependencies { forge("net.minecraftforge:forge:${rootProject.architectury.minecraft}-${rootProject.property("forge_version")}.+") implementation("thedarkcolour:kotlinforforge:${rootProject.property("kotlinforforge")}.0") implementation(project(path = ":common")) { isTransitive = false } add("developmentForge", project(path = ":common")) { isTransitive = false } - shadowC("org.jetbrains.kotlinx:kotlinx-serialization-core:1.2.1") { isTransitive = false } + shadowC("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVer") { isTransitive = false } + shadowC("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVer") { isTransitive = false } shadowC(project(path = ":common", configuration = "transformProductionForge")) { isTransitive = false } }; loom { useFabricMixin = true diff --git a/forge/src/main/kotlin/fr/username404/snowygui/forge/ForgeInit.kt b/forge/src/main/kotlin/fr/username404/snowygui/forge/ForgeInit.kt index 2a524bb..9e2ea0c 100644 --- a/forge/src/main/kotlin/fr/username404/snowygui/forge/ForgeInit.kt +++ b/forge/src/main/kotlin/fr/username404/snowygui/forge/ForgeInit.kt @@ -41,8 +41,10 @@ class ForgeInit: Snowy() { .filter { data: ModFileScanData.ClassData? -> (data!!.javaClass.getDeclaredField("clazz").apply { isAccessible = true }.get(data) as Type).className.let { classname -> classname.startsWith(FeaturePackage).let { - it && Class.forName(classname).declaredAnnotations.any { annotation -> - annotation is ButtonInfo + it && with(Class.forName(classname)) { + !kotlin.isAbstract && !kotlin.isData && declaredAnnotations.any { annotation -> + annotation is ButtonInfo + } } } } diff --git a/gradle.properties b/gradle.properties index 1dbf2b5..017188a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,6 +11,7 @@ minecraft=1.16.5 forge_version=36.1 kotlinforforge=1.12 kotlin_stdlib_version=1.5 +serializationVer=1.2.1 fabric_loader_version=0.11.3 fabric_language_kotlin=1.6.0+kotlin.1.5.0 fabric_resource_loader_version=0.2.5+059ea8667c