/* | |
** 2011 January 5 | |
** | |
** The author disclaims copyright to this source code. In place of | |
** a legal notice, here is a blessing: | |
** | |
** May you do good and not evil. | |
** May you find forgiveness for yourself and forgive others. | |
** May you share freely, never taking more than you give. | |
*/ | |
/* | |
* 2011 February 16 | |
* | |
* This source code is based on the work of Scaevolus (see notice above). | |
* It has been slightly modified by Mojang AB to limit the maximum cache | |
* size (relevant to extremely big worlds on Linux systems with limited | |
* number of file handles). The region files are postfixed with ".mcr" | |
* (Minecraft region file) instead of ".data" to differentiate from the | |
* original McRegion files. | |
* | |
*/ | |
/* | |
* 2011 February 20 | |
* | |
* Imported by CJ Kucera into X-Ray, from a blog post by Jens Bergensten | |
* at: http://mojang.com/2011/02/16/minecraft-save-file-format-in-beta-1-3/ | |
*/ | |
// A simple cache and wrapper for efficiently multiple RegionFiles simultaneously. | |
package com.plusminus.craft; | |
import java.io.*; | |
import java.lang.ref.*; | |
import java.util.*; | |
public class RegionFileCache { | |
private static final int MAX_CACHE_SIZE = 256; | |
private static final Map<File, Reference<RegionFile>> cache = new HashMap<File, Reference<RegionFile>>(); | |
private RegionFileCache() { | |
} | |
public static synchronized RegionFile getRegionFile(File basePath, int chunkX, int chunkZ) { | |
File regionDir = new File(basePath, "region"); | |
File file = new File(regionDir, "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mcr"); | |
Reference<RegionFile> ref = cache.get(file); | |
if (ref != null && ref.get() != null) { | |
return ref.get(); | |
} | |
/* Commented for X-Ray because I'd rather not modify anything, even if it's just a | |
* directory. We should never get here unless stuff exists, anyway. | |
if (!regionDir.exists()) { | |
regionDir.mkdirs(); | |
} | |
*/ | |
if (cache.size() >= MAX_CACHE_SIZE) { | |
RegionFileCache.clear(); | |
} | |
if (file.exists()) | |
{ | |
RegionFile reg = new RegionFile(file); | |
cache.put(file, new SoftReference<RegionFile>(reg)); | |
return reg; | |
} | |
else | |
{ | |
return null; | |
} | |
} | |
public static synchronized void clear() { | |
for (Reference<RegionFile> ref : cache.values()) { | |
try { | |
if (ref.get() != null) { | |
ref.get().close(); | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
cache.clear(); | |
} | |
public static int getSizeDelta(File basePath, int chunkX, int chunkZ) { | |
RegionFile r = getRegionFile(basePath, chunkX, chunkZ); | |
return r.getSizeDelta(); | |
} | |
public static DataInputStream getChunkDataInputStream(File basePath, int chunkX, int chunkZ) { | |
RegionFile r = getRegionFile(basePath, chunkX, chunkZ); | |
return r.getChunkDataInputStream(chunkX & 31, chunkZ & 31); | |
} | |
/* Commented for X-Ray since we won't be writing anything | |
public static DataOutputStream getChunkDataOutputStream(File basePath, int chunkX, int chunkZ) { | |
RegionFile r = getRegionFile(basePath, chunkX, chunkZ); | |
return r.getChunkDataOutputStream(chunkX & 31, chunkZ & 31); | |
} | |
*/ | |
} |