/*
* 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 static haven.MCache.cmaps;
import static haven.MCache.tilesz;
import java.security.*;
import java.util.*;
import java.net.*;
import java.io.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class MiniMap extends Widget {
static Map<String, Tex> grids = new WeakHashMap<String, Tex>();
static Set<String> loading = new HashSet<String>();
static Loader loader = new Loader();
public static final Tex bg = Resource.loadtex("gfx/hud/mmap/ptex");
public static final Tex nomap = Resource.loadtex("gfx/hud/mmap/nomap");
public static final Resource plx = Resource.load("gfx/hud/mmap/x");
MapView mv;
static class Loader implements Runnable {
Thread me = null;
private InputStream getreal(String nm) throws IOException {
URL url = new URL(Config.mapurl, nm + ".png");
URLConnection c = url.openConnection();
c.addRequestProperty("User-Agent", "Haven/1.0");
InputStream s = c.getInputStream();
/*
* I've commented this out, since it seems that the JNLP
* PersistenceService (or at least Sun's implementation of
* it) is SLOWER THAN SNAILS, so this caused more problems
* than it solved.
*
if(ResCache.global != null) {
StreamTee tee = new StreamTee(s);
tee.setncwe();
tee.attach(ResCache.global.store("mm/" + nm));
s = tee;
}
*/
return(s);
}
private InputStream getcached(String nm) throws IOException {
if(ResCache.global == null)
throw(new FileNotFoundException("No resource cache installed"));
return(ResCache.global.fetch("mm/" + nm));
}
public void run() {
try {
while(true) {
String grid;
synchronized(grids) {
grid = null;
for(String cg : loading) {
grid = cg;
break;
}
}
if(grid == null)
break;
try {
InputStream in;
try {
in = getcached(grid);
} catch(FileNotFoundException e) {
in = getreal(grid);
}
BufferedImage img;
try {
img = ImageIO.read(in);
} finally {
Utils.readtileof(in);
in.close();
}
Tex tex = new TexI(img);
synchronized(grids) {
grids.put(grid, tex);
loading.remove(grid);
}
} catch(IOException e) {
synchronized(grids) {
grids.put(grid, null);
loading.remove(grid);
}
}
}
} finally {
synchronized(this) {
me = null;
}
}
}
void start() {
synchronized(this) {
if(me == null) {
me = new HackThread(this, "Minimap loader");
me.setDaemon(true);
me.start();
}
}
}
void req(String nm) {
synchronized(grids) {
if(loading.contains(nm))
return;
loading.add(nm);
start();
}
}
}
public MiniMap(Coord c, Coord sz, Widget parent, MapView mv) {
super(c, sz, parent);
this.mv = mv;
}
public static Tex getgrid(final String nm) {
return(AccessController.doPrivileged(new PrivilegedAction<Tex>() {
public Tex run() {
synchronized(grids) {
if(grids.containsKey(nm)) {
return(grids.get(nm));
} else {
loader.req(nm);
return(null);
}
}
}
}));
}
public void draw(GOut g) {
Coord tc = mv.cc.div(tilesz);
Coord ulg = tc.div(cmaps);
while((ulg.x * cmaps.x) - tc.x + (sz.x / 2) > 0)
ulg.x--;
while((ulg.y * cmaps.y) - tc.y + (sz.y / 2) > 0)
ulg.y--;
boolean missing = false;
g.image(bg, Coord.z);
outer:
for(int y = ulg.y; (y * cmaps.y) - tc.y + (sz.y / 2) < sz.y; y++) {
for(int x = ulg.x; (x * cmaps.x) - tc.x + (sz.x / 2) < sz.x; x++) {
Coord cg = new Coord(x, y);
MCache.Grid grid;
synchronized(ui.sess.glob.map.req) {
synchronized(ui.sess.glob.map.grids) {
grid = ui.sess.glob.map.grids.get(cg);
if(grid == null)
ui.sess.glob.map.request(cg);
}
}
if(grid == null)
continue;
if(grid.mnm == null) {
missing = true;
break outer;
}
Tex tex = getgrid(grid.mnm);
if(tex == null)
continue;
g.image(tex, cg.mul(cmaps).add(tc.inv()).add(sz.div(2)));
}
}
if(missing) {
g.image(nomap, Coord.z);
} else {
if(!plx.loading) {
synchronized(ui.sess.glob.party.memb) {
for(Party.Member m : ui.sess.glob.party.memb.values()) {
Coord ptc;
try {
ptc = m.getc();
} catch(MCache.LoadingMap e) {
ptc = null;
}
if(ptc == null)
continue;
ptc = ptc.div(tilesz).add(tc.inv()).add(sz.div(2));
g.chcolor(m.col.getRed(), m.col.getGreen(), m.col.getBlue(), 128);
g.image(plx.layer(Resource.imgc).tex(), ptc.add(plx.layer(Resource.negc).cc.inv()));
g.chcolor();
}
}
}
}
super.draw(g);
}
}