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
+5
View File
@@ -0,0 +1,5 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @global-owner1 and @global-owner2 will be requested for
# review when someone opens a pull request.
* @JKetelaar @Fryslan @iSully @PBLord @SandroCoutinho @Shadowrs @Parabot/client-team
+5 -17
View File
@@ -1,20 +1,8 @@
* Provide a general summary of the issue in the **Title** above.
* Before you open an issue, please check if a similar issue already exists or has been closed before.
### Short description
...
### Important
Mark with [x] to select. Leave as [ ] to unselect.
### Steps to reproduce
...
### When reporting a bug/issue:
- [ ] Screenshot
- [ ] The Parabot version and the operating system you're using
- [ ] The behavior you expect to see, and the actual behavior
- [ ] Steps to reproduce the behavior
- [ ] \(optional) Possible solution/fix/workaround
### When you open an issue for a change/improvement/feature request:
- [ ] A description of the problem you're trying to solve, including _why_ you think this is a problem
- [ ] If the feature changes current behavior, reasons why your solution is better
- [ ] \(optional) Possible solution/fix/workaround
### Description
### Extra information (Operating system, device, etc)
...
-35
View File
@@ -1,37 +1,2 @@
Provide a general summary of your changes in the **Title** above.
### Important
Mark with [x] to select. Leave as [ ] to unselect.
If possible; include a screenshot or gif of the change you've made
### Motivation and Context
Each item you can check should be described in the _Description_ section.
- [ ] Why is this change required? What problem does it solve?
- [ ] If it fixes an open issue, include the text `Closes issue #1` (where 1 would be the issue number) to your commit message.
### Types of changes
What types of changes does your code introduce? Check all the boxes that apply:
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Cleanup (non-breaking change which cleans up the code)
### Final checklist
Go over all the following points and check all the boxes that apply.
If you're unsure about any of these, don't hesitate to ask. We're here to help!
Various areas of the codebase have been worked on by different people in recent years, so if you are unfamiliar with the general area you're working in, please feel free to chat with people who have experience in that area.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have tested the functionality
- [ ] I have added tests for this functionality
Your pull request will be tested via Travis CI to automatically indicate that your changes do not prevent compilation.
If it reports back that there are problems, you go to [the Travis system](https://travis-ci.org/Parabot/Parabot) and check the log report for your pull request to see what the problem was.
If you add new code to fix a Travis building issue/problem, then take note that you need to check the next pull request in the Travis system.
Travis issue numbers are different from GitHub issue numbers.
### Description
...
+31 -30
View File
@@ -1,30 +1,31 @@
- name: priority:low
color: bfe5bf
- name: priority:medium
color: bfe5bf
- name: priority:high
color: bfe5bf
- name: status:accepted
color: fef2c0
- name: status:unconfirmed
color: fef2c0
- name: status:needs more info
color: fef2c0
- name: status:rejected
color: fef2c0
- name: status:under consideration
color: fef2c0
- name: type:bug
color: f7c6c7
- name: type:feature
color: f7c6c7
- name: type:improvement
color: f7c6c7
- name: type:question
color: f7c6c7
- name: os:windows
color: "666699"
- name: os:mac
color: "666699"
- name: os:other
color: "666699"
labels:
- name: priority:low
color: bfe5bf
- name: priority:medium
color: bfe5bf
- name: priority:high
color: bfe5bf
- name: status:accepted
color: fef2c0
- name: status:unconfirmed
color: fef2c0
- name: status:needs more info
color: fef2c0
- name: status:rejected
color: fef2c0
- name: status:under consideration
color: fef2c0
- name: type:bug
color: f7c6c7
- name: type:feature
color: f7c6c7
- name: type:improvement
color: f7c6c7
- name: type:question
color: f7c6c7
- name: os:windows
color: "666699"
- name: os:mac
color: "666699"
- name: os:other
color: "666699"
+1 -1
View File
@@ -34,7 +34,7 @@ env:
- secure: UG+b1tEgc8xv9x4r//2OAIK1RrYv6n209KTTFMMwcnAa7DI8HaP8nljRa5/VhDhuKHdlVrYH/tI90v7UVBs0GDVNwK5V17Io0fMm3FUGZekSthTCqqno5wAGa9r6a6mMLtSaSmIFeIKi0+0d2ZwplRuhj/dtEYjjBBj+kK8g4nE=
- secure: St/fecUDInFBCRriYqgp2F8PU9/SooorgxD9Mrs+b0EsC7AbtSsQXvdIv2Lp6xzdQ0VSXPcLIhULPOYrmBKnGQ/NjXTIZXxnroyQxxnI6xyEWIZwiHRY/bKRJDRbQTxD9NL32szKiDSwnw7pu6llF4D64UqQvziq4Gm6VohU75M=
- secure: bD15GVZWowiknbfLavh8CxSh0GsnF5kT4kZ6ggCuUDGyj0mzqf7dNRnchQIKkCG0WRYyTrFN4pEiygeywWsipEeAVv9Xhx3cuUZmzeQaR5KCWabSwJ8gK6jZd1YhcWmM9vrdPHobZr65MP0y/8mu/Fovgky9dY7KDf4G3SebNrM=
- PARABOT_VERSION=2.6.8
- PARABOT_VERSION=2.7
cache:
directories:
+2 -2
View File
@@ -3,7 +3,7 @@
# Parabot
Parabot V2.6.8.
Parabot V2.7
#### Links
@@ -42,7 +42,7 @@ Then you'll need to add the dependency:
<dependency>
<groupId>org.parabot</groupId>
<artifactId>client</artifactId>
<version>2.6.3</version>
<version>2.7</version>
</dependency>
</dependencies>
```
+2 -2
View File
@@ -6,7 +6,7 @@
<groupId>org.parabot</groupId>
<artifactId>client</artifactId>
<version>2.6.8</version>
<version>2.7</version>
<packaging>jar</packaging>
@@ -73,7 +73,7 @@
<dependency>
<groupId>org.parabot</groupId>
<artifactId>internal-api</artifactId>
<version>1.51.1</version>
<version>1.52.1</version>
</dependency>
</dependencies>
+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() {
}
}