| /* | |
| ** 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); | |
| } | |
| */ | |
| } |