Merge branch 'v6' into feature/v6/json. It builds!

# Conflicts:
#	Bukkit/build.gradle
#	Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java
#	Bukkit/src/main/java/com/plotsquared/bukkit/generator/DelegatePlotGenerator.java
#	Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java
#	Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java
#	Bukkit/src/main/java/com/plotsquared/bukkit/queue/ChunkCoordinator.java
#	Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java
#	Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java
#	Core/src/main/java/com/plotsquared/core/PlotSquared.java
#	Core/src/main/java/com/plotsquared/core/command/Area.java
#	Core/src/main/java/com/plotsquared/core/command/Clear.java
#	Core/src/main/java/com/plotsquared/core/command/Debug.java
#	Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java
#	Core/src/main/java/com/plotsquared/core/command/Relight.java
#	Core/src/main/java/com/plotsquared/core/command/Set.java
#	Core/src/main/java/com/plotsquared/core/command/Template.java
#	Core/src/main/java/com/plotsquared/core/command/Trim.java
#	Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java
#	Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java
#	Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java
#	Core/src/main/java/com/plotsquared/core/plot/Plot.java
#	Core/src/main/java/com/plotsquared/core/plot/flag/GlobalFlagContainer.java
#	Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java
#	Core/src/main/java/com/plotsquared/core/queue/ChunkQueueCoordinator.java
#	Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java
#	Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java
#	Core/src/main/java/com/plotsquared/core/util/EntityUtil.java
#	Core/src/main/java/com/plotsquared/core/util/RegionManager.java
#	Core/src/main/java/com/plotsquared/core/util/WorldUtil.java
#	Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java
#	build.gradle
This commit is contained in:
dordsor21
2020-08-08 13:20:30 +01:00
92 changed files with 7970 additions and 3676 deletions

View File

