mirror of
https://codeberg.org/moonleay/Gimbal.git
synced 2025-07-06 23:25:46 +02:00
chore: moved group to net.moonleay
fix: fixed camera going meyhem when going 3rd person in NoClip
This commit is contained in:
parent
0cd271f139
commit
7383fa09e8
31 changed files with 125 additions and 107 deletions
13
src/main/java/net/moonleay/gimble/Main.kt
Normal file
13
src/main/java/net/moonleay/gimble/Main.kt
Normal file
|
@ -0,0 +1,13 @@
|
|||
package net.moonleay.gimble
|
||||
|
||||
import net.moonleay.gimble.build.BuildConstants
|
||||
import net.fabricmc.api.ModInitializer
|
||||
import org.apache.logging.log4j.LogManager
|
||||
|
||||
internal object Main : ModInitializer {
|
||||
private val LOGGER = LogManager.getLogger(BuildConstants.modName)
|
||||
|
||||
override fun onInitialize() {
|
||||
LOGGER.info("Main has been initialized")
|
||||
}
|
||||
}
|
29
src/main/java/net/moonleay/gimble/client/ClientMain.kt
Normal file
29
src/main/java/net/moonleay/gimble/client/ClientMain.kt
Normal file
|
@ -0,0 +1,29 @@
|
|||
package net.moonleay.gimble.client
|
||||
|
||||
import net.moonleay.gimble.build.BuildConstants
|
||||
import net.fabricmc.api.ClientModInitializer
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
||||
import net.moonleay.gimble.client.keybindings.KeybindingManager
|
||||
import net.moonleay.gimble.client.keybindings.KeybindingRegistrar
|
||||
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("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.")
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package net.moonleay.gimble.client.editor
|
||||
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.moonleay.gimble.client.util.ChatUtil
|
||||
import net.moonleay.gimble.client.editor.modes.Mode
|
||||
import net.moonleay.gimble.client.editor.modes.ModeModifier
|
||||
|
||||
object ClientEditor {
|
||||
var CURRENT_MODE = Mode.NORMAL
|
||||
val CURRENT_MODE_MODIFIER = mutableListOf<ModeModifier>()
|
||||
private val TEMP_DISABLED_MODIFIERS = mutableListOf<ModeModifier>()
|
||||
|
||||
|
||||
fun toggleModifier(mod: ModeModifier) {
|
||||
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)
|
||||
}
|
||||
|
||||
onModifiersUpdated()
|
||||
}
|
||||
|
||||
fun onModifiersUpdated() {
|
||||
CURRENT_MODE_MODIFIER.sort()
|
||||
checkForIncompatibleModeModifiers()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if(TEMP_DISABLED_MODIFIERS.isNotEmpty()) {
|
||||
ChatUtil.addToChatHistory("The following modifiers are not supported by this editor mode and are therefore currently disabled: " +
|
||||
getListAsString(TEMP_DISABLED_MODIFIERS), MinecraftClient.getInstance())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getListAsString(list: List<ModeModifier>): String{
|
||||
if(list.isEmpty())
|
||||
return "Empty list"
|
||||
val sb = StringBuilder()
|
||||
for (mod in list) {
|
||||
sb.append(mod.displayName)
|
||||
sb.append(" ")
|
||||
}
|
||||
return sb.toString().dropLast(1)
|
||||
}
|
||||
|
||||
fun getCurrentMode(): Mode {
|
||||
return CURRENT_MODE
|
||||
}
|
||||
|
||||
fun getCurrentModifier(): List<ModeModifier> {
|
||||
return CURRENT_MODE_MODIFIER
|
||||
}
|
||||
|
||||
fun containsModifier(mod: ModeModifier): Boolean {
|
||||
return CURRENT_MODE_MODIFIER.contains(mod)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package net.moonleay.gimble.client.editor.modes
|
||||
|
||||
enum class Mode(val displayName: String, val color: Int, val incompatibleModifiers: List<ModeModifier>){
|
||||
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
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package net.moonleay.gimble.client.editor.modes
|
||||
|
||||
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
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
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<GimbleShortcut>()
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package net.moonleay.gimble.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.editormode.EnableVisualModeShortcut
|
||||
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 org.apache.logging.log4j.LogManager
|
||||
import org.lwjgl.glfw.GLFW
|
||||
|
||||
object KeybindingRegistrar {
|
||||
|
||||
private val LOGGER = LogManager.getLogger(BuildConstants.modName)
|
||||
|
||||
fun registerKeybindings() {
|
||||
LOGGER.info("Registering keybindings...")
|
||||
registerSetGameModeKeybindings()
|
||||
registerSetEditorModeKeybindings()
|
||||
registerSetEditorModeModifierKeybindings()
|
||||
LOGGER.info("Keybindings have been registered.")
|
||||
}
|
||||
|
||||
private fun registerSetEditorModeModifierKeybindings() {
|
||||
val toggleBulldozerModifierShortcut = KeyBinding(
|
||||
"gimble.key.editor.modifier.bulldozer",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_B,
|
||||
"gimble.category.editormodifier"
|
||||
)
|
||||
val toggleForcePlaceModifierShortcut = KeyBinding(
|
||||
"gimble.key.editor.modifier.forceplace",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_F,
|
||||
"gimble.category.editormodifier"
|
||||
)
|
||||
val toggleNoUpdatesModifierShortcut = KeyBinding(
|
||||
"gimble.key.editor.modifier.noupdates",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_N,
|
||||
"gimble.category.editormodifier"
|
||||
)
|
||||
val toggleNoClipModifierShortcut = KeyBinding(
|
||||
"gimble.key.editor.modifier.noclip",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_C,
|
||||
"gimble.category.editormodifier"
|
||||
)
|
||||
|
||||
KeybindingManager.registerShortcut(ToggleBulldozerModifierShortcut(toggleBulldozerModifierShortcut))
|
||||
KeybindingManager.registerShortcut(ToggleForcePlaceModifierShortcut(toggleForcePlaceModifierShortcut))
|
||||
KeybindingManager.registerShortcut(ToggleNoUpdatesModifierShortcut(toggleNoUpdatesModifierShortcut))
|
||||
KeybindingManager.registerShortcut(ToggleNoClipModifierShortcut(toggleNoClipModifierShortcut))
|
||||
}
|
||||
|
||||
private fun registerSetEditorModeKeybindings() {
|
||||
val insertKeyBinding = KeyBinding(
|
||||
"gimble.key.editor.mode.insert",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_I,
|
||||
"gimble.category.editormode"
|
||||
)
|
||||
val replaceKeyBinding = KeyBinding(
|
||||
"gimble.key.editor.mode.replace",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_R,
|
||||
"gimble.category.editormode"
|
||||
)
|
||||
val visualKeyBinding = KeyBinding(
|
||||
"gimble.key.editor.mode.visual",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_V,
|
||||
"gimble.category.editormode"
|
||||
)
|
||||
KeybindingManager.registerShortcut(EnableInsertModeShortcut(insertKeyBinding))
|
||||
KeybindingManager.registerShortcut(EnableReplaceModeShortcut(replaceKeyBinding))
|
||||
KeybindingManager.registerShortcut(EnableVisualModeShortcut(visualKeyBinding))
|
||||
}
|
||||
|
||||
private fun registerSetGameModeKeybindings() {
|
||||
val survivalKeyBinding = KeyBinding(
|
||||
"gimble.key.game.mode.survival",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_UNKNOWN,
|
||||
"gimble.category.gamemode"
|
||||
)
|
||||
val creativeKeyBinding = KeyBinding(
|
||||
"gimble.key.game.mode.creative",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_UNKNOWN,
|
||||
"gimble.category.gamemode"
|
||||
)
|
||||
val spectatorKeyBinding = KeyBinding(
|
||||
"gimble.key.game.mode.spectator",
|
||||
InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_UNKNOWN,
|
||||
"gimble.category.gamemode"
|
||||
)
|
||||
KeybindingManager.registerShortcut(SurvivalModeShortcut(survivalKeyBinding))
|
||||
KeybindingManager.registerShortcut(CreativeModeShortcut(creativeKeyBinding))
|
||||
KeybindingManager.registerShortcut(SpectatorModeShortcut(spectatorKeyBinding))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
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)
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
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.client.editor.modes.Mode
|
||||
|
||||
|
||||
class EnableInsertModeShortcut(key: KeyBinding): GimbleShortcut(key) {
|
||||
override fun onPressed(client: MinecraftClient) {
|
||||
ClientEditor.CURRENT_MODE = Mode.INSERT
|
||||
|
||||
ClientEditor.checkForIncompatibleModeModifiers()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
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.client.editor.modes.Mode
|
||||
|
||||
|
||||
class EnableReplaceModeShortcut(key: KeyBinding): GimbleShortcut(key) {
|
||||
override fun onPressed(client: MinecraftClient) {
|
||||
ClientEditor.CURRENT_MODE = Mode.REPLACE
|
||||
|
||||
ClientEditor.checkForIncompatibleModeModifiers()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
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.client.editor.modes.Mode
|
||||
|
||||
|
||||
class EnableVisualModeShortcut(key: KeyBinding): GimbleShortcut(key) {
|
||||
override fun onPressed(client: MinecraftClient) {
|
||||
ClientEditor.CURRENT_MODE = Mode.VISUAL
|
||||
|
||||
ClientEditor.checkForIncompatibleModeModifiers()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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.client.editor.modes.ModeModifier
|
||||
|
||||
class ToggleBulldozerModifierShortcut(key: KeyBinding): GimbleShortcut(key) {
|
||||
override fun onPressed(client: MinecraftClient) {
|
||||
ClientEditor.toggleModifier(ModeModifier.BULLDOZER)
|
||||
|
||||
ClientEditor.onModifiersUpdated()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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.client.editor.modes.ModeModifier
|
||||
|
||||
class ToggleForcePlaceModifierShortcut(key: KeyBinding): GimbleShortcut(key) {
|
||||
override fun onPressed(client: MinecraftClient) {
|
||||
ClientEditor.toggleModifier(ModeModifier.FORCE_PLACE)
|
||||
|
||||
ClientEditor.onModifiersUpdated()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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.client.editor.modes.ModeModifier
|
||||
|
||||
class ToggleNoClipModifierShortcut(key: KeyBinding): GimbleShortcut(key) {
|
||||
override fun onPressed(client: MinecraftClient) {
|
||||
ClientEditor.toggleModifier(ModeModifier.NO_CLIP)
|
||||
|
||||
ClientEditor.onModifiersUpdated()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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.client.editor.modes.ModeModifier
|
||||
|
||||
class ToggleNoUpdatesModifierShortcut(key: KeyBinding): GimbleShortcut(key) {
|
||||
override fun onPressed(client: MinecraftClient) {
|
||||
ClientEditor.toggleModifier(ModeModifier.NO_UPDATES)
|
||||
|
||||
ClientEditor.onModifiersUpdated()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
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)
|
||||
}
|
||||
}
|
20
src/main/java/net/moonleay/gimble/client/util/ChatUtil.kt
Normal file
20
src/main/java/net/moonleay/gimble/client/util/ChatUtil.kt
Normal file
|
@ -0,0 +1,20 @@
|
|||
package net.moonleay.gimble.client.util
|
||||
|
||||
import net.minecraft.client.MinecraftClient
|
||||
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))
|
||||
}
|
||||
}
|
15
src/main/java/net/moonleay/gimble/datagen/DataGenerator.kt
Normal file
15
src/main/java/net/moonleay/gimble/datagen/DataGenerator.kt
Normal file
|
@ -0,0 +1,15 @@
|
|||
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))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
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")
|
||||
|
||||
}
|
||||
}
|
66
src/main/java/net/moonleay/gimble/mixin/HudMixin.java
Normal file
66
src/main/java/net/moonleay/gimble/mixin/HudMixin.java
Normal file
|
@ -0,0 +1,66 @@
|
|||
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.minecraft.text.Text;
|
||||
import net.moonleay.gimble.client.editor.ClientEditor;
|
||||
import net.moonleay.gimble.client.editor.modes.Mode;
|
||||
import net.moonleay.gimble.client.editor.modes.ModeModifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(InGameHud.class)
|
||||
public class HudMixin {
|
||||
|
||||
@Shadow @Final private MinecraftClient client;
|
||||
|
||||
@Inject(method = "renderStatusEffectOverlay", at = @At("HEAD"))
|
||||
private void render(MatrixStack matrices, CallbackInfo ci) {
|
||||
Mode currentMode = ClientEditor.INSTANCE.getCurrentMode();
|
||||
StringBuilder displayText = getStringBuilder(currentMode);
|
||||
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
TextRenderer tr = mc.textRenderer;
|
||||
// int screenWidth = mc.getWindow().getWidth();
|
||||
// int screenHeight = mc.getWindow().getHeight();
|
||||
// int scale = (mc.options.getGuiScale().getValue() == 0 ? 1 : mc.options.getGuiScale().getValue());
|
||||
// int bottomY = screenHeight / scale - 4 - tr.fontHeight - 12;
|
||||
|
||||
tr.drawWithShadow(matrices,
|
||||
Text.of(displayText.toString()),
|
||||
4, 4,
|
||||
currentMode.getColor());
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static @NotNull StringBuilder getStringBuilder(Mode currentMode) {
|
||||
List<ModeModifier> currentModifier = ClientEditor.INSTANCE.getCurrentModifier();
|
||||
StringBuilder displayText = new StringBuilder(currentMode.getDisplayName());
|
||||
if (!currentModifier.isEmpty()) {
|
||||
displayText.append(" [");
|
||||
for (int i = 0; i < currentModifier.size(); i++) {
|
||||
displayText.append(currentModifier.get(i).getDisplayName());
|
||||
if (i != currentModifier.size() - 1) {
|
||||
displayText.append(", ");
|
||||
}
|
||||
}
|
||||
displayText.append("]");
|
||||
}
|
||||
return displayText;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private int getXRight(String txt, int screenWidth) {
|
||||
return screenWidth / (MinecraftClient.getInstance().options.getGuiScale().getValue() == 0 ? 1 : MinecraftClient.getInstance().options.getGuiScale().getValue()) - 4 - MinecraftClient.getInstance().textRenderer.getWidth(Text.of(txt));
|
||||
}
|
||||
}
|
15
src/main/java/net/moonleay/gimble/mixin/KeyMixin.java
Normal file
15
src/main/java/net/moonleay/gimble/mixin/KeyMixin.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package net.moonleay.gimble.mixin;
|
||||
|
||||
import net.minecraft.client.Keyboard;
|
||||
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(Keyboard.class)
|
||||
public class KeyMixin {
|
||||
// This Mixin is not registered. This will be used to handle key events with static Buttons.
|
||||
@Inject(method = "onKey", at = @At("TAIL"))
|
||||
private void onKey(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) {
|
||||
}
|
||||
}
|
21
src/main/java/net/moonleay/gimble/mixin/NoClipCameraFix.java
Normal file
21
src/main/java/net/moonleay/gimble/mixin/NoClipCameraFix.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package net.moonleay.gimble.mixin;
|
||||
|
||||
import net.minecraft.client.render.Camera;
|
||||
import net.moonleay.gimble.client.editor.ClientEditor;
|
||||
import net.moonleay.gimble.client.editor.modes.ModeModifier;
|
||||
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 NoClipCameraFix {
|
||||
|
||||
@Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true)
|
||||
private void fixCameraInNoClip(double desiredCameraDistance, CallbackInfoReturnable<Double> cir) {
|
||||
if (ClientEditor.INSTANCE.containsModifier(ModeModifier.NO_CLIP)){
|
||||
cir.setReturnValue(desiredCameraDistance);
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
32
src/main/java/net/moonleay/gimble/mixin/NoClipMixin.java
Normal file
32
src/main/java/net/moonleay/gimble/mixin/NoClipMixin.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package net.moonleay.gimble.mixin;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.moonleay.gimble.client.editor.ClientEditor;
|
||||
import net.moonleay.gimble.client.editor.modes.ModeModifier;
|
||||
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(Entity.class)
|
||||
public class NoClipMixin {
|
||||
|
||||
@Shadow public boolean noClip;
|
||||
|
||||
@Inject(method = "tick", at = @At(value = "HEAD"))
|
||||
private void enoClip(CallbackInfo ci) {
|
||||
// TODO: Add player check, add multiplayer compat
|
||||
if(!((Entity)(Object)this instanceof PlayerEntity)) // Only check on player
|
||||
return;
|
||||
|
||||
if (!ClientEditor.INSTANCE.containsModifier(ModeModifier.NO_CLIP))
|
||||
return;
|
||||
PlayerEntity thePlayer = (PlayerEntity)(Object)this;
|
||||
if (!thePlayer.getAbilities().flying)
|
||||
return;
|
||||
|
||||
this.noClip = true;
|
||||
}
|
||||
}
|
45
src/main/java/net/moonleay/gimble/mixin/NormalModeMixin.java
Normal file
45
src/main/java/net/moonleay/gimble/mixin/NormalModeMixin.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package net.moonleay.gimble.mixin;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.option.GameOptions;
|
||||
import net.moonleay.gimble.client.editor.modes.Mode;
|
||||
import net.moonleay.gimble.client.editor.ClientEditor;
|
||||
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;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public class NormalModeMixin {
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public GameOptions options;
|
||||
|
||||
@Inject(method = "openPauseMenu", at = @At("HEAD"), cancellable = true)
|
||||
private void setNormalMode(boolean pause, CallbackInfo ci) {
|
||||
if (ClientEditor.INSTANCE.getCURRENT_MODE() != Mode.NORMAL){
|
||||
// Set the editor mode to normal
|
||||
ClientEditor.INSTANCE.setCURRENT_MODE(Mode.NORMAL);
|
||||
ClientEditor.INSTANCE.checkForIncompatibleModeModifiers();
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z"), cancellable = true)
|
||||
private void blockWorldManipulation(CallbackInfo ci) { // This could be replaced by net.minecraft.world.GameMode#isBlockBreakingRestricted
|
||||
if (ClientEditor.INSTANCE.getCURRENT_MODE() == Mode.NORMAL || ClientEditor.INSTANCE.getCURRENT_MODE() == Mode.VISUAL) {
|
||||
while(this.options.attackKey.wasPressed()) {
|
||||
}
|
||||
|
||||
while(this.options.useKey.wasPressed()) {
|
||||
}
|
||||
|
||||
while(this.options.pickItemKey.wasPressed()) {
|
||||
}
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
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.client.editor.modes.Mode;
|
||||
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) {
|
||||
// Check if should run
|
||||
if (!ClientEditor.INSTANCE.getCURRENT_MODE().equals(Mode.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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue