public void mapdata(Message msg) { long now = System.currentTimeMillis(); int pktid = msg.int32(); int off = msg.uint16(); int len = msg.uint16(); Defrag fragbuf; synchronized (fragbufs) { if ((fragbuf = fragbufs.get(pktid)) == null) { fragbuf = new Defrag(len); fragbufs.put(pktid, fragbuf); } fragbuf.add(msg.blob, 8, msg.blob.length - 8, off); fragbuf.last = now; if (fragbuf.done()) { mapdata2(fragbuf.msg()); fragbufs.remove(pktid); } /* Clean up old buffers */ for (Iterator<Map.Entry<Integer, Defrag>> i = fragbufs.entrySet().iterator(); i.hasNext(); ) { Map.Entry<Integer, Defrag> e = i.next(); Defrag old = e.getValue(); if (now - old.last > 10000) i.remove(); } } }
/** * Sets the time in milliseconds of the last activity related to this <tt>Conference</tt> to the * current system time. */ public void touch() { long now = System.currentTimeMillis(); synchronized (this) { if (getLastActivityTime() < now) lastActivityTime = now; } }
/** * Runs in {@link #sendKeepAliveMessageThread} and sends STUN keep-alive <tt>Message</tt>s to the * STUN server associated with the <tt>StunCandidateHarvester</tt> of this instance. * * @return <tt>true</tt> if the method is to be invoked again; otherwise, <tt>false</tt> */ private boolean runInSendKeepAliveMessageThread() { synchronized (sendKeepAliveMessageSyncRoot) { // Since we're going to #wait, make sure we're not canceled yet. if (sendKeepAliveMessageThread != Thread.currentThread()) return false; if (sendKeepAliveMessageInterval == SEND_KEEP_ALIVE_MESSAGE_INTERVAL_NOT_SPECIFIED) { return false; } // Determine the amount of milliseconds that we'll have to #wait. long timeout; if (sendKeepAliveMessageTime == -1) { /* * If we're just starting, don't just go and send a new STUN * keep-alive message but rather wait for the whole interval. */ timeout = sendKeepAliveMessageInterval; } else { timeout = sendKeepAliveMessageTime + sendKeepAliveMessageInterval - System.currentTimeMillis(); } // At long last, #wait if necessary. if (timeout > 0) { try { sendKeepAliveMessageSyncRoot.wait(timeout); } catch (InterruptedException iex) { } /* * Apart from being the time to send the STUN keep-alive * message, it could be that we've experienced a spurious * wake-up or that we've been canceled. */ return true; } } sendKeepAliveMessageTime = System.currentTimeMillis(); try { sendKeepAliveMessage(); } catch (StunException sex) { logger.log(Level.INFO, "Failed to send STUN keep-alive message.", sex); } return true; }
public void ctick() { long now = System.currentTimeMillis(); int dt = (int) (now - lastctick); synchronized (grids) { for (Grid g : grids.values()) { g.tick(dt); } } lastctick = now; }
public void sendreqs() { long now = System.currentTimeMillis(); synchronized (req) { for (Iterator<Map.Entry<Coord, Request>> i = req.entrySet().iterator(); i.hasNext(); ) { Map.Entry<Coord, Request> e = i.next(); Coord c = e.getKey(); Request r = e.getValue(); if (now - r.lastreq > 1000) { r.lastreq = now; if (++r.reqs >= 5) { i.remove(); } else { Message msg = new Message(Session.MSG_MAPREQ); msg.addcoord(c); sess.sendmsg(msg); } } } } }
public class MCache { public static final Coord tilesz = new Coord(11, 11); public static final Coord cmaps = new Coord(100, 100); public static final Coord cutsz = new Coord(25, 25); public static final Coord cutn = cmaps.div(cutsz); private final Resource.Spec[] nsets = new Resource.Spec[256]; @SuppressWarnings("unchecked") private final Reference<Resource>[] sets = new Reference[256]; @SuppressWarnings("unchecked") private final Reference<Tileset>[] csets = new Reference[256]; @SuppressWarnings("unchecked") private final Reference<Tiler>[] tiles = new Reference[256]; Map<Coord, Request> req = new HashMap<Coord, Request>(); Map<Coord, Grid> grids = new HashMap<Coord, Grid>(); Session sess; Set<Overlay> ols = new HashSet<Overlay>(); int olseq = 0; Random gen = new Random(); Map<Integer, Defrag> fragbufs = new TreeMap<Integer, Defrag>(); long lastctick = System.currentTimeMillis(); public static class LoadingMap extends Loading { public LoadingMap() {} public LoadingMap(Throwable cause) { super(cause); } } private static class Request { private long lastreq = 0; private int reqs = 0; } public class Overlay { private Coord c1, c2; private int mask; public Overlay(Coord c1, Coord c2, int mask) { this.c1 = c1; this.c2 = c2; this.mask = mask; ols.add(this); olseq++; } public void destroy() { ols.remove(this); } public void update(Coord c1, Coord c2) { if (!c1.equals(this.c1) || !c2.equals(this.c2)) { olseq++; this.c1 = c1; this.c2 = c2; } } } public class Grid { public final int tiles[] = new int[cmaps.x * cmaps.y]; public final int z[] = new int[cmaps.x * cmaps.y]; public final int ol[] = new int[cmaps.x * cmaps.y]; private final Cut cuts[]; int olseq = -1; private Collection<Gob>[] fo = null; public final Coord gc, ul; public long id; String mnm; private class Cut { MapMesh mesh; Defer.Future<MapMesh> dmesh; Rendered[] ols; int deftag; } private class Flavobj extends Gob { private Flavobj(Coord c, double a) { super(sess.glob, c); this.a = a; } public Random mkrandoom() { Random r = new Random(Grid.this.id); r.setSeed(r.nextInt() ^ rc.x); r.setSeed(r.nextInt() ^ rc.y); return (r); } } public Grid(Coord gc) { this.gc = gc; this.ul = gc.mul(cmaps); cuts = new Cut[cutn.x * cutn.y]; for (int i = 0; i < cuts.length; i++) cuts[i] = new Cut(); } public int gettile(Coord tc) { return (tiles[tc.x + (tc.y * cmaps.x)]); } public int getz(Coord tc) { return (z[tc.x + (tc.y * cmaps.x)]); } public int getol(Coord tc) { return (ol[tc.x + (tc.y * cmaps.x)]); } private void makeflavor() { @SuppressWarnings("unchecked") Collection<Gob>[] fo = (Collection<Gob>[]) new Collection[cutn.x * cutn.y]; for (int i = 0; i < fo.length; i++) fo[i] = new LinkedList<Gob>(); Coord c = new Coord(0, 0); Coord tc = gc.mul(cmaps); int i = 0; Random rnd = new Random(id); for (c.y = 0; c.y < cmaps.x; c.y++) { for (c.x = 0; c.x < cmaps.y; c.x++, i++) { Tileset set = tileset(tiles[i]); if (set.flavobjs.size() > 0) { if (rnd.nextInt(set.flavprob) == 0) { Resource r = set.flavobjs.pick(rnd); double a = rnd.nextDouble() * 2 * Math.PI; Gob g = new Flavobj(c.add(tc).mul(tilesz).add(tilesz.div(2)), a); g.setattr(new ResDrawable(g, r)); Coord cc = c.div(cutsz); fo[cc.x + (cc.y * cutn.x)].add(g); } } } } this.fo = fo; } public Collection<Gob> getfo(Coord cc) { if (fo == null) makeflavor(); return (fo[cc.x + (cc.y * cutn.x)]); } private Cut geticut(Coord cc) { return (cuts[cc.x + (cc.y * cutn.x)]); } public MapMesh getcut(Coord cc) { Cut cut = geticut(cc); if (cut.dmesh != null) { if (cut.dmesh.done() || (cut.mesh == null)) { cut.mesh = cut.dmesh.get(); cut.dmesh = null; } } return (cut.mesh); } public Rendered getolcut(int ol, Coord cc) { int nseq = MCache.this.olseq; if (this.olseq != nseq) { for (int i = 0; i < cutn.x * cutn.y; i++) cuts[i].ols = null; this.olseq = nseq; } Cut cut = geticut(cc); if (cut.ols == null) cut.ols = getcut(cc).makeols(); return (cut.ols[ol]); } private void buildcut(final Coord cc) { final Cut cut = geticut(cc); final int deftag = ++cut.deftag; cut.dmesh = Defer.later( new Defer.Callable<MapMesh>() { public MapMesh call() { Random rnd = new Random(id); rnd.setSeed(rnd.nextInt() ^ cc.x); rnd.setSeed(rnd.nextInt() ^ cc.y); return (MapMesh.build(MCache.this, rnd, ul.add(cc.mul(cutsz)), cutsz)); } }); } public void ivneigh(Coord nc) { Coord cc = new Coord(); for (cc.y = 0; cc.y < cutn.y; cc.y++) { for (cc.x = 0; cc.x < cutn.x; cc.x++) { if ((((nc.x < 0) && (cc.x == 0)) || ((nc.x > 0) && (cc.x == cutn.x - 1)) || (nc.x == 0)) && (((nc.y < 0) && (cc.y == 0)) || ((nc.y > 0) && (cc.y == cutn.y - 1)) || (nc.y == 0))) { buildcut(new Coord(cc)); } } } } public void tick(int dt) { if (fo != null) { for (Collection<Gob> fol : fo) { for (Gob fo : fol) fo.ctick(dt); } } } private void invalidate() { for (int y = 0; y < cutn.y; y++) { for (int x = 0; x < cutn.x; x++) buildcut(new Coord(x, y)); } fo = null; for (Coord ic : new Coord[] { new Coord(-1, -1), new Coord(0, -1), new Coord(1, -1), new Coord(-1, 0), new Coord(1, 0), new Coord(-1, 1), new Coord(0, 1), new Coord(1, 1) }) { Grid ng = grids.get(gc.add(ic)); if (ng != null) ng.ivneigh(ic.inv()); } loaded = true; } public void fill(Message msg) { String mmname = msg.string().intern(); if (mmname.equals("")) mnm = null; else mnm = mmname; int[] pfl = new int[256]; while (true) { int pidx = msg.uint8(); if (pidx == 255) break; pfl[pidx] = msg.uint8(); } Message blob = msg.inflate(); id = blob.int64(); for (int i = 0; i < tiles.length; i++) tiles[i] = blob.uint8(); for (int i = 0; i < z.length; i++) z[i] = blob.int16(); for (int i = 0; i < ol.length; i++) ol[i] = 0; while (true) { int pidx = blob.uint8(); if (pidx == 255) break; int fl = pfl[pidx]; int type = blob.uint8(); Coord c1 = new Coord(blob.uint8(), blob.uint8()); Coord c2 = new Coord(blob.uint8(), blob.uint8()); int ol; if (type == 0) { if ((fl & 1) == 1) ol = 2; else ol = 1; } else if (type == 1) { if ((fl & 1) == 1) ol = 8; else ol = 4; } else { throw (new RuntimeException("Unknown plot type " + type)); } for (int y = c1.y; y <= c2.y; y++) { for (int x = c1.x; x <= c2.x; x++) { this.ol[x + (y * cmaps.x)] |= ol; } } } invalidate(); } /* ===== BD Code Start ===== */ private BufferedImage gridImage; private boolean loaded = false; private boolean rendered = false; private int getz(int x, int y) { return (z[x + (y * cmaps.x)]); } public BufferedImage getGridImage() { if (rendered) return gridImage; if (!loaded) throw new Loading(); gridImage = TexI.mkbuf(cmaps); BufferedImage[] texes = new BufferedImage[256]; Coord c = new Coord(); for (c.y = 0; c.y < cmaps.y; c.y++) { for (c.x = 0; c.x < cmaps.x; c.x++) { int t = gettile(c); BufferedImage tex = tileimg(t, texes); if (tex != null) gridImage.setRGB( c.x, c.y, tex.getRGB( Utils.floormod(c.x, tex.getWidth()), Utils.floormod(c.y, tex.getHeight()))); } } for (c.y = 1; c.y < cmaps.y - 1; c.y++) { for (c.x = 1; c.x < cmaps.x - 1; c.x++) { int t = gettile(c); if ((gettile(c.add(-1, 0)) > t) || (gettile(c.add(1, 0)) > t) || (gettile(c.add(0, -1)) > t) || (gettile(c.add(0, 1)) > t)) gridImage.setRGB(c.x, c.y, Color.BLACK.getRGB()); } } rendered = true; return gridImage; } /* ===== BD Code End ===== */ } public MCache(Session sess) { this.sess = sess; } public void ctick() { long now = System.currentTimeMillis(); int dt = (int) (now - lastctick); synchronized (grids) { for (Grid g : grids.values()) { g.tick(dt); } } lastctick = now; } public void invalidate(Coord cc) { synchronized (req) { if (req.get(cc) == null) req.put(cc, new Request()); } } public void invalblob(Message msg) { int type = msg.uint8(); if (type == 0) { invalidate(msg.coord()); } else if (type == 1) { Coord ul = msg.coord(); Coord lr = msg.coord(); trim(ul, lr); } else if (type == 2) { trimall(); } } private Grid cached = null; public Grid getgrid(Coord gc) { synchronized (grids) { if ((cached == null) || !cached.gc.equals(cached)) { cached = grids.get(gc); if (cached == null) { request(gc); throw (new LoadingMap()); } } return (cached); } } public Grid getgridt(Coord tc) { return (getgrid(tc.div(cmaps))); } public int gettile(Coord tc) { Grid g = getgridt(tc); return (g.gettile(tc.sub(g.ul))); } public int getz(Coord tc) { Grid g = getgridt(tc); return (g.getz(tc.sub(g.ul))); } public float getcz(float px, float py) { float tw = tilesz.x, th = tilesz.y; Coord ul = new Coord(Utils.floordiv(px, tw), Utils.floordiv(py, th)); float sx = Utils.floormod(px, tw) / tw; float sy = Utils.floormod(py, th) / th; return (((1.0f - sy) * (((1.0f - sx) * getz(ul)) + (sx * getz(ul.add(1, 0))))) + (sy * (((1.0f - sx) * getz(ul.add(0, 1))) + (sx * getz(ul.add(1, 1)))))); } public float getcz(Coord pc) { return (getcz(pc.x, pc.y)); } public int getol(Coord tc) { Grid g = getgridt(tc); int ol = g.getol(tc.sub(g.ul)); for (Overlay lol : ols) { if (tc.isect(lol.c1, lol.c2.add(lol.c1.inv()).add(new Coord(1, 1)))) ol |= lol.mask; } return (ol); } public MapMesh getcut(Coord cc) { return (getgrid(cc.div(cutn)).getcut(cc.mod(cutn))); } public Collection<Gob> getfo(Coord cc) { return (getgrid(cc.div(cutn)).getfo(cc.mod(cutn))); } public Rendered getolcut(int ol, Coord cc) { return (getgrid(cc.div(cutn)).getolcut(ol, cc.mod(cutn))); } public void mapdata2(Message msg) { Coord c = msg.coord(); synchronized (grids) { synchronized (req) { if (req.containsKey(c)) { Grid g = grids.get(c); if (g == null) grids.put(c, g = new Grid(c)); g.fill(msg); req.remove(c); olseq++; } } } } public void mapdata(Message msg) { long now = System.currentTimeMillis(); int pktid = msg.int32(); int off = msg.uint16(); int len = msg.uint16(); Defrag fragbuf; synchronized (fragbufs) { if ((fragbuf = fragbufs.get(pktid)) == null) { fragbuf = new Defrag(len); fragbufs.put(pktid, fragbuf); } fragbuf.add(msg.blob, 8, msg.blob.length - 8, off); fragbuf.last = now; if (fragbuf.done()) { mapdata2(fragbuf.msg()); fragbufs.remove(pktid); } /* Clean up old buffers */ for (Iterator<Map.Entry<Integer, Defrag>> i = fragbufs.entrySet().iterator(); i.hasNext(); ) { Map.Entry<Integer, Defrag> e = i.next(); Defrag old = e.getValue(); if (now - old.last > 10000) i.remove(); } } } public Resource tilesetr(int i) { synchronized (sets) { Resource res = (sets[i] == null) ? null : (sets[i].get()); if (res == null) { if (nsets[i] == null) return (null); res = nsets[i].get(); sets[i] = new SoftReference<Resource>(res); } return (res); } } public Tileset tileset(int i) { synchronized (csets) { Tileset cset = (csets[i] == null) ? null : (csets[i].get()); if (cset == null) { Resource res = tilesetr(i); if (res == null) return (null); try { cset = res.layer(Resource.tileset); } catch (Loading e) { throw (new LoadingMap(e)); } csets[i] = new SoftReference<Tileset>(cset); } return (cset); } } public Tiler tiler(int i) { synchronized (tiles) { Tiler tile = (tiles[i] == null) ? null : (tiles[i].get()); if (tile == null) { Tileset set = tileset(i); if (set == null) return (null); tile = set.tfac().create(i, set); tiles[i] = new SoftReference<Tiler>(tile); } return (tile); } } public void tilemap(Message msg) { while (!msg.eom()) { int id = msg.uint8(); String resnm = msg.string(); int resver = msg.uint16(); nsets[id] = new Resource.Spec(resnm, resver); } } public void trimall() { synchronized (grids) { synchronized (req) { grids.clear(); req.clear(); } } } public void trim(Coord ul, Coord lr) { synchronized (grids) { synchronized (req) { for (Iterator<Map.Entry<Coord, Grid>> i = grids.entrySet().iterator(); i.hasNext(); ) { Map.Entry<Coord, Grid> e = i.next(); Coord gc = e.getKey(); Grid g = e.getValue(); if ((gc.x < ul.x) || (gc.y < ul.y) || (gc.x > lr.x) || (gc.y > lr.y)) i.remove(); } for (Iterator<Coord> i = req.keySet().iterator(); i.hasNext(); ) { Coord gc = i.next(); if ((gc.x < ul.x) || (gc.y < ul.y) || (gc.x > lr.x) || (gc.y > lr.y)) i.remove(); } } } } public void request(Coord gc) { synchronized (req) { if (!req.containsKey(gc)) req.put(gc, new Request()); } } public void reqarea(Coord ul, Coord br) { ul = ul.div(cutsz); br = br.div(cutsz); Coord rc = new Coord(); for (rc.y = ul.y; rc.y <= br.y; rc.y++) { for (rc.x = ul.x; rc.x <= br.x; rc.x++) { try { getcut(new Coord(rc)); } catch (Loading e) { } } } } public void sendreqs() { long now = System.currentTimeMillis(); synchronized (req) { for (Iterator<Map.Entry<Coord, Request>> i = req.entrySet().iterator(); i.hasNext(); ) { Map.Entry<Coord, Request> e = i.next(); Coord c = e.getKey(); Request r = e.getValue(); if (now - r.lastreq > 1000) { r.lastreq = now; if (++r.reqs >= 5) { i.remove(); } else { Message msg = new Message(Session.MSG_MAPREQ); msg.addcoord(c); sess.sendmsg(msg); } } } } } /* ===== BD Code Start ===== */ private BufferedImage tileimg(int t, BufferedImage[] texes) { BufferedImage img = texes[t]; if (img == null) { Resource r = tilesetr(t); if (r == null) return (null); Resource.Image ir = r.layer(Resource.imgc); if (ir == null) return (null); img = ir.img; texes[t] = img; } return (img); } /* ===== BD Code End ===== */ }