Offloading chunk conversion. SHould alleviate lag.

This commit is contained in:
Glitchfinder 2012-11-05 19:28:00 -08:00
parent 7fc99630e0
commit c21286dbc3
3 changed files with 34 additions and 87 deletions

View File

@ -15,7 +15,7 @@ import com.gmail.nossr50.util.blockmeta.HashChunkletManager;
import com.gmail.nossr50.util.blockmeta.chunkmeta.HashChunkManager; import com.gmail.nossr50.util.blockmeta.chunkmeta.HashChunkManager;
public class BlockStoreConversionZDirectory implements Runnable { 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 String cxs, czs, chunkletName, chunkName;
private org.bukkit.World world; private org.bukkit.World world;
private BukkitScheduler scheduler; private BukkitScheduler scheduler;

View File

@ -7,6 +7,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.Integer; import java.lang.Integer;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.UUID; import java.util.UUID;
@ -17,6 +18,7 @@ import org.bukkit.block.Block;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.ChunkletUnloader; 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.ChunkletStore;
import com.gmail.nossr50.util.blockmeta.PrimitiveChunkletStore; import com.gmail.nossr50.util.blockmeta.PrimitiveChunkletStore;
import com.gmail.nossr50.util.blockmeta.PrimitiveExChunkletStore; import com.gmail.nossr50.util.blockmeta.PrimitiveExChunkletStore;
@ -27,6 +29,7 @@ import org.getspout.spoutapi.chunkstore.mcMMOSimpleRegionFile;
public class HashChunkManager implements ChunkManager { public class HashChunkManager implements ChunkManager {
private HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>> regionFiles = new HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>>(); private HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>> regionFiles = new HashMap<UUID, HashMap<Long, mcMMOSimpleRegionFile>>();
public HashMap<String, ChunkStore> store = new HashMap<String, ChunkStore>(); public HashMap<String, ChunkStore> store = new HashMap<String, ChunkStore>();
public ArrayList<BlockStoreConversionZDirectory> converters = new ArrayList<BlockStoreConversionZDirectory>();
@Override @Override
public void closeAll() { public void closeAll() {
@ -377,88 +380,32 @@ public class HashChunkManager implements ChunkManager {
public void cleanUp() {} public void cleanUp() {}
public void convertChunk(File dataDir, int cx, int cz, World world) { public void convertChunk(File dataDir, int cx, int cz, World world) {
HashChunkletManager manager = new HashChunkletManager(); if(!dataDir.exists()) return;
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);
File cxDir = new File(dataDir, "" + cx); File cxDir = new File(dataDir, "" + cx);
if(!cxDir.exists()) return; if(!cxDir.exists()) return;
File czDir = new File(cxDir, "" + cz); File czDir = new File(cxDir, "" + cz);
if(!czDir.exists()) return; if(!czDir.exists()) return;
for(File yFile : czDir.listFiles()) { boolean conversionSet = false;
if(!yFile.exists())
for(BlockStoreConversionZDirectory converter : this.converters) {
if(converter == null)
continue; continue;
yFile.delete(); if(converter.taskID >= 0)
continue;
if(conversionSet)
converters.remove(converter);
converter.start(world, cxDir, czDir);
conversionSet = true;
} }
if(czDir.listFiles().length <= 0) if(!conversionSet) {
czDir.delete(); BlockStoreConversionZDirectory converter = new BlockStoreConversionZDirectory();
if(cxDir.listFiles().length <= 0) converter.start(world, cxDir, czDir);
cxDir.delete(); converters.add(converter);
if(dataDir.listFiles().length <= 0) }
dataDir.delete();
} }
} }

View File

@ -102,7 +102,7 @@ public class mcMMOSimpleRegionFile {
} }
} }
public final RandomAccessFile getFile() { public synchronized final RandomAccessFile getFile() {
lastAccessTime = System.currentTimeMillis(); lastAccessTime = System.currentTimeMillis();
if (file == null) { if (file == null) {
try { try {
@ -150,7 +150,7 @@ public class mcMMOSimpleRegionFile {
return file; return file;
} }
public boolean testCloseTimeout() { public synchronized boolean testCloseTimeout() {
/*if (System.currentTimeMillis() - TIMEOUT_TIME > lastAccessTime) { /*if (System.currentTimeMillis() - TIMEOUT_TIME > lastAccessTime) {
close(); close();
return true; return true;
@ -158,12 +158,12 @@ public class mcMMOSimpleRegionFile {
return false; return false;
} }
public DataOutputStream getOutputStream(int x, int z) { public synchronized DataOutputStream getOutputStream(int x, int z) {
int index = getChunkIndex(x, z); int index = getChunkIndex(x, z);
return new DataOutputStream(new DeflaterOutputStream(new mcMMOSimpleChunkBuffer(this, index))); 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 index = getChunkIndex(x, z);
int actualLength = dataActualLength[index]; int actualLength = dataActualLength[index];
if (actualLength == 0) { if (actualLength == 0) {
@ -176,7 +176,7 @@ public class mcMMOSimpleRegionFile {
return new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(data))); 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 oldStart = setInUse(index, false);
int start = findSpace(oldStart, size); int start = findSpace(oldStart, size);
getFile().seek(start << segmentSize); getFile().seek(start << segmentSize);
@ -188,7 +188,7 @@ public class mcMMOSimpleRegionFile {
saveFAT(); saveFAT();
} }
public void close() { public synchronized void close() {
try { try {
if (file != null) { if (file != null) {
file.seek(4096 * 2); 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) { if (dataActualLength[index] == 0) {
return dataStart[index]; return dataStart[index];
} }
@ -225,7 +225,7 @@ public class mcMMOSimpleRegionFile {
return dataStart[index]; return dataStart[index];
} }
private void extendFile() throws IOException { private synchronized void extendFile() throws IOException {
long extend = (-getFile().length()) & segmentMask; long extend = (-getFile().length()) & segmentMask;
getFile().seek(getFile().length()); 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); int segments = sizeToSegments(size);
boolean oldFree = true; boolean oldFree = true;
@ -268,7 +268,7 @@ public class mcMMOSimpleRegionFile {
return start; return start;
} }
private int sizeToSegments(int size) { private synchronized int sizeToSegments(int size) {
if (size <= 0) { if (size <= 0) {
return 1; return 1;
} else { } 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)) { if (rx != (x >> 5) || rz != (z >> 5)) {
throw new RuntimeException(x + ", " + z + " not in region " + rx + ", " + rz); throw new RuntimeException(x + ", " + z + " not in region " + rx + ", " + rz);
} }
@ -287,7 +287,7 @@ public class mcMMOSimpleRegionFile {
return (x << 5) + z; return (x << 5) + z;
} }
private void saveFAT() throws IOException { private synchronized void saveFAT() throws IOException {
getFile().seek(0); getFile().seek(0);
for (int i = 0; i < 1024; i++) { for (int i = 0; i < 1024; i++) {
getFile().writeInt(dataStart[i]); getFile().writeInt(dataStart[i]);