mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-11-27 13:15:28 +01:00
More abstract on World Regenerator (#1969)
* more abstract on delete chunks * update NMS to 1.18.2 * at most abstract, requires only the island and the world * it's weird that we can't use whenComplete * rename to WorldRegenerator
This commit is contained in:
parent
d07c1b5a8c
commit
6fba4bfbea
2
pom.xml
2
pom.xml
@ -68,7 +68,7 @@
|
|||||||
<powermock.version>2.0.9</powermock.version>
|
<powermock.version>2.0.9</powermock.version>
|
||||||
<mongodb.version>3.12.8</mongodb.version>
|
<mongodb.version>3.12.8</mongodb.version>
|
||||||
<!-- More visible way to change dependency versions -->
|
<!-- More visible way to change dependency versions -->
|
||||||
<spigot.version>1.18-R0.1-SNAPSHOT</spigot.version>
|
<spigot.version>1.18.2-R0.1-SNAPSHOT</spigot.version>
|
||||||
<!-- Might differ from the last Spigot release for short periods
|
<!-- Might differ from the last Spigot release for short periods
|
||||||
of time -->
|
of time -->
|
||||||
<paper.version>1.16.5-R0.1-SNAPSHOT</paper.version>
|
<paper.version>1.16.5-R0.1-SNAPSHOT</paper.version>
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
package world.bentobox.bentobox.nms;
|
|
||||||
|
|
||||||
import org.bukkit.Chunk;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
|
||||||
import org.bukkit.util.BoundingBox;
|
|
||||||
|
|
||||||
public interface NMSAbstraction {
|
|
||||||
/**
|
|
||||||
* Copy the chunk data and biome grid to the given chunk.
|
|
||||||
* @param chunk - chunk to copy to
|
|
||||||
* @param chunkData - chunk data to copy
|
|
||||||
* @param biomeGrid - biome grid to copy to
|
|
||||||
* @param limitBox - bounding box to limit the copying
|
|
||||||
*/
|
|
||||||
default void copyChunkDataToChunk(Chunk chunk, ChunkGenerator.ChunkData chunkData, ChunkGenerator.BiomeGrid biomeGrid, BoundingBox limitBox) {
|
|
||||||
double baseX = chunk.getX() << 4;
|
|
||||||
double baseZ = chunk.getZ() << 4;
|
|
||||||
int minHeight = chunk.getWorld().getMinHeight();
|
|
||||||
int maxHeight = chunk.getWorld().getMaxHeight();
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
if (!limitBox.contains(baseX + x, 0, baseZ + z)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int y = minHeight; y < maxHeight; y++) {
|
|
||||||
setBlockInNativeChunk(chunk, x, y, z, chunkData.getBlockData(x, y, z), false);
|
|
||||||
// 3D biomes, 4 blocks separated
|
|
||||||
if (x % 4 == 0 && y % 4 == 0 && z % 4 == 0) {
|
|
||||||
chunk.getBlock(x, y, z).setBiome(biomeGrid.getBiome(x, y, z));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the low-level chunk information for the given block to the new block ID and data. This
|
|
||||||
* change will not be propagated to clients until the chunk is refreshed to them.
|
|
||||||
* @param chunk - chunk to be changed
|
|
||||||
* @param x - x coordinate within chunk 0 - 15
|
|
||||||
* @param y - y coordinate within chunk 0 - world height, e.g. 255
|
|
||||||
* @param z - z coordinate within chunk 0 - 15
|
|
||||||
* @param blockData - block data to set the block
|
|
||||||
* @param applyPhysics - apply physics or not
|
|
||||||
*/
|
|
||||||
void setBlockInNativeChunk(Chunk chunk, int x, int y, int z, BlockData blockData, boolean applyPhysics);
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,137 @@
|
|||||||
|
package world.bentobox.bentobox.nms;
|
||||||
|
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||||
|
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
||||||
|
import world.bentobox.bentobox.util.MyBiomeGrid;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public abstract class SimpleWorldRegenerator implements WorldRegenerator {
|
||||||
|
private final BentoBox plugin;
|
||||||
|
|
||||||
|
protected SimpleWorldRegenerator() {
|
||||||
|
this.plugin = BentoBox.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the low-level chunk information for the given block to the new block ID and data. This
|
||||||
|
* change will not be propagated to clients until the chunk is refreshed to them.
|
||||||
|
*
|
||||||
|
* @param chunk - chunk to be changed
|
||||||
|
* @param x - x coordinate within chunk 0 - 15
|
||||||
|
* @param y - y coordinate within chunk 0 - world height, e.g. 255
|
||||||
|
* @param z - z coordinate within chunk 0 - 15
|
||||||
|
* @param blockData - block data to set the block
|
||||||
|
* @param applyPhysics - apply physics or not
|
||||||
|
*/
|
||||||
|
protected abstract void setBlockInNativeChunk(Chunk chunk, int x, int y, int z, BlockData blockData, boolean applyPhysics);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> regenerate(GameModeAddon gm, IslandDeletion di, World world) {
|
||||||
|
CompletableFuture<Void> bigFuture = new CompletableFuture<>();
|
||||||
|
new BukkitRunnable() {
|
||||||
|
private int chunkX = di.getMinXChunk();
|
||||||
|
private int chunkZ = di.getMinZChunk();
|
||||||
|
CompletableFuture<Void> currentTask = CompletableFuture.completedFuture(null);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!currentTask.isDone()) return;
|
||||||
|
if (isEnded(chunkX)) {
|
||||||
|
cancel();
|
||||||
|
bigFuture.complete(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<CompletableFuture<Void>> newTasks = new ArrayList<>();
|
||||||
|
for (int i = 0; i < plugin.getSettings().getDeleteSpeed(); i++) {
|
||||||
|
if (isEnded(chunkX)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final int x = chunkX;
|
||||||
|
final int z = chunkZ;
|
||||||
|
newTasks.add(regenerateChunk(gm, di, world, x, z));
|
||||||
|
chunkZ++;
|
||||||
|
if (chunkZ > di.getMaxZChunk()) {
|
||||||
|
chunkZ = di.getMinZChunk();
|
||||||
|
chunkX++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentTask = CompletableFuture.allOf(newTasks.toArray(new CompletableFuture[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEnded(int chunkX) {
|
||||||
|
return chunkX > di.getMaxXChunk();
|
||||||
|
}
|
||||||
|
}.runTaskTimer(plugin, 0L, 20L);
|
||||||
|
return bigFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private CompletableFuture<Void> regenerateChunk(GameModeAddon gm, IslandDeletion di, World world, int chunkX, int chunkZ) {
|
||||||
|
CompletableFuture<Chunk> chunkFuture = PaperLib.getChunkAtAsync(world, chunkX, chunkZ);
|
||||||
|
CompletableFuture<Void> invFuture = chunkFuture.thenAccept(chunk ->
|
||||||
|
Arrays.stream(chunk.getTileEntities()).filter(InventoryHolder.class::isInstance)
|
||||||
|
.filter(te -> di.inBounds(te.getLocation().getBlockX(), te.getLocation().getBlockZ()))
|
||||||
|
.forEach(te -> ((InventoryHolder) te).getInventory().clear())
|
||||||
|
);
|
||||||
|
CompletableFuture<Void> entitiesFuture = chunkFuture.thenAccept(chunk -> {
|
||||||
|
for (Entity e : chunk.getEntities()) {
|
||||||
|
if (!(e instanceof Player)) {
|
||||||
|
e.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
CompletableFuture<Chunk> copyFuture = chunkFuture.thenApply(chunk -> {
|
||||||
|
// Reset blocks
|
||||||
|
MyBiomeGrid grid = new MyBiomeGrid(chunk.getWorld().getEnvironment());
|
||||||
|
ChunkGenerator cg = gm.getDefaultWorldGenerator(chunk.getWorld().getName(), "delete");
|
||||||
|
// Will be null if use-own-generator is set to true
|
||||||
|
if (cg != null) {
|
||||||
|
ChunkGenerator.ChunkData cd = cg.generateChunkData(chunk.getWorld(), new Random(), chunk.getX(), chunk.getZ(), grid);
|
||||||
|
copyChunkDataToChunk(chunk, cd, grid, di.getBox());
|
||||||
|
}
|
||||||
|
return chunk;
|
||||||
|
});
|
||||||
|
CompletableFuture<Void> postCopyFuture = copyFuture.thenAccept(chunk -> {
|
||||||
|
// Remove all entities in chunk, including any dropped items as a result of clearing the blocks above
|
||||||
|
Arrays.stream(chunk.getEntities()).filter(e -> !(e instanceof Player) && di.inBounds(e.getLocation().getBlockX(), e.getLocation().getBlockZ())).forEach(Entity::remove);
|
||||||
|
});
|
||||||
|
return CompletableFuture.allOf(invFuture, entitiesFuture, postCopyFuture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyChunkDataToChunk(Chunk chunk, ChunkGenerator.ChunkData chunkData, ChunkGenerator.BiomeGrid biomeGrid, BoundingBox limitBox) {
|
||||||
|
double baseX = chunk.getX() << 4;
|
||||||
|
double baseZ = chunk.getZ() << 4;
|
||||||
|
int minHeight = chunk.getWorld().getMinHeight();
|
||||||
|
int maxHeight = chunk.getWorld().getMaxHeight();
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
if (!limitBox.contains(baseX + x, 0, baseZ + z)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int y = minHeight; y < maxHeight; y++) {
|
||||||
|
setBlockInNativeChunk(chunk, x, y, z, chunkData.getBlockData(x, y, z), false);
|
||||||
|
// 3D biomes, 4 blocks separated
|
||||||
|
if (x % 4 == 0 && y % 4 == 0 && z % 4 == 0) {
|
||||||
|
chunk.getBlock(x, y, z).setBiome(biomeGrid.getBiome(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package world.bentobox.bentobox.nms;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||||
|
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A world generator used by {@link world.bentobox.bentobox.util.DeleteIslandChunks}
|
||||||
|
*/
|
||||||
|
public interface WorldRegenerator {
|
||||||
|
/**
|
||||||
|
* Create a future to regenerate the regions of the island.
|
||||||
|
*
|
||||||
|
* @param gm the game mode
|
||||||
|
* @param di the island deletion
|
||||||
|
* @param world the world
|
||||||
|
* @return the completable future
|
||||||
|
*/
|
||||||
|
CompletableFuture<Void> regenerate(GameModeAddon gm, IslandDeletion di, World world);
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
package world.bentobox.bentobox.nms.fallback;
|
|
||||||
|
|
||||||
import org.bukkit.Chunk;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
|
|
||||||
import world.bentobox.bentobox.nms.NMSAbstraction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author tastybento
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class NMSHandler implements NMSAbstraction {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlockInNativeChunk(Chunk chunk, int x, int y, int z, BlockData blockData, boolean applyPhysics) {
|
|
||||||
chunk.getBlock(x, y, z).setBlockData(blockData, applyPhysics);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,20 @@
|
|||||||
|
package world.bentobox.bentobox.nms.fallback;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.nms.SimpleWorldRegenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tastybento
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WorldRegeneratorImpl extends SimpleWorldRegenerator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setBlockInNativeChunk(Chunk chunk, int x, int y, int z, BlockData blockData, boolean applyPhysics) {
|
||||||
|
chunk.getBlock(x, y, z).setBlockData(blockData, applyPhysics);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,19 +1,19 @@
|
|||||||
package world.bentobox.bentobox.nms.v1_18_R1;
|
package world.bentobox.bentobox.nms.v1_18_R2;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
|
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_18_R1.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPosition;
|
import net.minecraft.core.BlockPosition;
|
||||||
import net.minecraft.world.level.World;
|
import net.minecraft.world.level.World;
|
||||||
import net.minecraft.world.level.block.state.IBlockData;
|
import net.minecraft.world.level.block.state.IBlockData;
|
||||||
import net.minecraft.world.level.chunk.Chunk;
|
import net.minecraft.world.level.chunk.Chunk;
|
||||||
import world.bentobox.bentobox.nms.NMSAbstraction;
|
import world.bentobox.bentobox.nms.SimpleWorldRegenerator;
|
||||||
|
|
||||||
|
|
||||||
public class NMSHandler implements NMSAbstraction {
|
public class WorldRegeneratorImpl extends SimpleWorldRegenerator {
|
||||||
|
|
||||||
private static final IBlockData AIR = ((CraftBlockData) Bukkit.createBlockData(Material.AIR)).getState();
|
private static final IBlockData AIR = ((CraftBlockData) Bukkit.createBlockData(Material.AIR)).getState();
|
||||||
|
|
@ -1,29 +1,16 @@
|
|||||||
package world.bentobox.bentobox.util;
|
package world.bentobox.bentobox.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Chunk;
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
|
||||||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
import io.papermc.lib.PaperLib;
|
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||||
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
|
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
|
||||||
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
||||||
import world.bentobox.bentobox.nms.NMSAbstraction;
|
import world.bentobox.bentobox.nms.WorldRegenerator;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes islands chunk by chunk
|
* Deletes islands chunk by chunk
|
||||||
@ -37,16 +24,10 @@ public class DeleteIslandChunks {
|
|||||||
private final World netherWorld;
|
private final World netherWorld;
|
||||||
private final World endWorld;
|
private final World endWorld;
|
||||||
private final AtomicBoolean completed;
|
private final AtomicBoolean completed;
|
||||||
private final NMSAbstraction nms;
|
private final WorldRegenerator regenerator;
|
||||||
private int chunkX;
|
|
||||||
private int chunkZ;
|
|
||||||
private BukkitTask task;
|
|
||||||
private CompletableFuture<Void> currentTask = CompletableFuture.completedFuture(null);
|
|
||||||
|
|
||||||
public DeleteIslandChunks(BentoBox plugin, IslandDeletion di) {
|
public DeleteIslandChunks(BentoBox plugin, IslandDeletion di) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.chunkX = di.getMinXChunk();
|
|
||||||
this.chunkZ = di.getMinZChunk();
|
|
||||||
this.di = di;
|
this.di = di;
|
||||||
completed = new AtomicBoolean(false);
|
completed = new AtomicBoolean(false);
|
||||||
// Nether
|
// Nether
|
||||||
@ -61,9 +42,9 @@ public class DeleteIslandChunks {
|
|||||||
} else {
|
} else {
|
||||||
endWorld = null;
|
endWorld = null;
|
||||||
}
|
}
|
||||||
// NMS
|
// Regenerator
|
||||||
this.nms = Util.getNMS();
|
this.regenerator = Util.getRegenerator();
|
||||||
if (nms == null) {
|
if (regenerator == null) {
|
||||||
plugin.logError("Could not delete chunks because of NMS error");
|
plugin.logError("Could not delete chunks because of NMS error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -75,37 +56,23 @@ public class DeleteIslandChunks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void regenerateChunks() {
|
private void regenerateChunks() {
|
||||||
// Run through all chunks of the islands and regenerate them.
|
CompletableFuture<Void> all = plugin.getIWM().getAddon(di.getWorld())
|
||||||
task = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
.map(gm -> new CompletableFuture[]{
|
||||||
if (!currentTask.isDone()) return;
|
processWorld(gm, di.getWorld()), // Overworld
|
||||||
if (isEnded(chunkX)) {
|
processWorld(gm, netherWorld), // Nether
|
||||||
finish();
|
processWorld(gm, endWorld) // End
|
||||||
return;
|
})
|
||||||
}
|
.map(CompletableFuture::allOf)
|
||||||
List<CompletableFuture<Void>> newTasks = new ArrayList<>();
|
.orElseGet(() -> CompletableFuture.completedFuture(null));
|
||||||
for (int i = 0; i < plugin.getSettings().getDeleteSpeed(); i++) {
|
new BukkitRunnable() {
|
||||||
if (isEnded(chunkX)) {
|
@Override
|
||||||
break;
|
public void run() {
|
||||||
}
|
if (all.isDone()) {
|
||||||
final int x = chunkX;
|
finish();
|
||||||
final int z = chunkZ;
|
cancel();
|
||||||
plugin.getIWM().getAddon(di.getWorld()).ifPresent(gm -> {
|
|
||||||
newTasks.add(processChunk(gm, di.getWorld(), x, z)); // Overworld
|
|
||||||
newTasks.add(processChunk(gm, netherWorld, x, z)); // Nether
|
|
||||||
newTasks.add(processChunk(gm, endWorld, x, z)); // End
|
|
||||||
});
|
|
||||||
chunkZ++;
|
|
||||||
if (chunkZ > di.getMaxZChunk()) {
|
|
||||||
chunkZ = di.getMinZChunk();
|
|
||||||
chunkX++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentTask = CompletableFuture.allOf(newTasks.toArray(new CompletableFuture[0]));
|
}.runTaskTimer(plugin, 0, 20);
|
||||||
}, 0L, 20L);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isEnded(int chunkX) {
|
|
||||||
return chunkX > di.getMaxXChunk();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finish() {
|
private void finish() {
|
||||||
@ -113,44 +80,16 @@ public class DeleteIslandChunks {
|
|||||||
IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETED).build();
|
IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETED).build();
|
||||||
// We're done
|
// We're done
|
||||||
completed.set(true);
|
completed.set(true);
|
||||||
task.cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> processChunk(GameModeAddon gm, World world, int x, int z) {
|
private CompletableFuture<Void> processWorld(GameModeAddon gm, World world) {
|
||||||
if (world != null) {
|
if (world != null) {
|
||||||
return PaperLib.getChunkAtAsync(world, x, z).thenAccept(chunk -> regenerateChunk(gm, chunk, x, z));
|
return regenerator.regenerate(gm, di, world);
|
||||||
} else {
|
} else {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void regenerateChunk(GameModeAddon gm, Chunk chunk, int x, int z) {
|
|
||||||
// Clear all inventories
|
|
||||||
Arrays.stream(chunk.getTileEntities()).filter(InventoryHolder.class::isInstance)
|
|
||||||
.filter(te -> di.inBounds(te.getLocation().getBlockX(), te.getLocation().getBlockZ()))
|
|
||||||
.forEach(te -> ((InventoryHolder) te).getInventory().clear());
|
|
||||||
// Remove all entities
|
|
||||||
for (Entity e : chunk.getEntities()) {
|
|
||||||
if (!(e instanceof Player)) {
|
|
||||||
e.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Reset blocks
|
|
||||||
MyBiomeGrid grid = new MyBiomeGrid(chunk.getWorld().getEnvironment());
|
|
||||||
ChunkGenerator cg = gm.getDefaultWorldGenerator(chunk.getWorld().getName(), "delete");
|
|
||||||
// Will be null if use-own-generator is set to true
|
|
||||||
if (cg != null) {
|
|
||||||
ChunkData cd = cg.generateChunkData(chunk.getWorld(), new Random(), chunk.getX(), chunk.getZ(), grid);
|
|
||||||
createChunk(cd, chunk, grid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createChunk(ChunkData cd, Chunk chunk, MyBiomeGrid grid) {
|
|
||||||
nms.copyChunkDataToChunk(chunk, cd, grid, di.getBox());
|
|
||||||
// Remove all entities in chunk, including any dropped items as a result of clearing the blocks above
|
|
||||||
Arrays.stream(chunk.getEntities()).filter(e -> !(e instanceof Player) && di.inBounds(e.getLocation().getBlockX(), e.getLocation().getBlockZ())).forEach(Entity::remove);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCompleted() {
|
public boolean isCompleted() {
|
||||||
return completed.get();
|
return completed.get();
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ import io.papermc.lib.PaperLib;
|
|||||||
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
|
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.nms.NMSAbstraction;
|
import world.bentobox.bentobox.nms.WorldRegenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of utility methods
|
* A set of utility methods
|
||||||
@ -64,7 +64,7 @@ public class Util {
|
|||||||
private static final String THE_END = "_the_end";
|
private static final String THE_END = "_the_end";
|
||||||
private static String serverVersion = null;
|
private static String serverVersion = null;
|
||||||
private static BentoBox plugin = BentoBox.getInstance();
|
private static BentoBox plugin = BentoBox.getInstance();
|
||||||
private static NMSAbstraction nms = null;
|
private static WorldRegenerator regenerator = null;
|
||||||
|
|
||||||
private Util() {}
|
private Util() {}
|
||||||
|
|
||||||
@ -689,23 +689,37 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the NMS handler the plugin will use
|
* Set the regenerator the plugin will use
|
||||||
* @param nms the NMS handler
|
* @param regenerator the regenerator
|
||||||
*/
|
*/
|
||||||
public static void setNms(NMSAbstraction nms) {
|
public static void setRegenerator(WorldRegenerator regenerator) {
|
||||||
Util.nms = nms;
|
Util.regenerator = regenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the NMS handler the plugin will use
|
* Get the regenerator the plugin will use
|
||||||
* @return an NMS accelerated class for this server
|
* @return an accelerated regenerator class for this server
|
||||||
*/
|
*/
|
||||||
public static NMSAbstraction getNMS() {
|
public static WorldRegenerator getRegenerator() {
|
||||||
if (nms == null) {
|
if (regenerator == null) {
|
||||||
plugin.log("No NMS Handler was set, falling back to Bukkit API.");
|
String serverPackageName = Bukkit.getServer().getClass().getPackage().getName();
|
||||||
setNms(new world.bentobox.bentobox.nms.fallback.NMSHandler());
|
String pluginPackageName = plugin.getClass().getPackage().getName();
|
||||||
|
String version = serverPackageName.substring(serverPackageName.lastIndexOf('.') + 1);
|
||||||
|
WorldRegenerator handler;
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName(pluginPackageName + ".nms." + version + ".WorldRegeneratorImpl");
|
||||||
|
if (WorldRegenerator.class.isAssignableFrom(clazz)) {
|
||||||
|
handler = (WorldRegenerator) clazz.getConstructor().newInstance();
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Class " + clazz.getName() + " does not implement WorldRegenerator");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logWarning("No Regenerator found for " + version + ", falling back to Bukkit API.");
|
||||||
|
handler = new world.bentobox.bentobox.nms.fallback.WorldRegeneratorImpl();
|
||||||
|
}
|
||||||
|
setRegenerator(handler);
|
||||||
}
|
}
|
||||||
return nms;
|
return regenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user