@ -59,6 +59,7 @@ import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.plot.expiration.ExpireManager;
import com.plotsquared.core.plot.expiration.ExpiryTask;
import com.plotsquared.core.plot.flag.GlobalFlagContainer;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.plot.world.SinglePlotAreaManager;
@ -67,6 +68,7 @@ import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.LegacyConverter;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.ReflectionUtils;
import com.plotsquared.core.util.placeholders.PlaceholderRegistry;
import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.uuid.UUIDPipeline;
import com.sk89q.worldedit.WorldEdit;
@ -147,7 +149,7 @@ public class PlotSquared {
private File storageFile;
private EventDispatcher eventDispatcher;
private PlotListener plotListener;
private PlaceholderRegistry placeholderRegistry;
/**
* Initialize PlotSquared with the desired Implementation class.
*
@ -172,6 +174,9 @@ public class PlotSquared {
//
ConfigurationSerialization.registerClass(BlockBucket.class, "BlockBucket");
// Setup the global flag container
GlobalFlagContainer.setup();
try {
new ReflectionUtils(this.platform.getNMSPackage());
try {
@ -1501,6 +1506,10 @@ public class PlotSquared {
return this.plotListener;
}
public PlaceholderRegistry getPlaceholderRegistry() {
return this.placeholderRegistry;
}
public enum SortType {
CREATION_DATE, CREATION_DATE_TIMESTAMP, LAST_MODIFIED, DISTANCE_FROM_ORIGIN
}

View File

@ -49,6 +49,8 @@ import com.plotsquared.core.plot.PlotAreaTerrainType;
import com.plotsquared.core.plot.PlotAreaType;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.setup.PlotAreaBuilder;
import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.MathMan;
@ -59,7 +61,6 @@ import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.SetupUtils;
import com.plotsquared.core.util.StringMan;
import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.RunnableVal3;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
@ -70,11 +71,9 @@ import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.Template;
import javax.annotation.Nonnull;
@ -107,16 +106,16 @@ public class Area extends SubCommand {
private final SetupUtils setupUtils;
private final WorldUtil worldUtil;
private final RegionManager regionManager;
private final GlobalBlockQueue blockQueue;
private final Map<UUID, Map<String, Object>> metaData = new HashMap<>();
@Inject public Area(@Nonnull final PlotAreaManager plotAreaManager,
@WorldConfig @Nonnull final YamlConfiguration worldConfiguration,
@WorldFile @Nonnull final File worldFile,
@Nonnull final HybridPlotWorldFactory hybridPlotWorldFactory,
@Nonnull final SetupUtils setupUtils,
@Nonnull final WorldUtil worldUtil,
@Nonnull final RegionManager regionManager) {
@WorldConfig @Nonnull final YamlConfiguration worldConfiguration,
@WorldFile @Nonnull final File worldFile,
@Nonnull final HybridPlotWorldFactory hybridPlotWorldFactory,
@Nonnull final SetupUtils setupUtils, @Nonnull final WorldUtil worldUtil,
@Nonnull final RegionManager regionManager, @Nonnull final GlobalBlockQueue blockQueue) {
this.plotAreaManager = plotAreaManager;
this.worldConfiguration = worldConfiguration;
this.worldFile = worldFile;
@ -124,6 +123,7 @@ public class Area extends SubCommand {
this.setupUtils = setupUtils;
this.worldUtil = worldUtil;
this.regionManager = regionManager;
this.blockQueue = blockQueue;
}
@Override public boolean onCommand(final PlotPlayer<?> player, String[] args) {
@ -146,20 +146,24 @@ public class Area extends SubCommand {
player.sendMessage(TranslatableCaption.of("single.single_area_needs_name"));
return false;
}
final PlotArea existingArea = this.plotAreaManager.getPlotArea(player.getLocation().getWorldName(), args[1]);
final PlotArea existingArea =
this.plotAreaManager.getPlotArea(player.getLocation().getWorldName(), args[1]);
if (existingArea != null && existingArea.getId().equalsIgnoreCase(args[1])) {
player.sendMessage(TranslatableCaption.of("single.single_area_name_taken"));
return false;
}
final LocalSession localSession = WorldEdit.getInstance().getSessionManager().getIfPresent(player.toActor());
final LocalSession localSession =
WorldEdit.getInstance().getSessionManager().getIfPresent(player.toActor());
if (localSession == null) {
player.sendMessage(TranslatableCaption.of("single.single_area_missing_selection"));
return false;
}
Region playerSelectedRegion = null;
try {
playerSelectedRegion = localSession.getSelection(((Player) player.toActor()).getWorld());
} catch (final Exception ignored) {}
playerSelectedRegion =
localSession.getSelection(((Player) player.toActor()).getWorld());
} catch (final Exception ignored) {
}
if (playerSelectedRegion == null) {
player.sendMessage(TranslatableCaption.of("single.single_area_missing_selection"));
return false;
@ -176,15 +180,19 @@ public class Area extends SubCommand {
final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint();
final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint();
// Create a new selection that spans the entire vertical range of the world
final CuboidRegion selectedRegion = new CuboidRegion(playerSelectedRegion.getWorld(),
BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()),
BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ()));
final CuboidRegion selectedRegion =
new CuboidRegion(playerSelectedRegion.getWorld(),
BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()),
BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ()));
// There's only one plot in the area...
final PlotId plotId = PlotId.of(1, 1);
final HybridPlotWorld hybridPlotWorld = this.hybridPlotWorldFactory.create(player.getLocation().getWorldName(), args[1],
Objects.requireNonNull(PlotSquared.platform()).getDefaultGenerator(), plotId, plotId);
final HybridPlotWorld hybridPlotWorld = this.hybridPlotWorldFactory
.create(player.getLocation().getWorldName(), args[1],
Objects.requireNonNull(PlotSquared.platform()).getDefaultGenerator(),
plotId, plotId);
// Plot size is the same as the region width
hybridPlotWorld.PLOT_WIDTH = hybridPlotWorld.SIZE = (short) selectedRegion.getWidth();
hybridPlotWorld.PLOT_WIDTH =
hybridPlotWorld.SIZE = (short) selectedRegion.getWidth();
// We use a schematic generator
hybridPlotWorld.setTerrain(PlotAreaTerrainType.NONE);
// It is always a partial plot world
@ -192,23 +200,30 @@ public class Area extends SubCommand {
// We save the schematic :D
hybridPlotWorld.PLOT_SCHEMATIC = true;
// Set the road width to 0
hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0;
hybridPlotWorld.ROAD_WIDTH =
hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0;
// Set the plot height to the selection height
hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = playerSelectionMin.getBlockY();
hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT =
hybridPlotWorld.WALL_HEIGHT = playerSelectionMin.getBlockY();
// No sign plz
hybridPlotWorld.setAllowSigns(false);
final File parentFile = FileUtils.getFile(PlotSquared.platform().getDirectory(), "schematics" + File.separator +
"GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator +
hybridPlotWorld.getId());
final File parentFile = FileUtils.getFile(PlotSquared.platform().getDirectory(),
"schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator
+ hybridPlotWorld.getWorldName() + File.separator + hybridPlotWorld
.getId());
if (!parentFile.exists() && !parentFile.mkdirs()) {
player.sendMessage(TranslatableCaption.of("single.single_area_could_not_make_directories"));
return false;
}
final File file = new File(parentFile, "plot.schem");
try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) {
try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC
.getWriter(new FileOutputStream(file))) {
final BlockArrayClipboard clipboard = new BlockArrayClipboard(selectedRegion);
final EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(selectedRegion.getWorld(), -1);
final ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, selectedRegion, clipboard, selectedRegion.getMinimumPoint());
final EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(selectedRegion.getWorld(), -1);
final ForwardExtentCopy forwardExtentCopy =
new ForwardExtentCopy(editSession, selectedRegion, clipboard,
selectedRegion.getMinimumPoint());
forwardExtentCopy.setCopyingBiomes(true);
forwardExtentCopy.setCopyingEntities(true);
Operations.complete(forwardExtentCopy);
@ -231,14 +246,14 @@ public class Area extends SubCommand {
// Now the schematic is saved, which is wonderful!
PlotAreaBuilder singleBuilder = PlotAreaBuilder.ofPlotArea(hybridPlotWorld)
.plotManager(PlotSquared.platform().getPluginName())
.generatorName(PlotSquared.platform().getPluginName())
.maximumId(plotId)
.minimumId(plotId);
.plotManager(PlotSquared.platform().getPluginName())
.generatorName(PlotSquared.platform().getPluginName()).maximumId(plotId)
.minimumId(plotId);
Runnable singleRun = () -> {
final String path =
"worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld.getId() + '-'
+ singleBuilder.minimumId() + '-' + singleBuilder.maximumId();
"worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld
.getId() + '-' + singleBuilder.minimumId() + '-' + singleBuilder
.maximumId();
final int offsetX = singlePos1.getX();
final int offsetZ = singlePos1.getZ();
if (offsetX != 0) {
@ -276,8 +291,9 @@ public class Area extends SubCommand {
case 2:
switch (args[1].toLowerCase()) {
case "pos1": { // Set position 1
HybridPlotWorld area = (HybridPlotWorld) metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>())
.get("area_create_area");
HybridPlotWorld area = (HybridPlotWorld) metaData
.computeIfAbsent(player.getUUID(),
missingUUID -> new HashMap<>()).get("area_create_area");
if (area == null) {
player.sendMessage(TranslatableCaption.of("commandconfig.command_syntax"),
Templates.of("value", "/plot area create [world[:id]] [<modifier>=<value>]..."));
@ -294,14 +310,17 @@ public class Area extends SubCommand {
}
case "pos2": // Set position 2 and finish creation for type=2 (partial)
final HybridPlotWorld area = (HybridPlotWorld) metaData
.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).get("area_create_area");
.computeIfAbsent(player.getUUID(),
missingUUID -> new HashMap<>()).get("area_create_area");
if (area == null) {
player.sendMessage(TranslatableCaption.of("commandconfig.command_syntax"),
Templates.of("value", "/plot area create [world[:id]] [<modifier>=<value>]..."));
return false;
}
Location pos1 = player.getLocation();
Location pos2 = (Location) metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).get("area_pos1");
Location pos2 = (Location) metaData
.computeIfAbsent(player.getUUID(),
missingUUID -> new HashMap<>()).get("area_pos1");
int dx = Math.abs(pos1.getX() - pos2.getX());
int dz = Math.abs(pos1.getZ() - pos2.getZ());
int numX = Math.max(1,
@ -328,19 +347,20 @@ public class Area extends SubCommand {
return false;
}
PlotAreaBuilder builder = PlotAreaBuilder.ofPlotArea(area)
.plotManager(PlotSquared.platform().getPluginName())
.generatorName(PlotSquared.platform().getPluginName())
.minimumId(PlotId.of(1, 1))
.maximumId(PlotId.of(numX, numZ));
.plotManager(PlotSquared.platform().getPluginName())
.generatorName(PlotSquared.platform().getPluginName())
.minimumId(PlotId.of(1, 1)).maximumId(PlotId.of(numX, numZ));
final String path =
"worlds." + area.getWorldName() + ".areas." + area.getId() + '-'
+ builder.minimumId() + '-' + builder.maximumId();
Runnable run = () -> {
if (offsetX != 0) {
this.worldConfiguration.set(path + ".road.offset.x", offsetX);
this.worldConfiguration
.set(path + ".road.offset.x", offsetX);
}
if (offsetZ != 0) {
this.worldConfiguration.set(path + ".road.offset.z", offsetZ);
this.worldConfiguration
.set(path + ".road.offset.z", offsetZ);
}
final String world = this.setupUtils.setupWorld(builder);
if (this.worldUtil.isWorld(world)) {
@ -349,14 +369,13 @@ public class Area extends SubCommand {
player.teleport(this.worldUtil.getSpawn(world),
TeleportCause.COMMAND);
if (area.getTerrain() != PlotAreaTerrainType.ALL) {
this.regionManager.largeRegionTask(world, region,
new RunnableVal<BlockVector2>() {
@Override public void run(BlockVector2 value) {
AugmentedUtils
.generate(null, world, value.getX(),
value.getZ(), null);
}
}, null);
QueueCoordinator queue =
blockQueue.getNewQueue(worldUtil.getWeWorld(world));
queue.setChunkConsumer(chunk -> AugmentedUtils
.generate(null, world, chunk.getX(), chunk.getZ(),
null));
queue.addReadChunks(region.getChunks());
queue.enqueue();
}
} else {
player.sendMessage(
@ -383,15 +402,17 @@ public class Area extends SubCommand {
}
PlotAreaBuilder builder = PlotAreaBuilder.newBuilder();
builder.worldName(split[0]);
final HybridPlotWorld pa = this.hybridPlotWorldFactory.create(builder.worldName(),
id, PlotSquared.platform().getDefaultGenerator(), null, null);
final HybridPlotWorld pa = this.hybridPlotWorldFactory
.create(builder.worldName(), id,
PlotSquared.platform().getDefaultGenerator(), null, null);
PlotArea other = this.plotAreaManager.getPlotArea(pa.getWorldName(), id);
if (other != null && Objects.equals(pa.getId(), other.getId())) {
player.sendMessage(TranslatableCaption.of("setup.setup_world_taken"),
Template.of("value", pa.toString()));
return false;
}
Set<PlotArea> areas = this.plotAreaManager.getPlotAreasSet(pa.getWorldName());
Set<PlotArea> areas =
this.plotAreaManager.getPlotAreasSet(pa.getWorldName());
if (!areas.isEmpty()) {
PlotArea area = areas.iterator().next();
pa.setType(area.getType());
@ -477,7 +498,8 @@ public class Area extends SubCommand {
if (!this.worldConfiguration.contains(path)) {
this.worldConfiguration.createSection(path);
}
ConfigurationSection section = this.worldConfiguration.getConfigurationSection(path);
ConfigurationSection section =
this.worldConfiguration.getConfigurationSection(path);
pa.saveConfiguration(section);
pa.loadConfiguration(section);
builder.plotManager(PlotSquared.platform().getPluginName());
@ -627,7 +649,8 @@ public class Area extends SubCommand {
);
return false;
}
final List<PlotArea> areas = new ArrayList<>(Arrays.asList(this.plotAreaManager.getAllPlotAreas()));
final List<PlotArea> areas =
new ArrayList<>(Arrays.asList(this.plotAreaManager.getAllPlotAreas()));
paginate(player, areas, 8, page,
new RunnableVal3<Integer, PlotArea, CaptionHolder>() {
@Override public void run(Integer i, PlotArea area, CaptionHolder caption) {
@ -642,7 +665,8 @@ public class Area extends SubCommand {
PlotId max = area.getMax();
name = area.getWorldName() + ';' + area.getId() + ';' + min + ';'
+ max;
int size = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1);
int size =
(max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1);
percent = claimed == 0 ? 0 : size / (double) claimed;
region = area.getRegion().toString();
} else {
@ -694,15 +718,13 @@ public class Area extends SubCommand {
);
return false;
}
this.regionManager.largeRegionTask(area.getWorldName(), area.getRegion(),
new RunnableVal<BlockVector2>() {
@Override public void run(BlockVector2 value) {
AugmentedUtils
.generate(null, area.getWorldName(), value.getX(), value.getZ(),
null);
}
}, () -> player.sendMessage(TranslatableCaption.of("single.regeneration_complete"))
);
QueueCoordinator queue =
blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
queue.setChunkConsumer(chunk -> AugmentedUtils
.generate(null, area.getWorldName(), chunk.getX(), chunk.getZ(), null));
queue.addReadChunks(area.getRegion().getChunks());
queue.setCompleteTask(() -> player.sendMessage(TranslatableCaption.of("single.regeneration_complete")));
queue.enqueue();
return true;
}
case "goto":
@ -735,11 +757,13 @@ public class Area extends SubCommand {
} else {
CuboidRegion region = area.getRegion();
center = Location.at(area.getWorldName(), region.getMinimumPoint().getX()
+ (region.getMaximumPoint().getX() - region.getMinimumPoint().getX()) / 2,
+ (region.getMaximumPoint().getX() - region.getMinimumPoint().getX()) / 2,
0, region.getMinimumPoint().getZ()
+ (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ()) / 2);
this.worldUtil.getHighestBlock(area.getWorldName(), center.getX(), center.getZ(), y ->
player.teleport(center.withY(1 + y), TeleportCause.COMMAND));
+ (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ())
/ 2);
this.worldUtil
.getHighestBlock(area.getWorldName(), center.getX(), center.getZ(),
y -> player.teleport(center.withY(1 + y), TeleportCause.COMMAND));
}
return true;
case "delete":

View File

@ -42,7 +42,7 @@ import com.plotsquared.core.util.Permissions;
import com.plotsquared.core.util.task.RunnableVal2;
import com.plotsquared.core.util.task.RunnableVal3;
import net.kyori.adventure.text.minimessage.Template;
import com.plotsquared.core.util.task.TaskManager;
import javax.annotation.Nonnull;
import java.util.concurrent.CompletableFuture;
@ -94,7 +94,7 @@ public class Clear extends Command {
final long start = System.currentTimeMillis();
boolean result = plot.clear(true, false, () -> {
plot.unlink();
this.blockQueue.addEmptyTask(() -> {
TaskManager.runTask(() -> {
plot.removeRunning();
// If the state changes, then mark it as no longer done
if (DoneFlag.isDone(plot)) {

View File

@ -51,15 +51,6 @@ public interface CommandCaller {
*/
boolean hasPermission(@Nonnull String permission);
/**
* Checks if this object contains an override for the specified
* permission, by fully qualified name
*
* @param permission Name of the permission
* @return true if the permission is set, otherwise false
*/
boolean isPermissionSet(@Nonnull String permission);
/**
* Get the type of the caller
*

View File

@ -33,8 +33,8 @@ import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.StringMan;
import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.entity.EntityCategories;
import com.plotsquared.core.util.entity.EntityCategory;
import com.plotsquared.core.util.query.PlotQuery;
@ -63,12 +63,12 @@ public class Debug extends SubCommand {
private static final Logger logger = LoggerFactory.getLogger("P2/" + Debug.class.getSimpleName());
private final PlotAreaManager plotAreaManager;
private final RegionManager regionManager;
private final WorldUtil worldUtil;
@Inject public Debug(@Nonnull final PlotAreaManager plotAreaManager,
@Nonnull final RegionManager regionManager) {
@Nonnull final WorldUtil worldUtil) {
this.plotAreaManager = plotAreaManager;
this.regionManager = regionManager;
this.worldUtil = worldUtil;
}
@Override public boolean onCommand(PlotPlayer<?> player, String[] args) {
@ -82,9 +82,9 @@ public class Debug extends SubCommand {
if (args.length > 0 && "loadedchunks".equalsIgnoreCase(args[0])) {
final long start = System.currentTimeMillis();
player.sendMessage(TranslatableCaption.of("debug.fetching_loaded_chunks"));
TaskManager.runTaskAsync(() -> player.sendMessage(StaticCaption.of("Loaded chunks: " + this.regionManager.getChunkChunks(player.getLocation().getWorldName()).size() + "(" + (
System.currentTimeMillis() - start) + "ms) using thread: " + Thread
.currentThread().getName())));
TaskManager.runTaskAsync(() -> player.sendMessage(StaticCaption
.of("Loaded chunks: " + this.worldUtil.getChunkChunks(player.getLocation().getWorldName()).size() + "(" + (System.currentTimeMillis()
- start) + "ms) using thread: " + Thread.currentThread().getName())));
return true;
}
if (args.length > 0 && "uuids".equalsIgnoreCase(args[0])) {

View File

@ -35,6 +35,7 @@ import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotManager;
import net.kyori.adventure.text.minimessage.Template;
import com.plotsquared.core.queue.QueueCoordinator;
import javax.annotation.Nonnull;
import java.util.Arrays;
@ -91,9 +92,10 @@ public class DebugRoadRegen extends SubCommand {
player.sendMessage(TranslatableCaption.of("debug.requires_unmerged"));
} else {
PlotManager manager = area.getPlotManager();
manager.createRoadEast(plot);
manager.createRoadSouth(plot);
manager.createRoadSouthEast(plot);
QueueCoordinator queue = area.getQueue();
manager.createRoadEast(plot, queue);
manager.createRoadSouth(plot, queue);
manager.createRoadSouthEast(plot, queue);
player.sendMessage(
TranslatableCaption.of("debugroadregen.regen_done"),
Template.of("value", String.valueOf(plot.getId()))

View File

@ -25,12 +25,8 @@
*/
package com.plotsquared.core.command;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.configuration.caption.StaticCaption;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.RunnableVal2;
import com.plotsquared.core.util.task.RunnableVal3;
@ -50,12 +46,13 @@ public class Relight extends Command {
public CompletableFuture<Boolean> execute(final PlotPlayer<?> player, String[] args,
RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone) {
final Plot plot = player.getCurrentPlot();
player.sendMessage(StaticCaption.of("Not implemented."));
/* final Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return CompletableFuture.completedFuture(false);
}
final LocalBlockQueue queue = plot.getArea().getQueue(false);
final QueueCoordinator queue = plot.getArea().getQueue(false);
ChunkManager.chunkTask(plot, new RunnableVal<int[]>() {
@Override public void run(int[] value) {
queue.fixChunkLighting(value[0], value[1]);
@ -63,7 +60,7 @@ public class Relight extends Command {
}, () -> {
plot.refreshChunks();
player.sendMessage(TranslatableCaption.of("setblock.set_block_action_finished"));
}, 5);
}, 5);*/
return CompletableFuture.completedFuture(true);
}

View File

@ -35,7 +35,7 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.PatternUtil;
import com.plotsquared.core.util.Permissions;
import com.plotsquared.core.util.StringMan;
@ -70,13 +70,8 @@ public class Set extends SubCommand {
public static final String[] aliases = new String[] {"b", "w", "wf", "a", "h"};
private final SetCommand component;
private final WorldUtil worldUtil;
private final GlobalBlockQueue blockQueue;
@Inject public Set(@Nonnull final WorldUtil worldUtil,
@Nonnull final GlobalBlockQueue blockQueue) {
this.worldUtil = worldUtil;
this.blockQueue = blockQueue;
@Inject public Set(@Nonnull final WorldUtil worldUtil) {
this.component = new SetCommand() {
@Override public String getId() {
@ -158,11 +153,13 @@ public class Set extends SubCommand {
BackupManager.backup(player, plot, () -> {
plot.addRunning();
QueueCoordinator queue = plotArea.getQueue();
for (Plot current : plot.getConnectedPlots()) {
current.setComponent(component, pattern);
current.setComponent(component, pattern, queue);
}
queue.setCompleteTask(plot::removeRunning);
queue.enqueue();
player.sendMessage(TranslatableCaption.of("working.generating_component"));
blockQueue.addEmptyTask(plot::removeRunning);
});
return true;
}

View File

@ -41,7 +41,6 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.setup.PlotAreaBuilder;
import com.plotsquared.core.setup.SettingsNodesWrapper;
import com.plotsquared.core.util.FileBytes;
@ -71,20 +70,17 @@ public class Template extends SubCommand {
private final YamlConfiguration worldConfiguration;
private final File worldFile;
private final SetupUtils setupUtils;
private final GlobalBlockQueue globalBlockQueue;
private final WorldUtil worldUtil;
@Inject public Template(@Nonnull final PlotAreaManager plotAreaManager,
@WorldConfig @Nonnull final YamlConfiguration worldConfiguration,
@WorldFile @Nonnull final File worldFile,
@Nonnull final SetupUtils setupUtils,
@Nonnull final GlobalBlockQueue globalBlockQueue,
@Nonnull final WorldUtil worldUtil) {
this.plotAreaManager = plotAreaManager;
this.worldConfiguration = worldConfiguration;
this.worldFile = worldFile;
this.setupUtils = setupUtils;
this.globalBlockQueue = globalBlockQueue;
this.worldUtil = worldUtil;
}
@ -227,7 +223,7 @@ public class Template extends SubCommand {
.worldName(world);
this.setupUtils.setupWorld(builder);
this.globalBlockQueue.addEmptyTask(() -> {
TaskManager.runTask(() -> {
player.sendMessage(TranslatableCaption.of("debugimportworlds.done"));
player.teleport(this.worldUtil.getSpawn(world), TeleportCause.COMMAND);
});

View File

@ -35,7 +35,7 @@ import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.expiration.ExpireManager;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.RegionUtil;
import com.plotsquared.core.util.WorldUtil;
@ -98,7 +98,7 @@ public class Trim extends SubCommand {
if (ExpireManager.IMP != null) {
plots.removeAll(ExpireManager.IMP.getPendingExpired());
}
result.value1 = new HashSet<>(PlotSquared.platform().getRegionManager().getChunkChunks(world));
result.value1 = new HashSet<>(PlotSquared.platform().getWorldUtil().getChunkChunks(world));
result.value2 = new HashSet<>();
StaticCaption.of(" - MCA #: " + result.value1.size());
StaticCaption.of(" - CHUNKS: " + (result.value1.size() * 1024) + " (max)");
@ -190,7 +190,7 @@ public class Trim extends SubCommand {
}
}
}
final LocalBlockQueue queue = blockQueue.getNewQueue(world, false);
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(world));
TaskManager.getPlatformImplementation().objectTask(chunks, new RunnableVal<BlockVector2>() {
@Override public void run(BlockVector2 value) {
queue.regenChunk(value.getX(), value.getZ());

View File

@ -37,6 +37,7 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotInventory;
import com.plotsquared.core.plot.PlotItemStack;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.EconHandler;
import com.plotsquared.core.util.InventoryUtil;
import com.plotsquared.core.util.PatternUtil;
@ -70,8 +71,7 @@ public class ComponentPresetManager {
private final EconHandler econHandler;
private final InventoryUtil inventoryUtil;
@Inject public ComponentPresetManager(@Nullable final EconHandler econHandler, @Nonnull final
InventoryUtil inventoryUtil) {
@Inject public ComponentPresetManager(@Nullable final EconHandler econHandler, @Nonnull final InventoryUtil inventoryUtil) {
this.econHandler = econHandler;
this.inventoryUtil = inventoryUtil;
final File file = new File(Objects.requireNonNull(PlotSquared.platform()).getDirectory(), "components.yml");
@ -105,15 +105,13 @@ public class ComponentPresetManager {
this.guiName = yamlConfiguration.getString("title", "&6Plot Components");
if (yamlConfiguration.contains("presets")) {
this.presets = yamlConfiguration.getMapList("presets").stream().map(o -> (Map<String, Object>) o)
.map(ComponentPreset::deserialize).collect(Collectors.toList());
this.presets = yamlConfiguration.getMapList("presets").stream().map(o -> (Map<String, Object>) o).map(ComponentPreset::deserialize)
.collect(Collectors.toList());
} else {
final List<ComponentPreset> defaultPreset =
Collections.singletonList(new ComponentPreset(ClassicPlotManagerComponent.FLOOR,
"##wool", 0, "", "&6D&ai&cs&ec&bo &2F&3l&do&9o&4r",
final List<ComponentPreset> defaultPreset = Collections.singletonList(
new ComponentPreset(ClassicPlotManagerComponent.FLOOR, "##wool", 0, "", "&6D&ai&cs&ec&bo &2F&3l&do&9o&4r",
Arrays.asList("&6Spice up your plot floor"), ItemTypes.YELLOW_WOOL));
yamlConfiguration.set("presets", defaultPreset.stream().map(ComponentPreset::serialize)
.collect(Collectors.toList()));
yamlConfiguration.set("presets", defaultPreset.stream().map(ComponentPreset::serialize).collect(Collectors.toList()));
try {
yamlConfiguration.save(file);
} catch (final IOException e) {
@ -148,8 +146,7 @@ public class ComponentPresetManager {
final List<ComponentPreset> allowedPresets = new ArrayList<>(this.presets.size());
for (final ComponentPreset componentPreset : this.presets) {
if (!componentPreset.getPermission().isEmpty() && !Permissions
.hasPermission(player, componentPreset.getPermission())) {
if (!componentPreset.getPermission().isEmpty() && !Permissions.hasPermission(player, componentPreset.getPermission())) {
continue;
}
allowedPresets.add(componentPreset);
@ -194,11 +191,13 @@ public class ComponentPresetManager {
BackupManager.backup(player, plot, () -> {
plot.addRunning();
QueueCoordinator queue = plot.getArea().getQueue();
for (Plot current : plot.getConnectedPlots()) {
current.setComponent(componentPreset.getComponent().name(), pattern);
current.setComponent(componentPreset.getComponent().name(), pattern, queue);
}
queue.setCompleteTask(plot::removeRunning);
queue.enqueue();
player.sendMessage(TranslatableCaption.of("working.generating_component"));
PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(plot::removeRunning);
});
return false;
}

View File

@ -8,7 +8,7 @@
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) ${year} IntellectualSites
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -23,7 +23,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.configuration.caption;
public class CaptionHolder {

View File

@ -8,7 +8,7 @@
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) ${year} IntellectualSites
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -31,10 +31,10 @@ import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotAreaTerrainType;
import com.plotsquared.core.plot.PlotAreaType;
import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.AreaBoundDelegateLocalBlockQueue;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.queue.LocationOffsetDelegateLocalBlockQueue;
import com.plotsquared.core.queue.ScopedLocalBlockQueue;
import com.plotsquared.core.queue.AreaBoundDelegateQueueCoordinator;
import com.plotsquared.core.queue.LocationOffsetDelegateQueueCoordinator;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.RegionUtil;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BlockState;
@ -54,8 +54,11 @@ public class AugmentedUtils {
enabled = true;
}
public static boolean generate(@Nullable Object chunkObject, @Nonnull final String world,
final int chunkX, final int chunkZ, LocalBlockQueue queue) {
public static boolean generate(@Nullable Object chunkObject,
@Nonnull final String world,
final int chunkX,
final int chunkZ,
QueueCoordinator queue) {
if (!enabled) {
return false;
}
@ -71,6 +74,7 @@ public class AugmentedUtils {
if (areas.isEmpty()) {
return false;
}
boolean enqueue = false;
boolean generationResult = false;
for (final PlotArea area : areas) {
// A normal plot world may not contain any clusters
@ -80,16 +84,19 @@ public class AugmentedUtils {
}
// This means that full vanilla generation is used
// so we do not interfere
if (area.getTerrain() == PlotAreaTerrainType.ALL) {
if (area.getTerrain() == PlotAreaTerrainType.ALL || !area.contains(blockX, blockZ)) {
continue;
}
IndependentPlotGenerator generator = area.getGenerator();
// Mask
if (queue == null) {
queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world, false);
queue.setChunkObject(chunkObject);
enqueue = true;
queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(world));
if (chunkObject != null) {
queue.setChunkObject(chunkObject);
}
}
LocalBlockQueue primaryMask;
QueueCoordinator primaryMask;
// coordinates
int relativeBottomX;
int relativeBottomZ;
@ -102,14 +109,13 @@ public class AugmentedUtils {
relativeTopX = Math.min(15, area.getRegion().getMaximumPoint().getX() - blockX);
relativeTopZ = Math.min(15, area.getRegion().getMaximumPoint().getZ() - blockZ);
primaryMask = new AreaBoundDelegateLocalBlockQueue(area, queue);
primaryMask = new AreaBoundDelegateQueueCoordinator(area, queue);
} else {
relativeBottomX = relativeBottomZ = 0;
relativeTopX = relativeTopZ = 15;
primaryMask = queue;
}
LocalBlockQueue secondaryMask;
QueueCoordinator secondaryMask;
BlockState air = BlockTypes.AIR.getDefaultState();
if (area.getTerrain() == PlotAreaTerrainType.ROAD) {
PlotManager manager = area.getPlotManager();
@ -133,8 +139,7 @@ public class AugmentedUtils {
continue;
}
generationResult = true;
secondaryMask = new LocationOffsetDelegateLocalBlockQueue(canPlace, blockX, blockZ,
primaryMask);
secondaryMask = new LocationOffsetDelegateQueueCoordinator(canPlace, blockX, blockZ, primaryMask);
} else {
secondaryMask = primaryMask;
for (int x = relativeBottomX; x <= relativeTopX; x++) {
@ -146,20 +151,22 @@ public class AugmentedUtils {
}
generationResult = true;
}
primaryMask.setChunkObject(chunkObject);
primaryMask.setForceSync(true);
secondaryMask.setChunkObject(chunkObject);
secondaryMask.setForceSync(true);
if (chunkObject != null) {
primaryMask.setChunkObject(chunkObject);
}
if (chunkObject != null) {
secondaryMask.setChunkObject(chunkObject);
}
ScopedLocalBlockQueue scoped =
new ScopedLocalBlockQueue(secondaryMask, Location.at(world, blockX, 0, blockZ),
Location.at(world, blockX + 15, 255, blockZ + 15));
ScopedQueueCoordinator scoped =
new ScopedQueueCoordinator(secondaryMask, Location.at(world, blockX, 0, blockZ), Location.at(world, blockX + 15, 255, blockZ + 15));
generator.generateChunk(scoped, area);
generator.populateChunk(scoped, area);
scoped.setForceSync(true);
scoped.enqueue();
}
if (queue != null) {
queue.setForceSync(true);
queue.flush();
if (enqueue) {
queue.enqueue();
}
return generationResult;
}

View File

@ -25,7 +25,6 @@
*/
package com.plotsquared.core.generator;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.location.Direction;
import com.plotsquared.core.location.Location;
@ -33,15 +32,17 @@ import com.plotsquared.core.plot.BlockBucket;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotAreaTerrainType;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.BlockUtil;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.task.TaskManager;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
@ -53,98 +54,140 @@ public class ClassicPlotManager extends SquarePlotManager {
private final ClassicPlotWorld classicPlotWorld;
private final RegionManager regionManager;
public ClassicPlotManager(@Nonnull final ClassicPlotWorld classicPlotWorld,
@Nonnull final RegionManager regionManager) {
public ClassicPlotManager(@Nonnull final ClassicPlotWorld classicPlotWorld, @Nonnull final RegionManager regionManager) {
super(classicPlotWorld, regionManager);
this.classicPlotWorld = classicPlotWorld;
this.regionManager = regionManager;
}
@Override public boolean setComponent(PlotId plotId, String component, Pattern blocks) {
final Optional<ClassicPlotManagerComponent> componentOptional =
ClassicPlotManagerComponent.fromString(component);
@Override public boolean setComponent(@Nonnull PlotId plotId,
@Nonnull String component,
@Nonnull Pattern blocks,
@Nullable QueueCoordinator queue) {
final Optional<ClassicPlotManagerComponent> componentOptional = ClassicPlotManagerComponent.fromString(component);
if (componentOptional.isPresent()) {
switch (componentOptional.get()) {
case FLOOR:
return setFloor(plotId, blocks);
return setFloor(plotId, blocks, queue);
case WALL:
return setWallFilling(plotId, blocks);
return setWallFilling(plotId, blocks, queue);
case AIR:
return setAir(plotId, blocks);
return setAir(plotId, blocks, queue);
case MAIN:
return setMain(plotId, blocks);
return setMain(plotId, blocks, queue);
case MIDDLE:
return setMiddle(plotId, blocks);
return setMiddle(plotId, blocks, queue);
case OUTLINE:
return setOutline(plotId, blocks);
return setOutline(plotId, blocks, queue);
case BORDER:
return setWall(plotId, blocks);
return setWall(plotId, blocks, queue);
case ALL:
return setAll(plotId, blocks);
return setAll(plotId, blocks, queue);
}
}
return false;
}
@Override public boolean unClaimPlot(Plot plot, Runnable whenDone) {
setWallFilling(plot.getId(), classicPlotWorld.WALL_FILLING.toPattern());
if (!classicPlotWorld.WALL_BLOCK.isAir() || !classicPlotWorld.WALL_BLOCK
.equals(classicPlotWorld.CLAIMED_WALL_BLOCK)) {
setWall(plot.getId(), classicPlotWorld.WALL_BLOCK.toPattern());
@Override public boolean unClaimPlot(@Nonnull Plot plot, @Nullable Runnable whenDone, @Nullable QueueCoordinator queue) {
setWallFilling(plot.getId(), classicPlotWorld.WALL_FILLING.toPattern(), queue);
if (classicPlotWorld.PLACE_TOP_BLOCK && (!classicPlotWorld.WALL_BLOCK.isAir() || !classicPlotWorld.WALL_BLOCK
.equals(classicPlotWorld.CLAIMED_WALL_BLOCK))) {
setWall(plot.getId(), classicPlotWorld.WALL_BLOCK.toPattern(), queue);
}
return PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(whenDone);
TaskManager.runTask(whenDone);
return true;
}
public boolean setFloor(PlotId plotId, Pattern blocks) {
/**
* Set the plot floor
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setFloor(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
Plot plot = classicPlotWorld.getPlotAbs(plotId);
if (plot.isBasePlot()) {
return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks,
classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.PLOT_HEIGHT);
if (plot != null && plot.isBasePlot()) {
return this.regionManager
.setCuboids(classicPlotWorld, plot.getRegions(), blocks, classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.PLOT_HEIGHT, queue);
}
return false;
}
public boolean setAll(PlotId plotId, Pattern blocks) {
/**
* Sets the plot main, floor and air areas.
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setAll(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
Plot plot = classicPlotWorld.getPlotAbs(plotId);
if (plot.isBasePlot()) {
return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, getWorldHeight());
if (plot != null && plot.isBasePlot()) {
return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, getWorldHeight(), queue);
}
return false;
}
public boolean setAir(PlotId plotId, Pattern blocks) {
/**
* Sets the plot air region.
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setAir(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
Plot plot = classicPlotWorld.getPlotAbs(plotId);
if (plot.isBasePlot()) {
return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks,
classicPlotWorld.PLOT_HEIGHT + 1, getWorldHeight());
if (plot != null && plot.isBasePlot()) {
return this.regionManager
.setCuboids(classicPlotWorld, plot.getRegions(), blocks, classicPlotWorld.PLOT_HEIGHT + 1, getWorldHeight(), queue);
}
return false;
}
public boolean setMain(PlotId plotId, Pattern blocks) {
/**
* Sets the plot main blocks.
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setMain(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
Plot plot = classicPlotWorld.getPlotAbs(plotId);
if (plot.isBasePlot()) {
return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1,
classicPlotWorld.PLOT_HEIGHT - 1);
if (plot == null || plot.isBasePlot()) {
return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, classicPlotWorld.PLOT_HEIGHT - 1, queue);
}
return false;
}
public boolean setMiddle(PlotId plotId, Pattern blocks) {
/**
* Set the middle plot block to a Pattern
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setMiddle(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
Plot plot = classicPlotWorld.getPlotAbs(plotId);
if (!plot.isBasePlot()) {
if (plot == null || !plot.isBasePlot()) {
return false;
}
Location[] corners = plot.getCorners();
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
int x = MathMan.average(corners[0].getX(), corners[1].getX());
int z = MathMan.average(corners[0].getZ(), corners[1].getZ());
queue.setBlock(x, classicPlotWorld.PLOT_HEIGHT, z, blocks);
return queue.enqueue();
return !enqueue || queue.enqueue();
}
public boolean setOutline(PlotId plotId, Pattern blocks) {
/**
* Set a plot's outline
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setOutline(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
if (classicPlotWorld.ROAD_WIDTH == 0) {
return false;
}
@ -155,9 +198,18 @@ public class ClassicPlotManager extends SquarePlotManager {
return true;
}
Plot plot = classicPlotWorld.getPlotAbs(plotId);
if (plot == null) {
return false;
}
Location bottom = plot.getBottomAbs();
Location top = plot.getExtendedTopAbs();
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
int maxY = classicPlotWorld.getPlotManager().getWorldHeight();
if (!plot.getMerged(Direction.NORTH)) {
int z = bottom.getZ();
@ -194,19 +246,21 @@ public class ClassicPlotManager extends SquarePlotManager {
}
if (plot.isBasePlot()) {
for (CuboidRegion region : plot.getRegions()) {
Location pos1 =
Location.at(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(),
maxY, region.getMinimumPoint().getZ());
Location pos2 =
Location.at(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(),
maxY, region.getMaximumPoint().getZ());
Location pos1 = Location.at(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), maxY, region.getMinimumPoint().getZ());
Location pos2 = Location.at(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), maxY, region.getMaximumPoint().getZ());
queue.setCuboid(pos1, pos2, blocks);
}
}
return queue.enqueue();
return !enqueue || queue.enqueue();
}
public boolean setWallFilling(PlotId plotId, Pattern blocks) {
/**
* Set the wall filling for a plot
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setWallFilling(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
if (classicPlotWorld.ROAD_WIDTH == 0) {
return false;
}
@ -217,11 +271,18 @@ public class ClassicPlotManager extends SquarePlotManager {
return true;
}
Plot plot = classicPlotWorld.getPlotAbs(plotId);
Location bot = plot.getExtendedBottomAbs()
.subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0,
plot.getMerged(Direction.NORTH) ? 0 : 1);
if (plot == null) {
return false;
}
Location bot = plot.getExtendedBottomAbs().subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0, plot.getMerged(Direction.NORTH) ? 0 : 1);
Location top = plot.getExtendedTopAbs().add(1, 0, 1);
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
if (!plot.getMerged(Direction.NORTH)) {
int z = bot.getZ();
for (int x = bot.getX(); x < top.getX(); x++) {
@ -240,8 +301,7 @@ public class ClassicPlotManager extends SquarePlotManager {
}
if (!plot.getMerged(Direction.SOUTH)) {
int z = top.getZ();
for (int x = bot.getX();
x < top.getX() + (plot.getMerged(Direction.EAST) ? 0 : 1); x++) {
for (int x = bot.getX(); x < top.getX() + (plot.getMerged(Direction.EAST) ? 0 : 1); x++) {
for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks);
}
@ -249,17 +309,22 @@ public class ClassicPlotManager extends SquarePlotManager {
}
if (!plot.getMerged(Direction.EAST)) {
int x = top.getX();
for (int z = bot.getZ();
z < top.getZ() + (plot.getMerged(Direction.SOUTH) ? 0 : 1); z++) {
for (int z = bot.getZ(); z < top.getZ() + (plot.getMerged(Direction.SOUTH) ? 0 : 1); z++) {
for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks);
}
}
}
return queue.enqueue();
return !enqueue || queue.enqueue();
}
public boolean setWall(PlotId plotId, Pattern blocks) {
/**
* Set a plot's wall top block only
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public boolean setWall(@Nonnull PlotId plotId, @Nonnull Pattern blocks, @Nullable QueueCoordinator queue) {
if (classicPlotWorld.ROAD_WIDTH == 0) {
return false;
}
@ -270,11 +335,18 @@ public class ClassicPlotManager extends SquarePlotManager {
return true;
}
Plot plot = classicPlotWorld.getPlotAbs(plotId);
Location bot = plot.getExtendedBottomAbs()
.subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0,
plot.getMerged(Direction.NORTH) ? 0 : 1);
if (plot == null) {
return false;
}
Location bot = plot.getExtendedBottomAbs().subtract(plot.getMerged(Direction.WEST) ? 0 : 1, 0, plot.getMerged(Direction.NORTH) ? 0 : 1);
Location top = plot.getExtendedTopAbs().add(1, 0, 1);
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
enqueue = true;
queue = classicPlotWorld.getQueue();
}
int y = classicPlotWorld.WALL_HEIGHT + 1;
if (!plot.getMerged(Direction.NORTH)) {
int z = bot.getZ();
@ -290,237 +362,239 @@ public class ClassicPlotManager extends SquarePlotManager {
}
if (!plot.getMerged(Direction.SOUTH)) {
int z = top.getZ();
for (int x = bot.getX();
x < top.getX() + (plot.getMerged(Direction.EAST) ? 0 : 1); x++) {
for (int x = bot.getX(); x < top.getX() + (plot.getMerged(Direction.EAST) ? 0 : 1); x++) {
queue.setBlock(x, y, z, blocks);
}
}
if (!plot.getMerged(Direction.EAST)) {
int x = top.getX();
for (int z = bot.getZ();
z < top.getZ() + (plot.getMerged(Direction.SOUTH) ? 0 : 1); z++) {
for (int z = bot.getZ(); z < top.getZ() + (plot.getMerged(Direction.SOUTH) ? 0 : 1); z++) {
queue.setBlock(x, y, z, blocks);
}
}
return queue.enqueue();
return !enqueue || queue.enqueue();
}
/**
* PLOT MERGING.
*/
@Override public boolean createRoadEast(Plot plot) {
@Override public boolean createRoadEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue) {
Location pos1 = getPlotBottomLocAbs(plot.getId());
Location pos2 = getPlotTopLocAbs(plot.getId());
int sx = pos2.getX() + 1;
int ex = sx + classicPlotWorld.ROAD_WIDTH - 1;
int sz = pos1.getZ() - 2;
int ez = pos2.getZ() + 2;
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
int maxY = getWorldHeight();
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx,
Math.min(classicPlotWorld.WALL_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, maxY, ez - 1),
BlockTypes.AIR.getDefaultState());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, 0, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, 0, ez - 1),
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, Math.min(classicPlotWorld.WALL_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, maxY, ez - 1), BlockTypes.AIR.getDefaultState());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, 0, sz + 1), Location.at(classicPlotWorld.getWorldName(), ex, 0, ez - 1),
BlockUtil.get((short) 7, (byte) 0));
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1),
classicPlotWorld.WALL_FILLING.toPattern());
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1,
sz + 1),
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1,
ez - 1), classicPlotWorld.WALL_BLOCK.toPattern());
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1), classicPlotWorld.WALL_FILLING.toPattern());
if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), classicPlotWorld.WALL_BLOCK.toPattern());
}
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), ex, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT, ez - 1),
classicPlotWorld.WALL_FILLING.toPattern());
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1,
sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1,
ez - 1), classicPlotWorld.WALL_BLOCK.toPattern());
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT, ez - 1), classicPlotWorld.WALL_FILLING.toPattern());
if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), classicPlotWorld.WALL_BLOCK.toPattern());
}
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT,
ez - 1), classicPlotWorld.ROAD_BLOCK.toPattern());
return queue.enqueue();
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), classicPlotWorld.ROAD_BLOCK.toPattern());
return !enqueue || queue.enqueue();
}
@Override public boolean createRoadSouth(Plot plot) {
@Override public boolean createRoadSouth(@Nonnull Plot plot, @Nullable QueueCoordinator queue) {
Location pos1 = getPlotBottomLocAbs(plot.getId());
Location pos2 = getPlotTopLocAbs(plot.getId());
int sz = pos2.getZ() + 1;
int ez = sz + classicPlotWorld.ROAD_WIDTH - 1;
int sx = pos1.getX() - 2;
int ex = pos2.getX() + 2;
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1,
Math.min(classicPlotWorld.WALL_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1,
classicPlotWorld.getPlotManager().getWorldHeight(), ez),
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, Math.min(classicPlotWorld.WALL_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getPlotManager().getWorldHeight(), ez),
BlockTypes.AIR.getDefaultState());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 0, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez),
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 0, sz), Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez),
BlockUtil.get((short) 7, (byte) 0));
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, sz),
classicPlotWorld.WALL_FILLING.toPattern());
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1,
sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1,
sz), classicPlotWorld.WALL_BLOCK.toPattern());
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, sz), classicPlotWorld.WALL_FILLING.toPattern());
if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, sz), classicPlotWorld.WALL_BLOCK.toPattern());
}
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, ez),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, ez),
classicPlotWorld.WALL_FILLING.toPattern());
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1,
ez),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1,
ez), classicPlotWorld.WALL_BLOCK.toPattern());
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, ez), classicPlotWorld.WALL_FILLING.toPattern());
if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1, ez),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, ez), classicPlotWorld.WALL_BLOCK.toPattern());
}
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT,
ez - 1), classicPlotWorld.ROAD_BLOCK.toPattern());
return queue.enqueue();
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), classicPlotWorld.ROAD_BLOCK.toPattern());
return !enqueue || queue.enqueue();
}
@Override public boolean createRoadSouthEast(Plot plot) {
@Override public boolean createRoadSouthEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue) {
Location pos2 = getPlotTopLocAbs(plot.getId());
int sx = pos2.getX() + 1;
int ex = sx + classicPlotWorld.ROAD_WIDTH - 1;
int sz = pos2.getZ() + 1;
int ez = sz + classicPlotWorld.ROAD_WIDTH - 1;
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.ROAD_HEIGHT + 1,
sz + 1), Location.at(classicPlotWorld.getWorldName(), ex - 1,
classicPlotWorld.getPlotManager().getWorldHeight(), ez - 1),
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.ROAD_HEIGHT + 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getPlotManager().getWorldHeight(), ez - 1),
BlockTypes.AIR.getDefaultState());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 0, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez - 1),
BlockUtil.get((short) 7, (byte) 0));
Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez - 1), BlockUtil.get((short) 7, (byte) 0));
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT,
ez - 1), classicPlotWorld.ROAD_BLOCK.toPattern());
return queue.enqueue();
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), classicPlotWorld.ROAD_BLOCK.toPattern());
return !enqueue || queue.enqueue();
}
@Override public boolean removeRoadEast(Plot plot) {
@Override public boolean removeRoadEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue) {
Location pos1 = getPlotBottomLocAbs(plot.getId());
Location pos2 = getPlotTopLocAbs(plot.getId());
int sx = pos2.getX() + 1;
int ex = sx + classicPlotWorld.ROAD_WIDTH - 1;
int sz = pos1.getZ() - 1;
int ez = pos2.getZ() + 1;
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx,
Math.min(classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex,
classicPlotWorld.getPlotManager().getWorldHeight(), ez),
BlockTypes.AIR.getDefaultState());
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
queue
.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, Math.min(classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez),
BlockTypes.AIR.getDefaultState());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1,
ez - 1), classicPlotWorld.MAIN_BLOCK.toPattern());
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.PLOT_HEIGHT, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT, ez - 1),
classicPlotWorld.TOP_BLOCK.toPattern());
return queue.enqueue();
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez - 1), classicPlotWorld.MAIN_BLOCK.toPattern());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.PLOT_HEIGHT, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT, ez - 1), classicPlotWorld.TOP_BLOCK.toPattern());
return !enqueue || queue.enqueue();
}
@Override public boolean removeRoadSouth(Plot plot) {
@Override public boolean removeRoadSouth(@Nonnull Plot plot, @Nullable QueueCoordinator queue) {
Location pos1 = getPlotBottomLocAbs(plot.getId());
Location pos2 = getPlotTopLocAbs(plot.getId());
int sz = pos2.getZ() + 1;
int ez = sz + classicPlotWorld.ROAD_WIDTH - 1;
int sx = pos1.getX() - 1;
int ex = pos2.getX() + 1;
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx,
Math.min(classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex,
classicPlotWorld.getPlotManager().getWorldHeight(), ez),
BlockTypes.AIR.getDefaultState());
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
queue
.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, Math.min(classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez),
BlockTypes.AIR.getDefaultState());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT - 1,
ez), classicPlotWorld.MAIN_BLOCK.toPattern());
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.PLOT_HEIGHT, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT, ez),
classicPlotWorld.TOP_BLOCK.toPattern());
return queue.enqueue();
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT - 1, ez), classicPlotWorld.MAIN_BLOCK.toPattern());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.PLOT_HEIGHT, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT, ez), classicPlotWorld.TOP_BLOCK.toPattern());
return !enqueue || queue.enqueue();
}
@Override public boolean removeRoadSouthEast(Plot plot) {
@Override public boolean removeRoadSouthEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue) {
Location location = getPlotTopLocAbs(plot.getId());
int sx = location.getX() + 1;
int ex = sx + classicPlotWorld.ROAD_WIDTH - 1;
int sz = location.getZ() + 1;
int ez = sz + classicPlotWorld.ROAD_WIDTH - 1;
LocalBlockQueue queue = classicPlotWorld.getQueue(false);
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx,
Math.min(classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex,
classicPlotWorld.getPlotManager().getWorldHeight(), ez),
boolean enqueue = false;
if (queue == null) {
queue = classicPlotWorld.getQueue();
enqueue = true;
}
queue
.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, Math.min(classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez),
BlockTypes.AIR.getDefaultState());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez),
classicPlotWorld.MAIN_BLOCK.toPattern());
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.PLOT_HEIGHT, sz),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT, ez),
classicPlotWorld.TOP_BLOCK.toPattern());
return queue.enqueue();
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez), classicPlotWorld.MAIN_BLOCK.toPattern());
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.PLOT_HEIGHT, sz),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT, ez), classicPlotWorld.TOP_BLOCK.toPattern());
return !enqueue || queue.enqueue();
}
/**
* Finishing off plot merging by adding in the walls surrounding the plot (OPTIONAL)(UNFINISHED).
*
* @return false if part of the merge failed, otherwise true if successful.
*/
@Override public boolean finishPlotMerge(List<PlotId> plotIds) {
@Override public boolean finishPlotMerge(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
final BlockBucket claim = classicPlotWorld.CLAIMED_WALL_BLOCK;
if (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK)) {
if (classicPlotWorld.PLACE_TOP_BLOCK && (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK))) {
for (PlotId plotId : plotIds) {
setWall(plotId, claim.toPattern());
setWall(plotId, claim.toPattern(), queue);
}
}
if (Settings.General.MERGE_REPLACE_WALL) {
final BlockBucket wallBlock = classicPlotWorld.WALL_FILLING;
for (PlotId id : plotIds) {
setWallFilling(id, wallBlock.toPattern());
setWallFilling(id, wallBlock.toPattern(), queue);
}
}
return true;
}
@Override public boolean finishPlotUnlink(List<PlotId> plotIds) {
@Override public boolean finishPlotUnlink(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
final BlockBucket claim = classicPlotWorld.CLAIMED_WALL_BLOCK;
if (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK)) {
if (classicPlotWorld.PLACE_TOP_BLOCK && (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK))) {
for (PlotId id : plotIds) {
setWall(id, claim.toPattern());
setWall(id, claim.toPattern(), queue);
}
}
return true; // return false if unlink has been denied
}
@Override public boolean startPlotMerge(List<PlotId> plotIds) {
@Override public boolean startPlotMerge(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
return true;
}
@Override public boolean startPlotUnlink(List<PlotId> plotIds) {
@Override public boolean startPlotUnlink(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
return true;
}
@Override public boolean claimPlot(Plot plot) {
@Override public boolean claimPlot(@Nonnull Plot plot, @Nullable QueueCoordinator queue) {
final BlockBucket claim = classicPlotWorld.CLAIMED_WALL_BLOCK;
if (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK)) {
return setWall(plot.getId(), claim.toPattern());
if (classicPlotWorld.PLACE_TOP_BLOCK && (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK))) {
return setWall(plot.getId(), claim.toPattern(), queue);
}
return true;
}
@Override public String[] getPlotComponents(PlotId plotId) {
@Override public String[] getPlotComponents(@Nonnull PlotId plotId) {
return ClassicPlotManagerComponent.stringValues();
}
@ -530,11 +604,10 @@ public class ClassicPlotManager extends SquarePlotManager {
* @param plot The plot
* @return The location where a sign should be
*/
@Override public Location getSignLoc(Plot plot) {
@Override public Location getSignLoc(@Nonnull Plot plot) {
plot = plot.getBasePlot(false);
final Location bot = plot.getBottomAbs();
return Location.at(classicPlotWorld.getWorldName(), bot.getX() - 1,
classicPlotWorld.ROAD_HEIGHT + 1, bot.getZ() - 2);
return Location.at(classicPlotWorld.getWorldName(), bot.getX() - 1, classicPlotWorld.ROAD_HEIGHT + 1, bot.getZ() - 2);
}
}

View File

@ -58,6 +58,7 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld {
public BlockBucket ROAD_BLOCK = new BlockBucket(BlockTypes.QUARTZ_BLOCK);
// BlockUtil.get((short) 155, (byte) 0);
public boolean PLOT_BEDROCK = true;
public boolean PLACE_TOP_BLOCK = true;
public ClassicPlotWorld(@Nonnull final String worldName,
@Nullable final String id,
@ -91,6 +92,8 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld {
ConfigurationUtil.BLOCK_BUCKET),
new ConfigurationNode("wall.block_claimed", this.CLAIMED_WALL_BLOCK,
"Wall block (claimed)", ConfigurationUtil.BLOCK_BUCKET),
new ConfigurationNode("wall.place_top_block", this.PLACE_TOP_BLOCK,
"Place or not the top block", ConfigurationUtil.BOOLEAN),
new ConfigurationNode("road.width", this.ROAD_WIDTH, "Road width",
ConfigurationUtil.INTEGER),
new ConfigurationNode("road.height", this.ROAD_HEIGHT, "Road height",
@ -121,5 +124,6 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld {
this.WALL_FILLING = new BlockBucket(config.getString("wall.filling"));
this.WALL_HEIGHT = Math.min(254, config.getInt("wall.height"));
this.CLAIMED_WALL_BLOCK = new BlockBucket(config.getString("wall.block_claimed"));
this.PLACE_TOP_BLOCK = config.getBoolean("wall.place_top_block");
}
}

View File

@ -33,7 +33,7 @@ import com.plotsquared.core.inject.factory.HybridPlotWorldFactory;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.queue.ScopedLocalBlockQueue;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.MathMan;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -53,7 +53,7 @@ public class HybridGen extends IndependentPlotGenerator {
return PlotSquared.platform().getPluginName();
}
private void placeSchem(HybridPlotWorld world, ScopedLocalBlockQueue result, short relativeX,
private void placeSchem(HybridPlotWorld world, ScopedQueueCoordinator result, short relativeX,
short relativeZ, int x, int z, boolean isRoad) {
int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT);
if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad
@ -77,7 +77,7 @@ public class HybridGen extends IndependentPlotGenerator {
}
@Override
public void generateChunk(@Nonnull ScopedLocalBlockQueue result, @Nonnull PlotArea settings) {
public void generateChunk(@Nonnull ScopedQueueCoordinator result, @Nonnull PlotArea settings) {
Preconditions.checkNotNull(result, "result cannot be null");
Preconditions.checkNotNull(settings, "settings cannot be null");
@ -181,8 +181,10 @@ public class HybridGen extends IndependentPlotGenerator {
result.setBlock(x, y, z, hybridPlotWorld.WALL_FILLING.toPattern());
}
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z,
hybridPlotWorld.WALL_BLOCK.toPattern());
if (hybridPlotWorld.PLACE_TOP_BLOCK) {
result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z,
hybridPlotWorld.WALL_BLOCK.toPattern());
}
} else {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z,
true);
@ -206,8 +208,10 @@ public class HybridGen extends IndependentPlotGenerator {
result.setBlock(x, y, z, hybridPlotWorld.WALL_FILLING.toPattern());
}
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z,
hybridPlotWorld.WALL_BLOCK.toPattern());
if (hybridPlotWorld.PLACE_TOP_BLOCK) {
result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z,
hybridPlotWorld.WALL_BLOCK.toPattern());
}
} else {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z,
true);

View File

@ -34,21 +34,22 @@ import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotAreaTerrainType;
import com.plotsquared.core.plot.PlotAreaType;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.FileBytes;
import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.task.RunnableVal;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
@ -62,34 +63,24 @@ public class HybridPlotManager extends ClassicPlotManager {
private final HybridPlotWorld hybridPlotWorld;
private final RegionManager regionManager;
public HybridPlotManager(@Nonnull final HybridPlotWorld hybridPlotWorld,
@Nonnull final RegionManager regionManager) {
public HybridPlotManager(@Nonnull final HybridPlotWorld hybridPlotWorld, @Nonnull final RegionManager regionManager) {
super(hybridPlotWorld, regionManager);
this.hybridPlotWorld = hybridPlotWorld;
this.regionManager = regionManager;
}
@Override public void exportTemplate() throws IOException {
HashSet<FileBytes> files = Sets.newHashSet(
new FileBytes(Settings.Paths.TEMPLATES + "/tmp-data.yml",
Template.getBytes(hybridPlotWorld)));
String dir =
"schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld
.getWorldName() + File.separator;
HashSet<FileBytes> files = Sets.newHashSet(new FileBytes(Settings.Paths.TEMPLATES + "/tmp-data.yml", Template.getBytes(hybridPlotWorld)));
String dir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator;
try {
File sideRoad =
FileUtils.getFile(PlotSquared.platform().getDirectory(), dir + "sideroad.schem");
String newDir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator
+ "__TEMP_DIR__" + File.separator;
File sideRoad = FileUtils.getFile(PlotSquared.platform().getDirectory(), dir + "sideroad.schem");
String newDir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + "__TEMP_DIR__" + File.separator;
if (sideRoad.exists()) {
files.add(new FileBytes(newDir + "sideroad.schem",
Files.readAllBytes(sideRoad.toPath())));
files.add(new FileBytes(newDir + "sideroad.schem", Files.readAllBytes(sideRoad.toPath())));
}
File intersection =
FileUtils.getFile(PlotSquared.platform().getDirectory(), dir + "intersection.schem");
File intersection = FileUtils.getFile(PlotSquared.platform().getDirectory(), dir + "intersection.schem");
if (intersection.exists()) {
files.add(new FileBytes(newDir + "intersection.schem",
Files.readAllBytes(intersection.toPath())));
files.add(new FileBytes(newDir + "intersection.schem", Files.readAllBytes(intersection.toPath())));
}
File plot = FileUtils.getFile(PlotSquared.platform().getDirectory(), dir + "plot.schem");
if (plot.exists()) {
@ -101,42 +92,39 @@ public class HybridPlotManager extends ClassicPlotManager {
Template.zipAll(hybridPlotWorld.getWorldName(), files);
}
@Override public boolean createRoadEast(Plot plot) {
super.createRoadEast(plot);
@Override public boolean createRoadEast(@Nonnull final Plot plot, @Nullable QueueCoordinator queue) {
super.createRoadEast(plot, queue);
PlotId id = plot.getId();
PlotId id2 = PlotId.of(id.getX() + 1, id.getY());
Location bot = getPlotBottomLocAbs(id2);
Location top = getPlotTopLocAbs(id);
Location pos1 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, 0, bot.getZ() - 1);
Location pos2 = Location.at(hybridPlotWorld.getWorldName(), bot.getX(),
Math.min(getWorldHeight(), 255), top.getZ() + 1);
Location pos2 = Location.at(hybridPlotWorld.getWorldName(), bot.getX(), Math.min(getWorldHeight(), 255), top.getZ() + 1);
this.resetBiome(hybridPlotWorld, pos1, pos2);
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
return true;
}
LocalBlockQueue queue = hybridPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
queue = hybridPlotWorld.getQueue();
enqueue = true;
}
createSchemAbs(queue, pos1, pos2, true);
queue.enqueue();
return true;
return !enqueue || queue.enqueue();
}
private void resetBiome(@Nonnull final HybridPlotWorld hybridPlotWorld, @Nonnull final Location pos1,
@Nonnull final Location pos2) {
private void resetBiome(@Nonnull final HybridPlotWorld hybridPlotWorld, @Nonnull final Location pos1, @Nonnull final Location pos2) {
BiomeType biome = hybridPlotWorld.getPlotBiome();
if (!Objects.equals(PlotSquared.platform().getWorldUtil()
.getBiomeSynchronous(hybridPlotWorld.getWorldName(), (pos1.getX() + pos2.getX()) / 2,
(pos1.getZ() + pos2.getZ()) / 2), biome)) {
WorldUtil.setBiome(hybridPlotWorld.getWorldName(), pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(),
biome);
.getBiomeSynchronous(hybridPlotWorld.getWorldName(), (pos1.getX() + pos2.getX()) / 2, (pos1.getZ() + pos2.getZ()) / 2), biome)) {
WorldUtil.setBiome(hybridPlotWorld.getWorldName(), pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), biome);
}
}
private void createSchemAbs(LocalBlockQueue queue, Location pos1, Location pos2,
boolean isRoad) {
private void createSchemAbs(@Nonnull final QueueCoordinator queue, @Nonnull final Location pos1, @Nonnull final Location pos2, boolean isRoad) {
int size = hybridPlotWorld.SIZE;
int minY;
if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad
&& Settings.Schematics.PASTE_ON_TOP)) {
if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad && Settings.Schematics.PASTE_ON_TOP)) {
minY = hybridPlotWorld.SCHEM_Y;
} else {
minY = 1;
@ -173,37 +161,43 @@ public class HybridPlotManager extends ClassicPlotManager {
}
}
@Override public boolean createRoadSouth(Plot plot) {
super.createRoadSouth(plot);
@Override public boolean createRoadSouth(@Nonnull final Plot plot, @Nullable QueueCoordinator queue) {
super.createRoadSouth(plot, queue);
PlotId id = plot.getId();
PlotId id2 = PlotId.of(id.getX(), id.getY() + 1);
Location bot = getPlotBottomLocAbs(id2);
Location top = getPlotTopLocAbs(id);
Location pos1 = Location.at(hybridPlotWorld.getWorldName(), bot.getX() - 1, 0, top.getZ() + 1);
Location pos2 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1,
Math.min(getWorldHeight(), 255), bot.getZ());
Location pos2 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, Math.min(getWorldHeight(), 255), bot.getZ());
this.resetBiome(hybridPlotWorld, pos1, pos2);
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
return true;
}
LocalBlockQueue queue = hybridPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
enqueue = true;
queue = hybridPlotWorld.getQueue();
}
createSchemAbs(queue, pos1, pos2, true);
queue.enqueue();
return true;
return !enqueue || queue.enqueue();
}
@Override public boolean createRoadSouthEast(Plot plot) {
super.createRoadSouthEast(plot);
@Override public boolean createRoadSouthEast(@Nonnull final Plot plot, @Nullable QueueCoordinator queue) {
super.createRoadSouthEast(plot, queue);
PlotId id = plot.getId();
PlotId id2 = PlotId.of(id.getX() + 1, id.getY() + 1);
Location pos1 = getPlotTopLocAbs(id).add(1, 0, 1).withY(0);
Location pos2 = getPlotBottomLocAbs(id2).withY(Math.min(getWorldHeight(), 255));
LocalBlockQueue queue = hybridPlotWorld.getQueue(false);
boolean enqueue = false;
if (queue == null) {
enqueue = true;
queue = hybridPlotWorld.getQueue();
}
createSchemAbs(queue, pos1, pos2, true);
if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
createSchemAbs(queue, pos1, pos2, true);
}
return queue.enqueue();
return !enqueue || queue.enqueue();
}
/**
@ -213,7 +207,7 @@ public class HybridPlotManager extends ClassicPlotManager {
* don't need to do something quite as complex unless you happen to have 512x512 sized plots.
* </p>
*/
@Override public boolean clearPlot(Plot plot, final Runnable whenDone) {
@Override public boolean clearPlot(@Nonnull final Plot plot, @Nullable final Runnable whenDone, @Nullable QueueCoordinator queue) {
if (this.regionManager.notifyClear(this)) {
//If this returns false, the clear didn't work
if (this.regionManager.handleClear(plot, whenDone, this)) {
@ -221,12 +215,11 @@ public class HybridPlotManager extends ClassicPlotManager {
}
}
final String world = hybridPlotWorld.getWorldName();
Location pos1 = plot.getBottomAbs();
Location pos2 = plot.getExtendedTopAbs();
final Location pos1 = plot.getBottomAbs();
final Location pos2 = plot.getExtendedTopAbs();
// If augmented
final boolean canRegen =
(hybridPlotWorld.getType() == PlotAreaType.AUGMENTED) && (hybridPlotWorld.getTerrain()
!= PlotAreaTerrainType.NONE) && REGENERATIVE_CLEAR;
(hybridPlotWorld.getType() == PlotAreaType.AUGMENTED) && (hybridPlotWorld.getTerrain() != PlotAreaTerrainType.NONE) && REGENERATIVE_CLEAR;
// The component blocks
final Pattern plotfloor = hybridPlotWorld.TOP_BLOCK.toPattern();
final Pattern filling = hybridPlotWorld.MAIN_BLOCK.toPattern();
@ -240,43 +233,29 @@ public class HybridPlotManager extends ClassicPlotManager {
}
final BiomeType biome = hybridPlotWorld.getPlotBiome();
final LocalBlockQueue queue = hybridPlotWorld.getQueue(false);
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
@Override public void run(int[] value) {
// If the chunk isn't near the edge and it isn't an augmented world we can just regen the whole chunk
if (canRegen && (value[6] == 0)) {
queue.regenChunk(value[0], value[1]);
return;
}
/* Otherwise we need to set each component, as we don't want to regenerate the road or other plots that share the same chunk.*/
// Set the biome
WorldUtil.setBiome(world, value[2], value[3], value[4], value[5], biome);
// These two locations are for each component (e.g. bedrock, main block, floor, air)
Location bot = Location.at(world, value[2], 0, value[3]);
Location top = Location.at(world, value[4], 1, value[5]);
queue.setCuboid(bot, top, bedrock);
// Each component has a different layer
bot = bot.withY(1);
top = top.withY(hybridPlotWorld.PLOT_HEIGHT);
queue.setCuboid(bot, top, filling);
bot = bot.withY(hybridPlotWorld.PLOT_HEIGHT);
top = top.withY(hybridPlotWorld.PLOT_HEIGHT + 1);
queue.setCuboid(bot, top, plotfloor);
bot = bot.withY(hybridPlotWorld.PLOT_HEIGHT + 1);
top = top.withY(getWorldHeight());
queue.setCuboid(bot, top, air);
// And finally set the schematic, the y value is unimportant for this function
pastePlotSchematic(queue, bot, top);
}
}, () -> {
queue.enqueue();
// And notify whatever called this when plot clearing is done
PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(whenDone);
}, 10);
return true;
boolean enqueue = false;
if (queue == null) {
enqueue = true;
queue = hybridPlotWorld.getQueue();
}
if (!canRegen) {
queue.setCuboid(pos1.withY(0), pos2.withY(0), bedrock);
// Each component has a different layer
queue.setCuboid(pos1.withY(1), pos2.withY(hybridPlotWorld.PLOT_HEIGHT - 1), filling);
queue.setCuboid(pos1.withY(hybridPlotWorld.PLOT_HEIGHT), pos2.withY(hybridPlotWorld.PLOT_HEIGHT), plotfloor);
queue.setCuboid(pos1.withY(hybridPlotWorld.PLOT_HEIGHT + 1), pos2.withY(getWorldHeight()), air);
queue.setBiomeCuboid(pos1, pos2, biome);
} else {
queue.setRegenRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()));
}
pastePlotSchematic(queue, pos1, pos2);
if (whenDone != null) {
queue.setCompleteTask(whenDone);
}
return !enqueue || queue.enqueue();
}
public void pastePlotSchematic(LocalBlockQueue queue, Location bottom, Location top) {
public void pastePlotSchematic(@Nonnull final QueueCoordinator queue, @Nonnull final Location bottom, @Nonnull final Location top) {
if (!hybridPlotWorld.PLOT_SCHEMATIC) {
return;
}
@ -289,7 +268,7 @@ public class HybridPlotManager extends ClassicPlotManager {
* @param plot The plot
* @return The location where a sign should be
*/
@Override public Location getSignLoc(Plot plot) {
@Override public Location getSignLoc(@Nonnull final @NotNull Plot plot) {
return hybridPlotWorld.getSignLocation(plot);
}

View File

@ -41,7 +41,6 @@ import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.util.EconHandler;
import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.SchematicHandler;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompoundTagBuilder;
@ -81,8 +80,7 @@ public class HybridPlotWorld extends ClassicPlotWorld {
private Location SIGN_LOCATION;
private File root = null;
private final RegionManager regionManager;
private final SchematicHandler schematicHandler;
@Inject private SchematicHandler schematicHandler;
@Inject public HybridPlotWorld(@Assisted("world") final String worldName,
@Nullable @Assisted("id") final String id,
@ -90,13 +88,10 @@ public class HybridPlotWorld extends ClassicPlotWorld {
@Nullable @Assisted("min") final PlotId min,
@Nullable @Assisted("max") final PlotId max,
@WorldConfig @Nonnull final YamlConfiguration worldConfiguration,
@Nonnull final RegionManager regionManager,
@Nonnull final SchematicHandler schematicHandler,
@Nonnull final GlobalBlockQueue blockQueue,
@Nullable final EconHandler econHandler) {
super(worldName, id, generator, min, max, worldConfiguration, blockQueue, econHandler);
this.regionManager = regionManager;
this.schematicHandler = schematicHandler;
PlotSquared.platform().getInjector().injectMembers(this);
}
public static byte wrap(byte data, int start) {
@ -127,11 +122,9 @@ public class HybridPlotWorld extends ClassicPlotWorld {
Direction direction = MCDirections.fromRotation(rot);
if (direction != null) {
Vector3 vector = transform.apply(direction.toVector())
.subtract(transform.apply(Vector3.ZERO)).normalize();
Direction newDirection = Direction.findClosest(vector,
Direction.Flag.CARDINAL | Direction.Flag.ORDINAL
| Direction.Flag.SECONDARY_ORDINAL);
Vector3 vector = transform.apply(direction.toVector()).subtract(transform.apply(Vector3.ZERO)).normalize();
Direction newDirection =
Direction.findClosest(vector, Direction.Flag.CARDINAL | Direction.Flag.ORDINAL | Direction.Flag.SECONDARY_ORDINAL);
if (newDirection != null) {
CompoundTagBuilder builder = tag.createBuilder();
@ -147,7 +140,7 @@ public class HybridPlotWorld extends ClassicPlotWorld {
}
@Nonnull @Override protected PlotManager createManager() {
return new HybridPlotManager(this, this.regionManager);
return new HybridPlotManager(this, PlotSquared.platform().getRegionManager());
}
public Location getSignLocation(@Nonnull Plot plot) {
@ -218,21 +211,24 @@ public class HybridPlotWorld extends ClassicPlotWorld {
// Try to determine root. This means that plot areas can have separate schematic
// directories
if (!(root = FileUtils.getFile(PlotSquared.platform().getDirectory(), "schematics/GEN_ROAD_SCHEMATIC/" +
this.getWorldName() + "/" + this.getId())).exists()) {
root = FileUtils.getFile(PlotSquared.platform().getDirectory(),
"schematics/GEN_ROAD_SCHEMATIC/" + this.getWorldName());
if (!(root =
FileUtils.getFile(PlotSquared.platform().getDirectory(), "schematics/GEN_ROAD_SCHEMATIC/" + this.getWorldName() + "/" + this.getId()))
.exists()) {
root = FileUtils.getFile(PlotSquared.platform().getDirectory(), "schematics/GEN_ROAD_SCHEMATIC/" + this.getWorldName());
}
File schematic1File = new File(root, "sideroad.schem");
if (!schematic1File.exists())
if (!schematic1File.exists()) {
schematic1File = new File(root, "sideroad.schematic");
}
File schematic2File = new File(root, "intersection.schem");
if (!schematic2File.exists())
if (!schematic2File.exists()) {
schematic2File = new File(root, "intersection.schematic");
}
File schematic3File = new File(root, "plot.schem");
if (!schematic3File.exists())
if (!schematic3File.exists()) {
schematic3File = new File(root, "plot.schematic");
}
Schematic schematic1 = this.schematicHandler.getSchematic(schematic1File);
Schematic schematic2 = this.schematicHandler.getSchematic(schematic2File);
Schematic schematic3 = this.schematicHandler.getSchematic(schematic3File);
@ -285,18 +281,15 @@ public class HybridPlotWorld extends ClassicPlotWorld {
for (short x = 0; x < w3; x++) {
for (short z = 0; z < l3; z++) {
for (short y = 0; y < h3; y++) {
BaseBlock id = blockArrayClipboard3.getFullBlock(BlockVector3
.at(x + min.getBlockX(), y + min.getBlockY(), z + min.getBlockZ()));
BaseBlock id =
blockArrayClipboard3.getFullBlock(BlockVector3.at(x + min.getBlockX(), y + min.getBlockY(), z + min.getBlockZ()));
if (!id.getBlockType().getMaterial().isAir()) {
addOverlayBlock((short) (x + shift + oddshift + centerShiftX),
(short) (y + plotY), (short) (z + shift + oddshift + centerShiftZ),
id, false, h3);
addOverlayBlock((short) (x + shift + oddshift + centerShiftX), (short) (y + plotY),
(short) (z + shift + oddshift + centerShiftZ), id, false, h3);
}
}
BiomeType biome = blockArrayClipboard3
.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
addOverlayBiome((short) (x + shift + oddshift + centerShiftX),
(short) (z + shift + oddshift + centerShiftZ), biome);
BiomeType biome = blockArrayClipboard3.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
addOverlayBiome((short) (x + shift + oddshift + centerShiftX), (short) (z + shift + oddshift + centerShiftZ), biome);
}
}
@ -325,20 +318,15 @@ public class HybridPlotWorld extends ClassicPlotWorld {
for (short x = 0; x < w1; x++) {
for (short z = 0; z < l1; z++) {
for (short y = 0; y < h1; y++) {
BaseBlock id = blockArrayClipboard1.getFullBlock(BlockVector3
.at(x + min.getBlockX(), y + min.getBlockY(), z + min.getBlockZ()));
BaseBlock id = blockArrayClipboard1.getFullBlock(BlockVector3.at(x + min.getBlockX(), y + min.getBlockY(), z + min.getBlockZ()));
if (!id.getBlockType().getMaterial().isAir()) {
addOverlayBlock((short) (x - shift), (short) (y + roadY),
(short) (z + shift + oddshift), id, false, h1);
addOverlayBlock((short) (z + shift + oddshift), (short) (y + roadY),
(short) (shift - x + (oddshift - 1)), id, true, h1);
addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z + shift + oddshift), id, false, h1);
addOverlayBlock((short) (z + shift + oddshift), (short) (y + roadY), (short) (shift - x + (oddshift - 1)), id, true, h1);
}
}
BiomeType biome = blockArrayClipboard1
.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
BiomeType biome = blockArrayClipboard1.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
addOverlayBiome((short) (x - shift), (short) (z + shift + oddshift), biome);
addOverlayBiome((short) (z + shift + oddshift),
(short) (shift - x + (oddshift - 1)), biome);
addOverlayBiome((short) (z + shift + oddshift), (short) (shift - x + (oddshift - 1)), biome);
}
}
@ -351,22 +339,18 @@ public class HybridPlotWorld extends ClassicPlotWorld {
for (short x = 0; x < w2; x++) {
for (short z = 0; z < l2; z++) {
for (short y = 0; y < h2; y++) {
BaseBlock id = blockArrayClipboard2.getFullBlock(BlockVector3
.at(x + min.getBlockX(), y + min.getBlockY(), z + min.getBlockZ()));
BaseBlock id = blockArrayClipboard2.getFullBlock(BlockVector3.at(x + min.getBlockX(), y + min.getBlockY(), z + min.getBlockZ()));
if (!id.getBlockType().getMaterial().isAir()) {
addOverlayBlock((short) (x - shift), (short) (y + roadY),
(short) (z - shift), id, false, h2);
addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z - shift), id, false, h2);
}
}
BiomeType biome = blockArrayClipboard2
.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
BiomeType biome = blockArrayClipboard2.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
addOverlayBiome((short) (x - shift), (short) (z - shift), biome);
}
}
}
public void addOverlayBlock(short x, short y, short z, BaseBlock id, boolean rotate,
int height) {
public void addOverlayBlock(short x, short y, short z, BaseBlock id, boolean rotate, int height) {
if (z < 0) {
z += this.SIZE;
} else if (z >= this.SIZE) {

View File

@ -41,9 +41,9 @@ import com.plotsquared.core.plot.flag.GlobalFlagContainer;
import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.plot.flag.implementations.AnalysisFlag;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.ChunkBlockQueue;
import com.plotsquared.core.queue.ChunkQueueCoordinator;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.RegionManager;
@ -93,27 +93,26 @@ public class HybridUtils {
private final ChunkManager chunkManager;
private final GlobalBlockQueue blockQueue;
private final WorldUtil worldUtil;
private final RegionManager regionManager;
private final SchematicHandler schematicHandler;
@Inject public HybridUtils(@Nonnull final PlotAreaManager plotAreaManager,
@Nonnull final ChunkManager chunkManager, @Nonnull final GlobalBlockQueue blockQueue,
@Nonnull final WorldUtil worldUtil, @Nonnull final RegionManager regionManager, @Nonnull final SchematicHandler schematicHandler) {
@Nonnull final ChunkManager chunkManager,
@Nonnull final GlobalBlockQueue blockQueue,
@Nonnull final WorldUtil worldUtil,
@Nonnull final SchematicHandler schematicHandler) {
this.plotAreaManager = plotAreaManager;
this.chunkManager = chunkManager;
this.blockQueue = blockQueue;
this.worldUtil = worldUtil;
this.regionManager = regionManager;
this.schematicHandler = schematicHandler;
}
public void regeneratePlotWalls(final PlotArea area) {
PlotManager plotManager = area.getPlotManager();
plotManager.regenerateAllPlotWalls();
plotManager.regenerateAllPlotWalls(null);
}
public void analyzeRegion(final String world, final CuboidRegion region,
final RunnableVal<PlotAnalysis> whenDone) {
public void analyzeRegion(final String world, final CuboidRegion region, final RunnableVal<PlotAnalysis> whenDone) {
// int diff, int variety, int vertices, int rotation, int height_sd
/*
* diff: compare to base by looping through all blocks
@ -127,8 +126,6 @@ public class HybridUtils {
*
*/
TaskManager.runTaskAsync(() -> {
final LocalBlockQueue queue = blockQueue.getNewQueue(world, false);
final BlockVector3 bot = region.getMinimumPoint();
final BlockVector3 top = region.getMaximumPoint();
@ -150,7 +147,7 @@ public class HybridUtils {
}
HybridPlotWorld hpw = (HybridPlotWorld) area;
ChunkBlockQueue chunk = new ChunkBlockQueue(bot, top, false);
ChunkQueueCoordinator chunk = new ChunkQueueCoordinator(bot, top, false);
hpw.getGenerator().generateChunk(chunk, hpw);
final BlockState[][][] oldBlocks = chunk.getBlocks();
@ -160,6 +157,55 @@ public class HybridUtils {
System.gc();
System.gc();
QueueCoordinator queue = area.getQueue();
queue.addReadChunks(region.getChunks());
queue.setChunkConsumer(blockVector2 -> {
int X = blockVector2.getX();
int Z = blockVector2.getZ();
int minX;
if (X == cbx) {
minX = bx & 15;
} else {
minX = 0;
}
int minZ;
if (Z == cbz) {
minZ = bz & 15;
} else {
minZ = 0;
}
int maxX;
if (X == ctx) {
maxX = tx & 15;
} else {
maxX = 16;
}
int maxZ;
if (Z == ctz) {
maxZ = tz & 15;
} else {
maxZ = 16;
}
int chunkBlockX = X << 4;
int chunkBlockZ = Z << 4;
int xb = chunkBlockX - bx;
int zb = chunkBlockZ - bz;
for (int x = minX; x <= maxX; x++) {
int xx = chunkBlockX + x;
for (int z = minZ; z <= maxZ; z++) {
int zz = chunkBlockZ + z;
for (int y = 0; y < 256; y++) {
BlockState block = queue.getBlock(xx, y, zz);
int xr = xb + x;
int zr = zb + z;
newBlocks[y][xr][zr] = block;
}
}
}
});
final Runnable run = () -> TaskManager.runTaskAsync(() -> {
int size = width * length;
int[] changes = new int[size];
@ -186,30 +232,23 @@ public class HybridUtils {
} else {
// check vertices
// modifications_adjacent
if (x > 0 && z > 0 && y > 0 && x < width - 1 && z < length - 1
&& y < 255) {
if (newBlocks[y - 1][x][z].getBlockType().getMaterial()
.isAir()) {
if (x > 0 && z > 0 && y > 0 && x < width - 1 && z < length - 1 && y < 255) {
if (newBlocks[y - 1][x][z].getBlockType().getMaterial().isAir()) {
faces[i]++;
}
if (newBlocks[y][x - 1][z].getBlockType().getMaterial()
.isAir()) {
if (newBlocks[y][x - 1][z].getBlockType().getMaterial().isAir()) {
faces[i]++;
}
if (newBlocks[y][x][z - 1].getBlockType().getMaterial()
.isAir()) {
if (newBlocks[y][x][z - 1].getBlockType().getMaterial().isAir()) {
faces[i]++;
}
if (newBlocks[y + 1][x][z].getBlockType().getMaterial()
.isAir()) {
if (newBlocks[y + 1][x][z].getBlockType().getMaterial().isAir()) {
faces[i]++;
}
if (newBlocks[y][x + 1][z].getBlockType().getMaterial()
.isAir()) {
if (newBlocks[y][x + 1][z].getBlockType().getMaterial().isAir()) {
faces[i]++;
}
if (newBlocks[y][x][z + 1].getBlockType().getMaterial()
.isAir()) {
if (newBlocks[y][x][z + 1].getBlockType().getMaterial().isAir()) {
faces[i]++;
}
}
@ -248,57 +287,8 @@ public class HybridUtils {
whenDone.value = analysis;
whenDone.run();
});
System.gc();
Location botLoc = Location.at(world, bot.getX(), bot.getY(), bot.getZ());
Location topLoc = Location.at(world, top.getX(), top.getY(), top.getZ());
ChunkManager.chunkTask(botLoc, topLoc, new RunnableVal<int[]>() {
@Override public void run(int[] value) {
int X = value[0];
int Z = value[1];
int minX;
if (X == cbx) {
minX = bx & 15;
} else {
minX = 0;
}
int minZ;
if (Z == cbz) {
minZ = bz & 15;
} else {
minZ = 0;
}
int maxX;
if (X == ctx) {
maxX = tx & 15;
} else {
maxX = 16;
}
int maxZ;
if (Z == ctz) {
maxZ = tz & 15;
} else {
maxZ = 16;
}
int cbx = X << 4;
int cbz = Z << 4;
int xb = cbx - bx;
int zb = cbz - bz;
for (int x = minX; x <= maxX; x++) {
int xx = cbx + x;
for (int z = minZ; z <= maxZ; z++) {
int zz = cbz + z;
for (int y = 0; y < 256; y++) {
BlockState block = queue.getBlock(xx, y, zz);
int xr = xb + x;
int zr = zb + z;
newBlocks[y][xr][zr] = block;
}
}
}
}
}, () -> TaskManager.runTaskAsync(run), 5);
queue.setCompleteTask(run);
queue.enqueue();
});
}
@ -347,9 +337,7 @@ public class HybridUtils {
result.add(whenDone.value.data_sd);
result.add(whenDone.value.air_sd);
result.add(whenDone.value.variety_sd);
PlotFlag<?, ?> plotFlag =
GlobalFlagContainer.getInstance().getFlag(AnalysisFlag.class)
.createFlagInstance(result);
PlotFlag<?, ?> plotFlag = GlobalFlagContainer.getInstance().getFlag(AnalysisFlag.class).createFlagInstance(result);
PlotFlagAddEvent event = new PlotFlagAddEvent(plotFlag, origin);
if (event.getEventResult() == Result.DENY) {
return;
@ -371,15 +359,13 @@ public class HybridUtils {
run.run();
}
public int checkModified(LocalBlockQueue queue, int x1, int x2, int y1, int y2, int z1, int z2,
BlockState[] blocks) {
public int checkModified(QueueCoordinator queue, int x1, int x2, int y1, int y2, int z1, int z2, BlockState[] blocks) {
int count = 0;
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
for (int z = z1; z <= z2; z++) {
BlockState block = queue.getBlock(x, y, z);
boolean same =
Arrays.stream(blocks).anyMatch(p -> this.worldUtil.isBlockSame(block, p));
boolean same = Arrays.stream(blocks).anyMatch(p -> this.worldUtil.isBlockSame(block, p));
if (!same) {
count++;
}
@ -406,7 +392,7 @@ public class HybridUtils {
return false;
}
HybridUtils.UPDATE = true;
Set<BlockVector2> regions = this.regionManager.getChunkChunks(area.getWorldName());
Set<BlockVector2> regions = this.worldUtil.getChunkChunks(area.getWorldName());
return scheduleRoadUpdate(area, regions, extend, new HashSet<>());
}
@ -420,8 +406,7 @@ public class HybridUtils {
return scheduleRoadUpdate(plot.getArea(), regions, extend, new HashSet<>());
}
public boolean scheduleRoadUpdate(final PlotArea area, Set<BlockVector2> regions,
final int extend, Set<BlockVector2> chunks) {
public boolean scheduleRoadUpdate(final PlotArea area, Set<BlockVector2> regions, final int extend, Set<BlockVector2> chunks) {
HybridUtils.regions = regions;
HybridUtils.area = area;
HybridUtils.height = extend;
@ -438,7 +423,6 @@ public class HybridUtils {
if (!regenedRoad && Settings.DEBUG) {
logger.info("[P2] Failed to regenerate roads");
}
chunkManager.unloadChunk(area.getWorldName(), chunk, true);
}
if (Settings.DEBUG) {
logger.info("[P2] Cancelled road task");
@ -461,13 +445,11 @@ public class HybridUtils {
try {
if (chunks.size() < 1024) {
if (!HybridUtils.regions.isEmpty()) {
Iterator<BlockVector2> iterator =
HybridUtils.regions.iterator();
Iterator<BlockVector2> iterator = HybridUtils.regions.iterator();
BlockVector2 loc = iterator.next();
iterator.remove();
if (Settings.DEBUG) {
logger.info("[P2] Updating .mcr: {}, {} (approx 1024 chunks)",
loc.getX(), loc.getZ());
logger.info("[P2] Updating .mcr: {}, {} (approx 1024 chunks)", loc.getX(), loc.getZ());
logger.info("[P2] - Remaining: {}", HybridUtils.regions.size());
}
chunks.addAll(getChunks(loc));
@ -478,12 +460,10 @@ public class HybridUtils {
TaskManager.getPlatformImplementation().sync(() -> {
long start = System.currentTimeMillis();
Iterator<BlockVector2> iterator = chunks.iterator();
while (System.currentTimeMillis() - start < 20 && !chunks
.isEmpty()) {
while (System.currentTimeMillis() - start < 20 && !chunks.isEmpty()) {
final BlockVector2 chunk = iterator.next();
iterator.remove();
boolean regenedRoads =
regenerateRoad(area, chunk, extend);
boolean regenedRoads = regenerateRoad(area, chunk, extend);
if (!regenedRoads && Settings.DEBUG) {
logger.info("[P2] Failed to regenerate road");
}
@ -496,18 +476,10 @@ public class HybridUtils {
Iterator<BlockVector2> iterator = HybridUtils.regions.iterator();
BlockVector2 loc = iterator.next();
iterator.remove();
logger.error("[P2] Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)",
area.getWorldHash(), loc.getX(), loc.getZ());
int sx = loc.getX() << 5;
int sz = loc.getZ() << 5;
for (int x = sx; x < sx + 32; x++) {
for (int z = sz; z < sz + 32; z++) {
chunkManager.unloadChunk(area.getWorldName(), BlockVector2.at(x, z),
true);
}
}
logger.error("[P2] Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)", area.getWorldHash(), loc.getX(),
loc.getZ());
}
blockQueue.addEmptyTask(() -> TaskManager.runTaskLater(task, TaskTime.seconds(1L)));
TaskManager.runTaskLater(task, TaskTime.seconds(1L));
});
}
}
@ -517,7 +489,7 @@ public class HybridUtils {
public boolean setupRoadSchematic(Plot plot) {
final String world = plot.getWorldName();
final LocalBlockQueue queue = blockQueue.getNewQueue(world, false);
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(world));
Location bot = plot.getBottomAbs().subtract(1, 0, 1);
Location top = plot.getTopAbs();
final HybridPlotWorld plotworld = (HybridPlotWorld) plot.getArea();
@ -532,36 +504,31 @@ public class HybridUtils {
int tz = sz - 1;
int ty = get_ey(plotManager, queue, sx, ex, bz, tz, sy);
Set<CuboidRegion> sideRoad = new HashSet<>(
Collections.singletonList(RegionUtil.createRegion(sx, ex, sy, ey, sz, ez)));
final Set<CuboidRegion> intersection = new HashSet<>(
Collections.singletonList(RegionUtil.createRegion(sx, ex, sy, ty, bz, tz)));
Set<CuboidRegion> sideRoad = new HashSet<>(Collections.singletonList(RegionUtil.createRegion(sx, ex, sy, ey, sz, ez)));
final Set<CuboidRegion> intersection = new HashSet<>(Collections.singletonList(RegionUtil.createRegion(sx, ex, sy, ty, bz, tz)));
final String dir =
"schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + plot.getArea()
.toString() + File.separator;
final String dir = "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + plot.getArea().toString() + File.separator;
this.schematicHandler.getCompoundTag(world, sideRoad, new RunnableVal<CompoundTag>() {
@Override public void run(CompoundTag value) {
schematicHandler.save(value, dir + "sideroad.schem");
schematicHandler.getCompoundTag(world, intersection, new RunnableVal<CompoundTag>() {
@Override public void run(CompoundTag value) {
schematicHandler.save(value, dir + "intersection.schem");
plotworld.ROAD_SCHEMATIC_ENABLED = true;
try {
plotworld.setupSchematics();
} catch (SchematicHandler.UnsupportedFormatException e) {
e.printStackTrace();
}
@Override public void run(CompoundTag value) {
schematicHandler.save(value, dir + "intersection.schem");
plotworld.ROAD_SCHEMATIC_ENABLED = true;
try {
plotworld.setupSchematics();
} catch (SchematicHandler.UnsupportedFormatException e) {
e.printStackTrace();
}
});
}
});
}
});
return true;
}
public int get_ey(final PlotManager pm, LocalBlockQueue queue, int sx, int ex, int sz, int ez,
int sy) {
public int get_ey(final PlotManager pm, QueueCoordinator queue, int sx, int ex, int sz, int ez, int sy) {
int ey = sy;
for (int x = sx; x <= ex; x++) {
for (int z = sz; z <= ez; z++) {
@ -604,7 +571,7 @@ public class HybridUtils {
z -= plotWorld.ROAD_OFFSET_Z;
final int finalX = x;
final int finalZ = z;
LocalBlockQueue queue = this.blockQueue.getNewQueue(plotWorld.getWorldName(), false);
QueueCoordinator queue = this.blockQueue.getNewQueue(worldUtil.getWeWorld(plotWorld.getWorldName()));
if (id1 == null || id2 == null || id1 != id2) {
this.chunkManager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> {
if (id1 != null) {
@ -632,8 +599,7 @@ public class HybridUtils {
}
boolean condition;
if (toCheck.get()) {
condition = manager.getPlotId(finalX + X + plotWorld.ROAD_OFFSET_X, 1,
finalZ + Z + plotWorld.ROAD_OFFSET_Z) == null;
condition = manager.getPlotId(finalX + X + plotWorld.ROAD_OFFSET_X, 1, finalZ + Z + plotWorld.ROAD_OFFSET_Z) == null;
} else {
boolean gx = absX > plotWorld.PATH_WIDTH_LOWER;
boolean gz = absZ > plotWorld.PATH_WIDTH_LOWER;
@ -647,27 +613,23 @@ public class HybridUtils {
int maxY = Math.max(extend, blocks.length);
for (int y = 0; y < maxY; y++) {
if (y > blocks.length - 1) {
queue.setBlock(finalX + X + plotWorld.ROAD_OFFSET_X, minY + y,
finalZ + Z + plotWorld.ROAD_OFFSET_Z, WEExtent.AIRBASE);
queue.setBlock(finalX + X + plotWorld.ROAD_OFFSET_X, minY + y, finalZ + Z + plotWorld.ROAD_OFFSET_Z,
WEExtent.AIRBASE);
} else {
BaseBlock block = blocks[y];
if (block != null) {
queue.setBlock(finalX + X + plotWorld.ROAD_OFFSET_X,
minY + y, finalZ + Z + plotWorld.ROAD_OFFSET_Z, block);
queue.setBlock(finalX + X + plotWorld.ROAD_OFFSET_X, minY + y, finalZ + Z + plotWorld.ROAD_OFFSET_Z, block);
} else {
queue.setBlock(finalX + X + plotWorld.ROAD_OFFSET_X,
minY + y, finalZ + Z + plotWorld.ROAD_OFFSET_Z,
queue.setBlock(finalX + X + plotWorld.ROAD_OFFSET_X, minY + y, finalZ + Z + plotWorld.ROAD_OFFSET_Z,
WEExtent.AIRBASE);
}
}
}
BiomeType biome = plotWorld.G_SCH_B.get(MathMan.pair(absX, absZ));
if (biome != null) {
queue.setBiome(finalX + X + plotWorld.ROAD_OFFSET_X,
finalZ + Z + plotWorld.ROAD_OFFSET_Z, biome);
queue.setBiome(finalX + X + plotWorld.ROAD_OFFSET_X, finalZ + Z + plotWorld.ROAD_OFFSET_Z, biome);
} else {
queue.setBiome(finalX + X + plotWorld.ROAD_OFFSET_X,
finalZ + Z + plotWorld.ROAD_OFFSET_Z, plotWorld.getPlotBiome());
queue.setBiome(finalX + X + plotWorld.ROAD_OFFSET_X, finalZ + Z + plotWorld.ROAD_OFFSET_Z, plotWorld.getPlotBiome());
}
}
}

View File

@ -29,7 +29,7 @@ import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.SetupObject;
import com.plotsquared.core.queue.ScopedLocalBlockQueue;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.setup.PlotAreaBuilder;
/**
@ -52,9 +52,9 @@ public abstract class IndependentPlotGenerator {
* @param result
* @param settings
*/
public abstract void generateChunk(ScopedLocalBlockQueue result, PlotArea settings);
public abstract void generateChunk(ScopedQueueCoordinator result, PlotArea settings);
public boolean populateChunk(ScopedLocalBlockQueue result, PlotArea setting) {
public boolean populateChunk(ScopedQueueCoordinator result, PlotArea setting) {
return false;
}
@ -75,8 +75,7 @@ public abstract class IndependentPlotGenerator {
*
* @param setup
*/
@Deprecated
public void processSetup(SetupObject setup) {
@Deprecated public void processSetup(SetupObject setup) {
}
/**
@ -85,7 +84,8 @@ public abstract class IndependentPlotGenerator {
*
* @param builder the area builder to modify
*/
public void processAreaSetup(PlotAreaBuilder builder) { }
public void processAreaSetup(PlotAreaBuilder builder) {
}
/**
* It is preferred for the PlotArea object to do most of the initialization necessary.

View File

@ -32,7 +32,7 @@ import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.plot.world.SinglePlotAreaManager;
import com.plotsquared.core.queue.ScopedLocalBlockQueue;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -57,7 +57,7 @@ public class SingleWorldGenerator extends IndependentPlotGenerator {
return "PlotSquared:single";
}
@Override public void generateChunk(ScopedLocalBlockQueue result, PlotArea settings) {
@Override public void generateChunk(ScopedQueueCoordinator result, PlotArea settings) {
SinglePlotArea area = (SinglePlotArea) settings;
if (area.VOID) {
Location min = result.getMin();

View File

@ -30,13 +30,16 @@ import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.HashUtil;
import com.plotsquared.core.util.RegionManager;
import com.sk89q.worldedit.regions.CuboidRegion;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.Set;
@ -56,12 +59,14 @@ public abstract class SquarePlotManager extends GridPlotManager {
this.regionManager = regionManager;
}
@Override public boolean clearPlot(final Plot plot, final Runnable whenDone) {
@Override public boolean clearPlot(final @NotNull Plot plot, final @Nullable Runnable whenDone, @Nullable QueueCoordinator queue) {
final Set<CuboidRegion> regions = plot.getRegions();
Runnable run = new Runnable() {
@Override public void run() {
if (regions.isEmpty()) {
whenDone.run();
if (whenDone != null) {
whenDone.run();
}
return;
}
Iterator<CuboidRegion> iterator = regions.iterator();
@ -76,13 +81,13 @@ public abstract class SquarePlotManager extends GridPlotManager {
return true;
}
@Override public Location getPlotTopLocAbs(PlotId plotId) {
@Override public Location getPlotTopLocAbs(@NotNull PlotId plotId) {
int px = plotId.getX();
int pz = plotId.getY();
int x = (squarePlotWorld.ROAD_OFFSET_X + (px * (squarePlotWorld.ROAD_WIDTH
+ squarePlotWorld.PLOT_WIDTH))) - (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2) - 1;
int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH
+ squarePlotWorld.PLOT_WIDTH))) - (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2) - 1;
int x = (squarePlotWorld.ROAD_OFFSET_X + (px * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - (int) Math
.floor(squarePlotWorld.ROAD_WIDTH / 2) - 1;
int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - (int) Math
.floor(squarePlotWorld.ROAD_WIDTH / 2) - 1;
return Location.at(squarePlotWorld.getWorldName(), x, Math.min(getWorldHeight(), 255), z);
}
@ -130,7 +135,7 @@ public abstract class SquarePlotManager extends GridPlotManager {
}
}
public PlotId getNearestPlotId(PlotArea plotArea, int x, int y, int z) {
public PlotId getNearestPlotId(@Nonnull PlotArea plotArea, int x, int y, int z) {
SquarePlotWorld dpw = (SquarePlotWorld) plotArea;
if (dpw.ROAD_OFFSET_X != 0) {
x -= dpw.ROAD_OFFSET_X;
@ -191,8 +196,7 @@ public abstract class SquarePlotManager extends GridPlotManager {
rz = z % size;
}
PlotId id = PlotId.of(dx, dz);
boolean[] merged =
new boolean[] {rz <= pathWidthLower, rx > end, rz > end, rx <= pathWidthLower};
boolean[] merged = new boolean[] {rz <= pathWidthLower, rx > end, rz > end, rx <= pathWidthLower};
int hash = HashUtil.hash(merged);
// Not merged, and no need to check if it is
if (hash == 0) {
@ -230,8 +234,7 @@ public abstract class SquarePlotManager extends GridPlotManager {
return plot.getMerged(Direction.NORTHWEST) ? id : null;
}
} catch (Exception ignored) {
logger.error( "Invalid plot / road width in settings.yml for world: {}", squarePlotWorld
.getWorldName());
logger.error("Invalid plot / road width in settings.yml for world: {}", squarePlotWorld.getWorldName());
}
return null;
}
@ -239,15 +242,13 @@ public abstract class SquarePlotManager extends GridPlotManager {
/**
* Get the bottom plot loc (some basic math).
*/
@Override public Location getPlotBottomLocAbs(PlotId plotId) {
@Override public Location getPlotBottomLocAbs(@NotNull PlotId plotId) {
int px = plotId.getX();
int pz = plotId.getY();
int x = (squarePlotWorld.ROAD_OFFSET_X + (px * (squarePlotWorld.ROAD_WIDTH
+ squarePlotWorld.PLOT_WIDTH))) - squarePlotWorld.PLOT_WIDTH - (int) Math
.floor(squarePlotWorld.ROAD_WIDTH / 2);
int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH
+ squarePlotWorld.PLOT_WIDTH))) - squarePlotWorld.PLOT_WIDTH - (int) Math
.floor(squarePlotWorld.ROAD_WIDTH / 2);
int x = (squarePlotWorld.ROAD_OFFSET_X + (px * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - squarePlotWorld.PLOT_WIDTH
- (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2);
int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - squarePlotWorld.PLOT_WIDTH
- (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2);
return Location.at(squarePlotWorld.getWorldName(), x, squarePlotWorld.getMinBuildHeight(), z);
}
}

View File

@ -23,28 +23,17 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
package com.plotsquared.core.inject.factory;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.plotsquared.core.queue.ChunkCoordinatorBuilder;
import org.jetbrains.annotations.NotNull;
public class OffsetLocalBlockQueue extends DelegateLocalBlockQueue {
private final int ox;
private final int oy;
private final int oz;
import javax.annotation.Nonnull;
public OffsetLocalBlockQueue(LocalBlockQueue parent, int ox, int oy, int oz) {
super(parent);
this.ox = ox;
this.oy = oy;
this.oz = oz;
}
public interface ChunkCoordinatorBuilderFactory {
@Override public boolean setBiome(int x, int y, BiomeType biome) {
return super.setBiome(ox + x, oy + y, biome);
}
@Inject @Nonnull ChunkCoordinatorBuilder create(@Assisted @NotNull ChunkCoordinatorFactory chunkCoordinatorFactory);
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
return super.setBlock(ox + x, oy + y, oz + z, id);
}
}

View File

@ -0,0 +1,47 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.inject.factory;
import com.plotsquared.core.queue.ChunkCoordinator;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.function.Consumer;
public interface ChunkCoordinatorFactory {
@Nonnull ChunkCoordinator create(final long maxIterationTime,
final int initialBatchSize,
@Nonnull final Consumer<BlockVector2> chunkConsumer,
@Nonnull final World world,
@Nonnull final Collection<BlockVector2> requestedChunks,
@Nonnull final Runnable whenDone,
@Nonnull final Consumer<Throwable> throwableConsumer,
final boolean unloadAfter);
}

View File

@ -8,7 +8,7 @@
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) ${year} IntellectualSites
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -139,10 +139,6 @@ public class ConsolePlayer extends PlotPlayer<Actor> {
return true;
}
@Override public boolean isPermissionSet(@Nonnull String permission) {
return true;
}
@Override public void sendMessage(@Nonnull final Caption caption,
@Nonnull final Template... replacements) {
String message = caption.getComponent(this);

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ package com.plotsquared.core.plot;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.plotsquared.core.PlotSquared;
import com.google.common.collect.Lists;
import com.plotsquared.core.collection.QuadMap;
import com.plotsquared.core.configuration.ConfigurationNode;
@ -55,7 +56,7 @@ import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.plot.flag.implementations.DoneFlag;
import com.plotsquared.core.plot.flag.types.DoubleFlag;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.EconHandler;
import com.plotsquared.core.util.Expression;
import com.plotsquared.core.util.MathMan;
@ -183,8 +184,8 @@ public abstract class PlotArea {
@Nonnull protected abstract PlotManager createManager();
public LocalBlockQueue getQueue(final boolean autoQueue) {
return this.globalBlockQueue.getNewQueue(worldName, autoQueue);
public QueueCoordinator getQueue() {
return this.globalBlockQueue.getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(worldName));
}
/**
@ -947,7 +948,8 @@ public abstract class PlotArea {
final PlotId pos2 = plotIds.get(plotIds.size() - 1);
final PlotManager manager = getPlotManager();
manager.startPlotMerge(plotIds);
QueueCoordinator queue = getQueue();
manager.startPlotMerge(plotIds, queue);
final Set<UUID> trusted = new HashSet<>();
final Set<UUID> members = new HashSet<>();
final Set<UUID> denied = new HashSet<>();
@ -982,24 +984,25 @@ public abstract class PlotArea {
if (ly) {
if (!plot.getMerged(Direction.EAST) || !plot.getMerged(Direction.SOUTH)) {
if (removeRoads) {
plot.removeRoadSouthEast();
plot.removeRoadSouthEast(queue);
}
}
}
if (!plot.getMerged(Direction.EAST)) {
plot2 = plot.getRelative(1, 0);
plot.mergePlot(plot2, removeRoads);
plot.mergePlot(plot2, removeRoads, queue);
}
}
if (ly) {
if (!plot.getMerged(Direction.SOUTH)) {
plot2 = plot.getRelative(0, 1);
plot.mergePlot(plot2, removeRoads);
plot.mergePlot(plot2, removeRoads, queue);
}
}
}
}
manager.finishPlotMerge(plotIds);
manager.finishPlotMerge(plotIds, queue);
queue.enqueue();
return true;
}

View File

@ -43,7 +43,7 @@ public class PlotItemStack {
* @param amount Amount of items in the stack
* @param name The display name of the item stack
* @param lore The item stack lore
* @deprecated Use {@link PlotItemStack(String, int, String, String...)}
* @deprecated Use {@link #PlotItemStack(String, int, String, String...)}
*/
@Deprecated public PlotItemStack(final int id, final short data, final int amount,
final String name, final String... lore) {

View File

@ -28,9 +28,12 @@ package com.plotsquared.core.plot;
import com.plotsquared.core.command.Template;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.FileBytes;
import com.sk89q.worldedit.function.pattern.Pattern;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
@ -40,7 +43,7 @@ public abstract class PlotManager {
private final PlotArea plotArea;
public PlotManager(PlotArea plotArea) {
public PlotManager(@Nonnull PlotArea plotArea) {
this.plotArea = plotArea;
}
@ -53,19 +56,22 @@ public abstract class PlotManager {
public abstract PlotId getPlotId(int x, int y, int z);
// If you have a circular plot, just return the corner if it were a square
public abstract Location getPlotBottomLocAbs(PlotId plotId);
public abstract Location getPlotBottomLocAbs(@Nonnull PlotId plotId);
// the same applies here
public abstract Location getPlotTopLocAbs(PlotId plotId);
public abstract Location getPlotTopLocAbs(@Nonnull PlotId plotId);
/*
* Plot clearing (return false if you do not support some method)
public abstract boolean clearPlot(@Nonnull Plot plot, @Nullable Runnable whenDone, @Nullable QueueCoordinator queue);
public abstract boolean claimPlot(@Nonnull Plot plot, @Nullable QueueCoordinator queue);
/**
* Completes block changes associated with plot unclaim.
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean clearPlot(Plot plot, Runnable whenDone);
public abstract boolean claimPlot(Plot plot);
public abstract boolean unClaimPlot(Plot plot, Runnable whenDone);
public abstract boolean unClaimPlot(@Nonnull Plot plot, @Nullable Runnable whenDone, @Nullable QueueCoordinator queue);
/**
* Retrieves the location of where a sign should be for a plot.
@ -73,44 +79,98 @@ public abstract class PlotManager {
* @param plot The plot
* @return The location where a sign should be
*/
public abstract Location getSignLoc(Plot plot);
public abstract Location getSignLoc(@Nonnull Plot plot);
/*
* Plot set functions (return false if you do not support the specific set
* method).
*/
public abstract String[] getPlotComponents(PlotId plotId);
public abstract String[] getPlotComponents(@Nonnull PlotId plotId);
public abstract boolean setComponent(PlotId plotId, String component, Pattern blocks);
/*
* PLOT MERGING (return false if your generator does not support plot
* merging).
/**
* Set the specified components to the specified Pattern on the specified plot.
*
* @param component FLOOR, WALL, AIR, MAIN, MIDDLE, OUTLINE, BORDER, ALL (floor, air and main).
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean createRoadEast(Plot plot);
public abstract boolean setComponent(@Nonnull PlotId plotId,
@Nonnull String component,
@Nonnull Pattern blocks,
@Nullable QueueCoordinator queue);
public abstract boolean createRoadSouth(Plot plot);
/**
* Create the road east of the plot (not schematic-based)
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean createRoadEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue);
public abstract boolean createRoadSouthEast(Plot plot);
/**
* Create the road south of the plot (not schematic-based)
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean createRoadSouth(@Nonnull Plot plot, @Nullable QueueCoordinator queue);
public abstract boolean removeRoadEast(Plot plot);
/**
* Create the south-east corner of the road (intersection, not schematic-based)
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean createRoadSouthEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue);
public abstract boolean removeRoadSouth(Plot plot);
/**
* Replace the road to the east of the plot with standard plot blocks (for when merging plots)
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean removeRoadEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue);
public abstract boolean removeRoadSouthEast(Plot plot);
/**
* Replace the road to the south of the plot with standard plot blocks (for when merging plots)
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean removeRoadSouth(@Nonnull Plot plot, @Nullable QueueCoordinator queue);
public abstract boolean startPlotMerge(List<PlotId> plotIds);
/**
* Replace the road to the south east of the plot (intersection) with standard plot blocks (for when merging plots)
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean removeRoadSouthEast(@Nonnull Plot plot, @Nullable QueueCoordinator queue);
public abstract boolean startPlotUnlink(List<PlotId> plotIds);
public abstract boolean startPlotMerge(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
public abstract boolean finishPlotMerge(List<PlotId> plotIds);
public abstract boolean startPlotUnlink(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
public abstract boolean finishPlotUnlink(List<PlotId> plotIds);
/**
* Finishing off plot merging by adding in the walls surrounding the plot (OPTIONAL)(UNFINISHED).
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
* @return false if part if the merge failed, otherwise true if successful.
*/
public abstract boolean finishPlotMerge(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
/**
* Finished off an unlink by resetting the top wall block for unlinked plots
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public abstract boolean finishPlotUnlink(@Nonnull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
public void exportTemplate() throws IOException {
HashSet<FileBytes> files = new HashSet<>(Collections.singletonList(
new FileBytes(Settings.Paths.TEMPLATES + "/tmp-data.yml",
Template.getBytes(plotArea))));
HashSet<FileBytes> files =
new HashSet<>(Collections.singletonList(new FileBytes(Settings.Paths.TEMPLATES + "/tmp-data.yml", Template.getBytes(plotArea))));
Template.zipAll(plotArea.getWorldName(), files);
}
@ -121,15 +181,17 @@ public abstract class PlotManager {
/**
* Sets all the blocks along all the plot walls to their correct state (claimed or unclaimed).
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
* @return true if the wall blocks were successfully set
*/
public boolean regenerateAllPlotWalls() {
public boolean regenerateAllPlotWalls(@Nullable QueueCoordinator queue) {
boolean success = true;
for (Plot plot : plotArea.getPlots()) {
if (plot.hasOwner()) {
success &= claimPlot(plot);
success &= claimPlot(plot, queue);
} else {
success &= unClaimPlot(plot, null);
success &= unClaimPlot(plot, null, queue);
}
}
return success;

View File

@ -25,6 +25,7 @@
*/
package com.plotsquared.core.plot.flag;
import com.google.common.base.Preconditions;
import com.plotsquared.core.plot.flag.implementations.AnalysisFlag;
import com.plotsquared.core.plot.flag.implementations.AnimalAttackFlag;
import com.plotsquared.core.plot.flag.implementations.AnimalCapFlag;
@ -113,7 +114,13 @@ import java.util.Map;
public final class GlobalFlagContainer extends FlagContainer {
private static final GlobalFlagContainer instance = new GlobalFlagContainer();
private static GlobalFlagContainer instance;
public static void setup() {
Preconditions.checkState(instance == null, "Cannot setup the container twice");
instance = new GlobalFlagContainer();
}
private static Map<String, Class<?>> stringClassMap;
private GlobalFlagContainer() {
@ -123,6 +130,7 @@ public final class GlobalFlagContainer extends FlagContainer {
}
});
stringClassMap = new HashMap<>();
// Register all default flags here
// Boolean flags
this.addFlag(ExplosionFlag.EXPLOSION_FALSE);

View File

@ -144,8 +144,7 @@ public abstract class PlotFlag<T, F extends PlotFlag<T, F>> {
}
/**
* Get the category this flag belongs to. Usually a caption from
* {@link Captions}
* Get the category this flag belongs to. Usually a caption from {@link com.plotsquared.core.configuration.caption.TranslatableCaption}
* <p>
* These categories are used to categorize the flags when outputting
* flag lists to players.

View File

@ -31,11 +31,14 @@ import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.task.TaskManager;
import com.sk89q.worldedit.function.pattern.Pattern;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.List;
@ -53,15 +56,15 @@ public class SinglePlotManager extends PlotManager {
return PlotId.of(0, 0);
}
@Override public Location getPlotBottomLocAbs(@Nonnull final PlotId plotId) {
@Override public Location getPlotBottomLocAbs(@Nonnull final @NotNull PlotId plotId) {
return Location.at(plotId.toCommaSeparatedString(), -30000000, 0, -30000000);
}
@Override public Location getPlotTopLocAbs(@Nonnull final PlotId plotId) {
@Override public Location getPlotTopLocAbs(@Nonnull final @NotNull PlotId plotId) {
return Location.at(plotId.toCommaSeparatedString(), 30000000, 0, 30000000);
}
@Override public boolean clearPlot(Plot plot, final Runnable whenDone) {
@Override public boolean clearPlot(@NotNull Plot plot, final Runnable whenDone, @Nullable QueueCoordinator queue) {
PlotSquared.platform().getSetupUtils().unload(plot.getWorldName(), false);
final File worldFolder = new File(PlotSquared.platform().getWorldContainer(), plot.getWorldName());
TaskManager.getPlatformImplementation().taskAsync(() -> {
@ -73,71 +76,72 @@ public class SinglePlotManager extends PlotManager {
return true;
}
@Override public boolean claimPlot(Plot plot) {
@Override public boolean claimPlot(@NotNull Plot plot, @Nullable QueueCoordinator queue) {
// TODO
return true;
}
@Override public boolean unClaimPlot(Plot plot, Runnable whenDone) {
@Override public boolean unClaimPlot(@NotNull Plot plot, Runnable whenDone, @Nullable QueueCoordinator queue) {
if (whenDone != null) {
whenDone.run();
}
return true;
}
@Override public Location getSignLoc(Plot plot) {
@Override public Location getSignLoc(@NotNull Plot plot) {
return null;
}
@Override public String[] getPlotComponents(PlotId plotId) {
@Override public String[] getPlotComponents(@NotNull PlotId plotId) {
return new String[0];
}
@Override public boolean setComponent(PlotId plotId, String component, Pattern blocks) {
@Override
public boolean setComponent(@NotNull PlotId plotId, @NotNull String component, @NotNull Pattern blocks, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean createRoadEast(Plot plot) {
@Override public boolean createRoadEast(@NotNull Plot plot, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean createRoadSouth(Plot plot) {
@Override public boolean createRoadSouth(@NotNull Plot plot, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean createRoadSouthEast(Plot plot) {
@Override public boolean createRoadSouthEast(@NotNull Plot plot, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean removeRoadEast(Plot plot) {
@Override public boolean removeRoadEast(@NotNull Plot plot, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean removeRoadSouth(Plot plot) {
@Override public boolean removeRoadSouth(@NotNull Plot plot, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean removeRoadSouthEast(Plot plot) {
@Override public boolean removeRoadSouthEast(@NotNull Plot plot, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean startPlotMerge(List<PlotId> plotIds) {
@Override public boolean startPlotMerge(@NotNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean startPlotUnlink(List<PlotId> plotIds) {
@Override public boolean startPlotUnlink(@NotNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean finishPlotMerge(List<PlotId> plotIds) {
@Override public boolean finishPlotMerge(@NotNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean finishPlotUnlink(List<PlotId> plotIds) {
@Override public boolean finishPlotUnlink(@NotNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) {
return false;
}
@Override public boolean regenerateAllPlotWalls() {
@Override public boolean regenerateAllPlotWalls(@Nullable QueueCoordinator queue) {
return false;
}
}

View File

@ -26,6 +26,7 @@
package com.plotsquared.core.queue;
import com.plotsquared.core.plot.PlotArea;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -35,45 +36,64 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
public class AreaBoundDelegateLocalBlockQueue extends DelegateLocalBlockQueue {
/**
* Queue Coordinator that only sets blocks with the specified PlotArea
*/
public class AreaBoundDelegateQueueCoordinator extends DelegateQueueCoordinator {
private final PlotArea area;
public AreaBoundDelegateLocalBlockQueue(@Nonnull final PlotArea area,
@Nullable final LocalBlockQueue parent) {
public AreaBoundDelegateQueueCoordinator(@Nonnull final PlotArea area, @Nullable final QueueCoordinator parent) {
super(parent);
this.area = Objects.requireNonNull(area);
}
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
/**
* Gets the plot area block settings is limited to
*/
public PlotArea getArea() {
return this.area;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull BlockState id) {
if (area.contains(x, z)) {
return super.setBlock(x, y, z, id);
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
@Override public boolean setBlock(int x, int y, int z, @Nonnull BaseBlock id) {
if (area.contains(x, z)) {
return super.setBlock(x, y, z, id);
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, Pattern pattern) {
@Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
if (area.contains(x, z)) {
return super.setBlock(x, y, z, pattern);
}
return false;
}
@Override public boolean setBiome(int x, int z, BiomeType biome) {
@Override public boolean setBiome(int x, int z, @Nonnull BiomeType biome) {
if (area.contains(x, z)) {
return super.setBiome(x, z, biome);
}
return false;
}
public PlotArea getArea() {
return this.area;
@Override public boolean setBiome(int x, int y, int z, @Nonnull BiomeType biome) {
if (area.contains(x, z)) {
return super.setBiome(x, y, z, biome);
}
return false;
}
@Override public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) {
if (area.contains(x, z)) {
return super.setTile(x, y, z, tag);
}
return false;
}
}

View File

@ -1,274 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.plotsquared.core.util.ChunkUtil;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.PatternUtil;
import com.plotsquared.core.util.task.TaskManager;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nonnull;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ExecutionException;
public abstract class BasicLocalBlockQueue extends LocalBlockQueue {
private final String world;
private final ConcurrentHashMap<Long, LocalChunk> blockChunks = new ConcurrentHashMap<>();
private final ConcurrentLinkedDeque<LocalChunk> chunks = new ConcurrentLinkedDeque<>();
private long modified;
private LocalChunk lastWrappedChunk;
private int lastX = Integer.MIN_VALUE;
private int lastZ = Integer.MIN_VALUE;
private boolean setbiome = false;
private GlobalBlockQueue globalBlockQueue;
public BasicLocalBlockQueue(String world) {
super(world);
this.world = world;
this.modified = System.currentTimeMillis();
}
public abstract LocalChunk getLocalChunk(int x, int z);
@Override public abstract BlockState getBlock(int x, int y, int z);
public abstract void setComponents(LocalChunk lc)
throws ExecutionException, InterruptedException;
@Override public final String getWorld() {
return world;
}
@Override public final boolean next() {
lastX = Integer.MIN_VALUE;
lastZ = Integer.MIN_VALUE;
try {
if (this.blockChunks.size() == 0) {
return false;
}
synchronized (blockChunks) {
LocalChunk chunk = chunks.poll();
if (chunk != null) {
blockChunks.remove(chunk.longHash());
return this.execute(chunk);
}
}
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
public final boolean execute(@Nonnull LocalChunk lc)
throws ExecutionException, InterruptedException {
this.setComponents(lc);
return true;
}
@Override public void startSet(boolean parallel) {
// Do nothing
}
@Override public void endSet(boolean parallel) {
// Do nothing
}
@Override public final int size() {
return chunks.size();
}
@Override public final long getModified() {
return modified;
}
@Override public final void setModified(long modified) {
this.modified = modified;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
return setBlock(x, y, z, PatternUtil.apply(pattern, x, y, z));
}
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
if ((y > 255) || (y < 0)) {
return false;
}
int cx = x >> 4;
int cz = z >> 4;
if (cx != lastX || cz != lastZ) {
lastX = cx;
lastZ = cz;
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
lastWrappedChunk = this.blockChunks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = this.getLocalChunk(x >> 4, z >> 4);
lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
LocalChunk previous = this.blockChunks.put(pair, lastWrappedChunk);
if (previous == null) {
return chunks.add(lastWrappedChunk);
}
this.blockChunks.put(pair, previous);
lastWrappedChunk = previous;
}
}
lastWrappedChunk.setBlock(x & 15, y, z & 15, id);
return true;
}
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
// Trying to mix BlockState and BaseBlock leads to all kinds of issues.
// Since BaseBlock has more features than BlockState, simply convert
// all BlockStates to BaseBlocks
return setBlock(x, y, z, id.toBaseBlock());
}
@Override public final boolean setBiome(int x, int z, BiomeType biomeType) {
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
LocalChunk result = this.blockChunks.get(pair);
if (result == null) {
result = this.getLocalChunk(x >> 4, z >> 4);
LocalChunk previous = this.blockChunks.put(pair, result);
if (previous != null) {
this.blockChunks.put(pair, previous);
result = previous;
} else {
chunks.add(result);
}
}
result.setBiome(x & 15, z & 15, biomeType);
setbiome = true;
return true;
}
@Override public final boolean setBiome() {
return setbiome;
}
public final void setChunk(LocalChunk chunk) {
LocalChunk previous = this.blockChunks.put(chunk.longHash(), chunk);
if (previous != null) {
chunks.remove(previous);
}
chunks.add(chunk);
}
@Override public void flush() {
this.globalBlockQueue.dequeue(this);
try {
TaskManager.getPlatformImplementation().sync(() -> {
while (next()) {
}
return null;
});
} catch (final Exception e) {
e.printStackTrace();
}
}
public abstract class LocalChunk {
public final BasicLocalBlockQueue parent;
public final int z;
public final int x;
public BaseBlock[][] baseblocks;
public BiomeType[][] biomes;
public LocalChunk(BasicLocalBlockQueue parent, int x, int z) {
this.parent = parent;
this.x = x;
this.z = z;
}
/**
* Get the parent queue this chunk belongs to
*
* @return
*/
public BasicLocalBlockQueue getParent() {
return parent;
}
public int getX() {
return x;
}
public int getZ() {
return z;
}
public abstract void setBlock(final int x, final int y, final int z, final BaseBlock block);
public void setBiome(int x, int z, BiomeType biomeType) {
if (this.biomes == null) {
this.biomes = new BiomeType[16][];
}
BiomeType[] index = this.biomes[x];
if (index == null) {
index = this.biomes[x] = new BiomeType[16];
}
index[z] = biomeType;
}
public long longHash() {
return MathMan.pairInt(x, z);
}
@Override public int hashCode() {
return MathMan.pair((short) x, (short) z);
}
}
public class BasicLocalChunk extends LocalChunk {
public BasicLocalChunk(BasicLocalBlockQueue parent, int x, int z) {
super(parent, x, z);
baseblocks = new BaseBlock[16][];
}
@Override public void setBlock(int x, int y, int z, BaseBlock block) {
this.setInternal(x, y, z, block);
}
private void setInternal(final int x, final int y, final int z, final BaseBlock baseBlock) {
final int i = y >> 4;
final int j = ChunkUtil.getJ(x, y, z);
BaseBlock[] array = baseblocks[i];
if (array == null) {
array = (baseblocks[i] = new BaseBlock[4096]);
}
array[j] = baseBlock;
}
}
}

View File

@ -0,0 +1,273 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.plotsquared.core.util.PatternUtil;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.entity.EntityTypes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
/**
* Standard block setting queue that allows block setting across numerous chunks, without limits.
*/
public abstract class BasicQueueCoordinator extends QueueCoordinator {
private final World world;
private final ConcurrentHashMap<BlockVector2, LocalChunk> blockChunks = new ConcurrentHashMap<>();
private final List<BlockVector2> readRegion = new ArrayList<>();
private long modified;
private LocalChunk lastWrappedChunk;
private int lastX = Integer.MIN_VALUE;
private int lastZ = Integer.MIN_VALUE;
private boolean settingBiomes = false;
private boolean settingTiles = false;
private boolean regen = false;
private int[] regenStart;
private int[] regenEnd;
private CuboidRegion regenRegion = null;
private Consumer<BlockVector2> consumer = null;
private boolean unloadAfter = true;
private Runnable whenDone;
public BasicQueueCoordinator(@Nonnull World world) {
super(world);
this.world = world;
this.modified = System.currentTimeMillis();
}
@Override public abstract BlockState getBlock(int x, int y, int z);
@Override public final @Nonnull World getWorld() {
return world;
}
@Override public final int size() {
return blockChunks.size() + readRegion.size();
}
@Override public final void setModified(long modified) {
this.modified = modified;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
return setBlock(x, y, z, PatternUtil.apply(pattern, x, y, z));
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull BaseBlock id) {
if ((y > 255) || (y < 0)) {
return false;
}
LocalChunk chunk = getChunk(x >> 4, z >> 4);
chunk.setBlock(x & 15, y, z & 15, id);
return true;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull BlockState id) {
// Trying to mix BlockState and BaseBlock leads to all kinds of issues.
// Since BaseBlock has more features than BlockState, simply convert
// all BlockStates to BaseBlocks
return setBlock(x, y, z, id.toBaseBlock());
}
@Override public boolean setBiome(int x, int z, @Nonnull BiomeType biomeType) {
LocalChunk chunk = getChunk(x >> 4, z >> 4);
for (int y = 0; y < 256; y++) {
chunk.setBiome(x & 15, y, z & 15, biomeType);
}
settingBiomes = true;
return true;
}
@Override public final boolean setBiome(int x, int y, int z, @Nonnull BiomeType biomeType) {
LocalChunk chunk = getChunk(x >> 4, z >> 4);
chunk.setBiome(x & 15, y, z & 15, biomeType);
settingBiomes = true;
return true;
}
@Override public boolean isSettingBiomes() {
return this.settingBiomes;
}
@Override public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) {
LocalChunk chunk = getChunk(x >> 4, z >> 4);
chunk.setTile(x, y, z, tag);
settingTiles = true;
return true;
}
@Override public boolean isSettingTiles() {
return this.settingTiles;
}
@Override public boolean setEntity(@Nonnull Entity entity) {
if (entity.getState() == null || entity.getState().getType() == EntityTypes.PLAYER) {
return false;
}
Location location = entity.getLocation();
LocalChunk chunk = getChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4);
chunk.setEntity(location, entity.getState());
return true;
}
@Override public @Nonnull List<BlockVector2> getReadChunks() {
return this.readRegion;
}
@Override public void addReadChunk(@Nonnull BlockVector2 chunk) {
this.readRegion.add(chunk);
}
@Override public void addReadChunks(@Nonnull Set<BlockVector2> readRegion) {
this.readRegion.addAll(readRegion);
}
@Override public CuboidRegion getRegenRegion() {
return this.regenRegion != null ? this.regenRegion.clone() : null;
}
@Override public void setRegenRegion(@Nonnull CuboidRegion regenRegion) {
this.regenRegion = regenRegion;
}
@Override public void regenChunk(int x, int z) {
regen = true;
// There will never only be one nullified coordinate pair
if (regenStart == null) {
regenStart = new int[] {x, z};
regenEnd = new int[] {x, z};
return;
}
if (x < regenStart[0]) {
regenStart[0] = x;
}
if (z < regenStart[1]) {
regenStart[1] = z;
}
if (x > regenEnd[0]) {
regenEnd[0] = x;
}
if (z > regenEnd[1]) {
regenEnd[1] = z;
}
}
@Override public boolean isUnloadAfter() {
return this.unloadAfter;
}
@Override public void setUnloadAfter(boolean unloadAfter) {
this.unloadAfter = unloadAfter;
}
/**
* Gets the int[x,z] chunk coordinates where regeneration should start from
*/
public int[] getRegenStart() {
return regenStart;
}
/**
* Gets the int[x,z] chunk coordinates where regeneration should finish
*/
public int[] getRegenEnd() {
return regenEnd;
}
/**
* Whether the queue has a start/end to chunk regeneration
*/
public boolean isRegen() {
return regen;
}
/**
* Gets the map of ChunkCoordinates in {@link BlockVector2} form against the {@link LocalChunk} of cached chunks to be written
*/
@Nonnull public ConcurrentHashMap<BlockVector2, LocalChunk> getBlockChunks() {
return this.blockChunks;
}
/**
* Forces an {@link LocalChunk} into the list of chunks to be written. Overwrites existing chunks in the map
*/
public final void setChunk(@Nonnull LocalChunk chunk) {
this.blockChunks.put(BlockVector2.at(chunk.getX(), chunk.getZ()), chunk);
}
@Override @Nullable public final Consumer<BlockVector2> getChunkConsumer() {
return this.consumer;
}
@Override public final void setChunkConsumer(@Nonnull Consumer<BlockVector2> consumer) {
this.consumer = consumer;
}
@Override public Runnable getCompleteTask() {
return this.whenDone;
}
@Override public void setCompleteTask(Runnable whenDone) {
this.whenDone = whenDone;
}
/**
* Get the {@link LocalChunk} from the queue at the given chunk coordinates. Returns a new instance if one doesn't exist
*/
@Nonnull private LocalChunk getChunk(final int chunkX, final int chunkZ) {
if (chunkX != lastX || chunkZ != lastZ) {
lastX = chunkX;
lastZ = chunkZ;
BlockVector2 pair = BlockVector2.at(chunkX, chunkZ);
lastWrappedChunk = this.blockChunks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = new LocalChunk(this, chunkX, chunkZ);
LocalChunk previous = this.blockChunks.put(pair, lastWrappedChunk);
if (previous == null) {
return lastWrappedChunk;
}
lastWrappedChunk = previous;
}
}
return lastWrappedChunk;
}
}

View File

@ -0,0 +1,62 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.plotsquared.core.util.task.PlotSquaredTask;
public abstract class ChunkCoordinator implements PlotSquaredTask {
@Override public abstract void runTask();
@Override public boolean isCancelled() {
return false;
}
@Override public void cancel() {
// Do nothing
}
/**
* Starts the chunk coordinator. This will usually (implementation-specific-permitting) mark chunks to be loaded in batches,
* then add them to a queue and apply tickets once loaded to prevent unloading. A repeating task will then iterate over loaded
* chunks, access them with a Consumer(BlockVector2) and remove the ticket once work has been completed on it.
*/
public abstract void start();
/**
* Get the amount of remaining chunks (at the time of the method call)
*
* @return Snapshot view of remaining chunk count
*/
public abstract int getRemainingChunks();
/**
* Get the amount of requested chunks
*
* @return Requested chunk count
*/
public abstract int getTotalChunks();
}

View File

@ -0,0 +1,178 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.location.Location;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
/**
* Builds a {@link ChunkCoordinator} instance
*/
public class ChunkCoordinatorBuilder {
private final List<BlockVector2> requestedChunks = new LinkedList<>();
private final ChunkCoordinatorFactory chunkCoordinatorFactory;
private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace;
private World world;
private Consumer<BlockVector2> chunkConsumer;
private Runnable whenDone = () -> {
};
private long maxIterationTime = 60; // A little over 1 tick;
private int initialBatchSize = 4;
private boolean unloadAfter = true;
@Inject public ChunkCoordinatorBuilder(@Nonnull ChunkCoordinatorFactory chunkCoordinatorFactory) {
this.chunkCoordinatorFactory = chunkCoordinatorFactory;
}
/**
* Set the world
*/
@Nonnull public ChunkCoordinatorBuilder inWorld(@Nonnull final World world) {
this.world = Preconditions.checkNotNull(world, "World may not be null");
return this;
}
/**
* Add a chunk to be accessed
*/
@Nonnull public ChunkCoordinatorBuilder withChunk(@Nonnull final BlockVector2 chunkLocation) {
this.requestedChunks.add(Preconditions.checkNotNull(chunkLocation, "Chunk location may not be null"));
return this;
}
/**
* Add a Collection of chunks to be accessed
*/
@Nonnull public ChunkCoordinatorBuilder withChunks(@Nonnull final Collection<BlockVector2> chunkLocations) {
chunkLocations.forEach(this::withChunk);
return this;
}
/**
* Add chunks within a region to be accessed
*/
@Nonnull public ChunkCoordinatorBuilder withRegion(@Nonnull Location pos1, @Nonnull Location pos2) {
final int p1x = pos1.getX();
final int p1z = pos1.getZ();
final int p2x = pos2.getX();
final int p2z = pos2.getZ();
final int bcx = p1x >> 4;
final int bcz = p1z >> 4;
final int tcx = p2x >> 4;
final int tcz = p2z >> 4;
final ArrayList<BlockVector2> chunks = new ArrayList<>();
for (int x = bcx; x <= tcx; x++) {
for (int z = bcz; z <= tcz; z++) {
chunks.add(BlockVector2.at(x, z));
}
}
chunks.forEach(this::withChunk);
return this;
}
/**
* Set the consumer to be used when a chunk is loaded
*/
@Nonnull public ChunkCoordinatorBuilder withConsumer(@Nonnull final Consumer<BlockVector2> chunkConsumer) {
this.chunkConsumer = Preconditions.checkNotNull(chunkConsumer, "Chunk consumer may not be null");
return this;
}
/**
* Set the Runnable to run when all chunks have been accessed
*/
@Nonnull public ChunkCoordinatorBuilder withFinalAction(@Nullable final Runnable whenDone) {
if (whenDone == null) {
return this;
}
this.whenDone = whenDone;
return this;
}
/**
* Set the max time taken while iterating over and accessing loaded chunks
*/
@Nonnull public ChunkCoordinatorBuilder withMaxIterationTime(final long maxIterationTime) {
Preconditions.checkArgument(maxIterationTime > 0, "Max iteration time must be positive");
this.maxIterationTime = maxIterationTime;
return this;
}
/**
* Set the initial batch size to be used for loading chunks
*/
@Nonnull public ChunkCoordinatorBuilder withInitialBatchSize(final int initialBatchSize) {
Preconditions.checkArgument(initialBatchSize > 0, "Initial batch size must be positive");
this.initialBatchSize = initialBatchSize;
return this;
}
/**
* Set the consumer to be used to handle {@link Throwable}s
*/
@Nonnull public ChunkCoordinatorBuilder withThrowableConsumer(@Nonnull final Consumer<Throwable> throwableConsumer) {
this.throwableConsumer = Preconditions.checkNotNull(throwableConsumer, "Throwable consumer may not be null");
return this;
}
/**
* Set whether the chunks should be allow to unload after being accessed. This should only be used where the chunks are read from
* and then written to from a separate queue where they're consequently unloaded.
*/
@Nonnull public ChunkCoordinatorBuilder unloadAfter(final boolean unloadAfter) {
this.unloadAfter = unloadAfter;
return this;
}
/**
* Create a new {@link ChunkCoordinator} instance based on the values in the Builder instance.
*/
@Nonnull public ChunkCoordinator build() {
Preconditions.checkNotNull(this.world, "No world was supplied");
Preconditions.checkNotNull(this.chunkConsumer, "No chunk consumer was supplied");
Preconditions.checkNotNull(this.whenDone, "No final action was supplied");
Preconditions.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied");
return chunkCoordinatorFactory
.create(this.maxIterationTime, this.initialBatchSize, this.chunkConsumer, this.world, this.requestedChunks, this.whenDone,
this.throwableConsumer, this.unloadAfter);
}
}

View File

@ -28,65 +28,69 @@ package com.plotsquared.core.queue;
import com.plotsquared.core.location.Location;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
public class ChunkBlockQueue extends ScopedLocalBlockQueue {
/**
* Queue that is limited to a single chunk
*/
public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
public final BiomeType[] biomeGrid;
public final BiomeType[][][] biomeResult;
public final BlockState[][][] result;
private final int width;
private final int length;
@Deprecated private final int area;
private final BlockVector3 bot;
private final BlockVector3 top;
public ChunkBlockQueue(BlockVector3 bot, BlockVector3 top, boolean biomes) {
public ChunkQueueCoordinator(@Nonnull BlockVector3 bot, @Nonnull BlockVector3 top, boolean biomes) {
super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15));
this.width = top.getX() - bot.getX() + 1;
this.length = top.getZ() - bot.getZ() + 1;
this.area = width * length;
this.result = new BlockState[256][][];
this.biomeGrid = biomes ? new BiomeType[width * length] : null;
this.biomeResult = biomes ? new BiomeType[256][][] : null;
this.bot = bot;
this.top = top;
}
public BlockState[][][] getBlocks() {
@Nonnull public BlockState[][][] getBlocks() {
return result;
}
@Override public void fillBiome(BiomeType biomeType) {
if (biomeGrid == null) {
return;
}
Arrays.fill(biomeGrid, biomeType);
}
@Override public boolean setBiome(int x, int z, BiomeType biomeType) {
if (this.biomeGrid != null) {
biomeGrid[(z * width) + x] = biomeType;
@Override public boolean setBiome(int x, int z, @Nonnull BiomeType biomeType) {
if (this.biomeResult != null) {
for (int y = 0; y < 256; y++) {
this.storeCacheBiome(x, y, z, biomeType);
}
return true;
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
@Override public boolean setBiome(int x, int y, int z, @Nonnull BiomeType biomeType) {
if (this.biomeResult != null) {
this.storeCacheBiome(x, y, z, biomeType);
return true;
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull BlockState id) {
this.storeCache(x, y, z, id);
return true;
}
@Override public boolean setBlock(int x, int y, int z, Pattern pattern) {
@Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
this.storeCache(x, y, z, pattern.apply(BlockVector3.at(x, y, z)).toImmutableState());
return true;
}
private void storeCache(final int x, final int y, final int z, final BlockState id) {
private void storeCache(final int x, final int y, final int z, @Nonnull final BlockState id) {
BlockState[][] resultY = result[y];
if (resultY == null) {
result[y] = resultY = new BlockState[length][];
@ -98,7 +102,19 @@ public class ChunkBlockQueue extends ScopedLocalBlockQueue {
resultYZ[x] = id;
}
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
private void storeCacheBiome(final int x, final int y, final int z, @Nonnull final BiomeType id) {
BiomeType[][] resultY = biomeResult[y];
if (resultY == null) {
biomeResult[y] = resultY = new BiomeType[length][];
}
BiomeType[] resultYZ = resultY[z];
if (resultYZ == null) {
resultY[z] = resultYZ = new BiomeType[width];
}
resultYZ[x] = id;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull final BaseBlock id) {
this.storeCache(x, y, z, id.toImmutableState());
return true;
}
@ -114,15 +130,15 @@ public class ChunkBlockQueue extends ScopedLocalBlockQueue {
return null;
}
@Override @Nonnull public String getWorld() {
return "";
@Override @Nullable public World getWorld() {
return super.getWorld();
}
@Override public Location getMax() {
return Location.at(getWorld(), top.getX(), top.getY(), top.getZ());
@Override @Nonnull public Location getMax() {
return Location.at(getWorld().getName(), top.getX(), top.getY(), top.getZ());
}
@Override public Location getMin() {
return Location.at(getWorld(), bot.getX(), bot.getY(), bot.getZ());
@Override @Nonnull public Location getMin() {
return Location.at(getWorld().getName(), bot.getX(), bot.getY(), bot.getZ());
}
}

View File

@ -1,151 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
public class DelegateLocalBlockQueue extends LocalBlockQueue {
private final LocalBlockQueue parent;
public DelegateLocalBlockQueue(LocalBlockQueue parent) {
super(parent == null ? null : parent.getWorld());
this.parent = parent;
if (parent != null) {
this.setForceSync(parent.isForceSync());
this.setChunkObject(parent.getChunkObject());
}
}
public LocalBlockQueue getParent() {
return parent;
}
@Override public boolean next() {
return parent.next();
}
@Override public void startSet(boolean parallel) {
if (parent != null) {
parent.startSet(parallel);
}
}
@Override public void endSet(boolean parallel) {
if (parent != null) {
parent.endSet(parallel);
}
}
@Override public int size() {
if (parent != null) {
return parent.size();
}
return 0;
}
@Override public void optimize() {
if (parent != null) {
parent.optimize();
}
}
@Override public long getModified() {
if (parent != null) {
return parent.getModified();
}
return 0;
}
@Override public void setModified(long modified) {
if (parent != null) {
parent.setModified(modified);
}
}
@Override public boolean setBlock(int x, int y, int z, Pattern pattern) {
return parent.setBlock(x, y, z, pattern);
}
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
return parent.setBlock(x, y, z, id);
}
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
return parent.setBlock(x, y, z, id);
}
@Override public BlockState getBlock(int x, int y, int z) {
return parent.getBlock(x, y, z);
}
@Override public boolean setBiome(int x, int z, BiomeType biome) {
return parent.setBiome(x, z, biome);
}
@Override public boolean setBiome() {
return parent.setBiome();
}
@Override public String getWorld() {
return parent.getWorld();
}
@Override public void flush() {
if (parent != null) {
parent.flush();
}
}
@Override public void refreshChunk(int x, int z) {
if (parent != null) {
parent.refreshChunk(x, z);
}
}
@Override public void fixChunkLighting(int x, int z) {
if (parent != null) {
parent.fixChunkLighting(x, z);
}
}
@Override public void regenChunk(int x, int z) {
if (parent != null) {
parent.regenChunk(x, z);
}
}
@Override public boolean enqueue() {
if (parent != null) {
return parent.enqueue();
}
return false;
}
}

View File

@ -0,0 +1,251 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
/**
* Queue that delegates to a parent queue.
*/
public class DelegateQueueCoordinator extends QueueCoordinator {
private final QueueCoordinator parent;
public DelegateQueueCoordinator(QueueCoordinator parent) {
super(parent == null ? null : parent.getWorld());
this.parent = parent;
if (parent != null) {
this.setForceSync(parent.isForceSync());
}
}
public QueueCoordinator getParent() {
return parent;
}
@Override public int size() {
if (parent != null) {
return parent.size();
}
return 0;
}
@Override public void setModified(long modified) {
if (parent != null) {
parent.setModified(modified);
}
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
if (parent != null) {
return parent.setBlock(x, y, z, pattern);
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull BaseBlock id) {
if (parent != null) {
return parent.setBlock(x, y, z, id);
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull BlockState id) {
if (parent != null) {
return parent.setBlock(x, y, z, id);
}
return false;
}
@Override @Nullable public BlockState getBlock(int x, int y, int z) {
if (parent != null) {
return parent.getBlock(x, y, z);
}
return null;
}
@Override public boolean setBiome(int x, int z, @Nonnull BiomeType biome) {
if (parent != null) {
return parent.setBiome(x, z, biome);
}
return false;
}
@Override public boolean setBiome(int x, int y, int z, @Nonnull BiomeType biome) {
if (parent != null) {
return parent.setBiome(x, y, z, biome);
}
return false;
}
@Override public boolean isSettingBiomes() {
if (parent != null) {
return parent.isSettingBiomes();
}
return false;
}
@Override public boolean setEntity(@Nonnull Entity entity) {
if (parent != null) {
return parent.setEntity(entity);
}
return false;
}
@Override public void regenChunk(int x, int z) {
if (parent != null) {
parent.regenChunk(x, z);
}
}
@Override @Nullable public World getWorld() {
if (parent != null) {
return parent.getWorld();
}
return null;
}
@Override public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) {
if (parent != null) {
return parent.setTile(x, y, z, tag);
}
return false;
}
@Override public boolean isSettingTiles() {
if (parent != null) {
return parent.isSettingTiles();
}
return false;
}
@Override public boolean enqueue() {
if (parent != null) {
return parent.enqueue();
}
return false;
}
@Override public void start() {
if (parent != null) {
parent.start();
}
}
@Override public void cancel() {
if (parent != null) {
parent.cancel();
}
}
@Override public Runnable getCompleteTask() {
if (parent != null) {
return parent.getCompleteTask();
}
return null;
}
@Override public void setCompleteTask(Runnable whenDone) {
if (parent != null) {
parent.setCompleteTask(whenDone);
}
}
@Nullable @Override public Consumer<BlockVector2> getChunkConsumer() {
if (parent != null) {
return parent.getChunkConsumer();
}
return null;
}
@Override public void setChunkConsumer(@Nonnull Consumer<BlockVector2> consumer) {
if (parent != null) {
parent.setChunkConsumer(consumer);
}
}
@Override @Nonnull public List<BlockVector2> getReadChunks() {
if (parent != null) {
return parent.getReadChunks();
}
return new ArrayList<>();
}
@Override public void addReadChunks(@Nonnull Set<BlockVector2> readChunks) {
if (parent != null) {
parent.addReadChunks(readChunks);
}
}
@Override public void addReadChunk(@Nonnull BlockVector2 chunk) {
if (parent != null) {
parent.addReadChunk(chunk);
}
}
@Override public boolean isUnloadAfter() {
if (parent != null) {
return parent.isUnloadAfter();
}
return false;
}
@Override public void setUnloadAfter(boolean setUnloadAfter) {
if (parent != null) {
parent.setUnloadAfter(setUnloadAfter);
}
}
@Override @Nullable public CuboidRegion getRegenRegion() {
if (parent != null) {
return parent.getRegenRegion();
}
return null;
}
@Override public void setRegenRegion(@Nonnull CuboidRegion regenRegion) {
if (parent != null) {
parent.setRegenRegion(regenRegion);
}
}
}

View File

@ -26,326 +26,67 @@
package com.plotsquared.core.queue;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.util.task.RunnableVal2;
import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicBoolean;
public class GlobalBlockQueue {
private final int PARALLEL_THREADS;
private final ConcurrentLinkedDeque<LocalBlockQueue> activeQueues;
private final ConcurrentLinkedDeque<LocalBlockQueue> inactiveQueues;
private final ConcurrentLinkedDeque<Runnable> runnables;
private final AtomicBoolean running;
private final int targetTime;
private final ConcurrentLinkedDeque<QueueCoordinator> activeQueues;
private QueueProvider provider;
/**
* Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the
* server
*/
private long last;
private long secondLast;
private long lastSuccess;
private double lastPeriod = 0;
private final RunnableVal2<Long, LocalBlockQueue> SET_TASK =
new RunnableVal2<Long, LocalBlockQueue>() {
@Override public void run(Long free, LocalBlockQueue queue) {
do {
boolean more = queue.next();
if (!more) {
lastSuccess = last;
if (inactiveQueues.size() == 0 && activeQueues.size() == 0) {
runEmptyTasks();
}
return;
}
} while ((lastPeriod =
((GlobalBlockQueue.this.secondLast = System.currentTimeMillis())
- GlobalBlockQueue.this.last)) < free);
}
};
public GlobalBlockQueue(QueueProvider provider, int threads, int targetTime) {
public GlobalBlockQueue(@Nonnull QueueProvider provider) {
this.provider = provider;
this.activeQueues = new ConcurrentLinkedDeque<>();
this.inactiveQueues = new ConcurrentLinkedDeque<>();
this.runnables = new ConcurrentLinkedDeque<>();
this.running = new AtomicBoolean();
this.targetTime = targetTime;
this.PARALLEL_THREADS = threads;
}
public QueueProvider getProvider() {
return provider;
}
public void setProvider(QueueProvider provider) {
this.provider = provider;
}
public LocalBlockQueue getNewQueue(String world, boolean autoQueue) {
LocalBlockQueue queue = provider.getNewQueue(world);
/**
* Get a new {@link QueueCoordinator} for the given world.
*/
@Nonnull public QueueCoordinator getNewQueue(@Nonnull World world) {
QueueCoordinator queue = provider.getNewQueue(world);
// Auto-inject into the queue
PlotSquared.platform().getInjector().injectMembers(queue);
if (autoQueue) {
inactiveQueues.add(queue);
}
return queue;
}
public boolean stop() {
if (!running.get()) {
return false;
}
running.set(false);
return true;
public QueueProvider getProvider() {
return this.provider;
}
public boolean runTask() {
if (running.get()) {
return false;
}
running.set(true);
TaskManager.runTaskRepeat(new Runnable() {
@Override public void run() {
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
lastSuccess = System.currentTimeMillis();
lastPeriod = 0;
GlobalBlockQueue.this.runEmptyTasks();
return;
}
// Server laggy? Skip.
if (lastPeriod > targetTime) {
lastPeriod -= targetTime;
return;
}
SET_TASK.value1 = 50 + Math.min(
(50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last =
System.currentTimeMillis()),
GlobalBlockQueue.this.secondLast - System.currentTimeMillis());
SET_TASK.value2 = GlobalBlockQueue.this.getNextQueue();
if (SET_TASK.value2 == null) {
return;
}
if (!PlotSquared.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException(
"This shouldn't be possible for placement to occur off the main thread");
}
// Disable the async catcher as it can't discern async vs parallel
SET_TASK.value2.startSet(true);
try {
if (PARALLEL_THREADS <= 1) {
SET_TASK.run();
} else {
ArrayList<Thread> threads = new ArrayList<>();
for (int i = 0; i < PARALLEL_THREADS; i++) {
threads.add(new Thread(SET_TASK));
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
// Enable it again (note that we are still on the main thread)
SET_TASK.value2.endSet(true);
}
}
}, TaskTime.ticks(1L));
return true;
}
public QueueStage getStage(LocalBlockQueue queue) {
if (activeQueues.contains(queue)) {
return QueueStage.ACTIVE;
} else if (inactiveQueues.contains(queue)) {
return QueueStage.INACTIVE;
}
return QueueStage.NONE;
}
public boolean isStage(LocalBlockQueue queue, QueueStage stage) {
switch (stage) {
case ACTIVE:
return activeQueues.contains(queue);
case INACTIVE:
return inactiveQueues.contains(queue);
case NONE:
return !activeQueues.contains(queue) && !inactiveQueues.contains(queue);
}
return false;
public void setQueueProvider(@Nonnull QueueProvider provider) {
this.provider = provider;
}
/**
* TODO Documentation needed.
* Place an instance of {@link QueueCoordinator} into a list incase access is needed
* and then start it.
*
* @param queue todo
* @param queue {@link QueueCoordinator} instance to start.
* @return true if added to queue, false otherwise
*/
public boolean enqueue(LocalBlockQueue queue) {
public boolean enqueue(@Nonnull QueueCoordinator queue) {
boolean success = false;
success = inactiveQueues.remove(queue);
if (queue.size() > 0 && !activeQueues.contains(queue)) {
queue.optimize();
success = activeQueues.add(queue);
queue.start();
}
return success;
}
public void dequeue(LocalBlockQueue queue) {
inactiveQueues.remove(queue);
public void dequeue(@Nonnull QueueCoordinator queue) {
queue.cancel();
activeQueues.remove(queue);
}
public List<LocalBlockQueue> getAllQueues() {
ArrayList<LocalBlockQueue> list =
new ArrayList<>(activeQueues.size() + inactiveQueues.size());
list.addAll(inactiveQueues);
list.addAll(activeQueues);
return list;
}
public List<LocalBlockQueue> getActiveQueues() {
@Nonnull public List<QueueCoordinator> getActiveQueues() {
return new ArrayList<>(activeQueues);
}
public List<LocalBlockQueue> getInactiveQueues() {
return new ArrayList<>(inactiveQueues);
}
public void flush(LocalBlockQueue queue) {
SET_TASK.value1 = Long.MAX_VALUE;
SET_TASK.value2 = queue;
if (SET_TASK.value2 == null) {
return;
}
if (PlotSquared.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be flushed on the main thread!");
}
// Disable the async catcher as it can't discern async vs parallel
SET_TASK.value2.startSet(true);
try {
if (PARALLEL_THREADS <= 1) {
SET_TASK.run();
} else {
ArrayList<Thread> threads = new ArrayList<>();
for (int i = 0; i < PARALLEL_THREADS; i++) {
Thread thread = new Thread(SET_TASK);
thread.setName("PlotSquared Flush Task");
threads.add(thread);
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
// Enable it again (note that we are still on the main thread)
SET_TASK.value2.endSet(true);
dequeue(queue);
}
}
public LocalBlockQueue getNextQueue() {
long now = System.currentTimeMillis();
while (!activeQueues.isEmpty()) {
LocalBlockQueue queue = activeQueues.peek();
if (queue != null && queue.size() > 0) {
queue.setModified(now);
return queue;
} else {
activeQueues.poll();
}
}
int size = inactiveQueues.size();
if (size > 0) {
Iterator<LocalBlockQueue> iter = inactiveQueues.iterator();
try {
int total = 0;
LocalBlockQueue firstNonEmpty = null;
while (iter.hasNext()) {
LocalBlockQueue queue = iter.next();
long age = now - queue.getModified();
total += queue.size();
if (queue.size() == 0) {
if (age > 60000) {
iter.remove();
}
continue;
}
if (firstNonEmpty == null) {
firstNonEmpty = queue;
}
if (total > 64) {
firstNonEmpty.setModified(now);
return firstNonEmpty;
}
if (age > 1000) {
queue.setModified(now);
return queue;
}
}
} catch (ConcurrentModificationException e) {
e.printStackTrace();
}
}
return null;
}
public boolean isDone() {
return activeQueues.size() == 0 && inactiveQueues.size() == 0;
}
public boolean addEmptyTask(final Runnable whenDone) {
if (this.isDone()) {
// Run
this.runEmptyTasks();
if (whenDone != null) {
whenDone.run();
}
return true;
}
if (whenDone != null) {
this.runnables.add(whenDone);
}
return false;
}
private synchronized void runEmptyTasks() {
if (this.runnables.isEmpty()) {
return;
}
final ConcurrentLinkedDeque<Runnable> tmp = new ConcurrentLinkedDeque<>(this.runnables);
this.runnables.clear();
for (final Runnable runnable : tmp) {
runnable.run();
}
}
public enum QueueStage {
INACTIVE, ACTIVE, NONE
return activeQueues.size() == 0;
}
}

View File

@ -1,192 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.util.PatternUtil;
import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.StringMan;
import com.plotsquared.core.util.WorldUtil;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class LocalBlockQueue {
private boolean forceSync = false;
@Nullable private Object chunkObject;
@Inject private SchematicHandler schematicHandler;
@Inject private WorldUtil worldUtil;
@Inject private GlobalBlockQueue blockQueue;
/**
* Needed for compatibility with FAWE.
*
* @param world unused
*/
@Deprecated public LocalBlockQueue(String world) {
PlotSquared.platform().getInjector().injectMembers(this);
}
public ScopedLocalBlockQueue getForChunk(int x, int z) {
int bx = x << 4;
int bz = z << 4;
return new ScopedLocalBlockQueue(this, Location.at(getWorld(), bx, 0, bz),
Location.at(getWorld(), bx + 15, 255, bz + 255));
}
public abstract boolean next();
public abstract void startSet(boolean parallel);
public abstract void endSet(boolean parallel);
public abstract int size();
public abstract void optimize();
public abstract long getModified();
public abstract void setModified(long modified);
/**
* Sets the block at the coordinates provided to the given id.
*
* @param x the x coordinate from from 0 to 15 inclusive
* @param y the y coordinate from from 0 (inclusive) - maxHeight(exclusive)
* @param z the z coordinate from 0 to 15 inclusive
* @param id the id to set the block to
*/
public abstract boolean setBlock(final int x, final int y, final int z, final BlockState id);
public abstract boolean setBlock(final int x, final int y, final int z, final BaseBlock id);
public boolean setBlock(final int x, final int y, final int z, @Nonnull final Pattern pattern) {
return setBlock(x, y, z, PatternUtil.apply(pattern, x, y, z));
}
public boolean setTile(int x, int y, int z, CompoundTag tag) {
this.schematicHandler.restoreTile(this, tag, x, y, z);
return true;
}
public abstract BlockState getBlock(int x, int y, int z);
public abstract boolean setBiome(int x, int z, BiomeType biome);
public abstract boolean setBiome();
public abstract String getWorld();
public abstract void flush();
public final void setModified() {
setModified(System.currentTimeMillis());
}
public abstract void refreshChunk(int x, int z);
public abstract void fixChunkLighting(int x, int z);
public abstract void regenChunk(int x, int z);
public final void regenChunkSafe(int x, int z) {
regenChunk(x, z);
fixChunkLighting(x, z);
BlockVector2 loc = BlockVector2.at(x, z);
for (final PlotPlayer<?> pp : PlotSquared.platform().getPlayerManager().getPlayers()) {
Location pLoc = pp.getLocation();
if (!StringMan.isEqual(getWorld(), pLoc.getWorldName()) || !pLoc.getChunkLocation()
.equals(loc)) {
continue;
}
pp.teleport(pLoc.withY(this.worldUtil.getHighestBlockSynchronous(getWorld(), pLoc.getX(), pLoc.getZ())));
}
}
public boolean enqueue() {
return blockQueue.enqueue(this);
}
public void setCuboid(Location pos1, Location pos2, BlockState block) {
int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY()));
int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ());
int zMax = Math.max(pos1.getZ(), pos2.getZ());
for (int y = yMin; y <= yMax; y++) {
for (int x = xMin; x <= xMax; x++) {
for (int z = zMin; z <= zMax; z++) {
setBlock(x, y, z, block);
}
}
}
}
public void setCuboid(Location pos1, Location pos2, Pattern blocks) {
int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY()));
int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ());
int zMax = Math.max(pos1.getZ(), pos2.getZ());
for (int y = yMin; y <= yMax; y++) {
for (int x = xMin; x <= xMax; x++) {
for (int z = zMin; z <= zMax; z++) {
setBlock(x, y, z, blocks);
}
}
}
}
public boolean isForceSync() {
return this.forceSync;
}
@Nullable public Object getChunkObject() {
return this.chunkObject;
}
public void setForceSync(boolean forceSync) {
this.forceSync = forceSync;
}
public void setChunkObject(@Nullable Object chunkObject) {
this.chunkObject = chunkObject;
}
}

View File

@ -0,0 +1,117 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.plotsquared.core.util.ChunkUtil;
import com.plotsquared.core.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import javax.annotation.Nonnull;
import java.util.HashMap;
public class LocalChunk {
private final QueueCoordinator parent;
private final int x;
private final int z;
private final BaseBlock[][] baseblocks;
private final BiomeType[][] biomes;
private final HashMap<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final HashMap<Location, BaseEntity> entities = new HashMap<>();
public LocalChunk(@Nonnull QueueCoordinator parent, int x, int z) {
this.parent = parent;
this.x = x;
this.z = z;
baseblocks = new BaseBlock[16][];
biomes = new BiomeType[16][];
}
@Nonnull public QueueCoordinator getParent() {
return this.parent;
}
public int getX() {
return this.x;
}
public int getZ() {
return this.z;
}
@Nonnull public BaseBlock[][] getBaseblocks() {
return this.baseblocks;
}
@Nonnull public BiomeType[][] getBiomes() {
return this.biomes;
}
@Nonnull public HashMap<BlockVector3, CompoundTag> getTiles() {
return this.tiles;
}
public void setBiome(final int x, final int y, final int z, @Nonnull final BiomeType biomeType) {
final int i = y >> 4;
final int j = ChunkUtil.getJ(x, y, z);
BiomeType[] array = this.biomes[i];
if (array == null) {
array = this.biomes[i] = new BiomeType[4096];
}
array[j] = biomeType;
}
@Override public int hashCode() {
return MathMan.pair((short) x, (short) z);
}
public void setBlock(final int x, final int y, final int z, @Nonnull final BaseBlock baseBlock) {
final int i = y >> 4;
final int j = ChunkUtil.getJ(x, y, z);
BaseBlock[] array = baseblocks[i];
if (array == null) {
array = (baseblocks[i] = new BaseBlock[4096]);
}
array[j] = baseBlock;
}
public void setTile(final int x, final int y, final int z, @Nonnull final CompoundTag tag) {
tiles.put(BlockVector3.at(x, y, z), tag);
}
public void setEntity(@Nonnull Location location, @Nonnull BaseEntity entity) {
this.entities.put(location, entity);
}
@Nonnull public HashMap<Location, BaseEntity> getEntities() {
return this.entities;
}
}

View File

@ -25,40 +25,33 @@
*/
package com.plotsquared.core.queue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class LocationOffsetDelegateLocalBlockQueue extends DelegateLocalBlockQueue {
private static final Logger logger = LoggerFactory.getLogger("P2/" + LocationOffsetDelegateLocalBlockQueue.class.getSimpleName());
/**
* Offsets input coordinates and delegates to a parent queue
*/
public class LocationOffsetDelegateQueueCoordinator extends DelegateQueueCoordinator {
private final boolean[][] canPlace;
private final int blockX;
private final int blockZ;
public LocationOffsetDelegateLocalBlockQueue(final boolean[][] canPlace, final int blockX,
final int blockZ, @Nullable LocalBlockQueue parent) {
public LocationOffsetDelegateQueueCoordinator(final boolean[][] canPlace, final int blockX, final int blockZ, @Nullable QueueCoordinator parent) {
super(parent);
this.canPlace = canPlace;
this.blockX = blockX;
this.blockZ = blockZ;
}
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
if (canPlace[x - blockX][z - blockZ]) {
return super.setBlock(x, y, z, id);
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
@Override public boolean setBlock(int x, int y, int z, @Nonnull BlockState id) {
try {
if (canPlace[x - blockX][z - blockZ]) {
return super.setBlock(x, y, z, id);
@ -69,13 +62,49 @@ public class LocationOffsetDelegateLocalBlockQueue extends DelegateLocalBlockQue
return false;
}
@Override public boolean setBlock(int x, int y, int z, Pattern pattern) {
@Override public boolean setBlock(int x, int y, int z, @Nonnull BaseBlock id) {
try {
if (canPlace[x - blockX][z - blockZ]) {
return super.setBlock(x, y, z, id);
}
} catch (final Exception e) {
throw e;
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull 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) {
return super.setBiome(x, y, biome);
@Override public boolean setBiome(int x, int z, @Nonnull BiomeType biome) {
boolean result = true;
for (int y = 0; y < 256; y++) {
result &= this.setBiome(x, z, biome);
}
return result;
}
@Override public boolean setBiome(int x, int y, int z, @Nonnull BiomeType biome) {
try {
if (canPlace[x - blockX][z - blockZ]) {
return super.setBiome(x, y, z, biome);
}
} catch (final Exception e) {
throw e;
}
return false;
}
@Override public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) {
try {
if (canPlace[x - blockX][z - blockZ]) {
return super.setTile(x, y, z, tag);
}
} catch (final Exception e) {
throw e;
}
return false;
}
}

View File

@ -0,0 +1,336 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.queue;
import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.util.PatternUtil;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
public abstract class QueueCoordinator {
private boolean forceSync = false;
@Nullable private Object chunkObject;
@Inject private GlobalBlockQueue blockQueue;
/**
* Default constructor requires world to indicate any extents given to {@link QueueCoordinator} also need this constructor.
*/
public QueueCoordinator(@Nullable World world) {
PlotSquared.platform().getInjector().injectMembers(this);
}
/**
* Get a {@link ScopedQueueCoordinator} limited to the chunk at the specific chunk Coordinates
*/
public ScopedQueueCoordinator getForChunk(int x, int z) {
int bx = x << 4;
int bz = z << 4;
return new ScopedQueueCoordinator(this, Location.at(getWorld().getName(), bx, 0, bz),
Location.at(getWorld().getName(), bx + 15, 255, bz + 255));
}
/**
* Get the size of the queue in chunks
*/
public abstract int size();
/**
* Set when the queue was last modified
*/
public abstract void setModified(long modified);
/**
* Returns true if the queue should be forced to be synchronous when enqueued.
*/
public boolean isForceSync() {
return forceSync;
}
/**
* Set whether the queue should be forced to be synchronous
*/
public void setForceSync(boolean forceSync) {
this.forceSync = forceSync;
}
/**
* Get the Chunk Object set to the queue
*/
@Nullable public Object getChunkObject() {
return chunkObject;
}
/**
* Set a chunk object (e.g. the Bukkit Chunk object) to the queue
*/
public void setChunkObject(@Nonnull Object chunkObject) {
this.chunkObject = chunkObject;
}
/**
* Sets the block at the coordinates provided to the given id.
*
* @param x the x coordinate from from 0 to 15 inclusive
* @param y the y coordinate from from 0 (inclusive) - maxHeight(exclusive)
* @param z the z coordinate from 0 to 15 inclusive
* @param id the BlockState to set the block to
*/
public abstract boolean setBlock(final int x, final int y, final int z, @Nonnull final BlockState id);
/**
* Sets the block at the coordinates provided to the given id.
*
* @param x the x coordinate from from 0 to 15 inclusive
* @param y the y coordinate from from 0 (inclusive) - maxHeight(exclusive)
* @param z the z coordinate from 0 to 15 inclusive
* @param id the BaseBlock to set the block to
*/
public abstract boolean setBlock(final int x, final int y, final int z, @Nonnull final BaseBlock id);
/**
* Sets the block at the coordinates provided to the given id.
*
* @param x the x coordinate from from 0 to 15 inclusive
* @param y the y coordinate from from 0 (inclusive) - maxHeight(exclusive)
* @param z the z coordinate from 0 to 15 inclusive
* @param pattern the pattern to set the block to
*/
public boolean setBlock(final int x, final int y, final int z, @Nonnull final Pattern pattern) {
return setBlock(x, y, z, PatternUtil.apply(pattern, x, y, z));
}
/**
* Sets a tile entity at the coordinates provided to the given CompoundTag
*
* @param x the x coordinate from from 0 to 15 inclusive
* @param y the y coordinate from from 0 (inclusive) - maxHeight(exclusive)
* @param z the z coordinate from 0 to 15 inclusive
* @param tag the CompoundTag to set the tile to
*/
public abstract boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag);
/**
* Whether the queue has any tiles being set
*/
public abstract boolean isSettingTiles();
/**
* Get a block at the given coordinates.
*/
@Nullable public abstract BlockState getBlock(int x, int y, int z);
/**
* Set a biome in XZ. This will likely set to the whole column
*/
@Deprecated public abstract boolean setBiome(int x, int z, @Nonnull BiomeType biome);
/**
* Set a biome in XYZ
*/
public abstract boolean setBiome(int x, int y, int z, @Nonnull BiomeType biome);
/**
* Whether the queue has any biomes to be set
*/
public abstract boolean isSettingBiomes();
/**
* Add entities to be created
*/
public void addEntities(@Nonnull List<? extends Entity> entities) {
for (Entity e : entities) {
this.setEntity(e);
}
}
/**
* Add an entity to be created
*/
public abstract boolean setEntity(@Nonnull Entity entity);
/**
* Get the list of chunks that are added manually. This usually indicated the queue is "read only".
*/
@Nonnull public abstract List<BlockVector2> getReadChunks();
/**
* Add a set of {@link BlockVector2} Chunk coordinates to the Read Chunks list
*/
public abstract void addReadChunks(@Nonnull Set<BlockVector2> readChunks);
/**
* Add a {@link BlockVector2} Chunk coordinate to the Read Chunks list
*/
public abstract void addReadChunk(@Nonnull BlockVector2 chunk);
/**
* Whether chunks should be unloaded after being accessed
*/
public abstract boolean isUnloadAfter();
/**
* Set whether chunks should be unloaded after being accessed
*/
public abstract void setUnloadAfter(boolean unloadAfter);
/**
* Get the {@link CuboidRegion} designated for direct regeneration
*/
@Nullable public abstract CuboidRegion getRegenRegion();
/**
* Set the {@link CuboidRegion} designated for direct regeneration
*/
public abstract void setRegenRegion(@Nonnull CuboidRegion regenRegion);
/**
* Set a specific chunk at the chunk coordinates XZ to be regenerated.
*/
public abstract void regenChunk(int x, int z);
/**
* Get the world the queue is writing to
*/
@Nullable public abstract World getWorld();
/**
* Set the queue as having been modified now
*/
public final void setModified() {
setModified(System.currentTimeMillis());
}
/**
* Enqueue the queue with the {@link GlobalBlockQueue}
*/
public boolean enqueue() {
return blockQueue.enqueue(this);
}
/**
* Start the queue
*/
public abstract void start();
/**
* Cancel the queue. Not yet implemented.
*/
public abstract void cancel();
/**
* Get the task to be run when all chunks have been accessed
*/
public abstract Runnable getCompleteTask();
/**
* Set the task to be run when all chunks have been accessed
*/
public abstract void setCompleteTask(@Nullable Runnable whenDone);
/**
* Return the chunk consumer set to the queue or null if one is not set
*/
@Nullable public abstract Consumer<BlockVector2> getChunkConsumer();
/**
* Set the Consumer that will
*/
public abstract void setChunkConsumer(@Nonnull Consumer<BlockVector2> consumer);
/**
* Fill a cuboid between two positions with a BlockState
*/
public void setCuboid(@Nonnull Location pos1, @Nonnull Location pos2, @Nonnull BlockState block) {
int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY()));
int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ());
int zMax = Math.max(pos1.getZ(), pos2.getZ());
for (int y = yMin; y <= yMax; y++) {
for (int x = xMin; x <= xMax; x++) {
for (int z = zMin; z <= zMax; z++) {
setBlock(x, y, z, block);
}
}
}
}
/**
* Fill a cuboid between two positions with a Pattern
*/
public void setCuboid(@Nonnull Location pos1, @Nonnull Location pos2, @Nonnull Pattern blocks) {
int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY()));
int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ());
int zMax = Math.max(pos1.getZ(), pos2.getZ());
for (int y = yMin; y <= yMax; y++) {
for (int x = xMin; x <= xMax; x++) {
for (int z = zMin; z <= zMax; z++) {
setBlock(x, y, z, blocks);
}
}
}
}
/**
* Fill a cuboid between two positions with a BiomeType
*/
public void setBiomeCuboid(@Nonnull Location pos1, @Nonnull Location pos2, @Nonnull BiomeType biome) {
int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY()));
int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ());
int zMax = Math.max(pos1.getZ(), pos2.getZ());
for (int y = yMin; y <= yMax; y++) {
for (int x = xMin; x <= xMax; x++) {
for (int z = zMin; z <= zMax; z++) {
setBiome(x, y, z, biome);
}
}
}
}
}

View File

@ -25,25 +25,29 @@
*/
package com.plotsquared.core.queue;
import com.plotsquared.core.PlotSquared;
import com.sk89q.worldedit.world.World;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
public abstract class QueueProvider {
public static QueueProvider of(final Class<? extends LocalBlockQueue> primary,
final Class<? extends LocalBlockQueue> fallback) {
private static final Logger logger = LoggerFactory.getLogger("P2/" + PlotSquared.class.getSimpleName());
public static QueueProvider of(@Nonnull final Class<? extends QueueCoordinator> primary) {
return new QueueProvider() {
private boolean failed = false;
@Override public LocalBlockQueue getNewQueue(String world) {
if (!failed) {
try {
return (LocalBlockQueue) primary.getConstructors()[0].newInstance(world);
} catch (Throwable e) {
e.printStackTrace();
failed = true;
}
}
@Override public QueueCoordinator getNewQueue(@Nonnull World world) {
try {
return (LocalBlockQueue) fallback.getConstructors()[0].newInstance(world);
return (QueueCoordinator) primary.getConstructors()[0].newInstance(world);
} catch (Throwable e) {
logger.error("Error creating Queue: {} - Does it have the correct constructor(s)?", primary.getName());
if (!primary.getName().contains("com.plotsquared")) {
logger.error("It looks like {} is a custom queue. Please look for a plugin in its classpath and report to them.",
primary.getSimpleName());
}
e.printStackTrace();
}
return null;
@ -51,5 +55,8 @@ public abstract class QueueProvider {
};
}
public abstract LocalBlockQueue getNewQueue(String world);
/**
* Get a queue for the given world
*/
public abstract QueueCoordinator getNewQueue(@Nonnull World world);
}

View File

@ -26,12 +26,19 @@
package com.plotsquared.core.queue;
import com.plotsquared.core.location.Location;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue {
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Queue that only sets blocks with a designated area
*/
public class ScopedQueueCoordinator extends DelegateQueueCoordinator {
private final int minX;
private final int minY;
private final int minZ;
@ -44,7 +51,7 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue {
private final int dy;
private final int dz;
public ScopedLocalBlockQueue(LocalBlockQueue parent, Location min, Location max) {
public ScopedQueueCoordinator(@Nullable QueueCoordinator parent, @Nonnull Location min, @Nonnull Location max) {
super(parent);
this.minX = min.getX();
this.minY = min.getY();
@ -59,39 +66,46 @@ public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue {
this.dz = maxZ - minZ;
}
@Override public boolean setBiome(int x, int z, BiomeType biome) {
@Override public boolean setBiome(int x, int z, @Nonnull BiomeType biome) {
return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBiome(x + minX, z + minZ, biome);
}
@Override public boolean setBiome(int x, int y, int z, @Nonnull BiomeType biome) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setBiome(x + minX, y + minY, z + minZ, biome);
}
public void fillBiome(BiomeType biome) {
for (int x = 0; x <= dx; x++) {
for (int z = 0; z < dz; z++) {
setBiome(x, z, biome);
for (int y = 0; y <= dy; y++) {
for (int x = 0; x <= dx; x++) {
for (int z = 0; z < dz; z++) {
setBiome(x, y, z, biome);
}
}
}
}
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super
.setBlock(x + minX, y + minY, z + minZ, id);
@Override public boolean setBlock(int x, int y, int z, @Nonnull BaseBlock id) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setBlock(x + minX, y + minY, z + minZ, id);
}
@Override public boolean setBlock(int x, int y, int z, BlockState id) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super
.setBlock(x + minX, y + minY, z + minZ, id);
@Override public boolean setBlock(int x, int y, int z, @Nonnull BlockState id) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.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);
@Override public boolean setBlock(int x, int y, int z, @Nonnull 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() {
return Location.at(this.getWorld(), this.minX, this.minY, this.minZ);
@Override public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setTile(x + minX, y + minY, z + minZ, tag);
}
public Location getMax() {
return Location.at(this.getWorld(), this.maxX, this.maxY, this.maxZ);
@Nonnull public Location getMin() {
return Location.at(this.getWorld().getName(), this.minX, this.minY, this.minZ);
}
@Nonnull public Location getMax() {
return Location.at(this.getWorld().getName(), this.maxX, this.maxY, this.maxZ);
}
}

View File

@ -27,36 +27,30 @@ package com.plotsquared.core.util;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.queue.ScopedLocalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
public abstract class ChunkManager {
private static final Map<BlockVector2, RunnableVal<ScopedLocalBlockQueue>> forceChunks =
new ConcurrentHashMap<>();
private static final Map<BlockVector2, RunnableVal<ScopedLocalBlockQueue>> addChunks =
new ConcurrentHashMap<>();
private static final Map<BlockVector2, RunnableVal<ScopedQueueCoordinator>> forceChunks = new ConcurrentHashMap<>();
private static final Map<BlockVector2, RunnableVal<ScopedQueueCoordinator>> addChunks = new ConcurrentHashMap<>();
public static void setChunkInPlotArea(RunnableVal<ScopedLocalBlockQueue> force,
RunnableVal<ScopedLocalBlockQueue> add, String world, BlockVector2 loc) {
LocalBlockQueue queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world, false);
public static void setChunkInPlotArea(RunnableVal<ScopedQueueCoordinator> force,
RunnableVal<ScopedQueueCoordinator> add,
String world,
BlockVector2 loc) {
QueueCoordinator queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(world));
if (PlotSquared.get().getPlotAreaManager().isAugmented(world) && PlotSquared.get().isNonStandardGeneration(world, loc)) {
int blockX = loc.getX() << 4;
int blockZ = loc.getZ() << 4;
ScopedLocalBlockQueue scoped =
new ScopedLocalBlockQueue(queue, Location.at(world, blockX, 0, blockZ),
Location.at(world, blockX + 15, 255, blockZ + 15));
ScopedQueueCoordinator scoped =
new ScopedQueueCoordinator(queue, Location.at(world, blockX, 0, blockZ), Location.at(world, blockX + 15, 255, blockZ + 15));
if (force != null) {
force.run(scoped);
} else {
@ -65,7 +59,7 @@ public abstract class ChunkManager {
add.run(scoped);
}
}
queue.flush();
queue.enqueue();
} else {
if (force != null) {
forceChunks.put(loc, force);
@ -77,8 +71,8 @@ public abstract class ChunkManager {
}
}
public static boolean preProcessChunk(BlockVector2 loc, ScopedLocalBlockQueue queue) {
final RunnableVal<ScopedLocalBlockQueue> forceChunk = forceChunks.get(loc);
public static boolean preProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) {
final RunnableVal<ScopedQueueCoordinator> forceChunk = forceChunks.get(loc);
if (forceChunk != null) {
forceChunk.run(queue);
forceChunks.remove(loc);
@ -87,8 +81,8 @@ public abstract class ChunkManager {
return false;
}
public static boolean postProcessChunk(BlockVector2 loc, ScopedLocalBlockQueue queue) {
final RunnableVal<ScopedLocalBlockQueue> addChunk = forceChunks.get(loc);
public static boolean postProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) {
final RunnableVal<ScopedQueueCoordinator> addChunk = forceChunks.get(loc);
if (addChunk != null) {
addChunk.run(queue);
addChunks.remove(loc);
@ -97,107 +91,6 @@ public abstract class ChunkManager {
return false;
}
public static void chunkTask(final Plot plot, final RunnableVal<int[]> task,
final Runnable whenDone, final int allocate) {
final ArrayList<CuboidRegion> regions = new ArrayList<>(plot.getRegions());
Runnable smallTask = new Runnable() {
@Override public void run() {
if (regions.isEmpty()) {
TaskManager.runTask(whenDone);
return;
}
CuboidRegion value = regions.remove(0);
Location pos1 = Location.at(plot.getWorldName(), value.getMinimumPoint().getX(), 0,
value.getMinimumPoint().getZ());
Location pos2 = Location.at(plot.getWorldName(), value.getMaximumPoint().getX(), 0,
value.getMaximumPoint().getZ());
chunkTask(pos1, pos2, task, this, allocate);
}
};
smallTask.run();
}
/**
* The int[] will be in the form: [chunkX, chunkZ, pos1x, pos1z, pos2x, pos2z, isEdge] and will represent the bottom and top parts of the chunk
*
* @param pos1
* @param pos2
* @param task
* @param whenDone
*/
public static void chunkTask(Location pos1, Location pos2, final RunnableVal<int[]> task,
final Runnable whenDone, final int allocate) {
final int p1x = pos1.getX();
final int p1z = pos1.getZ();
final int p2x = pos2.getX();
final int p2z = pos2.getZ();
final int bcx = p1x >> 4;
final int bcz = p1z >> 4;
final int tcx = p2x >> 4;
final int tcz = p2z >> 4;
final ArrayList<BlockVector2> chunks = new ArrayList<>();
for (int x = bcx; x <= tcx; x++) {
for (int z = bcz; z <= tcz; z++) {
chunks.add(BlockVector2.at(x, z));
}
}
TaskManager.runTask(new Runnable() {
@Override public void run() {
long start = System.currentTimeMillis();
while (!chunks.isEmpty() && ((System.currentTimeMillis() - start) < allocate)) {
BlockVector2 chunk = chunks.remove(0);
task.value = new int[7];
task.value[0] = chunk.getX();
task.value[1] = chunk.getZ();
task.value[2] = task.value[0] << 4;
task.value[3] = task.value[1] << 4;
task.value[4] = task.value[2] + 15;
task.value[5] = task.value[3] + 15;
if (task.value[0] == bcx) {
task.value[2] = p1x;
task.value[6] = 1;
}
if (task.value[0] == tcx) {
task.value[4] = p2x;
task.value[6] = 1;
}
if (task.value[1] == bcz) {
task.value[3] = p1z;
task.value[6] = 1;
}
if (task.value[1] == tcz) {
task.value[5] = p2z;
task.value[6] = 1;
}
task.run();
}
if (!chunks.isEmpty()) {
TaskManager.runTaskLater(this, TaskTime.ticks(1L));
} else {
TaskManager.runTask(whenDone);
}
}
});
}
public abstract CompletableFuture loadChunk(String world, BlockVector2 loc, boolean force);
public abstract void unloadChunk(String world, BlockVector2 loc, boolean save);
public Plot hasPlot(String world, BlockVector2 chunk) {
int x1 = chunk.getX() << 4;
int z1 = chunk.getZ() << 4;
int x2 = x1 + 15;
int z2 = z1 + 15;
Location bot = Location.at(world, x1, 0, z1);
Plot plot = bot.getOwnedPlotAbs();
if (plot != null) {
return plot;
}
Location top = Location.at(world, x2, 0, z2);
plot = top.getOwnedPlotAbs();
return plot;
}
@Deprecated public abstract CompletableFuture loadChunk(String world, BlockVector2 loc, boolean force);
}

View File

@ -25,6 +25,10 @@
*/
package com.plotsquared.core.util;
import com.plotsquared.core.location.Location;
import com.sk89q.worldedit.math.BlockVector2;
import javax.annotation.Nonnull;
/**
* This cache is used for world generation and just saves a bit of calculation time when checking if something is in the plot area.
*/
@ -34,10 +38,10 @@ public class ChunkUtil {
* Cache of mapping x,y,z coordinates to the chunk array<br>
* - Used for efficient world generation<br>
*/
private static short[] x_loc;
private static short[][] y_loc;
private static short[] z_loc;
private static short[][][] CACHE_J = null;
private static final short[] x_loc;
private static final short[][] y_loc;
private static final short[] z_loc;
private static final short[][][] CACHE_J;
static {
x_loc = new short[4096];
@ -78,8 +82,7 @@ public class ChunkUtil {
* @param z Relative z coordinate
* @return J value for xyz position in Array[4096].
*/
public static int getJ(int x, int y,
int z) {
public static int getJ(int x, int y, int z) {
return CACHE_J[y][x][z];
}
@ -113,4 +116,22 @@ public class ChunkUtil {
public static int getZ(int j) {
return z_loc[j];
}
/**
* Returns true if the region pos1-pos2 contains the chunk
*
* @param pos1 Region minimum point
* @param pos2 Region maximum point
* @param chunk BlockVector2 of chunk coordinates
* @return true if the region pos1-pos2 contains the chunk
*/
public static boolean isWholeChunk(@Nonnull Location pos1, @Nonnull Location pos2, @Nonnull BlockVector2 chunk) {
int x1 = pos1.getX();
int z1 = pos1.getZ();
int x2 = pos2.getX();
int z2 = pos2.getZ();
int cx = chunk.getX() << 4;
int cz = chunk.getZ() << 4;
return cx > x1 && cz > z1 && cx < x2 && cz < z2;
}
}

View File

@ -42,7 +42,7 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
/**
* Entity related general utility methods
*/
public final class EntityUtil {
public class EntityUtil {
private EntityUtil() {
throw new UnsupportedOperationException(

View File

@ -106,6 +106,9 @@ public class EventDispatcher {
eventBus.unregister(listener);
}
}
public void callGenericEvent(@Nonnull final Object event) {
eventBus.post(event);
}
public void callEvent(@Nonnull final PlotEvent event) {
eventBus.post(event);

View File

@ -107,7 +107,7 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
/**
* Get a list of names given a list of UUIDs.
* - Uses the format {@link Captions#PLOT_USER_LIST} for the returned string
* - Uses the format {@link TranslatableCaption#of(String)} of "info.plot_user_list" for the returned string
*
* @param uuids UUIDs
* @return Name list

View File

@ -25,26 +25,31 @@
*/
package com.plotsquared.core.util;
import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.queue.BasicQueueCoordinator;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public abstract class RegionManager {
@ -52,6 +57,13 @@ public abstract class RegionManager {
private static final Logger logger = LoggerFactory.getLogger("P2/" + RegionManager.class.getSimpleName());
public static RegionManager manager = null;
private final WorldUtil worldUtil;
private final GlobalBlockQueue blockQueue;
@Inject public RegionManager(@Nonnull WorldUtil worldUtil, @Nonnull GlobalBlockQueue blockQueue) {
this.worldUtil = worldUtil;
this.blockQueue = blockQueue;
}
public static BlockVector2 getRegion(Location location) {
int x = location.getX() >> 9;
@ -59,52 +71,6 @@ public abstract class RegionManager {
return BlockVector2.at(x, z);
}
private final ChunkManager chunkManager;
public RegionManager(@Nonnull final ChunkManager chunkManager) {
this.chunkManager = chunkManager;
}
public void largeRegionTask(final String world, final CuboidRegion region,
final RunnableVal<BlockVector2> task, final Runnable whenDone) {
TaskManager.runTaskAsync(() -> {
HashSet<BlockVector2> chunks = new HashSet<>();
Set<BlockVector2> mcrs = this.getChunkChunks(world);
for (BlockVector2 mcr : mcrs) {
int bx = mcr.getX() << 9;
int bz = mcr.getZ() << 9;
int tx = bx + 511;
int tz = bz + 511;
if (bx <= region.getMaximumPoint().getX() && tx >= region.getMinimumPoint().getX()
&& bz <= region.getMaximumPoint().getZ() && tz >= region.getMinimumPoint()
.getZ()) {
for (int x = bx >> 4; x <= (tx >> 4); x++) {
int cbx = x << 4;
int ctx = cbx + 15;
if (cbx <= region.getMaximumPoint().getX() && ctx >= region
.getMinimumPoint().getX()) {
for (int z = bz >> 4; z <= (tz >> 4); z++) {
int cbz = z << 4;
int ctz = cbz + 15;
if (cbz <= region.getMaximumPoint().getZ() && ctz >= region
.getMinimumPoint().getZ()) {
chunks.add(BlockVector2.at(x, z));
}
}
}
}
}
}
TaskManager.getPlatformImplementation().objectTask(chunks, new RunnableVal<BlockVector2>() {
@Override public void run(BlockVector2 value) {
chunkManager.loadChunk(world, value, false)
.thenRun(() -> task.run(value));
}
}).thenAccept(ignore ->
TaskManager.getPlatformImplementation().taskLater(whenDone, TaskTime.ticks(1L)));
});
}
/**
* 0 = Entity
* 1 = Animal
@ -112,48 +78,13 @@ public abstract class RegionManager {
* 3 = Mob
* 4 = Boat
* 5 = Misc
*
* @param plot
* @return
*/
public abstract int[] countEntities(Plot plot);
public Set<BlockVector2> getChunkChunks(String world) {
File folder =
new File(PlotSquared.platform().getWorldContainer(), world + File.separator + "region");
File[] regionFiles = folder.listFiles();
if (regionFiles == null) {
throw new RuntimeException(
"Could not find worlds folder: " + folder + " ? (no read access?)");
}
HashSet<BlockVector2> chunks = new HashSet<>();
for (File file : regionFiles) {
String name = file.getName();
if (name.endsWith("mca")) {
String[] split = name.split("\\.");
try {
int x = Integer.parseInt(split[1]);
int z = Integer.parseInt(split[2]);
BlockVector2 loc = BlockVector2.at(x, z);
chunks.add(loc);
} catch (NumberFormatException ignored) {
}
}
}
return chunks;
}
public void deleteRegionFiles(String world, Collection<BlockVector2> chunks) {
deleteRegionFiles(world, chunks, null);
}
public void deleteRegionFiles(final String world, final Collection<BlockVector2> chunks,
final Runnable whenDone) {
public void deleteRegionFiles(final String world, final Collection<BlockVector2> chunks, final Runnable whenDone) {
TaskManager.runTaskAsync(() -> {
for (BlockVector2 loc : chunks) {
String directory =
world + File.separator + "region" + File.separator + "r." + loc.getX() + "."
+ loc.getZ() + ".mca";
String directory = world + File.separator + "region" + File.separator + "r." + loc.getX() + "." + loc.getZ() + ".mca";
File file = new File(PlotSquared.platform().getWorldContainer(), directory);
logger.info("[P2] - Deleting file: {} (max 1024 chunks)", file.getName());
if (file.exists()) {
@ -164,17 +95,30 @@ public abstract class RegionManager {
});
}
public boolean setCuboids(final PlotArea area, final Set<CuboidRegion> regions,
final Pattern blocks, int minY, int maxY) {
LocalBlockQueue queue = area.getQueue(false);
/**
* Set a number of cuboids to a certain block between two y values.
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
* @return true if not enqueued, otherwise whether the created queue enqueued.
*/
public boolean setCuboids(final PlotArea area,
final Set<CuboidRegion> regions,
final Pattern blocks,
int minY,
int maxY,
@Nullable QueueCoordinator queue) {
boolean enqueue = false;
if (queue == null) {
queue = area.getQueue();
enqueue = true;
}
for (CuboidRegion region : regions) {
Location pos1 = Location.at(area.getWorldName(), region.getMinimumPoint().getX(), minY,
region.getMinimumPoint().getZ());
Location pos2 = Location.at(area.getWorldName(), region.getMaximumPoint().getX(), maxY,
region.getMaximumPoint().getZ());
Location pos1 = Location.at(area.getWorldName(), region.getMinimumPoint().getX(), minY, region.getMinimumPoint().getZ());
Location pos2 = Location.at(area.getWorldName(), region.getMaximumPoint().getX(), maxY, region.getMaximumPoint().getZ());
queue.setCuboid(pos1, pos2, blocks);
}
return queue.enqueue();
return !enqueue || queue.enqueue();
}
/**
@ -196,27 +140,113 @@ public abstract class RegionManager {
/**
* Copy a region to a new location (in the same world)
*/
public abstract boolean copyRegion(Location pos1, Location pos2, Location newPos,
Runnable whenDone);
public boolean copyRegion(final Location pos1, final Location pos2, final Location newPos, final Runnable whenDone) {
final int relX = newPos.getX() - pos1.getX();
final int relZ = newPos.getZ() - pos1.getZ();
final com.sk89q.worldedit.world.World oldWorld = worldUtil.getWeWorld(pos1.getWorldName());
final com.sk89q.worldedit.world.World newWorld = worldUtil.getWeWorld(newPos.getWorldName());
final QueueCoordinator copyFrom = blockQueue.getNewQueue(oldWorld);
final BasicQueueCoordinator copyTo = (BasicQueueCoordinator) blockQueue.getNewQueue(newWorld);
copyFromTo(pos1, pos2, relX, relZ, oldWorld, copyFrom, copyTo, false);
copyFrom.setCompleteTask(copyTo::enqueue);
copyFrom
.addReadChunks(new CuboidRegion(BlockVector3.at(pos1.getX(), 0, pos1.getZ()), BlockVector3.at(pos2.getX(), 0, pos2.getZ())).getChunks());
copyTo.setCompleteTask(whenDone);
copyFrom.enqueue();
return true;
}
/**
* Assumptions:<br>
* - pos1 and pos2 are in the same plot<br>
* It can be harmful to the world if parameters outside this scope are provided
*
* @param pos1
* @param pos2
* @param whenDone
* @return
*/
public abstract boolean regenerateRegion(Location pos1, Location pos2, boolean ignoreAugment,
Runnable whenDone);
public abstract boolean regenerateRegion(Location pos1, Location pos2, boolean ignoreAugment, Runnable whenDone);
public abstract void clearAllEntities(Location pos1, Location pos2);
public abstract void swap(Location bot1, Location top1, Location bot2, Location top2,
Runnable whenDone);
public void swap(Location pos1, Location pos2, Location swapPos, final Runnable whenDone) {
int relX = swapPos.getX() - pos1.getX();
int relZ = swapPos.getZ() - pos1.getZ();
public abstract void setBiome(CuboidRegion region, int extendBiome, BiomeType biome,
String world, Runnable whenDone);
World world1 = worldUtil.getWeWorld(pos1.getWorldName());
World world2 = worldUtil.getWeWorld(swapPos.getWorldName());
QueueCoordinator fromQueue1 = blockQueue.getNewQueue(world1);
QueueCoordinator fromQueue2 = blockQueue.getNewQueue(world2);
fromQueue1.setUnloadAfter(false);
fromQueue2.setUnloadAfter(false);
fromQueue1.addReadChunks(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks());
fromQueue2.addReadChunks(new CuboidRegion(swapPos.getBlockVector3(),
BlockVector3.at(swapPos.getX() + pos2.getX() - pos1.getX(), 0, swapPos.getZ() + pos2.getZ() - pos1.getZ())).getChunks());
QueueCoordinator toQueue1 = blockQueue.getNewQueue(world1);
QueueCoordinator toQueue2 = blockQueue.getNewQueue(world2);
copyFromTo(pos1, pos2, relX, relZ, world1, fromQueue1, toQueue2, true);
copyFromTo(pos1, pos2, relX, relZ, world1, fromQueue2, toQueue1, true);
fromQueue1.setCompleteTask(fromQueue2::enqueue);
fromQueue2.setCompleteTask(toQueue1::enqueue);
toQueue1.setCompleteTask(toQueue2::enqueue);
toQueue2.setCompleteTask(whenDone);
}
private void copyFromTo(Location pos1,
Location pos2,
int relX,
int relZ,
World world1,
QueueCoordinator fromQueue,
QueueCoordinator toQueue,
boolean removeEntities) {
fromQueue.setChunkConsumer(chunk -> {
int cx = chunk.getX();
int cz = chunk.getZ();
int cbx = cx << 4;
int cbz = cz << 4;
int bx = Math.max(pos1.getX() & 15, 0);
int bz = Math.max(pos1.getZ() & 15, 0);
int tx = Math.min(pos2.getX() & 15, 15);
int tz = Math.min(pos2.getZ() & 15, 15);
for (int y = 0; y < 256; y++) {
for (int x = bx; x <= tx; x++) {
for (int z = bz; z <= tz; z++) {
int rx = cbx + x;
int rz = cbz + z;
BlockVector3 loc = BlockVector3.at(rx, y, rz);
toQueue.setBlock(rx + relX, y, rz + relZ, world1.getFullBlock(loc));
toQueue.setBiome(rx + relX, y, rz + relZ, world1.getBiome(loc));
}
}
}
Region region = new CuboidRegion(BlockVector3.at(cbx + bx, 0, cbz + bz), BlockVector3.at(cbx + tx, 255, cbz + tz));
toQueue.addEntities(world1.getEntities(region));
if (removeEntities) {
for (Entity entity : world1.getEntities(region)) {
entity.remove();
}
}
});
}
public void setBiome(final CuboidRegion region, final int extendBiome, final BiomeType biome, final String world, final Runnable whenDone) {
Location pos1 = Location
.at(world, region.getMinimumPoint().getX() - extendBiome, region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome);
Location pos2 = Location
.at(world, region.getMaximumPoint().getX() + extendBiome, region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome);
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(world));
final int minX = pos1.getX();
final int minZ = pos1.getZ();
final int maxX = pos2.getX();
final int maxZ = pos2.getZ();
queue.addReadChunks(region.getChunks());
queue.setChunkConsumer(blockVector2 -> {
final int cx = blockVector2.getX() << 4;
final int cz = blockVector2.getZ() << 4;
WorldUtil.setBiome(world, Math.max(minX, cx), Math.max(minZ, cz), Math.min(maxX, cx + 15), Math.min(maxZ, cz + 15), biome);
worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), world);
});
queue.setCompleteTask(whenDone);
queue.enqueue();
}
}

View File

@ -32,7 +32,7 @@ import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.schematic.Schematic;
import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.net.AbstractDelegateOutputStream;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager;
@ -107,18 +107,18 @@ public abstract class SchematicHandler {
private static final Logger logger = LoggerFactory.getLogger("P2/" + SchematicHandler.class.getSimpleName());
public static SchematicHandler manager;
private boolean exportAll = false;
private final WorldUtil worldUtil;
private boolean exportAll = false;
public SchematicHandler(@Nonnull final WorldUtil worldUtil) {
this.worldUtil = worldUtil;
}
public static void upload(@Nullable UUID uuid, @Nullable final String file,
@Nonnull final String extension, @Nullable final RunnableVal<OutputStream> writeTask,
@Nonnull final RunnableVal<URL> whenDone) {
public static void upload(@Nullable UUID uuid,
@Nullable final String file,
@Nonnull final String extension,
@Nullable final RunnableVal<OutputStream> writeTask,
@Nonnull final RunnableVal<URL> whenDone) {
if (writeTask == null) {
TaskManager.runTask(whenDone);
return;
@ -148,23 +148,16 @@ public abstract class SchematicHandler {
con.setDoOutput(true);
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (OutputStream output = con.getOutputStream();
PrintWriter writer = new PrintWriter(
new OutputStreamWriter(output, StandardCharsets.UTF_8), true)) {
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8), true)) {
String CRLF = "\r\n";
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append(
"Content-Type: text/plain; charset=" + StandardCharsets.UTF_8.displayName())
.append(CRLF);
writer.append("Content-Type: text/plain; charset=" + StandardCharsets.UTF_8.displayName()).append(CRLF);
String param = "value";
writer.append(CRLF).append(param).append(CRLF).flush();
writer.append("--" + boundary).append(CRLF);
writer.append(
"Content-Disposition: form-data; name=\"schematicFile\"; filename=\""
+ filename + '"').append(CRLF);
writer
.append("Content-Type: " + URLConnection.guessContentTypeFromName(filename))
.append(CRLF);
writer.append("Content-Disposition: form-data; name=\"schematicFile\"; filename=\"" + filename + '"').append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(filename)).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
writeTask.value = new AbstractDelegateOutputStream(output) {
@ -194,8 +187,7 @@ public abstract class SchematicHandler {
});
}
public boolean exportAll(Collection<Plot> collection, final File outputDir,
final String namingScheme, final Runnable ifSuccess) {
public boolean exportAll(Collection<Plot> collection, final File outputDir, final String namingScheme, final Runnable ifSuccess) {
if (this.exportAll) {
return false;
}
@ -224,13 +216,10 @@ public abstract class SchematicHandler {
final String name;
if (namingScheme == null) {
name =
plot.getId().getX() + ";" + plot.getId().getY() + ',' + plot.getArea() + ',' + owner;
name = plot.getId().getX() + ";" + plot.getId().getY() + ',' + plot.getArea() + ',' + owner;
} else {
name = namingScheme.replaceAll("%id%", plot.getId().toString())
.replaceAll("%idx%", plot.getId().getX() + "")
.replaceAll("%idy%", plot.getId().getY() + "")
.replaceAll("%world%", plot.getArea().toString());
name = namingScheme.replaceAll("%id%", plot.getId().toString()).replaceAll("%idx%", plot.getId().getX() + "")
.replaceAll("%idy%", plot.getId().getY() + "").replaceAll("%world%", plot.getArea().toString());
}
final String directory;
@ -267,9 +256,13 @@ public abstract class SchematicHandler {
* @param xOffset offset x to paste it from plot origin
* @param zOffset offset z to paste it from plot origin
*/
public void paste(final Schematic schematic, final Plot plot, final int xOffset,
final int yOffset, final int zOffset, final boolean autoHeight,
final RunnableVal<Boolean> whenDone) {
public void paste(final Schematic schematic,
final Plot plot,
final int xOffset,
final int yOffset,
final int zOffset,
final boolean autoHeight,
final RunnableVal<Boolean> whenDone) {
TaskManager.runTask(() -> {
if (whenDone != null) {
@ -280,17 +273,14 @@ public abstract class SchematicHandler {
return;
}
try {
final LocalBlockQueue queue = plot.getArea().getQueue(false);
BlockVector3 dimension = schematic.getClipboard().getDimensions();
final int WIDTH = dimension.getX();
final int LENGTH = dimension.getZ();
final int HEIGHT = dimension.getY();
// Validate dimensions
CuboidRegion region = plot.getLargestRegion();
if (((region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + xOffset
+ 1) < WIDTH) || (
(region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + zOffset
+ 1) < LENGTH) || (HEIGHT > 256)) {
if (((region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + xOffset + 1) < WIDTH) || (
(region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + zOffset + 1) < LENGTH) || (HEIGHT > 256)) {
TaskManager.runTask(whenDone);
return;
}
@ -306,9 +296,8 @@ public abstract class SchematicHandler {
if (pw instanceof ClassicPlotWorld) {
y_offset_actual = yOffset + ((ClassicPlotWorld) pw).PLOT_HEIGHT;
} else {
y_offset_actual = yOffset + 1 + this.worldUtil
.getHighestBlockSynchronous(plot.getWorldName(),
region.getMinimumPoint().getX() + 1,
y_offset_actual = yOffset + 1 + this.worldUtil
.getHighestBlockSynchronous(plot.getWorldName(), region.getMinimumPoint().getX() + 1,
region.getMinimumPoint().getZ() + 1);
}
}
@ -316,8 +305,8 @@ public abstract class SchematicHandler {
y_offset_actual = yOffset;
}
final Location pos1 = Location.at(plot.getWorldName(), region.getMinimumPoint().getX() + xOffset, y_offset_actual,
region.getMinimumPoint().getZ() + zOffset);
final Location pos1 = Location
.at(plot.getWorldName(), region.getMinimumPoint().getX() + xOffset, y_offset_actual, region.getMinimumPoint().getZ() + zOffset);
final Location pos2 = pos1.add(WIDTH - 1, HEIGHT - 1, LENGTH - 1);
final int p1x = pos1.getX();
@ -328,58 +317,32 @@ public abstract class SchematicHandler {
final int bcz = p1z >> 4;
final int tcx = p2x >> 4;
final int tcz = p2z >> 4;
// Paste schematic here
final QueueCoordinator queue = plot.getArea().getQueue();
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
@Override public void run(int[] value) {
BlockVector2 chunk = BlockVector2.at(value[0], value[1]);
int x = chunk.getX();
int z = chunk.getZ();
int xxb = x << 4;
int zzb = z << 4;
int xxt = xxb + 15;
int zzt = zzb + 15;
if (x == bcx) {
xxb = p1x;
}
if (x == tcx) {
xxt = p2x;
}
if (z == bcz) {
zzb = p1z;
}
if (z == tcz) {
zzt = p2z;
}
// Paste schematic here
for (int ry = 0; ry < Math.min(256, HEIGHT); ry++) {
int yy = y_offset_actual + ry;
if (yy > 255) {
continue;
}
for (int rz = zzb - p1z; rz <= (zzt - p1z); rz++) {
for (int rx = xxb - p1x; rx <= (xxt - p1x); rx++) {
int xx = p1x + xOffset + rx;
int zz = p1z + zOffset + rz;
BaseBlock id = blockArrayClipboard
.getFullBlock(BlockVector3.at(rx, ry, rz));
queue.setBlock(xx, yy, zz, id);
if (ry == 0) {
BiomeType biome =
blockArrayClipboard.getBiome(BlockVector2.at(rx, rz));
queue.setBiome(xx, zz, biome);
}
}
for (int ry = 0; ry < Math.min(256, HEIGHT); ry++) {
int yy = y_offset_actual + ry;
if (yy > 255) {
continue;
}
for (int rz = 0; rz <= blockArrayClipboard.getDimensions().getZ(); rz++) {
for (int rx = 0; rx < blockArrayClipboard.getDimensions().getX(); rx++) {
int xx = p1x + xOffset + rx;
int zz = p1z + zOffset + rz;
BaseBlock id = blockArrayClipboard.getFullBlock(BlockVector3.at(rx, ry, rz));
queue.setBlock(xx, yy, zz, id);
if (ry == 0) {
BiomeType biome = blockArrayClipboard.getBiome(BlockVector3.at(rx, ry, rz));
queue.setBiome(xx, yy, zz, biome);
}
}
queue.enqueue();
}
}, () -> {
if (whenDone != null) {
whenDone.value = true;
whenDone.run();
}
}, 10);
}
if (whenDone != null) {
whenDone.value = true;
}
queue.setCompleteTask(whenDone);
queue.enqueue();
} catch (Exception e) {
e.printStackTrace();
TaskManager.runTask(whenDone);
@ -387,8 +350,7 @@ public abstract class SchematicHandler {
});
}
public abstract boolean restoreTile(LocalBlockQueue queue, CompoundTag tag, int x, int y,
int z);
public abstract boolean restoreTile(QueueCoordinator queue, CompoundTag tag, int x, int y, int z);
/**
* Get a schematic
@ -397,8 +359,7 @@ public abstract class SchematicHandler {
* @return schematic if found, else null
*/
public Schematic getSchematic(String name) throws UnsupportedFormatException {
File parent =
FileUtils.getFile(PlotSquared.platform().getDirectory(), Settings.Paths.SCHEMATICS);
File parent = FileUtils.getFile(PlotSquared.platform().getDirectory(), Settings.Paths.SCHEMATICS);
if (!parent.exists()) {
if (!parent.mkdir()) {
throw new RuntimeException("Could not create schematic parent directory");
@ -407,11 +368,9 @@ public abstract class SchematicHandler {
if (!name.endsWith(".schem") && !name.endsWith(".schematic")) {
name = name + ".schem";
}
File file = FileUtils.getFile(PlotSquared.platform().getDirectory(),
Settings.Paths.SCHEMATICS + File.separator + name);
File file = FileUtils.getFile(PlotSquared.platform().getDirectory(), Settings.Paths.SCHEMATICS + File.separator + name);
if (!file.exists()) {
file = FileUtils.getFile(PlotSquared.platform().getDirectory(),
Settings.Paths.SCHEMATICS + File.separator + name);
file = FileUtils.getFile(PlotSquared.platform().getDirectory(), Settings.Paths.SCHEMATICS + File.separator + name);
}
return getSchematic(file);
}
@ -422,12 +381,10 @@ public abstract class SchematicHandler {
* @return Immutable collection with schematic names
*/
public Collection<String> getSchematicNames() {
final File parent =
FileUtils.getFile(PlotSquared.platform().getDirectory(), Settings.Paths.SCHEMATICS);
final File parent = FileUtils.getFile(PlotSquared.platform().getDirectory(), Settings.Paths.SCHEMATICS);
final List<String> names = new ArrayList<>();
if (parent.exists()) {
final String[] rawNames =
parent.list((dir, name) -> name.endsWith(".schematic") || name.endsWith(".schem"));
final String[] rawNames = parent.list((dir, name) -> name.endsWith(".schematic") || name.endsWith(".schem"));
if (rawNames != null) {
final List<String> transformed = Arrays.stream(rawNames)
//.map(rawName -> rawName.substring(0, rawName.length() - 10))
@ -457,8 +414,7 @@ public abstract class SchematicHandler {
e.printStackTrace();
}
} else {
throw new UnsupportedFormatException(
"This schematic format is not recognised or supported.");
throw new UnsupportedFormatException("This schematic format is not recognised or supported.");
}
return null;
}
@ -476,14 +432,12 @@ public abstract class SchematicHandler {
public Schematic getSchematic(@Nonnull InputStream is) {
try {
SpongeSchematicReader schematicReader =
new SpongeSchematicReader(new NBTInputStream(new GZIPInputStream(is)));
SpongeSchematicReader schematicReader = new SpongeSchematicReader(new NBTInputStream(new GZIPInputStream(is)));
Clipboard clip = schematicReader.read();
return new Schematic(clip);
} catch (IOException ignored) {
try {
MCEditSchematicReader schematicReader =
new MCEditSchematicReader(new NBTInputStream(new GZIPInputStream(is)));
MCEditSchematicReader schematicReader = new MCEditSchematicReader(new NBTInputStream(new GZIPInputStream(is)));
Clipboard clip = schematicReader.read();
return new Schematic(clip);
} catch (IOException e) {
@ -500,8 +454,7 @@ public abstract class SchematicHandler {
URL url = new URL(website);
URLConnection connection = new URL(url.toString()).openConnection();
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
rawJSON = reader.lines().collect(Collectors.joining());
}
JSONArray array = new JSONArray(rawJSON);
@ -524,8 +477,7 @@ public abstract class SchematicHandler {
}
upload(uuid, file, "schem", new RunnableVal<OutputStream>() {
@Override public void run(OutputStream output) {
try (NBTOutputStream nos = new NBTOutputStream(
new GZIPOutputStream(output, true))) {
try (NBTOutputStream nos = new NBTOutputStream(new GZIPOutputStream(output, true))) {
nos.writeNamedTag("Schematic", tag);
} catch (IOException e1) {
e1.printStackTrace();
@ -548,8 +500,7 @@ public abstract class SchematicHandler {
try {
File tmp = FileUtils.getFile(PlotSquared.platform().getDirectory(), path);
tmp.getParentFile().mkdirs();
try (NBTOutputStream nbtStream = new NBTOutputStream(
new GZIPOutputStream(new FileOutputStream(tmp)))) {
try (NBTOutputStream nbtStream = new NBTOutputStream(new GZIPOutputStream(new FileOutputStream(tmp)))) {
nbtStream.writeNamedTag("Schematic", tag);
}
} catch (FileNotFoundException e) {
@ -561,8 +512,7 @@ public abstract class SchematicHandler {
return true;
}
public void getCompoundTag(final String world, final Set<CuboidRegion> regions,
final RunnableVal<CompoundTag> whenDone) {
public void getCompoundTag(final String world, final Set<CuboidRegion> regions, final RunnableVal<CompoundTag> whenDone) {
// async
TaskManager.runTaskAsync(() -> {
// Main positions
@ -570,17 +520,15 @@ public abstract class SchematicHandler {
final Location bot = corners[0];
final Location top = corners[1];
CuboidRegion cuboidRegion =
new CuboidRegion(this.worldUtil.getWeWorld(world), bot.getBlockVector3(),
top.getBlockVector3());
CuboidRegion cuboidRegion = new CuboidRegion(this.worldUtil.getWeWorld(world), bot.getBlockVector3(), top.getBlockVector3());
final int width = cuboidRegion.getWidth();
int height = cuboidRegion.getHeight();
final int length = cuboidRegion.getLength();
Map<String, Tag> schematic = new HashMap<>();
schematic.put("Version", new IntTag(2));
schematic.put("DataVersion", new IntTag(WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.WORLD_EDITING).getDataVersion()));
schematic.put("DataVersion",
new IntTag(WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion()));
Map<String, Tag> metadata = new HashMap<>();
metadata.put("WEOffsetX", new IntTag(0));
@ -615,14 +563,12 @@ public abstract class SchematicHandler {
schematic.put("Palette", new CompoundTag(paletteTag));
schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray()));
schematic
.put("TileEntities", new ListTag(CompoundTag.class, tileEntities));
schematic.put("TileEntities", new ListTag(CompoundTag.class, tileEntities));
schematic.put("BiomePaletteMax", new IntTag(biomePalette.size()));
Map<String, Tag> biomePaletteTag = new HashMap<>();
biomePalette.forEach(
(key, value) -> biomePaletteTag.put(key, new IntTag(value)));
biomePalette.forEach((key, value) -> biomePaletteTag.put(key, new IntTag(value)));
schematic.put("BiomePalette", new CompoundTag(biomePaletteTag));
schematic.put("BiomeData", new ByteArrayTag(biomeBuffer.toByteArray()));
@ -653,33 +599,23 @@ public abstract class SchematicHandler {
final Runnable zTask = new Runnable() {
@Override public void run() {
long zstart = System.currentTimeMillis();
while (ziter.hasNext()
&& System.currentTimeMillis() - zstart < 20) {
while (ziter.hasNext() && System.currentTimeMillis() - zstart < 20) {
final int z = ziter.next();
Iterator<Integer> xiter =
IntStream.range(p1x, p2x + 1).iterator();
Iterator<Integer> xiter = IntStream.range(p1x, p2x + 1).iterator();
final Runnable xTask = new Runnable() {
@Override public void run() {
long xstart = System.currentTimeMillis();
final int ry = y - sy;
final int rz = z - p1z;
while (xiter.hasNext()
&& System.currentTimeMillis() - xstart
< 20) {
while (xiter.hasNext() && System.currentTimeMillis() - xstart < 20) {
final int x = xiter.next();
final int rx = x - p1x;
BlockVector3 point =
BlockVector3.at(x, y, z);
BaseBlock block = cuboidRegion.getWorld()
.getFullBlock(point);
BlockVector3 point = BlockVector3.at(x, y, z);
BaseBlock block = cuboidRegion.getWorld().getFullBlock(point);
if (block.getNbtData() != null) {
Map<String, Tag> values =
new HashMap<>();
for (Map.Entry<String, Tag> entry : block
.getNbtData().getValue()
.entrySet()) {
values.put(entry.getKey(),
entry.getValue());
Map<String, Tag> values = new HashMap<>();
for (Map.Entry<String, Tag> entry : block.getNbtData().getValue().entrySet()) {
values.put(entry.getKey(), entry.getValue());
}
// Remove 'id' if it exists. We want 'Id'
values.remove("id");
@ -689,16 +625,12 @@ public abstract class SchematicHandler {
values.remove("y");
values.remove("z");
values.put("Id",
new StringTag(block.getNbtId()));
values.put("Pos", new IntArrayTag(
new int[] {rx, ry, rz}));
values.put("Id", new StringTag(block.getNbtId()));
values.put("Pos", new IntArrayTag(new int[] {rx, ry, rz}));
tileEntities
.add(new CompoundTag(values));
tileEntities.add(new CompoundTag(values));
}
String blockKey =
block.toImmutableState().getAsString();
String blockKey = block.toImmutableState().getAsString();
int blockId;
if (palette.containsKey(blockKey)) {
blockId = palette.get(blockKey);
@ -717,8 +649,7 @@ public abstract class SchematicHandler {
continue;
}
BlockVector2 pt = BlockVector2.at(x, z);
BiomeType biome =
cuboidRegion.getWorld().getBiome(pt);
BiomeType biome = cuboidRegion.getWorld().getBiome(pt);
String biomeStr = biome.getId();
int biomeId;
if (biomePalette.containsKey(biomeStr)) {

View File

@ -56,6 +56,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@ -68,20 +69,14 @@ import java.util.zip.ZipOutputStream;
public abstract class WorldUtil {
private final RegionManager regionManager;
public WorldUtil(@Nonnull final RegionManager regionManager) {
this.regionManager = regionManager;
}
/**
* Set the biome in a region
*
* @param world World name
* @param p1x Min X
* @param p1z Min Z
* @param p2x Max X
* @param p2z Max Z
* @param p1x Min X
* @param p1z Min Z
* @param p2x Max X
* @param p2z Max Z
* @param biome Biome
*/
public static void setBiome(String world, int p1x, int p1z, int p2x, int p2z, BiomeType biome) {
@ -135,8 +130,7 @@ public abstract class WorldUtil {
* @param name Block name
* @return Comparison result containing the closets matching block
*/
@Nonnull public abstract StringComparison<BlockState>.ComparisonResult getClosestBlock(
@Nonnull String name);
@Nonnull public abstract StringComparison<BlockState>.ComparisonResult getClosestBlock(@Nonnull String name);
/**
* Set the block at the specified location to a sign, with given text
@ -156,8 +150,7 @@ public abstract class WorldUtil {
* @param z Chunk Z coordinate
* @param result Result consumer
*/
public abstract void getBiome(@Nonnull String world, int x, int z,
@Nonnull Consumer<BiomeType> result);
public abstract void getBiome(@Nonnull String world, int x, int z, @Nonnull Consumer<BiomeType> result);
/**
* Get the biome in a given chunk, asynchronously
@ -168,8 +161,7 @@ public abstract class WorldUtil {
* @return Biome
* @deprecated Use {@link #getBiome(String, int, int, Consumer)}
*/
@Deprecated @Nonnull public abstract BiomeType getBiomeSynchronous(@Nonnull String world, int x,
int z);
@Deprecated @Nonnull public abstract BiomeType getBiomeSynchronous(@Nonnull String world, int x, int z);
/**
* Get the block at a given location (asynchronously)
@ -196,8 +188,7 @@ public abstract class WorldUtil {
* @param z Z coordinate
* @param result Result consumer
*/
public abstract void getHighestBlock(@Nonnull String world, int x, int z,
@Nonnull IntConsumer result);
public abstract void getHighestBlock(@Nonnull String world, int x, int z, @Nonnull IntConsumer result);
/**
@ -209,8 +200,7 @@ public abstract class WorldUtil {
* @return Result
* @deprecated Use {@link #getHighestBlock(String, int, int, IntConsumer)}
*/
@Deprecated @Nonnegative
public abstract int getHighestBlockSynchronous(@Nonnull String world, int x, int z);
@Deprecated @Nonnegative public abstract int getHighestBlockSynchronous(@Nonnull String world, int x, int z);
/**
* Set the biome in a region
@ -219,8 +209,7 @@ public abstract class WorldUtil {
* @param region Region
* @param biome New biome
*/
public abstract void setBiomes(@Nonnull String world, @Nonnull CuboidRegion region,
@Nonnull BiomeType biome);
public abstract void setBiomes(@Nonnull String world, @Nonnull CuboidRegion region, @Nonnull BiomeType biome);
/**
* Get the WorldEdit {@link com.sk89q.worldedit.world.World} corresponding to a world name
@ -230,8 +219,16 @@ public abstract class WorldUtil {
*/
@Nonnull public abstract com.sk89q.worldedit.world.World getWeWorld(@Nonnull String world);
public void upload(@Nonnull final Plot plot, @Nullable final UUID uuid,
@Nullable final String file, @Nonnull final RunnableVal<URL> whenDone) {
/**
* Refresh (resend) chunk to player. Usually after setting the biome
*
* @param x Chunk x location
* @param z Chunk z location
* @param world World of the chunk
*/
public abstract void refreshChunk(int x, int z, String world);
public void upload(@Nonnull final Plot plot, @Nullable final UUID uuid, @Nullable final String file, @Nonnull final RunnableVal<URL> whenDone) {
plot.getHome(home -> SchematicHandler.upload(uuid, file, "zip", new RunnableVal<OutputStream>() {
@Override public void run(OutputStream output) {
try (final ZipOutputStream zos = new ZipOutputStream(output)) {
@ -240,8 +237,7 @@ public abstract class WorldUtil {
if (dat != null) {
ZipEntry ze = new ZipEntry("world" + File.separator + dat.getName());
zos.putNextEntry(ze);
try (NBTInputStream nis = new NBTInputStream(
new GZIPInputStream(new FileInputStream(dat)))) {
try (NBTInputStream nis = new NBTInputStream(new GZIPInputStream(new FileInputStream(dat)))) {
CompoundTag tag = (CompoundTag) nis.readNamedTag().getTag();
CompoundTag data = (CompoundTag) tag.getValue().get("Data");
Map<String, Tag> map = ReflectionUtils.getMap(data.getValue());
@ -249,8 +245,7 @@ public abstract class WorldUtil {
map.put("SpawnY", new IntTag(home.getY()));
map.put("SpawnZ", new IntTag(home.getZ()));
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (NBTOutputStream out = new NBTOutputStream(
new GZIPOutputStream(baos, true))) {
try (NBTOutputStream out = new NBTOutputStream(new GZIPOutputStream(baos, true))) {
//TODO Find what this should be called
out.writeNamedTag("Schematic????", tag);
}
@ -267,18 +262,14 @@ public abstract class WorldUtil {
int brz = bot.getZ() >> 9;
int trx = top.getX() >> 9;
int trz = top.getZ() >> 9;
Set<BlockVector2> files = regionManager.getChunkChunks(bot.getWorldName());
Set<BlockVector2> files = getChunkChunks(bot.getWorldName());
for (BlockVector2 mca : files) {
if (mca.getX() >= brx && mca.getX() <= trx && mca.getZ() >= brz
&& mca.getZ() <= trz) {
final File file =
getMcr(plot.getWorldName(), mca.getX(), mca.getZ());
if (mca.getX() >= brx && mca.getX() <= trx && mca.getZ() >= brz && mca.getZ() <= trz) {
final File file = getMcr(plot.getWorldName(), mca.getX(), mca.getZ());
if (file != null) {
//final String name = "r." + (x - cx) + "." + (z - cz) + ".mca";
String name = file.getName();
final ZipEntry ze = new ZipEntry(
"world" + File.separator + "region" + File.separator
+ name);
final ZipEntry ze = new ZipEntry("world" + File.separator + "region" + File.separator + name);
zos.putNextEntry(ze);
try (FileInputStream in = new FileInputStream(file)) {
int len;
@ -302,9 +293,7 @@ public abstract class WorldUtil {
}
@Nullable final File getDat(@Nonnull final String world) {
File file = new File(
PlotSquared.platform().getWorldContainer() + File.separator + world + File.separator
+ "level.dat");
File file = new File(PlotSquared.platform().getWorldContainer() + File.separator + world + File.separator + "level.dat");
if (file.exists()) {
return file;
}
@ -312,14 +301,38 @@ public abstract class WorldUtil {
}
@Nullable private File getMcr(@Nonnull final String world, final int x, final int z) {
final File file = new File(PlotSquared.platform().getWorldContainer(),
world + File.separator + "region" + File.separator + "r." + x + '.' + z + ".mca");
final File file =
new File(PlotSquared.platform().getWorldContainer(), world + File.separator + "region" + File.separator + "r." + x + '.' + z + ".mca");
if (file.exists()) {
return file;
}
return null;
}
public Set<BlockVector2> getChunkChunks(String world) {
File folder = new File(PlotSquared.platform().getWorldContainer(), world + File.separator + "region");
File[] regionFiles = folder.listFiles();
if (regionFiles == null) {
throw new RuntimeException("Could not find worlds folder: " + folder + " ? (no read access?)");
}
HashSet<BlockVector2> chunks = new HashSet<>();
for (File file : regionFiles) {
String name = file.getName();
if (name.endsWith("mca")) {
String[] split = name.split("\\.");
try {
int x = Integer.parseInt(split[1]);
int z = Integer.parseInt(split[2]);
BlockVector2 loc = BlockVector2.at(x, z);
chunks.add(loc);
} catch (NumberFormatException ignored) {
}
}
}
return chunks;
}
/**
* Check if two blocks are the same type)
*
@ -383,7 +396,6 @@ public abstract class WorldUtil {
* @param chunk Chunk coordinates
* @return Tile entity count
*/
@Nonnegative public abstract int getTileEntityCount(@Nonnull String world,
@Nonnull BlockVector2 chunk);
@Nonnegative public abstract int getTileEntityCount(@Nonnull String world, @Nonnull BlockVector2 chunk);
}

View File

@ -0,0 +1,60 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util.placeholders;
import com.google.common.base.Preconditions;
import com.plotsquared.core.player.PlotPlayer;
import org.jetbrains.annotations.NotNull;
/**
* A placeholder is a keyed value that gets replaced by a {@link PlotPlayer player}-specific value at runtime
*/
public abstract class Placeholder {
private final String key;
public Placeholder(@NotNull final String key) {
this.key = Preconditions.checkNotNull(key, "Key may not be null");
}
/**
* Get the value of the placeholder for a particular player
*
* @param player Player
* @return Placeholder value. Return {@code ""} if no placeholder value can be returned
*/
@NotNull public abstract String getValue(@NotNull final PlotPlayer<?> player);
/**
* Get the placeholder key
*
* @return Placeholder key
*/
@NotNull public final String getKey() {
return this.key;
}
}

View File

@ -0,0 +1,234 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util.placeholders;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.flag.GlobalFlagContainer;
import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.PlayerManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiFunction;
/**
* Registry that contains {@link Placeholder placeholders}
*/
public final class PlaceholderRegistry {
private final Map<String, Placeholder> placeholders;
private final EventDispatcher eventDispatcher;
public PlaceholderRegistry(@NotNull final EventDispatcher eventDispatcher) {
this.placeholders = Maps.newHashMap();
this.eventDispatcher = eventDispatcher;
this.registerDefault();
}
private void registerDefault() {
final GlobalFlagContainer globalFlagContainer = GlobalFlagContainer.getInstance();
for (final PlotFlag<?, ?> flag : globalFlagContainer.getRecognizedPlotFlags()) {
this.registerPlaceholder(new PlotFlagPlaceholder(flag, true));
this.registerPlaceholder(new PlotFlagPlaceholder(flag, false));
}
GlobalFlagContainer.getInstance().subscribe((flag, type) -> {
this.registerPlaceholder(new PlotFlagPlaceholder(flag, true));
this.registerPlaceholder(new PlotFlagPlaceholder(flag, false));
});
this.createPlaceholder("currentplot_world", player -> player.getLocation().getWorldName());
this.createPlaceholder("has_plot", player -> player.getPlotCount() > 0 ? "true" : "false");
this.createPlaceholder("allowed_plot_count", player -> Integer.toString(player.getAllowedPlots()));
this.createPlaceholder("plot_count", player -> Integer.toString(player.getPlotCount()));
this.createPlaceholder("currentplot_alias", (player, plot) -> plot.getAlias());
this.createPlaceholder("currentplot_owner", (player, plot) -> {
final UUID plotOwner = plot.getOwnerAbs();
if (plotOwner == null) {
return "";
}
try {
return PlayerManager.getName(plotOwner, false);
} catch (final Exception ignored) {}
return "unknown";
});
this.createPlaceholder("currentplot_members", (player, plot) -> {
if (plot.getMembers() == null && plot.getTrusted() == null) {
return "0";
}
return String.valueOf(plot.getMembers().size() + plot.getTrusted().size());
});
this.createPlaceholder("currentplot_members_added", (player, plot) -> {
if (plot.getMembers() == null) {
return "0";
}
return String.valueOf(plot.getMembers().size());
});
this.createPlaceholder("currentplot_members_trusted", (player, plot) -> {
if (plot.getTrusted() == null) {
return "0";
}
return String.valueOf(plot.getTrusted().size());
});
this.createPlaceholder("currentplot_members_denied", (player, plot) -> {
if (plot.getDenied() == null) {
return "0";
}
return String.valueOf(plot.getDenied().size());
});
this.createPlaceholder("has_build_rights", (player, plot) ->
plot.isAdded(player.getUUID()) ? "true" : "false");
this.createPlaceholder("currentplot_x", (player, plot) -> Integer.toString(plot.getId().getX()));
this.createPlaceholder("currentplot_y", (player, plot) -> Integer.toString(plot.getId().getY()));
this.createPlaceholder("currentplot_xy", (player, plot) -> plot.getId().toString());
this.createPlaceholder("currentplot_rating", (player, plot) -> Double.toString(plot.getAverageRating()));
this.createPlaceholder("currentplot_biome", (player, plot) -> plot.getBiomeSynchronous().toString());
}
/**
* Create a functional placeholder
*
* @param key Placeholder key
* @param placeholderFunction Placeholder generator. Cannot return null
*/
@SuppressWarnings("ALL") public void createPlaceholder(@NotNull final String key,
@NotNull final Function<PlotPlayer<?>, String> placeholderFunction) {
this.registerPlaceholder(new Placeholder(key) {
@Override @NotNull public String getValue(@NotNull final PlotPlayer<?> player) {
return placeholderFunction.apply(player);
}
});
}
/**
* Create a functional placeholder
*
* @param key Placeholder key
* @param placeholderFunction Placeholder generator. Cannot return null
*/
public void createPlaceholder(@NotNull final String key,
@NotNull final BiFunction<PlotPlayer<?>, Plot, String> placeholderFunction) {
this.registerPlaceholder(new PlotSpecificPlaceholder(key) {
@Override @NotNull public String getValue(@NotNull final PlotPlayer<?> player, @NotNull final Plot plot) {
return placeholderFunction.apply(player, plot);
}
});
}
/**
* Register a placeholder
*
* @param placeholder Placeholder instance
*/
public void registerPlaceholder(@NotNull final Placeholder placeholder) {
final Placeholder previous = this.placeholders
.put(placeholder.getKey().toLowerCase(Locale.ENGLISH),
Preconditions.checkNotNull(placeholder, "Placeholder may not be null"));
if (previous == null) {
this.eventDispatcher.callGenericEvent(new PlaceholderAddedEvent(placeholder));
}
}
/**
* Get a placeholder instance from its key
*
* @param key Placeholder key
* @return Placeholder value
*/
@Nullable public Placeholder getPlaceholder(@NotNull final String key) {
return this.placeholders.get(
Preconditions.checkNotNull(key, "Key may not be null").toLowerCase(Locale.ENGLISH));
}
/**
* Get the placeholder value evaluated for a player, and catch and deal with any problems
* occurring while doing so
*
* @param key Placeholder key
* @param player Player to evaluate for
* @return Replacement value
*/
@NotNull public String getPlaceholderValue(@NotNull final String key,
@NotNull final PlotPlayer<?> player) {
final Placeholder placeholder = getPlaceholder(key);
if (placeholder == null) {
return "";
}
String placeholderValue = "";
try {
placeholderValue = placeholder.getValue(player);
// If a placeholder for some reason decides to be disobedient, we catch it here
if (placeholderValue == null) {
new RuntimeException(String
.format("Placeholder '%s' returned null for player '%s'", placeholder.getKey(),
player.getName())).printStackTrace();
}
} catch (final Exception exception) {
new RuntimeException(String
.format("Placeholder '%s' failed to evalulate for player '%s'",
placeholder.getKey(), player.getName()), exception).printStackTrace();
}
return placeholderValue;
}
/**
* Get all placeholders
*
* @return Unmodifiable collection of placeholders
*/
@NotNull public Collection<Placeholder> getPlaceholders() {
return Collections.unmodifiableCollection(this.placeholders.values());
}
/**
* Event called when a new {@link Placeholder} has been added
*/
public static class PlaceholderAddedEvent {
private final Placeholder placeholder;
public PlaceholderAddedEvent(Placeholder placeholder) {
this.placeholder = placeholder;
}
public Placeholder getPlaceholder() {
return this.placeholder;
}
}
}

View File

@ -0,0 +1,76 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util.placeholders;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.flag.GlobalFlagContainer;
import com.plotsquared.core.plot.flag.PlotFlag;
import org.jetbrains.annotations.NotNull;
public final class PlotFlagPlaceholder extends PlotSpecificPlaceholder {
private final PlotFlag<?, ?> flag;
private final boolean local;
public PlotFlagPlaceholder(@NotNull final PlotFlag<?, ?> flag, final boolean local) {
super(String.format("currentplot_%sflag_%s", local ? "local": "", flag.getName()));
this.flag = flag;
this.local = local;
}
@Override @NotNull public String getValue(@NotNull final PlotPlayer<?> player, @NotNull final Plot plot) {
return this.getFlagValue(plot, this.flag.getName(), !this.local);
}
/**
* Return the flag value from its name on the current plot.
* If the flag doesn't exist it returns an empty string.
* If the flag exists but it is not set on current plot and the parameter inherit is set to true,
* it returns the default value.
*
* @param plot Current plot where the player is
* @param flagName Name of flag to get from current plot
* @param inherit Define if it returns only the flag set on the current plot or also inherited flags
* @return The value of flag serialized in string
*/
@NotNull private String getFlagValue(@NotNull final Plot plot, @NotNull final String flagName, final boolean inherit) {
if (flagName.isEmpty()) {
return "";
}
final PlotFlag<?, ?> flag = GlobalFlagContainer.getInstance().getFlagFromString(flagName);
if (flag == null) {
return "";
}
if (inherit) {
return plot.getFlag(flag).toString();
} else {
final PlotFlag<?, ?> plotFlag = plot.getFlagContainer().queryLocal(flag.getClass());
return (plotFlag != null) ? plotFlag.getValue().toString() : "";
}
}
}

View File

@ -0,0 +1,59 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util.placeholders;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import org.jetbrains.annotations.NotNull;
/**
* A {@link Placeholder placeholder} that requires a {@link com.plotsquared.core.plot.Plot plot}
*/
public abstract class PlotSpecificPlaceholder extends Placeholder {
public PlotSpecificPlaceholder(@NotNull final String key) {
super(key);
}
@Override @NotNull public final String getValue(@NotNull final PlotPlayer<?> player) {
final Plot plot = player.getCurrentPlot();
if (plot == null) {
return "";
}
return this.getValue(player, plot);
}
/**
* Get the value of the placeholder for the {@link PlotPlayer player} in a specific {@link Plot plot}
*
* @param player Player that the placeholder is evaluated for
* @param plot Plot that the player is in
* @return Placeholder value, or {@code ""} if the placeholder does not apply
*/
@NotNull public abstract String getValue(@NotNull final PlotPlayer<?> player,
@NotNull final Plot plot);
}

View File

@ -171,8 +171,10 @@ public class UUIDPipeline {
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException ignored) {
logger.warn("[P2] (UUID) Request for {} timed out", username);
// This is completely valid, we just don't care anymore
if (Settings.DEBUG) {
logger.warn("[P2] (UUID) Request for {} timed out", username);
}
}
return null;
}
@ -194,8 +196,10 @@ public class UUIDPipeline {
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException ignored) {
logger.warn("[P2] (UUID) Request for {} timed out", uuid);
// This is completely valid, we just don't care anymore
if (Settings.DEBUG) {
logger.warn("[P2] (UUID) Request for {} timed out", uuid);
}
}
return null;
}
@ -206,20 +210,19 @@ public class UUIDPipeline {
* @param username Username
* @param uuid UUID consumer
*/
public void getSingle(@Nonnull final String username,
@Nonnull final BiConsumer<UUID, Throwable> uuid) {
public void getSingle(@Nonnull final String username, @Nonnull final BiConsumer<UUID, Throwable> uuid) {
this.getUUIDs(Collections.singletonList(username)).applyToEither(timeoutAfter(Settings.UUID.NON_BLOCKING_TIMEOUT), Function.identity())
.whenComplete((uuids, throwable) -> {
if (throwable != null) {
uuid.accept(null, throwable);
} else {
if (!uuids.isEmpty()) {
uuid.accept(uuids.get(0).getUuid(), null);
if (throwable != null) {
uuid.accept(null, throwable);
} else {
uuid.accept(null, null);
if (!uuids.isEmpty()) {
uuid.accept(uuids.get(0).getUuid(), null);
} else {
uuid.accept(null, null);
}
}
}
});
});
}
/**
@ -228,20 +231,19 @@ public class UUIDPipeline {
* @param uuid UUID
* @param username Username consumer
*/
public void getSingle(@Nonnull final UUID uuid,
@Nonnull final BiConsumer<String, Throwable> username) {
public void getSingle(@Nonnull final UUID uuid, @Nonnull final BiConsumer<String, Throwable> username) {
this.getNames(Collections.singletonList(uuid)).applyToEither(timeoutAfter(Settings.UUID.NON_BLOCKING_TIMEOUT), Function.identity())
.whenComplete((uuids, throwable) -> {
if (throwable != null) {
username.accept(null, throwable);
} else {
if (!uuids.isEmpty()) {
username.accept(uuids.get(0).getUsername(), null);
if (throwable != null) {
username.accept(null, throwable);
} else {
username.accept(null, null);
if (!uuids.isEmpty()) {
username.accept(uuids.get(0).getUsername(), null);
} else {
username.accept(null, null);
}
}
}
});
});
}
/**
@ -254,8 +256,7 @@ public class UUIDPipeline {
* @param timeout Timeout in milliseconds
* @return Mappings
*/
public CompletableFuture<List<UUIDMapping>> getNames(@Nonnull final Collection<UUID> requests,
final long timeout) {
public CompletableFuture<List<UUIDMapping>> getNames(@Nonnull final Collection<UUID> requests, final long timeout) {
return this.getNames(requests).applyToEither(timeoutAfter(timeout), Function.identity());
}
@ -269,8 +270,7 @@ public class UUIDPipeline {
* @param timeout Timeout in milliseconds
* @return Mappings
*/
public CompletableFuture<List<UUIDMapping>> getUUIDs(@Nonnull final Collection<String> requests,
final long timeout) {
public CompletableFuture<List<UUIDMapping>> getUUIDs(@Nonnull final Collection<String> requests, final long timeout) {
return this.getUUIDs(requests).applyToEither(timeoutAfter(timeout), Function.identity());
}
@ -349,8 +349,7 @@ public class UUIDPipeline {
* @param requests Names
* @return Mappings
*/
public CompletableFuture<List<UUIDMapping>> getUUIDs(
@Nonnull final Collection<String> requests) {
public CompletableFuture<List<UUIDMapping>> getUUIDs(@Nonnull final Collection<String> requests) {
if (requests.isEmpty()) {
return CompletableFuture.completedFuture(Collections.emptyList());
}

View File

@ -181,6 +181,8 @@
"core.prefix": "<dark_gray>[</dark_gray><gold>P2</gold><dark_gray>] </dark_gray>",
"core.enabled": "<prefix><gold><value> is now enabled.</gold>",
"placeholder.hooked": "<prefix><gold>PlotSquared hooked into MVdWPlaceholderAPI</gold>",
"reload.reloaded_configs": "<prefix><gold>Translations and world settings have been reloaded successfully.</gold>",
"reload.reload_failed": "<prefix><red>Failed to reload file configurations.</red>",