package com.aposbot.gui; import com.aposbot._default.IClient; import com.aposbot._default.IClientInit; import com.aposbot._default.IScript; import com.aposbot._default.IScriptListener; import com.aposbot.Constants; import com.aposbot.utility.ScriptClassLoader; import com.aposbot.StandardCloseHandler; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.*; import java.net.MalformedURLException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.*; /** * Displays compiled scripts in a GUI and loads selected scripts. */ public final class ScriptFrame extends Frame { private static final long serialVersionUID = -7439187170235715096L; private static final String PROCESSING_ERROR = "Error processing script. Send this output to the script's author:"; private final IClient client; private final IClientInit clientInit; private final java.awt.List displayed_list; private final TextField field; private final TextField scriptSearchField; private ScriptEngineManager manager; private int lastSelectedIndex; public ScriptFrame(final IClient client, final IClientInit clientInit) { super("Scripts"); setFont(Constants.UI_FONT); this.client = client; this.clientInit = clientInit; setIconImages(Constants.ICONS); addWindowListener(new StandardCloseHandler(this, StandardCloseHandler.HIDE)); final Panel fpanel = new Panel(); fpanel.setLayout(new GridLayout(1, 0)); final Label l = new Label("Parameters:"); l.setFont(Constants.UI_FONT); fpanel.add(l); fpanel.add(field = new TextField("")); field.setFont(Constants.UI_FONT); add(fpanel, BorderLayout.NORTH); displayed_list = new java.awt.List(); displayed_list.setFont(Constants.UI_FONT); final ScrollPane scroll = new ScrollPane(); scroll.setFont(Constants.UI_FONT); scroll.add(displayed_list); add(scroll, BorderLayout.CENTER); final Panel searchPanel = new Panel(); searchPanel.setLayout(new GridLayout(1, 0)); final Label searchLabel = new Label("Search:"); searchLabel.setFont(Constants.UI_FONT); searchPanel.add(searchLabel); scriptSearchField = new TextField(""); scriptSearchField.addKeyListener(new KeyListener() { @Override public void keyTyped(final KeyEvent e) { } @Override public void keyPressed(final KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { displayed_list.select(getMatchedScriptIndex()); } } @Override public void keyReleased(final KeyEvent e) { } }); searchPanel.add(scriptSearchField); scriptSearchField.setFont(Constants.UI_FONT); final Panel okCancelButtonPanel = new Panel(); final Button okButton = new Button("OK"); okButton.setFont(Constants.UI_FONT); okButton.addActionListener(e -> { if (displayed_list.getSelectedIndex() == -1) { System.out.println("Script not selected."); } else { new Thread(this::initScript, "ScriptInit").start(); } }); okCancelButtonPanel.add(okButton); final Button cancelButton = new Button("Cancel"); cancelButton.setFont(Constants.UI_FONT); cancelButton.addActionListener(e -> setVisible(false)); okCancelButtonPanel.add(cancelButton); final Panel openCompileScriptsPanel = new Panel(); final Button openScriptsButton = new Button("Scripts Folder"); openScriptsButton.setFont(Constants.UI_FONT); openScriptsButton.addActionListener(e -> { try { Desktop.getDesktop().open(Constants.PATH_SCRIPT_SOURCE.toFile()); } catch (final Exception ex) { ex.printStackTrace(); } }); openCompileScriptsPanel.add(openScriptsButton); final Button compileScriptsButton = new Button("Compile Scripts"); compileScriptsButton.setFont(Constants.UI_FONT); compileScriptsButton.addActionListener(e -> { try { final ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "compile_scripts.cmd"); // If we're on Linux, use bash instead of cmd if (System.getProperty("os.name").toLowerCase().contains("linux")) { pb.command("bash", "-c", "./compile_scripts-linux.sh"); } // execute final Process p = pb.start(); // get both the output and the error stream final SequenceInputStream merged = new SequenceInputStream(p.getInputStream(), p.getErrorStream()); final BufferedReader br = new BufferedReader(new InputStreamReader(merged)); // read the output br.lines().forEach(System.out::println); // wait for the process to finish p.waitFor(); // get the exit code final int exitCode = p.exitValue(); // Close the streams br.close(); System.out.println("Exit code: " + exitCode); // Close the frame setVisible(false); } catch (final Exception ex) { ex.printStackTrace(); } }); openCompileScriptsPanel.add(compileScriptsButton); final Panel southPanel = new Panel(); southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS)); southPanel.add(searchPanel); southPanel.add(okCancelButtonPanel); southPanel.add(openCompileScriptsPanel); add(southPanel, BorderLayout.SOUTH); pack(); setMinimumSize(getSize()); final Insets in = getInsets(); setSize(in.right + in.left + 310, in.top + in.bottom + 240); } @Override public void setVisible(final boolean visible) { if (visible) { update(); toFront(); requestFocus(); } super.setVisible(visible); } public IScript initJavaScript(final String name) { final Class c; try { c = new ScriptClassLoader().loadClass(name.substring(0, name.indexOf(".class"))); } catch (final ClassNotFoundException | MalformedURLException e) { System.out.println("Error loading script:"); e.printStackTrace(); return null; } if (!IScript.class.isAssignableFrom(c)) { System.out.println("Error: " + name + " is not a valid Java script."); return null; } try { return (IScript) c.getConstructor(Class.forName("Extension")).newInstance(client); } catch (final Throwable t) { System.out.println("Failed to load script " + name + ":"); t.printStackTrace(); } return null; } private int getMatchedScriptIndex() { final String searchedScriptName = scriptSearchField.getText().toLowerCase(); final String[] availableScriptNames = displayed_list.getItems(); if (availableScriptNames.length == 0) return -1; final Map scriptSearchMatches = new TreeMap<>((s1, s2) -> { if (s1.length() > s2.length()) { return 1; } else if (s1.length() < s2.length()) { return -1; } else { return s1.compareTo(s2); } }); for (int i = 0; i < availableScriptNames.length; i++) { final String availableScriptName = availableScriptNames[i].toLowerCase(); if (searchedScriptName.equals(availableScriptName)) { return i; } if (availableScriptName.contains(searchedScriptName)) { scriptSearchMatches.put(availableScriptName, i); } } if (scriptSearchMatches.isEmpty()) return -1; return scriptSearchMatches.values().stream().findFirst().get(); } private void initScript() { final IScriptListener listener = clientInit.getScriptListener(); if (listener.isScriptRunning()) { System.out.println("Stop the script you are running first."); return; } listener.setIScript(null); System.gc(); lastSelectedIndex = displayed_list.getSelectedIndex(); final String selected_name = displayed_list.getSelectedItem(); final IScript script; if (selected_name.endsWith(".class")) { script = initJavaScript(selected_name); } else { script = initJSEScript(selected_name); } if (script == null) return; System.out.println("Selected script: " + script); try { script.init(field.getText()); } catch (final Throwable t) { if (t.getMessage() != null) { System.err.println(t.getMessage()); } else { System.err.println(PROCESSING_ERROR); t.printStackTrace(); } return; } clientInit.getScriptListener().setIScript(script); System.out.println("Press the \"Start script\" button to start it."); setVisible(false); } private IScript initJSEScript(final String name) { if (manager == null) { manager = new ScriptEngineManager(); } final int dot = name.indexOf('.'); if (dot == -1) { System.out.println("Error: " + name + " has no file extension."); return null; } final String ext = name.substring(dot + 1); final ScriptEngine engine = manager.getEngineByExtension(ext); if (engine == null) { System.out.println("Error: No script engine found for " + ext); return null; } if (!(engine instanceof Invocable)) { System.out.println("Error: Engine for " + ext + " is not invocable."); } final File file = Constants.PATH_SCRIPT.resolve(name).toFile(); try (final FileInputStream fileInputStream = new FileInputStream(file); final InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { engine.eval(bufferedReader); } catch (final Throwable t) { System.out.println("Error loading script:"); t.printStackTrace(); return null; } return client.createInvocableScript((Invocable) engine, name); } private void update() { final String[] files = Constants.PATH_SCRIPT.toFile().list(); if (files == null) { return; } final java.util.List list = new ArrayList<>(); for (final String file : files) { process(file, list); } if (list.isEmpty()) { System.err.println("Did yah forget to compile yer scripts!?"); return; } Collections.sort(list); displayed_list.removeAll(); for (final String str : list) { displayed_list.add(str); } displayed_list.select(lastSelectedIndex); } private void process(final String fileName, final List list) { if (!fileName.endsWith(".class") || fileName.indexOf('$') != -1) { return; } final File file = new File(fileName); if (file.isDirectory()) { final String[] fileList = file.list(); if (fileList != null) { for (final String name : fileList) { process(name, list); } } } list.add(fileName); } }