package net.CyanWool.io; /* ** 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. * */ // A simple cache and wrapper for efficiently multiple RegionFiles simultaneously. import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Map; import net.CyanWool.api.io.RegionFile; public class RegionFileCache { private static final int MAX_CACHE_SIZE = 256; private static final Map<File, Reference<RegionFile>> cache = new HashMap<File, Reference<RegionFile>>(); 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) + ".mca"); Reference<RegionFile> ref = cache.get(file); if (ref != null && ref.get() != null) { return ref.get(); } if (!regionDir.exists()) { regionDir.mkdirs(); } if (cache.size() >= MAX_CACHE_SIZE) { RegionFileCache.clear(); } RegionFile reg = new RegionFile(file); cache.put(file, new SoftReference<RegionFile>(reg)); return reg; } 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); } public static DataOutputStream getChunkDataOutputStream(File basePath, int chunkX, int chunkZ) { RegionFile r = getRegionFile(basePath, chunkX, chunkZ); return r.getChunkDataOutputStream(chunkX & 31, chunkZ & 31); } }