use of org.dynmap.storage.MapStorageTile in project dynmap by webbukkit.
the class MapStorageResourceHandler method handle.
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String path = baseRequest.getPathInfo();
int soff = 0, eoff;
// We're handling this request
baseRequest.setHandled(true);
if (core.getLoginRequired() && request.getSession(true).getAttribute(LoginServlet.USERID_ATTRIB) == null) {
response.sendError(HttpStatus.UNAUTHORIZED_401);
return;
}
if (path.charAt(0) == '/')
soff = 1;
eoff = path.indexOf('/', soff);
if (soff < 0) {
response.sendError(HttpStatus.NOT_FOUND_404);
return;
}
String world = path.substring(soff, eoff);
String uri = path.substring(eoff + 1);
// If faces directory, handle faces
if (world.equals("faces")) {
handleFace(response, uri);
return;
}
// If markers directory, handle markers
if (world.equals("_markers_")) {
handleMarkers(response, uri);
return;
}
DynmapWorld w = null;
if (core.mapManager != null) {
w = core.mapManager.getWorld(world);
}
// If world not found quit
if (w == null) {
response.setContentType("image/png");
OutputStream os = response.getOutputStream();
os.write(blankpng);
return;
}
// Get storage handler
MapStorage store = w.getMapStorage();
// Get tile reference, based on URI and world
MapStorageTile tile = store.getTile(w, uri);
if (tile == null) {
response.setContentType("image/png");
OutputStream os = response.getOutputStream();
os.write(blankpng);
return;
}
// Read tile
TileRead tr = null;
if (tile.getReadLock(5000)) {
tr = tile.read();
tile.releaseReadLock();
}
response.setHeader("Cache-Control", "max-age=0,must-revalidate");
String etag;
if (tr == null) {
etag = "\"" + blankpnghash + "\"";
} else {
etag = "\"" + tr.hashCode + "\"";
}
response.setHeader("ETag", etag);
String ifnullmatch = request.getHeader("If-None-Match");
if ((ifnullmatch != null) && ifnullmatch.equals(etag)) {
response.sendError(HttpStatus.NOT_MODIFIED_304);
return;
}
if (tr == null) {
response.setContentType("image/png");
response.setIntHeader("Content-Length", blankpng.length);
OutputStream os = response.getOutputStream();
os.write(blankpng);
return;
}
// Got tile, package up for response
response.setDateHeader("Last-Modified", tr.lastModified);
response.setIntHeader("Content-Length", tr.image.length());
response.setContentType(tr.format.getContentType());
ServletOutputStream out = response.getOutputStream();
out.write(tr.image.buffer(), 0, tr.image.length());
out.flush();
}
use of org.dynmap.storage.MapStorageTile in project dynmap by webbukkit.
the class AWSS3MapStorage method processEnumMapTiles.
private void processEnumMapTiles(DynmapWorld world, MapType map, ImageVariant var, MapStorageTileEnumCB cb, MapStorageBaseTileEnumCB cbBase, MapStorageTileSearchEndCB cbEnd) {
String basekey = prefix + "tiles/" + world.getName() + "/" + map.getPrefix() + var.variantSuffix + "/";
ListObjectsV2Request req = ListObjectsV2Request.builder().bucketName(bucketname).prefix(basekey).maxKeys(1000).build();
boolean done = false;
S3Client s3 = getConnection();
try {
while (!done) {
ListObjectsV2Response result = s3.listObjectsV2(req);
List<S3Object> objects = result.getContents();
for (S3Object os : objects) {
String key = os.getKey();
// Strip off base
key = key.substring(basekey.length());
// Parse the extension
String ext = null;
int extoff = key.lastIndexOf('.');
if (extoff >= 0) {
ext = key.substring(extoff + 1);
key = key.substring(0, extoff);
}
// If not valid image extension, ignore
ImageEncoding fmt = ImageEncoding.fromExt(ext);
if (fmt == null) {
continue;
}
// See if zoom tile: figure out zoom level
int zoom = 0;
if (key.startsWith("z")) {
while (key.startsWith("z")) {
key = key.substring(1);
zoom++;
}
if (key.startsWith("_")) {
key = key.substring(1);
}
}
// Split remainder to get coords
String[] coord = key.split("_");
if (coord.length == 2) {
// Must be 2 to be a tile
try {
int x = Integer.parseInt(coord[0]);
int y = Integer.parseInt(coord[1]);
// Invoke callback
MapStorageTile t = new StorageTile(world, map, x, y, zoom, var);
if (cb != null)
cb.tileFound(t, fmt);
if (cbBase != null && t.zoom == 0)
cbBase.tileFound(t, fmt);
t.cleanup();
} catch (NumberFormatException nfx) {
}
}
}
if (result.isTruncated()) {
// If more, build continuiation request
req = ListObjectsV2Request.builder().bucketName(bucketname).prefix(basekey).delimiter("").maxKeys(1000).continuationToken(result.getContinuationToken()).encodingType("url").requestPayer("requester").build();
} else {
// Else, we're done
done = true;
}
}
} catch (S3Exception x) {
if (!x.getCode().equals("SignatureDoesNotMatch")) {
// S3 behavior when no object match....
Log.severe("AWS Exception", x);
Log.severe("req=" + req);
}
} finally {
releaseConnection(s3);
}
if (cbEnd != null) {
cbEnd.searchEnded();
}
}
use of org.dynmap.storage.MapStorageTile in project dynmap by webbukkit.
the class DynmapWorld method processZoomFile.
private void processZoomFile(MapTypeState mts, MapStorageTile tile, boolean firstVariant) {
long mostRecentTimestamp = 0;
int step = 1 << tile.zoom;
MapStorageTile ztile = tile.getZoomOutTile();
int width = mts.tileSize, height = mts.tileSize;
BufferedImage zIm = null;
DynmapBufferedImage kzIm = null;
boolean blank = true;
int[] argb = new int[width * height];
int tx = ztile.x;
int ty = ztile.y;
ty = ty - step;
/* Adjust for negative step */
/* create image buffer */
kzIm = DynmapBufferedImage.allocateBufferedImage(width, height);
zIm = kzIm.buf_img;
for (int i = 0; i < 4; i++) {
boolean doblit = true;
int tx1 = tx + step * (1 & stepseq[i]);
int ty1 = ty + step * (stepseq[i] >> 1);
MapStorageTile tile1 = storage.getTile(this, tile.map, tx1, ty1, tile.zoom, tile.var);
if (tile1 == null)
continue;
tile1.getReadLock();
if (firstVariant) {
// We're handling this one - but only clear on first variant (so that we don't miss updates later)
mts.clearZoomOutInv(tile1.x, tile1.y, tile1.zoom);
}
try {
MapStorageTile.TileRead tr = tile1.read();
if (tr != null) {
BufferedImage im = null;
try {
im = ImageIOManager.imageIODecode(tr);
// Only consider the timestamp when the tile exists and isn't broken
mostRecentTimestamp = Math.max(mostRecentTimestamp, tr.lastModified);
} catch (IOException iox) {
// Broken file - zap it
tile1.delete();
}
if ((im != null) && (im.getWidth() >= width) && (im.getHeight() >= height)) {
int iwidth = im.getWidth();
int iheight = im.getHeight();
if (iwidth > iheight)
iwidth = iheight;
if ((iwidth == width) && (iheight == height)) {
im.getRGB(0, 0, width, height, argb, 0, width);
/* Read data */
im.flush();
/* Do binlinear scale to width/2 x height/2 */
int off = 0;
for (int y = 0; y < height; y += 2) {
off = y * width;
for (int x = 0; x < width; x += 2, off += 2) {
int p0 = argb[off];
int p1 = argb[off + 1];
int p2 = argb[off + width];
int p3 = argb[off + width + 1];
int alpha = ((p0 >> 24) & 0xFF) + ((p1 >> 24) & 0xFF) + ((p2 >> 24) & 0xFF) + ((p3 >> 24) & 0xFF);
int red = ((p0 >> 16) & 0xFF) + ((p1 >> 16) & 0xFF) + ((p2 >> 16) & 0xFF) + ((p3 >> 16) & 0xFF);
int green = ((p0 >> 8) & 0xFF) + ((p1 >> 8) & 0xFF) + ((p2 >> 8) & 0xFF) + ((p3 >> 8) & 0xFF);
int blue = (p0 & 0xFF) + (p1 & 0xFF) + (p2 & 0xFF) + (p3 & 0xFF);
argb[off >> 1] = (((alpha >> 2) & 0xFF) << 24) | (((red >> 2) & 0xFF) << 16) | (((green >> 2) & 0xFF) << 8) | ((blue >> 2) & 0xFF);
}
}
} else {
int[] buf = new int[iwidth * iwidth];
im.getRGB(0, 0, iwidth, iwidth, buf, 0, iwidth);
im.flush();
TexturePack.scaleTerrainPNGSubImage(iwidth, width / 2, buf, argb);
/* blit scaled rendered tile onto zoom-out tile */
zIm.setRGB(((i >> 1) != 0) ? 0 : width / 2, (i & 1) * height / 2, width / 2, height / 2, argb, 0, width / 2);
doblit = false;
}
blank = false;
} else {
if (tile1.map.getImageFormat().getEncoding() == ImageEncoding.JPG) {
Arrays.fill(argb, tile1.map.getBackgroundARGB(tile1.var));
} else {
Arrays.fill(argb, 0);
}
// Delete unusable tile
tile1.delete();
}
} else {
if (tile1.map.getImageFormat().getEncoding() == ImageEncoding.JPG) {
Arrays.fill(argb, tile1.map.getBackgroundARGB(tile1.var));
} else {
Arrays.fill(argb, 0);
}
}
} finally {
tile1.releaseReadLock();
}
/* blit scaled rendered tile onto zoom-out tile */
if (doblit) {
zIm.setRGB(((i >> 1) != 0) ? 0 : width / 2, (i & 1) * height / 2, width / 2, height / 2, argb, 0, width);
}
}
ztile.getWriteLock();
try {
MapManager mm = MapManager.mapman;
if (mm == null)
return;
long crc = MapStorage.calculateImageHashCode(kzIm.argb_buf, 0, kzIm.argb_buf.length);
/* Get hash of tile */
if (blank) {
if (ztile.exists()) {
ztile.delete();
MapManager.mapman.pushUpdate(this, new Client.Tile(ztile.getURI()));
enqueueZoomOutUpdate(ztile);
}
} else /* if (!ztile.matchesHashCode(crc)) */
{
ztile.write(crc, zIm, (mostRecentTimestamp == 0) ? System.currentTimeMillis() : mostRecentTimestamp);
MapManager.mapman.pushUpdate(this, new Client.Tile(ztile.getURI()));
enqueueZoomOutUpdate(ztile);
}
} finally {
ztile.releaseWriteLock();
DynmapBufferedImage.freeBufferedImage(kzIm);
}
}
use of org.dynmap.storage.MapStorageTile in project dynmap by webbukkit.
the class HDMap method purgeOldTiles.
public void purgeOldTiles(final DynmapWorld world, final TileFlags rendered) {
final MapStorage ms = world.getMapStorage();
ms.enumMapTiles(world, this, new MapStorageTileEnumCB() {
@Override
public void tileFound(MapStorageTile tile, ImageEncoding fmt) {
if (fmt != getImageFormat().getEncoding()) {
// Wrong format? toss it
/* Otherwise, delete tile */
tile.delete();
} else if (tile.zoom == 1) {
// If any were rendered, already triggered (and still needed
if (rendered.getFlag(tile.x, tile.y) || rendered.getFlag(tile.x + 1, tile.y) || rendered.getFlag(tile.x, tile.y - 1) || rendered.getFlag(tile.x + 1, tile.y - 1)) {
return;
}
tile.enqueueZoomOutUpdate();
} else if (tile.zoom == 0) {
if (rendered.getFlag(tile.x, tile.y)) {
/* If we rendered this tile, its good */
return;
}
/* Otherwise, delete tile */
tile.delete();
/* Push updates, clear hash code, and signal zoom tile update */
MapManager.mapman.pushUpdate(world, new Client.Tile(tile.getURI()));
tile.enqueueZoomOutUpdate();
}
}
});
}
use of org.dynmap.storage.MapStorageTile in project dynmap by webbukkit.
the class IsoHDPerspective method render.
@Override
public boolean render(MapChunkCache cache, HDMapTile tile, String mapname) {
final long startTimestamp = System.currentTimeMillis();
Color rslt = new Color();
MapIterator mapiter = cache.getIterator(0, 0, 0);
DynmapWorld world = tile.getDynmapWorld();
int tileSize = tile.getTileSize();
int scaled = 0;
if ((tile.boostzoom > 0) && MarkerAPIImpl.testTileForBoostMarkers(cache.getWorld(), this, tile.tx * tileSize, tile.ty * tileSize, tileSize)) {
scaled = tile.boostzoom;
}
int sizescale = 1 << scaled;
/* Build shader state object for each shader */
HDShaderState[] shaderstate = MapManager.mapman.hdmapman.getShaderStateForTile(tile, cache, mapiter, mapname, sizescale * this.basemodscale);
int numshaders = shaderstate.length;
if (numshaders == 0)
return false;
/* Check if nether world */
boolean isnether = world.isNether();
/* Create buffered image for each */
DynmapBufferedImage[] im = new DynmapBufferedImage[numshaders];
DynmapBufferedImage[] dayim = new DynmapBufferedImage[numshaders];
int[][] argb_buf = new int[numshaders][];
int[][] day_argb_buf = new int[numshaders][];
boolean[] isOpaque = new boolean[numshaders];
int[] bgday = new int[numshaders];
int[] bgnight = new int[numshaders];
for (int i = 0; i < numshaders; i++) {
HDLighting lighting = shaderstate[i].getLighting();
im[i] = DynmapBufferedImage.allocateBufferedImage(tileSize * sizescale, tileSize * sizescale);
argb_buf[i] = im[i].argb_buf;
if (lighting.isNightAndDayEnabled()) {
dayim[i] = DynmapBufferedImage.allocateBufferedImage(tileSize * sizescale, tileSize * sizescale);
day_argb_buf[i] = dayim[i].argb_buf;
}
isOpaque[i] = !shaderstate[i].getMap().getImageFormat().getEncoding().hasAlpha;
bgday[i] = shaderstate[i].getMap().getBackgroundARGBDay();
bgnight[i] = shaderstate[i].getMap().getBackgroundARGBNight();
}
// Mark the tiles we're going to render as validated
for (int i = 0; i < numshaders; i++) {
MapTypeState mts = world.getMapState(shaderstate[i].getMap());
if (mts != null) {
mts.validateTile(tile.tx, tile.ty);
}
}
/* Create perspective state object */
OurPerspectiveState ps = new OurPerspectiveState(mapiter, isnether, scaled);
ps.top = new Vector3D();
ps.bottom = new Vector3D();
ps.direction = new Vector3D();
double xbase = tile.tx * tileSize;
double ybase = tile.ty * tileSize;
boolean[] shaderdone = new boolean[numshaders];
boolean[] rendered = new boolean[numshaders];
double height = maxheight;
if (height == Integer.MIN_VALUE) {
/* Not set - assume world height - 1 */
if (isnether)
height = 127;
else
height = tile.getDynmapWorld().worldheight - 1;
}
double miny = minheight;
if (miny == Integer.MIN_VALUE) {
/* Not set - assume world height - 1 */
miny = tile.getDynmapWorld().minY;
}
for (int x = 0; x < tileSize * sizescale; x++) {
ps.px = x;
for (int y = 0; y < tileSize * sizescale; y++) {
ps.top.x = ps.bottom.x = xbase + (x + 0.5) / sizescale;
/* Start at center of pixel at Y=height+0.5, bottom at Y=-0.5 */
ps.top.y = ps.bottom.y = ybase + (y + 0.5) / sizescale;
ps.top.z = height + 0.5;
ps.bottom.z = miny - 0.5;
map_to_world.transform(ps.top);
/* Transform to world coordinates */
map_to_world.transform(ps.bottom);
ps.direction.set(ps.bottom);
ps.direction.subtract(ps.top);
ps.py = y / sizescale;
for (int i = 0; i < numshaders; i++) {
shaderstate[i].reset(ps);
}
try {
ps.raytrace(cache, shaderstate, shaderdone);
} catch (Exception ex) {
Log.severe("Error while raytracing tile: perspective=" + this.name + ", coord=" + mapiter.getX() + "," + mapiter.getY() + "," + mapiter.getZ() + ", blockid=" + mapiter.getBlockType() + ", lighting=" + mapiter.getBlockSkyLight() + ":" + mapiter.getBlockEmittedLight() + ", biome=" + mapiter.getBiome().toString(), ex);
ex.printStackTrace();
}
for (int i = 0; i < numshaders; i++) {
if (shaderdone[i] == false) {
shaderstate[i].rayFinished(ps);
} else {
shaderdone[i] = false;
rendered[i] = true;
}
shaderstate[i].getRayColor(rslt, 0);
int c_argb = rslt.getARGB();
if (c_argb != 0)
rendered[i] = true;
if (isOpaque[i] && (c_argb == 0)) {
argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = bgnight[i];
} else {
argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = c_argb;
}
if (day_argb_buf[i] != null) {
shaderstate[i].getRayColor(rslt, 1);
c_argb = rslt.getARGB();
if (isOpaque[i] && (c_argb == 0)) {
day_argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = bgday[i];
} else {
day_argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = c_argb;
}
}
}
}
}
boolean renderone = false;
/* Test to see if we're unchanged from older tile */
MapStorage storage = world.getMapStorage();
for (int i = 0; i < numshaders; i++) {
long crc = MapStorage.calculateImageHashCode(argb_buf[i], 0, argb_buf[i].length);
boolean tile_update = false;
String prefix = shaderstate[i].getMap().getPrefix();
MapStorageTile mtile = storage.getTile(world, shaderstate[i].getMap(), tile.tx, tile.ty, 0, MapType.ImageVariant.STANDARD);
mtile.getWriteLock();
try {
if (mtile.matchesHashCode(crc) == false) {
/* Wrap buffer as buffered image */
if (rendered[i]) {
mtile.write(crc, im[i].buf_img, startTimestamp);
} else {
mtile.delete();
}
MapManager.mapman.pushUpdate(tile.getDynmapWorld(), new Client.Tile(mtile.getURI()));
tile_update = true;
renderone = true;
} else {
if (!rendered[i]) {
mtile.delete();
}
}
} finally {
mtile.releaseWriteLock();
DynmapBufferedImage.freeBufferedImage(im[i]);
}
MapManager.mapman.updateStatistics(tile, prefix, true, tile_update, !rendered[i]);
/* Handle day image, if needed */
if (dayim[i] != null) {
crc = MapStorage.calculateImageHashCode(day_argb_buf[i], 0, day_argb_buf[i].length);
mtile = storage.getTile(world, shaderstate[i].getMap(), tile.tx, tile.ty, 0, MapType.ImageVariant.DAY);
mtile.getWriteLock();
tile_update = false;
try {
if (mtile.matchesHashCode(crc) == false) {
/* Wrap buffer as buffered image */
if (rendered[i]) {
mtile.write(crc, dayim[i].buf_img, startTimestamp);
} else {
mtile.delete();
}
MapManager.mapman.pushUpdate(tile.getDynmapWorld(), new Client.Tile(mtile.getURI()));
tile_update = true;
renderone = true;
} else {
if (!rendered[i]) {
mtile.delete();
}
}
} finally {
mtile.releaseWriteLock();
DynmapBufferedImage.freeBufferedImage(dayim[i]);
}
MapManager.mapman.updateStatistics(tile, prefix + "_day", true, tile_update, !rendered[i]);
}
}
return renderone;
}
Aggregations