From 8b7e576d3d73b167791775af5dabe1e7bf934370 Mon Sep 17 00:00:00 2001 From: moonleay Date: Wed, 1 May 2024 18:42:50 +0200 Subject: [PATCH 01/24] feat: added permission checks to server, reworked login process, upgraded gradle, upgraded loom Signed-off-by: moonleay --- build.gradle.kts | 15 +++++++ gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/java/net/moonleay/gimbal/Main.kt | 6 +++ .../net/moonleay/gimbal/client/ClientMain.kt | 8 +++- .../gimbal/client/editor/ClientEditor.kt | 42 ++++++++++--------- .../{networking => constants}/PacketIDs.kt | 5 +-- .../PermissionIDs.kt} | 19 ++------- .../gimbal/editor/state/GimbalPolicyType.kt | 5 ++- .../gimbal/editor/state/GimbalServerState.kt | 27 ++++++++++++ .../gimbal/networking/GimbalClient.kt | 40 +++++++++++------- .../gimbal/networking/GimbalServer.kt | 36 +++++++++------- src/main/resources/gimbal.mixins.json | 1 - .../moonleay/gimbal/build/BuildConstants.kt | 2 + 14 files changed, 136 insertions(+), 74 deletions(-) rename src/main/java/net/moonleay/gimbal/{networking => constants}/PacketIDs.kt (80%) rename src/main/java/net/moonleay/gimbal/{mixin/GimbalPolicyCheckMixin.java => constants/PermissionIDs.kt} (50%) create mode 100644 src/main/java/net/moonleay/gimbal/editor/state/GimbalServerState.kt diff --git a/build.gradle.kts b/build.gradle.kts index 60a443d..ef5bc1f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,13 @@ val mavenVersion = System.getenv("CI_COMMIT_TAG") ?: System.getenv("CI_COMMIT_SH val modId: String by project val modName: String by project +/* +* Gimbal version stuff +* */ + +val gimbalProtocolVersion = 2 + + val mavenGroup: String by project val mavenArtifact: String by project @@ -50,6 +57,9 @@ group = mavenGroup project.base.archivesName.set(mavenArtifact) repositories { + maven { // Dependency api + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } } fabricApi { @@ -66,6 +76,10 @@ dependencies { modImplementation("net.fabricmc:fabric-language-kotlin:$fabricKotlinVersion") modImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion") + modApi("me.lucko:fabric-permissions-api:0.2-SNAPSHOT") + { + exclude(group = "net.fabricmc") + } } val targetJavaVersion = 17 @@ -76,6 +90,7 @@ val templateProps = mapOf( "modVersion" to project.version as String, "modId" to modId, "modName" to modName, + "protocolVersion" to gimbalProtocolVersion, "minecraftVersion" to minecraftVersion, "fabricLoaderVersion" to fabricLoaderVersion, "fabricKotlinVersion" to fabricKotlinVersion, diff --git a/gradle.properties b/gradle.properties index df0fe30..aa5c709 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ #Generated by fabric-mod-template #Sun Apr 21 19:29:15 CEST 2024 -fabric.loom.version=1.4.6 +fabric.loom.version=1.6-SNAPSHOT kotlin.version=1.9.22 fabric.api.version=0.77.0+1.19.2 yarn.version=1.19.2+build.28 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ab05b50..ea3fa1d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -18,7 +18,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/net/moonleay/gimbal/Main.kt b/src/main/java/net/moonleay/gimbal/Main.kt index b9fb433..903d100 100644 --- a/src/main/java/net/moonleay/gimbal/Main.kt +++ b/src/main/java/net/moonleay/gimbal/Main.kt @@ -19,6 +19,7 @@ package net.moonleay.gimbal import net.fabricmc.api.ModInitializer +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents import net.moonleay.gimbal.build.BuildConstants import net.moonleay.gimbal.networking.GimbalServer import org.apache.logging.log4j.LogManager @@ -31,6 +32,11 @@ internal object Main : ModInitializer { LOGGER.info("Registering packets...") GimbalServer.registerPacketHandler() LOGGER.info("Packets have been registered.") + LOGGER.info("Registering events...") + ServerPlayConnectionEvents.INIT.register(ServerPlayConnectionEvents.Init { handler, server -> + GimbalServer.notifyPlayerOfPolicy(handler.player) + }) + LOGGER.info("Events have been registered.") LOGGER.info("Gimbal has been initialized on the common side.") LOGGER.info("${BuildConstants.modName} (${BuildConstants.modId}) v.${BuildConstants.modVersion} by moonleay") } diff --git a/src/main/java/net/moonleay/gimbal/client/ClientMain.kt b/src/main/java/net/moonleay/gimbal/client/ClientMain.kt index 0d81303..0f6f156 100644 --- a/src/main/java/net/moonleay/gimbal/client/ClientMain.kt +++ b/src/main/java/net/moonleay/gimbal/client/ClientMain.kt @@ -20,7 +20,9 @@ package net.moonleay.gimbal.client import net.fabricmc.api.ClientModInitializer import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents +import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents import net.moonleay.gimbal.build.BuildConstants +import net.moonleay.gimbal.client.editor.ClientEditor import net.moonleay.gimbal.client.keybindings.KeybindingManager import net.moonleay.gimbal.client.keybindings.KeybindingRegistrar import net.moonleay.gimbal.networking.GimbalClient @@ -33,7 +35,7 @@ internal object ClientMain : ClientModInitializer { override fun onInitializeClient() { LOGGER.info("Initializing Gimbal on the client side...") KeybindingRegistrar.registerKeybindings() - registerEvents() + this.registerEvents() LOGGER.info("Registering packets...") GimbalClient.registerPacketHandlers() LOGGER.info("Packets have been registered.") @@ -45,6 +47,10 @@ internal object ClientMain : ClientModInitializer { ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { client -> KeybindingManager.onClientTick(client) }) + + ClientLoginConnectionEvents.INIT.register(ClientLoginConnectionEvents.Init { _, _ -> + ClientEditor.onConnectedToNewWorld() // Client is connecting to a new server, reset the editor + }) LOGGER.info("Client events have been registered.") } diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index 2a732bb..e64b4e4 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -24,11 +24,11 @@ import net.moonleay.gimbal.client.util.ChatUtil import net.moonleay.gimbal.editor.ServerEditorManager import net.moonleay.gimbal.editor.state.EditorState import net.moonleay.gimbal.editor.state.GimbalPolicyType +import net.moonleay.gimbal.editor.state.GimbalServerState import net.moonleay.gimbal.editor.state.mode.Capability import net.moonleay.gimbal.editor.state.mode.Mode import net.moonleay.gimbal.editor.state.mode.ModeModifier import net.moonleay.gimbal.editor.util.EditorUtil -import net.moonleay.gimbal.editor.util.GimbalPolicy import net.moonleay.gimbal.networking.GimbalClient object ClientEditor { @@ -45,12 +45,6 @@ object ClientEditor { fun onConnectedToNewWorld() { POLICY = GimbalPolicyType.NOT_PRESENT - GimbalClient.checkIfServerHasGimble( - EditorState( - CURRENT_MODE, - CURRENT_MODE_MODIFIER - ) - ) if (TEMP_DISABLED_MODE == Mode.UNKNOWN) { TEMP_DISABLED_MODE = CURRENT_MODE @@ -62,9 +56,9 @@ object ClientEditor { CURRENT_MODE_MODIFIER.clear() } - fun onAllowedCheck(data: GimbalPolicy) { - POLICY = data.policy - if (data.policy == GimbalPolicyType.ALLOWED) { + fun onPolicyReceived(data: GimbalServerState, shouldUpdateServer: Boolean = true) { + POLICY = data.policyType + if (data.policyType == GimbalPolicyType.ALLOWED) { if (TEMP_DISABLED_MODE != Mode.UNKNOWN) { CURRENT_MODE = TEMP_DISABLED_MODE @@ -74,7 +68,13 @@ object ClientEditor { DISABLED_MODIFIERS_STORAGE ) DISABLED_MODIFIERS_STORAGE.clear() - onUpdated() + onUpdated(shouldUpdateServer) + + if (!shouldUpdateServer) + ServerEditorManager.updateEditorState( + MinecraftClient.getInstance().player!!.uuid, + this.getClientState() + ) } } @@ -99,11 +99,8 @@ object ClientEditor { * Send an updated player state to the server * */ private fun updateServerState() { - val state = EditorState( - CURRENT_MODE, - CURRENT_MODE_MODIFIER - ) - GimbalClient.sendEditorState(state) + val state = this.getClientState() + GimbalClient.sendStatePacket(state) ServerEditorManager.updateEditorState(MinecraftClient.getInstance().player!!.uuid, state) } @@ -150,17 +147,17 @@ object ClientEditor { onUpdated() } - private fun onUpdated() { + private fun onUpdated(shouldUpdateServer: Boolean = true) { CURRENT_MODE_MODIFIER.sortBy { it.displayName } - checkForIncompatibleModeModifiers() + checkForIncompatibleModeModifiers(shouldUpdateServer) } /** * This runs on Mode updated */ - private fun checkForIncompatibleModeModifiers() { + private fun checkForIncompatibleModeModifiers(shouldUpdateServer: Boolean = true) { if (TEMP_DISABLED_MODIFIERS.size > 0) { CURRENT_MODE_MODIFIER.addAll( TEMP_DISABLED_MODIFIERS @@ -185,7 +182,8 @@ object ClientEditor { } // Update State - updateServerState() + if (shouldUpdateServer) + updateServerState() if(TEMP_DISABLED_MODIFIERS.isNotEmpty()) { ChatUtil.showToastToSelf( @@ -230,4 +228,8 @@ object ClientEditor { fun getCurrentColor(): Int { return CURRENT_MODE.color } + + fun getClientState(): EditorState { + return EditorState(CURRENT_MODE, CURRENT_MODE_MODIFIER) + } } diff --git a/src/main/java/net/moonleay/gimbal/networking/PacketIDs.kt b/src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt similarity index 80% rename from src/main/java/net/moonleay/gimbal/networking/PacketIDs.kt rename to src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt index cae6037..500ff74 100644 --- a/src/main/java/net/moonleay/gimbal/networking/PacketIDs.kt +++ b/src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt @@ -16,14 +16,13 @@ * along with this program. If not, see . */ -package net.moonleay.gimbal.networking +package net.moonleay.gimbal.constants import net.minecraft.util.Identifier import net.moonleay.gimbal.build.BuildConstants object PacketIDs { val UPDATE_EDITOR_STATE_ID = Identifier(BuildConstants.modId, "update_editor_state") - val GIMBLE_PRERENCE_CHECK_ID = Identifier(BuildConstants.modId, "gimble_preference_check") - val TRANSFER_GIMBLE_POLICY_ID = Identifier(BuildConstants.modId, "gimble_is_present") + val GIMBAL_POLICY_PACKET_ID = Identifier(BuildConstants.modId, "gimble_policy") } diff --git a/src/main/java/net/moonleay/gimbal/mixin/GimbalPolicyCheckMixin.java b/src/main/java/net/moonleay/gimbal/constants/PermissionIDs.kt similarity index 50% rename from src/main/java/net/moonleay/gimbal/mixin/GimbalPolicyCheckMixin.java rename to src/main/java/net/moonleay/gimbal/constants/PermissionIDs.kt index 637f13d..7263609 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/GimbalPolicyCheckMixin.java +++ b/src/main/java/net/moonleay/gimbal/constants/PermissionIDs.kt @@ -16,21 +16,8 @@ * along with this program. If not, see . */ -package net.moonleay.gimbal.mixin; +package net.moonleay.gimbal.constants -import net.minecraft.client.gui.screen.DownloadingTerrainScreen; -import net.moonleay.gimbal.client.editor.ClientEditor; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(DownloadingTerrainScreen.class) -public class GimbalPolicyCheckMixin { - - - @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/DownloadingTerrainScreen;close()V", ordinal = -1)) - private void func(CallbackInfo ci) { - ClientEditor.INSTANCE.onConnectedToNewWorld(); - } +object PermissionIDs { + const val GIMBAL_USAGE_PERMISSION = "gimbal.use" } diff --git a/src/main/java/net/moonleay/gimbal/editor/state/GimbalPolicyType.kt b/src/main/java/net/moonleay/gimbal/editor/state/GimbalPolicyType.kt index cf045be..37c7341 100644 --- a/src/main/java/net/moonleay/gimbal/editor/state/GimbalPolicyType.kt +++ b/src/main/java/net/moonleay/gimbal/editor/state/GimbalPolicyType.kt @@ -18,8 +18,11 @@ package net.moonleay.gimbal.editor.state +import kotlinx.serialization.Serializable + +@Serializable enum class GimbalPolicyType { ALLOWED, DENIED, - NOT_PRESENT + NOT_PRESENT, } diff --git a/src/main/java/net/moonleay/gimbal/editor/state/GimbalServerState.kt b/src/main/java/net/moonleay/gimbal/editor/state/GimbalServerState.kt new file mode 100644 index 0000000..7dffedc --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/state/GimbalServerState.kt @@ -0,0 +1,27 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.editor.state + +import kotlinx.serialization.Serializable + +@Serializable +data class GimbalServerState( + val protocolVersion: Int, + val policyType: GimbalPolicyType, +) diff --git a/src/main/java/net/moonleay/gimbal/networking/GimbalClient.kt b/src/main/java/net/moonleay/gimbal/networking/GimbalClient.kt index c2b154a..fa179df 100644 --- a/src/main/java/net/moonleay/gimbal/networking/GimbalClient.kt +++ b/src/main/java/net/moonleay/gimbal/networking/GimbalClient.kt @@ -25,38 +25,46 @@ import kotlinx.serialization.encodeToByteArray import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking import net.fabricmc.fabric.api.networking.v1.PacketByteBufs import net.minecraft.network.PacketByteBuf +import net.moonleay.gimbal.build.BuildConstants import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.constants.PacketIDs import net.moonleay.gimbal.editor.state.EditorState -import net.moonleay.gimbal.editor.util.GimbalPolicy +import net.moonleay.gimbal.editor.state.GimbalPolicyType +import net.moonleay.gimbal.editor.state.GimbalServerState object GimbalClient { fun registerPacketHandlers() { - ClientPlayNetworking.registerGlobalReceiver(PacketIDs.TRANSFER_GIMBLE_POLICY_ID) { _, _, buf, _ -> - onAllowedCheck(buf) + ClientPlayNetworking.registerGlobalReceiver(PacketIDs.GIMBAL_POLICY_PACKET_ID) { _, _, buf, handler -> + val state = this.getServerState(buf) + val isUsable = this.isGimbalUsable(state) + if (isUsable) { + val buf = PacketByteBufs.create() + buf.writeByteArray(Cbor.encodeToByteArray(ClientEditor.getClientState())) + handler.sendPacket(PacketIDs.UPDATE_EDITOR_STATE_ID, buf) + } + ClientEditor.onPolicyReceived(state, false) } } @OptIn(ExperimentalSerializationApi::class) - private fun onAllowedCheck(buf: PacketByteBuf) { - val policy = Cbor.decodeFromByteArray(buf.readByteArray()) - ClientEditor.onAllowedCheck(policy) // Update the client's policy + private fun getServerState(buf: PacketByteBuf): GimbalServerState { + val serverState = Cbor.decodeFromByteArray(buf.readByteArray()) + return serverState } - /** - * Sends the given [EditorState] to the server. - */ - @OptIn(ExperimentalSerializationApi::class) - fun sendEditorState(state: EditorState) { - val buf = PacketByteBufs.create() - buf.writeByteArray(Cbor.encodeToByteArray(state)) - ClientPlayNetworking.send(PacketIDs.UPDATE_EDITOR_STATE_ID, buf) + private fun isGimbalUsable(state: GimbalServerState): Boolean { + return state.policyType == GimbalPolicyType.ALLOWED && state.protocolVersion.toString() == BuildConstants.protocolVersion } @OptIn(ExperimentalSerializationApi::class) - fun checkIfServerHasGimble(state: EditorState) { + private fun createStatePacket(state: EditorState): PacketByteBuf { val buf = PacketByteBufs.create() buf.writeByteArray(Cbor.encodeToByteArray(state)) - ClientPlayNetworking.send(PacketIDs.GIMBLE_PRERENCE_CHECK_ID, buf) + return buf + } + + fun sendStatePacket(state: EditorState) { + ClientPlayNetworking.send(PacketIDs.UPDATE_EDITOR_STATE_ID, createStatePacket(state)) } } diff --git a/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt b/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt index 7ba0d38..82f8968 100644 --- a/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt +++ b/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt @@ -21,28 +21,41 @@ package net.moonleay.gimbal.networking import kotlinx.serialization.cbor.Cbor import kotlinx.serialization.decodeFromByteArray import kotlinx.serialization.encodeToByteArray +import me.lucko.fabric.api.permissions.v0.Permissions import net.fabricmc.fabric.api.networking.v1.PacketByteBufs import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking import net.minecraft.network.PacketByteBuf import net.minecraft.server.network.ServerPlayerEntity +import net.moonleay.gimbal.build.BuildConstants +import net.moonleay.gimbal.constants.PacketIDs +import net.moonleay.gimbal.constants.PermissionIDs import net.moonleay.gimbal.editor.ServerEditorManager import net.moonleay.gimbal.editor.state.EditorState import net.moonleay.gimbal.editor.state.GimbalPolicyType -import net.moonleay.gimbal.editor.util.GimbalPolicy +import net.moonleay.gimbal.editor.state.GimbalServerState object GimbalServer { fun registerPacketHandler() { ServerPlayNetworking .registerGlobalReceiver(PacketIDs.UPDATE_EDITOR_STATE_ID) - { server, player, handler, buf, responseSender -> + { _, player, _, buf, _ -> handleStateUpdate(player, buf) } - ServerPlayNetworking - .registerGlobalReceiver(PacketIDs.GIMBLE_PRERENCE_CHECK_ID) - { server, player, handler, buf, responseSender -> - handlePresenceCheck(player, buf) - } + } + + fun notifyPlayerOfPolicy(player: ServerPlayerEntity) { + println("Sending policy packet to player ${player.name.string}...") + val buf = PacketByteBufs.create() + buf.writeByteArray( + Cbor.encodeToByteArray( + GimbalServerState( + BuildConstants.protocolVersion.toInt(), + if (this.isPlayerAllowedToUseGimbal(player)) GimbalPolicyType.ALLOWED else GimbalPolicyType.DENIED + ) + ) + ) + ServerPlayNetworking.send(player, PacketIDs.GIMBAL_POLICY_PACKET_ID, buf) } private fun handleStateUpdate(player: ServerPlayerEntity, buf: PacketByteBuf){ @@ -51,12 +64,7 @@ object GimbalServer { // player.sendMessage(Text.of("Mode: ${state.editorMode} with ${state.editorModifier}")) } - private fun handlePresenceCheck(player: ServerPlayerEntity, buf: PacketByteBuf) { - val state = Cbor.decodeFromByteArray(buf.readByteArray()) - ServerEditorManager.updateEditorState(player.uuid, state) - - val buffer = PacketByteBufs.create() - buffer.writeByteArray(Cbor.encodeToByteArray(GimbalPolicy(GimbalPolicyType.ALLOWED))) - ServerPlayNetworking.send(player, PacketIDs.TRANSFER_GIMBLE_POLICY_ID, buffer) + private fun isPlayerAllowedToUseGimbal(player: ServerPlayerEntity): Boolean { + return player.hasPermissionLevel(2) || Permissions.check(player, PermissionIDs.GIMBAL_USAGE_PERMISSION) } } diff --git a/src/main/resources/gimbal.mixins.json b/src/main/resources/gimbal.mixins.json index 2b67f6d..1b47528 100644 --- a/src/main/resources/gimbal.mixins.json +++ b/src/main/resources/gimbal.mixins.json @@ -11,7 +11,6 @@ "client": [ "BulldozerMixin", "BulldozerMixin2", - "GimbalPolicyCheckMixin", "HudMixin", "NoClipCameraFixMixin", "NormalModeMixin", diff --git a/src/main/templates/net/moonleay/gimbal/build/BuildConstants.kt b/src/main/templates/net/moonleay/gimbal/build/BuildConstants.kt index 5b12b57..d90f0ff 100644 --- a/src/main/templates/net/moonleay/gimbal/build/BuildConstants.kt +++ b/src/main/templates/net/moonleay/gimbal/build/BuildConstants.kt @@ -22,4 +22,6 @@ internal object BuildConstants { const val modId = "${modId}" const val modName = "${modName}" const val modVersion = "${modVersion}" + const val protocolVersion = "${protocolVersion}" } + From 8bcbcc021b2f2b7145d9b72f1fb045045717b93a Mon Sep 17 00:00:00 2001 From: moonleay Date: Wed, 1 May 2024 19:55:53 +0200 Subject: [PATCH 02/24] fix: fixed not being able to join worlds in multiplayer and singleplayer Signed-off-by: moonleay --- .../net/moonleay/gimbal/client/editor/ClientEditor.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index e64b4e4..b3c1a4f 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -70,11 +70,17 @@ object ClientEditor { DISABLED_MODIFIERS_STORAGE.clear() onUpdated(shouldUpdateServer) - if (!shouldUpdateServer) + if (!shouldUpdateServer) { + val player = MinecraftClient.getInstance().player + if (player == null) { + println("Player is null!") + return + } ServerEditorManager.updateEditorState( MinecraftClient.getInstance().player!!.uuid, this.getClientState() ) + } } } From c321746b0838400fd36354af158c40e1f1b3acaf Mon Sep 17 00:00:00 2001 From: moonleay Date: Wed, 1 May 2024 19:56:31 +0200 Subject: [PATCH 03/24] feat: bump version, set correct protocol version Signed-off-by: moonleay --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ef5bc1f..d677946 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,7 +30,7 @@ plugins { } val mavenVersion = System.getenv("CI_COMMIT_TAG") ?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" } -?: "0.1.1-dev" //""0.0.0-SNAPSHOT" +?: "0.2.0-dev" //"0.0.0-SNAPSHOT" val modId: String by project val modName: String by project @@ -38,7 +38,7 @@ val modName: String by project * Gimbal version stuff * */ -val gimbalProtocolVersion = 2 +val gimbalProtocolVersion = 1 val mavenGroup: String by project From dca01b275f96753c4e5e9906c5df756ce815f8a5 Mon Sep 17 00:00:00 2001 From: moonleay Date: Sat, 4 May 2024 02:35:49 +0200 Subject: [PATCH 04/24] feat!: reworked replace mode to work server side, added propper stair replacement support Signed-off-by: moonleay --- .../gimbal/mixin/ReplaceModeMixin.java | 78 +++++++------------ .../mixin/ReplaceStateUpdaterMixin.java | 74 ++++++++++++++++++ src/main/resources/gimbal.accesswidener | 1 + src/main/resources/gimbal.mixins.json | 7 +- 4 files changed, 108 insertions(+), 52 deletions(-) create mode 100644 src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java diff --git a/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java index 477b86d..8e2a4fa 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java @@ -18,70 +18,50 @@ package net.moonleay.gimbal.mixin; -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.client.particle.ParticleManager; -import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsageContext; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.moonleay.gimbal.client.editor.ClientEditor; +import net.minecraft.world.World; +import net.moonleay.gimbal.editor.ServerEditorManager; import net.moonleay.gimbal.editor.state.mode.Capability; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(MinecraftClient.class) -public abstract class ReplaceModeMixin { +import java.util.UUID; +@Mixin(ItemPlacementContext.class) +public abstract class ReplaceModeMixin extends ItemUsageContext { - @Shadow protected abstract void handleBlockBreaking(boolean breaking); + @Shadow + protected boolean canReplaceExisting; - @Shadow @Nullable public ClientPlayerInteractionManager interactionManager; + @Mutable + @Shadow + @Final + private BlockPos placementPos; - @Shadow @Final public ParticleManager particleManager; - - @Shadow @Nullable public ClientPlayerEntity player; - - @Shadow @Nullable public HitResult crosshairTarget; - - @Inject(method = "doItemUse", at = @At("HEAD")) - private void replaceBlock(CallbackInfo ci) { - assert this.player != null; - if (!this.player.isCreative()) - return; - // Check if should run - if (!ClientEditor.INSTANCE.shouldClient(Capability.REPLACE)) - return; // Mode is not REPLACE, ignore - MinecraftClient client = MinecraftClient.getInstance(); - assert this.interactionManager != null; - if (!this.interactionManager.getCurrentGameMode().isCreative()) - return; - if (!(this.crosshairTarget instanceof BlockHitResult blockHitResult)) - return; - if (blockHitResult == null) - return; - - // Gather data - BlockPos pos = blockHitResult.getBlockPos(); - Direction direction = blockHitResult.getSide(); - BlockState blockState = client.world.getBlockState(pos); - - // Start sending shit - client.getTutorialManager().onBlockBreaking(client.world, pos, blockState, 1.0F); - this.interactionManager.sendSequencedPacket(client.world, sequence -> { - this.interactionManager.breakBlock(pos); - return new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence); - }); - this.player.swingHand(Hand.MAIN_HAND); + public ReplaceModeMixin(PlayerEntity player, Hand hand, BlockHitResult hit) { + super(player, hand, hit); } + @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/hit/BlockHitResult;)V", at = @At(value = "RETURN")) + private void func(World world, PlayerEntity playerEntity, Hand hand, ItemStack itemStack, BlockHitResult blockHitResult, CallbackInfo ci) { + if (playerEntity == null) + return; + UUID id = playerEntity.getGameProfile().getId(); + if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE)) + return; + + this.canReplaceExisting = true; + this.placementPos = blockHitResult.getBlockPos(); + } } diff --git a/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java new file mode 100644 index 0000000..7d0772d --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java @@ -0,0 +1,74 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.mixin; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.StairsBlock; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemPlacementContext; +import net.moonleay.gimbal.editor.ServerEditorManager; +import net.moonleay.gimbal.editor.state.mode.Capability; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.UUID; + +import static net.minecraft.block.StairsBlock.*; + +@Mixin(BlockItem.class) +public abstract class ReplaceStateUpdaterMixin extends Item { + + public ReplaceStateUpdaterMixin(Settings settings) { + super(settings); + } + + @Shadow + protected abstract boolean place(ItemPlacementContext context, BlockState state); + + @Redirect(method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BlockItem;place(Lnet/minecraft/item/ItemPlacementContext;Lnet/minecraft/block/BlockState;)Z")) + private boolean func(BlockItem instance, ItemPlacementContext context, BlockState state) { + if (context.getPlayer() == null) + return this.place(context, state); + UUID id = context.getPlayer().getGameProfile().getId(); + if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE)) + return this.place(context, state); + BlockState oldState = context.getWorld().getBlockState(context.getBlockPos()); + Block targetBl = oldState.getBlock(); + if (state.getBlock() instanceof StairsBlock && targetBl instanceof StairsBlock targetStair) { + // Block and item is stairs, parse Stairs data + return this.place(context, copyStairState(oldState, instance)); + } + return this.place(context, state); + } + + + @Unique + public BlockState copyStairState(BlockState targetState, BlockItem item) { + BlockState blockState = item.getBlock().getDefaultState() + .with(FACING, targetState.get(FACING)) + .with(HALF, targetState.get(HALF)) + .with(WATERLOGGED, targetState.get(WATERLOGGED)); + return blockState.with(SHAPE, targetState.get(SHAPE)); + } +} diff --git a/src/main/resources/gimbal.accesswidener b/src/main/resources/gimbal.accesswidener index e659ad2..ee44473 100644 --- a/src/main/resources/gimbal.accesswidener +++ b/src/main/resources/gimbal.accesswidener @@ -2,3 +2,4 @@ accessWidener v2 named accessible method net/minecraft/client/MinecraftClient handleBlockBreaking (Z)V accessible method net/minecraft/client/network/ClientPlayerInteractionManager sendSequencedPacket (Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/network/SequencedPacketCreator;)V +accessible field net/minecraft/state/State owner Ljava/lang/Object; diff --git a/src/main/resources/gimbal.mixins.json b/src/main/resources/gimbal.mixins.json index 1b47528..adf557d 100644 --- a/src/main/resources/gimbal.mixins.json +++ b/src/main/resources/gimbal.mixins.json @@ -6,15 +6,16 @@ "mixins": [ "ForcePlaceMixin", "NoBlockUpdatesMixin", - "NoClipMixin" + "NoClipMixin", + "ReplaceModeMixin", + "ReplaceStateUpdaterMixin" ], "client": [ "BulldozerMixin", "BulldozerMixin2", "HudMixin", "NoClipCameraFixMixin", - "NormalModeMixin", - "ReplaceModeMixin" + "NormalModeMixin" ], "injectors": { "defaultRequire": 1 From b5d65623aa037fa35e972fac8a8d6534e774069c Mon Sep 17 00:00:00 2001 From: moonleay Date: Sat, 4 May 2024 02:36:41 +0200 Subject: [PATCH 05/24] chore!: bumped version to 0.3.0, bumped protocol version to 2 Signed-off-by: moonleay --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d677946..2ca88dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,7 +30,7 @@ plugins { } val mavenVersion = System.getenv("CI_COMMIT_TAG") ?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" } -?: "0.2.0-dev" //"0.0.0-SNAPSHOT" +?: "0.3.0" //"0.0.0-SNAPSHOT" val modId: String by project val modName: String by project @@ -38,7 +38,7 @@ val modName: String by project * Gimbal version stuff * */ -val gimbalProtocolVersion = 1 +val gimbalProtocolVersion = 2 val mavenGroup: String by project From 7cf65cffd294920d06b0aa96b670912d5e28a851 Mon Sep 17 00:00:00 2001 From: moonleay Date: Sat, 4 May 2024 02:39:54 +0200 Subject: [PATCH 06/24] chore: updated overlooked mentions of old name Signed-off-by: moonleay --- .../java/net/moonleay/gimbal/client/editor/ClientEditor.kt | 6 +++--- src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index b3c1a4f..a220346 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -116,7 +116,7 @@ object ClientEditor { * */ fun setMode(mode: Mode) { if (!isAllowed()) { - ChatUtil.showToastToSelf("Gimble is disabled", "You cannot change modes", MinecraftClient.getInstance()) + ChatUtil.showToastToSelf("Gimbal is disabled", "You cannot change modes", MinecraftClient.getInstance()) return } if (!MinecraftClient.getInstance().player!!.isCreative) @@ -131,7 +131,7 @@ object ClientEditor { * */ fun toggleModifier(mod: ModeModifier) { if (!isAllowed()) { - ChatUtil.showToastToSelf("Gimble is disabled", "You cannot change modifiers", MinecraftClient.getInstance()) + ChatUtil.showToastToSelf("Gimbal is disabled", "You cannot change modifiers", MinecraftClient.getInstance()) return } if (!MinecraftClient.getInstance().player!!.isCreative) @@ -226,7 +226,7 @@ object ClientEditor { displayText.append("]") } else if (!isAllowed() || !MinecraftClient.getInstance().player?.isCreative!!) { displayText.clear() - displayText.append("[GIMBLE DISABLED]") + displayText.append("[GIMBAL DISABLED]") } return Text.of(displayText.toString()) } diff --git a/src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt b/src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt index 500ff74..da664c0 100644 --- a/src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt +++ b/src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt @@ -23,6 +23,6 @@ import net.moonleay.gimbal.build.BuildConstants object PacketIDs { val UPDATE_EDITOR_STATE_ID = Identifier(BuildConstants.modId, "update_editor_state") - val GIMBAL_POLICY_PACKET_ID = Identifier(BuildConstants.modId, "gimble_policy") + val GIMBAL_POLICY_PACKET_ID = Identifier(BuildConstants.modId, "gimbal_policy") } From 13cbbfa72fe47a51cac9aa7aea43e76e153e2700 Mon Sep 17 00:00:00 2001 From: moonleay Date: Sat, 4 May 2024 02:48:56 +0200 Subject: [PATCH 07/24] chore: replaced println() with proper logging util Signed-off-by: moonleay --- .../java/net/moonleay/gimbal/client/editor/ClientEditor.kt | 7 ++++++- .../java/net/moonleay/gimbal/networking/GimbalServer.kt | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index a220346..dde4c56 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -20,6 +20,7 @@ package net.moonleay.gimbal.client.editor import net.minecraft.client.MinecraftClient import net.minecraft.text.Text +import net.moonleay.gimbal.build.BuildConstants import net.moonleay.gimbal.client.util.ChatUtil import net.moonleay.gimbal.editor.ServerEditorManager import net.moonleay.gimbal.editor.state.EditorState @@ -30,6 +31,7 @@ import net.moonleay.gimbal.editor.state.mode.Mode import net.moonleay.gimbal.editor.state.mode.ModeModifier import net.moonleay.gimbal.editor.util.EditorUtil import net.moonleay.gimbal.networking.GimbalClient +import org.apache.logging.log4j.LogManager object ClientEditor { private var POLICY = GimbalPolicyType.NOT_PRESENT @@ -43,6 +45,9 @@ object ClientEditor { private val DISABLED_MODIFIERS_STORAGE = mutableListOf() + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + + fun onConnectedToNewWorld() { POLICY = GimbalPolicyType.NOT_PRESENT if (TEMP_DISABLED_MODE == Mode.UNKNOWN) { @@ -73,7 +78,7 @@ object ClientEditor { if (!shouldUpdateServer) { val player = MinecraftClient.getInstance().player if (player == null) { - println("Player is null!") + LOGGER.warn("Player is null!") //FIXME: Fix player is null at world join! return } ServerEditorManager.updateEditorState( diff --git a/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt b/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt index 82f8968..fd0e654 100644 --- a/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt +++ b/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt @@ -18,6 +18,7 @@ package net.moonleay.gimbal.networking +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.cbor.Cbor import kotlinx.serialization.decodeFromByteArray import kotlinx.serialization.encodeToByteArray @@ -33,8 +34,10 @@ import net.moonleay.gimbal.editor.ServerEditorManager import net.moonleay.gimbal.editor.state.EditorState import net.moonleay.gimbal.editor.state.GimbalPolicyType import net.moonleay.gimbal.editor.state.GimbalServerState +import org.apache.logging.log4j.LogManager object GimbalServer { + private val LOGGER = LogManager.getLogger(BuildConstants.modName) fun registerPacketHandler() { ServerPlayNetworking @@ -44,8 +47,9 @@ object GimbalServer { } } + @OptIn(ExperimentalSerializationApi::class) fun notifyPlayerOfPolicy(player: ServerPlayerEntity) { - println("Sending policy packet to player ${player.name.string}...") + LOGGER.info("Sending policy to " + player.name.string) val buf = PacketByteBufs.create() buf.writeByteArray( Cbor.encodeToByteArray( From 5c77165d17d6c89f8a729f95d1af669a464c73dc Mon Sep 17 00:00:00 2001 From: moonleay Date: Sun, 5 May 2024 05:11:33 +0200 Subject: [PATCH 08/24] feat: added config, added config ui, started working on HUD configurator Signed-off-by: moonleay --- .../net/moonleay/gimbal/client/ClientMain.kt | 7 + .../gimbal/client/config/AnchorPoint.kt | 30 ++++ .../gimbal/client/config/Centerpoint.kt | 27 ++++ .../client/config/ClientConfigHolder.kt | 70 +++++++++ .../client/config/GimbalClientConfig.kt | 27 ++++ .../gimbal/client/config/GimbalGuiSettings.kt | 28 ++++ .../gimbal/client/config/ScaledRes.kt | 27 ++++ .../gimbal/client/screen/GimbalEditHudGui.kt | 135 ++++++++++++++++++ .../gimbal/client/screen/GimbalSettingsGui.kt | 84 +++++++++++ .../gimbal/client/util/screen/ScreenUtil.kt | 61 ++++++++ .../datagen/En_us_GimbalLanguageProvider.kt | 14 +- .../gimbal/mixin/YouInjectButtonMixin.java | 66 +++++++++ .../gimbal/mixin/YouInjectButtonMixin2.java | 65 +++++++++ .../gimbal_options_texture_button.png | Bin 0 -> 1228 bytes src/main/resources/gimbal.mixins.json | 4 +- 15 files changed, 643 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/config/Centerpoint.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt create mode 100644 src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java create mode 100644 src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java create mode 100644 src/main/resources/assets/gimbal/textures/gimbal_options_texture_button.png diff --git a/src/main/java/net/moonleay/gimbal/client/ClientMain.kt b/src/main/java/net/moonleay/gimbal/client/ClientMain.kt index 0f6f156..2af8b59 100644 --- a/src/main/java/net/moonleay/gimbal/client/ClientMain.kt +++ b/src/main/java/net/moonleay/gimbal/client/ClientMain.kt @@ -21,7 +21,9 @@ package net.moonleay.gimbal.client import net.fabricmc.api.ClientModInitializer import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents +import net.fabricmc.loader.api.FabricLoader import net.moonleay.gimbal.build.BuildConstants +import net.moonleay.gimbal.client.config.ClientConfigHolder import net.moonleay.gimbal.client.editor.ClientEditor import net.moonleay.gimbal.client.keybindings.KeybindingManager import net.moonleay.gimbal.client.keybindings.KeybindingRegistrar @@ -30,6 +32,7 @@ import org.apache.logging.log4j.LogManager internal object ClientMain : ClientModInitializer { private val LOGGER = LogManager.getLogger(BuildConstants.modName) + lateinit var CONFIG: ClientConfigHolder override fun onInitializeClient() { @@ -39,6 +42,10 @@ internal object ClientMain : ClientModInitializer { LOGGER.info("Registering packets...") GimbalClient.registerPacketHandlers() LOGGER.info("Packets have been registered.") + LOGGER.info("Loading client config.") + val gimbalConfigPath = FabricLoader.getInstance().configDir.resolve(BuildConstants.modId + "/client.json") + CONFIG = ClientConfigHolder(gimbalConfigPath) + LOGGER.info("Config has been loaded.") LOGGER.info("Gimbal has been initialized on the client side.") } diff --git a/src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt b/src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt new file mode 100644 index 0000000..29f34a2 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt @@ -0,0 +1,30 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +import kotlinx.serialization.Serializable + +@Serializable +enum class AnchorPoint { + TOP_LEFT, + TOP_RIGHT, + BOTTOM_RIGHT, + BOTTOM_LEFT, + CENTER +} diff --git a/src/main/java/net/moonleay/gimbal/client/config/Centerpoint.kt b/src/main/java/net/moonleay/gimbal/client/config/Centerpoint.kt new file mode 100644 index 0000000..2cb8029 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/Centerpoint.kt @@ -0,0 +1,27 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +enum class Centerpoint { + TOP_LEFT, + TOP_RIGHT, + BOTTOM_RIGHT, + BOTTOM_LEFT, + CENTER +} diff --git a/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt new file mode 100644 index 0000000..c385f49 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt @@ -0,0 +1,70 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromStream +import kotlinx.serialization.json.encodeToStream +import java.nio.file.Path +import kotlin.io.path.* + +class ClientConfigHolder(private val path: Path) { + var config: GimbalClientConfig + private set + + init { + config = load() + } + + fun updateConfig(new: GimbalClientConfig) { + config = new + save(config) + } + + @OptIn(ExperimentalSerializationApi::class) + fun load(): GimbalClientConfig { + if (!path.isReadable()) + save(GimbalClientConfig()) + return path.inputStream().use { + Json.decodeFromStream(it) + } + } + + @OptIn(ExperimentalSerializationApi::class) + fun save(conf: GimbalClientConfig) { + if (!path.isWritable()) { + if (!path.parent.exists()) { + path.parent.createDirectory() + } + if (!path.parent.isWritable()) { + throw Exception("Parent of path ${path.parent.pathString} is not writable.") + } + if (!path.exists()) + path.createFile() + if (!path.isWritable()) { + throw Exception("Path (${path.pathString}) exists, but is not writable.") + } + } + path.outputStream().use { + Json.encodeToStream(conf, it) + } + } + +} diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt new file mode 100644 index 0000000..b0184d7 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt @@ -0,0 +1,27 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +import kotlinx.serialization.Serializable + +@Serializable +data class GimbalClientConfig( + val guiSettings: GimbalGuiSettings = GimbalGuiSettings(), + val showToasts: Boolean = true, +) diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt new file mode 100644 index 0000000..2a274b0 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt @@ -0,0 +1,28 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +import kotlinx.serialization.Serializable + +@Serializable +data class GimbalGuiSettings( + val showHud: Boolean = true, + val scaledRes: ScaledRes = ScaledRes(4.0, 4.0), + val anchorPoint: AnchorPoint = AnchorPoint.TOP_LEFT, +) diff --git a/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt b/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt new file mode 100644 index 0000000..acf9a70 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt @@ -0,0 +1,27 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +import kotlinx.serialization.Serializable + +@Serializable +data class ScaledRes( + val scaledX: Double, + val scaledY: Double, +) diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt new file mode 100644 index 0000000..0b7fd61 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -0,0 +1,135 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.screen + +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.screen.ScreenTexts +import net.minecraft.text.Text +import net.moonleay.gimbal.build.BuildConstants +import net.moonleay.gimbal.client.config.* +import net.moonleay.gimbal.client.util.screen.ScreenUtil +import org.apache.logging.log4j.LogManager + +class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfigHolder) : + Screen(Text.translatable("gimbal.gui.edithud")) { + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + + private var tempXOffset = 4.0 + private var tempYOffset = 4.0 + private var shouldFollow = false + + init { + this.tempXOffset = cfg.config.guiSettings.scaledRes.scaledX + this.tempYOffset = cfg.config.guiSettings.scaledRes.scaledY + } + + override fun init() { + super.init() + this.addDrawableChild(ButtonWidget( + this.width / 2 + 10, this.height - 27, 90, 20, Text.translatable("gimbal.gui.resethud") + ) { _: ButtonWidget? -> + tempXOffset = 4.0 + tempYOffset = 4.0 + shouldFollow = false + }) + + this.addDrawableChild(ButtonWidget( + this.width / 2 - 100, this.height - 27, 90, 20, ScreenTexts.DONE + ) { _: ButtonWidget? -> + this.save() + this.client!!.setScreen( + this.parent + ) + }) + } + + private fun save() { + val oldConf = cfg.config + if (ScreenUtil.isPositionOutOfBounds(this.tempXOffset, this.tempYOffset)) { + LOGGER.info("Text is not in bounds. This will not be saved in order to keep the user from making the hud inaccessible.") + return + } + LOGGER.info("Saving Pos...") + + val newConf = GimbalClientConfig( + showToasts = oldConf.showToasts, + guiSettings = GimbalGuiSettings( + showHud = oldConf.guiSettings.showHud, + scaledRes = ScaledRes( + scaledX = this.tempXOffset, + scaledY = this.tempYOffset, + ) + ) + ) + + cfg.updateConfig(newConf) + } + + override fun close() { + this.save() + this.client!!.setScreen(this.parent) + } + + override fun tick() { + super.tick() + if (this.shouldFollow) { + val mouse = this.client?.mouse!! + val scaleFactor = this.client!!.window.calculateScaleFactor( + this.client!!.options.guiScale.value, + this.client!!.forcesUnicodeFont() + ) + this.tempXOffset = ScreenUtil.getScaled(this.width, mouse.x.toFloat() / scaleFactor) + this.tempYOffset = ScreenUtil.getScaled(this.height, mouse.y.toFloat() / scaleFactor) + } + } + + override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean { + this.shouldFollow = true + return super.mouseClicked(mouseX, mouseY, button) + } + + override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean { + this.shouldFollow = false + return super.mouseReleased(mouseX, mouseY, button) + } + + override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { + this.renderBackground(matrices) + drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 15, 16777215) + this.textRenderer.drawWithShadow( + matrices, + Text.translatable("gimbal.gui.examplehud"), + ScreenUtil.getXForRender( + ScreenUtil.getReal(this.width, this.tempXOffset), + AnchorPoint.CENTER, + this.textRenderer.getWidth(Text.translatable("gimbal.gui.examplehud")) + ), + ScreenUtil.getYForRender( + ScreenUtil.getReal(this.height, this.tempYOffset), + AnchorPoint.CENTER, + this.textRenderer.fontHeight + ), + 0xFFFFFF + ) // TODO: improve placement when changing the scaling +// LOGGER.info("width: ${this.width}, height: ${this.height}, posX: ${ScreenUtil.getReal(this.width, this.tempXOffset)}, posY: ${ScreenUtil.getReal(this.height, this.tempYOffset)}, scaleX: ${this.tempXOffset}, scaleY: ${this.tempYOffset}") + super.render(matrices, mouseX, mouseY, delta) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt new file mode 100644 index 0000000..99cedbb --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -0,0 +1,84 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.screen + +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.gui.widget.CyclingButtonWidget +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.screen.ScreenTexts +import net.minecraft.text.Text +import net.moonleay.gimbal.client.config.ClientConfigHolder +import net.moonleay.gimbal.client.config.GimbalClientConfig +import net.moonleay.gimbal.client.config.GimbalGuiSettings + +class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfigHolder) : + Screen(Text.translatable("gimbal.gui.settings")) { + override fun init() { + this.addDrawableChild(CyclingButtonWidget.onOffBuilder( +// Text.translatable("gimbal.gui.enabled"), +// Text.translatable("gimbal.gui.disabled") + ) + .initially(cfg.config.guiSettings.showHud) + .build( + this.width / 2 - 155, + this.height / 6 + 24 * 0, + 150, + 20, + Text.translatable("gimbal.gui.hud") + ) { _: CyclingButtonWidget?, isEnabled: Boolean? -> + val oldGui = cfg.config.guiSettings + val newGui = GimbalGuiSettings( + showHud = isEnabled ?: true, + scaledRes = oldGui.scaledRes, + anchorPoint = oldGui.anchorPoint + ) + val newConf = GimbalClientConfig( + guiSettings = newGui, + showToasts = cfg.config.showToasts + ) + cfg.updateConfig(newConf) + }) + this.addDrawableChild(ButtonWidget( + this.width / 2 - 155 + 160, + this.height / 6 + 24 * 0, + 150, + 20, + Text.translatable("gimbal.gui.edithud") + ) { _: ButtonWidget? -> + this.client!!.setScreen(GimbalEditHudGui(this, cfg)) + } + ) + + // Done button + this.addDrawableChild(ButtonWidget( + this.width / 2 - 100, this.height / 6 + 168, 200, 20, ScreenTexts.DONE + ) { _: ButtonWidget? -> + this.client!!.setScreen( + this.parent + ) + }) + } + + override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { + this.renderBackground(matrices) + drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 15, 16777215) + super.render(matrices, mouseX, mouseY, delta) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt new file mode 100644 index 0000000..c9166cb --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt @@ -0,0 +1,61 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.util.screen + +import net.moonleay.gimbal.client.config.AnchorPoint + +object ScreenUtil { + + fun getXForRender(x: Float, anchor: AnchorPoint, textWidth: Int): Float { + return when (anchor) { + AnchorPoint.TOP_LEFT -> x + AnchorPoint.BOTTOM_LEFT -> x + AnchorPoint.TOP_RIGHT -> x - textWidth + AnchorPoint.BOTTOM_RIGHT -> x - textWidth + AnchorPoint.CENTER -> x - textWidth / 2 + } + } + + fun getYForRender(y: Float, anchor: AnchorPoint, textHeight: Int): Float { + return when (anchor) { + AnchorPoint.TOP_LEFT -> y + AnchorPoint.TOP_RIGHT -> y + AnchorPoint.BOTTOM_RIGHT -> y - textHeight + AnchorPoint.BOTTOM_LEFT -> y - textHeight + AnchorPoint.CENTER -> y - textHeight / 2 + } + } + + fun getScaled(length: Int, real: Float): Double { + val scale = length / 100.0 + return real / scale + } + + fun getReal(length: Int, scaled: Double): Float { + val scale = length / 100.0 + return (scaled * scale).toFloat() + } + + fun isPositionOutOfBounds(x: Double, y: Double): Boolean { + val tooBig = 100 < x || 100 < y + val tooSmall = 0 > x || 0 > y + return tooBig || tooSmall + } + +} diff --git a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt b/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt index 34d0fce..0082df9 100644 --- a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt +++ b/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt @@ -26,13 +26,25 @@ class En_us_GimbalLanguageProvider(dataGenerator: FabricDataGenerator?) : override fun generateTranslations(translationBuilder: TranslationBuilder?) { if (translationBuilder == null) return + /// Screens + // Gimbal settings screen + translationBuilder.add("gimbal.gui.settings", "Gimbal Settings") + translationBuilder.add("gimbal.gui.hud", "Show HUD") + translationBuilder.add("gimbal.gui.edithud", "Edit HUD Layout...") + translationBuilder.add("gimbal.gui.resethud", "Reset Layout") + translationBuilder.add("gimbal.gui.examplehud", "EXAMPLE [No Clip, Force]") + + + translationBuilder.add("gimbal.gui.enabled", "Enabled") + translationBuilder.add("gimbal.gui.disabled", "Disabled") + + /// Options // Editor modes translationBuilder.add("gimbal.category.editormode", "Editor Modes") translationBuilder.add("gimbal.key.editor.mode.insert", "Enter Insert Mode") translationBuilder.add("gimbal.key.editor.mode.replace", "Enter Replace Mode") translationBuilder.add("gimbal.key.editor.mode.visual", "Enter Visual Mode") - // Editor mode modifiers translationBuilder.add("gimbal.category.editormodifier", "Editor Mode Modifiers") translationBuilder.add("gimbal.key.editor.modifier.bulldozer", "Toggle Bulldozer Modifier") diff --git a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java new file mode 100644 index 0000000..861ecd3 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java @@ -0,0 +1,66 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.mixin; + +import net.minecraft.client.gui.screen.GameMenuScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.TexturedButtonWidget; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.moonleay.gimbal.build.BuildConstants; +import net.moonleay.gimbal.client.ClientMain; +import net.moonleay.gimbal.client.screen.GimbalSettingsGui; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GameMenuScreen.class) +// What is my purpose? +public class YouInjectButtonMixin extends Screen { + // Go my god. + + @Unique + private static final Identifier GIMBAL_TEXTURE = new Identifier(BuildConstants.modId, "textures/gimbal_options_texture_button.png"); + + protected YouInjectButtonMixin(Text title) { + super(title); + } + + @Inject(method = "initWidgets", at = @At(value = "RETURN")) + private void func(CallbackInfo ci) { + this.addDrawableChild( + new TexturedButtonWidget( + this.width / 2 - 124, + this.height / 4 + 96 + -16, + 20, + 20, + 0, + 0, + 20, + GIMBAL_TEXTURE, + 20, + 40, + button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), + Text.translatable("gimbal.gui.settings") + ) + ); + } +} diff --git a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java new file mode 100644 index 0000000..70af1f4 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java @@ -0,0 +1,65 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.mixin; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.gui.widget.TexturedButtonWidget; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.moonleay.gimbal.build.BuildConstants; +import net.moonleay.gimbal.client.ClientMain; +import net.moonleay.gimbal.client.screen.GimbalSettingsGui; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public class YouInjectButtonMixin2 extends Screen { + + @Unique + private static final Identifier GIMBAL_TEXTURE = new Identifier(BuildConstants.modId, "textures/gimbal_options_texture_button.png"); + + protected YouInjectButtonMixin2(Text title) { + super(title); + } + + @Inject(method = "init", at = @At(value = "RETURN")) + private void func(CallbackInfo ci) { + int l = this.height / 4 + 48; + this.addDrawableChild( + new TexturedButtonWidget( + this.width / 2 - 124 - 24, + l + 72 + 12, + 20, + 20, + 0, + 0, + 20, + GIMBAL_TEXTURE, + 20, + 40, + button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), + Text.translatable("gimbal.gui.settings") + ) + ); + } +} diff --git a/src/main/resources/assets/gimbal/textures/gimbal_options_texture_button.png b/src/main/resources/assets/gimbal/textures/gimbal_options_texture_button.png new file mode 100644 index 0000000000000000000000000000000000000000..e11bf08f97c6518a69b22dfe74fc0cfd0f052465 GIT binary patch literal 1228 zcmV;-1T*`IP)Px(hDk(0R7i=nm0fHURTRg6b7y9|3-kjDY$Gj{no2AokdP2H6;UBRfyOk5K;XlmM8f34rH$2q7kQ)Y{rgO-)V8p}#Sa zDW&i{57RU;3+4HL=pU3)Vp)2Ny%(GG`mu#)^?GyBF#sIL z(HZzp%TLEJ3~bxRbzOuIyn5*zhaY*46FoZsh;%;-z_BM@;8^D_wm$GNmSvGlCXrI2 zluA3y)W)`L9LM3%stwfl>|p)cJpdeF0gf}uJ10(&Sd~CZh2uB~A+T*5+qMA^0Iutz zl+t=7R$QgNcNfpBei?u}cZLB71Z)oMT)^IoO$;w zU%Q9Ayj%csb7$!cg25o~Zk^8?$A9C_%I{H1Wo4*Wep$3dPx5Hlc1mX#)89WpFc{2= za%99|WMqUxt2XfF2Y-yK3ISjkhAs<$(JNuTdb@>quVSVfAQ%iXZ{A!Mhr{H~4Pu=h zNv9|Tj+44XJM{Id@7=}f=tgD?bpkMWuAjEH>%@-SLWDee68*&9kEUdZwR3*u!|c7- zglU@O+eg@newivvsQlXRHnV>_3#Dn$1( zz^3^hQs0~Eju*=%vfjh_HNwD9oQD?7p(I>DhgnXCnI0TRE31%W{SROOYTv$nM5C#4 z@H`LKbqNFlK&pET!@#mEeeq=0(9n?jDURdl%|IYPUS3|h41~}sA1oTE1RG6_=>(uAY=ByIUIhbIEs;GsV|IO36>^%PBKuU|I9@ zG397w)$}q&57aTHB$LUsLtnqz?&|wy%I=m%Ow-hv=#)pFzXAL=rpT(U>1Rqj9?y0d zJX@|K%e1L5#r~p9r~LmjC2;ydgb>{R@%%lR(ivJhwle`!{F(St@h8-FZv$Z4Qi<2- zG5qs|ET(jZmeLtY502WWHfJ+MDW&%B->;b>rNnhz%~{uV_2Bq7rqtEdjb} Date: Sun, 5 May 2024 20:03:29 +0200 Subject: [PATCH 09/24] feat: finished HUD pos conf system Signed-off-by: moonleay --- .../gimbal/client/config/GimbalGuiSettings.kt | 5 +- .../{AnchorPoint.kt => HorizontalAnchor.kt} | 10 ++-- .../gimbal/client/config/VerticalAnchor.kt | 28 ++++++++++ .../gimbal/client/screen/GimbalEditHudGui.kt | 53 ++++++++++++------- .../gimbal/client/screen/GimbalSettingsGui.kt | 5 +- .../gimbal/client/util/screen/ScreenUtil.kt | 38 ++++++++----- .../net/moonleay/gimbal/mixin/HudMixin.java | 44 +++++++++++++-- 7 files changed, 136 insertions(+), 47 deletions(-) rename src/main/java/net/moonleay/gimbal/client/config/{AnchorPoint.kt => HorizontalAnchor.kt} (88%) create mode 100644 src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt index 2a274b0..7c24608 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt @@ -23,6 +23,7 @@ import kotlinx.serialization.Serializable @Serializable data class GimbalGuiSettings( val showHud: Boolean = true, - val scaledRes: ScaledRes = ScaledRes(4.0, 4.0), - val anchorPoint: AnchorPoint = AnchorPoint.TOP_LEFT, + val offset: ScaledRes = ScaledRes(4.0, 4.0), + val horizontalAnchor: HorizontalAnchor = HorizontalAnchor.LEFT, + val verticalAnchor: VerticalAnchor = VerticalAnchor.TOP, ) diff --git a/src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt b/src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt similarity index 88% rename from src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt rename to src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt index 29f34a2..fa4dc4f 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt @@ -21,10 +21,8 @@ package net.moonleay.gimbal.client.config import kotlinx.serialization.Serializable @Serializable -enum class AnchorPoint { - TOP_LEFT, - TOP_RIGHT, - BOTTOM_RIGHT, - BOTTOM_LEFT, - CENTER +enum class HorizontalAnchor { + LEFT, + CENTER, + RIGHT, } diff --git a/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt b/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt new file mode 100644 index 0000000..7fd660a --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt @@ -0,0 +1,28 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +import kotlinx.serialization.Serializable + +@Serializable +enum class VerticalAnchor { + TOP, + CENTER, + BOTTOM, +} diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt index 0b7fd61..6af484e 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -24,7 +24,10 @@ import net.minecraft.client.util.math.MatrixStack import net.minecraft.screen.ScreenTexts import net.minecraft.text.Text import net.moonleay.gimbal.build.BuildConstants -import net.moonleay.gimbal.client.config.* +import net.moonleay.gimbal.client.config.ClientConfigHolder +import net.moonleay.gimbal.client.config.GimbalClientConfig +import net.moonleay.gimbal.client.config.GimbalGuiSettings +import net.moonleay.gimbal.client.config.ScaledRes import net.moonleay.gimbal.client.util.screen.ScreenUtil import org.apache.logging.log4j.LogManager @@ -37,8 +40,8 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig private var shouldFollow = false init { - this.tempXOffset = cfg.config.guiSettings.scaledRes.scaledX - this.tempYOffset = cfg.config.guiSettings.scaledRes.scaledY + this.tempXOffset = cfg.config.guiSettings.offset.scaledX + this.tempYOffset = cfg.config.guiSettings.offset.scaledY } override fun init() { @@ -69,14 +72,18 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig } LOGGER.info("Saving Pos...") + val anchor = ScreenUtil.getAnchor(this.tempXOffset, this.tempYOffset) + val newConf = GimbalClientConfig( showToasts = oldConf.showToasts, guiSettings = GimbalGuiSettings( showHud = oldConf.guiSettings.showHud, - scaledRes = ScaledRes( + offset = ScaledRes( scaledX = this.tempXOffset, scaledY = this.tempYOffset, - ) + ), + horizontalAnchor = anchor.first, + verticalAnchor = anchor.second ) ) @@ -92,12 +99,14 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig super.tick() if (this.shouldFollow) { val mouse = this.client?.mouse!! - val scaleFactor = this.client!!.window.calculateScaleFactor( - this.client!!.options.guiScale.value, - this.client!!.forcesUnicodeFont() - ) - this.tempXOffset = ScreenUtil.getScaled(this.width, mouse.x.toFloat() / scaleFactor) - this.tempYOffset = ScreenUtil.getScaled(this.height, mouse.y.toFloat() / scaleFactor) + val wantedX = ScreenUtil.getScaled(this.client!!.window.width, mouse.x.toFloat()) + val wantedY = ScreenUtil.getScaled(this.client!!.window.height, mouse.y.toFloat()) + if (!ScreenUtil.isPositionOutOfBounds(wantedX, wantedY)) { + this.tempXOffset = wantedX + this.tempYOffset = wantedY + } else { + LOGGER.info("Text is oob. wantedX: ${wantedX}, wantedY: ${wantedY}, width: ${this.client!!.window.width}, height: ${this.client!!.window.height}") + } } } @@ -114,22 +123,30 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { this.renderBackground(matrices) drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 15, 16777215) + val scaleFactor = this.client!!.window.calculateScaleFactor( + this.client!!.options.guiScale.value, + this.client!!.forcesUnicodeFont() + ) + val anchor = ScreenUtil.getAnchor(this.tempXOffset, this.tempYOffset) this.textRenderer.drawWithShadow( matrices, Text.translatable("gimbal.gui.examplehud"), - ScreenUtil.getXForRender( - ScreenUtil.getReal(this.width, this.tempXOffset), - AnchorPoint.CENTER, + ScreenUtil.getXForAnchor( + ScreenUtil.getReal(this.client!!.window.width, this.tempXOffset) / scaleFactor, + anchor.first, this.textRenderer.getWidth(Text.translatable("gimbal.gui.examplehud")) ), - ScreenUtil.getYForRender( - ScreenUtil.getReal(this.height, this.tempYOffset), - AnchorPoint.CENTER, + ScreenUtil.getYForAnchor( + ScreenUtil.getReal(this.client!!.window.height, this.tempYOffset) / scaleFactor, + anchor.second, this.textRenderer.fontHeight ), 0xFFFFFF ) // TODO: improve placement when changing the scaling -// LOGGER.info("width: ${this.width}, height: ${this.height}, posX: ${ScreenUtil.getReal(this.width, this.tempXOffset)}, posY: ${ScreenUtil.getReal(this.height, this.tempYOffset)}, scaleX: ${this.tempXOffset}, scaleY: ${this.tempYOffset}") +// LOGGER.info("width: ${this.width}, height: ${this.height}," + +// " posX: ${ScreenUtil.getReal(this.width, this.tempXOffset)}," + +// " posY: ${ScreenUtil.getReal(this.height, this.tempYOffset)}," + +// " scaleX: ${this.tempXOffset}, scaleY: ${this.tempYOffset}") super.render(matrices, mouseX, mouseY, delta) } } diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt index 99cedbb..0885102 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -46,8 +46,9 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi val oldGui = cfg.config.guiSettings val newGui = GimbalGuiSettings( showHud = isEnabled ?: true, - scaledRes = oldGui.scaledRes, - anchorPoint = oldGui.anchorPoint + offset = oldGui.offset, + horizontalAnchor = oldGui.horizontalAnchor, + verticalAnchor = oldGui.verticalAnchor, ) val newConf = GimbalClientConfig( guiSettings = newGui, diff --git a/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt index c9166cb..9c0c130 100644 --- a/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt +++ b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt @@ -18,27 +18,37 @@ package net.moonleay.gimbal.client.util.screen -import net.moonleay.gimbal.client.config.AnchorPoint +import net.moonleay.gimbal.client.config.HorizontalAnchor +import net.moonleay.gimbal.client.config.VerticalAnchor object ScreenUtil { - fun getXForRender(x: Float, anchor: AnchorPoint, textWidth: Int): Float { - return when (anchor) { - AnchorPoint.TOP_LEFT -> x - AnchorPoint.BOTTOM_LEFT -> x - AnchorPoint.TOP_RIGHT -> x - textWidth - AnchorPoint.BOTTOM_RIGHT -> x - textWidth - AnchorPoint.CENTER -> x - textWidth / 2 + fun getAnchor(x: Double, y: Double): Pair { + return when (x) { + in 0.0..<34.0 -> HorizontalAnchor.LEFT + in 34.0..<67.0 -> HorizontalAnchor.CENTER + else -> HorizontalAnchor.RIGHT + } to when (y) { + in 0.0..<34.0 -> VerticalAnchor.TOP + in 34.0..<67.0 -> VerticalAnchor.CENTER + else -> VerticalAnchor.BOTTOM } } - fun getYForRender(y: Float, anchor: AnchorPoint, textHeight: Int): Float { + fun getXForAnchor(x: Float, anchor: HorizontalAnchor, textWidth: Int): Float { return when (anchor) { - AnchorPoint.TOP_LEFT -> y - AnchorPoint.TOP_RIGHT -> y - AnchorPoint.BOTTOM_RIGHT -> y - textHeight - AnchorPoint.BOTTOM_LEFT -> y - textHeight - AnchorPoint.CENTER -> y - textHeight / 2 + HorizontalAnchor.LEFT -> x + HorizontalAnchor.CENTER -> x - (textWidth / 2) + HorizontalAnchor.RIGHT -> x - textWidth + } + } + + + fun getYForAnchor(y: Float, anchor: VerticalAnchor, textHeight: Int): Float { + return when (anchor) { + VerticalAnchor.TOP -> y + VerticalAnchor.CENTER -> y - (textHeight / 2) + VerticalAnchor.BOTTOM -> y - textHeight } } diff --git a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java index fab79b6..f9a3d89 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java @@ -22,7 +22,11 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.moonleay.gimbal.client.ClientMain; +import net.moonleay.gimbal.client.config.GimbalGuiSettings; import net.moonleay.gimbal.client.editor.ClientEditor; +import net.moonleay.gimbal.client.util.screen.ScreenUtil; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -31,16 +35,46 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(InGameHud.class) -public class HudMixin { +public abstract class HudMixin { @Shadow @Final private MinecraftClient client; + @Shadow + private int scaledHeight; + + @Shadow + public abstract void clear(); + @Inject(method = "renderStatusEffectOverlay", at = @At("HEAD")) private void render(MatrixStack matrices, CallbackInfo ci) { TextRenderer tr = this.client.textRenderer; - tr.drawWithShadow(matrices, - ClientEditor.INSTANCE.getModeDisplayText(), - 4, 4, - ClientEditor.INSTANCE.getCurrentColor()); + GimbalGuiSettings conf = ClientMain.CONFIG.getConfig().getGuiSettings(); + if (!conf.getShowHud()) + return; + int scaleFactor = this.client.getWindow() + .calculateScaleFactor( + this.client.options.getGuiScale().getValue(), + this.client.forcesUnicodeFont() + ); + Text displayText = ClientEditor.INSTANCE.getModeDisplayText(); + tr.drawWithShadow( + matrices, + displayText, + ScreenUtil.INSTANCE.getXForAnchor( + ScreenUtil.INSTANCE.getReal( + this.client.getWindow().getWidth(), + conf.getOffset().getScaledX() / scaleFactor), + conf.getHorizontalAnchor(), + this.client.textRenderer.getWidth(displayText) + ), + ScreenUtil.INSTANCE.getYForAnchor( + ScreenUtil.INSTANCE.getReal( + this.client.getWindow().getHeight(), + conf.getOffset().getScaledY() / scaleFactor), + conf.getVerticalAnchor(), + this.client.textRenderer.fontHeight + ), + ClientEditor.INSTANCE.getCurrentColor() + ); } } From d26f96ee0442073a5875bae6039623636ed8d9a1 Mon Sep 17 00:00:00 2001 From: moonleay Date: Sun, 5 May 2024 20:03:29 +0200 Subject: [PATCH 10/24] feat: finished HUD pos conf system Signed-off-by: moonleay --- .../gimbal/client/config/GimbalGuiSettings.kt | 5 +- .../{AnchorPoint.kt => HorizontalAnchor.kt} | 10 ++-- .../gimbal/client/config/VerticalAnchor.kt | 28 ++++++++++ .../gimbal/client/screen/GimbalEditHudGui.kt | 53 ++++++++++++------- .../gimbal/client/screen/GimbalSettingsGui.kt | 5 +- .../gimbal/client/util/screen/ScreenUtil.kt | 38 ++++++++----- .../net/moonleay/gimbal/mixin/HudMixin.java | 38 +++++++++++-- 7 files changed, 130 insertions(+), 47 deletions(-) rename src/main/java/net/moonleay/gimbal/client/config/{AnchorPoint.kt => HorizontalAnchor.kt} (88%) create mode 100644 src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt index 2a274b0..7c24608 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt @@ -23,6 +23,7 @@ import kotlinx.serialization.Serializable @Serializable data class GimbalGuiSettings( val showHud: Boolean = true, - val scaledRes: ScaledRes = ScaledRes(4.0, 4.0), - val anchorPoint: AnchorPoint = AnchorPoint.TOP_LEFT, + val offset: ScaledRes = ScaledRes(4.0, 4.0), + val horizontalAnchor: HorizontalAnchor = HorizontalAnchor.LEFT, + val verticalAnchor: VerticalAnchor = VerticalAnchor.TOP, ) diff --git a/src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt b/src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt similarity index 88% rename from src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt rename to src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt index 29f34a2..fa4dc4f 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/AnchorPoint.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt @@ -21,10 +21,8 @@ package net.moonleay.gimbal.client.config import kotlinx.serialization.Serializable @Serializable -enum class AnchorPoint { - TOP_LEFT, - TOP_RIGHT, - BOTTOM_RIGHT, - BOTTOM_LEFT, - CENTER +enum class HorizontalAnchor { + LEFT, + CENTER, + RIGHT, } diff --git a/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt b/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt new file mode 100644 index 0000000..7fd660a --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt @@ -0,0 +1,28 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config + +import kotlinx.serialization.Serializable + +@Serializable +enum class VerticalAnchor { + TOP, + CENTER, + BOTTOM, +} diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt index 0b7fd61..6af484e 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -24,7 +24,10 @@ import net.minecraft.client.util.math.MatrixStack import net.minecraft.screen.ScreenTexts import net.minecraft.text.Text import net.moonleay.gimbal.build.BuildConstants -import net.moonleay.gimbal.client.config.* +import net.moonleay.gimbal.client.config.ClientConfigHolder +import net.moonleay.gimbal.client.config.GimbalClientConfig +import net.moonleay.gimbal.client.config.GimbalGuiSettings +import net.moonleay.gimbal.client.config.ScaledRes import net.moonleay.gimbal.client.util.screen.ScreenUtil import org.apache.logging.log4j.LogManager @@ -37,8 +40,8 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig private var shouldFollow = false init { - this.tempXOffset = cfg.config.guiSettings.scaledRes.scaledX - this.tempYOffset = cfg.config.guiSettings.scaledRes.scaledY + this.tempXOffset = cfg.config.guiSettings.offset.scaledX + this.tempYOffset = cfg.config.guiSettings.offset.scaledY } override fun init() { @@ -69,14 +72,18 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig } LOGGER.info("Saving Pos...") + val anchor = ScreenUtil.getAnchor(this.tempXOffset, this.tempYOffset) + val newConf = GimbalClientConfig( showToasts = oldConf.showToasts, guiSettings = GimbalGuiSettings( showHud = oldConf.guiSettings.showHud, - scaledRes = ScaledRes( + offset = ScaledRes( scaledX = this.tempXOffset, scaledY = this.tempYOffset, - ) + ), + horizontalAnchor = anchor.first, + verticalAnchor = anchor.second ) ) @@ -92,12 +99,14 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig super.tick() if (this.shouldFollow) { val mouse = this.client?.mouse!! - val scaleFactor = this.client!!.window.calculateScaleFactor( - this.client!!.options.guiScale.value, - this.client!!.forcesUnicodeFont() - ) - this.tempXOffset = ScreenUtil.getScaled(this.width, mouse.x.toFloat() / scaleFactor) - this.tempYOffset = ScreenUtil.getScaled(this.height, mouse.y.toFloat() / scaleFactor) + val wantedX = ScreenUtil.getScaled(this.client!!.window.width, mouse.x.toFloat()) + val wantedY = ScreenUtil.getScaled(this.client!!.window.height, mouse.y.toFloat()) + if (!ScreenUtil.isPositionOutOfBounds(wantedX, wantedY)) { + this.tempXOffset = wantedX + this.tempYOffset = wantedY + } else { + LOGGER.info("Text is oob. wantedX: ${wantedX}, wantedY: ${wantedY}, width: ${this.client!!.window.width}, height: ${this.client!!.window.height}") + } } } @@ -114,22 +123,30 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) { this.renderBackground(matrices) drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 15, 16777215) + val scaleFactor = this.client!!.window.calculateScaleFactor( + this.client!!.options.guiScale.value, + this.client!!.forcesUnicodeFont() + ) + val anchor = ScreenUtil.getAnchor(this.tempXOffset, this.tempYOffset) this.textRenderer.drawWithShadow( matrices, Text.translatable("gimbal.gui.examplehud"), - ScreenUtil.getXForRender( - ScreenUtil.getReal(this.width, this.tempXOffset), - AnchorPoint.CENTER, + ScreenUtil.getXForAnchor( + ScreenUtil.getReal(this.client!!.window.width, this.tempXOffset) / scaleFactor, + anchor.first, this.textRenderer.getWidth(Text.translatable("gimbal.gui.examplehud")) ), - ScreenUtil.getYForRender( - ScreenUtil.getReal(this.height, this.tempYOffset), - AnchorPoint.CENTER, + ScreenUtil.getYForAnchor( + ScreenUtil.getReal(this.client!!.window.height, this.tempYOffset) / scaleFactor, + anchor.second, this.textRenderer.fontHeight ), 0xFFFFFF ) // TODO: improve placement when changing the scaling -// LOGGER.info("width: ${this.width}, height: ${this.height}, posX: ${ScreenUtil.getReal(this.width, this.tempXOffset)}, posY: ${ScreenUtil.getReal(this.height, this.tempYOffset)}, scaleX: ${this.tempXOffset}, scaleY: ${this.tempYOffset}") +// LOGGER.info("width: ${this.width}, height: ${this.height}," + +// " posX: ${ScreenUtil.getReal(this.width, this.tempXOffset)}," + +// " posY: ${ScreenUtil.getReal(this.height, this.tempYOffset)}," + +// " scaleX: ${this.tempXOffset}, scaleY: ${this.tempYOffset}") super.render(matrices, mouseX, mouseY, delta) } } diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt index 99cedbb..0885102 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -46,8 +46,9 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi val oldGui = cfg.config.guiSettings val newGui = GimbalGuiSettings( showHud = isEnabled ?: true, - scaledRes = oldGui.scaledRes, - anchorPoint = oldGui.anchorPoint + offset = oldGui.offset, + horizontalAnchor = oldGui.horizontalAnchor, + verticalAnchor = oldGui.verticalAnchor, ) val newConf = GimbalClientConfig( guiSettings = newGui, diff --git a/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt index c9166cb..9c0c130 100644 --- a/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt +++ b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt @@ -18,27 +18,37 @@ package net.moonleay.gimbal.client.util.screen -import net.moonleay.gimbal.client.config.AnchorPoint +import net.moonleay.gimbal.client.config.HorizontalAnchor +import net.moonleay.gimbal.client.config.VerticalAnchor object ScreenUtil { - fun getXForRender(x: Float, anchor: AnchorPoint, textWidth: Int): Float { - return when (anchor) { - AnchorPoint.TOP_LEFT -> x - AnchorPoint.BOTTOM_LEFT -> x - AnchorPoint.TOP_RIGHT -> x - textWidth - AnchorPoint.BOTTOM_RIGHT -> x - textWidth - AnchorPoint.CENTER -> x - textWidth / 2 + fun getAnchor(x: Double, y: Double): Pair { + return when (x) { + in 0.0..<34.0 -> HorizontalAnchor.LEFT + in 34.0..<67.0 -> HorizontalAnchor.CENTER + else -> HorizontalAnchor.RIGHT + } to when (y) { + in 0.0..<34.0 -> VerticalAnchor.TOP + in 34.0..<67.0 -> VerticalAnchor.CENTER + else -> VerticalAnchor.BOTTOM } } - fun getYForRender(y: Float, anchor: AnchorPoint, textHeight: Int): Float { + fun getXForAnchor(x: Float, anchor: HorizontalAnchor, textWidth: Int): Float { return when (anchor) { - AnchorPoint.TOP_LEFT -> y - AnchorPoint.TOP_RIGHT -> y - AnchorPoint.BOTTOM_RIGHT -> y - textHeight - AnchorPoint.BOTTOM_LEFT -> y - textHeight - AnchorPoint.CENTER -> y - textHeight / 2 + HorizontalAnchor.LEFT -> x + HorizontalAnchor.CENTER -> x - (textWidth / 2) + HorizontalAnchor.RIGHT -> x - textWidth + } + } + + + fun getYForAnchor(y: Float, anchor: VerticalAnchor, textHeight: Int): Float { + return when (anchor) { + VerticalAnchor.TOP -> y + VerticalAnchor.CENTER -> y - (textHeight / 2) + VerticalAnchor.BOTTOM -> y - textHeight } } diff --git a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java index fab79b6..607c7f2 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java @@ -22,7 +22,11 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.moonleay.gimbal.client.ClientMain; +import net.moonleay.gimbal.client.config.GimbalGuiSettings; import net.moonleay.gimbal.client.editor.ClientEditor; +import net.moonleay.gimbal.client.util.screen.ScreenUtil; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -31,16 +35,40 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(InGameHud.class) -public class HudMixin { +public abstract class HudMixin { @Shadow @Final private MinecraftClient client; @Inject(method = "renderStatusEffectOverlay", at = @At("HEAD")) private void render(MatrixStack matrices, CallbackInfo ci) { TextRenderer tr = this.client.textRenderer; - tr.drawWithShadow(matrices, - ClientEditor.INSTANCE.getModeDisplayText(), - 4, 4, - ClientEditor.INSTANCE.getCurrentColor()); + GimbalGuiSettings conf = ClientMain.CONFIG.getConfig().getGuiSettings(); + if (!conf.getShowHud()) + return; + int scaleFactor = this.client.getWindow() + .calculateScaleFactor( + this.client.options.getGuiScale().getValue(), + this.client.forcesUnicodeFont() + ); + Text displayText = ClientEditor.INSTANCE.getModeDisplayText(); + tr.drawWithShadow( + matrices, + displayText, + ScreenUtil.INSTANCE.getXForAnchor( + ScreenUtil.INSTANCE.getReal( + this.client.getWindow().getWidth(), + conf.getOffset().getScaledX() / scaleFactor), + conf.getHorizontalAnchor(), + this.client.textRenderer.getWidth(displayText) + ), + ScreenUtil.INSTANCE.getYForAnchor( + ScreenUtil.INSTANCE.getReal( + this.client.getWindow().getHeight(), + conf.getOffset().getScaledY() / scaleFactor), + conf.getVerticalAnchor(), + this.client.textRenderer.fontHeight + ), + ClientEditor.INSTANCE.getCurrentColor() + ); } } From e7355f97810738d9f323f3ca7bb4e8f769d4f9f0 Mon Sep 17 00:00:00 2001 From: moonleay Date: Sun, 5 May 2024 20:04:44 +0200 Subject: [PATCH 11/24] chore: removed unused vars Signed-off-by: moonleay --- src/main/java/net/moonleay/gimbal/mixin/HudMixin.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java index f9a3d89..607c7f2 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java @@ -39,12 +39,6 @@ public abstract class HudMixin { @Shadow @Final private MinecraftClient client; - @Shadow - private int scaledHeight; - - @Shadow - public abstract void clear(); - @Inject(method = "renderStatusEffectOverlay", at = @At("HEAD")) private void render(MatrixStack matrices, CallbackInfo ci) { TextRenderer tr = this.client.textRenderer; From 6002af93a5228ceebfbcfe586a0fb6758ed03e4d Mon Sep 17 00:00:00 2001 From: moonleay Date: Mon, 6 May 2024 02:52:28 +0200 Subject: [PATCH 12/24] feat: added settings and a config system refactor: Reworked translation key system Signed-off-by: moonleay --- .../client/config/ClientConfigHolder.kt | 1 + .../client/config/GimbalClientConfig.kt | 3 +- .../gimbal/client/config/GimbalGuiSettings.kt | 4 + .../client/config/{ => enums}/Centerpoint.kt | 2 +- .../config/{ => enums}/HorizontalAnchor.kt | 2 +- .../gimbal/client/config/enums/HudOptions.kt | 31 +++++ .../client/config/enums/ToastSettings.kt | 32 +++++ .../config/{ => enums}/VerticalAnchor.kt | 2 +- .../gimbal/client/editor/ClientEditor.kt | 104 ++++++++++++--- .../client/keybindings/KeybindingRegistrar.kt | 37 +++--- .../gimbal/client/screen/GimbalEditHudGui.kt | 24 ++-- .../gimbal/client/screen/GimbalSettingsGui.kt | 118 ++++++++++++++++- .../moonleay/gimbal/client/util/ChatUtil.kt | 12 +- .../moonleay/gimbal/client/util/ToastType.kt | 24 ++++ .../gimbal/client/util/screen/ScreenUtil.kt | 4 +- .../gimbal/constants/TranslationKeys.kt | 123 ++++++++++++++++++ .../datagen/En_us_GimbalLanguageProvider.kt | 69 +++++++--- .../gimbal/editor/state/mode/ModeModifier.kt | 10 +- .../net/moonleay/gimbal/mixin/HudMixin.java | 2 +- .../gimbal/mixin/YouInjectButtonMixin.java | 3 +- .../gimbal/mixin/YouInjectButtonMixin2.java | 3 +- 21 files changed, 517 insertions(+), 93 deletions(-) rename src/main/java/net/moonleay/gimbal/client/config/{ => enums}/Centerpoint.kt (94%) rename src/main/java/net/moonleay/gimbal/client/config/{ => enums}/HorizontalAnchor.kt (94%) create mode 100644 src/main/java/net/moonleay/gimbal/client/config/enums/HudOptions.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/config/enums/ToastSettings.kt rename src/main/java/net/moonleay/gimbal/client/config/{ => enums}/VerticalAnchor.kt (94%) create mode 100644 src/main/java/net/moonleay/gimbal/client/util/ToastType.kt create mode 100644 src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt diff --git a/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt index c385f49..b4d38ba 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt @@ -47,6 +47,7 @@ class ClientConfigHolder(private val path: Path) { } } + // TODO: Support incomplete config files @OptIn(ExperimentalSerializationApi::class) fun save(conf: GimbalClientConfig) { if (!path.isWritable()) { diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt index b0184d7..f673f28 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt @@ -19,9 +19,10 @@ package net.moonleay.gimbal.client.config import kotlinx.serialization.Serializable +import net.moonleay.gimbal.client.config.enums.ToastSettings @Serializable data class GimbalClientConfig( val guiSettings: GimbalGuiSettings = GimbalGuiSettings(), - val showToasts: Boolean = true, + val toastSettings: ToastSettings = ToastSettings.ALL, ) diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt index 7c24608..06755a1 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt @@ -19,6 +19,9 @@ package net.moonleay.gimbal.client.config import kotlinx.serialization.Serializable +import net.moonleay.gimbal.client.config.enums.HorizontalAnchor +import net.moonleay.gimbal.client.config.enums.HudOptions +import net.moonleay.gimbal.client.config.enums.VerticalAnchor @Serializable data class GimbalGuiSettings( @@ -26,4 +29,5 @@ data class GimbalGuiSettings( val offset: ScaledRes = ScaledRes(4.0, 4.0), val horizontalAnchor: HorizontalAnchor = HorizontalAnchor.LEFT, val verticalAnchor: VerticalAnchor = VerticalAnchor.TOP, + val hudOptions: HudOptions = HudOptions.ALL, ) diff --git a/src/main/java/net/moonleay/gimbal/client/config/Centerpoint.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/Centerpoint.kt similarity index 94% rename from src/main/java/net/moonleay/gimbal/client/config/Centerpoint.kt rename to src/main/java/net/moonleay/gimbal/client/config/enums/Centerpoint.kt index 2cb8029..a9cecc4 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/Centerpoint.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/Centerpoint.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package net.moonleay.gimbal.client.config +package net.moonleay.gimbal.client.config.enums enum class Centerpoint { TOP_LEFT, diff --git a/src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/HorizontalAnchor.kt similarity index 94% rename from src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt rename to src/main/java/net/moonleay/gimbal/client/config/enums/HorizontalAnchor.kt index fa4dc4f..439a56f 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/HorizontalAnchor.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/HorizontalAnchor.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package net.moonleay.gimbal.client.config +package net.moonleay.gimbal.client.config.enums import kotlinx.serialization.Serializable diff --git a/src/main/java/net/moonleay/gimbal/client/config/enums/HudOptions.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/HudOptions.kt new file mode 100644 index 0000000..e57f8c0 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/HudOptions.kt @@ -0,0 +1,31 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config.enums + +import kotlinx.serialization.Serializable +import net.minecraft.text.Text +import net.moonleay.gimbal.constants.TranslationKeys + +@Serializable +enum class HudOptions(val translatableText: Text) { + ALL(Text.translatable(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_ALL)), + NUMBER(Text.translatable(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_NUMBER)), + INITIAL(Text.translatable(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_INITIALS)), + ONLY_MODE(Text.translatable(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_MODE_ONLY)), +} diff --git a/src/main/java/net/moonleay/gimbal/client/config/enums/ToastSettings.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/ToastSettings.kt new file mode 100644 index 0000000..e581500 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/ToastSettings.kt @@ -0,0 +1,32 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.config.enums + +import kotlinx.serialization.Serializable +import net.minecraft.text.Text +import net.moonleay.gimbal.client.util.ToastType +import net.moonleay.gimbal.constants.TranslationKeys + +@Serializable +enum class ToastSettings(val translatableText: Text, val allowedTypes: List) { + ALL(Text.translatable(TranslationKeys.Gui.Config.Toasts.SHOW_ALL), listOf(ToastType.SYSTEM, ToastType.TOGGLE)), + ONLY_TOGGLE(Text.translatable(TranslationKeys.Gui.Config.Toasts.SHOW_TOGGLE), listOf(ToastType.TOGGLE)), + ONLY_SYSTEM(Text.translatable(TranslationKeys.Gui.Config.Toasts.SHOW_SYSTEM), listOf(ToastType.SYSTEM)), + NONE(Text.translatable(TranslationKeys.Gui.Config.Toasts.SHOW_NONE), listOf()) +} diff --git a/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/VerticalAnchor.kt similarity index 94% rename from src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt rename to src/main/java/net/moonleay/gimbal/client/config/enums/VerticalAnchor.kt index 7fd660a..d3ae146 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/VerticalAnchor.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/VerticalAnchor.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package net.moonleay.gimbal.client.config +package net.moonleay.gimbal.client.config.enums import kotlinx.serialization.Serializable diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index dde4c56..2982db4 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -21,7 +21,11 @@ package net.moonleay.gimbal.client.editor import net.minecraft.client.MinecraftClient import net.minecraft.text.Text import net.moonleay.gimbal.build.BuildConstants +import net.moonleay.gimbal.client.ClientMain +import net.moonleay.gimbal.client.config.GimbalClientConfig +import net.moonleay.gimbal.client.config.enums.HudOptions import net.moonleay.gimbal.client.util.ChatUtil +import net.moonleay.gimbal.client.util.ToastType import net.moonleay.gimbal.editor.ServerEditorManager import net.moonleay.gimbal.editor.state.EditorState import net.moonleay.gimbal.editor.state.GimbalPolicyType @@ -121,7 +125,13 @@ object ClientEditor { * */ fun setMode(mode: Mode) { if (!isAllowed()) { - ChatUtil.showToastToSelf("Gimbal is disabled", "You cannot change modes", MinecraftClient.getInstance()) + ChatUtil.showToastToSelf( + "Gimbal is disabled", + "You cannot change modes", + ToastType.SYSTEM, + ClientMain.CONFIG.config, + MinecraftClient.getInstance() + ) return } if (!MinecraftClient.getInstance().player!!.isCreative) @@ -136,23 +146,44 @@ object ClientEditor { * */ fun toggleModifier(mod: ModeModifier) { if (!isAllowed()) { - ChatUtil.showToastToSelf("Gimbal is disabled", "You cannot change modifiers", MinecraftClient.getInstance()) + ChatUtil.showToastToSelf( + "Gimbal is disabled", + "You cannot change modifiers", + ToastType.SYSTEM, + ClientMain.CONFIG.config, + MinecraftClient.getInstance() + ) return } if (!MinecraftClient.getInstance().player!!.isCreative) return if (CURRENT_MODE.incompatibleModifiers.contains(mod)){ - if (TEMP_DISABLED_MODIFIERS.contains(mod)) + if (TEMP_DISABLED_MODIFIERS.contains(mod)) { TEMP_DISABLED_MODIFIERS.remove(mod) - else + } else { TEMP_DISABLED_MODIFIERS.add(mod) + } } else { - if (CURRENT_MODE_MODIFIER.contains(mod)) + if (CURRENT_MODE_MODIFIER.contains(mod)) { CURRENT_MODE_MODIFIER.remove(mod) - else + ChatUtil.showToastToSelf( + "Disabled ${mod.displayName}", + "[${this.getDisplayNameListAsString(CURRENT_MODE_MODIFIER)}]", + ToastType.TOGGLE, ClientMain.CONFIG.config, + MinecraftClient.getInstance() + ) + + } else { CURRENT_MODE_MODIFIER.add(mod) + ChatUtil.showToastToSelf( + "Enabled ${mod.displayName}", + "[${this.getDisplayNameListAsString(CURRENT_MODE_MODIFIER)}]", + ToastType.TOGGLE, ClientMain.CONFIG.config, + MinecraftClient.getInstance() + ) + } } onUpdated() @@ -199,14 +230,17 @@ object ClientEditor { if(TEMP_DISABLED_MODIFIERS.isNotEmpty()) { ChatUtil.showToastToSelf( "${CURRENT_MODE.displayName} Mode disabled", - getListAsString(TEMP_DISABLED_MODIFIERS), MinecraftClient.getInstance() + getDisplayNameListAsString(TEMP_DISABLED_MODIFIERS), + ToastType.SYSTEM, + ClientMain.CONFIG.config, + MinecraftClient.getInstance() ) } } - private fun getListAsString(list: List): String{ + private fun getDisplayNameListAsString(list: List): String { if(list.isEmpty()) - return "Empty list" + return "" val sb = StringBuilder() for (mod in list) { sb.append(mod.displayName) @@ -215,25 +249,53 @@ object ClientEditor { return sb.toString().dropLast(2) } + private fun getShortNameListAsString(list: List): String { + if (list.isEmpty()) + return "" + val sb = StringBuilder() + for (mod in list) { + sb.append(mod.shortName) + sb.append(", ") + } + return sb.toString().dropLast(2) + } + /* * Get the display text to display in the HUD * */ - fun getModeDisplayText(): Text { + fun getModeDisplayText(config: GimbalClientConfig): Text { val displayText = StringBuilder(CURRENT_MODE.displayName) - if (CURRENT_MODE_MODIFIER.isNotEmpty() && isAllowed() && MinecraftClient.getInstance().player?.isCreative == true) { - displayText.append(" [") - for (i in CURRENT_MODE_MODIFIER.indices) { - displayText.append(CURRENT_MODE_MODIFIER[i].displayName) - if (i != CURRENT_MODE_MODIFIER.size - 1) { - displayText.append(", ") + if (isAllowed() && MinecraftClient.getInstance().player?.isCreative == true) { + when (config.guiSettings.hudOptions) { + HudOptions.ALL -> { + if (CURRENT_MODE_MODIFIER.size > 0) { + displayText.append(" [") + displayText.append(this.getDisplayNameListAsString(CURRENT_MODE_MODIFIER)) + displayText.append("]") + } + return Text.of(displayText.toString()) } + + HudOptions.NUMBER -> { + displayText.append(" (") + displayText.append(CURRENT_MODE_MODIFIER.size) + displayText.append(")") + return Text.of(displayText.toString()) + } + + HudOptions.INITIAL -> { + if (CURRENT_MODE_MODIFIER.size > 0) { + displayText.append(" [") + displayText.append(this.getShortNameListAsString(CURRENT_MODE_MODIFIER)) + displayText.append("]") + } + return Text.of(displayText.toString()) + } + + HudOptions.ONLY_MODE -> return Text.of(displayText.toString()) } - displayText.append("]") - } else if (!isAllowed() || !MinecraftClient.getInstance().player?.isCreative!!) { - displayText.clear() - displayText.append("[GIMBAL DISABLED]") } - return Text.of(displayText.toString()) + return Text.of("[GIMBAL DISABLED]") } fun getCurrentColor(): Int { diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingRegistrar.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingRegistrar.kt index 83a0e6d..fd37f7d 100644 --- a/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingRegistrar.kt +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingRegistrar.kt @@ -30,6 +30,7 @@ import net.moonleay.gimbal.client.keybindings.impl.editormodemodifier.ToggleNoUp import net.moonleay.gimbal.client.keybindings.impl.gamemode.CreativeModeShortcut import net.moonleay.gimbal.client.keybindings.impl.gamemode.SpectatorModeShortcut import net.moonleay.gimbal.client.keybindings.impl.gamemode.SurvivalModeShortcut +import net.moonleay.gimbal.constants.TranslationKeys import org.apache.logging.log4j.LogManager import org.lwjgl.glfw.GLFW @@ -47,28 +48,28 @@ object KeybindingRegistrar { private fun registerSetEditorModeModifierKeybindings() { val toggleBulldozerModifierShortcut = KeyBinding( - "gimbal.key.editor.modifier.bulldozer", + TranslationKeys.Keybindings.Binding.Editor.Modifier.BULLDOZER, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimbal.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) val toggleForcePlaceModifierShortcut = KeyBinding( - "gimbal.key.editor.modifier.forceplace", + TranslationKeys.Keybindings.Binding.Editor.Modifier.FORCE_PLACE, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimbal.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) val toggleNoUpdatesModifierShortcut = KeyBinding( - "gimbal.key.editor.modifier.noupdates", + TranslationKeys.Keybindings.Binding.Editor.Modifier.NO_UPDATES, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimbal.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) val toggleNoClipModifierShortcut = KeyBinding( - "gimbal.key.editor.modifier.noclip", + TranslationKeys.Keybindings.Binding.Editor.Modifier.NO_CLIP, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimbal.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) KeybindingManager.registerShortcut(ToggleBulldozerModifierShortcut(toggleBulldozerModifierShortcut)) @@ -79,16 +80,16 @@ object KeybindingRegistrar { private fun registerSetEditorModeKeybindings() { val insertKeyBinding = KeyBinding( - "gimbal.key.editor.mode.insert", + TranslationKeys.Keybindings.Binding.Editor.Mode.INSERT, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_I, - "gimbal.category.editormode" + TranslationKeys.Keybindings.Category.Editor.MODE ) val replaceKeyBinding = KeyBinding( - "gimbal.key.editor.mode.replace", + TranslationKeys.Keybindings.Binding.Editor.Mode.REPLACE, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_R, - "gimbal.category.editormode" + TranslationKeys.Keybindings.Category.Editor.MODE ) // val visualKeyBinding = KeyBinding( // "gimbal.key.editor.mode.visual", @@ -103,22 +104,22 @@ object KeybindingRegistrar { private fun registerSetGameModeKeybindings() { val survivalKeyBinding = KeyBinding( - "gimbal.key.game.mode.survival", + TranslationKeys.Keybindings.Binding.Game.Mode.SURVIVAL, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimbal.category.gamemode" + TranslationKeys.Keybindings.Category.Game.GAMEMODE ) val creativeKeyBinding = KeyBinding( - "gimbal.key.game.mode.creative", + TranslationKeys.Keybindings.Binding.Game.Mode.CREATIVE, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimbal.category.gamemode" + TranslationKeys.Keybindings.Category.Game.GAMEMODE ) val spectatorKeyBinding = KeyBinding( - "gimbal.key.game.mode.spectator", + TranslationKeys.Keybindings.Binding.Game.Mode.SPECTATOR, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimbal.category.gamemode" + TranslationKeys.Keybindings.Category.Game.GAMEMODE ) KeybindingManager.registerShortcut(SurvivalModeShortcut(survivalKeyBinding)) KeybindingManager.registerShortcut(CreativeModeShortcut(creativeKeyBinding)) diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt index 6af484e..b7682d7 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -29,10 +29,11 @@ import net.moonleay.gimbal.client.config.GimbalClientConfig import net.moonleay.gimbal.client.config.GimbalGuiSettings import net.moonleay.gimbal.client.config.ScaledRes import net.moonleay.gimbal.client.util.screen.ScreenUtil +import net.moonleay.gimbal.constants.TranslationKeys import org.apache.logging.log4j.LogManager class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfigHolder) : - Screen(Text.translatable("gimbal.gui.edithud")) { + Screen(Text.translatable(TranslationKeys.Gui.Config.Hud.EDIT_HUD)) { private val LOGGER = LogManager.getLogger(BuildConstants.modName) private var tempXOffset = 4.0 @@ -47,7 +48,7 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig override fun init() { super.init() this.addDrawableChild(ButtonWidget( - this.width / 2 + 10, this.height - 27, 90, 20, Text.translatable("gimbal.gui.resethud") + this.width / 2 + 10, this.height - 27, 90, 20, Text.translatable(TranslationKeys.Gui.Config.Hud.RESET_HUD) ) { _: ButtonWidget? -> tempXOffset = 4.0 tempYOffset = 4.0 @@ -75,7 +76,6 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig val anchor = ScreenUtil.getAnchor(this.tempXOffset, this.tempYOffset) val newConf = GimbalClientConfig( - showToasts = oldConf.showToasts, guiSettings = GimbalGuiSettings( showHud = oldConf.guiSettings.showHud, offset = ScaledRes( @@ -83,8 +83,10 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig scaledY = this.tempYOffset, ), horizontalAnchor = anchor.first, - verticalAnchor = anchor.second - ) + verticalAnchor = anchor.second, + hudOptions = oldConf.guiSettings.hudOptions + ), + toastSettings = oldConf.toastSettings ) cfg.updateConfig(newConf) @@ -104,8 +106,6 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig if (!ScreenUtil.isPositionOutOfBounds(wantedX, wantedY)) { this.tempXOffset = wantedX this.tempYOffset = wantedY - } else { - LOGGER.info("Text is oob. wantedX: ${wantedX}, wantedY: ${wantedY}, width: ${this.client!!.window.width}, height: ${this.client!!.window.height}") } } } @@ -130,11 +130,11 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig val anchor = ScreenUtil.getAnchor(this.tempXOffset, this.tempYOffset) this.textRenderer.drawWithShadow( matrices, - Text.translatable("gimbal.gui.examplehud"), + Text.translatable(TranslationKeys.Gui.Config.Hud.EXAMPLE_HUD_TEXT), ScreenUtil.getXForAnchor( ScreenUtil.getReal(this.client!!.window.width, this.tempXOffset) / scaleFactor, anchor.first, - this.textRenderer.getWidth(Text.translatable("gimbal.gui.examplehud")) + this.textRenderer.getWidth(Text.translatable(TranslationKeys.Gui.Config.Hud.EXAMPLE_HUD_TEXT)) ), ScreenUtil.getYForAnchor( ScreenUtil.getReal(this.client!!.window.height, this.tempYOffset) / scaleFactor, @@ -142,11 +142,7 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig this.textRenderer.fontHeight ), 0xFFFFFF - ) // TODO: improve placement when changing the scaling -// LOGGER.info("width: ${this.width}, height: ${this.height}," + -// " posX: ${ScreenUtil.getReal(this.width, this.tempXOffset)}," + -// " posY: ${ScreenUtil.getReal(this.height, this.tempYOffset)}," + -// " scaleX: ${this.tempXOffset}, scaleY: ${this.tempYOffset}") + ) super.render(matrices, mouseX, mouseY, delta) } } diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt index 0885102..c2cd5c0 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -27,9 +27,21 @@ import net.minecraft.text.Text import net.moonleay.gimbal.client.config.ClientConfigHolder import net.moonleay.gimbal.client.config.GimbalClientConfig import net.moonleay.gimbal.client.config.GimbalGuiSettings +import net.moonleay.gimbal.client.config.enums.HudOptions +import net.moonleay.gimbal.client.config.enums.ToastSettings +import net.moonleay.gimbal.constants.TranslationKeys class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfigHolder) : - Screen(Text.translatable("gimbal.gui.settings")) { + Screen(Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME)) { + + private var hudOptions: HudOptions + private var toastSettings: ToastSettings + + init { + this.hudOptions = cfg.config.guiSettings.hudOptions + this.toastSettings = cfg.config.toastSettings + } + override fun init() { this.addDrawableChild(CyclingButtonWidget.onOffBuilder( // Text.translatable("gimbal.gui.enabled"), @@ -41,7 +53,7 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi this.height / 6 + 24 * 0, 150, 20, - Text.translatable("gimbal.gui.hud") + Text.translatable(TranslationKeys.Gui.Config.Hud.SHOW_HUD) ) { _: CyclingButtonWidget?, isEnabled: Boolean? -> val oldGui = cfg.config.guiSettings val newGui = GimbalGuiSettings( @@ -49,24 +61,120 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi offset = oldGui.offset, horizontalAnchor = oldGui.horizontalAnchor, verticalAnchor = oldGui.verticalAnchor, + hudOptions = oldGui.hudOptions ) val newConf = GimbalClientConfig( guiSettings = newGui, - showToasts = cfg.config.showToasts + toastSettings = cfg.config.toastSettings ) cfg.updateConfig(newConf) }) + this.addDrawableChild(ButtonWidget( this.width / 2 - 155 + 160, this.height / 6 + 24 * 0, 150, 20, - Text.translatable("gimbal.gui.edithud") + Text.translatable(TranslationKeys.Gui.Config.Hud.EDIT_HUD) ) { _: ButtonWidget? -> this.client!!.setScreen(GimbalEditHudGui(this, cfg)) - } + }) + + this.addDrawableChild>( + CyclingButtonWidget.builder { value: HudOptions? -> + when (value) { + HudOptions.ALL -> { + return@builder HudOptions.ALL.translatableText + } + + HudOptions.NUMBER -> { + return@builder HudOptions.NUMBER.translatableText + } + + HudOptions.INITIAL -> { + return@builder HudOptions.INITIAL.translatableText + } + + HudOptions.ONLY_MODE -> { + return@builder HudOptions.ONLY_MODE.translatableText + } + + else -> return@builder Text.translatable(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_ALL) + } + } + .values(HudOptions.entries) + .initially(this.hudOptions) + .build( + this.width / 2 - 155, + this.height / 6 + 24 * 1, + 150, + 20, + Text.translatable(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_MODIFIERS) + ) { _: CyclingButtonWidget?, hudDO: HudOptions -> + this.hudOptions = hudDO + + val oldConfig = cfg.config + val oldGuiConfig = oldConfig.guiSettings + val newConfig = GimbalClientConfig( + guiSettings = GimbalGuiSettings( + horizontalAnchor = oldGuiConfig.horizontalAnchor, + verticalAnchor = oldGuiConfig.verticalAnchor, + showHud = oldGuiConfig.showHud, + offset = oldGuiConfig.offset, + hudOptions = this.hudOptions + ), + toastSettings = oldConfig.toastSettings + ) + cfg.updateConfig(newConfig) + } ) + + this.addDrawableChild>( + CyclingButtonWidget.builder { value: ToastSettings? -> + when (value) { + ToastSettings.ALL -> { + return@builder ToastSettings.ALL.translatableText + } + + ToastSettings.ONLY_TOGGLE -> { + return@builder ToastSettings.ONLY_TOGGLE.translatableText + } + + ToastSettings.ONLY_SYSTEM -> { + return@builder ToastSettings.ONLY_SYSTEM.translatableText + } + + ToastSettings.NONE -> { + return@builder ToastSettings.NONE.translatableText + } + + else -> return@builder Text.translatable(TranslationKeys.Gui.Config.Toasts.SHOW_ALL) + } + } + .values(ToastSettings.entries) + .initially(this.toastSettings) + .build( + this.width / 2 - 155 + 160, + this.height / 6 + 24 * 1, + 150, + 20, + Text.translatable(TranslationKeys.Gui.Config.Toasts.SHOW_TOASTS) + ) { _: CyclingButtonWidget?, toastStng: ToastSettings -> + this.toastSettings = toastStng + + val oldConfig = cfg.config + val newConfig = GimbalClientConfig( + guiSettings = oldConfig.guiSettings, + toastSettings = this.toastSettings + ) + cfg.updateConfig(newConfig) + } + ) + + + + // Done button this.addDrawableChild(ButtonWidget( this.width / 2 - 100, this.height / 6 + 168, 200, 20, ScreenTexts.DONE diff --git a/src/main/java/net/moonleay/gimbal/client/util/ChatUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/ChatUtil.kt index 9fd2b18..b53d959 100644 --- a/src/main/java/net/moonleay/gimbal/client/util/ChatUtil.kt +++ b/src/main/java/net/moonleay/gimbal/client/util/ChatUtil.kt @@ -21,6 +21,7 @@ package net.moonleay.gimbal.client.util import net.minecraft.client.MinecraftClient import net.minecraft.client.toast.SystemToast import net.minecraft.text.Text +import net.moonleay.gimbal.client.config.GimbalClientConfig object ChatUtil { /** @@ -37,7 +38,16 @@ object ChatUtil { client.inGameHud.chatHud.addMessage(Text.of(message)) } - fun showToastToSelf(title: String, description: String, client: MinecraftClient) { + fun showToastToSelf( + title: String, + description: String, + type: ToastType, + config: GimbalClientConfig, + client: MinecraftClient, + ) { + if (!config.toastSettings.allowedTypes.contains(type)) + return + val toast = SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.of(title), Text.of(description)) client.toastManager.add(toast) } diff --git a/src/main/java/net/moonleay/gimbal/client/util/ToastType.kt b/src/main/java/net/moonleay/gimbal/client/util/ToastType.kt new file mode 100644 index 0000000..4dc9312 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/util/ToastType.kt @@ -0,0 +1,24 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.util + +enum class ToastType { + TOGGLE, + SYSTEM, +} diff --git a/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt index 9c0c130..5a5d4f7 100644 --- a/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt +++ b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt @@ -18,8 +18,8 @@ package net.moonleay.gimbal.client.util.screen -import net.moonleay.gimbal.client.config.HorizontalAnchor -import net.moonleay.gimbal.client.config.VerticalAnchor +import net.moonleay.gimbal.client.config.enums.HorizontalAnchor +import net.moonleay.gimbal.client.config.enums.VerticalAnchor object ScreenUtil { diff --git a/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt new file mode 100644 index 0000000..6d4c355 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt @@ -0,0 +1,123 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.constants + +import net.moonleay.gimbal.build.BuildConstants + +object TranslationKeys { + object Gui { + const val BASE = "gui.${BuildConstants.modId}." + + object Config { + const val BASE = "${TranslationKeys.Gui.BASE}conf." + + const val SCREEN_NAME = "${BASE}settings" + const val GENERIC_ENABLED = "${BASE}enabled" + const val GENERIC_DISABLED = "${BASE}disabled" + + object Hud { + const val BASE = "${TranslationKeys.Gui.Config.BASE}hud." + + const val SHOW_HUD = "${BASE}show" + const val EDIT_HUD = "${BASE}edit" + const val RESET_HUD = "${BASE}reset" + const val EXAMPLE_HUD_TEXT = "${BASE}example" + + object Modifiers { + const val BASE = "${TranslationKeys.Gui.Config.Hud.BASE}modifiers." + + const val SHOW_MODIFIERS = "${BASE}show" + const val SHOW_ALL = "${BASE}all" + const val SHOW_NUMBER = "${BASE}number" + const val SHOW_INITIALS = "${BASE}initials" + const val SHOW_MODE_ONLY = "${BASE}modeOnly" + } + } + + object Toasts { + const val BASE = "${TranslationKeys.Gui.Config.BASE}toasts." + + const val SHOW_TOASTS = "${BASE}show" + const val SHOW_ALL = "${BASE}all" + const val SHOW_TOGGLE = "${BASE}toggle" + const val SHOW_SYSTEM = "${BASE}system" + const val SHOW_NONE = "${BASE}none" + } + } + } + + object Keybindings { + // No base here, Categories and Bindings have separate BASEs + object Category { + const val BASE = "category.${BuildConstants.modId}." + + object Editor { + const val BASE = "${TranslationKeys.Keybindings.Category.BASE}editor." + + const val MODE = "${BASE}mode" + const val MODIFIER = "${BASE}modifier" + } + + object Game { + const val BASE = "${TranslationKeys.Keybindings.Category.BASE}game." + + const val GAMEMODE = "${BASE}mode" + } + } + + object Binding { + const val BASE = "key.${BuildConstants.modId}." + + object Editor { + const val BASE = "${TranslationKeys.Keybindings.Binding.BASE}editor." + + object Mode { + const val BASE = "${TranslationKeys.Keybindings.Binding.Editor.BASE}mode." + + const val INSERT = "${BASE}insert" + const val REPLACE = "${BASE}replace" + const val VISUAL = "${BASE}visual" + } + + object Modifier { + const val BASE = "${TranslationKeys.Keybindings.Binding.Editor.BASE}modifier." + + const val BULLDOZER = "${BASE}autoClicker" + const val FORCE_PLACE = "${BASE}forcePlace" + const val NO_UPDATES = "${BASE}noUpdates" + const val NO_CLIP = "${BASE}noClip" + } + } + + object Game { + const val BASE = "${TranslationKeys.Keybindings.Binding.BASE}game." + + object Mode { + const val BASE = "${TranslationKeys.Keybindings.Binding.Game.BASE}mode." + + const val SURVIVAL = "${BASE}survival" + const val CREATIVE = "${BASE}creative" + const val SPECTATOR = "${BASE}spectator" + } + } + } + } + + +} diff --git a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt b/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt index 0082df9..666e1fe 100644 --- a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt +++ b/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt @@ -20,6 +20,7 @@ package net.moonleay.gimbal.datagen import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator import net.fabricmc.fabric.api.datagen.v1.provider.FabricLanguageProvider +import net.moonleay.gimbal.constants.TranslationKeys class En_us_GimbalLanguageProvider(dataGenerator: FabricDataGenerator?) : FabricLanguageProvider(dataGenerator, "en_us") { @@ -28,35 +29,63 @@ class En_us_GimbalLanguageProvider(dataGenerator: FabricDataGenerator?) : if (translationBuilder == null) return /// Screens // Gimbal settings screen - translationBuilder.add("gimbal.gui.settings", "Gimbal Settings") - translationBuilder.add("gimbal.gui.hud", "Show HUD") - translationBuilder.add("gimbal.gui.edithud", "Edit HUD Layout...") - translationBuilder.add("gimbal.gui.resethud", "Reset Layout") - translationBuilder.add("gimbal.gui.examplehud", "EXAMPLE [No Clip, Force]") + translationBuilder.add(TranslationKeys.Gui.Config.SCREEN_NAME, "Gimbal Settings") + + // Hud + translationBuilder.add(TranslationKeys.Gui.Config.Hud.SHOW_HUD, "Show HUD") - translationBuilder.add("gimbal.gui.enabled", "Enabled") - translationBuilder.add("gimbal.gui.disabled", "Disabled") + //Gimbal HUD pos edit + translationBuilder.add(TranslationKeys.Gui.Config.Hud.EDIT_HUD, "Edit HUD Layout...") + translationBuilder.add(TranslationKeys.Gui.Config.Hud.RESET_HUD, "Reset Layout") + translationBuilder.add(TranslationKeys.Gui.Config.Hud.EXAMPLE_HUD_TEXT, "EXAMPLE [No Clip, Force]") + + //Gimbal HUD Content + translationBuilder.add(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_MODIFIERS, "Show Modifiers") + translationBuilder.add(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_ALL, "All") + translationBuilder.add(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_NUMBER, "Number") + translationBuilder.add(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_INITIALS, "Short") + translationBuilder.add(TranslationKeys.Gui.Config.Hud.Modifiers.SHOW_MODE_ONLY, "None") + + //Gimbal Toasts + translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_TOASTS, "Show Toasts") + translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_ALL, "All") + translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_TOGGLE, "Only toggle") + translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_SYSTEM, "Only system") + translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_NONE, "None") + + // Gimbal Generic Gui + translationBuilder.add(TranslationKeys.Gui.Config.GENERIC_ENABLED, "Enabled") + translationBuilder.add(TranslationKeys.Gui.Config.GENERIC_DISABLED, "Disabled") /// Options // Editor modes - translationBuilder.add("gimbal.category.editormode", "Editor Modes") - translationBuilder.add("gimbal.key.editor.mode.insert", "Enter Insert Mode") - translationBuilder.add("gimbal.key.editor.mode.replace", "Enter Replace Mode") - translationBuilder.add("gimbal.key.editor.mode.visual", "Enter Visual Mode") + translationBuilder.add(TranslationKeys.Keybindings.Category.Editor.MODE, "Editor Modes") + translationBuilder.add(TranslationKeys.Keybindings.Binding.Editor.Mode.INSERT, "Enter Insert Mode") + translationBuilder.add(TranslationKeys.Keybindings.Binding.Editor.Mode.REPLACE, "Enter Replace Mode") + translationBuilder.add(TranslationKeys.Keybindings.Binding.Editor.Mode.VISUAL, "Enter Visual Mode") // Editor mode modifiers - translationBuilder.add("gimbal.category.editormodifier", "Editor Mode Modifiers") - translationBuilder.add("gimbal.key.editor.modifier.bulldozer", "Toggle Bulldozer Modifier") - translationBuilder.add("gimbal.key.editor.modifier.forceplace", "Toggle Force Place Modifier") - translationBuilder.add("gimbal.key.editor.modifier.noupdates", "Toggle No Updates Modifier") - translationBuilder.add("gimbal.key.editor.modifier.noclip", "Toggle No Clip Modifier") + translationBuilder.add(TranslationKeys.Keybindings.Category.Editor.MODIFIER, "Editor Mode Modifiers") + translationBuilder.add( + TranslationKeys.Keybindings.Binding.Editor.Modifier.BULLDOZER, + "Toggle Bulldozer Modifier" + ) + translationBuilder.add( + TranslationKeys.Keybindings.Binding.Editor.Modifier.FORCE_PLACE, + "Toggle Force Place Modifier" + ) + translationBuilder.add( + TranslationKeys.Keybindings.Binding.Editor.Modifier.NO_UPDATES, + "Toggle No Updates Modifier" + ) + translationBuilder.add(TranslationKeys.Keybindings.Binding.Editor.Modifier.NO_CLIP, "Toggle No Clip Modifier") // Game mode - translationBuilder.add("gimbal.category.gamemode", "Game Mode") - translationBuilder.add("gimbal.key.game.mode.survival", "Enable Survival Mode") - translationBuilder.add("gimbal.key.game.mode.creative", "Enable Creative Mode") - translationBuilder.add("gimbal.key.game.mode.spectator", "Enable Spectator Mode") + translationBuilder.add(TranslationKeys.Keybindings.Category.Game.GAMEMODE, "Game Mode") + translationBuilder.add(TranslationKeys.Keybindings.Binding.Game.Mode.SURVIVAL, "Enable Survival Mode") + translationBuilder.add(TranslationKeys.Keybindings.Binding.Game.Mode.CREATIVE, "Enable Creative Mode") + translationBuilder.add(TranslationKeys.Keybindings.Binding.Game.Mode.SPECTATOR, "Enable Spectator Mode") } } diff --git a/src/main/java/net/moonleay/gimbal/editor/state/mode/ModeModifier.kt b/src/main/java/net/moonleay/gimbal/editor/state/mode/ModeModifier.kt index 221941f..da99041 100644 --- a/src/main/java/net/moonleay/gimbal/editor/state/mode/ModeModifier.kt +++ b/src/main/java/net/moonleay/gimbal/editor/state/mode/ModeModifier.kt @@ -18,10 +18,10 @@ package net.moonleay.gimbal.editor.state.mode -enum class ModeModifier(val displayName: String) { +enum class ModeModifier(val displayName: String, val shortName: String) { // NONE("None"), // No Modifiers - default behavior - NO_UPDATES("NO UPDATES"), // Do not update blocks when placing - BULLDOZER("BULLDOZER"), // Break blocks fast - FORCE_PLACE("FORCE"), // Ignore block placement restrictions - NO_CLIP("NO CLIP"), // Do not collide with blocks +NO_UPDATES("NO UPDATES", "NU"), // Do not update blocks when placing + BULLDOZER("BULLDOZER", "BLR"), // Break blocks fast + FORCE_PLACE("FORCE", "FP"), // Ignore block placement restrictions + NO_CLIP("NO CLIP", "NC"), // Do not collide with blocks } diff --git a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java index 607c7f2..5c0f58f 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java @@ -50,7 +50,7 @@ public abstract class HudMixin { this.client.options.getGuiScale().getValue(), this.client.forcesUnicodeFont() ); - Text displayText = ClientEditor.INSTANCE.getModeDisplayText(); + Text displayText = ClientEditor.INSTANCE.getModeDisplayText(ClientMain.CONFIG.getConfig()); tr.drawWithShadow( matrices, displayText, diff --git a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java index 861ecd3..f86f610 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java @@ -26,6 +26,7 @@ import net.minecraft.util.Identifier; import net.moonleay.gimbal.build.BuildConstants; import net.moonleay.gimbal.client.ClientMain; import net.moonleay.gimbal.client.screen.GimbalSettingsGui; +import net.moonleay.gimbal.constants.TranslationKeys; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -59,7 +60,7 @@ public class YouInjectButtonMixin extends Screen { 20, 40, button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), - Text.translatable("gimbal.gui.settings") + Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME) ) ); } diff --git a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java index 70af1f4..b25789d 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java +++ b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java @@ -26,6 +26,7 @@ import net.minecraft.util.Identifier; import net.moonleay.gimbal.build.BuildConstants; import net.moonleay.gimbal.client.ClientMain; import net.moonleay.gimbal.client.screen.GimbalSettingsGui; +import net.moonleay.gimbal.constants.TranslationKeys; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -58,7 +59,7 @@ public class YouInjectButtonMixin2 extends Screen { 20, 40, button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), - Text.translatable("gimbal.gui.settings") + Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME) ) ); } From 31bab516036ba00b4cc73221feaf688721d3474b Mon Sep 17 00:00:00 2001 From: cookieso Date: Mon, 6 May 2024 21:43:57 +0200 Subject: [PATCH 13/24] fix: Made replace mode more dynamic to copy properties for all blocks --- .../mixin/ReplaceStateUpdaterMixin.java | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java index 7d0772d..255604a 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java @@ -18,12 +18,11 @@ package net.moonleay.gimbal.mixin; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.block.StairsBlock; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemPlacementContext; +import net.minecraft.state.property.Property; import net.moonleay.gimbal.editor.ServerEditorManager; import net.moonleay.gimbal.editor.state.mode.Capability; import org.spongepowered.asm.mixin.Mixin; @@ -34,8 +33,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import java.util.UUID; -import static net.minecraft.block.StairsBlock.*; - @Mixin(BlockItem.class) public abstract class ReplaceStateUpdaterMixin extends Item { @@ -54,21 +51,20 @@ public abstract class ReplaceStateUpdaterMixin extends Item { if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE)) return this.place(context, state); BlockState oldState = context.getWorld().getBlockState(context.getBlockPos()); - Block targetBl = oldState.getBlock(); - if (state.getBlock() instanceof StairsBlock && targetBl instanceof StairsBlock targetStair) { - // Block and item is stairs, parse Stairs data - return this.place(context, copyStairState(oldState, instance)); - } - return this.place(context, state); + return this.place(context, getTargetBlockState(oldState, instance.getBlock().getDefaultState())); } - @Unique - public BlockState copyStairState(BlockState targetState, BlockItem item) { - BlockState blockState = item.getBlock().getDefaultState() - .with(FACING, targetState.get(FACING)) - .with(HALF, targetState.get(HALF)) - .with(WATERLOGGED, targetState.get(WATERLOGGED)); - return blockState.with(SHAPE, targetState.get(SHAPE)); + public BlockState getTargetBlockState(BlockState oldState, BlockState newBlock) { + var oldManager = oldState.getBlock().getStateManager(); + var newManager = newBlock.getBlock().getStateManager(); + for (var prop : oldManager.getProperties()) { + var matchingProp = newManager.getProperty(prop.getName()); + if (matchingProp != null) { + //noinspection rawtypes,unchecked + newBlock = newBlock.with((Property) matchingProp, oldState.get(matchingProp)); + } + } + return newBlock; } } From 68e9eeceb6cfc4032736bcc48293252dbbfca4dd Mon Sep 17 00:00:00 2001 From: moonleay Date: Tue, 7 May 2024 01:14:11 +0200 Subject: [PATCH 14/24] chore: bumped protocol version, because server side component changed Signed-off-by: moonleay --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2ca88dd..b0bfac9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,7 +38,7 @@ val modName: String by project * Gimbal version stuff * */ -val gimbalProtocolVersion = 2 +val gimbalProtocolVersion = 3 val mavenGroup: String by project From 302f486f1c702fe631a03ba2c28cb9638c431619 Mon Sep 17 00:00:00 2001 From: moonleay Date: Fri, 10 May 2024 15:17:26 +0000 Subject: [PATCH 15/24] chore/add-ci (#3) Added ci for dev and release builds. Reviewed-on: https://codeberg.org/moonleay/Gimbal/pulls/3 Co-authored-by: moonleay Co-committed-by: moonleay --- .forgejo/workflows/build-dev.yml | 42 ++++++++++++++++++++++ .forgejo/workflows/build-release.yml | 54 ++++++++++++++++++++++++++++ build.gradle.kts | 53 +++++++++++++++++++++------ src/main/resources/fabric.mod.json | 3 ++ 4 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 .forgejo/workflows/build-dev.yml create mode 100644 .forgejo/workflows/build-release.yml diff --git a/.forgejo/workflows/build-dev.yml b/.forgejo/workflows/build-dev.yml new file mode 100644 index 0000000..e0449f4 --- /dev/null +++ b/.forgejo/workflows/build-dev.yml @@ -0,0 +1,42 @@ +on: + push: + branches-ignore: + - refs/tags/ + +jobs: + dev: + runs-on: nodebullshit + steps: + - uses: actions/checkout@v3 + name: Checkout + + - name: Set short git commit reference + id: vars + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - uses: https://github.com/actions/setup-java@v4 + name: Setup Java + with: + distribution: temurin + java-version: 17 + + - uses: https://github.com/gradle/actions/setup-gradle@v3 + name: Setup Gradle + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + + - run: ./gradlew runDatagen + name: Generate assets + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + + - run: ./gradlew build + name: Build project + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + + - run: ./gradlew publish + name: Upload + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + PACKAGE_REPO_KEY: ${{ secrets.PACKAGE_REPO_KEY }} diff --git a/.forgejo/workflows/build-release.yml b/.forgejo/workflows/build-release.yml new file mode 100644 index 0000000..01b60ea --- /dev/null +++ b/.forgejo/workflows/build-release.yml @@ -0,0 +1,54 @@ +on: + release: + types: + - released + - prereleased + - created + - published + +jobs: + release: + runs-on: nodebullshit + steps: + - uses: actions/checkout@v3 + name: Checkout + + - name: Fetch the full git repository + run: git fetch --prune --unshallow + + - name: Set short git commit reference + id: vars + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - uses: https://github.com/actions/setup-java@v4 + name: Setup Java + with: + distribution: temurin + java-version: 17 + + - uses: https://github.com/gradle/actions/setup-gradle@v3 + name: Setup Gradle + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + + - run: ./gradlew runDatagen + name: Generate assets + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + + - run: ./gradlew build + name: Build project + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + + - run: ./gradlew publish + name: Upload + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + PACKAGE_REPO_KEY: ${{ secrets.PACKAGE_REPO_KEY }} + + - run: ./gradlew modrinth + name: Publish to Modrinth + env: + GIT_SHA_SHORT: ${{ steps.vars.outputs.sha_short }} + MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} diff --git a/build.gradle.kts b/build.gradle.kts index b0bfac9..efb5c4d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,10 +27,13 @@ plugins { `maven-publish` eclipse id("org.jetbrains.gradle.plugin.idea-ext") + id("com.modrinth.minotaur") version "2.+" } -val mavenVersion = System.getenv("CI_COMMIT_TAG") ?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" } -?: "0.3.0" //"0.0.0-SNAPSHOT" +val ver = if ((System.getenv("GITHUB_REF") ?: "local").startsWith("refs/tags/")) + System.getenv("GITHUB_REF_NAME") ?: "err" else System.getenv("GIT_SHA_SHORT") ?: "0.0.0" + +val mavenVersion = ver val modId: String by project val modName: String by project @@ -184,17 +187,18 @@ publishing { } repositories { - if (System.getenv("CI_JOB_TOKEN") != null) { + if (System.getenv("CI") != null) { maven { - name = "GitLab" - val projectId = System.getenv("CI_PROJECT_ID") - val apiV4 = System.getenv("CI_API_V4_URL") - url = uri("$apiV4/projects/$projectId/packages/maven") + name = "Codeberg" + val repoOwner = System.getenv("GITHUB_REPOSITORY_OWNER") + val serverUrl = System.getenv("GITHUB_SERVER_URL") + val accessToken = System.getenv("PACKAGE_REPO_KEY") + url = uri("$serverUrl/api/packages/$repoOwner/maven") authentication { - create("token", HttpHeaderAuthentication::class.java) { - credentials(HttpHeaderCredentials::class.java) { - name = "Job-Token" - value = System.getenv("CI_JOB_TOKEN") + create("header", HttpHeaderAuthentication::class.java) { + credentials(HttpHeaderCredentials::class) { + name = "Authorization" + value = "token $accessToken" } } } @@ -203,6 +207,33 @@ publishing { } } +// build.gradle.kts +modrinth { + token.set(System.getenv("MODRINTH_TOKEN")) // Remember to have the MODRINTH_TOKEN environment variable set or else this will fail - just make sure it stays private! + projectId.set(modId) // This can be the project ID or the slug. Either will work! + versionNumber.set(mavenVersion) // You don't need to set this manually. Will fail if Modrinth has this version already + versionName.set("$modName $mavenVersion for $minecraftVersion") + versionType.set("alpha") // This is the default -- can also be `beta` or `alpha` + uploadFile.set(tasks.remapJar) // With Loom, this MUST be set to `remapJar` instead of `jar`! + gameVersions.addAll(listOf(project.ext["minecraft.version"] as String)) // Must be an array, even with only one version + loaders.add("fabric") // Must also be an array - no need to specify this if you're using Loom or ForgeGradle + changelog.set( + "Changelog v$mavenVersion\n\nCheckout the changelog [on codeberg](${System.getenv("GITHUB_SERVER_URL") ?: ""}/${ + System.getenv( + "GITHUB_REPOSITORY" + ) ?: "" + }/releases/tag/${System.getenv("GITHUB_REF_NAME") ?: ""})" + ) + dependencies { // A special DSL for creating dependencies + // scope.type + // The scope can be `required`, `optional`, `incompatible`, or `embedded` + // The type can either be `project` or `version` + required.project("fabric-api") // Creates a new required dependency on Fabric API + required.project("fabric-language-kotlin") + } +} + + rootProject.idea.project { this as ExtensionAware configure { diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2a47121..0f9c789 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -7,6 +7,9 @@ "authors": [ "moonleay" ], + "contributors": [ + "Cookieso" + ], "icon": "assets/${modId}/logo.png", "contact": { "email": "contact@moonleay.net", From 7325798098cdbf4789bd84d04b9c0f527eca777a Mon Sep 17 00:00:00 2001 From: moonleay Date: Sat, 11 May 2024 03:06:01 +0200 Subject: [PATCH 16/24] feat: improved loading and saving logic, made Json loader ignore unknown keys Signed-off-by: moonleay --- .../client/config/ClientConfigHolder.kt | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt index b4d38ba..0b7769e 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt @@ -30,42 +30,48 @@ class ClientConfigHolder(private val path: Path) { private set init { - config = load() + this.config = load() } fun updateConfig(new: GimbalClientConfig) { - config = new - save(config) + this.config = new + this.save(config) } @OptIn(ExperimentalSerializationApi::class) fun load(): GimbalClientConfig { if (!path.isReadable()) save(GimbalClientConfig()) - return path.inputStream().use { - Json.decodeFromStream(it) + val iStream = path.inputStream() + val gimbalClientConfig: GimbalClientConfig = iStream.use { + Json { + ignoreUnknownKeys = true + }.decodeFromStream(it) } + iStream.close() + return gimbalClientConfig } - // TODO: Support incomplete config files @OptIn(ExperimentalSerializationApi::class) fun save(conf: GimbalClientConfig) { + if (!path.parent.exists()) { + path.parent.createDirectory() + } + if (!path.parent.isWritable()) { + throw Exception("Parent of path ${path.parent.pathString} is not writable.") + } + if (!path.exists()) + path.createFile() if (!path.isWritable()) { - if (!path.parent.exists()) { - path.parent.createDirectory() - } - if (!path.parent.isWritable()) { - throw Exception("Parent of path ${path.parent.pathString} is not writable.") - } - if (!path.exists()) - path.createFile() - if (!path.isWritable()) { - throw Exception("Path (${path.pathString}) exists, but is not writable.") - } + throw Exception("Path (${path.pathString}) exists, but is not writable.") } - path.outputStream().use { - Json.encodeToStream(conf, it) + val oStream = path.outputStream() + oStream.use { + Json { + ignoreUnknownKeys = true + }.encodeToStream(conf, it) } + oStream.close() } } From 19f4b3649a60667ced30762c3993f23e95502cf6 Mon Sep 17 00:00:00 2001 From: moonleay Date: Thu, 16 May 2024 03:29:57 +0200 Subject: [PATCH 17/24] feat: created custom slider widget Signed-off-by: moonleay --- .../screen/widgets/GimbalSliderWidget.kt | 50 +++++++++++++++++++ .../moonleay/gimbal/client/util/NumberUtil.kt | 37 ++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt create mode 100644 src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt diff --git a/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt b/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt new file mode 100644 index 0000000..c6d2038 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt @@ -0,0 +1,50 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.screen.widgets + +import net.minecraft.client.gui.widget.SliderWidget +import net.minecraft.text.Text +import net.moonleay.gimbal.client.util.NumberUtil + +class GimbalSliderWidget( + x: Int, + y: Int, + width: Int, + height: Int, + private val text: Text, + value: Double, + private val lowerEnd: Double, + private val upperEnd: Double, + private val setValue: (Double) -> Unit, +) : + SliderWidget(x, y, width, height, text, value) { + init { + this.message = this.text.copy() + .append(": " + (NumberUtil.interpolate(this.value, 0.0, 1.0, this.lowerEnd, this.upperEnd).toInt())) + } + + override fun updateMessage() { + this.message = this.text.copy() + .append(": " + (NumberUtil.interpolate(this.value, 0.0, 1.0, this.lowerEnd, this.upperEnd).toInt())) + } + + override fun applyValue() { + this.setValue(this.value) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt new file mode 100644 index 0000000..5bdb3f3 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt @@ -0,0 +1,37 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.client.util + +object NumberUtil { + + /** + * Interpolate a Position between two numbers + */ + fun interpolate(number: Double, min: Double, max: Double, lowerEnd: Double, upperEnd: Double): Double { + val toAddToMin = (0 - min) * -1 + val minMaxDiff = max - min + val onePercent = minMaxDiff / 100.0 + val percentOfNumber = (number - toAddToMin) / onePercent + + val toAddToLowerEnd = (0 - lowerEnd) * -1 + val upperLowerDiff = upperEnd - lowerEnd + val onePercentOfEnd = upperLowerDiff / 100.0 + return (percentOfNumber * onePercentOfEnd) + toAddToLowerEnd + } +} From b4f46ee703d4f6e613b0c897b93845f8caf59b5a Mon Sep 17 00:00:00 2001 From: moonleay Date: Thu, 16 May 2024 03:31:41 +0200 Subject: [PATCH 18/24] feat: added option and config for player fly speed Signed-off-by: moonleay --- .../client/config/GimbalClientConfig.kt | 1 + .../gimbal/client/editor/ClientEditor.kt | 1 - .../gimbal/client/screen/GimbalEditHudGui.kt | 3 +- .../gimbal/client/screen/GimbalSettingsGui.kt | 33 ++++++++++++++++--- .../gimbal/constants/TranslationKeys.kt | 2 ++ .../datagen/En_us_GimbalLanguageProvider.kt | 7 ++-- 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt index f673f28..199908a 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt @@ -25,4 +25,5 @@ import net.moonleay.gimbal.client.config.enums.ToastSettings data class GimbalClientConfig( val guiSettings: GimbalGuiSettings = GimbalGuiSettings(), val toastSettings: ToastSettings = ToastSettings.ALL, + val playerFlySpeed: Int = 0, ) diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index 2982db4..303996f 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -45,7 +45,6 @@ object ClientEditor { private val CURRENT_MODE_MODIFIER = mutableListOf() private val TEMP_DISABLED_MODIFIERS = mutableListOf() - private val DISABLED_MODIFIERS_STORAGE = mutableListOf() diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt index b7682d7..c0ec0be 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -86,7 +86,8 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig verticalAnchor = anchor.second, hudOptions = oldConf.guiSettings.hudOptions ), - toastSettings = oldConf.toastSettings + toastSettings = oldConf.toastSettings, + playerFlySpeed = oldConf.playerFlySpeed ) cfg.updateConfig(newConf) diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt index c2cd5c0..c7d33e0 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -29,6 +29,8 @@ import net.moonleay.gimbal.client.config.GimbalClientConfig import net.moonleay.gimbal.client.config.GimbalGuiSettings import net.moonleay.gimbal.client.config.enums.HudOptions import net.moonleay.gimbal.client.config.enums.ToastSettings +import net.moonleay.gimbal.client.screen.widgets.GimbalSliderWidget +import net.moonleay.gimbal.client.util.NumberUtil import net.moonleay.gimbal.constants.TranslationKeys class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfigHolder) : @@ -36,10 +38,12 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi private var hudOptions: HudOptions private var toastSettings: ToastSettings + private var playerFlySpeed: Int init { this.hudOptions = cfg.config.guiSettings.hudOptions this.toastSettings = cfg.config.toastSettings + this.playerFlySpeed = cfg.config.playerFlySpeed } override fun init() { @@ -65,7 +69,8 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi ) val newConf = GimbalClientConfig( guiSettings = newGui, - toastSettings = cfg.config.toastSettings + toastSettings = cfg.config.toastSettings, + playerFlySpeed = cfg.config.playerFlySpeed ) cfg.updateConfig(newConf) }) @@ -123,7 +128,8 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi offset = oldGuiConfig.offset, hudOptions = this.hudOptions ), - toastSettings = oldConfig.toastSettings + toastSettings = oldConfig.toastSettings, + playerFlySpeed = oldConfig.playerFlySpeed ) cfg.updateConfig(newConfig) } @@ -166,14 +172,33 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi val oldConfig = cfg.config val newConfig = GimbalClientConfig( guiSettings = oldConfig.guiSettings, - toastSettings = this.toastSettings + toastSettings = this.toastSettings, + playerFlySpeed = oldConfig.playerFlySpeed ) cfg.updateConfig(newConfig) } ) + this.addDrawableChild(GimbalSliderWidget( + this.width / 2 - 155, + this.height / 6 + 24 * 2, + 150, + 20, + Text.translatable(TranslationKeys.Gui.Config.PLAYER_FLY_SPEED), + NumberUtil.interpolate(this.playerFlySpeed.toDouble(), 50.0, 500.0, 0.0, 1.0), + 50.0, + 500.0, + ) { value -> + this.playerFlySpeed = NumberUtil.interpolate(value, 0.0, 1.0, 50.0, 500.0).toInt() - + val oldConfig = cfg.config + val newConfig = GimbalClientConfig( + guiSettings = oldConfig.guiSettings, + toastSettings = this.toastSettings, + playerFlySpeed = this.playerFlySpeed + ) + cfg.updateConfig(newConfig) + }) // Done button this.addDrawableChild(ButtonWidget( diff --git a/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt index 6d4c355..d820f70 100644 --- a/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt +++ b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt @@ -31,6 +31,8 @@ object TranslationKeys { const val GENERIC_ENABLED = "${BASE}enabled" const val GENERIC_DISABLED = "${BASE}disabled" + const val PLAYER_FLY_SPEED = "${BASE}flySpeed" + object Hud { const val BASE = "${TranslationKeys.Gui.Config.BASE}hud." diff --git a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt b/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt index 666e1fe..3251f74 100644 --- a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt +++ b/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt @@ -50,10 +50,13 @@ class En_us_GimbalLanguageProvider(dataGenerator: FabricDataGenerator?) : //Gimbal Toasts translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_TOASTS, "Show Toasts") translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_ALL, "All") - translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_TOGGLE, "Only toggle") - translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_SYSTEM, "Only system") + translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_TOGGLE, "Only Toggle") + translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_SYSTEM, "Only System") translationBuilder.add(TranslationKeys.Gui.Config.Toasts.SHOW_NONE, "None") + // Gimbal Generic Settings + translationBuilder.add(TranslationKeys.Gui.Config.PLAYER_FLY_SPEED, "Fly Speed") + // Gimbal Generic Gui translationBuilder.add(TranslationKeys.Gui.Config.GENERIC_ENABLED, "Enabled") translationBuilder.add(TranslationKeys.Gui.Config.GENERIC_DISABLED, "Disabled") From 4c8404d30616583b2eef0c44f7aebadcf2f12b89 Mon Sep 17 00:00:00 2001 From: moonleay Date: Thu, 16 May 2024 03:52:34 +0200 Subject: [PATCH 19/24] refactor: combined Bulldozer and YouInjectButton mixin into one mixin each Signed-off-by: moonleay --- .../moonleay/gimbal/mixin/BulldozerMixin.java | 59 +++++++++---- .../gimbal/mixin/BulldozerMixin2.java | 52 ------------ .../gimbal/mixin/YouInjectButtonMixin.java | 85 +++++++++++++------ .../gimbal/mixin/YouInjectButtonMixin2.java | 66 -------------- src/main/resources/gimbal.mixins.json | 8 +- 5 files changed, 106 insertions(+), 164 deletions(-) delete mode 100644 src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin2.java delete mode 100644 src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java diff --git a/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin.java b/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin.java index a89604a..df682c2 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin.java @@ -20,9 +20,13 @@ package net.moonleay.gimbal.mixin; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.moonleay.gimbal.client.editor.ClientEditor; import net.moonleay.gimbal.editor.state.mode.Capability; import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -32,30 +36,49 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Objects; -@Mixin(MinecraftClient.class) public abstract class BulldozerMixin { - @Shadow protected int attackCooldown; + @Mixin(MinecraftClient.class) + public static abstract class MinecraftClientMixin { + @Shadow + @Nullable + public ClientPlayerEntity player; + @Shadow + protected int attackCooldown; - @Shadow - @Nullable - public ClientPlayerEntity player; - - @Inject(method = "doAttack", at = @At(value = "HEAD")) - private void func(CallbackInfoReturnable cir) { - if (!ClientEditor.INSTANCE.shouldClient(Capability.BULLDOZER) || !Objects.requireNonNull(this.player).isCreative()) { - return; + @Inject(method = "doAttack", at = @At(value = "HEAD")) + private void func(CallbackInfoReturnable cir) { + if (!ClientEditor.INSTANCE.shouldClient(Capability.BULLDOZER) || !Objects.requireNonNull(this.player).isCreative()) { + return; + } + this.attackCooldown = 0; + } + + @Inject(method = "handleBlockBreaking", at = @At(value = "HEAD")) + private void func2(boolean breaking, CallbackInfo ci) { + if (!ClientEditor.INSTANCE.shouldClient(Capability.BULLDOZER) || !breaking || !Objects.requireNonNull(this.player).isCreative()) { + return; + } + this.attackCooldown = 0; } - this.attackCooldown = 0; } - @Inject(method = "handleBlockBreaking", at = @At(value = "HEAD")) - private void func2(boolean breaking, CallbackInfo ci) { - if (!ClientEditor.INSTANCE.shouldClient(Capability.BULLDOZER) || !breaking || !Objects.requireNonNull(this.player).isCreative()) { - return; + @Mixin(ClientPlayerInteractionManager.class) + public static abstract class ClientPlayerInteractionManagerMixin { + + @Shadow + private int blockBreakingCooldown; + + @Shadow + @Final + private MinecraftClient client; + + @Inject(method = "updateBlockBreakingProgress", at = @At("HEAD")) + private void func(BlockPos pos, Direction direction, CallbackInfoReturnable cir) { + if (!ClientEditor.INSTANCE.shouldClient(Capability.BULLDOZER) || !Objects.requireNonNull(this.client.player).isCreative()) { + return; + } + this.blockBreakingCooldown = 0; } - this.attackCooldown = 0; } - - } diff --git a/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin2.java b/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin2.java deleted file mode 100644 index 19f1378..0000000 --- a/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin2.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Gimbal - * Copyright (C) 2024 moonleay - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.moonleay.gimbal.mixin; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.moonleay.gimbal.client.editor.ClientEditor; -import net.moonleay.gimbal.editor.state.mode.Capability; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Objects; - -@Mixin(ClientPlayerInteractionManager.class) -public class BulldozerMixin2 { - - @Shadow private int blockBreakingCooldown; - - @Shadow - @Final - private MinecraftClient client; - - @Inject(method = "updateBlockBreakingProgress", at = @At("HEAD")) - private void func(BlockPos pos, Direction direction, CallbackInfoReturnable cir) { - if (!ClientEditor.INSTANCE.shouldClient(Capability.BULLDOZER) || !Objects.requireNonNull(this.client.player).isCreative()) { - return; - } - this.blockBreakingCooldown = 0; - } -} diff --git a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java index f86f610..efa2a9c 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java @@ -20,6 +20,7 @@ package net.moonleay.gimbal.mixin; import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.widget.TexturedButtonWidget; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -33,35 +34,71 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(GameMenuScreen.class) // What is my purpose? -public class YouInjectButtonMixin extends Screen { +public class YouInjectButtonMixin { // Go my god. - @Unique - private static final Identifier GIMBAL_TEXTURE = new Identifier(BuildConstants.modId, "textures/gimbal_options_texture_button.png"); + @Mixin(TitleScreen.class) + public static abstract class TitleScreenMixin extends Screen { - protected YouInjectButtonMixin(Text title) { - super(title); + @Unique + private static final Identifier GIMBAL_TEXTURE = new Identifier(BuildConstants.modId, "textures/gimbal_options_texture_button.png"); + + protected TitleScreenMixin(Text title) { + super(title); + } + + @Inject(method = "init", at = @At(value = "RETURN")) + private void func(CallbackInfo ci) { + int l = this.height / 4 + 48; + this.addDrawableChild( + new TexturedButtonWidget( + this.width / 2 - 124 - 24, + l + 72 + 12, + 20, + 20, + 0, + 0, + 20, + GIMBAL_TEXTURE, + 20, + 40, + button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), + Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME) + ) + ); + } } - @Inject(method = "initWidgets", at = @At(value = "RETURN")) - private void func(CallbackInfo ci) { - this.addDrawableChild( - new TexturedButtonWidget( - this.width / 2 - 124, - this.height / 4 + 96 + -16, - 20, - 20, - 0, - 0, - 20, - GIMBAL_TEXTURE, - 20, - 40, - button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), - Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME) - ) - ); + + @Mixin(GameMenuScreen.class) + public static abstract class GameMenuScreenMixin extends Screen { + @Unique + private static final Identifier GIMBAL_TEXTURE = new Identifier(BuildConstants.modId, "textures/gimbal_options_texture_button.png"); + + protected GameMenuScreenMixin(Text title) { + super(title); + } + + @Inject(method = "initWidgets", at = @At(value = "RETURN")) + private void func(CallbackInfo ci) { + this.addDrawableChild( + new TexturedButtonWidget( + this.width / 2 - 124, + this.height / 4 + 96 + -16, + 20, + 20, + 0, + 0, + 20, + GIMBAL_TEXTURE, + 20, + 40, + button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), + Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME) + ) + ); + } } + } diff --git a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java deleted file mode 100644 index b25789d..0000000 --- a/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin2.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Gimbal - * Copyright (C) 2024 moonleay - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.moonleay.gimbal.mixin; - -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.gui.widget.TexturedButtonWidget; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.moonleay.gimbal.build.BuildConstants; -import net.moonleay.gimbal.client.ClientMain; -import net.moonleay.gimbal.client.screen.GimbalSettingsGui; -import net.moonleay.gimbal.constants.TranslationKeys; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(TitleScreen.class) -public class YouInjectButtonMixin2 extends Screen { - - @Unique - private static final Identifier GIMBAL_TEXTURE = new Identifier(BuildConstants.modId, "textures/gimbal_options_texture_button.png"); - - protected YouInjectButtonMixin2(Text title) { - super(title); - } - - @Inject(method = "init", at = @At(value = "RETURN")) - private void func(CallbackInfo ci) { - int l = this.height / 4 + 48; - this.addDrawableChild( - new TexturedButtonWidget( - this.width / 2 - 124 - 24, - l + 72 + 12, - 20, - 20, - 0, - 0, - 20, - GIMBAL_TEXTURE, - 20, - 40, - button -> this.client.setScreen(new GimbalSettingsGui(this, ClientMain.CONFIG)), - Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME) - ) - ); - } -} diff --git a/src/main/resources/gimbal.mixins.json b/src/main/resources/gimbal.mixins.json index 479b9ab..b383149 100644 --- a/src/main/resources/gimbal.mixins.json +++ b/src/main/resources/gimbal.mixins.json @@ -11,13 +11,13 @@ "ReplaceStateUpdaterMixin" ], "client": [ - "BulldozerMixin", - "BulldozerMixin2", + "BulldozerMixin$ClientPlayerInteractionManagerMixin", + "BulldozerMixin$MinecraftClientMixin", "HudMixin", "NoClipCameraFixMixin", "NormalModeMixin", - "YouInjectButtonMixin", - "YouInjectButtonMixin2" + "YouInjectButtonMixin$GameMenuScreenMixin", + "YouInjectButtonMixin$TitleScreenMixin" ], "injectors": { "defaultRequire": 1 From 6a89e5683f9e67e34a7d24892ca49f76e414572f Mon Sep 17 00:00:00 2001 From: moonleay Date: Thu, 16 May 2024 16:35:44 +0200 Subject: [PATCH 20/24] refactor: combined NoClip and ReplaceMode mixins into one mixin each Signed-off-by: moonleay --- .../gimbal/mixin/NoClipCameraFixMixin.java | 41 -------- .../moonleay/gimbal/mixin/NoClipMixin.java | 96 ++++++++++++------- .../gimbal/mixin/ReplaceModeMixin.java | 89 ++++++++++++----- .../mixin/ReplaceStateUpdaterMixin.java | 70 -------------- src/main/resources/gimbal.mixins.json | 8 +- 5 files changed, 127 insertions(+), 177 deletions(-) delete mode 100644 src/main/java/net/moonleay/gimbal/mixin/NoClipCameraFixMixin.java delete mode 100644 src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java diff --git a/src/main/java/net/moonleay/gimbal/mixin/NoClipCameraFixMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NoClipCameraFixMixin.java deleted file mode 100644 index 55a8882..0000000 --- a/src/main/java/net/moonleay/gimbal/mixin/NoClipCameraFixMixin.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Gimbal - * Copyright (C) 2024 moonleay - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.moonleay.gimbal.mixin; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.Camera; -import net.moonleay.gimbal.client.editor.ClientEditor; -import net.moonleay.gimbal.editor.state.mode.Capability; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(Camera.class) -public class NoClipCameraFixMixin { - - @Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true) - private void fixCameraInNoClip(double desiredCameraDistance, CallbackInfoReturnable cir) { - if (!ClientEditor.INSTANCE.shouldClient(Capability.NO_CLIP) || (!(MinecraftClient.getInstance().player != null && MinecraftClient.getInstance().player.isCreative()))) { - return; - } - cir.setReturnValue(desiredCameraDistance); - cir.cancel(); - } -} diff --git a/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java index fafab39..8e9a80a 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java @@ -19,12 +19,15 @@ package net.moonleay.gimbal.mixin; import com.mojang.authlib.GameProfile; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.Camera; import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerAbilities; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.World; +import net.moonleay.gimbal.client.editor.ClientEditor; import net.moonleay.gimbal.editor.ServerEditorManager; import net.moonleay.gimbal.editor.state.mode.Capability; import org.spongepowered.asm.mixin.Mixin; @@ -32,51 +35,72 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.UUID; -@Mixin(PlayerEntity.class) -public abstract class NoClipMixin extends LivingEntity { - @Shadow public abstract GameProfile getGameProfile(); +public abstract class NoClipMixin { - @Shadow public abstract PlayerAbilities getAbilities(); - - @Shadow - public abstract boolean isCreative(); - - protected NoClipMixin(EntityType entityType, World world) { - super(entityType, world); - } // Server side - - - @Inject(method = "tick", at = @At(value = "FIELD", - target = "Lnet/minecraft/entity/player/PlayerEntity;noClip:Z", shift = At.Shift.AFTER) - ) private void enoClip(CallbackInfo ci) { - if (!this.isCreative()) - return; - UUID uuid = this.getGameProfile().getId(); - - if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP)) { - return; // NoClip is not enabled + @Mixin(PlayerEntity.class) // Serverside, allows clipping + public static abstract class PlayerEntityMixin extends LivingEntity { + protected PlayerEntityMixin(EntityType entityType, World world) { + super(entityType, world); } - if (!this.getAbilities().flying) { - return; + + @Shadow + public abstract GameProfile getGameProfile(); + + @Shadow + public abstract PlayerAbilities getAbilities(); + + @Shadow + public abstract boolean isCreative(); + + @Inject(method = "tick", at = @At(value = "FIELD", + target = "Lnet/minecraft/entity/player/PlayerEntity;noClip:Z", shift = At.Shift.AFTER) + ) + private void enoClip(CallbackInfo ci) { + if (!this.isCreative()) + return; + UUID uuid = this.getGameProfile().getId(); + + if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP)) { + return; // NoClip is not enabled + } + if (!this.getAbilities().flying) { + return; + } + // Enable NoClip + this.noClip = true; + } + + @Inject(method = "updatePose", at = @At("HEAD")) + private void onUpdatePose(CallbackInfo ci) { + UUID uuid = this.getGameProfile().getId(); + + if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP)) + return; // NoClip is not enabled + if (!this.getAbilities().flying) + return; + + // Force standing pose in NoClip mode + + this.setPose(EntityPose.STANDING); } - // Enable NoClip - this.noClip = true; } - @Inject(method = "updatePose", at = @At("HEAD")) - private void onUpdatePose(CallbackInfo ci) { - UUID uuid = this.getGameProfile().getId(); - if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP)) - return; // NoClip is not enabled - if (!this.getAbilities().flying) - return; + @Mixin(Camera.class) // Clientside, fixes camera + public static abstract class CameraMixin { - // Force standing pose in NoClip mode - - this.setPose(EntityPose.STANDING); + @Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true) + private void fixCameraInNoClip(double desiredCameraDistance, CallbackInfoReturnable cir) { + if (!ClientEditor.INSTANCE.shouldClient(Capability.NO_CLIP) || (!(MinecraftClient.getInstance().player != null && MinecraftClient.getInstance().player.isCreative()))) { + return; + } + cir.setReturnValue(desiredCameraDistance); + cir.cancel(); + } } + } diff --git a/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java index 8e2a4fa..8a28216 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java @@ -18,50 +18,87 @@ package net.moonleay.gimbal.mixin; +import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemUsageContext; +import net.minecraft.item.*; +import net.minecraft.state.property.Property; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.moonleay.gimbal.editor.ServerEditorManager; import net.moonleay.gimbal.editor.state.mode.Capability; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.UUID; -@Mixin(ItemPlacementContext.class) -public abstract class ReplaceModeMixin extends ItemUsageContext { +public abstract class ReplaceModeMixin { - @Shadow - protected boolean canReplaceExisting; + @Mixin(ItemPlacementContext.class) + public static abstract class ItemPlacementContextMixin extends ItemUsageContext { + @Shadow + protected boolean canReplaceExisting; - @Mutable - @Shadow - @Final - private BlockPos placementPos; + @Mutable + @Shadow + @Final + private BlockPos placementPos; - public ReplaceModeMixin(PlayerEntity player, Hand hand, BlockHitResult hit) { - super(player, hand, hit); + public ItemPlacementContextMixin(PlayerEntity player, Hand hand, BlockHitResult hit) { + super(player, hand, hit); + } + + @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/hit/BlockHitResult;)V", at = @At(value = "RETURN")) + private void func(World world, PlayerEntity playerEntity, Hand hand, ItemStack itemStack, BlockHitResult blockHitResult, CallbackInfo ci) { + if (playerEntity == null) + return; + UUID id = playerEntity.getGameProfile().getId(); + if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE)) + return; + + this.canReplaceExisting = true; + this.placementPos = blockHitResult.getBlockPos(); + } } - @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/hit/BlockHitResult;)V", at = @At(value = "RETURN")) - private void func(World world, PlayerEntity playerEntity, Hand hand, ItemStack itemStack, BlockHitResult blockHitResult, CallbackInfo ci) { - if (playerEntity == null) - return; - UUID id = playerEntity.getGameProfile().getId(); - if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE)) - return; + @Mixin(BlockItem.class) + public static abstract class BlockItemMixin extends Item { - this.canReplaceExisting = true; - this.placementPos = blockHitResult.getBlockPos(); + public BlockItemMixin(Settings settings) { + super(settings); + } + + @Shadow + protected abstract boolean place(ItemPlacementContext context, BlockState state); + + @Redirect(method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BlockItem;place(Lnet/minecraft/item/ItemPlacementContext;Lnet/minecraft/block/BlockState;)Z")) + private boolean func(BlockItem instance, ItemPlacementContext context, BlockState state) { + if (context.getPlayer() == null) + return this.place(context, state); + UUID id = context.getPlayer().getGameProfile().getId(); + if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE)) + return this.place(context, state); + BlockState oldState = context.getWorld().getBlockState(context.getBlockPos()); + return this.place(context, getTargetBlockState(oldState, instance.getBlock().getDefaultState())); + } + + @Unique + public BlockState getTargetBlockState(BlockState oldState, BlockState newBlock) { + var oldManager = oldState.getBlock().getStateManager(); + var newManager = newBlock.getBlock().getStateManager(); + for (var prop : oldManager.getProperties()) { + var matchingProp = newManager.getProperty(prop.getName()); + if (matchingProp != null) { + //noinspection rawtypes,unchecked + newBlock = newBlock.with((Property) matchingProp, oldState.get(matchingProp)); + } + } + return newBlock; + } } + } diff --git a/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java deleted file mode 100644 index 255604a..0000000 --- a/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Gimbal - * Copyright (C) 2024 moonleay - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.moonleay.gimbal.mixin; - -import net.minecraft.block.BlockState; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.state.property.Property; -import net.moonleay.gimbal.editor.ServerEditorManager; -import net.moonleay.gimbal.editor.state.mode.Capability; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.util.UUID; - -@Mixin(BlockItem.class) -public abstract class ReplaceStateUpdaterMixin extends Item { - - public ReplaceStateUpdaterMixin(Settings settings) { - super(settings); - } - - @Shadow - protected abstract boolean place(ItemPlacementContext context, BlockState state); - - @Redirect(method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BlockItem;place(Lnet/minecraft/item/ItemPlacementContext;Lnet/minecraft/block/BlockState;)Z")) - private boolean func(BlockItem instance, ItemPlacementContext context, BlockState state) { - if (context.getPlayer() == null) - return this.place(context, state); - UUID id = context.getPlayer().getGameProfile().getId(); - if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE)) - return this.place(context, state); - BlockState oldState = context.getWorld().getBlockState(context.getBlockPos()); - return this.place(context, getTargetBlockState(oldState, instance.getBlock().getDefaultState())); - } - - @Unique - public BlockState getTargetBlockState(BlockState oldState, BlockState newBlock) { - var oldManager = oldState.getBlock().getStateManager(); - var newManager = newBlock.getBlock().getStateManager(); - for (var prop : oldManager.getProperties()) { - var matchingProp = newManager.getProperty(prop.getName()); - if (matchingProp != null) { - //noinspection rawtypes,unchecked - newBlock = newBlock.with((Property) matchingProp, oldState.get(matchingProp)); - } - } - return newBlock; - } -} diff --git a/src/main/resources/gimbal.mixins.json b/src/main/resources/gimbal.mixins.json index b383149..0babedd 100644 --- a/src/main/resources/gimbal.mixins.json +++ b/src/main/resources/gimbal.mixins.json @@ -6,15 +6,15 @@ "mixins": [ "ForcePlaceMixin", "NoBlockUpdatesMixin", - "NoClipMixin", - "ReplaceModeMixin", - "ReplaceStateUpdaterMixin" + "NoClipMixin$PlayerEntityMixin", + "ReplaceModeMixin$BlockItemMixin", + "ReplaceModeMixin$ItemPlacementContextMixin" ], "client": [ "BulldozerMixin$ClientPlayerInteractionManagerMixin", "BulldozerMixin$MinecraftClientMixin", "HudMixin", - "NoClipCameraFixMixin", + "NoClipMixin$CameraMixin", "NormalModeMixin", "YouInjectButtonMixin$GameMenuScreenMixin", "YouInjectButtonMixin$TitleScreenMixin" From 42737446b2897a8920148ac3ba4c137572166a91 Mon Sep 17 00:00:00 2001 From: moonleay Date: Fri, 17 May 2024 01:10:54 +0200 Subject: [PATCH 21/24] feat: added player fly speed controls Signed-off-by: moonleay --- .../client/config/GimbalClientConfig.kt | 2 +- .../gimbal/client/config/ScaledRes.kt | 4 +- .../gimbal/client/screen/GimbalSettingsGui.kt | 12 +++-- .../screen/widgets/GimbalSliderWidget.kt | 4 +- .../moonleay/gimbal/client/util/NumberUtil.kt | 15 +++++-- .../gimbal/mixin/PlayerFlySpeedMixin.java | 45 +++++++++++++++++++ src/main/resources/gimbal.mixins.json | 1 + 7 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 src/main/java/net/moonleay/gimbal/mixin/PlayerFlySpeedMixin.java diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt index 199908a..8cd6fd9 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt @@ -25,5 +25,5 @@ import net.moonleay.gimbal.client.config.enums.ToastSettings data class GimbalClientConfig( val guiSettings: GimbalGuiSettings = GimbalGuiSettings(), val toastSettings: ToastSettings = ToastSettings.ALL, - val playerFlySpeed: Int = 0, + val playerFlySpeed: Int = 100, ) diff --git a/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt b/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt index acf9a70..40d04aa 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt @@ -22,6 +22,6 @@ import kotlinx.serialization.Serializable @Serializable data class ScaledRes( - val scaledX: Double, - val scaledY: Double, + val scaledX: Double, // offsetX + val scaledY: Double, // offsetY ) diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt index c7d33e0..8e23ee9 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -185,11 +185,15 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi 150, 20, Text.translatable(TranslationKeys.Gui.Config.PLAYER_FLY_SPEED), - NumberUtil.interpolate(this.playerFlySpeed.toDouble(), 50.0, 500.0, 0.0, 1.0), - 50.0, - 500.0, + NumberUtil.linearInterpolate(this.playerFlySpeed.toDouble(), 100.0, 1000.0, 0.0, 1.0), + 100.0, + 1000.0, ) { value -> - this.playerFlySpeed = NumberUtil.interpolate(value, 0.0, 1.0, 50.0, 500.0).toInt() + this.playerFlySpeed = NumberUtil.linearInterpolate(value, 0.0, 1.0, 100.0, 1000.0).toInt() + + if (client!!.player != null && client!!.player!!.isCreative) { + client!!.player!!.abilities.flySpeed = (this.playerFlySpeed / 100) * 0.05f + } val oldConfig = cfg.config val newConfig = GimbalClientConfig( diff --git a/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt b/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt index c6d2038..c244615 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt @@ -36,12 +36,12 @@ class GimbalSliderWidget( SliderWidget(x, y, width, height, text, value) { init { this.message = this.text.copy() - .append(": " + (NumberUtil.interpolate(this.value, 0.0, 1.0, this.lowerEnd, this.upperEnd).toInt())) + .append(": " + (NumberUtil.linearInterpolate(this.value, 0.0, 1.0, this.lowerEnd, this.upperEnd).toInt())) } override fun updateMessage() { this.message = this.text.copy() - .append(": " + (NumberUtil.interpolate(this.value, 0.0, 1.0, this.lowerEnd, this.upperEnd).toInt())) + .append(": " + (NumberUtil.linearInterpolate(this.value, 0.0, 1.0, this.lowerEnd, this.upperEnd).toInt())) } override fun applyValue() { diff --git a/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt index 5bdb3f3..e335842 100644 --- a/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt +++ b/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt @@ -21,17 +21,24 @@ package net.moonleay.gimbal.client.util object NumberUtil { /** - * Interpolate a Position between two numbers + * Interpolate a number between two numbers in a linear way */ - fun interpolate(number: Double, min: Double, max: Double, lowerEnd: Double, upperEnd: Double): Double { - val toAddToMin = (0 - min) * -1 + fun linearInterpolate(number: Double, min: Double, max: Double, lowerEnd: Double, upperEnd: Double): Double { + val subtractFromNr = (0 - min) * -1 val minMaxDiff = max - min val onePercent = minMaxDiff / 100.0 - val percentOfNumber = (number - toAddToMin) / onePercent + val percentOfNumber = (number - subtractFromNr) / onePercent val toAddToLowerEnd = (0 - lowerEnd) * -1 val upperLowerDiff = upperEnd - lowerEnd val onePercentOfEnd = upperLowerDiff / 100.0 return (percentOfNumber * onePercentOfEnd) + toAddToLowerEnd } + + /** + * Interpolate a number between two numbers in a logarithmic way + */ + fun logarithmicInterpolate(number: Double, min: Double, max: Double, lowerEnd: Double, upperEnd: Double): Double { + TODO("Not impl.") + } } diff --git a/src/main/java/net/moonleay/gimbal/mixin/PlayerFlySpeedMixin.java b/src/main/java/net/moonleay/gimbal/mixin/PlayerFlySpeedMixin.java new file mode 100644 index 0000000..e846c91 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/PlayerFlySpeedMixin.java @@ -0,0 +1,45 @@ +/* + * Gimbal + * Copyright (C) 2024 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.gimbal.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.PlayerAbilitiesS2CPacket; +import net.moonleay.gimbal.client.ClientMain; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class PlayerFlySpeedMixin { + + @Shadow + @Final + private MinecraftClient client; + + @Inject(method = "onPlayerAbilities", at = @At(value = "RETURN")) + private void func(PlayerAbilitiesS2CPacket packet, CallbackInfo ci) { + this.client.player.getAbilities().setFlySpeed((ClientMain.CONFIG.getConfig().getPlayerFlySpeed() / 100) * 0.05f); + //client!!.player!!.abilities.flySpeed = (this.playerFlySpeed / 100) * 0.05f + } + +} diff --git a/src/main/resources/gimbal.mixins.json b/src/main/resources/gimbal.mixins.json index 0babedd..9de8288 100644 --- a/src/main/resources/gimbal.mixins.json +++ b/src/main/resources/gimbal.mixins.json @@ -16,6 +16,7 @@ "HudMixin", "NoClipMixin$CameraMixin", "NormalModeMixin", + "PlayerFlySpeedMixin", "YouInjectButtonMixin$GameMenuScreenMixin", "YouInjectButtonMixin$TitleScreenMixin" ], From 5252d9abdf72b1278751f90a78930c9687126370 Mon Sep 17 00:00:00 2001 From: moonleay Date: Thu, 13 Jun 2024 18:20:18 +0200 Subject: [PATCH 22/24] feat: changed server side state log to debug --- src/main/java/net/moonleay/gimbal/editor/ServerEditorManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/moonleay/gimbal/editor/ServerEditorManager.kt b/src/main/java/net/moonleay/gimbal/editor/ServerEditorManager.kt index 5bb3f96..c0a1801 100644 --- a/src/main/java/net/moonleay/gimbal/editor/ServerEditorManager.kt +++ b/src/main/java/net/moonleay/gimbal/editor/ServerEditorManager.kt @@ -32,7 +32,7 @@ object ServerEditorManager { fun updateEditorState(playerUUID: UUID, editorState: EditorState) { STATEMAP[playerUUID] = editorState - LOGGER.info("$playerUUID: ${editorState.editorMode} with ${editorState.editorModifier}") + LOGGER.debug("{}: {} with {}", playerUUID, editorState.editorMode, editorState.editorModifier) } From d59cf8f9f0f12ec8c87a8607484d42810266ef26 Mon Sep 17 00:00:00 2001 From: moonleay Date: Thu, 13 Jun 2024 18:39:27 +0200 Subject: [PATCH 23/24] feat: add default mode setting --- .../net/moonleay/gimbal/client/ClientMain.kt | 3 ++ .../client/config/ClientConfigHolder.kt | 2 + .../client/config/GimbalClientConfig.kt | 2 + .../gimbal/client/editor/ClientEditor.kt | 11 +++- .../gimbal/client/screen/GimbalEditHudGui.kt | 3 +- .../gimbal/client/screen/GimbalSettingsGui.kt | 50 +++++++++++++++++-- .../gimbal/constants/TranslationKeys.kt | 1 + .../moonleay/gimbal/datagen/DataGenerator.kt | 2 +- ...ageProvider.kt => EnUsLanguageProvider.kt} | 3 +- .../moonleay/gimbal/editor/state/mode/Mode.kt | 13 ++--- .../gimbal/mixin/NormalModeMixin.java | 6 +-- 11 files changed, 78 insertions(+), 18 deletions(-) rename src/main/java/net/moonleay/gimbal/datagen/{En_us_GimbalLanguageProvider.kt => EnUsLanguageProvider.kt} (96%) diff --git a/src/main/java/net/moonleay/gimbal/client/ClientMain.kt b/src/main/java/net/moonleay/gimbal/client/ClientMain.kt index 2af8b59..d3f1823 100644 --- a/src/main/java/net/moonleay/gimbal/client/ClientMain.kt +++ b/src/main/java/net/moonleay/gimbal/client/ClientMain.kt @@ -46,6 +46,9 @@ internal object ClientMain : ClientModInitializer { val gimbalConfigPath = FabricLoader.getInstance().configDir.resolve(BuildConstants.modId + "/client.json") CONFIG = ClientConfigHolder(gimbalConfigPath) LOGGER.info("Config has been loaded.") + LOGGER.info("Applying Config to client.") + ClientEditor.applyConfig(CONFIG.config) + LOGGER.info("Config has been applied.") LOGGER.info("Gimbal has been initialized on the client side.") } diff --git a/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt index 0b7769e..4ad504d 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt @@ -22,6 +22,7 @@ import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromStream import kotlinx.serialization.json.encodeToStream +import net.moonleay.gimbal.client.editor.ClientEditor import java.nio.file.Path import kotlin.io.path.* @@ -36,6 +37,7 @@ class ClientConfigHolder(private val path: Path) { fun updateConfig(new: GimbalClientConfig) { this.config = new this.save(config) + ClientEditor.applyConfig(config) } @OptIn(ExperimentalSerializationApi::class) diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt index 8cd6fd9..f84b5f3 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt @@ -20,10 +20,12 @@ package net.moonleay.gimbal.client.config import kotlinx.serialization.Serializable import net.moonleay.gimbal.client.config.enums.ToastSettings +import net.moonleay.gimbal.editor.state.mode.Mode @Serializable data class GimbalClientConfig( val guiSettings: GimbalGuiSettings = GimbalGuiSettings(), val toastSettings: ToastSettings = ToastSettings.ALL, val playerFlySpeed: Int = 100, + val defaultMode: Mode = Mode.NORMAL ) diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index 303996f..00c908e 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -40,7 +40,7 @@ import org.apache.logging.log4j.LogManager object ClientEditor { private var POLICY = GimbalPolicyType.NOT_PRESENT - private var CURRENT_MODE = Mode.NORMAL + private lateinit var CURRENT_MODE: Mode private var TEMP_DISABLED_MODE = Mode.UNKNOWN private val CURRENT_MODE_MODIFIER = mutableListOf() @@ -50,6 +50,13 @@ object ClientEditor { private val LOGGER = LogManager.getLogger(BuildConstants.modName) + fun applyConfig(config: GimbalClientConfig, isBoot: Boolean = true) { + if (isBoot) { + this.CURRENT_MODE = config.defaultMode + return + } + this.setMode(config.defaultMode) + } fun onConnectedToNewWorld() { POLICY = GimbalPolicyType.NOT_PRESENT @@ -106,7 +113,7 @@ object ClientEditor { } fun isInNonDefaultMode(): Boolean { - return CURRENT_MODE != Mode.NORMAL + return CURRENT_MODE != ClientMain.CONFIG.config.defaultMode } /* diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt index c0ec0be..3e84af2 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -87,7 +87,8 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig hudOptions = oldConf.guiSettings.hudOptions ), toastSettings = oldConf.toastSettings, - playerFlySpeed = oldConf.playerFlySpeed + playerFlySpeed = oldConf.playerFlySpeed, + defaultMode = oldConf.defaultMode ) cfg.updateConfig(newConf) diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt index 8e23ee9..f5e169f 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -32,6 +32,7 @@ import net.moonleay.gimbal.client.config.enums.ToastSettings import net.moonleay.gimbal.client.screen.widgets.GimbalSliderWidget import net.moonleay.gimbal.client.util.NumberUtil import net.moonleay.gimbal.constants.TranslationKeys +import net.moonleay.gimbal.editor.state.mode.Mode class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfigHolder) : Screen(Text.translatable(TranslationKeys.Gui.Config.SCREEN_NAME)) { @@ -39,11 +40,13 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi private var hudOptions: HudOptions private var toastSettings: ToastSettings private var playerFlySpeed: Int + private var defaultMode: Mode init { this.hudOptions = cfg.config.guiSettings.hudOptions this.toastSettings = cfg.config.toastSettings this.playerFlySpeed = cfg.config.playerFlySpeed + this.defaultMode = cfg.config.defaultMode } override fun init() { @@ -70,7 +73,8 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi val newConf = GimbalClientConfig( guiSettings = newGui, toastSettings = cfg.config.toastSettings, - playerFlySpeed = cfg.config.playerFlySpeed + playerFlySpeed = cfg.config.playerFlySpeed, + defaultMode = cfg.config.defaultMode ) cfg.updateConfig(newConf) }) @@ -129,7 +133,8 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi hudOptions = this.hudOptions ), toastSettings = oldConfig.toastSettings, - playerFlySpeed = oldConfig.playerFlySpeed + playerFlySpeed = oldConfig.playerFlySpeed, + defaultMode = oldConfig.defaultMode ) cfg.updateConfig(newConfig) } @@ -173,7 +178,8 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi val newConfig = GimbalClientConfig( guiSettings = oldConfig.guiSettings, toastSettings = this.toastSettings, - playerFlySpeed = oldConfig.playerFlySpeed + playerFlySpeed = oldConfig.playerFlySpeed, + defaultMode = oldConfig.defaultMode ) cfg.updateConfig(newConfig) } @@ -199,11 +205,47 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi val newConfig = GimbalClientConfig( guiSettings = oldConfig.guiSettings, toastSettings = this.toastSettings, - playerFlySpeed = this.playerFlySpeed + playerFlySpeed = this.playerFlySpeed, + defaultMode = oldConfig.defaultMode ) cfg.updateConfig(newConfig) }) + this.addDrawableChild>( + CyclingButtonWidget.builder { value: Mode? -> + if (value == null) { + return@builder Text.literal(Mode.UNKNOWN.displayName) + } + return@builder Text.literal(value.displayName) + } + .values(Mode.entries) + .initially(this.defaultMode) + .build( + this.width / 2 - 155 + 160, + this.height / 6 + 24 * 2, + 150, + 20, + Text.translatable(TranslationKeys.Gui.Config.DEFAULT_MODE) + ) { b: CyclingButtonWidget?, requestedMode: Mode -> + if (requestedMode.hidden){ + b!!.value = Mode.NORMAL + this.defaultMode = Mode.NORMAL + } + else { + this.defaultMode = requestedMode + } + + val oldConfig = cfg.config + val newConfig = GimbalClientConfig( + guiSettings = oldConfig.guiSettings, + toastSettings = oldConfig.toastSettings, + playerFlySpeed = oldConfig.playerFlySpeed, + defaultMode = this.defaultMode + ) + cfg.updateConfig(newConfig) + } + ) + // Done button this.addDrawableChild(ButtonWidget( this.width / 2 - 100, this.height / 6 + 168, 200, 20, ScreenTexts.DONE diff --git a/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt index d820f70..5aab860 100644 --- a/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt +++ b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt @@ -32,6 +32,7 @@ object TranslationKeys { const val GENERIC_DISABLED = "${BASE}disabled" const val PLAYER_FLY_SPEED = "${BASE}flySpeed" + const val DEFAULT_MODE = "${BASE}defaultMode" object Hud { const val BASE = "${TranslationKeys.Gui.Config.BASE}hud." diff --git a/src/main/java/net/moonleay/gimbal/datagen/DataGenerator.kt b/src/main/java/net/moonleay/gimbal/datagen/DataGenerator.kt index b328d97..bd2452e 100644 --- a/src/main/java/net/moonleay/gimbal/datagen/DataGenerator.kt +++ b/src/main/java/net/moonleay/gimbal/datagen/DataGenerator.kt @@ -28,6 +28,6 @@ internal class DataGenerator : DataGeneratorEntrypoint { override fun onInitializeDataGenerator(fabricDataGenerator: FabricDataGenerator) { LOGGER.info("Starting Data Generation") - fabricDataGenerator.addProvider(En_us_GimbalLanguageProvider(fabricDataGenerator)) + fabricDataGenerator.addProvider(EnUsLanguageProvider(fabricDataGenerator)) } } diff --git a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt b/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt similarity index 96% rename from src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt rename to src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt index 3251f74..2dc5d6b 100644 --- a/src/main/java/net/moonleay/gimbal/datagen/En_us_GimbalLanguageProvider.kt +++ b/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt @@ -22,7 +22,7 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator import net.fabricmc.fabric.api.datagen.v1.provider.FabricLanguageProvider import net.moonleay.gimbal.constants.TranslationKeys -class En_us_GimbalLanguageProvider(dataGenerator: FabricDataGenerator?) : +class EnUsLanguageProvider(dataGenerator: FabricDataGenerator?) : FabricLanguageProvider(dataGenerator, "en_us") { override fun generateTranslations(translationBuilder: TranslationBuilder?) { @@ -56,6 +56,7 @@ class En_us_GimbalLanguageProvider(dataGenerator: FabricDataGenerator?) : // Gimbal Generic Settings translationBuilder.add(TranslationKeys.Gui.Config.PLAYER_FLY_SPEED, "Fly Speed") + translationBuilder.add(TranslationKeys.Gui.Config.DEFAULT_MODE, "Default Mode") // Gimbal Generic Gui translationBuilder.add(TranslationKeys.Gui.Config.GENERIC_ENABLED, "Enabled") diff --git a/src/main/java/net/moonleay/gimbal/editor/state/mode/Mode.kt b/src/main/java/net/moonleay/gimbal/editor/state/mode/Mode.kt index 157cfa3..5481b22 100644 --- a/src/main/java/net/moonleay/gimbal/editor/state/mode/Mode.kt +++ b/src/main/java/net/moonleay/gimbal/editor/state/mode/Mode.kt @@ -18,10 +18,11 @@ package net.moonleay.gimbal.editor.state.mode -enum class Mode(val displayName: String, val color: Int, val incompatibleModifiers: List){ - UNKNOWN("UNKNOWN", 0x000000, listOf()), // Unknown mode. This mode cannot be entered - NORMAL("NORMAL", 0x90a959, listOf(ModeModifier.NO_UPDATES, ModeModifier.BULLDOZER, ModeModifier.FORCE_PLACE)), // Do nothing - INSERT("INSERT", 0xf4bf75, listOf()), // Place and break blocks - REPLACE("REPLACE", 0xac4242, listOf(ModeModifier.NO_UPDATES)), // Replace blocks - VISUAL("VISUAL", 0x6a9fb5, listOf(ModeModifier.BULLDOZER)), // Do fancy stuff with WE +enum class Mode(val displayName: String, val color: Int, val hidden: Boolean, val incompatibleModifiers: List){ + UNKNOWN("UNKNOWN", 0x000000, true, listOf()), // Unknown mode. This mode cannot be entered + NORMAL("NORMAL", 0x90a959, false, listOf(ModeModifier.NO_UPDATES, ModeModifier.BULLDOZER, ModeModifier.FORCE_PLACE)), // Do nothing + INSERT("INSERT", 0xf4bf75, false, listOf()), // Place and break blocks + REPLACE("REPLACE", 0xac4242, false, listOf(ModeModifier.NO_UPDATES)), // Replace blocks + // Add hidden modes after this comment + VISUAL("VISUAL", 0x6a9fb5, true, listOf(ModeModifier.BULLDOZER)), // Do fancy stuff with WE } diff --git a/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java index 7dc6232..023efa8 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java @@ -21,9 +21,9 @@ package net.moonleay.gimbal.mixin; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.option.GameOptions; +import net.moonleay.gimbal.client.ClientMain; import net.moonleay.gimbal.client.editor.ClientEditor; import net.moonleay.gimbal.editor.state.mode.Capability; -import net.moonleay.gimbal.editor.state.mode.Mode; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -43,12 +43,12 @@ public class NormalModeMixin { public ClientPlayerEntity player; @Inject(method = "openPauseMenu", at = @At("HEAD"), cancellable = true) - private void setNormalMode(boolean pause, CallbackInfo ci) { + private void setDefaultMode(boolean pause, CallbackInfo ci) { if (ClientEditor.INSTANCE.isInNonDefaultMode() && ClientEditor.INSTANCE.isAllowed()) { assert this.player != null; if (this.player.isCreative()) { // Set the editor mode to normal - ClientEditor.INSTANCE.setMode(Mode.NORMAL); + ClientEditor.INSTANCE.setMode(ClientMain.CONFIG.getConfig().getDefaultMode()); ci.cancel(); } } From dc732cc39f6ba362c87c17aebeb9eacb4c7eab02 Mon Sep 17 00:00:00 2001 From: moonleay Date: Thu, 13 Jun 2024 18:52:04 +0200 Subject: [PATCH 24/24] feat: add ESC resets mode setting --- .../client/config/GimbalClientConfig.kt | 1 + .../gimbal/client/editor/ClientEditor.kt | 4 ++- .../gimbal/client/screen/GimbalEditHudGui.kt | 1 + .../gimbal/client/screen/GimbalSettingsGui.kt | 28 ++++++++++++++++++- .../gimbal/constants/TranslationKeys.kt | 1 + .../gimbal/datagen/EnUsLanguageProvider.kt | 1 + .../gimbal/mixin/NormalModeMixin.java | 2 +- 7 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt index f84b5f3..5fd641c 100644 --- a/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.kt @@ -27,5 +27,6 @@ data class GimbalClientConfig( val guiSettings: GimbalGuiSettings = GimbalGuiSettings(), val toastSettings: ToastSettings = ToastSettings.ALL, val playerFlySpeed: Int = 100, + val shouldEscResetMode: Boolean = true, val defaultMode: Mode = Mode.NORMAL ) diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt index 00c908e..42d54c4 100644 --- a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -55,7 +55,9 @@ object ClientEditor { this.CURRENT_MODE = config.defaultMode return } - this.setMode(config.defaultMode) + if (!config.shouldEscResetMode) return + this.CURRENT_MODE = config.defaultMode + onUpdated() } fun onConnectedToNewWorld() { diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt index 3e84af2..0155e35 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -88,6 +88,7 @@ class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfig ), toastSettings = oldConf.toastSettings, playerFlySpeed = oldConf.playerFlySpeed, + shouldEscResetMode = oldConf.shouldEscResetMode, defaultMode = oldConf.defaultMode ) diff --git a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt index f5e169f..4e11df4 100644 --- a/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -74,6 +74,7 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi guiSettings = newGui, toastSettings = cfg.config.toastSettings, playerFlySpeed = cfg.config.playerFlySpeed, + shouldEscResetMode = cfg.config.shouldEscResetMode, defaultMode = cfg.config.defaultMode ) cfg.updateConfig(newConf) @@ -134,6 +135,7 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi ), toastSettings = oldConfig.toastSettings, playerFlySpeed = oldConfig.playerFlySpeed, + shouldEscResetMode = oldConfig.shouldEscResetMode, defaultMode = oldConfig.defaultMode ) cfg.updateConfig(newConfig) @@ -179,6 +181,7 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi guiSettings = oldConfig.guiSettings, toastSettings = this.toastSettings, playerFlySpeed = oldConfig.playerFlySpeed, + shouldEscResetMode = oldConfig.shouldEscResetMode, defaultMode = oldConfig.defaultMode ) cfg.updateConfig(newConfig) @@ -206,11 +209,33 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi guiSettings = oldConfig.guiSettings, toastSettings = this.toastSettings, playerFlySpeed = this.playerFlySpeed, + shouldEscResetMode = oldConfig.shouldEscResetMode, defaultMode = oldConfig.defaultMode ) cfg.updateConfig(newConfig) }) + this.addDrawableChild(CyclingButtonWidget.onOffBuilder() + .initially(cfg.config.shouldEscResetMode) + .build( + this.width / 2 - 155, + this.height / 6 + 24 * 3, + 150, + 20, + Text.translatable(TranslationKeys.Gui.Config.SHOULD_ESC_RESET_MODE) + ) { _: CyclingButtonWidget?, isEnabled: Boolean? -> + val newConf = GimbalClientConfig( + guiSettings = cfg.config.guiSettings, + toastSettings = cfg.config.toastSettings, + playerFlySpeed = cfg.config.playerFlySpeed, + shouldEscResetMode = isEnabled?: true, + defaultMode = cfg.config.defaultMode + ) + cfg.updateConfig(newConf) + }) + + + this.addDrawableChild>( CyclingButtonWidget.builder { value: Mode? -> if (value == null) { @@ -222,7 +247,7 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi .initially(this.defaultMode) .build( this.width / 2 - 155 + 160, - this.height / 6 + 24 * 2, + this.height / 6 + 24 * 3, 150, 20, Text.translatable(TranslationKeys.Gui.Config.DEFAULT_MODE) @@ -240,6 +265,7 @@ class GimbalSettingsGui(private val parent: Screen, private val cfg: ClientConfi guiSettings = oldConfig.guiSettings, toastSettings = oldConfig.toastSettings, playerFlySpeed = oldConfig.playerFlySpeed, + shouldEscResetMode = oldConfig.shouldEscResetMode, defaultMode = this.defaultMode ) cfg.updateConfig(newConfig) diff --git a/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt index 5aab860..0db8509 100644 --- a/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt +++ b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt @@ -32,6 +32,7 @@ object TranslationKeys { const val GENERIC_DISABLED = "${BASE}disabled" const val PLAYER_FLY_SPEED = "${BASE}flySpeed" + const val SHOULD_ESC_RESET_MODE = "${BASE}shouldESCResetMode" const val DEFAULT_MODE = "${BASE}defaultMode" object Hud { diff --git a/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt b/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt index 2dc5d6b..00279a1 100644 --- a/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt +++ b/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt @@ -56,6 +56,7 @@ class EnUsLanguageProvider(dataGenerator: FabricDataGenerator?) : // Gimbal Generic Settings translationBuilder.add(TranslationKeys.Gui.Config.PLAYER_FLY_SPEED, "Fly Speed") + translationBuilder.add(TranslationKeys.Gui.Config.SHOULD_ESC_RESET_MODE, "ESC Resets Mode") translationBuilder.add(TranslationKeys.Gui.Config.DEFAULT_MODE, "Default Mode") // Gimbal Generic Gui diff --git a/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java index 023efa8..d8f769a 100644 --- a/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java @@ -44,7 +44,7 @@ public class NormalModeMixin { @Inject(method = "openPauseMenu", at = @At("HEAD"), cancellable = true) private void setDefaultMode(boolean pause, CallbackInfo ci) { - if (ClientEditor.INSTANCE.isInNonDefaultMode() && ClientEditor.INSTANCE.isAllowed()) { + if (ClientMain.CONFIG.getConfig().getShouldEscResetMode() && ClientEditor.INSTANCE.isInNonDefaultMode() && ClientEditor.INSTANCE.isAllowed()) { assert this.player != null; if (this.player.isCreative()) { // Set the editor mode to normal