mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-06-25 02:04:44 +02:00
Implement progress subscribers
This commit is contained in:
@ -112,7 +112,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
||||
if (chunk == null) {
|
||||
return;
|
||||
}
|
||||
long iterationTime;
|
||||
long[] iterationTime = new long[2];
|
||||
int processedChunks = 0;
|
||||
do {
|
||||
final long start = System.currentTimeMillis();
|
||||
@ -127,8 +127,9 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
|
||||
processedChunks++;
|
||||
final long end = System.currentTimeMillis();
|
||||
// Update iteration time
|
||||
iterationTime = end - start;
|
||||
} while (2 * iterationTime /* last chunk + next chunk */ < this.maxIterationTime && (chunk = availableChunks.poll()) != null);
|
||||
iterationTime[0] = iterationTime[1];
|
||||
iterationTime[1] = end - start;
|
||||
} while (iterationTime[0] + iterationTime[1] < this.maxIterationTime * 2 && (chunk = availableChunks.poll()) != null);
|
||||
if (processedChunks < this.batchSize) {
|
||||
// Adjust batch size based on the amount of processed chunks per tick
|
||||
this.batchSize = processedChunks;
|
||||
|
@ -1,326 +0,0 @@
|
||||
/*
|
||||
* _____ _ _ _____ _
|
||||
* | __ \| | | | / ____| | |
|
||||
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
|
||||
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
|
||||
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
|
||||
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
|
||||
* | |
|
||||
* |_|
|
||||
* PlotSquared plot management system for Minecraft
|
||||
* Copyright (C) 2020 IntellectualSites
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.plotsquared.bukkit.queue;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.plotsquared.bukkit.BukkitPlatform;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Utility that allows for the loading and coordination of chunk actions
|
||||
* <p>
|
||||
* The coordinator takes in collection of chunk coordinates, loads them
|
||||
* and allows the caller to specify a sink for the loaded chunks. The
|
||||
* coordinator will prevent the chunks from being unloaded until the sink
|
||||
* has fully consumed the chunk
|
||||
* <p>
|
||||
* Usage:
|
||||
* <pre>{@code
|
||||
* final ChunkCoordinator chunkCoordinator = ChunkCoordinator.builder()
|
||||
* .inWorld(Objects.requireNonNull(Bukkit.getWorld("world"))).withChunk(BlockVector2.at(0, 0))
|
||||
* .withConsumer(chunk -> System.out.printf("Got chunk %d;%d", chunk.getX(), chunk.getZ()))
|
||||
* .withFinalAction(() -> System.out.println("All chunks have been loaded"))
|
||||
* .withThrowableConsumer(throwable -> System.err.println("Something went wrong... =("))
|
||||
* .withMaxIterationTime(25L)
|
||||
* .build();
|
||||
* chunkCoordinator.subscribeToProgress((coordinator, progress) ->
|
||||
* System.out.printf("Progress: %.1f", progress * 100.0f));
|
||||
* chunkCoordinator.start();
|
||||
* }</pre>
|
||||
*
|
||||
* @author Alexander Söderberg
|
||||
* @see #builder() To create a new coordinator instance
|
||||
*/
|
||||
public final class ChunkCoordinator extends BukkitRunnable {
|
||||
|
||||
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
|
||||
|
||||
private final Queue<BlockVector2> requestedChunks;
|
||||
private final Queue<Chunk> availableChunks;
|
||||
private final long maxIterationTime;
|
||||
private final Plugin plugin;
|
||||
private final Consumer<Chunk> chunkConsumer;
|
||||
private final World world;
|
||||
private final Runnable whenDone;
|
||||
private final Consumer<Throwable> throwableConsumer;
|
||||
private final int totalSize;
|
||||
|
||||
private AtomicInteger expectedSize;
|
||||
private int batchSize;
|
||||
|
||||
private ChunkCoordinator(final long maxIterationTime, final int initialBatchSize,
|
||||
@Nonnull final Consumer<Chunk> chunkConsumer, @Nonnull final World world,
|
||||
@Nonnull final Collection<BlockVector2> requestedChunks, @Nonnull final Runnable whenDone,
|
||||
@Nonnull final Consumer<Throwable> throwableConsumer) {
|
||||
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
|
||||
this.availableChunks = new LinkedBlockingQueue<>();
|
||||
this.totalSize = requestedChunks.size();
|
||||
this.expectedSize = new AtomicInteger(this.totalSize);
|
||||
this.world = world;
|
||||
this.batchSize = initialBatchSize;
|
||||
this.chunkConsumer = chunkConsumer;
|
||||
this.maxIterationTime = maxIterationTime;
|
||||
this.whenDone = whenDone;
|
||||
this.throwableConsumer = throwableConsumer;
|
||||
this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ChunkCoordinator} instance
|
||||
*
|
||||
* @return Coordinator builder instance
|
||||
*/
|
||||
@Nonnull public static ChunkCoordinatorBuilder builder() {
|
||||
return new ChunkCoordinatorBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the coordinator instance
|
||||
*/
|
||||
public void start() {
|
||||
// Request initial batch
|
||||
this.requestBatch();
|
||||
// Wait until next tick to give the chunks a chance to be loaded
|
||||
this.runTaskTimer(this.plugin, 1L, 1L);
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
Chunk chunk = this.availableChunks.poll();
|
||||
if (chunk == null) {
|
||||
return;
|
||||
}
|
||||
long iterationTime;
|
||||
int processedChunks = 0;
|
||||
do {
|
||||
final long start = System.currentTimeMillis();
|
||||
try {
|
||||
this.chunkConsumer.accept(chunk);
|
||||
} catch (final Throwable throwable) {
|
||||
this.throwableConsumer.accept(throwable);
|
||||
}
|
||||
this.freeChunk(chunk);
|
||||
processedChunks++;
|
||||
final long end = System.currentTimeMillis();
|
||||
// Update iteration time
|
||||
iterationTime = end - start;
|
||||
} while (2 * iterationTime /* last chunk + next chunk */ < this.maxIterationTime
|
||||
&& (chunk = availableChunks.poll()) != null);
|
||||
if (processedChunks < this.batchSize) {
|
||||
// Adjust batch size based on the amount of processed chunks per tick
|
||||
this.batchSize = processedChunks;
|
||||
}
|
||||
|
||||
final int expected = this.expectedSize.addAndGet(-processedChunks);
|
||||
|
||||
final float progress = ((float) totalSize - (float) expected) / (float) totalSize;
|
||||
for (final ProgressSubscriber subscriber : this.progressSubscribers) {
|
||||
subscriber.notifyProgress(this, progress);
|
||||
}
|
||||
|
||||
if (expected <= 0) {
|
||||
try {
|
||||
this.whenDone.run();
|
||||
} catch (final Throwable throwable) {
|
||||
this.throwableConsumer.accept(throwable);
|
||||
}
|
||||
this.cancel();
|
||||
} else {
|
||||
if (this.availableChunks.size() < processedChunks) {
|
||||
this.requestBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void requestBatch() {
|
||||
BlockVector2 chunk;
|
||||
for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) {
|
||||
// This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent
|
||||
PaperLib.getChunkAtAsync(this.world, chunk.getX(), chunk.getZ(), true, true)
|
||||
.whenComplete((chunkObject, throwable) -> {
|
||||
if (throwable != null) {
|
||||
throwable.printStackTrace();
|
||||
// We want one less because this couldn't be processed
|
||||
this.expectedSize.decrementAndGet();
|
||||
} else {
|
||||
this.processChunk(chunkObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void processChunk(@Nonnull final Chunk chunk) {
|
||||
if (!chunk.isLoaded()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ()));
|
||||
}
|
||||
chunk.addPluginChunkTicket(this.plugin);
|
||||
this.availableChunks.add(chunk);
|
||||
}
|
||||
|
||||
private void freeChunk(@Nonnull final Chunk chunk) {
|
||||
if (!chunk.isLoaded()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ()));
|
||||
}
|
||||
chunk.removePluginChunkTicket(this.plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of remaining chunks (at the time of the method call)
|
||||
*
|
||||
* @return Snapshot view of remaining chunk count
|
||||
*/
|
||||
public int getRemainingChunks() {
|
||||
return this.expectedSize.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of requested chunks
|
||||
*
|
||||
* @return Requested chunk count
|
||||
*/
|
||||
public int getTotalChunks() {
|
||||
return this.totalSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to coordinator progress updates
|
||||
*
|
||||
* @param subscriber Subscriber
|
||||
*/
|
||||
public void subscribeToProgress(@Nonnull final ChunkCoordinator.ProgressSubscriber subscriber) {
|
||||
this.progressSubscribers.add(subscriber);
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ProgressSubscriber {
|
||||
|
||||
/**
|
||||
* Notify about a progress update in the coordinator
|
||||
*
|
||||
* @param coordinator Coordinator instance that triggered the notification
|
||||
* @param progress Progress in the range [0, 1]
|
||||
*/
|
||||
void notifyProgress(@Nonnull final ChunkCoordinator coordinator, final float progress);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static final class ChunkCoordinatorBuilder {
|
||||
|
||||
private final List<BlockVector2> requestedChunks = new LinkedList<>();
|
||||
private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace;
|
||||
private World world;
|
||||
private Consumer<Chunk> chunkConsumer;
|
||||
private Runnable whenDone = () -> {
|
||||
};
|
||||
private long maxIterationTime = 60; // A little over 1 tick;
|
||||
private int initialBatchSize = 4;
|
||||
|
||||
private ChunkCoordinatorBuilder() {
|
||||
}
|
||||
|
||||
@Nonnull public ChunkCoordinatorBuilder inWorld(@Nonnull final World world) {
|
||||
this.world = Preconditions.checkNotNull(world, "World may not be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ChunkCoordinatorBuilder withChunk(@Nonnull final BlockVector2 chunkLocation) {
|
||||
this.requestedChunks
|
||||
.add(Preconditions.checkNotNull(chunkLocation, "Chunk location may not be null"));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull public ChunkCoordinatorBuilder withChunks(
|
||||
@Nonnull final Collection<BlockVector2> chunkLocations) {
|
||||
chunkLocations.forEach(this::withChunk);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ChunkCoordinatorBuilder withConsumer(@Nonnull final Consumer<Chunk> chunkConsumer) {
|
||||
this.chunkConsumer =
|
||||
Preconditions.checkNotNull(chunkConsumer, "Chunk consumer may not be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull public ChunkCoordinatorBuilder withFinalAction(@Nonnull final Runnable whenDone) {
|
||||
this.whenDone = Preconditions.checkNotNull(whenDone, "Final action may not be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull public ChunkCoordinatorBuilder withMaxIterationTime(final long maxIterationTime) {
|
||||
Preconditions
|
||||
.checkArgument(maxIterationTime > 0, "Max iteration time must be positive");
|
||||
this.maxIterationTime = maxIterationTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull public ChunkCoordinatorBuilder withInitialBatchSize(final int initialBatchSize) {
|
||||
Preconditions
|
||||
.checkArgument(initialBatchSize > 0, "Initial batch size must be positive");
|
||||
this.initialBatchSize = initialBatchSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull public ChunkCoordinatorBuilder withThrowableConsumer(
|
||||
@Nonnull final Consumer<Throwable> throwableConsumer) {
|
||||
this.throwableConsumer =
|
||||
Preconditions.checkNotNull(throwableConsumer, "Throwable consumer may not be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nonnull public ChunkCoordinator build() {
|
||||
Preconditions.checkNotNull(this.world, "No world was supplied");
|
||||
Preconditions.checkNotNull(this.chunkConsumer, "No chunk consumer was supplied");
|
||||
Preconditions.checkNotNull(this.whenDone, "No final action was supplied");
|
||||
Preconditions
|
||||
.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied");
|
||||
return new ChunkCoordinator(this.maxIterationTime, this.initialBatchSize,
|
||||
this.chunkConsumer, this.world, this.requestedChunks, this.whenDone,
|
||||
this.throwableConsumer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -30,6 +30,7 @@ import com.google.inject.Singleton;
|
||||
import com.plotsquared.core.generator.AugmentedUtils;
|
||||
import com.plotsquared.core.location.Location;
|
||||
import com.plotsquared.core.location.PlotLoc;
|
||||
import com.plotsquared.core.player.PlotPlayer;
|
||||
import com.plotsquared.core.plot.Plot;
|
||||
import com.plotsquared.core.plot.PlotArea;
|
||||
import com.plotsquared.core.plot.PlotManager;
|
||||
@ -53,10 +54,9 @@ import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -72,24 +72,21 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
|
||||
@Singleton
|
||||
public class BukkitRegionManager extends RegionManager {
|
||||
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName());
|
||||
private final GlobalBlockQueue blockQueue;
|
||||
|
||||
@Inject
|
||||
public BukkitRegionManager(@Nonnull WorldUtil worldUtil, @Nonnull GlobalBlockQueue blockQueue) {
|
||||
@Inject public BukkitRegionManager(@Nonnull WorldUtil worldUtil, @Nonnull GlobalBlockQueue blockQueue) {
|
||||
super(worldUtil, blockQueue);
|
||||
this.blockQueue = blockQueue;
|
||||
}
|
||||
|
||||
@Override public boolean handleClear(Plot plot, Runnable whenDone, PlotManager manager) {
|
||||
@Override
|
||||
public boolean handleClear(@Nonnull Plot plot, @Nullable Runnable whenDone, @Nonnull PlotManager manager, @Nullable PlotPlayer<?> player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public int[] countEntities(Plot plot) {
|
||||
@Override public int[] countEntities(@Nonnull Plot plot) {
|
||||
int[] existing = (int[]) plot.getMeta("EntityCount");
|
||||
if (existing != null && (System.currentTimeMillis() - (long) plot.getMeta("EntityCountTime")
|
||||
< 1000)) {
|
||||
if (existing != null && (System.currentTimeMillis() - (long) plot.getMeta("EntityCountTime") < 1000)) {
|
||||
return existing;
|
||||
}
|
||||
PlotArea area = plot.getArea();
|
||||
@ -161,8 +158,10 @@ public class BukkitRegionManager extends RegionManager {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override public boolean regenerateRegion(final Location pos1, final Location pos2,
|
||||
final boolean ignoreAugment, final Runnable whenDone) {
|
||||
@Override public boolean regenerateRegion(@Nonnull final Location pos1,
|
||||
@Nonnull final Location pos2,
|
||||
final boolean ignoreAugment,
|
||||
@Nullable final Runnable whenDone) {
|
||||
final BukkitWorld world = new BukkitWorld((World) pos1.getWorld());
|
||||
|
||||
final int p1x = pos1.getX();
|
||||
@ -176,8 +175,7 @@ public class BukkitRegionManager extends RegionManager {
|
||||
|
||||
final QueueCoordinator queue = blockQueue.getNewQueue(world);
|
||||
final QueueCoordinator regenQueue = blockQueue.getNewQueue(world);
|
||||
queue.addReadChunks(
|
||||
new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks());
|
||||
queue.addReadChunks(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks());
|
||||
queue.setChunkConsumer(chunk -> {
|
||||
|
||||
int x = chunk.getX();
|
||||
@ -187,8 +185,7 @@ public class BukkitRegionManager extends RegionManager {
|
||||
int xxt = xxb + 15;
|
||||
int zzt = zzb + 15;
|
||||
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
|
||||
AugmentedUtils
|
||||
.bypass(ignoreAugment, () -> regenQueue.regenChunk(chunk.getX(), chunk.getZ()));
|
||||
AugmentedUtils.bypass(ignoreAugment, () -> regenQueue.regenChunk(chunk.getX(), chunk.getZ()));
|
||||
return;
|
||||
}
|
||||
boolean checkX1 = false;
|
||||
@ -250,41 +247,37 @@ public class BukkitRegionManager extends RegionManager {
|
||||
if (checkX2 && checkZ2) {
|
||||
map.saveRegion(world, xxt2, xxt, zzt2, zzt); //
|
||||
}
|
||||
CuboidRegion currentPlotClear =
|
||||
RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
|
||||
map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z),
|
||||
currentPlotClear);
|
||||
AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager
|
||||
.setChunkInPlotArea(null, new RunnableVal<ScopedQueueCoordinator>() {
|
||||
@Override public void run(ScopedQueueCoordinator value) {
|
||||
Location min = value.getMin();
|
||||
int bx = min.getX();
|
||||
int bz = min.getZ();
|
||||
for (int x1 = 0; x1 < 16; x1++) {
|
||||
for (int z1 = 0; z1 < 16; z1++) {
|
||||
PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
|
||||
BaseBlock[] ids = map.allBlocks.get(plotLoc);
|
||||
if (ids != null) {
|
||||
for (int y = 0; y < Math.min(128, ids.length); y++) {
|
||||
BaseBlock id = ids[y];
|
||||
if (id != null) {
|
||||
value.setBlock(x1, y, z1, id);
|
||||
} else {
|
||||
value.setBlock(x1, y, z1,
|
||||
BlockTypes.AIR.getDefaultState());
|
||||
}
|
||||
CuboidRegion currentPlotClear = RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
|
||||
map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z), currentPlotClear);
|
||||
AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager.setChunkInPlotArea(null, new RunnableVal<ScopedQueueCoordinator>() {
|
||||
@Override public void run(ScopedQueueCoordinator value) {
|
||||
Location min = value.getMin();
|
||||
int bx = min.getX();
|
||||
int bz = min.getZ();
|
||||
for (int x1 = 0; x1 < 16; x1++) {
|
||||
for (int z1 = 0; z1 < 16; z1++) {
|
||||
PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
|
||||
BaseBlock[] ids = map.allBlocks.get(plotLoc);
|
||||
if (ids != null) {
|
||||
for (int y = 0; y < Math.min(128, ids.length); y++) {
|
||||
BaseBlock id = ids[y];
|
||||
if (id != null) {
|
||||
value.setBlock(x1, y, z1, id);
|
||||
} else {
|
||||
value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState());
|
||||
}
|
||||
for (int y = Math.min(128, ids.length); y < ids.length; y++) {
|
||||
BaseBlock id = ids[y];
|
||||
if (id != null) {
|
||||
value.setBlock(x1, y, z1, id);
|
||||
}
|
||||
}
|
||||
for (int y = Math.min(128, ids.length); y < ids.length; y++) {
|
||||
BaseBlock id = ids[y];
|
||||
if (id != null) {
|
||||
value.setBlock(x1, y, z1, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, world.getName(), chunk));
|
||||
}
|
||||
}, world.getName(), chunk));
|
||||
//map.restoreBlocks(worldObj, 0, 0);
|
||||
map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0);
|
||||
});
|
||||
@ -294,7 +287,7 @@ public class BukkitRegionManager extends RegionManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public void clearAllEntities(Location pos1, Location pos2) {
|
||||
@Override public void clearAllEntities(@Nonnull Location pos1, @Nonnull Location pos2) {
|
||||
String world = pos1.getWorldName();
|
||||
|
||||
final World bukkitWorld = BukkitUtil.getWorld(world);
|
||||
@ -312,8 +305,7 @@ public class BukkitRegionManager extends RegionManager {
|
||||
for (Entity entity : entities) {
|
||||
if (!(entity instanceof Player)) {
|
||||
org.bukkit.Location location = entity.getLocation();
|
||||
if (location.getX() >= bx && location.getX() <= tx && location.getZ() >= bz
|
||||
&& location.getZ() <= tz) {
|
||||
if (location.getX() >= bx && location.getX() <= tx && location.getZ() >= bz && location.getZ() <= tz) {
|
||||
if (entity.hasMetadata("ps-tmp-teleport")) {
|
||||
continue;
|
||||
}
|
||||
@ -323,17 +315,16 @@ public class BukkitRegionManager extends RegionManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void count(int[] count, Entity entity) {
|
||||
final com.sk89q.worldedit.world.entity.EntityType entityType =
|
||||
BukkitAdapter.adapt(entity.getType());
|
||||
private void count(int[] count, @Nonnull 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)) {
|
||||
} 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)) {
|
||||
} 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)) {
|
||||
|
Reference in New Issue
Block a user