geforkt von Mirrors/FastAsyncWorldEdit
implement block get
Dieser Commit ist enthalten in:
Ursprung
6692a2eb92
Commit
33e119ccb6
@ -10,7 +10,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
compile project(':worldedit-core')
|
||||
compile 'org.bukkit:craftbukkit-1.14:pre5'
|
||||
// compile 'org.bukkit:craftbukkit-1.14:pre5'
|
||||
compile 'net.milkbowl.vault:VaultAPI:1.7'
|
||||
compile 'com.sk89q:dummypermscompat:1.10'
|
||||
compile 'com.destroystokyo.paper:paper-api:1.13.2-R0.1-SNAPSHOT'
|
||||
|
@ -2,6 +2,9 @@ package com.boydti.fawe.bukkit;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.bukkit.beta.BukkitQueue;
|
||||
import com.boydti.fawe.bukkit.beta.BukkitQueueHandler;
|
||||
import com.boydti.fawe.bukkit.chat.BukkitChatManager;
|
||||
import com.boydti.fawe.bukkit.listener.AsyncTabCompleteListener;
|
||||
import com.boydti.fawe.bukkit.listener.BrushListener;
|
||||
@ -144,6 +147,11 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueHandler getQueueHandler() {
|
||||
return new BukkitQueueHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CUI getCUI(FawePlayer player) {
|
||||
if (Settings.IMP.EXPERIMENTAL.VANILLA_CUI) {
|
||||
|
@ -92,16 +92,16 @@ public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements Bukkit
|
||||
nbtCreateTagMethod.setAccessible(true);
|
||||
}
|
||||
|
||||
public int[] idbToStateOrdinal;
|
||||
public char[] idbToStateOrdinal;
|
||||
|
||||
private boolean init() {
|
||||
if (idbToStateOrdinal != null) return false;
|
||||
idbToStateOrdinal = new int[Block.REGISTRY_ID.a()]; // size
|
||||
idbToStateOrdinal = new char[Block.REGISTRY_ID.a()]; // size
|
||||
for (int i = 0; i < idbToStateOrdinal.length; i++) {
|
||||
BlockState state = BlockTypes.states[i];
|
||||
BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial();
|
||||
int id = Block.REGISTRY_ID.getId(material.getState());
|
||||
idbToStateOrdinal[id] = state.getOrdinal();
|
||||
idbToStateOrdinal[id] = state.getOrdinalChar();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -532,6 +532,16 @@ public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements Bukkit
|
||||
}
|
||||
}
|
||||
|
||||
public char adaptToChar(IBlockData ibd) {
|
||||
try {
|
||||
int id = Block.REGISTRY_ID.getId(ibd);
|
||||
return idbToStateOrdinal[id];
|
||||
} catch (NullPointerException e) {
|
||||
if (init()) return adaptToChar(ibd);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData adapt(BlockStateHolder state) {
|
||||
BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial();
|
||||
|
@ -2,23 +2,24 @@ package com.boydti.fawe.bukkit.beta;
|
||||
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.IGetBlocks;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
|
||||
|
||||
public class BukkitChunkHolder extends ChunkHolder<Boolean, BukkitQueue> {
|
||||
public class BukkitChunkHolder extends ChunkHolder<Boolean> {
|
||||
@Override
|
||||
public void init(final BukkitQueue extent, final int X, final int Z) {
|
||||
public void init(final IQueueExtent extent, final int X, final int Z) {
|
||||
super.init(extent, X, Z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGetBlocks get() {
|
||||
BukkitQueue extent = getExtent();
|
||||
return null;
|
||||
BukkitQueue extent = (BukkitQueue) getExtent();
|
||||
return new BukkitGetBlocks(extent.getNmsWorld(), getX(), getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply() {
|
||||
public boolean applyAsync() {
|
||||
BukkitGetBlocks get = (BukkitGetBlocks) cachedGet();
|
||||
CharSetBlocks set = (CharSetBlocks) cachedSet();
|
||||
// - getBlocks
|
||||
@ -37,10 +38,15 @@ public class BukkitChunkHolder extends ChunkHolder<Boolean, BukkitQueue> {
|
||||
// return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applySync() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Filter filter) {
|
||||
// for each block
|
||||
// filter.applyBlock(block)
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
}
|
||||
}
|
@ -16,8 +16,13 @@ public class BukkitFullChunk extends ChunkHolder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object apply() {
|
||||
return null;
|
||||
public boolean applyAsync() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applySync() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,8 +1,175 @@
|
||||
package com.boydti.fawe.bukkit.beta;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.bukkit.adapter.v1_13_1.Spigot_v1_13_R2;
|
||||
import com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13;
|
||||
import com.boydti.fawe.jnbt.anvil.BitArray4096;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import net.minecraft.server.v1_13_R2.Chunk;
|
||||
import net.minecraft.server.v1_13_R2.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_13_R2.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_13_R2.ChunkSection;
|
||||
import net.minecraft.server.v1_13_R2.DataBits;
|
||||
import net.minecraft.server.v1_13_R2.DataPalette;
|
||||
import net.minecraft.server.v1_13_R2.DataPaletteBlock;
|
||||
import net.minecraft.server.v1_13_R2.DataPaletteHash;
|
||||
import net.minecraft.server.v1_13_R2.DataPaletteLinear;
|
||||
import net.minecraft.server.v1_13_R2.IBlockData;
|
||||
import net.minecraft.server.v1_13_R2.World;
|
||||
|
||||
import static com.boydti.fawe.bukkit.v0.BukkitQueue_0.getAdapter;
|
||||
|
||||
public class BukkitGetBlocks extends CharGetBlocks {
|
||||
private ChunkSection[] sections;
|
||||
private Chunk nmsChunk;
|
||||
private World nmsWorld;
|
||||
private int X, Z;
|
||||
|
||||
public BukkitGetBlocks(World nmsWorld, int X, int Z) {/*d*/
|
||||
this.nmsWorld = nmsWorld;
|
||||
this.X = X;
|
||||
this.Z = Z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(int x, int z) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTag(int x, int y, int z) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char[] load(int layer) {
|
||||
return load(layer, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char[] load(int layer, char[] data) {
|
||||
ChunkSection section = getSections()[layer];
|
||||
// Section is null, return empty array
|
||||
if (section == null) {
|
||||
return FaweCache.EMPTY_CHAR_4096;
|
||||
}
|
||||
if (data == null || data == FaweCache.EMPTY_CHAR_4096) {
|
||||
data = new char[4096];
|
||||
}
|
||||
|
||||
// Efficiently convert ChunkSection to raw data
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
||||
final DataBits bits = (DataBits) BukkitQueue_1_13.fieldBits.get(blocks);
|
||||
final DataPalette<IBlockData> palette = (DataPalette<IBlockData>) BukkitQueue_1_13.fieldPalette.get(blocks);
|
||||
final int bitsPerEntry = bits.c();
|
||||
|
||||
final long[] blockStates = bits.a();
|
||||
new BitArray4096(blockStates, bitsPerEntry).toRaw(data);
|
||||
|
||||
int num_palette;
|
||||
if (palette instanceof DataPaletteLinear) {
|
||||
num_palette = ((DataPaletteLinear<IBlockData>) palette).b();
|
||||
} else if (palette instanceof DataPaletteHash) {
|
||||
num_palette = ((DataPaletteHash<IBlockData>) palette).b();
|
||||
} else {
|
||||
num_palette = 0;
|
||||
int[] paletteToBlockInts = FaweCache.PALETTE_TO_BLOCK.get();
|
||||
char[] paletteToBlockChars = FaweCache.PALETTE_TO_BLOCK_CHAR.get();
|
||||
try {
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char paletteVal = data[i];
|
||||
char ordinal = paletteToBlockChars[paletteVal];
|
||||
if (ordinal == Character.MAX_VALUE) {
|
||||
paletteToBlockInts[num_palette++] = paletteVal;
|
||||
IBlockData ibd = palette.a(data[i]);
|
||||
if (ibd == null) {
|
||||
ordinal = BlockTypes.AIR.getDefaultState().getOrdinalChar();
|
||||
} else {
|
||||
ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToChar(ibd);
|
||||
}
|
||||
paletteToBlockChars[paletteVal] = ordinal;
|
||||
}
|
||||
data[i] = ordinal;
|
||||
}
|
||||
} finally {
|
||||
for (int i = 0; i < num_palette; i++) {
|
||||
int paletteVal = paletteToBlockInts[i];
|
||||
paletteToBlockChars[paletteVal] = Character.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
char[] paletteToBlockChars = FaweCache.PALETTE_TO_BLOCK_CHAR.get();
|
||||
try {
|
||||
for (int i = 0; i < num_palette; i++) {
|
||||
IBlockData ibd = palette.a(i);
|
||||
char ordinal;
|
||||
if (ibd == null) {
|
||||
ordinal = BlockTypes.AIR.getDefaultState().getOrdinalChar();
|
||||
System.out.println("Invalid palette");
|
||||
} else {
|
||||
ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToChar(ibd);
|
||||
}
|
||||
paletteToBlockChars[i] = ordinal;
|
||||
}
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
char paletteVal = data[i];
|
||||
data[i] = paletteToBlockChars[paletteVal];
|
||||
}
|
||||
} finally {
|
||||
for (int i = 0; i < num_palette; i++) {
|
||||
paletteToBlockChars[i] = Character.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private ChunkSection[] getSections() {
|
||||
ChunkSection[] tmp = sections;
|
||||
if (tmp == null) {
|
||||
Chunk chunk = getChunk();
|
||||
sections = tmp = chunk.getSections();
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private Chunk getChunk() {
|
||||
Chunk tmp = nmsChunk;
|
||||
if (tmp == null) {
|
||||
ChunkProviderServer provider = (ChunkProviderServer) nmsWorld.getChunkProvider();
|
||||
nmsChunk = tmp = provider.chunks.get(ChunkCoordIntPair.a(X, Z));
|
||||
if (tmp == null) {
|
||||
System.out.println("SYNC");
|
||||
// TOOD load with paper
|
||||
nmsChunk = tmp = TaskManager.IMP.sync(() -> nmsWorld.getChunkAt(X, Z));
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return getSections()[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
if (aggressive) {
|
||||
sections = null;
|
||||
nmsChunk = null;
|
||||
}
|
||||
return super.trim(aggressive);
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,50 @@
|
||||
package com.boydti.fawe.bukkit.beta;
|
||||
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.implementation.SimpleCharQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
||||
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
||||
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import net.minecraft.server.v1_13_R2.WorldServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
|
||||
|
||||
public class BukkitQueue extends SingleThreadQueueExtent {
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class BukkitQueue extends SimpleCharQueueExtent {
|
||||
|
||||
private org.bukkit.World bukkitWorld;
|
||||
private WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public synchronized void init(WorldChunkCache cache) {
|
||||
World world = cache.getWorld();
|
||||
if (world instanceof BukkitWorld) {
|
||||
this.bukkitWorld = ((BukkitWorld) world).getWorld();
|
||||
} else {
|
||||
this.bukkitWorld = Bukkit.getWorld(world.getName());
|
||||
}
|
||||
checkNotNull(this.bukkitWorld);
|
||||
CraftWorld craftWorld = ((CraftWorld) bukkitWorld);
|
||||
this.nmsWorld = craftWorld.getHandle();
|
||||
super.init(cache);
|
||||
}
|
||||
|
||||
public WorldServer getNmsWorld() {
|
||||
return nmsWorld;
|
||||
}
|
||||
|
||||
public org.bukkit.World getBukkitWorld() {
|
||||
return bukkitWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void reset() {
|
||||
super.reset();
|
||||
}
|
||||
|
||||
private static final IterableThreadLocal<BukkitFullChunk> FULL_CHUNKS = new IterableThreadLocal<BukkitFullChunk>() {
|
||||
@Override
|
||||
public BukkitFullChunk init() {
|
||||
@ -24,9 +55,9 @@ public class BukkitQueue extends SingleThreadQueueExtent {
|
||||
@Override
|
||||
public IChunk create(boolean full) {
|
||||
if (full) {
|
||||
return FULL_CHUNKS.get();
|
||||
} else {
|
||||
return new BukkitChunkHolder();
|
||||
// TODO implement
|
||||
// return FULL_CHUNKS.get();
|
||||
}
|
||||
return new BukkitChunkHolder();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.boydti.fawe.bukkit.beta;
|
||||
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
|
||||
public class BukkitQueueHandler extends QueueHandler {
|
||||
@Override
|
||||
public IQueueExtent create() {
|
||||
return new BukkitQueue();
|
||||
}
|
||||
}
|
@ -68,8 +68,9 @@ import java.util.function.Supplier;
|
||||
|
||||
public class BukkitQueue_1_13 extends BukkitQueue_0<net.minecraft.server.v1_13_R2.Chunk, ChunkSection[], ChunkSection> {
|
||||
|
||||
protected final static Field fieldBits;
|
||||
protected final static Field fieldPalette;
|
||||
public final static Field fieldBits;
|
||||
public final static Field fieldPalette;
|
||||
|
||||
protected final static Field fieldSize;
|
||||
|
||||
protected final static Field fieldHashBlocks;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Commands;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -82,6 +83,8 @@ public class Fawe {
|
||||
private DefaultTransformParser transformParser;
|
||||
private ChatManager chatManager = new PlainChatManager();
|
||||
|
||||
private QueueHandler queueHandler;
|
||||
|
||||
/**
|
||||
* Get the implementation specific class
|
||||
*
|
||||
@ -199,6 +202,17 @@ public class Fawe {
|
||||
public void onDisable() {
|
||||
}
|
||||
|
||||
public QueueHandler getQueueHandler() {
|
||||
if (queueHandler == null) {
|
||||
synchronized (this) {
|
||||
if (queueHandler == null) {
|
||||
queueHandler = IMP.getQueueHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
return queueHandler;
|
||||
}
|
||||
|
||||
public CUI getCUI(Actor actor) {
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(actor);
|
||||
CUI cui = fp.getMeta("CUI");
|
||||
|
@ -13,6 +13,7 @@ import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
public class FaweCache implements Trimable {
|
||||
public static final char[] EMPTY_CHAR_4096 = new char[4096];
|
||||
|
||||
/*
|
||||
Palette buffers / cache
|
||||
@ -40,7 +41,16 @@ public class FaweCache implements Trimable {
|
||||
public static final IterableThreadLocal<int[]> PALETTE_TO_BLOCK = new IterableThreadLocal<int[]>() {
|
||||
@Override
|
||||
public int[] init() {
|
||||
return new int[Character.MAX_VALUE];
|
||||
return new int[Character.MAX_VALUE + 1];
|
||||
}
|
||||
};
|
||||
|
||||
public static final IterableThreadLocal<char[]> PALETTE_TO_BLOCK_CHAR = new IterableThreadLocal<char[]>() {
|
||||
@Override
|
||||
public char[] init() {
|
||||
char[] result = new char[Character.MAX_VALUE + 1];
|
||||
Arrays.fill(result, Character.MAX_VALUE);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@ -58,17 +68,10 @@ public class FaweCache implements Trimable {
|
||||
}
|
||||
};
|
||||
|
||||
public static Map<String, Object> asMap(Object... pairs) {
|
||||
HashMap<String, Object> map = new HashMap<>(pairs.length >> 1);
|
||||
for (int i = 0; i < pairs.length; i += 2) {
|
||||
String key = (String) pairs[i];
|
||||
Object value = pairs[i + 1];
|
||||
map.put(key, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static final class Palette {
|
||||
/**
|
||||
* Holds data for a palette used in a chunk section
|
||||
*/
|
||||
public static final class Palette {
|
||||
public int paletteToBlockLength;
|
||||
/**
|
||||
* Reusable buffer array, MUST check paletteToBlockLength for actual length
|
||||
@ -91,31 +94,31 @@ public class FaweCache implements Trimable {
|
||||
|
||||
/**
|
||||
* Convert raw char array to palette
|
||||
* @param layer
|
||||
* @param layerOffset
|
||||
* @param blocks
|
||||
* @return palette
|
||||
*/
|
||||
public static Palette toPalette(int layer, char[] blocks) {
|
||||
return toPalette(layer, null, blocks);
|
||||
public static Palette toPalette(int layerOffset, char[] blocks) {
|
||||
return toPalette(layerOffset, null, blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert raw int array to palette
|
||||
* @param layer
|
||||
* @param layerOffset
|
||||
* @param blocks
|
||||
* @return palette
|
||||
*/
|
||||
public static Palette toPalette(int layer, int[] blocks) {
|
||||
return toPalette(layer, blocks, null);
|
||||
public static Palette toPalette(int layerOffset, int[] blocks) {
|
||||
return toPalette(layerOffset, blocks, null);
|
||||
}
|
||||
|
||||
private static Palette toPalette(int layer, int[] blocksInts, char[] blocksChars) {
|
||||
private static Palette toPalette(int layerOffset, int[] blocksInts, char[] blocksChars) {
|
||||
int[] blockToPalette = BLOCK_TO_PALETTE.get();
|
||||
int[] paletteToBlock = PALETTE_TO_BLOCK.get();
|
||||
long[] blockstates = BLOCK_STATES.get();
|
||||
int[] blocksCopy = SECTION_BLOCKS.get();
|
||||
|
||||
int blockIndexStart = layer << 12;
|
||||
int blockIndexStart = layerOffset << 12;
|
||||
int blockIndexEnd = blockIndexStart + 4096;
|
||||
int num_palette = 0;
|
||||
try {
|
||||
@ -124,7 +127,7 @@ public class FaweCache implements Trimable {
|
||||
int ordinal = blocksChars[i];
|
||||
int palette = blockToPalette[ordinal];
|
||||
if (palette == Integer.MAX_VALUE) {
|
||||
BlockState state = BlockTypes.states[ordinal];
|
||||
// BlockState state = BlockTypes.states[ordinal];
|
||||
blockToPalette[ordinal] = palette = num_palette;
|
||||
paletteToBlock[num_palette] = ordinal;
|
||||
num_palette++;
|
||||
@ -183,6 +186,16 @@ public class FaweCache implements Trimable {
|
||||
Conversion methods between JNBT tags and raw values
|
||||
*/
|
||||
|
||||
public static Map<String, Object> asMap(Object... pairs) {
|
||||
HashMap<String, Object> map = new HashMap<>(pairs.length >> 1);
|
||||
for (int i = 0; i < pairs.length; i += 2) {
|
||||
String key = (String) pairs[i];
|
||||
Object value = pairs[i + 1];
|
||||
map.put(key, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static ShortTag asTag(short value) {
|
||||
return new ShortTag(value);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
@ -62,4 +63,6 @@ public interface IFawe {
|
||||
return "";
|
||||
}
|
||||
|
||||
QueueHandler getQueueHandler();
|
||||
|
||||
}
|
||||
|
249
worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java
Normale Datei
249
worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java
Normale Datei
@ -0,0 +1,249 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import static com.sk89q.worldedit.world.block.BlockTypes.states;
|
||||
public class CharFilterBlock implements FilterBlock {
|
||||
private IQueueExtent queue;
|
||||
private CharGetBlocks chunk;
|
||||
private char[] section;
|
||||
|
||||
@Override
|
||||
public void init(IQueueExtent queue) {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(int X, int Z, IGetBlocks chunk) {
|
||||
this.chunk = (CharGetBlocks) chunk;
|
||||
this.X = X;
|
||||
this.Z = Z;
|
||||
this.xx = X << 4;
|
||||
this.zz = Z << 4;
|
||||
}
|
||||
|
||||
public void init(char[] section, int layer) {
|
||||
this.section = section;
|
||||
this.layer = layer;
|
||||
this.yy = layer << 4;
|
||||
}
|
||||
|
||||
// local
|
||||
public int layer, index, x, y, z, xx, yy, zz, X, Z;
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return xx + x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getY() {
|
||||
return yy + y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return zz + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLocalX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLocalY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLocalZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkX() {
|
||||
return X;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkZ() {
|
||||
return Z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrdinal() {
|
||||
return section[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getState() {
|
||||
int ordinal = section[index];
|
||||
return BlockTypes.states[ordinal];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBaseBlock() {
|
||||
BlockState state = getState();
|
||||
BlockMaterial material = state.getMaterial();
|
||||
if (material.hasContainer()) {
|
||||
CompoundTag tag = chunk.getTag(x, y + (layer << 4), z);
|
||||
return state.toBaseBlock(tag);
|
||||
}
|
||||
return state.toBaseBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTag() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public BlockState getOrdinalBelow() {
|
||||
if (y > 0) {
|
||||
return states[section[index - 256]];
|
||||
}
|
||||
if (layer > 0) {
|
||||
final int newLayer = layer - 1;
|
||||
final CharGetBlocks chunk = this.chunk;
|
||||
return states[chunk.sections[newLayer].get(chunk, newLayer, index + 3840)];
|
||||
}
|
||||
return BlockTypes.__RESERVED__.getDefaultState();
|
||||
}
|
||||
|
||||
public BlockState getStateAbove() {
|
||||
if (y < 16) {
|
||||
return states[section[index + 256]];
|
||||
}
|
||||
if (layer < 16) {
|
||||
final int newLayer = layer + 1;
|
||||
final CharGetBlocks chunk = this.chunk;
|
||||
return states[chunk.sections[newLayer].get(chunk, newLayer, index - 3840)];
|
||||
}
|
||||
return BlockTypes.__RESERVED__.getDefaultState();
|
||||
}
|
||||
|
||||
public BlockState getStateRelativeY(int y) {
|
||||
int newY = this.y + y;
|
||||
int layerAdd = newY >> 4;
|
||||
switch (layerAdd) {
|
||||
case 0:
|
||||
return states[section[this.index + (y << 8)]];
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15: {
|
||||
int newLayer = layer + layerAdd;
|
||||
if (newLayer < 16) {
|
||||
int index = this.index + ((y & 15) << 8);
|
||||
return states[chunk.sections[newLayer].get(chunk, newLayer, index)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
case -2:
|
||||
case -3:
|
||||
case -4:
|
||||
case -5:
|
||||
case -6:
|
||||
case -7:
|
||||
case -8:
|
||||
case -9:
|
||||
case -10:
|
||||
case -11:
|
||||
case -12:
|
||||
case -13:
|
||||
case -14:
|
||||
case -15: {
|
||||
int newLayer = layer + layerAdd;
|
||||
if (newLayer >= 0) {
|
||||
int index = this.index + ((y & 15) << 8);
|
||||
return states[chunk.sections[newLayer].get(chunk, newLayer, index)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return BlockTypes.__RESERVED__.getDefaultState();
|
||||
}
|
||||
|
||||
public BlockState getStateRelative(final int x, final int y, final int z) {
|
||||
int newX = this.x + x;
|
||||
if (newX >> 4 == 0) {
|
||||
int newZ = this.z + z;
|
||||
if (newZ >> 4 == 0) {
|
||||
int newY = this.y + y;
|
||||
int layerAdd = newY >> 4;
|
||||
switch (layerAdd) {
|
||||
case 0:
|
||||
return states[section[this.index + ((y << 8) | (z << 4) | x)]];
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15: {
|
||||
int newLayer = layer + layerAdd;
|
||||
if (newLayer < 16) {
|
||||
int index = this.index + (((y & 15) << 8) | (z << 4) | x);
|
||||
return states[chunk.sections[newLayer].get(chunk, newLayer, index)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
case -2:
|
||||
case -3:
|
||||
case -4:
|
||||
case -5:
|
||||
case -6:
|
||||
case -7:
|
||||
case -8:
|
||||
case -9:
|
||||
case -10:
|
||||
case -11:
|
||||
case -12:
|
||||
case -13:
|
||||
case -14:
|
||||
case -15: {
|
||||
int newLayer = layer + layerAdd;
|
||||
if (newLayer >= 0) {
|
||||
int index = this.index + (((y & 15) << 8) | (z << 4) | x);
|
||||
return states[chunk.sections[newLayer].get(chunk, newLayer, index)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return BlockTypes.__RESERVED__.getDefaultState();
|
||||
}
|
||||
}
|
||||
// queue.get
|
||||
// TODO return normal get block
|
||||
int newY = this.y + y + yy;
|
||||
if (newY >= 0 && newY <= 256) {
|
||||
return queue.getBlock(xx + newX, newY, this.zz + this.z + z);
|
||||
}
|
||||
return BlockTypes.__RESERVED__.getDefaultState();
|
||||
}
|
||||
}
|
60
worldedit-core/src/main/java/com/boydti/fawe/beta/ChunkFuture.java
Normale Datei
60
worldedit-core/src/main/java/com/boydti/fawe/beta/ChunkFuture.java
Normale Datei
@ -0,0 +1,60 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class ChunkFuture implements Future<Void> {
|
||||
private final IChunk chunk;
|
||||
private volatile boolean cancelled;
|
||||
private volatile boolean done;
|
||||
|
||||
public ChunkFuture(IChunk chunk) {
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
public IChunk getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
cancelled = true;
|
||||
if (done) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get() throws InterruptedException, ExecutionException {
|
||||
synchronized (chunk) {
|
||||
if (!done) {
|
||||
this.wait();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
synchronized (chunk) {
|
||||
if (!done) {
|
||||
this.wait(unit.toMillis(timeout));
|
||||
if (!done) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -34,12 +34,9 @@ public interface Filter {
|
||||
* - e.g. block.setId(...)<br>
|
||||
* - Note: Performance is critical here<br>
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param block
|
||||
*/
|
||||
default void applyBlock(final int x, final int y, final int z, final BaseBlock block) {
|
||||
default void applyBlock(final FilterBlock block) {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,4 +56,8 @@ public interface Filter {
|
||||
default Filter fork() {
|
||||
return this;
|
||||
}
|
||||
|
||||
default void join(Filter parent) {
|
||||
|
||||
}
|
||||
}
|
||||
|
60
worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java
Normale Datei
60
worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java
Normale Datei
@ -0,0 +1,60 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
|
||||
public interface FilterBlock {
|
||||
void init(IQueueExtent queue);
|
||||
|
||||
void init(int X, int Z, IGetBlocks chunk);
|
||||
|
||||
int getOrdinal();
|
||||
|
||||
BlockState getState();
|
||||
|
||||
BaseBlock getBaseBlock();
|
||||
|
||||
CompoundTag getTag();
|
||||
|
||||
default BlockState getOrdinalBelow() {
|
||||
return getStateRelative(0, -1, 0);
|
||||
}
|
||||
|
||||
default BlockState getStateAbove() {
|
||||
return getStateRelative(0, 1, 0);
|
||||
}
|
||||
|
||||
default BlockState getStateRelativeY(int y) {
|
||||
return getStateRelative(0, y, 0);
|
||||
}
|
||||
|
||||
int getX();
|
||||
|
||||
int getY();
|
||||
|
||||
int getZ();
|
||||
|
||||
default int getLocalX() {
|
||||
return getX() & 15;
|
||||
}
|
||||
|
||||
default int getLocalY() {
|
||||
return getY() & 15;
|
||||
}
|
||||
|
||||
default int getLocalZ() {
|
||||
return getZ() & 15;
|
||||
}
|
||||
|
||||
default int getChunkX() {
|
||||
return getX() >> 4;
|
||||
}
|
||||
|
||||
default int getChunkZ() {
|
||||
return getZ() >> 4;
|
||||
}
|
||||
|
||||
BlockState getStateRelative(final int x, final int y, final int z);
|
||||
}
|
@ -3,6 +3,8 @@ package com.boydti.fawe.beta;
|
||||
/**
|
||||
* Shared interface for IGetBlocks and ISetBlocks
|
||||
*/
|
||||
public interface IBlocks {
|
||||
public interface IBlocks extends Trimable {
|
||||
boolean hasSection(int layer);
|
||||
|
||||
void reset();
|
||||
}
|
@ -8,17 +8,15 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
/**
|
||||
* Represents a chunk in the queue {@link IQueueExtent}
|
||||
* Used for getting and setting blocks / biomes / entities
|
||||
* @param <T> The result type (typically returns true when the chunk is applied)
|
||||
* @param <V> The IQueue class
|
||||
*/
|
||||
public interface IChunk<T, V extends IQueueExtent> extends Trimable {
|
||||
public interface IChunk extends Trimable {
|
||||
/**
|
||||
* Initialize at the location
|
||||
* @param extent
|
||||
* @param X
|
||||
* @param Z
|
||||
*/
|
||||
void init(V extent, int X, int Z);
|
||||
void init(IQueueExtent extent, int X, int Z);
|
||||
|
||||
int getX();
|
||||
|
||||
@ -38,10 +36,16 @@ public interface IChunk<T, V extends IQueueExtent> extends Trimable {
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Apply the queued changes to the world
|
||||
* @return
|
||||
* Apply the queued async changes to the world
|
||||
* @return false if applySync needs to run
|
||||
*/
|
||||
T apply();
|
||||
boolean applyAsync();
|
||||
|
||||
/**
|
||||
* Apply the queued sync changes to the world
|
||||
* @return true
|
||||
*/
|
||||
boolean applySync();
|
||||
|
||||
/* set - queues a change */
|
||||
boolean setBiome(int x, int y, int z, BiomeType biome);
|
||||
@ -60,4 +64,6 @@ public interface IChunk<T, V extends IQueueExtent> extends Trimable {
|
||||
BlockState getBlock(int x, int y, int z);
|
||||
|
||||
BaseBlock getFullBlock(int x, int y, int z);
|
||||
|
||||
void filter(Filter filter, FilterBlock mutable);
|
||||
}
|
||||
|
@ -7,11 +7,9 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
/**
|
||||
* Delegate for IChunk
|
||||
* @param <T> The result type (typically returns true when the chunk is applied)
|
||||
* @param <V> The IQueue class
|
||||
* @param <U> parent class
|
||||
*/
|
||||
public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V>> extends IChunk<T, V> {
|
||||
public interface IDelegateChunk<U extends IChunk> extends IChunk {
|
||||
U getParent();
|
||||
|
||||
default IChunk getRoot() {
|
||||
@ -48,7 +46,7 @@ public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V
|
||||
}
|
||||
|
||||
@Override
|
||||
default void init(final V extent, final int X, final int Z) {
|
||||
default void init(final IQueueExtent extent, final int X, final int Z) {
|
||||
getParent().init(extent, X, Z);
|
||||
}
|
||||
|
||||
@ -68,13 +66,19 @@ public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V
|
||||
return getParent().trim(aggressive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this chunk to the world
|
||||
* @return result T (typically a boolean)
|
||||
*/
|
||||
@Override
|
||||
default T apply() {
|
||||
return getParent().apply();
|
||||
default boolean applySync() {
|
||||
return getParent().applySync();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean applyAsync() {
|
||||
return getParent().applyAsync();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void filter(Filter filter, FilterBlock mutable) {
|
||||
getParent().filter(filter, mutable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,7 +21,7 @@ public interface IDelegateQueueExtent extends IQueueExtent {
|
||||
}
|
||||
|
||||
@Override
|
||||
default <T> Future<T> submit(IChunk<T, ?> chunk) {
|
||||
default Future<?> submit(IChunk chunk) {
|
||||
return getParent().submit(chunk);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
@ -14,6 +15,10 @@ public interface IGetBlocks extends IBlocks, Trimable {
|
||||
|
||||
BlockState getBlock(int x, int y, int z);
|
||||
|
||||
CompoundTag getTag(int x, int y, int z);
|
||||
|
||||
@Override
|
||||
boolean trim(boolean aggressive);
|
||||
|
||||
void filter(Filter filter, FilterBlock block);
|
||||
}
|
||||
|
@ -15,6 +15,12 @@ import java.util.concurrent.Future;
|
||||
public interface IQueueExtent extends Flushable, Trimable {
|
||||
void init(WorldChunkCache world);
|
||||
|
||||
/**
|
||||
* Get the {@link WorldChunkCache}
|
||||
* @return
|
||||
*/
|
||||
WorldChunkCache getCache();
|
||||
|
||||
/**
|
||||
* Get the IChunk at a position (and cache it if it's not already)
|
||||
* @param X
|
||||
@ -26,10 +32,9 @@ public interface IQueueExtent extends Flushable, Trimable {
|
||||
/**
|
||||
* Submit the chunk so that it's changes are applied to the world
|
||||
* @param chunk
|
||||
* @param <T> result type
|
||||
* @return result
|
||||
*/
|
||||
<T> Future<T> submit(IChunk<T, ?> chunk);
|
||||
Future<?> submit(IChunk chunk);
|
||||
|
||||
default boolean setBlock(final int x, final int y, final int z, final BlockStateHolder state) {
|
||||
final IChunk chunk = getCachedChunk(x >> 4, z >> 4);
|
||||
@ -75,4 +80,6 @@ public interface IQueueExtent extends Flushable, Trimable {
|
||||
*/
|
||||
@Override
|
||||
void flush();
|
||||
|
||||
FilterBlock initFilterBlock();
|
||||
}
|
@ -1,10 +1,17 @@
|
||||
package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.FilterBlock;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.Trimable;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
@ -12,6 +19,10 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Class which handles all the queues {@link IQueueExtent}
|
||||
@ -26,6 +37,17 @@ public abstract class QueueHandler implements Trimable {
|
||||
}
|
||||
};
|
||||
|
||||
public Future<?> submit(IChunk chunk) {
|
||||
if (Fawe.isMainThread()) {
|
||||
if (!chunk.applyAsync()) {
|
||||
chunk.applySync();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// TODO return future
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create the WorldChunkCache for a world
|
||||
* @param world
|
||||
@ -50,6 +72,12 @@ public abstract class QueueHandler implements Trimable {
|
||||
|
||||
public abstract IQueueExtent create();
|
||||
|
||||
public IQueueExtent getQueue(World world) {
|
||||
IQueueExtent queue = pool.get();
|
||||
queue.init(getOrCreate(world));
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(final boolean aggressive) {
|
||||
boolean result = true;
|
||||
@ -69,67 +97,68 @@ public abstract class QueueHandler implements Trimable {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void apply(final Region region, final Filter filter) { // TODO not MCAFilter, but another similar class
|
||||
// // The chunks positions to iterate over
|
||||
// final Set<BlockVector2> chunks = region.getChunks();
|
||||
// final Iterator<BlockVector2> chunksIter = chunks.iterator();
|
||||
//
|
||||
// // Get a pool, to operate on the chunks in parallel
|
||||
// final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
||||
// final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS);
|
||||
// final ForkJoinTask[] tasks = new ForkJoinTask[size];
|
||||
//
|
||||
// for (int i = 0; i < size; i++) {
|
||||
// tasks[i] = pool.submit(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// // Create a chunk that we will reuse/reset for each operation
|
||||
// IChunk chunk = create(true);
|
||||
//
|
||||
// while (true) {
|
||||
// // Get the next chunk pos
|
||||
// final BlockVector2 pos;
|
||||
// synchronized (chunksIter) {
|
||||
// if (!chunksIter.hasNext()) return;
|
||||
// pos = chunksIter.next();
|
||||
// }
|
||||
// final int X = pos.getX();
|
||||
// final int Z = pos.getZ();
|
||||
// final long pair = MathMan.pairInt(X, Z);
|
||||
//
|
||||
// // Initialize
|
||||
// chunk.init(SingleThreadQueueExtent.this, X, Z);
|
||||
//
|
||||
// { // Start set
|
||||
// lastPair = pair;
|
||||
// lastChunk = chunk;
|
||||
// }
|
||||
// try {
|
||||
// if (!filter.appliesChunk(X, Z)) {
|
||||
// continue;
|
||||
// }
|
||||
// chunk = filter.applyChunk(chunk);
|
||||
//
|
||||
// if (chunk == null) continue;
|
||||
//
|
||||
// chunk.filter(filter);
|
||||
//
|
||||
// filter.finishChunk(chunk);
|
||||
//
|
||||
// chunk.apply();
|
||||
// } finally
|
||||
// { // End set
|
||||
// lastPair = Long.MAX_VALUE;
|
||||
// lastChunk = null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// // Join the tasks
|
||||
// for (final ForkJoinTask task : tasks) {
|
||||
// task.join();
|
||||
// }
|
||||
public void apply(final World world, final Region region, final Filter filter) {
|
||||
// The chunks positions to iterate over
|
||||
final Set<BlockVector2> chunks = region.getChunks();
|
||||
final Iterator<BlockVector2> chunksIter = chunks.iterator();
|
||||
|
||||
// Get a pool, to operate on the chunks in parallel
|
||||
final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
||||
final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS);
|
||||
final ForkJoinTask[] tasks = new ForkJoinTask[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
tasks[i] = pool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Filter newFilter = filter.fork();
|
||||
// Create a chunk that we will reuse/reset for each operation
|
||||
IQueueExtent queue = getQueue(world);
|
||||
FilterBlock block = null;
|
||||
|
||||
while (true) {
|
||||
// Get the next chunk pos
|
||||
final BlockVector2 pos;
|
||||
synchronized (chunksIter) {
|
||||
if (!chunksIter.hasNext()) return;
|
||||
pos = chunksIter.next();
|
||||
}
|
||||
final int X = pos.getX();
|
||||
final int Z = pos.getZ();
|
||||
// TODO create full
|
||||
IChunk chunk = queue.getCachedChunk(X, Z);
|
||||
// Initialize
|
||||
chunk.init(queue, X, Z);
|
||||
try {
|
||||
if (!newFilter.appliesChunk(X, Z)) {
|
||||
continue;
|
||||
}
|
||||
chunk = newFilter.applyChunk(chunk);
|
||||
|
||||
if (chunk == null) continue;
|
||||
|
||||
if (block == null) block = queue.initFilterBlock();
|
||||
chunk.filter(newFilter, block);
|
||||
|
||||
newFilter.finishChunk(chunk);
|
||||
|
||||
queue.submit(chunk);
|
||||
} finally
|
||||
{
|
||||
if (filter != newFilter) {
|
||||
synchronized (filter) {
|
||||
newFilter.join(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Join the tasks
|
||||
for (final ForkJoinTask task : tasks) {
|
||||
task.join();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.beta.CharFilterBlock;
|
||||
import com.boydti.fawe.beta.FilterBlock;
|
||||
|
||||
public abstract class SimpleCharQueueExtent extends SingleThreadQueueExtent {
|
||||
@Override
|
||||
public FilterBlock initFilterBlock() {
|
||||
CharFilterBlock filter = new CharFilterBlock();
|
||||
filter.init(this);
|
||||
return filter;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.holder.ReferenceChunk;
|
||||
@ -12,8 +13,10 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -37,10 +40,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link WorldChunkCache}
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public WorldChunkCache getCache() {
|
||||
return cache;
|
||||
}
|
||||
@ -52,12 +52,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
||||
checkThread();
|
||||
cache = null;
|
||||
if (!chunks.isEmpty()) {
|
||||
for (IChunk chunk : chunks.values()) {
|
||||
chunk = chunk.getRoot();
|
||||
if (chunk != null) {
|
||||
CHUNK_POOL.add(chunk);
|
||||
}
|
||||
}
|
||||
CHUNK_POOL.addAll(chunks.values());
|
||||
chunks.clear();
|
||||
}
|
||||
lastChunk = null;
|
||||
@ -88,27 +83,19 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
||||
private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Override
|
||||
public <T> ForkJoinTask<T> submit(final IChunk<T, ?> chunk) {
|
||||
public Future<?> submit(final IChunk chunk) {
|
||||
if (chunk.isEmpty()) {
|
||||
CHUNK_POOL.add(chunk);
|
||||
return null;
|
||||
}
|
||||
// TODO use SetQueue to run in parallel
|
||||
final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
||||
return pool.submit(new Callable<T>() {
|
||||
@Override
|
||||
public T call() {
|
||||
IChunk<T, ?> tmp = chunk;
|
||||
|
||||
T result = tmp.apply();
|
||||
|
||||
tmp = tmp.getRoot();
|
||||
if (tmp != null) {
|
||||
CHUNK_POOL.add(tmp);
|
||||
}
|
||||
return result;
|
||||
if (Fawe.isMainThread()) {
|
||||
if (!chunk.applyAsync()) {
|
||||
chunk.applySync();
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
QueueHandler handler = Fawe.get().getQueueHandler();
|
||||
return handler.submit(chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -141,7 +128,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
||||
|
||||
@Override
|
||||
public final IChunk getCachedChunk(final int X, final int Z) {
|
||||
final long pair = MathMan.pairInt(X, Z);
|
||||
final long pair = (((long) X) << 32) | (Z & 0xffffffffL);
|
||||
if (pair == lastPair) {
|
||||
return lastChunk;
|
||||
}
|
||||
@ -178,14 +165,21 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
||||
public synchronized void flush() {
|
||||
checkThread();
|
||||
if (!chunks.isEmpty()) {
|
||||
final ForkJoinTask[] tasks = new ForkJoinTask[chunks.size()];
|
||||
final Future[] tasks = new ForkJoinTask[chunks.size()];
|
||||
int i = 0;
|
||||
for (final IChunk chunk : chunks.values()) {
|
||||
tasks[i++] = submit(chunk);
|
||||
}
|
||||
chunks.clear();
|
||||
for (final ForkJoinTask task : tasks) {
|
||||
if (task != null) task.join();
|
||||
for (final Future task : tasks) {
|
||||
if (task != null) {
|
||||
try {
|
||||
task.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reset();
|
||||
|
@ -3,5 +3,93 @@ package com.boydti.fawe.beta.implementation.blocks;
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
|
||||
public class CharBlocks implements IBlocks {
|
||||
protected char[][] blocks;
|
||||
public final char[][] blocks;
|
||||
public final Section[] sections;
|
||||
|
||||
public CharBlocks() {
|
||||
blocks = new char[16][];
|
||||
sections = new Section[16];
|
||||
for (int i = 0; i < 16; i++) sections[i] = NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
boolean result = true;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (sections[i] == NULL) {
|
||||
blocks[i] = null;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
for (int i = 0; i < 16; i++) sections[i] = NULL;
|
||||
}
|
||||
|
||||
protected char[] load(int layer) {
|
||||
return new char[4096];
|
||||
}
|
||||
|
||||
protected char[] load(int layer, char[] data) {
|
||||
for (int i = 0; i < 4096; i++) data[i] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return sections[layer] == FULL;
|
||||
}
|
||||
|
||||
public char get(int x, int y, int z) {
|
||||
int layer = y >> 4;
|
||||
int index = ((y & 15) << 8) | (z << 4) | (x & 15);
|
||||
return sections[layer].get(this, layer, index);
|
||||
}
|
||||
|
||||
public char set(int x, int y, int z, char value) {
|
||||
int layer = y >> 4;
|
||||
int index = ((y & 15) << 8) | (z << 4) | (x & 15);
|
||||
return sections[layer].set(this, layer, index, value);
|
||||
}
|
||||
|
||||
/*
|
||||
Section
|
||||
*/
|
||||
|
||||
public static abstract class Section {
|
||||
public abstract char[] get(CharBlocks blocks, int layer);
|
||||
|
||||
public final char get(CharBlocks blocks, int layer, int index) {
|
||||
return get(blocks, layer)[index];
|
||||
}
|
||||
|
||||
public final char set(CharBlocks blocks, int layer, int index, char value) {
|
||||
return get(blocks, layer)[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Section NULL = new Section() {
|
||||
@Override
|
||||
public final char[] get(CharBlocks blocks, int layer) {
|
||||
blocks.sections[layer] = FULL;
|
||||
char[] arr = blocks.blocks[layer];
|
||||
if (arr == null) {
|
||||
arr = blocks.blocks[layer] = blocks.load(layer);
|
||||
} else {
|
||||
blocks.blocks[layer] = blocks.load(layer, arr);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
};
|
||||
|
||||
public static final Section FULL = new Section() {
|
||||
@Override
|
||||
public final char[] get(CharBlocks blocks, int layer) {
|
||||
return blocks.blocks[layer];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,23 +1,52 @@
|
||||
package com.boydti.fawe.beta.implementation.blocks;
|
||||
|
||||
import com.boydti.fawe.beta.CharFilterBlock;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.FilterBlock;
|
||||
import com.boydti.fawe.beta.IGetBlocks;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
public class CharGetBlocks extends CharBlocks implements IGetBlocks {
|
||||
|
||||
public abstract class CharGetBlocks extends CharBlocks implements IGetBlocks {
|
||||
@Override
|
||||
public BaseBlock getFullBlock(final int x, final int y, final int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(final int x, final int z) {
|
||||
return BlockTypes.states[get(x, y, z)].toBaseBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(final int x, final int y, final int z) {
|
||||
return null;
|
||||
return BlockTypes.states[get(x, y, z)];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(Filter filter, FilterBlock block) {
|
||||
CharFilterBlock b = (CharFilterBlock) block;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (!hasSection(layer)) continue;
|
||||
char[] arr = sections[layer].get(this, layer);
|
||||
b.init(arr, layer);
|
||||
for (b.y = 0, b.index = 0; b.y < 16; b.y++) {
|
||||
for (b.z = 0; b.z < 16; b.z++) {
|
||||
for (b.x = 0; b.x < 16; b.x++, b.index++) {
|
||||
filter.applyBlock(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
sections[i] = NULL;
|
||||
blocks[i] = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
}
|
||||
}
|
@ -2,14 +2,48 @@ package com.boydti.fawe.beta.implementation.blocks;
|
||||
|
||||
import com.boydti.fawe.beta.ISetBlocks;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CharSetBlocks extends CharBlocks implements ISetBlocks {
|
||||
private byte[] biomes;
|
||||
private BiomeType[] biomes;
|
||||
private HashMap<Short, CompoundTag> tiles;
|
||||
private HashSet<CompoundTag> entities;
|
||||
private HashSet<UUID> entityRemoves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||
if (biomes == null) {
|
||||
biomes = new BiomeType[256];
|
||||
}
|
||||
biomes[x + (z << 4)] = biome;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BlockStateHolder holder) {
|
||||
set(x, y, z, holder.getOrdinalChar());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
if (biomes != null) return false;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (hasSection(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
biomes = null;
|
||||
super.reset();
|
||||
}
|
||||
}
|
@ -2,7 +2,23 @@ package com.boydti.fawe.beta.implementation.blocks;
|
||||
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
|
||||
// TODO implement
|
||||
public class FullCharBlocks implements IBlocks {
|
||||
public final boolean[] hasSections = new boolean[16];
|
||||
public final char[] blocks = new char[65536];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
package com.boydti.fawe.beta.implementation.holder;
|
||||
|
||||
import com.boydti.fawe.beta.CharFilterBlock;
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.FilterBlock;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
@ -18,11 +22,11 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* Abstract IChunk class that implements basic get/set blocks
|
||||
*/
|
||||
public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implements IChunk<T, V>, Supplier<IGetBlocks> {
|
||||
public abstract class ChunkHolder<T> implements IChunk, Supplier<IGetBlocks> {
|
||||
private IGetBlocks get;
|
||||
private ISetBlocks set;
|
||||
private IBlockDelegate delegate;
|
||||
private SingleThreadQueueExtent extent;
|
||||
private IQueueExtent extent;
|
||||
private int X,Z;
|
||||
|
||||
public ChunkHolder() {
|
||||
@ -33,6 +37,37 @@ public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implemen
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(Filter filter, FilterBlock block) {
|
||||
block.init(X, Z, get);
|
||||
IGetBlocks get = cachedGet();
|
||||
get.filter(filter, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
if (set != null) {
|
||||
boolean result = set.trim(aggressive);
|
||||
if (result) {
|
||||
delegate = NULL;
|
||||
get = null;
|
||||
set = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (aggressive) {
|
||||
get = null;
|
||||
if (delegate == BOTH) {
|
||||
delegate = SET;
|
||||
} else if (delegate == GET) {
|
||||
delegate = NULL;
|
||||
}
|
||||
} else {
|
||||
get.trim(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return set == null || set.isEmpty();
|
||||
@ -53,25 +88,29 @@ public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implemen
|
||||
}
|
||||
|
||||
private IGetBlocks newGet() {
|
||||
WorldChunkCache cache = extent.getCache();
|
||||
cache.get(MathMan.pairInt(X, Z), this);
|
||||
return new CharGetBlocks();
|
||||
if (extent instanceof SingleThreadQueueExtent) {
|
||||
WorldChunkCache cache = ((SingleThreadQueueExtent) extent).getCache();
|
||||
return cache.get(MathMan.pairInt(X, Z), this);
|
||||
}
|
||||
return get();
|
||||
}
|
||||
|
||||
public void init(final SingleThreadQueueExtent extent, final int X, final int Z) {
|
||||
@Override
|
||||
public void init(IQueueExtent extent, final int X, final int Z) {
|
||||
this.extent = extent;
|
||||
this.X = X;
|
||||
this.Z = Z;
|
||||
set = null;
|
||||
if (delegate == BOTH) {
|
||||
delegate = GET;
|
||||
} else if (delegate == SET) {
|
||||
if (set != null) {
|
||||
set.reset();
|
||||
delegate = SET;
|
||||
} else {
|
||||
delegate = NULL;
|
||||
}
|
||||
get = null;
|
||||
}
|
||||
|
||||
public V getExtent() {
|
||||
return (V) extent;
|
||||
public IQueueExtent getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,9 +22,10 @@ public class FinalizedChunk extends DelegateChunk {
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (getParent() != null) {
|
||||
apply();
|
||||
// TODO apply safely
|
||||
// apply();
|
||||
setParent(null);
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.boydti.fawe.beta.test;
|
||||
|
||||
import com.boydti.fawe.beta.Filter;
|
||||
import com.boydti.fawe.beta.FilterBlock;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.Countable;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CountFilter implements Filter {
|
||||
private int[] counter = new int[BlockTypes.states.length];
|
||||
|
||||
@Override
|
||||
public void applyBlock(FilterBlock block) {
|
||||
counter[block.getOrdinal()]++;
|
||||
}
|
||||
|
||||
public List<Countable<BlockState>> getDistribution() {
|
||||
List<Countable<BlockState>> distribution = new ArrayList<>();
|
||||
for (int i = 0; i < counter.length; i++) {
|
||||
int count = counter[i];
|
||||
if (count != 0) {
|
||||
distribution.add(new Countable<>(BlockTypes.states[i], count));
|
||||
}
|
||||
}
|
||||
Collections.sort(distribution);
|
||||
return distribution;
|
||||
}
|
||||
|
||||
public void print(Actor actor, long size) {
|
||||
for (Countable c : getDistribution()) {
|
||||
String name = c.getID().toString();
|
||||
String str = String.format("%-7s (%.3f%%) %s",
|
||||
String.valueOf(c.getAmount()),
|
||||
c.getAmount() / (double) size * 100,
|
||||
name);
|
||||
actor.print(BBC.getPrefix() + str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter fork() {
|
||||
return new CountFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void join(Filter parent) {
|
||||
CountFilter other = (CountFilter) parent;
|
||||
for (int i = 0; i < counter.length; i++) {
|
||||
other.counter[i] += this.counter[i];
|
||||
}
|
||||
}
|
||||
}
|
@ -159,4 +159,38 @@ public final class BitArray4096 {
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public final char[] toRaw(char[] buffer) {
|
||||
final long[] data = this.data;
|
||||
final int dataLength = longLen;
|
||||
final int bitsPerEntry = this.bitsPerEntry;
|
||||
final int maxEntryValue = this.maxEntryValue;
|
||||
final int maxSeqLocIndex = this.maxSeqLocIndex;
|
||||
|
||||
int localStart = 0;
|
||||
char lastVal;
|
||||
int arrI = 0;
|
||||
long l;
|
||||
for (int i = 0; i < dataLength; i++) {
|
||||
l = data[i];
|
||||
for (; localStart <= maxSeqLocIndex; localStart += bitsPerEntry) {
|
||||
lastVal = (char) (l >>> localStart & maxEntryValue);
|
||||
buffer[arrI++] = lastVal;
|
||||
}
|
||||
if (localStart < 64) {
|
||||
if (i != dataLength - 1) {
|
||||
lastVal = (char) (l >>> localStart);
|
||||
localStart -= maxSeqLocIndex;
|
||||
l = data[i + 1];
|
||||
int localShift = bitsPerEntry - localStart;
|
||||
lastVal |= l << localShift;
|
||||
lastVal &= maxEntryValue;
|
||||
buffer[arrI++] = lastVal;
|
||||
}
|
||||
} else {
|
||||
localStart = 0;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
}
|
@ -19,7 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
||||
import com.boydti.fawe.beta.test.CountFilter;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
@ -61,20 +66,25 @@ import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
|
||||
import com.sk89q.worldedit.math.noise.RandomNoise;
|
||||
import com.sk89q.worldedit.regions.*;
|
||||
import com.sk89q.worldedit.util.Countable;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.util.command.binding.Range;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.biome.Biomes;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@ -261,6 +271,19 @@ public class RegionCommands extends MethodCommands {
|
||||
BBC.VISITOR_BLOCK.send(player, blocksChanged);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"debugtest"},
|
||||
usage = "",
|
||||
desc = "debugtest",
|
||||
help = "debugtest"
|
||||
)
|
||||
public void debugtest(Player player, @Selection Region region) throws WorldEditException {
|
||||
QueueHandler queueHandler = Fawe.get().getQueueHandler();
|
||||
World world = player.getWorld();
|
||||
CountFilter filter = new CountFilter();
|
||||
queueHandler.apply(world, region, filter);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"/curve", "/spline"},
|
||||
usage = "<pattern> [thickness]",
|
||||
|
@ -710,7 +710,7 @@ public class SelectionCommands {
|
||||
distributionData = (List) editSession.getBlockDistributionWithData(region);
|
||||
else
|
||||
distributionData = (List) editSession.getBlockDistribution(region);
|
||||
size = session.getSelection(player.getWorld()).getArea();
|
||||
size = region.getArea();
|
||||
|
||||
if (distributionData.size() <= 0) {
|
||||
player.printError(BBC.getPrefix() + "No blocks counted.");
|
||||
|
@ -21,6 +21,8 @@ package com.sk89q.worldedit.command;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
||||
import com.boydti.fawe.command.FaweParser;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Commands;
|
||||
@ -70,6 +72,7 @@ import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
||||
|
@ -19,25 +19,23 @@
|
||||
|
||||
package com.sk89q.worldedit.world.block;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||
import com.sk89q.worldedit.blocks.TileEntityBlock;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.registry.state.PropertyKey;
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a "snapshot" of a block with NBT Data.
|
||||
*
|
||||
@ -84,7 +82,6 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
|
||||
*/
|
||||
|
||||
public BaseBlock(BlockState blockState) {
|
||||
// this(blockState, blockState.getNbtData());
|
||||
this.blockState = blockState;
|
||||
}
|
||||
|
||||
@ -210,7 +207,12 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock toBaseBlock() {
|
||||
public final char getOrdinalChar() {
|
||||
return blockState.getOrdinalChar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BaseBlock toBaseBlock() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ import java.util.stream.Stream;
|
||||
public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
||||
private final int internalId;
|
||||
private final int ordinal;
|
||||
private final char ordinalChar;
|
||||
private final BlockType blockType;
|
||||
private BlockMaterial material;
|
||||
private BaseBlock emptyBaseBlock;
|
||||
@ -60,6 +61,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
||||
this.blockType = blockType;
|
||||
this.internalId = internalId;
|
||||
this.ordinal = ordinal;
|
||||
this.ordinalChar = (char) ordinal;
|
||||
this.emptyBaseBlock = new BaseBlock(this);
|
||||
}
|
||||
|
||||
@ -285,7 +287,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock toBaseBlock() {
|
||||
public final BaseBlock toBaseBlock() {
|
||||
return this.emptyBaseBlock;
|
||||
}
|
||||
|
||||
@ -330,10 +332,15 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrdinal() {
|
||||
return this.ordinal;
|
||||
}
|
||||
@Override
|
||||
public int getOrdinal() {
|
||||
return this.ordinal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final char getOrdinalChar() {
|
||||
return this.ordinalChar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -63,6 +63,9 @@ public interface BlockStateHolder<B extends BlockStateHolder<B>> extends FawePat
|
||||
@Deprecated
|
||||
int getOrdinal();
|
||||
|
||||
@Deprecated
|
||||
char getOrdinalChar();
|
||||
|
||||
BlockMaterial getMaterial();
|
||||
/**
|
||||
* Get type id (legacy uses)
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren