Merge pull request #2743 from IntellectualSites/features/v5/async-load

Prevent synchronous chunk loading whenever possible
This commit is contained in:
Alexander Söderberg 2020-04-09 15:09:18 +02:00 committed by GitHub
commit 7c25c60252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 923 additions and 528 deletions

View File

@ -20,6 +20,7 @@ import com.github.intellectualsites.plotsquared.bukkit.util.BukkitTaskManager;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil; import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.bukkit.util.Metrics; import com.github.intellectualsites.plotsquared.bukkit.util.Metrics;
import com.github.intellectualsites.plotsquared.bukkit.util.SetGenCB; import com.github.intellectualsites.plotsquared.bukkit.util.SetGenCB;
import com.github.intellectualsites.plotsquared.bukkit.util.UpdateUtility;
import com.github.intellectualsites.plotsquared.bukkit.util.block.BukkitLocalQueue; import com.github.intellectualsites.plotsquared.bukkit.util.block.BukkitLocalQueue;
import com.github.intellectualsites.plotsquared.bukkit.uuid.DefaultUUIDWrapper; import com.github.intellectualsites.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
import com.github.intellectualsites.plotsquared.bukkit.uuid.FileUUIDHandler; import com.github.intellectualsites.plotsquared.bukkit.uuid.FileUUIDHandler;
@ -37,10 +38,9 @@ import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
import com.github.intellectualsites.plotsquared.plot.generator.HybridGen; import com.github.intellectualsites.plotsquared.plot.generator.HybridGen;
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils; import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator; import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator;
import com.github.intellectualsites.plotsquared.plot.listener.PlotListener;
import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotAreaTerrainType;
import com.github.intellectualsites.plotsquared.plot.object.PlotAreaType;
import com.github.intellectualsites.plotsquared.plot.object.PlotId; import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.SetupObject; import com.github.intellectualsites.plotsquared.plot.object.SetupObject;
@ -49,8 +49,21 @@ import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManag
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SingleWorldGenerator; import com.github.intellectualsites.plotsquared.plot.object.worlds.SingleWorldGenerator;
import com.github.intellectualsites.plotsquared.plot.util.*; import com.github.intellectualsites.plotsquared.plot.util.ChatManager;
import com.github.intellectualsites.plotsquared.bukkit.util.UpdateUtility; import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
import com.github.intellectualsites.plotsquared.plot.util.ConsoleColors;
import com.github.intellectualsites.plotsquared.plot.util.EconHandler;
import com.github.intellectualsites.plotsquared.plot.util.InventoryUtil;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.PremiumVerification;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils;
import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
import com.github.intellectualsites.plotsquared.plot.util.SetupUtils;
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandlerImplementation;
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider; import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider;
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper; import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
@ -586,6 +599,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
final PlayerEvents main = new PlayerEvents(); final PlayerEvents main = new PlayerEvents();
getServer().getPluginManager().registerEvents(main, this); getServer().getPluginManager().registerEvents(main, this);
getServer().getPluginManager().registerEvents(new EntitySpawnListener(), this); getServer().getPluginManager().registerEvents(new EntitySpawnListener(), this);
PlotListener.startRunnable();
} }
@Override public void registerForceFieldEvents() { @Override public void registerForceFieldEvents() {

View File

@ -27,6 +27,6 @@ public class BukkitAugmentedGenerator extends BlockPopulator {
@Override @Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) { public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) {
AugmentedUtils.generate(world.getName(), source.getX(), source.getZ(), null); AugmentedUtils.generate(source, world.getName(), source.getX(), source.getZ(), null);
} }
} }

View File

@ -776,7 +776,7 @@ public class PlayerEvents extends PlotListener implements Listener {
// to is identical to the plot's home location, and untrusted-visit is true // to is identical to the plot's home location, and untrusted-visit is true
// i.e. untrusted-visit can override deny-teleport // i.e. untrusted-visit can override deny-teleport
// this is acceptable, because otherwise it wouldn't make sense to have both flags set // this is acceptable, because otherwise it wouldn't make sense to have both flags set
if (!result && !(plot.getFlag(UntrustedVisitFlag.class) && plot.getHome() if (!result && !(plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous()
.equals(BukkitUtil.getLocationFull(to)))) { .equals(BukkitUtil.getLocationFull(to)))) {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
Captions.PERMISSION_ADMIN_ENTRY_DENIED); Captions.PERMISSION_ADMIN_ENTRY_DENIED);
@ -2353,6 +2353,7 @@ public class PlayerEvents extends PlotListener implements Listener {
TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName()); TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName());
PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer());
pp.unregister(); pp.unregister();
PlotListener.logout(pp.getUUID());
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)

View File

@ -162,7 +162,7 @@ public class Placeholders extends PlaceholderExpansion {
if (pl.getCurrentPlot() == null) { if (pl.getCurrentPlot() == null) {
return ""; return "";
} }
return plot.getBiome() + ""; return plot.getBiomeSynchronous() + "";
} }
default: default:
break; break;

View File

@ -1,5 +1,6 @@
package com.github.intellectualsites.plotsquared.bukkit.util; package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.BukkitMain;
import com.github.intellectualsites.plotsquared.bukkit.object.entity.EntityWrapper; import com.github.intellectualsites.plotsquared.bukkit.object.entity.EntityWrapper;
import com.github.intellectualsites.plotsquared.bukkit.object.entity.ReplicatingEntityWrapper; import com.github.intellectualsites.plotsquared.bukkit.object.entity.ReplicatingEntityWrapper;
import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.PlotSquared;
@ -43,6 +44,7 @@ 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.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -114,9 +116,28 @@ public class BukkitChunkManager extends ChunkManager {
@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);
for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) { if (Bukkit.isPrimaryThread()) {
BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5); for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) {
chunks.add(loc); BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5);
chunks.add(loc);
}
} else {
final Semaphore semaphore = new Semaphore(1);
try {
PlotSquared.debug("Attempting to make an asynchronous call to getLoadedChunks."
+ " Will halt the calling thread until completed.");
semaphore.acquire();
Bukkit.getScheduler().runTask(BukkitMain.getPlugin(BukkitMain.class), () -> {
for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) {
BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5);
chunks.add(loc);
}
semaphore.release();
});
semaphore.acquireUninterruptibly();
} catch (final Exception e) {
e.printStackTrace();
}
} }
return chunks; return chunks;
} }
@ -285,111 +306,112 @@ public class BukkitChunkManager extends ChunkManager {
int zzb = z << 4; int zzb = z << 4;
int xxt = xxb + 15; int xxt = xxb + 15;
int zzt = zzb + 15; int zzt = zzb + 15;
Chunk chunkObj = worldObj.getChunkAt(x, z); PaperLib.getChunkAtAsync(worldObj, x, z, false).thenAccept(chunkObj -> {
if (!chunkObj.load(false)) { if (chunkObj == null) {
continue; return;
} }
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false); final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
AugmentedUtils.bypass(ignoreAugment,
() -> queue.regenChunkSafe(chunk.getX(), chunk.getZ()));
return;
}
boolean checkX1 = false;
int xxb2;
if (x == bcx) {
xxb2 = p1x - 1;
checkX1 = true;
} else {
xxb2 = xxb;
}
boolean checkX2 = false;
int xxt2;
if (x == tcx) {
xxt2 = p2x + 1;
checkX2 = true;
} else {
xxt2 = xxt;
}
boolean checkZ1 = false;
int zzb2;
if (z == bcz) {
zzb2 = p1z - 1;
checkZ1 = true;
} else {
zzb2 = zzb;
}
boolean checkZ2 = false;
int zzt2;
if (z == tcz) {
zzt2 = p2z + 1;
checkZ2 = true;
} else {
zzt2 = zzt;
}
final ContentMap map = new ContentMap();
if (checkX1) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); //
}
if (checkX2) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); //
}
if (checkZ1) {
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); //
}
if (checkZ2) {
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); //
}
if (checkX1 && checkZ1) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); //
}
if (checkX2 && checkZ1) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ?
}
if (checkX1 && checkZ2) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ?
}
if (checkX2 && checkZ2) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); //
}
CuboidRegion currentPlotClear =
RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
map.saveEntitiesOut(chunkObj, currentPlotClear);
AugmentedUtils.bypass(ignoreAugment, AugmentedUtils.bypass(ignoreAugment,
() -> queue.regenChunkSafe(chunk.getX(), chunk.getZ())); () -> setChunkInPlotArea(null, new RunnableVal<ScopedLocalBlockQueue>() {
continue; @Override public void run(ScopedLocalBlockQueue value) {
} Location min = value.getMin();
boolean checkX1 = false; int bx = min.getX();
int bz = min.getZ();
int xxb2; for (int x1 = 0; x1 < 16; x1++) {
for (int z1 = 0; z1 < 16; z1++) {
if (x == bcx) { PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
xxb2 = p1x - 1; BaseBlock[] ids = map.allBlocks.get(plotLoc);
checkX1 = true; if (ids != null) {
} else { for (int y = 0; y < Math.min(128, ids.length); y++) {
xxb2 = xxb; BaseBlock id = ids[y];
} if (id != null) {
boolean checkX2 = false; value.setBlock(x1, y, z1, id);
int xxt2; } else {
if (x == tcx) { value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState());
xxt2 = p2x + 1; }
checkX2 = true;
} else {
xxt2 = xxt;
}
boolean checkZ1 = false;
int zzb2;
if (z == bcz) {
zzb2 = p1z - 1;
checkZ1 = true;
} else {
zzb2 = zzb;
}
boolean checkZ2 = false;
int zzt2;
if (z == tcz) {
zzt2 = p2z + 1;
checkZ2 = true;
} else {
zzt2 = zzt;
}
final ContentMap map = new ContentMap();
if (checkX1) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); //
}
if (checkX2) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); //
}
if (checkZ1) {
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); //
}
if (checkZ2) {
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); //
}
if (checkX1 && checkZ1) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); //
}
if (checkX2 && checkZ1) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ?
}
if (checkX1 && checkZ2) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ?
}
if (checkX2 && checkZ2) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); //
}
CuboidRegion currentPlotClear =
RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
map.saveEntitiesOut(chunkObj, currentPlotClear);
AugmentedUtils.bypass(ignoreAugment,
() -> setChunkInPlotArea(null, new RunnableVal<ScopedLocalBlockQueue>() {
@Override public void run(ScopedLocalBlockQueue 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);
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); }
} }
} }
} }
} }
} }
} }, world, chunk));
}, world, chunk)); //map.restoreBlocks(worldObj, 0, 0);
//map.restoreBlocks(worldObj, 0, 0); map.restoreEntities(worldObj, 0, 0);
map.restoreEntities(worldObj, 0, 0); });
} }
if (!chunks.isEmpty()) { if (!chunks.isEmpty()) {
TaskManager.runTaskLater(this, 1); TaskManager.runTaskLater(this, 1);

View File

@ -1,5 +1,6 @@
package com.github.intellectualsites.plotsquared.bukkit.util; package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.BukkitMain;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer; import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.config.Captions;
@ -7,7 +8,6 @@ import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.object.schematic.PlotItem;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.MathMan; import com.github.intellectualsites.plotsquared.plot.util.MathMan;
import com.github.intellectualsites.plotsquared.plot.util.StringComparison; import com.github.intellectualsites.plotsquared.plot.util.StringComparison;
@ -20,8 +20,10 @@ import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.regions.CuboidRegion; 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.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import io.papermc.lib.PaperLib;
import lombok.NonNull; import lombok.NonNull;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.World; import org.bukkit.World;
@ -33,18 +35,17 @@ import org.bukkit.block.data.Directional;
import org.bukkit.block.data.type.WallSign; import org.bukkit.block.data.type.WallSign;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.UUID;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
@SuppressWarnings({"unused", "WeakerAccess"}) @SuppressWarnings({"unused", "WeakerAccess"})
@ -104,17 +105,6 @@ public class BukkitUtil extends WorldUtil {
return getPlot(player.getLocation()); return getPlot(player.getLocation());
} }
/**
* Get home location.
*
* @param plot Plot that you want to get the location for
* @return plot bottom location
* @see Plot
*/
public static org.bukkit.Location getHomeLocation(Plot plot) {
return BukkitUtil.getLocation(plot.getHome());
}
/** /**
* Get the PlotPlayer for an offline player. * Get the PlotPlayer for an offline player.
* *
@ -219,7 +209,6 @@ public class BukkitUtil extends WorldUtil {
* *
* @param player the recipient of the message * @param player the recipient of the message
* @param caption the message * @param caption the message
* @see MainUtil#sendMessage(com.github.intellectualsites.plotsquared.commands.CommandCaller, Captions, String...)
*/ */
public static void sendMessage(Player player, Captions caption) { public static void sendMessage(Player player, Captions caption) {
MainUtil.sendMessage(BukkitUtil.getPlayer(player), caption); MainUtil.sendMessage(BukkitUtil.getPlayer(player), caption);
@ -303,11 +292,43 @@ public class BukkitUtil extends WorldUtil {
return getWorld(worldName) != null; return getWorld(worldName) != null;
} }
@Override public BiomeType getBiome(String world, int x, int z) { @Override public void getBiome(String world, int x, int z, final Consumer<BiomeType> result) {
ensureLoaded(world, x, z, chunk ->
result.accept(BukkitAdapter.adapt(getWorld(world).getBiome(x, z))));
}
@Override public BiomeType getBiomeSynchronous(String world, int x, int z) {
return BukkitAdapter.adapt(getWorld(world).getBiome(x, z)); return BukkitAdapter.adapt(getWorld(world).getBiome(x, z));
} }
@Override public int getHighestBlock(@NonNull final String world, final int x, final int z) { @Override public void getHighestBlock(@NonNull final String world, final int x, final int z,
final IntConsumer result) {
ensureLoaded(world, x, z, chunk -> {
final World bukkitWorld = getWorld(world);
// Skip top and bottom block
int air = 1;
for (int y = bukkitWorld.getMaxHeight() - 1; y >= 0; y--) {
Block block = bukkitWorld.getBlockAt(x, y, z);
Material type = block.getType();
if (type.isSolid()) {
if (air > 1) {
result.accept(y);
return;
}
air = 0;
} else {
if (block.isLiquid()) {
result.accept(y);
return;
}
air++;
}
}
result.accept(bukkitWorld.getMaxHeight() - 1);
});
}
@Override public int getHighestBlockSynchronous(String world, int x, int z) {
final World bukkitWorld = getWorld(world); final World bukkitWorld = getWorld(world);
// Skip top and bottom block // Skip top and bottom block
int air = 1; int air = 1;
@ -329,7 +350,17 @@ public class BukkitUtil extends WorldUtil {
return bukkitWorld.getMaxHeight() - 1; return bukkitWorld.getMaxHeight() - 1;
} }
@Override @Nullable public String[] getSign(@NonNull final Location location) { @Override public void getSign(@NonNull final Location location, final Consumer<String[]> result) {
ensureLoaded(location, chunk -> {
final Block block = chunk.getWorld().getBlockAt(getLocation(location));
if (block.getState() instanceof Sign) {
Sign sign = (Sign) block.getState();
result.accept(sign.getLines());
}
});
}
@Override @Nullable public String[] getSignSynchronous(@NonNull final Location location) {
Block block = getWorld(location.getWorld()) Block block = getWorld(location.getWorld())
.getBlockAt(location.getX(), location.getY(), location.getZ()); .getBlockAt(location.getX(), location.getY(), location.getZ());
return TaskManager.IMP.sync(new RunnableVal<String[]>() { return TaskManager.IMP.sync(new RunnableVal<String[]>() {
@ -365,60 +396,42 @@ public class BukkitUtil extends WorldUtil {
@Override @SuppressWarnings("deprecation") @Override @SuppressWarnings("deprecation")
public void setSign(@NonNull final String worldName, final int x, final int y, final int z, public void setSign(@NonNull final String worldName, final int x, final int y, final int z,
@NonNull final String[] lines) { @NonNull final String[] lines) {
final World world = getWorld(worldName); ensureLoaded(worldName, x, z, chunk -> {
final Block block = world.getBlockAt(x, y, z); final World world = getWorld(worldName);
// block.setType(Material.AIR); final Block block = world.getBlockAt(x, y, z);
final Material type = block.getType(); // block.setType(Material.AIR);
if (type != Material.LEGACY_SIGN && type != Material.LEGACY_WALL_SIGN) { final Material type = block.getType();
BlockFace facing = BlockFace.EAST; if (type != Material.LEGACY_SIGN && type != Material.LEGACY_WALL_SIGN) {
if (world.getBlockAt(x, y, z + 1).getType().isSolid()) { BlockFace facing = BlockFace.EAST;
facing = BlockFace.NORTH; if (world.getBlockAt(x, y, z + 1).getType().isSolid()) {
} else if (world.getBlockAt(x + 1, y, z).getType().isSolid()) { facing = BlockFace.NORTH;
facing = BlockFace.WEST; } else if (world.getBlockAt(x + 1, y, z).getType().isSolid()) {
} else if (world.getBlockAt(x, y, z - 1).getType().isSolid()) { facing = BlockFace.WEST;
facing = BlockFace.SOUTH; } else if (world.getBlockAt(x, y, z - 1).getType().isSolid()) {
facing = BlockFace.SOUTH;
}
if (PlotSquared.get().IMP.getServerVersion()[1] == 13) {
block.setType(Material.valueOf("WALL_SIGN"), false);
} else {
block.setType(Material.valueOf("OAK_WALL_SIGN"), false);
}
if (!(block.getBlockData() instanceof WallSign)) {
PlotSquared.debug(block.getBlockData().getAsString());
throw new RuntimeException("Something went wrong generating a sign");
}
final Directional sign = (Directional) block.getBlockData();
sign.setFacing(facing);
block.setBlockData(sign, false);
} }
if (PlotSquared.get().IMP.getServerVersion()[1] == 13) { final org.bukkit.block.BlockState blockstate = block.getState();
block.setType(Material.valueOf("WALL_SIGN"), false); if (blockstate instanceof Sign) {
} else { final Sign sign = (Sign) blockstate;
block.setType(Material.valueOf("OAK_WALL_SIGN"), false); for (int i = 0; i < lines.length; i++) {
sign.setLine(i, lines[i]);
}
sign.update(true);
} }
if (!(block.getBlockData() instanceof WallSign)) { });
PlotSquared.debug(block.getBlockData().getAsString());
throw new RuntimeException("Something went wrong generating a sign");
}
final Directional sign = (Directional) block.getBlockData();
sign.setFacing(facing);
block.setBlockData(sign, false);
}
final org.bukkit.block.BlockState blockstate = block.getState();
if (blockstate instanceof Sign) {
final Sign sign = (Sign) blockstate;
for (int i = 0; i < lines.length; i++) {
sign.setLine(i, lines[i]);
}
sign.update(true);
}
}
@Override
public boolean addItems(@NonNull final String worldName, @NonNull final PlotItem items) {
final World world = getWorld(worldName);
final Block block = world.getBlockAt(items.x, items.y, items.z);
final org.bukkit.block.BlockState state = block.getState();
if (state instanceof InventoryHolder) {
InventoryHolder holder = (InventoryHolder) state;
Inventory inv = holder.getInventory();
for (int i = 0; i < items.types.length; i++) {
// ItemStack item = new ItemStack(LegacyMappings.fromLegacyId(items.id[i]).getMaterial(), items.amount[i], items.data[i]);
ItemStack item =
new ItemStack(BukkitAdapter.adapt(items.types[i]), items.amount[i]);
inv.addItem(item);
}
state.update(true);
return true;
}
return false;
} }
@Override public boolean isBlockSolid(@NonNull final BlockState block) { @Override public boolean isBlockSolid(@NonNull final BlockState block) {
@ -471,7 +484,15 @@ public class BukkitUtil extends WorldUtil {
return new BukkitWorld(Bukkit.getWorld(world)); return new BukkitWorld(Bukkit.getWorld(world));
} }
@Override public BlockState getBlock(@NonNull final Location location) { @Override public void getBlock(@NonNull final Location location, final Consumer<BlockState> result) {
ensureLoaded(location, chunk -> {
final World world = getWorld(location.getWorld());
final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ());
result.accept(BukkitAdapter.asBlockType(block.getType()).getDefaultState());
});
}
@Override public BlockState getBlockSynchronous(@NonNull final Location location) {
final World world = getWorld(location.getWorld()); final World world = getWorld(location.getWorld());
final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ()); final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ());
return BukkitAdapter.asBlockType(block.getType()).getDefaultState(); return BukkitAdapter.asBlockType(block.getType()).getDefaultState();
@ -496,4 +517,24 @@ public class BukkitUtil extends WorldUtil {
@Override public void setFoodLevel(PlotPlayer player, int foodLevel) { @Override public void setFoodLevel(PlotPlayer player, int foodLevel) {
Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel); Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel);
} }
private static void ensureLoaded(final String world, final int x, final int z, final Consumer<Chunk> chunkConsumer) {
PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true).thenAccept(chunk ->
ensureMainThread(chunkConsumer, chunk));
}
private static void ensureLoaded(final Location location, final Consumer<Chunk> chunkConsumer) {
PaperLib.getChunkAtAsync(getLocation(location), true).thenAccept(chunk ->
ensureMainThread(chunkConsumer, chunk));
}
private static <T> void ensureMainThread(final Consumer<T> consumer, final T value) {
if (Bukkit.isPrimaryThread()) {
consumer.accept(value);
} else {
Bukkit.getScheduler().runTask(BukkitMain.getPlugin(BukkitMain.class), () ->
consumer.accept(value));
}
}
} }

View File

@ -12,9 +12,11 @@ import java.util.UUID;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.callConstructor; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.callConstructor;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.callMethod; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.callMethod;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getCbClass; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getCbClass;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getField;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getNmsClass; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getNmsClass;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getUtilClass; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getUtilClass;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeConstructor; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeConstructor;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeField;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeMethod; import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.makeMethod;
public class OfflinePlayerUtil { public class OfflinePlayerUtil {
@ -67,11 +69,26 @@ public class OfflinePlayerUtil {
return callConstructor(c, worldServer); return callConstructor(c, worldServer);
} }
public static Object getWorldServerNew() {
Object server = getMinecraftServer();
Class<?> minecraftServerClass = getNmsClass("MinecraftServer");
Class<?> dimensionManager = getNmsClass("DimensionManager");
Object overworld = getField(makeField(dimensionManager, "OVERWORLD"), null);
Method getWorldServer = makeMethod(minecraftServerClass, "getWorldServer", dimensionManager);
return callMethod(getWorldServer, server, overworld);
}
private static Object getWorldServer() { private static Object getWorldServer() {
Object server = getMinecraftServer(); Object server = getMinecraftServer();
Class<?> minecraftServerClass = getNmsClass("MinecraftServer"); Class<?> minecraftServerClass = getNmsClass("MinecraftServer");
Method getWorldServer = makeMethod(minecraftServerClass, "getWorldServer", int.class); Method getWorldServer = makeMethod(minecraftServerClass, "getWorldServer", int.class);
return callMethod(getWorldServer, server, 0); Object o;
try {
o = callMethod(getWorldServer, server, 0);
} catch (final RuntimeException e) {
o = getWorldServerNew();
}
return o;
} }
//NMS Utils //NMS Utils

View File

@ -18,6 +18,7 @@ import com.sk89q.worldedit.world.block.BlockState;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import lombok.NonNull; import lombok.NonNull;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
@ -25,6 +26,7 @@ import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
public class BukkitLocalQueue extends BasicLocalBlockQueue { public class BukkitLocalQueue extends BasicLocalBlockQueue {
@ -88,7 +90,7 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue {
@Override public final void setComponents(LocalChunk lc) @Override public final void setComponents(LocalChunk lc)
throws ExecutionException, InterruptedException { throws ExecutionException, InterruptedException {
setBaseBlocks(lc); setBaseBlocks(lc);
if (setBiome()) { if (setBiome() && lc.biomes != null) {
setBiomes(lc); setBiomes(lc);
} }
} }
@ -98,40 +100,59 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue {
if (worldObj == null) { if (worldObj == null) {
throw new NullPointerException("World cannot be null."); throw new NullPointerException("World cannot be null.");
} }
PaperLib.getChunkAtAsync(worldObj, localChunk.getX(), localChunk.getZ(), true) final Consumer<Chunk> chunkConsumer = chunk -> {
.thenAccept(chunk -> { for (int layer = 0; layer < localChunk.baseblocks.length; layer++) {
for (int layer = 0; layer < localChunk.baseblocks.length; layer++) { BaseBlock[] blocksLayer = localChunk.baseblocks[layer];
BaseBlock[] blocksLayer = localChunk.baseblocks[layer]; if (blocksLayer != null) {
if (blocksLayer != null) { for (int j = 0; j < blocksLayer.length; j++) {
for (int j = 0; j < blocksLayer.length; j++) { if (blocksLayer[j] != null) {
if (blocksLayer[j] != null) { BaseBlock block = blocksLayer[j];
BaseBlock block = blocksLayer[j]; int x = MainUtil.x_loc[layer][j];
int x = MainUtil.x_loc[layer][j]; int y = MainUtil.y_loc[layer][j];
int y = MainUtil.y_loc[layer][j]; int z = MainUtil.z_loc[layer][j];
int z = MainUtil.z_loc[layer][j];
BlockData blockData = BukkitAdapter.adapt(block); BlockData blockData = BukkitAdapter.adapt(block);
Block existing = chunk.getBlock(x, y, z); Block existing = chunk.getBlock(x, y, z);
if (BukkitBlockUtil.get(existing).equals(block) && existing final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData());
.getBlockData().matches(blockData)) { if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing
continue; .getBlockData().matches(blockData)) {
} continue;
}
existing.setType(BukkitAdapter.adapt(block.getBlockType()), false); existing.setType(BukkitAdapter.adapt(block.getBlockType()), false);
existing.setBlockData(blockData, false); existing.setBlockData(blockData, false);
if (block.hasNbtData()) { if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData(); CompoundTag tag = block.getNbtData();
StateWrapper sw = new StateWrapper(tag); StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(worldObj.getName(), existing.getX(), sw.restoreTag(worldObj.getName(), existing.getX(),
existing.getY(), existing.getZ()); existing.getY(), existing.getZ());
}
} }
} }
} }
} }
}); }
};
if (isForceSync()) {
chunkConsumer.accept(getChunk(worldObj, localChunk));
} else {
PaperLib.getChunkAtAsync(worldObj, localChunk.getX(), localChunk.getZ(), true).thenAccept(chunkConsumer);
}
}
private Chunk getChunk(final World world, final LocalChunk localChunk) {
Chunk chunk = null;
if (this.getChunkObject() != null && this.getChunkObject() instanceof Chunk) {
chunk = (Chunk) this.getChunkObject();
}
if (chunk == null) {
chunk = world.getChunkAt(localChunk.getX(), localChunk.getZ());
}
if (!chunk.isLoaded()) {
chunk.load(true);
}
return chunk;
} }
private void setMaterial(@NonNull final BlockState plotBlock, @NonNull final Block block) { private void setMaterial(@NonNull final BlockState plotBlock, @NonNull final Block block) {
@ -148,7 +169,10 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue {
if (worldObj == null) { if (worldObj == null) {
throw new NullPointerException("World cannot be null."); throw new NullPointerException("World cannot be null.");
} }
PaperLib.getChunkAtAsync(worldObj, lc.getX(), lc.getZ(), true).thenAccept(chunk -> { if (lc.biomes == null) {
throw new NullPointerException("Biomes cannot be null.");
}
final Consumer<Chunk> chunkConsumer = chunk -> {
for (int x = 0; x < lc.biomes.length; x++) { for (int x = 0; x < lc.biomes.length; x++) {
BiomeType[] biomeZ = lc.biomes[x]; BiomeType[] biomeZ = lc.biomes[x];
if (biomeZ != null) { if (biomeZ != null) {
@ -157,13 +181,18 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue {
BiomeType biomeType = biomeZ[z]; BiomeType biomeType = biomeZ[z];
Biome biome = BukkitAdapter.adapt(biomeType); Biome biome = BukkitAdapter.adapt(biomeType);
worldObj worldObj.setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z,
.setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, biome); biome);
} }
} }
} }
} }
}); };
if (this.isForceSync()) {
chunkConsumer.accept(getChunk(worldObj, lc));
} else {
PaperLib.getChunkAtAsync(worldObj, lc.getX(), lc.getZ(), true).thenAccept(chunkConsumer);
}
} }
} }

