mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 17:57:38 +00:00
implement block get
This commit is contained in:
parent
6692a2eb92
commit
33e119ccb6
@ -10,7 +10,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':worldedit-core')
|
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 'net.milkbowl.vault:VaultAPI:1.7'
|
||||||
compile 'com.sk89q:dummypermscompat:1.10'
|
compile 'com.sk89q:dummypermscompat:1.10'
|
||||||
compile 'com.destroystokyo.paper:paper-api:1.13.2-R0.1-SNAPSHOT'
|
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.Fawe;
|
||||||
import com.boydti.fawe.IFawe;
|
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.chat.BukkitChatManager;
|
||||||
import com.boydti.fawe.bukkit.listener.AsyncTabCompleteListener;
|
import com.boydti.fawe.bukkit.listener.AsyncTabCompleteListener;
|
||||||
import com.boydti.fawe.bukkit.listener.BrushListener;
|
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
|
@Override
|
||||||
public CUI getCUI(FawePlayer player) {
|
public CUI getCUI(FawePlayer player) {
|
||||||
if (Settings.IMP.EXPERIMENTAL.VANILLA_CUI) {
|
if (Settings.IMP.EXPERIMENTAL.VANILLA_CUI) {
|
||||||
|
@ -92,16 +92,16 @@ public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements Bukkit
|
|||||||
nbtCreateTagMethod.setAccessible(true);
|
nbtCreateTagMethod.setAccessible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] idbToStateOrdinal;
|
public char[] idbToStateOrdinal;
|
||||||
|
|
||||||
private boolean init() {
|
private boolean init() {
|
||||||
if (idbToStateOrdinal != null) return false;
|
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++) {
|
for (int i = 0; i < idbToStateOrdinal.length; i++) {
|
||||||
BlockState state = BlockTypes.states[i];
|
BlockState state = BlockTypes.states[i];
|
||||||
BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial();
|
BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial();
|
||||||
int id = Block.REGISTRY_ID.getId(material.getState());
|
int id = Block.REGISTRY_ID.getId(material.getState());
|
||||||
idbToStateOrdinal[id] = state.getOrdinal();
|
idbToStateOrdinal[id] = state.getOrdinalChar();
|
||||||
}
|
}
|
||||||
return true;
|
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
|
@Override
|
||||||
public BlockData adapt(BlockStateHolder state) {
|
public BlockData adapt(BlockStateHolder state) {
|
||||||
BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial();
|
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.Filter;
|
||||||
import com.boydti.fawe.beta.IGetBlocks;
|
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.blocks.CharSetBlocks;
|
||||||
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
|
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
|
||||||
|
|
||||||
public class BukkitChunkHolder extends ChunkHolder<Boolean, BukkitQueue> {
|
public class BukkitChunkHolder extends ChunkHolder<Boolean> {
|
||||||
@Override
|
@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);
|
super.init(extent, X, Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IGetBlocks get() {
|
public IGetBlocks get() {
|
||||||
BukkitQueue extent = getExtent();
|
BukkitQueue extent = (BukkitQueue) getExtent();
|
||||||
return null;
|
return new BukkitGetBlocks(extent.getNmsWorld(), getX(), getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean apply() {
|
public boolean applyAsync() {
|
||||||
BukkitGetBlocks get = (BukkitGetBlocks) cachedGet();
|
BukkitGetBlocks get = (BukkitGetBlocks) cachedGet();
|
||||||
CharSetBlocks set = (CharSetBlocks) cachedSet();
|
CharSetBlocks set = (CharSetBlocks) cachedSet();
|
||||||
// - getBlocks
|
// - getBlocks
|
||||||
@ -37,6 +38,11 @@ public class BukkitChunkHolder extends ChunkHolder<Boolean, BukkitQueue> {
|
|||||||
// return true;
|
// return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applySync() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(final Filter filter) {
|
public void set(final Filter filter) {
|
||||||
// for each block
|
// for each block
|
||||||
|
@ -16,8 +16,13 @@ public class BukkitFullChunk extends ChunkHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply() {
|
public boolean applyAsync() {
|
||||||
return null;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applySync() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,8 +1,175 @@
|
|||||||
package com.boydti.fawe.bukkit.beta;
|
package com.boydti.fawe.bukkit.beta;
|
||||||
|
|
||||||
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
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.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 {
|
public class BukkitGetBlocks extends CharGetBlocks {
|
||||||
private ChunkSection[] sections;
|
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;
|
package com.boydti.fawe.bukkit.beta;
|
||||||
|
|
||||||
import com.boydti.fawe.beta.IChunk;
|
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.SingleThreadQueueExtent;
|
||||||
import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
||||||
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
||||||
|
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||||
import com.sk89q.worldedit.world.World;
|
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
|
@Override
|
||||||
public synchronized void init(WorldChunkCache cache) {
|
public synchronized void init(WorldChunkCache cache) {
|
||||||
World world = cache.getWorld();
|
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);
|
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>() {
|
private static final IterableThreadLocal<BukkitFullChunk> FULL_CHUNKS = new IterableThreadLocal<BukkitFullChunk>() {
|
||||||
@Override
|
@Override
|
||||||
public BukkitFullChunk init() {
|
public BukkitFullChunk init() {
|
||||||
@ -24,9 +55,9 @@ public class BukkitQueue extends SingleThreadQueueExtent {
|
|||||||
@Override
|
@Override
|
||||||
public IChunk create(boolean full) {
|
public IChunk create(boolean full) {
|
||||||
if (full) {
|
if (full) {
|
||||||
return FULL_CHUNKS.get();
|
// TODO implement
|
||||||
} else {
|
// return FULL_CHUNKS.get();
|
||||||
|
}
|
||||||
return new BukkitChunkHolder();
|
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> {
|
public class BukkitQueue_1_13 extends BukkitQueue_0<net.minecraft.server.v1_13_R2.Chunk, ChunkSection[], ChunkSection> {
|
||||||
|
|
||||||
protected final static Field fieldBits;
|
public final static Field fieldBits;
|
||||||
protected final static Field fieldPalette;
|
public final static Field fieldPalette;
|
||||||
|
|
||||||
protected final static Field fieldSize;
|
protected final static Field fieldSize;
|
||||||
|
|
||||||
protected final static Field fieldHashBlocks;
|
protected final static Field fieldHashBlocks;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.boydti.fawe;
|
package com.boydti.fawe;
|
||||||
|
|
||||||
|
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.config.Commands;
|
import com.boydti.fawe.config.Commands;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
@ -82,6 +83,8 @@ public class Fawe {
|
|||||||
private DefaultTransformParser transformParser;
|
private DefaultTransformParser transformParser;
|
||||||
private ChatManager chatManager = new PlainChatManager();
|
private ChatManager chatManager = new PlainChatManager();
|
||||||
|
|
||||||
|
private QueueHandler queueHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the implementation specific class
|
* Get the implementation specific class
|
||||||
*
|
*
|
||||||
@ -199,6 +202,17 @@ public class Fawe {
|
|||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueueHandler getQueueHandler() {
|
||||||
|
if (queueHandler == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (queueHandler == null) {
|
||||||
|
queueHandler = IMP.getQueueHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return queueHandler;
|
||||||
|
}
|
||||||
|
|
||||||
public CUI getCUI(Actor actor) {
|
public CUI getCUI(Actor actor) {
|
||||||
FawePlayer<Object> fp = FawePlayer.wrap(actor);
|
FawePlayer<Object> fp = FawePlayer.wrap(actor);
|
||||||
CUI cui = fp.getMeta("CUI");
|
CUI cui = fp.getMeta("CUI");
|
||||||
|
@ -13,6 +13,7 @@ import java.lang.reflect.Field;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class FaweCache implements Trimable {
|
public class FaweCache implements Trimable {
|
||||||
|
public static final char[] EMPTY_CHAR_4096 = new char[4096];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Palette buffers / cache
|
Palette buffers / cache
|
||||||
@ -40,7 +41,16 @@ public class FaweCache implements Trimable {
|
|||||||
public static final IterableThreadLocal<int[]> PALETTE_TO_BLOCK = new IterableThreadLocal<int[]>() {
|
public static final IterableThreadLocal<int[]> PALETTE_TO_BLOCK = new IterableThreadLocal<int[]>() {
|
||||||
@Override
|
@Override
|
||||||
public int[] init() {
|
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);
|
* Holds data for a palette used in a chunk section
|
||||||
for (int i = 0; i < pairs.length; i += 2) {
|
*/
|
||||||
String key = (String) pairs[i];
|
public static final class Palette {
|
||||||
Object value = pairs[i + 1];
|
|
||||||
map.put(key, value);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class Palette {
|
|
||||||
public int paletteToBlockLength;
|
public int paletteToBlockLength;
|
||||||
/**
|
/**
|
||||||
* Reusable buffer array, MUST check paletteToBlockLength for actual length
|
* Reusable buffer array, MUST check paletteToBlockLength for actual length
|
||||||
@ -91,31 +94,31 @@ public class FaweCache implements Trimable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert raw char array to palette
|
* Convert raw char array to palette
|
||||||
* @param layer
|
* @param layerOffset
|
||||||
* @param blocks
|
* @param blocks
|
||||||
* @return palette
|
* @return palette
|
||||||
*/
|
*/
|
||||||
public static Palette toPalette(int layer, char[] blocks) {
|
public static Palette toPalette(int layerOffset, char[] blocks) {
|
||||||
return toPalette(layer, null, blocks);
|
return toPalette(layerOffset, null, blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert raw int array to palette
|
* Convert raw int array to palette
|
||||||
* @param layer
|
* @param layerOffset
|
||||||
* @param blocks
|
* @param blocks
|
||||||
* @return palette
|
* @return palette
|
||||||
*/
|
*/
|
||||||
public static Palette toPalette(int layer, int[] blocks) {
|
public static Palette toPalette(int layerOffset, int[] blocks) {
|
||||||
return toPalette(layer, blocks, null);
|
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[] blockToPalette = BLOCK_TO_PALETTE.get();
|
||||||
int[] paletteToBlock = PALETTE_TO_BLOCK.get();
|
int[] paletteToBlock = PALETTE_TO_BLOCK.get();
|
||||||
long[] blockstates = BLOCK_STATES.get();
|
long[] blockstates = BLOCK_STATES.get();
|
||||||
int[] blocksCopy = SECTION_BLOCKS.get();
|
int[] blocksCopy = SECTION_BLOCKS.get();
|
||||||
|
|
||||||
int blockIndexStart = layer << 12;
|
int blockIndexStart = layerOffset << 12;
|
||||||
int blockIndexEnd = blockIndexStart + 4096;
|
int blockIndexEnd = blockIndexStart + 4096;
|
||||||
int num_palette = 0;
|
int num_palette = 0;
|
||||||
try {
|
try {
|
||||||
@ -124,7 +127,7 @@ public class FaweCache implements Trimable {
|
|||||||
int ordinal = blocksChars[i];
|
int ordinal = blocksChars[i];
|
||||||
int palette = blockToPalette[ordinal];
|
int palette = blockToPalette[ordinal];
|
||||||
if (palette == Integer.MAX_VALUE) {
|
if (palette == Integer.MAX_VALUE) {
|
||||||
BlockState state = BlockTypes.states[ordinal];
|
// BlockState state = BlockTypes.states[ordinal];
|
||||||
blockToPalette[ordinal] = palette = num_palette;
|
blockToPalette[ordinal] = palette = num_palette;
|
||||||
paletteToBlock[num_palette] = ordinal;
|
paletteToBlock[num_palette] = ordinal;
|
||||||
num_palette++;
|
num_palette++;
|
||||||
@ -183,6 +186,16 @@ public class FaweCache implements Trimable {
|
|||||||
Conversion methods between JNBT tags and raw values
|
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) {
|
public static ShortTag asTag(short value) {
|
||||||
return new ShortTag(value);
|
return new ShortTag(value);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.boydti.fawe;
|
package com.boydti.fawe;
|
||||||
|
|
||||||
|
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||||
import com.boydti.fawe.object.FaweCommand;
|
import com.boydti.fawe.object.FaweCommand;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
@ -62,4 +63,6 @@ public interface IFawe {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueueHandler getQueueHandler();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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>
|
* - e.g. block.setId(...)<br>
|
||||||
* - Note: Performance is critical here<br>
|
* - Note: Performance is critical here<br>
|
||||||
*
|
*
|
||||||
* @param x
|
|
||||||
* @param y
|
|
||||||
* @param z
|
|
||||||
* @param block
|
* @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() {
|
default Filter fork() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void join(Filter parent) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
* 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}
|
* Represents a chunk in the queue {@link IQueueExtent}
|
||||||
* Used for getting and setting blocks / biomes / entities
|
* 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
|
* Initialize at the location
|
||||||
* @param extent
|
* @param extent
|
||||||
* @param X
|
* @param X
|
||||||
* @param Z
|
* @param Z
|
||||||
*/
|
*/
|
||||||
void init(V extent, int X, int Z);
|
void init(IQueueExtent extent, int X, int Z);
|
||||||
|
|
||||||
int getX();
|
int getX();
|
||||||
|
|
||||||
@ -38,10 +36,16 @@ public interface IChunk<T, V extends IQueueExtent> extends Trimable {
|
|||||||
boolean isEmpty();
|
boolean isEmpty();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the queued changes to the world
|
* Apply the queued async changes to the world
|
||||||
* @return
|
* @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 */
|
/* set - queues a change */
|
||||||
boolean setBiome(int x, int y, int z, BiomeType biome);
|
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);
|
BlockState getBlock(int x, int y, int z);
|
||||||
|
|
||||||
BaseBlock getFullBlock(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
|
* 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
|
* @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();
|
U getParent();
|
||||||
|
|
||||||
default IChunk getRoot() {
|
default IChunk getRoot() {
|
||||||
@ -48,7 +46,7 @@ public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
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);
|
return getParent().trim(aggressive);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply this chunk to the world
|
|
||||||
* @return result T (typically a boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
default T apply() {
|
default boolean applySync() {
|
||||||
return getParent().apply();
|
return getParent().applySync();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean applyAsync() {
|
||||||
|
return getParent().applyAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void filter(Filter filter, FilterBlock mutable) {
|
||||||
|
getParent().filter(filter, mutable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,7 +21,7 @@ public interface IDelegateQueueExtent extends IQueueExtent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default <T> Future<T> submit(IChunk<T, ?> chunk) {
|
default Future<?> submit(IChunk chunk) {
|
||||||
return getParent().submit(chunk);
|
return getParent().submit(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.boydti.fawe.beta;
|
package com.boydti.fawe.beta;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
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);
|
BlockState getBlock(int x, int y, int z);
|
||||||
|
|
||||||
|
CompoundTag getTag(int x, int y, int z);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean trim(boolean aggressive);
|
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 {
|
public interface IQueueExtent extends Flushable, Trimable {
|
||||||
void init(WorldChunkCache world);
|
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)
|
* Get the IChunk at a position (and cache it if it's not already)
|
||||||
* @param X
|
* @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
|
* Submit the chunk so that it's changes are applied to the world
|
||||||
* @param chunk
|
* @param chunk
|
||||||
* @param <T> result type
|
|
||||||
* @return result
|
* @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) {
|
default boolean setBlock(final int x, final int y, final int z, final BlockStateHolder state) {
|
||||||
final IChunk chunk = getCachedChunk(x >> 4, z >> 4);
|
final IChunk chunk = getCachedChunk(x >> 4, z >> 4);
|
||||||
@ -75,4 +80,6 @@ public interface IQueueExtent extends Flushable, Trimable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
|
FilterBlock initFilterBlock();
|
||||||
}
|
}
|
@ -1,10 +1,17 @@
|
|||||||
package com.boydti.fawe.beta.implementation;
|
package com.boydti.fawe.beta.implementation;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.beta.Filter;
|
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.IQueueExtent;
|
||||||
import com.boydti.fawe.beta.Trimable;
|
import com.boydti.fawe.beta.Trimable;
|
||||||
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
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.boydti.fawe.wrappers.WorldWrapper;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
@ -12,6 +19,10 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
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}
|
* 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
|
* Get or create the WorldChunkCache for a world
|
||||||
* @param world
|
* @param world
|
||||||
@ -50,6 +72,12 @@ public abstract class QueueHandler implements Trimable {
|
|||||||
|
|
||||||
public abstract IQueueExtent create();
|
public abstract IQueueExtent create();
|
||||||
|
|
||||||
|
public IQueueExtent getQueue(World world) {
|
||||||
|
IQueueExtent queue = pool.get();
|
||||||
|
queue.init(getOrCreate(world));
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean trim(final boolean aggressive) {
|
public boolean trim(final boolean aggressive) {
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
@ -69,67 +97,68 @@ public abstract class QueueHandler implements Trimable {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void apply(final Region region, final Filter filter) { // TODO not MCAFilter, but another similar class
|
public void apply(final World world, final Region region, final Filter filter) {
|
||||||
// // The chunks positions to iterate over
|
// The chunks positions to iterate over
|
||||||
// final Set<BlockVector2> chunks = region.getChunks();
|
final Set<BlockVector2> chunks = region.getChunks();
|
||||||
// final Iterator<BlockVector2> chunksIter = chunks.iterator();
|
final Iterator<BlockVector2> chunksIter = chunks.iterator();
|
||||||
//
|
|
||||||
// // Get a pool, to operate on the chunks in parallel
|
// Get a pool, to operate on the chunks in parallel
|
||||||
// final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
||||||
// final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS);
|
final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS);
|
||||||
// final ForkJoinTask[] tasks = new ForkJoinTask[size];
|
final ForkJoinTask[] tasks = new ForkJoinTask[size];
|
||||||
//
|
|
||||||
// for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
// tasks[i] = pool.submit(new Runnable() {
|
tasks[i] = pool.submit(new Runnable() {
|
||||||
// @Override
|
@Override
|
||||||
// public void run() {
|
public void run() {
|
||||||
// // Create a chunk that we will reuse/reset for each operation
|
Filter newFilter = filter.fork();
|
||||||
// IChunk chunk = create(true);
|
// Create a chunk that we will reuse/reset for each operation
|
||||||
//
|
IQueueExtent queue = getQueue(world);
|
||||||
// while (true) {
|
FilterBlock block = null;
|
||||||
// // Get the next chunk pos
|
|
||||||
// final BlockVector2 pos;
|
while (true) {
|
||||||
// synchronized (chunksIter) {
|
// Get the next chunk pos
|
||||||
// if (!chunksIter.hasNext()) return;
|
final BlockVector2 pos;
|
||||||
// pos = chunksIter.next();
|
synchronized (chunksIter) {
|
||||||
// }
|
if (!chunksIter.hasNext()) return;
|
||||||
// final int X = pos.getX();
|
pos = chunksIter.next();
|
||||||
// final int Z = pos.getZ();
|
}
|
||||||
// final long pair = MathMan.pairInt(X, Z);
|
final int X = pos.getX();
|
||||||
//
|
final int Z = pos.getZ();
|
||||||
// // Initialize
|
// TODO create full
|
||||||
// chunk.init(SingleThreadQueueExtent.this, X, Z);
|
IChunk chunk = queue.getCachedChunk(X, Z);
|
||||||
//
|
// Initialize
|
||||||
// { // Start set
|
chunk.init(queue, X, Z);
|
||||||
// lastPair = pair;
|
try {
|
||||||
// lastChunk = chunk;
|
if (!newFilter.appliesChunk(X, Z)) {
|
||||||
// }
|
continue;
|
||||||
// try {
|
}
|
||||||
// if (!filter.appliesChunk(X, Z)) {
|
chunk = newFilter.applyChunk(chunk);
|
||||||
// continue;
|
|
||||||
// }
|
if (chunk == null) continue;
|
||||||
// chunk = filter.applyChunk(chunk);
|
|
||||||
//
|
if (block == null) block = queue.initFilterBlock();
|
||||||
// if (chunk == null) continue;
|
chunk.filter(newFilter, block);
|
||||||
//
|
|
||||||
// chunk.filter(filter);
|
newFilter.finishChunk(chunk);
|
||||||
//
|
|
||||||
// filter.finishChunk(chunk);
|
queue.submit(chunk);
|
||||||
//
|
} finally
|
||||||
// chunk.apply();
|
{
|
||||||
// } finally
|
if (filter != newFilter) {
|
||||||
// { // End set
|
synchronized (filter) {
|
||||||
// lastPair = Long.MAX_VALUE;
|
newFilter.join(filter);
|
||||||
// lastChunk = null;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// });
|
}
|
||||||
// }
|
});
|
||||||
//
|
}
|
||||||
// // Join the tasks
|
|
||||||
// for (final ForkJoinTask task : tasks) {
|
// Join the tasks
|
||||||
// task.join();
|
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;
|
package com.boydti.fawe.beta.implementation;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.beta.IChunk;
|
import com.boydti.fawe.beta.IChunk;
|
||||||
import com.boydti.fawe.beta.IQueueExtent;
|
import com.boydti.fawe.beta.IQueueExtent;
|
||||||
import com.boydti.fawe.beta.implementation.holder.ReferenceChunk;
|
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.Callable;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.concurrent.ForkJoinTask;
|
import java.util.concurrent.ForkJoinTask;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -37,10 +40,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the {@link WorldChunkCache}
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public WorldChunkCache getCache() {
|
public WorldChunkCache getCache() {
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
@ -52,12 +52,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
checkThread();
|
checkThread();
|
||||||
cache = null;
|
cache = null;
|
||||||
if (!chunks.isEmpty()) {
|
if (!chunks.isEmpty()) {
|
||||||
for (IChunk chunk : chunks.values()) {
|
CHUNK_POOL.addAll(chunks.values());
|
||||||
chunk = chunk.getRoot();
|
|
||||||
if (chunk != null) {
|
|
||||||
CHUNK_POOL.add(chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chunks.clear();
|
chunks.clear();
|
||||||
}
|
}
|
||||||
lastChunk = null;
|
lastChunk = null;
|
||||||
@ -88,27 +83,19 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ForkJoinTask<T> submit(final IChunk<T, ?> chunk) {
|
public Future<?> submit(final IChunk chunk) {
|
||||||
if (chunk.isEmpty()) {
|
if (chunk.isEmpty()) {
|
||||||
CHUNK_POOL.add(chunk);
|
CHUNK_POOL.add(chunk);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// TODO use SetQueue to run in parallel
|
if (Fawe.isMainThread()) {
|
||||||
final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
if (!chunk.applyAsync()) {
|
||||||
return pool.submit(new Callable<T>() {
|
chunk.applySync();
|
||||||
@Override
|
|
||||||
public T call() {
|
|
||||||
IChunk<T, ?> tmp = chunk;
|
|
||||||
|
|
||||||
T result = tmp.apply();
|
|
||||||
|
|
||||||
tmp = tmp.getRoot();
|
|
||||||
if (tmp != null) {
|
|
||||||
CHUNK_POOL.add(tmp);
|
|
||||||
}
|
}
|
||||||
return result;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
QueueHandler handler = Fawe.get().getQueueHandler();
|
||||||
|
return handler.submit(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -141,7 +128,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final IChunk getCachedChunk(final int X, final int Z) {
|
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) {
|
if (pair == lastPair) {
|
||||||
return lastChunk;
|
return lastChunk;
|
||||||
}
|
}
|
||||||
@ -178,14 +165,21 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
public synchronized void flush() {
|
public synchronized void flush() {
|
||||||
checkThread();
|
checkThread();
|
||||||
if (!chunks.isEmpty()) {
|
if (!chunks.isEmpty()) {
|
||||||
final ForkJoinTask[] tasks = new ForkJoinTask[chunks.size()];
|
final Future[] tasks = new ForkJoinTask[chunks.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (final IChunk chunk : chunks.values()) {
|
for (final IChunk chunk : chunks.values()) {
|
||||||
tasks[i++] = submit(chunk);
|
tasks[i++] = submit(chunk);
|
||||||
}
|
}
|
||||||
chunks.clear();
|
chunks.clear();
|
||||||
for (final ForkJoinTask task : tasks) {
|
for (final Future task : tasks) {
|
||||||
if (task != null) task.join();
|
if (task != null) {
|
||||||
|
try {
|
||||||
|
task.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reset();
|
reset();
|
||||||
|
@ -3,5 +3,93 @@ package com.boydti.fawe.beta.implementation.blocks;
|
|||||||
import com.boydti.fawe.beta.IBlocks;
|
import com.boydti.fawe.beta.IBlocks;
|
||||||
|
|
||||||
public class CharBlocks implements 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;
|
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.boydti.fawe.beta.IGetBlocks;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
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
|
@Override
|
||||||
public BaseBlock getFullBlock(final int x, final int y, final int z) {
|
public BaseBlock getFullBlock(final int x, final int y, final int z) {
|
||||||
return null;
|
return BlockTypes.states[get(x, y, z)].toBaseBlock();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BiomeType getBiome(final int x, final int z) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(final int x, final int y, final int z) {
|
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.boydti.fawe.beta.ISetBlocks;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
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.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class CharSetBlocks extends CharBlocks implements ISetBlocks {
|
public class CharSetBlocks extends CharBlocks implements ISetBlocks {
|
||||||
private byte[] biomes;
|
private BiomeType[] biomes;
|
||||||
private HashMap<Short, CompoundTag> tiles;
|
private HashMap<Short, CompoundTag> tiles;
|
||||||
private HashSet<CompoundTag> entities;
|
private HashSet<CompoundTag> entities;
|
||||||
private HashSet<UUID> entityRemoves;
|
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;
|
import com.boydti.fawe.beta.IBlocks;
|
||||||
|
|
||||||
|
// TODO implement
|
||||||
public class FullCharBlocks implements IBlocks {
|
public class FullCharBlocks implements IBlocks {
|
||||||
public final boolean[] hasSections = new boolean[16];
|
public final boolean[] hasSections = new boolean[16];
|
||||||
public final char[] blocks = new char[65536];
|
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;
|
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.CharGetBlocks;
|
||||||
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
|
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
|
||||||
import com.boydti.fawe.beta.IChunk;
|
import com.boydti.fawe.beta.IChunk;
|
||||||
@ -18,11 +22,11 @@ import java.util.function.Supplier;
|
|||||||
/**
|
/**
|
||||||
* Abstract IChunk class that implements basic get/set blocks
|
* 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 IGetBlocks get;
|
||||||
private ISetBlocks set;
|
private ISetBlocks set;
|
||||||
private IBlockDelegate delegate;
|
private IBlockDelegate delegate;
|
||||||
private SingleThreadQueueExtent extent;
|
private IQueueExtent extent;
|
||||||
private int X,Z;
|
private int X,Z;
|
||||||
|
|
||||||
public ChunkHolder() {
|
public ChunkHolder() {
|
||||||
@ -33,6 +37,37 @@ public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implemen
|
|||||||
this.delegate = delegate;
|
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
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return set == null || set.isEmpty();
|
return set == null || set.isEmpty();
|
||||||
@ -53,25 +88,29 @@ public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IGetBlocks newGet() {
|
private IGetBlocks newGet() {
|
||||||
WorldChunkCache cache = extent.getCache();
|
if (extent instanceof SingleThreadQueueExtent) {
|
||||||
cache.get(MathMan.pairInt(X, Z), this);
|
WorldChunkCache cache = ((SingleThreadQueueExtent) extent).getCache();
|
||||||
return new CharGetBlocks();
|
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.extent = extent;
|
||||||
this.X = X;
|
this.X = X;
|
||||||
this.Z = Z;
|
this.Z = Z;
|
||||||
set = null;
|
if (set != null) {
|
||||||
if (delegate == BOTH) {
|
set.reset();
|
||||||
delegate = GET;
|
delegate = SET;
|
||||||
} else if (delegate == SET) {
|
} else {
|
||||||
delegate = NULL;
|
delegate = NULL;
|
||||||
}
|
}
|
||||||
|
get = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public V getExtent() {
|
public IQueueExtent getExtent() {
|
||||||
return (V) extent;
|
return extent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,7 +22,8 @@ public class FinalizedChunk extends DelegateChunk {
|
|||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
if (getParent() != null) {
|
if (getParent() != null) {
|
||||||
apply();
|
// TODO apply safely
|
||||||
|
// apply();
|
||||||
setParent(null);
|
setParent(null);
|
||||||
}
|
}
|
||||||
super.finalize();
|
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;
|
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;
|
package com.sk89q.worldedit.command;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.FaweAPI;
|
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.config.BBC;
|
||||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||||
import com.boydti.fawe.object.FaweLimit;
|
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.convolution.HeightMapFilter;
|
||||||
import com.sk89q.worldedit.math.noise.RandomNoise;
|
import com.sk89q.worldedit.math.noise.RandomNoise;
|
||||||
import com.sk89q.worldedit.regions.*;
|
import com.sk89q.worldedit.regions.*;
|
||||||
|
import com.sk89q.worldedit.util.Countable;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||||
import com.sk89q.worldedit.util.command.binding.Range;
|
import com.sk89q.worldedit.util.command.binding.Range;
|
||||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||||
import com.sk89q.worldedit.util.command.binding.Text;
|
import com.sk89q.worldedit.util.command.binding.Text;
|
||||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
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.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.biome.Biomes;
|
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.BlockStateHolder;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -261,6 +271,19 @@ public class RegionCommands extends MethodCommands {
|
|||||||
BBC.VISITOR_BLOCK.send(player, blocksChanged);
|
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(
|
@Command(
|
||||||
aliases = {"/curve", "/spline"},
|
aliases = {"/curve", "/spline"},
|
||||||
usage = "<pattern> [thickness]",
|
usage = "<pattern> [thickness]",
|
||||||
|
@ -710,7 +710,7 @@ public class SelectionCommands {
|
|||||||
distributionData = (List) editSession.getBlockDistributionWithData(region);
|
distributionData = (List) editSession.getBlockDistributionWithData(region);
|
||||||
else
|
else
|
||||||
distributionData = (List) editSession.getBlockDistribution(region);
|
distributionData = (List) editSession.getBlockDistribution(region);
|
||||||
size = session.getSelection(player.getWorld()).getArea();
|
size = region.getArea();
|
||||||
|
|
||||||
if (distributionData.size() <= 0) {
|
if (distributionData.size() <= 0) {
|
||||||
player.printError(BBC.getPrefix() + "No blocks counted.");
|
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.Fawe;
|
||||||
import com.boydti.fawe.FaweAPI;
|
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.command.FaweParser;
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.config.Commands;
|
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.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
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.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||||
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
||||||
|
@ -19,25 +19,23 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.world.block;
|
package com.sk89q.worldedit.world.block;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
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.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
import com.sk89q.worldedit.registry.state.Property;
|
||||||
import com.sk89q.worldedit.registry.state.PropertyKey;
|
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 javax.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a "snapshot" of a block with NBT Data.
|
* Represents a "snapshot" of a block with NBT Data.
|
||||||
*
|
*
|
||||||
@ -84,7 +82,6 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public BaseBlock(BlockState blockState) {
|
public BaseBlock(BlockState blockState) {
|
||||||
// this(blockState, blockState.getNbtData());
|
|
||||||
this.blockState = blockState;
|
this.blockState = blockState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +207,12 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseBlock toBaseBlock() {
|
public final char getOrdinalChar() {
|
||||||
|
return blockState.getOrdinalChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final BaseBlock toBaseBlock() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ import java.util.stream.Stream;
|
|||||||
public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
||||||
private final int internalId;
|
private final int internalId;
|
||||||
private final int ordinal;
|
private final int ordinal;
|
||||||
|
private final char ordinalChar;
|
||||||
private final BlockType blockType;
|
private final BlockType blockType;
|
||||||
private BlockMaterial material;
|
private BlockMaterial material;
|
||||||
private BaseBlock emptyBaseBlock;
|
private BaseBlock emptyBaseBlock;
|
||||||
@ -60,6 +61,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
|||||||
this.blockType = blockType;
|
this.blockType = blockType;
|
||||||
this.internalId = internalId;
|
this.internalId = internalId;
|
||||||
this.ordinal = ordinal;
|
this.ordinal = ordinal;
|
||||||
|
this.ordinalChar = (char) ordinal;
|
||||||
this.emptyBaseBlock = new BaseBlock(this);
|
this.emptyBaseBlock = new BaseBlock(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +287,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseBlock toBaseBlock() {
|
public final BaseBlock toBaseBlock() {
|
||||||
return this.emptyBaseBlock;
|
return this.emptyBaseBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,6 +337,11 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
|
|||||||
return this.ordinal;
|
return this.ordinal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final char getOrdinalChar() {
|
||||||
|
return this.ordinalChar;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getAsString();
|
return getAsString();
|
||||||
|
@ -63,6 +63,9 @@ public interface BlockStateHolder<B extends BlockStateHolder<B>> extends FawePat
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
int getOrdinal();
|
int getOrdinal();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
char getOrdinalChar();
|
||||||
|
|
||||||
BlockMaterial getMaterial();
|
BlockMaterial getMaterial();
|
||||||
/**
|
/**
|
||||||
* Get type id (legacy uses)
|
* Get type id (legacy uses)
|
||||||
|
Loading…
Reference in New Issue
Block a user