From 7db9c0b9a2c836ba389ce480fa6d7fb9eee35b6d Mon Sep 17 00:00:00 2001 From: boy0001 Date: Sun, 26 Jul 2015 00:43:19 +1000 Subject: [PATCH] Fixed a couple issues related to world generation / clearing - Fixed competition of multiple augmented populators if there are several augmented plot clusters of specific terrain type - Fixed fastmode clearing sometimes doing strange things if chunks connected to the road have not previously been generated - Fixed fastmode clearing not setting block data correctly on unloaded chunks under specific conditions. --- .../plot/generator/AugmentedPopulator.java | 40 +-- .../plot/util/ChunkManager.java | 9 + .../plot/util/bukkit/BukkitChunkManager.java | 260 ++++++++++++------ 3 files changed, 203 insertions(+), 106 deletions(-) diff --git a/src/main/java/com/intellectualcrafters/plot/generator/AugmentedPopulator.java b/src/main/java/com/intellectualcrafters/plot/generator/AugmentedPopulator.java index 67a29bdcf..d0f737648 100644 --- a/src/main/java/com/intellectualcrafters/plot/generator/AugmentedPopulator.java +++ b/src/main/java/com/intellectualcrafters/plot/generator/AugmentedPopulator.java @@ -120,6 +120,21 @@ public class AugmentedPopulator extends BlockPopulator { @Override public void populate(final World world, final Random rand, final Chunk chunk) { + final int cx = chunk.getX(); + final int cz = chunk.getZ(); + final int bx = cx << 4; + final int bz = cz << 4; + final int tx = bx + 15; + final int tz = bz + 15; + final boolean inX1 = ((bx >= this.bx) && (bx <= this.tx)); + final boolean inX2 = ((tx >= this.bx) && (tx <= this.tx)); + final boolean inZ1 = ((bz >= this.bz) && (bz <= this.tz)); + final boolean inZ2 = ((tz >= this.bz) && (tz <= this.tz)); + final boolean inX = inX1 || inX2; + final boolean inZ = inZ1 || inZ2; + if (!inX || !inZ) { + return; + } if (this.plotworld.TERRAIN == 3) { int X = chunk.getX() << 4; int Z = chunk.getZ() << 4; @@ -170,44 +185,29 @@ public class AugmentedPopulator extends BlockPopulator { } return; } - final int X = chunk.getX(); - final int Z = chunk.getZ(); - final int x = X << 4; - final int z = Z << 4; - final int x2 = x + 15; - final int z2 = z + 15; - final boolean inX1 = ((x >= this.bx) && (x <= this.tx)); - final boolean inX2 = ((x2 >= this.bx) && (x2 <= this.tx)); - final boolean inZ1 = ((z >= this.bz) && (z <= this.tz)); - final boolean inZ2 = ((z2 >= this.bz) && (z2 <= this.tz)); - final boolean inX = inX1 || inX2; - final boolean inZ = inZ1 || inZ2; - if (!inX || !inZ) { - return; - } final boolean check; check = !inX1 || !inX2 || !inZ1 || !inZ2; if (this.plotworld.TERRAIN > 1) { - final PlotId plot1 = this.manager.getPlotIdAbs(this.plotworld, x, 0, z); - final PlotId plot2 = this.manager.getPlotIdAbs(this.plotworld, x2, 0, z2); + final PlotId plot1 = this.manager.getPlotIdAbs(this.plotworld, bx, 0, bz); + final PlotId plot2 = this.manager.getPlotIdAbs(this.plotworld, tx, 0, tz); if ((plot1 != null) && (plot2 != null) && plot1.equals(plot2)) { return; } } if (this.o) { - populateBlocks(world, rand, X, Z, x, z, check); + populateBlocks(world, rand, cx, cz, bx, bz, check); } else { TaskManager.runTaskLater(new Runnable() { @Override public void run() { - populateBiome(world, x, z); + populateBiome(world, bx, bz); } }, 20 + rand.nextInt(10)); TaskManager.runTaskLater(new Runnable() { @Override public void run() { chunk.load(true); - populateBlocks(world, rand, X, Z, x, z, check); + populateBlocks(world, rand, cx, cz, bx, bz, check); } }, 40 + rand.nextInt(40)); } diff --git a/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java b/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java index 1e0ec2ce1..1cf3585cb 100644 --- a/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java +++ b/src/main/java/com/intellectualcrafters/plot/util/ChunkManager.java @@ -47,6 +47,15 @@ public abstract class ChunkManager { public abstract boolean copyRegion(final Location pos1, final Location pos2, final Location newPos, final Runnable whenDone); + /** + * Assumptions:
+ * - pos1 and pos2 are in the same plot
+ * It can be harmful to the world if parameters outside this scope are provided + * @param pos1 + * @param pos2 + * @param whenDone + * @return + */ public abstract boolean regenerateRegion(final Location pos1, final Location pos2, final Runnable whenDone); public abstract void clearAllEntities(final Plot plot); diff --git a/src/main/java/com/intellectualcrafters/plot/util/bukkit/BukkitChunkManager.java b/src/main/java/com/intellectualcrafters/plot/util/bukkit/BukkitChunkManager.java index f3c2d5d62..fc9681002 100644 --- a/src/main/java/com/intellectualcrafters/plot/util/bukkit/BukkitChunkManager.java +++ b/src/main/java/com/intellectualcrafters/plot/util/bukkit/BukkitChunkManager.java @@ -2,6 +2,8 @@ package com.intellectualcrafters.plot.util.bukkit; import com.intellectualcrafters.plot.BukkitMain; import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.generator.AugmentedPopulator; +import com.intellectualcrafters.plot.generator.HybridPlotWorld; import com.intellectualcrafters.plot.object.BlockLoc; import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.Location; @@ -10,12 +12,16 @@ import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotLoc; import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.object.PlotWorld; import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.entity.EntityWrapper; import com.intellectualcrafters.plot.util.ChunkManager; +import com.intellectualcrafters.plot.util.ClusterManager; import com.intellectualcrafters.plot.util.MainUtil; +import com.intellectualcrafters.plot.util.SetBlockQueue; import com.intellectualcrafters.plot.util.SetBlockQueue.ChunkWrapper; import com.intellectualcrafters.plot.util.TaskManager; + import org.apache.commons.lang.mutable.MutableInt; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -49,6 +55,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.entity.Vehicle; +import org.bukkit.generator.BlockPopulator; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; @@ -59,6 +66,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Random; public class BukkitChunkManager extends ChunkManager { @Override @@ -296,99 +304,179 @@ public class BukkitChunkManager extends ChunkManager { TaskManager.tasks.put(currentIndex, loadTask); return true; } + + public void saveRegion(World world, int x1, int x2, int z1, int z2) { + if (z1 > z2) { + int tmp = z1; + z1 = z2; + z2 = tmp; + } + if (x1 > x2) { + int tmp = x1; + x1 = x2; + x2 = tmp; + } + for (int x = x1; x <= x2; x++) { + for (int z = z1; z <= z2; z++) { + saveBlocks(world, 255, x, z); + } + } + } @Override public boolean regenerateRegion(final Location pos1, final Location pos2, final Runnable whenDone) { - TaskManager.index.increment(); - final Plugin plugin = BukkitMain.THIS; - final World world = Bukkit.getWorld(pos1.getWorld()); - final Chunk c1 = world.getChunkAt(pos1.getX() >> 4, pos1.getZ() >> 4); - final Chunk c2 = world.getChunkAt(pos2.getX() >> 4, pos2.getZ() >> 4); - final int sx = pos1.getX(); - final int sz = pos1.getZ(); - final int ex = pos2.getX(); - final int ez = pos2.getZ(); - final int c1x = c1.getX(); - final int c1z = c1.getZ(); - final int c2x = c2.getX(); - final int c2z = c2.getZ(); - final ArrayList chunks = new ArrayList(); - for (int x = c1x; x <= c2x; x++) { - for (int z = c1z; z <= c2z; z++) { - final Chunk chunk = world.getChunkAt(x, z); - chunk.load(false); - chunks.add(chunk); + final String world = pos1.getWorld(); + PlotWorld plotworld = PS.get().getPlotWorld(world); + final int p1x = pos1.getX(); + final int p1z = pos1.getZ(); + final int p2x = pos2.getX(); + final int p2z = pos2.getZ(); + final int bcx = p1x >> 4; + final int bcz = p1z >> 4; + final int tcx = p2x >> 4; + final int tcz = p2z >> 4; + + final boolean canRegen = (plotworld.TYPE != 0 && plotworld.TERRAIN == 0); + + final ArrayList chunks = new ArrayList(); + + for (int x = bcx; x <= tcx; x++) { + for (int z = bcz; z <= tcz; z++) { + chunks.add(new ChunkLoc(x, z)); } } - final int maxY = world.getMaxHeight(); - final Integer currentIndex = TaskManager.index.toInteger(); - final Integer task = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() { - @Override - public void run() { - final long start = System.currentTimeMillis(); - while ((System.currentTimeMillis() - start) < 20) { - if (chunks.size() == 0) { - TaskManager.runTaskLater(whenDone, 1); - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); - TaskManager.tasks.remove(currentIndex); - return; - } - CURRENT_PLOT_CLEAR = new RegionWrapper(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); - final Chunk chunk = chunks.get(0); - chunks.remove(0); - final int x = chunk.getX(); - final int z = chunk.getZ(); - boolean loaded = true; - if (!chunk.isLoaded()) { - final boolean result = chunk.load(false); - if (!result) { - loaded = false; - } - if (!chunk.isLoaded()) { - loaded = false; - } - } - if (loaded) { - initMaps(); - final int absX = x << 4; - final int absZ = z << 4; - boolean save = false; - if ((x == c1x) || (z == c1z)) { - save = true; - for (int X = 0; X < 16; X++) { - for (int Z = 0; Z < 16; Z++) { - if ((((X + absX) < sx) || ((Z + absZ) < sz)) || (((X + absX) > ex) || ((Z + absZ) > ez))) { - saveBlocks(world, maxY, X + absX, Z + absZ); - } - } - } - } else if ((x == c2x) || (z == c2z)) { - for (int X = 0; X < 16; X++) { - save = true; - for (int Z = 0; Z < 16; Z++) { - if ((((X + absX) > ex) || ((Z + absZ) > ez)) || (((X + absX) < sx) || ((Z + absZ) < sz))) { - saveBlocks(world, maxY, X + absX, Z + absZ); - } - } - } - } - if (save) { - saveEntitiesOut(chunk, CURRENT_PLOT_CLEAR); - } - ChunkLoc loc = new ChunkLoc(chunk.getX(), chunk.getZ()); - regenerateChunk(world.getName(), loc); - if (save) { - restoreBlocks(world, 0, 0); - restoreEntities(world, 0, 0); - } - MainUtil.update(world.getName(), loc); - BukkitSetBlockManager.setBlockManager.update(Arrays.asList(new Chunk[] { chunk })); - } - CURRENT_PLOT_CLEAR = null; + + AugmentedPopulator augpop = null; + final World worldObj = Bukkit.getWorld(world); + List populators = worldObj.getPopulators(); + for (BlockPopulator populator : populators) { + if (populator instanceof AugmentedPopulator) { + AugmentedPopulator current = ((AugmentedPopulator) populator); + if (current.cluster == null) { + augpop = current; + break; + } + else if (ClusterManager.contains(current.cluster, pos1)) { + augpop = current; + break; } } - }, 1, 1); - TaskManager.tasks.put(currentIndex, task); + } + final AugmentedPopulator ap = augpop; + TaskManager.runTask(new Runnable() { + @Override + public void run() { + long start = System.currentTimeMillis(); + while (chunks.size() > 0 && System.currentTimeMillis() - start < 50) { + ChunkLoc chunk = chunks.remove(0); + int x = chunk.x; + int z = chunk.z; + int xxb = x << 4; + int zzb = z << 4; + int xxt = xxb + 15; + int zzt = zzb + 15; + CURRENT_PLOT_CLEAR = null; + Chunk chunkObj = worldObj.getChunkAt(x, z); + if (!chunkObj.load(false)) { + System.out.print("FAILED TO LOAD CHUNK!!!: " + x + "," + z); + continue; + } + CURRENT_PLOT_CLEAR = new RegionWrapper(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); + if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { + if (canRegen && ap != null) { + ap.populate(worldObj, null, chunkObj); + } + else { + regenerateChunk(world, chunk); + } + continue; + } + boolean checkX1 = false; + boolean checkX2 = false; + boolean checkZ1 = false; + boolean checkZ2 = false; + + int xxb2; + int zzb2; + int xxt2; + int zzt2; + + if (x == bcx) { + xxb2 = p1x - 1; + checkX1 = true; + } + else { + xxb2 = xxb; + } + if (x == tcx) { + xxt2 = p2x + 1; + checkX2 = true; + } + else { + xxt2 = xxt; + } + if (z == bcz) { + zzb2 = p1z - 1; + checkZ1 = true; + } + else { + zzb2 = zzb; + } + if (z == tcz) { + zzt2 = p2z + 1; + checkZ2 = true; + } + else { + zzt2 = zzt; + } + initMaps(); + if (checkX1) { + saveRegion(worldObj, xxb , xxb2, zzb2, zzt2); // + } + if (checkX2) { + saveRegion(worldObj, xxt2 , xxt, zzb2, zzt2); // + } + if (checkZ1) { + saveRegion(worldObj, xxb2 , xxt2, zzb, zzb2); // + } + if (checkZ2) { + saveRegion(worldObj, xxb2 , xxt2, zzt2, zzt); // + } + if (checkX1 && checkZ1) { + saveRegion(worldObj, xxb , xxb2, zzb, zzb2); // + } + if (checkX2 && checkZ1) { + System.out.print("CX2 && CZ1"); + System.out.print(xxt2 +',' + xxt + " | " + zzb + "," + zzb2); + saveRegion(worldObj, xxt2 , xxt, zzb, zzb2); // ? + } + if (checkX1 && checkZ2) { + System.out.print("CX1 && CZ2"); + System.out.print(xxb +',' + xxb2 + " | " + zzt2 + "," + zzt); + saveRegion(worldObj, xxb , xxb2, zzt2, zzt); // ? + } + if (checkX2 && checkZ2) { + saveRegion(worldObj, xxt2 , xxt, zzt2, zzt); // + } + saveEntitiesOut(chunkObj, CURRENT_PLOT_CLEAR); + if (canRegen && ap != null) { + ap.populate(worldObj, null, chunkObj); + } + else { + regenerateChunk(world, chunk); + } + restoreBlocks(worldObj, 0, 0); + restoreEntities(worldObj, 0, 0); + } + CURRENT_PLOT_CLEAR = null; + if (chunks.size() != 0) { + TaskManager.runTaskLater(this, 1); + } + else { + TaskManager.runTaskLater(whenDone, 1); + } + } + }); return true; }