diff --git a/README.md b/README.md index 13636de..2227780 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ This project reserve-engineers some of the capabilities of [FLHook](https://gith - [Usage](#usage) * [Requirements](#requirements) * [Installation](#installation) + + [Example](#example) - [Development](#development) * [Requirements](#requirements-1) * [Installation](#installation-1) @@ -20,13 +21,28 @@ See the [help file](/src/main/resources/help.txt). ### Installation 1. Download the [latest jar file](https://github.com/EtienneLamoureux/reverse-flhook/releases) -2. Locate your local Discovery Freelancer installation -3. Navigate to the jar location -4. Create a new file, named `application.yml` -5. In the new file, paste the following, using a **plain-text editor**: `data.ini.rootPath: ` -6. Open a command prompt -7. Navigate to the jar location -8. Run it using `java -jar reverseFLHook-.jar []` +2. Navigate to the jar location +3. Create a new file, next to the jar, named `application.yml` +4. Using a **plain-text editor**, copy [this](https://github.com/EtienneLamoureux/reverse-flhook/blob/main/src/main/resources/application.yml) into the new file +5. Change the value `data.ini.rootPath` to point to your local Discovery Freelancer installation +6. Save and close the new file +7. Open a command prompt +8. Navigate to the jar location +9. Run it using `java -jar reverseFLHook-.jar []` + +#### Example +```cmd +$ java -jar reverseFLHook-1.3.0.jar survey li01 li01_07_base -auto -copy + ___ ___ _ _ _ _ + | _ \ ___ __ __ ___ _ _ ___ ___ | __| | | | || | ___ ___ | |__ + | / / -_) \ V / / -_) | '_| (_-< / -_) | _| | |__ | __ | / _ \ / _ \ | / / + |_|_\ \___| \_/ \___| |_| /__/ \___| |_| |____| |_||_| \___/ \___/ |_\_\ + +40011C05-2CBE93B3-37362526-7F1A2F20-30ADA171-C3CA7401-6165EE75 +Hyperspace coordinates copied to clipboard! +Typing hyperspace coordinates in 5 seconds... +Done! +``` ## Development ### Requirements diff --git a/build.gradle b/build.gradle index c8f2bd9..fe4460f 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } group = 'com.etiennelamoureux' -version = '1.2.0' +version = '1.3.0' sourceCompatibility = '11' repositories { diff --git a/src/main/java/com/etiennelamoureux/reverseflhook/CommandLineController.java b/src/main/java/com/etiennelamoureux/reverseflhook/CommandLineController.java index 1fc109d..b42121a 100644 --- a/src/main/java/com/etiennelamoureux/reverseflhook/CommandLineController.java +++ b/src/main/java/com/etiennelamoureux/reverseflhook/CommandLineController.java @@ -2,6 +2,7 @@ import com.etiennelamoureux.reverseflhook.jump.HyperspaceCoordinates; import com.etiennelamoureux.reverseflhook.jump.HyperspaceCoordinatesService; +import com.etiennelamoureux.reverseflhook.utils.KeyboardUtil; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.io.BufferedReader; @@ -32,7 +33,23 @@ public void run(String... args) throws Exception { } } - private void run(Deque arguments) { + private Deque stackArguments(String... args) { + Deque arguments = new LinkedList<>(); + Arrays.stream(args).forEach(n -> arguments.addLast(n)); + + return arguments; + } + + private void printHelp() { + try (Stream lines = new BufferedReader(new InputStreamReader( + Thread.currentThread().getContextClassLoader().getResourceAsStream("help.txt"))).lines()) { + lines.forEach(line -> System.out.println(line)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void run(Deque arguments) throws InterruptedException { Command command = getCommand(arguments); HyperspaceCoordinates hyperspaceCoordinates; @@ -57,36 +74,37 @@ private void run(Deque arguments) { } } + System.out.println(hyperspaceCoordinates.toString()); + if (arguments.contains(Flags.COPY)) { - Toolkit.getDefaultToolkit().getSystemClipboard() - .setContents(new StringSelection(hyperspaceCoordinates.toString()), null); + copyToClipboard(hyperspaceCoordinates); } if (arguments.contains(Flags.AUTO)) { - // TODO + typeOnKeyboard(hyperspaceCoordinates); } + } - System.out.println(hyperspaceCoordinates.toString()); + private Command getCommand(Deque arguments) { + return Command.valueOf(arguments.pop().toUpperCase(Locale.ROOT)); } - private Deque stackArguments(String... args) { - Deque arguments = new LinkedList<>(); - Arrays.stream(args).forEach(n -> arguments.addLast(n)); + private void copyToClipboard(HyperspaceCoordinates hyperspaceCoordinates) { + Toolkit.getDefaultToolkit().getSystemClipboard() + .setContents(new StringSelection(hyperspaceCoordinates.toString()), null); - return arguments; + System.out.println("Hyperspace coordinates copied to clipboard!"); } - private Command getCommand(Deque arguments) { - return Command.valueOf(arguments.pop().toUpperCase(Locale.ROOT)); - } + private void typeOnKeyboard(HyperspaceCoordinates hyperspaceCoordinates) + throws InterruptedException { + System.out.println("Typing hyperspace coordinates in 5 seconds..."); + Thread.sleep(5000l); - private void printHelp() { - try (Stream lines = new BufferedReader(new InputStreamReader( - Thread.currentThread().getContextClassLoader().getResourceAsStream("help.txt"))).lines()) { - lines.forEach(line -> System.out.println(line)); - } catch (Exception e) { - e.printStackTrace(); - } + new KeyboardUtil().type( + KeyboardUtil.ENTER + "/setcoords " + hyperspaceCoordinates.toString() + KeyboardUtil.ENTER); + + System.out.println("Done!"); } enum Command { diff --git a/src/main/java/com/etiennelamoureux/reverseflhook/exceptions/KeyboardException.java b/src/main/java/com/etiennelamoureux/reverseflhook/exceptions/KeyboardException.java new file mode 100644 index 0000000..de0c1c2 --- /dev/null +++ b/src/main/java/com/etiennelamoureux/reverseflhook/exceptions/KeyboardException.java @@ -0,0 +1,9 @@ +package com.etiennelamoureux.reverseflhook.exceptions; + +public class KeyboardException extends RuntimeException { + private static final long serialVersionUID = 1422275621352262759L; + + public KeyboardException(Exception e) { + super(e); + } +} diff --git a/src/main/java/com/etiennelamoureux/reverseflhook/utils/KeyboardUtil.java b/src/main/java/com/etiennelamoureux/reverseflhook/utils/KeyboardUtil.java new file mode 100644 index 0000000..998a1de --- /dev/null +++ b/src/main/java/com/etiennelamoureux/reverseflhook/utils/KeyboardUtil.java @@ -0,0 +1,84 @@ +package com.etiennelamoureux.reverseflhook.utils; + +import com.etiennelamoureux.reverseflhook.exceptions.KeyboardException; +import java.awt.AWTException; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +public class KeyboardUtil { + public static final String ENTER = "&"; + private static final long DELAY = 20l; + + private Robot robot; + private Map keyEventsByChar; + + public KeyboardUtil() { + try { + robot = new Robot(); + } catch (AWTException e) { + throw new KeyboardException(e); + } + + keyEventsByChar = new HashMap<>(); + keyEventsByChar.put("0", KeyEvent.VK_0); + keyEventsByChar.put("1", KeyEvent.VK_1); + keyEventsByChar.put("2", KeyEvent.VK_2); + keyEventsByChar.put("3", KeyEvent.VK_3); + keyEventsByChar.put("4", KeyEvent.VK_4); + keyEventsByChar.put("5", KeyEvent.VK_5); + keyEventsByChar.put("6", KeyEvent.VK_6); + keyEventsByChar.put("7", KeyEvent.VK_7); + keyEventsByChar.put("8", KeyEvent.VK_8); + keyEventsByChar.put("9", KeyEvent.VK_9); + keyEventsByChar.put("a", KeyEvent.VK_A); + keyEventsByChar.put("b", KeyEvent.VK_B); + keyEventsByChar.put("c", KeyEvent.VK_C); + keyEventsByChar.put("d", KeyEvent.VK_D); + keyEventsByChar.put("e", KeyEvent.VK_E); + keyEventsByChar.put("f", KeyEvent.VK_F); + keyEventsByChar.put("g", KeyEvent.VK_G); + keyEventsByChar.put("h", KeyEvent.VK_H); + keyEventsByChar.put("i", KeyEvent.VK_I); + keyEventsByChar.put("j", KeyEvent.VK_J); + keyEventsByChar.put("k", KeyEvent.VK_K); + keyEventsByChar.put("l", KeyEvent.VK_L); + keyEventsByChar.put("m", KeyEvent.VK_M); + keyEventsByChar.put("n", KeyEvent.VK_N); + keyEventsByChar.put("o", KeyEvent.VK_O); + keyEventsByChar.put("p", KeyEvent.VK_P); + keyEventsByChar.put("q", KeyEvent.VK_Q); + keyEventsByChar.put("r", KeyEvent.VK_R); + keyEventsByChar.put("s", KeyEvent.VK_S); + keyEventsByChar.put("t", KeyEvent.VK_T); + keyEventsByChar.put("u", KeyEvent.VK_U); + keyEventsByChar.put("v", KeyEvent.VK_V); + keyEventsByChar.put("w", KeyEvent.VK_W); + keyEventsByChar.put("x", KeyEvent.VK_X); + keyEventsByChar.put("y", KeyEvent.VK_Y); + keyEventsByChar.put("z", KeyEvent.VK_Z); + keyEventsByChar.put(" ", KeyEvent.VK_SPACE); + keyEventsByChar.put("/", KeyEvent.VK_DIVIDE); + keyEventsByChar.put("-", KeyEvent.VK_MINUS); + keyEventsByChar.put(ENTER, KeyEvent.VK_ENTER); + } + + public void type(String string) { + for (int i = 0; i < string.length(); i++) { + key(string.toLowerCase(Locale.ROOT).substring(i, i + 1)); + } + } + + private void key(String key) { + try { + robot.keyPress(keyEventsByChar.get(key)); + Thread.sleep(DELAY); + robot.keyRelease(keyEventsByChar.get(key)); + Thread.sleep(DELAY); + } catch (InterruptedException e) { + throw new KeyboardException(e); + } + } +} diff --git a/src/main/java/com/etiennelamoureux/reverseflhook/utils/Secret.java b/src/main/java/com/etiennelamoureux/reverseflhook/utils/Secret.java index 52c8ca1..ee46ff8 100644 --- a/src/main/java/com/etiennelamoureux/reverseflhook/utils/Secret.java +++ b/src/main/java/com/etiennelamoureux/reverseflhook/utils/Secret.java @@ -3,6 +3,9 @@ import org.springframework.beans.factory.annotation.Value; public class Secret { + /** + * Discovery Freelancer server's secret + */ private static final String SECRET = "8ea084da-545c4aa5-39353348-4593c040"; private static Secret instance; diff --git a/src/test/java/com/etiennelamoureux/reverseflhook/CommandLineControllerITest.java b/src/test/java/com/etiennelamoureux/reverseflhook/CommandLineControllerITest.java index 66adc8a..d2e809f 100644 --- a/src/test/java/com/etiennelamoureux/reverseflhook/CommandLineControllerITest.java +++ b/src/test/java/com/etiennelamoureux/reverseflhook/CommandLineControllerITest.java @@ -5,6 +5,7 @@ import java.awt.datatransfer.DataFlavor; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -35,4 +36,10 @@ public void givenCopyFlagWhenSurveyingThenCoordsAreInClipboard() throws Exceptio String hyperspaceCoordinates = (String) clipboard.getData(DataFlavor.stringFlavor); commandLineController.run("refresh", hyperspaceCoordinates); } + + @Disabled(value = "Actually sends key-press events") + @Test + public void givenAutoFlagWhenSurveyingThenDontThrow() throws Exception { + commandLineController.run("survey", "ew01", "ew01_01_base", CommandLineController.Flags.AUTO); + } }