Compare commits

...

45 Commits
1.18 ... 1.21

Author SHA1 Message Date
Username404-59 12e2e4a1d8
Fix scrolling
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 22:57:20 +01:00
Username404-59 8003a86242
Use the right bus for miscellaneous handlers too
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 22:02:24 +01:00
Username404-59 83b82ba1d9
OOPS! use the mod event bus for initialisation
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 21:54:30 +01:00
Username404-59 e93e06ca97
Use the right event bus on neoforge
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 21:47:51 +01:00
Username404-59 82ace01131
Revert to using buildDir
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 21:31:40 +01:00
Username404-59 930cbc2f6a
Replace OptionValueAccessor.java with an access widener to make it work fine on forge
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 20:56:17 +01:00
Username404-59 9503ac000b
Move KeyMappings and KeyAccessor to fabric, to replace them using a RegisterKeyMappingsEvent in neoforge
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 19:54:44 +01:00
Username404-59 2fa0575f68
Move TitleScreenMixin to fabric, to replace it using a RegisterMenuScreensEvent in neoforge
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 19:48:02 +01:00
Username404-59 febeddb093
Move EndTickMixin to fabric, to replace it using a ClientTickEvent in neoforge
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 19:36:04 +01:00
Username404-59 b4574ef5b8
Fix neoforge.mods.toml
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 18:43:40 +01:00
Username404-59 dc286683a5
Switch to architectury-loom 1.7, fix the port to 1.21
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 18:43:40 +01:00
Username404-59 6535278331
Make mixin compatibility levels higher
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 16:17:22 +01:00
Username404-59 95b912c308
Remove a unused import in Snowy.kt
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 16:05:53 +01:00
Username404-59 48b8904b4d
Accept even more recent proguard versions
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 16:01:03 +01:00
Username404-59 bf317e38f0
Finish porting to 1.21
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-02-02 15:58:22 +01:00
Username404 c506c9a9d2
Port to 1.21
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-07-18 18:16:21 +02:00
Username404-59 0db5d80cf1
Bump the version to 0.3.5
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-07-18 17:52:13 +02:00
Username404-59 d44f871335
ClickGui.kt: Fix moving clickboxes
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-07-18 17:50:21 +02:00
Username404-59 d60d506c6c
Fix indentation errors in ClickBox.kt
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-05-25 17:55:29 +02:00
Username404-59 c58eee6631
Fix font rendering
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-05-25 17:53:15 +02:00
Username404-59 c204db0d47
Remove a useless import in Keystrokes.kt
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-05-24 23:10:38 +02:00
Username404-59 aebff3e15e
Depend on the right forge version
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-05-24 23:10:37 +02:00
Username404-59 01c420b4cc
Update dependencies
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-05-24 23:10:37 +02:00
Username404-59 bc10ffa2cf
Update gradle
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2024-05-24 23:10:37 +02:00
Username404 5563e59603
Update parchment mappings
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:45:09 +01:00
Username404 2772d52217
Port to 1.20
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:45:09 +01:00
Username404 f4834255ec
Port to 1.19.4
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:45:07 +01:00
Username404 771820f72f
Use 22w16b versions of dependencies
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:43:20 +01:00
Username404 45c3fe54e8
Update to minecraft 1.18.1
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:43:14 +01:00
Username404 40d9ee1605
Set the kotlinforforge dependency to 2.0.1 since older versions won't work on minecraft 1.17+ 2024-02-25 15:41:18 +01:00
Username404-59 119b75811f
Update to minecraft 1.17 2024-02-25 15:41:17 +01:00
Username404 0f28ac6b33
Update parchment mappings
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 36cf819f02
Fix the previous commit
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 9e0214acd9
Fix versions in fabric.mod.json and mods.toml
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 4df3066134
Remove a useless init block in ClickBox.kt
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 76b28db14b
Remove redundant kotlinx.coroutines usage in ClickBox.kt
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 312b875267
Supress a warning in GammaBoost.kt
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 f8ae9f1ad1
Use a project dependency instead of a specific version when publishing to modrinth
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 840e041817
Use a different function to replace /say when permissions are not high enough
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 65d8aa75ee
Remove a null check in SnowyScreen
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:54 +01:00
Username404 24c99cd79e
Remove a now useless Suppress annotation
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:53 +01:00
Username404 ed9ccc399f
Set JAVA_HOME
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:53 +01:00
Username404 7574605480
Port to 1.19.4
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 15:02:52 +01:00
Username404 3d5b6133e5
Incomplete port to 22w16b
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 14:55:55 +01:00
Username404 0a2175c2e1
Use 22w16b versions of dependencies
Signed-off-by: Username404 <w.iron.zombie@gmail.com>
2024-02-25 14:55:55 +01:00
48 changed files with 366 additions and 306 deletions

3
Jenkinsfile vendored
View File

@ -1,5 +1,8 @@
pipeline { pipeline {
agent any agent any
environment {
JAVA_HOME='/usr/lib/jvm/temurin-17-jdk-amd64/'
}
options { options {
buildDiscarder(logRotator(numToKeepStr: '48', artifactNumToKeepStr: '96')) buildDiscarder(logRotator(numToKeepStr: '48', artifactNumToKeepStr: '96'))

View File

@ -1,23 +1,24 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.modrinth.minotaur.ModrinthExtension import com.modrinth.minotaur.ModrinthExtension
import com.modrinth.minotaur.request.VersionType
import com.modrinth.minotaur.dependencies.DependencyType import com.modrinth.minotaur.dependencies.DependencyType
import masecla.modrinth4j.model.version.ProjectVersion.VersionType
import net.fabricmc.loom.LoomGradleExtension import net.fabricmc.loom.LoomGradleExtension
import net.fabricmc.loom.api.LoomGradleExtensionAPI
buildscript { buildscript {
dependencies { dependencies {
classpath("com.guardsquare:proguard-gradle:[7.4, 7.5[") { classpath("com.guardsquare:proguard-gradle:[7.5, 7.7[") {
exclude("com.android.tools.build") exclude("com.android.tools.build")
} }
} }
} }
plugins { plugins {
kotlin("jvm") version "1.9.22" kotlin("jvm") version "2.0.0"
kotlin("plugin.serialization") version "1.9.22" kotlin("plugin.serialization") version "2.0.0"
id("com.github.johnrengelman.shadow") version "8.1.1" apply false id("com.github.johnrengelman.shadow") version "8.1.1" apply false
id("architectury-plugin") version "[3.4.124, 3.5[" id("architectury-plugin") version "[3.4.160, 3.5["
id("dev.architectury.loom") version "1.4-SNAPSHOT" apply false id("dev.architectury.loom") version "1.7-SNAPSHOT" apply false
id("com.github.ben-manes.versions") version "0.51.0" id("com.github.ben-manes.versions") version "0.51.0"
id("net.kyori.indra.git") version "3.1.3" id("net.kyori.indra.git") version "3.1.3"
id("org.cqfn.diktat.diktat-gradle-plugin") version "1.2.5" id("org.cqfn.diktat.diktat-gradle-plugin") version "1.2.5"
@ -25,17 +26,17 @@ plugins {
} }
group = "fr.username404" group = "fr.username404"
version = "0.3.4" version = "0.3.5"
val groupAndName = "${rootProject.group}.${rootProject.name.toLowerCase()}" val groupAndName = "${rootProject.group}.${rootProject.name.lowercase()}"
val javaVer: String = "17" val javaVer: String = "21"
val sourceJavaVer: String = javaVer val sourceJavaVer: String = javaVer
val kotlinVer: String by rootProject val kotlinVer: String by rootProject
val kotlinSplitVersion = kotlinVer.split('.') val kotlinSplitVersion = kotlinVer.split('.')
val serializationVer: String by rootProject val serializationVer: String by rootProject
val mcBase: String = (rootProject.property("minecraft") as String).also { val minecraftVersion: String = (rootProject.property("minecraft") as String).also {
architectury { minecraft = it } architectury { minecraft = it }
}.substring(0..3) }
val kotlinX: String = "org.jetbrains.kotlinx" val kotlinX: String = "org.jetbrains.kotlinx"
subprojects { subprojects {
@ -50,18 +51,17 @@ subprojects {
apply(plugin = "dev.architectury.loom") apply(plugin = "dev.architectury.loom")
apply(plugin = "org.jetbrains.kotlin.plugin.serialization") apply(plugin = "org.jetbrains.kotlin.plugin.serialization")
extensions.configure<LoomGradleExtension>("loom") { extensions.configure<LoomGradleExtension>("loom") {
mappingsDep = layered { if (this@subprojects.project.name != "common") {
officialMojangMappings().parchment("org.parchmentmc.data:parchment-${rootProject.architectury.minecraft}:2022.02.13") accessWidenerPath.set(project(":common").extensions.getByType<LoomGradleExtensionAPI>().accessWidenerPath)
} }
mappingsDep = layered {
silentMojangMappingsLicense() silentMojangMappingsLicense()
officialMojangMappings().parchment("org.parchmentmc.data:parchment-1.21:2024.06.23")
}
val refmap = "snowygui-${project.name}-refmap.json" val refmap = "snowygui-${project.name}-refmap.json"
mixin { mixin {
defaultRefmapName.set(refmap) useLegacyMixinAp = true
if (isForge) { defaultRefmapName = refmap
forge {
mixinConfigs("snowygui-common.mixins.json", "snowygui-forge.mixins.json")
}
}
} }
} }
apply(plugin = "com.github.johnrengelman.shadow") apply(plugin = "com.github.johnrengelman.shadow")
@ -75,8 +75,8 @@ subprojects {
implementation("$kotlinX:kotlinx-serialization-core:$serializationVer") implementation("$kotlinX:kotlinx-serialization-core:$serializationVer")
implementation("$kotlinX:kotlinx-serialization-json:$serializationVer") implementation("$kotlinX:kotlinx-serialization-json:$serializationVer")
listOf( listOf(
"com.typesafe:config:1.4.2", "com.typesafe:config:1.4.3",
"io.github.config4k:config4k:0.4.2", "io.github.config4k:config4k:0.6.0",
"com.github.Vatuu:discord-rpc:1.6.2" "com.github.Vatuu:discord-rpc:1.6.2"
).forEach { implementation(it); shadowC(it) { isTransitive = false; exclude("com.sun.jna") } } ).forEach { implementation(it); shadowC(it) { isTransitive = false; exclude("com.sun.jna") } }
"minecraft"("com.mojang:minecraft:${rootProject.property("minecraft")}") "minecraft"("com.mojang:minecraft:${rootProject.property("minecraft")}")
@ -86,8 +86,8 @@ subprojects {
extensions.configure<ModrinthExtension>("modrinth") { extensions.configure<ModrinthExtension>("modrinth") {
projectId.set("OuGyGg6A") projectId.set("OuGyGg6A")
syncBodyFrom.set("$rootDir/README.md") syncBodyFrom.set("$rootDir/README.md")
gameVersions.add(mcBase) gameVersions.add(minecraftVersion)
if (project.name == "forge") dependencies.add(com.modrinth.minotaur.dependencies.VersionDependency("Bxm9xbNJ", DependencyType.REQUIRED)) // Kotlinforforge dependency if (project.name == "forge") dependencies.add(com.modrinth.minotaur.dependencies.ModDependency("ordsPcFz", DependencyType.REQUIRED)) // Kotlinforforge dependency
versionNumber.set(rootProject.version.toString() + "-${project.name}") versionNumber.set(rootProject.version.toString() + "-${project.name}")
versionType.set(VersionType.ALPHA.name) versionType.set(VersionType.ALPHA.name)
detectLoaders.set(false) detectLoaders.set(false)
@ -134,6 +134,7 @@ subprojects {
flattenpackagehierarchy("$group.snowygui") flattenpackagehierarchy("$group.snowygui")
allowaccessmodification() allowaccessmodification()
adaptclassstrings() adaptclassstrings()
dontnote() // This is needed to silence warnings about duplicate classes
"$group.**".also { dontnote(it); dontwarn(it) } "$group.**".also { dontnote(it); dontwarn(it) }
// kotlinx-serialization related configuration: // kotlinx-serialization related configuration:
@ -169,9 +170,9 @@ subprojects {
dependsOn(shrinkJar) dependsOn(shrinkJar)
val shrinkedJar = shrinkJar.get().outJarFileCollection.singleFile val shrinkedJar = shrinkJar.get().outJarFileCollection.singleFile
archiveBaseName.set(shadowJar.archiveBaseName) archiveBaseName.set(shadowJar.archiveBaseName)
archiveVersion.set("[${rootProject.version}+$mcBase]") archiveVersion.set("[${rootProject.version}+$minecraftVersion]")
archiveClassifier.set(this@subprojects.name) archiveClassifier.set(this@subprojects.name)
input.set(shrinkedJar) inputFile.set(shrinkedJar)
if (!archiveFileName.get().contains("common")) destinationDirectory.set(file("$rootDir/remappedJars")) if (!archiveFileName.get().contains("common")) destinationDirectory.set(file("$rootDir/remappedJars"))
} }
getByName("modrinth").dependsOn(build) getByName("modrinth").dependsOn(build)
@ -206,9 +207,10 @@ allprojects {
"-Xbackend-threads=0", "-Xno-param-assertions", "-Xno-call-assertions", "-Xbackend-threads=0", "-Xno-param-assertions", "-Xno-call-assertions",
"-opt-in=kotlin.RequiresOptIn", "-Xextended-compiler-checks", "-Xassertions=jvm", "-progressive" "-opt-in=kotlin.RequiresOptIn", "-Xextended-compiler-checks", "-Xassertions=jvm", "-progressive"
) )
jvmTarget = if (javaVer.toInt() < 9) "1.$javaVer" else javaVer jvmTarget = javaVer
languageVersion = (kotlinSplitVersion[0] + '.' + (kotlinSplitVersion[1].toShort() + 1).toString()) // Uncomment when updating to architectury-loom 1.9
apiVersion = "${kotlinSplitVersion[0]}.${kotlinSplitVersion[1]}" //languageVersion = (kotlinSplitVersion[0] + '.' + (kotlinSplitVersion[1].toShort() + 1).toString())
//apiVersion = "${kotlinSplitVersion[0]}.${kotlinSplitVersion[1]}"
} }
} }
withType(JavaCompile::class) { withType(JavaCompile::class) {
@ -216,7 +218,7 @@ allprojects {
encoding = "UTF-8" encoding = "UTF-8"
isFork = true isFork = true
release.set(javaVer.toInt()) release.set(javaVer.toInt())
sourceCompatibility = "11" sourceCompatibility = sourceJavaVer
targetCompatibility = javaVer targetCompatibility = javaVer
} }
} }
@ -228,12 +230,14 @@ allprojects {
} }
val modProperties = mapOf( val modProperties = mapOf(
"mod_version" to (rootProject.version as String), "mod_version" to (rootProject.version as String),
"minecraft_version" to mcBase, "minecraft_version" to minecraftVersion,
"java_version" to javaVer, "java_version" to javaVer,
"mod_group" to this@allprojects.group, "mod_group" to this@allprojects.group,
"fabric_kotlin" to rootProject.property("fabric_language_kotlin"), "fabric_kotlin" to rootProject.property("fabric_language_kotlin"),
"kotlinforforge" to rootProject.property("kotlinforforge"), "kotlinforforge" to rootProject.property("kotlinforforge"),
"clothconfig" to rootProject.property("clothconfig_version") "clothconfig" to rootProject.property("clothconfig_version"),
"fabric_loader" to rootProject.property("fabric_loader_version"),
"forge_version" to rootProject.property("forge_version")
) )
inputs.properties(modProperties) inputs.properties(modProperties)
filesNotMatching(listOf("*.png")) { filesNotMatching(listOf("*.png")) {

View File

@ -1,4 +1,4 @@
architectury { common(); injectInjectables = false } architectury { common("fabric", "neoforge"); injectInjectables = false }
dependencies { dependencies {
modImplementation("net.fabricmc:fabric-loader:${rootProject.property("fabric_loader_version")}") modImplementation("net.fabricmc:fabric-loader:${rootProject.property("fabric_loader_version")}")
modImplementation("me.shedaniel.cloth:cloth-config:${rootProject.property("clothconfig_version")}") { modImplementation("me.shedaniel.cloth:cloth-config:${rootProject.property("clothconfig_version")}") {
@ -6,4 +6,8 @@ dependencies {
} }
} }
loom {
accessWidenerPath = file("src/main/resources/${rootProject.name.lowercase()}.accessWidener")
}
tasks.getByName("shrinkJar").enabled = false tasks.getByName("shrinkJar").enabled = false

View File

@ -14,17 +14,29 @@ object ClickGui: SnowyScreen() {
private inline fun buttonsContext(args: ColoredElement.() -> Unit) = boxContext { buttons.forEach { private inline fun buttonsContext(args: ColoredElement.() -> Unit) = boxContext { buttons.forEach {
if (it.y > y + height) it.args() if (it.y > y + height) it.args()
} } } }
override fun mouseClicked(d: Double, e: Double, i: Int): Boolean { buttonsContext { this.mouseClicked(d, e, i) }; return false }
override fun mouseReleased(d: Double, e: Double, i: Int): Boolean { buttonsContext { this.mouseReleased(d, e, i) }; return false } private var draggingBox: String? = null
override fun mouseScrolled(d: Double, e: Double, f: Double): Boolean { boxContext { scroll(d, e, f) }; return false } private inline fun currentBoxContext(args: ClickBox.() -> Unit): Unit? = draggingBox?.run { boxContext { if (name.string == draggingBox) args() } }
private var offsetX: Double = 0.0;
private var offsetY: Double = 0.0;
override fun mouseClicked(d: Double, e: Double, i: Int): Boolean {
if (i == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
clickBoxes.find { it.isWithinBounds(d, e) }?.let { draggingBox = it.name.string }
currentBoxContext {
offsetX = d - (x + width)
offsetY = e - (y + height)
}
}
buttonsContext { this.mouseClicked(d, e, i) }; return super.mouseClicked(d, e, i);
}
override fun mouseReleased(d: Double, e: Double, i: Int): Boolean { draggingBox = null; buttonsContext { this.mouseReleased(d, e, i) }; return false }
override fun mouseScrolled(d: Double, e: Double, f: Double, scrollY: Double): Boolean { boxContext { scroll(d, e, scrollY) }; return false }
override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double): Boolean { override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double): Boolean {
if (i == GLFW.GLFW_MOUSE_BUTTON_LEFT) { if (i == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
components.forEach { currentBoxContext {
if (it.isWithinBounds(d.minus(f), e.minus(g)) && !isDragging) { x = (d + offsetX).coerceIn(0.0..this@ClickGui.width - width.toDouble())
isDragging = true y = (e + offsetY).coerceIn(0.0..this@ClickGui.height - height.toDouble())
it.x = d.minus(f) + (d - (it.x + it.width))
it.y = e.minus(g) + (e - (it.y + it.height))
} else isDragging = false
} }
} }
return super.mouseDragged(d, e, i, f, g) return super.mouseDragged(d, e, i, f, g)

View File

@ -4,7 +4,8 @@ import fr.username404.snowygui.config.Configuration
import fr.username404.snowygui.gui.feature.ButtonImpl import fr.username404.snowygui.gui.feature.ButtonImpl
import fr.username404.snowygui.gui.feature.ButtonInfo import fr.username404.snowygui.gui.feature.ButtonInfo
import fr.username404.snowygui.misc.AddKeyMaps import fr.username404.snowygui.misc.AddKeyMaps
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.network.chat.Component
import net.minecraft.network.chat.Component.translatable
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger import org.apache.logging.log4j.Logger
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
@ -15,8 +16,7 @@ abstract class Snowy {
private val displayInitMessage: Boolean by Configuration private val displayInitMessage: Boolean by Configuration
abstract val annotatedButtons: Set<Class<out ButtonImpl>> abstract val annotatedButtons: Set<Class<out ButtonImpl>>
companion object { companion object {
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") val MissingComponent: Component = translatable("MISSING_COMPONENT")
object MissingComponent: TranslatableComponent(null) { override fun getString(): String = "MISSING_COMPONENT" }
@Suppress("JVM_STATIC_ON_CONST_OR_JVM_FIELD") // See KT-39868 @Suppress("JVM_STATIC_ON_CONST_OR_JVM_FIELD") // See KT-39868
@JvmStatic @JvmStatic
protected const val FeaturePackage: String = "fr.username404.snowygui.gui.feature" protected const val FeaturePackage: String = "fr.username404.snowygui.gui.feature"

View File

@ -1,35 +1,31 @@
package fr.username404.snowygui.config package fr.username404.snowygui.config
import com.mojang.blaze3d.vertex.PoseStack
import fr.username404.snowygui.ClickGui import fr.username404.snowygui.ClickGui
import fr.username404.snowygui.utils.FontUtil
import fr.username404.snowygui.gui.elements.ClickBox import fr.username404.snowygui.gui.elements.ClickBox
import fr.username404.snowygui.gui.elements.ClickBox.Companion.buttonsMax import fr.username404.snowygui.gui.elements.ClickBox.Companion.buttonsMax
import fr.username404.snowygui.gui.elements.ClickBox.Companion.sortAlphabetically import fr.username404.snowygui.gui.elements.ClickBox.Companion.sortAlphabetically
import fr.username404.snowygui.gui.feature.Category import fr.username404.snowygui.gui.feature.*
import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.utils.FontUtil
import fr.username404.snowygui.gui.feature.Macro import net.minecraft.client.gui.GuiGraphics
import fr.username404.snowygui.gui.feature.Keystrokes
import fr.username404.snowygui.gui.feature.Zoom
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.network.chat.Component.translatable
import java.util.Optional import java.util.Optional
private const val confPrefix: String = "screen.snowy.config" private const val confPrefix: String = "screen.snowy.config"
private val translationComponent = TranslatableComponent(confPrefix) private val translationComponent = translatable(confPrefix)
var configScreenParent: Screen? = null var configScreenParent: Screen? = null
private fun supplyComponent(string: String?): Optional<Component> = string?.run { private fun supplyComponent(string: String?): Optional<Component> = string?.run {
Optional.of(TranslatableComponent(string)) Optional.of(translatable(string))
} ?: Optional.empty() } ?: Optional.empty()
val SnowyConfigScreen: Screen = object: Screen(translationComponent) { val SnowyConfigScreen: Screen = object: Screen(translationComponent) {
override fun isPauseScreen(): Boolean = false override fun isPauseScreen(): Boolean = false
override fun render(poseStack: PoseStack, i: Int, j: Int, f: Float) { override fun render(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, pTick: Float) {
super.renderBackground(poseStack) super.renderBackground(guiGraphics, mouseX, mouseY, pTick)
FontUtil.drawScaled(poseStack, FontUtil.drawScaled(guiGraphics,
text = "An appropriate version of the Cloth Config mod is required for the configuration of snowygui.", 16.0, 16.0, text = "An appropriate version of the Cloth Config mod is required for the configuration of snowygui.", 16.0, 16.0,
color = Colors.WHITE, scaleFactor = 0.85F color = Colors.WHITE, scaleFactor = 0.85F
) )
@ -47,20 +43,20 @@ val SnowyConfigScreen: Screen = object: Screen(translationComponent) {
.setShouldListSmoothScroll(true) .setShouldListSmoothScroll(true)
.setTitle(translationComponent).apply { .setTitle(translationComponent).apply {
with(entryBuilder()) { with(entryBuilder()) {
getOrCreateCategory(TranslatableComponent("$confPrefix.general")).addEntry(startSubCategory(TranslatableComponent("$confPrefix.behavior")).apply { getOrCreateCategory(translatable("$confPrefix.general")).addEntry(startSubCategory(translatable("$confPrefix.behavior")).apply {
addAll( addAll(
setOf( setOf(
startBooleanToggle(TranslatableComponent("$confPrefix.behavior.sortalphabetically"), sortAlphabetically) startBooleanToggle(translatable("$confPrefix.behavior.sortalphabetically"), sortAlphabetically)
.setDefaultValue(true).requireRestart() .setDefaultValue(true).requireRestart()
.setSaveConsumer { sortAlphabetically = it }.build(), .setSaveConsumer { sortAlphabetically = it }.build(),
startDoubleField(TranslatableComponent("$confPrefix.behavior.zoom.factor"), Zoom.zoomFactor).setSaveConsumer { startDoubleField(translatable("$confPrefix.behavior.zoom.factor"), Zoom.zoomFactor).setSaveConsumer {
Zoom.zoomFactor = it Zoom.zoomFactor = it
}.setMin(1.1).build(), }.setMin(1.1).build(),
startBooleanToggle(TranslatableComponent("$confPrefix.behavior.zoom.smoothcamera"), Zoom.smoothCameraOnZoom).setSaveConsumer { startBooleanToggle(translatable("$confPrefix.behavior.zoom.smoothcamera"), Zoom.smoothCameraOnZoom).setSaveConsumer {
Zoom.smoothCameraOnZoom = it Zoom.smoothCameraOnZoom = it
Zoom.execAction() Zoom.execAction()
}.build(), }.build(),
startEnumSelector(TranslatableComponent("$confPrefix.behavior.keystrokes.position"), Keystrokes.Position::class.java, Keystrokes.Position.values().find { startEnumSelector(translatable("$confPrefix.behavior.keystrokes.position"), Keystrokes.Position::class.java, Keystrokes.Position.values().find {
it.value == Keystrokes.currentPosition it.value == Keystrokes.currentPosition
}).setSaveConsumer { }).setSaveConsumer {
Keystrokes.currentPosition = it.value Keystrokes.currentPosition = it.value
@ -68,7 +64,7 @@ val SnowyConfigScreen: Screen = object: Screen(translationComponent) {
) )
) )
}.build()) }.build())
.addEntry(startSubCategory(TranslatableComponent("$confPrefix.colors")).also { builder -> .addEntry(startSubCategory(translatable("$confPrefix.colors")).also { builder ->
builder.addAll( builder.addAll(
ClickGui.clickBoxes.map { box -> ClickGui.clickBoxes.map { box ->
startColorField(box.name, box.color).setSaveConsumer { startColorField(box.name, box.color).setSaveConsumer {
@ -77,7 +73,7 @@ val SnowyConfigScreen: Screen = object: Screen(translationComponent) {
} }
) )
}.build()).addEntry(startStrList( }.build()).addEntry(startStrList(
TranslatableComponent(Category.MACROS.translationKey), Category.MACROS.box.name,
macrosButtons.getTitleCommand() macrosButtons.getTitleCommand()
).setInsertInFront(false).setDefaultValue(Configuration.foundMacros.getTitleCommand()).setErrorSupplier { list -> ).setInsertInFront(false).setDefaultValue(Configuration.foundMacros.getTitleCommand()).setErrorSupplier { list ->
supplyComponent(if (list.size > buttonsMax) "$confPrefix.general.macros.toomuchbuttons" else null) supplyComponent(if (list.size > buttonsMax) "$confPrefix.general.macros.toomuchbuttons" else null)
@ -93,7 +89,7 @@ val SnowyConfigScreen: Screen = object: Screen(translationComponent) {
} }
) )
} }
}.setTooltip(TranslatableComponent("$confPrefix.general.macros.tooltip")).setSaveConsumer { it.forEach { string -> }.setTooltip(translatable("$confPrefix.general.macros.tooltip")).setSaveConsumer { it.forEach { string ->
with(string.split(":")) { with(string.split(":")) {
if (size == 2) Macro(title = component1().trimStart(), command = component2().trim()).let { newMacro -> if (size == 2) Macro(title = component1().trimStart(), command = component2().trim()).let { newMacro ->
macrosButtons.removeIf { existingMacro -> macrosButtons.removeIf { existingMacro ->

View File

@ -29,6 +29,8 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.TranslatableContents
import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.ApiStatus
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.isSuperclassOf import kotlin.reflect.full.isSuperclassOf
@ -46,9 +48,9 @@ object Configuration {
} }
}, },
"box_colors" to mapOf<String, Int>(*ClickGui.clickBoxes.filter { box -> "box_colors" to mapOf<String, Int>(*ClickGui.clickBoxes.filter { box ->
(box.name.key != MissingComponent.key) && Category.fromBox(box)?.categoryColor != box.color ((box.name.contents as TranslatableContents).key != (MissingComponent.contents as TranslatableContents).key) && Category.fromBox(box)?.categoryColor != box.color
}.map { }.map {
it.name.key to it.color (it.name as TranslatableContents).key to it.color
}.toTypedArray()), }.toTypedArray()),
) )
} }

View File

@ -4,11 +4,11 @@ import com.mojang.blaze3d.vertex.*
import fr.username404.snowygui.Snowy import fr.username404.snowygui.Snowy
import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.utils.RenderingUtil import fr.username404.snowygui.utils.RenderingUtil
import fr.username404.snowygui.utils.RenderingUtil.colorEnd import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.events.GuiEventListener import net.minecraft.client.gui.components.events.GuiEventListener
fun interface Renderable { fun interface Renderable {
fun render(poseStack: PoseStack?) fun render(guiGraphics: GuiGraphics?)
} }
abstract class Element( abstract class Element(
@ -19,17 +19,22 @@ abstract class Element(
open var x = xOrigin; open var y = yOrigin open var x = xOrigin; open var y = yOrigin
fun isWithinBounds(coordinateX: Double, coordinateY: Double, offsetWidth: Double = 0.0, offsetHeight: Double = 0.0): Boolean = fun isWithinBounds(coordinateX: Double, coordinateY: Double, offsetWidth: Double = 0.0, offsetHeight: Double = 0.0): Boolean =
(coordinateX in x..(x + width + offsetWidth)) && (coordinateY in y..(y + height + offsetHeight)) (coordinateX in x..(x + width + offsetWidth)) && (coordinateY in y..(y + height + offsetHeight))
@JvmField
protected var focused = false
override fun isFocused() = focused
override fun setFocused(boolean: Boolean) { focused = boolean }
companion object { companion object {
private var caughtError: Boolean = false private var caughtError: Boolean = false
fun fromRenderable(r: Renderable, x: Double, y: Double, width: Int, height: Int): Element { fun fromRenderable(r: Renderable, x: Double, y: Double, width: Int, height: Int): Element {
return object: Element(x, y, width, height) { return object: Element(x, y, width, height) {
override fun render(poseStack: PoseStack?) = r.render(poseStack) override fun render(guiGraphics: GuiGraphics?) = r.render(guiGraphics)
} }
} }
} }
open fun display(stack: PoseStack? = null) { open fun display(guiGraphics: GuiGraphics? = null) {
if (!hidden && !caughtError) try { if (!hidden && !caughtError) try {
render(stack) render(guiGraphics)
} catch (t: Throwable) { } catch (t: Throwable) {
with(Snowy.logs) { with(Snowy.logs) {
error("An element from snowy threw an error: \n\t$t") error("An element from snowy threw an error: \n\t$t")
@ -49,11 +54,11 @@ abstract class ColoredElement(
companion object { companion object {
@JvmStatic protected fun VertexConsumer.colorIt(color: Int, opacity: Float = 1F): VertexConsumer { @JvmStatic protected fun VertexConsumer.colorIt(color: Int, opacity: Float = 1F): VertexConsumer {
with(hextoRGB(color)) { with(hextoRGB(color)) {
return this@colorIt.color(get(0), get(1), get(2), opacity) return this@colorIt.setColor(get(0), get(1), get(2), opacity)
} }
} }
} }
internal fun VertexConsumer.colorEnd(color: Int = this@ColoredElement.color) = colorEnd(color, opacity) internal fun VertexConsumer.colorEnd(color: Int = this@ColoredElement.color) = colorIt(color, opacity)
protected fun defaultRectFunc() = RenderingUtil.drawRectangle(x, y, height, width, color, opacity) protected fun defaultRectFunc() = RenderingUtil.drawRectangle(x, y, height, width, color, opacity)
} }

View File

@ -1,16 +1,14 @@
package fr.username404.snowygui.gui package fr.username404.snowygui.gui
import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.network.chat.Component.translatable
abstract class SnowyScreen(translatableString: String = "screen.snowy.gui", private val willPauseScreen: Boolean = false): Screen(TranslatableComponent(translatableString)) { abstract class SnowyScreen(translatableString: String = "screen.snowy.gui", private val willPauseScreen: Boolean = false): Screen(translatable(translatableString)) {
abstract val components: MutableCollection<Element> abstract val components: MutableCollection<Element>
override fun render(poseStack: PoseStack?, i: Int, j: Int, f: Float) { override fun render(guiGraphics: GuiGraphics, i: Int, j: Int, f: Float) {
if (poseStack != null) {
components.forEach { components.forEach {
it.display(poseStack) it.display(guiGraphics)
}
} }
} }
override fun isPauseScreen(): Boolean = willPauseScreen override fun isPauseScreen(): Boolean = willPauseScreen

View File

@ -1,25 +1,23 @@
package fr.username404.snowygui.gui.elements package fr.username404.snowygui.gui.elements
import com.mojang.blaze3d.vertex.BufferUploader
import com.mojang.blaze3d.vertex.DefaultVertexFormat import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.VertexFormat
import fr.username404.snowygui.Snowy.Companion.MissingComponent import fr.username404.snowygui.Snowy.Companion.MissingComponent
import fr.username404.snowygui.config.Configuration import fr.username404.snowygui.config.Configuration
import com.mojang.blaze3d.vertex.VertexFormat
import fr.username404.snowygui.gui.ColoredElement import fr.username404.snowygui.gui.ColoredElement
import fr.username404.snowygui.gui.feature.ButtonImpl import fr.username404.snowygui.gui.feature.ButtonImpl
import fr.username404.snowygui.gui.feature.Category import fr.username404.snowygui.gui.feature.Category
import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.utils.RenderingUtil.buffer
import fr.username404.snowygui.utils.RenderingUtil.colorShader import fr.username404.snowygui.utils.RenderingUtil.colorShader
import fr.username404.snowygui.utils.RenderingUtil.endDraw import fr.username404.snowygui.utils.RenderingUtil.endDraw
import fr.username404.snowygui.utils.RenderingUtil.prepareDraw import fr.username404.snowygui.utils.RenderingUtil.prepareDraw
import fr.username404.snowygui.utils.RenderingUtil.tessellator import fr.username404.snowygui.utils.RenderingUtil.tessellator
import io.github.config4k.extract import io.github.config4k.extract
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.client.gui.Font
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.network.chat.Component
import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.ApiStatus
import java.util.TreeSet import java.util.TreeSet
import kotlin.collections.LinkedHashSet import kotlin.collections.LinkedHashSet
@ -27,17 +25,17 @@ import kotlin.collections.LinkedHashSet
@ApiStatus.Internal @ApiStatus.Internal
class ClickBox( class ClickBox(
x: Double, y: Double, x: Double, y: Double,
override var color: Int = Colors.BLUE.hexValue, val name: Component = MissingComponent,
val name: TranslatableComponent = MissingComponent override var color: Int = savedColors?.get(name.string) ?: Colors.BLUE.hexValue,
): ColoredElement(x, y, 80, 10, color, 0.5F) { ): ColoredElement(x, y, 80, 10, color, 0.5F) {
fun isCategory(c: Category): Boolean = (name.key == c.translationKey) fun isCategory(c: Category): Boolean = (name.string == c.box.name.string)
val buttons: MutableSet<ButtonImpl> = val buttons: MutableSet<ButtonImpl> =
if (sortAlphabetically) if (sortAlphabetically)
TreeSet(compareBy(String.CASE_INSENSITIVE_ORDER) { it.title }) TreeSet(compareBy(String.CASE_INSENSITIVE_ORDER) { it.title })
else LinkedHashSet() else LinkedHashSet()
override fun display(stack: PoseStack?) { override fun display(guiGraphics: GuiGraphics?) {
hidden = buttons.isEmpty() || hidden hidden = buttons.isEmpty() || hidden
super.display(stack) super.display(guiGraphics)
} }
@JvmField @JvmField
@ -47,7 +45,7 @@ class ClickBox(
opacity = 0.75F opacity = 0.75F
) { ) {
override val color: Int get() = this@ClickBox.color override val color: Int get() = this@ClickBox.color
override fun render(poseStack: PoseStack?) { override fun render(guiGraphics: GuiGraphics?) {
prepareDraw() prepareDraw()
colorShader(); defaultRectFunc() colorShader(); defaultRectFunc()
endDraw() endDraw()
@ -77,57 +75,56 @@ class ClickBox(
var sortAlphabetically: Boolean by Configuration var sortAlphabetically: Boolean by Configuration
const val buttonsMax: Short = 16 // TODO Remove the buttons limit const val buttonsMax: Short = 16 // TODO Remove the buttons limit
const val clickboxHeightOffset: Int = 80 const val clickboxHeightOffset: Int = 80
private const val inclination: Double = 2.5 private const val inclination: Float = 2.5F
} }
override fun render(poseStack: PoseStack?) { override fun render(guiGraphics: GuiGraphics?) {
runBlocking { val x = x.toFloat()
val y = y.toFloat()
val currentHeight = y + (height + clickboxHeightOffset)
prepareDraw() prepareDraw()
with(buffer) { with(tessellator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR)) {
begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR)
// Render the header: // Render the header:
vertex(x, y + height, 0.0).colorEnd() addVertex(x, y + height, 0.0F).colorEnd()
vertex(x + width + inclination, y + height, 0.0).colorEnd() addVertex(x + width + inclination, y + height, 0.0F).colorEnd()
vertex(x + width, y, 0.0).colorEnd() addVertex(x + width, y, 0.0F).colorEnd()
vertex(x + inclination, y, 0.0).colorEnd() addVertex(x + inclination, y, 0.0F).colorEnd()
// Render the box: // Render the box:
val currentHeight = y + (height + clickboxHeightOffset) addVertex(x, currentHeight, 0.0F).colorEnd()
vertex(x, currentHeight, 0.0).colorEnd() addVertex(x + width + inclination, currentHeight, 0.0F).colorEnd()
vertex(x + width + inclination, currentHeight, 0.0).colorEnd() addVertex(x + width + inclination, y + height, 0.0F).colorEnd()
vertex(x + width + inclination, y + height, 0.0).colorEnd() BufferUploader.drawWithShader(buildOrThrow())
tessellator.end()
colorShader() colorShader()
begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR) with(tessellator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR)) {
vertex(x + inclination, y + height, 0.0).colorEnd(Colors.WHITE_LINES.hexValue) addVertex(x + inclination, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue)
vertex(x + width, y + height, 0.0).colorEnd(Colors.WHITE_LINES.hexValue) addVertex(x + width, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue)
tessellator.end() BufferUploader.drawWithShader(buildOrThrow())
}
} }
endDraw() endDraw()
val renderButtons = if (buttons.isNotEmpty()) launch(start = CoroutineStart.UNDISPATCHED) { if (buttons.isNotEmpty()) {
buttonsProgressBar.apply { buttonsProgressBar.apply {
x = this@ClickBox.x + this@ClickBox.width - 3 this.x = this@ClickBox.x + this@ClickBox.width - 3
y = this@ClickBox.y + this@ClickBox.height + 3 this.y = this@ClickBox.y + this@ClickBox.height + 3
}.display(poseStack) }.display(guiGraphics)
buttons.forEachIndexed { num, button -> buttons.forEachIndexed { num, button ->
val fullHeight = (y + height.toDouble())..(y + height + clickboxHeightOffset) val fullHeight = (y + height.toDouble())..(this.y + height + clickboxHeightOffset)
button.also { button.also {
it.x = x + 3 it.x = this.x + 3
it.y = y + 3 + height + (((num + 1) - barStage) * 9) it.y = this.y + 3 + height + (((num + 1) - barStage) * 9)
it.hidden = if ((num + 1) <= 8) ((it.y) !in fullHeight) else ((it.y + it.height) !in fullHeight) it.hidden = if ((num + 1) <= 8) ((it.y) !in fullHeight) else ((it.y + it.height) !in fullHeight)
}.display(poseStack) }.display(guiGraphics)
} }
} else null }
if (poseStack != null) { guiGraphics?.run {
Minecraft.getInstance().font.draw(poseStack, name.string, x.toFloat() + 5, y.toFloat() + 1.5F, Colors.TRANSPARENT.hexValue) with(Minecraft.getInstance().font) {
renderButtons?.join() drawInBatch(name.string,
(x + 5), (y + 2), Colors.TRANSPARENT.hexValue, false,
pose().last().pose(), bufferSource(), Font.DisplayMode.NORMAL, 0, 15728880, isBidirectional
)
} }
} }
} }
init {
savedColors?.get(name.key)?.let {
this.color = it
}
}
} }

View File

@ -1,19 +1,19 @@
package fr.username404.snowygui.gui.feature package fr.username404.snowygui.gui.feature
import com.mojang.blaze3d.vertex.PoseStack
import fr.username404.snowygui.ClickGui import fr.username404.snowygui.ClickGui
import fr.username404.snowygui.Snowy import fr.username404.snowygui.Snowy
import fr.username404.snowygui.config.Configuration import fr.username404.snowygui.config.Configuration
import fr.username404.snowygui.gui.ColoredElement import fr.username404.snowygui.gui.ColoredElement
import fr.username404.snowygui.utils.FontUtil
import fr.username404.snowygui.gui.feature.ButtonInfo.Companion.Type import fr.username404.snowygui.gui.feature.ButtonInfo.Companion.Type
import fr.username404.snowygui.utils.FontUtil
import fr.username404.snowygui.utils.RenderingUtil.colorShader
import fr.username404.snowygui.utils.RenderingUtil.endDraw import fr.username404.snowygui.utils.RenderingUtil.endDraw
import fr.username404.snowygui.utils.RenderingUtil.prepareDraw import fr.username404.snowygui.utils.RenderingUtil.prepareDraw
import fr.username404.snowygui.utils.RenderingUtil.colorShader import net.minecraft.client.gui.GuiGraphics
import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.findAnnotation
sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) { sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
internal companion object { companion object {
private fun addButtons(vararg buttons: ButtonImpl) { private fun addButtons(vararg buttons: ButtonImpl) {
buttons.groupBy { impl -> buttons.groupBy { impl ->
ClickGui.clickBoxes.find { box -> ClickGui.clickBoxes.find { box ->
@ -90,12 +90,12 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
lightDown() lightDown()
}; return false }; return false
} }
final override fun render(poseStack: PoseStack?) { final override fun render(guiGraphics: GuiGraphics?) {
prepareDraw() prepareDraw()
colorShader(); defaultRectFunc() colorShader(); defaultRectFunc()
endDraw() endDraw()
if (poseStack != null) { if (guiGraphics != null) {
FontUtil.drawScaled(poseStack, title, x + 1, y + 1, 0.75F) FontUtil.drawScaled(guiGraphics, title, x + 1, y + 1, 0.75F)
} }
} }
} }

View File

@ -1,13 +1,13 @@
package fr.username404.snowygui.gui.feature package fr.username404.snowygui.gui.feature
import com.mojang.blaze3d.vertex.PoseStack
import fr.username404.snowygui.EventSnowy import fr.username404.snowygui.EventSnowy
import fr.username404.snowygui.argsLambda import fr.username404.snowygui.argsLambda
import fr.username404.snowygui.gui.Renderable import fr.username404.snowygui.gui.Renderable
import net.minecraft.client.gui.GuiGraphics
sealed class ButtonImplWithHud: ButtonImpl() { sealed class ButtonImplWithHud: ButtonImpl() {
protected abstract val hudRenderLambda: Renderable protected abstract val hudRenderLambda: Renderable
private val generatedLambda: argsLambda = { hudRenderLambda.render(it.first() as PoseStack?) } private val generatedLambda: argsLambda = { hudRenderLambda.render(it.first() as GuiGraphics?) }
final override fun execAction() { final override fun execAction() {
EventSnowy["HudRender"].run { EventSnowy["HudRender"].run {
if (toggled) add(generatedLambda) if (toggled) add(generatedLambda)

View File

@ -2,7 +2,8 @@ package fr.username404.snowygui.gui.feature
import fr.username404.snowygui.ClickGui import fr.username404.snowygui.ClickGui
import fr.username404.snowygui.gui.elements.ClickBox import fr.username404.snowygui.gui.elements.ClickBox
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.network.chat.Component.translatable
import net.minecraft.network.chat.contents.TranslatableContents
/** /**
* Should be used on classes/objects extending [ButtonImpl] * Should be used on classes/objects extending [ButtonImpl]
@ -22,7 +23,7 @@ annotation class ButtonInfo(
TOGGLE, TOGGLE,
CLICK CLICK
} }
enum class Category(val translationKey: String, val categoryColor: Int, val shouldHide: Boolean = false) { enum class Category(translationKey: String, val categoryColor: Int, val shouldHide: Boolean = false) {
MISC("snowy.clickbox.misc", Colors.BLUE), MISC("snowy.clickbox.misc", Colors.BLUE),
HUD("snowy.clickbox.hud", Colors.DARK_PURPLE), HUD("snowy.clickbox.hud", Colors.DARK_PURPLE),
MACROS("snowy.clickbox.macros", Colors.GREEN); MACROS("snowy.clickbox.macros", Colors.GREEN);
@ -35,14 +36,14 @@ annotation class ButtonInfo(
x = 4.0 + (ordinal - ClickGui.clickBoxes.count { category -> x = 4.0 + (ordinal - ClickGui.clickBoxes.count { category ->
category.hidden category.hidden
}) * 86, y = 4.0, }) * 86, y = 4.0,
name = TranslatableComponent(translationKey), name = translatable(translationKey),
color = categoryColor color = categoryColor
); private set ); private set
private fun addBox() = ClickGui.components.add(box.apply { if (shouldHide) hidden = true }) private fun addBox() = ClickGui.components.add(box.apply { if (shouldHide) hidden = true })
constructor( constructor(
translationKey: String, categoryColor: Colors, condition: Boolean = false translationKey: String, categoryColor: Colors, condition: Boolean = false
): this(translationKey, categoryColor.hexValue, condition) ): this(translationKey, categoryColor.hexValue, condition)
constructor(categoryBox: ClickBox): this(translationKey = categoryBox.name.key, categoryColor = categoryBox.color) { constructor(categoryBox: ClickBox): this(translationKey = (categoryBox.name.contents as TranslatableContents).key, categoryColor = categoryBox.color) {
with(ClickGui.components) { with(ClickGui.components) {
remove(this@Category.box) remove(this@Category.box)
this@Category.box = categoryBox this@Category.box = categoryBox

View File

@ -10,8 +10,8 @@ import net.arikia.dev.drpc.DiscordRPC as discord_rpc
object DiscordRPC: ButtonImpl() { object DiscordRPC: ButtonImpl() {
private val RPCHandlers: DiscordEventHandlers = DiscordEventHandlers.Builder().build() private val RPCHandlers: DiscordEventHandlers = DiscordEventHandlers.Builder().build()
private val RichPresence: DiscordRichPresence.Builder = DiscordRichPresence private val RichPresence: DiscordRichPresence.Builder = DiscordRichPresence
.Builder("Playing Minecraft ${Minecraft.getInstance().game.version.name}") .Builder("Playing Minecraft ${Minecraft.getInstance().launchedVersion}")
.setDetails("Launched with ${Minecraft.getInstance().launchedVersion}") .setDetails("Launched with ${Minecraft.getInstance().versionType}")
.setBigImage("icon", "SnowyGUI") .setBigImage("icon", "SnowyGUI")
override fun execAction() { override fun execAction() {
if (toggled) discord_rpc.discordUpdatePresence(RichPresence.build()) if (toggled) discord_rpc.discordUpdatePresence(RichPresence.build())

View File

@ -8,7 +8,9 @@ object GammaBoost: ButtonImpl() {
private var oldGamma = 0.0 private var oldGamma = 0.0
override fun execAction() { override fun execAction() {
with(Minecraft.getInstance().options) { with(Minecraft.getInstance().options) {
gamma = if (toggled) { val gamma = gamma().get()
gamma().value =
if (toggled) {
if (gamma < boost) oldGamma = gamma if (gamma < boost) oldGamma = gamma
boost boost
} else oldGamma } else oldGamma

View File

@ -1,12 +1,12 @@
package fr.username404.snowygui.gui.feature package fr.username404.snowygui.gui.feature
import com.mojang.blaze3d.vertex.PoseStack
import fr.username404.snowygui.config.Configuration import fr.username404.snowygui.config.Configuration
import fr.username404.snowygui.gui.ColoredElement import fr.username404.snowygui.gui.ColoredElement
import fr.username404.snowygui.gui.Renderable import fr.username404.snowygui.gui.Renderable
import fr.username404.snowygui.utils.FontUtil import fr.username404.snowygui.utils.FontUtil
import fr.username404.snowygui.utils.RenderingUtil import fr.username404.snowygui.utils.RenderingUtil
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
@ButtonInfo(Category.HUD) @ButtonInfo(Category.HUD)
object Keystrokes: ButtonImplWithHud() { object Keystrokes: ButtonImplWithHud() {
@ -41,14 +41,14 @@ object Keystrokes: ButtonImplWithHud() {
return dynamicOpacity[i] return dynamicOpacity[i]
} }
private fun drawKey(x: Double, y: Double, key: Int, poseStack: PoseStack? = null) { private fun drawKey(x: Double, y: Double, key: Int, guiGraphics: GuiGraphics?) {
RenderingUtil.prepareDraw() RenderingUtil.prepareDraw()
RenderingUtil.drawRectangle( RenderingUtil.drawRectangle(
x, y, height / 2, height / 2, x, y, height / 2, height / 2,
color = color, opacity = getDynamicOpacity(key).toFloat() color = color, opacity = getDynamicOpacity(key).toFloat()
) )
RenderingUtil.endDraw() RenderingUtil.endDraw()
poseStack?.let { guiGraphics?.let {
FontUtil.drawScaled( FontUtil.drawScaled(
it, keysArray.first[key].translatedKeyMessage.string.uppercase(), it, keysArray.first[key].translatedKeyMessage.string.uppercase(),
x + height.toDouble() / 5.5, y + height.toDouble() / 6.5, x + height.toDouble() / 5.5, y + height.toDouble() / 6.5,
@ -57,11 +57,11 @@ object Keystrokes: ButtonImplWithHud() {
} }
} }
private fun getNewPos(i: Int) = x + (i * (2 + (height / 2))) private fun getNewPos(i: Int) = x + (i * (2 + (height / 2)))
override fun render(poseStack: PoseStack?) = with(RenderingUtil) { override fun render(guiGraphics: GuiGraphics?) = with(RenderingUtil) {
for (i in 0 until 3) { for (i in 0 until 3) {
drawKey(getNewPos(i), y, i, poseStack) drawKey(getNewPos(i), y, i, guiGraphics)
} }
drawKey(getNewPos(1), y - (height / 2) - 2, 3, poseStack) drawKey(getNewPos(1), y - (height / 2) - 2, 3, guiGraphics)
} }
} }
override val hudRenderLambda = Renderable { override val hudRenderLambda = Renderable {

View File

@ -15,12 +15,12 @@ data class Macro(
override var title: String = command override var title: String = command
): ButtonImpl() { ): ButtonImpl() {
override fun execAction(): Unit = with(Minecraft.getInstance().player!!) { override fun execAction(): Unit = with(Minecraft.getInstance().player!!) {
chat( connection.run {
"/$command".let { command.let {
if (it.startsWith("/say") && !hasPermissions(2)) { if (it.startsWith("say") && !hasPermissions(2)) {
it.drop(5) sendChat(it.drop(4))
} else it } else sendCommand(it)
} }
) }
} }
} }

View File

@ -1,13 +1,14 @@
package fr.username404.snowygui.utils package fr.username404.snowygui.utils
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import fr.username404.snowygui.gui.feature.Colors import fr.username404.snowygui.gui.feature.Colors
import net.minecraft.client.gui.GuiGraphics
object FontUtil { object FontUtil {
fun drawScaled(stack: PoseStack, text: String, x: Double, y: Double, scaleFactor: Float, color: Colors = Colors.BLACK) { fun drawScaled(guiGraphics: GuiGraphics, text: String, x: Double, y: Double, scaleFactor: Float, color: Colors = Colors.BLACK) {
val stack = guiGraphics.pose()
stack.scale(scaleFactor, scaleFactor, scaleFactor) stack.scale(scaleFactor, scaleFactor, scaleFactor)
Minecraft.getInstance().font.draw(stack, text, (x / scaleFactor).toFloat(), (y / scaleFactor).toFloat(), color.hexValue) guiGraphics.drawString(Minecraft.getInstance().font, text, (x / scaleFactor).toInt(), (y / scaleFactor).toInt(), color.hexValue, false)
val factorToOriginal = 1F / scaleFactor val factorToOriginal = 1F / scaleFactor
stack.scale(factorToOriginal, factorToOriginal, factorToOriginal) stack.scale(factorToOriginal, factorToOriginal, factorToOriginal)
} }

View File

@ -1,7 +1,7 @@
package fr.username404.snowygui.utils package fr.username404.snowygui.utils
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.BufferBuilder import com.mojang.blaze3d.vertex.BufferUploader
import com.mojang.blaze3d.vertex.DefaultVertexFormat import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.Tesselator import com.mojang.blaze3d.vertex.Tesselator
import com.mojang.blaze3d.vertex.VertexConsumer import com.mojang.blaze3d.vertex.VertexConsumer
@ -12,36 +12,32 @@ import net.minecraft.client.renderer.GameRenderer
object RenderingUtil { object RenderingUtil {
@JvmField val tessellator: Tesselator = Tesselator.getInstance() @JvmField val tessellator: Tesselator = Tesselator.getInstance()
@JvmField val buffer: BufferBuilder = tessellator.builder
@JvmStatic @JvmStatic
fun VertexConsumer.colorIt(color: Int, opacity: Float = 1F): VertexConsumer = hextoRGB(color).run { fun VertexConsumer.colorIt(color: Int, opacity: Float = 1F): VertexConsumer = hextoRGB(color).run {
color(get(0), get(1), get(2), opacity) setColor(get(0), get(1), get(2), opacity)
} }
fun VertexConsumer.colorEnd(color: Int, opacity: Float = 1F) = colorIt(color, opacity).endVertex()
fun colorShader() { fun colorShader() {
RenderSystem.setShader(GameRenderer::getPositionColorShader) RenderSystem.setShader(GameRenderer::getPositionColorShader)
RenderSystem.setShaderColor(1F, 1F, 1F, 1F) RenderSystem.setShaderColor(1F, 1F, 1F, 1F)
} }
fun prepareDraw() { fun prepareDraw() {
colorShader() colorShader()
RenderSystem.disableTexture()
RenderSystem.enableBlend() RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc() RenderSystem.defaultBlendFunc()
} }
fun endDraw() { fun endDraw() {
RenderSystem.enableTexture()
RenderSystem.disableBlend() RenderSystem.disableBlend()
} }
fun drawRectangle( fun drawRectangle(
x: Double, y: Double, height: Int, width: Int, x: Double, y: Double, height: Int, width: Int,
color: Int = Colors.TRANSPARENT(), opacity: Float = 1F color: Int = Colors.TRANSPARENT(), opacity: Float = 1F
): Unit = buffer.run { ): Unit = tessellator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR).run {
fun VertexConsumer.colorEnd() = colorEnd(color, opacity) fun VertexConsumer.colorIt() = colorIt(color, opacity)
begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR) val x = x.toFloat() ; val y = y.toFloat()
vertex(x, y + height, 0.0).colorEnd() addVertex(x, y + height, 0.0F).colorIt()
vertex(x + width, y + height, 0.0).colorEnd() addVertex(x + width, y + height, 0.0F).colorIt()
vertex(x + width, y, 0.0).colorEnd() addVertex(x + width, y, 0.0F).colorIt()
vertex(x, y, 0.0).colorEnd() addVertex(x, y, 0.0F).colorIt()
tessellator.end() BufferUploader.drawWithShader(buildOrThrow())
} }
} }

View File

@ -1,13 +1,8 @@
{ {
"required": true, "required": true,
"package": "fr.username404.snowygui.mixins", "package": "fr.username404.snowygui.mixins",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_18",
"client": [ "client": [],
"KeysAccessor",
"KeyMappings",
"EndTickMixin",
"TitleScreenMixin"
],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1
}, },

View File

@ -0,0 +1,3 @@
accessWidener v2 named
accessible field net/minecraft/client/OptionInstance value Ljava/lang/Object;
mutable field net/minecraft/client/OptionInstance value Ljava/lang/Object;

View File

@ -0,0 +1,3 @@
{
"accessWidener": "snowygui.accessWidener"
}

View File

@ -23,7 +23,7 @@ dependencies {
exclude(group = Groups.FabricApi, module = "fabric-api-base") exclude(group = Groups.FabricApi, module = "fabric-api-base")
exclude(group = Groups.FabricApi, module = "fabric-resource-loader-v0") exclude(group = Groups.FabricApi, module = "fabric-resource-loader-v0")
} }
implementation(project(path = ":common")) { isTransitive = false } implementation(project(path = ":common", configuration = "namedElements")) { isTransitive = false }
add("developmentFabric", project(path = ":common")) { isTransitive = false } add("developmentFabric", project(path = ":common")) { isTransitive = false }
shadowC(project(path = ":common", configuration = "transformProductionFabric")) { isTransitive = false } shadowC(project(path = ":common", configuration = "transformProductionFabric")) { isTransitive = false }
} }

View File

@ -1,6 +1,5 @@
package fr.username404.snowygui.fabric package fr.username404.snowygui.fabric
import com.mojang.blaze3d.vertex.PoseStack
import fr.username404.snowygui.EventSnowy import fr.username404.snowygui.EventSnowy
import fr.username404.snowygui.Snowy import fr.username404.snowygui.Snowy
import fr.username404.snowygui.gui.feature.ButtonImpl import fr.username404.snowygui.gui.feature.ButtonImpl
@ -8,10 +7,13 @@ import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback.EVENT import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback.EVENT
import net.fabricmc.loader.api.FabricLoader import net.fabricmc.loader.api.FabricLoader
import net.minecraft.client.DeltaTracker
import net.minecraft.client.gui.GuiGraphics
import kotlin.io.path.exists import kotlin.io.path.exists
import kotlin.io.path.isDirectory import kotlin.io.path.isDirectory
import kotlin.io.path.listDirectoryEntries import kotlin.io.path.listDirectoryEntries
import kotlin.io.path.pathString import kotlin.io.path.pathString
import kotlin.jvm.optionals.getOrNull
class FabricInit: Snowy(), ClientModInitializer { class FabricInit: Snowy(), ClientModInitializer {
override fun onInitializeClient() { override fun onInitializeClient() {
@ -19,12 +21,12 @@ class FabricInit: Snowy(), ClientModInitializer {
EVENT.register( EVENT.register(
object: HudRenderCallback, EventSnowy { object: HudRenderCallback, EventSnowy {
override val type: String = "HudRender" override val type: String = "HudRender"
override fun onHudRender(matrixStack: PoseStack?, tickDelta: Float) = fire(matrixStack) override fun onHudRender(guiGraphics: GuiGraphics?, tickCounter: DeltaTracker?) = fire(guiGraphics)
} }
) )
} }
override val annotatedButtons = FabricLoader.getInstance().allMods.map { override val annotatedButtons = FabricLoader.getInstance().allMods.mapNotNull {
it.getPath(FeaturePackage.replace('.', '/')) it.findPath(FeaturePackage.replace('.', '/')).getOrNull()
}.filter { it.exists() && it.isDirectory() }.flatMap { buttonsDirectory -> }.filter { it.exists() && it.isDirectory() }.flatMap { buttonsDirectory ->
mutableSetOf<Class<out ButtonImpl>>().apply { mutableSetOf<Class<out ButtonImpl>>().apply {
buttonsDirectory.listDirectoryEntries("*.class").forEach { file -> buttonsDirectory.listDirectoryEntries("*.class").forEach { file ->

View File

@ -6,23 +6,17 @@ import net.fabricmc.loader.api.FabricLoader
@JvmField @JvmField
var isOkZoomerPresent: Boolean = FabricLoader.getInstance().isModLoaded("okzoomer") var isOkZoomerPresent: Boolean = FabricLoader.getInstance().isModLoaded("okzoomer")
private val okZoomerPairs by lazy { private val okZoomerPairs by lazy {
try { with(Class.forName("io.github.ennuil.okzoomer.utils.ZoomUtils").getDeclaredField("ZOOMER_ZOOM")) {
with(Class.forName("io.github.joaoh1.okzoomer.client.utils.ZoomUtils")) {
(getField("zoomDivisor") to null) to (getField("zoomState") to null)
}
} catch (e: ClassNotFoundException) {
with(Class.forName("io.github.ennuil.okzoomer.utils.ZoomUtils").getDeclaredField("zoomerZoom")) {
get(null).javaClass.run { get(null).javaClass.run {
(getDeclaredField("zoomDivisor") to this@with.get(null)) to (getDeclaredField("zoom") to this@with.get(null)) (getDeclaredField("zoomDivisor") to this@with.get(null)) to (getDeclaredField("zoom") to this@with.get(null))
} }
}
}.apply { first.first.isAccessible = true; second.first.isAccessible = true; } }.apply { first.first.isAccessible = true; second.first.isAccessible = true; }
} }
fun fabricZoom() { fun fabricZoom() {
try { try {
with(okZoomerPairs) { with(okZoomerPairs) {
first.run { first.setDouble(second, Zoom.zoomFactor) } first.run { first.setFloat(second, Zoom.zoomFactor.toFloat()) }
second.run { first.setBoolean(second, Zoom.toggled) } second.run { first.setBoolean(second, Zoom.toggled) }
} }
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -32,12 +32,13 @@
"snowygui-common.mixins.json", "snowygui-common.mixins.json",
"snowygui-fabric.mixins.json" "snowygui-fabric.mixins.json"
], ],
"accessWidener": "snowygui.accessWidener",
"depends": { "depends": {
"fabricloader": ">=0.11.0", "fabricloader": ">=${fabric_loader}",
"fabric-language-kotlin": ">=${fabric_kotlin}", "fabric-language-kotlin": ">=${fabric_kotlin}",
"fabric-resource-loader-v0": "*", "fabric-resource-loader-v0": "*",
"fabric-rendering-v1": "*", "fabric-rendering-v1": "*",
"minecraft": ">=${minecraft_version}" "minecraft": ">=1.19-alpha.22.16.b"
}, },
"recommends": { "recommends": {
"cloth-config2": ">=${clothconfig}" "cloth-config2": ">=${clothconfig}"

View File

@ -1,8 +1,12 @@
{ {
"required": true, "required": true,
"package": "fr.username404.snowygui.mixins", "package": "fr.username404.snowygui.mixins",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_18",
"client": [ "client": [
"EndTickMixin",
"TitleScreenMixin",
"KeysAccessor",
"KeyMappings",
"ZoomMixin", "ZoomMixin",
"OkZoomerAlternativeMixin" "OkZoomerAlternativeMixin"
], ],

View File

@ -1,25 +0,0 @@
architectury { platformSetupLoomIde(); forge() }
repositories {
maven(url = "https://thedarkcolour.github.io/KotlinForForge/")
}
dependencies {
forge("net.minecraftforge:forge:${rootProject.architectury.minecraft}-${rootProject.property("forge_version")}.+")
implementation("thedarkcolour:kotlinforforge:${rootProject.property("kotlinforforge")}")
modApi("me.shedaniel.cloth:cloth-config-forge:${rootProject.property("clothconfig_version")}")
implementation(project(path = ":common")) { isTransitive = false }
add("developmentForge", project(path = ":common")) { isTransitive = false }
shadowC(project(path = ":common", configuration = "transformProductionForge")) { isTransitive = false }
}; loom {
if (JavaVersion.current().isJava9Compatible) {
runs {
val args: MutableList<String> = mutableListOf("-Dfml.earlyprogresswindow=false")
args += if (JavaVersion.current() < JavaVersion.VERSION_17) {
listOf("--add-exports java.base/sun.security.util=ALL-UNNAMED", "--add-opens java.base/java.util.jar=ALL-UNNAMED")
} else listOf("--illegal-access=permit")
this.forEach {
it.vmArgs(args)
}
}
}
}

View File

@ -1 +0,0 @@
loom.platform=forge

View File

@ -1,15 +0,0 @@
package fr.username404.snowygui.forge
import fr.username404.snowygui.EventSnowy
import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
object HudHandler: EventSnowy {
override val type: String = "HudRender"
@SubscribeEvent
fun handleRendering(event: RenderGameOverlayEvent.Post) {
if (event.type == RenderGameOverlayEvent.ElementType.ALL) {
fire(event.matrixStack)
}
}
}

View File

@ -1,12 +0,0 @@
package fr.username404.snowygui.forge
import fr.username404.snowygui.gui.feature.Zoom
import net.minecraftforge.client.event.EntityViewRenderEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
object ZoomHandler {
@SubscribeEvent
fun onFOVEvent(event: EntityViewRenderEvent.FieldOfView) {
if (Zoom.toggled) event.fov = Zoom.getNewZoom(event.fov)
}
}

View File

@ -7,16 +7,16 @@ org.gradle.parallel=true
org.gradle.unsafe.configuration-cache=on org.gradle.unsafe.configuration-cache=on
org.gradle.vfs.watch=true org.gradle.vfs.watch=true
minecraft=1.18.1 minecraft=1.21
forge_version=39.1 forge_version=21.0.143
kotlinforforge=3.1.0 kotlinforforge=5.4.0
kotlinVer=1.6.0 kotlinVer=2.0.0
kotlin_coroutines_version=1.5.0 kotlin_coroutines_version=1.7.1
serializationVer=1.2.1 serializationVer=1.7.0
fabric_loader_version=0.11.7 fabric_loader_version=0.14.20
fabric_language_kotlin=1.7.0+kotlin.1.6.0 fabric_language_kotlin=1.11.0+kotlin.2.0.0
fabric_resource_loader_version=0.4.14+713c266865 fabric_resource_loader_version=1.1.3+b559734490
fabric_rendering_api_version=1.10.6+713c266865 fabric_rendering_api_version=5.0.3+d132107690
fabric_api_base_version=0.3.0+a02b4463d5 fabric_api_base_version=0.4.42+6573ed8c90
clothconfig_version=6.2.57 clothconfig_version=15.0.127
modmenu_version=3.0.1 modmenu_version=11.0.0

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-rc-1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

26
neoforge/build.gradle.kts Normal file
View File

@ -0,0 +1,26 @@
architectury { platformSetupLoomIde(); neoForge() }
repositories {
maven(url = "https://maven.neoforged.net/releases/")
maven(url = "https://thedarkcolour.github.io/KotlinForForge/")
}
dependencies {
neoForge("net.neoforged:neoforge:${rootProject.property("forge_version").toString().let {
return@let if (it.length > 4) it else "$it.+"
}}")
implementation("thedarkcolour:kotlinforforge:${rootProject.property("kotlinforforge")}")
modApi("me.shedaniel.cloth:cloth-config-neoforge:${rootProject.property("clothconfig_version")}")
implementation(project(path = ":common", configuration = "namedElements")) { isTransitive = false }
add("developmentNeoForge", project(path = ":common")) { isTransitive = false }
shadowC(project(path = ":common", configuration = "transformProductionNeoForge")) { isTransitive = false }
}; loom {
runs {
val args: MutableList<String> = mutableListOf("-Dfml.earlyprogresswindow=false")
args += listOf("--illegal-access=permit")
this.forEach {
it.vmArgs(args)
}
}
}

View File

@ -0,0 +1 @@
loom.platform=neoforge

View File

@ -0,0 +1,11 @@
package fr.username404.snowygui.forge
import fr.username404.snowygui.EventSnowy
import net.neoforged.bus.api.SubscribeEvent
import net.neoforged.neoforge.client.event.ClientTickEvent
object EndTickHandler: EventSnowy {
override val type: String = "EndTick"
@SubscribeEvent
fun handleEndTick(event: ClientTickEvent.Post) = fire<Any>()
}

View File

@ -4,25 +4,19 @@ import fr.username404.snowygui.Snowy
import fr.username404.snowygui.config.SnowyConfigScreen import fr.username404.snowygui.config.SnowyConfigScreen
import fr.username404.snowygui.config.configScreenParent import fr.username404.snowygui.config.configScreenParent
import fr.username404.snowygui.gui.feature.ButtonImpl import fr.username404.snowygui.gui.feature.ButtonImpl
import net.minecraftforge.fml.ModList import net.neoforged.fml.ModContainer
import net.minecraftforge.fml.common.Mod import net.neoforged.fml.ModList
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent import net.neoforged.fml.common.Mod
import net.minecraftforge.client.ConfigGuiHandler import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent
import net.minecraftforge.forgespi.language.ModFileScanData import net.neoforged.neoforge.client.gui.IConfigScreenFactory
import net.neoforged.neoforge.common.NeoForge
import net.neoforged.neoforgespi.language.ModFileScanData
import org.objectweb.asm.Type import org.objectweb.asm.Type
import thedarkcolour.kotlinforforge.forge.FORGE_BUS
import thedarkcolour.kotlinforforge.forge.LOADING_CONTEXT
import thedarkcolour.kotlinforforge.forge.MOD_BUS
@Mod("snowygui") @Mod("snowygui")
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
class ForgeInit: Snowy() { class ForgeInit(container: ModContainer): Snowy() {
private fun initSetup(event: FMLClientSetupEvent) = atInit() private fun initSetup(event: FMLClientSetupEvent) = atInit()
private fun configSetup(event: FMLClientSetupEvent) {
LOADING_CONTEXT.registerExtensionPoint(
ConfigGuiHandler.ConfigGuiFactory::class.java
) { ConfigGuiHandler.ConfigGuiFactory { _, parent -> configScreenParent = parent; SnowyConfigScreen } }
}
override val annotatedButtons = ModList.get() // Forge-specific reflection override val annotatedButtons = ModList.get() // Forge-specific reflection
.allScanData .allScanData
.flatMap { obj: ModFileScanData -> obj.classes } .flatMap { obj: ModFileScanData -> obj.classes }
@ -34,13 +28,18 @@ class ForgeInit: Snowy() {
.map { Class.forName((it!!.javaClass.getDeclaredField("clazz").apply { isAccessible = true }.get(it) as Type).className).asSubclass(ButtonImpl::class.java)} .map { Class.forName((it!!.javaClass.getDeclaredField("clazz").apply { isAccessible = true }.get(it) as Type).className).asSubclass(ButtonImpl::class.java)}
.toSet() .toSet()
init { init {
with(MOD_BUS) { container.eventBus!!.run {
addListener(this@ForgeInit::initSetup) addListener(this@ForgeInit::initSetup)
addListener(this@ForgeInit::configSetup) register(MiscModBusHandlers)
} }
with(FORGE_BUS) { NeoForge.EVENT_BUS.run {
register(EndTickHandler)
register(HudHandler) register(HudHandler)
register(ZoomHandler) register(ZoomHandler)
} }
container.registerExtensionPoint(
IConfigScreenFactory::class.java,
IConfigScreenFactory { _, parent -> configScreenParent = parent; SnowyConfigScreen }
)
} }
} }

View File

@ -0,0 +1,13 @@
package fr.username404.snowygui.forge
import fr.username404.snowygui.EventSnowy
import net.neoforged.bus.api.SubscribeEvent
import net.neoforged.neoforge.client.event.RenderGuiEvent
object HudHandler: EventSnowy {
override val type: String = "HudRender"
@SubscribeEvent
fun handleRendering(event: RenderGuiEvent.Post) {
fire(event.guiGraphics)
}
}

View File

@ -0,0 +1,22 @@
package fr.username404.snowygui.forge
import fr.username404.snowygui.ClickGui
import fr.username404.snowygui.gui.feature.ButtonImpl
import fr.username404.snowygui.misc.AddKeyMaps
import net.neoforged.bus.api.SubscribeEvent
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent
object MiscModBusHandlers {
@SubscribeEvent
fun handleClickGuiInit(event: RegisterMenuScreensEvent) {
ClickGui.tick()
ButtonImpl.initButtons()
}
@SubscribeEvent
fun handleKeys(event: RegisterKeyMappingsEvent) {
AddKeyMaps.list.forEach {
event.register(it.key)
}
}
}

View File

@ -0,0 +1,12 @@
package fr.username404.snowygui.forge
import fr.username404.snowygui.gui.feature.Zoom
import net.neoforged.bus.api.SubscribeEvent
import net.neoforged.neoforge.client.event.ComputeFovModifierEvent
object ZoomHandler {
@SubscribeEvent
fun onFOVEvent(event: ComputeFovModifierEvent) {
if (Zoom.toggled) event.newFovModifier = Zoom.getNewZoom(event.newFovModifier.toDouble()).toFloat()
}
}

View File

@ -14,16 +14,16 @@ A cross-platform mod offering a useful interface.
logoFile = "icon.png" logoFile = "icon.png"
[[dependencies.snowygui]] [[dependencies.snowygui]]
modId = "cloth-config" modId = "cloth_config"
mandatory = false mandatory = false
versionRange = "[${clothconfig},)" versionRange = "[${clothconfig},)"
ordering = "BEFORE" ordering = "BEFORE"
side = "CLIENT" side = "CLIENT"
[[dependencies.snowygui]] [[dependencies.snowygui]]
modId = "forge" modId = "neoforge"
mandatory = true mandatory = true
versionRange = "[37,)" versionRange = "[${forge_version},)"
ordering = "NONE" ordering = "NONE"
side = "BOTH" side = "BOTH"
@ -33,3 +33,9 @@ mandatory = true
versionRange = "[${minecraft_version},)" versionRange = "[${minecraft_version},)"
ordering = "NONE" ordering = "NONE"
side = "BOTH" side = "BOTH"
[[mixins]]
config = "snowygui-common.mixins.json"
[[mixins]]
config = "snowygui-neoforge.mixins.json"

View File

@ -1,7 +1,7 @@
{ {
"required": false, "required": false,
"package": "fr.username404.snowygui.mixins", "package": "fr.username404.snowygui.mixins",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_21",
"client": [], "client": [],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1

View File

@ -2,7 +2,7 @@ pluginManagement {
repositories { repositories {
maven(url = "https://maven.fabricmc.net/") maven(url = "https://maven.fabricmc.net/")
maven(url = "https://maven.architectury.dev/") maven(url = "https://maven.architectury.dev/")
maven(url = "https://maven.minecraftforge.net/") maven(url = "https://maven.neoforged.net/releases/")
mavenCentral() mavenCentral()
mavenLocal() mavenLocal()
gradlePluginPortal() gradlePluginPortal()
@ -11,7 +11,7 @@ pluginManagement {
include("common") include("common")
include("fabric") include("fabric")
include("forge") include("neoforge")
rootProject.name = "SnowyGUI" rootProject.name = "SnowyGUI"