Deletes chunks manually to solve 1.14 chunk regen removal

This commit is contained in:
tastybento 2019-04-29 19:19:58 -07:00
parent bceb0e1c07
commit 603e525013
3 changed files with 94 additions and 54 deletions

View File

@ -124,17 +124,11 @@ public abstract class GameModeAddon extends Addon {
@NonNull @NonNull
public abstract ChunkGenerator getDefaultWorldGenerator(String worldName, String id); public abstract ChunkGenerator getDefaultWorldGenerator(String worldName, String id);
/** /**
* Tells the Game Mode Addon to save its settings. Used when world settings are changed * Tells the Game Mode Addon to save its settings. Used when world settings are changed
* in-game and need to be saved. * in-game and need to be saved.
* @since 1.4.0 * @since 1.4.0
*/ */
public abstract void saveWorldSettings(); public abstract void saveWorldSettings();
/**
* When called, the game mode must regenerate the chunk to its original state.
* Used when an island is deleted.
* @param chunk - chunk to regenerate
*/
public abstract void regerateChunk(Chunk chunk);
} }

View File

@ -122,6 +122,7 @@ public class AddonsManager {
// Addon successfully loaded // Addon successfully loaded
addon.setState(Addon.State.LOADED); addon.setState(Addon.State.LOADED);
} catch (NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) { } catch (NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
e.printStackTrace();
// Looks like the addon is incompatible, because it tries to refer to missing classes... // Looks like the addon is incompatible, because it tries to refer to missing classes...
handleAddonIncompatibility(addon); handleAddonIncompatibility(addon);
} catch (Exception e) { } catch (Exception e) {
@ -144,6 +145,7 @@ public class AddonsManager {
addon.setState(Addon.State.ENABLED); addon.setState(Addon.State.ENABLED);
plugin.log("Enabling " + addon.getDescription().getName() + "..."); plugin.log("Enabling " + addon.getDescription().getName() + "...");
} catch (NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) { } catch (NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
e.printStackTrace();
// Looks like the addon is incompatible, because it tries to refer to missing classes... // Looks like the addon is incompatible, because it tries to refer to missing classes...
handleAddonIncompatibility(addon); handleAddonIncompatibility(addon);
} catch (Exception e) { } catch (Exception e) {

View File

@ -1,59 +1,103 @@
package world.bentobox.bentobox.util; package world.bentobox.bentobox.util;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
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;
/** /**
* Deletes islands fast using chunk regeneration * Deletes islands chunk by chunk
* *
* @author tastybento * @author tastybento
*/ */
public class DeleteIslandChunks { public class DeleteIslandChunks {
/** /**
* This is how many chunks per world will be done in one tick. * This is how many chunks per world will be done in one tick.
*/ */
private static final int SPEED = 5; private static final int SPEED = 5;
private int x; private int x;
private int z; private int z;
private BukkitTask task; private BukkitTask task;
public DeleteIslandChunks(BentoBox plugin, IslandDeletion di) { public DeleteIslandChunks(BentoBox plugin, IslandDeletion di) {
// Fire event // Fire event
IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETE_CHUNKS).build(); IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETE_CHUNKS).build();
x = di.getMinXChunk(); x = di.getMinXChunk();
z = di.getMinZChunk(); z = di.getMinZChunk();
// Run through all chunks of the islands and regenerate them. // Run through all chunks of the islands and regenerate them.
task = Bukkit.getScheduler().runTaskTimer(plugin, () -> { task = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
for (int i = 0; i < SPEED; i++) { for (int i = 0; i < SPEED; i++) {
plugin.getIWM().getAddon(di.getWorld()).ifPresent(gm -> { plugin.getIWM().getAddon(di.getWorld()).ifPresent(gm -> {
gm.regerateChunk(di.getWorld().getChunkAt(x, z)); regerateChunk(gm, di.getWorld().getChunkAt(x, z));
if (plugin.getIWM().isNetherGenerate(di.getWorld()) && plugin.getIWM().isNetherIslands(di.getWorld())) { if (plugin.getIWM().isNetherGenerate(di.getWorld()) && plugin.getIWM().isNetherIslands(di.getWorld())) {
gm.regerateChunk(gm.getNetherWorld().getChunkAt(x, z)); regerateChunk(gm, plugin.getIWM().getNetherWorld(di.getWorld()).getChunkAt(x, z));
} }
if (plugin.getIWM().isEndGenerate(di.getWorld()) && plugin.getIWM().isEndIslands(di.getWorld())) { if (plugin.getIWM().isEndGenerate(di.getWorld()) && plugin.getIWM().isEndIslands(di.getWorld())) {
gm.regerateChunk(gm.getEndWorld().getChunkAt(x, z)); regerateChunk(gm, plugin.getIWM().getEndWorld(di.getWorld()).getChunkAt(x, z));
} }
z++; z++;
if (z > di.getMaxZChunk()) { if (z > di.getMaxZChunk()) {
z = di.getMinZChunk(); z = di.getMinZChunk();
x++; x++;
if (x > di.getMaxXChunk()) { if (x > di.getMaxXChunk()) {
// We're done // We're done
task.cancel(); task.cancel();
// Fire event // Fire event
IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETED).build(); IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETED).build();
} }
} }
}); });
} }
}, 0L, 1L); }, 0L, 1L);
} }
private void regerateChunk(GameModeAddon gm, Chunk chunk) {
// Clear all inventories
Arrays.stream(chunk.getTileEntities()).filter(te -> (te instanceof InventoryHolder)).forEach(te -> ((InventoryHolder)te).getInventory().clear());
// Reset blocks
MyBiomeGrid grid = new MyBiomeGrid();
ChunkData cd = gm.getDefaultWorldGenerator(chunk.getWorld().getName(), "").generateChunkData(chunk.getWorld(), new Random(), chunk.getX(), chunk.getZ(), grid);
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
chunk.getBlock(x, 0, z).setBiome(grid.getBiome(x, z));
for (int y = 0; y < chunk.getWorld().getMaxHeight(); y++) {
chunk.getBlock(x, y, z).setBlockData(cd.getBlockData(x, y, z));
}
}
}
// 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)).forEach(Entity::remove);
}
class MyBiomeGrid implements BiomeGrid {
Map<Vector, Biome> map = new HashMap<>();
@Override
public Biome getBiome(int x, int z) {
return map.getOrDefault(new Vector(x,0,z), Biome.PLAINS);
}
@Override
public void setBiome(int x, int z, Biome bio) {
map.put(new Vector(x,0,z), bio);
}
}
} }