Skip to content

Instantly share code, notes, and snippets.

@dgladkov
Created February 25, 2010 18:54
Show Gist options
  • Save dgladkov/314898 to your computer and use it in GitHub Desktop.
Save dgladkov/314898 to your computer and use it in GitHub Desktop.
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 = in = new MiniMap.MapFragmentInputStream(getreal(grid), Config.mapdir + "/" + grid + ".png");
}
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.mc.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;
}
MapFragmentCoordsWriter.getInstance().writeMapFragmentCoords(grid.mnm, cg);
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 = m.getc();
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);
}
private static final class MapFragmentInputStream extends InputStream
{
private InputStream input;
private FileOutputStream output;
public MapFragmentInputStream(InputStream mapInputStream, String fileName)
{
try
{
this.output = new FileOutputStream(fileName);
} catch (FileNotFoundException e) {
}
this.input = mapInputStream;
}
public int read() throws IOException {
int b = this.input.read();
if (b != -1) {
this.output.write(b);
this.output.flush();
}
return b;
}
}
public static final class MapFragmentCoordsWriter
{
private static MapFragmentCoordsWriter _instance = new MapFragmentCoordsWriter();
Hashtable coordsHash;
File coordsFile;
public MapFragmentCoordsWriter()
{
this.coordsHash = new Hashtable();
this.coordsFile = new File(Config.mapdir + "/fragdata" + System.currentTimeMillis() + ".txt"); }
public static MapFragmentCoordsWriter getInstance() {
return _instance;
}
public synchronized void writeMapFragmentCoords(String fragmentID, Coord coords) {
if (!(this.coordsHash.containsKey(fragmentID))) {
this.coordsHash.put(fragmentID, coords);
try {
FileWriter out = new FileWriter(this.coordsFile, true);
out.write(fragmentID + ";" + coords.x + "," + coords.y + "\n");
out.flush();
} catch (IOException e) {
}
}
}
public synchronized void beginNewSession() {
this.coordsFile = new File(Config.mapdir + "/fragdata" + System.currentTimeMillis() + ".txt");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment