/*
* This file is part of the Haven & Hearth game client.
* Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and
* Björn Johannessen <johannessen.bjorn@gmail.com>
*
* Redistribution and/or modification of this file is subject to the
* terms of the GNU Lesser General Public License, version 3, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Other parts of this source tree adhere to other copying
* rights. Please see the file `COPYING' in the root directory of the
* source tree for details.
*
* A copy the GNU Lesser General Public License is distributed along
* with the source tree of which this file is a part in the file
* `doc/LPGL-3'. If it is missing for any reason, please see the Free
* Software Foundation's website at <http://www.fsf.org/>, or write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
package haven;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Frame;
import java.awt.GraphicsDevice;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
import java.util.Collection;
import java.util.LinkedList;
@SuppressWarnings("serial")
public class MainFrame extends Frame implements Runnable, FSMan {
public static String VERSION = "20.01.14";
private static final String TITLE = String.format("Haven and Hearth (modified by Ender v%s)", VERSION);
HavenPanel p;
ThreadGroup g;
DisplayMode fsmode = null, prefs = null;
Dimension insetsSize;
public static Dimension innerSize;
public static Point centerPoint;
public static Coord screenSZ;
public static MainFrame instance;
static {
try {
javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {}
}
DisplayMode findmode(int w, int h) {
GraphicsDevice dev = getGraphicsConfiguration().getDevice();
if(!dev.isFullScreenSupported())
return(null);
DisplayMode b = null;
for(DisplayMode m : dev.getDisplayModes()) {
int d = m.getBitDepth();
if((m.getWidth() == w) && (m.getHeight() == h) && ((d == 24) || (d == 32) || (d == DisplayMode.BIT_DEPTH_MULTI))) {
if((b == null) || (d > b.getBitDepth()) || ((d == b.getBitDepth()) && (m.getRefreshRate() > b.getRefreshRate())))
b = m;
}
}
return(b);
}
public void setfs() {
GraphicsDevice dev = getGraphicsConfiguration().getDevice();
if(prefs != null)
return;
prefs = dev.getDisplayMode();
try {
setVisible(false);
dispose();
setUndecorated(true);
setVisible(true);
dev.setFullScreenWindow(this);
dev.setDisplayMode(fsmode);
} catch(Exception e) {
throw(new RuntimeException(e));
}
}
public void setwnd() {
GraphicsDevice dev = getGraphicsConfiguration().getDevice();
if(prefs == null)
return;
try {
dev.setDisplayMode(prefs);
dev.setFullScreenWindow(null);
setVisible(false);
dispose();
setUndecorated(false);
setVisible(true);
} catch(Exception e) {
throw(new RuntimeException(e));
}
prefs = null;
}
public boolean hasfs() {
return(prefs != null);
}
public void togglefs() {
if(prefs == null)
setfs();
else
setwnd();
}
private void seticon() {
Image icon;
try {
InputStream data = MainFrame.class.getResourceAsStream("icon.png");
icon = javax.imageio.ImageIO.read(data);
data.close();
} catch(IOException e) {
throw(new Error(e));
}
setIconImage(icon);
}
@Override
public void setTitle(String charname) {
String str = TITLE;
if(charname != null){
str = charname+" - "+str;
}
super.setTitle(str);
}
public MainFrame(int w, int h) {
super("");
setTitle(null);
instance = this;
innerSize = new Dimension(w, h);
centerPoint = new Point(innerSize.width / 2, innerSize.height / 2);
screenSZ = new Coord(Toolkit.getDefaultToolkit().getScreenSize());
p = new HavenPanel(w, h);
fsmode = findmode(w, h);
add(p);
pack();
Insets insets = getInsets();
insetsSize = new Dimension(insets.left + insets.right, insets.top + insets.bottom);
setResizable(true);
setMinimumSize(new Dimension(800 + insetsSize.width, 600 + insetsSize.height));
p.requestFocusInWindow();
seticon();
setVisible(true);
p.init();
setExtendedState(getExtendedState() | MAXIMIZED_BOTH);
}
public static Coord getScreenSize() {
return screenSZ;
}
public static Coord getInnerSize() {
return new Coord(innerSize.width, innerSize.height);
}
public static Coord getCenterPoint() {
return new Coord(centerPoint.x, centerPoint.y);
}
public void run() {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
g.interrupt();
}
});
addComponentListener(new ComponentAdapter() {
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 {
while(true) {
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);
RemoteUI rui = new RemoteUI(sess);
rui.run(p.newui(sess));
}
} catch(InterruptedException e) {
} finally {
ui.interrupt();
dispose();
}
}
public static void setupres() {
if(ResCache.global != null)
Resource.addcache(ResCache.global);
if(Config.resurl != null)
Resource.addurl(Config.resurl);
if(ResCache.global != null) {
try {
Resource.loadlist(ResCache.global.fetch("tmp/allused"), -10);
} catch(IOException e) {}
}
if(!Config.nopreload) {
try {
InputStream pls;
pls = Resource.class.getResourceAsStream("res-preload");
if(pls != null)
Resource.loadlist(pls, -5);
pls = Resource.class.getResourceAsStream("res-bgload");
if(pls != null)
Resource.loadlist(pls, -10);
} catch(IOException e) {
throw(new Error(e));
}
}
}
static {
WebBrowser.self = JnlpBrowser.create();
}
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();
MainFrame f = new MainFrame(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) {}
}
}
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 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));
}
}
}