More work on anvil API
Fix IO exception with history on disk
Optimize chunk index caching
This commit is contained in:
Jesse Boyd 2016-08-20 13:33:56 +10:00
parent 4267bf1c27
commit 4ddffb197b
38 changed files with 1224 additions and 547 deletions

View File

@ -115,7 +115,7 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk> {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = blocks[FaweCache.CACHE_J[y][x][z]];
char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
if (combinedId > 1) {
palette.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
}

View File

@ -128,7 +128,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
lastBits = (DataBits) fieldBits.get(dataPaletteBlock);
lastBlocks = dataPaletteBlock;
}
int i = FaweCache.CACHE_J[y][x & 15][z & 15];
int i = FaweCache.CACHE_J[y][z & 15][x & 15];
return lastBits.a(i) != 0;
} catch (IllegalAccessException e) {
e.printStackTrace();
@ -456,12 +456,12 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
int x = ((int) Math.round(ent.locX) & 15);
int z = ((int) Math.round(ent.locZ) & 15);
int y = (int) Math.round(ent.locY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityTypes.b(ent);
if (id != null) {
@ -541,7 +541,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
if (array == null || y < 0 || y > 255) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -607,12 +607,12 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
if (toRemove == null) {
toRemove = new HashMap<>();
@ -666,10 +666,10 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
int nonEmptyBlockCount = 0;
for (int y = 0; y < 16; y++) {
short[][] i1 = FaweCache.CACHE_J[y];
for (int x= 0; x < 16; x++) {
short[] i2 = i1[x];
for (int z = 0; z < 16; z++) {
char combinedId = array[i2[z]];
for (int z = 0; z < 16; z++) {
short[] i2 = i1[z];
for (int x= 0; x < 16; x++) {
char combinedId = array[i2[x]];
switch (combinedId) {
case 0:
IBlockData existing = nibble.a(x, y, z);

View File

@ -34,8 +34,8 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk> {
@Override
public void setBlock(int x, int y, int z, int id, int data) {
int i = FaweCache.CACHE_I[y][x][z];
int j = FaweCache.CACHE_J[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
int j = FaweCache.CACHE_J[y][z][x];
byte[] vs = this.byteIds[i];
char[] vs2 = this.ids[i];
if (vs2 == null) {

View File

@ -116,7 +116,7 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
public int getCombinedId4Data(ChunkSection ls, int x, int y, int z) {
byte[] ids = ls.getIdArray();
NibbleArray datasNibble = ls.getDataArray();
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
int combined = (ids[i] << 4) + (datasNibble == null ? 0 : datasNibble.a(x & 15, y & 15, z & 15));
return combined;
}
@ -174,12 +174,12 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
int x = ((int) Math.round(ent.locX) & 15);
int z = ((int) Math.round(ent.locZ) & 15);
int y = (int) Math.round(ent.locY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityTypes.b(ent);
if (id != null) {
@ -257,7 +257,7 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -309,12 +309,12 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
int lx = pos.x & 15;
int ly = pos.y;
int lz = pos.z & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
if (toRemove == null) {
toRemove = new HashMap<>();
@ -642,7 +642,7 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
@Override
public boolean hasBlock(ChunkSection section, int x, int y, int z) {
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
return section.getIdArray()[i] != 0;
}

View File

@ -115,7 +115,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
@Override
public int getCombinedId4Data(ChunkSection section, int x, int y, int z) {
char[] ls = section.getIdArray();
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
return ls[FaweCache.CACHE_J[y][z & 15][x & 15]];
}
@Override
@ -169,12 +169,12 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
int x = ((int) Math.round(ent.locX) & 15);
int z = ((int) Math.round(ent.locZ) & 15);
int y = (int) Math.round(ent.locY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityTypes.b(ent);
if (id != null) {
@ -254,7 +254,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -306,12 +306,12 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
if (toRemove == null) {
toRemove = new HashMap<>();
@ -634,7 +634,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
@Override
public boolean hasBlock(ChunkSection section, int x, int y, int z) {
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
return section.getIdArray()[i] != 0;
}

View File

@ -115,7 +115,7 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = blocks[FaweCache.CACHE_J[y][x][z]];
char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
if (combinedId > 1) {
palette.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
}

View File

@ -297,12 +297,12 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
if ((y < 0) || (y > 255)) {
return 1;
}
final int i = FaweCache.CACHE_I[y][x][z];
final int i = FaweCache.CACHE_I[y][z][x];
final char[] section = sections[i];
if (section == null) {
return 0;
}
final int j = FaweCache.CACHE_J[y][x][z];
final int j = FaweCache.CACHE_J[y][z][x];
return section[j] >> 4;
}
@ -401,12 +401,12 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
int x = ((int) Math.round(ent.locX) & 15);
int z = ((int) Math.round(ent.locZ) & 15);
int y = (int) Math.round(ent.locY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityTypes.b(ent);
if (id != null) {
@ -487,7 +487,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
if (array == null || y < 0 || y > 255) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -553,12 +553,12 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
if (toRemove == null) {
toRemove = new HashMap<>();
@ -620,7 +620,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = array[FaweCache.CACHE_J[y][x][z]];
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
switch (combinedId) {
case 0:
IBlockData existing = nibble.a(x, y, z);
@ -762,7 +762,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
lastBits = (DataBits) fieldBits.get(dataPaletteBlock);
lastBlocks = dataPaletteBlock;
}
int i = FaweCache.CACHE_J[y][x & 15][z & 15];
int i = FaweCache.CACHE_J[y][z & 15][x & 15];
return lastBits.a(i) != 0;
} catch (IllegalAccessException e) {
e.printStackTrace();

View File

@ -27,11 +27,11 @@ import java.util.Map;
public class FaweCache {
/**
* [ y | x | z ] => index
* [ y | z | x ] => index
*/
public final static short[][][] CACHE_I = new short[256][16][16];
/**
* [ y | x | z ] => index
* [ y | z | x ] => index
*/
public final static short[][][] CACHE_J = new short[256][16][16];
@ -128,8 +128,8 @@ public class FaweCache {
for (int y = 0; y < 256; y++) {
final short i = (short) (y >> 4);
final short j = (short) (((y & 0xF) << 8) | (z << 4) | x);
CACHE_I[y][x][z] = i;
CACHE_J[y][x][z] = j;
CACHE_I[y][z][x] = i;
CACHE_J[y][z][x] = j;
CACHE_X[i][j] = (byte) x;
CACHE_Y[i][j] = (short) y;
CACHE_Z[i][j] = (byte) z;
@ -622,9 +622,12 @@ public class FaweCache {
return asTag((Collection) value);
} else if (value instanceof byte[]) {
return asTag((byte[]) value);
} else if (value instanceof int[]) {
return asTag((int[]) value);
} else if (value instanceof Tag) {
return (Tag) value;
} else if (value == null) {
System.out.println("Invalid nbt: " + value);
return null;
} else {
Class<? extends Object> clazz = value.getClass();
@ -640,6 +643,7 @@ public class FaweCache {
e.printStackTrace();
}
}
System.out.println("Invalid nbt: " + value);
return null;
}
}

View File

@ -24,6 +24,12 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
public int[][] biomes;
private int bitMask = -1;
public HashMap<BytePair, CompoundTag> tiles;
public HashSet<CompoundTag> entities;
public HashSet<UUID> entityRemoves;
public T chunk;
/**
@ -139,16 +145,14 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
}
public int getCombinedId(int x, int y, int z) {
short i = FaweCache.CACHE_I[y][x][z];
short i = FaweCache.CACHE_I[y][z][x];
char[] array = getIdArray(i);
if (array == null) {
return 0;
}
return array[FaweCache.CACHE_J[y][x][z]];
return array[FaweCache.CACHE_J[y][z][x]];
}
public HashMap<BytePair, CompoundTag> tiles;
@Override
public void setTile(int x, int y, int z, CompoundTag tile) {
if (tiles == null) {
@ -181,12 +185,6 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
return entities == null ? new HashSet<CompoundTag>() : entities;
}
public HashSet<CompoundTag> entities;
public HashSet<UUID> entityRemoves;
@Override
public void setEntity(CompoundTag tag) {
if (entities == null) {
@ -210,8 +208,8 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
@Override
public void setBlock(int x, int y, int z, int id) {
final int i = FaweCache.CACHE_I[y][x][z];
final int j = FaweCache.CACHE_J[y][x][z];
final int i = FaweCache.CACHE_I[y][z][x];
final int j = FaweCache.CACHE_J[y][z][x];
char[] vs = this.ids[i];
if (vs == null) {
vs = this.ids[i] = new char[4096];
@ -249,8 +247,8 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
@Override
public void setBlock(final int x, final int y, final int z, final int id, int data) {
final int i = FaweCache.CACHE_I[y][x][z];
final int j = FaweCache.CACHE_J[y][x][z];
final int i = FaweCache.CACHE_I[y][z][x];
final int j = FaweCache.CACHE_J[y][z][x];
char[] vs = this.ids[i];
if (vs == null) {
vs = this.ids[i] = new char[4096];

View File

@ -0,0 +1,118 @@
package com.boydti.fawe.example;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MainUtil;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
public class DefaultFaweQueueMap implements IFaweQueueMap {
private final MappedFaweQueue parent;
public DefaultFaweQueueMap(MappedFaweQueue parent) {
this.parent = parent;
}
/**
* Map of chunks in the queue
*/
public ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
public ConcurrentLinkedDeque<FaweChunk> chunks = new ConcurrentLinkedDeque<FaweChunk>() {
@Override
public boolean add(FaweChunk o) {
if (parent.getProgressTask() != null) {
parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1);
}
return super.add(o);
}
};
@Override
public Collection<FaweChunk> getFaweCunks() {
return new HashSet<>(chunks);
}
@Override
public void forEachChunk(RunnableVal<FaweChunk> onEach) {
for (FaweChunk chunk : chunks) {
onEach.run(chunk);
}
}
@Override
public FaweChunk getFaweChunk(int cx, int cz) {
if (cx == lastX && cz == lastZ) {
return lastWrappedChunk;
}
long pair = (long) (lastX = cx) << 32 | (lastX = cz) & 0xFFFFFFFFL;
FaweChunk chunk = this.blocks.get(pair);
if (chunk == null) {
chunk = this.getNewFaweChunk(cx, cz);
FaweChunk previous = this.blocks.put(pair, chunk);
if (previous != null) {
blocks.put(pair, previous);
return previous;
}
this.blocks.put(pair, previous);
chunks.add(previous);
}
return chunk;
}
@Override
public void add(FaweChunk chunk) {
long pair = (long) (chunk.getX()) << 32 | (chunk.getZ()) & 0xFFFFFFFFL;
FaweChunk previous = this.blocks.put(pair, chunk);
if (previous == null) {
chunks.add(chunk);
} else {
blocks.put(pair, previous);
}
}
@Override
public void clear() {
blocks.clear();
chunks.clear();
}
@Override
public int size() {
return chunks.size();
}
private FaweChunk getNewFaweChunk(int cx, int cz) {
return parent.getFaweChunk(cx, cz);
}
private FaweChunk lastWrappedChunk;
private int lastX = Integer.MIN_VALUE;
private int lastZ = Integer.MIN_VALUE;
@Override
public boolean next() {
lastX = Integer.MIN_VALUE;
lastZ = Integer.MIN_VALUE;
try {
if (this.blocks.size() == 0) {
return false;
}
synchronized (blocks) {
FaweChunk chunk = chunks.poll();
if (chunk != null) {
blocks.remove(chunk.longHash());
parent.execute(chunk);
return true;
}
}
} catch (Throwable e) {
MainUtil.handleError(e);
}
return false;
}
}

View File

@ -0,0 +1,22 @@
package com.boydti.fawe.example;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.RunnableVal;
import java.util.Collection;
public interface IFaweQueueMap {
Collection<FaweChunk> getFaweCunks();
void forEachChunk(RunnableVal<FaweChunk> onEach);
FaweChunk getFaweChunk(int cx, int cz);
void add(FaweChunk chunk);
void clear();
int size();
boolean next();
}

View File

@ -19,48 +19,53 @@ import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
private WORLD impWorld;
/**
* Map of chunks in the queue
*/
public ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
public ConcurrentLinkedDeque<FaweChunk> chunks = new ConcurrentLinkedDeque<FaweChunk>() {
@Override
public boolean add(FaweChunk o) {
if (getProgressTask() != null) {
getProgressTask().run(ProgressType.QUEUE, size() + 1);
}
return super.add(o);
}
};
private IFaweQueueMap map;
public ArrayDeque<Runnable> tasks = new ArrayDeque<>();
public MappedFaweQueue(final String world) {
this(world, null);
}
public MappedFaweQueue(final String world, IFaweQueueMap map) {
super(world);
if (map == null) {
map = new DefaultFaweQueueMap(this);
}
this.map = map;
}
public IFaweQueueMap getFaweQueueMap() {
return map;
}
@Override
public Collection<FaweChunk> getFaweChunks() {
return Collections.unmodifiableCollection(chunks);
return map.getFaweCunks();
}
@Override
public void optimize() {
ArrayList<Thread> threads = new ArrayList<Thread>();
for (final FaweChunk chunk : chunks) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
chunk.optimize();
}
});
threads.add(thread);
thread.start();
}
final ArrayList<Thread> threads = new ArrayList<Thread>();
map.forEachChunk(new RunnableVal<FaweChunk>() {
@Override
public void run(final FaweChunk chunk) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
chunk.optimize();
}
});
threads.add(thread);
thread.start();
}
});
for (Thread thread : threads) {
try {
thread.join();
@ -76,10 +81,6 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
size();
}
public MappedFaweQueue(final String world) {
super(world);
}
public abstract WORLD getImpWorld();
public abstract boolean isChunkLoaded(WORLD world, int x, int z);
@ -114,50 +115,16 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
@Override
public void addNotifyTask(int x, int z, Runnable runnable) {
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
FaweChunk result = this.blocks.get(pair);
if (result == null) {
result = this.getFaweChunk(x, z);
result.addNotifyTask(runnable);
FaweChunk previous = this.blocks.put(pair, result);
if (previous == null) {
chunks.add(result);
return;
}
this.blocks.put(pair, previous);
result = previous;
}
result.addNotifyTask(runnable);
FaweChunk chunk = map.getFaweChunk(x, z);
chunk.addNotifyTask(runnable);
}
private FaweChunk lastWrappedChunk;
private int lastX = Integer.MIN_VALUE;
private int lastZ = Integer.MIN_VALUE;
@Override
public boolean setBlock(int x, int y, int z, int id, int data) {
int cx = x >> 4;
int cz = z >> 4;
if (cx != lastX || cz != lastZ) {
lastX = cx;
lastZ = cz;
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
lastWrappedChunk = this.blocks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = this.getFaweChunk(cx, cz);
lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data);
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
if (previous == null) {
chunks.add(lastWrappedChunk);
return true;
}
this.blocks.put(pair, previous);
lastWrappedChunk = previous;
}
}
lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data);
FaweChunk chunk = map.getFaweChunk(cx, cz);
chunk.setBlock(x & 15, y, z & 15, id, data);
return true;
}
@ -165,24 +132,8 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
public boolean setBlock(int x, int y, int z, int id) {
int cx = x >> 4;
int cz = z >> 4;
if (cx != lastX || cz != lastZ) {
lastX = cx;
lastZ = cz;
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
lastWrappedChunk = this.blocks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = this.getFaweChunk(x >> 4, z >> 4);
lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
if (previous == null) {
chunks.add(lastWrappedChunk);
return true;
}
this.blocks.put(pair, previous);
lastWrappedChunk = previous;
}
}
lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
FaweChunk chunk = map.getFaweChunk(cx, cz);
chunk.setBlock(x & 15, y, z & 15, id);
return true;
}
@ -193,24 +144,8 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
}
int cx = x >> 4;
int cz = z >> 4;
if (cx != lastX || cz != lastZ) {
lastX = cx;
lastZ = cz;
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
lastWrappedChunk = this.blocks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = this.getFaweChunk(x >> 4, z >> 4);
lastWrappedChunk.setTile(x & 15, y, z & 15, tag);
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
if (previous == null) {
chunks.add(lastWrappedChunk);
return;
}
this.blocks.put(pair, previous);
lastWrappedChunk = previous;
}
}
lastWrappedChunk.setTile(x & 15, y, z & 15, tag);
FaweChunk chunk = map.getFaweChunk(cx, cz);
chunk.setTile(x & 15, y, z & 15, tag);
}
@Override
@ -220,24 +155,8 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
}
int cx = x >> 4;
int cz = z >> 4;
if (cx != lastX || cz != lastZ) {
lastX = cx;
lastZ = cz;
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
lastWrappedChunk = this.blocks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = this.getFaweChunk(x >> 4, z >> 4);
lastWrappedChunk.setEntity(tag);
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
if (previous == null) {
chunks.add(lastWrappedChunk);
return;
}
this.blocks.put(pair, previous);
lastWrappedChunk = previous;
}
}
lastWrappedChunk.setEntity(tag);
FaweChunk chunk = map.getFaweChunk(cx, cz);
chunk.setEntity(tag);
}
@Override
@ -247,64 +166,22 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
}
int cx = x >> 4;
int cz = z >> 4;
if (cx != lastX || cz != lastZ) {
lastX = cx;
lastZ = cz;
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
lastWrappedChunk = this.blocks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = this.getFaweChunk(x >> 4, z >> 4);
lastWrappedChunk.removeEntity(uuid);
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
if (previous == null) {
chunks.add(lastWrappedChunk);
return;
}
this.blocks.put(pair, previous);
lastWrappedChunk = previous;
}
}
lastWrappedChunk.removeEntity(uuid);
FaweChunk chunk = map.getFaweChunk(cx, cz);
chunk.removeEntity(uuid);
}
@Override
public boolean setBiome(int x, int z, BaseBiome biome) {
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
FaweChunk result = this.blocks.get(pair);
if (result == null) {
result = this.getFaweChunk(x >> 4, z >> 4);
FaweChunk previous = this.blocks.put(pair, result);
if (previous != null) {
this.blocks.put(pair, previous);
result = previous;
} else {
chunks.add(result);
}
}
result.setBiome(x & 15, z & 15, biome);
int cx = x >> 4;
int cz = z >> 4;
FaweChunk chunk = map.getFaweChunk(cx, cz);
chunk.setBiome(x & 15, z & 15, biome);
return true;
}
@Override
public FaweChunk next() {
lastX = Integer.MIN_VALUE;
lastZ = Integer.MIN_VALUE;
try {
if (this.blocks.size() == 0) {
return null;
}
synchronized (blocks) {
FaweChunk chunk = chunks.poll();
if (chunk != null) {
blocks.remove(chunk.longHash());
this.execute(chunk);
return chunk;
}
}
} catch (Throwable e) {
MainUtil.handleError(e);
}
return null;
public boolean next() {
return map.next();
}
public void runTasks() {
@ -324,7 +201,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
@Override
public int size() {
int size = chunks.size();
int size = map.size();
if (size == 0 && SetQueue.IMP.getStage(this) != SetQueue.QueueStage.INACTIVE) {
runTasks();
}
@ -341,7 +218,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
}
// Set blocks / entities / biome
if (getProgressTask() != null) {
getProgressTask().run(ProgressType.QUEUE, chunks.size());
getProgressTask().run(ProgressType.QUEUE, map.size());
getProgressTask().run(ProgressType.DISPATCH, ++dispatched);
}
if (getChangeTask() != null) {
@ -362,18 +239,13 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
@Override
public void clear() {
this.blocks.clear();
this.chunks.clear();
map.clear();
runTasks();
}
@Override
public void setChunk(FaweChunk chunk) {
FaweChunk previous = this.blocks.put(chunk.longHash(), (FaweChunk) chunk);
if (previous != null) {
chunks.remove(previous);
}
chunks.add((FaweChunk) chunk);
map.add(chunk);
}
public int lastChunkX = Integer.MIN_VALUE;

View File

@ -16,6 +16,10 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
super(world);
}
public NMSMappedFaweQueue(String world, IFaweQueueMap map) {
super(world, map);
}
private NMSRelighter relighter;
@Override
@ -87,12 +91,12 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
if ((y < 0) || (y > 255)) {
return 1;
}
final int i = FaweCache.CACHE_I[y][x][z];
final int i = FaweCache.CACHE_I[y][z][x];
final char[] section = sections[i];
if (section == null) {
return 0;
}
final int j = FaweCache.CACHE_J[y][x][z];
final int j = FaweCache.CACHE_J[y][z][x];
return section[j] >> 4;
}

View File

@ -1,22 +0,0 @@
package com.boydti.fawe.jnbt;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.object.FaweQueue;
public class MCAChunk extends CharFaweChunk<Void> {
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*
* @param parent
* @param x
* @param z
*/
public MCAChunk(FaweQueue parent, int x, int z) {
super(parent, x, z);
}
@Override
public Void getNewChunk() {
return null;
}
}

View File

@ -1,146 +0,0 @@
package com.boydti.fawe.jnbt;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.RunnableVal3;
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.sk89q.jnbt.NBTInputStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
public class MCAFile {
private final File file;
private final BufferedRandomAccessFile raf;
public final byte[] locations;
private Field fieldBuf1;
private Field fieldBuf2;
private Field fieldBuf3;
private byte[] buffer1 = new byte[Settings.HISTORY.BUFFER_SIZE];
private byte[] buffer2 = new byte[Settings.HISTORY.BUFFER_SIZE];
private byte[] buffer3 = new byte[720];
public MCAFile(File file) throws Exception {
this.file = file;
if (!file.exists()) {
throw new FileNotFoundException(file.toString());
}
this.locations = new byte[4096];
this.raf = new BufferedRandomAccessFile(file, "rw", Settings.HISTORY.BUFFER_SIZE);
raf.read(locations);
fieldBuf1 = BufferedInputStream.class.getDeclaredField("buf");
fieldBuf1.setAccessible(true);
fieldBuf2 = InflaterInputStream.class.getDeclaredField("buf");
fieldBuf2.setAccessible(true);
fieldBuf3 = NBTInputStream.class.getDeclaredField("buf");
fieldBuf3.setAccessible(true);
}
public MCAFile(File regionFolder, int mcrX, int mcrZ) throws Exception {
this(new File(regionFolder, "r." + mcrX + "." + mcrZ + ".mca"));
}
/**
* @param onEach cx, cz, offset
*/
public void forEachChunk(RunnableVal3<Integer, Integer, Integer> onEach) {
int i = 0;
for (int z = 0; z < 32; z++) {
for (int x = 0; x < 32; x++, i += 4) {
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF)));
int size = locations[i + 3] & 0xFF;
if (size != 0) {
onEach.run(x, z, offset << 12);
}
}
}
}
public int getOffset(int cx, int cz) {
int i = (cx << 2) + (cz << 7);
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF)));
int size = locations[i + 3] & 0xFF;
return offset << 12;
}
private NBTStreamer getChunkReader(int offset) throws Exception {
raf.seek(offset);
int size = raf.readInt();
int compression = raf.readByte();
byte[] data = new byte[size];
raf.read(data);
ByteArrayInputStream bais = new ByteArrayInputStream(data);
InflaterInputStream iis = new InflaterInputStream(bais, new Inflater(), 1);
fieldBuf2.set(iis, buffer2);
BufferedInputStream bis = new BufferedInputStream(iis, 1);
fieldBuf1.set(bis, buffer1);
NBTInputStream nis = new NBTInputStream(bis);
fieldBuf3.set(nis, buffer3);
return new NBTStreamer(nis);
}
public int countId(int offset, final int id) throws Exception {
try {
NBTStreamer streamer = getChunkReader(offset);
NBTStreamer.ByteReader reader = new NBTStreamer.ByteReader() {
public int countId = id;
public int count = 0;
@Override
public void run(int index, int byteValue) {
if (byteValue == countId) {
count++;
}
}
};
streamer.addReader(".Level.Sections.#.Blocks.#", reader);
streamer.readFully();
return reader.getClass().getField("count").getInt(reader);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
public static void main(String[] args) throws Exception {
File folder = new File("../../mc/world/region");
long start = System.nanoTime();
final AtomicInteger count = new AtomicInteger();
final int id = 1;
for (File file : folder.listFiles()) {
// {
// File file = new File(folder, "r.0.0.mca");
System.out.println(file);
final MCAFile mca = new MCAFile(file);
mca.forEachChunk(new RunnableVal3<Integer, Integer, Integer>() {
@Override
public void run(Integer cx, Integer cz, Integer offset) {
try {
count.addAndGet(mca.countId(offset, id));
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
long diff = System.nanoTime() - start;
System.out.println(diff / 1000000d);
System.out.println("Count: " + count);
// My results
// 496,772,342 stone
// 35,164 chunks
// 17.175 seconds
}
}

View File

@ -0,0 +1,397 @@
package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class MCAChunk extends FaweChunk<Void> {
// ids: byte[16][4096]
// data: byte[16][2048]
// skylight: byte[16][2048]
// blocklight: byte[16][2048]
// entities: Map<BytePair, CompoundTag>
// tiles: List<CompoundTag>
// biomes: byte[256]
// compressedSize: int
// modified: boolean
// deleted: boolean
public byte[][] ids;
public byte[][] data;
public byte[][] skyLight;
public byte[][] blockLight;
public byte[] biomes;
public Map<BytePair, CompoundTag> tiles = new HashMap<>();
public Map<UUID, CompoundTag> entities = new HashMap<>();
private long inhabitedTime;
private long lastUpdate;
private int[] heightMap;
public int compressedSize;
private boolean modified;
private boolean deleted;
public CompoundTag toTag() {
if (deleted) {
return null;
}
// TODO optimize this as it's slow
// e.g. by precalculating the length
HashMap<String, Object> level = new HashMap<String, Object>();
level.put("Entities", new ListTag(CompoundTag.class, new ArrayList<CompoundTag>(entities.values())));
level.put("TileEntities", new ListTag(CompoundTag.class, new ArrayList<CompoundTag>(tiles.values())));
level.put("InhabitedTime", inhabitedTime);
level.put("LastUpdate", lastUpdate);
level.put("LightPopulated", (byte) 0);
level.put("TerrainPopulated", (byte) 1);
level.put("V", (byte) 1);
level.put("xPos", getX());
level.put("zPos", getZ());
if (biomes != null) {
level.put("Biomes", biomes);
}
level.put("HeightMap", heightMap);
ArrayList<HashMap<String, Object>> sections = new ArrayList<>();
for (int layer = 0; layer < ids.length; layer++) {
byte[] idLayer = ids[layer];
if (idLayer == null) {
continue;
}
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("Y", (byte) layer);
map.put("BlockLight", blockLight[layer]);
map.put("SkyLight", skyLight[layer]);
map.put("Blocks", idLayer);
map.put("Data", data[layer]);
sections.add(map);
}
level.put("Sections", sections);
HashMap<String, Object> root = new HashMap<>();
root.put("Level", level);
return FaweCache.asTag(root);
}
public MCAChunk(MCAChunk parent, boolean shallow) {
super(parent.getParent(), parent.getX(), parent.getZ());
if (shallow) {
this.ids = parent.ids;
this.data = parent.data;
this.skyLight = parent.skyLight;
this.blockLight = parent.blockLight;
this.biomes = parent.biomes;
this.tiles = parent.tiles;
this.entities = parent.entities;
this.inhabitedTime = parent.inhabitedTime;
this.lastUpdate = parent.lastUpdate;
this.heightMap = parent.heightMap;
this.compressedSize = parent.compressedSize;
this.modified = parent.modified;
this.deleted = parent.deleted;
} else {
this.ids = (byte[][]) MainUtil.copyNd(parent.ids);
this.data = (byte[][]) MainUtil.copyNd(parent.data);
this.skyLight = (byte[][]) MainUtil.copyNd(parent.skyLight);
this.blockLight = (byte[][]) MainUtil.copyNd(parent.blockLight);
this.biomes = parent.biomes.clone();
this.tiles = new HashMap<>(parent.tiles);
this.entities = new HashMap<>(parent.entities);
this.inhabitedTime = parent.inhabitedTime;
this.lastUpdate = parent.lastUpdate;
this.heightMap = parent.heightMap.clone();
this.compressedSize = parent.compressedSize;
this.modified = parent.modified;
this.deleted = parent.deleted;
}
}
public MCAChunk(NBTInputStream nis, FaweQueue parent, int x, int z, int compressedSize) throws IOException {
super(parent, x, z);
ids = new byte[16][];
data = new byte[16][];
skyLight = new byte[16][];
blockLight = new byte[16][];
this.compressedSize = compressedSize;
// NamedTag tag = nis.readNamedTag();
NBTStreamer streamer = new NBTStreamer(nis);
streamer.addReader(".Level.InhabitedTime", new RunnableVal2<Integer, Long>() {
@Override
public void run(Integer index, Long value) {
inhabitedTime = value;
}
});
streamer.addReader(".Level.LastUpdate", new RunnableVal2<Integer, Long>() {
@Override
public void run(Integer index, Long value) {
lastUpdate = value;
}
});
streamer.addReader(".Level.Sections.#", new RunnableVal2<Integer, CompoundTag>() {
@Override
public void run(Integer index, CompoundTag tag) {
int layer = tag.getByte("Y");
ids[layer] = tag.getByteArray("Blocks");
data[layer] = tag.getByteArray("Data");
skyLight[layer] = tag.getByteArray("SkyLight");
blockLight[layer] = tag.getByteArray("BlockLight");
}
});
streamer.addReader(".Level.Entities.#", new RunnableVal2<Integer, CompoundTag>() {
@Override
public void run(Integer index, CompoundTag tile) {
int x = tile.getInt("x") & 15;
int y = tile.getInt("y");
int z = tile.getInt("z") & 15;
byte i = MathMan.pair16((byte) x, (byte) z);
byte j = (byte) y;
BytePair pair = new BytePair(i, j);
tiles.put(pair, tile);
}
});
streamer.addReader(".Level.TileEntities.#", new RunnableVal2<Integer, CompoundTag>() {
@Override
public void run(Integer index, CompoundTag entityTag) {
if (entities == null) {
entities = new HashMap<UUID, CompoundTag>();
}
long least = entityTag.getLong("UUIDLeast");
long most = entityTag.getLong("UUIDMost");
entities.put(new UUID(most, least), entityTag);
}
});
streamer.addReader(".Level.Biomes", new RunnableVal2<Integer, byte[]>() {
@Override
public void run(Integer index, byte[] value) {
biomes = value;
}
});
streamer.addReader(".Level.HeightMap", new RunnableVal2<Integer, int[]>() {
@Override
public void run(Integer index, int[] value) {
heightMap = value;
}
});
streamer.readFully();
}
public boolean isModified() {
return modified;
}
@Override
public int getBitMask() {
int bitMask = 0;
for (int section = 0; section < ids.length; section++) {
if (ids[section] != null) {
bitMask += 1 << section;
}
}
return bitMask;
}
@Override
public void setTile(int x, int y, int z, CompoundTag tile) {
modified = true;
byte i = MathMan.pair16((byte) x, (byte) z);
byte j = (byte) y;
BytePair pair = new BytePair(i, j);
tiles.put(pair, tile);
}
@Override
public void setEntity(CompoundTag entityTag) {
modified = true;
long least = entityTag.getLong("UUIDLeast");
long most = entityTag.getLong("UUIDMost");
entities.put(new UUID(most, least), entityTag);
}
@Override
public void setBiome(int x, int z, BaseBiome biome) {
modified = true;
biomes[x + (z << 4)] = (byte) biome.getId();;
}
@Override
public Set<CompoundTag> getEntities() {
return new HashSet<>(entities.values());
}
@Override
public Map<BytePair, CompoundTag> getTiles() {
return tiles == null ? new HashMap<BytePair, CompoundTag>() : tiles;
}
@Override
public CompoundTag getTile(int x, int y, int z) {
if (tiles == null || tiles.isEmpty()) {
return null;
}
byte i = MathMan.pair16((byte) x, (byte) z);
byte j = (byte) y;
BytePair pair = new BytePair(i, j);
return tiles.get(pair);
}
public boolean doesSectionExist(int cy) {
return ids[cy] != null;
}
@Override
public FaweChunk<Void> copy(boolean shallow) {
return new MCAChunk(this, shallow);
}
@Override
public int getBlockCombinedId(int x, int y, int z) {
int layer = y >> 4;
byte[] idLayer = ids[layer];
if (idLayer == null) {
return 0;
}
int j = FaweCache.CACHE_J[y][z & 15][x & 15];
int id = idLayer[j];
if (FaweCache.hasData(id)) {
byte[] dataLayer = data[layer];
if (dataLayer != null) {
return (id << 4) + dataLayer[j];
}
}
return id << 4;
}
@Override
public Set<UUID> getEntityRemoves() {
return new HashSet<>();
}
public void setSkyLight(int x, int y, int z, int value) {
modified = true;
int layer = y >> 4;
byte[] skyLayer = skyLight[layer];
if (skyLayer == null) {
return;
}
int index = FaweCache.CACHE_J[y][z & 15][x & 15];
setNibble(index, skyLayer, value);
}
public void setBlockLight(int x, int y, int z, int value) {
modified = true;
int layer = y >> 4;
byte[] blockLayer = blockLight[layer];
if (blockLayer == null) {
return;
}
int index = FaweCache.CACHE_J[y][z & 15][x & 15];
setNibble(index, blockLayer, value);
}
public int getSkyLight(int x, int y, int z) {
modified = true;
int layer = y >> 4;
byte[] skyLayer = skyLight[layer];
if (skyLayer == null) {
return 0;
}
int index = FaweCache.CACHE_J[y][z & 15][x & 15];
return getNibble(index, skyLayer);
}
public int getBlockLight(int x, int y, int z) {
modified = true;
int layer = y >> 4;
byte[] blockLayer = blockLight[layer];
if (blockLayer == null) {
return 0;
}
int index = FaweCache.CACHE_J[y][z & 15][x & 15];
return getNibble(index, blockLayer);
}
public void setFullbright() {
modified = true;
for (byte[] array : skyLight) {
if (array != null) {
Arrays.fill(array, (byte) 255);
}
}
}
public void removeLight() {
for (int i = 0; i < skyLight.length; i++) {
byte[] array1 = skyLight[i];
if (array1 == null) {
continue;
}
byte[] array2 = blockLight[i];
Arrays.fill(array1, (byte) 0);
Arrays.fill(array2, (byte) 0);
}
}
private int getNibble(int index, byte[] array) {
int indexShift = index >> 1;
if((index & 1) == 0) {
return array[index] & 15;
} else {
return array[index] >> 4 & 15;
}
}
private void setNibble(int index, byte[] array, int value) {
int indexShift = index >> 1;
if((index & 1) == 0) {
array[indexShift] = (byte)(array[indexShift] & 240 | value & 15);
} else {
array[indexShift] = (byte)(array[indexShift] & 15 | (value & 15) << 4);
}
}
@Override
public void setBlock(int x, int y, int z, int id, int data) {
modified = true;
int layer = y >> 4;
byte[] idsLayer = ids[layer];
if (idsLayer == null) {
return;
}
int j = FaweCache.CACHE_J[y][z & 15][x & 15];
idsLayer[j] = (byte) id;
byte[] dataLayer = this.data[layer];
dataLayer[j] = (byte) data;
}
@Override
public void removeEntity(UUID uuid) {
modified = true;
entities.remove(uuid);
}
@Override
public Void getChunk() {
throw new UnsupportedOperationException("Not applicable for this");
}
@Override
public char[][] getCombinedIdArrays() {
throw new UnsupportedOperationException("Not applicable for this");
}
}

View File

@ -0,0 +1,347 @@
package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.RunnableVal4;
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
/**
* Chunk format: http://minecraft.gamepedia.com/Chunk_format#Entity_format
* e.g.: `.Level.Entities.#` (Starts with a . as the root tag is unnamed)
*/
public class MCAFile {
private final File file;
private final BufferedRandomAccessFile raf;
private final byte[] locations;
private final FaweQueue queue;
private Field fieldBuf1;
private Field fieldBuf2;
private Field fieldBuf3;
private Field fieldBuf4;
private Field fieldBuf5;
private Field fieldBuf6;
private byte[] buffer1 = new byte[Settings.HISTORY.BUFFER_SIZE];
private byte[] buffer2 = new byte[Settings.HISTORY.BUFFER_SIZE];
private byte[] buffer3 = new byte[720];
private Map<Integer, MCAChunk> chunks = new HashMap<>();
public MCAFile(FaweQueue parent, File file) throws Exception {
this.queue = parent;
this.file = file;
if (!file.exists()) {
throw new FileNotFoundException(file.toString());
}
this.locations = new byte[4096];
this.raf = new BufferedRandomAccessFile(file, "rw", Settings.HISTORY.BUFFER_SIZE);
raf.read(locations);
fieldBuf1 = BufferedInputStream.class.getDeclaredField("buf");
fieldBuf1.setAccessible(true);
fieldBuf2 = InflaterInputStream.class.getDeclaredField("buf");
fieldBuf2.setAccessible(true);
fieldBuf3 = NBTInputStream.class.getDeclaredField("buf");
fieldBuf3.setAccessible(true);
fieldBuf4 = ByteArrayOutputStream.class.getDeclaredField("buf");
fieldBuf4.setAccessible(true);
fieldBuf5 = DeflaterOutputStream.class.getDeclaredField("buf");
fieldBuf5.setAccessible(true);
fieldBuf6 = BufferedOutputStream.class.getDeclaredField("buf");
fieldBuf6.setAccessible(true);
}
public MCAFile(FaweQueue parent, int mcrX, int mcrZ) throws Exception {
this(parent, new File(parent.getSaveFolder(), "r." + mcrX + "." + mcrZ + ".mca"));
}
public MCAChunk getCachedChunk(int cx, int cz) {
int pair = MathMan.pair((short) (cx & 31), (short) (cz & 31));
return chunks.get(pair);
}
public MCAChunk getChunk(int cx, int cz) throws IOException {
MCAChunk cached = getCachedChunk(cx, cz);
if (cached != null) {
return cached;
} else {
return readChunk(cx, cz);
}
}
public MCAChunk readChunk(int cx, int cz) throws IOException {
int i = (cx << 2) + (cz << 7);
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF))) << 12;
int size = (locations[i + 3] & 0xFF) << 12;
NBTInputStream nis = getChunkIS(offset);
MCAChunk chunk = new MCAChunk(nis, queue, cx, cz, size);
int pair = MathMan.pair((short) (cx & 31), (short) (cz & 31));
chunks.put(pair, chunk);
return chunk;
}
/**
* @param onEach cx, cz, offset, size
*/
public void forEachChunk(RunnableVal4<Integer, Integer, Integer, Integer> onEach) {
int i = 0;
for (int z = 0; z < 32; z++) {
for (int x = 0; x < 32; x++, i += 4) {
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF)));
int size = locations[i + 3] & 0xFF;
if (size != 0) {
onEach.run(x, z, offset << 12, size << 12);
}
}
}
}
public int getOffset(int cx, int cz) {
int i = (cx << 2) + (cz << 7);
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF)));
return offset << 12;
}
public int getSize(int cx, int cz) {
int i = (cx << 2) + (cz << 7);
return (locations[i + 3] & 0xFF) << 12;
}
public List<Integer> getChunks() {
final List<Integer> values = new ArrayList<>(chunks.size());
for (int i = 0; i < locations.length; i+=4) {
int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i+ 2] & 0xFF)));
values.add(offset);
}
return values;
}
private byte[] getChunkCompressedBytes(int offset) throws IOException{
raf.seek(offset);
int size = raf.readInt();
int compression = raf.readByte();
byte[] data = new byte[size];
raf.read(data);
return data;
}
private void writeSafe(int offset, byte[] data) throws IOException {
int len = data.length + 5;
raf.seek(offset);
if (raf.length() - offset < len) {
raf.setLength(offset + len);
}
raf.writeInt(data.length);
raf.writeByte(2);
raf.write(data);
}
private NBTInputStream getChunkIS(int offset) throws IOException {
try {
byte[] data = getChunkCompressedBytes(offset);
ByteArrayInputStream bais = new ByteArrayInputStream(data);
InflaterInputStream iis = new InflaterInputStream(bais, new Inflater(), 1);
fieldBuf2.set(iis, buffer2);
BufferedInputStream bis = new BufferedInputStream(iis, 1);
fieldBuf1.set(bis, buffer1);
NBTInputStream nis = new NBTInputStream(bis);
fieldBuf3.set(nis, buffer3);
return nis;
} catch (IllegalAccessException unlikely) {
unlikely.printStackTrace();
return null;
}
}
public void streamChunk(int cx, int cz, RunnableVal<NBTStreamer> addReaders) throws IOException {
streamChunk(getOffset(cx, cz), addReaders);
}
public void streamChunk(int offset, RunnableVal<NBTStreamer> addReaders) throws IOException {
NBTInputStream is = getChunkIS(offset);
NBTStreamer ns = new NBTStreamer(is);
addReaders.run(ns);
ns.readFully();
}
/**
* @param onEach chunk
*/
public void forEachCachedChunk(RunnableVal<MCAChunk> onEach) {
for (Map.Entry<Integer, MCAChunk> entry : chunks.entrySet()) {
onEach.run(entry.getValue());
}
}
public List<MCAChunk> getCachedChunks() {
return new ArrayList<>(chunks.values());
}
private NBTStreamer getChunkReader(int offset) throws Exception {
return new NBTStreamer(getChunkIS(offset));
}
public void uncache(int cx, int cz) {
int pair = MathMan.pair((short) (cx & 31), (short) (cz & 31));
chunks.remove(pair);
}
private byte[] toBytes(MCAChunk chunk) throws Exception {
CompoundTag tag = chunk.toTag();
if (tag == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(0);
fieldBuf4.set(baos, buffer3);
DeflaterOutputStream deflater = new DeflaterOutputStream(baos, new Deflater(9), 1, true);
fieldBuf5.set(deflater, buffer2);
BufferedOutputStream bos = new BufferedOutputStream(deflater, 1);
fieldBuf6.set(bos, buffer1);
NBTOutputStream nos = new NBTOutputStream(bos);
nos.writeNamedTag("", tag);
bos.flush();
byte[] result = baos.toByteArray();
return result;
}
private byte[] getChunkBytes(int cx, int cz) throws Exception{
MCAChunk mca = getCachedChunk(cx, cz);
if (mca == null) {
int offset = getOffset(cx, cz);
if (offset == 0) {
return null;
}
return getChunkCompressedBytes(offset);
}
return toBytes(mca);
}
private void writeHeader(int cx, int cz, int offsetMedium, int sizeByte) throws IOException {
int i = (cx << 2) + (cz << 7);
raf.seek(i);
raf.write((offsetMedium >>> 16) & 0xFF);
raf.write((offsetMedium >>> 8) & 0xFF);
raf.write((offsetMedium >>> 0) & 0xFF);
raf.write(sizeByte);
}
public void flush() {
final HashMap<Integer, Integer> offsetMap = new HashMap<>(); // Offset -> <byte cx, byte cz, short size>
forEachChunk(new RunnableVal4<Integer, Integer, Integer, Integer>() {
@Override
public void run(Integer cx, Integer cz, Integer offset, Integer size) {
short pair1 = MathMan.pairByte((byte) (cx & 31), (byte) (cz & 31));
short pair2 = (short) (size >> 12);
offsetMap.put(offset, MathMan.pair(pair1, pair2));
}
});
HashMap<Integer, byte[]> relocate = new HashMap<Integer, byte[]>();
int start = 8192;
int end = 8192;
int nextOffset = 8192;
try {
for (int count = 0; count < offsetMap.size(); count++) {
int loc = offsetMap.get(nextOffset);
int offset = nextOffset;
short cxz = MathMan.unpairX(loc);
int cx = MathMan.unpairShortX(cxz);
int cz = MathMan.unpairShortY(cxz);
int size = MathMan.unpairY(loc) << 12;
nextOffset += size;
end += size;
int pair = MathMan.pair((short) (cx & 31), (short) (cz & 31));
byte[] newBytes = relocate.get(pair);
if (newBytes == null) {
if (offset == start) {
MCAChunk cached = getCachedChunk(cx, cz);
if (cached == null || !cached.isModified()) {
start += size;
continue;
} else {
newBytes = toBytes(cached);
}
} else {
newBytes = getChunkBytes(cx, cz);
}
}
if (newBytes == null) {
System.out.println("Deleting: " + cx + "," + cz);
// Don't write
continue;
}
int len = newBytes.length + 5;
int oldSize = (size + 4095) >> 12;
int newSize = (len + 4095) >> 12;
int nextOffset2 = nextOffset;
while (start + len > end) {
int nextLoc = offsetMap.get(nextOffset2);
short nextCXZ = MathMan.unpairX(nextLoc);
int nextCX = MathMan.unpairShortX(nextCXZ);
int nextCZ = MathMan.unpairShortY(nextCXZ);
if (getCachedChunk(nextCX, nextCZ) == null) {
byte[] nextBytes = getChunkCompressedBytes(nextOffset2);
relocate.put(pair, nextBytes);
}
System.out.println("Relocating " + nextCX + "," + nextCZ);
int nextSize = MathMan.unpairY(nextLoc) << 12;
end += nextSize;
nextOffset2 += nextSize;
}
System.out.println("Writing: " + cx + "," + cz);
writeSafe(start, newBytes);
if (offset != start || end != start + size) {
System.out.println("Header: " + cx + "," + cz + " | " + offset + "," + start + " | " + end + "," + (start + size) + " | " + size + " | " + start);
writeHeader(cx, cz, offset >> 12, newSize);
}
start += newSize << 12;
}
raf.flush();
} catch (Throwable e) {
e.printStackTrace();
}
// TODO write header
}
public static void main(String[] args) throws Exception {
// io benchmark
File folder = new File("../../mc/world/region");
long start = System.nanoTime();
final AtomicInteger count = new AtomicInteger();
final int id = 1;
// for (File file : folder.listFiles()) {
{ // Testing read/write
File file = new File(folder, "r.-2.-3.mca");
final MCAFile mca = new MCAFile(null, file);
MCAChunk chunk = mca.getChunk(29, 30);
System.out.println("Block ID: " + chunk.getBlockCombinedId(0, 0, 0));
chunk.setBlock(0,0,0, 5);
mca.flush();
}
long diff = System.nanoTime() - start;
System.out.println(diff / 1000000d); // Time diff
}
}

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.jnbt;
package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
@ -12,127 +12,139 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, MCAChunk, MCAChunk, char[]> {
public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, MCAChunk, MCAChunk, MCAChunk> {
private final FaweQueue parent;
public MCAQueue(FaweQueue parent) {
super(parent.getWorldName());
super(parent.getWorldName(), new MCAQueueMap());
this.parent = parent;
}
@Override
public void setFullbright(MCAChunk sections) {
}
@Override
public boolean removeLighting(MCAChunk sections, RelightMode mode, boolean hasSky) {
return false;
}
@Override
public void relight(int x, int y, int z) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public void relightBlock(int x, int y, int z) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public void relightSky(int x, int y, int z) {
}
@Override
public void setSkyLight(char[] chars, int x, int y, int z, int value) {
}
@Override
public void setBlockLight(char[] chars, int x, int y, int z, int value) {
}
@Override
public void refreshChunk(FaweChunk fs) {
}
@Override
public CharFaweChunk getPrevious(CharFaweChunk fs, MCAChunk sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
return null;
}
@Override
public CompoundTag getTileEntity(MCAChunk mcaChunk, int x, int y, int z) {
return null;
}
@Override
public MCAChunk getChunk(FaweQueue faweQueue, int x, int z) {
return null;
}
@Override
public FaweQueue getImpWorld() {
return null;
}
@Override
public boolean isChunkLoaded(FaweQueue faweQueue, int x, int z) {
return false;
throw new UnsupportedOperationException("Not supported");
}
@Override
public boolean regenerateChunk(FaweQueue faweQueue, int x, int z) {
return false;
throw new UnsupportedOperationException("Not supported");
}
@Override
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
throw new UnsupportedOperationException("Not supported");
}
@Override
public CharFaweChunk getPrevious(CharFaweChunk fs, MCAChunk sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
throw new UnsupportedOperationException("Not supported");
}
@Override
public MCAChunk getChunk(FaweQueue faweQueue, int x, int z) {
return (MCAChunk) getFaweChunk(x, z);
}
@Override
public FaweQueue getImpWorld() {
return parent;
}
@Override
public void setFullbright(MCAChunk sections) {
sections.setFullbright();
}
@Override
public boolean removeLighting(MCAChunk sections, RelightMode mode, boolean hasSky) {
if (mode != RelightMode.NONE) {
sections.removeLight();
return true;
}
return false;
}
@Override
public void setSkyLight(MCAChunk chars, int x, int y, int z, int value) {
chars.setSkyLight(x, y, z, value);
}
@Override
public void setBlockLight(MCAChunk chars, int x, int y, int z, int value) {
chars.setBlockLight(x, y, z, value);
}
@Override
public void refreshChunk(FaweChunk fs) {
// Nothing
}
@Override
public CompoundTag getTileEntity(MCAChunk mcaChunk, int x, int y, int z) {
return mcaChunk.getTile(x, y, z);
}
@Override
public boolean isChunkLoaded(FaweQueue faweQueue, int x, int z) {
return true;
}
@Override
public FaweChunk getFaweChunk(int x, int z) {
return null;
return getFaweQueueMap().getFaweChunk(x, z);
}
@Override
public File getSaveFolder() {
return null;
return parent.getSaveFolder();
}
@Override
public boolean hasSky() {
return false;
return parent.hasSky();
}
@Override
public boolean loadChunk(FaweQueue faweQueue, int x, int z, boolean generate) {
return false;
return true;
}
@Override
public MCAChunk getCachedSections(FaweQueue faweQueue, int cx, int cz) {
return (MCAChunk) getFaweQueueMap().getFaweChunk(cx, cz);
}
@Override
public MCAChunk getCachedSection(MCAChunk mcaChunk, int cy) {
if (mcaChunk.doesSectionExist(cy)) {
return mcaChunk;
}
return null;
}
@Override
public int getCombinedId4Data(char[] chars, int x, int y, int z) {
return 0;
public int getCombinedId4Data(MCAChunk chars, int x, int y, int z) {
return chars.getBlockCombinedId(x, y, z);
}
@Override
public int getSkyLight(char[] sections, int x, int y, int z) {
return 0;
public int getSkyLight(MCAChunk sections, int x, int y, int z) {
return sections.getSkyLight(x, y, z);
}
@Override
public int getEmmittedLight(char[] sections, int x, int y, int z) {
return 0;
public int getEmmittedLight(MCAChunk sections, int x, int y, int z) {
return sections.getBlockLight(x, y, z);
}
}

View File

@ -0,0 +1,45 @@
package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.example.IFaweQueueMap;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.RunnableVal;
import java.util.Collection;
public class MCAQueueMap implements IFaweQueueMap {
@Override
public Collection<FaweChunk> getFaweCunks() {
return null;
}
@Override
public void forEachChunk(RunnableVal<FaweChunk> onEach) {
}
@Override
public FaweChunk getFaweChunk(int cx, int cz) {
return null;
}
@Override
public void add(FaweChunk chunk) {
}
@Override
public void clear() {
}
@Override
public int size() {
return 0;
}
@Override
public boolean next() {
return false;
}
}

View File

@ -109,7 +109,7 @@ public abstract class FaweChunk<T> {
public int getBlockCombinedId(int x, int y, int z) {
char[][] arrays = getCombinedIdArrays();
char[] array = arrays[y >> 4];
return array != null ? (array[FaweCache.CACHE_J[y][x][z]]) : 0;
return array != null ? (array[FaweCache.CACHE_J[y][z][x]]) : 0;
}
/**

View File

@ -132,11 +132,11 @@ public abstract class FaweQueue {
public abstract boolean setBiome(final int x, final int z, final BaseBiome biome);
public abstract FaweChunk<?> getFaweChunk(int x, int z);
public abstract FaweChunk getFaweChunk(int x, int z);
public abstract Collection<FaweChunk> getFaweChunks();
public abstract void setChunk(final FaweChunk<?> chunk);
public abstract void setChunk(final FaweChunk chunk);
public abstract File getSaveFolder();
@ -219,7 +219,7 @@ public abstract class FaweQueue {
* Gets the FaweChunk and sets the requested blocks
* @return
*/
public abstract FaweChunk next();
public abstract boolean next();
public void saveMemory() {
MainUtil.sendAdmin(BBC.OOM.s());

View File

@ -0,0 +1,24 @@
package com.boydti.fawe.object;
public abstract class RunnableVal4<T, U, V, W> implements Runnable {
public T value1;
public U value2;
public V value3;
public W value4;
public RunnableVal4() {}
public RunnableVal4(T value1, U value2, V value3, W value4) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
this.value4 = value4;
}
@Override
public void run() {
run(value1, value2, value3, value4);
}
public abstract void run(T value1, U value2, V value3, W value4);
}

View File

@ -202,12 +202,12 @@ public abstract class FaweChangeSet implements ChangeSet {
for (int y = 0; y < 16; y++) {
short[][] i1 = FaweCache.CACHE_J[y];
int yy = y + startY;
for (int x = 0; x < 16; x++) {
int xx = x + bx;
short[] i2 = i1[x];
for (int z = 0; z < 16; z++) {
int zz = z + bz;
int index = i2[z];
for (int z = 0; z < 16; z++) {
int zz = z + bz;
short[] i2 = i1[z];
for (int x = 0; x < 16; x++) {
int xx = x + bx;
int index = i2[x];
int combinedIdCurrent = currentLayer[index];
switch (combinedIdCurrent) {
case 0:

View File

@ -1,6 +1,6 @@
package com.boydti.fawe.object.extent;
import com.boydti.fawe.jnbt.MCAFile;
import com.boydti.fawe.jnbt.anvil.MCAFile;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.Vector;

View File

@ -103,6 +103,9 @@ public class ProcessedWEExtent extends FaweRegionExtent {
return super.setBiome(position, biome);
} else if (!limit.MAX_FAILS()) {
WEManager.IMP.cancelEditSafe(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
return false;
} else {
return false;
}
}

View File

@ -26,7 +26,7 @@ public class FaweLocalBlockQueue extends LocalBlockQueue {
@Override
public boolean next() {
return IMP.next() != null;
return IMP.next();
}
@Override

View File

@ -130,7 +130,7 @@ public class DelegateFaweQueue extends FaweQueue {
}
@Override
public void setChunk(FaweChunk<?> chunk) {
public void setChunk(FaweChunk chunk) {
parent.setChunk(chunk);
}
@ -165,7 +165,7 @@ public class DelegateFaweQueue extends FaweQueue {
}
@Override
public FaweChunk next() {
public boolean next() {
return parent.next();
}

View File

@ -2,7 +2,6 @@ package com.boydti.fawe.util;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal2;
import java.util.ArrayList;
@ -42,8 +41,8 @@ public class SetQueue {
@Override
public void run(Long free, FaweQueue queue) {
do {
final FaweChunk<?> current = queue.next();
if (current == null) {
final boolean current = queue.next();
if (current == false) {
lastSuccess = last;
if (inactiveQueues.size() == 0 && activeQueues.size() == 0) {
runEmptyTasks();
@ -269,12 +268,12 @@ public class SetQueue {
return null;
}
public FaweChunk<?> next() {
public boolean next() {
while (activeQueues.size() > 0) {
FaweQueue queue = activeQueues.poll();
if (queue != null) {
final FaweChunk<?> set = queue.next();
if (set != null) {
final boolean set = queue.next();
if (set) {
activeQueues.add(queue);
return set;
}
@ -290,8 +289,8 @@ public class SetQueue {
long diff = now - lastSuccess;
if (diff > Settings.QUEUE.MAX_WAIT_MS) {
for (FaweQueue queue : tmp) {
FaweChunk result = queue.next();
if (result != null) {
boolean result = queue.next();
if (result) {
return result;
}
}
@ -299,7 +298,7 @@ public class SetQueue {
// These edits never finished
inactiveQueues.clear();
}
return null;
return false;
}
}
if (Settings.QUEUE.TARGET_SIZE != -1) {
@ -309,19 +308,19 @@ public class SetQueue {
}
if (total > Settings.QUEUE.TARGET_SIZE) {
for (FaweQueue queue : tmp) {
FaweChunk result = queue.next();
if (result != null) {
boolean result = queue.next();
if (result) {
return result;
}
}
}
}
}
return null;
return false;
}
public boolean forceChunkSet() {
return next() != null;
return next();
}
/**

View File

@ -315,7 +315,7 @@ public class LocalSession {
File file = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid + File.separator + "index");
if (getHistoryNegativeIndex() != 0) {
try {
if (file.exists()) {
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}

View File

@ -101,7 +101,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = blocks[FaweCache.CACHE_J[y][x][z]];
char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
if (combinedId > 1) {
palette.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
}

View File

@ -269,12 +269,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
@ -327,7 +327,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -372,12 +372,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
tile.getValue().invalidate();;
iterator.remove();
@ -428,7 +428,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = array[FaweCache.CACHE_J[y][x][z]];
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
switch (combinedId) {
case 0:
IBlockState existing = nibble.get(x, y, z);

View File

@ -35,8 +35,8 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
@Override
public void setBlock(int x, int y, int z, int id, int data) {
int i = FaweCache.CACHE_I[y][x][z];
int j = FaweCache.CACHE_J[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
int j = FaweCache.CACHE_J[y][z][x];
byte[] vs = this.byteIds[i];
char[] vs2 = this.ids[i];
if (vs2 == null) {

View File

@ -122,7 +122,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
public int getCombinedId4Data(ExtendedBlockStorage ls, int x, int y, int z) {
byte[] ids = ls.getBlockLSBArray();
NibbleArray datasNibble = ls.getBlockMSBArray();
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
int combined = (ids[i] << 4) + (datasNibble == null ? 0 : datasNibble.get(x & 15, y & 15, z & 15));
return combined;
}
@ -299,7 +299,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -344,12 +344,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int lx = pos.chunkPosX & 15;
int ly = pos.chunkPosY;
int lz = pos.chunkPosZ & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
tile.getValue().invalidate();;
iterator.remove();
@ -535,12 +535,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
@ -663,7 +663,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
@Override
public boolean hasBlock(ExtendedBlockStorage section, int x, int y, int z) {
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
return section.getBlockLSBArray()[i] != 0;
}

View File

@ -159,7 +159,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
@Override
public int getCombinedId4Data(ExtendedBlockStorage ls, int x, int y, int z) {
return ls.getData()[FaweCache.CACHE_J[y][x & 15][z & 15]];
return ls.getData()[FaweCache.CACHE_J[y][z & 15][x & 15]];
}
@Override
@ -219,12 +219,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
@ -276,7 +276,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -321,12 +321,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
tile.getValue().invalidate();;
iterator.remove();
@ -515,13 +515,13 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
if (y < 0 || y > 255) {
return 1;
}
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
ExtendedBlockStorage section = sections[i];
if (section == null) {
return 0;
}
char[] array = section.getData();
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
return array[j] >> 4;
}
@ -627,7 +627,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
@Override
public boolean hasBlock(ExtendedBlockStorage section, int x, int y, int z) {
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
return section.getData()[i] != 0;
}

View File

@ -101,7 +101,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = blocks[FaweCache.CACHE_J[y][x][z]];
char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
if (combinedId > 1) {
palette.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
}

View File

@ -269,12 +269,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
@ -327,7 +327,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -372,12 +372,12 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
tile.getValue().invalidate();;
iterator.remove();
@ -428,7 +428,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
char combinedId = array[FaweCache.CACHE_J[y][x][z]];
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
switch (combinedId) {
case 0:
IBlockState existing = nibble.get(x, y, z);

View File

@ -279,12 +279,12 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
@ -334,7 +334,7 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
if (array == null) {
continue;
}
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][x][z]] != 0) {
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
nmsWorld.removeEntity(entity);
}
}
@ -379,12 +379,12 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int j = FaweCache.CACHE_I[ly][lz][lx];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lz][lx];
if (array[k] != 0) {
tile.getValue().invalidate();
iterator.remove();
@ -642,13 +642,13 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
if (y < 0 || y > 255) {
return 1;
}
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
ExtendedBlockStorage section = sections[i];
if (section == null) {
return 0;
}
char[] array = section.getData();
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
return array[j] >> 4;
}
@ -673,7 +673,7 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
@Override
public int getCombinedId4Data(char[] chars, int x, int y, int z) {
return chars[FaweCache.CACHE_J[y][x & 15][z & 15]];
return chars[FaweCache.CACHE_J[y][z & 15][x & 15]];
}

View File

@ -250,12 +250,12 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
public BlockState map(UnmodifiableBlockVolume volume, int xx, int y, int zz) {
int x = xx & 15;
int z = zz & 15;
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
char[] array = ids[i];
if (array == null) {
return null;
}
int combinedId = array[FaweCache.CACHE_J[y][x][z]];
int combinedId = array[FaweCache.CACHE_J[y][z][x]];
switch (combinedId) {
case 0:
return null;
@ -421,13 +421,13 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
if (y < 0 || y > 255) {
return 1;
}
int i = FaweCache.CACHE_I[y][x][z];
int i = FaweCache.CACHE_I[y][z][x];
ExtendedBlockStorage section = sections[i];
if (section == null) {
return 0;
}
char[] array = section.getData();
int j = FaweCache.CACHE_J[y][x][z];
int j = FaweCache.CACHE_J[y][z][x];
return array[j] >> 4;
}
@ -453,6 +453,6 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
@Override
public int getCombinedId4Data(char[] chars, int x, int y, int z) {
return chars[FaweCache.CACHE_J[y][x & 15][z & 15]];
return chars[FaweCache.CACHE_J[y][z & 15][x & 15]];
}
}