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;
|
||||
|
||||
import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter;
|
||||
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
|
||||
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
|
||||
import com.fastasyncworldedit.core.queue.Filter;
|
||||
import com.fastasyncworldedit.core.queue.IChunk;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
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 <S> Child which extends Filter
|
||||
* @param <L> Left 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
|
||||
public static <T extends Filter, S extends Filter> LinkedFilter<? extends T, ? extends S> of(T parent, S child) {
|
||||
if (parent instanceof VectorizedFilter p && child instanceof VectorizedFilter c) {
|
||||
return new VectorizedLinkedFilter(p, c);
|
||||
public static <L extends Filter, R extends Filter> LinkedFilter<? extends L, ? extends R> of(L left, R right) {
|
||||
if (left instanceof VectorizedFilter l && right instanceof VectorizedFilter r) {
|
||||
return new VectorizedLinkedFilter(l, r);
|
||||
}
|
||||
return new LinkedFilter<>(parent, child);
|
||||
return new LinkedFilter<>(left, right);
|
||||
}
|
||||
|
||||
public LinkedFilter(T parent, S child) {
|
||||
super(parent);
|
||||
this.child = child;
|
||||
public L getLeft() {
|
||||
return this.left;
|
||||
}
|
||||
|
||||
public S getChild() {
|
||||
return this.child;
|
||||
public R getRight() {
|
||||
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
|
||||
public void applyBlock(FilterBlock block) {
|
||||
this.getParent().applyBlock(block);
|
||||
this.getChild().applyBlock(block);
|
||||
getLeft().applyBlock(block);
|
||||
getRight().applyBlock(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedFilter<? extends LinkedFilter<T, S>, ? extends Filter> newInstance(Filter other) {
|
||||
return new LinkedFilter<>(this, other);
|
||||
public void finishChunk(IChunk chunk) {
|
||||
getLeft().finishChunk(chunk);
|
||||
getRight().finishChunk(chunk);
|
||||
}
|
||||
|
||||
private final static class VectorizedLinkedFilter<T extends VectorizedFilter, S extends VectorizedFilter>
|
||||
extends LinkedFilter<T, S> implements VectorizedFilter {
|
||||
@Override
|
||||
public Filter fork() {
|
||||
return new LinkedFilter<>(getLeft().fork(), getRight().fork());
|
||||
}
|
||||
|
||||
public VectorizedLinkedFilter(final T parent, final S child) {
|
||||
super(parent, child);
|
||||
@Override
|
||||
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
|
||||
public ShortVector applyVector(final ShortVector get, final ShortVector set) {
|
||||
ShortVector res = getParent().applyVector(get, set);
|
||||
return getChild().applyVector(get, res);
|
||||
ShortVector res = getLeft().applyVector(get, set);
|
||||
return getRight().applyVector(get, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedFilter<? extends LinkedFilter<T, S>, Filter> newInstance(Filter other) {
|
||||
if (other instanceof VectorizedFilter o) {
|
||||
return new VectorizedLinkedFilter(this, o);
|
||||
}
|
||||
return new LinkedFilter<>(this, other);
|
||||
}
|
||||
public Filter fork() {
|
||||
return new VectorizedLinkedFilter<>((L) getLeft().fork(), (R) getRight().fork());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -83,12 +83,20 @@ public abstract class ChunkFilterBlock extends AbstractExtentFilterBlock {
|
||||
/**
|
||||
* 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) {
|
||||
region.filter(chunk, filter, this, get, set, full);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
initLayer(get, set, layer);
|
||||
|
@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.queue;
|
||||
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
@ -10,30 +11,29 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public interface Filter {
|
||||
|
||||
/**
|
||||
* Checks whether a chunk should be read.
|
||||
*
|
||||
* @param chunkX the x coordinate in the chunk
|
||||
* @param chunkZ the z coordinate in the chunk
|
||||
*/
|
||||
default boolean appliesChunk(
|
||||
int chunkX,
|
||||
int chunkZ
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
// /**
|
||||
// * Checks whether a chunk should be read.
|
||||
// *
|
||||
// * @param chunkX the x coordinate in the chunk
|
||||
// * @param chunkZ the z coordinate in the chunk
|
||||
// */
|
||||
// default boolean appliesChunk(
|
||||
// int chunkX,
|
||||
// int chunkZ
|
||||
// ) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Do something with the IChunk<br> - Return null if you don't want to filter blocks<br> -
|
||||
* Return the chunk if you do want to filter blocks<br>
|
||||
* Do something with the IChunk<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;
|
||||
}
|
||||
|
||||
default boolean appliesLayer(IChunk chunk, int layer) {
|
||||
return true;
|
||||
}
|
||||
// default boolean appliesLayer(IChunk chunk, int layer) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
@Override
|
||||
default boolean appliesChunk(int chunkX, int chunkZ) {
|
||||
return getParent().appliesChunk(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
default <V extends IChunk> V applyChunk(V chunk, @Nullable Region region) {
|
||||
return getParent().applyChunk(chunk, region);
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean appliesLayer(IChunk chunk, int layer) {
|
||||
return getParent().appliesLayer(chunk, layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void applyBlock(FilterBlock block) {
|
||||
getParent().applyBlock(block);
|
||||
|
@ -140,9 +140,9 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
|
||||
int chunkZ,
|
||||
boolean full
|
||||
) {
|
||||
if (!filter.appliesChunk(chunkX, chunkZ)) {
|
||||
return block;
|
||||
}
|
||||
// if (!filter.appliesChunk(chunkX, chunkZ)) {
|
||||
// return block;
|
||||
// }
|
||||
T chunk = this.getOrCreateChunk(chunkX, chunkZ);
|
||||
|
||||
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.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Countable;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
@ -227,7 +226,7 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
||||
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
|
||||
VectorizedFilter vectorizedPattern = SimdSupport.vectorizedPattern(pattern);
|
||||
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
|
||||
|
@ -269,7 +269,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4);
|
||||
int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4);
|
||||
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;
|
||||
}
|
||||
block = block.initLayer(get, set, layer);
|
||||
@ -319,7 +320,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
int layer,
|
||||
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;
|
||||
}
|
||||
block = block.initLayer(get, set, layer);
|
||||
@ -341,7 +343,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
int maxZ,
|
||||
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;
|
||||
}
|
||||
block = block.initLayer(get, set, layer);
|
||||
@ -359,7 +362,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
int yEnd,
|
||||
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;
|
||||
}
|
||||
block = block.initLayer(get, set, layer);
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren