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/LICENSE b/LICENSE index 782b415..353ae17 100644 --- a/LICENSE +++ b/LICENSE @@ -631,7 +631,7 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - Gimble + Gimbal Copyright (C) 2024 moonleay This program is free software: you can redistribute it and/or modify @@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - Gimble Copyright (C) 2024 moonleay + Gimbal Copyright (C) 2024 moonleay This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/README.md b/README.md index 2d8dd06..71c794c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,21 @@ -# The Gimble project +# The Gimbal project This project aims to improve the experience of creating structures in Minecraft. +# Links + + + Join the Discord + + + Read the wiki + + + Clone the source code + + + Report a problem + + ## Features - **Modes** Use different modes to edit structures. Think Vim for Minecraft. [x] - **Modifier** Use modifiers to change the behavior of the modes and your building experience. [x] diff --git a/build.gradle.kts b/build.gradle.kts index b121bc2..efb5c4d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,21 @@ +/* + * 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 . + */ + import org.jetbrains.gradle.ext.ProjectSettings import org.jetbrains.gradle.ext.TaskTriggersConfig import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -9,13 +27,23 @@ 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.1.0-dev" //""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 +/* +* Gimbal version stuff +* */ + +val gimbalProtocolVersion = 3 + + val mavenGroup: String by project val mavenArtifact: String by project @@ -32,6 +60,9 @@ group = mavenGroup project.base.archivesName.set(mavenArtifact) repositories { + maven { // Dependency api + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } } fabricApi { @@ -48,6 +79,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 @@ -58,6 +93,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, @@ -151,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" } } } @@ -170,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/gradle.properties b/gradle.properties index 1fae464..aa5c709 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,36 @@ +# +# 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 . +# + #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 idea-ext.version=1.1.6 org.gradle.jvmargs=-Xmx2G -modId=gimble +modId=gimbal kotlinx.serialization.version=1.6.2 fabric.kotlin.version=1.10.18+kotlin.1.9.22 mavenGroup=net.moonleay kotlin.code.style=official minecraft.version=1.19.2 -modName=Gimble +modName=Gimbal #fabric.loader.version=0.15.10 -mavenArtifact=gimble +mavenArtifact=gimbal fabric.loader.version=0.14.0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e09..ea3fa1d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +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 . +# + 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/gradlew b/gradlew index 1aa94a4..1e55349 100755 --- a/gradlew +++ b/gradlew @@ -1,19 +1,21 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Gimbal +# Copyright (C) 2024 moonleay # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# 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. # -# https://www.apache.org/licenses/LICENSE-2.0 +# 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. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # ############################################################################## diff --git a/settings.gradle.kts b/settings.gradle.kts index 487fa1f..1a3e400 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,21 @@ +/* + * 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 . + */ + pluginManagement { repositories { maven { diff --git a/src/main/java/net/moonleay/gimbal/Main.kt b/src/main/java/net/moonleay/gimbal/Main.kt new file mode 100644 index 0000000..903d100 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/Main.kt @@ -0,0 +1,43 @@ +/* + * 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 + +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 + +internal object Main : ModInitializer { + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + + override fun onInitialize() { + LOGGER.info("Initializing Gimbal on the common side...") + 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 new file mode 100644 index 0000000..d3f1823 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/ClientMain.kt @@ -0,0 +1,67 @@ +/* + * 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 + +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 +import net.moonleay.gimbal.networking.GimbalClient +import org.apache.logging.log4j.LogManager + +internal object ClientMain : ClientModInitializer { + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + lateinit var CONFIG: ClientConfigHolder + + + override fun onInitializeClient() { + LOGGER.info("Initializing Gimbal on the client side...") + KeybindingRegistrar.registerKeybindings() + this.registerEvents() + 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("Applying Config to client.") + ClientEditor.applyConfig(CONFIG.config) + LOGGER.info("Config has been applied.") + LOGGER.info("Gimbal has been initialized on the client side.") + } + + private fun registerEvents() { + LOGGER.info("Registering client events...") + 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/config/ClientConfigHolder.kt b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt new file mode 100644 index 0000000..4ad504d --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/ClientConfigHolder.kt @@ -0,0 +1,79 @@ +/* + * 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 net.moonleay.gimbal.client.editor.ClientEditor +import java.nio.file.Path +import kotlin.io.path.* + +class ClientConfigHolder(private val path: Path) { + var config: GimbalClientConfig + private set + + init { + this.config = load() + } + + fun updateConfig(new: GimbalClientConfig) { + this.config = new + this.save(config) + ClientEditor.applyConfig(config) + } + + @OptIn(ExperimentalSerializationApi::class) + fun load(): GimbalClientConfig { + if (!path.isReadable()) + save(GimbalClientConfig()) + val iStream = path.inputStream() + val gimbalClientConfig: GimbalClientConfig = iStream.use { + Json { + ignoreUnknownKeys = true + }.decodeFromStream(it) + } + iStream.close() + return gimbalClientConfig + } + + @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()) { + throw Exception("Path (${path.pathString}) exists, but is not writable.") + } + val oStream = path.outputStream() + oStream.use { + Json { + ignoreUnknownKeys = true + }.encodeToStream(conf, it) + } + oStream.close() + } + +} 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..5fd641c --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalClientConfig.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 + +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 shouldEscResetMode: Boolean = true, + val defaultMode: Mode = Mode.NORMAL +) 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..06755a1 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/GimbalGuiSettings.kt @@ -0,0 +1,33 @@ +/* + * 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 +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( + val showHud: Boolean = true, + 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/ScaledRes.kt b/src/main/java/net/moonleay/gimbal/client/config/ScaledRes.kt new file mode 100644 index 0000000..40d04aa --- /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, // offsetX + val scaledY: Double, // offsetY +) diff --git a/src/main/java/net/moonleay/gimbal/client/config/enums/Centerpoint.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/Centerpoint.kt new file mode 100644 index 0000000..a9cecc4 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/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.enums + +enum class Centerpoint { + TOP_LEFT, + TOP_RIGHT, + BOTTOM_RIGHT, + BOTTOM_LEFT, + CENTER +} diff --git a/src/main/java/net/moonleay/gimbal/client/config/enums/HorizontalAnchor.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/HorizontalAnchor.kt new file mode 100644 index 0000000..439a56f --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/HorizontalAnchor.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.enums + +import kotlinx.serialization.Serializable + +@Serializable +enum class HorizontalAnchor { + LEFT, + CENTER, + RIGHT, +} 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/enums/VerticalAnchor.kt b/src/main/java/net/moonleay/gimbal/client/config/enums/VerticalAnchor.kt new file mode 100644 index 0000000..d3ae146 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/config/enums/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.enums + +import kotlinx.serialization.Serializable + +@Serializable +enum class VerticalAnchor { + TOP, + CENTER, + BOTTOM, +} diff --git a/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt new file mode 100644 index 0000000..42d54c4 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/editor/ClientEditor.kt @@ -0,0 +1,316 @@ +/* + * 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.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 +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.networking.GimbalClient +import org.apache.logging.log4j.LogManager + +object ClientEditor { + private var POLICY = GimbalPolicyType.NOT_PRESENT + + private lateinit var CURRENT_MODE: Mode + private var TEMP_DISABLED_MODE = Mode.UNKNOWN + + private val CURRENT_MODE_MODIFIER = mutableListOf() + private val TEMP_DISABLED_MODIFIERS = mutableListOf() + private val DISABLED_MODIFIERS_STORAGE = mutableListOf() + + + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + + fun applyConfig(config: GimbalClientConfig, isBoot: Boolean = true) { + if (isBoot) { + this.CURRENT_MODE = config.defaultMode + return + } + if (!config.shouldEscResetMode) return + this.CURRENT_MODE = config.defaultMode + onUpdated() + } + + fun onConnectedToNewWorld() { + POLICY = GimbalPolicyType.NOT_PRESENT + if (TEMP_DISABLED_MODE == Mode.UNKNOWN) { + TEMP_DISABLED_MODE = + CURRENT_MODE + } + CURRENT_MODE = Mode.INSERT + DISABLED_MODIFIERS_STORAGE.addAll( + CURRENT_MODE_MODIFIER + ) + CURRENT_MODE_MODIFIER.clear() + } + + 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 + TEMP_DISABLED_MODE = Mode.UNKNOWN + } + CURRENT_MODE_MODIFIER.addAll( + DISABLED_MODIFIERS_STORAGE + ) + DISABLED_MODIFIERS_STORAGE.clear() + onUpdated(shouldUpdateServer) + + if (!shouldUpdateServer) { + val player = MinecraftClient.getInstance().player + if (player == null) { + LOGGER.warn("Player is null!") //FIXME: Fix player is null at world join! + return + } + ServerEditorManager.updateEditorState( + MinecraftClient.getInstance().player!!.uuid, + this.getClientState() + ) + } + } + } + + fun isAllowed(): Boolean { + return POLICY == GimbalPolicyType.ALLOWED + } + + fun shouldClient(capability: Capability): Boolean { + return EditorUtil.shouldPlayer( + capability, EditorState( + CURRENT_MODE, + CURRENT_MODE_MODIFIER + ) + ) + } + + fun isInNonDefaultMode(): Boolean { + return CURRENT_MODE != ClientMain.CONFIG.config.defaultMode + } + + /* + * Send an updated player state to the server + * */ + private fun updateServerState() { + val state = this.getClientState() + GimbalClient.sendStatePacket(state) + ServerEditorManager.updateEditorState(MinecraftClient.getInstance().player!!.uuid, state) + } + + + /* + * Set the current mode + * */ + fun setMode(mode: Mode) { + if (!isAllowed()) { + ChatUtil.showToastToSelf( + "Gimbal is disabled", + "You cannot change modes", + ToastType.SYSTEM, + ClientMain.CONFIG.config, + MinecraftClient.getInstance() + ) + return + } + if (!MinecraftClient.getInstance().player!!.isCreative) + return + CURRENT_MODE = mode + + onUpdated() + } + + /* + * Toggle a mode modifier + * */ + fun toggleModifier(mod: ModeModifier) { + if (!isAllowed()) { + 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)) { + TEMP_DISABLED_MODIFIERS.remove(mod) + } else { + TEMP_DISABLED_MODIFIERS.add(mod) + } + } + else { + if (CURRENT_MODE_MODIFIER.contains(mod)) { + CURRENT_MODE_MODIFIER.remove(mod) + 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() + } + + private fun onUpdated(shouldUpdateServer: Boolean = true) { + CURRENT_MODE_MODIFIER.sortBy { + it.displayName + } + checkForIncompatibleModeModifiers(shouldUpdateServer) + } + + /** + * This runs on Mode updated + */ + private fun checkForIncompatibleModeModifiers(shouldUpdateServer: Boolean = true) { + if (TEMP_DISABLED_MODIFIERS.size > 0) { + CURRENT_MODE_MODIFIER.addAll( + TEMP_DISABLED_MODIFIERS + ) + TEMP_DISABLED_MODIFIERS.clear() + } + + val incompatibleModeModifiers = CURRENT_MODE.incompatibleModifiers + for (mod in CURRENT_MODE_MODIFIER) { + if (incompatibleModeModifiers.contains(mod)) { + TEMP_DISABLED_MODIFIERS.add(mod) + } + } + for (mod in TEMP_DISABLED_MODIFIERS) { + if (CURRENT_MODE_MODIFIER.contains(mod)) { // This check is probably useless. + CURRENT_MODE_MODIFIER.remove(mod) + } + } + + CURRENT_MODE_MODIFIER.sortBy { + it.displayName + } + + // Update State + if (shouldUpdateServer) + updateServerState() + + if(TEMP_DISABLED_MODIFIERS.isNotEmpty()) { + ChatUtil.showToastToSelf( + "${CURRENT_MODE.displayName} Mode disabled", + getDisplayNameListAsString(TEMP_DISABLED_MODIFIERS), + ToastType.SYSTEM, + ClientMain.CONFIG.config, + MinecraftClient.getInstance() + ) + } + } + + private fun getDisplayNameListAsString(list: List): String { + if(list.isEmpty()) + return "" + val sb = StringBuilder() + for (mod in list) { + sb.append(mod.displayName) + sb.append(", ") + } + 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(config: GimbalClientConfig): Text { + val displayText = StringBuilder(CURRENT_MODE.displayName) + 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()) + } + } + return Text.of("[GIMBAL DISABLED]") + } + + 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/client/keybindings/KeybindingManager.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingManager.kt new file mode 100644 index 0000000..40e0f2f --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingManager.kt @@ -0,0 +1,43 @@ +/* + * 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.keybindings + +import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl +import net.minecraft.client.MinecraftClient +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut + +object KeybindingManager { + + private val shortcuts = mutableListOf() + + /** + * Register a shortcut. This will also register the keybinding. + * */ + fun registerShortcut(shortcut: GimbalShortcut) { + shortcuts.add(shortcut) + KeyBindingRegistryImpl.registerKeyBinding(shortcut.keyBinding) + } + + fun onClientTick(client: MinecraftClient){ + // Sadly, this cannot be done without iterating over all shortcuts :madge: + for (shortcut in shortcuts) + if (shortcut.keyBinding.wasPressed()) + shortcut.onPressed(client) + } +} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/KeybindingRegistrar.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingRegistrar.kt similarity index 54% rename from src/main/java/net/moonleay/gimble/client/keybindings/KeybindingRegistrar.kt rename to src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingRegistrar.kt index 018e736..fd37f7d 100644 --- a/src/main/java/net/moonleay/gimble/client/keybindings/KeybindingRegistrar.kt +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/KeybindingRegistrar.kt @@ -1,17 +1,36 @@ -package net.moonleay.gimble.client.keybindings +/* + * 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.keybindings import net.minecraft.client.option.KeyBinding import net.minecraft.client.util.InputUtil -import net.moonleay.gimble.build.BuildConstants -import net.moonleay.gimble.client.keybindings.impl.editormode.EnableInsertModeShortcut -import net.moonleay.gimble.client.keybindings.impl.editormode.EnableReplaceModeShortcut -import net.moonleay.gimble.client.keybindings.impl.editormodemodifier.ToggleBulldozerModifierShortcut -import net.moonleay.gimble.client.keybindings.impl.editormodemodifier.ToggleForcePlaceModifierShortcut -import net.moonleay.gimble.client.keybindings.impl.editormodemodifier.ToggleNoClipModifierShortcut -import net.moonleay.gimble.client.keybindings.impl.editormodemodifier.ToggleNoUpdatesModifierShortcut -import net.moonleay.gimble.client.keybindings.impl.gamemode.CreativeModeShortcut -import net.moonleay.gimble.client.keybindings.impl.gamemode.SpectatorModeShortcut -import net.moonleay.gimble.client.keybindings.impl.gamemode.SurvivalModeShortcut +import net.moonleay.gimbal.build.BuildConstants +import net.moonleay.gimbal.client.keybindings.impl.editormode.EnableInsertModeShortcut +import net.moonleay.gimbal.client.keybindings.impl.editormode.EnableReplaceModeShortcut +import net.moonleay.gimbal.client.keybindings.impl.editormodemodifier.ToggleBulldozerModifierShortcut +import net.moonleay.gimbal.client.keybindings.impl.editormodemodifier.ToggleForcePlaceModifierShortcut +import net.moonleay.gimbal.client.keybindings.impl.editormodemodifier.ToggleNoClipModifierShortcut +import net.moonleay.gimbal.client.keybindings.impl.editormodemodifier.ToggleNoUpdatesModifierShortcut +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 @@ -29,28 +48,28 @@ object KeybindingRegistrar { private fun registerSetEditorModeModifierKeybindings() { val toggleBulldozerModifierShortcut = KeyBinding( - "gimble.key.editor.modifier.bulldozer", + TranslationKeys.Keybindings.Binding.Editor.Modifier.BULLDOZER, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimble.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) val toggleForcePlaceModifierShortcut = KeyBinding( - "gimble.key.editor.modifier.forceplace", + TranslationKeys.Keybindings.Binding.Editor.Modifier.FORCE_PLACE, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimble.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) val toggleNoUpdatesModifierShortcut = KeyBinding( - "gimble.key.editor.modifier.noupdates", + TranslationKeys.Keybindings.Binding.Editor.Modifier.NO_UPDATES, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimble.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) val toggleNoClipModifierShortcut = KeyBinding( - "gimble.key.editor.modifier.noclip", + TranslationKeys.Keybindings.Binding.Editor.Modifier.NO_CLIP, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimble.category.editormodifier" + TranslationKeys.Keybindings.Category.Editor.MODIFIER ) KeybindingManager.registerShortcut(ToggleBulldozerModifierShortcut(toggleBulldozerModifierShortcut)) @@ -61,22 +80,22 @@ object KeybindingRegistrar { private fun registerSetEditorModeKeybindings() { val insertKeyBinding = KeyBinding( - "gimble.key.editor.mode.insert", + TranslationKeys.Keybindings.Binding.Editor.Mode.INSERT, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_I, - "gimble.category.editormode" + TranslationKeys.Keybindings.Category.Editor.MODE ) val replaceKeyBinding = KeyBinding( - "gimble.key.editor.mode.replace", + TranslationKeys.Keybindings.Binding.Editor.Mode.REPLACE, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_R, - "gimble.category.editormode" + TranslationKeys.Keybindings.Category.Editor.MODE ) // val visualKeyBinding = KeyBinding( -// "gimble.key.editor.mode.visual", +// "gimbal.key.editor.mode.visual", // InputUtil.Type.KEYSYM, // GLFW.GLFW_KEY_V, -// "gimble.category.editormode" +// "gimbal.category.editormode" // ) KeybindingManager.registerShortcut(EnableInsertModeShortcut(insertKeyBinding)) KeybindingManager.registerShortcut(EnableReplaceModeShortcut(replaceKeyBinding)) @@ -85,22 +104,22 @@ object KeybindingRegistrar { private fun registerSetGameModeKeybindings() { val survivalKeyBinding = KeyBinding( - "gimble.key.game.mode.survival", + TranslationKeys.Keybindings.Binding.Game.Mode.SURVIVAL, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimble.category.gamemode" + TranslationKeys.Keybindings.Category.Game.GAMEMODE ) val creativeKeyBinding = KeyBinding( - "gimble.key.game.mode.creative", + TranslationKeys.Keybindings.Binding.Game.Mode.CREATIVE, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimble.category.gamemode" + TranslationKeys.Keybindings.Category.Game.GAMEMODE ) val spectatorKeyBinding = KeyBinding( - "gimble.key.game.mode.spectator", + TranslationKeys.Keybindings.Binding.Game.Mode.SPECTATOR, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - "gimble.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/keybindings/impl/GimbalShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/GimbalShortcut.kt new file mode 100644 index 0000000..fd7f299 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/GimbalShortcut.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.keybindings.impl + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding + +abstract class GimbalShortcut(val keyBinding: KeyBinding) { + + abstract fun onPressed(client: MinecraftClient) +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableInsertModeShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableInsertModeShortcut.kt new file mode 100644 index 0000000..31208c9 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableInsertModeShortcut.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.keybindings.impl.editormode + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.editor.state.mode.Mode + + +class EnableInsertModeShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ClientEditor.setMode(Mode.INSERT) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableReplaceModeShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableReplaceModeShortcut.kt new file mode 100644 index 0000000..bfee8c7 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableReplaceModeShortcut.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.keybindings.impl.editormode + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.editor.state.mode.Mode + + +class EnableReplaceModeShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ClientEditor.setMode(Mode.REPLACE) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableVisualModeShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableVisualModeShortcut.kt new file mode 100644 index 0000000..26136a0 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormode/EnableVisualModeShortcut.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.keybindings.impl.editormode + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.editor.state.mode.Mode + + +class EnableVisualModeShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ClientEditor.setMode(Mode.VISUAL) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleBulldozerModifierShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleBulldozerModifierShortcut.kt new file mode 100644 index 0000000..6ca9306 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleBulldozerModifierShortcut.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.keybindings.impl.editormodemodifier + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.editor.state.mode.ModeModifier + +class ToggleBulldozerModifierShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ClientEditor.toggleModifier(ModeModifier.BULLDOZER) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleForcePlaceModifierShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleForcePlaceModifierShortcut.kt new file mode 100644 index 0000000..18c7ce3 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleForcePlaceModifierShortcut.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.keybindings.impl.editormodemodifier + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.editor.state.mode.ModeModifier + +class ToggleForcePlaceModifierShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ClientEditor.toggleModifier(ModeModifier.FORCE_PLACE) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleNoClipModifierShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleNoClipModifierShortcut.kt new file mode 100644 index 0000000..0d23bab --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleNoClipModifierShortcut.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.keybindings.impl.editormodemodifier + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.editor.state.mode.ModeModifier + +class ToggleNoClipModifierShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ClientEditor.toggleModifier(ModeModifier.NO_CLIP) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleNoUpdatesModifierShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleNoUpdatesModifierShortcut.kt new file mode 100644 index 0000000..960e031 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/editormodemodifier/ToggleNoUpdatesModifierShortcut.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.keybindings.impl.editormodemodifier + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.editor.ClientEditor +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.editor.state.mode.ModeModifier + +class ToggleNoUpdatesModifierShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ClientEditor.toggleModifier(ModeModifier.NO_UPDATES) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/CreativeModeShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/CreativeModeShortcut.kt new file mode 100644 index 0000000..11c9edf --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/CreativeModeShortcut.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.keybindings.impl.gamemode + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.client.util.ChatUtil + +class CreativeModeShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ChatUtil.sendCommand("/gamemode creative", client, false) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/SpectatorModeShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/SpectatorModeShortcut.kt new file mode 100644 index 0000000..599d163 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/SpectatorModeShortcut.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.keybindings.impl.gamemode + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.client.util.ChatUtil + +class SpectatorModeShortcut(key: KeyBinding) : GimbalShortcut(key) { + override fun onPressed(client: MinecraftClient) { + ChatUtil.sendCommand("/gamemode spectator", client, false) + } +} diff --git a/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/SurvivalModeShortcut.kt b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/SurvivalModeShortcut.kt new file mode 100644 index 0000000..c14a4ae --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/keybindings/impl/gamemode/SurvivalModeShortcut.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.keybindings.impl.gamemode + +import net.minecraft.client.MinecraftClient +import net.minecraft.client.option.KeyBinding +import net.moonleay.gimbal.client.keybindings.impl.GimbalShortcut +import net.moonleay.gimbal.client.util.ChatUtil + + +class SurvivalModeShortcut(key: KeyBinding) : GimbalShortcut(key) { + + override fun onPressed(client: MinecraftClient) { + ChatUtil.sendCommand("/gamemode survival", client, false) + } +} 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..0155e35 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalEditHudGui.kt @@ -0,0 +1,151 @@ +/* + * 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.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 net.moonleay.gimbal.constants.TranslationKeys +import org.apache.logging.log4j.LogManager + +class GimbalEditHudGui(private val parent: Screen, private val cfg: ClientConfigHolder) : + Screen(Text.translatable(TranslationKeys.Gui.Config.Hud.EDIT_HUD)) { + 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.offset.scaledX + this.tempYOffset = cfg.config.guiSettings.offset.scaledY + } + + override fun init() { + super.init() + this.addDrawableChild(ButtonWidget( + this.width / 2 + 10, this.height - 27, 90, 20, Text.translatable(TranslationKeys.Gui.Config.Hud.RESET_HUD) + ) { _: 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 anchor = ScreenUtil.getAnchor(this.tempXOffset, this.tempYOffset) + + val newConf = GimbalClientConfig( + guiSettings = GimbalGuiSettings( + showHud = oldConf.guiSettings.showHud, + offset = ScaledRes( + scaledX = this.tempXOffset, + scaledY = this.tempYOffset, + ), + horizontalAnchor = anchor.first, + verticalAnchor = anchor.second, + hudOptions = oldConf.guiSettings.hudOptions + ), + toastSettings = oldConf.toastSettings, + playerFlySpeed = oldConf.playerFlySpeed, + shouldEscResetMode = oldConf.shouldEscResetMode, + defaultMode = oldConf.defaultMode + ) + + 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 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 + } + } + } + + 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) + 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(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(TranslationKeys.Gui.Config.Hud.EXAMPLE_HUD_TEXT)) + ), + ScreenUtil.getYForAnchor( + ScreenUtil.getReal(this.client!!.window.height, this.tempYOffset) / scaleFactor, + anchor.second, + this.textRenderer.fontHeight + ), + 0xFFFFFF + ) + 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..4e11df4 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/screen/GimbalSettingsGui.kt @@ -0,0 +1,290 @@ +/* + * 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 +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 +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)) { + + 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() { + 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(TranslationKeys.Gui.Config.Hud.SHOW_HUD) + ) { _: CyclingButtonWidget?, isEnabled: Boolean? -> + val oldGui = cfg.config.guiSettings + val newGui = GimbalGuiSettings( + showHud = isEnabled ?: true, + offset = oldGui.offset, + horizontalAnchor = oldGui.horizontalAnchor, + verticalAnchor = oldGui.verticalAnchor, + hudOptions = oldGui.hudOptions + ) + val newConf = GimbalClientConfig( + guiSettings = newGui, + toastSettings = cfg.config.toastSettings, + playerFlySpeed = cfg.config.playerFlySpeed, + shouldEscResetMode = cfg.config.shouldEscResetMode, + defaultMode = cfg.config.defaultMode + ) + cfg.updateConfig(newConf) + }) + + this.addDrawableChild(ButtonWidget( + this.width / 2 - 155 + 160, + this.height / 6 + 24 * 0, + 150, + 20, + 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, + playerFlySpeed = oldConfig.playerFlySpeed, + shouldEscResetMode = oldConfig.shouldEscResetMode, + defaultMode = oldConfig.defaultMode + ) + 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, + playerFlySpeed = oldConfig.playerFlySpeed, + shouldEscResetMode = oldConfig.shouldEscResetMode, + defaultMode = oldConfig.defaultMode + ) + 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.linearInterpolate(this.playerFlySpeed.toDouble(), 100.0, 1000.0, 0.0, 1.0), + 100.0, + 1000.0, + ) { value -> + 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( + 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) { + 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 * 3, + 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, + shouldEscResetMode = oldConfig.shouldEscResetMode, + defaultMode = this.defaultMode + ) + cfg.updateConfig(newConfig) + } + ) + + // 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/screen/widgets/GimbalSliderWidget.kt b/src/main/java/net/moonleay/gimbal/client/screen/widgets/GimbalSliderWidget.kt new file mode 100644 index 0000000..c244615 --- /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.linearInterpolate(this.value, 0.0, 1.0, this.lowerEnd, this.upperEnd).toInt())) + } + + override fun updateMessage() { + this.message = this.text.copy() + .append(": " + (NumberUtil.linearInterpolate(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/ChatUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/ChatUtil.kt new file mode 100644 index 0000000..b53d959 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/util/ChatUtil.kt @@ -0,0 +1,54 @@ +/* + * 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 + +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 { + /** + * Note: command arg should contain "/" at the beginning. + * */ + fun sendCommand(command: String, client: MinecraftClient, addToHistory: Boolean = true): Boolean { + if (addToHistory) { + client.inGameHud.chatHud.addToMessageHistory(command) + } + return client.player?.sendCommand(command.substring(1))?: false + } + + fun addToChatHistory(message: String, client: MinecraftClient) { + client.inGameHud.chatHud.addMessage(Text.of(message)) + } + + 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/NumberUtil.kt b/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt new file mode 100644 index 0000000..e335842 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/util/NumberUtil.kt @@ -0,0 +1,44 @@ +/* + * 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 number between two numbers in a linear way + */ + 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 - 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/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 new file mode 100644 index 0000000..5a5d4f7 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/client/util/screen/ScreenUtil.kt @@ -0,0 +1,71 @@ +/* + * 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.enums.HorizontalAnchor +import net.moonleay.gimbal.client.config.enums.VerticalAnchor + +object ScreenUtil { + + 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 getXForAnchor(x: Float, anchor: HorizontalAnchor, textWidth: Int): Float { + return when (anchor) { + 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 + } + } + + 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/constants/PacketIDs.kt b/src/main/java/net/moonleay/gimbal/constants/PacketIDs.kt new file mode 100644 index 0000000..da664c0 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/constants/PacketIDs.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.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 GIMBAL_POLICY_PACKET_ID = Identifier(BuildConstants.modId, "gimbal_policy") + +} diff --git a/src/main/java/net/moonleay/gimbal/constants/PermissionIDs.kt b/src/main/java/net/moonleay/gimbal/constants/PermissionIDs.kt new file mode 100644 index 0000000..7263609 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/constants/PermissionIDs.kt @@ -0,0 +1,23 @@ +/* + * 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 + +object PermissionIDs { + const val GIMBAL_USAGE_PERMISSION = "gimbal.use" +} 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..0db8509 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/constants/TranslationKeys.kt @@ -0,0 +1,127 @@ +/* + * 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" + + const val PLAYER_FLY_SPEED = "${BASE}flySpeed" + const val SHOULD_ESC_RESET_MODE = "${BASE}shouldESCResetMode" + const val DEFAULT_MODE = "${BASE}defaultMode" + + 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/DataGenerator.kt b/src/main/java/net/moonleay/gimbal/datagen/DataGenerator.kt new file mode 100644 index 0000000..bd2452e --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/datagen/DataGenerator.kt @@ -0,0 +1,33 @@ +/* + * 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.datagen + +import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint +import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator +import net.moonleay.gimbal.build.BuildConstants +import org.apache.logging.log4j.LogManager + +internal class DataGenerator : DataGeneratorEntrypoint { + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + + override fun onInitializeDataGenerator(fabricDataGenerator: FabricDataGenerator) { + LOGGER.info("Starting Data Generation") + fabricDataGenerator.addProvider(EnUsLanguageProvider(fabricDataGenerator)) + } +} diff --git a/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt b/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt new file mode 100644 index 0000000..00279a1 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/datagen/EnUsLanguageProvider.kt @@ -0,0 +1,96 @@ +/* + * 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.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 EnUsLanguageProvider(dataGenerator: FabricDataGenerator?) : + FabricLanguageProvider(dataGenerator, "en_us") { + + override fun generateTranslations(translationBuilder: TranslationBuilder?) { + if (translationBuilder == null) return + /// Screens + // Gimbal settings screen + translationBuilder.add(TranslationKeys.Gui.Config.SCREEN_NAME, "Gimbal Settings") + + // Hud + translationBuilder.add(TranslationKeys.Gui.Config.Hud.SHOW_HUD, "Show HUD") + + + //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 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 + translationBuilder.add(TranslationKeys.Gui.Config.GENERIC_ENABLED, "Enabled") + translationBuilder.add(TranslationKeys.Gui.Config.GENERIC_DISABLED, "Disabled") + + /// Options + // Editor modes + 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(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(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/ServerEditorManager.kt b/src/main/java/net/moonleay/gimbal/editor/ServerEditorManager.kt new file mode 100644 index 0000000..c0a1801 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/ServerEditorManager.kt @@ -0,0 +1,55 @@ +/* + * 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 + +import net.moonleay.gimbal.build.BuildConstants +import net.moonleay.gimbal.editor.state.EditorState +import net.moonleay.gimbal.editor.state.mode.Capability +import net.moonleay.gimbal.editor.util.EditorUtil +import org.apache.logging.log4j.LogManager +import java.util.* + +object ServerEditorManager { + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + + private val STATEMAP = mutableMapOf() + + fun updateEditorState(playerUUID: UUID, editorState: EditorState) { + STATEMAP[playerUUID] = editorState + LOGGER.debug("{}: {} with {}", playerUUID, editorState.editorMode, editorState.editorModifier) + } + + + /* + * Check if a player should be able to perform an action + * */ + fun shouldPlayer(playerUUID: UUID, capability: Capability): Boolean { + if (!STATEMAP.containsKey(playerUUID)) + return false + val state = STATEMAP[playerUUID]!! + return EditorUtil.shouldPlayer(capability, state) + } + + +// fun playerHasModifier(playerUUID: UUID, modifier: ModeModifier): Boolean { +// if (!STATEMAP.containsKey(playerUUID)) +// return false +// return STATEMAP[playerUUID]!!.editorModifier.contains(modifier) ?: false +// } +} diff --git a/src/main/java/net/moonleay/gimbal/editor/state/EditorState.kt b/src/main/java/net/moonleay/gimbal/editor/state/EditorState.kt new file mode 100644 index 0000000..bda6a97 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/state/EditorState.kt @@ -0,0 +1,29 @@ +/* + * 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 +import net.moonleay.gimbal.editor.state.mode.Mode +import net.moonleay.gimbal.editor.state.mode.ModeModifier + +@Serializable +data class EditorState( + var editorMode: Mode, + var editorModifier: MutableList, +) diff --git a/src/main/java/net/moonleay/gimbal/editor/state/GimbalPolicyType.kt b/src/main/java/net/moonleay/gimbal/editor/state/GimbalPolicyType.kt new file mode 100644 index 0000000..37c7341 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/state/GimbalPolicyType.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.editor.state + +import kotlinx.serialization.Serializable + +@Serializable +enum class GimbalPolicyType { + ALLOWED, + DENIED, + 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/editor/state/mode/Capability.kt b/src/main/java/net/moonleay/gimbal/editor/state/mode/Capability.kt new file mode 100644 index 0000000..bc8a055 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/state/mode/Capability.kt @@ -0,0 +1,29 @@ +/* + * 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.mode + +enum class Capability { + INSERT, + REPLACE, + CAN_INTERACT, + NO_CLIP, + FORCE_PLACE, + NO_UPDATES, + BULLDOZER, +} 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 new file mode 100644 index 0000000..5481b22 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/state/mode/Mode.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.editor.state.mode + +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/editor/state/mode/ModeModifier.kt b/src/main/java/net/moonleay/gimbal/editor/state/mode/ModeModifier.kt new file mode 100644 index 0000000..da99041 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/state/mode/ModeModifier.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.mode + +enum class ModeModifier(val displayName: String, val shortName: String) { +// NONE("None"), // No Modifiers - default behavior +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/gimble/editor/util/EditorUtil.kt b/src/main/java/net/moonleay/gimbal/editor/util/EditorUtil.kt similarity index 53% rename from src/main/java/net/moonleay/gimble/editor/util/EditorUtil.kt rename to src/main/java/net/moonleay/gimbal/editor/util/EditorUtil.kt index 6c37255..55b3c52 100644 --- a/src/main/java/net/moonleay/gimble/editor/util/EditorUtil.kt +++ b/src/main/java/net/moonleay/gimbal/editor/util/EditorUtil.kt @@ -1,9 +1,28 @@ -package net.moonleay.gimble.editor.util +/* + * 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.util + +import net.moonleay.gimbal.editor.state.EditorState +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.gimble.editor.state.EditorState -import net.moonleay.gimble.editor.state.mode.Capability -import net.moonleay.gimble.editor.state.mode.Mode -import net.moonleay.gimble.editor.state.mode.ModeModifier object EditorUtil { diff --git a/src/main/java/net/moonleay/gimbal/editor/util/GimbalPolicy.kt b/src/main/java/net/moonleay/gimbal/editor/util/GimbalPolicy.kt new file mode 100644 index 0000000..1d4e5ce --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/editor/util/GimbalPolicy.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.util + +import kotlinx.serialization.Serializable +import net.moonleay.gimbal.editor.state.GimbalPolicyType + +@Serializable +data class GimbalPolicy( + val policy: GimbalPolicyType, +) diff --git a/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin.java b/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin.java new file mode 100644 index 0000000..df682c2 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/BulldozerMixin.java @@ -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.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; +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.Objects; + +public abstract class BulldozerMixin { + + @Mixin(MinecraftClient.class) + public static abstract class MinecraftClientMixin { + @Shadow + @Nullable + public ClientPlayerEntity player; + @Shadow + protected int attackCooldown; + + @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; + } + } + + @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; + } + } +} diff --git a/src/main/java/net/moonleay/gimble/mixin/ForcePlaceMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ForcePlaceMixin.java similarity index 53% rename from src/main/java/net/moonleay/gimble/mixin/ForcePlaceMixin.java rename to src/main/java/net/moonleay/gimbal/mixin/ForcePlaceMixin.java index 4a861fd..042d704 100644 --- a/src/main/java/net/moonleay/gimble/mixin/ForcePlaceMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/ForcePlaceMixin.java @@ -1,10 +1,28 @@ -package net.moonleay.gimble.mixin; +/* + * 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.ItemPlacementContext; -import net.moonleay.gimble.editor.ServerEditorManager; -import net.moonleay.gimble.editor.state.mode.Capability; +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.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.java new file mode 100644 index 0000000..5c0f58f --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/HudMixin.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.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; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(InGameHud.class) +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; + 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(ClientMain.CONFIG.getConfig()); + 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() + ); + } +} diff --git a/src/main/java/net/moonleay/gimble/mixin/NoBlockUpdatesMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NoBlockUpdatesMixin.java similarity index 58% rename from src/main/java/net/moonleay/gimble/mixin/NoBlockUpdatesMixin.java rename to src/main/java/net/moonleay/gimbal/mixin/NoBlockUpdatesMixin.java index 4055ad1..9fec1e5 100644 --- a/src/main/java/net/moonleay/gimble/mixin/NoBlockUpdatesMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/NoBlockUpdatesMixin.java @@ -1,11 +1,29 @@ -package net.moonleay.gimble.mixin; +/* + * 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.item.BlockItem; import net.minecraft.item.ItemPlacementContext; -import net.moonleay.gimble.editor.ServerEditorManager; -import net.moonleay.gimble.editor.state.mode.Capability; +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.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java new file mode 100644 index 0000000..8e9a80a --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java @@ -0,0 +1,106 @@ +/* + * 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 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; +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; + +public abstract class NoClipMixin { + + @Mixin(PlayerEntity.class) // Serverside, allows clipping + public static abstract class PlayerEntityMixin extends LivingEntity { + protected PlayerEntityMixin(EntityType entityType, World world) { + super(entityType, world); + } + + @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); + } + } + + + @Mixin(Camera.class) // Clientside, fixes camera + public static abstract class CameraMixin { + + @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/gimble/mixin/NormalModeMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java similarity index 58% rename from src/main/java/net/moonleay/gimble/mixin/NormalModeMixin.java rename to src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java index 372a400..d8f769a 100644 --- a/src/main/java/net/moonleay/gimble/mixin/NormalModeMixin.java +++ b/src/main/java/net/moonleay/gimbal/mixin/NormalModeMixin.java @@ -1,11 +1,29 @@ -package net.moonleay.gimble.mixin; +/* + * 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.ClientPlayerEntity; import net.minecraft.client.option.GameOptions; -import net.moonleay.gimble.client.editor.ClientEditor; -import net.moonleay.gimble.editor.state.mode.Capability; -import net.moonleay.gimble.editor.state.mode.Mode; +import net.moonleay.gimbal.client.ClientMain; +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.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -25,12 +43,12 @@ public class NormalModeMixin { public ClientPlayerEntity player; @Inject(method = "openPauseMenu", at = @At("HEAD"), cancellable = true) - private void setNormalMode(boolean pause, CallbackInfo ci) { - if (ClientEditor.INSTANCE.isInNonDefaultMode() && ClientEditor.INSTANCE.isAllowed()) { + private void setDefaultMode(boolean pause, CallbackInfo ci) { + 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 - ClientEditor.INSTANCE.setMode(Mode.NORMAL); + ClientEditor.INSTANCE.setMode(ClientMain.CONFIG.getConfig().getDefaultMode()); ci.cancel(); } } 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/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java new file mode 100644 index 0000000..8a28216 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java @@ -0,0 +1,104 @@ +/* + * 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.entity.player.PlayerEntity; +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.*; +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; + +public abstract class ReplaceModeMixin { + + @Mixin(ItemPlacementContext.class) + public static abstract class ItemPlacementContextMixin extends ItemUsageContext { + @Shadow + protected boolean canReplaceExisting; + + @Mutable + @Shadow + @Final + private BlockPos placementPos; + + 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(); + } + } + + @Mixin(BlockItem.class) + public static abstract class BlockItemMixin extends Item { + + 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/YouInjectButtonMixin.java b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java new file mode 100644 index 0000000..efa2a9c --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/mixin/YouInjectButtonMixin.java @@ -0,0 +1,104 @@ +/* + * 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.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; + +// What is my purpose? +public class YouInjectButtonMixin { + // Go my god. + + @Mixin(TitleScreen.class) + public static abstract class TitleScreenMixin extends Screen { + + @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) + ) + ); + } + } + + + @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/networking/GimbalClient.kt b/src/main/java/net/moonleay/gimbal/networking/GimbalClient.kt new file mode 100644 index 0000000..fa179df --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/networking/GimbalClient.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.networking + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.cbor.Cbor +import kotlinx.serialization.decodeFromByteArray +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.state.GimbalPolicyType +import net.moonleay.gimbal.editor.state.GimbalServerState + +object GimbalClient { + + fun registerPacketHandlers() { + 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 getServerState(buf: PacketByteBuf): GimbalServerState { + val serverState = Cbor.decodeFromByteArray(buf.readByteArray()) + return serverState + } + + private fun isGimbalUsable(state: GimbalServerState): Boolean { + return state.policyType == GimbalPolicyType.ALLOWED && state.protocolVersion.toString() == BuildConstants.protocolVersion + } + + @OptIn(ExperimentalSerializationApi::class) + private fun createStatePacket(state: EditorState): PacketByteBuf { + val buf = PacketByteBufs.create() + buf.writeByteArray(Cbor.encodeToByteArray(state)) + 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 new file mode 100644 index 0000000..fd0e654 --- /dev/null +++ b/src/main/java/net/moonleay/gimbal/networking/GimbalServer.kt @@ -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.networking + +import kotlinx.serialization.ExperimentalSerializationApi +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.state.GimbalServerState +import org.apache.logging.log4j.LogManager + +object GimbalServer { + private val LOGGER = LogManager.getLogger(BuildConstants.modName) + + fun registerPacketHandler() { + ServerPlayNetworking + .registerGlobalReceiver(PacketIDs.UPDATE_EDITOR_STATE_ID) + { _, player, _, buf, _ -> + handleStateUpdate(player, buf) + } + } + + @OptIn(ExperimentalSerializationApi::class) + fun notifyPlayerOfPolicy(player: ServerPlayerEntity) { + LOGGER.info("Sending policy to " + 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){ + val state = Cbor.decodeFromByteArray(buf.readByteArray()) + ServerEditorManager.updateEditorState(player.uuid, state) +// player.sendMessage(Text.of("Mode: ${state.editorMode} with ${state.editorModifier}")) + } + + private fun isPlayerAllowedToUseGimbal(player: ServerPlayerEntity): Boolean { + return player.hasPermissionLevel(2) || Permissions.check(player, PermissionIDs.GIMBAL_USAGE_PERMISSION) + } +} diff --git a/src/main/java/net/moonleay/gimble/Main.kt b/src/main/java/net/moonleay/gimble/Main.kt deleted file mode 100644 index 5cdb815..0000000 --- a/src/main/java/net/moonleay/gimble/Main.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.moonleay.gimble - -import net.moonleay.gimble.build.BuildConstants -import net.fabricmc.api.ModInitializer -import net.moonleay.gimble.networking.GimbleServer -import org.apache.logging.log4j.LogManager - -internal object Main : ModInitializer { - private val LOGGER = LogManager.getLogger(BuildConstants.modName) - - override fun onInitialize() { - LOGGER.info("Initializing Gimble on the common side...") - LOGGER.info("Registering packets...") - GimbleServer.registerPacketHandler() - LOGGER.info("Packets have been registered.") - LOGGER.info("Gimble 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/gimble/client/ClientMain.kt b/src/main/java/net/moonleay/gimble/client/ClientMain.kt deleted file mode 100644 index c520c08..0000000 --- a/src/main/java/net/moonleay/gimble/client/ClientMain.kt +++ /dev/null @@ -1,33 +0,0 @@ -package net.moonleay.gimble.client - -import net.fabricmc.api.ClientModInitializer -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents -import net.moonleay.gimble.build.BuildConstants -import net.moonleay.gimble.client.keybindings.KeybindingManager -import net.moonleay.gimble.client.keybindings.KeybindingRegistrar -import net.moonleay.gimble.networking.GimbleClient -import org.apache.logging.log4j.LogManager - -internal object ClientMain : ClientModInitializer { - private val LOGGER = LogManager.getLogger(BuildConstants.modName) - - - override fun onInitializeClient() { - LOGGER.info("Initializing Gimble on the client side...") - KeybindingRegistrar.registerKeybindings() - registerEvents() - LOGGER.info("Registering packets...") - GimbleClient.registerPacketHandlers() - LOGGER.info("Packets have been registered.") - LOGGER.info("Gimble has been initialized on the client side.") - } - - private fun registerEvents() { - LOGGER.info("Registering client events...") - ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { client -> - KeybindingManager.onClientTick(client) - }) - LOGGER.info("Client events have been registered.") - } - -} diff --git a/src/main/java/net/moonleay/gimble/client/editor/ClientEditor.kt b/src/main/java/net/moonleay/gimble/client/editor/ClientEditor.kt deleted file mode 100644 index 894ba28..0000000 --- a/src/main/java/net/moonleay/gimble/client/editor/ClientEditor.kt +++ /dev/null @@ -1,193 +0,0 @@ -package net.moonleay.gimble.client.editor - -import net.minecraft.client.MinecraftClient -import net.minecraft.text.Text -import net.moonleay.gimble.client.util.ChatUtil -import net.moonleay.gimble.editor.ServerEditorManager -import net.moonleay.gimble.editor.state.EditorState -import net.moonleay.gimble.editor.state.GimblePolicyType -import net.moonleay.gimble.editor.state.mode.Capability -import net.moonleay.gimble.editor.state.mode.Mode -import net.moonleay.gimble.editor.state.mode.ModeModifier -import net.moonleay.gimble.editor.util.EditorUtil -import net.moonleay.gimble.editor.util.GimblePolicy -import net.moonleay.gimble.networking.GimbleClient - -object ClientEditor { - private var POLICY = GimblePolicyType.NOT_PRESENT - - private var CURRENT_MODE = Mode.NORMAL - private var TEMP_DISABLED_MODE = Mode.UNKNOWN - - private val CURRENT_MODE_MODIFIER = mutableListOf() - private val TEMP_DISABLED_MODIFIERS = mutableListOf() - - private val DISABLED_MODIFIERS_STORAGE = mutableListOf() - - - fun onConnectedToNewWorld() { - POLICY = GimblePolicyType.NOT_PRESENT - GimbleClient.checkIfServerHasGimble(EditorState(CURRENT_MODE, CURRENT_MODE_MODIFIER)) - if (TEMP_DISABLED_MODE == Mode.UNKNOWN) { - TEMP_DISABLED_MODE = CURRENT_MODE - } - CURRENT_MODE = Mode.INSERT - DISABLED_MODIFIERS_STORAGE.addAll(CURRENT_MODE_MODIFIER) - CURRENT_MODE_MODIFIER.clear() - } - - fun onAllowedCheck(data: GimblePolicy) { - POLICY = data.policy - if (data.policy == GimblePolicyType.ALLOWED) { - if (TEMP_DISABLED_MODE != Mode.UNKNOWN) { - CURRENT_MODE = TEMP_DISABLED_MODE - TEMP_DISABLED_MODE = Mode.UNKNOWN - } - CURRENT_MODE_MODIFIER.addAll(DISABLED_MODIFIERS_STORAGE) - DISABLED_MODIFIERS_STORAGE.clear() - this.onUpdated() - } - } - - fun isAllowed(): Boolean { - return POLICY == GimblePolicyType.ALLOWED - } - - fun shouldClient(capability: Capability): Boolean { - return EditorUtil.shouldPlayer(capability, EditorState(CURRENT_MODE, CURRENT_MODE_MODIFIER)) - } - - fun isInNonDefaultMode(): Boolean { - return CURRENT_MODE != Mode.NORMAL - } - - /* - * Send an updated player state to the server - * */ - private fun updateServerState() { - val state = EditorState(CURRENT_MODE, CURRENT_MODE_MODIFIER) - GimbleClient.sendEditorState(state) - ServerEditorManager.updateEditorState(MinecraftClient.getInstance().player!!.uuid, state) - } - - - /* - * Set the current mode - * */ - fun setMode(mode: Mode) { - if (!isAllowed()) { - ChatUtil.showToastToSelf("Gimble is disabled", "You cannot change modes", MinecraftClient.getInstance()) - return - } - if (!MinecraftClient.getInstance().player!!.isCreative) - return - CURRENT_MODE = mode - - this.onUpdated() - } - - /* - * Toggle a mode modifier - * */ - fun toggleModifier(mod: ModeModifier) { - if (!isAllowed()) { - ChatUtil.showToastToSelf("Gimble is disabled", "You cannot change modifiers", MinecraftClient.getInstance()) - return - } - if (!MinecraftClient.getInstance().player!!.isCreative) - return - - if (CURRENT_MODE.incompatibleModifiers.contains(mod)){ - if (TEMP_DISABLED_MODIFIERS.contains(mod)) - TEMP_DISABLED_MODIFIERS.remove(mod) - else - TEMP_DISABLED_MODIFIERS.add(mod) - } - else { - if (CURRENT_MODE_MODIFIER.contains(mod)) - CURRENT_MODE_MODIFIER.remove(mod) - else - CURRENT_MODE_MODIFIER.add(mod) - } - - this.onUpdated() - } - - private fun onUpdated() { - CURRENT_MODE_MODIFIER.sortBy { - it.displayName - } - this.checkForIncompatibleModeModifiers() - } - - /** - * This runs on Mode updated - */ - private fun checkForIncompatibleModeModifiers() { - if (TEMP_DISABLED_MODIFIERS.size > 0) { - CURRENT_MODE_MODIFIER.addAll( - TEMP_DISABLED_MODIFIERS - ) - TEMP_DISABLED_MODIFIERS.clear() - } - - val incompatibleModeModifiers = CURRENT_MODE.incompatibleModifiers - for (mod in CURRENT_MODE_MODIFIER) { - if (incompatibleModeModifiers.contains(mod)) { - TEMP_DISABLED_MODIFIERS.add(mod) - } - } - for (mod in TEMP_DISABLED_MODIFIERS) { - if (CURRENT_MODE_MODIFIER.contains(mod)) { // This check is probably useless. - CURRENT_MODE_MODIFIER.remove(mod) - } - } - - CURRENT_MODE_MODIFIER.sortBy { - it.displayName - } - - // Update State - this.updateServerState() - - if(TEMP_DISABLED_MODIFIERS.isNotEmpty()) { - ChatUtil.showToastToSelf("${CURRENT_MODE.displayName} Mode disabled", getListAsString(TEMP_DISABLED_MODIFIERS), MinecraftClient.getInstance()) - } - } - - private fun getListAsString(list: List): String{ - if(list.isEmpty()) - return "Empty list" - val sb = StringBuilder() - for (mod in list) { - sb.append(mod.displayName) - sb.append(", ") - } - return sb.toString().dropLast(2) - } - - /* - * Get the display text to display in the HUD - * */ - fun getModeDisplayText(): Text { - val displayText = StringBuilder(CURRENT_MODE.displayName) - if (CURRENT_MODE_MODIFIER.isNotEmpty() && this.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(", ") - } - } - displayText.append("]") - } else if (!this.isAllowed() || !MinecraftClient.getInstance().player?.isCreative!!) { - displayText.clear() - displayText.append("[GIMBLE DISABLED]") - } - return Text.of(displayText.toString()) - } - - fun getCurrentColor(): Int { - return CURRENT_MODE.color - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/KeybindingManager.kt b/src/main/java/net/moonleay/gimble/client/keybindings/KeybindingManager.kt deleted file mode 100644 index 5257977..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/KeybindingManager.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.moonleay.gimble.client.keybindings - -import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl -import net.minecraft.client.MinecraftClient -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut - -object KeybindingManager { - - private val shortcuts = mutableListOf() - - /** - * Register a shortcut. This will also register the keybinding. - * */ - fun registerShortcut(shortcut: GimbleShortcut) { - shortcuts.add(shortcut) - KeyBindingRegistryImpl.registerKeyBinding(shortcut.keyBinding) - } - - fun onClientTick(client: MinecraftClient){ - // Sadly, this cannot be done without iterating over all shortcuts :madge: - for (shortcut in shortcuts) - if (shortcut.keyBinding.wasPressed()) - shortcut.onPressed(client) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/GimbleShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/GimbleShortcut.kt deleted file mode 100644 index fdaa1a3..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/GimbleShortcut.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding - -abstract class GimbleShortcut(val keyBinding: KeyBinding) { - - abstract fun onPressed(client: MinecraftClient) -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableInsertModeShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableInsertModeShortcut.kt deleted file mode 100644 index a77abdf..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableInsertModeShortcut.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.editormode - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.editor.ClientEditor -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.editor.state.mode.Mode - - -class EnableInsertModeShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ClientEditor.setMode(Mode.INSERT) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableReplaceModeShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableReplaceModeShortcut.kt deleted file mode 100644 index dfa9316..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableReplaceModeShortcut.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.editormode - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.editor.ClientEditor -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.editor.state.mode.Mode - - -class EnableReplaceModeShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ClientEditor.setMode(Mode.REPLACE) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableVisualModeShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableVisualModeShortcut.kt deleted file mode 100644 index 36711aa..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormode/EnableVisualModeShortcut.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.editormode - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.editor.ClientEditor -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.editor.state.mode.Mode - - -class EnableVisualModeShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ClientEditor.setMode(Mode.VISUAL) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleBulldozerModifierShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleBulldozerModifierShortcut.kt deleted file mode 100644 index 3fd31be..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleBulldozerModifierShortcut.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.editormodemodifier - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.editor.ClientEditor -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.editor.state.mode.ModeModifier - -class ToggleBulldozerModifierShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ClientEditor.toggleModifier(ModeModifier.BULLDOZER) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleForcePlaceModifierShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleForcePlaceModifierShortcut.kt deleted file mode 100644 index eae4119..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleForcePlaceModifierShortcut.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.editormodemodifier - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.editor.ClientEditor -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.editor.state.mode.ModeModifier - -class ToggleForcePlaceModifierShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ClientEditor.toggleModifier(ModeModifier.FORCE_PLACE) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleNoClipModifierShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleNoClipModifierShortcut.kt deleted file mode 100644 index 40a0940..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleNoClipModifierShortcut.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.editormodemodifier - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.editor.ClientEditor -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.editor.state.mode.ModeModifier - -class ToggleNoClipModifierShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ClientEditor.toggleModifier(ModeModifier.NO_CLIP) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleNoUpdatesModifierShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleNoUpdatesModifierShortcut.kt deleted file mode 100644 index 5380fdf..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/editormodemodifier/ToggleNoUpdatesModifierShortcut.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.editormodemodifier - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.editor.ClientEditor -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.editor.state.mode.ModeModifier - -class ToggleNoUpdatesModifierShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ClientEditor.toggleModifier(ModeModifier.NO_UPDATES) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/CreativeModeShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/CreativeModeShortcut.kt deleted file mode 100644 index 57008a4..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/CreativeModeShortcut.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.gamemode - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.client.util.ChatUtil - -class CreativeModeShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ChatUtil.sendCommand("/gamemode creative", client, false) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/SpectatorModeShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/SpectatorModeShortcut.kt deleted file mode 100644 index 346e783..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/SpectatorModeShortcut.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.gamemode - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.client.util.ChatUtil - -class SpectatorModeShortcut(key: KeyBinding): GimbleShortcut(key) { - override fun onPressed(client: MinecraftClient) { - ChatUtil.sendCommand("/gamemode spectator", client, false) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/SurvivalModeShortcut.kt b/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/SurvivalModeShortcut.kt deleted file mode 100644 index 387ea8d..0000000 --- a/src/main/java/net/moonleay/gimble/client/keybindings/impl/gamemode/SurvivalModeShortcut.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.moonleay.gimble.client.keybindings.impl.gamemode - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.option.KeyBinding -import net.moonleay.gimble.client.keybindings.impl.GimbleShortcut -import net.moonleay.gimble.client.util.ChatUtil - - -class SurvivalModeShortcut(key: KeyBinding) : GimbleShortcut(key) { - - override fun onPressed(client: MinecraftClient) { - ChatUtil.sendCommand("/gamemode survival", client, false) - } -} diff --git a/src/main/java/net/moonleay/gimble/client/util/ChatUtil.kt b/src/main/java/net/moonleay/gimble/client/util/ChatUtil.kt deleted file mode 100644 index cc30396..0000000 --- a/src/main/java/net/moonleay/gimble/client/util/ChatUtil.kt +++ /dev/null @@ -1,26 +0,0 @@ -package net.moonleay.gimble.client.util - -import net.minecraft.client.MinecraftClient -import net.minecraft.client.toast.SystemToast -import net.minecraft.text.Text - -object ChatUtil { - /** - * Note: command arg should contain "/" at the beginning. - * */ - fun sendCommand(command: String, client: MinecraftClient, addToHistory: Boolean = true): Boolean { - if (addToHistory) { - client.inGameHud.chatHud.addToMessageHistory(command) - } - return client.player?.sendCommand(command.substring(1))?: false - } - - fun addToChatHistory(message: String, client: MinecraftClient) { - client.inGameHud.chatHud.addMessage(Text.of(message)) - } - - fun showToastToSelf(title: String, description: String, client: MinecraftClient) { - 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/gimble/datagen/DataGenerator.kt b/src/main/java/net/moonleay/gimble/datagen/DataGenerator.kt deleted file mode 100644 index a2267c8..0000000 --- a/src/main/java/net/moonleay/gimble/datagen/DataGenerator.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.moonleay.gimble.datagen - -import net.moonleay.gimble.build.BuildConstants -import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint -import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator -import org.apache.logging.log4j.LogManager - -internal class DataGenerator : DataGeneratorEntrypoint { - private val LOGGER = LogManager.getLogger(BuildConstants.modName) - - override fun onInitializeDataGenerator(fabricDataGenerator: FabricDataGenerator) { - LOGGER.info("Starting Data Generation") - fabricDataGenerator.addProvider(En_us_GimbleLanguageProvider(fabricDataGenerator)) - } -} diff --git a/src/main/java/net/moonleay/gimble/datagen/En_us_GimbleLanguageProvider.kt b/src/main/java/net/moonleay/gimble/datagen/En_us_GimbleLanguageProvider.kt deleted file mode 100644 index cca1464..0000000 --- a/src/main/java/net/moonleay/gimble/datagen/En_us_GimbleLanguageProvider.kt +++ /dev/null @@ -1,32 +0,0 @@ -package net.moonleay.gimble.datagen - -import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator -import net.fabricmc.fabric.api.datagen.v1.provider.FabricLanguageProvider - -class En_us_GimbleLanguageProvider(dataGenerator: FabricDataGenerator?) : - FabricLanguageProvider(dataGenerator, "en_us") { - - override fun generateTranslations(translationBuilder: TranslationBuilder?) { - if (translationBuilder == null) return - // Editor modes - translationBuilder.add("gimble.category.editormode", "Editor Modes") - translationBuilder.add("gimble.key.editor.mode.insert", "Enter Insert Mode") - translationBuilder.add("gimble.key.editor.mode.replace", "Enter Replace Mode") - translationBuilder.add("gimble.key.editor.mode.visual", "Enter Visual Mode") - - - // Editor mode modifiers - translationBuilder.add("gimble.category.editormodifier", "Editor Mode Modifiers") - translationBuilder.add("gimble.key.editor.modifier.bulldozer", "Toggle Bulldozer Modifier") - translationBuilder.add("gimble.key.editor.modifier.forceplace", "Toggle Force Place Modifier") - translationBuilder.add("gimble.key.editor.modifier.noupdates", "Toggle No Updates Modifier") - translationBuilder.add("gimble.key.editor.modifier.noclip", "Toggle No Clip Modifier") - - // Game mode - translationBuilder.add("gimble.category.gamemode", "Game Mode") - translationBuilder.add("gimble.key.game.mode.survival", "Enable Survival Mode") - translationBuilder.add("gimble.key.game.mode.creative", "Enable Creative Mode") - translationBuilder.add("gimble.key.game.mode.spectator", "Enable Spectator Mode") - - } -} diff --git a/src/main/java/net/moonleay/gimble/editor/ServerEditorManager.kt b/src/main/java/net/moonleay/gimble/editor/ServerEditorManager.kt deleted file mode 100644 index 25a3513..0000000 --- a/src/main/java/net/moonleay/gimble/editor/ServerEditorManager.kt +++ /dev/null @@ -1,37 +0,0 @@ -package net.moonleay.gimble.editor - -import net.moonleay.gimble.build.BuildConstants -import net.moonleay.gimble.editor.state.EditorState -import net.moonleay.gimble.editor.state.mode.Capability -import net.moonleay.gimble.editor.util.EditorUtil -import org.apache.logging.log4j.LogManager -import java.util.* - -object ServerEditorManager { - private val LOGGER = LogManager.getLogger(BuildConstants.modName) - - private val STATEMAP = mutableMapOf() - - fun updateEditorState(playerUUID: UUID, editorState: EditorState) { - STATEMAP[playerUUID] = editorState - LOGGER.info("$playerUUID: ${editorState.editorMode} with ${editorState.editorModifier}") - } - - - /* - * Check if a player should be able to perform an action - * */ - fun shouldPlayer(playerUUID: UUID, capability: Capability): Boolean { - if (!STATEMAP.containsKey(playerUUID)) - return false - val state = STATEMAP[playerUUID]!! - return EditorUtil.shouldPlayer(capability, state) - } - - -// fun playerHasModifier(playerUUID: UUID, modifier: ModeModifier): Boolean { -// if (!STATEMAP.containsKey(playerUUID)) -// return false -// return STATEMAP[playerUUID]!!.editorModifier.contains(modifier) ?: false -// } -} diff --git a/src/main/java/net/moonleay/gimble/editor/state/EditorState.kt b/src/main/java/net/moonleay/gimble/editor/state/EditorState.kt deleted file mode 100644 index 57e0d5f..0000000 --- a/src/main/java/net/moonleay/gimble/editor/state/EditorState.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.moonleay.gimble.editor.state - -import kotlinx.serialization.Serializable -import net.moonleay.gimble.editor.state.mode.Mode -import net.moonleay.gimble.editor.state.mode.ModeModifier - -@Serializable -data class EditorState( - var editorMode: Mode, - var editorModifier: MutableList, -) diff --git a/src/main/java/net/moonleay/gimble/editor/state/GimblePolicyType.kt b/src/main/java/net/moonleay/gimble/editor/state/GimblePolicyType.kt deleted file mode 100644 index 52cda45..0000000 --- a/src/main/java/net/moonleay/gimble/editor/state/GimblePolicyType.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.moonleay.gimble.editor.state - -enum class GimblePolicyType { - ALLOWED, - DENIED, - NOT_PRESENT -} diff --git a/src/main/java/net/moonleay/gimble/editor/state/mode/Capability.kt b/src/main/java/net/moonleay/gimble/editor/state/mode/Capability.kt deleted file mode 100644 index 14dd079..0000000 --- a/src/main/java/net/moonleay/gimble/editor/state/mode/Capability.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.moonleay.gimble.editor.state.mode - -enum class Capability { - INSERT, - REPLACE, - CAN_INTERACT, - NO_CLIP, - FORCE_PLACE, - NO_UPDATES, - BULLDOZER, -} diff --git a/src/main/java/net/moonleay/gimble/editor/state/mode/Mode.kt b/src/main/java/net/moonleay/gimble/editor/state/mode/Mode.kt deleted file mode 100644 index 95d7961..0000000 --- a/src/main/java/net/moonleay/gimble/editor/state/mode/Mode.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.moonleay.gimble.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()), // Replace blocks - VISUAL("VISUAL", 0x6a9fb5, listOf(ModeModifier.BULLDOZER)), // Do fancy stuff with WE -} diff --git a/src/main/java/net/moonleay/gimble/editor/state/mode/ModeModifier.kt b/src/main/java/net/moonleay/gimble/editor/state/mode/ModeModifier.kt deleted file mode 100644 index f7bc6bb..0000000 --- a/src/main/java/net/moonleay/gimble/editor/state/mode/ModeModifier.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.moonleay.gimble.editor.state.mode - -enum class ModeModifier(val displayName: 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 -} diff --git a/src/main/java/net/moonleay/gimble/editor/util/GimblePolicy.kt b/src/main/java/net/moonleay/gimble/editor/util/GimblePolicy.kt deleted file mode 100644 index 620e682..0000000 --- a/src/main/java/net/moonleay/gimble/editor/util/GimblePolicy.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.moonleay.gimble.editor.util - -import kotlinx.serialization.Serializable -import net.moonleay.gimble.editor.state.GimblePolicyType - -@Serializable -data class GimblePolicy( - val policy: GimblePolicyType, -) diff --git a/src/main/java/net/moonleay/gimble/mixin/BulldozerMixin.java b/src/main/java/net/moonleay/gimble/mixin/BulldozerMixin.java deleted file mode 100644 index 1134cd5..0000000 --- a/src/main/java/net/moonleay/gimble/mixin/BulldozerMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package net.moonleay.gimble.mixin; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.moonleay.gimble.client.editor.ClientEditor; -import net.moonleay.gimble.editor.state.mode.Capability; -import org.jetbrains.annotations.Nullable; -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; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Objects; - -@Mixin(MinecraftClient.class) -public abstract class BulldozerMixin { - - @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; - } - 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; - } - - -} diff --git a/src/main/java/net/moonleay/gimble/mixin/BulldozerMixin2.java b/src/main/java/net/moonleay/gimble/mixin/BulldozerMixin2.java deleted file mode 100644 index ae8d081..0000000 --- a/src/main/java/net/moonleay/gimble/mixin/BulldozerMixin2.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.moonleay.gimble.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.gimble.client.editor.ClientEditor; -import net.moonleay.gimble.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/gimble/mixin/GimblePolicyCheckMixin.java b/src/main/java/net/moonleay/gimble/mixin/GimblePolicyCheckMixin.java deleted file mode 100644 index 951c4aa..0000000 --- a/src/main/java/net/moonleay/gimble/mixin/GimblePolicyCheckMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.moonleay.gimble.mixin; - -import net.minecraft.client.gui.screen.DownloadingTerrainScreen; -import net.moonleay.gimble.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 GimblePolicyCheckMixin { - - - @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(); - } -} diff --git a/src/main/java/net/moonleay/gimble/mixin/HudMixin.java b/src/main/java/net/moonleay/gimble/mixin/HudMixin.java deleted file mode 100644 index dd16008..0000000 --- a/src/main/java/net/moonleay/gimble/mixin/HudMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.moonleay.gimble.mixin; - -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.moonleay.gimble.client.editor.ClientEditor; -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(InGameHud.class) -public 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()); - } -} diff --git a/src/main/java/net/moonleay/gimble/mixin/NoClipCameraFixMixin.java b/src/main/java/net/moonleay/gimble/mixin/NoClipCameraFixMixin.java deleted file mode 100644 index 0874f9a..0000000 --- a/src/main/java/net/moonleay/gimble/mixin/NoClipCameraFixMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.moonleay.gimble.mixin; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.Camera; -import net.moonleay.gimble.client.editor.ClientEditor; -import net.moonleay.gimble.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/gimble/mixin/NoClipMixin.java b/src/main/java/net/moonleay/gimble/mixin/NoClipMixin.java deleted file mode 100644 index f66885d..0000000 --- a/src/main/java/net/moonleay/gimble/mixin/NoClipMixin.java +++ /dev/null @@ -1,64 +0,0 @@ -package net.moonleay.gimble.mixin; - -import com.mojang.authlib.GameProfile; -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.gimble.editor.ServerEditorManager; -import net.moonleay.gimble.editor.state.mode.Capability; -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; - -import java.util.UUID; - -@Mixin(PlayerEntity.class) -public abstract class NoClipMixin extends LivingEntity { - @Shadow public abstract GameProfile getGameProfile(); - - @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 - } - 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); - } -} diff --git a/src/main/java/net/moonleay/gimble/mixin/ReplaceModeMixin.java b/src/main/java/net/moonleay/gimble/mixin/ReplaceModeMixin.java deleted file mode 100644 index cfaed01..0000000 --- a/src/main/java/net/moonleay/gimble/mixin/ReplaceModeMixin.java +++ /dev/null @@ -1,69 +0,0 @@ -package net.moonleay.gimble.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.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.gimble.client.editor.ClientEditor; -import net.moonleay.gimble.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; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MinecraftClient.class) -public abstract class ReplaceModeMixin { - - - @Shadow protected abstract void handleBlockBreaking(boolean breaking); - - @Shadow @Nullable public ClientPlayerInteractionManager interactionManager; - - @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); - } - -} diff --git a/src/main/java/net/moonleay/gimble/networking/GimbleClient.kt b/src/main/java/net/moonleay/gimble/networking/GimbleClient.kt deleted file mode 100644 index 718c7c8..0000000 --- a/src/main/java/net/moonleay/gimble/networking/GimbleClient.kt +++ /dev/null @@ -1,42 +0,0 @@ -package net.moonleay.gimble.networking - -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.cbor.Cbor -import kotlinx.serialization.decodeFromByteArray -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.gimble.client.editor.ClientEditor -import net.moonleay.gimble.editor.state.EditorState -import net.moonleay.gimble.editor.util.GimblePolicy - -object GimbleClient { - - fun registerPacketHandlers() { - ClientPlayNetworking.registerGlobalReceiver(PacketIDs.TRANSFER_GIMBLE_POLICY_ID) { _, _, buf, _ -> - onAllowedCheck(buf) - } - } - - private fun onAllowedCheck(buf: PacketByteBuf) { - val policy = Cbor.decodeFromByteArray(buf.readByteArray()) - ClientEditor.onAllowedCheck(policy) // Update the client's policy - } - - /** - * 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) - } - - fun checkIfServerHasGimble(state: EditorState) { - val buf = PacketByteBufs.create() - buf.writeByteArray(Cbor.encodeToByteArray(state)) - ClientPlayNetworking.send(PacketIDs.GIMBLE_PRERENCE_CHECK_ID, buf) - } -} diff --git a/src/main/java/net/moonleay/gimble/networking/GimbleServer.kt b/src/main/java/net/moonleay/gimble/networking/GimbleServer.kt deleted file mode 100644 index 8b182b5..0000000 --- a/src/main/java/net/moonleay/gimble/networking/GimbleServer.kt +++ /dev/null @@ -1,44 +0,0 @@ -package net.moonleay.gimble.networking - -import kotlinx.serialization.cbor.Cbor -import kotlinx.serialization.decodeFromByteArray -import kotlinx.serialization.encodeToByteArray -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.gimble.editor.ServerEditorManager -import net.moonleay.gimble.editor.state.EditorState -import net.moonleay.gimble.editor.state.GimblePolicyType -import net.moonleay.gimble.editor.util.GimblePolicy - -object GimbleServer { - - fun registerPacketHandler() { - ServerPlayNetworking - .registerGlobalReceiver(PacketIDs.UPDATE_EDITOR_STATE_ID) - { server, player, handler, buf, responseSender -> - handleStateUpdate(player, buf) - } - ServerPlayNetworking - .registerGlobalReceiver(PacketIDs.GIMBLE_PRERENCE_CHECK_ID) - { server, player, handler, buf, responseSender -> - handlePresenceCheck(player, buf) - } - } - - private fun handleStateUpdate(player: ServerPlayerEntity, buf: PacketByteBuf){ - val state = Cbor.decodeFromByteArray(buf.readByteArray()) - ServerEditorManager.updateEditorState(player.uuid, state) -// 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(GimblePolicy(GimblePolicyType.ALLOWED))) - ServerPlayNetworking.send(player, PacketIDs.TRANSFER_GIMBLE_POLICY_ID, buffer) - } -} diff --git a/src/main/java/net/moonleay/gimble/networking/PacketIDs.kt b/src/main/java/net/moonleay/gimble/networking/PacketIDs.kt deleted file mode 100644 index 4587ff8..0000000 --- a/src/main/java/net/moonleay/gimble/networking/PacketIDs.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.moonleay.gimble.networking - -import net.minecraft.util.Identifier -import net.moonleay.gimble.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") - -} diff --git a/src/main/resources/assets/gimbal/logo.png b/src/main/resources/assets/gimbal/logo.png new file mode 100644 index 0000000..07dbd45 Binary files /dev/null and b/src/main/resources/assets/gimbal/logo.png differ 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 0000000..e11bf08 Binary files /dev/null and b/src/main/resources/assets/gimbal/textures/gimbal_options_texture_button.png differ diff --git a/src/main/resources/assets/gimble/logo.png b/src/main/resources/assets/gimble/logo.png deleted file mode 100644 index ab1e23e..0000000 Binary files a/src/main/resources/assets/gimble/logo.png and /dev/null differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f653362..0f9c789 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -3,16 +3,19 @@ "id": "${modId}", "version": "${modVersion}", "name": "${modName}", - "description": "An open source building assist mod featuring vim-like modes and modifiers.", + "description": "An open source building assist mod featuring Vim-like modes and modifiers.", "authors": [ "moonleay" ], + "contributors": [ + "Cookieso" + ], "icon": "assets/${modId}/logo.png", "contact": { "email": "contact@moonleay.net", "homepage": "https://moonleay.net", - "sources": "https://codeberg.org/moonleay/Gimble", - "issues": "https://codeberg.org/moonleay/Gimble/issues" + "sources": "https://codeberg.org/moonleay/Gimbal", + "issues": "https://codeberg.org/moonleay/Gimbal/issues" }, "license": "GPL-3.0", "environment": "*", @@ -20,19 +23,19 @@ "client": [ { "adapter": "kotlin", - "value": "net.moonleay.gimble.client.ClientMain" + "value": "net.moonleay.gimbal.client.ClientMain" } ], "main": [ { "adapter": "kotlin", - "value": "net.moonleay.gimble.Main" + "value": "net.moonleay.gimbal.Main" } ], "fabric-datagen": [ { "adapter": "kotlin", - "value": "net.moonleay.gimble.datagen.DataGenerator" + "value": "net.moonleay.gimbal.datagen.DataGenerator" } ] }, diff --git a/src/main/resources/gimble.accesswidener b/src/main/resources/gimbal.accesswidener similarity index 81% rename from src/main/resources/gimble.accesswidener rename to src/main/resources/gimbal.accesswidener index e659ad2..ee44473 100644 --- a/src/main/resources/gimble.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 new file mode 100644 index 0000000..9de8288 --- /dev/null +++ b/src/main/resources/gimbal.mixins.json @@ -0,0 +1,26 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.moonleay.gimbal.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "ForcePlaceMixin", + "NoBlockUpdatesMixin", + "NoClipMixin$PlayerEntityMixin", + "ReplaceModeMixin$BlockItemMixin", + "ReplaceModeMixin$ItemPlacementContextMixin" + ], + "client": [ + "BulldozerMixin$ClientPlayerInteractionManagerMixin", + "BulldozerMixin$MinecraftClientMixin", + "HudMixin", + "NoClipMixin$CameraMixin", + "NormalModeMixin", + "PlayerFlySpeedMixin", + "YouInjectButtonMixin$GameMenuScreenMixin", + "YouInjectButtonMixin$TitleScreenMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/gimble.mixins.json b/src/main/resources/gimble.mixins.json deleted file mode 100644 index 9ec9090..0000000 --- a/src/main/resources/gimble.mixins.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "net.moonleay.gimble.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - "ForcePlaceMixin", - "NoBlockUpdatesMixin", - "NoClipMixin" - ], - "client": [ - "BulldozerMixin", - "BulldozerMixin2", - "GimblePolicyCheckMixin", - "HudMixin", - "NoClipCameraFixMixin", - "NormalModeMixin", - "ReplaceModeMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/src/main/templates/net/moonleay/gimbal/build/BuildConstants.kt b/src/main/templates/net/moonleay/gimbal/build/BuildConstants.kt new file mode 100644 index 0000000..d90f0ff --- /dev/null +++ b/src/main/templates/net/moonleay/gimbal/build/BuildConstants.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.build + +internal object BuildConstants { + const val modId = "${modId}" + const val modName = "${modName}" + const val modVersion = "${modVersion}" + const val protocolVersion = "${protocolVersion}" +} + diff --git a/src/main/templates/net/moonleay/gimble/build/BuildConstants.kt b/src/main/templates/net/moonleay/gimble/build/BuildConstants.kt deleted file mode 100644 index 85b65ee..0000000 --- a/src/main/templates/net/moonleay/gimble/build/BuildConstants.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.moonleay.gimble.build - -internal object BuildConstants { - const val modId = "${modId}" - const val modName = "${modName}" - const val modVersion = "${modVersion}" -}