Skip to content

Commit

Permalink
Fix: Custom Garden Keybinds (#2948)
Browse files Browse the repository at this point in the history
Co-authored-by: Empa <itsempa@users.noreply.github.com>
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 20, 2024
1 parent 4b0618b commit 2a1d09f
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 91 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package at.hannibal2.skyhanni.config.features.garden;

import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.features.garden.farming.GardenCustomKeybinds;
import at.hannibal2.skyhanni.utils.KeyboardManager;
import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton;
import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind;
import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
import net.minecraft.client.Minecraft;
import io.github.notenoughupdates.moulconfig.observer.Property;
import org.lwjgl.input.Keyboard;

public class KeyBindConfig {
Expand All @@ -23,70 +25,49 @@ public class KeyBindConfig {

@ConfigOption(name = "Disable All", desc = "Disable all keys.")
@ConfigEditorButton(buttonText = "Disable")
public Runnable presetDisable = () -> {
attack = Keyboard.KEY_NONE;
useItem = Keyboard.KEY_NONE;
left = Keyboard.KEY_NONE;
right = Keyboard.KEY_NONE;
forward = Keyboard.KEY_NONE;
back = Keyboard.KEY_NONE;
jump = Keyboard.KEY_NONE;
sneak = Keyboard.KEY_NONE;

Minecraft.getMinecraft().thePlayer.closeScreen();
};
public Runnable presetDisable = GardenCustomKeybinds::disableAll;

@ConfigOption(name = "Set Default", desc = "Reset all keys to default.")
@ConfigEditorButton(buttonText = "Default")
public Runnable presetDefault = () -> {
attack = -100;
useItem = -99;
left = Keyboard.KEY_A;
right = Keyboard.KEY_D;
forward = Keyboard.KEY_W;
back = Keyboard.KEY_S;
jump = Keyboard.KEY_SPACE;
sneak = Keyboard.KEY_LSHIFT;
Minecraft.getMinecraft().thePlayer.closeScreen();
};
public Runnable presetDefault = GardenCustomKeybinds::defaultAll;

@Expose
@ConfigOption(name = "Attack", desc = "")
@ConfigEditorKeybind(defaultKey = -100)
public int attack = -100;
@ConfigEditorKeybind(defaultKey = KeyboardManager.LEFT_MOUSE)
public Property<Integer> attack = Property.of(KeyboardManager.LEFT_MOUSE);

@Expose
@ConfigOption(name = "Use Item", desc = "")
@ConfigEditorKeybind(defaultKey = -99)
public int useItem = -99;
@ConfigEditorKeybind(defaultKey = KeyboardManager.RIGHT_MOUSE)
public Property<Integer> useItem = Property.of(KeyboardManager.RIGHT_MOUSE);

@Expose
@ConfigOption(name = "Move Left", desc = "")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_A)
public int left = Keyboard.KEY_A;
public Property<Integer> left = Property.of(Keyboard.KEY_A);

@Expose
@ConfigOption(name = "Move Right", desc = "")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_D)
public int right = Keyboard.KEY_D;
public Property<Integer> right = Property.of(Keyboard.KEY_D);

@Expose
@ConfigOption(name = "Move Forward", desc = "")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_W)
public int forward = Keyboard.KEY_W;
public Property<Integer> forward = Property.of(Keyboard.KEY_W);

@Expose
@ConfigOption(name = "Move Back", desc = "")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_S)
public int back = Keyboard.KEY_S;
public Property<Integer> back = Property.of(Keyboard.KEY_S);

@Expose
@ConfigOption(name = "Jump", desc = "")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_SPACE)
public int jump = Keyboard.KEY_SPACE;
public Property<Integer> jump = Property.of(Keyboard.KEY_SPACE);

@Expose
@ConfigOption(name = "Sneak", desc = "")
@ConfigEditorKeybind(defaultKey = Keyboard.KEY_LSHIFT)
public int sneak = Keyboard.KEY_LSHIFT;
public Property<Integer> sneak = Property.of(Keyboard.KEY_LSHIFT);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
package at.hannibal2.skyhanni.features.garden.farming

import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.events.ConfigLoadEvent
import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.SecondPassedEvent
import at.hannibal2.skyhanni.features.garden.GardenAPI
import at.hannibal2.skyhanni.mixins.transformers.AccessorKeyBinding
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.ChatUtils
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld
import at.hannibal2.skyhanni.utils.ConditionalUtils
import at.hannibal2.skyhanni.utils.KeyboardManager
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import io.github.notenoughupdates.moulconfig.observer.Property
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.inventory.GuiEditSign
import net.minecraft.client.settings.KeyBinding
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.input.Keyboard
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
import java.util.IdentityHashMap
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

Expand All @@ -24,71 +29,119 @@ object GardenCustomKeybinds {
private val config get() = GardenAPI.config.keyBind
private val mcSettings get() = Minecraft.getMinecraft().gameSettings

private val map: MutableMap<KeyBinding, () -> Int> = IdentityHashMap()
private var map: Map<KeyBinding, Int> = emptyMap()
private var lastWindowOpenTime = SimpleTimeMark.farPast()
private var lastDuplicateKeybindsWarnTime = SimpleTimeMark.farPast()
private var isDuplicate = false

init {
map[mcSettings.keyBindAttack] = { config.attack }
map[mcSettings.keyBindUseItem] = { config.useItem }
map[mcSettings.keyBindLeft] = { config.left }
map[mcSettings.keyBindRight] = { config.right }
map[mcSettings.keyBindForward] = { config.forward }
map[mcSettings.keyBindBack] = { config.back }
map[mcSettings.keyBindJump] = { config.jump }
map[mcSettings.keyBindSneak] = { config.sneak }
private fun Int.keybind() = (mcSettings.keyBindAttack as AccessorKeyBinding).hash_skyhanni.lookup(this)
?: ErrorManager.skyHanniError("Keybind $this not found")

@JvmStatic
fun isKeyDown(keyBinding: KeyBinding, cir: CallbackInfoReturnable<Boolean>) {
if (!isActive()) return
val override = map[keyBinding]?.keybind() ?: return
val accessor = override as AccessorKeyBinding
cir.returnValue = accessor.pressed_skyhanni
}

private fun isEnabled() = GardenAPI.inGarden() && config.enabled && !(GardenAPI.onBarnPlot && config.excludeBarn)
@JvmStatic
fun isKeyPressed(keyBinding: KeyBinding, cir: CallbackInfoReturnable<Boolean>) {
if (!isActive()) return
val override = map[keyBinding] ?: return
cir.returnValue = override.isKeyClicked()
}

@SubscribeEvent
fun onTick(event: LorenzTickEvent) {
if (!isEnabled()) return
val screen = Minecraft.getMinecraft().currentScreen ?: return
if (screen !is GuiEditSign) return
lastWindowOpenTime = SimpleTimeMark.now()
}

private fun isActive(): Boolean {
if (!isEnabled()) return false
if (GardenAPI.toolInHand == null) return false
@SubscribeEvent
fun onSecondPassed(event: SecondPassedEvent) {
if (!isEnabled()) return
if (!isDuplicate || lastDuplicateKeybindsWarnTime.passedSince() < 30.seconds) return
ChatUtils.chatAndOpenConfig(
"Duplicate Custom Keybinds aren't allowed!",
GardenAPI.config::keyBind,
)
lastDuplicateKeybindsWarnTime = SimpleTimeMark.now()
}

if (Minecraft.getMinecraft().currentScreen != null) {
if (Minecraft.getMinecraft().currentScreen is GuiEditSign) {
lastWindowOpenTime = SimpleTimeMark.now()
@SubscribeEvent
fun onConfigLoad(event: ConfigLoadEvent) {
with(config) {
ConditionalUtils.onToggle(attack, useItem, left, right, forward, back, jump, sneak) {
update()
}
return false
update()
}
}

// TODO remove workaround
if (lastWindowOpenTime.passedSince() < 300.milliseconds) return false

val areDuplicates = map.values
.map { it() }
.filter { it != Keyboard.KEY_NONE }
.let { values -> values.size != values.toSet().size }
if (areDuplicates) {
if (lastDuplicateKeybindsWarnTime.passedSince() > 30.seconds) {
ChatUtils.chatAndOpenConfig(
"Duplicate Custom Keybinds aren't allowed!",
GardenAPI.config::keyBind
)
lastDuplicateKeybindsWarnTime = SimpleTimeMark.now()
private fun update() {
with(config) {
with(mcSettings) {
map = buildMap {
fun add(keyBinding: KeyBinding, property: Property<Int>) {
val value = property.get()
if (value != keyBinding.keyCode) put(keyBinding, value)
}
add(keyBindAttack, attack)
add(keyBindUseItem, useItem)
add(keyBindLeft, left)
add(keyBindRight, right)
add(keyBindForward, forward)
add(keyBindBack, back)
add(keyBindJump, jump)
add(keyBindSneak, sneak)
}
}
return false
}
calculateDuplicates()
lastDuplicateKeybindsWarnTime = SimpleTimeMark.farPast()
KeyBinding.unPressAllKeys()
}

return true
private fun calculateDuplicates() {
isDuplicate = map.values
.filter { it != Keyboard.KEY_NONE }
.let { values -> values.size != values.toSet().size }
}

private fun isEnabled() = GardenAPI.inGarden() && config.enabled && !(GardenAPI.onBarnPlot && config.excludeBarn)

private fun isActive(): Boolean =
isEnabled() && GardenAPI.toolInHand != null && !isDuplicate && lastWindowOpenTime.passedSince() > 300.milliseconds

@JvmStatic
fun isKeyDown(keyBinding: KeyBinding, cir: CallbackInfoReturnable<Boolean>) {
if (!isActive()) return
val override = map[keyBinding] ?: return
val keyCode = override()
cir.returnValue = keyCode.isKeyHeld()
fun disableAll() {
with(config) {
attack.set(Keyboard.KEY_NONE)
useItem.set(Keyboard.KEY_NONE)
left.set(Keyboard.KEY_NONE)
right.set(Keyboard.KEY_NONE)
forward.set(Keyboard.KEY_NONE)
back.set(Keyboard.KEY_NONE)
jump.set(Keyboard.KEY_NONE)
sneak.set(Keyboard.KEY_NONE)
}
}

@JvmStatic
fun onTick(keyCode: Int, ci: CallbackInfo) {
if (!isActive()) return
if (keyCode == 0) return
val keyBinding = map.entries.firstOrNull { it.value() == keyCode }?.key ?: return
ci.cancel()
keyBinding as AccessorKeyBinding
keyBinding.pressTime_skyhanni++
fun defaultAll() {
with(config) {
attack.set(KeyboardManager.LEFT_MOUSE)
useItem.set(KeyboardManager.RIGHT_MOUSE)
left.set(Keyboard.KEY_A)
right.set(Keyboard.KEY_D)
forward.set(Keyboard.KEY_W)
back.set(Keyboard.KEY_S)
jump.set(Keyboard.KEY_SPACE)
sneak.set(Keyboard.KEY_LSHIFT)
}
}

@SubscribeEvent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package at.hannibal2.skyhanni.mixins.transformers;

import net.minecraft.client.settings.KeyBinding;
import net.minecraft.util.IntHashMap;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(KeyBinding.class)
public interface AccessorKeyBinding {

@Accessor("pressTime")
int getPressTime_skyhanni();
@Accessor("pressed")
boolean getPressed_skyhanni();

@Accessor("pressTime")
void setPressTime_skyhanni(int pressTime);
@Accessor("hash")
IntHashMap<KeyBinding> getHash_skyhanni();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@

@Mixin(KeyBinding.class)
public class MixinKeyBinding {
@Inject(method = "onTick", at = @At("HEAD"), cancellable = true)
private static void noOnTick(int keyCode, CallbackInfo ci) {
GardenCustomKeybinds.onTick(keyCode, ci);
}

@Inject(method = "isKeyDown", at = @At("HEAD"), cancellable = true)
public void noIsKeyDown(CallbackInfoReturnable<Boolean> cir) {
Expand All @@ -26,6 +22,7 @@ public void noIsKeyDown(CallbackInfoReturnable<Boolean> cir) {

@Inject(method = "isPressed", at = @At("HEAD"), cancellable = true)
public void noIsPressed(CallbackInfoReturnable<Boolean> cir) {
GardenCustomKeybinds.isKeyPressed((KeyBinding) (Object) this, cir);
TextInput.Companion.onMinecraftInput((KeyBinding) (Object) this, cir);
GraphEditor.INSTANCE.onMinecraftInput((KeyBinding) (Object) this, cir);
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/utils/KeyboardManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import org.lwjgl.input.Mouse
@SkyHanniModule
object KeyboardManager {

const val LEFT_MOUSE = -100
const val RIGHT_MOUSE = -99

private var lastClickedMouseButton = -1

// A mac-only key, represents Windows key on windows (but different key code)
Expand Down

0 comments on commit 2a1d09f

Please sign in to comment.