Many Much

- Add readregions to queues for when we're setting our own consumer (usually meaning the queue writes its own blocks, so it doesn't know which chunks to actually load)
 - Finish removing chunk/regionTasks
 - Allow the queue to not remove tickets from chunks (useful for swapping chunks so they don't unload needlessly)
 - Remove a lot of unused methods
 - Implement entities to queues
 - Remove chunk unloading (the server should really handle it)
This commit is contained in:
dordsor21 2020-07-23 17:30:23 +01:00
parent 207e56969b
commit 27498f68fb
No known key found for this signature in database
GPG Key ID: 1E53E88969FFCF0B
21 changed files with 504 additions and 540 deletions

View File

@ -53,7 +53,6 @@ import com.plotsquared.core.plot.world.DefaultPlotAreaManager;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotAreaManager;
import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.queue.ChunkCoordinatorBuilder;
import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueProvider; import com.plotsquared.core.queue.QueueProvider;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
@ -94,8 +93,8 @@ public class BukkitModule extends AbstractModule {
bind(InventoryUtil.class).to(BukkitInventoryUtil.class); bind(InventoryUtil.class).to(BukkitInventoryUtil.class);
bind(SetupUtils.class).to(BukkitSetupUtils.class); bind(SetupUtils.class).to(BukkitSetupUtils.class);
bind(WorldUtil.class).to(BukkitUtil.class); bind(WorldUtil.class).to(BukkitUtil.class);
bind(GlobalBlockQueue.class).toInstance(new GlobalBlockQueue( bind(GlobalBlockQueue.class)
QueueProvider.of(BukkitQueueCoordinator.class, BukkitQueueCoordinator.class))); .toInstance(new GlobalBlockQueue(QueueProvider.of(BukkitQueueCoordinator.class)));
bind(ChunkManager.class).to(BukkitChunkManager.class); bind(ChunkManager.class).to(BukkitChunkManager.class);
bind(RegionManager.class).to(BukkitRegionManager.class); bind(RegionManager.class).to(BukkitRegionManager.class);
bind(SchematicHandler.class).to(BukkitSchematicHandler.class); bind(SchematicHandler.class).to(BukkitSchematicHandler.class);

View File

@ -69,6 +69,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
private final org.bukkit.World bukkitWorld; private final org.bukkit.World bukkitWorld;
private final Runnable whenDone; private final Runnable whenDone;
private final Consumer<Throwable> throwableConsumer; private final Consumer<Throwable> throwableConsumer;
private final boolean unloadAfter;
private final int totalSize; private final int totalSize;
private final AtomicInteger expectedSize; private final AtomicInteger expectedSize;
@ -80,7 +81,8 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
@Assisted @Nonnull final World world, @Assisted @Nonnull final World world,
@Assisted @Nonnull final Collection<BlockVector2> requestedChunks, @Assisted @Nonnull final Collection<BlockVector2> requestedChunks,
@Assisted @Nonnull final Runnable whenDone, @Assisted @Nonnull final Runnable whenDone,
@Assisted @Nonnull final Consumer<Throwable> throwableConsumer) { @Assisted @Nonnull final Consumer<Throwable> throwableConsumer,
@Assisted final boolean unloadAfter) {
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks); this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
this.availableChunks = new LinkedBlockingQueue<>(); this.availableChunks = new LinkedBlockingQueue<>();
this.totalSize = requestedChunks.size(); this.totalSize = requestedChunks.size();
@ -90,6 +92,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
this.maxIterationTime = maxIterationTime; this.maxIterationTime = maxIterationTime;
this.whenDone = whenDone; this.whenDone = whenDone;
this.throwableConsumer = throwableConsumer; this.throwableConsumer = throwableConsumer;
this.unloadAfter = unloadAfter;
this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class); this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
this.bukkitWorld = Bukkit.getWorld(world.getName()); this.bukkitWorld = Bukkit.getWorld(world.getName());
} }
@ -119,7 +122,9 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
} catch (final Throwable throwable) { } catch (final Throwable throwable) {
this.throwableConsumer.accept(throwable); this.throwableConsumer.accept(throwable);
} }
if (unloadAfter) {
this.freeChunk(chunk); this.freeChunk(chunk);
}
processedChunks++; processedChunks++;
final long end = System.currentTimeMillis(); final long end = System.currentTimeMillis();
// Update iteration time // Update iteration time

View File

@ -52,17 +52,16 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Container; import org.bukkit.block.Container;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import javax.annotation.Nonnull; import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer; import java.util.function.Consumer;
public class BukkitQueueCoordinator extends BasicQueueCoordinator { public class BukkitQueueCoordinator extends BasicQueueCoordinator {
private final World world;
private final SideEffectSet sideEffectSet; private final SideEffectSet sideEffectSet;
private org.bukkit.World bukkitWorld; private org.bukkit.World bukkitWorld;
@Inject private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory; @Inject private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory;
@ -72,13 +71,12 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
@Inject public BukkitQueueCoordinator(World world) { @Inject public BukkitQueueCoordinator(World world) {
super(world); super(world);
this.world = world;
sideEffectSet = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF) sideEffectSet = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF)
.with(SideEffect.NEIGHBORS, SideEffect.State.OFF); .with(SideEffect.NEIGHBORS, SideEffect.State.OFF);
} }
@Override public BlockState getBlock(int x, int y, int z) { @Override public BlockState getBlock(int x, int y, int z) {
org.bukkit.World worldObj = BukkitAdapter.adapt(world); org.bukkit.World worldObj = BukkitAdapter.adapt(getWorld());
if (worldObj != null) { if (worldObj != null) {
Block block = worldObj.getBlockAt(x, y, z); Block block = worldObj.getBlockAt(x, y, z);
return BukkitBlockUtil.get(block); return BukkitBlockUtil.get(block);
@ -103,7 +101,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
BlockVector3.at(getRegenStart()[0] << 4, 0, getRegenStart()[1] << 4), BlockVector3.at(getRegenStart()[0] << 4, 0, getRegenStart()[1] << 4),
BlockVector3.at((getRegenEnd()[0] << 4) + 15, 255, (getRegenEnd()[1] << 4) + 15)); BlockVector3.at((getRegenEnd()[0] << 4) + 15, 255, (getRegenEnd()[1] << 4) + 15));
regenClipboard = new BlockArrayClipboard(region); regenClipboard = new BlockArrayClipboard(region);
world.regenerate(region, regenClipboard); getWorld().regenerate(region, regenClipboard);
} else { } else {
regenClipboard = null; regenClipboard = null;
} }
@ -164,40 +162,51 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
int x = sx + ChunkUtil.getX(j); int x = sx + ChunkUtil.getX(j);
int y = ChunkUtil.getY(layer, j); int y = ChunkUtil.getY(layer, j);
int z = sz + ChunkUtil.getZ(j); int z = sz + ChunkUtil.getZ(j);
world.setBiome(BlockVector3.at(x, y, z), biome); getWorld().setBiome(BlockVector3.at(x, y, z), biome);
} }
} }
if (localChunk.getTiles().size() > 0) { if (localChunk.getTiles().size() > 0) {
localChunk.getTiles().forEach(((blockVector3, tag) -> { localChunk.getTiles().forEach(((blockVector3, tag) -> {
try { try {
BaseBlock block = world.getBlock(blockVector3).toBaseBlock(tag); BaseBlock block = getWorld().getBlock(blockVector3).toBaseBlock(tag);
world.setBlock(blockVector3, block, sideEffectSet); getWorld().setBlock(blockVector3, block, sideEffectSet);
} catch (WorldEditException ignored) { } catch (WorldEditException ignored) {
StateWrapper sw = new StateWrapper(tag); StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(world.getName(), blockVector3.getX(), blockVector3.getY(), sw.restoreTag(getWorld().getName(), blockVector3.getX(),
blockVector3.getZ()); blockVector3.getY(), blockVector3.getZ());
} }
})); }));
} }
if (localChunk.getEntities().size() > 0) {
localChunk.getEntities().forEach((location, entity) -> {
getWorld().createEntity(location, entity);
});
}
}; };
} }
CuboidRegion region;
Collection<BlockVector2> read = new ArrayList<>();
if ((region = getReadRegion()) != null) {
read = region.getChunks();
}
chunkCoordinator = chunkCoordinator =
chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(world) chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(getWorld())
.withChunks(getBlockChunks().keySet()).withInitialBatchSize(3) .withChunks(getBlockChunks().keySet()).withChunks(read).withInitialBatchSize(3)
.withMaxIterationTime(40).withThrowableConsumer(Throwable::printStackTrace) .withMaxIterationTime(40).withThrowableConsumer(Throwable::printStackTrace)
.withFinalAction(whenDone).withConsumer(consumer).build(); .withFinalAction(whenDone).withConsumer(consumer).unloadAfter(isUnloadAfter())
.build();
return super.enqueue(); return super.enqueue();
} }
private void setWorldBlock(int x, int y, int z, BaseBlock block, BlockVector2 blockVector2) { private void setWorldBlock(int x, int y, int z, BaseBlock block, BlockVector2 blockVector2) {
try { try {
world.setBlock(BlockVector3.at(x, y, z), block, sideEffectSet); getWorld().setBlock(BlockVector3.at(x, y, z), block, sideEffectSet);
} catch (WorldEditException ignored) { } catch (WorldEditException ignored) {
// Fallback to not so nice method // Fallback to not so nice method
BlockData blockData = BukkitAdapter.adapt(block); BlockData blockData = BukkitAdapter.adapt(block);
if (bukkitWorld == null) { if (bukkitWorld == null) {
bukkitWorld = Bukkit.getWorld(world.getName()); bukkitWorld = Bukkit.getWorld(getWorld().getName());
} }
Chunk chunk = bukkitWorld.getChunkAt(blockVector2.getX(), blockVector2.getZ()); Chunk chunk = bukkitWorld.getChunkAt(blockVector2.getX(), blockVector2.getZ());
@ -218,7 +227,8 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
CompoundTag tag = block.getNbtData(); CompoundTag tag = block.getNbtData();
StateWrapper sw = new StateWrapper(tag); StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(world.getName(), existing.getX(), existing.getY(), existing.getZ()); sw.restoreTag(getWorld().getName(), existing.getX(), existing.getY(),
existing.getZ());
} }
} }
} }
@ -227,13 +237,4 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
this.whenDone = whenDone; this.whenDone = whenDone;
} }
private void setMaterial(@Nonnull final BlockState plotBlock, @Nonnull final Block block) {
Material material = BukkitAdapter.adapt(plotBlock.getBlockType());
block.setType(material, false);
}
private boolean equals(@Nonnull final BlockState plotBlock, @Nonnull final Block block) {
return plotBlock.equals(BukkitBlockUtil.get(block));
}
} }

View File

@ -129,37 +129,4 @@ public class BukkitChunkManager extends ChunkManager {
.getChunkAtAsync(BukkitUtil.getWorld(world), chunkLoc.getX(), chunkLoc.getZ(), force); .getChunkAtAsync(BukkitUtil.getWorld(world), chunkLoc.getX(), chunkLoc.getZ(), force);
} }
@Override
public void unloadChunk(final String world, final BlockVector2 chunkLoc, final boolean save) {
if (!PlotSquared.get().isMainThread(Thread.currentThread())) {
TaskManager.runTask(() -> BukkitUtil.getWorld(world)
.unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save));
} else {
BukkitUtil.getWorld(world).unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save);
}
}
private void count(int[] count, Entity entity) {
final com.sk89q.worldedit.world.entity.EntityType entityType =
BukkitAdapter.adapt(entity.getType());
if (EntityCategories.PLAYER.contains(entityType)) {
return;
} else if (EntityCategories.PROJECTILE.contains(entityType) || EntityCategories.OTHER
.contains(entityType) || EntityCategories.HANGING.contains(entityType)) {
count[CAP_MISC]++;
} else if (EntityCategories.ANIMAL.contains(entityType) || EntityCategories.VILLAGER
.contains(entityType) || EntityCategories.TAMEABLE.contains(entityType)) {
count[CAP_MOB]++;
count[CAP_ANIMAL]++;
} else if (EntityCategories.VEHICLE.contains(entityType)) {
count[CAP_VEHICLE]++;
} else if (EntityCategories.HOSTILE.contains(entityType)) {
count[CAP_MOB]++;
count[CAP_MONSTER]++;
}
count[CAP_ENTITY]++;
}
} }

View File

@ -28,15 +28,13 @@ package com.plotsquared.bukkit.util;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.generator.AugmentedUtils; import com.plotsquared.core.generator.AugmentedUtils;
import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.location.PlotLoc; import com.plotsquared.core.location.PlotLoc;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotManager; import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
@ -45,13 +43,11 @@ import com.plotsquared.core.util.RegionUtil;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.entity.EntityCategories;
import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
@ -63,17 +59,13 @@ import org.bukkit.entity.Player;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ANIMAL; import static com.plotsquared.core.util.entity.EntityCategories.CAP_ANIMAL;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY; import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC; import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC;
@ -86,19 +78,8 @@ public class BukkitRegionManager extends RegionManager {
private static final Logger logger = private static final Logger logger =
LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName()); LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName());
private final WorldUtil worldUtil; @Inject private WorldUtil worldUtil;
private final ChunkCoordinatorFactory chunkCoordinatorFactory; @Inject private GlobalBlockQueue blockQueue;
private final ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory;
@Inject public BukkitRegionManager(@Nonnull final ChunkManager chunkManager,
@Nonnull final WorldUtil worldUtil,
@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory,
@Nonnull ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory) {
super(chunkManager, worldUtil, chunkCoordinatorBuilderFactory);
this.worldUtil = worldUtil;
this.chunkCoordinatorFactory = chunkCoordinatorFactory;
this.chunkCoordinatorBuilderFactory = chunkCoordinatorBuilderFactory;
}
@Override public Set<BlockVector2> getChunkChunks(String world) { @Override public Set<BlockVector2> getChunkChunks(String world) {
Set<BlockVector2> chunks = super.getChunkChunks(world); Set<BlockVector2> chunks = super.getChunkChunks(world);
@ -141,7 +122,6 @@ public class BukkitRegionManager extends RegionManager {
} }
PlotArea area = plot.getArea(); PlotArea area = plot.getArea();
World world = BukkitUtil.getWorld(area.getWorldName()); World world = BukkitUtil.getWorld(area.getWorldName());
Location bot = plot.getBottomAbs(); Location bot = plot.getBottomAbs();
Location top = plot.getTopAbs(); Location top = plot.getTopAbs();
int bx = bot.getX() >> 4; int bx = bot.getX() >> 4;
@ -209,53 +189,6 @@ public class BukkitRegionManager extends RegionManager {
return count; return count;
} }
@Override @Inject
public boolean copyRegion(final Location pos1, final Location pos2, final Location newPos,
final Runnable whenDone) {
final int relX = newPos.getX() - pos1.getX();
final int relZ = newPos.getZ() - pos1.getZ();
final com.sk89q.worldedit.world.World oldWorld = worldUtil.getWeWorld(pos1.getWorldName());
final BukkitWorld newWorld = new BukkitWorld((World) newPos.getWorld());
assert oldWorld.equals(newWorld);
final ContentMap map = new ContentMap();
final QueueCoordinator queue =
PlotSquared.platform().getGlobalBlockQueue().getNewQueue(newWorld);
chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(newWorld)
.withRegion(pos1, pos2).withThrowableConsumer(Throwable::printStackTrace)
.withRegion(pos1, pos2).withInitialBatchSize(4).withMaxIterationTime(45)
.withConsumer(chunk -> {
int cbx = chunk.getX();
int cbz = chunk.getZ();
int bx = Math.max(pos1.getX() & 15, 0);
int bz = Math.max(pos1.getZ() & 15, 0);
int tx = Math.min(pos2.getX() & 15, 15);
int tz = Math.min(pos2.getZ() & 15, 15);
for (int x = bx; x <= tx; x++) {
for (int z = bz; z <= tz; z++) {
map.saveBlocks(newWorld, 256, cbx + x, cbz + z, relX, relZ);
}
}
}).withFinalAction(() -> {
for (Entry<PlotLoc, BaseBlock[]> entry : map.allBlocks.entrySet()) {
PlotLoc loc = entry.getKey();
BaseBlock[] blocks = entry.getValue();
for (int y = 0; y < blocks.length; y++) {
if (blocks[y] != null) {
BaseBlock block = blocks[y];
queue.setBlock(loc.getX(), y, loc.getZ(), block);
}
}
}
queue.setCompleteTask(() -> {
//map.restoreBlocks(newWorld, 0, 0);
map.restoreEntities(Bukkit.getWorld(newPos.getWorldName()), relX, relZ);
TaskManager.runTask(whenDone);
});
queue.enqueue();
});
return true;
}
@Override @Inject public boolean regenerateRegion(final Location pos1, final Location pos2, @Override @Inject public boolean regenerateRegion(final Location pos1, final Location pos2,
final boolean ignoreAugment, final Runnable whenDone) { final boolean ignoreAugment, final Runnable whenDone) {
final BukkitWorld world = new BukkitWorld((World) pos1.getWorld()); final BukkitWorld world = new BukkitWorld((World) pos1.getWorld());
@ -269,20 +202,9 @@ public class BukkitRegionManager extends RegionManager {
final int tcx = p2x >> 4; final int tcx = p2x >> 4;
final int tcz = p2z >> 4; final int tcz = p2z >> 4;
final List<BlockVector2> chunks = new ArrayList<>(); final QueueCoordinator queue = blockQueue.getNewQueue(world);
queue.setReadRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()));
for (int x = bcx; x <= tcx; x++) { queue.setChunkConsumer(chunk -> {
for (int z = bcz; z <= tcz; z++) {
chunks.add(BlockVector2.at(x, z));
}
}
final QueueCoordinator queue =
PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world);
chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(world)
.withRegion(pos1, pos2).withThrowableConsumer(Throwable::printStackTrace)
.withRegion(pos1, pos2).withInitialBatchSize(4).withMaxIterationTime(45)
.withConsumer(chunk -> {
int x = chunk.getX(); int x = chunk.getX();
int z = chunk.getZ(); int z = chunk.getZ();
@ -291,8 +213,8 @@ public class BukkitRegionManager extends RegionManager {
int xxt = xxb + 15; int xxt = xxb + 15;
int zzt = zzb + 15; int zzt = zzb + 15;
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
AugmentedUtils.bypass(ignoreAugment, AugmentedUtils
() -> queue.regenChunk(chunk.getX(), chunk.getZ())); .bypass(ignoreAugment, () -> queue.regenChunk(chunk.getX(), chunk.getZ()));
return; return;
} }
boolean checkX1 = false; boolean checkX1 = false;
@ -378,8 +300,7 @@ public class BukkitRegionManager extends RegionManager {
BlockTypes.AIR.getDefaultState()); BlockTypes.AIR.getDefaultState());
} }
} }
for (int y = Math.min(128, ids.length); for (int y = Math.min(128, ids.length); y < ids.length; y++) {
y < ids.length; y++) {
BaseBlock id = ids[y]; BaseBlock id = ids[y];
if (id != null) { if (id != null) {
value.setBlock(x1, y, z1, id); value.setBlock(x1, y, z1, id);
@ -392,7 +313,9 @@ public class BukkitRegionManager extends RegionManager {
}, world.getName(), chunk)); }, world.getName(), chunk));
//map.restoreBlocks(worldObj, 0, 0); //map.restoreBlocks(worldObj, 0, 0);
map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0); map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0);
}).withFinalAction(whenDone); });
queue.setCompleteTask(whenDone);
queue.enqueue();
return true; return true;
} }
@ -425,62 +348,6 @@ public class BukkitRegionManager extends RegionManager {
} }
} }
@Override public void swap(Location bot1, Location top1, Location bot2, Location top2,
final Runnable whenDone) {
CuboidRegion region1 =
RegionUtil.createRegion(bot1.getX(), top1.getX(), bot1.getZ(), top1.getZ());
CuboidRegion region2 =
RegionUtil.createRegion(bot2.getX(), top2.getX(), bot2.getZ(), top2.getZ());
final World world1 = Bukkit.getWorld(bot1.getWorldName());
final World world2 = Bukkit.getWorld(bot2.getWorldName());
checkNotNull(world1, "Critical error during swap.");
checkNotNull(world2, "Critical error during swap.");
int relX = bot2.getX() - bot1.getX();
int relZ = bot2.getZ() - bot1.getZ();
final ArrayDeque<ContentMap> maps = new ArrayDeque<>();
for (int x = bot1.getX() >> 4; x <= top1.getX() >> 4; x++) {
for (int z = bot1.getZ() >> 4; z <= top1.getZ() >> 4; z++) {
Chunk chunk1 = world1.getChunkAt(x, z);
Chunk chunk2 = world2.getChunkAt(x + (relX >> 4), z + (relZ >> 4));
maps.add(
BukkitChunkManager.swapChunk(world1, world2, chunk1, chunk2, region1, region2));
}
}
PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(() -> {
for (ContentMap map : maps) {
map.restoreEntities(world1, 0, 0);
TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L));
}
});
}
@Override
public void setBiome(final CuboidRegion region, final int extendBiome, final BiomeType biome,
final String world, final Runnable whenDone) {
Location pos1 = Location.at(world, region.getMinimumPoint().getX() - extendBiome,
region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome);
Location pos2 = Location.at(world, region.getMaximumPoint().getX() + extendBiome,
region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome);
final QueueCoordinator queue = PlotSquared.platform().getGlobalBlockQueue()
.getNewQueue(worldUtil.getWeWorld(world));
final int minX = pos1.getX();
final int minZ = pos1.getZ();
final int maxX = pos2.getX();
final int maxZ = pos2.getZ();
queue.setChunkConsumer(blockVector2 -> {
final int cx = blockVector2.getX() << 4;
final int cz = blockVector2.getZ() << 4;
WorldUtil
.setBiome(world, Math.max(minX, cx), Math.max(minZ, cz), Math.min(maxX, cx + 15),
Math.min(maxZ, cz + 15), biome);
worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), world);
});
queue.enqueue();
}
private void count(int[] count, Entity entity) { private void count(int[] count, Entity entity) {
final com.sk89q.worldedit.world.entity.EntityType entityType = final com.sk89q.worldedit.world.entity.EntityType entityType =
BukkitAdapter.adapt(entity.getType()); BukkitAdapter.adapt(entity.getType());

View File

@ -27,8 +27,6 @@ package com.plotsquared.core.command;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.inject.annotations.WorldConfig;
import com.plotsquared.core.inject.annotations.WorldFile;
import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Captions;
import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.ConfigurationSection;
import com.plotsquared.core.configuration.ConfigurationUtil; import com.plotsquared.core.configuration.ConfigurationUtil;
@ -36,6 +34,8 @@ import com.plotsquared.core.configuration.file.YamlConfiguration;
import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.events.TeleportCause;
import com.plotsquared.core.generator.AugmentedUtils; import com.plotsquared.core.generator.AugmentedUtils;
import com.plotsquared.core.generator.HybridPlotWorld; import com.plotsquared.core.generator.HybridPlotWorld;
import com.plotsquared.core.inject.annotations.WorldConfig;
import com.plotsquared.core.inject.annotations.WorldFile;
import com.plotsquared.core.inject.factory.HybridPlotWorldFactory; import com.plotsquared.core.inject.factory.HybridPlotWorldFactory;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.player.ConsolePlayer; import com.plotsquared.core.player.ConsolePlayer;
@ -46,6 +46,8 @@ import com.plotsquared.core.plot.PlotAreaType;
import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.message.PlotMessage; import com.plotsquared.core.plot.message.PlotMessage;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.setup.PlotAreaBuilder;
import com.plotsquared.core.util.FileUtils; import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MainUtil;
@ -57,7 +59,6 @@ import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.SetupUtils;
import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.StringMan;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.task.RunnableVal3;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
@ -68,12 +69,11 @@ import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import javax.annotation.Nonnull;
import javax.annotation.Nonnull;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -100,14 +100,14 @@ public class Area extends SubCommand {
private final SetupUtils setupUtils; private final SetupUtils setupUtils;
private final WorldUtil worldUtil; private final WorldUtil worldUtil;
private final RegionManager regionManager; private final RegionManager regionManager;
private final GlobalBlockQueue blockQueue;
@Inject public Area(@Nonnull final PlotAreaManager plotAreaManager, @Inject public Area(@Nonnull final PlotAreaManager plotAreaManager,
@WorldConfig @Nonnull final YamlConfiguration worldConfiguration, @WorldConfig @Nonnull final YamlConfiguration worldConfiguration,
@WorldFile @Nonnull final File worldFile, @WorldFile @Nonnull final File worldFile,
@Nonnull final HybridPlotWorldFactory hybridPlotWorldFactory, @Nonnull final HybridPlotWorldFactory hybridPlotWorldFactory,
@Nonnull final SetupUtils setupUtils, @Nonnull final SetupUtils setupUtils, @Nonnull final WorldUtil worldUtil,
@Nonnull final WorldUtil worldUtil, @Nonnull final RegionManager regionManager, @Nonnull final GlobalBlockQueue blockQueue) {
@Nonnull final RegionManager regionManager) {
this.plotAreaManager = plotAreaManager; this.plotAreaManager = plotAreaManager;
this.worldConfiguration = worldConfiguration; this.worldConfiguration = worldConfiguration;
this.worldFile = worldFile; this.worldFile = worldFile;
@ -115,6 +115,7 @@ public class Area extends SubCommand {
this.setupUtils = setupUtils; this.setupUtils = setupUtils;
this.worldUtil = worldUtil; this.worldUtil = worldUtil;
this.regionManager = regionManager; this.regionManager = regionManager;
this.blockQueue = blockQueue;
} }
@Override public boolean onCommand(final PlotPlayer<?> player, String[] args) { @Override public boolean onCommand(final PlotPlayer<?> player, String[] args) {
@ -129,27 +130,32 @@ public class Area extends SubCommand {
return false; return false;
} }
if (!Permissions.hasPermission(player, Captions.PERMISSION_AREA_CREATE)) { if (!Permissions.hasPermission(player, Captions.PERMISSION_AREA_CREATE)) {
MainUtil.sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_AREA_CREATE); MainUtil.sendMessage(player, Captions.NO_PERMISSION,
Captions.PERMISSION_AREA_CREATE);
return false; return false;
} }
if (args.length < 2) { if (args.length < 2) {
MainUtil.sendMessage(player, Captions.SINGLE_AREA_NEEDS_NAME); MainUtil.sendMessage(player, Captions.SINGLE_AREA_NEEDS_NAME);
return false; return false;
} }
final PlotArea existingArea = this.plotAreaManager.getPlotArea(player.getLocation().getWorldName(), args[1]); final PlotArea existingArea =
this.plotAreaManager.getPlotArea(player.getLocation().getWorldName(), args[1]);
if (existingArea != null && existingArea.getId().equalsIgnoreCase(args[1])) { if (existingArea != null && existingArea.getId().equalsIgnoreCase(args[1])) {
MainUtil.sendMessage(player, Captions.SINGLE_AREA_NAME_TAKEN); MainUtil.sendMessage(player, Captions.SINGLE_AREA_NAME_TAKEN);
return false; return false;
} }
final LocalSession localSession = WorldEdit.getInstance().getSessionManager().getIfPresent(player.toActor()); final LocalSession localSession =
WorldEdit.getInstance().getSessionManager().getIfPresent(player.toActor());
if (localSession == null) { if (localSession == null) {
MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION);
return false; return false;
} }
Region playerSelectedRegion = null; Region playerSelectedRegion = null;
try { try {
playerSelectedRegion = localSession.getSelection(((Player) player.toActor()).getWorld()); playerSelectedRegion =
} catch (final Exception ignored) {} localSession.getSelection(((Player) player.toActor()).getWorld());
} catch (final Exception ignored) {
}
if (playerSelectedRegion == null) { if (playerSelectedRegion == null) {
MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION);
return false; return false;
@ -158,23 +164,28 @@ public class Area extends SubCommand {
MainUtil.sendMessage(player, Captions.SINGLE_AREA_NOT_SQUARE); MainUtil.sendMessage(player, Captions.SINGLE_AREA_NOT_SQUARE);
return false; return false;
} }
if (this.plotAreaManager.getPlotAreas( if (this.plotAreaManager
Objects.requireNonNull(playerSelectedRegion.getWorld()).getName(), CuboidRegion.makeCuboid(playerSelectedRegion)).length != 0) { .getPlotAreas(Objects.requireNonNull(playerSelectedRegion.getWorld()).getName(),
CuboidRegion.makeCuboid(playerSelectedRegion)).length != 0) {
MainUtil.sendMessage(player, Captions.SINGLE_AREA_OVERLAPPING); MainUtil.sendMessage(player, Captions.SINGLE_AREA_OVERLAPPING);
} }
// Alter the region // Alter the region
final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint(); final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint();
final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint(); final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint();
// Create a new selection that spans the entire vertical range of the world // Create a new selection that spans the entire vertical range of the world
final CuboidRegion selectedRegion = new CuboidRegion(playerSelectedRegion.getWorld(), final CuboidRegion selectedRegion =
new CuboidRegion(playerSelectedRegion.getWorld(),
BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()), BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()),
BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ())); BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ()));
// There's only one plot in the area... // There's only one plot in the area...
final PlotId plotId = PlotId.of(1, 1); final PlotId plotId = PlotId.of(1, 1);
final HybridPlotWorld hybridPlotWorld = this.hybridPlotWorldFactory.create(player.getLocation().getWorldName(), args[1], final HybridPlotWorld hybridPlotWorld = this.hybridPlotWorldFactory
Objects.requireNonNull(PlotSquared.platform()).getDefaultGenerator(), plotId, plotId); .create(player.getLocation().getWorldName(), args[1],
Objects.requireNonNull(PlotSquared.platform()).getDefaultGenerator(),
plotId, plotId);
// Plot size is the same as the region width // Plot size is the same as the region width
hybridPlotWorld.PLOT_WIDTH = hybridPlotWorld.SIZE = (short) selectedRegion.getWidth(); hybridPlotWorld.PLOT_WIDTH =
hybridPlotWorld.SIZE = (short) selectedRegion.getWidth();
// We use a schematic generator // We use a schematic generator
hybridPlotWorld.setTerrain(PlotAreaTerrainType.NONE); hybridPlotWorld.setTerrain(PlotAreaTerrainType.NONE);
// It is always a partial plot world // It is always a partial plot world
@ -182,23 +193,30 @@ public class Area extends SubCommand {
// We save the schematic :D // We save the schematic :D
hybridPlotWorld.PLOT_SCHEMATIC = true; hybridPlotWorld.PLOT_SCHEMATIC = true;
// Set the road width to 0 // Set the road width to 0
hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0; hybridPlotWorld.ROAD_WIDTH =
hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0;
// Set the plot height to the selection height // Set the plot height to the selection height
hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = playerSelectionMin.getBlockY(); hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT =
hybridPlotWorld.WALL_HEIGHT = playerSelectionMin.getBlockY();
// No sign plz // No sign plz
hybridPlotWorld.setAllowSigns(false); hybridPlotWorld.setAllowSigns(false);
final File parentFile = FileUtils.getFile(PlotSquared.platform().getDirectory(), "schematics" + File.separator + final File parentFile = FileUtils.getFile(PlotSquared.platform().getDirectory(),
"GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator + "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator
hybridPlotWorld.getId()); + hybridPlotWorld.getWorldName() + File.separator + hybridPlotWorld
.getId());
if (!parentFile.exists() && !parentFile.mkdirs()) { if (!parentFile.exists() && !parentFile.mkdirs()) {
MainUtil.sendMessage(player, Captions.SINGLE_AREA_COULD_NOT_MAKE_DIRECTORIES); MainUtil.sendMessage(player, Captions.SINGLE_AREA_COULD_NOT_MAKE_DIRECTORIES);
return false; return false;
} }
final File file = new File(parentFile, "plot.schem"); final File file = new File(parentFile, "plot.schem");
try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) { try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC
.getWriter(new FileOutputStream(file))) {
final BlockArrayClipboard clipboard = new BlockArrayClipboard(selectedRegion); final BlockArrayClipboard clipboard = new BlockArrayClipboard(selectedRegion);
final EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(selectedRegion.getWorld(), -1); final EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
final ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, selectedRegion, clipboard, selectedRegion.getMinimumPoint()); .getEditSession(selectedRegion.getWorld(), -1);
final ForwardExtentCopy forwardExtentCopy =
new ForwardExtentCopy(editSession, selectedRegion, clipboard,
selectedRegion.getMinimumPoint());
forwardExtentCopy.setCopyingBiomes(true); forwardExtentCopy.setCopyingBiomes(true);
forwardExtentCopy.setCopyingEntities(true); forwardExtentCopy.setCopyingEntities(true);
Operations.complete(forwardExtentCopy); Operations.complete(forwardExtentCopy);
@ -222,13 +240,13 @@ public class Area extends SubCommand {
// Now the schematic is saved, which is wonderful! // Now the schematic is saved, which is wonderful!
PlotAreaBuilder singleBuilder = PlotAreaBuilder.ofPlotArea(hybridPlotWorld) PlotAreaBuilder singleBuilder = PlotAreaBuilder.ofPlotArea(hybridPlotWorld)
.plotManager(PlotSquared.platform().getPluginName()) .plotManager(PlotSquared.platform().getPluginName())
.generatorName(PlotSquared.platform().getPluginName()) .generatorName(PlotSquared.platform().getPluginName()).maximumId(plotId)
.maximumId(plotId)
.minimumId(plotId); .minimumId(plotId);
Runnable singleRun = () -> { Runnable singleRun = () -> {
final String path = final String path =
"worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld.getId() + '-' "worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld
+ singleBuilder.minimumId() + '-' + singleBuilder.maximumId(); .getId() + '-' + singleBuilder.minimumId() + '-' + singleBuilder
.maximumId();
final int offsetX = singlePos1.getX(); final int offsetX = singlePos1.getX();
final int offsetZ = singlePos1.getZ(); final int offsetZ = singlePos1.getZ();
if (offsetX != 0) { if (offsetX != 0) {
@ -316,17 +334,18 @@ public class Area extends SubCommand {
PlotAreaBuilder builder = PlotAreaBuilder.ofPlotArea(area) PlotAreaBuilder builder = PlotAreaBuilder.ofPlotArea(area)
.plotManager(PlotSquared.platform().getPluginName()) .plotManager(PlotSquared.platform().getPluginName())
.generatorName(PlotSquared.platform().getPluginName()) .generatorName(PlotSquared.platform().getPluginName())
.minimumId(PlotId.of(1, 1)) .minimumId(PlotId.of(1, 1)).maximumId(PlotId.of(numX, numZ));
.maximumId(PlotId.of(numX, numZ));
final String path = final String path =
"worlds." + area.getWorldName() + ".areas." + area.getId() + '-' "worlds." + area.getWorldName() + ".areas." + area.getId() + '-'
+ builder.minimumId() + '-' + builder.maximumId(); + builder.minimumId() + '-' + builder.maximumId();
Runnable run = () -> { Runnable run = () -> {
if (offsetX != 0) { if (offsetX != 0) {
this.worldConfiguration.set(path + ".road.offset.x", offsetX); this.worldConfiguration
.set(path + ".road.offset.x", offsetX);
} }
if (offsetZ != 0) { if (offsetZ != 0) {
this.worldConfiguration.set(path + ".road.offset.z", offsetZ); this.worldConfiguration
.set(path + ".road.offset.z", offsetZ);
} }
final String world = this.setupUtils.setupWorld(builder); final String world = this.setupUtils.setupWorld(builder);
if (this.worldUtil.isWorld(world)) { if (this.worldUtil.isWorld(world)) {
@ -335,14 +354,13 @@ public class Area extends SubCommand {
player.teleport(this.worldUtil.getSpawn(world), player.teleport(this.worldUtil.getSpawn(world),
TeleportCause.COMMAND); TeleportCause.COMMAND);
if (area.getTerrain() != PlotAreaTerrainType.ALL) { if (area.getTerrain() != PlotAreaTerrainType.ALL) {
this.regionManager.largeRegionTask(world, region, QueueCoordinator queue =
new RunnableVal<BlockVector2>() { blockQueue.getNewQueue(worldUtil.getWeWorld(world));
@Override public void run(BlockVector2 value) { queue.setChunkConsumer(chunk -> AugmentedUtils
AugmentedUtils .generate(null, world, chunk.getX(), chunk.getZ(),
.generate(null, world, value.getX(), queue));
value.getZ(), null); queue.setReadRegion(region);
} queue.enqueue();
}, null);
} }
} else { } else {
MainUtil.sendMessage(player, MainUtil.sendMessage(player,
@ -368,14 +386,16 @@ public class Area extends SubCommand {
} }
PlotAreaBuilder builder = PlotAreaBuilder.newBuilder(); PlotAreaBuilder builder = PlotAreaBuilder.newBuilder();
builder.worldName(split[0]); builder.worldName(split[0]);
final HybridPlotWorld pa = this.hybridPlotWorldFactory.create(builder.worldName(), final HybridPlotWorld pa = this.hybridPlotWorldFactory
id, PlotSquared.platform().getDefaultGenerator(), null, null); .create(builder.worldName(), id,
PlotSquared.platform().getDefaultGenerator(), null, null);
PlotArea other = this.plotAreaManager.getPlotArea(pa.getWorldName(), id); PlotArea other = this.plotAreaManager.getPlotArea(pa.getWorldName(), id);
if (other != null && Objects.equals(pa.getId(), other.getId())) { if (other != null && Objects.equals(pa.getId(), other.getId())) {
Captions.SETUP_WORLD_TAKEN.send(player, pa.toString()); Captions.SETUP_WORLD_TAKEN.send(player, pa.toString());
return false; return false;
} }
Set<PlotArea> areas = this.plotAreaManager.getPlotAreasSet(pa.getWorldName()); Set<PlotArea> areas =
this.plotAreaManager.getPlotAreasSet(pa.getWorldName());
if (!areas.isEmpty()) { if (!areas.isEmpty()) {
PlotArea area = areas.iterator().next(); PlotArea area = areas.iterator().next();
pa.setType(area.getType()); pa.setType(area.getType());
@ -454,7 +474,8 @@ public class Area extends SubCommand {
if (!this.worldConfiguration.contains(path)) { if (!this.worldConfiguration.contains(path)) {
this.worldConfiguration.createSection(path); this.worldConfiguration.createSection(path);
} }
ConfigurationSection section = this.worldConfiguration.getConfigurationSection(path); ConfigurationSection section =
this.worldConfiguration.getConfigurationSection(path);
pa.saveConfiguration(section); pa.saveConfiguration(section);
pa.loadConfiguration(section); pa.loadConfiguration(section);
builder.plotManager(PlotSquared.platform().getPluginName()); builder.plotManager(PlotSquared.platform().getPluginName());
@ -581,7 +602,8 @@ public class Area extends SubCommand {
Captions.COMMAND_SYNTAX.send(player, getCommandString() + " list [#]"); Captions.COMMAND_SYNTAX.send(player, getCommandString() + " list [#]");
return false; return false;
} }
final List<PlotArea> areas = new ArrayList<>(Arrays.asList(this.plotAreaManager.getAllPlotAreas())); final List<PlotArea> areas =
new ArrayList<>(Arrays.asList(this.plotAreaManager.getAllPlotAreas()));
paginate(player, areas, 8, page, paginate(player, areas, 8, page,
new RunnableVal3<Integer, PlotArea, PlotMessage>() { new RunnableVal3<Integer, PlotArea, PlotMessage>() {
@Override public void run(Integer i, PlotArea area, PlotMessage message) { @Override public void run(Integer i, PlotArea area, PlotMessage message) {
@ -596,7 +618,8 @@ public class Area extends SubCommand {
PlotId max = area.getMax(); PlotId max = area.getMax();
name = area.getWorldName() + ';' + area.getId() + ';' + min + ';' name = area.getWorldName() + ';' + area.getId() + ';' + min + ';'
+ max; + max;
int size = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1); int size =
(max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1);
percent = claimed == 0 ? 0 : size / (double) claimed; percent = claimed == 0 ? 0 : size / (double) claimed;
region = area.getRegion().toString(); region = area.getRegion().toString();
} else { } else {
@ -641,14 +664,14 @@ public class Area extends SubCommand {
"$4Stop the server and delete: " + area.getWorldName() + "/region"); "$4Stop the server and delete: " + area.getWorldName() + "/region");
return false; return false;
} }
this.regionManager.largeRegionTask(area.getWorldName(), area.getRegion(),
new RunnableVal<BlockVector2>() { QueueCoordinator queue =
@Override public void run(BlockVector2 value) { blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
AugmentedUtils queue.setChunkConsumer(chunk -> AugmentedUtils
.generate(null, area.getWorldName(), value.getX(), value.getZ(), .generate(null, area.getWorldName(), chunk.getX(), chunk.getZ(), queue));
null); queue.setReadRegion(area.getRegion());
} queue.setCompleteTask(() -> player.sendMessage("Regen complete"));
}, () -> player.sendMessage("Regen complete")); queue.enqueue();
return true; return true;
} }
case "goto": case "goto":
@ -678,9 +701,11 @@ public class Area extends SubCommand {
center = Location.at(area.getWorldName(), region.getMinimumPoint().getX() center = Location.at(area.getWorldName(), region.getMinimumPoint().getX()
+ (region.getMaximumPoint().getX() - region.getMinimumPoint().getX()) / 2, + (region.getMaximumPoint().getX() - region.getMinimumPoint().getX()) / 2,
0, region.getMinimumPoint().getZ() 0, region.getMinimumPoint().getZ()
+ (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ()) / 2); + (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ())
this.worldUtil.getHighestBlock(area.getWorldName(), center.getX(), center.getZ(), y -> / 2);
player.teleport(center.withY(1 + y), TeleportCause.COMMAND)); this.worldUtil
.getHighestBlock(area.getWorldName(), center.getX(), center.getZ(),
y -> player.teleport(center.withY(1 + y), TeleportCause.COMMAND));
} }
return true; return true;
case "delete": case "delete":

View File

@ -72,6 +72,7 @@ public class AugmentedUtils {
if (areas.isEmpty()) { if (areas.isEmpty()) {
return false; return false;
} }
boolean enqueue = false;
boolean generationResult = false; boolean generationResult = false;
for (final PlotArea area : areas) { for (final PlotArea area : areas) {
// A normal plot world may not contain any clusters // A normal plot world may not contain any clusters
@ -81,15 +82,19 @@ public class AugmentedUtils {
} }
// This means that full vanilla generation is used // This means that full vanilla generation is used
// so we do not interfere // so we do not interfere
if (area.getTerrain() == PlotAreaTerrainType.ALL) { if (area.getTerrain() == PlotAreaTerrainType.ALL || !area.contains(blockX, blockZ)) {
continue; continue;
} }
IndependentPlotGenerator generator = area.getGenerator(); IndependentPlotGenerator generator = area.getGenerator();
// Mask // Mask
if (queue == null) { if (queue == null) {
queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(world)); enqueue = true;
queue = PlotSquared.platform().getGlobalBlockQueue()
.getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(world));
if (chunkObject != null) {
queue.setChunkObject(chunkObject); queue.setChunkObject(chunkObject);
} }
}
QueueCoordinator primaryMask; QueueCoordinator primaryMask;
// coordinates // coordinates
int relativeBottomX; int relativeBottomX;
@ -109,7 +114,6 @@ public class AugmentedUtils {
relativeTopX = relativeTopZ = 15; relativeTopX = relativeTopZ = 15;
primaryMask = queue; primaryMask = queue;
} }
QueueCoordinator secondaryMask; QueueCoordinator secondaryMask;
BlockState air = BlockTypes.AIR.getDefaultState(); BlockState air = BlockTypes.AIR.getDefaultState();
if (area.getTerrain() == PlotAreaTerrainType.ROAD) { if (area.getTerrain() == PlotAreaTerrainType.ROAD) {
@ -147,10 +151,12 @@ public class AugmentedUtils {
} }
generationResult = true; generationResult = true;
} }
if (chunkObject != null) {
primaryMask.setChunkObject(chunkObject); primaryMask.setChunkObject(chunkObject);
primaryMask.setForceSync(true); }
if (chunkObject != null) {
secondaryMask.setChunkObject(chunkObject); secondaryMask.setChunkObject(chunkObject);
secondaryMask.setForceSync(true); }
ScopedQueueCoordinator scoped = ScopedQueueCoordinator scoped =
new ScopedQueueCoordinator(secondaryMask, Location.at(world, blockX, 0, blockZ), new ScopedQueueCoordinator(secondaryMask, Location.at(world, blockX, 0, blockZ),
@ -158,8 +164,7 @@ public class AugmentedUtils {
generator.generateChunk(scoped, area); generator.generateChunk(scoped, area);
generator.populateChunk(scoped, area); generator.populateChunk(scoped, area);
} }
if (queue != null) { if (enqueue) {
queue.setForceSync(true);
queue.enqueue(); queue.enqueue();
} }
return generationResult; return generationResult;

View File

@ -42,6 +42,7 @@ import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
@ -247,6 +248,8 @@ public class HybridPlotManager extends ClassicPlotManager {
final BiomeType biome = hybridPlotWorld.getPlotBiome(); final BiomeType biome = hybridPlotWorld.getPlotBiome();
final QueueCoordinator queue = hybridPlotWorld.getQueue(); final QueueCoordinator queue = hybridPlotWorld.getQueue();
queue.setReadRegion(new CuboidRegion(plot.getExtendedBottomAbs().getBlockVector3(),
plot.getExtendedTopAbs().getBlockVector3()));
queue.setChunkConsumer(blockVector2 -> { queue.setChunkConsumer(blockVector2 -> {
// If the chunk isn't near the edge and it isn't an augmented world we can just regen the whole chunk // If the chunk isn't near the edge and it isn't an augmented world we can just regen the whole chunk
if (canRegen && ChunkUtil.isWholeChunk(pos1, pos2, blockVector2)) { if (canRegen && ChunkUtil.isWholeChunk(pos1, pos2, blockVector2)) {

View File

@ -161,7 +161,7 @@ public class HybridUtils {
System.gc(); System.gc();
QueueCoordinator queue = area.getQueue(); QueueCoordinator queue = area.getQueue();
queue.setReadRegion(region);
queue.setChunkConsumer(blockVector2 -> { queue.setChunkConsumer(blockVector2 -> {
int X = blockVector2.getX(); int X = blockVector2.getX();
int Z = blockVector2.getZ(); int Z = blockVector2.getZ();
@ -438,7 +438,6 @@ public class HybridUtils {
if (!regenedRoad && Settings.DEBUG) { if (!regenedRoad && Settings.DEBUG) {
logger.info("[P2] Failed to regenerate roads"); logger.info("[P2] Failed to regenerate roads");
} }
chunkManager.unloadChunk(area.getWorldName(), chunk, true);
} }
if (Settings.DEBUG) { if (Settings.DEBUG) {
logger.info("[P2] Cancelled road task"); logger.info("[P2] Cancelled road task");
@ -500,15 +499,6 @@ public class HybridUtils {
logger.error( logger.error(
"[P2] Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)", "[P2] Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)",
area.getWorldHash(), loc.getX(), loc.getZ()); area.getWorldHash(), loc.getX(), loc.getZ());
int sx = loc.getX() << 5;
int sz = loc.getZ() << 5;
for (int x = sx; x < sx + 32; x++) {
for (int z = sz; z < sz + 32; z++) {
chunkManager
.unloadChunk(area.getWorldName(), BlockVector2.at(x, z),
true);
}
}
} }
TaskManager.runTaskLater(task, TaskTime.seconds(1L)); TaskManager.runTaskLater(task, TaskTime.seconds(1L));
}); });

View File

@ -28,7 +28,6 @@ package com.plotsquared.core.inject.factory;
import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.ChunkCoordinator;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Collection; import java.util.Collection;
@ -37,8 +36,8 @@ import java.util.function.Consumer;
public interface ChunkCoordinatorFactory { public interface ChunkCoordinatorFactory {
@Nonnull ChunkCoordinator create(final long maxIterationTime, final int initialBatchSize, @Nonnull ChunkCoordinator create(final long maxIterationTime, final int initialBatchSize,
@NotNull final Consumer<BlockVector2> chunkConsumer, @NotNull final World world, @Nonnull final Consumer<BlockVector2> chunkConsumer, @Nonnull final World world,
@NotNull final Collection<BlockVector2> requestedChunks, @NotNull final Runnable whenDone, @Nonnull final Collection<BlockVector2> requestedChunks, @Nonnull final Runnable whenDone,
@NotNull final Consumer<Throwable> throwableConsumer); @Nonnull final Consumer<Throwable> throwableConsumer, final boolean unloadAfter);
} }

View File

@ -3312,9 +3312,7 @@ public class Plot {
Location pos2 = corners[1]; Location pos2 = corners[1];
Location pos3 = Location pos3 =
pos1.add(offsetX, 0, offsetZ).withWorld(destination.getWorldName()); pos1.add(offsetX, 0, offsetZ).withWorld(destination.getWorldName());
Location pos4 = regionManager.swap(pos1, pos2, pos3, this);
pos2.add(offsetX, 0, offsetZ).withWorld(destination.getWorldName());
regionManager.swap(pos1, pos2, pos3, pos4, this);
} }
} }
}.run(); }.run();

View File

@ -27,12 +27,16 @@ package com.plotsquared.core.queue;
import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.PatternUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.entity.EntityTypes;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -53,6 +57,8 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
private int[] regenStart; private int[] regenStart;
private int[] regenEnd; private int[] regenEnd;
private Consumer<BlockVector2> consumer = null; private Consumer<BlockVector2> consumer = null;
private boolean unloadAfter = true;
private CuboidRegion readRegion = null;
private GlobalBlockQueue globalBlockQueue; private GlobalBlockQueue globalBlockQueue;
@ -61,12 +67,6 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
this.modified = System.currentTimeMillis(); this.modified = System.currentTimeMillis();
} }
public LocalChunk getLocalChunk(int x, int z) {
return new LocalChunk(this, x, z) {
// Allow implementation-specific custom stuff here
};
}
@Override public abstract BlockState getBlock(int x, int y, int z); @Override public abstract BlockState getBlock(int x, int y, int z);
@Override public final World getWorld() { @Override public final World getWorld() {
@ -132,12 +132,30 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
return this.settingTiles; return this.settingTiles;
} }
@Override public boolean setEntity(Entity entity) {
if (entity.getState() == null || entity.getState().getType() == EntityTypes.PLAYER) {
return false;
}
Location location = entity.getBlockLocation();
LocalChunk chunk = getChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4);
chunk.setEntity(location, entity.getState());
return true;
}
@Override public CuboidRegion getReadRegion() {
return this.readRegion;
}
@Override public void setReadRegion(CuboidRegion readRegion) {
this.readRegion = readRegion;
}
@Override public void regenChunk(int x, int z) { @Override public void regenChunk(int x, int z) {
regen = true; regen = true;
// There will never only be one nullified coordinate pair // There will never only be one nullified coordinate pair
if (regenStart == null) { if (regenStart == null) {
regenStart = new int[]{x, z}; regenStart = new int[] {x, z};
regenEnd = new int[]{x, z}; regenEnd = new int[] {x, z};
return; return;
} }
if (x < regenStart[0]) { if (x < regenStart[0]) {
@ -154,6 +172,14 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
} }
} }
@Override public boolean isUnloadAfter() {
return this.unloadAfter;
}
@Override public void setUnloadAfter(boolean unloadAfter) {
this.unloadAfter = unloadAfter;
}
public int[] getRegenStart() { public int[] getRegenStart() {
return regenStart; return regenStart;
} }
@ -189,7 +215,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
BlockVector2 pair = BlockVector2.at(chunkX, chunkZ); BlockVector2 pair = BlockVector2.at(chunkX, chunkZ);
lastWrappedChunk = this.blockChunks.get(pair); lastWrappedChunk = this.blockChunks.get(pair);
if (lastWrappedChunk == null) { if (lastWrappedChunk == null) {
lastWrappedChunk = this.getLocalChunk(chunkX, chunkZ); lastWrappedChunk = new LocalChunk(this, chunkX, chunkZ);
LocalChunk previous = this.blockChunks.put(pair, lastWrappedChunk); LocalChunk previous = this.blockChunks.put(pair, lastWrappedChunk);
if (previous == null) { if (previous == null) {
return lastWrappedChunk; return lastWrappedChunk;
@ -199,6 +225,4 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
} }
return lastWrappedChunk; return lastWrappedChunk;
} }
} }

View File

@ -30,6 +30,7 @@ import com.google.inject.Inject;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -51,30 +52,32 @@ public class ChunkCoordinatorBuilder {
}; };
private long maxIterationTime = 60; // A little over 1 tick; private long maxIterationTime = 60; // A little over 1 tick;
private int initialBatchSize = 4; private int initialBatchSize = 4;
private boolean unloadAfter = true;
private CuboidRegion readRegion = null;
@Inject @Inject
public ChunkCoordinatorBuilder(@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory) { public ChunkCoordinatorBuilder(@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory) {
this.chunkCoordinatorFactory = chunkCoordinatorFactory; this.chunkCoordinatorFactory = chunkCoordinatorFactory;
} }
@NotNull public ChunkCoordinatorBuilder inWorld(@NotNull final World world) { @Nonnull public ChunkCoordinatorBuilder inWorld(@Nonnull final World world) {
this.world = Preconditions.checkNotNull(world, "World may not be null"); this.world = Preconditions.checkNotNull(world, "World may not be null");
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withChunk(@NotNull final BlockVector2 chunkLocation) { @Nonnull public ChunkCoordinatorBuilder withChunk(@Nonnull final BlockVector2 chunkLocation) {
this.requestedChunks this.requestedChunks
.add(Preconditions.checkNotNull(chunkLocation, "Chunk location may not be null")); .add(Preconditions.checkNotNull(chunkLocation, "Chunk location may not be null"));
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withChunks( @Nonnull public ChunkCoordinatorBuilder withChunks(
@NotNull final Collection<BlockVector2> chunkLocations) { @Nonnull final Collection<BlockVector2> chunkLocations) {
chunkLocations.forEach(this::withChunk); chunkLocations.forEach(this::withChunk);
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withRegion(Location pos1, Location pos2) { @Nonnull public ChunkCoordinatorBuilder withRegion(Location pos1, Location pos2) {
final int p1x = pos1.getX(); final int p1x = pos1.getX();
final int p1z = pos1.getZ(); final int p1z = pos1.getZ();
final int p2x = pos2.getX(); final int p2x = pos2.getX();
@ -95,45 +98,50 @@ public class ChunkCoordinatorBuilder {
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withConsumer( @Nonnull public ChunkCoordinatorBuilder withConsumer(
@NotNull final Consumer<BlockVector2> chunkConsumer) { @Nonnull final Consumer<BlockVector2> chunkConsumer) {
this.chunkConsumer = this.chunkConsumer =
Preconditions.checkNotNull(chunkConsumer, "Chunk consumer may not be null"); Preconditions.checkNotNull(chunkConsumer, "Chunk consumer may not be null");
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withFinalAction(@NotNull final Runnable whenDone) { @Nonnull public ChunkCoordinatorBuilder withFinalAction(@Nonnull final Runnable whenDone) {
this.whenDone = Preconditions.checkNotNull(whenDone, "Final action may not be null"); this.whenDone = Preconditions.checkNotNull(whenDone, "Final action may not be null");
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withMaxIterationTime(final long maxIterationTime) { @Nonnull public ChunkCoordinatorBuilder withMaxIterationTime(final long maxIterationTime) {
Preconditions.checkArgument(maxIterationTime > 0, "Max iteration time must be positive"); Preconditions.checkArgument(maxIterationTime > 0, "Max iteration time must be positive");
this.maxIterationTime = maxIterationTime; this.maxIterationTime = maxIterationTime;
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withInitialBatchSize(final int initialBatchSize) { @Nonnull public ChunkCoordinatorBuilder withInitialBatchSize(final int initialBatchSize) {
Preconditions.checkArgument(initialBatchSize > 0, "Initial batch size must be positive"); Preconditions.checkArgument(initialBatchSize > 0, "Initial batch size must be positive");
this.initialBatchSize = initialBatchSize; this.initialBatchSize = initialBatchSize;
return this; return this;
} }
@NotNull public ChunkCoordinatorBuilder withThrowableConsumer( @Nonnull public ChunkCoordinatorBuilder withThrowableConsumer(
@NotNull final Consumer<Throwable> throwableConsumer) { @Nonnull final Consumer<Throwable> throwableConsumer) {
this.throwableConsumer = this.throwableConsumer =
Preconditions.checkNotNull(throwableConsumer, "Throwable consumer may not be null"); Preconditions.checkNotNull(throwableConsumer, "Throwable consumer may not be null");
return this; return this;
} }
@NotNull public ChunkCoordinator build() { @Nonnull public ChunkCoordinatorBuilder unloadAfter(final boolean unloadAfter) {
this.unloadAfter = unloadAfter;
return this;
}
@Nonnull public ChunkCoordinator build() {
Preconditions.checkNotNull(this.world, "No world was supplied"); Preconditions.checkNotNull(this.world, "No world was supplied");
Preconditions.checkNotNull(this.chunkConsumer, "No chunk consumer was supplied"); Preconditions.checkNotNull(this.chunkConsumer, "No chunk consumer was supplied");
Preconditions.checkNotNull(this.whenDone, "No final action was supplied"); Preconditions.checkNotNull(this.whenDone, "No final action was supplied");
Preconditions.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied"); Preconditions.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied");
return chunkCoordinatorFactory return chunkCoordinatorFactory
.create(this.maxIterationTime, this.initialBatchSize, this.chunkConsumer, this.world, .create(this.maxIterationTime, this.initialBatchSize, this.chunkConsumer, this.world,
this.requestedChunks, this.whenDone, this.throwableConsumer); this.requestedChunks, this.whenDone, this.throwableConsumer, this.unloadAfter);
} }
} }

View File

@ -26,8 +26,10 @@
package com.plotsquared.core.queue; package com.plotsquared.core.queue;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -113,6 +115,13 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
return false; return false;
} }
@Override public boolean setEntity(Entity entity) {
if (parent != null) {
return parent.setEntity(entity);
}
return false;
}
@Override public void regenChunk(int x, int z) { @Override public void regenChunk(int x, int z) {
if (parent != null) { if (parent != null) {
parent.regenChunk(x, z); parent.regenChunk(x, z);
@ -170,4 +179,31 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
parent.setChunkConsumer(consumer); parent.setChunkConsumer(consumer);
} }
} }
@Override public CuboidRegion getReadRegion() {
if (parent != null) {
return parent.getReadRegion();
}
return null;
}
@Override public void setReadRegion(CuboidRegion readRegion) {
if (parent != null) {
parent.setReadRegion(readRegion);
}
}
@Override public boolean isUnloadAfter() {
if (parent != null) {
return parent.isUnloadAfter();
}
return false;
}
@Override public void setUnloadAfter(boolean setUnloadAfter) {
if (parent != null) {
parent.setUnloadAfter(setUnloadAfter);
}
}
} }

View File

@ -26,25 +26,27 @@
package com.plotsquared.core.queue; package com.plotsquared.core.queue;
import com.plotsquared.core.util.ChunkUtil; import com.plotsquared.core.util.ChunkUtil;
import com.plotsquared.core.util.MainUtil;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import java.util.HashMap; import java.util.HashMap;
public class LocalChunk { public class LocalChunk {
private final BasicQueueCoordinator parent; private final QueueCoordinator parent;
private final int x; private final int x;
private final int z; private final int z;
private final BaseBlock[][] baseblocks; private final BaseBlock[][] baseblocks;
private final BiomeType[][] biomes; private final BiomeType[][] biomes;
private final HashMap<BlockVector3, CompoundTag> tiles = new HashMap<>(); private final HashMap<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final HashMap<Location, BaseEntity> entities = new HashMap<>();
public LocalChunk(BasicQueueCoordinator parent, int x, int z) { public LocalChunk(QueueCoordinator parent, int x, int z) {
this.parent = parent; this.parent = parent;
this.x = x; this.x = x;
this.z = z; this.z = z;
@ -52,7 +54,7 @@ public class LocalChunk {
biomes = new BiomeType[16][]; biomes = new BiomeType[16][];
} }
public BasicQueueCoordinator getParent() { public QueueCoordinator getParent() {
return this.parent; return this.parent;
} }
@ -103,4 +105,12 @@ public class LocalChunk {
public void setTile(final int x, final int y, final int z, final CompoundTag tag) { public void setTile(final int x, final int y, final int z, final CompoundTag tag) {
tiles.put(BlockVector3.at(x, y, z), tag); tiles.put(BlockVector3.at(x, y, z), tag);
} }
public void setEntity(Location location, BaseEntity entity) {
this.entities.put(location, entity);
}
public HashMap<Location, BaseEntity> getEntities() {
return this.entities;
}
} }

View File

@ -30,8 +30,10 @@ import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.PatternUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -40,6 +42,7 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
public abstract class QueueCoordinator { public abstract class QueueCoordinator {
@ -108,6 +111,22 @@ public abstract class QueueCoordinator {
public abstract boolean isSettingBiomes(); public abstract boolean isSettingBiomes();
public void addEntities(List<? extends Entity> entities) {
for (Entity e : entities) {
this.setEntity(e);
}
}
public abstract boolean setEntity(Entity entity);
public abstract CuboidRegion getReadRegion();
public abstract void setReadRegion(CuboidRegion readRegion);
public abstract void setUnloadAfter(boolean unloadAfter);
public abstract boolean isUnloadAfter();
public abstract void regenChunk(int x, int z); public abstract void regenChunk(int x, int z);
public abstract World getWorld(); public abstract World getWorld();

View File

@ -28,23 +28,12 @@ package com.plotsquared.core.queue;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
public abstract class QueueProvider { public abstract class QueueProvider {
public static QueueProvider of(final Class<? extends QueueCoordinator> primary, public static QueueProvider of(final Class<? extends QueueCoordinator> primary) {
final Class<? extends QueueCoordinator> fallback) {
return new QueueProvider() { return new QueueProvider() {
private boolean failed = false;
@Override public QueueCoordinator getNewQueue(World world) { @Override public QueueCoordinator getNewQueue(World world) {
if (!failed) {
try { try {
return (QueueCoordinator) primary.getConstructors()[0].newInstance(world); return (QueueCoordinator) primary.getConstructors()[0].newInstance(world);
} catch (Throwable e) {
e.printStackTrace();
failed = true;
}
}
try {
return (QueueCoordinator) fallback.getConstructors()[0].newInstance(world);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -27,7 +27,6 @@ package com.plotsquared.core.util;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal;
@ -98,21 +97,4 @@ public abstract class ChunkManager {
@Deprecated @Deprecated
public abstract CompletableFuture loadChunk(String world, BlockVector2 loc, boolean force); public abstract CompletableFuture loadChunk(String world, BlockVector2 loc, boolean force);
@Deprecated public abstract void unloadChunk(String world, BlockVector2 loc, boolean save);
public Plot hasPlot(String world, BlockVector2 chunk) {
int x1 = chunk.getX() << 4;
int z1 = chunk.getZ() << 4;
int x2 = x1 + 15;
int z2 = z1 + 15;
Location bot = Location.at(world, x1, 0, z1);
Plot plot = bot.getOwnedPlotAbs();
if (plot != null) {
return plot;
}
Location top = Location.at(world, x2, 0, z2);
plot = top.getOwnedPlotAbs();
return plot;
}
} }

View File

@ -25,24 +25,27 @@
*/ */
package com.plotsquared.core.util; package com.plotsquared.core.util;
import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotManager; import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.BasicQueueCoordinator;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.File; import java.io.File;
import java.util.Collection; import java.util.Collection;
@ -55,12 +58,9 @@ public abstract class RegionManager {
LoggerFactory.getLogger("P2/" + RegionManager.class.getSimpleName()); LoggerFactory.getLogger("P2/" + RegionManager.class.getSimpleName());
public static RegionManager manager = null; public static RegionManager manager = null;
private final ChunkManager chunkManager; @Inject private WorldUtil worldUtil;
@Inject private ChunkManager chunkManager;
public RegionManager(@Nonnull final ChunkManager chunkManager, @Nonnull WorldUtil worldUtil, @Inject private GlobalBlockQueue blockQueue;
@Nonnull ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory) {
this.chunkManager = chunkManager;
}
public static BlockVector2 getRegion(Location location) { public static BlockVector2 getRegion(Location location) {
int x = location.getX() >> 9; int x = location.getX() >> 9;
@ -68,46 +68,6 @@ public abstract class RegionManager {
return BlockVector2.at(x, z); return BlockVector2.at(x, z);
} }
public void largeRegionTask(final String world, final CuboidRegion region,
final RunnableVal<BlockVector2> task, final Runnable whenDone) {
TaskManager.runTaskAsync(() -> {
HashSet<BlockVector2> chunks = new HashSet<>();
Set<BlockVector2> mcrs = this.getChunkChunks(world);
for (BlockVector2 mcr : mcrs) {
int bx = mcr.getX() << 9;
int bz = mcr.getZ() << 9;
int tx = bx + 511;
int tz = bz + 511;
if (bx <= region.getMaximumPoint().getX() && tx >= region.getMinimumPoint().getX()
&& bz <= region.getMaximumPoint().getZ() && tz >= region.getMinimumPoint()
.getZ()) {
for (int x = bx >> 4; x <= (tx >> 4); x++) {
int cbx = x << 4;
int ctx = cbx + 15;
if (cbx <= region.getMaximumPoint().getX() && ctx >= region
.getMinimumPoint().getX()) {
for (int z = bz >> 4; z <= (tz >> 4); z++) {
int cbz = z << 4;
int ctz = cbz + 15;
if (cbz <= region.getMaximumPoint().getZ() && ctz >= region
.getMinimumPoint().getZ()) {
chunks.add(BlockVector2.at(x, z));
}
}
}
}
}
}
TaskManager.getPlatformImplementation()
.objectTask(chunks, new RunnableVal<BlockVector2>() {
@Override public void run(BlockVector2 value) {
chunkManager.loadChunk(world, value, false).thenRun(() -> task.run(value));
}
}).thenAccept(ignore -> TaskManager.getPlatformImplementation()
.taskLater(whenDone, TaskTime.ticks(1L)));
});
}
/** /**
* 0 = Entity * 0 = Entity
* 1 = Animal * 1 = Animal
@ -115,9 +75,6 @@ public abstract class RegionManager {
* 3 = Mob * 3 = Mob
* 4 = Boat * 4 = Boat
* 5 = Misc * 5 = Misc
*
* @param plot
* @return
*/ */
public abstract int[] countEntities(Plot plot); public abstract int[] countEntities(Plot plot);
@ -146,10 +103,6 @@ public abstract class RegionManager {
return chunks; return chunks;
} }
public void deleteRegionFiles(String world, Collection<BlockVector2> chunks) {
deleteRegionFiles(world, chunks, null);
}
public void deleteRegionFiles(final String world, final Collection<BlockVector2> chunks, public void deleteRegionFiles(final String world, final Collection<BlockVector2> chunks,
final Runnable whenDone) { final Runnable whenDone) {
TaskManager.runTaskAsync(() -> { TaskManager.runTaskAsync(() -> {
@ -167,16 +120,10 @@ public abstract class RegionManager {
}); });
} }
public boolean setCuboids(final PlotArea area, final Set<CuboidRegion> regions,
final Pattern blocks, int minY, int maxY) {
return setCuboids(area, regions, blocks, minY, maxY, null);
}
public boolean setCuboids(final PlotArea area, final Set<CuboidRegion> regions, public boolean setCuboids(final PlotArea area, final Set<CuboidRegion> regions,
final Pattern blocks, int minY, int maxY, @Nullable QueueCoordinator queue) { final Pattern blocks, int minY, int maxY, @Nullable QueueCoordinator queue) {
boolean enqueue = false; boolean enqueue = false;
if(queue == null) { if (queue == null) {
queue = area.getQueue(); queue = area.getQueue();
enqueue = true; enqueue = true;
} }
@ -209,27 +156,116 @@ public abstract class RegionManager {
/** /**
* Copy a region to a new location (in the same world) * Copy a region to a new location (in the same world)
*/ */
public abstract boolean copyRegion(Location pos1, Location pos2, Location newPos, public boolean copyRegion(final Location pos1, final Location pos2, final Location newPos,
Runnable whenDone); final Runnable whenDone) {
final int relX = newPos.getX() - pos1.getX();
final int relZ = newPos.getZ() - pos1.getZ();
final com.sk89q.worldedit.world.World oldWorld = worldUtil.getWeWorld(pos1.getWorldName());
final com.sk89q.worldedit.world.World newWorld =
worldUtil.getWeWorld(newPos.getWorldName());
final QueueCoordinator copyFrom = blockQueue.getNewQueue(oldWorld);
final BasicQueueCoordinator copyTo =
(BasicQueueCoordinator) blockQueue.getNewQueue(newWorld);
copyFromTo(pos1, pos2, relX, relZ, oldWorld, copyFrom, copyTo, false);
copyFrom.setCompleteTask(copyTo::enqueue);
copyFrom.setReadRegion(new CuboidRegion(BlockVector3.at(pos1.getX(), 0, pos1.getZ()),
BlockVector3.at(pos2.getX(), 0, pos2.getZ())));
copyTo.setCompleteTask(whenDone);
copyFrom.enqueue();
return true;
}
/** /**
* Assumptions:<br> * Assumptions:<br>
* - pos1 and pos2 are in the same plot<br> * - pos1 and pos2 are in the same plot<br>
* It can be harmful to the world if parameters outside this scope are provided * 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(Location pos1, Location pos2, boolean ignoreAugment, public abstract boolean regenerateRegion(Location pos1, Location pos2, boolean ignoreAugment,
Runnable whenDone); Runnable whenDone);
public abstract void clearAllEntities(Location pos1, Location pos2); public abstract void clearAllEntities(Location pos1, Location pos2);
public abstract void swap(Location bot1, Location top1, Location bot2, Location top2, public void swap(Location pos1, Location pos2, Location swapPos, final Runnable whenDone) {
Runnable whenDone); int relX = swapPos.getX() - pos1.getX();
int relZ = swapPos.getZ() - pos1.getZ();
public abstract void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, World world1 = worldUtil.getWeWorld(pos1.getWorldName());
String world, Runnable whenDone); World world2 = worldUtil.getWeWorld(swapPos.getWorldName());
QueueCoordinator fromQueue1 = blockQueue.getNewQueue(world1);
QueueCoordinator fromQueue2 = blockQueue.getNewQueue(world2);
fromQueue1.setUnloadAfter(false);
fromQueue2.setUnloadAfter(false);
fromQueue1.setReadRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()));
fromQueue2.setReadRegion(new CuboidRegion(swapPos.getBlockVector3(), BlockVector3
.at(swapPos.getX() + pos2.getX() - pos1.getX(), 0,
swapPos.getZ() + pos2.getZ() - pos1.getZ())));
QueueCoordinator toQueue1 = blockQueue.getNewQueue(world1);
QueueCoordinator toQueue2 = blockQueue.getNewQueue(world2);
copyFromTo(pos1, pos2, relX, relZ, world1, fromQueue1, toQueue2, true);
copyFromTo(pos1, pos2, relX, relZ, world1, fromQueue2, toQueue1, true);
fromQueue1.setCompleteTask(fromQueue2::enqueue);
fromQueue2.setCompleteTask(toQueue1::enqueue);
toQueue1.setCompleteTask(toQueue2::enqueue);
toQueue2.setCompleteTask(whenDone);
}
private void copyFromTo(Location pos1, Location pos2, int relX, int relZ, World world1,
QueueCoordinator fromQueue, QueueCoordinator toQueue, boolean removeEntities) {
fromQueue.setChunkConsumer(chunk -> {
int cx = chunk.getX();
int cz = chunk.getZ();
int cbx = cx << 4;
int cbz = cz << 4;
int bx = Math.max(pos1.getX() & 15, 0);
int bz = Math.max(pos1.getZ() & 15, 0);
int tx = Math.min(pos2.getX() & 15, 15);
int tz = Math.min(pos2.getZ() & 15, 15);
for (int y = 0; y < 256; y++) {
for (int x = bx; x <= tx; x++) {
for (int z = bz; z <= tz; z++) {
int rx = cbx + x;
int rz = cbz + z;
BlockVector3 loc = BlockVector3.at(rx, y, rz);
toQueue.setBlock(rx + relX, y, rz + relZ, world1.getFullBlock(loc));
toQueue.setBiome(rx + relX, y, rz + relZ, world1.getBiome(loc));
}
}
}
Region region = new CuboidRegion(BlockVector3.at(cbx + bx, 0, cbz + bz),
BlockVector3.at(cbx + tx, 255, cbz + tz));
toQueue.addEntities(world1.getEntities(region));
if (removeEntities) {
for (Entity entity : world1.getEntities(region)) {
entity.remove();
}
}
});
}
public void setBiome(final CuboidRegion region, final int extendBiome, final BiomeType biome,
final String world, final Runnable whenDone) {
Location pos1 = Location.at(world, region.getMinimumPoint().getX() - extendBiome,
region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome);
Location pos2 = Location.at(world, region.getMaximumPoint().getX() + extendBiome,
region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome);
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(world));
final int minX = pos1.getX();
final int minZ = pos1.getZ();
final int maxX = pos2.getX();
final int maxZ = pos2.getZ();
queue.setReadRegion(region);
queue.setChunkConsumer(blockVector2 -> {
final int cx = blockVector2.getX() << 4;
final int cz = blockVector2.getZ() << 4;
WorldUtil
.setBiome(world, Math.max(minX, cx), Math.max(minZ, cz), Math.min(maxX, cx + 15),
Math.min(maxZ, cz + 15), biome);
worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), world);
});
queue.setCompleteTask(whenDone);
queue.enqueue();
}
} }

View File

@ -330,7 +330,8 @@ public abstract class SchematicHandler {
final int bcz = p1z >> 4; final int bcz = p1z >> 4;
final int tcx = p2x >> 4; final int tcx = p2x >> 4;
final int tcz = p2z >> 4; final int tcz = p2z >> 4;
queue.setReadRegion(
new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()));
queue.setChunkConsumer(blockVector2 -> { queue.setChunkConsumer(blockVector2 -> {
int x = blockVector2.getX(); int x = blockVector2.getX();
int z = blockVector2.getZ(); int z = blockVector2.getZ();

View File

@ -81,7 +81,7 @@ subprojects { subproject ->
dependencies { dependencies {
compile group: 'org.json', name: 'json', version: '20200518' compile group: 'org.json', name: 'json', version: '20200518'
implementation("com.sk89q.worldedit:worldedit-core:7.0.0") { implementation("com.sk89q.worldedit:worldedit-core:7.2.0-SNAPSHOT") {
exclude(module: "bukkit-classloader-check") exclude(module: "bukkit-classloader-check")
exclude(module: "mockito-core") exclude(module: "mockito-core")
exclude(module: "dummypermscompat") exclude(module: "dummypermscompat")