diff --git a/src/main/java/net/wurstclient/WurstClient.java b/src/main/java/net/wurstclient/WurstClient.java index b10e451c..c3b3a5b9 100644 --- a/src/main/java/net/wurstclient/WurstClient.java +++ b/src/main/java/net/wurstclient/WurstClient.java @@ -18,7 +18,10 @@ import net.wurstclient.command.CmdList; import net.wurstclient.command.CmdProcessor; import net.wurstclient.event.EventManager; import net.wurstclient.events.ChatOutputListener; +import net.wurstclient.events.KeyPressListener; import net.wurstclient.hack.HackList; +import net.wurstclient.keybinds.KeybindList; +import net.wurstclient.keybinds.KeybindProcessor; public enum WurstClient { @@ -54,11 +57,20 @@ public enum WurstClient cmds = new CmdList(); - gui = new ClickGui(wurstFolder.resolve("windows.json")); + Path keybindsFile = wurstFolder.resolve("keybinds.json"); + KeybindList keybinds = new KeybindList(keybindsFile); + keybinds.init(); + + Path guiFile = wurstFolder.resolve("windows.json"); + gui = new ClickGui(guiFile); CmdProcessor cmdProcessor = new CmdProcessor(cmds); eventManager.add(ChatOutputListener.class, cmdProcessor); + KeybindProcessor keybindProcessor = + new KeybindProcessor(hax, keybinds, cmdProcessor); + eventManager.add(KeyPressListener.class, keybindProcessor); + analytics.trackPageView("/mc1.14.2/v" + VERSION, "Wurst " + VERSION + " MC1.14.2"); } diff --git a/src/main/java/net/wurstclient/events/KeyPressListener.java b/src/main/java/net/wurstclient/events/KeyPressListener.java new file mode 100644 index 00000000..33656f86 --- /dev/null +++ b/src/main/java/net/wurstclient/events/KeyPressListener.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2014 - 2019 | Wurst-Imperium | All rights reserved. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.events; + +import java.util.ArrayList; + +import net.wurstclient.event.Event; +import net.wurstclient.event.Listener; + +public interface KeyPressListener extends Listener +{ + public void onKeyPress(KeyPressEvent event); + + public static class KeyPressEvent extends Event + { + private final int keyCode; + private final int scanCode; + private final int action; + private final int modifiers; + + public KeyPressEvent(int keyCode, int scanCode, int action, + int modifiers) + { + this.keyCode = keyCode; + this.scanCode = scanCode; + this.action = action; + this.modifiers = modifiers; + } + + @Override + public void fire(ArrayList listeners) + { + for(KeyPressListener listener : listeners) + listener.onKeyPress(this); + } + + @Override + public Class getListenerType() + { + return KeyPressListener.class; + } + + public int getKeyCode() + { + return keyCode; + } + + public int getScanCode() + { + return scanCode; + } + + public int getAction() + { + return action; + } + + public int getModifiers() + { + return modifiers; + } + } +} diff --git a/src/main/java/net/wurstclient/keybinds/Keybind.java b/src/main/java/net/wurstclient/keybinds/Keybind.java new file mode 100644 index 00000000..f95b4577 --- /dev/null +++ b/src/main/java/net/wurstclient/keybinds/Keybind.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 - 2019 | Wurst-Imperium | All rights reserved. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.keybinds; + +public class Keybind +{ + private final String key; + private final String commands; + + public Keybind(String key, String commands) + { + this.key = key; + this.commands = commands; + } + + public String getKey() + { + return key; + } + + public String getCommands() + { + return commands; + } +} diff --git a/src/main/java/net/wurstclient/keybinds/KeybindList.java b/src/main/java/net/wurstclient/keybinds/KeybindList.java new file mode 100644 index 00000000..5d3924dc --- /dev/null +++ b/src/main/java/net/wurstclient/keybinds/KeybindList.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2014 - 2019 | Wurst-Imperium | All rights reserved. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.keybinds; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Map.Entry; +import java.util.TreeMap; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import net.minecraft.client.util.InputUtil; +import net.wurstclient.util.json.JsonUtils; + +public final class KeybindList +{ + private final Path path; + private final ArrayList keybinds = new ArrayList<>(); + + public KeybindList(Path file) + { + path = file; + } + + public void init() + { + JsonObject json; + try(BufferedReader reader = Files.newBufferedReader(path)) + { + json = JsonUtils.JSON_PARSER.parse(reader).getAsJsonObject(); + + }catch(NoSuchFileException e) + { + loadDefaults(); + return; + + }catch(Exception e) + { + System.out.println("Failed to load " + path.getFileName()); + e.printStackTrace(); + + loadDefaults(); + return; + } + + keybinds.clear(); + + TreeMap keybinds2 = new TreeMap<>(); + for(Entry entry : json.entrySet()) + { + String key = entry.getKey(); + + // test if key is valid + try + { + InputUtil.fromName(key); + + }catch(IllegalArgumentException e) + { + continue; + } + + JsonElement value = entry.getValue(); + String commands; + if(value.isJsonPrimitive() && value.getAsJsonPrimitive().isString()) + commands = value.getAsString(); + else if(value.isJsonArray()) + { + ArrayList commands2 = new ArrayList<>(); + + for(JsonElement e : value.getAsJsonArray()) + if(e.isJsonPrimitive() && e.getAsJsonPrimitive().isString()) + commands2.add(e.getAsString()); + + commands = String.join(";", commands2); + }else + continue; + + keybinds2.put(key, commands); + } + + for(Entry entry : keybinds2.entrySet()) + keybinds.add(new Keybind(entry.getKey(), entry.getValue())); + + save(); + } + + public void loadDefaults() + { + keybinds.clear(); + keybinds.add(new Keybind("key.keyboard.b", "fastplace;fastbreak")); + keybinds.add(new Keybind("key.keyboard.c", "fullbright")); + keybinds.add(new Keybind("key.keyboard.g", "flight")); + keybinds.add(new Keybind("key.keyboard.semicolon", "speednuker")); + keybinds.add(new Keybind("key.keyboard.h", "/home")); + keybinds.add(new Keybind("key.keyboard.j", "jesus")); + keybinds.add(new Keybind("key.keyboard.k", "multiaura")); + keybinds.add(new Keybind("key.keyboard.n", "nuker")); + keybinds.add(new Keybind("key.keyboard.r", "killaura")); + keybinds.add(new Keybind("key.keyboard.right.shift", "navigator")); + keybinds.add(new Keybind("key.keyboard.right.control", "clickgui")); + keybinds.add(new Keybind("key.keyboard.u", "freecam")); + keybinds.add(new Keybind("key.keyboard.x", "x-ray")); + keybinds.add(new Keybind("key.keyboard.y", "sneak")); + save(); + } + + private void save() + { + JsonObject json = new JsonObject(); + for(Keybind keybind : keybinds) + json.addProperty(keybind.getKey(), keybind.getCommands()); + + try(BufferedWriter writer = Files.newBufferedWriter(path)) + { + JsonUtils.PRETTY_GSON.toJson(json, writer); + + }catch(IOException e) + { + System.out.println("Failed to save " + path.getFileName()); + e.printStackTrace(); + } + } + + public int size() + { + return keybinds.size(); + } + + public Keybind get(int index) + { + return keybinds.get(index); + } + + public String getCommands(String key) + { + for(Keybind keybind : keybinds) + { + if(!key.equals(keybind.getKey())) + continue; + + return keybind.getCommands(); + } + + return null; + } + + public void add(String key, String commands) + { + keybinds.removeIf(keybind -> key.equals(keybind.getKey())); + keybinds.add(new Keybind(key, commands)); + keybinds.sort(Comparator.comparing(Keybind::getKey)); + save(); + } + + public void remove(String key) + { + keybinds.removeIf(keybind -> key.equals(keybind.getKey())); + save(); + } + + public void removeAll() + { + keybinds.clear(); + save(); + } +} diff --git a/src/main/java/net/wurstclient/keybinds/KeybindProcessor.java b/src/main/java/net/wurstclient/keybinds/KeybindProcessor.java new file mode 100644 index 00000000..297e9049 --- /dev/null +++ b/src/main/java/net/wurstclient/keybinds/KeybindProcessor.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014 - 2019 | Wurst-Imperium | All rights reserved. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.keybinds; + +import org.lwjgl.glfw.GLFW; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.InputUtil; +import net.wurstclient.WurstClient; +import net.wurstclient.clickgui.ClickGuiScreen; +import net.wurstclient.command.CmdProcessor; +import net.wurstclient.events.KeyPressListener; +import net.wurstclient.hack.Hack; +import net.wurstclient.hack.HackList; + +public final class KeybindProcessor implements KeyPressListener +{ + private final HackList hax; + private final KeybindList keybinds; + private final CmdProcessor cmdProcessor; + + public KeybindProcessor(HackList hax, KeybindList keybinds, + CmdProcessor cmdProcessor) + { + this.hax = hax; + this.keybinds = keybinds; + this.cmdProcessor = cmdProcessor; + } + + @Override + public void onKeyPress(KeyPressEvent event) + { + Screen screen = WurstClient.MC.currentScreen; + if(screen != null && !(screen instanceof ClickGuiScreen)) + return; + + if(event.getAction() != GLFW.GLFW_PRESS) + return; + + int keyCode = event.getKeyCode(); + int scanCode = event.getScanCode(); + String keyName = InputUtil.getKeyCode(keyCode, scanCode).getName(); + + String cmds = keybinds.getCommands(keyName); + if(cmds == null) + return; + + cmds = cmds.replace(";", "\u00a7").replace("\u00a7\u00a7", ";"); + for(String cmd : cmds.split("\u00a7")) + { + cmd = cmd.trim(); + + if(cmd.startsWith(".")) + cmdProcessor.process(cmd.substring(1)); + else if(cmd.contains(" ")) + cmdProcessor.process(cmd); + else + { + Hack hack = hax.getHackByName(cmd); + + if(hack != null) + hack.setEnabled(!hack.isEnabled()); + else + cmdProcessor.process(cmd); + } + } + } +} diff --git a/src/main/java/net/wurstclient/mixin/KeyboardMixin.java b/src/main/java/net/wurstclient/mixin/KeyboardMixin.java new file mode 100644 index 00000000..d69864de --- /dev/null +++ b/src/main/java/net/wurstclient/mixin/KeyboardMixin.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014 - 2019 | Wurst-Imperium | All rights reserved. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.mixin; + +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; + +import net.minecraft.client.Keyboard; +import net.wurstclient.WurstClient; +import net.wurstclient.events.KeyPressListener.KeyPressEvent; + +@Mixin(Keyboard.class) +public class KeyboardMixin +{ + @Inject(at = @At("HEAD"), method = "onKey(JIIII)V") + private void onOnKey(long windowHandle, int keyCode, int scanCode, + int action, int modifiers, CallbackInfo ci) + { + KeyPressEvent event = + new KeyPressEvent(keyCode, scanCode, action, modifiers); + + WurstClient.INSTANCE.getEventManager().fire(event); + } +} diff --git a/src/main/resources/modid.mixins.json b/src/main/resources/modid.mixins.json index 58e4d1e3..9b418d28 100644 --- a/src/main/resources/modid.mixins.json +++ b/src/main/resources/modid.mixins.json @@ -6,7 +6,8 @@ ], "client": [ "ChatHudMixin", - "ClientPlayerEntityMixin" + "ClientPlayerEntityMixin", + "KeyboardMixin" ], "injectors": { "defaultRequire": 1