Skip to content

Commit 5337cd0

Browse files
committed
Improve chunk regeneration performance
1 parent 0bc688a commit 5337cd0

File tree

7 files changed

+88
-13
lines changed

7 files changed

+88
-13
lines changed

LandLord-api/src/main/java/biz/princeps/landlord/api/IRegenerationManager.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import org.bukkit.Location;
44
import org.bukkit.World;
55

6+
import java.util.concurrent.CompletableFuture;
7+
68
public interface IRegenerationManager {
79

810
/**
@@ -22,4 +24,15 @@ public interface IRegenerationManager {
2224
default void regenerateChunk(Location location) {
2325
regenerateChunk(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
2426
}
27+
28+
/**
29+
* Regenerates all chunks of the given lands. All lands must belong to the same world.
30+
*
31+
* @param lands a non-empty iterable of lands to regenerate.
32+
* @return a future that completes when all given chunks are regenerated.
33+
*/
34+
default CompletableFuture<Void> regenerateChunks(Iterable<IOwnedLand> lands) {
35+
lands.forEach(l -> regenerateChunk(l.getALocation()));
36+
return CompletableFuture.completedFuture(null);
37+
}
2538
}

LandLord-core/src/main/java/biz/princeps/landlord/commands/claiming/Unclaim.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import org.bukkit.Particle;
1717
import org.bukkit.entity.Player;
1818

19+
import java.util.List;
20+
1921
/**
2022
* Project: LandLord
2123
* Created by Alex D. (SpatiumPrinceps)
@@ -125,7 +127,7 @@ public void performUnclaim(boolean isAdmin, IOwnedLand ol, Player player) {
125127
wg.unclaim(ol.getWorld(), ol.getName());
126128

127129
if (plugin.getConfig().getBoolean("CommandSettings.Unclaim.regenerate")) {
128-
plugin.getRegenerationManager().regenerateChunk(ol.getALocation());
130+
plugin.getRegenerationManager().regenerateChunks(List.of(ol));
129131
}
130132

131133
// remove possible homes

LandLord-core/src/main/java/biz/princeps/landlord/commands/management/Regenerate.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
import biz.princeps.lib.command.Properties;
1111
import biz.princeps.lib.gui.ConfirmationGUI;
1212
import com.google.common.collect.Sets;
13+
import org.bukkit.Bukkit;
1314
import org.bukkit.entity.Player;
1415
import org.bukkit.scheduler.BukkitRunnable;
1516

17+
import java.util.List;
18+
1619

1720
/**
1821
* Project: LandLord
@@ -83,10 +86,12 @@ public void run() {
8386
}
8487
}.runTask(plugin);
8588

86-
plugin.getRegenerationManager().regenerateChunk(finalLand.getALocation());
87-
lm.sendMessage(player, lm.getString(player, "Commands.Regenerate.success")
88-
.replace("%land%", finalLand.getName()));
89-
player.closeInventory();
89+
plugin.getRegenerationManager().regenerateChunks(List.of(finalLand))
90+
.whenCompleteAsync((v, e) -> {
91+
lm.sendMessage(player, lm.getString(player, "Commands.Regenerate.success")
92+
.replace("%land%", finalLand.getName()));
93+
player.closeInventory();
94+
}, r -> Bukkit.getScheduler().runTask(plugin, r));
9095
}
9196

9297
}, (p2) -> lm.sendMessage(player, lm.getString(player, "Commands.Regenerate.abort")

LandLord-core/src/main/java/biz/princeps/landlord/multi/MultiUnclaimTask.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
import org.bukkit.entity.Player;
1515
import org.bukkit.scheduler.BukkitRunnable;
1616

17+
import java.util.ArrayList;
1718
import java.util.Collection;
19+
import java.util.List;
1820

1921
public class MultiUnclaimTask extends AMultiTask<IOwnedLand> {
2022

@@ -28,6 +30,7 @@ public class MultiUnclaimTask extends AMultiTask<IOwnedLand> {
2830
private final World world;
2931
private final ManageMode manageMode;
3032
private double totalPayBack;
33+
private final List<IOwnedLand> delayedRegenerations;
3134

3235
public MultiUnclaimTask(ILandLord plugin, Player player, Collection<IOwnedLand> operations, World world, ManageMode manageMode) {
3336
super(plugin, operations);
@@ -42,6 +45,7 @@ public MultiUnclaimTask(ILandLord plugin, Player player, Collection<IOwnedLand>
4245
this.world = world;
4346
this.manageMode = manageMode;
4447
this.totalPayBack = 0;
48+
this.delayedRegenerations = new ArrayList<>();
4549
}
4650

4751
@Override
@@ -68,10 +72,9 @@ public boolean process(IOwnedLand ownedLand) {
6872
totalPayBack += payback;
6973
}
7074

71-
Location location = ownedLand.getALocation();
7275
wgManager.unclaim(ownedLand.getWorld(), ownedLand.getName());
7376
if (plugin.getConfig().getBoolean("CommandSettings.Unclaim.regenerate", false)) {
74-
plugin.getRegenerationManager().regenerateChunk(location);
77+
delayedRegenerations.add(ownedLand);
7578
}
7679

7780
// remove possible homes
@@ -110,6 +113,10 @@ public void complete() {
110113
break;
111114
}
112115

116+
if (!delayedRegenerations.isEmpty()) {
117+
plugin.getRegenerationManager().regenerateChunks(delayedRegenerations);
118+
}
119+
113120
new BukkitRunnable() {
114121
@Override
115122
public void run() {
Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,72 @@
11
package biz.princeps.landlord.regenerators;
22

3+
import biz.princeps.landlord.LandLord;
4+
import biz.princeps.landlord.api.IOwnedLand;
35
import biz.princeps.landlord.api.IRegenerationManager;
46
import com.sk89q.worldedit.EditSession;
57
import com.sk89q.worldedit.WorldEdit;
68
import com.sk89q.worldedit.bukkit.BukkitAdapter;
9+
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
710
import com.sk89q.worldedit.math.BlockVector3;
811
import com.sk89q.worldedit.regions.CuboidRegion;
912
import com.sk89q.worldedit.regions.Region;
13+
import com.sk89q.worldedit.regions.RegionIntersection;
1014
import org.bukkit.World;
1115

16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.concurrent.CompletableFuture;
19+
import java.util.logging.Level;
20+
1221
public class RegenerationManager implements IRegenerationManager {
1322

1423
@Override
1524
public void regenerateChunk(World world, int x, int z) {
1625
com.sk89q.worldedit.world.World weWorld = BukkitAdapter.adapt(world);
17-
Region region = new CuboidRegion(BlockVector3.at(x << 4, weWorld.getMinY(), z << 4),
18-
BlockVector3.at((x << 4) + 15, weWorld.getMaxY(), (z << 4) + 15));
26+
Region region = regionForChunk(x, z, weWorld.getMinY(), weWorld.getMaxY());
1927
WorldEdit worldEdit = WorldEdit.getInstance();
2028
EditSession editSession = worldEdit.getEditSessionFactory().getEditSession(weWorld, -1);
2129
weWorld.regenerate(region, editSession);
2230
editSession.close();
2331
}
32+
33+
@Override
34+
public CompletableFuture<Void> regenerateChunks(Iterable<IOwnedLand> lands) {
35+
List<Region> regions = new ArrayList<>();
36+
World world = null;
37+
for (IOwnedLand land : lands) {
38+
if (world == null) {
39+
world = land.getWorld();
40+
} else if (!world.equals(land.getWorld())) {
41+
return CompletableFuture.failedFuture(new IllegalArgumentException("Lands from different worlds"));
42+
}
43+
regions.add(regionForChunk(land.getChunkX(), land.getChunkZ(), world.getMinHeight(), world.getMaxHeight()));
44+
}
45+
RegionIntersection intersection = new RegionIntersection(regions);
46+
com.sk89q.worldedit.world.World weWorld = BukkitAdapter.adapt(world);
47+
if (isFawe()) {
48+
return CompletableFuture.runAsync(() -> regenerate(weWorld, intersection))
49+
.exceptionally(ex -> {
50+
LandLord.getPlugin(LandLord.class).getLogger().log(Level.SEVERE, "failed to regenerate chunks", ex);
51+
return null;
52+
});
53+
}
54+
regenerate(weWorld, intersection);
55+
return CompletableFuture.completedFuture(null);
56+
}
57+
58+
private static boolean isFawe() {
59+
return WorldEditPlugin.getPlugin(WorldEditPlugin.class).getName().equals("FastAsyncWorldEdit");
60+
}
61+
62+
private static void regenerate(com.sk89q.worldedit.world.World weWorld, RegionIntersection intersection) {
63+
try (EditSession es = WorldEdit.getInstance().newEditSession(weWorld)) {
64+
weWorld.regenerate(intersection, es);
65+
}
66+
}
67+
68+
private static CuboidRegion regionForChunk(int x, int z, int minY, int maxY) {
69+
return new CuboidRegion(BlockVector3.at(x << 4, minY, z << 4),
70+
BlockVector3.at((x << 4) + 15, maxY, (z << 4) + 15));
71+
}
2472
}

build.gradle.kts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ subprojects {
1818

1919
tasks {
2020
register<RunServer>("runLatest") {
21-
minecraftVersion("1.21.1")
21+
minecraftVersion("1.21.4")
2222
pluginJars(*project(":LandLord-latest").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile }
2323
.toTypedArray())
2424
downloadPlugins {
25-
modrinth("worldguard", "7.0.12")
25+
modrinth("worldguard", "f9NoeotB") // 7.0.13
2626
// worldedit supports multiple platforms, we need to use the specific version id
2727
// instead of the actual version
28-
modrinth("worldedit", "ecqqLKUO") // 7.3.8
28+
modrinth("fastasyncworldedit", "cf5QSDJ7") // 2.12.3 Paper
2929
}
3030
runDirectory = file("run/latest")
3131
group = "run paper"

buildSrc/src/main/kotlin/biz.princeps.java-conventions.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repositories {
1010
mavenCentral()
1111
// Spigot & Paper
1212
maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") }
13-
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
13+
maven { url = uri("https://repo.papermc.io/repository/maven-public/") }
1414
// WorldEdit & WorldGuard
1515
maven { url = uri("https://maven.enginehub.org/repo/") }
1616
// Towny

0 commit comments

Comments
 (0)