View File

@ -147,7 +147,7 @@ public class Area extends SubCommand {
ChunkManager.largeRegionTask(world, region, ChunkManager.largeRegionTask(world, region,
new RunnableVal<BlockVector2>() { new RunnableVal<BlockVector2>() {
@Override public void run(BlockVector2 value) { @Override public void run(BlockVector2 value) {
AugmentedUtils.generate(world, value.getX(), AugmentedUtils.generate(null, world, value.getX(),
value.getZ(), null); value.getZ(), null);
} }
}, null); }, null);
@ -445,7 +445,7 @@ public class Area extends SubCommand {
new RunnableVal<BlockVector2>() { new RunnableVal<BlockVector2>() {
@Override public void run(BlockVector2 value) { @Override public void run(BlockVector2 value) {
AugmentedUtils AugmentedUtils
.generate(area.getWorldName(), value.getX(), value.getZ(), null); .generate(null, area.getWorldName(), value.getX(), value.getZ(), null);
} }
}, () -> player.sendMessage("Regen complete")); }, () -> player.sendMessage("Regen complete"));
return true; return true;
@ -471,16 +471,18 @@ public class Area extends SubCommand {
Location center; Location center;
if (area.getType() != PlotAreaType.PARTIAL) { if (area.getType() != PlotAreaType.PARTIAL) {
center = WorldUtil.IMP.getSpawn(area.getWorldName()); center = WorldUtil.IMP.getSpawn(area.getWorldName());
player.teleport(center, TeleportCause.COMMAND);
} else { } else {
CuboidRegion region = area.getRegion(); CuboidRegion region = area.getRegion();
center = new Location(area.getWorldName(), region.getMinimumPoint().getX() center = new Location(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()) / 2);
center.setY(1 + WorldUtil.IMP WorldUtil.IMP.getHighestBlock(area.getWorldName(), center.getX(), center.getZ(), y -> {
.getHighestBlock(area.getWorldName(), center.getX(), center.getZ())); center.setY(1 + y);
player.teleport(center, TeleportCause.COMMAND);
});
} }
player.teleport(center, TeleportCause.COMMAND);
return true; return true;
case "delete": case "delete":
case "remove": case "remove":

View File

@ -8,9 +8,7 @@ import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc; import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.events.PlayerAutoPlotEvent; import com.github.intellectualsites.plotsquared.plot.events.PlayerAutoPlotEvent;
import com.github.intellectualsites.plotsquared.plot.events.PlotAutoMergeEvent; import com.github.intellectualsites.plotsquared.plot.events.PlotAutoMergeEvent;
import com.github.intellectualsites.plotsquared.plot.events.PlotMergeEvent;
import com.github.intellectualsites.plotsquared.plot.events.Result; import com.github.intellectualsites.plotsquared.plot.events.Result;
import com.github.intellectualsites.plotsquared.plot.object.Direction;
import com.github.intellectualsites.plotsquared.plot.object.Expression; import com.github.intellectualsites.plotsquared.plot.object.Expression;
import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
@ -19,6 +17,7 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.object.TeleportCause; import com.github.intellectualsites.plotsquared.plot.object.TeleportCause;
import com.github.intellectualsites.plotsquared.plot.util.AutoClaimFinishTask;
import com.github.intellectualsites.plotsquared.plot.util.EconHandler; import com.github.intellectualsites.plotsquared.plot.util.EconHandler;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.Permissions; import com.github.intellectualsites.plotsquared.plot.util.Permissions;
@ -42,7 +41,7 @@ public class Auto extends SubCommand {
return id.getNextId(step); return id.getNextId(step);
} }
private static boolean checkAllowedPlots(PlotPlayer player, PlotArea plotarea, public static boolean checkAllowedPlots(PlotPlayer player, PlotArea plotarea,
@Nullable Integer allowedPlots, int sizeX, int sizeZ) { @Nullable Integer allowedPlots, int sizeX, int sizeZ) {
if (allowedPlots == null) { if (allowedPlots == null) {
allowedPlots = player.getAllowedPlots(); allowedPlots = player.getAllowedPlots();
@ -94,7 +93,7 @@ public class Auto extends SubCommand {
final String schematic) { final String schematic) {
Set<Plot> plots = player.getPlots(); Set<Plot> plots = player.getPlots();
if (!plots.isEmpty()) { if (!plots.isEmpty()) {
plots.iterator().next().teleportPlayer(player, TeleportCause.COMMAND); plots.iterator().next().teleportPlayer(player, TeleportCause.COMMAND, result -> {});
} else { } else {
autoClaimSafe(player, area, start, schematic); autoClaimSafe(player, area, start, schematic);
} }
@ -126,31 +125,7 @@ public class Auto extends SubCommand {
player.setMeta(Auto.class.getName(), true); player.setMeta(Auto.class.getName(), true);
autoClaimFromDatabase(player, area, start, new RunnableVal<Plot>() { autoClaimFromDatabase(player, area, start, new RunnableVal<Plot>() {
@Override public void run(final Plot plot) { @Override public void run(final Plot plot) {
TaskManager.IMP.sync(new RunnableVal<Object>() { TaskManager.IMP.sync(new AutoClaimFinishTask(player, plot, area, allowedPlots, schematic));
@Override public void run(Object ignore) {
player.deleteMeta(Auto.class.getName());
if (plot == null) {
MainUtil.sendMessage(player, Captions.NO_FREE_PLOTS);
return;
}
if (checkAllowedPlots(player, area, allowedPlots, 1, 1)) {
plot.claim(player, true, schematic, false);
if (area.isAutoMerge()) {
PlotMergeEvent event = PlotSquared.get().getEventDispatcher()
.callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player);
if (event.getEventResult() == Result.DENY) {
sendMessage(player, Captions.EVENT_DENIED, "Auto merge");
} else {
plot.autoMerge(event.getDir(), event.getMax(), player.getUUID(),
true);
}
}
} else {
DBFunc.delete(plot);
}
}
});
} }
}); });
} }

View File

@ -555,7 +555,7 @@ public class Cluster extends SubCommand {
return false; return false;
} }
} }
player.teleport(cluster.getHome(), TeleportCause.COMMAND); cluster.getHome(home -> player.teleport(home, TeleportCause.COMMAND));
return MainUtil.sendMessage(player, Captions.CLUSTER_TELEPORTING); return MainUtil.sendMessage(player, Captions.CLUSTER_TELEPORTING);
} }
case "i": case "i":

View File

@ -4,8 +4,10 @@ import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.StringMan; import com.github.intellectualsites.plotsquared.plot.util.StringMan;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import java.util.Map; import java.util.Map;
@ -23,9 +25,16 @@ public class Debug extends SubCommand {
MainUtil.sendMessage(player, MainUtil.sendMessage(player,
"Key: " + meta.getKey() + " Value: " + meta.getValue().toString() + " , "); "Key: " + meta.getKey() + " Value: " + meta.getValue().toString() + " , ");
} }
;
} }
} }
if (args.length > 0 && "loadedchunks".equalsIgnoreCase(args[0])) {
final long start = System.currentTimeMillis();
MainUtil.sendMessage(player, "Fetching loaded chunks...");
TaskManager.runTaskAsync(() -> MainUtil.sendMessage(player,"Loaded chunks: " +
ChunkManager.manager.getChunkChunks(player.getLocation().getWorld()).size() + "(" + (System.currentTimeMillis() - start) + "ms) using thread: " +
Thread.currentThread().getName()));
return true;
}
if ((args.length > 0) && args[0].equalsIgnoreCase("msg")) { if ((args.length > 0) && args[0].equalsIgnoreCase("msg")) {
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
for (Captions caption : Captions.values()) { for (Captions caption : Captions.values()) {

View File

@ -71,7 +71,7 @@ public class DebugClaimTest extends SubCommand {
Location location = manager.getSignLoc(plot); Location location = manager.getSignLoc(plot);
BlockVector2 chunk = BlockVector2.at(location.getX() >> 4, location.getZ() >> 4); BlockVector2 chunk = BlockVector2.at(location.getX() >> 4, location.getZ() >> 4);
ChunkManager.manager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> { ChunkManager.manager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> {
String[] lines = WorldUtil.IMP.getSign(location); String[] lines = WorldUtil.IMP.getSignSynchronous(location);
if (lines != null) { if (lines != null) {
String line = lines[2]; String line = lines[2];
if (line != null && line.length() > 2) { if (line != null && line.length() > 2) {

View File

@ -47,7 +47,7 @@ public class Like extends SubCommand {
for (final Plot plot : plots) { for (final Plot plot : plots) {
if ((!Settings.Done.REQUIRED_FOR_RATINGS || DoneFlag.isDone(plot)) && plot if ((!Settings.Done.REQUIRED_FOR_RATINGS || DoneFlag.isDone(plot)) && plot
.isBasePlot() && (!plot.getLikes().containsKey(uuid))) { .isBasePlot() && (!plot.getLikes().containsKey(uuid))) {
plot.teleportPlayer(player, TeleportCause.COMMAND); plot.teleportPlayer(player, TeleportCause.COMMAND, result -> {});
MainUtil.sendMessage(player, Captions.RATE_THIS); MainUtil.sendMessage(player, Captions.RATE_THIS);
return true; return true;
} }

View File

@ -208,7 +208,7 @@ public class MainCommand extends Command {
.equals(area) || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN) .equals(area) || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN)
|| Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_SUDO_AREA)) || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_SUDO_AREA))
&& !newPlot.isDenied(player.getUUID())) { && !newPlot.isDenied(player.getUUID())) {
Location newLoc = newPlot.getCenter(); Location newLoc = newPlot.getCenterSynchronous();
if (player.canTeleport(newLoc)) { if (player.canTeleport(newLoc)) {
// Save meta // Save meta
location = player.getMeta(PlotPlayer.META_LOCATION); location = player.getMeta(PlotPlayer.META_LOCATION);

View File

@ -24,7 +24,7 @@ public class Middle extends SubCommand {
if (plot == null) { if (plot == null) {
return sendMessage(player, Captions.NOT_IN_PLOT); return sendMessage(player, Captions.NOT_IN_PLOT);
} }
player.teleport(plot.getCenter(), TeleportCause.COMMAND); plot.getCenter(center -> player.teleport(center, TeleportCause.COMMAND));
return true; return true;
} }
} }

View File

@ -61,7 +61,7 @@ public class Rate extends SubCommand {
if ((!Settings.Done.REQUIRED_FOR_RATINGS || DoneFlag.isDone(p)) && p if ((!Settings.Done.REQUIRED_FOR_RATINGS || DoneFlag.isDone(p)) && p
.isBasePlot() && (!p.getRatings().containsKey(uuid)) && !p .isBasePlot() && (!p.getRatings().containsKey(uuid)) && !p
.isAdded(uuid)) { .isAdded(uuid)) {
p.teleportPlayer(player, TeleportCause.COMMAND); p.teleportPlayer(player, TeleportCause.COMMAND, result -> {});
MainUtil.sendMessage(player, Captions.RATE_THIS); MainUtil.sendMessage(player, Captions.RATE_THIS);
return true; return true;
} }

View File

@ -32,7 +32,7 @@ public class Target extends SubCommand {
if (StringMan.isEqualIgnoreCaseToAny(args[0], "near", "nearest")) { if (StringMan.isEqualIgnoreCaseToAny(args[0], "near", "nearest")) {
int distance = Integer.MAX_VALUE; int distance = Integer.MAX_VALUE;
for (Plot plot : PlotSquared.get().getPlots(location.getWorld())) { for (Plot plot : PlotSquared.get().getPlots(location.getWorld())) {
double current = plot.getCenter().getEuclideanDistanceSquared(location); double current = plot.getCenterSynchronous().getEuclideanDistanceSquared(location);
if (current < distance) { if (current < distance) {
distance = (int) current; distance = (int) current;
target = plot; target = plot;
@ -45,7 +45,7 @@ public class Target extends SubCommand {
} else if ((target = MainUtil.getPlotFromString(player, args[0], true)) == null) { } else if ((target = MainUtil.getPlotFromString(player, args[0], true)) == null) {
return false; return false;
} }
player.setCompassTarget(target.getCenter()); target.getCenter(player::setCompassTarget);
MainUtil.sendMessage(player, Captions.COMPASS_TARGET); MainUtil.sendMessage(player, Captions.COMPASS_TARGET);
return true; return true;
} }

View File

@ -153,13 +153,14 @@ public class Visit extends Command {
return CompletableFuture.completedFuture(false); return CompletableFuture.completedFuture(false);
} }
} }
confirm.run(this, () -> { confirm.run(this, () ->
if (plot.teleportPlayer(player, TeleportCause.COMMAND)) { plot.teleportPlayer(player, TeleportCause.COMMAND, result -> {
if (result) {
whenDone.run(Visit.this, CommandResult.SUCCESS); whenDone.run(Visit.this, CommandResult.SUCCESS);
} else { } else {
whenDone.run(Visit.this, CommandResult.FAILURE); whenDone.run(Visit.this, CommandResult.FAILURE);
} }
}, () -> whenDone.run(Visit.this, CommandResult.FAILURE)); }), () -> whenDone.run(Visit.this, CommandResult.FAILURE));
return CompletableFuture.completedFuture(true); return CompletableFuture.completedFuture(true);
} }

View File

@ -352,5 +352,7 @@ public class Settings extends Config {
public static boolean EXTERNAL_PLACEHOLDERS = true; public static boolean EXTERNAL_PLACEHOLDERS = true;
@Comment("Make road regeneration persistent across restarts") public static boolean @Comment("Make road regeneration persistent across restarts") public static boolean
PERSISTENT_ROAD_REGEN = false; PERSISTENT_ROAD_REGEN = false;
@Comment("Try to guess plot owners from sign data. This may decrease server performance")
public static boolean GUESS_PLOT_OWNER = false;
} }
} }

View File

@ -69,6 +69,7 @@ import com.github.intellectualsites.plotsquared.plot.flags.implementations.Untru
import com.github.intellectualsites.plotsquared.plot.flags.implementations.UseFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.UseFlag;
import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleBreakFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleBreakFlag;
import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleCapFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleCapFlag;
import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehiclePlaceFlag;
import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleUseFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VehicleUseFlag;
import com.github.intellectualsites.plotsquared.plot.flags.implementations.VillagerInteractFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VillagerInteractFlag;
import com.github.intellectualsites.plotsquared.plot.flags.implementations.VineGrowFlag; import com.github.intellectualsites.plotsquared.plot.flags.implementations.VineGrowFlag;
@ -138,6 +139,7 @@ public final class GlobalFlagContainer extends FlagContainer {
this.addFlag(TamedAttackFlag.TAMED_ATTACK_FALSE); this.addFlag(TamedAttackFlag.TAMED_ATTACK_FALSE);
this.addFlag(TamedInteractFlag.TAMED_INTERACT_FALSE); this.addFlag(TamedInteractFlag.TAMED_INTERACT_FALSE);
this.addFlag(VehicleBreakFlag.VEHICLE_BREAK_FALSE); this.addFlag(VehicleBreakFlag.VEHICLE_BREAK_FALSE);
this.addFlag(VehiclePlaceFlag.VEHICLE_PLACE_FALSE);
this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE); this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE);
this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE); this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE);
this.addFlag(VineGrowFlag.VINE_GROW_TRUE); this.addFlag(VineGrowFlag.VINE_GROW_TRUE);

View File

@ -11,11 +11,15 @@ import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue; import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.block.ScopedLocalBlockQueue; import com.github.intellectualsites.plotsquared.plot.util.block.ScopedLocalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.world.RegionUtil; import com.github.intellectualsites.plotsquared.plot.util.world.RegionUtil;
import com.sk89q.worldedit.function.pattern.Pattern;
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.biome.BiomeType;
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.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set; import java.util.Set;
@ -29,7 +33,7 @@ public class AugmentedUtils {
enabled = true; enabled = true;
} }
public static boolean generate(@NotNull final String world, final int chunkX, final int chunkZ, public static boolean generate(@Nullable Object chunkObject, @NotNull final String world, final int chunkX, final int chunkZ,
LocalBlockQueue queue) { LocalBlockQueue queue) {
if (!enabled) { if (!enabled) {
return false; return false;
@ -54,6 +58,7 @@ public class AugmentedUtils {
// Mask // Mask
if (queue == null) { if (queue == null) {
queue = GlobalBlockQueue.IMP.getNewQueue(world, false); queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
queue.setChunkObject(chunkObject);
} }
LocalBlockQueue primaryMask; LocalBlockQueue primaryMask;
// coordinates // coordinates
@ -102,7 +107,7 @@ public class AugmentedUtils {
for (int y = 1; y < 128; y++) { for (int y = 1; y < 128; y++) {
queue.setBlock(rx, y, rz, air); queue.setBlock(rx, y, rz, air);
} }
canPlace[x][z] = can; canPlace[x][z] = true;
has = true; has = true;
} }
} }
@ -119,6 +124,24 @@ public class AugmentedUtils {
return false; return false;
} }
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
try {
if (canPlace[x - blockX][z - blockZ]) {
return super.setBlock(x, y, z, id);
}
} catch (final Exception e) {
PlotSquared.debug(String.format("Failed to set block at: %d;%d;%d (to = %s) with offset %d;%d."
+ " Translated to: %d;%d", x, y, z, id, blockX, blockZ, x - blockX, z - blockZ));
throw e;
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, Pattern pattern) {
final BlockVector3 blockVector3 = BlockVector3.at(x + blockX, y, z + blockZ);
return this.setBlock(x, y, z, pattern.apply(blockVector3));
}
@Override public boolean setBiome(int x, int y, BiomeType biome) { @Override public boolean setBiome(int x, int y, BiomeType biome) {
return super.setBiome(x, y, biome); return super.setBiome(x, y, biome);
} }
@ -134,13 +157,18 @@ public class AugmentedUtils {
} }
toReturn = true; toReturn = true;
} }
ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(secondaryMask, primaryMask.setChunkObject(chunkObject);
new Location(area.getWorldName(), blockX, 0, blockZ), primaryMask.setForceSync(true);
new Location(area.getWorldName(), blockX + 15, 255, blockZ + 15)); secondaryMask.setChunkObject(chunkObject);
secondaryMask.setForceSync(true);
ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(secondaryMask, new Location(world, blockX, 0, blockZ),
new Location(world, blockX + 15, 255, blockZ + 15));
generator.generateChunk(scoped, area); generator.generateChunk(scoped, area);
generator.populateChunk(scoped, area); generator.populateChunk(scoped, area);
} }
if (queue != null) { if (queue != null) {
queue.setForceSync(true);
queue.flush(); queue.flush();
} }
return toReturn; return toReturn;

View File

@ -5,6 +5,7 @@ import com.github.intellectualsites.plotsquared.plot.object.BlockBucket;
import com.github.intellectualsites.plotsquared.plot.object.Direction; import com.github.intellectualsites.plotsquared.plot.object.Direction;
import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotAreaTerrainType;
import com.github.intellectualsites.plotsquared.plot.object.PlotId; import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.plot.util.MathMan; import com.github.intellectualsites.plotsquared.plot.util.MathMan;
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue; import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
@ -150,6 +151,12 @@ public class ClassicPlotManager extends SquarePlotManager {
if (classicPlotWorld.ROAD_WIDTH == 0) { if (classicPlotWorld.ROAD_WIDTH == 0) {
return false; return false;
} }
// When using full vanilla generation, don't generate the walls
if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) {
// Return true because the method actually did what it's intended to in this case,
// which is absolutely nothing
return true;
}
Plot plot = classicPlotWorld.getPlotAbs(plotId); Plot plot = classicPlotWorld.getPlotAbs(plotId);
Location bottom = plot.getBottomAbs(); Location bottom = plot.getBottomAbs();
Location top = plot.getExtendedTopAbs(); Location top = plot.getExtendedTopAbs();
@ -206,6 +213,12 @@ public class ClassicPlotManager extends SquarePlotManager {
if (classicPlotWorld.ROAD_WIDTH == 0) { if (classicPlotWorld.ROAD_WIDTH == 0) {
return false; return false;
} }
// When using full vanilla generation, don't generate the walls
if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) {
// Return true because the method actually did what it's intended to in this case,
// which is absolutely nothing
return true;
}
Plot plot = classicPlotWorld.getPlotAbs(plotId); Plot plot = classicPlotWorld.getPlotAbs(plotId);
Location bot = plot.getExtendedBottomAbs() Location bot = plot.getExtendedBottomAbs()
.subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0, .subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0,
@ -253,6 +266,12 @@ public class ClassicPlotManager extends SquarePlotManager {
if (classicPlotWorld.ROAD_WIDTH == 0) { if (classicPlotWorld.ROAD_WIDTH == 0) {
return false; return false;
} }
// When using full vanilla generation, don't generate the walls
if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) {
// Return true because the method actually did what it's intended to in this case,
// which is absolutely nothing
return true;
}
Plot plot = classicPlotWorld.getPlotAbs(plotId); Plot plot = classicPlotWorld.getPlotAbs(plotId);
Location bot = plot.getExtendedBottomAbs() Location bot = plot.getExtendedBottomAbs()
.subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0, .subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0,

View File

@ -179,8 +179,8 @@ public class HybridPlotManager extends ClassicPlotManager {
Location pos2 = plot.getExtendedTopAbs(); Location pos2 = plot.getExtendedTopAbs();
// If augmented // If augmented
final boolean canRegen = final boolean canRegen =
(hybridPlotWorld.getType() == PlotAreaType.NORMAL) (hybridPlotWorld.getType() == PlotAreaType.AUGMENTED)
&& (hybridPlotWorld.getTerrain() == PlotAreaTerrainType.NONE) && REGENERATIVE_CLEAR; && (hybridPlotWorld.getTerrain() != PlotAreaTerrainType.NONE) && REGENERATIVE_CLEAR;
// The component blocks // The component blocks
final Pattern plotfloor = hybridPlotWorld.TOP_BLOCK.toPattern(); final Pattern plotfloor = hybridPlotWorld.TOP_BLOCK.toPattern();
final Pattern filling = hybridPlotWorld.MAIN_BLOCK.toPattern(); final Pattern filling = hybridPlotWorld.MAIN_BLOCK.toPattern();

View File

@ -363,7 +363,7 @@ public abstract class HybridUtils {
} }
HybridUtils.UPDATE = true; HybridUtils.UPDATE = true;
Set<BlockVector2> regions = new HashSet<>(); Set<BlockVector2> regions = new HashSet<>();
regions.add(ChunkManager.getRegion(plot.getCenter())); regions.add(ChunkManager.getRegion(plot.getCenterSynchronous()));
return scheduleRoadUpdate(plot.getArea(), regions, extend, new HashSet<>()); return scheduleRoadUpdate(plot.getArea(), regions, extend, new HashSet<>());
} }

View File

@ -66,6 +66,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.github.intellectualsites.plotsquared.plot.commands.SubCommand.sendMessage; import static com.github.intellectualsites.plotsquared.plot.commands.SubCommand.sendMessage;
@ -1041,10 +1042,6 @@ public class Plot {
if (!isLoaded()) { if (!isLoaded()) {
return; return;
} }
if (!PlotSquared.get().isMainThread(Thread.currentThread())) {
TaskManager.runTask(() -> Plot.this.setSign(name));
return;
}
PlotManager manager = this.area.getPlotManager(); PlotManager manager = this.area.getPlotManager();
if (this.area.allowSigns()) { if (this.area.allowSigns()) {
Location location = manager.getSignLoc(this); Location location = manager.getSignLoc(this);
@ -1057,9 +1054,7 @@ public class Plot {
"%plr%", name), "%plr%", name),
Captions.OWNER_SIGN_LINE_4.formatted().replaceAll("%id%", id).replaceAll( Captions.OWNER_SIGN_LINE_4.formatted().replaceAll("%id%", id).replaceAll(
"%plr%", name)}; "%plr%", name)};
WorldUtil.IMP WorldUtil.IMP.setSign(this.getWorldName(), location.getX(), location.getY(), location.getZ(), lines);
.setSign(this.getWorldName(), location.getX(), location.getY(), location.getZ(),
lines);
} }
} }
@ -1325,7 +1320,32 @@ public class Plot {
return this.unlinkPlot(true, true); return this.unlinkPlot(true, true);
} }
public Location getCenter() { public void getCenter(final Consumer<Location> result) {
Location[] corners = getCorners();
Location top = corners[0];
Location bot = corners[1];
Location location =
new Location(this.getWorldName(), MathMan.average(bot.getX(), top.getX()),
MathMan.average(bot.getY(), top.getY()), MathMan.average(bot.getZ(), top.getZ()));
if (!isLoaded()) {
result.accept(location);
return;
}
WorldUtil.IMP.getHighestBlock(getWorldName(), location.getX(), location.getZ(), y -> {
int height = y;
if (area.allowSigns()) {
height = Math.max(y, getManager().getSignLoc(this).getY());
}
location.setY(1 + height);
result.accept(location);
});
}
/**
* @deprecated May cause synchronous chunk loads
*/
@Deprecated
public Location getCenterSynchronous() {
Location[] corners = getCorners(); Location[] corners = getCorners();
Location top = corners[0]; Location top = corners[0];
Location bot = corners[1]; Location bot = corners[1];
@ -1335,7 +1355,7 @@ public class Plot {
if (!isLoaded()) { if (!isLoaded()) {
return location; return location;
} }
int y = WorldUtil.IMP.getHighestBlock(getWorldName(), location.getX(), location.getZ()); int y = WorldUtil.IMP.getHighestBlockSynchronous(getWorldName(), location.getX(), location.getZ());
if (area.allowSigns()) { if (area.allowSigns()) {
y = Math.max(y, getManager().getSignLoc(this).getY()); y = Math.max(y, getManager().getSignLoc(this).getY());
} }
@ -1343,28 +1363,54 @@ public class Plot {
return location; return location;
} }
public Location getSide() { /**
* @deprecated May cause synchronous chunk loads
*/
@Deprecated
public Location getSideSynchronous() {
CuboidRegion largest = getLargestRegion(); CuboidRegion largest = getLargestRegion();
int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1) int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1)
+ largest.getMinimumPoint().getX(); + largest.getMinimumPoint().getX();
int z = largest.getMinimumPoint().getZ() - 1; int z = largest.getMinimumPoint().getZ() - 1;
PlotManager manager = getManager(); PlotManager manager = getManager();
int y = isLoaded() ? WorldUtil.IMP.getHighestBlock(getWorldName(), x, z) : 62; int y = isLoaded() ? WorldUtil.IMP.getHighestBlockSynchronous(getWorldName(), x, z) : 62;
if (area.allowSigns() && (y <= 0 || y >= 255)) { if (area.allowSigns() && (y <= 0 || y >= 255)) {
y = Math.max(y, manager.getSignLoc(this).getY() - 1); y = Math.max(y, manager.getSignLoc(this).getY() - 1);
} }
return new Location(getWorldName(), x, y + 1, z); return new Location(getWorldName(), x, y + 1, z);
} }
public void getSide(Consumer<Location> result) {
CuboidRegion largest = getLargestRegion();
int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1)
+ largest.getMinimumPoint().getX();
int z = largest.getMinimumPoint().getZ() - 1;
PlotManager manager = getManager();
if (isLoaded()) {
WorldUtil.IMP.getHighestBlock(getWorldName(), x, z, y -> {
int height = y;
if (area.allowSigns() && (y <= 0 || y >= 255)) {
height = Math.max(y, manager.getSignLoc(this).getY() - 1);
}
result.accept(new Location(getWorldName(), x, height + 1, z));
});
} else {
int y = 62;
if (area.allowSigns()) {
y = Math.max(y, manager.getSignLoc(this).getY() - 1);
}
result.accept(new Location(getWorldName(), x, y + 1, z));
}
}
/** /**
* Return the home location for the plot * @deprecated May cause synchronous chunk loading
*
* @return Home location
*/ */
public Location getHome() { @Deprecated
public Location getHomeSynchronous() {
BlockLoc home = this.getPosition(); BlockLoc home = this.getPosition();
if (home == null || home.getX() == 0 && home.getZ() == 0) { if (home == null || home.getX() == 0 && home.getZ() == 0) {
return this.getDefaultHome(true); return this.getDefaultHomeSynchronous(true);
} else { } else {
Location bottom = this.getBottomAbs(); Location bottom = this.getBottomAbs();
Location location = new Location(bottom.getWorld(), bottom.getX() + home.getX(), Location location = new Location(bottom.getWorld(), bottom.getX() + home.getX(),
@ -1373,15 +1419,46 @@ public class Plot {
if (!isLoaded()) { if (!isLoaded()) {
return location; return location;
} }
if (!WorldUtil.IMP.getBlock(location).getBlockType().getMaterial().isAir()) { if (!WorldUtil.IMP.getBlockSynchronous(location).getBlockType().getMaterial().isAir()) {
location.setY(Math.max(1 + WorldUtil.IMP location.setY(Math.max(1 + WorldUtil.IMP
.getHighestBlock(this.getWorldName(), location.getX(), location.getZ()), .getHighestBlockSynchronous(this.getWorldName(), location.getX(), location.getZ()),
bottom.getY())); bottom.getY()));
} }
return location; return location;
} }
} }
/**
* Return the home location for the plot
*/
public void getHome(final Consumer<Location> result) {
BlockLoc home = this.getPosition();
if (home == null || home.getX() == 0 && home.getZ() == 0) {
this.getDefaultHome(result);
} else {
Location bottom = this.getBottomAbs();
Location location = new Location(bottom.getWorld(), bottom.getX() + home.getX(),
bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(),
home.getPitch());
if (!isLoaded()) {
result.accept(location);
return;
}
WorldUtil.IMP.getBlock(location, block -> {
if (!block.getBlockType().getMaterial().isAir()) {
WorldUtil.IMP
.getHighestBlock(this.getWorldName(), location.getX(), location.getZ(), y -> {
location.setY(Math.max(1 + y,
bottom.getY()));
result.accept(location);
});
} else {
result.accept(location);
}
});
}
}
/** /**
* Sets the home location * Sets the home location
* *
@ -1406,11 +1483,15 @@ public class Plot {
* *
* @return Location * @return Location
*/ */
public Location getDefaultHome() { public void getDefaultHome(Consumer<Location> result) {
return getDefaultHome(false); getDefaultHome(false, result);
} }
public Location getDefaultHome(boolean member) { /**
* @deprecated May cause synchronous chunk loads
*/
@Deprecated
public Location getDefaultHomeSynchronous(final boolean member) {
Plot plot = this.getBasePlot(false); Plot plot = this.getBasePlot(false);
PlotLoc loc = member ? area.getDefaultHome() : area.getNonmemberHome(); PlotLoc loc = member ? area.getDefaultHome() : area.getNonmemberHome();
if (loc != null) { if (loc != null) {
@ -1430,12 +1511,47 @@ public class Plot {
z = bot.getZ() + loc.getZ(); z = bot.getZ() + loc.getZ();
} }
int y = loc.getY() < 1 ? int y = loc.getY() < 1 ?
(isLoaded() ? WorldUtil.IMP.getHighestBlock(plot.getWorldName(), x, z) + 1 : 63) : (isLoaded() ? WorldUtil.IMP.getHighestBlockSynchronous(plot.getWorldName(), x, z) + 1 : 63) :
loc.getY(); loc.getY();
return new Location(plot.getWorldName(), x, y, z); return new Location(plot.getWorldName(), x, y, z);
} }
// Side // Side
return plot.getSide(); return plot.getSideSynchronous();
}
public void getDefaultHome(boolean member, Consumer<Location> result) {
Plot plot = this.getBasePlot(false);
PlotLoc loc = member ? area.getDefaultHome() : area.getNonmemberHome();
if (loc != null) {
int x;
int z;
if (loc.getX() == Integer.MAX_VALUE && loc.getZ() == Integer.MAX_VALUE) {
// center
CuboidRegion largest = plot.getLargestRegion();
x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX()
>> 1) + largest.getMinimumPoint().getX();
z = (largest.getMaximumPoint().getZ() >> 1) - (largest.getMinimumPoint().getZ()
>> 1) + largest.getMinimumPoint().getZ();
} else {
// specific
Location bot = plot.getBottomAbs();
x = bot.getX() + loc.getX();
z = bot.getZ() + loc.getZ();
}
if (loc.getY() < 1) {
if (isLoaded()) {
WorldUtil.IMP.getHighestBlock(plot.getWorldName(), x, z, y ->
result.accept(new Location(plot.getWorldName(), x, y + 1, z)));
} else {
result.accept(new Location(plot.getWorldName(), x, 63, z));
}
} else {
result.accept(new Location(plot.getWorldName(), x, loc.getY(), z));
}
return;
}
// Side
plot.getSide(result);
} }
public double getVolume() { public double getVolume() {
@ -1611,7 +1727,7 @@ public class Plot {
setSign(player.getName()); setSign(player.getName());
MainUtil.sendMessage(player, Captions.CLAIMED); MainUtil.sendMessage(player, Captions.CLAIMED);
if (teleport && Settings.Teleport.ON_CLAIM) { if (teleport && Settings.Teleport.ON_CLAIM) {
teleportPlayer(player, TeleportCause.COMMAND); teleportPlayer(player, TeleportCause.COMMAND, result -> {});
} }
PlotArea plotworld = getArea(); PlotArea plotworld = getArea();
if (plotworld.isSchematicOnClaim()) { if (plotworld.isSchematicOnClaim()) {
@ -1711,9 +1827,18 @@ public class Plot {
* *
* @return the name of the biome * @return the name of the biome
*/ */
public BiomeType getBiome() { public void getBiome(Consumer<BiomeType> result) {
Location location = this.getCenter(); this.getCenter(location ->
return WorldUtil.IMP.getBiome(location.getWorld(), location.getX(), location.getZ()); WorldUtil.IMP.getBiome(location.getWorld(), location.getX(), location.getZ(), result));
}
/**
* @deprecated May cause synchronous chunk loads
*/
@Deprecated
public BiomeType getBiomeSynchronous() {
final Location location = this.getCenterSynchronous();
return WorldUtil.IMP.getBiomeSynchronous(location.getWorld(), location.getX(), location.getZ());
} }
//TODO Better documentation needed. //TODO Better documentation needed.
@ -2205,9 +2330,6 @@ public class Plot {
/** /**
* Gets the set home location or 0,0,0 if no location is set<br> * Gets the set home location or 0,0,0 if no location is set<br>
* - Does not take the default home location into account * - Does not take the default home location into account
*
* @return
* @see #getHome()
*/ */
public BlockLoc getPosition() { public BlockLoc getPosition() {
return this.getSettings().getPosition(); return this.getSettings().getPosition();
@ -2246,7 +2368,7 @@ public class Plot {
if (this.hasOwner()) { if (this.hasOwner()) {
return this.owner; return this.owner;
} }
if (!this.area.allowSigns()) { if (!this.area.allowSigns() || !Settings.Enabled_Components.GUESS_PLOT_OWNER) {
return null; return null;
} }
try { try {
@ -2255,7 +2377,7 @@ public class Plot {
@Override public void run(String[] value) { @Override public void run(String[] value) {
ChunkManager.manager ChunkManager.manager
.loadChunk(location.getWorld(), location.getBlockVector2(), false); .loadChunk(location.getWorld(), location.getBlockVector2(), false);
this.value = WorldUtil.IMP.getSign(location); this.value = WorldUtil.IMP.getSignSynchronous(location);
} }
}); });
if (lines == null) { if (lines == null) {
@ -2876,8 +2998,8 @@ public class Plot {
* @param player the player * @param player the player
* @return if the teleport succeeded * @return if the teleport succeeded
*/ */
public boolean teleportPlayer(final PlotPlayer player) { public void teleportPlayer(final PlotPlayer player, Consumer<Boolean> result) {
return teleportPlayer(player, TeleportCause.PLUGIN); teleportPlayer(player, TeleportCause.PLUGIN, result);
} }
/** /**
@ -2887,41 +3009,43 @@ public class Plot {
* @param cause the cause of the teleport * @param cause the cause of the teleport
* @return if the teleport succeeded * @return if the teleport succeeded
*/ */
public boolean teleportPlayer(final PlotPlayer player, TeleportCause cause) { public void teleportPlayer(final PlotPlayer player, TeleportCause cause, Consumer<Boolean> resultConsumer) {
Plot plot = this.getBasePlot(false); Plot plot = this.getBasePlot(false);
Result result = Result result =
PlotSquared.get().getEventDispatcher().callTeleport(player, player.getLocation(), plot).getEventResult(); PlotSquared.get().getEventDispatcher().callTeleport(player, player.getLocation(), plot).getEventResult();
if (result == Result.DENY) { if (result == Result.DENY) {
sendMessage(player, Captions.EVENT_DENIED, "Teleport"); sendMessage(player, Captions.EVENT_DENIED, "Teleport");
return false; resultConsumer.accept(false);
return;
} }
final Location location; final Consumer<Location> locationConsumer = location -> {
if (this.area.isHomeAllowNonmember() || plot.isAdded(player.getUUID())) { if (Settings.Teleport.DELAY == 0 || Permissions.hasPermission(player, "plots.teleport.delay.bypass")) {
location = this.getHome();
} else {
location = this.getDefaultHome(false);
}
if (Settings.Teleport.DELAY == 0 || Permissions
.hasPermission(player, "plots.teleport.delay.bypass")) {
MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT);
player.teleport(location, cause);
return true;
}
MainUtil.sendMessage(player, Captions.TELEPORT_IN_SECONDS, Settings.Teleport.DELAY + "");
final String name = player.getName();
TaskManager.TELEPORT_QUEUE.add(name);
TaskManager.runTaskLater(() -> {
if (!TaskManager.TELEPORT_QUEUE.contains(name)) {
MainUtil.sendMessage(player, Captions.TELEPORT_FAILED);
return;
}
TaskManager.TELEPORT_QUEUE.remove(name);
if (player.isOnline()) {
MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT); MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT);
player.teleport(location, cause); player.teleport(location, cause);
resultConsumer.accept(true);
return;
} }
}, Settings.Teleport.DELAY * 20); MainUtil.sendMessage(player, Captions.TELEPORT_IN_SECONDS, Settings.Teleport.DELAY + "");
return true; final String name = player.getName();
TaskManager.TELEPORT_QUEUE.add(name);
TaskManager.runTaskLater(() -> {
if (!TaskManager.TELEPORT_QUEUE.contains(name)) {
MainUtil.sendMessage(player, Captions.TELEPORT_FAILED);
return;
}
TaskManager.TELEPORT_QUEUE.remove(name);
if (player.isOnline()) {
MainUtil.sendMessage(player, Captions.TELEPORTED_TO_PLOT);
player.teleport(location, cause);
}
}, Settings.Teleport.DELAY * 20);
resultConsumer.accept(true);
};
if (this.area.isHomeAllowNonmember() || plot.isAdded(player.getUUID())) {
this.getHome(locationConsumer);
} else {
this.getDefaultHome(false, locationConsumer);
}
} }
/** /**

View File

@ -32,7 +32,7 @@ public enum PlotAreaTerrainType {
.collect(Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity())); .collect(Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity()));
public static Optional<PlotAreaTerrainType> fromString(String typeString) { public static Optional<PlotAreaTerrainType> fromString(String typeString) {
return Optional.ofNullable(types.get(typeString)); return Optional.ofNullable(types.get(typeString.toLowerCase()));
} }
@Deprecated @Deprecated

View File

@ -7,6 +7,7 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import java.util.HashSet; import java.util.HashSet;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
public class PlotCluster { public class PlotCluster {
public PlotArea area; public PlotArea area;
@ -86,8 +87,6 @@ public class PlotCluster {
/** /**
* Get the area (in plots). * Get the area (in plots).
*
* @return
*/ */
public int getArea() { public int getArea() {
return (1 + this.pos2.x - this.pos1.x) * (1 + this.pos2.y - this.pos1.y); return (1 + this.pos2.x - this.pos1.x) * (1 + this.pos2.y - this.pos1.y);
@ -125,26 +124,31 @@ public class PlotCluster {
+ this.pos2.y; + this.pos2.y;
} }
public Location getHome() { public void getHome(Consumer<Location> result) {
BlockLoc home = this.settings.getPosition(); BlockLoc home = this.settings.getPosition();
Location toReturn; Consumer<Location> locationConsumer = toReturn -> {
MainUtil.getHighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ(), max -> {
if (max > toReturn.getY()) {
toReturn.setY(1 + max);
}
result.accept(toReturn);
});
};
if (home.getY() == 0) { if (home.getY() == 0) {
// default pos // default pos
Plot center = getCenterPlot(); Plot center = getCenterPlot();
toReturn = center.getHome(); center.getHome(location -> {
if (toReturn.getY() == 0) { Location toReturn = location;
PlotManager manager = this.area.getPlotManager(); if (toReturn.getY() == 0) {
Location location = manager.getSignLoc(center); PlotManager manager = this.area.getPlotManager();
toReturn.setY(location.getY()); Location locationSign = manager.getSignLoc(center);
} toReturn.setY(locationSign.getY());
}
locationConsumer.accept(toReturn);
});
} else { } else {
toReturn = getClusterBottom().add(home.getX(), home.getY(), home.getZ()); locationConsumer.accept(getClusterBottom().add(home.getX(), home.getY(), home.getZ()));
} }
int max = MainUtil.getHeighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ());
if (max > toReturn.getY()) {
toReturn.setY(1 + max);
}
return toReturn;
} }
public PlotId getCenterPlotId() { public PlotId getCenterPlotId() {

View File

@ -628,19 +628,17 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer {
}); });
} else if (!PlotSquared.get().isMainThread(Thread.currentThread())) { } else if (!PlotSquared.get().isMainThread(Thread.currentThread())) {
if (getMeta("teleportOnLogin", true)) { if (getMeta("teleportOnLogin", true)) {
if (plot.teleportPlayer(PlotPlayer.this)) { plot.teleportPlayer(PlotPlayer.this, result -> TaskManager.runTask(() -> {
TaskManager.runTask(() -> { if (getMeta("teleportOnLogin", true)) {
if (getMeta("teleportOnLogin", true)) { if (plot.isLoaded()) {
if (plot.isLoaded()) { teleport(location);
teleport(location); sendMessage(CaptionUtility.format(PlotPlayer.this,
sendMessage(CaptionUtility.format(PlotPlayer.this, Captions.TELEPORTED_TO_PLOT.getTranslated())
Captions.TELEPORTED_TO_PLOT.getTranslated()) + " (quitLoc-unloaded) (" + plotX + "," + plotZ
+ " (quitLoc-unloaded) (" + plotX + "," + plotZ + ")");
+ ")");
}
} }
}); }
} }));
} }
} }
} catch (Throwable e) { } catch (Throwable e) {

View File

@ -1,14 +1,11 @@
package com.github.intellectualsites.plotsquared.plot.object.worlds; package com.github.intellectualsites.plotsquared.plot.object.worlds;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag;
import com.github.intellectualsites.plotsquared.plot.object.BlockLoc; import com.github.intellectualsites.plotsquared.plot.object.BlockLoc;
import com.github.intellectualsites.plotsquared.plot.object.Location; import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotId; import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.TeleportCause;
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 org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -18,6 +15,7 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
public class SinglePlot extends Plot { public class SinglePlot extends Plot {
private Set<CuboidRegion> regions = Collections.singleton( private Set<CuboidRegion> regions = Collections.singleton(
@ -51,17 +49,8 @@ public class SinglePlot extends Plot {
return (SinglePlotArea) super.getArea(); return (SinglePlotArea) super.getArea();
} }
public boolean teleportPlayer(final PlotPlayer player, TeleportCause cause) { @Override public void getSide(Consumer<Location> result) {
if (isLoaded()) { getCenter(result);
return super.teleportPlayer(player, cause);
} else {
Captions.NOT_LOADED.send(player);
return false;
}
}
@Override public Location getSide() {
return getCenter();
} }
@Override protected boolean isLoaded() { @Override protected boolean isLoaded() {

View File

@ -0,0 +1,50 @@
package com.github.intellectualsites.plotsquared.plot.util;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.commands.Auto;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.events.PlotMergeEvent;
import com.github.intellectualsites.plotsquared.plot.events.Result;
import com.github.intellectualsites.plotsquared.plot.object.Direction;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import lombok.RequiredArgsConstructor;
import static com.github.intellectualsites.plotsquared.plot.util.MainUtil.sendMessage;
@RequiredArgsConstructor public final class AutoClaimFinishTask extends RunnableVal<Object> {
private final PlotPlayer player;
private final Plot plot;
private final PlotArea area;
private final int allowedPlots;
private final String schematic;
@Override public void run(Object value) {
player.deleteMeta(Auto.class.getName());
if (plot == null) {
sendMessage(player, Captions.NO_FREE_PLOTS);
return;
}
if (Auto.checkAllowedPlots(player, area, allowedPlots, 1, 1)) {
plot.claim(player, true, schematic, false);
if (area.isAutoMerge()) {
PlotMergeEvent event = PlotSquared.get().getEventDispatcher()
.callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player);
if (event.getEventResult() == Result.DENY) {
sendMessage(player, Captions.EVENT_DENIED, "Auto merge");
} else {
plot.autoMerge(event.getDir(), event.getMax(), player.getUUID(),
true);
}
}
} else {
DBFunc.delete(plot);
}
}
}

View File

@ -185,7 +185,7 @@ public class EventDispatcher {
final Plot plot = player.getCurrentPlot(); final Plot plot = player.getCurrentPlot();
if (Settings.Teleport.ON_LOGIN && plot != null && !(plot if (Settings.Teleport.ON_LOGIN && plot != null && !(plot
.getArea() instanceof SinglePlotArea)) { .getArea() instanceof SinglePlotArea)) {
TaskManager.runTask(() -> plot.teleportPlayer(player)); TaskManager.runTask(() -> plot.teleportPlayer(player, result -> {}));
MainUtil.sendMessage(player, MainUtil.sendMessage(player,
CaptionUtility.format(player, Captions.TELEPORTED_TO_ROAD.getTranslated()) CaptionUtility.format(player, Captions.TELEPORTED_TO_ROAD.getTranslated())
+ " (on-login) " + "(" + plot.getId().x + ";" + plot.getId().y + ")"); + " (on-login) " + "(" + plot.getId().x + ";" + plot.getId().y + ")");
@ -195,7 +195,7 @@ public class EventDispatcher {
public void doRespawnTask(final PlotPlayer player) { public void doRespawnTask(final PlotPlayer player) {
final Plot plot = player.getCurrentPlot(); final Plot plot = player.getCurrentPlot();
if (Settings.Teleport.ON_DEATH && plot != null) { if (Settings.Teleport.ON_DEATH && plot != null) {
TaskManager.runTask(() -> plot.teleportPlayer(player)); TaskManager.runTask(() -> plot.teleportPlayer(player, result -> {}));
MainUtil.sendMessage(player, Captions.TELEPORTED_TO_ROAD); MainUtil.sendMessage(player, Captions.TELEPORTED_TO_ROAD);
} }
} }

View File

@ -56,6 +56,7 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.function.IntFunction; import java.util.function.IntFunction;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -232,7 +233,7 @@ public class MainUtil {
*/ */
public static boolean resetBiome(PlotArea area, Location pos1, Location pos2) { public static boolean resetBiome(PlotArea area, Location pos1, Location pos2) {
BiomeType biome = area.getPlotBiome(); BiomeType biome = area.getPlotBiome();
if (!Objects.equals(WorldUtil.IMP.getBiome(area.getWorldName(), (pos1.getX() + pos2.getX()) / 2, if (!Objects.equals(WorldUtil.IMP.getBiomeSynchronous(area.getWorldName(), (pos1.getX() + pos2.getX()) / 2,
(pos1.getZ() + pos2.getZ()) / 2), biome)) { (pos1.getZ() + pos2.getZ()) / 2), biome)) {
MainUtil.setBiome(area.getWorldName(), pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), MainUtil.setBiome(area.getWorldName(), pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(),
biome); biome);
@ -589,18 +590,15 @@ public class MainUtil {
/** /**
* Get the highest block at a location. * Get the highest block at a location.
*
* @param world
* @param x
* @param z
* @return
*/ */
public static int getHeighestBlock(String world, int x, int z) { public static void getHighestBlock(String world, int x, int z, IntConsumer result) {
int result = WorldUtil.IMP.getHighestBlock(world, x, z); WorldUtil.IMP.getHighestBlock(world, x, z, highest -> {
if (result == 0) { if (highest == 0) {
return 63; result.accept(63);
} } else {
return result; result.accept(highest);
}
});
} }
/** /**
@ -752,116 +750,118 @@ public class MainUtil {
/** /**
* Format a string with plot information. * Format a string with plot information.
* *
* @param info * @param iInfo
* @param plot * @param plot
* @param player * @param player
* @param full * @param full
* @param whenDone * @param whenDone
*/ */
public static void format(String info, final Plot plot, PlotPlayer player, final boolean full, public static void format(final String iInfo, final Plot plot, PlotPlayer player, final boolean full,
final RunnableVal<String> whenDone) { final RunnableVal<String> whenDone) {
int num = plot.getConnectedPlots().size(); int num = plot.getConnectedPlots().size();
String alias = !plot.getAlias().isEmpty() ? plot.getAlias() : Captions.NONE.getTranslated(); String alias = !plot.getAlias().isEmpty() ? plot.getAlias() : Captions.NONE.getTranslated();
Location bot = plot.getCorners()[0]; Location bot = plot.getCorners()[0];
BiomeType biome = WorldUtil.IMP.getBiome(plot.getWorldName(), bot.getX(), bot.getZ()); WorldUtil.IMP.getBiome(plot.getWorldName(), bot.getX(), bot.getZ(), biome -> {
String trusted = getPlayerList(plot.getTrusted()); String info = iInfo;
String members = getPlayerList(plot.getMembers()); String trusted = getPlayerList(plot.getTrusted());
String denied = getPlayerList(plot.getDenied()); String members = getPlayerList(plot.getMembers());
String seen; String denied = getPlayerList(plot.getDenied());
if (Settings.Enabled_Components.PLOT_EXPIRY && ExpireManager.IMP != null) { String seen;
if (plot.isOnline()) { if (Settings.Enabled_Components.PLOT_EXPIRY && ExpireManager.IMP != null) {
seen = Captions.NOW.getTranslated(); if (plot.isOnline()) {
} else { seen = Captions.NOW.getTranslated();
int time = (int) (ExpireManager.IMP.getAge(plot) / 1000);
if (time != 0) {
seen = MainUtil.secToTime(time);
} else { } else {
seen = Captions.UNKNOWN.getTranslated(); int time = (int) (ExpireManager.IMP.getAge(plot) / 1000);
} if (time != 0) {
} seen = MainUtil.secToTime(time);
} else {
seen = Captions.NEVER.getTranslated();
}
String description = plot.getFlag(DescriptionFlag.class);
if (description.isEmpty()) {
description = Captions.PLOT_NO_DESCRIPTION.getTranslated();
}
StringBuilder flags = new StringBuilder();
Collection<PlotFlag<?, ?>> flagCollection = plot.getApplicableFlags(true);
if (flagCollection.isEmpty()) {
flags.append(Captions.NONE.getTranslated());
} else {
String prefix = " ";
for (final PlotFlag<?, ?> flag : flagCollection) {
Object value;
if (flag instanceof DoubleFlag && !Settings.General.SCIENTIFIC) {
value = FLAG_DECIMAL_FORMAT.format(flag.getValue());
} else {
value = flag.toString();
}
flags.append(prefix).append(CaptionUtility.format(player, Captions.PLOT_FLAG_LIST.getTranslated(),
flag.getName(), CaptionUtility.formatRaw(player, value.toString(), "")));
prefix = ", ";
}
}
boolean build = plot.isAdded(player.getUUID());
String owner = plot.getOwners().isEmpty() ? "unowned" : getPlayerList(plot.getOwners());
if (plot.getArea() != null) {
info = info.replace("%area%", plot.getArea().getWorldName() +
(plot.getArea().getId() == null ? "" : "(" + plot.getArea().getId() + ")"));
} else {
info = info.replace("%area%", Captions.NONE.getTranslated());
}
info = info.replace("%id%", plot.getId().toString());
info = info.replace("%alias%", alias);
info = info.replace("%num%", String.valueOf(num));
info = info.replace("%desc%", description);
info = info.replace("%biome%", biome.toString().toLowerCase());
info = info.replace("%owner%", owner);
info = info.replace("%members%", members);
info = info.replace("%player%", player.getName());
info = info.replace("%trusted%", trusted);
info = info.replace("%helpers%", members);
info = info.replace("%denied%", denied);
info = info.replace("%seen%", seen);
info = info.replace("%flags%", flags);
info = info.replace("%build%", String.valueOf(build));
if (info.contains("%rating%")) {
final String newInfo = info;
TaskManager.runTaskAsync(() -> {
String info1;
if (Settings.Ratings.USE_LIKES) {
info1 = newInfo.replaceAll("%rating%",
String.format("%.0f%%", Like.getLikesPercentage(plot) * 100D));
} else {
int max = 10;
if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES
.isEmpty()) {
max = 8;
}
if (full && Settings.Ratings.CATEGORIES != null
&& Settings.Ratings.CATEGORIES.size() > 1) {
double[] ratings = MainUtil.getAverageRatings(plot);
String rating = "";
String prefix = "";
for (int i = 0; i < ratings.length; i++) {
rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String
.format("%.1f", ratings[i]);
prefix = ",";
}
info1 = newInfo.replaceAll("%rating%", rating);
} else { } else {
info1 = newInfo.replaceAll("%rating%", seen = Captions.UNKNOWN.getTranslated();
String.format("%.1f", plot.getAverageRating()) + '/' + max);
} }
} }
whenDone.run(info1); } else {
}); seen = Captions.NEVER.getTranslated();
return; }
}
whenDone.run(info); String description = plot.getFlag(DescriptionFlag.class);
if (description.isEmpty()) {
description = Captions.PLOT_NO_DESCRIPTION.getTranslated();
}
StringBuilder flags = new StringBuilder();
Collection<PlotFlag<?, ?>> flagCollection = plot.getApplicableFlags(true);
if (flagCollection.isEmpty()) {
flags.append(Captions.NONE.getTranslated());
} else {
String prefix = " ";
for (final PlotFlag<?, ?> flag : flagCollection) {
Object value;
if (flag instanceof DoubleFlag && !Settings.General.SCIENTIFIC) {
value = FLAG_DECIMAL_FORMAT.format(flag.getValue());
} else {
value = flag.toString();
}
flags.append(prefix).append(CaptionUtility.format(player, Captions.PLOT_FLAG_LIST.getTranslated(),
flag.getName(), CaptionUtility.formatRaw(player, value.toString(), "")));
prefix = ", ";
}
}
boolean build = plot.isAdded(player.getUUID());
String owner = plot.getOwners().isEmpty() ? "unowned" : getPlayerList(plot.getOwners());
if (plot.getArea() != null) {
info = info.replace("%area%", plot.getArea().getWorldName() +
(plot.getArea().getId() == null ? "" : "(" + plot.getArea().getId() + ")"));
} else {
info = info.replace("%area%", Captions.NONE.getTranslated());
}
info = info.replace("%id%", plot.getId().toString());
info = info.replace("%alias%", alias);
info = info.replace("%num%", String.valueOf(num));
info = info.replace("%desc%", description);
info = info.replace("%biome%", biome.toString().toLowerCase());
info = info.replace("%owner%", owner);
info = info.replace("%members%", members);
info = info.replace("%player%", player.getName());
info = info.replace("%trusted%", trusted);
info = info.replace("%helpers%", members);
info = info.replace("%denied%", denied);
info = info.replace("%seen%", seen);
info = info.replace("%flags%", flags);
info = info.replace("%build%", String.valueOf(build));
if (info.contains("%rating%")) {
final String newInfo = info;
TaskManager.runTaskAsync(() -> {
String info1;
if (Settings.Ratings.USE_LIKES) {
info1 = newInfo.replaceAll("%rating%",
String.format("%.0f%%", Like.getLikesPercentage(plot) * 100D));
} else {
int max = 10;
if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES
.isEmpty()) {
max = 8;
}
if (full && Settings.Ratings.CATEGORIES != null
&& Settings.Ratings.CATEGORIES.size() > 1) {
double[] ratings = MainUtil.getAverageRatings(plot);
String rating = "";
String prefix = "";
for (int i = 0; i < ratings.length; i++) {
rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String
.format("%.1f", ratings[i]);
prefix = ",";
}
info1 = newInfo.replaceAll("%rating%", rating);
} else {
info1 = newInfo.replaceAll("%rating%",
String.format("%.1f", plot.getAverageRating()) + '/' + max);
}
}
whenDone.run(info1);
});
return;
}
whenDone.run(info);
});
} }
public static boolean deleteDirectory(File directory) { public static boolean deleteDirectory(File directory) {

View File

@ -0,0 +1,28 @@
package com.github.intellectualsites.plotsquared.plot.util;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import lombok.RequiredArgsConstructor;
import java.util.Iterator;
@RequiredArgsConstructor public class ObjectTaskRunnable<T> implements Runnable {
private final Iterator<T> iterator;
private final RunnableVal<T> task;
private final Runnable whenDone;
@Override public void run() {
long start = System.currentTimeMillis();
boolean hasNext;
while ((hasNext = iterator.hasNext()) && System.currentTimeMillis() - start < 5) {
task.value = iterator.next();
task.run();
}
if (!hasNext) {
TaskManager.runTaskLater(whenDone, 1);
} else {
TaskManager.runTaskLater(this, 1);
}
}
}

View File

@ -0,0 +1,28 @@
package com.github.intellectualsites.plotsquared.plot.util;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import lombok.RequiredArgsConstructor;
import java.util.concurrent.atomic.AtomicBoolean;
@RequiredArgsConstructor public class RuntimeExceptionRunnableVal<T> extends RunnableVal<RuntimeException> {
private final RunnableVal<T> function;
private final AtomicBoolean running;
@Override public void run(RuntimeException value) {
try {
function.run();
} catch (RuntimeException e) {
this.value = e;
} catch (Throwable neverHappens) {
neverHappens.printStackTrace();
} finally {
running.set(false);
}
synchronized (function) {
function.notifyAll();
}
}
}

View File

@ -178,8 +178,7 @@ public abstract class SchematicHandler {
if (pw instanceof ClassicPlotWorld) { if (pw instanceof ClassicPlotWorld) {
y_offset_actual = yOffset + ((ClassicPlotWorld) pw).PLOT_HEIGHT; y_offset_actual = yOffset + ((ClassicPlotWorld) pw).PLOT_HEIGHT;
} else { } else {
y_offset_actual = yOffset + 1 + MainUtil y_offset_actual = yOffset + 1 + WorldUtil.IMP.getHighestBlockSynchronous(plot.getWorldName(),
.getHeighestBlock(plot.getWorldName(),
region.getMinimumPoint().getX() + 1, region.getMinimumPoint().getX() + 1,
region.getMinimumPoint().getZ() + 1); region.getMinimumPoint().getZ() + 1);
} }

View File

@ -93,21 +93,7 @@ public abstract class TaskManager {
public static <T> void objectTask(Collection<T> objects, final RunnableVal<T> task, public static <T> void objectTask(Collection<T> objects, final RunnableVal<T> task,
final Runnable whenDone) { final Runnable whenDone) {
final Iterator<T> iterator = objects.iterator(); final Iterator<T> iterator = objects.iterator();
TaskManager.runTask(new Runnable() { TaskManager.runTask(new ObjectTaskRunnable<>(iterator, task, whenDone));
@Override public void run() {
long start = System.currentTimeMillis();
boolean hasNext;
while ((hasNext = iterator.hasNext()) && System.currentTimeMillis() - start < 5) {
task.value = iterator.next();
task.run();
}
if (!hasNext) {
TaskManager.runTaskLater(whenDone, 1);
} else {
TaskManager.runTaskLater(this, 1);
}
}
});
} }
public <T> T sync(final RunnableVal<T> function) { public <T> T sync(final RunnableVal<T> function) {
@ -120,22 +106,7 @@ public abstract class TaskManager {
return function.value; return function.value;
} }
final AtomicBoolean running = new AtomicBoolean(true); final AtomicBoolean running = new AtomicBoolean(true);
RunnableVal<RuntimeException> run = new RunnableVal<RuntimeException>() { final RuntimeExceptionRunnableVal<T> run = new RuntimeExceptionRunnableVal<>(function, running);
@Override public void run(RuntimeException value) {
try {
function.run();
} catch (RuntimeException e) {
this.value = e;
} catch (Throwable neverHappens) {
neverHappens.printStackTrace();
} finally {
running.set(false);
}
synchronized (function) {
function.notifyAll();
}
}
};
TaskManager.IMP.task(run); TaskManager.IMP.task(run);
try { try {
synchronized (function) { synchronized (function) {

View File

@ -5,7 +5,6 @@ import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.object.schematic.PlotItem;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
@ -15,6 +14,7 @@ import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion; 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.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@ -25,11 +25,12 @@ import java.net.URL;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import org.jetbrains.annotations.NotNull;
public abstract class WorldUtil { public abstract class WorldUtil {
public static WorldUtil IMP; public static WorldUtil IMP;
@ -38,7 +39,13 @@ public abstract class WorldUtil {
public abstract boolean isWorld(String worldName); public abstract boolean isWorld(String worldName);
public abstract String[] getSign(Location location); public abstract void getSign(Location location, Consumer<String[]> result);
/**
* @deprecated May result in synchronous chunk loading
*/
@Deprecated
public abstract String[] getSignSynchronous(Location location);
public abstract Location getSpawn(String world); public abstract Location getSpawn(String world);
@ -52,13 +59,29 @@ public abstract class WorldUtil {
public abstract StringComparison<BlockState>.ComparisonResult getClosestBlock(String name); public abstract StringComparison<BlockState>.ComparisonResult getClosestBlock(String name);
public abstract BiomeType getBiome(String world, int x, int z); public abstract void getBiome(String world, int x, int z, Consumer<BiomeType> result);
public abstract BlockState getBlock(Location location); /**
* @deprecated May result in synchronous chunk loading
*/
@Deprecated
public abstract BiomeType getBiomeSynchronous(String world, int x, int z);
public abstract int getHighestBlock(String world, int x, int z); public abstract void getBlock(Location location, Consumer<BlockState> result);
public abstract boolean addItems(String world, PlotItem item); /**
* @deprecated May result in synchronous chunk loading
*/
@Deprecated
public abstract BlockState getBlockSynchronous(Location location);
public abstract void getHighestBlock(String world, int x, int z, final IntConsumer result);
/**
* @deprecated May result in synchronous chunk loading
*/
@Deprecated
public abstract int getHighestBlockSynchronous(String world, int x, int z);
public abstract void setSign(String world, int x, int y, int z, String[] lines); public abstract void setSign(String world, int x, int y, int z, String[] lines);
@ -67,8 +90,7 @@ public abstract class WorldUtil {
public abstract com.sk89q.worldedit.world.World getWeWorld(String world); public abstract com.sk89q.worldedit.world.World getWeWorld(String world);
public void upload(@NotNull final Plot plot, UUID uuid, String file, RunnableVal<URL> whenDone) { public void upload(@NotNull final Plot plot, UUID uuid, String file, RunnableVal<URL> whenDone) {
final Location home = plot.getHome(); plot.getHome(home -> MainUtil.upload(uuid, file, "zip", new RunnableVal<OutputStream>() {
MainUtil.upload(uuid, file, "zip", new RunnableVal<OutputStream>() {
@Override public void run(OutputStream output) { @Override public void run(OutputStream output) {
try (final ZipOutputStream zos = new ZipOutputStream(output)) { try (final ZipOutputStream zos = new ZipOutputStream(output)) {
File dat = getDat(plot.getWorldName()); File dat = getDat(plot.getWorldName());
@ -135,7 +157,7 @@ public abstract class WorldUtil {
e.printStackTrace(); e.printStackTrace();
} }
} }
}, whenDone); }, whenDone));
} }
public File getDat(String world) { public File getDat(String world) {

View File

@ -222,6 +222,7 @@ public abstract class BasicLocalBlockQueue extends LocalBlockQueue {
public class BasicLocalChunk extends LocalChunk { public class BasicLocalChunk extends LocalChunk {
public BasicLocalChunk(BasicLocalBlockQueue parent, int x, int z) { public BasicLocalChunk(BasicLocalBlockQueue parent, int x, int z) {
super(parent, x, z); super(parent, x, z);
baseblocks = new BaseBlock[16][]; baseblocks = new BaseBlock[16][];

View File

@ -12,6 +12,11 @@ public class DelegateLocalBlockQueue extends LocalBlockQueue {
public DelegateLocalBlockQueue(LocalBlockQueue parent) { public DelegateLocalBlockQueue(LocalBlockQueue parent) {
super(parent == null ? null : parent.getWorld()); super(parent == null ? null : parent.getWorld());
this.parent = parent; this.parent = parent;
if (parent != null) {
this.setForceSync(parent.isForceSync());
this.setChunkObject(parent.getChunkObject());
}
} }
public LocalBlockQueue getParent() { public LocalBlockQueue getParent() {

View File

@ -13,12 +13,18 @@ import com.sk89q.worldedit.math.BlockVector2;
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 lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map; import java.util.Map;
import org.jetbrains.annotations.NotNull;
public abstract class LocalBlockQueue { public abstract class LocalBlockQueue {
@Getter @Setter private boolean forceSync = false;
@Getter @Setter @Nullable private Object chunkObject;
/** /**
* Needed for compatibility with FAWE. * Needed for compatibility with FAWE.
* *
@ -100,7 +106,7 @@ public abstract class LocalBlockQueue {
.equals(loc)) { .equals(loc)) {
continue; continue;
} }
pLoc.setY(WorldUtil.IMP.getHighestBlock(getWorld(), pLoc.getX(), pLoc.getZ())); pLoc.setY(WorldUtil.IMP.getHighestBlockSynchronous(getWorld(), pLoc.getX(), pLoc.getZ()));
pp.teleport(pLoc); pp.teleport(pLoc);
} }
} }

View File

@ -6,6 +6,7 @@ import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotManager; import com.github.intellectualsites.plotsquared.plot.object.PlotManager;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3; import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3;
import com.sk89q.worldedit.function.pattern.Pattern;
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;
@ -36,8 +37,10 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue {
this.dx = maxX - minX; this.dx = maxX - minX;
this.dy = maxY - minY; this.dy = maxY - minY;
this.dz = maxZ - minZ; this.dz = maxZ - minZ;
}
this.setForceSync(parent.isForceSync());
this.setChunkObject(parent.getChunkObject());
}
@Override public boolean setBiome(int x, int z, BiomeType biome) { @Override public boolean setBiome(int x, int z, BiomeType biome) {
return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBiome(x + minX, z + minZ, biome); return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBiome(x + minX, z + minZ, biome);
@ -61,6 +64,11 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue {
.setBlock(x + minX, y + minY, z + minZ, id); .setBlock(x + minX, y + minY, z + minZ, id);
} }
@Override public boolean setBlock(int x, int y, int z, Pattern pattern) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super
.setBlock(x + minX, y + minY, z + minZ, pattern);
}
public Location getMin() { public Location getMin() {
return new Location(getWorld(), minX, minY, minZ); return new Location(getWorld(), minX, minY, minZ);
} }

View File

@ -119,7 +119,7 @@ public class ExpireManager {
if (!isExpired(new ArrayDeque<>(tasks), current).isEmpty()) { if (!isExpired(new ArrayDeque<>(tasks), current).isEmpty()) {
TaskManager.runTask(() -> { TaskManager.runTask(() -> {
pp.setMeta("ignoreExpireTask", true); pp.setMeta("ignoreExpireTask", true);
pp.teleport(current.getCenter()); current.getCenter(pp::teleport);
pp.deleteMeta("ignoreExpireTask"); pp.deleteMeta("ignoreExpireTask");
PlotMessage msg = new PlotMessage() PlotMessage msg = new PlotMessage()
.text(num + " " + (num > 1 ? "plots are" : "plot is") + " expired: ") .text(num + " " + (num > 1 ? "plots are" : "plot is") + " expired: ")