geforkt von Mirrors/FastAsyncWorldEdit
WIP filter patterns
Dieser Commit ist enthalten in:
Ursprung
459629a2f2
Commit
c797dcb194
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -10,7 +10,4 @@ public abstract class DelegateFilter implements IDelegateFilter {
|
||||
public Filter getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Filter fork();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
public interface FilterBlockMask {
|
||||
boolean applyBlock(final FilterBlock block);
|
||||
}
|
192
worldedit-core/src/main/java/com/boydti/fawe/beta/Flood.java
Normale Datei
192
worldedit-core/src/main/java/com/boydti/fawe/beta/Flood.java
Normale Datei
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,32 +29,27 @@ 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.
|
||||
@ -63,24 +58,7 @@ public class BlockVector3 {
|
||||
* 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() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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() + ")";
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren