Skip to content

Commit 4e57613

Browse files
authored
Reduce lock contention caused by regen pattern (#3046)
1 parent 77264c3 commit 4e57613

File tree

1 file changed

+64
-14
lines changed
  • worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter

1 file changed

+64
-14
lines changed

worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.fastasyncworldedit.bukkit.adapter;
22

3+
import com.fastasyncworldedit.core.queue.IChunk;
34
import com.fastasyncworldedit.core.queue.IChunkCache;
45
import com.fastasyncworldedit.core.queue.IChunkGet;
56
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
@@ -16,12 +17,14 @@
1617
import com.sk89q.worldedit.world.block.BaseBlock;
1718
import org.bukkit.generator.BiomeProvider;
1819
import org.bukkit.generator.WorldInfo;
20+
import org.jetbrains.annotations.NotNull;
21+
import org.jetbrains.annotations.Nullable;
1922

2023
import java.util.Collections;
2124
import java.util.List;
2225
import java.util.concurrent.TimeUnit;
26+
import java.util.function.BiFunction;
2327
import java.util.function.BooleanSupplier;
24-
import java.util.function.Function;
2528

2629
/**
2730
* Represents an abstract regeneration handler.
@@ -109,18 +112,45 @@ private void copyToWorld() {
109112
boolean genbiomes = options.shouldRegenBiomes();
110113
boolean hasBiome = options.hasBiomeType();
111114
BiomeType biome = options.getBiomeType();
115+
Pattern pattern;
112116
if (!genbiomes && !hasBiome) {
113-
target.setBlocks(region, new PlacementPattern());
114-
}
115-
if (hasBiome) {
116-
target.setBlocks(region, new WithBiomePlacementPattern(ignored -> biome));
117-
} else if (genbiomes) {
118-
target.setBlocks(region, new WithBiomePlacementPattern(vec -> source.getBiome(vec)));
117+
pattern = new PlacementPattern();
118+
} else if (hasBiome) {
119+
pattern = new WithBiomePlacementPattern((ignored1, ignored2) -> biome);
120+
} else {
121+
pattern = new WithBiomePlacementPattern((vec, chunk) -> {
122+
if (chunk != null) {
123+
return chunk.getBiomeType(vec.x() & 15, vec.y(), vec.z() & 15);
124+
}
125+
return source.getBiome(vec);
126+
});
119127
}
128+
target.setBlocks(region, pattern);
120129
TaskManager.taskManager().cancel(taskId);
121130
}
122131

123-
private class PlacementPattern implements Pattern {
132+
private abstract class ChunkwisePattern implements Pattern {
133+
// the chunk we're currently operating on, if any.
134+
// allows faster access to chunk data than source.getFullBlock(...)
135+
protected @Nullable IChunk chunk;
136+
137+
@Override
138+
public @NotNull <T extends IChunk> T applyChunk(final T chunk, @Nullable final Region region) {
139+
this.chunk = source.getOrCreateChunk(chunk.getX(), chunk.getZ());
140+
return chunk;
141+
}
142+
143+
@Override
144+
public void finishChunk(final IChunk chunk) {
145+
this.chunk = null;
146+
}
147+
148+
@Override
149+
public abstract Pattern fork();
150+
151+
}
152+
153+
private class PlacementPattern extends ChunkwisePattern {
124154

125155
@Override
126156
public BaseBlock applyBlock(final BlockVector3 position) {
@@ -129,16 +159,26 @@ public BaseBlock applyBlock(final BlockVector3 position) {
129159

130160
@Override
131161
public boolean apply(final Extent extent, final BlockVector3 get, final BlockVector3 set) throws WorldEditException {
132-
return extent.setBlock(set.x(), set.y(), set.z(), source.getFullBlock(get.x(), get.y(), get.z()));
162+
BaseBlock fullBlock;
163+
if (chunk != null) {
164+
fullBlock = chunk.getFullBlock(get.x() & 15, get.y(), get.z() & 15);
165+
} else {
166+
fullBlock = source.getFullBlock(get.x(), get.y(), get.z());
167+
}
168+
return set.setFullBlock(extent, fullBlock);
133169
}
134170

171+
@Override
172+
public Pattern fork() {
173+
return new PlacementPattern();
174+
}
135175
}
136176

137-
private class WithBiomePlacementPattern implements Pattern {
177+
private class WithBiomePlacementPattern extends ChunkwisePattern {
138178

139-
private final Function<BlockVector3, BiomeType> biomeGetter;
179+
private final BiFunction<BlockVector3, @Nullable IChunk, BiomeType> biomeGetter;
140180

141-
private WithBiomePlacementPattern(final Function<BlockVector3, BiomeType> biomeGetter) {
181+
private WithBiomePlacementPattern(final BiFunction<BlockVector3, @Nullable IChunk, BiomeType> biomeGetter) {
142182
this.biomeGetter = biomeGetter;
143183
}
144184

@@ -149,10 +189,20 @@ public BaseBlock applyBlock(final BlockVector3 position) {
149189

150190
@Override
151191
public boolean apply(final Extent extent, final BlockVector3 get, final BlockVector3 set) throws WorldEditException {
152-
return extent.setBlock(set.x(), set.y(), set.z(), source.getFullBlock(get.x(), get.y(), get.z()))
153-
&& extent.setBiome(set.x(), set.y(), set.z(), biomeGetter.apply(get));
192+
final BaseBlock fullBlock;
193+
if (chunk != null) {
194+
fullBlock = chunk.getFullBlock(get.x() & 15, get.y(), get.z() & 15);
195+
} else {
196+
fullBlock = source.getFullBlock(get.x(), get.y(), get.z());
197+
}
198+
return extent.setBlock(set.x(), set.y(), set.z(), fullBlock)
199+
&& extent.setBiome(set.x(), set.y(), set.z(), biomeGetter.apply(get, chunk));
154200
}
155201

202+
@Override
203+
public Pattern fork() {
204+
return new WithBiomePlacementPattern(this.biomeGetter);
205+
}
156206
}
157207

158208
//functions to be implemented by sub class

0 commit comments

Comments
 (0)