package haven;
import java.awt.Component;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class MaidFrame extends MainFrame implements KeyListener {
private static List<SessionData> sessions = new ArrayList<SessionData>();
private static int index;
public MaidFrame(int w, int h) {
super(w, h);
Console.setscmd("bot", new Console.Command() {
public void run(Console cons, String[] args) {
String[] maidArgs = null;
if (args.length > 2)
maidArgs = Arrays.copyOfRange(args, 2, args.length);
MaidUI.instance.maid.doTask(args[1], maidArgs);
}
});
}
public synchronized static SessionData getCurrentSession() {
return (index < sessions.size()) ? sessions.get(index) : null;
}
private void addSession() {
sessions.get(0).sb.visible = true;
Thread t = new HackThread(new Runnable() {
public void run() {
try {
sessionRunner();
} catch (InterruptedException e) {
}
}
}, "Haven alternate thread");
t.start();
}
private synchronized static void addSession(SessionData ses) {
sessions.add(ses);
index = sessions.size() - 1;
}
private synchronized static void replaceSession(SessionData ses, SessionData newSes) {
int i = sessions.indexOf(ses);
if (i >= 0)
sessions.set(i, newSes);
else
sessions.add(newSes);
}
private synchronized static void nextSession() {
index = (index + 1) % sessions.size();
((MaidFrame) MainFrame.instance).switchSession();
}
private synchronized static void previousSession() {
index = index == 0 ? sessions.size() - 1 : index - 1;
((MaidFrame) MainFrame.instance).switchSession();
}
private synchronized static void firstSession() {
index = 0;
((MaidFrame) MainFrame.instance).switchSession();
}
private synchronized static void lastSession() {
index = sessions.size() - 1;
((MaidFrame) MainFrame.instance).switchSession();
}
private void switchSession() {
UI newUi = sessions.get(index).getUI();
UI.instance = newUi;
p.ui = newUi;
if (p.ui.sess != null) {
MainFrame.instance.setTitle(p.ui.sess.charname);
UI.instance.sess.glob.oc.lastctick = 0;
} else {
MainFrame.instance.setTitle(null);
}
}
public synchronized static void switchToSession(int index) {
if (index != MaidFrame.index) {
MaidFrame.index = index;
((MaidFrame) MainFrame.instance).switchSession();
}
}
// This is not synchronized!!! Extra care should be taken when using!
public static List<SessionData> getSessionList() {
return sessions;
}
public static int getSessionCount() {
return sessions.size();
}
public synchronized static void removeSession(UI ui) {
int i;
for (i = 0; i < sessions.size(); i++) {
if (sessions.get(i).getUI() == ui)
break;
}
if (i < sessions.size())
sessions.remove(i);
}
@Override
public Component add(Component comp) {
if (comp instanceof HavenPanel) {
comp.addKeyListener(this);
}
return super.add(comp);
}
@Override
public void remove(Component comp) {
if (comp instanceof HavenPanel) {
comp.removeKeyListener(this);
}
super.remove(comp);
}
public void keyPressed(KeyEvent e) {
if (e.isShiftDown()) {
e.consume();
}
}
public void keyReleased(KeyEvent e) {
if (e.isShiftDown()) {
int i;
switch (e.getKeyCode()) {
case KeyEvent.VK_F1:
i = 0;
break;
case KeyEvent.VK_F2:
i = 1;
break;
case KeyEvent.VK_F3:
i = 2;
break;
case KeyEvent.VK_F4:
i = 3;
break;
case KeyEvent.VK_F5:
i = 4;
break;
case KeyEvent.VK_F6:
i = 5;
break;
case KeyEvent.VK_F7:
i = 6;
break;
case KeyEvent.VK_F8:
i = 7;
break;
case KeyEvent.VK_F9:
i = 8;
break;
case KeyEvent.VK_F10:
i = 9;
break;
case KeyEvent.VK_F11:
i = 10;
break;
case KeyEvent.VK_F12:
i = 11;
break;
case KeyEvent.VK_ESCAPE:
i = -2;
break;
default:
return;
}
e.consume();
if (i >= 0) {
MaidUI.instance.maid.doTask(i);
} else if (i == -2) {
MaidUI.instance.maid.stopTask();
}
} else if (e.isAltDown()) {
switch (e.getKeyCode()) {
case KeyEvent.VK_INSERT:
addSession();
break;
case KeyEvent.VK_PAGE_UP:
nextSession();
break;
case KeyEvent.VK_PAGE_DOWN:
previousSession();
break;
case KeyEvent.VK_A:
Config.autoaggro = !Config.autoaggro;
Config.aggrored = true;
Config.aggrounknown = true;
Config.saveOptions();
String str = "Auto-aggro: " + (Config.autoaggro ? "ON" : "OFF");
UI curSessUI = getCurrentSession().getUI();
curSessUI.cons.out.println(str);
curSessUI.slen.error(str);
break;
default:
return;
}
e.consume();
} else if (e.isControlDown()) {
switch (e.getKeyCode()) {
case KeyEvent.VK_S:
addSession();
break;
default:
return;
}
e.consume();
}
}
public void keyTyped(KeyEvent e) {
if (e.isShiftDown()) {
e.consume();
}
}
private void sessionRunner() throws InterruptedException {
SessionData ns = null;
while (true) {
UI loginUi = p.newui(null);
p.ui = loginUi;
// add login UI so we can switch to it
// once the session has been established we will need to replace it
// with proper UI
SessionData loginThreadUi = new SessionData(Thread.currentThread(), loginUi);
// if session was closed remotely
// we need to replace the old sessiondata object
if (ns != null)
replaceSession(ns, loginThreadUi);
else
addSession(loginThreadUi);
Widget pwdg = loginUi.widgets.get(0);
Coord sbc = SessionBar.initPos;
// if there is already another sessionbar use its coord
if (MaidFrame.getSessionCount() > 1) {
try {
sbc = MaidFrame.getSessionList().get(0).sb.c;
} catch (Exception e) {
}
}
MaidFrame.getCurrentSession().sb = new SessionBar(sbc, pwdg);
if (MaidFrame.getSessionCount() == 1)
MaidFrame.getCurrentSession().sb.visible = false;
Bootstrap bill = new Bootstrap();
if (Config.defserv != null) {
bill.setaddr(Config.defserv);
}
if ((Config.authuser != null) && (Config.authck != null)) {
bill.setinitcookie(Config.authuser, Config.authck);
Config.authck = null;
}
Session sess = bill.run(p, loginUi);
RemoteUI rui = new RemoteUI(sess);
UI n = p.newui(sess);
sess.ui = n;
ns = new SessionData(Thread.currentThread(), n);
replaceSession(loginThreadUi, ns);
rui.run(n);
}
}
// @Override
public void run() {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
g.interrupt();
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent evt) {
innerSize.setSize(getWidth() - insetsSize.width, getHeight() - insetsSize.height);
centerPoint.setLocation(innerSize.width / 2, innerSize.height / 2);
}
});
Thread ui = new HackThread(p, "Haven UI thread");
p.setfsm(this);
ui.start();
try {
sessionRunner();
} catch (InterruptedException e) {
} finally {
ui.interrupt();
dispose();
}
}
public static void main(final String[] args) {
/*
* Set up the error handler as early as humanly possible.
*/
ThreadGroup g = new ThreadGroup("Haven client");
String ed;
if (!(ed = Utils.getprop("haven.errorurl", "")).equals("")) {
try {
final haven.error.ErrorHandler hg = new haven.error.ErrorHandler(new java.net.URL(ed));
hg.sethandler(new haven.error.ErrorGui(null) {
public void errorsent() {
hg.interrupt();
}
});
g = hg;
} catch (java.net.MalformedURLException e) {
}
}
Thread main = new HackThread(g, new Runnable() {
public void run() {
try {
javabughack();
} catch (InterruptedException e) {
return;
}
main2(args);
}
}, "Haven main thread");
main.start();
try {
main.join();
} catch (InterruptedException e) {
g.interrupt();
return;
}
System.exit(0);
}
private static void javabughack() throws InterruptedException {
/*
* Work around a stupid deadlock bug in AWT.
*/
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
PrintStream bitbucket = new PrintStream(new ByteArrayOutputStream());
bitbucket.print(LoginScreen.textf);
bitbucket.print(LoginScreen.textfs);
}
});
} catch (java.lang.reflect.InvocationTargetException e) {
/*
* Oh, how I love Swing!
*/
throw (new Error(e));
}
/*
* Work around another deadl bug in Sun's JNLP client.
*/
javax.imageio.spi.IIORegistry.getDefaultInstance();
}
private static void main2(String[] args) {
Config.cmdline(args);
ThreadGroup g = HackThread.tg();
setupres();
MaidFrame f = new MaidFrame(800, 600);
if (Config.fullscreen) {
f.setfs();
}
f.g = g;
if (g instanceof haven.error.ErrorHandler) {
final haven.error.ErrorHandler hg = (haven.error.ErrorHandler) g;
hg.sethandler(new haven.error.ErrorGui(null) {
public void errorsent() {
hg.interrupt();
}
});
}
f.run();
dumplist(Resource.loadwaited, Config.loadwaited);
dumplist(Resource.cached(), Config.allused);
if (ResCache.global != null) {
try {
Collection<Resource> used = new LinkedList<Resource>();
for (Resource res : Resource.cached()) {
if (res.prio >= 0) {
used.add(res);
}
}
Writer w = new OutputStreamWriter(ResCache.global.store("tmp/allused"), "UTF-8");
try {
Resource.dumplist(used, w);
} finally {
w.close();
}
} catch (IOException e) {
}
}
}
private static void dumplist(Collection<Resource> list, String fn) {
try {
if (fn != null) {
Writer w = new OutputStreamWriter(new FileOutputStream(fn), "UTF-8");
try {
Resource.dumplist(list, w);
} finally {
w.close();
}
}
} catch (IOException e) {
throw (new RuntimeException(e));
}
}
}