WIP filter patterns

This commit is contained in:
Jesse Boyd 2019-05-12 23:32:04 +10:00
parent 459629a2f2
commit c797dcb194
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
61 changed files with 2075 additions and 793 deletions

View File

@ -1,10 +1,9 @@
package com.boydti.fawe.bukkit.beta;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IGetBlocks;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.ISetBlocks;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.implementation.QueueHandler;
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
@ -49,7 +48,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
}
@Override
public IGetBlocks get() {
public IChunkGet get() {
BukkitQueue extent = (BukkitQueue) getExtent();
return new BukkitGetBlocks(extent.getNmsWorld(), getX(), getZ());
}
@ -78,7 +77,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
int Z = getZ();
BukkitQueue extent = (BukkitQueue) getExtent();
BukkitGetBlocks get = (BukkitGetBlocks) getOrCreateGet();
ISetBlocks set = getOrCreateSet();
IChunkSet set = getOrCreateSet();
Chunk nmsChunk = extent.ensureLoaded(X, Z);

View File

@ -13,7 +13,9 @@ import com.boydti.fawe.object.collection.IterableThreadLocal;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockID;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;

View File

@ -1,94 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.blocks;
import static com.google.common.base.Preconditions.checkNotNull;
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.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
/**
* A implementation of a lazy block for {@link Extent#getLazyBlock(Vector)}
* that takes the block's ID and metadata, but will defer loading of NBT
* data until time of access.
*
* <p>NBT data is later loaded using a call to {@link Extent#getBlock(Vector)}
* with a stored {@link Extent} and location.</p>
*
* <p>All mutators on this object will throw an
* {@link UnsupportedOperationException}.</p>
*/
public class LazyBlock extends BaseBlock {
private final Extent extent;
private final BlockVector3 position;
private boolean loaded = false;
/**
* Create a new lazy block.
*
* @param type the block type
* @param extent the extent to later load the full block data from
* @param position the position to later load the full block data from
*/
public LazyBlock(BlockType type, Extent extent, BlockVector3 position) {
super(type);
checkNotNull(extent);
checkNotNull(position);
this.extent = extent;
this.position = position;
}
/**
* Create a new lazy block.
*
* @param state the block state
* @param extent the extent to later load the full block data from
* @param position the position to later load the full block data from
*/
public LazyBlock(BlockState state, Extent extent, BlockVector3 position) {
super(state);
checkNotNull(extent);
checkNotNull(position);
this.extent = extent;
this.position = position;
}
@Override
public CompoundTag getNbtData() {
if (!loaded) {
BaseBlock loadedBlock = extent.getFullBlock(position);
this.nbtData = loadedBlock.getNbtData();
loaded = true;
}
return super.getNbtData();
}
@Override
public void setNbtData(CompoundTag nbtData) {
throw new UnsupportedOperationException("This object is immutable");
}
}

View File

@ -0,0 +1,88 @@
package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.awt.image.BufferedImage;
import java.util.concurrent.ThreadLocalRandom;
public class ArrayFilterBlock extends SimpleFilterBlock {
private final char[] blocks;
private final byte[] heights;
private final int yOffset;
private int x, z, index;
private char ordinal;
private final int width, length;
public ArrayFilterBlock(Extent extent, char[] blocks, byte[] heights, int width, int length, int yOffset) {
super(extent);
this.blocks = blocks;
this.width = width;
this.length = length;
this.heights = heights;
this.yOffset = yOffset;
}
public void filter2D(Filter filter) {
for (z = 0; z < length; z++) {
for (x = 0; x < width; x++, index++) {
ordinal = blocks[ordinal];
filter.applyBlock(this);
}
}
}
@Override
public void setOrdinal(int ordinal) {
blocks[index] = (char) ordinal;
}
@Override
public void setState(BlockState state) {
blocks[index] = state.getOrdinalChar();
}
@Override
public void setFullBlock(BaseBlock block) {
blocks[index] = block.getOrdinalChar();
}
@Override
public int getOrdinal() {
return ordinal;
}
@Override
public BlockState getState() {
return BlockTypes.states[ordinal];
}
@Override
public BaseBlock getBaseBlock() {
return getState().toBaseBlock();
}
@Override
public CompoundTag getTag() {
return null;
}
@Override
public int getX() {
return x;
}
@Override
public int getY() {
return (heights[index] & 0xFF) + yOffset;
}
@Override
public int getZ() {
return z;
}
}

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
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;
@ -12,11 +13,10 @@ import com.sk89q.worldedit.world.registry.BlockMaterial;
import javax.annotation.Nullable;
import static com.sk89q.worldedit.world.block.BlockTypes.states;
public class CharFilterBlock implements FilterBlock {
private IQueueExtent queue;
public class CharFilterBlock extends ChunkFilterBlock {
private CharGetBlocks get;
private ISetBlocks set;
private IChunkSet set;
private char[] getArr;
private @Nullable char[] setArr;
@ -25,14 +25,12 @@ public class CharFilterBlock implements FilterBlock {
// local
private int layer, index, x, y, z, xx, yy, zz, X, Z;
@Override
public final FilterBlock init(final IQueueExtent queue) {
this.queue = queue;
return this;
public CharFilterBlock(IQueueExtent queueExtent) {
super(queueExtent);
}
@Override
public final FilterBlock init(final int X, final int Z, final IGetBlocks chunk) {
public final ChunkFilterBlock init(final int X, final int Z, final IChunkGet chunk) {
this.get = (CharGetBlocks) chunk;
this.X = X;
this.Z = Z;
@ -41,11 +39,32 @@ public class CharFilterBlock implements FilterBlock {
return this;
}
@Override
public final void filter(final IGetBlocks iget, final ISetBlocks iset, final int layer, final Filter filter, final @Nullable Region region, BlockVector3 min, BlockVector3 max) {
public void flood(final IChunkGet iget, final IChunkSet iset, final int layer, Flood flood, FilterBlockMask mask) {
final int maxDepth = flood.getMaxDepth();
final boolean checkDepth = maxDepth < Character.MAX_VALUE;
if (init(iget, iset, layer)) {
while ((index = flood.poll()) != -1) {
x = index & 15;
z = (index >> 4) & 15;
y = (index >> 8) & 15;
if (mask.applyBlock(this)) {
int depth = index >> 12;
if (checkDepth && depth > maxDepth) {
continue;
}
flood.apply(x, y, z, depth);
}
}
}
}
private final boolean init(final IChunkGet iget, final IChunkSet iset, final int layer) {
this.layer = layer;
final CharGetBlocks get = (CharGetBlocks) iget;
if (!get.hasSection(layer)) return;
if (!get.hasSection(layer)) return false;
this.set = iset;
getArr = get.sections[layer].get(get, layer);
if (set.hasSection(layer)) {
@ -56,17 +75,24 @@ public class CharFilterBlock implements FilterBlock {
setArr = null;
}
this.yy = layer << 4;
if (region == null) {
if (min != null && max != null) {
iterate(min, max, layer, filter);
return true;
}
@Override
public final void filter(final IChunkGet iget, final IChunkSet iset, final int layer, final Filter filter, final @Nullable Region region, BlockVector3 min, BlockVector3 max) {
if (init(iget, iset, layer)) {
if (region == null) {
if (min != null && max != null) {
iterate(min, max, layer, filter);
} else {
iterate(filter);
}
} else {
iterate(filter);
}
} else {
if (min != null && max != null) {
iterate(region, min, max, layer, filter);
} else {
iterate(region, filter);
if (min != null && max != null) {
iterate(region, min, max, layer, filter);
} else {
iterate(region, filter);
}
}
}
}
@ -227,7 +253,7 @@ public class CharFilterBlock implements FilterBlock {
@Override
public final CompoundTag getTag() {
return null;
return get.getTag(x, y + (layer << 4), z);
}
public final BlockState getOrdinalBelow() {
@ -310,71 +336,135 @@ public class CharFilterBlock implements FilterBlock {
public final BlockState getStateRelative(final int x, final int y, final int z) {
final int newX = this.x + x;
if (newX >> 4 == 0) {
final int newZ = this.z + z;
if (newZ >> 4 == 0) {
final int newY = this.y + y;
final int layerAdd = newY >> 4;
switch (layerAdd) {
case 0:
return states[getArr[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: {
final int newLayer = layer + layerAdd;
if (newLayer < 16) {
final int index = ((newY & 15) << 8) + (newZ << 4) + newX;
return states[get.sections[newLayer].get(get, 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: {
final int newLayer = layer + layerAdd;
if (newLayer >= 0) {
final int index = ((newY & 15) << 8) + (newZ << 4) + newX;
return states[get.sections[newLayer].get(get, newLayer, index)];
}
break;
final int newZ = this.z + z;
if (newX >> 4 == 0 && newZ >> 4 == 0) {
final int newY = this.y + y;
final int layerAdd = newY >> 4;
switch (layerAdd) {
case 0:
return states[getArr[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: {
final int newLayer = layer + layerAdd;
if (newLayer < 16) {
final int index = ((newY & 15) << 8) + (newZ << 4) + newX;
return states[get.sections[newLayer].get(get, 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: {
final int newLayer = layer + layerAdd;
if (newLayer >= 0) {
final int index = ((newY & 15) << 8) + (newZ << 4) + newX;
return states[get.sections[newLayer].get(get, newLayer, index)];
}
break;
}
return BlockTypes.__RESERVED__.getDefaultState();
}
return BlockTypes.__RESERVED__.getDefaultState();
}
// queue.get
// TODO return normal get block
final int newY = this.y + y + yy;
if (newY >= 0 && newY <= 256) {
return queue.getBlock(xx + newX, newY, this.zz + this.z + z);
return getExtent().getBlock(xx + newX, newY, this.zz + newZ);
}
return BlockTypes.__RESERVED__.getDefaultState();
}
public final BaseBlock getFullBlockRelative(final int x, final int y, final int z) {
final int newX = this.x + x;
final int newZ = this.z + z;
if (newX >> 4 == 0 && newZ >> 4 == 0) {
final int newY = this.y + y;
final int layerAdd = newY >> 4;
BlockState state = BlockTypes.__RESERVED__.getDefaultState();
switch (layerAdd) {
case 0:
state = states[getArr[this.index + ((y << 8) + (z << 4) + x)]];
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: {
final int newLayer = layer + layerAdd;
if (newLayer < 16) {
final int index = ((newY & 15) << 8) + (newZ << 4) + newX;
state = states[get.sections[newLayer].get(get, 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: {
final int newLayer = layer + layerAdd;
if (newLayer >= 0) {
final int index = ((newY & 15) << 8) + (newZ << 4) + newX;
state = states[get.sections[newLayer].get(get, newLayer, index)];
}
break;
}
}
if (state.getMaterial().hasContainer()) {
final CompoundTag tag = get.getTag(x, y + (layer << 4), z);
return state.toBaseBlock(tag);
}
}
final int newY = this.y + y + yy;
if (newY >= 0 && newY <= 256) {
return getExtent().getFullBlock(xx + newX, newY, this.zz + newZ);
}
return BlockTypes.__RESERVED__.getDefaultState().toBaseBlock();
}
/*
Set delegate
*/
@ -383,6 +473,22 @@ public class CharFilterBlock implements FilterBlock {
return delegate = FULL;
}
@Override
public BiomeType getBiome(int x, int z) {
if ((x >> 4) == X && (z >> 4) == Z) {
return get.getBiome(x & 15, z & 15);
}
return getExtent().getBiome(x, z);
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
if ((x >> 4) == X && (z >> 4) == Z) {
return set.setBiome(x & 15, z & 15, biome);
}
return getExtent().setBiome(x, y, z, biome);
}
private interface SetDelegate {
void set(CharFilterBlock block, char value);
}

View File

@ -0,0 +1,19 @@
package com.boydti.fawe.beta;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import javax.annotation.Nullable;
public abstract class ChunkFilterBlock extends FilterBlock {
public ChunkFilterBlock(Extent extent) {
super(extent);
}
public abstract ChunkFilterBlock init(int X, int Z, IChunkGet chunk);
public abstract void flood(final IChunkGet iget, final IChunkSet iset, final int layer, Flood flood, FilterBlockMask mask);
public abstract void filter(IChunkGet get, IChunkSet set, int layer, Filter filter, @Nullable Region region, BlockVector3 min, BlockVector3 max);
}

View File

@ -10,7 +10,4 @@ public abstract class DelegateFilter implements IDelegateFilter {
public Filter getParent() {
return parent;
}
@Override
public abstract Filter fork();
}

View File

@ -0,0 +1,5 @@
package com.boydti.fawe.beta;
public interface DirectionMask {
boolean apply(int fromX, int fromY, int fromZ, int toX, int toY, int toZ);
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -8,64 +9,97 @@ import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nullable;
public interface FilterBlock {
FilterBlock init(IQueueExtent queue);
public abstract class FilterBlock extends BlockVector3 implements Extent {
private final Extent extent;
FilterBlock init(int X, int Z, IGetBlocks chunk);
public FilterBlock(Extent extent) {
this.extent = extent;
}
void filter(IGetBlocks get, ISetBlocks set, int layer, Filter filter, @Nullable Region region, BlockVector3 min, BlockVector3 max);
public final Extent getExtent() {
return extent;
}
void setOrdinal(int ordinal);
public abstract void setOrdinal(int ordinal);
void setState(BlockState state);
public abstract void setState(BlockState state);
void setFullBlock(BaseBlock block);
public abstract void setFullBlock(BaseBlock block);
int getOrdinal();
public abstract int getOrdinal();
BlockState getState();
public abstract BlockState getState();
BaseBlock getBaseBlock();
public abstract BaseBlock getBaseBlock();
CompoundTag getTag();
public abstract CompoundTag getTag();
default BlockState getOrdinalBelow() {
@Override
public BlockVector3 getMinimumPoint() {
return getExtent().getMinimumPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return getExtent().getMaximumPoint();
}
@Override
public BlockState getBlock(int x, int y, int z) {
return getStateRelative(x - getX(), y - getY(), z - getZ());
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
return getFullBlockRelative(x - getX(), y - getY(), z - getZ());
}
public BlockState getOrdinalBelow() {
return getStateRelative(0, -1, 0);
}
default BlockState getStateAbove() {
public BlockState getStateAbove() {
return getStateRelative(0, 1, 0);
}
default BlockState getStateRelativeY(final int y) {
public BlockState getStateRelativeY(final int y) {
return getStateRelative(0, y, 0);
}
int getX();
public BlockState getStateRelative(final int x, final int y, final int z) {
return getFullBlockRelative(x, y, z).toBlockState();
}
int getY();
public BaseBlock getFullBlockRelative(int x, int y, int z) {
return getExtent().getFullBlock(x + getX(), y + getY(), z + getZ());
}
int getZ();
@Override
public abstract int getX();
default int getLocalX() {
@Override
public abstract int getY();
@Override
public abstract int getZ();
public int getLocalX() {
return getX() & 15;
}
default int getLocalY() {
public int getLocalY() {
return getY() & 15;
}
default int getLocalZ() {
public int getLocalZ() {
return getZ() & 15;
}
default int getChunkX() {
public int getChunkX() {
return getX() >> 4;
}
default int getChunkZ() {
public int getChunkZ() {
return getZ() >> 4;
}
BlockState getStateRelative(final int x, final int y, final int z);
}

View File

@ -0,0 +1,5 @@
package com.boydti.fawe.beta;
public interface FilterBlockMask {
boolean applyBlock(final FilterBlock block);
}

View File

@ -0,0 +1,192 @@
package com.boydti.fawe.beta;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.beta.implementation.QueueHandler;
import com.boydti.fawe.beta.implementation.WorldChunkCache;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.World;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Flood {
private final int maxBranch;
private final int maxDepth;
private final Direction[] directions;
private int[] queue;
private long[] visit;
private int[][] queues;
private long[][] visits;
private int X, Y, Z;
private ConcurrentLinkedQueue<int[]> queuePool = new ConcurrentLinkedQueue<>();
private final Long2ObjectLinkedOpenHashMap<long[][]> chunkVisits;
private final Long2ObjectLinkedOpenHashMap<int[][]> chunkQueues;
public Flood(int maxBranch, int maxDepth, Direction[] directions) {
this.maxBranch = maxBranch;
this.maxDepth = maxDepth;
this.directions = directions;
this.queues = new int[27][];
this.visits = new long[27][];
this.chunkVisits = new Long2ObjectLinkedOpenHashMap<>();
this.chunkQueues = new Long2ObjectLinkedOpenHashMap<>();
}
public synchronized void run(World world) {
QueueHandler queueHandler = Fawe.get().getQueueHandler();
IQueueExtent fq = queueHandler.getQueue(world);
while (!chunkQueues.isEmpty()) {
long firstKey = chunkQueues.firstLongKey();
int X = MathMan.unpairIntX(firstKey);
int Z = MathMan.unpairIntY(firstKey);
int[][] chunkQueue = chunkQueues.get(firstKey);
// apply
}
}
private void init(int X, int Y, int Z) {
this.X = X;
this.Y = Y;
this.Z = Z;
}
public void start(int x, int y, int z) {
push(x, y, z, 0);
}
private void push(int x, int y, int z, int depth) {
int X = x >> 4;
int Z = z >> 4;
long pair = MathMan.pairInt(X, Z);
int layer = y >> 4;
int[] section = getOrCreateQueue(pair, layer);
int val = (x & 15) + ((z & 15) << 4) + ((y & 15) << 8) + (depth << 12);
push(section, val);
}
private int[] getOrCreateQueue(long pair, int layer) {
int[][] arrs = chunkQueues.get(pair);
if (arrs == null) {
chunkQueues.put(pair, arrs = new int[16][]);
}
int[] section = arrs[layer];
if (section == null) {
arrs[layer] = section = newQueue();
}
return section;
}
private int[] newQueue() {
int[] arr = queuePool.poll();
if (arr != null) {
arr[0] = 2;
arr[1] = 2;
return arr;
}
return new int[4096];
}
public int poll() {
int index = queue[0];
if (index == queue[1]) {
return -1;
}
queue[0] = index + 1;
return queue[index];
}
private void push(int[] queue, int val) {
int indexStart = queue[0];
int indexEnd = queue[1];
push(indexStart, indexEnd, queue, val);
}
private void push(int indexStart, int indexEnd, int[] queue, int val) {
if (indexStart > 2) {
queue[0] = --indexStart;
queue[indexStart] = val;
} else {
queue[indexEnd] = val;
queue[0] = ++indexEnd;
}
}
public Direction[] getDirections() {
return directions;
}
public int getMaxBranch() {
return maxBranch;
}
public int getMaxDepth() {
return maxDepth;
}
public void apply(int x, int y, int z, int depth) {
for (int i = 0, j = 0; i < directions.length && j < maxBranch; i++) {
final Direction dir = directions[i];
final int ty = y + dir.getBlockY();
final int tx = x + dir.getBlockX();
final int tz = z + dir.getBlockZ();
int index;
long[] visit;
int[] queue;
final int or = tx | ty | tz;
if (or > 15 || or < 0) {
visit = this.visit;
queue = this.queue;
index = tx + (tz << 4) + (ty << 8);
} else {
int nextX = tx >> 4;
int nextY = ty >> 4;
int nextZ = tz >> 4;
int sectionIndex = nextX + nextZ * 3 + nextZ * 9 + 13;
visit = visits[sectionIndex];
queue = queues[sectionIndex];
if (visit == null || queue == null) {
long pair = MathMan.pairInt(X + nextX, Z + nextZ);
int layer = Y + nextY;
if (layer < 0 || layer > 15) {
continue;
}
queues[sectionIndex] = queue = getOrCreateQueue(pair, layer);
}
index = (tx & 15) + ((tz & 15) << 4) + ((ty & 15) << 8);
}
if (!getAndSet(visit, index)) {
j++;
push(queue, index + (depth << 12));
}
}
}
public void set(long[] bits, int i) {
bits[i >> 6] |= (1L << (i & 0x3F));
}
public final boolean getAndSet(long[] bits, int i) {
int index = i >> 6;
long offset = (1L << (i & 0x3F));
long val = bits[index];
if ((val & offset) != 0) {
return true;
} else {
bits[index] |= offset;
return false;
}
}
public boolean get(long[] bits, final int i) {
return (bits[i >> 6] & (1L << (i & 0x3F))) != 0;
}
}

View File

@ -11,7 +11,6 @@ import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.Supplier;
/**
* Represents a chunk in the queue {@link IQueueExtent}
@ -72,7 +71,9 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
* @param unitialized a mutable block vector (buffer)
* @param unitialized2 a mutable block vector (buffer)
*/
void filter(Filter filter, FilterBlock block, @Nullable Region region, MutableBlockVector3 unitialized, MutableBlockVector3 unitialized2);
void filter(Filter filter, ChunkFilterBlock block, @Nullable Region region, MutableBlockVector3 unitialized, MutableBlockVector3 unitialized2);
void flood(Flood flood, FilterBlockMask mask, ChunkFilterBlock block);
/* set - queues a change */
boolean setBiome(int x, int y, int z, BiomeType biome);

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -8,11 +9,14 @@ import com.sk89q.worldedit.world.block.BlockState;
/**
* Interface for getting blocks
*/
public interface IGetBlocks extends IBlocks, Trimable {
public interface IChunkGet extends IBlocks, Trimable, InputExtent {
@Override
BaseBlock getFullBlock(int x, int y, int z);
@Override
BiomeType getBiome(int x, int z);
@Override
BlockState getBlock(int x, int y, int z);
CompoundTag getTag(int x, int y, int z);

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.OutputExtent;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -14,8 +15,8 @@ import java.util.UUID;
/**
* Interface for setting blocks
*/
public interface ISetBlocks extends IBlocks {
boolean setBiome(int x, int y, int z, BiomeType biome);
public interface IChunkSet extends IBlocks, OutputExtent {
boolean setBiome(int x, int z, BiomeType biome);
boolean setBlock(int x, int y, int z, BlockStateHolder holder);

View File

@ -26,6 +26,11 @@ public interface IDelegateChunk<U extends IChunk> extends IChunk {
return root;
}
@Override
default void flood(Flood flood, FilterBlockMask mask, FilterBlock block) {
getParent().flood(flood, mask, block);
}
@Override
default boolean setBiome(final int x, final int y, final int z, final BiomeType biome) {
return getParent().setBiome(x, y, z, biome);

View File

@ -39,7 +39,11 @@ public interface IDelegateFilter extends Filter {
@Override
default Filter fork() {
return newInstance(getParent().fork());
Filter fork = getParent().fork();
if (fork != getParent()) {
return newInstance(fork);
}
return this;
}
Filter newInstance(Filter other);

View File

@ -1,7 +1,10 @@
package com.boydti.fawe.beta;
import com.boydti.fawe.beta.implementation.WorldChunkCache;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
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.BlockStateHolder;
@ -12,7 +15,7 @@ import java.util.concurrent.Future;
* TODO: implement Extent (need to refactor Extent first)
* Interface for a queue based extent which uses chunks
*/
public interface IQueueExtent extends Flushable, Trimable {
public interface IQueueExtent extends Flushable, Trimable, Extent {
void init(WorldChunkCache world);
/**
@ -51,11 +54,26 @@ public interface IQueueExtent extends Flushable, Trimable {
return chunk.getBlock(x & 15, y, z & 15);
}
@Override
default BaseBlock getFullBlock(int x, int y, int z) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4);
return chunk.getFullBlock(x & 15, y, z & 15);
}
default BiomeType getBiome(final int x, final int z) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4);
return chunk.getBiome(x & 15, z & 15);
}
@Override
default BlockVector3 getMinimumPoint() {
return getCache().getWorld().getMinimumPoint();
}
@Override
default BlockVector3 getMaximumPoint() {
return getCache().getWorld().getMaximumPoint();
}
/**
* Create a new root IChunk object<br>
* - Full chunks will be reused, so a more optimized chunk can be returned in that case<br>
@ -81,5 +99,5 @@ public interface IQueueExtent extends Flushable, Trimable {
@Override
void flush();
FilterBlock initFilterBlock();
ChunkFilterBlock initFilterBlock();
}

View File

@ -0,0 +1,70 @@
package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nullable;
public abstract class SimpleFilterBlock extends FilterBlock {
public SimpleFilterBlock(Extent extent) {
super(extent);
}
private int x, y, z, ordinal;
private CompoundTag nbt;
public void init(int x, int y, int z, int ordinal) {
this.x = x;
this.y = y;
this.z = z;
this.ordinal = ordinal;
}
public void init(int x, int y, int z, int ordinal, CompoundTag nbt) {
this.x = x;
this.y = y;
this.z = z;
this.ordinal = ordinal;
this.nbt = nbt;
}
@Override
public int getOrdinal() {
return ordinal;
}
@Override
public BlockState getState() {
return BlockTypes.states[ordinal];
}
@Override
public BaseBlock getBaseBlock() {
return getState().toBaseBlock(nbt);
}
@Override
public CompoundTag getTag() {
return nbt;
}
@Override
public int getX() {
return x;
}
@Override
public int getY() {
return y;
}
@Override
public int getZ() {
return z;
}
}

View File

@ -0,0 +1,26 @@
package com.boydti.fawe.beta.filters;
import com.boydti.fawe.beta.DelegateFilter;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.beta.FilterBlockMask;
import java.awt.image.BufferedImage;
import java.util.concurrent.ThreadLocalRandom;
public class ArrayImageMask implements FilterBlockMask {
private final ThreadLocalRandom r;
private final boolean white;
private final BufferedImage img;
public ArrayImageMask(BufferedImage img, boolean white) {
this.img = img;
this.white = white;
this.r = ThreadLocalRandom.current();
}
@Override
public boolean applyBlock(FilterBlock block) {
int height = img.getRGB(block.getX(), block.getZ()) & 0xFF;
return ((height == 255 || height > 0 && !white && r.nextInt(256) <= height));
}
}

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.beta.IChunk;
@ -163,7 +164,7 @@ public abstract class QueueHandler implements Trimable, Runnable {
// Create a chunk that we will reuse/reset for each operation
final IQueueExtent queue = getQueue(world);
synchronized (queue) {
FilterBlock block = null;
ChunkFilterBlock block = null;
while (true) {
// Get the next chunk posWeakChunk

View File

@ -6,8 +6,6 @@ import com.boydti.fawe.beta.FilterBlock;
public abstract class SimpleCharQueueExtent extends SingleThreadQueueExtent {
@Override
public FilterBlock initFilterBlock() {
FilterBlock filter = new CharFilterBlock();
filter = filter.init(this);
return filter;
return new CharFilterBlock(this);
}
}

View File

@ -1,6 +1,6 @@
package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.IGetBlocks;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.Trimable;
import com.sk89q.worldedit.world.World;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
@ -15,7 +15,7 @@ import java.util.function.Supplier;
* - avoids conversion between palette and raw data on every block get
*/
public class WorldChunkCache implements Trimable {
protected final Long2ObjectLinkedOpenHashMap<WeakReference<IGetBlocks>> getCache;
protected final Long2ObjectLinkedOpenHashMap<WeakReference<IChunkGet>> getCache;
private final World world;
protected WorldChunkCache(final World world) {
@ -37,13 +37,13 @@ public class WorldChunkCache implements Trimable {
* @param provider used to create if it isn't already cached
* @return cached IGetBlocks
*/
public synchronized IGetBlocks get(final long index, final Supplier<IGetBlocks> provider) {
final WeakReference<IGetBlocks> ref = getCache.get(index);
public synchronized IChunkGet get(final long index, final Supplier<IChunkGet> provider) {
final WeakReference<IChunkGet> ref = getCache.get(index);
if (ref != null) {
final IGetBlocks blocks = ref.get();
final IChunkGet blocks = ref.get();
if (blocks != null) return blocks;
}
final IGetBlocks blocks = provider.get();
final IChunkGet blocks = provider.get();
getCache.put(index, new WeakReference<>(blocks));
return blocks;
}
@ -52,11 +52,11 @@ public class WorldChunkCache implements Trimable {
public synchronized boolean trim(final boolean aggressive) {
boolean result = true;
if (!getCache.isEmpty()) {
final ObjectIterator<Long2ObjectMap.Entry<WeakReference<IGetBlocks>>> iter = getCache.long2ObjectEntrySet().fastIterator();
final ObjectIterator<Long2ObjectMap.Entry<WeakReference<IChunkGet>>> iter = getCache.long2ObjectEntrySet().fastIterator();
while (iter.hasNext()) {
final Long2ObjectMap.Entry<WeakReference<IGetBlocks>> entry = iter.next();
final WeakReference<IGetBlocks> value = entry.getValue();
final IGetBlocks igb = value.get();
final Long2ObjectMap.Entry<WeakReference<IChunkGet>> entry = iter.next();
final WeakReference<IChunkGet> value = entry.getValue();
final IChunkGet igb = value.get();
if (igb == null) iter.remove();
else {
result = false;

View File

@ -1,11 +1,11 @@
package com.boydti.fawe.beta.implementation.blocks;
import com.boydti.fawe.beta.IGetBlocks;
import com.boydti.fawe.beta.IChunkGet;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
public abstract class CharGetBlocks extends CharBlocks implements IGetBlocks {
public abstract class CharGetBlocks extends CharBlocks implements IChunkGet {
@Override
public BaseBlock getFullBlock(final int x, final int y, final int z) {
return BlockTypes.states[get(x, y, z)].toBaseBlock();

View File

@ -1,6 +1,6 @@
package com.boydti.fawe.beta.implementation.blocks;
import com.boydti.fawe.beta.ISetBlocks;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -14,7 +14,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class CharSetBlocks extends CharBlocks implements ISetBlocks {
public class CharSetBlocks extends CharBlocks implements IChunkSet {
public BiomeType[] biomes;
public HashMap<Short, CompoundTag> tiles;
public HashSet<CompoundTag> entities;

View File

@ -1,12 +1,15 @@
package com.boydti.fawe.beta.implementation.holder;
import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.beta.FilterBlockMask;
import com.boydti.fawe.beta.Flood;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IGetBlocks;
import com.boydti.fawe.beta.ISetBlocks;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent;
import com.boydti.fawe.beta.implementation.WorldChunkCache;
import com.boydti.fawe.util.MathMan;
@ -23,9 +26,9 @@ import java.util.function.Supplier;
/**
* Abstract IChunk class that implements basic get/set blocks
*/
public abstract class ChunkHolder implements IChunk, Supplier<IGetBlocks> {
private IGetBlocks get;
private ISetBlocks set;
public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
private IChunkGet get;
private IChunkSet set;
private IBlockDelegate delegate;
private IQueueExtent extent;
private int X,Z;
@ -39,9 +42,14 @@ public abstract class ChunkHolder implements IChunk, Supplier<IGetBlocks> {
}
@Override
public void filter(final Filter filter, FilterBlock block, @Nullable Region region, final MutableBlockVector3 min, final MutableBlockVector3 max) {
final IGetBlocks get = getOrCreateGet();
final ISetBlocks set = getOrCreateSet();
public void flood(Flood flood, FilterBlockMask mask, ChunkFilterBlock block) {
// block.flood(get, set, mask, block, );
}
@Override
public void filter(final Filter filter, ChunkFilterBlock block, @Nullable Region region, @Nullable final MutableBlockVector3 min, @Nullable final MutableBlockVector3 max) {
final IChunkGet get = getOrCreateGet();
final IChunkSet set = getOrCreateSet();
try {
if (region != null) {
switch (region.getChunkBounds(X, Z, min, max)) {
@ -106,21 +114,21 @@ public abstract class ChunkHolder implements IChunk, Supplier<IGetBlocks> {
return set == null || set.isEmpty();
}
public final IGetBlocks getOrCreateGet() {
public final IChunkGet getOrCreateGet() {
if (get == null) get = newGet();
return get;
}
public final ISetBlocks getOrCreateSet() {
public final IChunkSet getOrCreateSet() {
if (set == null) set = set();
return set;
}
public ISetBlocks set() {
public IChunkSet set() {
return new CharSetBlocks();
}
private IGetBlocks newGet() {
private IChunkGet newGet() {
if (extent instanceof SingleThreadQueueExtent) {
final WorldChunkCache cache = ((SingleThreadQueueExtent) extent).getCache();
return cache.get(MathMan.pairInt(X, Z), this);

View File

@ -1,5 +1,8 @@
package com.boydti.fawe.beta.implementation.holder;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.beta.FilterBlockMask;
import com.boydti.fawe.beta.Flood;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IDelegateChunk;

View File

@ -2,6 +2,12 @@ package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.ArrayFilterBlock;
import com.boydti.fawe.beta.DelegateFilter;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.beta.SimpleFilterBlock;
import com.boydti.fawe.beta.filters.ArrayImageMask;
import com.boydti.fawe.example.SimpleIntFaweChunk;
import com.boydti.fawe.jnbt.anvil.HeightMapMCADrawer;
import com.boydti.fawe.jnbt.anvil.MCAChunk;
@ -1022,7 +1028,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
@Override
public BlockState getBlock(BlockVector3 position) {
return getLazyBlock(position);
return getBlock(position.getX(), position.getY(), position.getZ());
}
public BlockState getFloor(int x, int z) {
@ -1045,12 +1051,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return getLazyBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ());
}
@Override
public BlockState getLazyBlock(int x, int y, int z) {
public BlockState getBlock(int x, int y, int z) {
return BlockState.getFromInternalId(getCombinedId4Data(x, y, z));
}
@ -1340,6 +1341,11 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
}
}
public void test() {
// ArrayImageMask mask = new ArrayImageMask(img, white);
// filter = new ArrayFilterBlock(this, overlayArr, heights.get(), getWidth(), getLength(), 1);
}
public void setOverlay(BufferedImage img, Pattern pattern, boolean white) {
if (pattern instanceof BlockStateHolder) {
setOverlay(img, ((BlockStateHolder) pattern).getInternalId(), white);

View File

@ -72,7 +72,7 @@ public interface FaweQueue extends HasFaweQueue, Extent {
}
@Override
default BlockState getLazyBlock(int x, int y, int z) {
default BlockState getBlock(int x, int y, int z) {
int combinedId4Data = getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId());
try {
BlockState state = BlockState.getFromInternalId(combinedId4Data);

View File

@ -50,6 +50,7 @@ public class SurfaceSpline implements Brush {
n.setContinuity(continuity);
nodes.add(n);
}
MutableBlockVector3 mutable = MutableBlockVector3.at(0, 0, 0);
interpol.setNodes(nodes);
final double splinelength = interpol.arcLength(0, 1);
for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
@ -60,7 +61,7 @@ public class SurfaceSpline implements Brush {
tipy = editSession.getNearestSurfaceTerrainBlock(tipx, tipz, tipy, 0, maxY);
if (tipy == -1) continue;
if (radius == 0) {
BlockVector3 set = MutableBlockVector3.get(tipx, tipy, tipz);
BlockVector3 set = mutable.setComponents(tipx, tipy, tipz);
try {
pattern.apply(editSession, set, set);
} catch (WorldEditException e) {

View File

@ -24,7 +24,12 @@ public interface VirtualWorld extends SimpleWorld, FaweQueue, Closeable {
@Override
default BaseBlock getFullBlock(BlockVector3 position) {
return getLazyBlock(position).toBaseBlock();
return getBlock(position).toBaseBlock();
}
@Override
default BaseBlock getFullBlock(int x, int y, int z) {
return getBlock(x, y, z).toBaseBlock();
}
@Override

View File

@ -43,7 +43,7 @@ public class BlockVectorSet extends AbstractCollection<BlockVector3> implements
int newSize = count + size;
if (newSize > index) {
int localIndex = index - count;
MutableBlockVector3 pos = new MutableBlockVector3(set.getIndex(localIndex));
BlockVector3 pos = set.getIndex(localIndex);
if (pos != null) {
int pair = entry.getIntKey();
int cx = MathMan.unpairX(pair);

View File

@ -244,9 +244,9 @@ public final class DifferentialArray<T> implements DifferentialCollection<T> {
return dataBytes;
}
// public char[] getCharArray() {
// return dataChars;
// }
public char[] getCharArray() {
return dataChars;
}
public int[] getIntArray() {
return dataInts;

View File

@ -0,0 +1,213 @@
package com.boydti.fawe.object.collection;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
/**
* Records changes made through the {@link #set(int, int, int, char)} method<br/>
* Changes are not recorded if you edit the raw data
*/
public final class DifferentialCharBlockBuffer implements DifferentialCollection<char[][][][][]> {
private final int width, length;
private final int t1, t2;
private char[][][][][] data;
private char[][][][][] changes;
public DifferentialCharBlockBuffer(int width, int length) {
this.width = width;
this.length = length;
this.t1 = (length + 15) >> 4;
this.t2 = (width + 15) >> 4;
}
@Override
public char[][][][][] get() {
return data;
}
@Override
public void flushChanges(FaweOutputStream out) throws IOException {
boolean modified = isModified();
out.writeBoolean(modified);
if (modified) {
writeArray(changes, 0, 0, out);
}
clearChanges();
}
private void writeArray(Object arr, int level, int index, FaweOutputStream out) throws IOException {
if (level == 4) {
if (arr != null) {
char[] level4 = (char[]) arr;
out.writeVarInt(level4.length);
for (char c : level4) {
out.writeChar(c);
}
} else {
out.writeVarInt(0);
}
} else {
int len = arr == null ? 0 : Array.getLength(arr);
out.writeVarInt(len);
for (int i = 0; i < len; i++) {
Object elem = Array.get(arr, i);
writeArray(elem, level + 1, i, out);
}
}
}
@Override
public void undoChanges(FaweInputStream in) throws IOException {
if (changes != null && changes.length != 0) throw new IllegalStateException("There are uncommitted changes, please flush first");
boolean modified = in.readBoolean();
if (modified) {
int len = in.readVarInt();
if (len == 0) {
data = null;
} else {
for (int i = 0; i < len; i++) {
readArray(data, i, 1, in);
}
}
}
clearChanges();
}
@Override
public void redoChanges(FaweInputStream in) throws IOException {
clearChanges();
throw new UnsupportedOperationException("Not implemented");
}
private void readArray(Object dataElem, int index, int level, FaweInputStream in) throws IOException {
int len = in.readVarInt();
if (level == 4) {
char[][] castedElem = (char[][]) dataElem;
if (len == 0) {
castedElem[index] = null;
} else {
char[] current = castedElem[index];
for (int i = 0; i < len; i++) {
current[i] = in.readChar();
}
}
} else {
if (len == 0) {
Array.set(dataElem, index, null);
} else {
Object nextElem = Array.get(dataElem, index);
for (int i = 0; i < len; i++) {
readArray(nextElem, i, level + 1, in);
}
}
}
}
public boolean isModified() {
return changes != null;
}
public void clearChanges() {
changes = null;
}
public void set(int x, int y, int z, char combined) {
if (combined == 0) combined = 1;
int localX = x & 15;
int localZ = z & 15;
int chunkX = x >> 4;
int chunkZ = z >> 4;
if (data == null) {
data = new char[t1][][][][];
changes = new char[0][][][][];
}
char[][][][] arr = data[chunkZ];
if (arr == null) {
arr = data[chunkZ] = new char[t2][][][];
}
char[][][] arr2 = arr[chunkX];
if (arr2 == null) {
arr2 = arr[chunkX] = new char[256][][];
}
char[][] yMap = arr2[y];
if (yMap == null) {
arr2[y] = yMap = new char[16][];
}
boolean newSection;
char current;
char[] zMap = yMap[localZ];
if (zMap == null) {
yMap[localZ] = zMap = new char[16];
if (changes == null) {
changes = new char[t1][][][][];
} else if (changes != null && changes.length != 0) {
initialChange(changes, chunkX, chunkZ, localX, localZ, y, (char) -combined);
}
} else {
if (changes == null || changes.length == 0) changes = new char[t1][][][][];
appendChange(changes, chunkX, chunkZ, localX, localZ, y, (char) (zMap[localX] - combined));
}
zMap[localX] = combined;
}
private void initialChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
char[][][][] arr = src[chunkZ];
if (arr == null) {
src[chunkZ] = new char[0][][][];
return;
} else if (arr.length == 0) return;
char[][][] arr2 = arr[chunkX];
if (arr2 == null) {
arr[chunkX] = new char[0][][];
return;
} else if (arr2.length == 0) return;
char[][] yMap = arr2[y];
if (yMap == null) {
arr2[y] = new char[0][];
return;
} else if (yMap.length == 0) return;
char[] zMap = yMap[localZ];
if (zMap == null) {
yMap[localZ] = new char[0];
return;
} else if (zMap.length == 0) return;
char current = zMap[localX];
zMap[localX] = combined;
}
private void appendChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
char[][][][] arr = src[chunkZ];
if (arr == null || arr.length == 0) {
arr = src[chunkZ] = new char[t2][][][];
}
char[][][] arr2 = arr[chunkX];
if (arr2 == null || arr2.length == 0) {
arr2 = arr[chunkX] = new char[256][][];
}
char[][] yMap = arr2[y];
if (yMap == null || yMap.length == 0) {
arr2[y] = yMap = new char[16][];
}
char[] zMap = yMap[localZ];
if (zMap == null || zMap.length == 0) {
yMap[localZ] = zMap = new char[16];
}
zMap[localX] = combined;
}
}

View File

@ -100,7 +100,7 @@ public class LocalBlockVectorSet implements Set<BlockVector3> {
this.offsetZ = z;
}
public BlockVector3 getIndex(int getIndex) {
protected BlockVector3 getIndex(int getIndex) {
int size = size();
if (getIndex > size) {
return null;

View File

@ -2,8 +2,10 @@ package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.object.DataAnglePattern;
import com.boydti.fawe.util.TextureHolder;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -15,11 +17,11 @@ import com.sk89q.worldedit.world.block.BlockType;
import java.io.IOException;
public class AngleColorPattern extends DataAnglePattern {
protected transient TextureHolder util;
protected transient TextureUtil util;
public AngleColorPattern(Extent extent, TextureHolder util, int distance) {
public AngleColorPattern(Extent extent, TextureHolder holder, int distance) {
super(extent, distance);
this.util = util;
this.util = holder.getTextureUtil();
}
public int getColor(int color, int slope) {
@ -31,15 +33,28 @@ public class AngleColorPattern extends DataAnglePattern {
return (((color >> 24) & 0xFF) << 24) + (newRed << 16) + (newGreen << 8) + (newBlue << 0);
}
@Override
public void apply(FilterBlock block) {
BlockState state = block.getState();
int slope = getSlope(state, block);
if (slope == -1) return;
int color = util.getColor(state.getBlockType());
if (color == 0) return;
int newColor = getColor(color, slope);
BlockType newBlock = util.getNearestBlock(newColor);
if (newBlock == null) return;
newBlock.apply(block);
}
@Override
public BaseBlock apply(BlockVector3 position) {
BaseBlock block = extent.getFullBlock(position);
int slope = getSlope(block, position);
if (slope == -1) return block;
int color = util.getTextureUtil().getColor(block.getBlockType());
int color = util.getColor(block.getBlockType());
if (color == 0) return block;
int newColor = getColor(color, slope);
return util.getTextureUtil().getNearestBlock(newColor).getDefaultState().toBaseBlock();
return util.getNearestBlock(newColor).getDefaultState().toBaseBlock();
}
@Override
@ -51,7 +66,7 @@ public class AngleColorPattern extends DataAnglePattern {
int z = vector.getBlockZ();
int height = extent.getNearestSurfaceTerrainBlock(x, z, y, 0, maxY);
if (height > 0) {
BlockStateHolder below = extent.getLazyBlock(x, height - 1, z);
BlockStateHolder below = extent.getBlock(x, height - 1, z);
if (!below.getBlockType().getMaterial().isMovementBlocker()) {
return Integer.MAX_VALUE;
}
@ -65,16 +80,11 @@ public class AngleColorPattern extends DataAnglePattern {
BlockStateHolder block = extent.getBlock(getPosition);
int slope = getSlope(block, getPosition);
if (slope == -1) return false;
int color = util.getTextureUtil().getColor(block.getBlockType());
int color = util.getColor(block.getBlockType());
if (color == 0) return false;
int newColor = getColor(color, slope);
BlockType newBlock = util.getTextureUtil().getNearestBlock(newColor);
BlockType newBlock = util.getNearestBlock(newColor);
if (newBlock == null) return false;
return extent.setBlock(setPosition, newBlock.getDefaultState());
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(true, 0, 100);
}
}

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.schematic.Schematic;
import com.sk89q.worldedit.WorldEditException;
@ -25,14 +26,15 @@ public class RandomFullClipboardPattern extends AbstractPattern {
private final Extent extent;
private final MutableBlockVector3 mutable = new MutableBlockVector3();
private final List<ClipboardHolder> clipboards;
private boolean randomRotate;
private boolean randomFlip;
private final boolean randomRotate;
private final boolean randomFlip;
public RandomFullClipboardPattern(Extent extent, List<ClipboardHolder> clipboards, boolean randomRotate, boolean randomFlip) {
checkNotNull(clipboards);
this.clipboards = clipboards;
this.extent = extent;
this.randomRotate = randomRotate;
this.randomFlip = randomFlip;
}
@Override

View File

@ -86,16 +86,4 @@ public class FaweQueueDelegateExtent extends DelegateFaweQueue {
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
return parentExtent.setBlock(x, y, z, block);
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return parentExtent.getLazyBlock(position);
}
@Override
public BlockState getLazyBlock(int x, int y, int z) {
return parentExtent.getLazyBlock(x, y, z);
}
}

View File

@ -2,14 +2,36 @@ package com.boydti.fawe.util;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.anvil.MCAQueue;
import com.boydti.fawe.jnbt.anvil.MCAWorld;
import com.boydti.fawe.logging.LoggingChangeSet;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.*;
import com.boydti.fawe.object.brush.visualization.VirtualWorld;
import com.boydti.fawe.object.changeset.BlockBagChangeSet;
import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.FastWorldEditExtent;
import com.boydti.fawe.object.extent.HeightBoundExtent;
import com.boydti.fawe.object.extent.MultiRegionExtent;
import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.object.extent.ProcessedWEExtent;
import com.boydti.fawe.object.extent.SingleRegionExtent;
import com.boydti.fawe.object.extent.SlowExtent;
import com.boydti.fawe.object.extent.StripNBTExtent;
import com.boydti.fawe.object.progress.ChatProgressTracker;
import com.boydti.fawe.object.progress.DefaultProgressTracker;
import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.eventbus.EventBus;
@ -190,7 +212,214 @@ public class EditSessionBuilder {
return this;
}
private boolean wrapped;
private AbstractDelegateExtent wrapExtent(final AbstractDelegateExtent extent, final EventBus eventBus, EditSessionEvent event, final EditSession.Stage stage) {
event = event.clone(stage);
event.setExtent(extent);
eventBus.post(event);
if (event.isCancelled()) {
return new NullExtent(extent, BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
}
final Extent toReturn = event.getExtent();
if(toReturn instanceof com.sk89q.worldedit.extent.NullExtent) {
return new NullExtent(toReturn, null);
}
if (!(toReturn instanceof AbstractDelegateExtent)) {
Fawe.debug("Extent " + toReturn + " must be AbstractDelegateExtent");
return extent;
}
if (toReturn != extent) {
String className = toReturn.getClass().getName().toLowerCase();
for (String allowed : Settings.IMP.EXTENT.ALLOWED_PLUGINS) {
if (className.contains(allowed.toLowerCase())) {
this.wrapped = true;
return (AbstractDelegateExtent) toReturn;
}
}
if (Settings.IMP.EXTENT.DEBUG) {
Fawe.debug("&cPotentially unsafe extent blocked: " + toReturn.getClass().getName());
Fawe.debug("&8 - &7For area restrictions, it is recommended to use the FaweAPI");
Fawe.debug("&8 - &7For block logging, it is recommended to use use BlocksHub");
Fawe.debug("&8 - &7To allow this plugin add it to the FAWE `allowed-plugins` list");
Fawe.debug("&8 - &7To hide this message set `debug` to false in the FAWE config.yml");
if (toReturn.getClass().getName().contains("CoreProtect")) {
Fawe.debug("Note on CoreProtect: ");
Fawe.debug(" - If you disable CP's WE logger (CP config) and this still shows, please update CP");
Fawe.debug(" - Use BlocksHub and set `debug` false in the FAWE config");
}
}
}
return extent;
}
public EditSessionBuilder commit() {
// reset
wrapped = false;
//
if (worldName == null) {
if (world == null) {
if (queue == null) {
worldName = "";
} else {
worldName = queue.getWorldName();
}
} else {
worldName = Fawe.imp().getWorldName(world);
}
}
if (world == null && !this.worldName.isEmpty()) {
world = FaweAPI.getWorld(this.worldName);
}
if (eventBus == null) {
eventBus = WorldEdit.getInstance().getEventBus();
}
if (event == null) {
event = new EditSessionEvent(world, player == null ? null : (player.getPlayer()), -1, null);
}
if (player == null && event.getActor() != null) {
player = FawePlayer.wrap(event.getActor());
}
if (limit == null) {
if (player == null) {
limit = FaweLimit.MAX;
} else {
limit = player.getLimit();
}
}
if (autoQueue == null) {
autoQueue = true;
}
if (fastmode == null) {
if (player == null) {
fastmode = !Settings.IMP.HISTORY.ENABLE_FOR_CONSOLE;
} else {
fastmode = player.getSession().hasFastMode();
}
}
if (checkMemory == null) {
checkMemory = player != null && !this.fastmode;
}
if (checkMemory) {
if (MemUtil.isMemoryLimitedSlow()) {
if (Perm.hasPermission(player, "worldedit.fast")) {
BBC.WORLDEDIT_OOM_ADMIN.send(player);
}
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY);
}
}
// this.originalLimit = limit;
this.blockBag = limit.INVENTORY_MODE != 0 ? blockBag : null;
// this.limit = limit.copy();
if (queue == null) {
boolean placeChunks = this.fastmode || this.limit.FAST_PLACEMENT;
World unwrapped = WorldWrapper.unwrap(world);
if (unwrapped instanceof FaweQueue) {
queue = (FaweQueue) unwrapped;
} else if (unwrapped instanceof MCAWorld) {
queue = ((MCAWorld) unwrapped).getQueue();
} else if (player != null && world.equals(player.getWorld())) {
queue = player.getFaweQueue(placeChunks, autoQueue);
} else {
queue = SetQueue.IMP.getNewQueue(world, placeChunks, autoQueue);
}
}
if (combineStages == null) {
combineStages =
// If it's enabled in the settings
Settings.IMP.HISTORY.COMBINE_STAGES
// If fast placement is disabled, it's slower to perform a copy on each chunk
&& this.limit.FAST_PLACEMENT
// If the specific queue doesn't support it
&& queue.supports(FaweQueue.Capability.CHANGE_TASKS)
// If the edit uses items from the inventory we can't use a delayed task
&& this.blockBag == null;
}
// if (Settings.IMP.EXPERIMENTAL.ANVIL_QUEUE_MODE && !(queue instanceof MCAQueue)) {
// queue = new MCAQueue(queue);
// }
if (!Settings.IMP.QUEUE.PROGRESS.DISPLAY.equalsIgnoreCase("false") && player != null) {
switch (Settings.IMP.QUEUE.PROGRESS.DISPLAY.toLowerCase()) {
case "chat":
this.queue.setProgressTask(new ChatProgressTracker(player));
break;
case "title":
case "true":
default:
this.queue.setProgressTask(new DefaultProgressTracker(player));
}
}
// this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), eventBus, event, EditSession.Stage.BEFORE_CHANGE);
// this.bypassHistory = (this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER));
// if (!this.fastMode || changeSet != null) {
// if (changeSet == null) {
// if (Settings.IMP.HISTORY.USE_DISK) {
// UUID uuid = player == null ? EditSession.CONSOLE : player.getUUID();
// if (Settings.IMP.HISTORY.USE_DATABASE) {
// changeSet = new RollbackOptimizedHistory(world, uuid);
// } else {
// changeSet = new DiskStorageHistory(world, uuid);
// }
// } else if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) {
// changeSet = new CPUOptimizedChangeSet(world);
// } else {
// changeSet = new MemoryOptimizedHistory(world);
// }
// }
// if (this.limit.SPEED_REDUCTION > 0) {
// this.bypassHistory = new SlowExtent(this.bypassHistory, this.limit.SPEED_REDUCTION);
// }
// if (changeSet instanceof NullChangeSet && Fawe.imp().getBlocksHubApi() != null && player != null) {
// changeSet = LoggingChangeSet.wrap(player, changeSet);
// }
// if (!(changeSet instanceof NullChangeSet)) {
// if (!(changeSet instanceof LoggingChangeSet) && player != null && Fawe.imp().getBlocksHubApi() != null) {
// changeSet = LoggingChangeSet.wrap(player, changeSet);
// }
// if (this.blockBag != null) {
// changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1);
// }
// if (combineStages) {
// changeTask = changeSet;
// changeSet.addChangeTask(queue);
// } else {
// this.extent = (history = new HistoryExtent(this, bypassHistory, changeSet, queue));
//// if (this.blockBag != null) {
//// this.extent = new BlockBagExtent(this.extent, blockBag, limit.INVENTORY_MODE == 1);
//// }
// }
// }
// }
// if (allowedRegions == null) {
// if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(queue instanceof VirtualWorld)) {
// allowedRegions = player.getCurrentRegions();
// }
// }
// this.maxY = getWorld() == null ? 255 : world.getMaxY();
// if (allowedRegions != null) {
// if (allowedRegions.length == 0) {
// this.extent = new NullExtent(this.extent, BBC.WORLDEDIT_CANCEL_REASON_NO_REGION);
// } else {
// this.extent = new ProcessedWEExtent(this.extent, this.limit);
// if (allowedRegions.length == 1) {
// Region region = allowedRegions[0];
// this.extent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]);
// } else {
// this.extent = new MultiRegionExtent(this.extent, this.limit, allowedRegions);
// }
// }
// } else {
// this.extent = new HeightBoundExtent(this.extent, this.limit, 0, maxY);
// }
// if (this.limit.STRIP_NBT != null && !this.limit.STRIP_NBT.isEmpty()) {
// this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT);
// }
// this.extent = wrapExtent(this.extent, bus, event, Stage.BEFORE_HISTORY);
return this;
}
public EditSession build() {
return new EditSession(worldName, world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, eventBus, event);
return new EditSession(worldName, world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, eventBus, event);
}
}

View File

@ -486,7 +486,7 @@ public class TextureUtil implements TextureHolder {
BlockType block = getNearestBlock(color);
TextureUtil.BiomeColor biome = getNearestBiome(color);
int blockColor = getColor(block);
blockAndBiomeIdOutput[0] = block.getInternalId();
blockAndBiomeIdOutput[0] = block.getDefaultState().getOrdinalChar();
blockAndBiomeIdOutput[1] = biome.id;
if (colorDistance(biome.grassCombined, color) - biomePriority > colorDistance(blockColor,
color)) {

View File

@ -235,11 +235,6 @@ public class WorldWrapper extends AbstractWorld {
return parent.getBlock(position);
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return parent.getLazyBlock(position);
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return parent.getFullBlock(position);

View File

@ -42,7 +42,6 @@ import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.boydti.fawe.object.collection.LocalBlockVectorSet;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.FastWorldEditExtent;
@ -61,6 +60,7 @@ import com.boydti.fawe.object.mask.ResettableMask;
import com.boydti.fawe.object.pattern.ExistingPattern;
import com.boydti.fawe.object.progress.ChatProgressTracker;
import com.boydti.fawe.object.progress.DefaultProgressTracker;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.ExtentTraverser;
import com.boydti.fawe.util.MaskTraverser;
import com.boydti.fawe.util.MathMan;
@ -79,28 +79,18 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.MaskingExtent;
import com.sk89q.worldedit.extent.cache.LastAccessExtentCache;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.BlockBagExtent;
import com.sk89q.worldedit.extent.reorder.ChunkBatchingExtent;
import com.sk89q.worldedit.extent.reorder.MultiStageReorder;
import com.sk89q.worldedit.extent.validation.BlockChangeLimiter;
import com.sk89q.worldedit.extent.validation.DataValidatorExtent;
import com.sk89q.worldedit.extent.world.BlockQuirkExtent;
import com.sk89q.worldedit.extent.world.ChunkLoadingExtent;
import com.sk89q.worldedit.extent.world.FastModeExtent;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.RegionMaskingFilter;
import com.sk89q.worldedit.function.block.BlockDistributionCounter;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.block.Naturalizer;
import com.sk89q.worldedit.function.generator.ForestGenerator;
import com.sk89q.worldedit.function.generator.GardenPatchGenerator;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
import com.sk89q.worldedit.function.mask.BlockStateMask;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.mask.BoundedHeightMask;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
@ -116,7 +106,6 @@ import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.WaterloggedRemover;
import com.sk89q.worldedit.function.util.RegionOffset;
import com.sk89q.worldedit.function.visitor.DirectionalVisitor;
import com.sk89q.worldedit.function.visitor.DownwardVisitor;
@ -127,12 +116,10 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.history.UndoContext;
import com.sk89q.worldedit.history.change.BlockChange;
import com.sk89q.worldedit.history.changeset.BlockOptimizedHistory;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.internal.expression.runtime.ExpressionTimeoutException;
import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.math.BlockVector2;
@ -142,7 +129,6 @@ import com.sk89q.worldedit.math.MutableBlockVector2;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.math.Vector2;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.interpolation.Interpolation;
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
import com.sk89q.worldedit.math.interpolation.Node;
import com.sk89q.worldedit.math.noise.RandomNoise;
@ -159,21 +145,30 @@ import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.collection.DoubleArrayList;
import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.NullWorld;
import com.sk89q.worldedit.world.SimpleWorld;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.*;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockID;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.weather.WeatherType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import static com.google.common.base.Preconditions.checkArgument;
@ -204,19 +199,19 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
BEFORE_CHANGE
}
private World world;
private String worldName;
private FaweQueue queue;
private boolean wrapped;
private boolean fastMode;
private AbstractDelegateExtent extent;
private HistoryExtent history;
private AbstractDelegateExtent bypassHistory;
private AbstractDelegateExtent bypassAll;
private FaweLimit originalLimit;
private FaweLimit limit;
private FawePlayer player;
private FaweChangeSet changeTask;
private final World world;
private final String worldName;
private final FaweQueue queue;
private final boolean wrapped;
private final boolean fastMode;
private final AbstractDelegateExtent extent;
private final HistoryExtent history;
private final AbstractDelegateExtent bypassHistory;
private final AbstractDelegateExtent bypassAll;
private final FaweLimit originalLimit;
private final FaweLimit limit;
private final FawePlayer player;
private final FaweChangeSet changeTask;
private MutableBlockVector3 mutablebv = new MutableBlockVector3();
@ -249,7 +244,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
if (event == null) {
event = new EditSessionEvent(world, player == null ? null : (player.getPlayer()), -1, null);
}
event.setEditSession(this);
if (player == null && event.getActor() != null) {
player = FawePlayer.wrap(event.getActor());
}
@ -393,7 +387,10 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT);
}
this.extent = wrapExtent(this.extent, bus, event, Stage.BEFORE_HISTORY);
setExtent(this.extent);
}
public EditSession(EditSessionBuilder builder) {
super(builder.)
}
/**
@ -496,15 +493,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
return bypassHistory;
}
public Extent getExtent() {
return extent;
}
public void setExtent(AbstractDelegateExtent extent) {
this.extent = extent;
new ExtentTraverser(this).setNext(extent);
}
/**
* Get the FawePlayer or null
*
@ -1057,17 +1045,8 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
return queue.getOpacity(x, y, z);
}
@Override
public BlockState getLazyBlock(final BlockVector3 position) {
return getLazyBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ());
}
public BlockState getLazyBlock(int x, int y, int z) {
return extent.getLazyBlock(x, y, z);
}
public BlockState getBlock(int x, int y, int z) {
return getLazyBlock(x, y, z);
return extent.getBlock(x, y, z);
}
@Override
@ -1085,7 +1064,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
*
* @param position the position
* @return the block type
* @deprecated Use {@link #getLazyBlock(BlockVector3)} or {@link #getBlock(BlockVector3)}
* @deprecated Use {@link #getBlock(BlockVector3)} or {@link #getBlock(BlockVector3)}
*/
@Deprecated
public BlockType getBlockType(final BlockVector3 position) {
@ -1099,7 +1078,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
* @param z the Z coordinate
* @param minY minimal height
* @param maxY maximal height
* @param filter a mask of blocks to consider, or null to consider any solid (movement-blocking) block
* @return height of highest block found or 'minY'
*/
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
@ -2918,11 +2896,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
* Generate a shape for the given expression.
*
* @param region the region to generate the shape in
* @param zero the coordinate origin for x/y/z variables
* @param unit the scale of the x/y/z/ variables
* @param pattern the default material to make the shape from
* @param expressionString the expression defining the shape
* @param hollow whether the shape should be hollow
* @return number of blocks changed
* @throws ExpressionException
* @throws MaxChangedBlocksException
@ -3433,8 +3406,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
CompoundTag nbt = block.getNbtData();
if (nbt != null) {
if (nbt.containsKey("items")) {
block.setNbtData(null);
return setBlock(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), block);
return setBlock(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), block.toBlockState().toBaseBlock());
}
}
return false;

View File

@ -49,7 +49,7 @@ public class AreaPickaxe implements BlockTool {
for (int x = ox - range; x <= ox + range; ++x) {
for (int z = oz - range; z <= oz + range; ++z) {
for (int y = oy + range; y >= oy - range; --y) {
if (initialType.equals(editSession.getLazyBlock(x, y, z))) {
if (initialType.equals(editSession.getBlock(x, y, z))) {
continue;
}
editSession.setBlock(x, y, z, BlockTypes.AIR.getDefaultState());

View File

@ -49,7 +49,7 @@ public class GravityBrush implements Brush {
for (int z = position.getBlockZ() + size; z > position.getBlockZ() - size; --z) {
int freeSpot = startCheckY;
for (int y = startCheckY; y <= endY; y++) {
BlockStateHolder block = editSession.getLazyBlock(x, y, z);
BlockStateHolder block = editSession.getBlock(x, y, z);
if (!block.getBlockType().getMaterial().isAir()) {
if (y != freeSpot) {
editSession.setBlock(x, y, z, EditSession.nullBlock);

View File

@ -66,7 +66,6 @@ public class EditSessionEvent extends Event implements Cancellable {
private final int maxBlocks;
private final Stage stage;
private Extent extent;
private EditSession session;
private boolean cancelled;
/**
@ -84,14 +83,6 @@ public class EditSessionEvent extends Event implements Cancellable {
this.stage = stage;
}
public void setEditSession(EditSession session) {
this.session = session;
}
public EditSession getEditSession() {
return session;
}
/**
* Get the actor for this event.
*
@ -169,9 +160,7 @@ public class EditSessionEvent extends Event implements Cancellable {
* @return a new event
*/
public EditSessionEvent clone(Stage stage) {
EditSessionEvent clone = new EditSessionEvent(world, actor, maxBlocks, stage);
clone.setEditSession(session);
return clone;
return new EditSessionEvent(world, actor, maxBlocks, stage);
}

View File

@ -22,8 +22,6 @@ package com.sk89q.worldedit.extent;
import com.boydti.fawe.jnbt.anvil.generator.GenBase;
import com.boydti.fawe.jnbt.anvil.generator.Resource;
import com.boydti.fawe.object.extent.LightingExtent;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -41,29 +39,40 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.util.List;
import javax.annotation.Nullable;
import java.util.List;
public class AbstractDelegateExtent implements LightingExtent {
private transient final Extent extent;
protected MutableBlockVector3 mutable = new MutableBlockVector3(0, 0, 0);
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Create a new instance.
*
* @param extent the extent
*/
public AbstractDelegateExtent(Extent extent) {
checkNotNull(extent);
this.extent = extent;
public class AbstractDelegateExtent implements Extent, LightingExtent {
private final Extent extent;
public AbstractDelegateExtent(Extent parent) {
this.extent = parent;
}
public int getSkyLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getSkyLight(x, y, z);
}
return 0;
/**
* Get the extent.
*
* @return the extent
*/
public final Extent getExtent() {
return extent;
}
/*
Bounds
*/
@Override
public BlockVector3 getMinimumPoint() {
return extent.getMinimumPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return extent.getMaximumPoint();
}
@Override
@ -71,11 +80,40 @@ public class AbstractDelegateExtent implements LightingExtent {
return extent.getMaxY();
}
/*
Input + Output
*/
@Override
public BlockType getBlockType(BlockVector3 position) {
return extent.getBlockType(position);
public BlockState getBlock(int x, int y, int z) {
return extent.getBlock(x, y, z);
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
return extent.getFullBlock(x, y, z);
}
@Override
public BiomeType getBiome(int x, int z) {
return extent.getBiome(x, z);
}
@Override
public boolean setBiome(int x, int z, BiomeType biome) {
return extent.setBiome(x, z, biome);
}
/*
Light
*/
public int getSkyLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getSkyLight(x, y, z);
}
return 0;
}
public int getBlockLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
@ -88,7 +126,7 @@ public class AbstractDelegateExtent implements LightingExtent {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getOpacity(x, y, z);
}
return getLazyBlock(x, y, z).getBlockType().getMaterial().getLightOpacity();
return getBlock(x, y, z).getBlockType().getMaterial().getLightOpacity();
}
@Override
@ -103,164 +141,20 @@ public class AbstractDelegateExtent implements LightingExtent {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getBrightness(x, y, z);
}
return getLazyBlock(x, y, z).getBlockType().getMaterial().getLightValue();
return getBlock(x, y, z).getBlockType().getMaterial().getLightValue();
}
/**
* Get the extent.
*
* @return the extent
/*
Generic
*/
public Extent getExtent() {
return extent;
}
@Override
public BlockState getLazyBlock(int x, int y, int z) {
return extent.getLazyBlock(mutable.setComponents(x, y, z));
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return extent.getLazyBlock(position);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
return setBlock(mutable.setComponents(x, y, z), block);
}
public BlockState getBlock(BlockVector3 position) {
return extent.getBlock(position);
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return extent.getFullBlock(position);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
return extent.setBlock(location, block);
}
@Override
@Nullable
public Entity createEntity(Location location, BaseEntity entity) {
return extent.createEntity(location, entity);
}
@Override
public List<? extends Entity> getEntities() {
return extent.getEntities();
}
@Override
public List<? extends Entity> getEntities(Region region) {
return extent.getEntities(region);
}
@Override
public BiomeType getBiome(BlockVector2 position) {
return extent.getBiome(position);
}
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return extent.setBiome(position, biome);
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
return extent.setBiome(x, y, z, biome);
}
@Override
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
return extent.getHighestTerrainBlock(x, z, minY, maxY);
}
@Override
public BlockVector3 getMinimumPoint() {
return extent.getMinimumPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return extent.getMaximumPoint();
}
protected Operation commitBefore() {
return null;
}
@Override
public String toString() {
return super.toString() + ":" + extent.toString();
}
@Override
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceLayer(x, z, y, minY, maxY);
}
@Override
public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) {
return extent.getHighestTerrainBlock(x, z, minY, maxY, filter);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
}
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, boolean ignoreAir) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
}
@Override
public void addCaves(Region region) throws WorldEditException {
extent.addCaves(region);
}
@Override
public void generate(Region region, GenBase gen) throws WorldEditException {
extent.generate(region, gen);
}
@Override
public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException {
extent.spawnResource(region, gen, rarity, frequency);
}
@Override
public boolean contains(BlockVector3 pt) {
return extent.contains(pt);
}
@Override
public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
extent.addOre(region, mask, material, size, frequency, rarity, minY, maxY);
}
@Override
public void addOres(Region region, Mask mask) throws WorldEditException {
extent.addOres(region, mask);
protected Operation commitBefore() {
return null;
}
@Override
@ -279,6 +173,4 @@ public class AbstractDelegateExtent implements LightingExtent {
return null;
}
}
}

View File

@ -117,33 +117,11 @@ public interface Extent extends InputExtent, OutputExtent {
return null;
}
@Override
default BlockState getBlock(BlockVector3 position) {
return getFullBlock(position).toImmutableState();
}
@Override
default BlockState getLazyBlock(BlockVector3 position) {
return getFullBlock(position).toImmutableState();
}
default BlockState getLazyBlock(int x, int y, int z) {
return getLazyBlock(BlockVector3.at(x, y, z));
}
default <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T state) throws WorldEditException {
return setBlock(BlockVector3.at(x, y, z), state);
}
default boolean setBiome(int x, int y, int z, BiomeType biome) {
return setBiome(BlockVector2.at(x, z), biome);
}
default int getHighestTerrainBlock(final int x, final int z, int minY, int maxY) {
maxY = Math.min(maxY, Math.max(0, maxY));
minY = Math.max(0, minY);
for (int y = maxY; y >= minY; --y) {
BlockState block = getLazyBlock(x, y, z);
BlockState block = getBlock(x, y, z);
if (block.getBlockType().getMaterial().isMovementBlocker()) {
return y;
}
@ -167,20 +145,20 @@ public interface Extent extends InputExtent, OutputExtent {
int clearanceBelow = y - minY;
int clearance = Math.min(clearanceAbove, clearanceBelow);
BlockState block = getLazyBlock(x, y, z);
BlockState block = getBlock(x, y, z);
boolean state = !block.getBlockType().getMaterial().isMovementBlocker();
int data1 = PropertyGroup.LEVEL.get(block);
int data2 = data1;
int offset = state ? 0 : 1;
for (int d = 0; d <= clearance; d++) {
int y1 = y + d;
block = getLazyBlock(x, y1, z);
block = getBlock(x, y1, z);
if (!block.getBlockType().getMaterial().isMovementBlocker() != state) {
return ((y1 - offset) << 4) - (15 - (state ? PropertyGroup.LEVEL.get(block) : data1));
}
data1 = PropertyGroup.LEVEL.get(block);
int y2 = y - d;
block = getLazyBlock(x, y2, z);
block = getBlock(x, y2, z);
if (!block.getBlockType().getMaterial().isMovementBlocker() != state) {
return ((y2 + offset) << 4) - (15 - (state ? PropertyGroup.LEVEL.get(block) : data2));
}
@ -189,7 +167,7 @@ public interface Extent extends InputExtent, OutputExtent {
if (clearanceAbove != clearanceBelow) {
if (clearanceAbove < clearanceBelow) {
for (int layer = y - clearance - 1; layer >= minY; layer--) {
block = getLazyBlock(x, layer, z);
block = getBlock(x, layer, z);
if (!block.getBlockType().getMaterial().isMovementBlocker() != state) {
int data = (state ? PropertyGroup.LEVEL.get(block) : data1);
return ((layer + offset) << 4) + 0;
@ -198,7 +176,7 @@ public interface Extent extends InputExtent, OutputExtent {
}
} else {
for (int layer = y + clearance + 1; layer <= maxY; layer++) {
block = getLazyBlock(x, layer, z);
block = getBlock(x, layer, z);
if (!block.getBlockType().getMaterial().isMovementBlocker() != state) {
return ((layer - offset) << 4) - (15 - (state ? PropertyGroup.LEVEL.get(block) : data2));
}
@ -254,33 +232,33 @@ public interface Extent extends InputExtent, OutputExtent {
int clearanceAbove = maxY - y;
int clearanceBelow = y - minY;
int clearance = Math.min(clearanceAbove, clearanceBelow);
BlockStateHolder block = getLazyBlock(x, y, z);
BlockStateHolder block = getBlock(x, y, z);
boolean state = !block.getBlockType().getMaterial().isMovementBlocker();
int offset = state ? 0 : 1;
for (int d = 0; d <= clearance; d++) {
int y1 = y + d;
block = getLazyBlock(x, y1, z);
block = getBlock(x, y1, z);
if (!block.getMaterial().isMovementBlocker() != state && block.getBlockType() != BlockTypes.__RESERVED__) return y1 - offset;
int y2 = y - d;
block = getLazyBlock(x, y2, z);
block = getBlock(x, y2, z);
if (!block.getMaterial().isMovementBlocker() != state && block.getBlockType() != BlockTypes.__RESERVED__) return y2 + offset;
}
if (clearanceAbove != clearanceBelow) {
if (clearanceAbove < clearanceBelow) {
for (int layer = y - clearance - 1; layer >= minY; layer--) {
block = getLazyBlock(x, layer, z);
block = getBlock(x, layer, z);
if (!block.getMaterial().isMovementBlocker() != state && block.getBlockType() != BlockTypes.__RESERVED__) return layer + offset;
}
} else {
for (int layer = y + clearance + 1; layer <= maxY; layer++) {
block = getLazyBlock(x, layer, z);
block = getBlock(x, layer, z);
if (!block.getMaterial().isMovementBlocker() != state && block.getBlockType() != BlockTypes.__RESERVED__) return layer - offset;
}
}
}
int result = state ? failedMin : failedMax;
if(result > 0 && !ignoreAir) {
block = getLazyBlock(x, result, z);
block = getBlock(x, result, z);
return block.getBlockType().getMaterial().isAir() ? -1 : result;
}
return result;
@ -296,7 +274,7 @@ public interface Extent extends InputExtent, OutputExtent {
}
}
default public void addSchems(Region region, Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException {
default void addSchems(Region region, Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException {
spawnResource(region, new SchemGen(mask, this, clipboards, rotate), rarity, 1);
}
@ -320,11 +298,11 @@ public interface Extent extends InputExtent, OutputExtent {
return (pt.containedWithin(min, max));
}
default public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
default void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
spawnResource(region, new OreGen(this, mask, material, size, minY, maxY), rarity, frequency);
}
default public void addOres(Region region, Mask mask) throws WorldEditException {
default void addOres(Region region, Mask mask) throws WorldEditException {
addOre(region, mask, BlockTypes.DIRT.getDefaultState(), 33, 10, 100, 0, 255);
addOre(region, mask, BlockTypes.GRAVEL.getDefaultState(), 33, 8, 100, 0, 255);
addOre(region, mask, BlockTypes.ANDESITE.getDefaultState(), 33, 10, 100, 0, 79);

View File

@ -22,6 +22,8 @@ package com.sk89q.worldedit.extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableBlockVector2;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -46,42 +48,31 @@ public interface InputExtent {
* @param position position of the block
* @return the block
*/
BlockState getBlock(BlockVector3 position);
default BlockState getBlock(BlockVector3 position) {
return getBlock(position.getX(), position.getY(), position.getZ());
}
default BlockState getBlock(int x, int y, int z) {
return getBlock(MutableBlockVector3.get(x, y, z));
}
default BlockType getBlockType(BlockVector3 position) {
return getBlock(position).getBlockType();
}
/**
* Get a lazy, immutable snapshot of the block at the given location that only
* immediately contains information about the block's type (and metadata).
*
* <p>Further information (such as NBT data) will be available <strong>by the
* time of access</strong>. Therefore, it is not recommended that
* this method is used if the world is being simulated at the time of
* call. If the block needs to be stored for future use, then this method should
* definitely not be used. Moreover, the block that is returned is immutable (or
* should be), and therefore modifications should not be attempted on it. If a
* modifiable copy is required, then the block should be cloned.</p>
*
* <p>This method exists because it is sometimes important to inspect the block
* at a given location, but {@link #getBlock(Vector)} may be too expensive in
* the underlying implementation. It is also not possible to implement
* caching if the returned object is mutable, so this methods allows caching
* implementations to be used.</p>
*
* @param position position of the block
* @return the block
*/
BlockState getLazyBlock(BlockVector3 position);
/**
* Get a immutable snapshot of the block at the given location.
*
* @param position position of the block
* @return the block
*/
BaseBlock getFullBlock(BlockVector3 position);
default BaseBlock getFullBlock(BlockVector3 position) {
return getFullBlock(position.getX(), position.getY(), position.getZ());
}
default BaseBlock getFullBlock(int x, int y, int z) {
return getFullBlock(MutableBlockVector3.get(x, y, z));
}
/**
* Get the biome at the given location.
@ -92,6 +83,11 @@ public interface InputExtent {
* @param position the (x, z) location to check the biome at
* @return the biome at the location
*/
BiomeType getBiome(BlockVector2 position);
default BiomeType getBiome(BlockVector2 position) {
return getBiome(position.getX(), position.getZ());
}
default BiomeType getBiome(int x, int z) {
return getBiome(MutableBlockVector2.get(x, z));
}
}

View File

@ -23,6 +23,8 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableBlockVector2;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -50,7 +52,13 @@ public interface OutputExtent {
* @return true if the block was successfully set (return value may not be accurate)
* @throws WorldEditException thrown on an error
*/
<T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) throws WorldEditException;
default <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) throws WorldEditException {
return setBlock(position.getX(), position.getY(), position.getZ(), block);
}
default <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
return setBlock(MutableBlockVector3.get(x, y, z), block);
}
/**
* Set the biome.
@ -59,7 +67,13 @@ public interface OutputExtent {
* @param biome the biome to set to
* @return true if the biome was successfully set (return value may not be accurate)
*/
boolean setBiome(BlockVector2 position, BiomeType biome);
default boolean setBiome(BlockVector2 position, BiomeType biome) {
return setBiome(position.getX(), 0, position.getBlockZ(), biome);
}
default boolean setBiome(int x, int y, int z, BiomeType biome) {
return setBiome(MutableBlockVector2.get(x, z), biome);
}
/**
* Return an {@link Operation} that should be called to tie up loose ends

View File

@ -0,0 +1,177 @@
package com.sk89q.worldedit.extent;
import com.boydti.fawe.jnbt.anvil.generator.GenBase;
import com.boydti.fawe.jnbt.anvil.generator.Resource;
import com.boydti.fawe.object.extent.LightingExtent;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.Location;
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.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import javax.annotation.Nullable;
import java.util.List;
public class PassthroughExtent extends AbstractDelegateExtent {
private final Extent extent;
public PassthroughExtent(Extent parent) {
super(parent);
this.extent = parent;
}
@Override
public List<? extends Entity> getEntities(Region region) {
return extent.getEntities(region);
}
@Override
public List<? extends Entity> getEntities() {
return extent.getEntities();
}
@Override
@Nullable
public Entity createEntity(Location location, BaseEntity entity) {
return extent.createEntity(location, entity);
}
@Override
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
return extent.getHighestTerrainBlock(x, z, minY, maxY);
}
@Override
public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) {
return extent.getHighestTerrainBlock(x, z, minY, maxY, filter);
}
@Override
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceLayer(x, z, y, minY, maxY);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, boolean ignoreAir) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
}
@Override
public void addCaves(Region region) throws WorldEditException {
extent.addCaves(region);
}
@Override
public void generate(Region region, GenBase gen) throws WorldEditException {
extent.generate(region, gen);
}
@Override
public void addSchems(Region region, Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException {
extent.addSchems(region, mask, clipboards, rarity, rotate);
}
@Override
public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException {
extent.spawnResource(region, gen, rarity, frequency);
}
@Override
public boolean contains(BlockVector3 pt) {
return extent.contains(pt);
}
@Override
public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
extent.addOre(region, mask, material, size, frequency, rarity, minY, maxY);
}
@Override
public void addOres(Region region, Mask mask) throws WorldEditException {
extent.addOres(region, mask);
}
@Override
public List<Countable<BlockType>> getBlockDistribution(Region region) {
return extent.getBlockDistribution(region);
}
@Override
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
return extent.getBlockDistributionWithData(region);
}
@Override
public BlockArrayClipboard lazyCopy(Region region) {
return extent.lazyCopy(region);
}
@Override
public BlockState getBlock(BlockVector3 position) {
return extent.getBlock(position);
}
@Override
public BlockType getBlockType(BlockVector3 position) {
return extent.getBlockType(position);
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return extent.getFullBlock(position);
}
@Override
public BiomeType getBiome(BlockVector2 position) {
return extent.getBiome(position);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) throws WorldEditException {
return extent.setBlock(position, block);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
return extent.setBlock(x, y, z, block);
}
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return extent.setBiome(position, biome);
}
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.function.mask;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.math.BlockVector3;
@ -42,6 +43,8 @@ public interface Mask {
*/
boolean test(BlockVector3 vector);
// boolean test(FilterBlock block);
/**
* Get the 2D version of this mask if one exists.
*

View File

@ -16,17 +16,17 @@ import com.sk89q.worldedit.world.block.BlockState;
*/
@Link(clazz = UtilityCommands.class, value = "patterns")
public interface FawePattern extends Pattern {
@Deprecated
default BaseBlock apply(BlockVector3 position) {
throw new UnsupportedOperationException("Please use apply(extent, get, set)");
}
/**
* Return a {@link BlockStateHolder} for the given position.
*
* @return a block
*/
@Override
boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException;
//
// @Deprecated
// default BaseBlock apply(BlockVector3 position) {
// throw new UnsupportedOperationException("Please use apply(extent, get, set)");
// }
//
// /**
// * Return a {@link BlockStateHolder} for the given position.
// *
// * @return a block
// */
// @Override
// boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException;
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.function.pattern;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.UtilityCommands;
@ -26,23 +27,12 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockState;
/**
* Returns a {@link BlockStateHolder} for a given position.
*/
@Link(clazz = UtilityCommands.class, value = "patterns")
public interface Pattern{
// @Override
// default BaseBlock next(BlockVector3 position) {
// return new BaseBlock(apply(position));
// }
//
// @Override
// default BaseBlock next(int x, int y, int z) {
// return new BaseBlock(apply(BlockVector3.at(x, y, z)));
// }
public interface Pattern {
/**
* Return a {@link BlockStateHolder} for the given position.
@ -55,4 +45,10 @@ public interface Pattern{
default boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return extent.setBlock(set, apply(get));
}
// void apply(FilterBlock block);
default void apply(FilterBlock block) {
apply((BlockVector3) block).apply(block);
}
}

View File

@ -1,23 +1,19 @@
package com.sk89q.worldedit.function.visitor;
import com.boydti.fawe.example.MappedFaweQueue;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HasFaweQueue;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.math.BlockVector3;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* A chunk based search algorithm
@ -58,15 +54,15 @@ public class ScanChunk {
private final RegionFunction function;
private final BlockVector3[] directions;
private final Long2ObjectOpenHashMap<long[][]> visited;
private final Long2ObjectOpenHashMap<char[]> queues;
private final Long2ObjectOpenHashMap<long[][]> visits;
private final Long2ObjectOpenHashMap<char[][]> queues;
public ScanChunk(final RegionFunction function) {
this.function = function;
this.directions = DEFAULT_DIRECTIONS;
this.queues = new Long2ObjectOpenHashMap<>();
this.visited = new Long2ObjectOpenHashMap<>();
this.visits = new Long2ObjectOpenHashMap<>();
}
public static final long pairInt(int x, int y) {
@ -77,7 +73,7 @@ public class ScanChunk {
int X = x >> 4;
int Z = z >> 4;
long pair = pairInt(X, Z);
long[][] chunk = visited.get(pair);
long[][] chunk = visits.get(pair);
if (chunk == null) return false;
int layer = y >> 4;
long[] section = chunk[layer];
@ -87,7 +83,7 @@ public class ScanChunk {
public void start(int x, int y, int z) {
if (!isVisited(x, y, z)) {
queue(x, y, z);
push(x, y, z);
visit(x, y, z);
}
}
@ -96,45 +92,240 @@ public class ScanChunk {
int X = x >> 4;
int Z = z >> 4;
long pair = pairInt(X, Z);
long[][] chunk = visited.get(pair);
if (chunk == null) {
visited.put(pair, chunk = new long[16][]);
long[][] arrs = visits.get(pair);
if (arrs == null) {
visits.put(pair, arrs = new long[16][]);
}
int layer = y >> 4;
long[] section = chunk[layer];
long[] section = arrs[layer];
if (section == null) {
chunk[layer] = section = new long[64];
arrs[layer] = section = new long[64];
}
set(section, getLocalIndex(x & 15, y & 15, z & 15));
}
public void queue(int x, int y, int z) {
private char[] getOrCreateQueue(long pair, int layer) {
char[][] arrs = queues.get(pair);
if (arrs == null) {
queues.put(pair, arrs = new char[16][]);
}
char[] section = arrs[layer];
if (section == null) {
arrs[layer] = section = newQueue();
}
return section;
}
private void push(int x, int y, int z) {
int X = x >> 4;
int Z = z >> 4;
long pair = pairInt(X, Z);
char[] queue = queues.get(pair);
if (queue == null) {
queue = queues.put(pair, queue = new char[MAX_QUEUE + 2]);
queue[0] = 2;
queue[1] = 2;
int layer = y >> 4;
char[] section = getOrCreateQueue(pair, layer);
push(section, x & 15, y & 15, z & 15);
}
private void push(char[] queue, int x, int y, int z) {
char indexStart = queue[0];
char indexEnd = queue[1];
push(indexStart, indexEnd, queue, x, y, z);
}
private void push(char indexStart, char indexEnd, char[] queue, int x, int y, int z) {
char index = getLocalIndex(x, y, z);
if (indexStart > 2) {
queue[0] = --indexStart;
queue[indexStart] = index;
} else {
queue[indexEnd] = index;
queue[0] = ++indexEnd;
}
if (queue[1] >= queue.length) {
queue[1] = 2;
}
queue[queue[1]++] = getLocalIndex(x & 15, y, z & 15);
}
public void process() {
LongArraySet set = new LongArraySet();
while (!queues.isEmpty()) {
ObjectIterator<Long2ObjectMap.Entry<char[]>> iter = queues.long2ObjectEntrySet().fastIterator();
Long2ObjectMap.Entry<char[]> entry = iter.next();
long index = entry.getLongKey();
int X = MathMan.unpairIntX(index);
int Z = MathMan.unpairIntY(index);
// ObjectIterator<Long2ObjectMap.Entry<char[][]>> iter = queues.long2ObjectEntrySet().fastIterator();
// Long2ObjectMap.Entry<char[][]> entry = iter.next();
// long index = entry.getLongKey();
// int X = MathMan.unpairIntX(index);
// int Z = MathMan.unpairIntY(index);
// // check that adjacent chunks aren;t being processed
//
// char[] queue = entry.getValue();
// long[][] visit = visits.get(index);
// if (visit == null) {
// visits.put(index, visit = new long[16][]);
// }
}
}
private ConcurrentLinkedQueue<char[]> queuePool = new ConcurrentLinkedQueue<>();
private char[] newQueue() {
char[] arr = queuePool.poll();
if (arr != null) {
arr[0] = 2;
arr[1] = 2;
return arr;
}
return new char[4096];
}
public void process4(int xx, int yy, int zz, char[] queue, long[] visit) {
char index;
while ((index = queue[0]) != queue[1]) {
queue[0]++;
char triple = queue[index];
int x = index & 15;
int z = (index >> 4) & 15;
int y = index >> 8;
int absX = xx + x;
int absY = yy + y;
int absZ = zz + z;
apply(xx + x, yy + y, zz + z);
int x1 = x, x2 = x;
// find start of scan-line
int i1 = index;
while (true) {
if (x1 < 0) {
// queue in west chunk
break;
}
if (get(visit, i1)) break;
// visit
set(visit, i1);
i1--;
x1--;
}
i1++;
x1++;
// find end of scan-line
int i2 = index;
while (true) {
if (x2 > 15) {
// queue in east chunk
break;
}
if (get(visit, i2)) break;
set(visit, i2);
i2++;
x2++;
}
i2--;
x2--;
// find start
}
}
public void apply(int x, int y, int z) {
}
public void process4(int X, int Z, char[][] queues, long[][] visit) {
int xx = X << 4;
int zz = Z << 4;
// TODO fetch instead of create
final BlockVector3[] dirs = directions;
char[][] dirQueues = new char[directions.length][];
while (true) {
boolean empty = true;
for (int layer = 0; layer < 16; layer++) {
char[] queue = queues[layer];
if (queue == null) continue;
char index;
while ((index = queue[0]) != queue[1]) {
queue[0]++;
char triple = queue[index];
int x = index & 15;
int z = (index >> 4) & 15;
int y = index >> 8;
}
queuePool.add(queue);
queues[layer] = null;
continue;
}
if (empty) break;
}
// empty queues
// while (indexStart != indexEnd) {
// char index = queue[indexStart++];
// byte dirs = 0xF;
// int x = index & 15;
// int z = (index >> 4) & 15;
// int y = index >> 8;
//
// int layer = y >> 4;
// long[] visitBits = visit[layer];
//
// int x1 = x;
// int x2 = x;
//
// // find start of scan-line
// int i1 = index;
// while (true) {
// if (x1 < 0) {
// // queue in adjacent chunk
// break;
// }
// if (get(visitBits, i1--)) break;
// x1--;
// }
// i1++;
// x1++;
//
// // find end of scan-line
// int i2 = index;
// while (true) {
// if (x2 > 15) {
// // queue in adjacent chunk
// break;
// }
// if (get(visitBits, i2++)) break;
// x2++;
// }
// i2--;
// x2--;
//
// boolean scanUp = false;
// boolean scanDown = false;
// boolean scanLeft = false;
// boolean scanRight = false;
//
// for (int i = i1; i <= i2; i++) {
// if (!scanDown && y > 0 && )
// }
//
// for (int i=x1; i<=x2; i++) { // find scan-lines above this one
// if (!inScanLine && y>0 && ip.getPixel(i,y-1)==color)
// {push(i, y-1); inScanLine = true;}
// else if (inScanLine && y>0 && ip.getPixel(i,y-1)!=color)
// inScanLine = false;
// }
//
// inScanLine = false;
// for (int i=x1; i<=x2; i++) { // find scan-lines below this one
// if (!inScanLine && y<height-1 && ip.getPixel(i,y+1)==color)
// {push(i, y+1); inScanLine = true;}
// else if (inScanLine && y<height-1 && ip.getPixel(i,y+1)!=color)
// inScanLine = false;
// }
// }
}
public void set(long[] bits, int i) {
bits[i >> 6] |= (1L << (i & 0x3F));
}
@ -144,7 +335,7 @@ public class ScanChunk {
}
public char getLocalIndex(int x, int y, int z) {
return (char) (y + (x << 8) + (z << 12));
return (char) (x + (z << 4) + (y << 8));
}

View File

@ -29,58 +29,36 @@ import java.util.Comparator;
/**
* An immutable 3-dimensional vector.
*/
public class BlockVector3 {
public abstract class BlockVector3 {
public static final BlockVector3 ZERO = new BlockVector3(0, 0, 0);
public static final BlockVector3 UNIT_X = new BlockVector3(1, 0, 0);
public static final BlockVector3 UNIT_Y = new BlockVector3(0, 1, 0);
public static final BlockVector3 UNIT_Z = new BlockVector3(0, 0, 1);
public static final BlockVector3 ONE = new BlockVector3(1, 1, 1);
public static final BlockVector3 ZERO = new BlockVector3Imp(0, 0, 0);
public static final BlockVector3 UNIT_X = new BlockVector3Imp(1, 0, 0);
public static final BlockVector3 UNIT_Y = new BlockVector3Imp(0, 1, 0);
public static final BlockVector3 UNIT_Z = new BlockVector3Imp(0, 0, 1);
public static final BlockVector3 ONE = new BlockVector3Imp(1, 1, 1);
public static BlockVector3 at(double x, double y, double z) {
return at((int) Math.floor(x), (int) Math.floor(y), (int) Math.floor(z));
}
public static BlockVector3 at(int x, int y, int z) {
return new BlockVector3(x, y, z);
return new BlockVector3Imp(x, y, z);
}
// thread-safe initialization idiom
private static final class YzxOrderComparator {
private static final Comparator<BlockVector3> YZX_ORDER = (a, b) -> {
return ComparisonChain.start()
.compare(a.y, b.y)
.compare(a.z, b.z)
.compare(a.x, b.x)
.result();
};
}
static final Comparator<BlockVector3> YZX_ORDER = (a, b) -> ComparisonChain.start()
.compare(a.getY(), b.getY())
.compare(a.getZ(), b.getZ())
.compare(a.getX(), b.getX())
.result();
/**
* Returns a comparator that sorts vectors first by Y, then Z, then X.
*
*
* <p>
* Useful for sorting by chunk block storage order.
*/
public static Comparator<BlockVector3> sortByCoordsYzx() {
return YzxOrderComparator.YZX_ORDER;
}
protected int x, y, z;
protected BlockVector3(){}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
protected BlockVector3(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
return YZX_ORDER;
}
public MutableBlockVector3 setComponents(double x, double y, double z) {
@ -92,27 +70,27 @@ public class BlockVector3 {
}
public MutableBlockVector3 mutX(double x) {
return new MutableBlockVector3((int) x, y, z);
return new MutableBlockVector3((int) x, getY(), getZ());
}
public MutableBlockVector3 mutY(double y) {
return new MutableBlockVector3(x, (int) y, z);
return new MutableBlockVector3(getX(), (int) y, getZ());
}
public MutableBlockVector3 mutZ(double z) {
return new MutableBlockVector3(x, y, (int) z);
return new MutableBlockVector3(getX(), getY(), (int) z);
}
public MutableBlockVector3 mutX(int x) {
return new MutableBlockVector3(x, y, z);
return new MutableBlockVector3(x, getY(), getZ());
}
public MutableBlockVector3 mutY(int y) {
return new MutableBlockVector3(x, y, z);
return new MutableBlockVector3(getX(), y, getZ());
}
public MutableBlockVector3 mutZ(int z) {
return new MutableBlockVector3(x, y, z);
return new MutableBlockVector3(getX(), getY(), z);
}
/**
@ -120,9 +98,7 @@ public class BlockVector3 {
*
* @return the x coordinate
*/
public int getX() {
return x;
}
public abstract int getX();
/**
* Get the X coordinate.
@ -130,7 +106,7 @@ public class BlockVector3 {
* @return the x coordinate
*/
public int getBlockX() {
return x;
return getX();
}
/**
@ -140,7 +116,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 withX(int x) {
return BlockVector3.at(x, y, z);
return BlockVector3.at(x, getY(), getZ());
}
/**
@ -148,9 +124,7 @@ public class BlockVector3 {
*
* @return the y coordinate
*/
public int getY() {
return y;
}
public abstract int getY();
/**
* Get the Y coordinate.
@ -158,7 +132,7 @@ public class BlockVector3 {
* @return the y coordinate
*/
public int getBlockY() {
return y;
return getY();
}
/**
@ -168,7 +142,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 withY(int y) {
return BlockVector3.at(x, y, z);
return BlockVector3.at(getX(), y, getZ());
}
/**
@ -176,9 +150,7 @@ public class BlockVector3 {
*
* @return the z coordinate
*/
public int getZ() {
return z;
}
public abstract int getZ();
/**
* Get the Z coordinate.
@ -186,7 +158,7 @@ public class BlockVector3 {
* @return the z coordinate
*/
public int getBlockZ() {
return z;
return getZ();
}
/**
@ -196,7 +168,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 withZ(int z) {
return BlockVector3.at(x, y, z);
return BlockVector3.at(getX(), getY(), z);
}
/**
@ -206,7 +178,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 add(BlockVector3 other) {
return add(other.x, other.y, other.z);
return add(other.getX(), other.getY(), other.getZ());
}
/**
@ -218,7 +190,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 add(int x, int y, int z) {
return BlockVector3.at(this.x + x, this.y + y, this.z + z);
return BlockVector3.at(this.getX() + x, this.getY() + y, this.getZ() + z);
}
/**
@ -229,12 +201,12 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 add(BlockVector3... others) {
int newX = x, newY = y, newZ = z;
int newX = getX(), newY = getY(), newZ = getZ();
for (BlockVector3 other : others) {
newX += other.x;
newY += other.y;
newZ += other.z;
newX += other.getX();
newY += other.getY();
newZ += other.getZ();
}
return BlockVector3.at(newX, newY, newZ);
@ -248,7 +220,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 subtract(BlockVector3 other) {
return subtract(other.x, other.y, other.z);
return subtract(other.getX(), other.getY(), other.getZ());
}
/**
@ -261,7 +233,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 subtract(int x, int y, int z) {
return BlockVector3.at(this.x - x, this.y - y, this.z - z);
return BlockVector3.at(this.getX() - x, this.getY() - y, this.getZ() - z);
}
/**
@ -272,12 +244,12 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 subtract(BlockVector3... others) {
int newX = x, newY = y, newZ = z;
int newX = getX(), newY = getY(), newZ = getZ();
for (BlockVector3 other : others) {
newX -= other.x;
newY -= other.y;
newZ -= other.z;
newX -= other.getX();
newY -= other.getY();
newZ -= other.getZ();
}
return BlockVector3.at(newX, newY, newZ);
@ -290,7 +262,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 multiply(BlockVector3 other) {
return multiply(other.x, other.y, other.z);
return multiply(other.getX(), other.getY(), other.getZ());
}
/**
@ -302,7 +274,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 multiply(int x, int y, int z) {
return BlockVector3.at(this.x * x, this.y * y, this.z * z);
return BlockVector3.at(this.getX() * x, this.getY() * y, this.getZ() * z);
}
/**
@ -312,12 +284,12 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 multiply(BlockVector3... others) {
int newX = x, newY = y, newZ = z;
int newX = getX(), newY = getY(), newZ = getZ();
for (BlockVector3 other : others) {
newX *= other.x;
newY *= other.y;
newZ *= other.z;
newX *= other.getX();
newY *= other.getY();
newZ *= other.getZ();
}
return BlockVector3.at(newX, newY, newZ);
@ -340,7 +312,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 divide(BlockVector3 other) {
return divide(other.x, other.y, other.z);
return divide(other.getX(), other.getY(), other.getZ());
}
/**
@ -352,7 +324,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 divide(int x, int y, int z) {
return BlockVector3.at(this.x / x, this.y / y, this.z / z);
return BlockVector3.at(this.getX() / x, this.getY() / y, this.getZ() / z);
}
/**
@ -380,7 +352,7 @@ public class BlockVector3 {
* @return length, squared
*/
public int lengthSq() {
return x * x + y * y + z * z;
return getX() * getX() + getY() * getY() + getZ() * getZ();
}
/**
@ -400,9 +372,9 @@ public class BlockVector3 {
* @return distance
*/
public int distanceSq(BlockVector3 other) {
int dx = other.x - x;
int dy = other.y - y;
int dz = other.z - z;
int dx = other.getX() - getX();
int dy = other.getY() - getY();
int dz = other.getZ() - getZ();
return dx * dx + dy * dy + dz * dz;
}
@ -414,9 +386,9 @@ public class BlockVector3 {
*/
public BlockVector3 normalize() {
double len = length();
double x = this.x / len;
double y = this.y / len;
double z = this.z / len;
double x = this.getX() / len;
double y = this.getY() / len;
double z = this.getZ() / len;
return BlockVector3.at(x, y, z);
}
@ -427,7 +399,7 @@ public class BlockVector3 {
* @return the dot product of this and the other vector
*/
public double dot(BlockVector3 other) {
return x * other.x + y * other.y + z * other.z;
return getX() * other.getX() + getY() * other.getY() + getZ() * other.getZ();
}
/**
@ -437,10 +409,10 @@ public class BlockVector3 {
* @return the cross product of this and the other vector
*/
public BlockVector3 cross(BlockVector3 other) {
return new BlockVector3(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
return new BlockVector3Imp(
getY() * other.getZ() - getZ() * other.getY(),
getZ() * other.getX() - getX() * other.getZ(),
getX() * other.getY() - getY() * other.getX()
);
}
@ -452,7 +424,7 @@ public class BlockVector3 {
* @return true if the vector is contained
*/
public boolean containedWithin(BlockVector3 min, BlockVector3 max) {
return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z;
return getX() >= min.getX() && getX() <= max.getX() && getY() >= min.getY() && getY() <= max.getY() && getZ() >= min.getZ() && getZ() <= max.getZ();
}
/**
@ -464,11 +436,11 @@ public class BlockVector3 {
*/
public BlockVector3 clampY(int min, int max) {
checkArgument(min <= max, "minimum cannot be greater than maximum");
if (y < min) {
return BlockVector3.at(x, min, z);
if (getY() < min) {
return BlockVector3.at(getX(), min, getZ());
}
if (y > max) {
return BlockVector3.at(x, max, z);
if (getY() > max) {
return BlockVector3.at(getX(), max, getZ());
}
return this;
}
@ -512,7 +484,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 abs() {
return BlockVector3.at(Math.abs(x), Math.abs(y), Math.abs(z));
return BlockVector3.at(Math.abs(getX()), Math.abs(getY()), Math.abs(getZ()));
}
/**
@ -528,8 +500,8 @@ public class BlockVector3 {
*/
public BlockVector3 transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) {
angle = Math.toRadians(angle);
double x = this.x - aboutX;
double z = this.z - aboutZ;
double x = this.getX() - aboutX;
double z = this.getZ() - aboutZ;
double cos = Math.cos(angle);
double sin = Math.sin(angle);
double x2 = x * cos - z * sin;
@ -537,7 +509,7 @@ public class BlockVector3 {
return BlockVector3.at(
x2 + aboutX + translateX,
y,
getY(),
z2 + aboutZ + translateZ
);
}
@ -583,10 +555,10 @@ public class BlockVector3 {
* @return minimum
*/
public BlockVector3 getMinimum(BlockVector3 v2) {
return new BlockVector3(
Math.min(x, v2.x),
Math.min(y, v2.y),
Math.min(z, v2.z)
return new BlockVector3Imp(
Math.min(getX(), v2.getX()),
Math.min(getY(), v2.getY()),
Math.min(getZ(), v2.getZ())
);
}
@ -597,10 +569,10 @@ public class BlockVector3 {
* @return maximum
*/
public BlockVector3 getMaximum(BlockVector3 v2) {
return new BlockVector3(
Math.max(x, v2.x),
Math.max(y, v2.y),
Math.max(z, v2.z)
return new BlockVector3Imp(
Math.max(getX(), v2.getX()),
Math.max(getY(), v2.getY()),
Math.max(getZ(), v2.getZ())
);
}
@ -610,31 +582,34 @@ public class BlockVector3 {
* @return a new {@link BlockVector2}
*/
public BlockVector2 toBlockVector2() {
return BlockVector2.at(x, z);
return BlockVector2.at(getX(), getZ());
}
public Vector3 toVector3() {
return Vector3.at(x, y, z);
return Vector3.at(getX(), getY(), getZ());
}
@Override
public boolean equals(Object obj) {
public final boolean equals(Object obj) {
if (!(obj instanceof BlockVector3)) {
return false;
}
BlockVector3 other = (BlockVector3) obj;
return other.x == this.x && other.y == this.y && other.z == this.z;
return equals((BlockVector3) obj);
}
public final boolean equals(BlockVector3 other) {
return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this.getZ();
}
@Override
public int hashCode() {
return (x ^ (z << 12)) ^ (y << 24);
return (getX() ^ (getZ() << 12)) ^ (getY() << 24);
}
@Override
public String toString() {
return "(" + x + ", " + y + ", " + z + ")";
return "(" + getX() + ", " + getY() + ", " + getZ() + ")";
}
}

View File

@ -0,0 +1,87 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.math;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.ComparisonChain;
import com.sk89q.worldedit.math.transform.AffineTransform;
import java.util.Comparator;
/**
* An immutable 3-dimensional vector.
*/
public class BlockVector3Imp extends BlockVector3 {
public static final BlockVector3Imp ZERO = new BlockVector3Imp(0, 0, 0);
public static final BlockVector3Imp UNIT_X = new BlockVector3Imp(1, 0, 0);
public static final BlockVector3Imp UNIT_Y = new BlockVector3Imp(0, 1, 0);
public static final BlockVector3Imp UNIT_Z = new BlockVector3Imp(0, 0, 1);
public static final BlockVector3Imp ONE = new BlockVector3Imp(1, 1, 1);
public static BlockVector3Imp at(double x, double y, double z) {
return at((int) Math.floor(x), (int) Math.floor(y), (int) Math.floor(z));
}
public static BlockVector3Imp at(int x, int y, int z) {
return new BlockVector3Imp(x, y, z);
}
private final int x, y, z;
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
protected BlockVector3Imp(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public final int getX() {
return x;
}
@Override
public final int getY() {
return y;
}
@Override
public final int getZ() {
return z;
}
@Override
public int hashCode() {
return (getX() ^ (getZ() << 12)) ^ (getY() << 24);
}
@Override
public String toString() {
return "(" + getX() + ", " + getY() + ", " + getZ() + ")";
}
}

View File

@ -9,6 +9,14 @@ public class MutableBlockVector3 extends BlockVector3 {
}
};
public static MutableBlockVector3 at(double x, double y, double z) {
return at((int) Math.floor(x), (int) Math.floor(y), (int) Math.floor(z));
}
public static MutableBlockVector3 at(int x, int y, int z) {
return new MutableBlockVector3(x, y, z);
}
public static MutableBlockVector3 get(int x, int y, int z) {
return MUTABLE_CACHE.get().setComponents(x, y, z);
}
@ -16,15 +24,19 @@ public class MutableBlockVector3 extends BlockVector3 {
public MutableBlockVector3() {}
public MutableBlockVector3(BlockVector3 other) {
super(other.getX(), other.getY(), other.getZ());
this(other.getX(), other.getY(), other.getZ());
}
public MutableBlockVector3 setComponents(BlockVector3 other) {
return setComponents(other.getBlockX(), other.getBlockY(), other.getBlockZ());
}
private int x,y,z;
public MutableBlockVector3(int x, int y, int z) {
super(x, y, z);
this.x = x;
this.y = y;
this.z = z;
}
@Override
@ -35,6 +47,21 @@ public class MutableBlockVector3 extends BlockVector3 {
return this;
}
@Override
public final int getX() {
return x;
}
@Override
public final int getY() {
return y;
}
@Override
public final int getZ() {
return z;
}
@Override
public MutableBlockVector3 mutX(double x) {
this.x = (int) x;

View File

@ -91,11 +91,6 @@ public abstract class AbstractWorld implements World {
return false;
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return getBlock(position);
}
@Override
public boolean queueBlockBreakEffect(Platform server, BlockVector3 position, BlockType blockType, double priority) {
if (taskId == -1) {

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.world.block;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
@ -47,9 +48,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class BaseBlock implements BlockStateHolder<BaseBlock> {
private final BlockState blockState;
@Nullable
protected CompoundTag nbtData;
private final CompoundTag nbtData;
@Deprecated
public BaseBlock() {
@ -83,6 +82,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
public BaseBlock(BlockState blockState) {
this.blockState = blockState;
nbtData = null;
}
/**
@ -157,7 +157,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
@Override
public void setNbtData(@Nullable CompoundTag nbtData) {
this.nbtData = nbtData;
throw new UnsupportedOperationException("Immutable");
}
/**
@ -202,7 +202,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
}
@Override
public int getOrdinal() {
public final int getOrdinal() {
return blockState.getOrdinal();
}
@ -227,6 +227,10 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
}
}
public BlockState toBlockState() {
return blockState;
}
@Override
public int hashCode() {
return getOrdinal();
@ -246,7 +250,12 @@ public class BaseBlock implements BlockStateHolder<BaseBlock> {
return extent.setBlock(set, this);
}
@Override
@Override
public void apply(FilterBlock block) {
block.setFullBlock(this);
}
@Override
public boolean hasNbtData() {
return this.nbtData != null;
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.world.block;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.object.string.MutableCharSequence;
import com.boydti.fawe.util.StringMan;
@ -62,7 +63,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
this.internalId = internalId;
this.ordinal = ordinal;
this.ordinalChar = (char) ordinal;
this.emptyBaseBlock = new BaseBlock(this);
this.emptyBaseBlock = new ImmutableBaseBlock(this);
}
/**
@ -218,6 +219,11 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
return extent.setBlock(set, this);
}
@Override
public final void apply(FilterBlock block) {
block.setOrdinal(ordinal);
}
@Override
public BaseBlock apply(BlockVector3 position) {
return this.toBaseBlock();
@ -333,7 +339,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
}
@Override
public int getOrdinal() {
public final int getOrdinal() {
return this.ordinal;
}

View File

@ -21,6 +21,7 @@ package com.sk89q.worldedit.world.block;
import static com.google.common.base.Preconditions.checkArgument;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
@ -45,7 +46,7 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class BlockType implements FawePattern {
public final class BlockType implements FawePattern {
private final String id;
private final BlockTypes.Settings settings;
@ -179,7 +180,7 @@ public class BlockType implements FawePattern {
*
* @return The default state
*/
public BlockState getDefaultState() {
public final BlockState getDefaultState() {
return this.settings.defaultState;
}
@ -306,6 +307,11 @@ public class BlockType implements FawePattern {
return this.getDefaultState().toBaseBlock();
}
@Override
public final void apply(FilterBlock block) {
block.setOrdinal(getDefaultState().getOrdinal());
}
public Mask toMask(Extent extent) {
return new SingleBlockTypeMask(extent, this);
}

View File

@ -0,0 +1,28 @@
package com.sk89q.worldedit.world.block;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.jnbt.CompoundTag;
import javax.annotation.Nullable;
public final class ImmutableBaseBlock extends BaseBlock {
public ImmutableBaseBlock(BlockState blockState) {
super(blockState);
}
@Nullable
@Override
public CompoundTag getNbtData() {
return null;
}
@Override
public boolean hasNbtData() {
return false;
}
@Override
public final void apply(FilterBlock block) {
block.setOrdinal(getOrdinal());
}
}