Search in sources :

Example 1 with MapStorageTile

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();
}
Also used : MapStorageTile(org.dynmap.storage.MapStorageTile) ServletOutputStream(javax.servlet.ServletOutputStream) TileRead(org.dynmap.storage.MapStorageTile.TileRead) OutputStream(java.io.OutputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ServletOutputStream(javax.servlet.ServletOutputStream) DynmapWorld(org.dynmap.DynmapWorld) MapStorage(org.dynmap.storage.MapStorage)

Example 2 with MapStorageTile

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();
    }
}
Also used : ImageEncoding(org.dynmap.MapType.ImageEncoding) MapStorageTile(org.dynmap.storage.MapStorageTile) S3Exception(io.github.linktosriram.s3lite.api.exception.S3Exception) ListObjectsV2Request(io.github.linktosriram.s3lite.api.request.ListObjectsV2Request) S3Object(io.github.linktosriram.s3lite.api.response.S3Object) S3Client(io.github.linktosriram.s3lite.api.client.S3Client) MapStorageTile(org.dynmap.storage.MapStorageTile) ListObjectsV2Response(io.github.linktosriram.s3lite.api.response.ListObjectsV2Response)

Example 3 with MapStorageTile

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);
    }
}
Also used : MapStorageTile(org.dynmap.storage.MapStorageTile) DynmapBufferedImage(org.dynmap.utils.DynmapBufferedImage) IOException(java.io.IOException) BufferedImage(java.awt.image.BufferedImage) DynmapBufferedImage(org.dynmap.utils.DynmapBufferedImage)

Example 4 with MapStorageTile

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();
            }
        }
    });
}
Also used : MapStorageTileEnumCB(org.dynmap.storage.MapStorageTileEnumCB) MapStorageTile(org.dynmap.storage.MapStorageTile) MapStorageTile(org.dynmap.storage.MapStorageTile) MapTile(org.dynmap.MapTile) MapStorage(org.dynmap.storage.MapStorage)

Example 5 with MapStorageTile

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;
}
Also used : MapStorageTile(org.dynmap.storage.MapStorageTile) Color(org.dynmap.Color) MapIterator(org.dynmap.utils.MapIterator) MapTypeState(org.dynmap.MapTypeState) MapStorage(org.dynmap.storage.MapStorage) DynmapBufferedImage(org.dynmap.utils.DynmapBufferedImage) Vector3D(org.dynmap.utils.Vector3D) DynmapWorld(org.dynmap.DynmapWorld) Client(org.dynmap.Client)

Aggregations

MapStorageTile (org.dynmap.storage.MapStorageTile)7 MapStorage (org.dynmap.storage.MapStorage)3 DynmapWorld (org.dynmap.DynmapWorld)2 ImageEncoding (org.dynmap.MapType.ImageEncoding)2 DynmapBufferedImage (org.dynmap.utils.DynmapBufferedImage)2 S3Client (io.github.linktosriram.s3lite.api.client.S3Client)1 S3Exception (io.github.linktosriram.s3lite.api.exception.S3Exception)1 ListObjectsV2Request (io.github.linktosriram.s3lite.api.request.ListObjectsV2Request)1 ListObjectsV2Response (io.github.linktosriram.s3lite.api.response.ListObjectsV2Response)1 S3Object (io.github.linktosriram.s3lite.api.response.S3Object)1 BufferedImage (java.awt.image.BufferedImage)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 File (java.io.File)1 IOException (java.io.IOException)1 OutputStream (java.io.OutputStream)1 RandomAccessFile (java.io.RandomAccessFile)1 LinkedList (java.util.LinkedList)1 ServletOutputStream (javax.servlet.ServletOutputStream)1 Client (org.dynmap.Client)1 Color (org.dynmap.Color)1