mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
some refactoring to pipeline classes (WIP)
This commit is contained in:
parent
14d5275e05
commit
cfbde956f4
@ -6,8 +6,6 @@ import com.boydti.fawe.beta.IQueueExtent;
|
||||
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;
|
||||
import com.boydti.fawe.bukkit.v1_14.BukkitQueue_1_14;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -24,7 +22,6 @@ import net.minecraft.server.v1_14_R1.Chunk;
|
||||
import net.minecraft.server.v1_14_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_14_R1.Entity;
|
||||
import net.minecraft.server.v1_14_R1.EntityTypes;
|
||||
import net.minecraft.server.v1_14_R1.MinecraftKey;
|
||||
import net.minecraft.server.v1_14_R1.NBTTagCompound;
|
||||
import net.minecraft.server.v1_14_R1.NBTTagInt;
|
||||
import net.minecraft.server.v1_14_R1.TileEntity;
|
||||
@ -283,14 +280,14 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
|
||||
final int y = (blockHash & 0xFF);
|
||||
final int z = (blockHash >> 8 & 0xF) + bz;
|
||||
final BlockPosition pos = new BlockPosition(x, y, z);
|
||||
synchronized (BukkitQueue_0.class) {
|
||||
synchronized (nmsWorld) {
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||
if (tileEntity == null || tileEntity.isRemoved()) {
|
||||
nmsWorld.removeTileEntity(pos);
|
||||
tileEntity = nmsWorld.getTileEntity(pos);
|
||||
}
|
||||
if (tileEntity != null) {
|
||||
final NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_14.fromNative(nativeTag);
|
||||
final NBTTagCompound tag = (NBTTagCompound) fromNative(nativeTag);
|
||||
tag.set("x", new NBTTagInt(x));
|
||||
tag.set("y", new NBTTagInt(y));
|
||||
tag.set("z", new NBTTagInt(z));
|
||||
|
@ -10,6 +10,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import java.io.Flushable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* TODO: implement Extent (need to refactor Extent first)
|
||||
@ -22,7 +23,7 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
* Get the {@link WorldChunkCache}
|
||||
* @return
|
||||
*/
|
||||
WorldChunkCache getCache();
|
||||
IChunkGet getCachedGet(int X, int Z, Supplier<IChunkGet> supplier);
|
||||
|
||||
/**
|
||||
* Get the IChunk at a position (and cache it if it's not already)
|
||||
@ -67,12 +68,12 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
|
||||
@Override
|
||||
default BlockVector3 getMinimumPoint() {
|
||||
return getCache().getWorld().getMinimumPoint();
|
||||
return getWorld().getMinimumPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
default BlockVector3 getMaximumPoint() {
|
||||
return getCache().getWorld().getMaximumPoint();
|
||||
return getWorld().getMaximumPoint();
|
||||
}
|
||||
/**
|
||||
* Create a new root IChunk object<br>
|
||||
|
@ -9,23 +9,16 @@ import com.boydti.fawe.beta.filters.DistrFilter;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.SingleBlockStateMask;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Countable;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
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.block.BlockTypes;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -132,7 +125,12 @@ public class MultiThreadedQueue extends AbstractDelegateExtent implements IQueue
|
||||
|
||||
@Override
|
||||
public int setBlocks(Set<BlockVector3> vset, Pattern pattern) {
|
||||
TODO
|
||||
if (vset instanceof Region) {
|
||||
setBlocks((Region) vset, pattern);
|
||||
}
|
||||
for (BlockVector3 blockVector3 : vset) {
|
||||
pattern.apply(this, blockVector3, blockVector3);
|
||||
}
|
||||
return getChanges();
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.implementation.holder.ReferenceChunk;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -13,6 +14,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -38,8 +40,8 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldChunkCache getCache() {
|
||||
return cache;
|
||||
public IChunkGet getCachedGet(int X, int Z, Supplier<IChunkGet> supplier) {
|
||||
return cache.get(MathMan.pairInt(X, Z), supplier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,8 +110,10 @@ public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
|
||||
|
||||
private IChunkGet newGet() {
|
||||
if (extent instanceof SingleThreadQueueExtent) {
|
||||
final WorldChunkCache cache = ((SingleThreadQueueExtent) extent).getCache();
|
||||
return cache.get(MathMan.pairInt(X, Z), this);
|
||||
IChunkGet newGet = extent.getCachedGet(X, Z, this);
|
||||
if (newGet != null) {
|
||||
return newGet;
|
||||
}
|
||||
}
|
||||
return get();
|
||||
}
|
||||
|
@ -1,65 +1,73 @@
|
||||
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;
|
||||
import com.boydti.fawe.jnbt.anvil.MCAWriter;
|
||||
import com.boydti.fawe.object.*;
|
||||
import com.boydti.fawe.object.FaweInputStream;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.Metadatable;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.brush.visualization.VirtualWorld;
|
||||
import com.boydti.fawe.object.change.StreamChange;
|
||||
import com.boydti.fawe.object.changeset.CFIChangeSet;
|
||||
import com.boydti.fawe.object.collection.*;
|
||||
import com.boydti.fawe.object.collection.DifferentialArray;
|
||||
import com.boydti.fawe.object.collection.DifferentialBlockBuffer;
|
||||
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
||||
import com.boydti.fawe.object.collection.LocalBlockVector2DSet;
|
||||
import com.boydti.fawe.object.collection.SummedAreaTable;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.object.queue.LazyFaweChunk;
|
||||
import com.boydti.fawe.object.schematic.Schematic;
|
||||
import com.boydti.fawe.util.*;
|
||||
import com.boydti.fawe.util.CachedTextureUtil;
|
||||
import com.boydti.fawe.util.RandomTextureUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
import com.boydti.fawe.util.image.Drawable;
|
||||
import com.boydti.fawe.util.image.ImageViewer;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.registry.state.PropertyKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.registry.state.PropertyKey;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.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 javax.annotation.Nullable;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// TODO FIXME
|
||||
public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Drawable, VirtualWorld {
|
||||
@ -200,11 +208,6 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
this.editSession = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Capability capability) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Used for visualizing the world on a map
|
||||
private ImageViewer viewer;
|
||||
// Used for visualizing the world by sending chunk packets
|
||||
@ -239,11 +242,6 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return metaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getQueue() {
|
||||
throw new UnsupportedOperationException("Not supported: Queue is not backed by a real world");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getOrigin() {
|
||||
return Vector3.at(chunkOffset.getBlockX() << 4, 0, chunkOffset.getBlockZ() << 4);
|
||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.jnbt.anvil;
|
||||
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
||||
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
|
||||
import java.io.File;
|
||||
@ -12,7 +13,7 @@ import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
public abstract class MCAWriter {
|
||||
public abstract class MCAWriter implements Extent {
|
||||
private File folder;
|
||||
private final int length;
|
||||
private final int width;
|
||||
|
@ -0,0 +1,135 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Collections2;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Adapt a collection to a set
|
||||
* (It's assumed that the collection is set like, otherwise behavior will be weird)
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class AdaptedSetCollection<T, V> implements Set<V> {
|
||||
private final Function<T, V> adapter;
|
||||
private final Collection<V> adapted;
|
||||
private final Collection<T> original;
|
||||
|
||||
public AdaptedSetCollection(Collection<T> collection, Function<T, V> adapter) {
|
||||
this.original = collection;
|
||||
this.adapted = Collections2.transform(collection, adapter);
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public Collection<T> getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return adapted.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return adapted.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return adapted.contains(o);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<V> iterator() {
|
||||
return adapted.iterator();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return adapted.toArray();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <V> V[] toArray(@NotNull V[] a) {
|
||||
return adapted.toArray(a);
|
||||
}
|
||||
|
||||
public boolean add(V v) {
|
||||
return adapted.add(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return adapted.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(@NotNull Collection<?> c) {
|
||||
return adapted.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean addAll(@NotNull Collection<? extends V> c) {
|
||||
return adapted.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> c) {
|
||||
return adapted.removeAll(c);
|
||||
}
|
||||
|
||||
public boolean removeIf(Predicate<? super V> filter) {
|
||||
return adapted.removeIf(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> c) {
|
||||
return adapted.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
adapted.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return adapted.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return adapted.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<V> spliterator() {
|
||||
return adapted.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<V> stream() {
|
||||
return adapted.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<V> parallelStream() {
|
||||
return adapted.parallelStream();
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super V> action) {
|
||||
adapted.forEach(action);
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.AbstractRegion;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class BlockSet extends AbstractRegion {
|
||||
private final int chunkOffsetX;
|
||||
private final int chunkOffsetZ;
|
||||
private final int blockOffsetX;
|
||||
private final int blockOffsetZ;
|
||||
|
||||
public BlockSet(int offsetX, int offsetZ) {
|
||||
super(null);
|
||||
this.chunkOffsetX = offsetX;
|
||||
this.chunkOffsetZ = offsetZ;
|
||||
this.blockOffsetX = offsetX << 4;
|
||||
this.blockOffsetZ = offsetZ << 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
try {
|
||||
return contains((BlockVector3) o);
|
||||
} catch (ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(BlockVector3 obj) {
|
||||
return contains(obj.getX(), obj.getY(), obj.getZ());
|
||||
}
|
||||
|
||||
protected final int lowestBit(long bitBuffer) {
|
||||
final long lowBit = Long.lowestOneBit(bitBuffer);
|
||||
return Long.bitCount(lowBit - 1);
|
||||
}
|
||||
|
||||
protected final int highestBit(long bitBuffer) {
|
||||
final long lowBit = Long.highestOneBit(bitBuffer);
|
||||
return Long.bitCount(lowBit - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlobal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final int getBlockOffsetX() {
|
||||
return blockOffsetX;
|
||||
}
|
||||
|
||||
public int getBlockOffsetZ() {
|
||||
return blockOffsetZ;
|
||||
}
|
||||
|
||||
public int getChunkOffsetX() {
|
||||
return chunkOffsetX;
|
||||
}
|
||||
|
||||
public int getChunkOffsetZ() {
|
||||
return chunkOffsetZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(BlockVector3 p) {
|
||||
return add(p.getX(), p.getY(), p.getZ());
|
||||
}
|
||||
|
||||
public boolean remove(BlockVector3 p) {
|
||||
return remove(p.getX(), p.getY(), p.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
try {
|
||||
return remove((BlockVector3) o);
|
||||
} catch (ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean contains(int x, int y, int z);
|
||||
public abstract boolean add(int x, int y, int z);
|
||||
public abstract void set(int x, int y, int z);
|
||||
public abstract void clear(int x, int y, int z);
|
||||
public abstract boolean remove(int x, int y, int z);
|
||||
public abstract Iterator<BlockVector3> iterator();
|
||||
public abstract Set<BlockVector2> getChunks();
|
||||
public abstract Set<BlockVector3> getChunkCubes();
|
||||
public abstract BlockVector3 getMaximumPoint();
|
||||
public abstract BlockVector3 getMinimumPoint();
|
||||
|
||||
@Override
|
||||
public void expand(BlockVector3... changes) throws RegionOperationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contract(BlockVector3... changes) throws RegionOperationException {
|
||||
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class ChunkBVecSet implements Set<BlockVector3> {
|
||||
private final int offsetX, offsetZ;
|
||||
private final ChunkBitSet set;
|
||||
private int size = 0;
|
||||
|
||||
public ChunkBVecSet(int size) {
|
||||
this(Integer.MAX_VALUE, Integer.MAX_VALUE, new ChunkBitSet(size));
|
||||
}
|
||||
|
||||
public ChunkBVecSet(ChunkBitSet set, int offsetX, int offsetZ) {
|
||||
this.offsetX = offsetX;
|
||||
this.offsetZ = offsetZ;
|
||||
this.set = set;
|
||||
}
|
||||
|
||||
public ChunkBitSet getBitSet() {
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
try {
|
||||
return contain((BlockVector3) o);
|
||||
} catch (ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contain(BlockVector3 obj) {
|
||||
return contain(obj.getX(), obj.getY(), obj.getZ());
|
||||
}
|
||||
|
||||
public boolean contain(int x, int y, int z) {
|
||||
return set.get(x - offsetX, y, z - offsetZ);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> T[] toArray(@NotNull T[] a) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(BlockVector3 blockVector3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(@NotNull Collection<?> c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@NotNull Collection<? extends BlockVector3> c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ChunkBitSet {
|
||||
private final static int CHUNK_LAYERS = 16;
|
||||
private final static int BITS_PER_LAYER = 4096;
|
||||
private final static int BITS_PER_WORD = 6;
|
||||
private final static int WORDS = BITS_PER_LAYER >> BITS_PER_WORD;
|
||||
private final static IRow NULL_ROW_X = new NullRowX();
|
||||
private final static IRow NULL_ROW_Z = new NullRowZ();
|
||||
private final static IRow NULL_ROW_Y = new NullRowY();
|
||||
|
||||
private final IRow[] rows;
|
||||
|
||||
public ChunkBitSet() {
|
||||
this(16);
|
||||
}
|
||||
|
||||
public ChunkBitSet(int size) {
|
||||
this.rows = new IRow[size];
|
||||
for (int i = 0; i < size; i++) rows[i] = NULL_ROW_X;
|
||||
}
|
||||
|
||||
public boolean get(int x, int y, int z) {
|
||||
return rows[x >> 4].get(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
public void add(int x, int y, int z) {
|
||||
rows[x >> 4].add(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z) {
|
||||
rows[x >> 4].set(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
public void clear(int x, int y, int z) {
|
||||
rows[x >> 4].clear(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
private interface IRow {
|
||||
default boolean get(IRow[] rows, int x, int y, int z) { return false; }
|
||||
void set(IRow[] rows, int x, int y, int z);
|
||||
default boolean add(IRow[] rows, int x, int y, int z) {
|
||||
set(rows, x, y, z);
|
||||
return true;
|
||||
}
|
||||
default void clear(IRow[] rows, int x, int y, int z) { return; }
|
||||
}
|
||||
|
||||
private static class NullRowX implements IRow {
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
IRow row = new RowX(parent.length);
|
||||
parent[x >> 4] = row;
|
||||
row.set(parent, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NullRowZ implements IRow {
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
IRow row = new RowZ();
|
||||
parent[z >> 4] = row;
|
||||
row.set(parent, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NullRowY implements IRow {
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
IRow row = new RowY();
|
||||
parent[y >> 4] = row;
|
||||
row.set(parent, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RowX implements IRow {
|
||||
private final IRow[] rows;
|
||||
|
||||
public RowX(int size) {
|
||||
this.rows = new IRow[size];
|
||||
for (int i = 0; i < size; i++) rows[i] = NULL_ROW_Z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(IRow[] parent, int x, int y, int z) {
|
||||
return rows[z >> 4].get(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[z >> 4].set(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(IRow[] parent, int x, int y, int z) {
|
||||
return this.rows[z >> 4].add(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[z >> 4].clear(this.rows, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RowZ implements IRow {
|
||||
private final IRow[] rows;
|
||||
|
||||
public RowZ() {
|
||||
this.rows = new IRow[CHUNK_LAYERS];
|
||||
for (int i = 0; i < CHUNK_LAYERS; i++) rows[i] = NULL_ROW_Y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(IRow[] parent, int x, int y, int z) {
|
||||
return rows[y >> 4].get(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[y >> 4].set(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(IRow[] parent, int x, int y, int z) {
|
||||
return this.rows[y >> 4].add(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[y >> 4].set(this.rows, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RowY implements IRow {
|
||||
private final long[] bits;
|
||||
|
||||
public RowY() {
|
||||
this.bits = new long[WORDS];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
return (bits[i >> 6] & (1L << (i & 0x3F))) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
bits[i >> 6] |= (1L << (i & 0x3F));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
int offset = i >> 6;
|
||||
long value = bits[offset];
|
||||
long mask = (1L << (i & 0x3F));
|
||||
if ((value & mask) != 0) {
|
||||
bits[offset] = value | mask;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
bits[i >> 6] &= ~(1L << (i & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
private static IRow[] resize(IRow[] arr, IRow def) {
|
||||
int len = arr.length;
|
||||
int newLen = len == 1 ? 1 : Integer.highestOneBit(len - 1) * 2;
|
||||
IRow[] copy = Arrays.copyOf(arr, newLen, IRow[].class);
|
||||
for (int i = len; i < newLen; i++) copy[i] = def;
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,137 @@
|
||||
//package com.boydti.fawe.object.collection;
|
||||
//
|
||||
//import com.sk89q.worldedit.math.BlockVector2;
|
||||
//import com.sk89q.worldedit.math.BlockVector3;
|
||||
//
|
||||
//import java.util.Iterator;
|
||||
//import java.util.Set;
|
||||
//
|
||||
//public final class CpuBlockSet extends BlockSet {
|
||||
// private static final int DIRTY_SET = 0x1;
|
||||
// private static final int DIRTY_CLEAR = 0x10;
|
||||
//
|
||||
// public static int WORLD_HEIGHT = 256;
|
||||
// private final long[] bits;
|
||||
// private final byte[] dirty;
|
||||
// private final int chunkShift;
|
||||
// private final int chunkShift2;
|
||||
//
|
||||
// public CpuBlockSet(int size, int offsetX, int offsetZ) {
|
||||
// super(offsetX, offsetZ);
|
||||
// size = size == 1 ? 1 : Integer.highestOneBit(size - 1) * 2;
|
||||
// int arrayLen = (size * size * WORLD_HEIGHT) >> 6;
|
||||
// int bitShift = Integer.bitCount(Integer.highestOneBit(size) - 1);
|
||||
// this.chunkShift = 12 + bitShift;
|
||||
// this.chunkShift2 = 12 + bitShift * 2;
|
||||
// this.bits = new long[arrayLen];
|
||||
// this.dirty = new byte[arrayLen >> 12];
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public BlockVector3 getMinimumPoint() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public BlockVector3 getMaximumPoint() {
|
||||
// // visited set
|
||||
// // queue (longs)
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Iterator<BlockVector3> iterator() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Set<BlockVector2> getChunks() {
|
||||
// // next 65536
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Set<BlockVector3> getChunkCubes() {
|
||||
// // next 4096
|
||||
// }
|
||||
//
|
||||
// private final boolean contains(final int i) {
|
||||
// return (bits[i >> 6] & (1L << (i & 0x3F))) != 0;
|
||||
// }
|
||||
//
|
||||
// private final boolean add(final int i) {
|
||||
// int offset = i >> 6;
|
||||
// long value = bits[offset];
|
||||
// long mask = (1L << (i & 0x3F));
|
||||
// if ((value & mask) == 0) {
|
||||
// dirty[i >> 16] |= DIRTY_SET;
|
||||
// bits[offset] = value | mask;
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// private final boolean remove(final int i) {
|
||||
// int offset = i >> 6;
|
||||
// long value = bits[offset];
|
||||
// long mask = (1L << (i & 0x3F));
|
||||
// if ((value & mask) != 0) {
|
||||
// bits[offset] = value & ~mask;
|
||||
// dirty[i >> 16] |= DIRTY_CLEAR;
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// private final void set(final int i) {
|
||||
// bits[i >> 6] |= (1L << (i & 0x3F));
|
||||
// dirty[i >> 12] |= DIRTY_SET;
|
||||
// }
|
||||
//
|
||||
// private final void clear(final int i) {
|
||||
// bits[i >> 6] &= ~(1L << (i & 0x3F));
|
||||
// dirty[i >> 12] |= DIRTY_CLEAR;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean contains(int x, int y, int z) {
|
||||
// return contains(index(x, y, z));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean add(int x, int y, int z) {
|
||||
// return add(index(x, y, z));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void set(int x, int y, int z) {
|
||||
// set(index(x, y, z));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void clear(int x, int y, int z) {
|
||||
// clear(index(x, y, z));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean remove(int x, int y, int z) {
|
||||
// return remove(index(x, y, z));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void clear() {
|
||||
// for (int i = 0; i < dirty.length; i++) {
|
||||
// boolean isDirty = dirty[i] != 0;
|
||||
// if (isDirty) {
|
||||
// dirty[i] = 0;
|
||||
// int start = i << 10;
|
||||
// int end = Math.min(bits.length, (i + 1) << 10);
|
||||
// for (int j = start; j < end; j++) {
|
||||
// bits[j] = 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private final int index(int x, int y, int z) {
|
||||
// return (((y & 15) << 8) | ((z & 15) << 4) | (x & 15)) | ((y >> 4) << chunkShift2) | ((z >> 4) << chunkShift) | ((x >> 4) << 12);
|
||||
// }
|
||||
//}
|
@ -0,0 +1,917 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Memory optimized BlockVector3 Set using a sparsely populated bitset and grouped by chunk section
|
||||
* Note on spaghetti code / duplication
|
||||
* - Uses a minimum of 1 bit per entry
|
||||
* - 99.9% of the time there are no if checks on get/clear
|
||||
* - Grouping / iteration is by chunk section, and the y>z>x order
|
||||
*/
|
||||
public final class MemBlockSet extends BlockSet {
|
||||
private final static int CHUNK_LAYERS = 16;
|
||||
private final static int BITS_PER_LAYER = 4096;
|
||||
private final static int BITS_PER_WORD = 6;
|
||||
private final static int WORDS = BITS_PER_LAYER >> BITS_PER_WORD;
|
||||
private final static IRow NULL_ROW_X = new NullRowX();
|
||||
private final static IRow NULL_ROW_Z = new NullRowZ();
|
||||
private final static IRow NULL_ROW_Y = new NullRowY();
|
||||
private final IRow[] rows;
|
||||
private final MutableBlockVector3 mutable;
|
||||
|
||||
public MemBlockSet() {
|
||||
this(16, 0, 0);
|
||||
}
|
||||
|
||||
public MemBlockSet(int size, int offsetX, int offsetZ) {
|
||||
super(offsetX, offsetZ);
|
||||
this.rows = new IRow[size];
|
||||
for (int i = 0; i < size; i++) rows[i] = NULL_ROW_X;
|
||||
this.mutable = new MutableBlockVector3();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int x, int y, int z) {
|
||||
x -= getBlockOffsetX();
|
||||
z -= getBlockOffsetZ();
|
||||
return rows[x >> 4].get(this.rows, x, y, z - getBlockOffsetZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(int x, int y, int z) {
|
||||
x -= getBlockOffsetX();
|
||||
z -= getBlockOffsetZ();
|
||||
return rows[x >> 4].add(this.rows, x, y, z - getBlockOffsetZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z) {
|
||||
x -= getBlockOffsetX();
|
||||
z -= getBlockOffsetZ();
|
||||
rows[x >> 4].set(this.rows, x, y, z - getBlockOffsetZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(int x, int y, int z) {
|
||||
x -= getBlockOffsetX();
|
||||
z -= getBlockOffsetZ();
|
||||
rows[x >> 4].clear(this.rows, x, y, z - getBlockOffsetZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(int x, int y, int z) {
|
||||
x -= getBlockOffsetX();
|
||||
z -= getBlockOffsetZ();
|
||||
return rows[x >> 4].remove(this.rows, x, y, z - getBlockOffsetZ());
|
||||
}
|
||||
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return BlockVector3.at(getMinX(), getMinY(), getMinZ());
|
||||
}
|
||||
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return BlockVector3.at(getMaxX(), getMaxY(), getMaxZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<BlockVector2> getChunks() {
|
||||
return new AbstractSet<BlockVector2>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<BlockVector2> iterator() {
|
||||
return new Iterator<BlockVector2>() {
|
||||
private MutableBlockVector2 mutable = new MutableBlockVector2();
|
||||
private boolean hasNext;
|
||||
private int X,Z;
|
||||
private int setX, setZ;
|
||||
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
for (;X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (nullRowX instanceof RowX) {
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (;Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (nullRowZ instanceof RowZ) {
|
||||
setX = X;
|
||||
setZ = Z;
|
||||
Z++;
|
||||
hasNext = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Z = 0;
|
||||
}
|
||||
}
|
||||
hasNext = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector2 next() {
|
||||
mutable.setComponents(setX + getBlockOffsetX(), setZ + getBlockOffsetZ());
|
||||
init();
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("This set is immutable.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int size = 0;
|
||||
for (int X = 0;X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (nullRowX instanceof RowX) {
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (nullRowZ instanceof RowZ) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return MemBlockSet.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if (o instanceof BlockVector2) {
|
||||
BlockVector2 other = (BlockVector2) o;
|
||||
IRow rowx = rows[other.getX() - getChunkOffsetX()];
|
||||
if (rowx instanceof RowX) {
|
||||
return ((RowX) rowx).rows[other.getZ() - getChunkOffsetZ()] instanceof RowZ;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Set<BlockVector3> getChunkCubes() {
|
||||
return new AbstractSet<BlockVector3>() {
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return new Iterator<BlockVector3>() {
|
||||
private MutableBlockVector3 mutable = new MutableBlockVector3();
|
||||
private boolean hasNext;
|
||||
private int X, Z, Y;
|
||||
private int setX, setY, setZ;
|
||||
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
for (;X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (nullRowX instanceof RowX) {
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (;Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (nullRowZ instanceof RowZ) {
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
for (;Y < rowz.rows.length;Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (nullRowY instanceof RowY) {
|
||||
setX = X;
|
||||
setY = Y;
|
||||
setZ = Z;
|
||||
Z++;
|
||||
hasNext = true;
|
||||
}
|
||||
}
|
||||
Y = 0;
|
||||
}
|
||||
}
|
||||
Z = 0;
|
||||
}
|
||||
}
|
||||
hasNext = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 next() {
|
||||
mutable.setComponents(setX + getBlockOffsetX(), setY, setZ + getBlockOffsetX());
|
||||
init();
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("This set is immutable.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int size = 0;
|
||||
for (int X = 0;X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (nullRowX instanceof RowX) {
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (nullRowZ instanceof RowZ) {
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
for (int Y = 0; Y < rowz.rows.length; Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (nullRowY instanceof RowY) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return MemBlockSet.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if (o instanceof BlockVector3) {
|
||||
BlockVector3 other = (BlockVector3) o;
|
||||
IRow rowx = rows[other.getX() - getChunkOffsetX()];
|
||||
if (rowx instanceof RowX) {
|
||||
IRow rowz = ((RowX) rowx).rows[other.getZ()];
|
||||
if (rowz instanceof RowZ) {
|
||||
return ((RowZ) rowz).rows[other.getY() - getChunkOffsetZ()] instanceof RowY;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
int maxY = 15;
|
||||
int maxy = 16;
|
||||
int by = Integer.MAX_VALUE;
|
||||
for (int X = 0; X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
outer:
|
||||
for (int Y = 0; Y <= maxY; Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
int localMaxy = Y == maxY ? maxy : 15;
|
||||
for (int y = 0, i = 0; y < localMaxy; y++) {
|
||||
for (int xz = 0; xz < 4; xz++, i++) {
|
||||
long val = rowY.bits[i];
|
||||
if (val != 0) {
|
||||
if (y == 0) {
|
||||
maxY = Y - 1;
|
||||
maxy = 16;
|
||||
} else {
|
||||
maxY = Y;
|
||||
maxy = y;
|
||||
}
|
||||
by = (Y << 4) + y;
|
||||
if (by == 0) return 0;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return by;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
int maxY = 0;
|
||||
int maxy = 0;
|
||||
int by = Integer.MIN_VALUE;
|
||||
for (int X = 0; X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
outer:
|
||||
for (int Y = 15; Y >= maxY; Y--) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
int localMaxy = Y == maxY ? maxy : 0;
|
||||
for (int y = 15, i = 63; y >= localMaxy; y--) {
|
||||
for (int xz = 3; xz >= 0; xz--, i--) {
|
||||
long val = rowY.bits[i];
|
||||
if (val != 0) {
|
||||
if (y == 15) {
|
||||
maxY = Y + 1;
|
||||
maxy = 0;
|
||||
} else {
|
||||
maxY = Y;
|
||||
maxy = y + 1;
|
||||
}
|
||||
by = (Y << 4) + y;
|
||||
if (by == 255) return 255;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return by;
|
||||
}
|
||||
|
||||
public int getMaxZ() {
|
||||
int maxChunkZ = 0;
|
||||
int maxz = -1;
|
||||
int tz = Integer.MIN_VALUE;
|
||||
for (int X = rows.length - 1; X >= 0; X--) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
outer:
|
||||
for (int Z = rowx.rows.length - 1; Z >= maxChunkZ ; Z--) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
if (Z != maxChunkZ) {
|
||||
maxChunkZ = Z;
|
||||
maxz = -1;
|
||||
}
|
||||
for (int Y = rowz.rows.length - 1; Y >= 0; Y--) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
for (int y = 15, i1 = 63; y >= 0; y--, i1 -= 4) {
|
||||
for (int z = 12, i = i1; z > maxz - 3; z -= 4, i--) {
|
||||
long bitBuffer = rowY.bits[i];
|
||||
if (bitBuffer != 0) {
|
||||
int highest = highestBit(bitBuffer);
|
||||
maxz = z + (highest >> 4);
|
||||
if (maxz == 15) {
|
||||
tz = (maxChunkZ << 4) + 15;
|
||||
maxChunkZ++;
|
||||
break outer;
|
||||
} else {
|
||||
tz = Math.max(tz, (maxChunkZ << 4) + maxz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tz + getBlockOffsetZ();
|
||||
}
|
||||
|
||||
public int getMaxX() {
|
||||
for (int X = rows.length - 1; X >= 0; X--) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
int tx = (X << 4);
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
long or = 0;
|
||||
for (int Z = rowx.rows.length - 1; Z >= 0 ; Z--) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
for (int Y = rowz.rows.length - 1; Y >= 0; Y--) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
for (long value : rowY.bits) {
|
||||
or |= value;
|
||||
}
|
||||
or = (or & 0xFFFF) | ((or >> 16) & 0xFFFF) | ((or >> 32) & 0xFFFF) | ((or >> 48) & 0xFFFF);
|
||||
if (highestBit(or) == 15) return tx + 15;
|
||||
}
|
||||
}
|
||||
int highest = highestBit(or);
|
||||
if (highest != 64) {
|
||||
return tx + highest + getBlockOffsetX();
|
||||
}
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public int getMinZ() {
|
||||
int maxChunkZ = rows.length - 1;
|
||||
int maxz = 16;
|
||||
int bz = Integer.MAX_VALUE;
|
||||
for (int X = 0; X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
outer:
|
||||
for (int Z = 0; Z <= maxChunkZ; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
if (Z != maxChunkZ) {
|
||||
maxChunkZ = Z;
|
||||
maxz = 16;
|
||||
}
|
||||
for (int Y = 0; Y < rowz.rows.length; Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
for (int y = 0, i1 = 0; y < 16; y++, i1 += 4) {
|
||||
for (int z = 0, i = i1; z < maxz; z += 4, i++) {
|
||||
long bitBuffer = rowY.bits[i];
|
||||
if (bitBuffer != 0) {
|
||||
int lowest = lowestBit(bitBuffer);
|
||||
maxz = z + (lowest >> 4);
|
||||
if (maxz == 0) {
|
||||
bz = (maxChunkZ << 4);
|
||||
maxChunkZ--;
|
||||
break outer;
|
||||
} else {
|
||||
bz = Math.min(bz, (maxChunkZ << 4) + maxz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bz + getBlockOffsetZ();
|
||||
}
|
||||
|
||||
public int getMinX() {
|
||||
for (int X = 0; X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
int bx = X << 4;
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
long or = 0;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
for (int Y = 0; Y < rowz.rows.length; Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
for (long value : rowY.bits) {
|
||||
or |= value;
|
||||
}
|
||||
or = (or & 0xFFFF) | ((or >> 16) & 0xFFFF) | ((or >> 32) & 0xFFFF) | ((or >> 48) & 0xFFFF);
|
||||
if (lowestBit(or) == 0) return bx;
|
||||
}
|
||||
}
|
||||
int lowest = lowestBit(or);
|
||||
if (lowest != 64) {
|
||||
return bx + lowest + getBlockOffsetX();
|
||||
}
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public void iterate(BlockIterator iterator) {
|
||||
for (int X = 0; X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
int bx = getBlockOffsetX() + (X << 4);
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
int bz = getBlockOffsetZ() + (Z << 4);
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
for (int Y = 0; Y < rowz.rows.length; Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
int by = Y << 4;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
for (int y = 0, i = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z += 4, i++) {
|
||||
long bitBuffer = rowY.bits[i];
|
||||
if (bitBuffer != 0) {
|
||||
if (bitBuffer == -1L) {
|
||||
for (int zz = z; zz < z + 4; zz++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
iterator.apply(bx + x, by + y, bz + zz);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
final long lowBit = Long.lowestOneBit(bitBuffer);
|
||||
final int bitIndex = Long.bitCount(lowBit - 1);
|
||||
int x = bitIndex & 15;
|
||||
int zz = z + (bitIndex >> 4);
|
||||
iterator.apply(bx + x, by + y, bz + zz);
|
||||
bitBuffer = bitBuffer ^ lowBit;
|
||||
} while (bitBuffer != 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BlockVector3> iterator() {
|
||||
return new Iterator<BlockVector3>() {
|
||||
private int bx, by, bz, zz, yy;
|
||||
private RowX rowX;
|
||||
private RowZ rowZ;
|
||||
private RowY rowY;
|
||||
private long[] bits;
|
||||
private int bitsIndex = 0;
|
||||
private int yIndex = 0;
|
||||
private int zIndex = 0;
|
||||
private int xIndex = 0;
|
||||
private long bitBuffer = 0;
|
||||
private boolean next;
|
||||
|
||||
{
|
||||
if (nextRowX()) {
|
||||
if (nextRowZ()) {
|
||||
if (nextRowY()) {
|
||||
next = nextLong();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean nextRowX() {
|
||||
while (xIndex < rows.length) {
|
||||
bx = getBlockOffsetX() + (xIndex << 4);
|
||||
IRow nullRowX = rows[xIndex++];
|
||||
if (nullRowX instanceof RowX) {
|
||||
rowX = (RowX) nullRowX;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean nextRowZ() {
|
||||
while (zIndex < rowX.rows.length) {
|
||||
bz = getBlockOffsetZ() + (zIndex << 4);
|
||||
IRow nullRowZ = rowX.rows[zIndex++];
|
||||
if (nullRowZ instanceof RowZ) {
|
||||
rowZ = (RowZ) nullRowZ;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (nextRowX()) {
|
||||
zIndex = 0;
|
||||
return nextRowZ();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean nextRowY() {
|
||||
while (yIndex < rowZ.rows.length) {
|
||||
by = yIndex << 4;
|
||||
IRow nullRowY = rowZ.rows[yIndex++];
|
||||
if (nullRowY instanceof RowY) {
|
||||
rowY = (RowY) nullRowY;
|
||||
bits = rowY.bits;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (nextRowZ()) {
|
||||
yIndex = 0;
|
||||
return nextRowY();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean nextLong() {
|
||||
if (bitBuffer == 0) {
|
||||
do {
|
||||
bitBuffer = bits[bitsIndex++];
|
||||
if (bitsIndex == bits.length) {
|
||||
bitsIndex = 0;
|
||||
if (!nextRowY()) {
|
||||
return next = false;
|
||||
}
|
||||
}
|
||||
} while (bitBuffer == 0);
|
||||
zz = bz + (((bitsIndex - 1) << 2) & 15);
|
||||
yy = by + ((bitsIndex - 1) >> 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 next() {
|
||||
final long lowBit = Long.lowestOneBit(bitBuffer);
|
||||
final int bitIndex = Long.bitCount(lowBit-1);
|
||||
{
|
||||
mutable.setComponents((bx) + (bitIndex & 15), yy, (zz) + (bitIndex));
|
||||
}
|
||||
bitBuffer = bitBuffer ^ lowBit;
|
||||
nextLong();
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
// TODO optimize
|
||||
MemBlockSet.this.remove(mutable);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
for (int X = 0; X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
for (int Y = 0; Y < 16; Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
for (long bit : rowY.bits) {
|
||||
if (bit != 0) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return (int) sizeLong();
|
||||
}
|
||||
|
||||
public long sizeLong() {
|
||||
long total = 0;
|
||||
long lastBit = 0;
|
||||
int lastCount = 0;
|
||||
for (int X = 0; X < rows.length; X++) {
|
||||
IRow nullRowX = rows[X];
|
||||
if (!(nullRowX instanceof RowX)) continue;
|
||||
RowX rowx = (RowX) nullRowX;
|
||||
for (int Z = 0; Z < rowx.rows.length; Z++) {
|
||||
IRow nullRowZ = rowx.rows[Z];
|
||||
if (!(nullRowZ instanceof RowZ)) continue;
|
||||
RowZ rowz = (RowZ) nullRowZ;
|
||||
outer:
|
||||
for (int Y = 0; Y < 16; Y++) {
|
||||
IRow nullRowY = rowz.rows[Y];
|
||||
if (!(nullRowY instanceof RowY)) continue;
|
||||
RowY rowY = (RowY) nullRowY;
|
||||
for (long bit : rowY.bits) {
|
||||
if (bit == 0) continue;
|
||||
else if (bit == -1L) {
|
||||
total += 64;
|
||||
}
|
||||
else if (bit == lastBit) {
|
||||
total += lastCount;
|
||||
} else {
|
||||
lastBit = bit;
|
||||
total += lastCount = Long.bitCount(bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
Arrays.fill(rows, NULL_ROW_X);
|
||||
}
|
||||
|
||||
public interface BlockIterator {
|
||||
void apply(int x, int y, int z);
|
||||
}
|
||||
|
||||
private interface IRow {
|
||||
default boolean get(IRow[] rows, int x, int y, int z) { return false; }
|
||||
void set(IRow[] rows, int x, int y, int z);
|
||||
default boolean add(IRow[] rows, int x, int y, int z) {
|
||||
set(rows, x, y, z);
|
||||
return true;
|
||||
}
|
||||
default boolean remove(IRow[] rows, int x, int y, int z) {
|
||||
remove(rows, x, y, z);
|
||||
return false;
|
||||
}
|
||||
default void clear(IRow[] rows, int x, int y, int z) { return; }
|
||||
}
|
||||
|
||||
private static final class NullRowX implements IRow {
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
IRow row = new RowX(parent.length);
|
||||
parent[x >> 4] = row;
|
||||
row.set(parent, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NullRowZ implements IRow {
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
IRow row = new RowZ();
|
||||
parent[z >> 4] = row;
|
||||
row.set(parent, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NullRowY implements IRow {
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
IRow row = new RowY();
|
||||
parent[y >> 4] = row;
|
||||
row.set(parent, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RowX implements IRow {
|
||||
private final IRow[] rows;
|
||||
|
||||
public RowX(int size) {
|
||||
this.rows = new IRow[size];
|
||||
for (int i = 0; i < size; i++) rows[i] = NULL_ROW_Z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(IRow[] parent, int x, int y, int z) {
|
||||
return rows[z >> 4].get(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[z >> 4].set(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(IRow[] parent, int x, int y, int z) {
|
||||
return this.rows[z >> 4].add(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[z >> 4].clear(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(IRow[] parent, int x, int y, int z) {
|
||||
return this.rows[z >> 4].remove(this.rows, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RowZ implements IRow {
|
||||
private final IRow[] rows;
|
||||
|
||||
public RowZ() {
|
||||
this.rows = new IRow[CHUNK_LAYERS];
|
||||
for (int i = 0; i < CHUNK_LAYERS; i++) rows[i] = NULL_ROW_Y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(IRow[] parent, int x, int y, int z) {
|
||||
return rows[y >> 4].get(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[y >> 4].set(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(IRow[] parent, int x, int y, int z) {
|
||||
return this.rows[y >> 4].add(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(IRow[] parent, int x, int y, int z) {
|
||||
this.rows[y >> 4].set(this.rows, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(IRow[] parent, int x, int y, int z) {
|
||||
return this.rows[y >> 4].remove(this.rows, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RowY implements IRow {
|
||||
private final long[] bits;
|
||||
|
||||
public RowY() {
|
||||
this.bits = new long[WORDS];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
return (bits[i >> 6] & (1L << (i & 0x3F))) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
bits[i >> 6] |= (1L << (i & 0x3F));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
int offset = i >> 6;
|
||||
long value = bits[offset];
|
||||
long mask = (1L << (i & 0x3F));
|
||||
if ((value & mask) == 0) {
|
||||
bits[offset] = value | mask;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(IRow[] parent, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
bits[i >> 6] &= ~(1L << (i & 0x3F));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(IRow[] rows, int x, int y, int z) {
|
||||
int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15);
|
||||
int offset = i >> 6;
|
||||
long value = bits[offset];
|
||||
long mask = (1L << (i & 0x3F));
|
||||
if ((value & mask) != 0) {
|
||||
bits[offset] = value & ~mask;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static IRow[] resize(IRow[] arr, IRow def) {
|
||||
int len = arr.length;
|
||||
int newLen = len == 1 ? 1 : Integer.highestOneBit(len - 1) * 2;
|
||||
IRow[] copy = Arrays.copyOf(arr, newLen, IRow[].class);
|
||||
for (int i = len; i < newLen; i++) copy[i] = def;
|
||||
return copy;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package com.boydti.fawe.object.regions;
|
||||
|
||||
import com.boydti.fawe.object.HasFaweQueue;
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
@ -49,7 +48,7 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
setMinMax(p.getBlockX(), p.getBlockY(), p.getBlockZ());
|
||||
return true;
|
||||
}
|
||||
}, 256, extent instanceof HasFaweQueue ? (HasFaweQueue) extent : null);
|
||||
}, 256);
|
||||
search.setVisited(set);
|
||||
search.visit(BlockVector3.at(x, y, z));
|
||||
Operations.completeBlindly(search);
|
||||
|
@ -1125,8 +1125,8 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
||||
final int startCheckY = fullHeight ? 0 : startPerformY;
|
||||
final int endY = region.getMaximumPoint().getBlockY();
|
||||
RegionVisitor visitor = new RegionVisitor(flat, pos -> {
|
||||
int x = pos.getBlockX();
|
||||
int z = pos.getBlockZ();
|
||||
int x = pos.getX();
|
||||
int z = pos.getZ();
|
||||
int freeSpot = startCheckY;
|
||||
for (int y = startCheckY; y <= endY; y++) {
|
||||
if (y < startPerformY) {
|
||||
@ -1175,7 +1175,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
||||
final BlockReplace replace = new BlockReplace(EditSession.this, pattern);
|
||||
|
||||
// Pick how we're going to visit blocks
|
||||
RecursiveVisitor visitor = new DirectionalVisitor(mask, replace, origin, direction, (int) (radius * 2 + 1), this);
|
||||
RecursiveVisitor visitor = new DirectionalVisitor(mask, replace, origin, direction, (int) (radius * 2 + 1));
|
||||
|
||||
// Start at the origin
|
||||
visitor.visit(origin);
|
||||
@ -1230,9 +1230,9 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
||||
// Pick how we're going to visit blocks
|
||||
RecursiveVisitor visitor;
|
||||
if (recursive) {
|
||||
visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), this);
|
||||
visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1));
|
||||
} else {
|
||||
visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1), this);
|
||||
visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1));
|
||||
}
|
||||
|
||||
// Start at the origin
|
||||
@ -1510,7 +1510,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
||||
int minY = region.getMinimumPoint().getBlockY();
|
||||
int maxY = Math.min(getMaximumPoint().getBlockY(), region.getMaximumPoint().getBlockY() + 1);
|
||||
SurfaceRegionFunction surface = new SurfaceRegionFunction(this, offset, minY, maxY);
|
||||
FlatRegionVisitor visitor = new FlatRegionVisitor(asFlatRegion(region), surface, this);
|
||||
FlatRegionVisitor visitor = new FlatRegionVisitor(asFlatRegion(region), surface);
|
||||
Operations.completeBlindly(visitor);
|
||||
return this.changes = visitor.getAffected();
|
||||
}
|
||||
@ -1674,7 +1674,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
||||
} else {
|
||||
replace = new BlockReplace(this, (BlockTypes.AIR.getDefaultState()));
|
||||
}
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), this);
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1));
|
||||
|
||||
// Around the origin in a 3x3 block
|
||||
for (BlockVector3 position : CuboidRegion.fromCenter(origin, 1)) {
|
||||
@ -2556,7 +2556,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
Operations.completeBlindly(visitor);
|
||||
changes += visitor.getAffected();
|
||||
return changes;
|
||||
@ -3061,12 +3061,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
||||
return false;
|
||||
}
|
||||
|
||||
// public void dropItem(BlockVector3 position, BaseItemStack item) {
|
||||
// if (getWorld() != null) {
|
||||
// getWorld().dropItem(position, item);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void simulateBlockMine(BlockVector3 position) {
|
||||
TaskManager.IMP.sync((Supplier<Object>) () -> {
|
||||
|
@ -19,13 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.boydti.fawe.example.MappedFaweQueue;
|
||||
import com.boydti.fawe.jnbt.anvil.generator.CavesGen;
|
||||
import com.boydti.fawe.jnbt.anvil.generator.GenBase;
|
||||
import com.boydti.fawe.jnbt.anvil.generator.OreGen;
|
||||
import com.boydti.fawe.jnbt.anvil.generator.Resource;
|
||||
import com.boydti.fawe.jnbt.anvil.generator.SchemGen;
|
||||
|
||||
import com.boydti.fawe.object.clipboard.WorldCopyClipboard;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
@ -35,7 +33,6 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.function.RegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.block.BlockReplace;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
@ -54,7 +51,6 @@ import com.sk89q.worldedit.registry.state.PropertyGroup;
|
||||
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;
|
||||
@ -403,7 +399,7 @@ public interface Extent extends InputExtent, OutputExtent {
|
||||
}
|
||||
|
||||
default boolean cancel() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default int getMaxY() {
|
||||
|
@ -20,14 +20,7 @@
|
||||
package com.sk89q.worldedit.function.visitor;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.example.MappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.HasFaweQueue;
|
||||
import com.boydti.fawe.object.IntegerTrio;
|
||||
import com.boydti.fawe.object.collection.BlockVectorSet;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
@ -39,11 +32,11 @@ import com.sk89q.worldedit.util.Direction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Performs a breadth-first search starting from points added with
|
||||
* {@link #visit(BlockVector3)}. The search continues
|
||||
@ -87,7 +80,6 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
private final RegionFunction function;
|
||||
private BlockVector3[] directions;
|
||||
private BlockVectorSet visited;
|
||||
private final MappedFaweQueue mFaweQueue;
|
||||
private BlockVectorSet queue;
|
||||
private int currentDepth = 0;
|
||||
private final int maxDepth;
|
||||
@ -105,15 +97,7 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
}
|
||||
|
||||
public BreadthFirstSearch(RegionFunction function, int maxDepth) {
|
||||
this(function, maxDepth, null);
|
||||
checkNotNull(function);
|
||||
|
||||
}
|
||||
|
||||
public BreadthFirstSearch(RegionFunction function, int maxDepth, HasFaweQueue faweQueue) {
|
||||
checkNotNull(function);
|
||||
FaweQueue fq = faweQueue != null ? faweQueue.getQueue() : null;
|
||||
this.mFaweQueue = fq instanceof MappedFaweQueue ? (MappedFaweQueue) fq : null;
|
||||
this.queue = new BlockVectorSet();
|
||||
this.visited = new BlockVectorSet();
|
||||
this.function = function;
|
||||
@ -236,28 +220,6 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
BlockVectorSet tempQueue = new BlockVectorSet();
|
||||
BlockVectorSet chunkLoadSet = new BlockVectorSet();
|
||||
for (currentDepth = 0; !queue.isEmpty() && currentDepth <= maxDepth; currentDepth++) {
|
||||
if (mFaweQueue != null && Settings.IMP.QUEUE.PRELOAD_CHUNKS > 1) {
|
||||
int cx = Integer.MIN_VALUE;
|
||||
int cz = Integer.MIN_VALUE;
|
||||
for (BlockVector3 from : queue) {
|
||||
for (BlockVector3 direction : dirs) {
|
||||
int x = from.getBlockX() + direction.getX();
|
||||
int z = from.getBlockZ() + direction.getZ();
|
||||
if (cx != (cx = x >> 4) || cz != (cz = z >> 4)) {
|
||||
int y = from.getBlockY() + direction.getY();
|
||||
if (y < 0 || y >= 256) {
|
||||
continue;
|
||||
}
|
||||
if (!visited.contains(x, y, z)) {
|
||||
chunkLoadSet.add(cx, 0, cz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (BlockVector3 chunk : chunkLoadSet) {
|
||||
mFaweQueue.queueChunkLoad(chunk.getBlockX(), chunk.getBlockZ());
|
||||
}
|
||||
}
|
||||
for (BlockVector3 from : queue) {
|
||||
if (function.apply(from)) affected++;
|
||||
for (int i = 0, j = 0; i < dirs.length && j < maxBranch; i++) {
|
||||
|
@ -19,15 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.function.visitor;
|
||||
|
||||
import com.boydti.fawe.object.HasFaweQueue;
|
||||
import com.sk89q.worldedit.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
@ -43,11 +38,11 @@ public class DirectionalVisitor extends RecursiveVisitor {
|
||||
private final BlockVector3 dirVec;
|
||||
|
||||
public DirectionalVisitor(Mask mask, RegionFunction function, BlockVector3 origin, BlockVector3 direction) {
|
||||
this(mask, function, origin, direction, Integer.MAX_VALUE, null);
|
||||
this(mask, function, origin, direction, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public DirectionalVisitor(Mask mask, RegionFunction function, BlockVector3 origin, BlockVector3 direction, int distance, HasFaweQueue hasFaweQueue) {
|
||||
super(mask, function, distance, hasFaweQueue);
|
||||
public DirectionalVisitor(Mask mask, RegionFunction function, BlockVector3 origin, BlockVector3 direction, int distance) {
|
||||
super(mask, function, distance);
|
||||
checkNotNull(mask);
|
||||
this.origin = origin;
|
||||
this.dirVec = direction;
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.function.visitor;
|
||||
|
||||
import com.boydti.fawe.object.HasFaweQueue;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
@ -45,11 +44,7 @@ public class RecursiveVisitor extends BreadthFirstSearch {
|
||||
* @param function the function
|
||||
*/
|
||||
public RecursiveVisitor(Mask mask, RegionFunction function, int maxDepth) {
|
||||
this(mask, function, maxDepth, null);
|
||||
}
|
||||
|
||||
public RecursiveVisitor(Mask mask, RegionFunction function, int maxDepth, HasFaweQueue faweQueue) {
|
||||
super(function, maxDepth, faweQueue);
|
||||
super(function, maxDepth);
|
||||
checkNotNull(mask);
|
||||
this.mask = mask;
|
||||
}
|
||||
|
@ -27,13 +27,14 @@ import com.sk89q.worldedit.regions.iterator.RegionIterator;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractRegion implements Region {
|
||||
public abstract class AbstractRegion extends AbstractSet<BlockVector3> implements Region {
|
||||
|
||||
protected World world;
|
||||
|
||||
@ -41,6 +42,11 @@ public abstract class AbstractRegion implements Region {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return getArea();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getCenter() {
|
||||
return getMinimumPoint().add(getMaximumPoint()).toVector3().divide(2);
|
||||
@ -100,21 +106,6 @@ public abstract class AbstractRegion implements Region {
|
||||
return points;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of blocks in the region.
|
||||
*
|
||||
* @return number of blocks
|
||||
*/
|
||||
@Override
|
||||
public int getArea() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return (max.getX() - min.getX() + 1) *
|
||||
(max.getY() - min.getY() + 1) *
|
||||
(max.getZ() - min.getZ() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X-size.
|
||||
*
|
||||
|
@ -62,14 +62,23 @@ public interface Region extends Iterable<BlockVector3>, Cloneable {
|
||||
*
|
||||
* @return center point
|
||||
*/
|
||||
Vector3 getCenter();
|
||||
default Vector3 getCenter() {
|
||||
return getMinimumPoint().add(getMaximumPoint()).toVector3().divide(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of blocks in the region.
|
||||
*
|
||||
* @return number of blocks
|
||||
*/
|
||||
int getArea();
|
||||
default int getArea() {
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
|
||||
return (max.getX() - min.getX() + 1) *
|
||||
(max.getY() - min.getY() + 1) *
|
||||
(max.getZ() - min.getZ() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X-size.
|
||||
|
Loading…
Reference in New Issue
Block a user