First commit

This commit is contained in:
Clisprail
2013-04-03 20:21:15 +02:00
commit c230a353b1
44 changed files with 2104 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
bin
.classpath
.project
.settings
.metadata
Binary file not shown.
+24
View File
@@ -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);
}
}
+121
View File
@@ -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;
}
}
+27
View File
@@ -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());
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

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()]);
}
}