diff --git a/src/main/java/com/gmail/nossr50/config/HiddenConfig.java b/src/main/java/com/gmail/nossr50/config/HiddenConfig.java index 18c3644d3..d1d4f1638 100644 --- a/src/main/java/com/gmail/nossr50/config/HiddenConfig.java +++ b/src/main/java/com/gmail/nossr50/config/HiddenConfig.java @@ -28,7 +28,7 @@ public class HiddenConfig { if (mcMMO.p.getResource(fileName) != null) { config = YamlConfiguration.loadConfiguration(mcMMO.p.getResource(fileName)); chunkletsEnabled = config.getBoolean("Options.Chunklets", true); - conversionRate = config.getInt("Options.ConversionRate", 3); + conversionRate = config.getInt("Options.ConversionRate", 1); } } diff --git a/src/main/java/com/gmail/nossr50/runnables/blockstoreconversion/BlockStoreConversionZDirectory.java b/src/main/java/com/gmail/nossr50/runnables/blockstoreconversion/BlockStoreConversionZDirectory.java index 5b7bcfa01..543cc9e33 100755 --- a/src/main/java/com/gmail/nossr50/runnables/blockstoreconversion/BlockStoreConversionZDirectory.java +++ b/src/main/java/com/gmail/nossr50/runnables/blockstoreconversion/BlockStoreConversionZDirectory.java @@ -15,7 +15,7 @@ import com.gmail.nossr50.util.blockmeta.HashChunkletManager; import com.gmail.nossr50.util.blockmeta.chunkmeta.HashChunkManager; public class BlockStoreConversionZDirectory implements Runnable { - private int taskID, cx, cz, x, y, z, y2, xPos, zPos, cxPos, czPos; + public int taskID, cx, cz, x, y, z, y2, xPos, zPos, cxPos, czPos; private String cxs, czs, chunkletName, chunkName; private org.bukkit.World world; private BukkitScheduler scheduler; diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java index 3faef4be7..225725dca 100755 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java @@ -7,6 +7,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.lang.Integer; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.UUID; @@ -17,6 +18,7 @@ import org.bukkit.block.Block; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.runnables.ChunkletUnloader; +import com.gmail.nossr50.runnables.blockstoreconversion.BlockStoreConversionZDirectory; import com.gmail.nossr50.util.blockmeta.ChunkletStore; import com.gmail.nossr50.util.blockmeta.PrimitiveChunkletStore; import com.gmail.nossr50.util.blockmeta.PrimitiveExChunkletStore; @@ -27,9 +29,10 @@ import org.getspout.spoutapi.chunkstore.mcMMOSimpleRegionFile; public class HashChunkManager implements ChunkManager { private HashMap> regionFiles = new HashMap>(); public HashMap store = new HashMap(); + public ArrayList converters = new ArrayList(); @Override - public void closeAll() { + public synchronized void closeAll() { for (UUID uid : regionFiles.keySet()) { HashMap worldRegions = regionFiles.get(uid); Iterator itr = worldRegions.values().iterator(); @@ -45,7 +48,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public ChunkStore readChunkStore(World world, int x, int z) throws IOException { + public synchronized ChunkStore readChunkStore(World world, int x, int z) throws IOException { mcMMOSimpleRegionFile rf = getSimpleRegionFile(world, x, z); InputStream in = rf.getInputStream(x, z); if (in == null) { @@ -72,7 +75,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void writeChunkStore(World world, int x, int z, ChunkStore data) { + public synchronized void writeChunkStore(World world, int x, int z, ChunkStore data) { if (!data.isDirty()) { return; } @@ -89,14 +92,14 @@ public class HashChunkManager implements ChunkManager { } @Override - public void closeChunkStore(World world, int x, int z) { + public synchronized void closeChunkStore(World world, int x, int z) { mcMMOSimpleRegionFile rf = getSimpleRegionFile(world, x, z); if (rf != null) { rf.close(); } } - private mcMMOSimpleRegionFile getSimpleRegionFile(World world, int x, int z) { + private synchronized mcMMOSimpleRegionFile getSimpleRegionFile(World world, int x, int z) { File directory = new File(world.getWorldFolder(), "mcmmo_regions"); directory.mkdirs(); @@ -127,17 +130,17 @@ public class HashChunkManager implements ChunkManager { } @Override - public void loadChunklet(int cx, int cy, int cz, World world) { + public synchronized void loadChunklet(int cx, int cy, int cz, World world) { loadChunk(cx, cz, world); } @Override - public void unloadChunklet(int cx, int cy, int cz, World world) { + public synchronized void unloadChunklet(int cx, int cy, int cz, World world) { unloadChunk(cx, cz, world); } @Override - public void loadChunk(int cx, int cz, World world) { + public synchronized void loadChunk(int cx, int cz, World world) { if(world == null) return; @@ -146,6 +149,10 @@ public class HashChunkManager implements ChunkManager { ChunkStore in = null; + File dataDir = new File(world.getWorldFolder(), "mcmmo_data"); + if(dataDir.exists()) + convertChunk(dataDir, cx, cz, world, true); + try { in = readChunkStore(world, cx, cz); } @@ -157,7 +164,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void unloadChunk(int cx, int cz, World world) { + public synchronized void unloadChunk(int cx, int cz, World world) { saveChunk(cx, cz, world); if(store.containsKey(world.getName() + "," + cx + "," + cz)) { @@ -166,7 +173,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void saveChunk(int cx, int cz, World world) { + public synchronized void saveChunk(int cx, int cz, World world) { if(world == null) return; @@ -181,7 +188,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public boolean isChunkLoaded(int cx, int cz, World world) { + public synchronized boolean isChunkLoaded(int cx, int cz, World world) { if(world == null) return false; @@ -189,10 +196,10 @@ public class HashChunkManager implements ChunkManager { } @Override - public void chunkLoaded(int cx, int cz, World world) {} + public synchronized void chunkLoaded(int cx, int cz, World world) {} @Override - public void chunkUnloaded(int cx, int cz, World world) { + public synchronized void chunkUnloaded(int cx, int cz, World world) { if(world == null) return; @@ -200,7 +207,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void saveWorld(World world) { + public synchronized void saveWorld(World world) { if(world == null) return; @@ -226,7 +233,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void unloadWorld(World world) { + public synchronized void unloadWorld(World world) { if(world == null) return; @@ -252,10 +259,10 @@ public class HashChunkManager implements ChunkManager { } @Override - public void loadWorld(World world) {} + public synchronized void loadWorld(World world) {} @Override - public void saveAll() { + public synchronized void saveAll() { closeAll(); for(World world : Bukkit.getWorlds()) { @@ -264,7 +271,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void unloadAll() { + public synchronized void unloadAll() { closeAll(); for(World world : Bukkit.getWorlds()) { @@ -273,7 +280,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public boolean isTrue(int x, int y, int z, World world) { + public synchronized boolean isTrue(int x, int y, int z, World world) { if(world == null) return false; @@ -297,7 +304,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public boolean isTrue(Block block) { + public synchronized boolean isTrue(Block block) { if(block == null) return false; @@ -305,7 +312,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void setTrue(int x, int y, int z, World world) { + public synchronized void setTrue(int x, int y, int z, World world) { if(world == null) return; @@ -332,7 +339,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void setTrue(Block block) { + public synchronized void setTrue(Block block) { if(block == null) return; @@ -340,7 +347,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void setFalse(int x, int y, int z, World world) { + public synchronized void setFalse(int x, int y, int z, World world) { if(world == null) return; @@ -366,7 +373,7 @@ public class HashChunkManager implements ChunkManager { } @Override - public void setFalse(Block block) { + public synchronized void setFalse(Block block) { if(block == null) return; @@ -374,91 +381,39 @@ public class HashChunkManager implements ChunkManager { } @Override - public void cleanUp() {} + public synchronized void cleanUp() {} - public void convertChunk(File dataDir, int cx, int cz, World world) { - HashChunkletManager manager = new HashChunkletManager(); - manager.loadChunk(cx, cz, world); - - for(int y = 0; y < (world.getMaxHeight() / 64); y++) { - String chunkletName = world.getName() + "," + cx + "," + cz + "," + y; - ChunkletStore tempChunklet = manager.store.get(chunkletName); - PrimitiveChunkletStore primitiveChunklet = null; - PrimitiveExChunkletStore primitiveExChunklet = null; - if(tempChunklet instanceof PrimitiveChunkletStore) - primitiveChunklet = (PrimitiveChunkletStore) tempChunklet; - else if(tempChunklet instanceof PrimitiveExChunkletStore) - primitiveExChunklet = (PrimitiveExChunkletStore) tempChunklet; - if(tempChunklet == null) { - continue; - } else { - String chunkName = world.getName() + "," + cx + "," + cz; - PrimitiveChunkStore cChunk = (PrimitiveChunkStore) store.get(chunkName); - - if(cChunk != null) { - int xPos = cx * 16; - int zPos = cz * 16; - - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - int cxPos = xPos + x; - int czPos = zPos + z; - - for(int y2 = (64 * y); y2 < (64 * y + 64); y2++) { - if(!manager.isTrue(cxPos, y2, czPos, world)) - continue; - - setTrue(cxPos, y2, czPos, world); - } - } - } - continue; - } - - setTrue(cx * 16, 0, cz * 16, world); - setFalse(cx * 16, 0, cz * 16, world); - cChunk = (PrimitiveChunkStore) store.get(chunkName); - - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - boolean[] oldArray; - if(primitiveChunklet != null) - oldArray = primitiveChunklet.store[x][z]; - if(primitiveExChunklet != null) - oldArray = primitiveExChunklet.store[x][z]; - else - return; - boolean[] newArray = cChunk.store[x][z]; - if(oldArray.length < 64) - return; - else if(newArray.length < ((y * 64) + 64)) - return; - System.arraycopy(oldArray, 0, newArray, (y * 64), 64); - } - } - } - } - - manager.unloadChunk(cx, cz, world); - unloadChunk(cx, cz, world); + public synchronized void convertChunk(File dataDir, int cx, int cz, World world) { + convertChunk(dataDir, cx, cz, world, false); + } + public synchronized void convertChunk(File dataDir, int cx, int cz, World world, boolean actually) { + if(!actually) + return; + if(!dataDir.exists()) return; File cxDir = new File(dataDir, "" + cx); if(!cxDir.exists()) return; File czDir = new File(cxDir, "" + cz); if(!czDir.exists()) return; - for(File yFile : czDir.listFiles()) { - if(!yFile.exists()) + boolean conversionSet = false; + + for(BlockStoreConversionZDirectory converter : this.converters) { + if(converter == null) continue; - yFile.delete(); + if(converter.taskID >= 0) + continue; + + converter.start(world, cxDir, czDir); + conversionSet = true; + break; } - if(czDir.listFiles().length <= 0) - czDir.delete(); - if(cxDir.listFiles().length <= 0) - cxDir.delete(); - if(dataDir.listFiles().length <= 0) - dataDir.delete(); + if(!conversionSet) { + BlockStoreConversionZDirectory converter = new BlockStoreConversionZDirectory(); + converter.start(world, cxDir, czDir); + converters.add(converter); + } } } diff --git a/src/main/java/org/getspout/spoutapi/chunkstore/mcMMOSimpleRegionFile.java b/src/main/java/org/getspout/spoutapi/chunkstore/mcMMOSimpleRegionFile.java index 8acd53434..1e3354479 100755 --- a/src/main/java/org/getspout/spoutapi/chunkstore/mcMMOSimpleRegionFile.java +++ b/src/main/java/org/getspout/spoutapi/chunkstore/mcMMOSimpleRegionFile.java @@ -102,7 +102,7 @@ public class mcMMOSimpleRegionFile { } } - public final RandomAccessFile getFile() { + public synchronized final RandomAccessFile getFile() { lastAccessTime = System.currentTimeMillis(); if (file == null) { try { @@ -150,7 +150,7 @@ public class mcMMOSimpleRegionFile { return file; } - public boolean testCloseTimeout() { + public synchronized boolean testCloseTimeout() { /*if (System.currentTimeMillis() - TIMEOUT_TIME > lastAccessTime) { close(); return true; @@ -158,12 +158,12 @@ public class mcMMOSimpleRegionFile { return false; } - public DataOutputStream getOutputStream(int x, int z) { + public synchronized DataOutputStream getOutputStream(int x, int z) { int index = getChunkIndex(x, z); return new DataOutputStream(new DeflaterOutputStream(new mcMMOSimpleChunkBuffer(this, index))); } - public DataInputStream getInputStream(int x, int z) throws IOException { + public synchronized DataInputStream getInputStream(int x, int z) throws IOException { int index = getChunkIndex(x, z); int actualLength = dataActualLength[index]; if (actualLength == 0) { @@ -176,7 +176,7 @@ public class mcMMOSimpleRegionFile { return new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(data))); } - void write(int index, byte[] buffer, int size) throws IOException { + synchronized void write(int index, byte[] buffer, int size) throws IOException { int oldStart = setInUse(index, false); int start = findSpace(oldStart, size); getFile().seek(start << segmentSize); @@ -188,7 +188,7 @@ public class mcMMOSimpleRegionFile { saveFAT(); } - public void close() { + public synchronized void close() { try { if (file != null) { file.seek(4096 * 2); @@ -200,7 +200,7 @@ public class mcMMOSimpleRegionFile { } } - private int setInUse(int index, boolean used) { + private synchronized int setInUse(int index, boolean used) { if (dataActualLength[index] == 0) { return dataStart[index]; } @@ -225,7 +225,7 @@ public class mcMMOSimpleRegionFile { return dataStart[index]; } - private void extendFile() throws IOException { + private synchronized void extendFile() throws IOException { long extend = (-getFile().length()) & segmentMask; getFile().seek(getFile().length()); @@ -235,7 +235,7 @@ public class mcMMOSimpleRegionFile { } } - private int findSpace(int oldStart, int size) { + private synchronized int findSpace(int oldStart, int size) { int segments = sizeToSegments(size); boolean oldFree = true; @@ -268,7 +268,7 @@ public class mcMMOSimpleRegionFile { return start; } - private int sizeToSegments(int size) { + private synchronized int sizeToSegments(int size) { if (size <= 0) { return 1; } else { @@ -276,7 +276,7 @@ public class mcMMOSimpleRegionFile { } } - private Integer getChunkIndex(int x, int z) { + private synchronized Integer getChunkIndex(int x, int z) { if (rx != (x >> 5) || rz != (z >> 5)) { throw new RuntimeException(x + ", " + z + " not in region " + rx + ", " + rz); } @@ -287,7 +287,7 @@ public class mcMMOSimpleRegionFile { return (x << 5) + z; } - private void saveFAT() throws IOException { + private synchronized void saveFAT() throws IOException { getFile().seek(0); for (int i = 0; i < 1024; i++) { getFile().writeInt(dataStart[i]); diff --git a/src/main/resources/hidden.yml b/src/main/resources/hidden.yml index 468ae99f5..175985949 100644 --- a/src/main/resources/hidden.yml +++ b/src/main/resources/hidden.yml @@ -6,4 +6,4 @@ Options: # true to use Chunklets metadata store system, false to disable Chunklets: true # Square root of the number of chunks to convert per tick. - ConversionRate: 3 \ No newline at end of file + ConversionRate: 1 \ No newline at end of file