private void doFileWrites(
      final File fname,
      final KzedMapTile mtile,
      final KzedBufferedImage img,
      final KzedBufferedImage img_day,
      final KzedZoomedMapTile zmtile,
      final File zoomFile,
      final KzedBufferedImage zimg,
      final KzedBufferedImage zimg_day,
      boolean rendered) {

    /* Get coordinates of zoomed tile */
    int ox = (mtile.px == zmtile.getTileX()) ? 0 : KzedMap.tileWidth / 2;
    int oy = (mtile.py == zmtile.getTileY()) ? 0 : KzedMap.tileHeight / 2;

    /* Test to see if we're unchanged from older tile */
    FileLockManager.getWriteLock(fname);
    TileHashManager hashman = MapManager.mapman.hashman;
    long crc = hashman.calculateTileHash(img.argb_buf);
    boolean updated_fname = false;
    int tx = mtile.px / KzedMap.tileWidth;
    int ty = mtile.py / KzedMap.tileHeight;
    if ((!fname.exists()) || (crc != hashman.getImageHashCode(mtile.getKey(), null, tx, ty))) {
      Debug.debug("saving image " + fname.getPath());
      try {
        ImageIO.write(img.buf_img, "png", fname);
      } catch (IOException e) {
        Debug.error("Failed to save image: " + fname.getPath(), e);
      } catch (java.lang.NullPointerException e) {
        Debug.error("Failed to save image (NullPointerException): " + fname.getPath(), e);
      }
      MapManager.mapman.pushUpdate(mtile.getWorld(), new Client.Tile(mtile.getFilename()));
      hashman.updateHashCode(mtile.getKey(), null, tx, ty, crc);
      updated_fname = true;
    }
    KzedMap.freeBufferedImage(img);
    FileLockManager.releaseWriteLock(fname);
    MapManager.mapman.updateStatistics(mtile, null, true, updated_fname, !rendered);

    mtile.file = fname;

    boolean updated_dfname = false;
    File dfname = new File(fname.getParent(), mtile.getDayFilename());
    if (img_day != null) {
      FileLockManager.getWriteLock(dfname);
      crc = hashman.calculateTileHash(img.argb_buf);
      if ((!dfname.exists()) || (crc != hashman.getImageHashCode(mtile.getKey(), "day", tx, ty))) {
        Debug.debug("saving image " + dfname.getPath());
        try {
          ImageIO.write(img_day.buf_img, "png", dfname);
        } catch (IOException e) {
          Debug.error("Failed to save image: " + dfname.getPath(), e);
        } catch (java.lang.NullPointerException e) {
          Debug.error("Failed to save image (NullPointerException): " + dfname.getPath(), e);
        }
        MapManager.mapman.pushUpdate(mtile.getWorld(), new Client.Tile(mtile.getDayFilename()));
        hashman.updateHashCode(mtile.getKey(), "day", tx, ty, crc);
        updated_dfname = true;
      }
      KzedMap.freeBufferedImage(img_day);
      FileLockManager.releaseWriteLock(dfname);
      MapManager.mapman.updateStatistics(mtile, "day", true, updated_dfname, !rendered);
    }

    // Since we've already got the new tile, and we're on an async thread, just
    // make the zoomed tile here
    boolean ztile_updated = false;
    FileLockManager.getWriteLock(zoomFile);
    if (updated_fname || (!zoomFile.exists())) {
      saveZoomedTile(zmtile, zoomFile, zimg, ox, oy);
      MapManager.mapman.pushUpdate(zmtile.getWorld(), new Client.Tile(zmtile.getFilename()));
      ztile_updated = true;
    }
    KzedMap.freeBufferedImage(zimg);
    FileLockManager.releaseWriteLock(zoomFile);
    MapManager.mapman.updateStatistics(zmtile, null, true, ztile_updated, !rendered);

    if (zimg_day != null) {
      File zoomFile_day = new File(zoomFile.getParent(), zmtile.getDayFilename());
      ztile_updated = false;
      FileLockManager.getWriteLock(zoomFile_day);
      if (updated_dfname || (!zoomFile_day.exists())) {
        saveZoomedTile(zmtile, zoomFile_day, zimg_day, ox, oy);
        MapManager.mapman.pushUpdate(zmtile.getWorld(), new Client.Tile(zmtile.getDayFilename()));
        ztile_updated = true;
      }
      KzedMap.freeBufferedImage(zimg_day);
      FileLockManager.releaseWriteLock(zoomFile_day);
      MapManager.mapman.updateStatistics(zmtile, "day", true, ztile_updated, !rendered);
    }
  }
  private boolean doFileWrites(
      final File fname,
      final KzedMapTile mtile,
      final DynmapBufferedImage img,
      final DynmapBufferedImage img_day,
      final KzedZoomedMapTile zmtile,
      final File zoomFile,
      final DynmapBufferedImage zimg,
      final DynmapBufferedImage zimg_day) {
    boolean didwrite = false;

    /* Get coordinates of zoomed tile */
    int ox = (mtile.px == zmtile.getTileX()) ? 0 : KzedMap.tileWidth / 2;
    int oy = (mtile.py == zmtile.getTileY()) ? 0 : KzedMap.tileHeight / 2;

    /* Test to see if we're unchanged from older tile */
    TileHashManager hashman = MapManager.mapman.hashman;
    long crc = hashman.calculateTileHash(img.argb_buf);
    boolean updated_fname = false;
    int tx = mtile.px / KzedMap.tileWidth;
    int ty = mtile.py / KzedMap.tileHeight;
    FileLockManager.getWriteLock(fname);
    try {
      if ((!fname.exists())
          || (crc != hashman.getImageHashCode(mtile.getKey(prefix), null, tx, ty))) {
        Debug.debug("saving image " + fname.getPath());
        if (!fname.getParentFile().exists()) fname.getParentFile().mkdirs();
        try {
          FileLockManager.imageIOWrite(img.buf_img, ImageFormat.FORMAT_PNG, fname);
        } catch (IOException e) {
          Debug.error("Failed to save image: " + fname.getPath(), e);
        } catch (java.lang.NullPointerException e) {
          Debug.error("Failed to save image (NullPointerException): " + fname.getPath(), e);
        }
        MapManager.mapman.pushUpdate(mtile.getDynmapWorld(), new Client.Tile(mtile.getFilename()));
        hashman.updateHashCode(mtile.getKey(prefix), null, tx, ty, crc);
        updated_fname = true;
        didwrite = true;
      }
    } finally {
      FileLockManager.releaseWriteLock(fname);
      DynmapBufferedImage.freeBufferedImage(img);
    }
    MapManager.mapman.updateStatistics(mtile, prefix, true, updated_fname, true);

    mtile.file = fname;

    boolean updated_dfname = false;

    File dfname = new File(mtile.getDynmapWorld().worldtilepath, mtile.getDayFilename());
    if (img_day != null) {
      crc = hashman.calculateTileHash(img.argb_buf);
      FileLockManager.getWriteLock(dfname);
      try {
        if ((!dfname.exists())
            || (crc != hashman.getImageHashCode(mtile.getKey(prefix), "day", tx, ty))) {
          Debug.debug("saving image " + dfname.getPath());
          if (!dfname.getParentFile().exists()) dfname.getParentFile().mkdirs();
          try {
            FileLockManager.imageIOWrite(img_day.buf_img, ImageFormat.FORMAT_PNG, dfname);
          } catch (IOException e) {
            Debug.error("Failed to save image: " + dfname.getPath(), e);
          } catch (java.lang.NullPointerException e) {
            Debug.error("Failed to save image (NullPointerException): " + dfname.getPath(), e);
          }
          MapManager.mapman.pushUpdate(
              mtile.getDynmapWorld(), new Client.Tile(mtile.getDayFilename()));
          hashman.updateHashCode(mtile.getKey(prefix), "day", tx, ty, crc);
          updated_dfname = true;
          didwrite = true;
        }
      } finally {
        FileLockManager.releaseWriteLock(dfname);
        DynmapBufferedImage.freeBufferedImage(img_day);
      }
      MapManager.mapman.updateStatistics(mtile, prefix + "_day", true, updated_dfname, true);
    }

    // Since we've already got the new tile, and we're on an async thread, just
    // make the zoomed tile here
    boolean ztile_updated = false;
    FileLockManager.getWriteLock(zoomFile);
    try {
      if (updated_fname || (!zoomFile.exists())) {
        saveZoomedTile(zmtile, zoomFile, zimg, ox, oy, null);
        MapManager.mapman.pushUpdate(
            zmtile.getDynmapWorld(), new Client.Tile(zmtile.getFilename()));
        zmtile.getDynmapWorld().enqueueZoomOutUpdate(zoomFile);
        ztile_updated = true;
      }
    } finally {
      FileLockManager.releaseWriteLock(zoomFile);
      DynmapBufferedImage.freeBufferedImage(zimg);
    }
    MapManager.mapman.updateStatistics(zmtile, null, true, ztile_updated, true);

    if (zimg_day != null) {
      File zoomFile_day = new File(zmtile.getDynmapWorld().worldtilepath, zmtile.getDayFilename());
      ztile_updated = false;
      FileLockManager.getWriteLock(zoomFile_day);
      try {
        if (updated_dfname || (!zoomFile_day.exists())) {
          saveZoomedTile(zmtile, zoomFile_day, zimg_day, ox, oy, "day");
          MapManager.mapman.pushUpdate(
              zmtile.getDynmapWorld(), new Client.Tile(zmtile.getDayFilename()));
          zmtile.getDynmapWorld().enqueueZoomOutUpdate(zoomFile_day);
          ztile_updated = true;
        }
      } finally {
        FileLockManager.releaseWriteLock(zoomFile_day);
        DynmapBufferedImage.freeBufferedImage(zimg_day);
      }
      MapManager.mapman.updateStatistics(zmtile, "day", true, ztile_updated, true);
    }
    return didwrite;
  }