blob: db03d82ecf6c31edb6104a9e58be8f4c7439ede3 [file] [log] [blame] [raw]
/*
** 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);
}
*/
}