Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make usage of stateful patterns thread-safe #2633

Merged
merged 4 commits into from Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern;

import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
Expand Down Expand Up @@ -57,4 +58,9 @@ public BaseBlock applyBlock(BlockVector3 vector) {
}
}

@Override
public Pattern fork() {
return new ExpressionPattern(this.expression.clone());
}

}
Expand Up @@ -7,6 +7,8 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;

import java.util.Arrays;

import static java.lang.Math.floorDiv;

/**
Expand Down Expand Up @@ -52,4 +54,10 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return patternsArray[index].apply(extent, get, set);
}

@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear2DBlockPattern(forked, this.xScale, this.zScale);
}

}
Expand Up @@ -7,6 +7,8 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;

import java.util.Arrays;

import static java.lang.Math.floorDiv;

/**
Expand Down Expand Up @@ -56,4 +58,10 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return patternsArray[index].apply(extent, get, set);
}

@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear3DBlockPattern(forked, this.xScale, this.yScale, this.zScale);
}

}
Expand Up @@ -7,6 +7,8 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;

import java.util.Arrays;

public class LinearBlockPattern extends AbstractPattern implements ResettablePattern {

private final Pattern[] patternsArray;
Expand Down Expand Up @@ -42,4 +44,10 @@ public void reset() {
index = 0;
}

@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new LinearBlockPattern(forked);
}

}
Expand Up @@ -43,4 +43,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return secondary.apply(extent, get, set);
}

@Override
public Pattern fork() {
return new MaskedPattern(this.mask.copy(), this.primary.fork(), this.secondary.fork());
}

}
Expand Up @@ -36,4 +36,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, mutable, set);
}

@Override
public Pattern fork() {
return new NoXPattern(this.pattern.fork());
}

}
Expand Up @@ -36,4 +36,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, mutable, set);
}

@Override
public Pattern fork() {
return new NoYPattern(this.pattern.fork());
}

}
@@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern;

import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
Expand Down Expand Up @@ -36,4 +37,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, mutable, set);
}

@Override
public Pattern fork() {
return new NoZPattern(this.pattern.fork());
}

}
Expand Up @@ -60,4 +60,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, get, mutable);
}

@Override
public Pattern fork() {
return new OffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}

}
Expand Up @@ -72,4 +72,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, get, mutable);
}

@Override
public Pattern fork() {
return new RandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}

}
Expand Up @@ -63,4 +63,11 @@ public void reset() {
origin = null;
}

@Override
public Pattern fork() {
RelativePattern forked = new RelativePattern(this.pattern.fork(), this.minY, this.maxY);
forked.origin = this.origin; // maintain origin for forks
Copy link
Member

@dordsor21 dordsor21 Mar 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably look at having the origin be toImmutable()ised when it's set (for this and any other patterns)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would otherwise already cause bugs I think? But yeah, that might make sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly, but can't be too careful aha

return forked;
}

}
Expand Up @@ -94,4 +94,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W
return pattern.apply(extent, get, set);
}

@Override
public Pattern fork() {
return new SolidRandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}

}
Expand Up @@ -129,4 +129,9 @@ private boolean canPassthrough(BlockVector3 v) {
return !block.getBlockType().getMaterial().isMovementBlocker();
}

@Override
public Pattern fork() {
return new SurfaceRandomOffsetPattern(this.pattern.fork(), this.moves, this.minY, this.maxY);
}

}
Expand Up @@ -235,4 +235,11 @@ public Iterable<BlockVector2> asFlatRegion() {
};
}

//FAWE - stateful pattern
@Override
public Pattern fork() {
return new ForgetfulExtentBuffer(extent, mask.copy());
}
//FAWE end

}
Expand Up @@ -25,6 +25,8 @@
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;

import java.util.Arrays;

import static com.google.common.base.Preconditions.checkArgument;

/**
Expand Down Expand Up @@ -64,4 +66,12 @@ public BaseBlock applyBlock(BlockVector3 position) {
return lastBlock;
}

//FAWE - stateful pattern
@Override
public Pattern fork() {
final Pattern[] forkedPatterns = Arrays.stream(patterns).map(Pattern::fork).toArray(Pattern[]::new);
return new ExtentBufferedCompositePattern(getExtent(), forkedPatterns);
}
//FAWE end

}
Expand Up @@ -59,6 +59,11 @@ default void applyBlock(final FilterBlock block) {
apply(block, block, block);
}

@Override
default Pattern fork() { // covariant return type
return this;
}

//FAWE end

/**
Expand Down
Expand Up @@ -67,6 +67,13 @@ public RandomPattern(SimpleRandom random, RandomPattern parent) {
this.collection = RandomCollection.of(weights, random);
this.patterns = parent.patterns;
}

private RandomPattern(SimpleRandom random, Map<Pattern, Double> weights) {
this.random = random;
this.weights = weights;
this.collection = RandomCollection.of(weights, random);
this.patterns = new LinkedHashSet<>(weights.keySet());
}
//FAWE end

/**
Expand Down Expand Up @@ -107,6 +114,14 @@ public BaseBlock applyBlock(BlockVector3 position) {
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return collection.next(get.getBlockX(), get.getBlockY(), get.getBlockZ()).apply(extent, get, set);
}

@Override
public Pattern fork() {
final LinkedHashMap<Pattern, Double> newWeights = new LinkedHashMap<>();
this.weights.forEach((p, w) -> newWeights.put(p.fork(), w));
return new RandomPattern(this.random, newWeights);
}

//FAWE end

}
Expand Up @@ -29,13 +29,16 @@

import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import static com.sk89q.worldedit.blocks.Blocks.resolveProperties;

public class StateApplyingPattern extends AbstractExtentPattern {

private final Map<String, String> states;
private final Map<BlockType, Map<Property<Object>, Object>> cache = Maps.newHashMap();
//FAWE - avoid race conditions
private final Map<BlockType, Map<Property<Object>, Object>> cache = new ConcurrentHashMap<>();
//FAWE end

public StateApplyingPattern(Extent extent, Map<String, String> statesToSet) {
super(extent);
Expand Down