Compare commits

..

4 Commits

Author SHA1 Message Date
aa112228de
Put the right minecraft version in fabric.mod.json
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-04-25 23:43:02 +02:00
fd267a4b10
Bump version to 0.3.6
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-04-16 21:23:08 +02:00
a86e8b1ebe
Fix my stupid configuration system
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-04-16 21:23:06 +02:00
e22ff551df
Fix the mod on neoforge 1.21.5 by notably using the mod loader configuration directories
Signed-off-by: Username404-59 <w.iron.zombie@gmail.com>
2025-04-16 21:22:46 +02:00
31 changed files with 249 additions and 455 deletions

View File

@ -1,27 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="SnowyGUI [build]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-PdevBuild=true" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>

View File

@ -1,27 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="SnowyGUI [build-release]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-PdevBuild=false" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>

View File

@ -4,22 +4,21 @@ import com.modrinth.minotaur.dependencies.DependencyType
import masecla.modrinth4j.model.version.ProjectVersion.VersionType
import net.fabricmc.loom.LoomGradleExtension
import net.fabricmc.loom.api.LoomGradleExtensionAPI
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
buildscript {
dependencies {
classpath("com.guardsquare:proguard-gradle:[7.8, 7.9[") {
classpath("com.guardsquare:proguard-gradle:[7.5, 7.7[") {
exclude("com.android.tools.build")
}
}
}
plugins {
kotlin("jvm") version "2.3.0"
kotlin("plugin.serialization") version "2.3.0"
kotlin("jvm") version "2.0.0"
kotlin("plugin.serialization") version "2.0.0"
id("com.github.johnrengelman.shadow") version "8.1.1" apply false
id("architectury-plugin") version "[3.4.160, 3.5["
id("dev.architectury.loom") version "[1.13.464, 1.14[" apply false
id("dev.architectury.loom") version "1.9-SNAPSHOT" apply false
id("com.github.ben-manes.versions") version "0.51.0"
id("net.kyori.indra.git") version "3.1.3"
id("org.cqfn.diktat.diktat-gradle-plugin") version "1.2.5"
@ -27,7 +26,7 @@ plugins {
}
group = "fr.username404"
version = "0.4.2"
version = "0.3.6"
val groupAndName = "${rootProject.group}.${rootProject.name.lowercase()}"
val javaVer: String = "21"
@ -39,7 +38,6 @@ val minecraftVersion: String = (rootProject.property("minecraft") as String).als
architectury { minecraft = it }
}
val kotlinX: String = "org.jetbrains.kotlinx"
val devBuild = rootProject.hasProperty("devBuild") && rootProject.property("devBuild").toString().toBoolean()
subprojects {
group = rootProject.group.toString()
@ -58,7 +56,12 @@ subprojects {
}
mappingsDep = layered {
silentMojangMappingsLicense()
officialMojangMappings().parchment("org.parchmentmc.data:parchment-1.21.11:2025.12.20")
officialMojangMappings().parchment("org.parchmentmc.data:parchment-1.21:2024.06.23")
}
val refmap = "snowygui-${project.name}-refmap.json"
mixin {
useLegacyMixinAp = true
defaultRefmapName = refmap
}
}
apply(plugin = "com.github.johnrengelman.shadow")
@ -164,16 +167,14 @@ subprojects {
mergeinterfacesaggressively()
}
withType(net.fabricmc.loom.task.RemapJarTask::class) {
if (!devBuild) {
dependsOn(shrinkJar)
val shrinkedJar = shrinkJar.get().outJarFileCollection.singleFile
inputFile.set(shrinkedJar)
} else inputFile.set(shadowJar.archiveFile)
dependsOn(shrinkJar)
val shrinkedJar = shrinkJar.get().outJarFileCollection.singleFile
archiveBaseName.set(shadowJar.archiveBaseName)
archiveVersion.set("[${rootProject.version}+$minecraftVersion]")
archiveClassifier.set(this@subprojects.name)
if (this@subprojects.name.contains("forge"))
atAccessWideners.set(listOf("${rootProject.name.lowercase()}.accessWidener"))
inputFile.set(shrinkedJar)
if (!archiveFileName.get().contains("common")) destinationDirectory.set(file("$rootDir/remappedJars"))
}
getByName("modrinth").dependsOn(build)
@ -200,18 +201,19 @@ allprojects {
}
tasks {
withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class) {
compilerOptions {
with(kotlinOptions) {
// https://github.com/JetBrains/kotlin/blob/master/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt
freeCompilerArgs = listOf(
"-Xjvm-default=all", "-Xlambdas=indy", "-Xtype-enhancement-improvements-strict-mode",
"-Xmultifile-parts-inherit",
"-Xbackend-threads=0", "-Xno-param-assertions", "-Xno-call-assertions",
"-opt-in=kotlin.RequiresOptIn", "-Xassertions=jvm", "-progressive"
"-opt-in=kotlin.RequiresOptIn", "-Xextended-compiler-checks", "-Xassertions=jvm", "-progressive"
)
jvmTarget = javaVer
// Uncomment when updating to architectury-loom 1.9
//languageVersion = (kotlinSplitVersion[0] + '.' + (kotlinSplitVersion[1].toShort() + 1).toString())
//apiVersion = "${kotlinSplitVersion[0]}.${kotlinSplitVersion[1]}"
}
compilerOptions.jvmTarget.set(JvmTarget.fromTarget(javaVer))
}
withType(JavaCompile::class) {
with(options) {

View File

@ -1,23 +0,0 @@
package fr.username404.snowygui.mixins;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import fr.username404.snowygui.gui.feature.GammaBoost;
import net.minecraft.client.renderer.LightTexture;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(LightTexture.class)
abstract class GammaMixin {
@ModifyExpressionValue(
method = "updateLightTexture(F)V", at = @At(
value = "INVOKE",
target = "Ljava/lang/Double;floatValue()F",
ordinal = 1
)
)
public float highGamma(float original) {
if (GammaBoost.INSTANCE.getToggled())
return GammaBoost.BOOST;
return original;
}
}

View File

@ -4,9 +4,7 @@ import fr.username404.snowygui.gui.ColoredElement
import fr.username404.snowygui.gui.Element
import fr.username404.snowygui.gui.SnowyScreen
import fr.username404.snowygui.gui.elements.ClickBox
import net.minecraft.client.input.MouseButtonEvent
import org.lwjgl.glfw.GLFW
import kotlin.math.roundToInt
object ClickGui: SnowyScreen() {
override val components = mutableSetOf<Element>()
@ -19,32 +17,28 @@ object ClickGui: SnowyScreen() {
private var draggingBox: String? = null
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(event: MouseButtonEvent, isDoubleClick: Boolean): Boolean {
if (event.input() == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
clickBoxes.find { it.isWithinBounds(event.x, event.y) }?.let { draggingBox = it.name.string }
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 = event.x - (x + width)
offsetY = event.y - (y + height)
offsetX = d - (x + width)
offsetY = e - (y + height)
}
}
buttonsContext { this.mouseClicked(event, isDoubleClick) }; return super.mouseClicked(event, isDoubleClick);
buttonsContext { this.mouseClicked(d, e, i) }; return super.mouseClicked(d, e, i);
}
override fun mouseReleased(event: MouseButtonEvent): Boolean { draggingBox = null; buttonsContext { this.mouseReleased(event) }; return false }
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(event: MouseButtonEvent, mouseX: Double, mouseY: Double): Boolean {
if (event.input() == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double): Boolean {
if (i == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
currentBoxContext {
val targetX = (event.x + offsetX).coerceIn(0.0..this@ClickGui.width - width.toDouble())
val targetY = (event.y + offsetY).coerceIn(0.0..this@ClickGui.height - height.toDouble())
// Snap to integer pixels => stable spacing
x = targetX.roundToInt().toDouble()
y = targetY.roundToInt().toDouble()
x = (d + offsetX).coerceIn(0.0..this@ClickGui.width - width.toDouble())
y = (e + offsetY).coerceIn(0.0..this@ClickGui.height - height.toDouble())
}
}
return super.mouseDragged(event, mouseX, mouseY)
return super.mouseDragged(d, e, i, f, g)
}
}

View File

@ -1,6 +1,6 @@
package fr.username404.snowygui
import fr.username404.snowygui.config.LazyConfiguration
import fr.username404.snowygui.config.Configuration
import fr.username404.snowygui.gui.feature.ButtonImpl
import fr.username404.snowygui.gui.feature.ButtonInfo
import fr.username404.snowygui.misc.AddKeyMaps
@ -13,30 +13,30 @@ import java.lang.reflect.Modifier
abstract class Snowy {
protected fun Class<*>.isValidForButtonCollection(): Boolean =
!Modifier.isAbstract(modifiers) && declaredAnnotations.any { it is ButtonInfo && !it.ignored }
private val displayInitMessage: Lazy<Boolean> by LazyConfiguration
abstract val annotatedButtons: Lazy<Set<Class<out ButtonImpl>>>
private val displayInitMessage: Boolean by Configuration
abstract val annotatedButtons: Set<Class<out ButtonImpl>>
companion object {
val MissingComponent: Component = translatable("MISSING_COMPONENT")
@Suppress("JVM_STATIC_ON_CONST_OR_JVM_FIELD") // See KT-39868
@JvmStatic
protected const val FEATURE_PACKAGE: String = "fr.username404.snowygui.gui.feature"
protected const val FeaturePackage: String = "fr.username404.snowygui.gui.feature"
lateinit var annotatedButtons: () -> Set<Class<out ButtonImpl>>
fun onEvent(e: Any, lambda: argsLambda) = EventSnowy[e.toString()].add(lambda)
@JvmField
val logs: Logger = LogManager.getLogger()
}
init { Companion.annotatedButtons = { annotatedButtons.value } }
init { Companion.annotatedButtons = ::annotatedButtons::get }
private fun eventsInit() {
onEvent("EndTick") {
for (key in AddKeyMaps.list.keys) {
if (key.isDown) {
AddKeyMaps.list[key]?.invoke()
for (Key in AddKeyMaps.list.keys) {
if (Key.isDown) {
AddKeyMaps.list[Key]?.invoke()
}
}
}
}
fun atInit() {
if (displayInitMessage.value) logs.info("Init point of SnowyGUI hit.")
if (displayInitMessage) logs.info("Init point of SnowyGUI hit.")
eventsInit()
}
}

View File

@ -2,10 +2,10 @@ package fr.username404.snowygui.config
import fr.username404.snowygui.ClickGui
import fr.username404.snowygui.gui.elements.ClickBox
import fr.username404.snowygui.gui.elements.ClickBox.Companion.buttonsMax
import fr.username404.snowygui.gui.elements.ClickBox.Companion.sortAlphabetically
import fr.username404.snowygui.gui.feature.*
import fr.username404.snowygui.utils.FontUtil
import me.shedaniel.clothconfig2.gui.entries.StringListListEntry
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
@ -75,9 +75,9 @@ val SnowyConfigScreen: Screen = object: Screen(translationComponent) {
}.build()).addEntry(startStrList(
Category.MACROS.box.name,
macrosButtons.getTitleCommand()
).setCreateNewInstance {
entry -> StringListListEntry.StringListCell("ExampleMacro: say hello", entry)
}.setInsertInFront(false).setDefaultValue(Configuration.foundMacros.getTitleCommand()).setCellErrorSupplier { cell ->
).setInsertInFront(false).setDefaultValue(Configuration.foundMacros.getTitleCommand()).setErrorSupplier { list ->
supplyComponent(if (list.size > buttonsMax) "$confPrefix.general.macros.toomuchbuttons" else null)
}.setCellErrorSupplier { cell ->
with(cell.split(":")) {
supplyComponent(
when {

View File

@ -21,6 +21,7 @@ import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import net.minecraft.network.chat.contents.TranslatableContents
import org.jetbrains.annotations.ApiStatus
@ -118,13 +119,13 @@ object Configuration {
)
}
private fun Config.withFullModifiableValues() = @Suppress("DEPRECATION_ERROR")
ModifiableValues.entries.fold(this) { previous, entry ->
previous.withValue(entry.key, entry.value.let {
ConfigValueFactory.fromAnyRef(
if (it !is Lazy<*>) it else it.value
)
})
}
ModifiableValues.entries.fold(this) { previous, entry ->
previous.withValue(entry.key, entry.value.let {
ConfigValueFactory.fromAnyRef(
if (it !is Lazy<*>) it else it.value
)
})
}
private suspend fun writeConfig(c: Config) = coroutineScope {
launch(start = CoroutineStart.UNDISPATCHED) {
file.writeText(
@ -173,11 +174,5 @@ object Configuration {
convertValue(T::class) ?: throw e
}
operator fun <T> setValue(ref: Any?, property: KProperty<*>, value: T) = @Suppress("DEPRECATION_ERROR")
ModifiableValues.setValue(ref, property, value)
}
object LazyConfiguration {
inline operator fun <reified T: Any> getValue(ref: Any?, property: KProperty<*>): Lazy<T> = lazy {
Configuration.getValue<T>(ref, property);
}
ModifiableValues.setValue(ref, property, value)
}

View File

@ -1,6 +1,6 @@
package fr.username404.snowygui.gui
import com.mojang.blaze3d.vertex.VertexConsumer
import com.mojang.blaze3d.vertex.*
import fr.username404.snowygui.Snowy
import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.utils.RenderingUtil
@ -58,12 +58,8 @@ abstract class ColoredElement(
}
}
}
internal fun VertexConsumer.colorEnd(color: Int = this@ColoredElement.color) = colorIt(color, opacity)
protected fun defaultRectFunc(guiGraphics: GuiGraphics?) = guiGraphics?.let {
RenderingUtil.drawRectangle(it, x, y, height, width, color, opacity)
}
protected fun defaultRectFunc() = RenderingUtil.drawRectangle(x, y, height, width, color, opacity)
}
fun hextoRGB(hex: Int): MutableList<Float> {

View File

@ -1,21 +1,23 @@
package fr.username404.snowygui.gui.elements
import com.mojang.blaze3d.vertex.BufferUploader
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.VertexFormat
import fr.username404.snowygui.Snowy.Companion.MissingComponent
import fr.username404.snowygui.config.Configuration
import fr.username404.snowygui.gui.ColoredElement
import fr.username404.snowygui.gui.feature.ButtonImpl
import fr.username404.snowygui.gui.feature.Category
import fr.username404.snowygui.gui.feature.Colors
import fr.username404.snowygui.utils.RenderingUtil
import fr.username404.snowygui.utils.RenderingUtil.colorShader
import fr.username404.snowygui.utils.RenderingUtil.endDraw
import fr.username404.snowygui.utils.RenderingUtil.prepareDraw
import fr.username404.snowygui.utils.RenderingUtil.tessellator
import io.github.config4k.extract
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.Font
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.network.chat.Component
import net.minecraft.util.ARGB
import kotlin.math.floor
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
import org.jetbrains.annotations.ApiStatus
import java.util.TreeSet
import kotlin.collections.LinkedHashSet
@ -25,7 +27,7 @@ class ClickBox(
x: Double, y: Double,
val name: Component = 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.string == c.box.name.string)
val buttons: MutableSet<ButtonImpl> =
if (sortAlphabetically)
@ -44,28 +46,24 @@ class ClickBox(
) {
override val color: Int get() = this@ClickBox.color
override fun render(guiGraphics: GuiGraphics?) {
defaultRectFunc(guiGraphics)
prepareDraw()
colorShader(); defaultRectFunc()
endDraw()
}
init { height = 8 }
}
var barStage: Int = 0; private set
var barStage: Int = 1; private set
fun scroll(d: Double, e: Double, supplied: Double) {
if (!isWithinBounds(d, e, offsetHeight = clickboxHeightOffset.toDouble())) return
if (buttons.isEmpty()) return
// This allows scrolling until only the last button is visible at the top
val maxScroll = max(0, buttons.size - 1)
val step = when {
supplied < 0 -> 1
supplied > 0 -> -1
else -> 0
if (isWithinBounds(d, e, offsetHeight = clickboxHeightOffset.toDouble())) {
with(buttonsProgressBar) {
if ((height > 8 || (supplied < 0)) && (((height < (buttons.size * 8)) && (height < originalHeight)) || (supplied > 0))) {
height -= supplied.toInt()
if (buttons.isNotEmpty()) (height / 8).let {
if (it > 0) barStage = it
}
}
}
}
if (step == 0) return
barStage = (barStage + step).coerceIn(0, maxScroll)
}
companion object {
@ -75,96 +73,58 @@ class ClickBox(
}
}
var sortAlphabetically: Boolean by Configuration
const val buttonsMax: Short = 16 // TODO Remove the buttons limit
const val clickboxHeightOffset: Int = 80
private const val inclination: Float = 2.5F
}
override fun render(guiGraphics: GuiGraphics?) {
val xi = floor(x).toInt()
val yi = floor(y).toInt()
val x = x.toFloat()
val y = y.toFloat()
val currentHeight = y + (height + clickboxHeightOffset)
prepareDraw()
with(tessellator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR)) {
// Render the header:
addVertex(x, y + height, 0.0F).colorEnd()
addVertex(x + width + inclination, y + height, 0.0F).colorEnd()
addVertex(x + width, y, 0.0F).colorEnd()
addVertex(x + inclination, y, 0.0F).colorEnd()
// Header
RenderingUtil.drawSlantedHeader(
guiGraphics = guiGraphics,
x = xi,
y = yi,
width = width,
height = height,
slantTop = inclination,
color = color,
opacity = opacity
)
// Render the box:
addVertex(x, currentHeight, 0.0F).colorEnd()
addVertex(x + width + inclination, currentHeight, 0.0F).colorEnd()
addVertex(x + width + inclination, y + height, 0.0F).colorEnd()
BufferUploader.drawWithShader(buildOrThrow())
// Body
RenderingUtil.drawRectangle(
guiGraphics = guiGraphics,
x = xi.toDouble(),
y = (yi + height).toDouble(),
height = clickboxHeightOffset,
width = width + inclination.roundToInt(),
color = color,
opacity = opacity
)
// Separator line
RenderingUtil.hLine(
guiGraphics = guiGraphics,
x1 = (xi + inclination).toInt(),
x2 = (xi + width),
y = (yi + height),
rgb = Colors.WHITE_LINES.hexValue,
opacity = 1f
)
colorShader()
with(tessellator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR)) {
addVertex(x + inclination, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue)
addVertex(x + width, y + height, 0.0F).colorEnd(Colors.WHITE_LINES.hexValue)
BufferUploader.drawWithShader(buildOrThrow())
}
}
endDraw()
if (buttons.isNotEmpty()) {
val barWidth = 3
val leftPadding = 3
val gapToBar = 1
val rowHeight = 9
val visibleRows = 8
val maxScroll = max(0, buttons.size - visibleRows)
val actualContentHeight = min(buttons.size, visibleRows) * rowHeight
val minBarH = 8
val currentBarH = if (maxScroll == 0) minBarH*(barStage + 1)
else minBarH + ((actualContentHeight - minBarH).toFloat() * barStage / maxScroll).roundToInt()
buttonsProgressBar.apply {
this.width = barWidth
this.height = currentBarH.coerceAtMost(actualContentHeight)
this.x = (xi + this@ClickBox.width - barWidth).toDouble()
this.y = (yi + this@ClickBox.height + 3).toDouble()
this.x = this@ClickBox.x + this@ClickBox.width - 3
this.y = this@ClickBox.y + this@ClickBox.height + 3
}.display(guiGraphics)
val buttonWidth = (this@ClickBox.width - leftPadding - barWidth - gapToBar).coerceAtLeast(10)
val contentStartY = yi + height + 3
val maxContentY = contentStartY + (8 * 9)
buttons.forEachIndexed { num, button ->
val rowOffset = num - barStage
val yPos = contentStartY + (rowOffset * 9)
val fullHeight = (y + height.toDouble())..(this.y + height + clickboxHeightOffset)
button.also {
it.x = (xi + leftPadding).toDouble()
it.y = yPos.toDouble()
it.width = buttonWidth
it.hidden = (rowOffset < 0) || (yPos + it.height > maxContentY)
it.x = this.x + 3
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)
}.display(guiGraphics)
}
}
with(Minecraft.getInstance().font) {
guiGraphics?.drawString(
this,
Component.nullToEmpty(name.string),
(xi + 5 + (inclination / 2f)).toInt(),
(yi + 2),
ARGB.opaque(Colors.WHITE.hexValue),
false
)
guiGraphics?.run {
with(Minecraft.getInstance().font) {
drawInBatch(Component.nullToEmpty(name.string),
(x + 5), (y + 2), Colors.TRANSPARENT.hexValue, false,
pose().last().pose(), bufferSource, Font.DisplayMode.NORMAL, 0, 15728880, isBidirectional
)
}
}
}
}

View File

@ -6,8 +6,10 @@ import fr.username404.snowygui.config.Configuration
import fr.username404.snowygui.gui.ColoredElement
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.prepareDraw
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.input.MouseButtonEvent
import kotlin.reflect.full.findAnnotation
sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
@ -43,26 +45,20 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
}.plus(Configuration.foundMacros).toTypedArray()
)
}
var isDisabled: Boolean = false; set(value) {
field = value
hidden = value
}
@JvmField
val info = this::class.findAnnotation<ButtonInfo>() ?: throw Exception("Missing @ButtonInfo annotaton")
final override var color = info.parent.categoryColor; get() {
return info.parent.box.color.let {
if (field == it) field else it
}
}
open val title: String = this@ButtonImpl::class.simpleName.toString()
protected open fun execAction() = Unit
private var wasWithinBounds: Boolean = false
var toggled: Boolean = false; private set(value) {
if (field xor value) {
if (value) lightUp() else lightDown()
@ -70,12 +66,10 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
execAction()
} else field = value
}
private fun lightUp() { opacity += ButtonInfo.lightningFactor }
private fun lightDown() { opacity -= ButtonInfo.lightningFactor }
final override fun mouseClicked(event: MouseButtonEvent, isDoubleClick: Boolean): Boolean {
wasWithinBounds = isWithinBounds(event.x, event.y).also {
final override fun mouseClicked(d: Double, e: Double, i: Int): Boolean {
wasWithinBounds = isWithinBounds(d, e).also {
if (it) {
if (info.kind == Type.TOGGLE) {
toggled = !toggled
@ -85,16 +79,16 @@ sealed class ButtonImpl: ColoredElement(0.0, 0.0, 73, 8, opacity = 0.60F) {
return false
}
final override fun mouseReleased(event: MouseButtonEvent): Boolean {
final override fun mouseReleased(d: Double, e: Double, i: Int): Boolean {
if (wasWithinBounds && (info.kind == Type.CLICK)) {
execAction()
lightDown()
}
return false
}; return false
}
final override fun render(guiGraphics: GuiGraphics?) {
defaultRectFunc(guiGraphics)
prepareDraw()
colorShader(); defaultRectFunc()
endDraw()
if (guiGraphics != null) {
FontUtil.drawScaled(guiGraphics, title, x + 1, y + 1, 0.75F)
}

View File

@ -3,16 +3,11 @@ package fr.username404.snowygui.gui.feature
import fr.username404.snowygui.EventSnowy
import fr.username404.snowygui.argsLambda
import fr.username404.snowygui.gui.Renderable
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
sealed class ButtonImplWithHud: ButtonImpl() {
protected abstract val hudRenderLambda: Renderable
private val generatedLambda: argsLambda = {
if (!Minecraft.getInstance().options.hideGui) {
hudRenderLambda.render(it.first() as GuiGraphics?)
}
}
private val generatedLambda: argsLambda = { hudRenderLambda.render(it.first() as GuiGraphics?) }
final override fun execAction() {
EventSnowy["HudRender"].run {
if (toggled) add(generatedLambda)

View File

@ -28,7 +28,7 @@ annotation class ButtonInfo(
HUD("snowy.clickbox.hud", Colors.DARK_PURPLE),
MACROS("snowy.clickbox.macros", Colors.GREEN);
companion object {
fun fromBox(box: ClickBox): Category? = entries.find {
fun fromBox(box: ClickBox): Category? = values().find {
box.isCategory(it)
}
}

View File

@ -1,6 +1,19 @@
package fr.username404.snowygui.gui.feature
import net.minecraft.client.Minecraft
@ButtonInfo(Category.MISC)
object GammaBoost: ButtonImpl() {
const val BOOST = 1400.0F
private const val boost = 1400.0
private var oldGamma = 0.0
override fun execAction() {
with(Minecraft.getInstance().options) {
val gamma = gamma().get()
gamma().value =
if (toggled) {
if (gamma < boost) oldGamma = gamma
boost
} else oldGamma
}
}
}

View File

@ -44,7 +44,7 @@ object Keystrokes: ButtonImplWithHud() {
private fun drawKey(x: Double, y: Double, key: Int, guiGraphics: GuiGraphics?) {
RenderingUtil.prepareDraw()
RenderingUtil.drawRectangle(
guiGraphics, x, y, height / 2, height / 2,
x, y, height / 2, height / 2,
color = color, opacity = getDynamicOpacity(key).toFloat()
)
RenderingUtil.endDraw()
@ -68,7 +68,7 @@ object Keystrokes: ButtonImplWithHud() {
hud.display(it)
}
init {
if (!Position.entries.map { it.value }.contains(currentPosition)) {
if (!Position.values().map { it.value }.contains(currentPosition)) {
currentPosition = Position.LEFT.value
}
}

View File

@ -3,7 +3,6 @@ package fr.username404.snowygui.gui.feature
import fr.username404.snowygui.gui.feature.ButtonInfo.Companion.Type
import kotlinx.serialization.Serializable
import net.minecraft.client.Minecraft
import net.minecraft.server.permissions.Permissions
/**
* @property command The command to execute
@ -18,7 +17,7 @@ data class Macro(
override fun execAction(): Unit = with(Minecraft.getInstance().player!!) {
connection.run {
command.let {
if (it.startsWith("say") && !this@with.permissions().hasPermission(Permissions.COMMANDS_GAMEMASTER)) {
if (it.startsWith("say") && !hasPermissions(2)) {
sendChat(it.drop(4))
} else sendCommand(it)
}

View File

@ -6,26 +6,20 @@ import fr.username404.snowygui.config.SnowyConfigScreen
import fr.username404.snowygui.config.configScreenParent
import net.minecraft.client.KeyMapping
import net.minecraft.client.Minecraft
import net.minecraft.resources.Identifier
import org.lwjgl.glfw.GLFW.GLFW_KEY_U
import org.lwjgl.glfw.GLFW.GLFW_KEY_Y
private typealias privateLambda = (() -> Unit)?
object AddKeyMaps {
private const val prefix = "snowy"
var category: KeyMapping.Category? = null; private set
@JvmOverloads
internal fun mkMap(
translationSuffix: String,
key: Int, category: String = "controls",
key: Int, category: String = "keycategory",
lambda: privateLambda = null
): Pair<KeyMapping, privateLambda> = KeyMapping(
"key.$prefix.$translationSuffix", InputConstants.Type.KEYSYM,
key, this.category ?: run {
this.category = KeyMapping.Category.register(
Identifier.fromNamespaceAndPath("snowygui", category)
); this.category
}!!
key, "category.$prefix.$category"
) to lambda
val list: MutableMap<KeyMapping, privateLambda> = with(Minecraft.getInstance()) {
mutableMapOf(

View File

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

View File

@ -1,104 +1,43 @@
package fr.username404.snowygui.utils
import com.mojang.blaze3d.opengl.GlStateManager
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.BufferUploader
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.Tesselator
import com.mojang.blaze3d.vertex.VertexConsumer
import com.mojang.blaze3d.vertex.VertexFormat
import fr.username404.snowygui.gui.feature.Colors
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.util.ARGB
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.max
import kotlin.math.min
import fr.username404.snowygui.gui.hextoRGB
import net.minecraft.client.renderer.CoreShaders
object RenderingUtil {
fun prepareDraw() = GlStateManager._enableBlend()
fun endDraw() = GlStateManager._disableBlend()
private fun argbFromRgb(rgb: Int, opacity: Float = 1f): Int {
return ARGB.color(
(opacity.coerceIn(0f, 1f) * 255f).toInt().coerceIn(0, 255),
(rgb shr 16) and 0xFF,
(rgb shr 8) and 0xFF,
rgb and 0xFF
)
@JvmField val tessellator: Tesselator = Tesselator.getInstance()
@JvmStatic
fun VertexConsumer.colorIt(color: Int, opacity: Float = 1F): VertexConsumer = hextoRGB(color).run {
setColor(get(0), get(1), get(2), opacity)
}
fun colorShader() {
RenderSystem.setShader(CoreShaders.POSITION_COLOR)
RenderSystem.setShaderColor(1F, 1F, 1F, 1F)
}
fun prepareDraw() {
colorShader()
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
}
fun endDraw() {
RenderSystem.disableBlend()
}
fun drawRectangle(
guiGraphics: GuiGraphics?,
x: Double,
y: Double,
height: Int,
width: Int,
color: Int = Colors.TRANSPARENT(),
opacity: Float = 1F
) {
if (guiGraphics == null) return
val x1 = floor(x).toInt()
val y1 = floor(y).toInt()
val x2 = ceil(x + width).toInt()
val y2 = ceil(y + height).toInt()
prepareDraw()
guiGraphics.fill(x1, y1, x2, y2, argbFromRgb(color, opacity))
endDraw()
}
fun drawSlantedHeader(
guiGraphics: GuiGraphics?,
x: Int,
y: Int,
width: Int,
height: Int,
slantTop: Float,
color: Int,
opacity: Float
) {
if (guiGraphics == null) return
if (width <= 0 || height <= 0) return
val slant = slantTop.toDouble()
val baseArgb = argbFromRgb(color, opacity)
prepareDraw()
for (dy in 0 until height) {
val t = if (height == 1) 0.0 else dy.toDouble() / (height - 1).toDouble()
val leftF = x + slant * (1.0 - t)
val rightF = x + width + slant * t
val left = min(leftF, rightF)
val right = max(leftF, rightF)
val lx = floor(left).toInt()
val rx = floor(right).toInt()
val yy = y + dy
val midStart = lx + 1
val midEnd = rx
if (midEnd > midStart) {
guiGraphics.fill(midStart, yy, midEnd, yy + 1, baseArgb)
}
val leftFrac = (left - floor(left)).toFloat().coerceIn(0f, 1f)
val rightFrac = (right - floor(right)).toFloat().coerceIn(0f, 1f)
val leftAlpha = (1f - leftFrac) * opacity
val rightAlpha = rightFrac * opacity
if (leftAlpha > 0f) guiGraphics.fill(lx, yy, lx + 1, yy + 1, argbFromRgb(color, leftAlpha))
if (rightAlpha > 0f) guiGraphics.fill(rx, yy, rx + 1, yy + 1, argbFromRgb(color, rightAlpha))
if (rx <= lx) {
guiGraphics.fill(lx, yy, lx + 1, yy + 1, baseArgb)
}
}
endDraw()
}
fun hLine(guiGraphics: GuiGraphics?, x1: Int, x2: Int, y: Int, rgb: Int, opacity: Float = 1f) {
if (guiGraphics == null) return
prepareDraw()
guiGraphics.hLine(x1, x2, y, argbFromRgb(rgb, opacity))
endDraw()
x: Double, y: Double, height: Int, width: Int,
color: Int = Colors.TRANSPARENT(), opacity: Float = 1F
): Unit = tessellator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR).run {
fun VertexConsumer.colorIt() = colorIt(color, opacity)
val x = x.toFloat() ; val y = y.toFloat()
addVertex(x, y + height, 0.0F).colorIt()
addVertex(x + width, y + height, 0.0F).colorIt()
addVertex(x + width, y, 0.0F).colorIt()
addVertex(x, y, 0.0F).colorIt()
BufferUploader.drawWithShader(buildOrThrow())
}
}

View File

@ -7,13 +7,14 @@
"screen.snowy.config.general.macros.missingelement": "Missing element(s) next to the separator",
"screen.snowy.config.general.macros.toomuchdelimiters": "Too much separators (only one is allowed)",
"screen.snowy.config.general.macros.toomuchcharacters": "Too much characters (16 is the maximum)",
"screen.snowy.config.general.macros.toomuchbuttons": "Too much entries (16 is the maximum)",
"screen.snowy.config.colors": "Box colors",
"screen.snowy.config.behavior": "Behavior",
"screen.snowy.config.behavior.sortalphabetically": "Sort buttons alphabetically",
"screen.snowy.config.behavior.zoom.factor": "Zoom factor",
"screen.snowy.config.behavior.zoom.smoothcamera": "Smooth camera on zoom",
"screen.snowy.config.behavior.keystrokes.position": "Position of the keystrokes HUD element",
"key.category.snowygui.controls": "SnowyGUI",
"category.snowy.keycategory": "SnowyGUI",
"key.snowy.opengui": "Open the snowy gui",
"key.snowy.configkey": "Open the snowy configuration screen",
"snowy.clickbox.misc": "Miscellaneous",

View File

@ -7,13 +7,14 @@
"screen.snowy.config.general.macros.missingelement": "Élément(s) manquant(s) avant ou après le séparateur",
"screen.snowy.config.general.macros.toomuchdelimiters": "Séparateurs trop nombreux (un seul est autorisé)",
"screen.snowy.config.general.macros.toomuchcharacters": "Trop de caractères (le maximum est de 16)",
"screen.snowy.config.general.macros.toomuchbuttons": "Trop d'entrées (le maximum est de 16)",
"screen.snowy.config.colors": "Couleurs des boîtes",
"screen.snowy.config.behavior": "Comportement",
"screen.snowy.config.behavior.sortalphabetically": "Trier les boutons alphabétiquement",
"screen.snowy.config.behavior.zoom.factor": "Facteur de zoom",
"screen.snowy.config.behavior.zoom.smoothcamera": "Caméra fluide pendant le zoom",
"screen.snowy.config.behavior.keystrokes.position": "Position de l'élément keystrokes de l'ATH",
"key.category.snowygui.controls": "SnowyGUI",
"category.snowy.keycategory": "SnowyGUI",
"key.snowy.opengui": "Ouvrir l'interface de snowy",
"key.snowy.configkey": "Ouvrir l'écran de configuration de snowy",
"snowy.clickbox.misc": "Divers",

View File

@ -2,11 +2,10 @@
"required": true,
"package": "fr.username404.snowygui.mixins",
"compatibilityLevel": "JAVA_18",
"client": [
"GammaMixin"
],
"client": [],
"injectors": {
"defaultRequire": 1
},
"minVersion": "0.8"
"minVersion": "0.8",
"refmap": "snowygui-common-refmap.json"
}

View File

@ -3,7 +3,4 @@ accessWidener v2 named
accessible field net/minecraft/client/OptionInstance value Ljava/lang/Object;
mutable field net/minecraft/client/OptionInstance value Ljava/lang/Object;
accessible field com/mojang/blaze3d/opengl/GlCommandEncoder inRenderPass Z
mutable field com/mojang/blaze3d/opengl/GlCommandEncoder inRenderPass Z
accessible method net/minecraft/client/KeyMapping$Category register (Ljava/lang/String;)Lnet/minecraft/client/KeyMapping$Category;
accessible field net/minecraft/client/gui/GuiGraphics bufferSource Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;

View File

@ -14,10 +14,10 @@ architectury { platformSetupLoomIde(); fabric() }
dependencies {
modImplementation("${Groups.Fabric}:fabric-loader:${rootProject.property("fabric_loader_version")}")
modApi("${Groups.FabricApi}:fabric-rendering-v1:${rootProject.property("fabric_rendering_api_version")}")
modApi("${Groups.FabricApi}:fabric-api-base:${rootProject.property("fabric_api_base_version")}")
include(modApi("${Groups.FabricApi}:fabric-rendering-v1:${rootProject.property("fabric_rendering_api_version")}")!!)
include(modApi("${Groups.FabricApi}:fabric-api-base:${rootProject.property("fabric_api_base_version")}")!!)
modApi("me.shedaniel.cloth:cloth-config-fabric:${rootProject.property("clothconfig_version")}") { exclude(group = Groups.FabricApi) }
modImplementation("${Groups.FabricApi}:fabric-resource-loader-v0:${rootProject.property("fabric_resource_loader_version")}")
include(modImplementation("${Groups.FabricApi}:fabric-resource-loader-v0:${rootProject.property("fabric_resource_loader_version")}")!!)
modImplementation(group = "net.fabricmc", name = "fabric-language-kotlin", version = rootProject.property("fabric_language_kotlin") as String)
modImplementation("com.terraformersmc:modmenu:${rootProject.property("modmenu_version")}") {
exclude(group = Groups.FabricApi, module = "fabric-api-base")

View File

@ -25,11 +25,14 @@ abstract class KeyMappings {
@Inject(method = "<init>*", at = @At("RETURN"))
private void onSettingsConstructed(Minecraft minecraft, File file, CallbackInfo ci) {
final var categoryList = KeysAccessor.getSortedCategoryList();
final var categoryMap = KeysAccessor.getSortedCategoryMap();
var newKeys = Lists.newArrayList(keyMappings);
for (KeyMapping key : keysToAdd) {
if (!categoryList.contains(key.getCategory()))
categoryList.add(key.getCategory());
if (!categoryMap.containsKey(key.getCategory())) {
Optional<Integer> biggest = categoryMap.values().stream().max(Integer::compareTo);
int biggestInt = biggest.orElse(0);
categoryMap.put(key.getCategory(), biggestInt + 1);
}
newKeys.remove(key);
newKeys.add(key);
}

View File

@ -4,10 +4,10 @@ import net.minecraft.client.KeyMapping;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
import java.util.Map;
@Mixin(KeyMapping.Category.class)
@Mixin(KeyMapping.class)
public interface KeysAccessor {
@Accessor("SORT_ORDER")
static List<KeyMapping.Category> getSortedCategoryList() { throw new AssertionError(); }
@Accessor("CATEGORY_SORT_ORDER")
static Map<String, Integer> getSortedCategoryMap() { throw new AssertionError(); }
}

View File

@ -7,7 +7,6 @@ import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback.EVENT
import net.fabricmc.loader.api.FabricLoader
import net.fabricmc.loader.launch.common.FabricLauncherBase
import net.minecraft.client.DeltaTracker
import net.minecraft.client.gui.GuiGraphics
import kotlin.io.path.exists
@ -22,25 +21,20 @@ class FabricInit: Snowy(), ClientModInitializer {
EVENT.register(
object: HudRenderCallback, EventSnowy {
override val type: String = "HudRender"
override fun onHudRender(guiGraphics: GuiGraphics, tickCounter: DeltaTracker) = fire(guiGraphics)
override fun onHudRender(guiGraphics: GuiGraphics?, tickCounter: DeltaTracker?) = fire(guiGraphics)
}
)
}
override val annotatedButtons = lazy {
FabricLoader.getInstance().allMods.mapNotNull {
it.findPath(FEATURE_PACKAGE.replace('.', '/')).getOrNull()
}.filter { it.exists() && it.isDirectory() }.flatMap { buttonsDirectory ->
buttonsDirectory.listDirectoryEntries("*.class").mapNotNull { file ->
@Suppress("DEPRECATION")
FabricLauncherBase.getClass(
file.pathString.drop(1)
.replace('/', '.').removeSuffix(".class")
).let { foundClass ->
if (foundClass.isValidForButtonCollection())
foundClass.asSubclass(ButtonImpl::class.java)
else null
override val annotatedButtons = FabricLoader.getInstance().allMods.mapNotNull {
it.findPath(FeaturePackage.replace('.', '/')).getOrNull()
}.filter { it.exists() && it.isDirectory() }.flatMap { buttonsDirectory ->
mutableSetOf<Class<out ButtonImpl>>().apply {
buttonsDirectory.listDirectoryEntries("*.class").forEach { file ->
@Suppress("DEPRECATION") net.fabricmc.loader.launch.common.
FabricLauncherBase.getClass(file.pathString.drop(1).replace('/', '.').removeSuffix(".class")).let { foundClass ->
if (foundClass.isValidForButtonCollection()) add(foundClass.asSubclass(ButtonImpl::class.java))
}
}
}.toSet()
}
}
}.toSet()
}

View File

@ -1,22 +1,22 @@
org.gradle.daemon=false
kotlin.code.style=official
org.gradle.jvmargs=-Xmx2G -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+AlwaysPreTouch
org.gradle.jvmargs=-Xmx2G -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+AlwaysPreTouch
kotlin.incremental=true
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.unsafe.configuration-cache=on
org.gradle.vfs.watch=true
minecraft=1.21.11
forge_version=21.11.38-beta
kotlinforforge=6.1.0
kotlinVer=2.3.0
kotlin_coroutines_version=1.10.2
serializationVer=1.9.0
fabric_loader_version=0.18.4
fabric_language_kotlin=1.13.8+kotlin.2.3.0
fabric_resource_loader_version=3.3.4+4fc5413f53
fabric_rendering_api_version=16.2.5+1fb1cde953
fabric_api_base_version=1.0.5+4ebb5c0853
clothconfig_version=21.11.151
modmenu_version=17.0.0-beta.2
minecraft=1.21.2
forge_version=21.2.1-beta
kotlinforforge=5.7.0
kotlinVer=2.1.0
kotlin_coroutines_version=1.9.0
serializationVer=1.7.3
fabric_loader_version=0.14.20
fabric_language_kotlin=1.13.0+kotlin.2.1.0
fabric_resource_loader_version=3.0.5+c47b9d4373
fabric_rendering_api_version=8.0.5+c47b9d4373
fabric_api_base_version=0.4.48+c47b9d4373
clothconfig_version=16.0.143
modmenu_version=12.0.0

View File

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

View File

@ -1,6 +1,5 @@
package fr.username404.snowygui.forge
import fr.username404.snowygui.ClickGui
import fr.username404.snowygui.Snowy
import fr.username404.snowygui.config.SnowyConfigScreen
import fr.username404.snowygui.config.configScreenParent
@ -12,29 +11,22 @@ import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent
import net.neoforged.neoforge.client.gui.IConfigScreenFactory
import net.neoforged.neoforge.common.NeoForge
import net.neoforged.neoforgespi.language.ModFileScanData
import org.objectweb.asm.Type
@Mod("snowygui")
@Suppress("UNUSED_PARAMETER")
class ForgeInit(container: ModContainer): Snowy() {
private fun initSetup(event: FMLClientSetupEvent) {
atInit()
ClickGui.tick()
ButtonImpl.initButtons()
}
override val annotatedButtons = lazy { // Forge-specific reflection
ModList.get()
.allScanData
.flatMap { obj: ModFileScanData -> obj.classes }
.filter { data: ModFileScanData.ClassData? ->
data!!.clazz.className.startsWith(FEATURE_PACKAGE)
private fun initSetup(event: FMLClientSetupEvent) = atInit()
override val annotatedButtons = ModList.get() // Forge-specific reflection
.allScanData
.flatMap { obj: ModFileScanData -> obj.classes }
.filter { data: ModFileScanData.ClassData? ->
(data!!.javaClass.getDeclaredField("clazz").apply { isAccessible = true }.get(data) as Type).className.let { classname ->
classname.startsWith(FeaturePackage) && Class.forName(classname).isValidForButtonCollection()
}
.mapNotNull {
Class.forName((it!!.clazz.className), false, this::class.java.classLoader).run {
takeIf { isValidForButtonCollection() }
}?.asSubclass(ButtonImpl::class.java)
}
.toSet()
}
}
.map { Class.forName((it!!.javaClass.getDeclaredField("clazz").apply { isAccessible = true }.get(it) as Type).className).asSubclass(ButtonImpl::class.java)}
.toSet()
init {
container.eventBus!!.run {
addListener(this@ForgeInit::initSetup)

View File

@ -1,10 +1,18 @@
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 {