mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-01 02:46:41 +00:00
WIP filter patterns
This commit is contained in:
@ -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
Normal file
192
worldedit-core/src/main/java/com/boydti/fawe/beta/Flood.java
Normal file
@ -0,0 +1,192 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class Flood {
|
||||
private final int maxBranch;
|
||||
private final int maxDepth;
|
||||
private final Direction[] directions;
|
||||
|
||||
private int[] queue;
|
||||
private long[] visit;
|
||||
|
||||
private int[][] queues;
|
||||
private long[][] visits;
|
||||
|
||||
private int X, Y, Z;
|
||||
|
||||
private ConcurrentLinkedQueue<int[]> queuePool = new ConcurrentLinkedQueue<>();
|
||||
private final Long2ObjectLinkedOpenHashMap<long[][]> chunkVisits;
|
||||
private final Long2ObjectLinkedOpenHashMap<int[][]> chunkQueues;
|
||||
|
||||
public Flood(int maxBranch, int maxDepth, Direction[] directions) {
|
||||
this.maxBranch = maxBranch;
|
||||
this.maxDepth = maxDepth;
|
||||
this.directions = directions;
|
||||
|
||||
this.queues = new int[27][];
|
||||
this.visits = new long[27][];
|
||||
|
||||
this.chunkVisits = new Long2ObjectLinkedOpenHashMap<>();
|
||||
this.chunkQueues = new Long2ObjectLinkedOpenHashMap<>();
|
||||
}
|
||||
|
||||
public synchronized void run(World world) {
|
||||
QueueHandler queueHandler = Fawe.get().getQueueHandler();
|
||||
IQueueExtent fq = queueHandler.getQueue(world);
|
||||
while (!chunkQueues.isEmpty()) {
|
||||
long firstKey = chunkQueues.firstLongKey();
|
||||
int X = MathMan.unpairIntX(firstKey);
|
||||
int Z = MathMan.unpairIntY(firstKey);
|
||||
int[][] chunkQueue = chunkQueues.get(firstKey);
|
||||
// apply
|
||||
}
|
||||
}
|
||||
|
||||
private void init(int X, int Y, int Z) {
|
||||
this.X = X;
|
||||
this.Y = Y;
|
||||
this.Z = Z;
|
||||
}
|
||||
|
||||
public void start(int x, int y, int z) {
|
||||
push(x, y, z, 0);
|
||||
}
|
||||
|
||||
private void push(int x, int y, int z, int depth) {
|
||||
int X = x >> 4;
|
||||
int Z = z >> 4;
|
||||
long pair = MathMan.pairInt(X, Z);
|
||||
int layer = y >> 4;
|
||||
int[] section = getOrCreateQueue(pair, layer);
|
||||
int val = (x & 15) + ((z & 15) << 4) + ((y & 15) << 8) + (depth << 12);
|
||||
push(section, val);
|
||||
}
|
||||
|
||||
private int[] getOrCreateQueue(long pair, int layer) {
|
||||
int[][] arrs = chunkQueues.get(pair);
|
||||
if (arrs == null) {
|
||||
chunkQueues.put(pair, arrs = new int[16][]);
|
||||
}
|
||||
int[] section = arrs[layer];
|
||||
if (section == null) {
|
||||
arrs[layer] = section = newQueue();
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
private int[] newQueue() {
|
||||
int[] arr = queuePool.poll();
|
||||
if (arr != null) {
|
||||
arr[0] = 2;
|
||||
arr[1] = 2;
|
||||
return arr;
|
||||
}
|
||||
return new int[4096];
|
||||
}
|
||||
|
||||
public int poll() {
|
||||
int index = queue[0];
|
||||
if (index == queue[1]) {
|
||||
return -1;
|
||||
}
|
||||
queue[0] = index + 1;
|
||||
return queue[index];
|
||||
}
|
||||
|
||||
private void push(int[] queue, int val) {
|
||||
int indexStart = queue[0];
|
||||
int indexEnd = queue[1];
|
||||
push(indexStart, indexEnd, queue, val);
|
||||
}
|
||||
|
||||
private void push(int indexStart, int indexEnd, int[] queue, int val) {
|
||||
if (indexStart > 2) {
|
||||
queue[0] = --indexStart;
|
||||
queue[indexStart] = val;
|
||||
} else {
|
||||
queue[indexEnd] = val;
|
||||
queue[0] = ++indexEnd;
|
||||
}
|
||||
}
|
||||
|
||||
public Direction[] getDirections() {
|
||||
return directions;
|
||||
}
|
||||
|
||||
public int getMaxBranch() {
|
||||
return maxBranch;
|
||||
}
|
||||
|
||||
public int getMaxDepth() {
|
||||
return maxDepth;
|
||||
}
|
||||
|
||||
public void apply(int x, int y, int z, int depth) {
|
||||
for (int i = 0, j = 0; i < directions.length && j < maxBranch; i++) {
|
||||
final Direction dir = directions[i];
|
||||
final int ty = y + dir.getBlockY();
|
||||
final int tx = x + dir.getBlockX();
|
||||
final int tz = z + dir.getBlockZ();
|
||||
|
||||
int index;
|
||||
long[] visit;
|
||||
int[] queue;
|
||||
final int or = tx | ty | tz;
|
||||
if (or > 15 || or < 0) {
|
||||
visit = this.visit;
|
||||
queue = this.queue;
|
||||
index = tx + (tz << 4) + (ty << 8);
|
||||
} else {
|
||||
int nextX = tx >> 4;
|
||||
int nextY = ty >> 4;
|
||||
int nextZ = tz >> 4;
|
||||
int sectionIndex = nextX + nextZ * 3 + nextZ * 9 + 13;
|
||||
visit = visits[sectionIndex];
|
||||
queue = queues[sectionIndex];
|
||||
if (visit == null || queue == null) {
|
||||
long pair = MathMan.pairInt(X + nextX, Z + nextZ);
|
||||
int layer = Y + nextY;
|
||||
if (layer < 0 || layer > 15) {
|
||||
continue;
|
||||
}
|
||||
queues[sectionIndex] = queue = getOrCreateQueue(pair, layer);
|
||||
}
|
||||
index = (tx & 15) + ((tz & 15) << 4) + ((ty & 15) << 8);
|
||||
}
|
||||
if (!getAndSet(visit, index)) {
|
||||
j++;
|
||||
push(queue, index + (depth << 12));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void set(long[] bits, int i) {
|
||||
bits[i >> 6] |= (1L << (i & 0x3F));
|
||||
}
|
||||
|
||||
public final boolean getAndSet(long[] bits, int i) {
|
||||
int index = i >> 6;
|
||||
long offset = (1L << (i & 0x3F));
|
||||
long val = bits[index];
|
||||
if ((val & offset) != 0) {
|
||||
return true;
|
||||
} else {
|
||||
bits[index] |= offset;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean get(long[] bits, final int i) {
|
||||
return (bits[i >> 6] & (1L << (i & 0x3F))) != 0;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
Reference in New Issue
Block a user