Skip to content

Commit cc12d28

Browse files
authored
Fix several intertwined input bugs (#5480)
- Input.isPressed() accurately reflects keyboard inputs - Freecam is not affected by other modules' movement inputs (e.g. AutoWalk) - GUIMove does not continuously override key states or emit KeyEvents - GUIMove arrow keys interact correctly with Freecam
1 parent 7fe9330 commit cc12d28

6 files changed

Lines changed: 123 additions & 81 deletions

File tree

src/main/java/meteordevelopment/meteorclient/mixin/KeyBindingAccessor.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import net.minecraft.client.util.InputUtil;
1010
import org.spongepowered.asm.mixin.Mixin;
1111
import org.spongepowered.asm.mixin.gen.Accessor;
12+
import org.spongepowered.asm.mixin.gen.Invoker;
1213

1314
import java.util.Map;
1415

@@ -17,6 +18,9 @@ public interface KeyBindingAccessor {
1718
@Accessor("CATEGORY_ORDER_MAP")
1819
static Map<String, Integer> getCategoryOrderMap() { return null; }
1920

21+
@Accessor("KEYS_BY_ID")
22+
static Map<String, KeyBinding> getKeysById() { return null; }
23+
2024
@Accessor("boundKey")
2125
InputUtil.Key getKey();
2226

@@ -25,4 +29,7 @@ public interface KeyBindingAccessor {
2529

2630
@Accessor("timesPressed")
2731
void meteor$setTimesPressed(int timesPressed);
32+
33+
@Invoker("reset")
34+
void invokeReset();
2835
}

src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
99
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
1010
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
11+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
12+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
1113
import com.llamalad7.mixinextras.sugar.Local;
1214
import meteordevelopment.meteorclient.MeteorClient;
1315
import meteordevelopment.meteorclient.events.entity.player.ItemUseCrosshairTargetEvent;
@@ -21,6 +23,7 @@
2123
import meteordevelopment.meteorclient.renderer.MeteorRenderPipelines;
2224
import meteordevelopment.meteorclient.systems.config.Config;
2325
import meteordevelopment.meteorclient.systems.modules.Modules;
26+
import meteordevelopment.meteorclient.systems.modules.movement.GUIMove;
2427
import meteordevelopment.meteorclient.systems.modules.player.FastUse;
2528
import meteordevelopment.meteorclient.systems.modules.player.Multitask;
2629
import meteordevelopment.meteorclient.systems.modules.render.ESP;
@@ -37,6 +40,7 @@
3740
import net.minecraft.client.network.ClientPlayerEntity;
3841
import net.minecraft.client.network.ClientPlayerInteractionManager;
3942
import net.minecraft.client.option.GameOptions;
43+
import net.minecraft.client.option.KeyBinding;
4044
import net.minecraft.client.util.Window;
4145
import net.minecraft.client.world.ClientWorld;
4246
import net.minecraft.entity.Entity;
@@ -149,6 +153,33 @@ private void onSetScreen(Screen screen, CallbackInfo info) {
149153
if (event.isCancelled()) info.cancel();
150154
}
151155

156+
@WrapOperation(method = "setScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;unpressAll()V"))
157+
private void onSetScreenKeyBindingUnpressAll(Operation<Void> op) {
158+
Modules modules = Modules.get();
159+
if (modules == null) {
160+
op.call();
161+
return;
162+
}
163+
164+
GUIMove guimove = modules.get(GUIMove.class);
165+
if (guimove == null || !guimove.isActive() || guimove.skip()) {
166+
op.call();
167+
return;
168+
}
169+
170+
GameOptions options = MeteorClient.mc.options;
171+
for (KeyBinding kb : KeyBindingAccessor.getKeysById().values()) {
172+
if (kb == options.forwardKey) continue;
173+
if (kb == options.leftKey) continue;
174+
if (kb == options.rightKey) continue;
175+
if (kb == options.backKey) continue;
176+
if (guimove.sneak.get() && kb == options.sneakKey) continue;
177+
if (guimove.sprint.get() && kb == options.sprintKey) continue;
178+
if (guimove.jump.get() && kb == options.jumpKey) continue;
179+
((KeyBindingAccessor) kb).invokeReset();
180+
}
181+
}
182+
152183
@Inject(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isItemEnabled(Lnet/minecraft/resource/featuretoggle/FeatureSet;)Z"))
153184
private void onDoItemUseHand(CallbackInfo ci, @Local ItemStack itemStack) {
154185
FastUse fastUse = Modules.get().get(FastUse.class);

src/main/java/meteordevelopment/meteorclient/systems/modules/movement/AutoWalk.java

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,17 @@
1212
import meteordevelopment.meteorclient.mixininterface.IVec3d;
1313
import meteordevelopment.meteorclient.pathing.NopPathManager;
1414
import meteordevelopment.meteorclient.pathing.PathManagers;
15-
import meteordevelopment.meteorclient.settings.*;
15+
import meteordevelopment.meteorclient.settings.BoolSetting;
16+
import meteordevelopment.meteorclient.settings.EnumSetting;
1617
import meteordevelopment.meteorclient.settings.Setting;
1718
import meteordevelopment.meteorclient.settings.SettingGroup;
1819
import meteordevelopment.meteorclient.systems.modules.Categories;
1920
import meteordevelopment.meteorclient.systems.modules.Module;
2021
import meteordevelopment.meteorclient.systems.modules.Modules;
21-
import meteordevelopment.meteorclient.systems.modules.movement.GUIMove;
2222
import meteordevelopment.meteorclient.utils.Utils;
23-
import meteordevelopment.meteorclient.utils.misc.input.Input;
2423
import meteordevelopment.meteorclient.utils.misc.input.KeyAction;
2524
import meteordevelopment.orbit.EventHandler;
2625
import meteordevelopment.orbit.EventPriority;
27-
import net.minecraft.client.option.KeyBinding;
2826

2927
public class AutoWalk extends Module {
3028
private final SettingGroup sgGeneral = settings.getDefaultGroup();
@@ -105,10 +103,10 @@ private void onTick(TickEvent.Pre event) {
105103
}
106104

107105
switch (direction.get()) {
108-
case Forwards -> setPressed(mc.options.forwardKey, true);
109-
case Backwards -> setPressed(mc.options.backKey, true);
110-
case Left -> setPressed(mc.options.leftKey, true);
111-
case Right -> setPressed(mc.options.rightKey, true);
106+
case Forwards -> mc.options.forwardKey.setPressed(true);
107+
case Backwards -> mc.options.backKey.setPressed(true);
108+
case Left -> mc.options.leftKey.setPressed(true);
109+
case Right -> mc.options.rightKey.setPressed(true);
112110
}
113111
} else {
114112
if (PathManagers.get() instanceof NopPathManager) {
@@ -150,15 +148,10 @@ private void onPlayerMove(PlayerMoveEvent event) {
150148
}
151149

152150
private void unpress() {
153-
setPressed(mc.options.forwardKey, false);
154-
setPressed(mc.options.backKey, false);
155-
setPressed(mc.options.leftKey, false);
156-
setPressed(mc.options.rightKey, false);
157-
}
158-
159-
private void setPressed(KeyBinding key, boolean pressed) {
160-
key.setPressed(pressed);
161-
Input.setKeyState(key, pressed);
151+
mc.options.forwardKey.setPressed(false);
152+
mc.options.backKey.setPressed(false);
153+
mc.options.leftKey.setPressed(false);
154+
mc.options.rightKey.setPressed(false);
162155
}
163156

164157
private boolean isMovementKey(int key) {

src/main/java/meteordevelopment/meteorclient/systems/modules/movement/GUIMove.java

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,24 @@
55

66
package meteordevelopment.meteorclient.systems.modules.movement;
77

8-
import meteordevelopment.meteorclient.MeteorClient;
9-
import meteordevelopment.meteorclient.events.entity.player.PlayerTickMovementEvent;
8+
import meteordevelopment.meteorclient.events.game.OpenScreenEvent;
109
import meteordevelopment.meteorclient.events.meteor.KeyEvent;
10+
import meteordevelopment.meteorclient.events.meteor.MouseButtonEvent;
1111
import meteordevelopment.meteorclient.events.render.Render3DEvent;
1212
import meteordevelopment.meteorclient.gui.WidgetScreen;
1313
import meteordevelopment.meteorclient.mixin.CreativeInventoryScreenAccessor;
14-
import meteordevelopment.meteorclient.mixin.KeyBindingAccessor;
1514
import meteordevelopment.meteorclient.settings.*;
1615
import meteordevelopment.meteorclient.systems.modules.Categories;
1716
import meteordevelopment.meteorclient.systems.modules.Module;
17+
import meteordevelopment.meteorclient.systems.modules.Modules;
18+
import meteordevelopment.meteorclient.systems.modules.render.Freecam;
1819
import meteordevelopment.meteorclient.utils.misc.input.Input;
1920
import meteordevelopment.meteorclient.utils.misc.input.KeyAction;
2021
import meteordevelopment.orbit.EventHandler;
22+
import meteordevelopment.orbit.EventPriority;
2123
import net.minecraft.client.gui.screen.ChatScreen;
2224
import net.minecraft.client.gui.screen.ingame.*;
2325
import net.minecraft.client.option.KeyBinding;
24-
import net.minecraft.client.util.InputUtil;
2526
import net.minecraft.item.ItemGroups;
2627
import net.minecraft.util.math.MathHelper;
2728

@@ -43,22 +44,22 @@ public enum Screens {
4344
.build()
4445
);
4546

46-
private final Setting<Boolean> jump = sgGeneral.add(new BoolSetting.Builder()
47+
public final Setting<Boolean> jump = sgGeneral.add(new BoolSetting.Builder()
4748
.name("jump")
4849
.description("Allows you to jump while in GUIs.")
4950
.defaultValue(true)
5051
.onChanged(aBoolean -> {
51-
if (isActive() && !aBoolean) set(mc.options.jumpKey, false);
52+
if (isActive() && !aBoolean) mc.options.jumpKey.setPressed(false);
5253
})
5354
.build()
5455
);
5556

56-
private final Setting<Boolean> sneak = sgGeneral.add(new BoolSetting.Builder()
57+
public final Setting<Boolean> sneak = sgGeneral.add(new BoolSetting.Builder()
5758
.name("sneak")
5859
.description("Allows you to sneak while in GUIs.")
5960
.defaultValue(true)
6061
.onChanged(aBoolean -> {
61-
if (isActive() && !aBoolean) set(mc.options.sneakKey, false);
62+
if (isActive() && !aBoolean) mc.options.sneakKey.setPressed(false);
6263
})
6364
.build()
6465
);
@@ -68,7 +69,7 @@ public enum Screens {
6869
.description("Allows you to sprint while in GUIs.")
6970
.defaultValue(true)
7071
.onChanged(aBoolean -> {
71-
if (isActive() && !aBoolean) set(mc.options.sprintKey, false);
72+
if (isActive() && !aBoolean) mc.options.sprintKey.setPressed(false);
7273
})
7374
.build()
7475
);
@@ -94,14 +95,14 @@ public GUIMove() {
9495

9596
@Override
9697
public void onDeactivate() {
97-
set(mc.options.forwardKey, false);
98-
set(mc.options.backKey, false);
99-
set(mc.options.leftKey, false);
100-
set(mc.options.rightKey, false);
101-
102-
if (jump.get()) set(mc.options.jumpKey, false);
103-
if (sneak.get()) set(mc.options.sneakKey, false);
104-
if (sprint.get()) set(mc.options.sprintKey, false);
98+
mc.options.forwardKey.setPressed(false);
99+
mc.options.backKey.setPressed(false);
100+
mc.options.leftKey.setPressed(false);
101+
mc.options.rightKey.setPressed(false);
102+
103+
if (jump.get()) mc.options.jumpKey.setPressed(false);
104+
if (sneak.get()) mc.options.sneakKey.setPressed(false);
105+
if (sprint.get()) mc.options.sprintKey.setPressed(false);
105106
}
106107

107108
public boolean disableSpace() {
@@ -111,20 +112,29 @@ public boolean disableArrows() {
111112
return isActive() && arrowsRotate.get();
112113
}
113114

114-
@EventHandler
115-
private void onPlayerMoveEvent(PlayerTickMovementEvent event) {
115+
private void onInput(int key, KeyAction action, boolean mouse) {
116116
if (skip()) return;
117117
if (screens.get() == Screens.GUI && !(mc.currentScreen instanceof WidgetScreen)) return;
118118
if (screens.get() == Screens.Inventory && mc.currentScreen instanceof WidgetScreen) return;
119119

120-
set(mc.options.forwardKey, Input.isPressed(mc.options.forwardKey));
121-
set(mc.options.backKey, Input.isPressed(mc.options.backKey));
122-
set(mc.options.leftKey, Input.isPressed(mc.options.leftKey));
123-
set(mc.options.rightKey, Input.isPressed(mc.options.rightKey));
120+
pass(mc.options.forwardKey, key, action, mouse);
121+
pass(mc.options.backKey, key, action, mouse);
122+
pass(mc.options.leftKey, key, action, mouse);
123+
pass(mc.options.rightKey, key, action, mouse);
124+
125+
if (jump.get()) pass(mc.options.jumpKey, key, action, mouse);
126+
if (sneak.get()) pass(mc.options.sneakKey, key, action, mouse);
127+
if (sprint.get()) pass(mc.options.sprintKey, key, action, mouse);
128+
}
124129

125-
if (jump.get()) set(mc.options.jumpKey, Input.isPressed(mc.options.jumpKey));
126-
if (sneak.get()) set(mc.options.sneakKey, Input.isPressed(mc.options.sneakKey));
127-
if (sprint.get()) set(mc.options.sprintKey, Input.isPressed(mc.options.sprintKey));
130+
@EventHandler
131+
private void onKey(KeyEvent event) {
132+
onInput(event.key, event.action, false);
133+
}
134+
135+
@EventHandler
136+
private void onButton(MouseButtonEvent event) {
137+
onInput(event.button, event.action, true);
128138
}
129139

130140
@EventHandler
@@ -135,31 +145,40 @@ private void onRender3D(Render3DEvent event) {
135145

136146
float rotationDelta = Math.min((float) (rotateSpeed.get() * event.frameTime * 20f), 100);
137147

148+
Freecam freecam = Modules.get().get(Freecam.class);
149+
138150
if (arrowsRotate.get()) {
139-
float yaw = mc.player.getYaw();
140-
float pitch = mc.player.getPitch();
151+
if (!freecam.isActive()) {
152+
float yaw = mc.player.getYaw();
153+
float pitch = mc.player.getPitch();
154+
155+
if (Input.isKeyPressed(GLFW_KEY_LEFT)) yaw -= rotationDelta;
156+
if (Input.isKeyPressed(GLFW_KEY_RIGHT)) yaw += rotationDelta;
157+
if (Input.isKeyPressed(GLFW_KEY_UP)) pitch -= rotationDelta;
158+
if (Input.isKeyPressed(GLFW_KEY_DOWN)) pitch += rotationDelta;
141159

142-
if (Input.isKeyPressed(GLFW_KEY_LEFT)) yaw -= rotationDelta;
143-
if (Input.isKeyPressed(GLFW_KEY_RIGHT)) yaw += rotationDelta;
144-
if (Input.isKeyPressed(GLFW_KEY_UP)) pitch -= rotationDelta;
145-
if (Input.isKeyPressed(GLFW_KEY_DOWN)) pitch += rotationDelta;
160+
pitch = MathHelper.clamp(pitch, -90, 90);
146161

162+
mc.player.setYaw(yaw);
163+
mc.player.setPitch(pitch);
164+
} else {
165+
double dy = 0, dx = 0;
147166

148-
pitch = MathHelper.clamp(pitch, -90, 90);
167+
if (Input.isKeyPressed(GLFW_KEY_LEFT)) dy = -rotationDelta;
168+
if (Input.isKeyPressed(GLFW_KEY_RIGHT)) dy = rotationDelta;
169+
if (Input.isKeyPressed(GLFW_KEY_UP)) dx = -rotationDelta;
170+
if (Input.isKeyPressed(GLFW_KEY_DOWN)) dx = rotationDelta;
149171

150-
mc.player.setYaw(yaw);
151-
mc.player.setPitch(pitch);
172+
freecam.changeLookDirection(dy, dx);
173+
}
152174
}
153175
}
154176

155-
private void set(KeyBinding bind, boolean pressed) {
156-
boolean wasPressed = bind.isPressed();
157-
bind.setPressed(pressed);
158-
159-
InputUtil.Key key = ((KeyBindingAccessor) bind).getKey();
160-
if (wasPressed != pressed && key.getCategory() == InputUtil.Type.KEYSYM) {
161-
MeteorClient.EVENT_BUS.post(KeyEvent.get(key.getCode(), 0, pressed ? KeyAction.Press : KeyAction.Release));
162-
}
177+
private void pass(KeyBinding bind, int key, KeyAction action, boolean mouse) {
178+
if (!mouse && !bind.matchesKey(key, 0)) return;
179+
if (mouse && !bind.matchesMouse(key)) return;
180+
if (action == KeyAction.Press) bind.setPressed(true);
181+
if (action == KeyAction.Release) bind.setPressed(false);
163182
}
164183

165184
public boolean skip() {

src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/modes/Bounce.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
import meteordevelopment.meteorclient.events.packets.PacketEvent;
1313
import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.ElytraFlightMode;
1414
import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.ElytraFlightModes;
15-
import meteordevelopment.meteorclient.utils.misc.input.Input;
1615
import net.minecraft.client.network.ClientPlayerEntity;
17-
import net.minecraft.client.option.KeyBinding;
1816
import net.minecraft.component.DataComponentTypes;
1917
import net.minecraft.entity.EquipmentSlot;
2018
import net.minecraft.entity.effect.StatusEffects;
@@ -43,8 +41,8 @@ public void onTick() {
4341
if (checkConditions(mc.player)) {
4442
if (!rubberbanded) {
4543
if (prevFov != 0 && !elytraFly.sprint.get()) mc.options.getFovEffectScale().setValue(0.0); // This stops the FOV effects from constantly going on and off.
46-
if (elytraFly.autoJump.get()) setPressed(mc.options.jumpKey, true);
47-
setPressed(mc.options.forwardKey, true);
44+
if (elytraFly.autoJump.get()) mc.options.jumpKey.setPressed(true);
45+
mc.options.forwardKey.setPressed(true);
4846
mc.player.setYaw(getYawDirection());
4947
if (elytraFly.lockPitch.get()) mc.player.setPitch(elytraFly.pitch.get().floatValue());
5048
}
@@ -76,8 +74,8 @@ public void onPreTick() {
7674
}
7775

7876
private void unpress() {
79-
setPressed(mc.options.forwardKey, false);
80-
if (elytraFly.autoJump.get()) setPressed(mc.options.jumpKey, false);
77+
mc.options.forwardKey.setPressed(false);
78+
if (elytraFly.autoJump.get()) mc.options.jumpKey.setPressed(false);
8179
}
8280

8381
@Override
@@ -95,12 +93,6 @@ public void onPacketSend(PacketEvent.Send event) {
9593
}
9694
}
9795

98-
99-
private void setPressed(KeyBinding key, boolean pressed) {
100-
key.setPressed(pressed);
101-
Input.setKeyState(key, pressed);
102-
}
103-
10496
public static boolean recastElytra(ClientPlayerEntity player) {
10597
if (checkConditions(player) && ignoreGround(player)) {
10698
player.networkHandler.sendPacket(new ClientCommandC2SPacket(player, ClientCommandC2SPacket.Mode.START_FALL_FLYING));

0 commit comments

Comments
 (0)