Merge branch 'merge' into 1.15

This commit is contained in:
NotMyFault
2019-12-19 19:05:27 +01:00
36 changed files with 323 additions and 196 deletions

View File

@ -4,6 +4,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
import com.boydti.fawe.beta.Trimable;
import com.boydti.fawe.beta.implementation.filter.block.CharFilterBlock;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.collection.BitArray4096;
@ -48,6 +52,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Supplier;
public enum FaweCache implements Trimable {
@ -194,6 +199,24 @@ public enum FaweCache implements Trimable {
return pool;
}
public <T, V> LoadingCache<T, V> createCache(Supplier<V> withInitial) {
return CacheBuilder.newBuilder().build(new CacheLoader<T, V>() {
@Override
public V load(T key) {
return withInitial.get();
}
});
}
public <T, V> LoadingCache<T, V> createCache(Function<T, V> withInitial) {
return CacheBuilder.newBuilder().build(new CacheLoader<T, V>() {
@Override
public V load(T key) {
return withInitial.apply(key);
}
});
}
/*
Exceptions
*/

View File

@ -51,7 +51,7 @@ public class CombinedBlocks implements IBlocks {
public char[] load(int layer) {
if (primary.hasSection(layer)) {
char[] blocks = primary.load(layer);
if (secondary.hasSection(layer)) {
if (secondary.hasSection(layer) && primary != secondary) {
int i = 0;
for (; i < 4096; i++) {
if (blocks[i] == 0) {
@ -75,42 +75,55 @@ public class CombinedBlocks implements IBlocks {
@Override
public BlockState getBlock(int x, int y, int z) {
BlockState block = primary.getBlock(x, y, z);
if (block == null) {
if (block.getBlockType() == BlockTypes.__RESERVED__) {
return secondary.getBlock(x, y, z);
}
return BlockTypes.__RESERVED__.getDefaultState();
return block;
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
Map<BlockVector3, CompoundTag> tiles = primary.getTiles();
if (tiles.isEmpty()) {
return secondary.getTiles();
}
Map<BlockVector3, CompoundTag> otherTiles = secondary.getTiles();
if (!otherTiles.isEmpty()) {
HashMap<BlockVector3, CompoundTag> copy = null;
for (Map.Entry<BlockVector3, CompoundTag> entry : otherTiles.entrySet()) {
BlockVector3 pos = entry.getKey();
BlockState block = primary.getBlock(pos.getX(), pos.getY(), pos.getZ());
if (block.getBlockType() == BlockTypes.__RESERVED__) {
if (copy == null) copy = new HashMap<>(tiles);
copy.put(pos, entry.getValue());
}
if (primary != secondary) {
if (tiles.isEmpty()) {
return secondary.getTiles();
}
Map<BlockVector3, CompoundTag> otherTiles = secondary.getTiles();
if (!otherTiles.isEmpty()) {
HashMap<BlockVector3, CompoundTag> copy = null;
for (Map.Entry<BlockVector3, CompoundTag> entry : otherTiles.entrySet()) {
BlockVector3 pos = entry.getKey();
BlockState block = primary.getBlock(pos.getX(), pos.getY(), pos.getZ());
if (block.getBlockType() == BlockTypes.__RESERVED__) {
if (copy == null) copy = new HashMap<>(tiles);
copy.put(pos, entry.getValue());
}
}
if (copy != null) return copy;
}
if (copy != null) return copy;
}
return tiles;
}
@Override
public CompoundTag getTile(int x, int y, int z) {
CompoundTag tile = primary.getTile(x, y, z);
if (tile != null) {
return tile;
}
return secondary.getTile(x, y, z);
}
@Override
public Set<CompoundTag> getEntities() {
Set<CompoundTag> ents1 = primary.getEntities();
Set<CompoundTag> ents2 = secondary.getEntities();
if (ents1.isEmpty()) return ents2;
if (ents2.isEmpty()) return ents1;
HashSet<CompoundTag> joined = new HashSet<>(ents1);
joined.addAll(ents2);
Set<CompoundTag> joined = primary.getEntities();
if (primary != secondary) {
Set<CompoundTag> ents2 = secondary.getEntities();
if (joined.isEmpty()) return ents2;
if (ents2.isEmpty()) return joined;
joined = new HashSet<>(joined);
joined.addAll(ents2);
}
return joined;
}

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.beta;
import com.boydti.fawe.beta.implementation.filter.block.CharFilterBlock;
import com.boydti.fawe.beta.implementation.filter.block.FilterBlock;
import com.sk89q.worldedit.regions.Region;
import javax.annotation.Nullable;

View File

@ -1,6 +1,9 @@
package com.boydti.fawe.beta;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.implementation.filter.block.CharFilterBlock;
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
import com.boydti.fawe.beta.implementation.filter.block.FilterBlock;
import com.boydti.fawe.beta.implementation.processors.EmptyBatchProcessor;
import com.boydti.fawe.beta.implementation.processors.MultiBatchProcessor;
import com.sk89q.jnbt.CompoundTag;

View File

@ -31,6 +31,8 @@ public interface IBlocks extends Trimable {
Map<BlockVector3, CompoundTag> getTiles();
CompoundTag getTile(int x, int y, int z);
Set<CompoundTag> getEntities();
BiomeType getBiomeType(int x, int y, int z);

View File

@ -90,7 +90,7 @@ public interface IChunk extends Trimable, IChunkGet, IChunkSet {
BaseBlock getFullBlock(int x, int y, int z);
@Override
CompoundTag getTag(int x, int y, int z);
CompoundTag getTile(int x, int y, int z);
@Override
default IChunk reset() {

View File

@ -26,9 +26,6 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput {
@Override
BlockState getBlock(int x, int y, int z);
@Override
CompoundTag getTag(int x, int y, int z);
@Override
Map<BlockVector3, CompoundTag> getTiles();

View File

@ -54,6 +54,11 @@ public interface IDelegateChunk<U extends IQueueChunk> extends IQueueChunk {
// getParent().flood(flood, mask, block);
// }
@Override
default CompoundTag getTile(int x, int y, int z) {
return getParent().getTile(x, y, z);
}
@Override
default boolean setTile(int x, int y, int z, CompoundTag tag) {
return getParent().setTile(x, y, z, tag);

View File

@ -3,5 +3,5 @@ package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
public interface ITileInput {
CompoundTag getTag(int x, int y, int z);
CompoundTag getTile(int x, int y, int z);
}

View File

@ -12,6 +12,7 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@ -26,6 +27,11 @@ public class BitSetBlocks implements IChunkSet {
this.blockState = blockState;
}
@Override
public boolean hasSection(int layer) {
return row.rows[layer] != MemBlockSet.NULL_ROW_Y;
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
@ -122,12 +128,17 @@ public class BitSetBlocks implements IChunkSet {
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return Collections.emptyMap();
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return null;
}
@Override
public Set<CompoundTag> getEntities() {
return null;
return Collections.emptySet();
}
@Override
@ -135,11 +146,6 @@ public class BitSetBlocks implements IChunkSet {
return null;
}
@Override
public boolean hasSection(int layer) {
return false;
}
@Override
public IChunkSet reset() {
row.reset();

View File

@ -55,6 +55,11 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
return tiles == null ? Collections.emptyMap() : tiles;
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return tiles == null ? null : tiles.get(x, y, z);
}
@Override
public Set<CompoundTag> getEntities() {
return entities == null ? Collections.emptySet() : entities;

View File

@ -42,7 +42,7 @@ public class FallbackChunkGet implements IChunkGet {
}
@Override
public CompoundTag getTag(int x, int y, int z) {
public CompoundTag getTile(int x, int y, int z) {
return extent.getFullBlock(bx + x, y, bz + z).getNbtData();
}

View File

@ -37,13 +37,13 @@ public enum NullChunkGet implements IChunkGet {
}
@Override
public CompoundTag getTag(int x, int y, int z) {
return null;
public Map<BlockVector3, CompoundTag> getTiles() {
return Collections.emptyMap();
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return Collections.emptyMap();
public CompoundTag getTile(int x, int y, int z) {
return null;
}
@Override

View File

@ -1,8 +1,6 @@
package com.boydti.fawe.beta.implementation.chunk;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.CombinedBlocks;
import com.boydti.fawe.beta.IBlocks;
import com.boydti.fawe.beta.IQueueChunk;
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
@ -65,6 +63,11 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk {
return delegate.set(this).setTile(x, y, z, tag);
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return delegate.set(this).getTile(x, y, z);
}
@Override
public void setEntity(CompoundTag tag) {
delegate.set(this).setEntity(tag);
@ -316,18 +319,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk {
final IChunkGet get = getOrCreateGet();
final IChunkSet set = getOrCreateSet();
try {
block = block.init(chunkX, chunkZ, get);
if (region != null) {
region.filter(this, filter, block, get, set, full);
} else {
for (int layer = 0; layer < 16; layer++) {
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(this, layer)) {
continue;
}
block.init(get, set, layer);
block.filter(filter);
}
}
block.filter(this, get, set, filter, region, full);
} finally {
filter.finishChunk(this);
}

View File

@ -122,6 +122,11 @@ public enum NullChunk implements IQueueChunk {
return Collections.emptyMap();
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return null;
}
@Override
public Set<CompoundTag> getEntities() {
return Collections.emptySet();

View File

@ -2,11 +2,14 @@ package com.boydti.fawe.beta.implementation.filter.block;
import com.sk89q.worldedit.extent.Extent;
public abstract class SimpleFilterBlock extends FilterBlock {
/**
* Filter block with an extent
*/
public abstract class AbstractExtentFilterBlock extends FilterBlock {
private final Extent extent;
public SimpleFilterBlock(Extent extent) {
public AbstractExtentFilterBlock(Extent extent) {
this.extent = extent;
}

View File

@ -8,12 +8,11 @@ import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import javax.annotation.Nullable;
public class ArrayFilterBlock extends SimpleFilterBlock {
public class ArrayFilterBlock extends AbstractExtentFilterBlock {
private final char[] blocks;
private final byte[] heights;
@ -22,6 +21,7 @@ public class ArrayFilterBlock extends SimpleFilterBlock {
private int x, z, index;
private char ordinal;
// TODO use in CFI
public ArrayFilterBlock(Extent extent, char[] blocks, byte[] heights, int width, int length,
int yOffset) {
super(extent);

View File

@ -6,9 +6,9 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlockMask;
import com.boydti.fawe.beta.Flood;
import com.boydti.fawe.beta.IBlocks;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
@ -38,6 +38,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
block.initSet().set(block, value);
}
};
private CharGetBlocks get;
private IChunkSet set;
private char[] getArr;
@ -47,13 +48,12 @@ public class CharFilterBlock extends ChunkFilterBlock {
// local
private int layer, index, x, y, z, xx, yy, zz, chunkX, chunkZ;
public CharFilterBlock(IQueueExtent queueExtent) {
super(queueExtent);
public CharFilterBlock(Extent extent) {
super(extent);
}
@Override
public final ChunkFilterBlock init(int chunkX, int chunkZ, IChunkGet chunk) {
this.get = (CharGetBlocks) chunk;
public final ChunkFilterBlock initChunk(int chunkX, int chunkZ) {
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.xx = chunkX << 4;
@ -61,12 +61,34 @@ public class CharFilterBlock extends ChunkFilterBlock {
return this;
}
@Override
public final ChunkFilterBlock initLayer(IBlocks iget, IChunkSet iset, int layer) {
this.get = (CharGetBlocks) iget;
this.layer = layer;
final IBlocks get = (CharGetBlocks) iget;
if (!get.hasSection(layer)) {
getArr = FaweCache.IMP.EMPTY_CHAR_4096;
} else {
getArr = get.load(layer);
}
this.set = iset;
if (set.hasSection(layer)) {
setArr = set.load(layer);
delegate = FULL;
} else {
delegate = NULL;
setArr = null;
}
this.yy = layer << 4;
return this;
}
@Override
public void flood(IChunkGet iget, IChunkSet iset, int layer, Flood flood,
FilterBlockMask mask) {
final int maxDepth = flood.getMaxDepth();
final boolean checkDepth = maxDepth < Character.MAX_VALUE;
if (init(iget, iset, layer) != null) { // TODO replace with hasSection
if (initLayer(iget, iset, layer) != null) { // TODO replace with hasSection
while ((index = flood.poll()) != -1) {
x = index & 15;
z = index >> 4 & 15;
@ -85,27 +107,6 @@ public class CharFilterBlock extends ChunkFilterBlock {
}
}
@Override
public final ChunkFilterBlock init(IChunkGet iget, IChunkSet iset, int layer) {
this.layer = layer;
final CharGetBlocks get = (CharGetBlocks) iget;
if (!get.hasSection(layer)) {
getArr = FaweCache.IMP.EMPTY_CHAR_4096;
} else {
getArr = get.sections[layer].get(get, layer);
}
this.set = iset;
if (set.hasSection(layer)) {
setArr = set.load(layer);
delegate = FULL;
} else {
delegate = NULL;
setArr = null;
}
this.yy = layer << 4;
return this;
}
@Override
public void filter(Filter filter, int x, int y, int z) {
this.x = x;
@ -247,7 +248,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
final BlockState state = getBlock();
final BlockMaterial material = state.getMaterial();
if (material.hasContainer()) {
final CompoundTag tag = get.getTag(x, y + yy, z);
final CompoundTag tag = get.getTile(x, y + yy, z);
return state.toBaseBlock(tag);
}
return state.toBaseBlock();
@ -264,7 +265,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
@Override
public final CompoundTag getNbtData() {
return get.getTag(x, y + yy, z);
return get.getTile(x, y + yy, z);
}
/*
NORTH(Vector3.at(0, 0, -1), Flag.CARDINAL, 3, 1),

View File

@ -3,34 +3,132 @@ package com.boydti.fawe.beta.implementation.filter.block;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlockMask;
import com.boydti.fawe.beta.Flood;
import com.boydti.fawe.beta.IBlocks;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.regions.Region;
public abstract class ChunkFilterBlock extends SimpleFilterBlock {
/**
* Filter block implementation which uses chunks
* - First call initChunk
* - Then for each layer, call initLayer
* - Then use whatever filter method you want, to iterate over the blocks in that layer
*/
public abstract class ChunkFilterBlock extends AbstractExtentFilterBlock {
public ChunkFilterBlock(Extent extent) {
super(extent);
}
public abstract ChunkFilterBlock init(int chunkX, int chunkZ, IChunkGet chunk);
/**
* Initialize with chunk coordinates
* - The layer must also be initialized
* @param chunkX
* @param chunkZ
* @return
*/
public abstract ChunkFilterBlock initChunk(int chunkX, int chunkZ);
public abstract ChunkFilterBlock init(IChunkGet iget, IChunkSet iset,
int layer);
/**
* Initialize a chunk layer
* - The chunk coordinates must also be initialized first
* @param iget
* @param iset
* @param layer
* @return
*/
public abstract ChunkFilterBlock initLayer(IBlocks iget, IChunkSet iset, int layer);
public abstract void flood(IChunkGet iget, IChunkSet iset, int layer,
Flood flood, FilterBlockMask mask);
/**
* filter a single block
* @param filter
* @param x
* @param y
* @param z
*/
public abstract void filter(Filter filter, int x, int y, int z);
/**
* Filter a cuboid region
* @param filter
* @param minX
* @param minY
* @param minZ
* @param maxX
* @param maxY
* @param maxZ
*/
public abstract void filter(Filter filter, int minX, int minY, int minZ, int maxX, int maxY,
int maxZ);
/**
* Filter everything in the layer
* @param filter
*/
public abstract void filter(Filter filter);
/**
* Filter everything between y layers
* @param filter
* @param yStart
* @param yEnd
*/
public abstract void filter(Filter filter, int yStart, int yEnd);
/**
* Filter with a region
* @param filter
* @param region
*/
public abstract void filter(Filter filter, Region region);
/**
* Filter with a chunk object
* @param chunk
* @param get
* @param set
* @param filter
* @return
*/
public final IChunkSet filter(IChunk chunk, IChunkGet get, IChunkSet set, Filter filter) {
initChunk(chunk.getX(), chunk.getZ());
for (int layer = 0; layer < 16; layer++) {
if (set.hasSection(layer)) {
initLayer(get, set, layer);
filter(filter);
}
}
return set;
}
/**
* Filter a chunk with a region / filter
* @param chunk
* @param get
* @param set
* @param filter
* @param region
* @param full
* @return
*/
public final IChunkSet filter(IChunk chunk, IChunkGet get, IChunkSet set, Filter filter, Region region, boolean full) {
if (region != null) {
region.filter(chunk, filter, this, get, set, full);
} else {
for (int layer = 0; layer < 16; layer++) {
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
continue;
}
initLayer(get, set, layer);
filter(filter);
}
}
return set;
}
}

View File

@ -12,6 +12,10 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nullable;
/**
* A class representing a block with a position
* - Used for optimized block operations to avoid lookups
*/
public abstract class FilterBlock extends BlockVector3 implements Extent, TileEntityBlock {
public abstract Extent getExtent();

View File

@ -501,12 +501,8 @@ public class MCAChunk implements IChunk {
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
return null;
}
@Override
public CompoundTag getTag(int x, int y, int z) {
return null;
BlockState block = getBlock(x, y, z);
return block.toBaseBlock(this, x, y, z);
}
@Override
@ -570,18 +566,7 @@ public class MCAChunk implements IChunk {
@Override
public void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) {
try {
if (region != null) {
region.filter(this, filter, block, this, this, full);
} else {
block = block.init(chunkX, chunkZ, this);
for (int layer = 0; layer < 16; layer++) {
if ((!full && !this.hasSection(layer)) || !filter.appliesLayer(this, layer)) {
continue;
}
block.init(this, this, layer);
block.filter(filter);
}
}
block.filter(this, this, this, filter, region, full);
} finally {
filter.finishChunk(this);
}

View File

@ -47,6 +47,12 @@ public class BlockVector3ChunkMap<T> implements Map<BlockVector3, T>, IAdaptedMa
return map.put(key, value);
}
public T get(int x, int y, int z) {
short key = MathMan.tripleBlockCoord(x, y, z);
return map.get(key);
}
public T remove(int x, int y, int z) {
short key = MathMan.tripleBlockCoord(x, y, z);
return map.remove(key);

View File

@ -824,7 +824,7 @@ public final class MemBlockSet extends BlockSet {
}
public static final class RowZ implements IRow {
private final IRow[] rows;
public final IRow[] rows;
public RowZ() {
this.rows = new IRow[FaweCache.IMP.CHUNK_LAYERS];