First commit
@@ -0,0 +1,5 @@
|
||||
bin
|
||||
.classpath
|
||||
.project
|
||||
.settings
|
||||
.metadata
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.parabot;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import org.parabot.core.ui.ServerSelector;
|
||||
|
||||
/**
|
||||
* Parabot X - A revolution in bot clients
|
||||
*
|
||||
* @author Clisprail
|
||||
* @author Matt, Dane, Queue, Parameter
|
||||
* @version 2.0
|
||||
*/
|
||||
public class Landing {
|
||||
|
||||
public static void main(String... args) {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
ServerSelector.getInstance().setVisible(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package org.parabot.core;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.util.HashMap;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import org.parabot.core.asm.ASMClassLoader;
|
||||
import org.parabot.core.bot.loader.BotLoader;
|
||||
import org.parabot.core.classpath.ClassPath;
|
||||
import org.parabot.core.ui.components.GamePanel;
|
||||
import org.parabot.environment.servers.ServerProvider;
|
||||
|
||||
/**
|
||||
* Game context
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class Context {
|
||||
private static HashMap<ThreadGroup, Context> threadGroups = new HashMap<ThreadGroup, Context>();
|
||||
private static int id = 1;
|
||||
|
||||
private ASMClassLoader classLoader = null;
|
||||
private ClassPath classPath = null;
|
||||
private ServerProvider serverProvider = null;
|
||||
private int tab = 0;
|
||||
private Applet gameApplet = null;
|
||||
|
||||
public boolean added = false;
|
||||
|
||||
public Context(final ServerProvider serverProvider) {
|
||||
threadGroups.put(Thread.currentThread().getThreadGroup(), this);
|
||||
tab = id;
|
||||
this.serverProvider = serverProvider;
|
||||
id++;
|
||||
this.classPath = new ClassPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ServerProvider class loader
|
||||
* @param serverEnvironment
|
||||
*/
|
||||
public void setEnvironment(ASMClassLoader serverEnvironment) {
|
||||
classLoader = new BotLoader(classPath, serverEnvironment);
|
||||
}
|
||||
|
||||
/**
|
||||
* ClassPath
|
||||
* @return classpath
|
||||
*/
|
||||
public ClassPath getClassPath() {
|
||||
return classPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if applet has been set
|
||||
* @return <b>true</b> if set
|
||||
*/
|
||||
public boolean appletSet() {
|
||||
return gameApplet != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets game applet
|
||||
* @return applet
|
||||
*/
|
||||
public Applet getApplet() {
|
||||
return gameApplet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the context from threadgroup
|
||||
* @return context
|
||||
*/
|
||||
public static Context resolve() {
|
||||
return threadGroups.get(Thread.currentThread().getThreadGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the game
|
||||
*/
|
||||
public void load() {
|
||||
serverProvider.parseJar();
|
||||
gameApplet = serverProvider.fetchApplet();
|
||||
final GamePanel panel = GamePanel.getInstance();
|
||||
panel.removeLoader();
|
||||
panel.setContext(this);
|
||||
gameApplet.setSize(765, 503);
|
||||
java.util.Timer t = new java.util.Timer();
|
||||
t.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
gameApplet.setBounds(0, 0, 765, 503);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server prodiver belonging to this context
|
||||
* @return server provider
|
||||
*/
|
||||
public ServerProvider getServerProvider() {
|
||||
return serverProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets class loader from this context
|
||||
* @return class loader
|
||||
*/
|
||||
public ASMClassLoader getASMClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public static int getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getTab() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.parabot.core;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class Core {
|
||||
private static boolean devMode = false;
|
||||
|
||||
/**
|
||||
* Enables the developers mode
|
||||
*/
|
||||
public static void enableDevMode() {
|
||||
devMode = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if bot is in developers mode
|
||||
* @return <b>true</b> if bot is in developers mode
|
||||
*/
|
||||
public static boolean isDevMode() {
|
||||
return devMode;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.parabot.core.asm;
|
||||
|
||||
|
||||
import java.net.URL;
|
||||
import java.security.AllPermission;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permissions;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.parabot.core.classpath.ClassPath;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
* @author Matt
|
||||
*
|
||||
*/
|
||||
public class ASMClassLoader extends ClassLoader {
|
||||
|
||||
public Map<String,Class<?>>classCache = new HashMap<String,Class<?>>();
|
||||
public ClassPath classPath = null;
|
||||
|
||||
public ASMClassLoader(final ClassPath classPath) {
|
||||
this.classPath = classPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URL findResource(String name) {
|
||||
if (getSystemResource(name) == null) {
|
||||
if (classPath.resources.containsKey(name))
|
||||
return classPath.resources.get(name);
|
||||
else
|
||||
return null;
|
||||
} else
|
||||
return getSystemResource(name);
|
||||
}
|
||||
|
||||
public void addClassToCache(final Class<?> clazz) {
|
||||
String clazzName = clazz.getName().replace('.', '/');
|
||||
classCache.put(clazzName, clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
return findClass(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String key = name.replace('.', '/');
|
||||
if(classCache.containsKey(key)) {
|
||||
return classCache.get(key);
|
||||
}
|
||||
|
||||
ClassNode node = classPath.classes.get(key);
|
||||
if (node != null) {
|
||||
classPath.classes.remove(key);
|
||||
Class<?>c = nodeToClass(node);
|
||||
classCache.put(key, c);
|
||||
return c;
|
||||
} else
|
||||
return super.getSystemClassLoader().loadClass(name);
|
||||
}
|
||||
|
||||
public final Class<?> nodeToClass(ClassNode node) {
|
||||
if (super.findLoadedClass(node.name) != null)
|
||||
return findLoadedClass(node.name);
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
node.accept(cw);
|
||||
byte[] b = cw.toByteArray();
|
||||
return defineClass(node.name.replace('/', '.'), b, 0, b.length,
|
||||
getDomain());
|
||||
}
|
||||
|
||||
private final ProtectionDomain getDomain() {
|
||||
CodeSource code = new CodeSource(null, (Certificate[]) null);
|
||||
return new ProtectionDomain(code, getPermissions());
|
||||
}
|
||||
|
||||
private final Permissions getPermissions() {
|
||||
Permissions permissions = new Permissions();
|
||||
permissions.add(new AllPermission());
|
||||
return permissions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.parabot.core.asm;
|
||||
|
||||
public class Injector {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package org.parabot.core.asm.adapters;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
/**
|
||||
* Adds a method into a Classnode which returns a field
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class AddGetterAdapter implements Opcodes {
|
||||
private ClassNode into = null;
|
||||
private ClassNode fieldLocation = null;
|
||||
private FieldNode fieldNode = null;
|
||||
private String methodName = null;
|
||||
private String returnDesc = null;
|
||||
private boolean staticField = false;
|
||||
private boolean staticMethod = false;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param into - classnode to inject getter method in
|
||||
* @param fieldLocation - classnode where field is located
|
||||
* @param fieldName - field name to get
|
||||
* @param methodName - method name of getter
|
||||
* @param returnDesc - return type of method, can be null for default return
|
||||
* @param staticMethod - pass true if you want the method to be static
|
||||
*/
|
||||
public AddGetterAdapter(final ClassNode into, final ClassNode fieldLocation, final FieldNode fieldNode,
|
||||
final String methodName, final String returnDesc, final boolean staticMethod) {
|
||||
this.into = into;
|
||||
this.fieldLocation = fieldLocation;
|
||||
this.fieldNode = fieldNode;
|
||||
this.methodName = methodName;
|
||||
this.returnDesc = returnDesc == null ? fieldNode.desc : returnDesc;
|
||||
this.staticField = Modifier.isStatic(fieldNode.access);
|
||||
this.staticMethod = staticMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param fieldLocation
|
||||
* @param fieldNode
|
||||
* @param methodName
|
||||
*/
|
||||
public AddGetterAdapter(final ClassNode fieldLocation, final FieldNode fieldNode, final String methodName) {
|
||||
this.into = fieldLocation;
|
||||
this.fieldLocation = fieldLocation;
|
||||
this.fieldNode = fieldNode;
|
||||
this.methodName = methodName;
|
||||
this.returnDesc = fieldNode.desc;
|
||||
this.staticField = Modifier.isStatic(fieldNode.access);
|
||||
this.staticMethod = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates if this getter can be injected, if not a runtime exception is thrown
|
||||
*/
|
||||
public void validate() {
|
||||
if(methodName == null) {
|
||||
throw new RuntimeException("Null method name");
|
||||
}
|
||||
if(into == null) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Into ClassNode is null, at : ").append(methodName).append("()");
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
if(fieldNode == null) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("FieldLocation ClassNode is null, at : ").append(methodName).append("()");
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
if(fieldNode == null) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("FieldNode is null, at : ").append(methodName).append("()");
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
for(final MethodNode methodNode : into.methods) {
|
||||
if(methodNode.name.equals(methodName)) {
|
||||
final Type[] args = Type.getArgumentTypes(methodNode.desc);
|
||||
if(args != null && args.length != 0) {
|
||||
continue;
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Duplicated method detected. ").append(methodName).append("() in ").append(into.name);
|
||||
throw new RuntimeException(sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects this the method getter
|
||||
*/
|
||||
public void inject() {
|
||||
MethodNode method = new MethodNode(ACC_PUBLIC | (staticMethod ? ACC_STATIC : 0), methodName, "()" + returnDesc, null, null);
|
||||
if (staticField) {
|
||||
method.visitVarInsn(ALOAD, 0);
|
||||
}
|
||||
method.visitFieldInsn(staticField ? GETSTATIC : GETFIELD, fieldLocation.name, fieldNode.name, fieldNode.desc);
|
||||
if (!fieldNode.desc.equals(returnDesc)) {
|
||||
if (returnDesc.contains("L")) {
|
||||
if (!returnDesc.contains("[")) {
|
||||
method.visitTypeInsn(CHECKCAST,returnDesc.replaceFirst("L", "").replaceAll(";", ""));
|
||||
} else {
|
||||
method.visitTypeInsn(CHECKCAST, returnDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldNode.desc.equals("J") && returnDesc.equals("I"))
|
||||
method.visitInsn(L2I);
|
||||
|
||||
method.visitInsn(getReturnOpcode(returnDesc));
|
||||
method.visitMaxs(0, 0);
|
||||
into.methods.add(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return right opcode for desc
|
||||
* @param desc
|
||||
* @return return opcode
|
||||
*/
|
||||
private static int getReturnOpcode(String desc) {
|
||||
desc = desc.substring(desc.indexOf("L") + 1);
|
||||
if (desc.length() > 1) {
|
||||
return ARETURN;
|
||||
}
|
||||
final char c = desc.charAt(0);
|
||||
switch (c)
|
||||
{
|
||||
case 'I':
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'C':
|
||||
return IRETURN;
|
||||
case 'J':
|
||||
return LRETURN;
|
||||
case 'F':
|
||||
return FRETURN;
|
||||
case 'D':
|
||||
return DRETURN;
|
||||
}
|
||||
throw new RuntimeException("Wrong desc type: " + c);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.parabot.core.bot.loader;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.parabot.core.asm.ASMClassLoader;
|
||||
import org.parabot.core.classpath.ClassPath;
|
||||
|
||||
/**
|
||||
* Handles client class calls
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class BotLoader extends ASMClassLoader {
|
||||
private ASMClassLoader serverProvider = null;
|
||||
|
||||
public BotLoader(ClassPath classPath, ASMClassLoader serverProvider) {
|
||||
super(classPath);
|
||||
this.serverProvider = serverProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
return findClass(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String key = name.replace('.', '/');
|
||||
if(serverProvider.classCache.containsKey(key)) {
|
||||
return serverProvider.classCache.get(key);
|
||||
}
|
||||
ClassNode node = serverProvider.classPath.classes.get(key);
|
||||
if (node != null) {
|
||||
serverProvider.classPath.classes.remove(key);
|
||||
Class<?>c = serverProvider.nodeToClass(node);
|
||||
serverProvider.classCache.put(key, c);
|
||||
return c;
|
||||
}
|
||||
return super.findClass(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package org.parabot.core.classpath;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
* @author Matt
|
||||
*/
|
||||
public class ClassPath {
|
||||
public final HashMap<String, ClassNode> classes = new HashMap<String, ClassNode>();
|
||||
public final Map<String, URL> resources = new HashMap<String, URL>();
|
||||
|
||||
/**
|
||||
* Adds jar to this classpath
|
||||
* @param jarLocation
|
||||
*/
|
||||
public void addJar(final String jarLocation) {
|
||||
JarParser.parseJar(this, jarLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and loads all classes/jar files in folder
|
||||
*
|
||||
* @param file to find class / jar files
|
||||
* @param root
|
||||
*/
|
||||
public void loadClasses(final File f, File root) {
|
||||
if (f == null)
|
||||
return;
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
}
|
||||
if (root == null) {
|
||||
root = f;
|
||||
}
|
||||
for (File f1 : f.listFiles()) {
|
||||
if (f1 == null) {
|
||||
continue;
|
||||
} else if (f1.isDirectory()) {
|
||||
loadClasses(f1, root);
|
||||
} else {
|
||||
try (FileInputStream fin = new FileInputStream(f1)) {
|
||||
if (f1.getName().endsWith(".class"))
|
||||
loadClass(fin);
|
||||
else if (f.equals(root) && f1.getName().endsWith(".jar")) {
|
||||
loadClasses(f1.toURI().toURL());
|
||||
} else {
|
||||
String path = f1.toURI().relativize(root.toURI())
|
||||
.getPath();
|
||||
Resources.loadResource(this, path, fin);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads classes from zip/jar files
|
||||
*
|
||||
* @param url to file
|
||||
*/
|
||||
private void loadClasses(URL u) {
|
||||
try (ZipInputStream zin = new ZipInputStream(u.openStream())) {
|
||||
ZipEntry e;
|
||||
while ((e = zin.getNextEntry()) != null) {
|
||||
if (e.isDirectory())
|
||||
continue;
|
||||
if (e.getName().endsWith(".class")) {
|
||||
loadClass(zin);
|
||||
} else {
|
||||
Resources.loadResource(this, e.getName(), zin);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads class from input stream
|
||||
*
|
||||
* @param inputstream
|
||||
* @throws IOException
|
||||
*/
|
||||
private void loadClass(InputStream in) throws IOException {
|
||||
ClassReader cr = new ClassReader(in);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
classes.put(cn.name, cn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the classnodes into a jar
|
||||
*
|
||||
* @param jarName
|
||||
*/
|
||||
public void dump(final String jarName) {
|
||||
JarDumper.dump(this, jarName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.parabot.core.classpath;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class JarDumper {
|
||||
|
||||
/**
|
||||
* Dumps classnodes to a jar file
|
||||
* @param classPath
|
||||
* @param fileName
|
||||
*/
|
||||
public static void dump(final ClassPath classPath, final String fileName) {
|
||||
try {
|
||||
FileOutputStream stream = new FileOutputStream(new File(fileName));
|
||||
JarOutputStream out = new JarOutputStream(stream);
|
||||
for (ClassNode cn : classPath.classes.values()) {
|
||||
JarEntry je = new JarEntry(cn.name + ".class");
|
||||
out.putNextEntry(je);
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
out.write(cw.toByteArray());
|
||||
}
|
||||
out.close();
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.parabot.core.classpath;
|
||||
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* A class for parsing a jar file
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class JarParser {
|
||||
|
||||
/**
|
||||
* Parses a jar from an URL
|
||||
* @param classPath
|
||||
* @param jarLocation
|
||||
*/
|
||||
public static void parseJar(final ClassPath classPath, final String jarLocation) {
|
||||
try {
|
||||
URL jarURL = new URL("jar:" + jarLocation + "!/");
|
||||
JarURLConnection jarConnection = (JarURLConnection) jarURL
|
||||
.openConnection();
|
||||
JarFile theJar = jarConnection.getJarFile();
|
||||
Enumeration<?> en = theJar.entries();
|
||||
while (en.hasMoreElements()) {
|
||||
JarEntry entry = (JarEntry) en.nextElement();
|
||||
if (entry.getName().endsWith(".class")) {
|
||||
ClassReader cr = new ClassReader(
|
||||
theJar.getInputStream(entry));
|
||||
ClassNode cn = new ClassNode();
|
||||
//cr.accept(cn, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
cr.accept(cn, 0);
|
||||
classPath.classes.put(cn.name, cn);
|
||||
} else if (!entry.isDirectory()
|
||||
&& !entry.getName().startsWith("META-INF")) {
|
||||
Resources.loadResource(classPath, entry.getName(), theJar.getInputStream(entry));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.parabot.core.classpath;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
* @author Matt
|
||||
*/
|
||||
public class Resources {
|
||||
|
||||
/**
|
||||
* Dumps a resource from a input stream
|
||||
* @param classPath
|
||||
* @param name
|
||||
* @param inputstream
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void loadResource(final ClassPath classPath, final String name, final InputStream in)
|
||||
throws IOException {
|
||||
File f = File.createTempFile("bot", ".tmp", new File("./"));
|
||||
f.deleteOnExit();
|
||||
try (OutputStream out = new FileOutputStream(f)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buffer)) != -1)
|
||||
out.write(buffer, 0, len);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
classPath.resources.put(name, f.toURI().toURL());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.parabot.core.logging;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public class LabelLogHandler extends Handler
|
||||
{
|
||||
public final JLabel label = new JLabel();
|
||||
private final Color defaultColor;
|
||||
|
||||
public LabelLogHandler()
|
||||
{
|
||||
super();
|
||||
defaultColor = label.getForeground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final LogRecord record) {
|
||||
StringBuilder b = new StringBuilder(record.getMessage());
|
||||
|
||||
if (record.getLevel().intValue() > Level.WARNING.intValue()) {
|
||||
label.setForeground(new Color(0xcc0000));
|
||||
} else {
|
||||
label.setForeground(defaultColor);
|
||||
b.append(" ...");
|
||||
}
|
||||
|
||||
label.setText(new String(b));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.parabot.core.logging;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
public class LogFormatter extends Formatter
|
||||
{
|
||||
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
|
||||
private final boolean appendNewLine;
|
||||
|
||||
public LogFormatter()
|
||||
{
|
||||
this(true);
|
||||
}
|
||||
|
||||
public LogFormatter(final boolean appendNewLine)
|
||||
{
|
||||
this.appendNewLine = appendNewLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(final LogRecord record) {
|
||||
final StringBuilder result = new StringBuilder().append("[").append(record.getLevel().getName()).append("] ").append(new Date(record.getMillis())).append(": ").append(record.getLoggerName()).append(": ").append(record.getMessage()).append(throwableToString(record.getThrown()));
|
||||
if (appendNewLine) {
|
||||
result.append(LogFormatter.LINE_SEPARATOR);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatMessage(final LogRecord record) {
|
||||
return String.format(record.getMessage());
|
||||
}
|
||||
|
||||
private String throwableToString(final Throwable t) {
|
||||
if (t != null) {
|
||||
final Writer exception = new StringWriter();
|
||||
final PrintWriter printWriter = new PrintWriter(exception);
|
||||
t.printStackTrace(printWriter);
|
||||
return exception.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.parabot.core.logging;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Paris
|
||||
*/
|
||||
public class LogOutputStream extends OutputStream {
|
||||
protected boolean hasBeenClosed = false;
|
||||
protected Logger category;
|
||||
protected Level priority;
|
||||
protected StringBuilder buffer;
|
||||
|
||||
public LogOutputStream(final Logger category, final Level priority) {
|
||||
this.priority = priority;
|
||||
this.category = category;
|
||||
buffer = new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
flush();
|
||||
hasBeenClosed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
final String txt = buffer.toString().replace("\\s+$", "");
|
||||
if (txt.trim().length() != 0) {
|
||||
category.log(priority, txt);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
buffer.setLength(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final int b) throws IOException {
|
||||
if (hasBeenClosed) {
|
||||
throw new IOException("The stream has been closed.");
|
||||
} else if (b != 0) {
|
||||
buffer.append((char) (b & 0xff));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package org.parabot.core.logging;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Rectangle;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
/**
|
||||
* Non swing methods are thread safe.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class LogTextArea extends JList
|
||||
{
|
||||
private static final int MAX_ENTRIES = 100;
|
||||
private static final Rectangle BOTTOM_OF_WINDOW = new Rectangle(0, Integer.MAX_VALUE, 0, 0);
|
||||
private static final long serialVersionUID = 0;
|
||||
private final LogQueue logQueue = new LogQueue();
|
||||
private final LogAreaListModel model = new LogAreaListModel();
|
||||
private final Runnable scrollToBottom = new Runnable()
|
||||
{
|
||||
public void run() {
|
||||
scrollRectToVisible(LogTextArea.BOTTOM_OF_WINDOW);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Formatter formatter = new Formatter()
|
||||
{
|
||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss");
|
||||
|
||||
@Override
|
||||
public String format(final LogRecord record) {
|
||||
final String[] className = record.getLoggerName().split("\\.");
|
||||
final String name = className[className.length - 1];
|
||||
final int maxLen = 16;
|
||||
final String append = "...";
|
||||
|
||||
return String.format("[%s] %-" + maxLen + "s %s %s", dateFormat.format(record.getMillis()), name.length() > maxLen ? name.substring(0, maxLen - append.length()) + append : name, record.getMessage(), throwableToString(record.getThrown()));
|
||||
}
|
||||
};
|
||||
|
||||
private static String throwableToString(final Throwable t) {
|
||||
if (t != null) {
|
||||
final Writer exception = new StringWriter();
|
||||
final PrintWriter printWriter = new PrintWriter(exception);
|
||||
t.printStackTrace(printWriter);
|
||||
return exception.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static final Formatter copyPasteFormatter = new LogFormatter(false);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public LogTextArea()
|
||||
{
|
||||
setModel(model);
|
||||
setCellRenderer(new Renderer());
|
||||
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
String fontName = Font.MONOSPACED;
|
||||
for (final Font font : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) {
|
||||
final String name = font.getName();
|
||||
if (name.matches("Monaco|Consolas")) {
|
||||
fontName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setFont(new Font(fontName, Font.PLAIN, 12));
|
||||
|
||||
new Thread(logQueue, "LogGuiQueue").start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a new entry to be shown in the list. Thread safe.
|
||||
*
|
||||
* @param logRecord
|
||||
* The entry.
|
||||
*/
|
||||
public void log(final LogRecord logRecord) {
|
||||
logQueue.queue(new WrappedLogRecord(logRecord));
|
||||
}
|
||||
|
||||
private class LogAreaListModel extends AbstractListModel
|
||||
{
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
private List<WrappedLogRecord> records = new ArrayList<WrappedLogRecord>(LogTextArea.MAX_ENTRIES);
|
||||
|
||||
public void addAllElements(final List<WrappedLogRecord> obj) {
|
||||
records.addAll(obj);
|
||||
if (getSize() > LogTextArea.MAX_ENTRIES) {
|
||||
records.subList(0, (getSize() - LogTextArea.MAX_ENTRIES)).clear();
|
||||
|
||||
fireContentsChanged(this, 0, (getSize() - 1));
|
||||
} else {
|
||||
fireIntervalAdded(this, (getSize() - 1), (getSize() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
public Object getElementAt(final int index) {
|
||||
return records.get(index);
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return records.size();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes every #FLUSH_RATE (milliseconds)
|
||||
*/
|
||||
private class LogQueue implements Runnable
|
||||
{
|
||||
public static final int FLUSH_RATE = 1000;
|
||||
private final Object lock = new Object();
|
||||
private List<WrappedLogRecord> queue = new ArrayList<WrappedLogRecord>(100);
|
||||
|
||||
public void queue(final WrappedLogRecord record) {
|
||||
synchronized (lock) {
|
||||
queue.add(record);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
List<WrappedLogRecord> toFlush = null;
|
||||
|
||||
synchronized (lock) {
|
||||
if (queue.size() != 0) {
|
||||
toFlush = new ArrayList<WrappedLogRecord>(queue);
|
||||
queue = queue.subList(0, 0);
|
||||
}
|
||||
}
|
||||
if (toFlush != null) { // Hold the lock for as little time as
|
||||
// possible
|
||||
model.addAllElements(toFlush);
|
||||
SwingUtilities.invokeLater(scrollToBottom);
|
||||
}
|
||||
try {
|
||||
Thread.sleep(LogQueue.FLUSH_RATE);
|
||||
} catch (final InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Renderer implements ListCellRenderer
|
||||
{
|
||||
private final Border EMPTY_BORDER = new EmptyBorder(1, 1, 1, 1);
|
||||
private final Border SELECTED_BORDER = UIManager.getBorder("List.focusCellHighlightBorder");
|
||||
private final Color DARK_GREEN = new Color(0, 0xcc, 0), DARK_RED = new Color(0xcc, 0, 0), DARK_PINK = new Color(0xff, 0, 0x66);
|
||||
|
||||
public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean cellHasFocus) {
|
||||
if (!(value instanceof WrappedLogRecord)) {
|
||||
return new JLabel();
|
||||
}
|
||||
final WrappedLogRecord wlr = (WrappedLogRecord) value;
|
||||
|
||||
final JTextPane result = new JTextPane();
|
||||
result.setDragEnabled(true);
|
||||
result.setText(wlr.formatted);
|
||||
result.setComponentOrientation(list.getComponentOrientation());
|
||||
result.setFont(list.getFont());
|
||||
result.setBorder(cellHasFocus || isSelected ? SELECTED_BORDER : EMPTY_BORDER);
|
||||
|
||||
result.setForeground(Color.BLACK);
|
||||
|
||||
if (wlr.record.getLevel() == Level.SEVERE) {
|
||||
result.setBackground(DARK_RED);
|
||||
result.setForeground(Color.BLACK);
|
||||
}
|
||||
|
||||
if (wlr.record.getLevel() == Level.WARNING) {
|
||||
result.setForeground(DARK_PINK);
|
||||
}
|
||||
|
||||
if (wlr.record.getLevel() == Level.FINE || wlr.record.getLevel() == Level.FINER || wlr.record.getLevel() == Level.FINEST) {
|
||||
result.setForeground(DARK_GREEN);
|
||||
}
|
||||
|
||||
final Object[] parameters = wlr.record.getParameters();
|
||||
if (parameters != null) {
|
||||
for (final Object parameter : parameters) {
|
||||
if (parameter == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parameter instanceof Color) {
|
||||
result.setForeground((Color) parameter);
|
||||
} else if (parameter instanceof Font) {
|
||||
result.setFont((Font) parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the log records so we can control the copy paste text (via #toString)
|
||||
*/
|
||||
private class WrappedLogRecord
|
||||
{
|
||||
public final LogRecord record;
|
||||
public final String formatted;
|
||||
|
||||
public WrappedLogRecord(final LogRecord record)
|
||||
{
|
||||
this.record = record;
|
||||
formatted = LogTextArea.formatter.format(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return LogTextArea.copyPasteFormatter.format(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.parabot.core.logging;
|
||||
|
||||
import java.util.logging.ConsoleHandler;
|
||||
|
||||
/**
|
||||
* Logs to System.out
|
||||
*/
|
||||
public class SystemConsoleHandler extends ConsoleHandler {
|
||||
public SystemConsoleHandler() {
|
||||
super();
|
||||
setOutputStream(System.out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.parabot.core.logging;
|
||||
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
|
||||
public class TextAreaLogHandler extends Handler {
|
||||
public static final LogTextArea TEXT_AREA = new LogTextArea();
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final LogRecord record) {
|
||||
TextAreaLogHandler.TEXT_AREA.log(record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.parabot.core.parsers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class ServerManifestParser {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package org.parabot.core.ui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.WindowConstants;
|
||||
|
||||
import org.parabot.core.Context;
|
||||
import org.parabot.core.ui.components.BotToolbar;
|
||||
import org.parabot.core.ui.components.GamePanel;
|
||||
import org.parabot.core.ui.components.LogArea;
|
||||
import org.parabot.core.ui.images.Images;
|
||||
import org.parabot.core.ui.utils.Center;
|
||||
|
||||
/**
|
||||
* Bot frame
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class BotUI extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static BotUI instance = null;
|
||||
|
||||
public static BotUI getInstance() {
|
||||
return instance == null ? instance = new BotUI() : instance;
|
||||
}
|
||||
|
||||
public BotUI() {
|
||||
JMenuBar bar = new JMenuBar();
|
||||
JMenu file = new JMenu("File");
|
||||
JMenuItem screenshot = new JMenuItem("Screenshot");
|
||||
screenshot.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Context c = GamePanel.getInstance().context;
|
||||
GamePanel.getInstance().setContext(null);
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
GamePanel.getInstance().setContext(c);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
});
|
||||
file.add(screenshot);
|
||||
bar.add(file);
|
||||
|
||||
JScrollPane textPane = LogArea.getInstance();
|
||||
GroupLayout layout = new GroupLayout(getContentPane());
|
||||
JToolBar tool = BotToolbar.getInstance();
|
||||
GamePanel pane = GamePanel.getInstance();
|
||||
pane.addLoader();
|
||||
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
||||
getContentPane().setLayout(layout);
|
||||
setJMenuBar(bar);
|
||||
setDefaultLookAndFeelDecorated(true);
|
||||
setTitle("parabot v2");
|
||||
setIconImage(Images.getResource("/org/parabot/core/ui/images/icon.png"));
|
||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
setResizable(false);
|
||||
Center.centerFramea(this, 775, 683);
|
||||
layout.setHorizontalGroup(layout
|
||||
.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout
|
||||
.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout
|
||||
.createParallelGroup(GroupLayout.Alignment.LEADING)))
|
||||
.addComponent(tool, 768, 768, 768)
|
||||
.addComponent(pane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(textPane, 768, 768, 768));
|
||||
layout.setVerticalGroup(layout
|
||||
.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout
|
||||
.createSequentialGroup()
|
||||
.addComponent(tool, 30, 30, 30)
|
||||
.addComponent(pane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(textPane, 100, 100, 100)
|
||||
.addContainerGap(58, Short.MAX_VALUE)));
|
||||
LogArea.log("Welcome to Parabot v2");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.parabot.core.ui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import org.parabot.core.ui.utils.Center;
|
||||
import org.parabot.core.ui.widgets.ServerWidget;
|
||||
|
||||
|
||||
public class ServerSelector extends JFrame
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static ServerSelector instance = null;
|
||||
|
||||
public static ServerSelector getInstance() {
|
||||
if(instance != null) {
|
||||
instance.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
return instance;
|
||||
}
|
||||
return instance = new ServerSelector();
|
||||
}
|
||||
|
||||
|
||||
public ServerSelector() {
|
||||
setLayout(null);
|
||||
ServerWidget[] widgets = getServers();
|
||||
JPanel p = new JPanel();
|
||||
p.setBounds(0, 0, 400, 800);
|
||||
p.setLayout(null);
|
||||
p.setPreferredSize(new Dimension(400, widgets.length * 100));
|
||||
JScrollPane pane = new JScrollPane(p);
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
for (int i = 0; i < widgets.length; i++) {
|
||||
widgets[i].setBounds(0, i * 100, 400, 100);
|
||||
p.add(widgets[i]);
|
||||
}
|
||||
pane.setBounds(0, 0, 400, 200);
|
||||
pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
getContentPane().add(pane);
|
||||
setResizable(false);
|
||||
setTitle("Servers");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
Center.centerFramea(this, 406, 228);
|
||||
}
|
||||
|
||||
public ServerWidget[] getServers() {
|
||||
ArrayList<ServerWidget> widgets = new ArrayList<ServerWidget>();
|
||||
widgets.add(new ServerWidget("RecklessPk", "Clisprail", "317"));
|
||||
widgets.add(new ServerWidget("Soulsplit", "Clisprail", "317"));
|
||||
widgets.add(new ServerWidget("RS2007", "Clisprail", "10"));
|
||||
return widgets.toArray(new ServerWidget[widgets.size()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.parabot.core.ui.applet;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import org.parabot.core.ui.images.Images;
|
||||
|
||||
/**
|
||||
* An informative applet which tells the user what bot is doing
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class LoadApplet extends Applet {
|
||||
private static final long serialVersionUID = 7412412644921803896L;
|
||||
private static LoadApplet current = null;
|
||||
private static String state = "Initializing loader...";
|
||||
private FontMetrics fontMetrics = null;
|
||||
private BufferedImage bot_image = null;
|
||||
|
||||
public LoadApplet() {
|
||||
bot_image = Images.getResource("/org/parabot/core/ui/images/para.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
setSize(775, 510);
|
||||
setBackground(Color.black);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints on this applet
|
||||
*/
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
g.setFont(new Font("Calibri", Font.PLAIN, 18));
|
||||
if (fontMetrics == null) {
|
||||
fontMetrics = g.getFontMetrics();
|
||||
}
|
||||
g.setColor(Color.white);
|
||||
int x = (getWidth() / 2) - (fontMetrics.stringWidth(state) / 2);
|
||||
g.drawString(state, x, 200);
|
||||
g.setFont(new Font("Calibri", Font.PLAIN, 12));
|
||||
final String version = "v2.0";
|
||||
g.drawString(version,
|
||||
getWidth() - g.getFontMetrics().stringWidth(version) - 10,
|
||||
getHeight() - 12);
|
||||
x = (getWidth() / 2) - (bot_image.getWidth() / 2);
|
||||
g.drawImage(bot_image, x, 80, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets instance of this applet
|
||||
* @return instance of this applet
|
||||
*/
|
||||
public static LoadApplet get() {
|
||||
if (current != null) {
|
||||
return current;
|
||||
}
|
||||
final LoadApplet splash = new LoadApplet();
|
||||
splash.init();
|
||||
current = splash;
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status message and repaints the applet
|
||||
* @param message
|
||||
*/
|
||||
public static void setState(final String message) {
|
||||
state = message;
|
||||
current.repaint();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package org.parabot.core.ui.components;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import org.parabot.core.Context;
|
||||
import org.parabot.core.ui.ServerSelector;
|
||||
import org.parabot.core.ui.images.Images;
|
||||
|
||||
/**
|
||||
* Bot toolbar
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class BotToolbar extends JToolBar {
|
||||
private static final long serialVersionUID = 5373484845104212180L;
|
||||
private static BotToolbar instance = null;
|
||||
private JButton tab = null;
|
||||
private static Map<TabButton, Context> environments = new HashMap<TabButton, Context>();
|
||||
|
||||
public BotToolbar() {
|
||||
setFloatable(false);
|
||||
final JButton run = new JButton();
|
||||
final JButton pause = new JButton();
|
||||
tab = new JButton();
|
||||
tab.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ServerSelector.getInstance().setVisible(true);
|
||||
}
|
||||
|
||||
});
|
||||
run.setFocusable(false);
|
||||
pause.setFocusable(false);
|
||||
tab.setFocusable(false);
|
||||
try {
|
||||
run.setIcon(new ImageIcon(Images.getResource("/org/parabot/core/ui/images/run.png")));
|
||||
pause.setIcon(new ImageIcon(Images.getResource("/org/parabot/core/ui/images/pause.png")));
|
||||
tab.setIcon(new ImageIcon(Images.getResource("/org/parabot/core/ui/images/add.png")));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
//add(tab);
|
||||
add(Box.createHorizontalGlue());
|
||||
add(run);
|
||||
add(pause);
|
||||
}
|
||||
|
||||
public static BotToolbar getInstance() {
|
||||
return instance == null ? instance = new BotToolbar() : instance;
|
||||
}
|
||||
|
||||
public void addTab(final Context context, final String name) {
|
||||
TabButton b = new TabButton(name);
|
||||
b.setActive(true);
|
||||
b.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final TabButton tabButton = (TabButton) e.getSource();
|
||||
final Context context = environments.get(tabButton);
|
||||
for(final TabButton button : environments.keySet()) {
|
||||
button.setActive(false);
|
||||
}
|
||||
tabButton.setActive(true);
|
||||
if(!context.appletSet()) {
|
||||
return;
|
||||
}
|
||||
GamePanel.getInstance().setContext(context);
|
||||
}
|
||||
|
||||
});
|
||||
//add(b, getComponentIndex(tab));
|
||||
add(b, 0);
|
||||
environments.put(b, context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tab button
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
private final class TabButton extends JButton {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public TabButton(final String name) {
|
||||
super(name);
|
||||
setFocusable(false);
|
||||
setHorizontalTextPosition(SwingConstants.LEFT);
|
||||
setIcon(getBlackClose());
|
||||
final Component c = this;
|
||||
addMouseMotionListener(new MouseMotionAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(final MouseEvent e) {
|
||||
if (e.getX() > getWidth() - getIcon().getIconWidth()
|
||||
&& e.getX() < getWidth() - getIconTextGap()) {
|
||||
setIcon(getRedClose());
|
||||
} else {
|
||||
setIcon(getBlackClose());
|
||||
}
|
||||
}
|
||||
});
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
@SuppressWarnings("unused")
|
||||
final int n = getComponentIndex(c);
|
||||
if (e.getX() > getWidth() - getIcon().getIconWidth()
|
||||
&& e.getX() < getWidth() - getIconTextGap()) {
|
||||
// close
|
||||
} else {
|
||||
// enable
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(final MouseEvent e) {
|
||||
setIcon(getBlackClose());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final ImageIcon getBlackClose() {
|
||||
try {
|
||||
return new ImageIcon(Images.getResource("/org/parabot/core/ui/images/close.png"));
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Unable to load icon image: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private final ImageIcon getRedClose() {
|
||||
try {
|
||||
return new ImageIcon(Images.getResource("/org/parabot/core/ui/images/close_red.png"));
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Unable to load icon image: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setActive(final boolean active) {
|
||||
setFont(getFont().deriveFont(active ? Font.BOLD : Font.PLAIN));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.parabot.core.ui.components;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.parabot.core.Context;
|
||||
import org.parabot.core.ui.applet.LoadApplet;
|
||||
|
||||
/**
|
||||
*
|
||||
* Main panel where applets are added.
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GamePanel extends JPanel {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static GamePanel instance = null;
|
||||
private static LoadApplet loader = LoadApplet.get();
|
||||
public Context context = null;
|
||||
|
||||
private GamePanel() {
|
||||
setFocusable(true);
|
||||
setFocusTraversalKeysEnabled(false);
|
||||
setOpaque(true);
|
||||
setBackground(Color.black);
|
||||
setPreferredSize(new Dimension(770, 503));
|
||||
GroupLayout panelLayout = new GroupLayout(this);
|
||||
setLayout(panelLayout);
|
||||
panelLayout.setHorizontalGroup(panelLayout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING).addGap(0, 770, Short.MAX_VALUE));
|
||||
panelLayout.setVerticalGroup(panelLayout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING).addGap(0, 418, Short.MAX_VALUE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates context of this panel and adds a different Applet to the panel
|
||||
* @param context
|
||||
*/
|
||||
public void setContext(final Context c) {
|
||||
if(context != null) {
|
||||
context.getApplet().setVisible(false);
|
||||
}
|
||||
context = c;
|
||||
if(c == null) {
|
||||
return;
|
||||
}
|
||||
final Applet gameApplet = context.getApplet();
|
||||
if(!c.added) {
|
||||
add(gameApplet);
|
||||
c.added = true;
|
||||
return;
|
||||
}
|
||||
gameApplet.setVisible(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets instance of this panel
|
||||
* @return instance of this panel
|
||||
*/
|
||||
public static GamePanel getInstance() {
|
||||
return instance == null ? instance = new GamePanel() : instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the loader applet
|
||||
*/
|
||||
public void addLoader() {
|
||||
add(loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the loader applet
|
||||
*/
|
||||
public void removeLoader() {
|
||||
remove(loader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.parabot.core.ui.components;
|
||||
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
|
||||
import org.parabot.core.logging.LogFormatter;
|
||||
import org.parabot.core.logging.LogTextArea;
|
||||
import org.parabot.core.logging.SystemConsoleHandler;
|
||||
import org.parabot.core.logging.TextAreaLogHandler;
|
||||
|
||||
public class LogArea extends JScrollPane {
|
||||
private static final long serialVersionUID = 6571141103751675714L;
|
||||
private static LogArea instance = null;
|
||||
private static LogTextArea logArea = new LogTextArea();
|
||||
|
||||
private LogArea() {
|
||||
super(TextAreaLogHandler.TEXT_AREA,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
logArea.setPreferredSize(new Dimension(775, 80));
|
||||
setPreferredSize(new Dimension(776, 100));
|
||||
setSize(775, 100);
|
||||
setVisible(true);
|
||||
registerLogging();
|
||||
}
|
||||
|
||||
public static LogArea getInstance() {
|
||||
return instance == null ? instance = new LogArea() : instance;
|
||||
}
|
||||
|
||||
private static final Logger log = Logger.getLogger("Bot");
|
||||
|
||||
public static void log(String s) {
|
||||
log.info(s);
|
||||
}
|
||||
|
||||
public static void error(String s) {
|
||||
log.severe(s);
|
||||
}
|
||||
|
||||
public static void clearLog() {
|
||||
logArea.clearSelection();
|
||||
}
|
||||
|
||||
public static void hideLog() {
|
||||
logArea.setVisible(false);
|
||||
}
|
||||
|
||||
public static void showLog() {
|
||||
logArea.setVisible(true);
|
||||
}
|
||||
|
||||
public void registerLogging() {
|
||||
final Properties logging = new Properties();
|
||||
final String logFormatter = LogFormatter.class.getCanonicalName();
|
||||
final String fileHandler = FileHandler.class.getCanonicalName();
|
||||
logging.setProperty("handlers",
|
||||
TextAreaLogHandler.class.getCanonicalName() + "," + fileHandler);
|
||||
logging.setProperty(".level", "INFO");
|
||||
logging.setProperty(SystemConsoleHandler.class.getCanonicalName()
|
||||
+ ".formatter", logFormatter);
|
||||
logging.setProperty(fileHandler + ".formatter", logFormatter);
|
||||
logging.setProperty(TextAreaLogHandler.class.getCanonicalName()
|
||||
+ ".formatter", logFormatter);
|
||||
final ByteArrayOutputStream logout = new ByteArrayOutputStream();
|
||||
try {
|
||||
logging.store(logout, "");
|
||||
LogManager.getLogManager().readConfiguration(
|
||||
new ByteArrayInputStream(logout.toByteArray()));
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.parabot.core.ui.components;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class ServerPanel extends JPanel {
|
||||
private static final long serialVersionUID = 6034139911394898295L;
|
||||
|
||||
|
||||
public ServerPanel() {
|
||||
setBorder(null);
|
||||
setOpaque(false);
|
||||
setPreferredSize(new Dimension(765, 503));
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
setLayout(layout);
|
||||
layout.setHorizontalGroup(layout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING).addGap(0, 706, Short.MAX_VALUE));
|
||||
layout.setVerticalGroup(layout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING).addGap(0, 418, Short.MAX_VALUE));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
g.setColor(Color.LIGHT_GRAY);
|
||||
g.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.parabot.core.ui.images;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class Images {
|
||||
private static final HashMap<String, BufferedImage> imageCache = new HashMap<String, BufferedImage>();
|
||||
|
||||
public static BufferedImage getResource(final String resource) {
|
||||
if(imageCache.containsKey(resource)) {
|
||||
return imageCache.get(resource);
|
||||
}
|
||||
try {
|
||||
final BufferedImage img = ImageIO.read(Images.class.getResourceAsStream(resource));
|
||||
imageCache.put(resource, img);
|
||||
return img;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Failed to load image from resource. " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 125 B |
|
After Width: | Height: | Size: 155 B |
|
After Width: | Height: | Size: 110 B |
@@ -0,0 +1,30 @@
|
||||
package org.parabot.core.ui.utils;
|
||||
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public final class Center {
|
||||
|
||||
/**
|
||||
* Centers a JFrame
|
||||
* @param frame
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
public static final void centerFramea(final JFrame f, final int width, final int height) {
|
||||
final Dimension fscreen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
final int x = (fscreen.width - width) / 2;
|
||||
final int y = (fscreen.height - height) / 2;
|
||||
f.setBounds(x, y, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package org.parabot.core.ui.widgets;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.GradientPaint;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.parabot.environment.Environment;
|
||||
|
||||
/**
|
||||
* A colorful server widget
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class ServerWidget extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String name = null;
|
||||
|
||||
final ActionListener play = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
load(new URL("http://parnassian.host56.com/" + name
|
||||
+ ".jar"), name);
|
||||
} catch (MalformedURLException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ServerWidget(final String serverName, final String author,
|
||||
final String revision) {
|
||||
setLayout(null);
|
||||
this.name = serverName.replaceAll(" ", "");
|
||||
JLabel l = new JLabel();
|
||||
l.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
l.setForeground(Color.white);
|
||||
l.setText(serverName);
|
||||
l.setBounds(10, 10, 100, 20);
|
||||
add(l);
|
||||
final Font f = new Font("Arial", Font.PLAIN, 12);
|
||||
add(l);
|
||||
l = new JLabel();
|
||||
l.setFont(f);
|
||||
l.setForeground(Color.white);
|
||||
l.setBounds(10, 45, 100, 20);
|
||||
l.setText("Author: " + author);
|
||||
add(l);
|
||||
l = new JLabel();
|
||||
l.setFont(f);
|
||||
l.setForeground(Color.white);
|
||||
l.setBounds(10, 60, 100, 20);
|
||||
l.setText("Revision: " + revision);
|
||||
add(l);
|
||||
final JButton b = new JButton("Start");
|
||||
b.setFocusable(false);
|
||||
b.setBounds(300, 70, 70, 20);
|
||||
b.setOpaque(false);
|
||||
b.addActionListener(play);
|
||||
add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
setOpaque(false);
|
||||
super.paintComponent(g);
|
||||
setOpaque(true);
|
||||
int w = getWidth();
|
||||
int h = getHeight();
|
||||
Color color1 = new Color(160, 0, 0);
|
||||
Color color2 = color1.darker();
|
||||
GradientPaint gp = new GradientPaint(0, 0, color1, 0, h, color2);
|
||||
g2d.setPaint(gp);
|
||||
g2d.fillRect(0, 0, w, h);
|
||||
}
|
||||
|
||||
public void load(final URL url, final String serverName) {
|
||||
Environment.load(url, serverName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.parabot.environment;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URL;
|
||||
|
||||
import org.parabot.core.Context;
|
||||
import org.parabot.core.classpath.ClassPath;
|
||||
import org.parabot.core.ui.BotUI;
|
||||
import org.parabot.core.ui.ServerSelector;
|
||||
import org.parabot.core.ui.components.BotToolbar;
|
||||
import org.parabot.environment.servers.ServerProvider;
|
||||
import org.parabot.environment.servers.loader.ServerLoader;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public class Environment {
|
||||
|
||||
/**
|
||||
* Loads a new environment
|
||||
* @param url
|
||||
*/
|
||||
public static void load(final URL url, final String serverName) {
|
||||
ServerSelector.getInstance().dispose();
|
||||
if(!BotUI.getInstance().isVisible()) {
|
||||
BotUI.getInstance().setVisible(true);
|
||||
}
|
||||
|
||||
final ClassPath classPath = new ClassPath();
|
||||
classPath.addJar(url.toString());
|
||||
|
||||
final ServerLoader serverLoader = new ServerLoader(classPath);
|
||||
final String[] serverProviders = serverLoader.getServerClassNames();
|
||||
if (serverProviders == null) {
|
||||
throw new RuntimeException("No server provided.");
|
||||
}
|
||||
|
||||
final String id = "tab" + Context.getID();
|
||||
final ThreadGroup bot = new ThreadGroup(id);
|
||||
new Thread(bot, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final Class<?> serverProviderClass = serverLoader.loadClass(serverProviders[0]);
|
||||
final Constructor<?> con = serverProviderClass.getConstructor();
|
||||
ServerProvider server = (ServerProvider) con.newInstance();
|
||||
server.context.setEnvironment(serverLoader);
|
||||
BotToolbar.getInstance().addTab(server.context, serverName);
|
||||
server.context.load();
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Error while loading server. " + t.getMessage());
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.parabot.environment.api.utils;
|
||||
|
||||
/**
|
||||
* A simple class to filter things
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
* @param <F>
|
||||
*/
|
||||
public interface Filter<F>
|
||||
{
|
||||
public boolean accept(F f);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.parabot.environment.servers;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* A server manifest
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ServerManifest {
|
||||
|
||||
String author();
|
||||
|
||||
String name();
|
||||
|
||||
double version();
|
||||
|
||||
Type type();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.parabot.environment.servers;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.applet.AppletStub;
|
||||
import java.net.URL;
|
||||
import javax.swing.JMenuBar;
|
||||
|
||||
import org.parabot.core.Context;
|
||||
/**
|
||||
* Provides a server to the bot
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public abstract class ServerProvider {
|
||||
public Context context = new Context(this);
|
||||
|
||||
/**
|
||||
* Hooks to parse
|
||||
* @return URL to hooks file
|
||||
*/
|
||||
public URL getHooks() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jar to parse
|
||||
* @return URL to client jar
|
||||
*/
|
||||
public abstract String getJar();
|
||||
|
||||
public abstract Applet fetchApplet();
|
||||
|
||||
public String getAccessorsPackage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom items to the bot menu bar
|
||||
* @param menu bar to add items on
|
||||
*/
|
||||
public void addMenuItems(JMenuBar bar) {
|
||||
}
|
||||
|
||||
public AppletStub getStub() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void parseJar() {
|
||||
context.getClassPath().addJar(getJar());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.parabot.environment.servers;
|
||||
|
||||
/**
|
||||
*
|
||||
* Bot type
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
INJECTION, REFLECTION, COLOR, OTHER
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.parabot.environment.servers.loader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.parabot.core.asm.ASMClassLoader;
|
||||
import org.parabot.core.classpath.ClassPath;
|
||||
import org.parabot.environment.servers.ServerProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Clisprail
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ServerLoader extends ASMClassLoader {
|
||||
private ClassPath classPath = null;
|
||||
|
||||
public ServerLoader(ClassPath classPath) {
|
||||
super(classPath);
|
||||
this.classPath = classPath;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all classes that extends ServerProvider
|
||||
* @return string array of class names that extends ServerProvider
|
||||
*/
|
||||
public final String[] getServerClassNames() {
|
||||
final List<String> classNames = new ArrayList<String>();
|
||||
for (ClassNode c : classPath.classes.values())
|
||||
if (c.superName.replace('/', '.').equals(
|
||||
ServerProvider.class.getName())) {
|
||||
classNames.add(c.name.replace('/', '.'));
|
||||
}
|
||||
return classNames.toArray(new String[classNames.size()]);
|
||||
}
|
||||
|
||||
}
|
||||