Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-17 00:20:09 +01:00
fix: adjust linked filter to be left-right and do not link to new forked instances (#2913)
* fix: adjust linked filter to be left-right and do not link to new forked instances - Assume that child filters know about their own forks - fixes #1874 * Remove appliesChunk|Layer for now
Dieser Commit ist enthalten in:
Ursprung
393f80165c
Commit
7daafa97f0
@ -1,69 +1,92 @@
|
|||||||
package com.fastasyncworldedit.core.extent.filter;
|
package com.fastasyncworldedit.core.extent.filter;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter;
|
|
||||||
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
|
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
|
||||||
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
|
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
|
||||||
import com.fastasyncworldedit.core.queue.Filter;
|
import com.fastasyncworldedit.core.queue.Filter;
|
||||||
|
import com.fastasyncworldedit.core.queue.IChunk;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import jdk.incubator.vector.ShortVector;
|
import jdk.incubator.vector.ShortVector;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter which links two Filters together for single-filter-input operations.
|
* Filter which links two Filters together for single-filter-input operations. Left filter is operated first.
|
||||||
*
|
*
|
||||||
* @param <T> Parent which extends Filter
|
* @param <L> Left filter
|
||||||
* @param <S> Child which extends Filter
|
* @param <R> Right filter
|
||||||
*/
|
*/
|
||||||
public sealed class LinkedFilter<T extends Filter, S extends Filter> extends DelegateFilter<T> {
|
public sealed class LinkedFilter<L extends Filter, R extends Filter> implements Filter {
|
||||||
|
|
||||||
private final S child;
|
private final L left;
|
||||||
|
private final R right;
|
||||||
|
|
||||||
|
public LinkedFilter(L left, R right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"}) // we defeated the type system
|
@SuppressWarnings({"unchecked", "rawtypes"}) // we defeated the type system
|
||||||
public static <T extends Filter, S extends Filter> LinkedFilter<? extends T, ? extends S> of(T parent, S child) {
|
public static <L extends Filter, R extends Filter> LinkedFilter<? extends L, ? extends R> of(L left, R right) {
|
||||||
if (parent instanceof VectorizedFilter p && child instanceof VectorizedFilter c) {
|
if (left instanceof VectorizedFilter l && right instanceof VectorizedFilter r) {
|
||||||
return new VectorizedLinkedFilter(p, c);
|
return new VectorizedLinkedFilter(l, r);
|
||||||
}
|
}
|
||||||
return new LinkedFilter<>(parent, child);
|
return new LinkedFilter<>(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedFilter(T parent, S child) {
|
public L getLeft() {
|
||||||
super(parent);
|
return this.left;
|
||||||
this.child = child;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public S getChild() {
|
public R getRight() {
|
||||||
return this.child;
|
return this.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends IChunk> T applyChunk(T chunk, @Nullable Region region) {
|
||||||
|
chunk = getLeft().applyChunk(chunk, region);
|
||||||
|
return getRight().applyChunk(chunk, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyBlock(FilterBlock block) {
|
public void applyBlock(FilterBlock block) {
|
||||||
this.getParent().applyBlock(block);
|
getLeft().applyBlock(block);
|
||||||
this.getChild().applyBlock(block);
|
getRight().applyBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LinkedFilter<? extends LinkedFilter<T, S>, ? extends Filter> newInstance(Filter other) {
|
public void finishChunk(IChunk chunk) {
|
||||||
return new LinkedFilter<>(this, other);
|
getLeft().finishChunk(chunk);
|
||||||
|
getRight().finishChunk(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static class VectorizedLinkedFilter<T extends VectorizedFilter, S extends VectorizedFilter>
|
@Override
|
||||||
extends LinkedFilter<T, S> implements VectorizedFilter {
|
public Filter fork() {
|
||||||
|
return new LinkedFilter<>(getLeft().fork(), getRight().fork());
|
||||||
|
}
|
||||||
|
|
||||||
public VectorizedLinkedFilter(final T parent, final S child) {
|
@Override
|
||||||
super(parent, child);
|
public void join() {
|
||||||
|
getLeft().join();
|
||||||
|
getRight().join();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static class VectorizedLinkedFilter<L extends VectorizedFilter, R extends VectorizedFilter>
|
||||||
|
extends LinkedFilter<L, R> implements VectorizedFilter {
|
||||||
|
|
||||||
|
public VectorizedLinkedFilter(final L left, final R right) {
|
||||||
|
super(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ShortVector applyVector(final ShortVector get, final ShortVector set) {
|
public ShortVector applyVector(final ShortVector get, final ShortVector set) {
|
||||||
ShortVector res = getParent().applyVector(get, set);
|
ShortVector res = getLeft().applyVector(get, set);
|
||||||
return getChild().applyVector(get, res);
|
return getRight().applyVector(get, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LinkedFilter<? extends LinkedFilter<T, S>, Filter> newInstance(Filter other) {
|
public Filter fork() {
|
||||||
if (other instanceof VectorizedFilter o) {
|
return new VectorizedLinkedFilter<>((L) getLeft().fork(), (R) getRight().fork());
|
||||||
return new VectorizedLinkedFilter(this, o);
|
}
|
||||||
}
|
|
||||||
return new LinkedFilter<>(this, other);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -83,12 +83,20 @@ public abstract class ChunkFilterBlock extends AbstractExtentFilterBlock {
|
|||||||
/**
|
/**
|
||||||
* Filter a chunk with a region / filter.
|
* Filter a chunk with a region / filter.
|
||||||
*/
|
*/
|
||||||
public synchronized final IChunkSet filter(IChunk chunk, IChunkGet get, IChunkSet set, Filter filter, Region region, boolean full) {
|
public synchronized final IChunkSet filter(
|
||||||
|
IChunk chunk,
|
||||||
|
IChunkGet get,
|
||||||
|
IChunkSet set,
|
||||||
|
Filter filter,
|
||||||
|
Region region,
|
||||||
|
boolean full
|
||||||
|
) {
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
region.filter(chunk, filter, this, get, set, full);
|
region.filter(chunk, filter, this, get, set, full);
|
||||||
} else {
|
} else {
|
||||||
for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) {
|
for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) {
|
||||||
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
//if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
||||||
|
if (!full && !get.hasSection(layer)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
initLayer(get, set, layer);
|
initLayer(get, set, layer);
|
||||||
|
@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.queue;
|
|||||||
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
|
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,30 +11,29 @@ import javax.annotation.Nullable;
|
|||||||
*/
|
*/
|
||||||
public interface Filter {
|
public interface Filter {
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Checks whether a chunk should be read.
|
// * Checks whether a chunk should be read.
|
||||||
*
|
// *
|
||||||
* @param chunkX the x coordinate in the chunk
|
// * @param chunkX the x coordinate in the chunk
|
||||||
* @param chunkZ the z coordinate in the chunk
|
// * @param chunkZ the z coordinate in the chunk
|
||||||
*/
|
// */
|
||||||
default boolean appliesChunk(
|
// default boolean appliesChunk(
|
||||||
int chunkX,
|
// int chunkX,
|
||||||
int chunkZ
|
// int chunkZ
|
||||||
) {
|
// ) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do something with the IChunk<br> - Return null if you don't want to filter blocks<br> -
|
* Do something with the IChunk<br>
|
||||||
* Return the chunk if you do want to filter blocks<br>
|
|
||||||
*/
|
*/
|
||||||
default <T extends IChunk> T applyChunk(T chunk, @Nullable Region region) {
|
default @Nonnull <T extends IChunk> T applyChunk(T chunk, @Nullable Region region) {
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean appliesLayer(IChunk chunk, int layer) {
|
// default boolean appliesLayer(IChunk chunk, int layer) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make changes to the block here<br> - e.g., block.setId(...)<br> - Note: Performance is
|
* Make changes to the block here<br> - e.g., block.setId(...)<br> - Note: Performance is
|
||||||
|
@ -9,21 +9,11 @@ public interface IDelegateFilter extends Filter {
|
|||||||
|
|
||||||
Filter getParent();
|
Filter getParent();
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean appliesChunk(int chunkX, int chunkZ) {
|
|
||||||
return getParent().appliesChunk(chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default <V extends IChunk> V applyChunk(V chunk, @Nullable Region region) {
|
default <V extends IChunk> V applyChunk(V chunk, @Nullable Region region) {
|
||||||
return getParent().applyChunk(chunk, region);
|
return getParent().applyChunk(chunk, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean appliesLayer(IChunk chunk, int layer) {
|
|
||||||
return getParent().appliesLayer(chunk, layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void applyBlock(FilterBlock block) {
|
default void applyBlock(FilterBlock block) {
|
||||||
getParent().applyBlock(block);
|
getParent().applyBlock(block);
|
||||||
|
@ -140,9 +140,9 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
|
|||||||
int chunkZ,
|
int chunkZ,
|
||||||
boolean full
|
boolean full
|
||||||
) {
|
) {
|
||||||
if (!filter.appliesChunk(chunkX, chunkZ)) {
|
// if (!filter.appliesChunk(chunkX, chunkZ)) {
|
||||||
return block;
|
// return block;
|
||||||
}
|
// }
|
||||||
T chunk = this.getOrCreateChunk(chunkX, chunkZ);
|
T chunk = this.getOrCreateChunk(chunkX, chunkZ);
|
||||||
|
|
||||||
T newChunk = filter.applyChunk(chunk, region);
|
T newChunk = filter.applyChunk(chunk, region);
|
||||||
|
@ -30,7 +30,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
|||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Countable;
|
import com.sk89q.worldedit.util.Countable;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
@ -227,7 +226,7 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
|
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
|
||||||
VectorizedFilter vectorizedPattern = SimdSupport.vectorizedPattern(pattern);
|
VectorizedFilter vectorizedPattern = SimdSupport.vectorizedPattern(pattern);
|
||||||
var filter = LinkedFilter.of(vectorizedPattern == null ? pattern : vectorizedPattern, new CountFilter());
|
var filter = LinkedFilter.of(vectorizedPattern == null ? pattern : vectorizedPattern, new CountFilter());
|
||||||
return this.changes = apply(region, filter, true).getChild().getTotal();
|
return this.changes = apply(region, filter, true).getRight().getTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -269,7 +269,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
|||||||
int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4);
|
int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4);
|
||||||
int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4);
|
int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4);
|
||||||
for (int layer = minSection; layer <= maxSection; layer++) {
|
for (int layer = minSection; layer <= maxSection; layer++) {
|
||||||
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
//if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
||||||
|
if (!full && !get.hasSection(layer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
block = block.initLayer(get, set, layer);
|
block = block.initLayer(get, set, layer);
|
||||||
@ -319,7 +320,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
|||||||
int layer,
|
int layer,
|
||||||
boolean full
|
boolean full
|
||||||
) {
|
) {
|
||||||
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
//if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
||||||
|
if (!full && !get.hasSection(layer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
block = block.initLayer(get, set, layer);
|
block = block.initLayer(get, set, layer);
|
||||||
@ -341,7 +343,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
|||||||
int maxZ,
|
int maxZ,
|
||||||
boolean full
|
boolean full
|
||||||
) {
|
) {
|
||||||
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
//if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
||||||
|
if (!full && !get.hasSection(layer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
block = block.initLayer(get, set, layer);
|
block = block.initLayer(get, set, layer);
|
||||||
@ -359,7 +362,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
|||||||
int yEnd,
|
int yEnd,
|
||||||
boolean full
|
boolean full
|
||||||
) {
|
) {
|
||||||
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
//if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
|
||||||
|
if (!full && !get.hasSection(layer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
block = block.initLayer(get, set, layer);
|
block = block.initLayer(get, set, layer);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren