Merge branch 'development' into patch-1

This commit is contained in:
Jak
2018-11-11 09:20:31 +00:00
committed by GitHub
28 changed files with 512 additions and 268 deletions
+6 -2
View File
@@ -17,10 +17,10 @@ import java.io.File;
import java.io.IOException;
/**
* Parabot v2.6
* Parabot v2.7
*
* @author Everel, JKetelaar, Matt, Dane
* @version 2.6
* @version 2.7
* @see <a href="http://www.parabot.org">Homepage</a>
*/
public final class Landing {
@@ -81,6 +81,7 @@ public final class Landing {
System.exit(0);
break;
case "-debug":
case "-offlinemode":
Core.setDebug(true);
break;
case "-v":
@@ -143,6 +144,9 @@ public final class Landing {
case "-no_validation":
Core.disableValidation();
break;
case "-uuid":
Core.setQuickLaunchByUuid(Integer.parseInt(args[++i]));
break;
}
}
}
+46 -11
View File
@@ -32,11 +32,11 @@ import java.util.TimerTask;
* @author Everel, JKetelaar, Matt
*/
public class Context {
public static final HashMap<ThreadGroup, Context> threadGroups = new HashMap<ThreadGroup, Context>();
private static ArrayList<Paintable> paintables = new ArrayList<Paintable>();
public static final HashMap<ThreadGroup, Context> threadGroups = new HashMap<>();
private static Context instance;
private static String username;
private static ArrayList<Paintable> paintables = new ArrayList<>();
private static Context instance;
private static String username;
private ASMClassLoader classLoader;
private ClassPath classPath;
@@ -52,22 +52,20 @@ public class Context {
private PBKeyListener pbKeyListener;
private ServerProviderInfo providerInfo;
private JSONParser jsonParser;
private PrintStream defaultOut;
private PrintStream defaultErr = System.err;
private PrintStream defaultOut;
private PrintStream defaultErr;
private Context(final ServerProvider serverProvider) {
threadGroups.put(Thread.currentThread().getThreadGroup(), this);
System.setProperty("sun.java.command", "");
this.serverProvider = serverProvider;
this.paintDebugger = new PaintDebugger();
this.classPath = new ClassPath();
this.classLoader = new ASMClassLoader(classPath);
this.randomHandler = new RandomHandler();
this.jsonParser = new JSONParser();
this.defaultOut = System.out;
this.defaultErr = System.err;
}
@@ -76,21 +74,43 @@ public class Context {
String version = System.getProperty("java.version");
int pos = version.indexOf('.');
pos = version.indexOf('.', pos+1);
return Double.parseDouble (version.substring (0, pos));
return Double.parseDouble(version.substring (0, pos));
}
/**
* Returns the instance of this class, based on a given ServerProvider
*
* @param serverProvider
*
* @return
*/
public static Context getInstance(ServerProvider serverProvider) {
return instance == null ? instance = new Context(serverProvider) : instance;
}
/**
* Returns the instance of this class
*
* @return
*/
public static Context getInstance() {
return getInstance(null);
}
/**
* Returns the username of the current logged in user to Parabot
*
* @return
*/
public static String getUsername() {
return username;
}
/**
* Sets the username for the logged in user to Parabot
*
* @param username
*/
public static void setUsername(String username) {
Context.username = username;
}
@@ -192,9 +212,13 @@ public class Context {
panel.add(gameApplet);
panel.validate();
serverProvider.preAppletInit();
gameApplet.init();
gameApplet.start();
serverProvider.postAppletStart();
java.util.Timer t = new java.util.Timer();
t.schedule(new TimerTask() {
@Override
@@ -237,7 +261,8 @@ public class Context {
Core.verbose(TranslationHelper.translate("DONE"));
}
Applet applet = serverProvider.fetchApplet();
// if applet is null the server provider will call setApplet itself
// If applet is null the server provider will call setApplet itself
if (applet != null) {
setApplet(applet);
}
@@ -370,10 +395,20 @@ public class Context {
return this.randomHandler;
}
/**
* Returns the JSON Parser instance
*
* @return
*/
public JSONParser getJsonParser() {
return jsonParser;
}
/**
* Returns the PBKeyListener instance
*
* @return
*/
public PBKeyListener getPbKeyListener() {
return pbKeyListener;
}
+16 -4
View File
@@ -28,7 +28,8 @@ import java.security.NoSuchAlgorithmException;
@SuppressWarnings("Duplicates")
public class Core {
private static boolean debug;
private static int quickLaunchByUuid = -1; // used like -server, but denoted by an Int rather than the server name
private static boolean debug; // Debug mode is Offline Mode. No BDN connection for Servers/Scripts/User Login. Not related to debug messages.
private static boolean verbose;
private static boolean dump;
private static boolean loadLocal; //Loads both local and public scripts/servers
@@ -46,6 +47,14 @@ public class Core {
return validate;
}
public static int getQuickLaunchByUuid() {
return quickLaunchByUuid;
}
public static void setQuickLaunchByUuid(int quickLaunchByUuid) {
Core.quickLaunchByUuid = quickLaunchByUuid;
}
/**
* Enabled loadLocal mode
*
@@ -63,7 +72,7 @@ public class Core {
}
/**
* Enabled debug mode
* Set debug mode AKA Offline Mode. If true, BDN login will be skipped, so BDN Servers or Scripts will be unavailable.
*
* @param debug
*/
@@ -95,7 +104,7 @@ public class Core {
}
/**
* @return if the client is in debug mode.
* @return if the client is in debug mode AKA Offline Mode. BDN Servers and Scripts are unavailable.
*/
public static boolean inDebugMode() {
return debug;
@@ -161,7 +170,9 @@ public class Core {
String result;
if ((result = WebUtil.getContents(String.format(Configuration.COMPARE_CHECKSUM_URL, "client", currentVersion.get()), "checksum=" + URLEncoder.encode(sb.toString(), "UTF-8"))) != null) {
JSONObject object = (JSONObject) WebUtil.getJsonParser().parse(result);
return (boolean) object.get("result");
boolean upToDate = (boolean) object.get("result");
Core.verbose("Local checksum: " + URLEncoder.encode(sb.toString(), "UTF-8") + ". " + (upToDate ? "This matches BDN and is up to date." : "BDN mismatch, must be Out Of Date."));
return upToDate;
}
}
} catch (NoSuchAlgorithmException | ParseException | IOException | URISyntaxException e) {
@@ -187,6 +198,7 @@ public class Core {
if (!latest) {
Directories.clearCache();
}
Core.verbose("Local version: " + currentVersion.get() + ". " + (latest ? "This is up to date." : "This is Out Of Date. Cache will be cleared."));
return latest;
}
} catch (IOException | ParseException e) {
@@ -16,8 +16,12 @@ import java.util.Map;
public class RedirectClassAdapter extends ClassVisitor implements Opcodes {
public static Map<String, Class<?>> getRedirects() {
return redirects;
}
private static final Map<String, Class<?>> redirects = new HashMap<String, Class<?>>();
private static PrintStream str_out, class_out;
private static PrintStream str_out, class_out;
static {
redirects.put("java/awt/Toolkit", ToolkitRedirect.class);
@@ -40,17 +40,19 @@ public class AddCallbackAdapter implements Injectable, Opcodes {
Label l0 = new Label();
inject.add(new LabelNode(l0));
int offset = 0;
for (int arg : args) {
if (Modifier.isStatic(method.access)) {
int loadOpcode = ASMUtils.getLoadOpcode(types[arg]
.getDescriptor());
inject.add(new VarInsnNode(loadOpcode, arg + offset));
if (loadOpcode == Opcodes.LLOAD) {
offset++;
if (args != null) {
for (int arg : args) {
if (Modifier.isStatic(method.access)) {
int loadOpcode = ASMUtils.getLoadOpcode(types[arg]
.getDescriptor());
inject.add(new VarInsnNode(loadOpcode, arg + offset));
if (loadOpcode == Opcodes.LLOAD) {
offset++;
}
} else {
inject.add(new VarInsnNode(ASMUtils.getLoadOpcode(types[arg]
.getDescriptor()), arg + 1));
}
} else {
inject.add(new VarInsnNode(ASMUtils.getLoadOpcode(types[arg]
.getDescriptor()), arg + 1));
}
}
inject.add(new MethodInsnNode(INVOKESTATIC,
@@ -6,8 +6,7 @@ import org.parabot.environment.scripts.Script;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
@@ -25,7 +24,7 @@ public class ClassRedirect {
}
public static Object newInstance(Class<?> c) throws IllegalAccessException, InstantiationException {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.newInstance();
}
@@ -34,7 +33,7 @@ public class ClassRedirect {
}
public static Field getDeclaredField(Class<?> c, String s) throws NoSuchFieldException, SecurityException {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getDeclaredField(s);
}
@@ -43,7 +42,7 @@ public class ClassRedirect {
}
public static Method getDeclaredMethod(Class<?> c, String name, Class<?>... params) throws NoSuchMethodException, SecurityException {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getDeclaredMethod(name, params);
}
@@ -65,7 +64,7 @@ public class ClassRedirect {
}
public static Field[] getDeclaredFields(Class<?> c) {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getDeclaredFields();
}
System.err.println(c.getName() + "#getDeclaredFields()" + " Blocked.");
@@ -73,7 +72,7 @@ public class ClassRedirect {
}
public static Method[] getDeclaredMethods(Class<?> c) {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getDeclaredMethods();
}
System.err.println(c.getName() + "#getDeclaredMethods()" + " Blocked.");
@@ -81,7 +80,7 @@ public class ClassRedirect {
}
public static Field[] getFields(Class<?> c) {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getFields();
}
System.err.println(c.getName() + "#getFields()" + " Blocked.");
@@ -89,7 +88,7 @@ public class ClassRedirect {
}
public static Annotation[] getAnnotations(Class<?> c) {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getAnnotations();
}
System.err.println(c.getName() + "#getFields()" + " Blocked.");
@@ -105,7 +104,7 @@ public class ClassRedirect {
}
public static Method getMethod(Class<?> c, String name, Class<?>... params) throws NoSuchMethodException, SecurityException {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getMethod(name, params);
}
System.err.println(c.getName() + "#getMethod()" + " Blocked.");
@@ -114,7 +113,7 @@ public class ClassRedirect {
public static Field getField(Class<?> c, String name)
throws NoSuchFieldException, SecurityException {
if (validStack()) {
if (validStack() || validRequest(c)) {
return c.getField(name);
}
System.err.println(c.getName() + "#getField()" + " Blocked.");
@@ -146,6 +145,62 @@ public class ClassRedirect {
return !c.getName().contains("parabot") && c.desiredAssertionStatus();
}
public static Type getGenericSuperclass(Class c) {
return c.getGenericSuperclass();
}
public static boolean isArray(Class c) {
return c.isArray();
}
public static int getModifiers(Class c) {
return c.getModifiers();
}
public static Class getEnclosingClass(Class c) {
return c.getEnclosingClass();
}
public static boolean isPrimitive(Class c) {
return c.isPrimitive();
}
public static boolean isAssignableFrom(Class c1, Class c2) {
return c1.isAssignableFrom(c2);
}
public static boolean isAnonymousClass(Class c) {
return c.isAnonymousClass();
}
public static boolean isLocalClass(Class c) {
return c.isLocalClass();
}
public static boolean isInterface(Class c) {
return c.isInterface();
}
public static Class[] getInterfaces(Class c) {
return c.getInterfaces();
}
public static Type[] getGenericInterfaces(Class c) {
return c.getGenericInterfaces();
}
public static TypeVariable[] getTypeParameters(Class c) {
return c.getTypeParameters();
}
public static Annotation getAnnotation(Class c, Class annotationClass) {
return c.getAnnotation(annotationClass);
}
public static Constructor getDeclaredConstructor(Class c, Class[] parameterTypes) throws NoSuchMethodException, SecurityException {
return c.getDeclaredConstructor(parameterTypes);
}
private static boolean validStack() {
Exception e = new Exception();
for (StackTraceElement elem : e.getStackTrace()) {
@@ -155,4 +210,9 @@ public class ClassRedirect {
}
return false;
}
private static boolean validRequest(Class c) {
Core.verbose("Got request for class: " + c.getName());
return !c.getName().toLowerCase().contains("parabot");
}
}
@@ -26,14 +26,16 @@ public class Callback implements Injectable {
this.invokeMethod = callbackMethod;
this.desc = callbackDesc;
this.conditional = conditional;
if (args.contains(",")) {
final String[] strArgs = args.split(",");
this.args = new int[strArgs.length];
for (int i = 0; i < this.args.length; i++) {
this.args[i] = Integer.parseInt(strArgs[i]);
if (args.length() > 0) {
if (args.contains(",")) {
final String[] strArgs = args.split(",");
this.args = new int[strArgs.length];
for (int i = 0; i < this.args.length; i++) {
this.args[i] = Integer.parseInt(strArgs[i]);
}
} else {
this.args = new int[]{Integer.parseInt(args)};
}
} else {
this.args = new int[]{ Integer.parseInt(args) };
}
}
@@ -9,6 +9,7 @@ public class ServerDescription implements Comparable<ServerDescription> {
private String serverName;
private String author;
private double revision;
public int uuid;
public ServerDescription(final String serverName, final String author,
final double revision) {
@@ -37,6 +38,12 @@ public class ServerDescription implements Comparable<ServerDescription> {
@Override
public int compareTo(ServerDescription o) {
if (this.getServerName().equalsIgnoreCase(o.getServerName())) {
if (getAuthor().equals(o.getAuthor())) {
return Double.compare(o.getRevision(), getRevision());
}
return getAuthor().compareTo(o.getAuthor());
}
return this.getServerName().compareTo(o.getServerName());
}
@@ -50,7 +50,28 @@ public class ServerProviderInfo {
}
}
/**
* Initialize configuration with data provided by {@link org.parabot.core.parsers.servers.LocalServers} from a {@code /parabot/servers/config.json} file. Also loads the default Settings map from the BDN.
* @param clientJar Name of the client jar file
* @param hooks Name of the hooks file
* @param name Server name
* @param clientClass Entry class within the client jar
* @param bankTabs Bank tabs - only relevant for certain servers. Default 0
*/
public ServerProviderInfo(String clientJar, String hooks, String name, String clientClass, int bankTabs) {
this(clientJar, hooks, name, clientClass, bankTabs, null);
}
/**
* Initialize configuration with data provided by {@link org.parabot.core.parsers.servers.LocalServers} from a {@code /parabot/servers/config.json} file. Also loads the default Settings map from the BDN.
* @param clientJar Name of the client jar file
* @param hooks Name of the hooks file
* @param name Server name
* @param clientClass Entry class within the client jar
* @param bankTabs Bank tabs - only relevant for certain servers. Default 0
* @param randoms A URL to an endpoint where the Randoms are located. Can be Null, in which case getRandoms() will fallback to the default BDN Randoms URL.
*/
public ServerProviderInfo(String clientJar, String hooks, String name, String clientClass, int bankTabs, String randoms) {
this.properties = new Properties();
this.settings = new HashMap<>();
@@ -69,6 +90,7 @@ public class ServerProviderInfo {
this.properties.setProperty("provider_crc32", String.valueOf(getCRC32(name, "provider")));
this.properties.setProperty("client_crc32", String.valueOf(getCRC32(name, "client")));
this.properties.setProperty("bank_tabs", String.valueOf(bankTabs));
this.properties.setProperty("randoms_jar", randoms);
}
private long getCRC32(String name, String type) {
@@ -141,4 +163,23 @@ public class ServerProviderInfo {
public HashMap<String, Integer> getSettings() {
return settings;
}
/**
* Gets the URL to download the Randoms JAR from.
* @return The provided URL in the server config JSON (denoted by 'randoms:') or, fallback to the default BDN URL.
*/
public URL getRandoms() {
try {
String randomsUrl = properties.getProperty("randoms_jar");
if (randomsUrl == null || randomsUrl.length() == 0) {
// Fallback to default BDN URL if there is no 'randoms' specified in the server JSON configuration.
randomsUrl = Configuration.GET_RANDOMS + (Configuration.BOT_VERSION.isNightly() ? Configuration.NIGHTLY_APPEND : "");
}
return new URL(randomsUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
// Will never return null, unless the BDN URL is changed. It shouldn't be.
return null;
}
}
@@ -13,4 +13,19 @@ public class NoProgressListener implements ProgressListener {
public void updateDownloadSpeed(double mbPerSecond) {
}
@Override
public void updateMessage(String message) {
}
@Override
public void updateMessageAndProgress(String message, double progress) {
}
@Override
public double getCurrentProgress() {
return 0;
}
}
@@ -65,8 +65,17 @@ public class XMLHookParser extends HookParser {
}
private static final String getValue(String tag, Element element) {
if (element.getElementsByTagName(tag).item(0) == null) {
throw new NullPointerException("MISSING HOOK TAG: The '" + tag + "' xml tag is missing from one of the hooks of type: " + element.getParentNode().getNodeName());
}
NodeList nodes = element.getElementsByTagName(tag).item(0)
.getChildNodes();
if (nodes.getLength() == 0 || nodes.item(0) == null) {
if (Core.inVerboseMode()) {
System.err.println("WARNING: Invalid Hook " + tag + " subnode. Tag is missing or empty?");
}
return "";
}
Node node = (Node) nodes.item(0);
return node.getNodeValue();
}
@@ -1,18 +1,18 @@
package org.parabot.core.parsers.randoms;
import org.parabot.api.io.WebUtil;
import org.parabot.core.Configuration;
import org.parabot.core.Context;
import org.parabot.core.Core;
import org.parabot.core.Directories;
import org.parabot.core.io.NoProgressListener;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import org.parabot.api.io.WebUtil;
import org.parabot.api.output.Logger;
import org.parabot.core.Configuration;
import org.parabot.core.Context;
import org.parabot.core.Core;
import org.parabot.core.Directories;
import org.parabot.core.io.NoProgressListener;
/**
* @author JKetelaar
@@ -23,12 +23,21 @@ public class PublicRandoms extends RandomParser {
@Override
public void parse() {
File myJar = new File(Directories.getCachePath() + File.separator + fileName);
if (!myJar.exists() || !myJar.canRead()) {
download();
final File destination = new File(Directories.getCachePath() + File.separator + fileName);
final URL overrideDownload = Context.getInstance().getServerProviderInfo().getRandoms();
if (overrideDownload == null) {
throw new NullPointerException("Unable to grab URL for Randoms jar. Default URL for BDN randoms must have changed!");
}
Core.verbose(String.format("[%s] Destination: %s | dl: %s", getClass().getSimpleName(), destination, overrideDownload));
if (!destination.exists() || !destination.canRead()) {
Core.verbose(String.format("[%s] Missing %s - downloading from %s...", getClass().getSimpleName(), destination.getAbsolutePath(), overrideDownload));
download(destination, overrideDownload);
}
try {
URL url = myJar.toURI().toURL();
URL url = destination.toURI().toURL();
URL[] urls = new URL[]{ url };
String server = Context.getInstance().getServerProviderInfo().getServerName();
@@ -36,7 +45,7 @@ public class PublicRandoms extends RandomParser {
Class<?> classToLoad = Class.forName("org.parabot.randoms.Core", true, child);
Method method = classToLoad.getDeclaredMethod("init", String.class);
Object instance = classToLoad.newInstance();
System.out.println(server);
Core.verbose(String.format("[%s] %s %s", getClass().getSimpleName(), "Initing core Randoms for", server));
method.invoke(instance, server);
Core.verbose("Successfully parsed public random!");
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | ClassNotFoundException | MalformedURLException e) {
@@ -45,17 +54,14 @@ public class PublicRandoms extends RandomParser {
}
}
private void download() {
private void download(final File destination, URL downloadLink) {
try {
File random = new File(Directories.getCachePath() + File.separator + fileName);
if (random.exists()) {
if (destination.exists()) {
Core.verbose("Public random dependency already exists, no need to download it...");
return;
}
String downloadLink = ((Configuration.BOT_VERSION.isNightly()) ? Configuration.GET_RANDOMS + Configuration.NIGHTLY_APPEND : Configuration.GET_RANDOMS);
WebUtil.downloadFile(new URL(downloadLink), random, new NoProgressListener());
WebUtil.downloadFile(downloadLink, destination, new NoProgressListener());
} catch (Exception e) {
e.printStackTrace();
}
@@ -1,7 +1,13 @@
package org.parabot.core.parsers.servers;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.parabot.core.Configuration;
import org.parabot.core.Core;
import org.parabot.core.Directories;
import org.parabot.core.classpath.ClassPath;
@@ -13,12 +19,6 @@ import org.parabot.environment.servers.executers.LocalPublicServerExecuter;
import org.parabot.environment.servers.executers.LocalServerExecuter;
import org.parabot.environment.servers.loader.ServerLoader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
/**
* Parses local server providers located in the servers directory
*
@@ -86,17 +86,28 @@ public class LocalServers extends ServerParser {
if ((bank = object.get("bank")) != null) {
bankTabs = (int) bank;
}
String uuidStr = (String) object.get("uuid"); // optional
JSONObject locations = (JSONObject) object.get("locations");
String server = (String) locations.get("server");
String provider = (String) locations.get("provider");
String hooks = (String) locations.get("hooks");
String randoms = (String) locations.get("randoms");
if (randoms == null) {
randoms = Configuration.GET_RANDOMS + (Configuration.BOT_VERSION.isNightly() ? Configuration.NIGHTLY_APPEND : "");
}
Core.verbose("[LocalServers]: Parsed server: " + name);
ServerProviderInfo serverProviderInfo = new ServerProviderInfo(server, hooks, name, clientClass, bankTabs, randoms);
Core.verbose("[Local server]: " + name);
ServerProviderInfo serverProviderInfo = new ServerProviderInfo(server, hooks, name, clientClass, bankTabs);
ServerDescription desc = new ServerDescription(name, author, version);
if (uuidStr != null && uuidStr.length() > 0) {
desc.uuid = Integer.parseInt(uuidStr);
}
ServerDescription desc = new ServerDescription(name,
author, version);
SERVER_CACHE.put(desc, new LocalPublicServerExecuter(name, serverProviderInfo, server, provider));
} catch (IOException | ParseException e) {
e.printStackTrace();
@@ -6,6 +6,7 @@ import org.parabot.core.forum.AccountManager;
import org.parabot.core.ui.images.Images;
import org.parabot.core.ui.utils.SwingUtil;
import org.parabot.core.ui.utils.UILog;
import org.parabot.environment.input.Keyboard;
import javax.swing.*;
import java.awt.*;
@@ -72,7 +73,7 @@ public class LoginUI extends JFrame {
txtUsername.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 10 || e.getKeyCode() == 13) {
if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == Keyboard.ENTER_KEYCODE) {
txtPassword.requestFocus();
}
}
@@ -85,7 +86,7 @@ public class LoginUI extends JFrame {
txtPassword.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 10 || e.getKeyCode() == 13) {
if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == Keyboard.ENTER_KEYCODE) {
attemptLogin();
}
}
@@ -1,5 +1,6 @@
package org.parabot.core.ui;
import org.parabot.core.Core;
import org.parabot.core.desc.ServerDescription;
import org.parabot.core.parsers.servers.ServerParser;
import org.parabot.core.ui.components.ServerComponent;
@@ -23,7 +24,7 @@ public class ServerSelector extends JPanel {
public ServerSelector() {
Queue<ServerComponent> widgets = getServers();
if (initServer != null) {
if (initServer != null || Core.getQuickLaunchByUuid() > -1) {
if (runServer(widgets)) {
initServer = null;
return;
@@ -67,7 +68,7 @@ public class ServerSelector extends JPanel {
}
/**
* This method is called when -server argument is given
* This method is called when -server argument is given, or -uuid arg is given.
*
* @param widgets
*/
@@ -75,12 +76,25 @@ public class ServerSelector extends JPanel {
if (widgets == null || widgets.isEmpty()) {
return false;
}
final String serverName = initServer.toLowerCase();
for (ServerComponent widget : widgets) {
if (widget.desc.getServerName().toLowerCase().equals(serverName)) {
Environment.load(widget.desc);
return true;
if (Core.getQuickLaunchByUuid() > -1) { // match the pre-requested server config uuid to quick-launch
for (ServerComponent widget : widgets) {
if (widget.desc.uuid == Core.getQuickLaunchByUuid()) {
Environment.load(widget.desc);
return true;
}
}
System.err.println("No server config with -uuid " + Core.getQuickLaunchByUuid() + " was found to quick launch.");
}
if (initServer != null) {
final String serverName = initServer.toLowerCase(); // match the pre-requested server name to quick-launch
for (ServerComponent widget : widgets) {
if (widget.desc.getServerName().toLowerCase().equals(serverName)) {
Environment.load(widget.desc);
return true;
}
}
System.err.println("No server config with -server " + serverName + " was found to quick launch.");
}
return false;
}
@@ -275,4 +275,20 @@ public class VerboseLoader extends JPanel implements ProgressListener {
public void updateDownloadSpeed(double mbPerSecond) {
progressBar.setText(String.format("(%.2fMB/s)", mbPerSecond));
}
@Override
public void updateMessage(String message) {
VerboseLoader.setState(message);
}
@Override
public void updateMessageAndProgress(String message, double progress) {
VerboseLoader.setState(message);
onProgressUpdate(progress);
}
@Override
public double getCurrentProgress() {
return progressBar.getValue();
}
}
@@ -53,6 +53,30 @@ public final class Time {
return true;
}
/**
* Sleeps until SleepCondition is valid, but with a minimum timeout.
*
* @param conn the condition.
* @param timeout the time in milliseconds before it stops sleeping.
* @param minimumTimeout the minimum time to sleep.
*
* @return whether it ran successfully without timing out.
*/
public static boolean sleep(SleepCondition conn, int timeout, int minimumTimeout) {
long start = System.currentTimeMillis();
if(!sleep(conn, timeout)) {
return false;
}
long t;
if((t = System.currentTimeMillis() - start) < minimumTimeout) {
Time.sleep((int)(minimumTimeout - t));
}
return true;
}
/**
* Gets current time in milliseconds
*
@@ -105,7 +105,18 @@ public class Timer {
* @return hourly gains
*/
public int getPerHour(final int gained) {
return (int) ((gained) * 3600000D / (System.currentTimeMillis() - start));
return getPerHour(gained, 0);
}
/**
* Calculates hourly gains based on given variable, with variable start amount
*
* @param gained total gained amount
* @param startAmount start amount
* @return hourly gains
*/
public int getPerHour(final int gained, final int startAmount) {
return (int) (((gained - startAmount) * 3600000D) / (System.currentTimeMillis() - start));
}
/**
@@ -16,6 +16,12 @@ import java.util.Random;
public class Keyboard implements KeyListener {
private static HashMap<Character, Character> specialChars;
/**
* {@code KeyEvent.VK_ENTER} is actually New Line, '\n'.
* The code for the Enter button is 13. It has no associated {@link KeyEvent} constant.
*/
public static final int ENTER_KEYCODE = 13;
static {
char[] spChars = { '~', '!', '@', '#', '%', '^', '&', '*', '(', ')',
'_', '+', '{', '}', ':', '<', '>', '?', '"', '|' };
@@ -38,12 +44,30 @@ public class Keyboard implements KeyListener {
return Context.getInstance().getKeyboard();
}
/**
* Generates a random number in the range of 40-140.
* @return The random number
*/
private static long getRandom() {
Random rand = new Random();
return rand.nextInt(100) + 40;
}
/**
* Types the given String and afterwards presses Enter.
*
* @param s The String to type.
*/
public void sendKeys(String s) {
sendKeys(s, true);
}
/**
* Types the given String and optionally presses Enter afterwards.
* @param s The String to type.
* @param enterAfter True if {@code KeyEvent.VK_ENTER} should be pressed afterwards. This is actually the '\n' character, for New Line. Useful for logging in.
*/
public void sendKeys(String s, boolean enterAfter) {
pressTime = System.currentTimeMillis();
for (char c : s.toCharArray()) {
@@ -56,9 +80,15 @@ public class Keyboard implements KeyListener {
sendKeyEvent(ke);
}
}
clickKey(10);
if (enterAfter) {
clickKey(KeyEvent.VK_ENTER);
}
}
/**
* Creates and sends a single KeyEvent using the given Char.
* @param c The char to send.
*/
public void clickKey(char c) {
pressTime = System.currentTimeMillis();
@@ -67,6 +97,11 @@ public class Keyboard implements KeyListener {
}
}
/**
* Creates and sends a given KeyEvent using the given keyCode.
* <p>Use constants where possible, from {@link KeyEvent}, such as {@code KeyEvent.VK_ENTER}
* @param keyCode The keycode to send.
*/
public void clickKey(int keyCode) {
pressTime = System.currentTimeMillis();
@@ -75,6 +110,12 @@ public class Keyboard implements KeyListener {
}
}
/**
* Creates and sends a given PRESS KeyEvent using the given keyCode. Note, this does not send a Release Event
* typically associated with a key click.
* <p>Use constants where possible, from {@link KeyEvent}, such as {@code KeyEvent.VK_ENTER}
* @param keyCode
*/
public void pressKey(int keyCode) {
pressTime = System.currentTimeMillis();
@@ -82,6 +123,12 @@ public class Keyboard implements KeyListener {
sendKeyEvent(ke);
}
/**
* Creates and sends a given RELEASE KeyEvent using the given keyCode. Note, this does not send a Press Event
* typically associated with a key click.
* <p>Use constants where possible, from {@link KeyEvent}, such as {@code KeyEvent.VK_ENTER}
* @param keyCode
*/
public void releaseKey(int keyCode) {
pressTime = System.currentTimeMillis();
@@ -89,6 +136,15 @@ public class Keyboard implements KeyListener {
sendKeyEvent(ke);
}
/**
* Creates KeyEvents to perform a Click of the given Char. This includes a Press, Typed and Release event
* in addition to an initial shiftDown and ending shiftUp if the character is a Special Char such as {@code !"£$%^&*(}
*
* {@see specialChars}
* @param target Component this event is linked to.
* @param c Char to send.
* @return KeyEvents for each action.
*/
private KeyEvent[] createKeyClick(Component target, char c) {
pressTime += 2 * getRandom();
@@ -129,27 +185,23 @@ public class Keyboard implements KeyListener {
}
}
/**
* Creates KeyEvents for Press and Release of the given keyCode.
* @param target
* @param keyCode
* @return An array containing Press and Release KeyEvents.
*/
private KeyEvent[] createKeyClick(Component target, int keyCode) {
int modifier = 0;
switch (keyCode) {
case KeyEvent.VK_SHIFT:
modifier = KeyEvent.SHIFT_MASK;
break;
case KeyEvent.VK_ALT:
modifier = KeyEvent.ALT_MASK;
break;
case KeyEvent.VK_CONTROL:
modifier = KeyEvent.CTRL_MASK;
break;
}
KeyEvent pressed = new KeyEvent(target, KeyEvent.KEY_PRESSED,
pressTime, modifier, keyCode, KeyEvent.CHAR_UNDEFINED);
KeyEvent released = new KeyEvent(target, KeyEvent.KEY_RELEASED,
pressTime + getRandom(), 0, keyCode, KeyEvent.CHAR_UNDEFINED);
return new KeyEvent[]{ pressed, released };
return new KeyEvent[]{ createKeyPress(target, keyCode), createKeyRelease(target, keyCode) };
}
/**
* Creates a Press type KeyEvent
* @param target
* @param keyCode
* @return
*/
private KeyEvent createKeyPress(Component target, int keyCode) {
int modifier = 0;
switch (keyCode) {
@@ -169,26 +221,23 @@ public class Keyboard implements KeyListener {
return pressed;
}
/**
* Creates a Release type KeyEvent
* @param target
* @param keyCode
* @return
*/
private KeyEvent createKeyRelease(Component target, int keyCode) {
@SuppressWarnings("unused")
int modifier = 0;
switch (keyCode) {
case KeyEvent.VK_SHIFT:
modifier = KeyEvent.SHIFT_MASK;
break;
case KeyEvent.VK_ALT:
modifier = KeyEvent.ALT_MASK;
break;
case KeyEvent.VK_CONTROL:
modifier = KeyEvent.CTRL_MASK;
break;
}
KeyEvent released = new KeyEvent(target, KeyEvent.KEY_RELEASED,
pressTime + getRandom(), 0, keyCode, KeyEvent.CHAR_UNDEFINED);
return released;
}
/**
* Actually triggers sending of a given KeyEvent in the instance of KeyListeners' {@code component} field.
* @param e
*/
public void sendKeyEvent(KeyEvent e) {
for (KeyListener kl : component.getKeyListeners()) {
if (kl instanceof Keyboard) {
@@ -210,16 +259,28 @@ public class Keyboard implements KeyListener {
}
}
/**
* Allows the {@code KeyListener.keyPressed} event to be overridden.
* @param e
*/
@Override
public void keyPressed(KeyEvent e) {
}
/**
* Allows the {@code KeyListener.keyReleased} event to be overridden.
* @param e
*/
@Override
public void keyReleased(KeyEvent e) {
}
/**
* Allows the {@code KeyListener.keyTyped} event to be overridden.
* @param e
*/
@Override
public void keyTyped(KeyEvent e) {
@@ -1,66 +0,0 @@
package org.parabot.environment.scripts;
import org.parabot.environment.scripts.framework.AbstractFramework;
import org.parabot.environment.scripts.framework.LoopTask;
import org.parabot.environment.scripts.framework.Strategy;
import java.util.Collection;
/**
* Holds various script frameworks
*
* @author Everel
*/
public class Frameworks {
public static Looper getLooper(LoopTask loopTask) {
return new Looper(loopTask);
}
public static StrategyWorker getStrategyWorker(Collection<Strategy> strategies) {
return new StrategyWorker(strategies);
}
}
class Looper extends AbstractFramework {
private LoopTask loopTask = null;
public Looper(LoopTask loopTask) {
this.loopTask = loopTask;
}
@Override
public boolean execute() {
int sleepTime = loopTask.loop();
if (sleepTime < 0) {
return false;
}
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
}
class StrategyWorker extends AbstractFramework {
private Collection<Strategy> strategies;
public StrategyWorker(Collection<Strategy> strategies) {
this.strategies = strategies;
}
@Override
public boolean execute() {
for (Strategy s : strategies) {
if (s.activate()) {
s.execute();
return true;
}
}
return true;
}
}
@@ -146,4 +146,20 @@ public abstract class ServerProvider implements Opcodes {
}
/**
* Called in Context.setApplet before applet.init() is called. Exclusively used for manipulating the Frame attached
* to the applet of Roatpkz.
*/
public void preAppletInit() {
}
/**
* Called in Context.setApplet before after applet.start() and applet.init() are called. Exclusively used for manipulating the Frame attached
* to the applet of Roatpkz.
*/
public void postAppletStart() {
}
}