diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle
index 8378e37d2..694c6f319 100644
--- a/Bukkit/build.gradle
+++ b/Bukkit/build.gradle
@@ -2,6 +2,7 @@ plugins {
id "com.github.johnrengelman.shadow"
}
repositories {
+ mavenLocal()
maven { url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" }
maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url = "https://jitpack.io" }
@@ -15,7 +16,7 @@ repositories {
maven { url = "https://mvn.intellectualsites.com/content/repositories/snapshots" }
maven { url = "https://repo.wea-ondara.net/repository/public/" }
maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" }
- mavenLocal()
+ maven { url = "http://repo.mvdw-software.be/content/groups/public/" }
}
@@ -25,7 +26,7 @@ dependencies {
compile(project(":PlotSquared-Core"))
compile("com.destroystokyo.paper:paper-api:1.16.1-R0.1-SNAPSHOT")
implementation("org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT")
- compile(group: "com.sk89q.worldedit", name: "worldedit-bukkit", version: "7.1.0") {
+ compile(group: "com.sk89q.worldedit", name: "worldedit-bukkit", version: "7.2.0-SNAPSHOT") {
exclude(module: "bukkit")
}
@@ -44,8 +45,10 @@ dependencies {
implementation('net.kyori:adventure-text-minimessage:3.0.0-SNAPSHOT')
compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false }
compile('com.sk89q:squirrelid:1.0.0-SNAPSHOT'){ transitive = false }
+ compile('be.maximvdw:MVdWPlaceholderAPI:2.1.1-SNAPSHOT'){ transitive = false }
// logging
implementation('org.apache.logging.log4j:log4j-slf4j-impl:2.8.1')
+ compile('be.maximvdw:MVdWPlaceholderAPI:3.1.1-SNAPSHOT'){ transitive = false }
}
sourceCompatibility = 1.8
diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml
index b9e6fbb23..6a6cb057e 100644
--- a/Bukkit/pom.xml
+++ b/Bukkit/pom.xml
@@ -27,7 +27,7 @@
com.plotsquared
PlotSquared-Core
- 5.12.5
+ 6.0.0-SUPER-SNAPSHOT
compile
@@ -39,7 +39,7 @@
com.sk89q.worldedit
worldedit-bukkit
- 7.1.0
+ 7.2.0-SNAPSHOT
compile
@@ -90,10 +90,22 @@
+
+ be.maximvdw
+ MVdWPlaceholderAPI
+ 3.1.1-SNAPSHOT
+ compile
+
+
+ *
+ *
+
+
+
com.sk89q.worldedit
worldedit-core
- 7.0.0
+ 7.2.0-SNAPSHOT
runtime
@@ -110,30 +122,6 @@
-
- net.kyori
- text-api
- 3.0.2
- runtime
-
-
- net.kyori
- text-serializer-gson
- 3.0.2
- runtime
-
-
- net.kyori
- text-serializer-legacy
- 3.0.2
- runtime
-
-
- net.kyori
- text-serializer-plain
- 3.0.2
- runtime
-
com.google.guava
guava
@@ -182,6 +170,18 @@
4.0-dev-106
runtime
+
+ net.kyori
+ adventure-platform-bukkit
+ 4.0.0-SNAPSHOT
+ runtime
+
+
+ net.kyori
+ adventure-text-minimessage
+ 3.0.0-SNAPSHOT
+ runtime
+
org.apache.logging.log4j
log4j-slf4j-impl
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java
index d05fb7bf7..65233e117 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java
@@ -36,15 +36,19 @@ import com.plotsquared.bukkit.inject.BackupModule;
import com.plotsquared.bukkit.inject.BukkitModule;
import com.plotsquared.bukkit.inject.PermissionModule;
import com.plotsquared.bukkit.inject.WorldManagerModule;
+import com.plotsquared.bukkit.listener.BlockEventListener;
import com.plotsquared.bukkit.listener.ChunkListener;
+import com.plotsquared.bukkit.listener.EntityEventListener;
import com.plotsquared.bukkit.listener.EntitySpawnListener;
import com.plotsquared.bukkit.listener.PaperListener;
-import com.plotsquared.bukkit.listener.PlayerEvents;
+import com.plotsquared.bukkit.listener.PlayerEventListener;
+import com.plotsquared.bukkit.listener.ProjectileEventListener;
+import com.plotsquared.bukkit.listener.ServerListener;
import com.plotsquared.bukkit.listener.SingleWorldListener;
import com.plotsquared.bukkit.listener.WorldEvents;
import com.plotsquared.bukkit.placeholder.PlaceholderFormatter;
-import com.plotsquared.bukkit.placeholder.Placeholders;
import com.plotsquared.bukkit.player.BukkitPlayer;
+import com.plotsquared.bukkit.placeholder.PAPIPlaceholders;
import com.plotsquared.bukkit.player.BukkitPlayerManager;
import com.plotsquared.bukkit.util.task.BukkitTaskManager;
import com.plotsquared.bukkit.util.BukkitUtil;
@@ -94,7 +98,6 @@ import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag;
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.GlobalBlockQueue;
import com.plotsquared.core.setup.PlotAreaBuilder;
import com.plotsquared.core.setup.SettingsNodesWrapper;
import com.plotsquared.core.util.ConsoleColors;
@@ -160,7 +163,8 @@ import static com.plotsquared.core.util.PremiumVerification.getResourceID;
import static com.plotsquared.core.util.PremiumVerification.getUserID;
import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
-@SuppressWarnings("unused") public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPlatform {
+@SuppressWarnings("unused")
+public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPlatform {
private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitPlatform.class.getSimpleName());
private static final int BSTATS_ID = 1404;
@@ -233,10 +237,8 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
final PlotSquared plotSquared = new PlotSquared(this, "Bukkit");
if (PlotSquared.platform().getServerVersion()[1] < 13) {
- System.out.println(
- "You can't use this version of PlotSquared on a server less than Minecraft 1.13.2.");
- System.out
- .println("Please check the download page for the link to the legacy versions.");
+ System.out.println("You can't use this version of PlotSquared on a server less than Minecraft 1.13.2.");
+ System.out.println("Please check the download page for the link to the legacy versions.");
System.out.println("The server will now be shutdown to prevent any corruption.");
Bukkit.shutdown();
return;
@@ -244,11 +246,9 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
// We create the injector after PlotSquared has been initialized, so that we have access
// to generated instances and settings
- this.injector = Guice.createInjector(Stage.PRODUCTION, new PermissionModule(),
- new WorldManagerModule(),
- new PlotSquaredModule(),
- new BukkitModule(this),
- new BackupModule());
+ this.injector = Guice
+ .createInjector(Stage.PRODUCTION, new PermissionModule(), new WorldManagerModule(), new PlotSquaredModule(), new BukkitModule(this),
+ new BackupModule());
this.injector.injectMembers(this);
this.serverLocale = Locale.forLanguageTag(Settings.Enabled_Components.DEFAULT_LOCALE);
@@ -292,8 +292,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
// Do stuff that was previously done in PlotSquared
// Kill entities
- if (Settings.Enabled_Components.KILL_ROAD_MOBS
- || Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
+ if (Settings.Enabled_Components.KILL_ROAD_MOBS || Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
this.runEntityTask();
}
@@ -311,7 +310,11 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
if (Settings.Enabled_Components.EVENTS) {
- getServer().getPluginManager().registerEvents(getInjector().getInstance(PlayerEvents.class), this);
+ getServer().getPluginManager().registerEvents(getInjector().getInstance(PlayerEventListener.class), this);
+ getServer().getPluginManager().registerEvents(getInjector().getInstance(BlockEventListener.class), this);
+ getServer().getPluginManager().registerEvents(getInjector().getInstance(EntityEventListener.class), this);
+ getServer().getPluginManager().registerEvents(getInjector().getInstance(ProjectileEventListener.class), this);
+ getServer().getPluginManager().registerEvents(getInjector().getInstance(ServerListener.class), this);
getServer().getPluginManager().registerEvents(getInjector().getInstance(EntitySpawnListener.class), this);
if (PaperLib.isPaper() && Settings.Paper_Components.PAPER_LISTENERS) {
getServer().getPluginManager().registerEvents(getInjector().getInstance(PaperListener.class), this);
@@ -325,10 +328,6 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
getServer().getPluginManager().registerEvents(getInjector().getInstance(ChunkListener.class), this);
}
- // Start the global block queue
- final GlobalBlockQueue globalBlockQueue = this.injector.getInstance(GlobalBlockQueue.class);
- globalBlockQueue.runTask();
-
// Commands
if (Settings.Enabled_Components.COMMANDS) {
this.registerCommands();
@@ -372,9 +371,9 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
continue;
}
if (!worldUtil.isWorld(world) && !world.equals("*")) {
- logger.warn("[P2] `{}` was not properly loaded - {} will now try to load it properly",
- world, this.getPluginName());
- logger.warn("[P2] - Are you trying to delete this world? Remember to remove it from the worlds.yml, bukkit.yml and multiverse worlds.yml");
+ logger.warn("[P2] `{}` was not properly loaded - {} will now try to load it properly", world, this.getPluginName());
+ logger.warn(
+ "[P2] - Are you trying to delete this world? Remember to remove it from the worlds.yml, bukkit.yml and multiverse worlds.yml");
logger.warn("[P2] - Your world management plugin may be faulty (or non existent)");
logger.warn("[P2] This message may also be a false positive and could be ignored.");
this.setGenerator(world);
@@ -408,16 +407,14 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService("user_cache.db");
final SQLiteUUIDService legacyUUIDService;
- if (Settings.UUID.LEGACY_DATABASE_SUPPORT &&
- FileUtils.getFile(PlotSquared.platform().getDirectory(), "usercache.db").exists()) {
+ if (Settings.UUID.LEGACY_DATABASE_SUPPORT && FileUtils.getFile(PlotSquared.platform().getDirectory(), "usercache.db").exists()) {
legacyUUIDService = new SQLiteUUIDService("usercache.db");
} else {
legacyUUIDService = null;
}
final LuckPermsUUIDService luckPermsUUIDService;
- if (Settings.UUID.SERVICE_LUCKPERMS &&
- Bukkit.getPluginManager().getPlugin("LuckPerms") != null) {
+ if (Settings.UUID.SERVICE_LUCKPERMS && Bukkit.getPluginManager().getPlugin("LuckPerms") != null) {
luckPermsUUIDService = new LuckPermsUUIDService();
logger.info("[P2] (UUID) Using LuckPerms as a complementary UUID service");
} else {
@@ -425,8 +422,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
final BungeePermsUUIDService bungeePermsUUIDService;
- if (Settings.UUID.SERVICE_BUNGEE_PERMS &&
- Bukkit.getPluginManager().getPlugin("BungeePerms") != null) {
+ if (Settings.UUID.SERVICE_BUNGEE_PERMS && Bukkit.getPluginManager().getPlugin("BungeePerms") != null) {
bungeePermsUUIDService = new BungeePermsUUIDService();
logger.info("[P2] (UUID) Using BungeePerms as a complementary UUID service");
} else {
@@ -474,11 +470,9 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
this.backgroundPipeline.registerService(essentialsUUIDService);
}
- final SquirrelIdUUIDService impromptuMojangService =
- new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT);
+ final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT);
this.impromptuPipeline.registerService(impromptuMojangService);
- final SquirrelIdUUIDService backgroundMojangService =
- new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT);
+ final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT);
this.backgroundPipeline.registerService(backgroundMojangService);
} else {
this.impromptuPipeline.registerService(sqLiteUUIDService);
@@ -499,7 +493,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
- injector.getInstance(Placeholders.class).register();
+ injector.getInstance(PAPIPlaceholders.class).register();
if (Settings.Enabled_Components.EXTERNAL_PLACEHOLDERS) {
ChatFormatter.formatters.add(getInjector().getInstance(PlaceholderFormatter.class));
}
@@ -537,8 +531,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
this.methodUnloadSetup = true;
try {
ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
- this.methodUnloadChunk0 = classCraftWorld.getRealClass()
- .getDeclaredMethod("unloadChunk0", int.class, int.class, boolean.class);
+ this.methodUnloadChunk0 = classCraftWorld.getRealClass().getDeclaredMethod("unloadChunk0", int.class, int.class, boolean.class);
this.methodUnloadChunk0.setAccessible(true);
} catch (Throwable event) {
event.printStackTrace();
@@ -569,8 +562,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
final Plot plot = area.getOwnedPlot(id);
if (plot != null) {
- if (!plot.getFlag(ServerPlotFlag.class) || PlotSquared.platform().getPlayerManager()
- .getPlayerIfExists(plot.getOwner()) == null) {
+ if (!plot.getFlag(ServerPlotFlag.class) || PlotSquared.platform().getPlayerManager().getPlayerIfExists(plot.getOwner()) == null) {
if (world.getKeepSpawnInMemory()) {
world.setKeepSpawnInMemory(false);
return;
@@ -588,8 +580,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
boolean result;
if (methodUnloadChunk0 != null) {
try {
- result = (boolean) methodUnloadChunk0
- .invoke(world, chunkI.getX(), chunkI.getZ(), true);
+ result = (boolean) methodUnloadChunk0.invoke(world, chunkI.getX(), chunkI.getZ(), true);
} catch (Throwable e) {
methodUnloadChunk0 = null;
e.printStackTrace();
@@ -612,8 +603,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
}
- private void startUuidCaching(@Nonnull final SQLiteUUIDService sqLiteUUIDService,
- @Nonnull final CacheUUIDService cacheUUIDService) {
+ private void startUuidCaching(@Nonnull final SQLiteUUIDService sqLiteUUIDService, @Nonnull final CacheUUIDService cacheUUIDService) {
// Load all uuids into a big chunky boi queue
final Queue uuidQueue = new LinkedBlockingQueue<>();
PlotSquared.get().forEachPlotRaw(plot -> {
@@ -653,8 +643,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
// fresh batch
secondRun = false;
// Populate the request list
- for (int i = 0;
- i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) {
+ for (int i = 0; i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) {
uuidList.add(uuidQueue.poll());
read++;
}
@@ -760,8 +749,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
case "MINECART_TNT":
case "BOAT":
if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
- com.plotsquared.core.location.Location location =
- BukkitUtil.adapt(entity.getLocation());
+ com.plotsquared.core.location.Location location = BukkitUtil.adapt(entity.getLocation());
Plot plot = location.getPlot();
if (plot == null) {
if (location.isPlotArea()) {
@@ -791,9 +779,8 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
case "FIREBALL":
case "DRAGON_FIREBALL":
case "DROPPED_ITEM":
- if (Settings.Enabled_Components.KILL_ROAD_ITEMS && plotArea
- .getOwnedPlotAbs(BukkitUtil.adapt(entity.getLocation()))
- == null) {
+ if (Settings.Enabled_Components.KILL_ROAD_ITEMS
+ && plotArea.getOwnedPlotAbs(BukkitUtil.adapt(entity.getLocation())) == null) {
entity.remove();
}
// dropped item
@@ -817,15 +804,12 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
PlotId originalPlotId = (PlotId) meta.get(0).value();
if (originalPlotId != null) {
- com.plotsquared.core.location.Location pLoc =
- BukkitUtil.adapt(entity.getLocation());
+ com.plotsquared.core.location.Location pLoc = BukkitUtil.adapt(entity.getLocation());
PlotArea area = pLoc.getPlotArea();
if (area != null) {
PlotId currentPlotId = area.getPlotAbs(pLoc).getId();
- if (!originalPlotId.equals(currentPlotId) && (
- currentPlotId == null || !area
- .getPlot(originalPlotId)
- .equals(area.getPlot(currentPlotId)))) {
+ if (!originalPlotId.equals(currentPlotId) && (currentPlotId == null || !area.getPlot(originalPlotId)
+ .equals(area.getPlot(currentPlotId)))) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
@@ -836,15 +820,12 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
} else {
//This is to apply the metadata to already spawned shulkers (see EntitySpawnListener.java)
- com.plotsquared.core.location.Location pLoc =
- BukkitUtil.adapt(entity.getLocation());
+ com.plotsquared.core.location.Location pLoc = BukkitUtil.adapt(entity.getLocation());
PlotArea area = pLoc.getPlotArea();
if (area != null) {
PlotId currentPlotId = area.getPlotAbs(pLoc).getId();
if (currentPlotId != null) {
- entity.setMetadata("shulkerPlot",
- new FixedMetadataValue(
- (Plugin) PlotSquared.platform(), currentPlotId));
+ entity.setMetadata("shulkerPlot", new FixedMetadataValue((Plugin) PlotSquared.platform(), currentPlotId));
}
}
}
@@ -925,11 +906,9 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
if (BukkitUtil.adapt(location).isPlotRoad()) {
if (entity instanceof LivingEntity) {
LivingEntity livingEntity = (LivingEntity) entity;
- if (!livingEntity.isLeashed() || !entity
- .hasMetadata("keep")) {
+ if (!livingEntity.isLeashed() || !entity.hasMetadata("keep")) {
Entity passenger = entity.getPassenger();
- if (!(passenger instanceof Player) && entity
- .getMetadata("keep").isEmpty()) {
+ if (!(passenger instanceof Player) && entity.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
@@ -940,8 +919,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
} else {
Entity passenger = entity.getPassenger();
- if (!(passenger instanceof Player) && entity
- .getMetadata("keep").isEmpty()) {
+ if (!(passenger instanceof Player) && entity.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
@@ -962,9 +940,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}), TaskTime.seconds(1L));
}
- @Override @Nullable
- public final ChunkGenerator getDefaultWorldGenerator(@Nonnull final String worldName,
- final String id) {
+ @Override @Nullable public final ChunkGenerator getDefaultWorldGenerator(@Nonnull final String worldName, final String id) {
final IndependentPlotGenerator result;
if (id != null && id.equalsIgnoreCase("single")) {
result = getInjector().getInstance(SingleWorldGenerator.class);
@@ -977,8 +953,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
return (ChunkGenerator) result.specify(worldName);
}
- @Override @Nullable public GeneratorWrapper> getGenerator(@Nonnull final String world,
- @Nullable final String name) {
+ @Override @Nullable public GeneratorWrapper> getGenerator(@Nonnull final String world, @Nullable final String name) {
if (name == null) {
return null;
}
@@ -990,8 +965,8 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
return new BukkitPlotGenerator(world, gen, this.plotAreaManager);
} else {
- return new BukkitPlotGenerator(world, getInjector()
- .getInstance(Key.get(IndependentPlotGenerator.class, DefaultGenerator.class)), this.plotAreaManager);
+ return new BukkitPlotGenerator(world, getInjector().getInstance(Key.get(IndependentPlotGenerator.class, DefaultGenerator.class)),
+ this.plotAreaManager);
}
}
@@ -1011,19 +986,14 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
map.put(plotAreaType.name().toLowerCase(), terrainTypes);
}
for (final PlotArea plotArea : this.plotAreaManager.getAllPlotAreas()) {
- final Map terrainTypeMap =
- map.get(plotArea.getType().name().toLowerCase());
- terrainTypeMap.put(plotArea.getTerrain().name().toLowerCase(),
- terrainTypeMap.get(plotArea.getTerrain().name().toLowerCase()) + 1);
+ final Map terrainTypeMap = map.get(plotArea.getType().name().toLowerCase());
+ terrainTypeMap.put(plotArea.getTerrain().name().toLowerCase(), terrainTypeMap.get(plotArea.getTerrain().name().toLowerCase()) + 1);
}
return map;
}));
- metrics.addCustomChart(new Metrics.SimplePie("premium",
- () -> PremiumVerification.isPremium() ? "Premium" : "Non-Premium"));
+ metrics.addCustomChart(new Metrics.SimplePie("premium", () -> PremiumVerification.isPremium() ? "Premium" : "Non-Premium"));
metrics.addCustomChart(new Metrics.SimplePie("worldedit_implementation",
- () -> Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null ?
- "FastAsyncWorldEdit" :
- "WorldEdit"));
+ () -> Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null ? "FastAsyncWorldEdit" : "WorldEdit"));
}
@Override public void unregister(@Nonnull final PlotPlayer> player) {
@@ -1036,12 +1006,10 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
// create world
ConfigurationSection worldConfig = this.worldConfiguration.getConfigurationSection("worlds." + worldName);
String manager = worldConfig.getString("generator.plugin", getPluginName());
- PlotAreaBuilder builder = PlotAreaBuilder.newBuilder().plotManager(manager)
- .generatorName(worldConfig.getString("generator.init", manager))
- .plotAreaType(ConfigurationUtil.getType(worldConfig))
- .terrainType(ConfigurationUtil.getTerrain(worldConfig))
- .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null))
- .worldName(worldName);
+ PlotAreaBuilder builder =
+ PlotAreaBuilder.newBuilder().plotManager(manager).generatorName(worldConfig.getString("generator.init", manager))
+ .plotAreaType(ConfigurationUtil.getType(worldConfig)).terrainType(ConfigurationUtil.getTerrain(worldConfig))
+ .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)).worldName(worldName);
getInjector().getInstance(SetupUtils.class).setupWorld(builder);
world = Bukkit.getWorld(worldName);
} else {
@@ -1071,16 +1039,14 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
return name.substring(name.lastIndexOf('.') + 1);
}
- @Override public GeneratorWrapper> wrapPlotGenerator(@Nullable final String world,
- @Nonnull final IndependentPlotGenerator generator) {
+ @Override public GeneratorWrapper> wrapPlotGenerator(@Nullable final String world, @Nonnull final IndependentPlotGenerator generator) {
return new BukkitPlotGenerator(world, generator, this.plotAreaManager);
}
@Override public List, Boolean>> getPluginIds() {
List, Boolean>> names = new ArrayList<>();
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
- Map.Entry id = new AbstractMap.SimpleEntry<>(plugin.getName(),
- plugin.getDescription().getVersion());
+ Map.Entry id = new AbstractMap.SimpleEntry<>(plugin.getName(), plugin.getDescription().getVersion());
names.add(new AbstractMap.SimpleEntry<>(id, plugin.isEnabled()));
}
return names;
@@ -1115,11 +1081,11 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}
@Override @Nonnull public PlatformWorldManager> getWorldManager() {
- return getInjector().getInstance(Key.get(new TypeLiteral>() {}));
+ return getInjector().getInstance(Key.get(new TypeLiteral>() {
+ }));
}
- @Override @Nonnull @SuppressWarnings("ALL")
- public PlayerManager extends PlotPlayer, ? extends Player> getPlayerManager() {
+ @Override @Nonnull @SuppressWarnings("ALL") public PlayerManager extends PlotPlayer, ? extends Player> getPlayerManager() {
return (PlayerManager) getInjector().getInstance(PlayerManager.class);
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BlockStatePopulator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BlockStatePopulator.java
index e74266394..9a05dd773 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BlockStatePopulator.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BlockStatePopulator.java
@@ -30,8 +30,9 @@ import com.plotsquared.core.generator.IndependentPlotGenerator;
import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager;
-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.sk89q.worldedit.bukkit.BukkitWorld;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
@@ -44,30 +45,25 @@ final class BlockStatePopulator extends BlockPopulator {
private final IndependentPlotGenerator plotGenerator;
private final PlotAreaManager plotAreaManager;
- private LocalBlockQueue queue;
+ private QueueCoordinator queue;
- public BlockStatePopulator(@Nonnull final IndependentPlotGenerator plotGenerator,
- @Nonnull final PlotAreaManager plotAreaManager) {
+ public BlockStatePopulator(@Nonnull final IndependentPlotGenerator plotGenerator, @Nonnull final PlotAreaManager plotAreaManager) {
this.plotGenerator = plotGenerator;
this.plotAreaManager = plotAreaManager;
}
- @Override
- public void populate(@Nonnull final World world, @Nonnull final Random random,
- @Nonnull final Chunk source) {
+ @Override public void populate(@Nonnull final World world, @Nonnull final Random random, @Nonnull final Chunk source) {
if (this.queue == null) {
- this.queue = PlotSquared.platform().getGlobalBlockQueue()
- .getNewQueue(world.getName(), false);
+ this.queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(new BukkitWorld(world));
}
final PlotArea area = this.plotAreaManager.getPlotArea(world.getName(), null);
if (area == null) {
return;
}
- final ChunkWrapper wrap =
- new ChunkWrapper(area.getWorldName(), source.getX(), source.getZ());
- final ScopedLocalBlockQueue chunk = this.queue.getForChunk(wrap.x, wrap.z);
+ final ChunkWrapper wrap = new ChunkWrapper(area.getWorldName(), source.getX(), source.getZ());
+ final ScopedQueueCoordinator chunk = this.queue.getForChunk(wrap.x, wrap.z);
if (this.plotGenerator.populateChunk(chunk, area)) {
- this.queue.flush();
+ this.queue.enqueue();
}
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java
index 94d6d99e4..c1db952e2 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java
@@ -34,7 +34,7 @@ import com.plotsquared.core.generator.SingleWorldGenerator;
import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager;
-import com.plotsquared.core.queue.ScopedLocalBlockQueue;
+import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkManager;
import com.sk89q.worldedit.math.BlockVector2;
import org.bukkit.World;
@@ -62,7 +62,7 @@ public class BukkitPlotGenerator extends ChunkGenerator
private final String levelName;
- public BukkitPlotGenerator(@Nonnull final String name,
+ public BukkitPlotGenerator(@Nonnull final String name,
@Nonnull final IndependentPlotGenerator generator,
@Nonnull final PlotAreaManager plotAreaManager) {
this.plotAreaManager = plotAreaManager;
@@ -186,7 +186,7 @@ public class BukkitPlotGenerator extends ChunkGenerator
return result.getChunkData();
}
- private void generate(BlockVector2 loc, World world, ScopedLocalBlockQueue result) {
+ private void generate(BlockVector2 loc, World world, ScopedQueueCoordinator result) {
// Load if improperly loaded
if (!this.loaded) {
String name = world.getName();
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/DelegatePlotGenerator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/DelegatePlotGenerator.java
index 6906c446d..6a0a3ce7d 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/DelegatePlotGenerator.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/DelegatePlotGenerator.java
@@ -31,7 +31,7 @@ import com.plotsquared.core.generator.IndependentPlotGenerator;
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.bukkit.BukkitAdapter;
import org.bukkit.World;
@@ -63,7 +63,7 @@ final class DelegatePlotGenerator extends IndependentPlotGenerator {
return PlotSquared.platform().getDefaultGenerator().getNewPlotArea(world, id, min, max);
}
- @Override public void generateChunk(final ScopedLocalBlockQueue result, PlotArea settings) {
+ @Override public void generateChunk(final ScopedQueueCoordinator result, PlotArea settings) {
World world = BukkitUtil.getWorld(this.world);
Location min = result.getMin();
int chunkX = min.getX() >> 4;
@@ -71,11 +71,7 @@ final class DelegatePlotGenerator extends IndependentPlotGenerator {
Random random = new Random(MathMan.pair((short) chunkX, (short) chunkZ));
try {
ChunkGenerator.BiomeGrid grid = new ChunkGenerator.BiomeGrid() {
- @Override
- public void setBiome(
- final int x,
- final int z,
- @Nonnull final Biome biome) {
+ @Override public void setBiome(int x, int z, @Nonnull Biome biome) {
result.setBiome(x, z, BukkitAdapter.adapt(biome));
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java
index cbd5dc213..a5702d156 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/BukkitModule.java
@@ -31,7 +31,8 @@ import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.bukkit.player.BukkitPlayerManager;
-import com.plotsquared.bukkit.queue.BukkitLocalQueue;
+import com.plotsquared.bukkit.queue.BukkitChunkCoordinator;
+import com.plotsquared.bukkit.queue.BukkitQueueCoordinator;
import com.plotsquared.bukkit.schematic.BukkitSchematicHandler;
import com.plotsquared.bukkit.util.BukkitChunkManager;
import com.plotsquared.bukkit.util.BukkitEconHandler;
@@ -45,10 +46,13 @@ import com.plotsquared.core.generator.HybridGen;
import com.plotsquared.core.generator.IndependentPlotGenerator;
import com.plotsquared.core.inject.annotations.ConsoleActor;
import com.plotsquared.core.inject.annotations.DefaultGenerator;
+import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
+import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.inject.factory.HybridPlotWorldFactory;
import com.plotsquared.core.plot.world.DefaultPlotAreaManager;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotAreaManager;
+import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueProvider;
import com.plotsquared.core.util.ChunkManager;
@@ -88,8 +92,7 @@ public class BukkitModule extends AbstractModule {
bind(InventoryUtil.class).to(BukkitInventoryUtil.class);
bind(SetupUtils.class).to(BukkitSetupUtils.class);
bind(WorldUtil.class).to(BukkitUtil.class);
- bind(GlobalBlockQueue.class).toInstance(new GlobalBlockQueue(
- QueueProvider.of(BukkitLocalQueue.class, BukkitLocalQueue.class), 1, Settings.QUEUE.TARGET_TIME));
+ bind(GlobalBlockQueue.class).toInstance(new GlobalBlockQueue(QueueProvider.of(BukkitQueueCoordinator.class)));
bind(ChunkManager.class).to(BukkitChunkManager.class);
bind(RegionManager.class).to(BukkitRegionManager.class);
bind(SchematicHandler.class).to(BukkitSchematicHandler.class);
@@ -99,6 +102,8 @@ public class BukkitModule extends AbstractModule {
bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class);
}
install(new FactoryModuleBuilder().build(HybridPlotWorldFactory.class));
+ install(new FactoryModuleBuilder().implement(ChunkCoordinator.class, BukkitChunkCoordinator.class).build(ChunkCoordinatorFactory.class));
+ install(new FactoryModuleBuilder().build(ChunkCoordinatorBuilderFactory.class));
}
@Provides @Singleton @Nullable EconHandler provideEconHandler() {
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/BlockEventListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/BlockEventListener.java
new file mode 100644
index 000000000..99828db99
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/BlockEventListener.java
@@ -0,0 +1,1078 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.listener;
+
+import com.plotsquared.bukkit.player.BukkitPlayer;
+import com.plotsquared.bukkit.util.BukkitUtil;
+import com.plotsquared.core.PlotSquared;
+import com.plotsquared.core.configuration.Settings;
+import com.plotsquared.core.configuration.caption.TranslatableCaption;
+import com.plotsquared.core.database.DBFunc;
+import com.plotsquared.core.location.Location;
+import com.plotsquared.core.permissions.Permission;
+import com.plotsquared.core.player.PlotPlayer;
+import com.plotsquared.core.plot.Plot;
+import com.plotsquared.core.plot.PlotArea;
+import com.plotsquared.core.plot.flag.implementations.BlockBurnFlag;
+import com.plotsquared.core.plot.flag.implementations.BlockIgnitionFlag;
+import com.plotsquared.core.plot.flag.implementations.BreakFlag;
+import com.plotsquared.core.plot.flag.implementations.CoralDryFlag;
+import com.plotsquared.core.plot.flag.implementations.DisablePhysicsFlag;
+import com.plotsquared.core.plot.flag.implementations.DoneFlag;
+import com.plotsquared.core.plot.flag.implementations.ExplosionFlag;
+import com.plotsquared.core.plot.flag.implementations.GrassGrowFlag;
+import com.plotsquared.core.plot.flag.implementations.IceFormFlag;
+import com.plotsquared.core.plot.flag.implementations.IceMeltFlag;
+import com.plotsquared.core.plot.flag.implementations.InstabreakFlag;
+import com.plotsquared.core.plot.flag.implementations.KelpGrowFlag;
+import com.plotsquared.core.plot.flag.implementations.LiquidFlowFlag;
+import com.plotsquared.core.plot.flag.implementations.MycelGrowFlag;
+import com.plotsquared.core.plot.flag.implementations.PlaceFlag;
+import com.plotsquared.core.plot.flag.implementations.RedstoneFlag;
+import com.plotsquared.core.plot.flag.implementations.SnowFormFlag;
+import com.plotsquared.core.plot.flag.implementations.SnowMeltFlag;
+import com.plotsquared.core.plot.flag.implementations.SoilDryFlag;
+import com.plotsquared.core.plot.flag.implementations.VineGrowFlag;
+import com.plotsquared.core.plot.flag.types.BlockTypeWrapper;
+import com.plotsquared.core.plot.world.PlotAreaManager;
+import com.plotsquared.core.util.MainUtil;
+import com.plotsquared.core.util.Permissions;
+import com.plotsquared.core.util.task.TaskManager;
+import com.plotsquared.core.util.task.TaskTime;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.bukkit.BukkitAdapter;
+import com.sk89q.worldedit.world.block.BlockType;
+import net.kyori.adventure.text.minimessage.Template;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Fireball;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockBurnEvent;
+import org.bukkit.event.block.BlockDamageEvent;
+import org.bukkit.event.block.BlockDispenseEvent;
+import org.bukkit.event.block.BlockExplodeEvent;
+import org.bukkit.event.block.BlockFadeEvent;
+import org.bukkit.event.block.BlockFormEvent;
+import org.bukkit.event.block.BlockFromToEvent;
+import org.bukkit.event.block.BlockGrowEvent;
+import org.bukkit.event.block.BlockIgniteEvent;
+import org.bukkit.event.block.BlockPhysicsEvent;
+import org.bukkit.event.block.BlockPistonExtendEvent;
+import org.bukkit.event.block.BlockPistonRetractEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.block.BlockRedstoneEvent;
+import org.bukkit.event.block.BlockSpreadEvent;
+import org.bukkit.event.block.EntityBlockFormEvent;
+import org.bukkit.event.world.StructureGrowEvent;
+import org.bukkit.material.Directional;
+import org.bukkit.projectiles.BlockProjectileSource;
+import org.bukkit.util.Vector;
+
+import javax.annotation.Nonnull;
+import javax.inject.Inject;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+@SuppressWarnings("unused")
+public class BlockEventListener implements Listener {
+
+ private final PlotAreaManager plotAreaManager;
+ private final WorldEdit worldEdit;
+
+ @Inject public BlockEventListener(@Nonnull final PlotAreaManager plotAreaManager, @Nonnull final WorldEdit worldEdit) {
+ this.plotAreaManager = plotAreaManager;
+ this.worldEdit = worldEdit;
+ }
+
+ public static void sendBlockChange(final org.bukkit.Location bloc, final BlockData data) {
+ TaskManager.runTaskLater(() -> {
+ String world = bloc.getWorld().getName();
+ int x = bloc.getBlockX();
+ int z = bloc.getBlockZ();
+ int distance = Bukkit.getViewDistance() * 16;
+
+ for (final PlotPlayer> player : PlotSquared.platform().getPlayerManager().getPlayers()) {
+ Location location = player.getLocation();
+ if (location.getWorldName().equals(world)) {
+ if (16 * Math.abs(location.getX() - x) / 16 > distance || 16 * Math.abs(location.getZ() - z) / 16 > distance) {
+ continue;
+ }
+ ((BukkitPlayer) player).player.sendBlockChange(bloc, data);
+ }
+ }
+ }, TaskTime.ticks(3L));
+ }
+
+ @EventHandler public void onRedstoneEvent(BlockRedstoneEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
+ if (plot == null) {
+ if (area.isRoadFlags() && !area.getRoadFlag(RedstoneFlag.class)) {
+ event.setNewCurrent(0);
+ }
+ return;
+ }
+ if (!plot.getFlag(RedstoneFlag.class)) {
+ event.setNewCurrent(0);
+ plot.debug("Redstone event was cancelled because redstone = false");
+ return;
+ }
+ if (Settings.Redstone.DISABLE_OFFLINE) {
+ boolean disable = false;
+ if (!plot.getOwner().equals(DBFunc.SERVER)) {
+ if (plot.isMerged()) {
+ disable = true;
+ for (UUID owner : plot.getOwners()) {
+ if (PlotSquared.platform().getPlayerManager().getPlayerIfExists(owner) != null) {
+ disable = false;
+ break;
+ }
+ }
+ } else {
+ disable = PlotSquared.platform().getPlayerManager().getPlayerIfExists(plot.getOwnerAbs()) == null;
+ }
+ }
+ if (disable) {
+ for (UUID trusted : plot.getTrusted()) {
+ if (PlotSquared.platform().getPlayerManager().getPlayerIfExists(trusted) != null) {
+ disable = false;
+ break;
+ }
+ }
+ if (disable) {
+ event.setNewCurrent(0);
+ plot.debug("Redstone event was cancelled because no trusted player was in the plot");
+ return;
+ }
+ }
+ }
+ if (Settings.Redstone.DISABLE_UNOCCUPIED) {
+ for (final PlotPlayer> player : PlotSquared.platform().getPlayerManager().getPlayers()) {
+ if (plot.equals(player.getCurrentPlot())) {
+ return;
+ }
+ }
+ event.setNewCurrent(0);
+ }
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onPhysicsEvent(BlockPhysicsEvent event) {
+ switch (event.getChangedType()) {
+ case COMPARATOR: {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ if (location.isPlotArea()) {
+ return;
+ }
+ Plot plot = location.getOwnedPlotAbs();
+ if (plot == null) {
+ return;
+ }
+ if (!plot.getFlag(RedstoneFlag.class)) {
+ event.setCancelled(true);
+ plot.debug("Prevented comparator update because redstone = false");
+ }
+ return;
+ }
+ case ANVIL:
+ case DRAGON_EGG:
+ case GRAVEL:
+ case SAND:
+ case TURTLE_EGG:
+ case TURTLE_HELMET:
+ case TURTLE_SPAWN_EGG: {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlotAbs(location);
+ if (plot == null) {
+ return;
+ }
+ if (plot.getFlag(DisablePhysicsFlag.class)) {
+ event.setCancelled(true);
+ plot.debug("Prevented block physics because disable-physics = true");
+ }
+ return;
+ }
+ default:
+ if (Settings.Redstone.DETECT_INVALID_EDGE_PISTONS) {
+ Block block = event.getBlock();
+ switch (block.getType()) {
+ case PISTON:
+ case STICKY_PISTON:
+ org.bukkit.block.data.Directional piston = (org.bukkit.block.data.Directional) block.getBlockData();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlotAbs(location);
+ if (plot == null) {
+ return;
+ }
+ switch (piston.getFacing()) {
+ case EAST:
+ location = location.add(1, 0, 0);
+ break;
+ case SOUTH:
+ location = location.add(-1, 0, 0);
+ break;
+ case WEST:
+ location = location.add(0, 0, 1);
+ break;
+ case NORTH:
+ location = location.add(0, 0, -1);
+ break;
+ }
+ Plot newPlot = area.getOwnedPlotAbs(location);
+ if (!plot.equals(newPlot)) {
+ event.setCancelled(true);
+ plot.debug("Prevented piston update because of invalid edge piston detection");
+ return;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void blockCreate(BlockPlaceEvent event) {
+ Location location = BukkitUtil.adapt(event.getBlock().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ Plot plot = area.getPlot(location);
+ if (plot != null) {
+ if ((location.getY() > area.getMaxBuildHeight() || location.getY() < area
+ .getMinBuildHeight()) && !Permissions
+ .hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_HEIGHT_LIMIT)) {
+ event.setCancelled(true);
+ pp.sendMessage(
+ TranslatableCaption.of("height.height_limit"),
+ Template.of("limit", String.valueOf(area.getMaxBuildHeight()))
+ );
+ }
+ if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ return;
+ }
+ } else if (!plot.isAdded(pp.getUUID())) {
+ List place = plot.getFlag(PlaceFlag.class);
+ if (place != null) {
+ Block block = event.getBlock();
+ if (place.contains(
+ BlockTypeWrapper.get(BukkitAdapter.asBlockType(block.getType())))) {
+ return;
+ }
+ }
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ plot.debug(player.getName() + " could not place " + event.getBlock().getType()
+ + " because of the place flag");
+ return;
+ }
+ } else if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ return;
+ }
+ }
+ if (plot.getFlag(DisablePhysicsFlag.class)) {
+ Block block = event.getBlockPlaced();
+ if (block.getType().hasGravity()) {
+ sendBlockChange(block.getLocation(), block.getBlockData());
+ plot.debug(event.getBlock().getType()
+ + " did not fall because of disable-physics = true");
+ }
+ }
+ } else if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_ROAD)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST) public void blockDestroy(BlockBreakEvent event) {
+ Player player = event.getPlayer();
+ Location location = BukkitUtil.adapt(event.getBlock().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getPlot(location);
+ if (plot != null) {
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ if (event.getBlock().getY() == 0) {
+ if (!Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.groundlevel")
+ );
+ event.setCancelled(true);
+ return;
+ }
+ } else if ((location.getY() > area.getMaxBuildHeight() || location.getY() < area
+ .getMinBuildHeight()) && !Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_HEIGHT_LIMIT)) {
+ event.setCancelled(true);
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("height.height_limit"),
+ Template.of("limit", String.valueOf(area.getMaxBuildHeight()))
+ );
+ }
+ if (!plot.hasOwner()) {
+ if (!Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_UNOWNED, true)) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ if (!plot.isAdded(plotPlayer.getUUID())) {
+ List destroy = plot.getFlag(BreakFlag.class);
+ Block block = event.getBlock();
+ final BlockType blockType = BukkitAdapter.asBlockType(block.getType());
+ for (final BlockTypeWrapper blockTypeWrapper : destroy) {
+ if (blockTypeWrapper.accepts(blockType)) {
+ return;
+ }
+ }
+ if (Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_OTHER)) {
+ return;
+ }
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.other")
+ );
+ event.setCancelled(true);
+ } else if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
+ if (!Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ return;
+ }
+ }
+ return;
+ }
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ if (Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_DESTROY_ROAD)) {
+ return;
+ }
+ if (this.worldEdit!= null && pp.getAttribute("worldedit")) {
+ if (player.getInventory().getItemInMainHand().getType() == Material
+ .getMaterial(this.worldEdit.getConfiguration().wandItem)) {
+ return;
+ }
+ }
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.road")
+ );
+ event.setCancelled(true);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBlockSpread(BlockSpreadEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ if (location.isPlotRoad()) {
+ event.setCancelled(true);
+ return;
+ }
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot == null) {
+ return;
+ }
+ switch (event.getSource().getType()) {
+ case GRASS_BLOCK:
+ if (!plot.getFlag(GrassGrowFlag.class)) {
+ plot.debug("Grass could not grow because grass-grow = false");
+ event.setCancelled(true);
+ }
+ break;
+ case MYCELIUM:
+ if (!plot.getFlag(MycelGrowFlag.class)) {
+ plot.debug("Mycelium could not grow because mycel-grow = false");
+ event.setCancelled(true);
+ }
+ break;
+ case VINE:
+ if (!plot.getFlag(VineGrowFlag.class)) {
+ plot.debug("Vine could not grow because vine-grow = false");
+ event.setCancelled(true);
+ }
+ break;
+ case KELP:
+ if (!plot.getFlag(KelpGrowFlag.class)) {
+ plot.debug("Kelp could not grow because kelp-grow = false");
+ event.setCancelled(true);
+ }
+ break;
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBlockForm(BlockFormEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ if (location.isPlotRoad()) {
+ event.setCancelled(true);
+ return;
+ }
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot == null) {
+ return;
+ }
+ switch (event.getNewState().getType()) {
+ case SNOW:
+ case SNOW_BLOCK:
+ if (!plot.getFlag(SnowFormFlag.class)) {
+ plot.debug("Snow could not form because snow-form = false");
+ event.setCancelled(true);
+ }
+ return;
+ case ICE:
+ case FROSTED_ICE:
+ case PACKED_ICE:
+ if (!plot.getFlag(IceFormFlag.class)) {
+ plot.debug("Ice could not form because ice-form = false");
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onEntityBlockForm(EntityBlockFormEvent event) {
+ String world = event.getBlock().getWorld().getName();
+ if (!this.plotAreaManager.hasPlotArea(world)) {
+ return;
+ }
+ Location location = BukkitUtil.adapt(event.getBlock().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot == null) {
+ event.setCancelled(true);
+ return;
+ }
+ Entity entity = event.getEntity();
+ if (entity instanceof Player) {
+ Player player = (Player) entity;
+ if (!plot.hasOwner()) {
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ if (plot.getFlag(IceFormFlag.class)) {
+ plot.debug("Ice could not be formed because ice-form = false");
+ return;
+ }
+ event.setCancelled(true);
+ return;
+ }
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ if (!plot.isAdded(plotPlayer.getUUID())) {
+ if (plot.getFlag(IceFormFlag.class)) {
+ plot.debug("Ice could not be formed because ice-form = false");
+ return;
+ }
+ event.setCancelled(true);
+ return;
+ }
+ return;
+ }
+ if (!plot.getFlag(IceFormFlag.class)) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onBlockDamage(BlockDamageEvent event) {
+ Player player = event.getPlayer();
+ Location location = BukkitUtil.adapt(event.getBlock().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ if (player.getGameMode() != GameMode.SURVIVAL) {
+ return;
+ }
+ Plot plot = area.getPlot(location);
+ if (plot != null) {
+ if (plot.getFlag(InstabreakFlag.class)) {
+ Block block = event.getBlock();
+ BlockBreakEvent call = new BlockBreakEvent(block, player);
+ Bukkit.getServer().getPluginManager().callEvent(call);
+ if (!call.isCancelled()) {
+ event.getBlock().breakNaturally();
+ }
+ }
+ if (location.getY() == 0) {
+ event.setCancelled(true);
+ return;
+ }
+ if (!plot.hasOwner()) {
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ if (Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_UNOWNED)) {
+ return;
+ }
+ event.setCancelled(true);
+ return;
+ }
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ if (!plot.isAdded(plotPlayer.getUUID())) {
+ List destroy = plot.getFlag(BreakFlag.class);
+ Block block = event.getBlock();
+ if (destroy
+ .contains(BlockTypeWrapper.get(BukkitAdapter.asBlockType(block.getType())))
+ || Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_OTHER)) {
+ return;
+ }
+ plot.debug(player.getName() + " could not break " + block.getType()
+ + " because it was not in the break flag");
+ event.setCancelled(true);
+ return;
+ }
+ return;
+ }
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ if (Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_ROAD)) {
+ return;
+ }
+ event.setCancelled(true);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onFade(BlockFadeEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot == null) {
+ event.setCancelled(true);
+ return;
+ }
+ switch (block.getType()) {
+ case ICE:
+ if (!plot.getFlag(IceMeltFlag.class)) {
+ plot.debug("Ice could not melt because ice-melt = false");
+ event.setCancelled(true);
+ }
+ break;
+ case SNOW:
+ if (!plot.getFlag(SnowMeltFlag.class)) {
+ plot.debug("Snow could not melt because snow-melt = false");
+ event.setCancelled(true);
+ }
+ break;
+ case FARMLAND:
+ if (!plot.getFlag(SoilDryFlag.class)) {
+ plot.debug("Soil could not dry because soil-dry = false");
+ event.setCancelled(true);
+ }
+ break;
+ case TUBE_CORAL_BLOCK:
+ case BRAIN_CORAL_BLOCK:
+ case BUBBLE_CORAL_BLOCK:
+ case FIRE_CORAL_BLOCK:
+ case HORN_CORAL_BLOCK:
+ case TUBE_CORAL:
+ case BRAIN_CORAL:
+ case BUBBLE_CORAL:
+ case FIRE_CORAL:
+ case HORN_CORAL:
+ case TUBE_CORAL_FAN:
+ case BRAIN_CORAL_FAN:
+ case BUBBLE_CORAL_FAN:
+ case FIRE_CORAL_FAN:
+ case HORN_CORAL_FAN:
+ case BRAIN_CORAL_WALL_FAN:
+ case BUBBLE_CORAL_WALL_FAN:
+ case FIRE_CORAL_WALL_FAN:
+ case HORN_CORAL_WALL_FAN:
+ case TUBE_CORAL_WALL_FAN:
+ if (!plot.getFlag(CoralDryFlag.class)) {
+ plot.debug("Coral could not dry because coral-dry = false");
+ event.setCancelled(true);
+ }
+ break;
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onChange(BlockFromToEvent event) {
+ Block from = event.getBlock();
+
+ // Check liquid flow flag inside of origin plot too
+ final Location fLocation = BukkitUtil.adapt(from.getLocation());
+ final PlotArea fromArea = fLocation.getPlotArea();
+ if (fromArea != null) {
+ final Plot plot = fromArea.getOwnedPlot(fLocation);
+ if (plot != null && plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event.getBlock().isLiquid()) {
+ plot.debug("Liquid could now flow because liquid-flow = disabled");
+ event.setCancelled(true);
+ return;
+ }
+ }
+
+ Block to = event.getToBlock();
+ Location tLocation = BukkitUtil.adapt(to.getLocation());
+ PlotArea area = tLocation.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlot(tLocation);
+ if (plot != null) {
+ if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects.equals(plot, area.getOwnedPlot(fLocation))) {
+ event.setCancelled(true);
+ return;
+ }
+ if (plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.ENABLED && event.getBlock().isLiquid()) {
+ return;
+ }
+ if (plot.getFlag(DisablePhysicsFlag.class)) {
+ plot.debug(event.getBlock().getType() + " could not update because disable-physics = true");
+ event.setCancelled(true);
+ return;
+ }
+ if (plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event.getBlock().isLiquid()) {
+ plot.debug("Liquid could not flow because liquid-flow = disabled");
+ event.setCancelled(true);
+ }
+ } else if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects.equals(null, area.getOwnedPlot(fLocation))) {
+ event.setCancelled(true);
+ } else if (event.getBlock().isLiquid()) {
+ final org.bukkit.Location location = event.getBlock().getLocation();
+
+ /*
+ X = block location
+ A-H = potential plot locations
+ Z
+ ^
+ | A B C
+ o D X E
+ | F G H
+ v
+ <-----O-----> x
+ */
+ if (BukkitUtil.adapt(location.clone().add(-1, 0, 1) /* A */).getPlot() != null
+ || BukkitUtil.adapt(location.clone().add(1, 0, 0) /* B */).getPlot() != null
+ || BukkitUtil.adapt(location.clone().add(1, 0, 1) /* C */).getPlot() != null
+ || BukkitUtil.adapt(location.clone().add(-1, 0, 0) /* D */).getPlot() != null
+ || BukkitUtil.adapt(location.clone().add(1, 0, 0) /* E */).getPlot() != null
+ || BukkitUtil.adapt(location.clone().add(-1, 0, -1) /* F */).getPlot() != null
+ || BukkitUtil.adapt(location.clone().add(0, 0, -1) /* G */).getPlot() != null
+ || BukkitUtil.adapt(location.clone().add(1, 0, 1) /* H */).getPlot() != null) {
+ event.setCancelled(true);
+ }
+ }
+ }
+
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onGrow(BlockGrowEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ if (location.isUnownedPlotArea()) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBlockPistonExtend(BlockPistonExtendEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ BlockFace face = event.getDirection();
+ Vector relative = new Vector(face.getModX(), face.getModY(), face.getModZ());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return;
+ }
+ for (Block block1 : event.getBlocks()) {
+ Location bloc = BukkitUtil.adapt(block1.getLocation());
+ if (bloc.isPlotArea() || bloc.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ()).isPlotArea()) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ if (location.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ()).isPlotArea()) {
+ // Prevent pistons from extending if they are: bordering a plot
+ // area, facing inside plot area, and not pushing any blocks
+ event.setCancelled(true);
+ }
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot == null) {
+ event.setCancelled(true);
+ return;
+ }
+ for (Block block1 : event.getBlocks()) {
+ Location bloc = BukkitUtil.adapt(block1.getLocation());
+ if (!area.contains(bloc.getX(), bloc.getZ()) || !area.contains(bloc.getX() + relative.getBlockX(), bloc.getZ() + relative.getBlockZ())) {
+ event.setCancelled(true);
+ return;
+ }
+ if (!plot.equals(area.getOwnedPlot(bloc)) || !plot
+ .equals(area.getOwnedPlot(bloc.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ())))) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ if (!plot.equals(area.getOwnedPlot(location.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ())))) {
+ // This branch is only necessary to prevent pistons from extending
+ // if they are: on a plot edge, facing outside the plot, and not
+ // pushing any blocks
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBlockPistonRetract(BlockPistonRetractEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ BlockFace face = event.getDirection();
+ Vector relative = new Vector(face.getModX(), face.getModY(), face.getModZ());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return;
+ }
+ for (Block block1 : event.getBlocks()) {
+ Location bloc = BukkitUtil.adapt(block1.getLocation());
+ if (bloc.isPlotArea() || bloc.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ()).isPlotArea()) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot == null) {
+ event.setCancelled(true);
+ return;
+ }
+ for (Block block1 : event.getBlocks()) {
+ Location bloc = BukkitUtil.adapt(block1.getLocation());
+ if (!area.contains(bloc.getX(), bloc.getZ()) || !area.contains(bloc.getX() + relative.getBlockX(), bloc.getZ() + relative.getBlockZ())) {
+ event.setCancelled(true);
+ return;
+ }
+ if (!plot.equals(area.getOwnedPlot(bloc)) || !plot
+ .equals(area.getOwnedPlot(bloc.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ())))) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBlockDispense(BlockDispenseEvent event) {
+ Material type = event.getItem().getType();
+ switch (type) {
+ case SHULKER_BOX:
+ case WHITE_SHULKER_BOX:
+ case ORANGE_SHULKER_BOX:
+ case MAGENTA_SHULKER_BOX:
+ case LIGHT_BLUE_SHULKER_BOX:
+ case YELLOW_SHULKER_BOX:
+ case LIME_SHULKER_BOX:
+ case PINK_SHULKER_BOX:
+ case GRAY_SHULKER_BOX:
+ case LIGHT_GRAY_SHULKER_BOX:
+ case CYAN_SHULKER_BOX:
+ case PURPLE_SHULKER_BOX:
+ case BLUE_SHULKER_BOX:
+ case BROWN_SHULKER_BOX:
+ case GREEN_SHULKER_BOX:
+ case RED_SHULKER_BOX:
+ case BLACK_SHULKER_BOX:
+ case CARVED_PUMPKIN:
+ case WITHER_SKELETON_SKULL:
+ case FLINT_AND_STEEL:
+ case BONE_MEAL:
+ case SHEARS:
+ case GLASS_BOTTLE:
+ case GLOWSTONE:
+ case COD_BUCKET:
+ case PUFFERFISH_BUCKET:
+ case SALMON_BUCKET:
+ case TROPICAL_FISH_BUCKET:
+ case BUCKET:
+ case WATER_BUCKET:
+ case LAVA_BUCKET: {
+ if (event.getBlock().getType() == Material.DROPPER) {
+ return;
+ }
+ BlockFace targetFace = ((Directional) event.getBlock().getState().getData()).getFacing();
+ Location location = BukkitUtil.adapt(event.getBlock().getRelative(targetFace).getLocation());
+ if (location.isPlotRoad()) {
+ event.setCancelled(true);
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onStructureGrow(StructureGrowEvent event) {
+ if (!this.plotAreaManager.hasPlotArea(event.getWorld().getName())) {
+ return;
+ }
+ List blocks = event.getBlocks();
+ if (blocks.isEmpty()) {
+ return;
+ }
+ Location location = BukkitUtil.adapt(blocks.get(0).getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ for (int i = blocks.size() - 1; i >= 0; i--) {
+ location = BukkitUtil.adapt(blocks.get(i).getLocation());
+ if (location.isPlotArea()) {
+ blocks.remove(i);
+ }
+ }
+ return;
+ } else {
+ Plot origin = area.getOwnedPlot(location);
+ if (origin == null) {
+ event.setCancelled(true);
+ return;
+ }
+ for (int i = blocks.size() - 1; i >= 0; i--) {
+ location = BukkitUtil.adapt(blocks.get(i).getLocation());
+ if (!area.contains(location.getX(), location.getZ())) {
+ blocks.remove(i);
+ continue;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (!Objects.equals(plot, origin)) {
+ event.getBlocks().remove(i);
+ }
+ }
+ }
+ Plot origin = area.getPlot(location);
+ if (origin == null) {
+ event.setCancelled(true);
+ return;
+ }
+ for (int i = blocks.size() - 1; i >= 0; i--) {
+ location = BukkitUtil.adapt(blocks.get(i).getLocation());
+ Plot plot = area.getOwnedPlot(location);
+ /*
+ * plot → the base plot of the merged area
+ * origin → the plot where the event gets called
+ */
+
+ // Are plot and origin different AND are both plots merged
+ if (!Objects.equals(plot, origin) && (!plot.isMerged() && !origin.isMerged())) {
+ event.getBlocks().remove(i);
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBigBoom(BlockExplodeEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ String world = location.getWorldName();
+ if (!this.plotAreaManager.hasPlotArea(world)) {
+ return;
+ }
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ Iterator iterator = event.blockList().iterator();
+ while (iterator.hasNext()) {
+ location = BukkitUtil.adapt(iterator.next().getLocation());
+ if (location.isPlotArea()) {
+ iterator.remove();
+ }
+ }
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot == null || !plot.getFlag(ExplosionFlag.class)) {
+ event.setCancelled(true);
+ if (plot != null) {
+ plot.debug("Explosion was cancelled because explosion = false");
+ }
+ }
+ event.blockList().removeIf(blox -> !plot.equals(area.getOwnedPlot(BukkitUtil.adapt(blox.getLocation()))));
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBlockBurn(BlockBurnEvent event) {
+ Block block = event.getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+
+ Plot plot = location.getOwnedPlot();
+ if (plot == null || !plot.getFlag(BlockBurnFlag.class)) {
+ if (plot != null) {
+ plot.debug("Block burning was cancelled because block-burn = false");
+ }
+ event.setCancelled(true);
+ }
+
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onBlockIgnite(BlockIgniteEvent event) {
+ Player player = event.getPlayer();
+ Entity ignitingEntity = event.getIgnitingEntity();
+ Block block = event.getBlock();
+ BlockIgniteEvent.IgniteCause igniteCause = event.getCause();
+ Location location1 = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location1.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ if (igniteCause == BlockIgniteEvent.IgniteCause.LIGHTNING) {
+ event.setCancelled(true);
+ return;
+ }
+
+ Plot plot = area.getOwnedPlot(location1);
+ if (player != null) {
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ if (plot == null) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_ROAD)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.road")
+ );
+ event.setCancelled(true);
+ }
+ } else if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.unowned")
+ );
+ event.setCancelled(true);
+ }
+ } else if (!plot.isAdded(pp.getUUID())) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ }
+ } else if (!plot.getFlag(BlockIgnitionFlag.class)) {
+ event.setCancelled(true);
+ }
+ } else {
+ if (plot == null) {
+ event.setCancelled(true);
+ return;
+ }
+ if (ignitingEntity != null) {
+ if (!plot.getFlag(BlockIgnitionFlag.class)) {
+ event.setCancelled(true);
+ plot.debug("Block ignition was cancelled because block-ignition = false");
+ return;
+ }
+ if (igniteCause == BlockIgniteEvent.IgniteCause.FIREBALL) {
+ if (ignitingEntity instanceof Fireball) {
+ Projectile fireball = (Projectile) ignitingEntity;
+ Location location = null;
+ if (fireball.getShooter() instanceof Entity) {
+ Entity shooter = (Entity) fireball.getShooter();
+ location = BukkitUtil.adapt(shooter.getLocation());
+ } else if (fireball.getShooter() instanceof BlockProjectileSource) {
+ Block shooter =
+ ((BlockProjectileSource) fireball.getShooter()).getBlock();
+ location = BukkitUtil.adapt(shooter.getLocation());
+ }
+ if (location != null && !plot.equals(location.getPlot())) {
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ } else if (event.getIgnitingBlock() != null) {
+ Block ignitingBlock = event.getIgnitingBlock();
+ Plot plotIgnited = BukkitUtil.adapt(ignitingBlock.getLocation()).getPlot();
+ if (igniteCause == BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL && (
+ !plot.getFlag(BlockIgnitionFlag.class) || plotIgnited == null || !plotIgnited
+ .equals(plot)) || (igniteCause == BlockIgniteEvent.IgniteCause.SPREAD
+ || igniteCause == BlockIgniteEvent.IgniteCause.LAVA) && (
+ !plot.getFlag(BlockIgnitionFlag.class) || plotIgnited == null || !plotIgnited
+ .equals(plot))) {
+ event.setCancelled(true);
+ }
+ }
+ }
+ }
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntityEventListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntityEventListener.java
new file mode 100644
index 000000000..2d4162881
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntityEventListener.java
@@ -0,0 +1,330 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.listener;
+
+import com.plotsquared.bukkit.util.BukkitEntityUtil;
+import com.plotsquared.bukkit.util.BukkitUtil;
+import com.plotsquared.core.PlotSquared;
+import com.plotsquared.core.configuration.Settings;
+import com.plotsquared.core.location.Location;
+import com.plotsquared.core.plot.Plot;
+import com.plotsquared.core.plot.PlotArea;
+import com.plotsquared.core.plot.flag.implementations.DisablePhysicsFlag;
+import com.plotsquared.core.plot.flag.implementations.ExplosionFlag;
+import com.plotsquared.core.plot.flag.implementations.InvincibleFlag;
+import com.plotsquared.core.plot.flag.implementations.MobPlaceFlag;
+import com.plotsquared.core.plot.world.PlotAreaManager;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Ageable;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.FallingBlock;
+import org.bukkit.entity.TNTPrimed;
+import org.bukkit.entity.Vehicle;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityChangeBlockEvent;
+import org.bukkit.event.entity.EntityCombustByEntityEvent;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityExplodeEvent;
+import org.bukkit.event.entity.ExplosionPrimeEvent;
+import org.bukkit.event.vehicle.VehicleCreateEvent;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.metadata.MetadataValue;
+import org.bukkit.plugin.Plugin;
+
+import javax.annotation.Nonnull;
+import javax.inject.Inject;
+import java.util.Iterator;
+import java.util.List;
+
+@SuppressWarnings("unused")
+public class EntityEventListener implements Listener {
+
+ private final PlotAreaManager plotAreaManager;
+ private float lastRadius;
+
+ @Inject public EntityEventListener(@Nonnull final PlotAreaManager plotAreaManager) {
+ this.plotAreaManager = plotAreaManager;
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST) public void onEntityCombustByEntity(EntityCombustByEntityEvent event) {
+ EntityDamageByEntityEvent eventChange =
+ new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE_TICK, event.getDuration());
+ onEntityDamageByEntityEvent(eventChange);
+ if (eventChange.isCancelled()) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST) public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
+ Entity damager = event.getDamager();
+ Location location = BukkitUtil.adapt(damager.getLocation());
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return;
+ }
+ Entity victim = event.getEntity();
+/*
+ if (victim.getType().equals(EntityType.ITEM_FRAME)) {
+ Plot plot = BukkitUtil.getLocation(victim).getPlot();
+ if (plot != null && !plot.isAdded(damager.getUniqueId())) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+*/
+ if (!BukkitEntityUtil.entityDamage(damager, victim, event.getCause())) {
+ if (event.isCancelled()) {
+ if (victim instanceof Ageable) {
+ Ageable ageable = (Ageable) victim;
+ if (ageable.getAge() == -24000) {
+ ageable.setAge(0);
+ ageable.setAdult();
+ }
+ }
+ }
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void creatureSpawnEvent(CreatureSpawnEvent event) {
+ Entity entity = event.getEntity();
+ Location location = BukkitUtil.adapt(entity.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ CreatureSpawnEvent.SpawnReason reason = event.getSpawnReason();
+ switch (reason.toString()) {
+ case "DISPENSE_EGG":
+ case "EGG":
+ case "OCELOT_BABY":
+ case "SPAWNER_EGG":
+ if (!area.isSpawnEggs()) {
+ event.setCancelled(true);
+ return;
+ }
+ break;
+ case "REINFORCEMENTS":
+ case "NATURAL":
+ case "MOUNT":
+ case "PATROL":
+ case "RAID":
+ case "SHEARED":
+ case "SHOULDER_ENTITY":
+ case "SILVERFISH_BLOCK":
+ case "TRAP":
+ case "VILLAGE_DEFENSE":
+ case "VILLAGE_INVASION":
+ case "BEEHIVE":
+ case "CHUNK_GEN":
+ if (!area.isMobSpawning()) {
+ event.setCancelled(true);
+ return;
+ }
+ case "BREEDING":
+ if (!area.isSpawnBreeding()) {
+ event.setCancelled(true);
+ return;
+ }
+ break;
+ case "BUILD_IRONGOLEM":
+ case "BUILD_SNOWMAN":
+ case "BUILD_WITHER":
+ case "CUSTOM":
+ if (!area.isSpawnCustom() && entity.getType() != EntityType.ARMOR_STAND) {
+ event.setCancelled(true);
+ return;
+ }
+ break;
+ case "SPAWNER":
+ if (!area.isMobSpawnerSpawning()) {
+ event.setCancelled(true);
+ return;
+ }
+ break;
+ }
+ Plot plot = area.getOwnedPlotAbs(location);
+ if (plot == null) {
+ if (!area.isMobSpawning()) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ if (BukkitEntityUtil.checkEntity(entity, plot)) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onEntityFall(EntityChangeBlockEvent event) {
+ if (event.getEntityType() != EntityType.FALLING_BLOCK) {
+ return;
+ }
+ Block block = event.getBlock();
+ World world = block.getWorld();
+ String worldName = world.getName();
+ if (!this.plotAreaManager.hasPlotArea(worldName)) {
+ return;
+ }
+ Location location = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlotAbs(location);
+ if (plot == null || plot.getFlag(DisablePhysicsFlag.class)) {
+ event.setCancelled(true);
+ plot.debug("Falling block event was cancelled because disable-physics = true");
+ return;
+ }
+ if (event.getTo().hasGravity()) {
+ Entity entity = event.getEntity();
+ List meta = entity.getMetadata("plot");
+ if (meta.isEmpty()) {
+ return;
+ }
+ Plot origin = (Plot) meta.get(0).value();
+ if (origin != null && !origin.equals(plot)) {
+ event.setCancelled(true);
+ entity.remove();
+ }
+ } else if (event.getTo() == Material.AIR) {
+ event.getEntity().setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.platform(), plot));
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGH) public void onDamage(EntityDamageEvent event) {
+ if (event.getEntityType() != EntityType.PLAYER) {
+ return;
+ }
+ Location location = BukkitUtil.adapt(event.getEntity().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
+ if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(InvincibleFlag.class)) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ if (plot.getFlag(InvincibleFlag.class)) {
+ plot.debug(event.getEntity().getName() + " could not take damage because invincible = true");
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBigBoom(EntityExplodeEvent event) {
+ Location location = BukkitUtil.adapt(event.getLocation());
+ PlotArea area = location.getPlotArea();
+ boolean plotArea = location.isPlotArea();
+ if (!plotArea) {
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return;
+ }
+ return;
+ }
+ Plot plot = area.getOwnedPlot(location);
+ if (plot != null) {
+ if (plot.getFlag(ExplosionFlag.class)) {
+ List meta = event.getEntity().getMetadata("plot");
+ Plot origin;
+ if (meta.isEmpty()) {
+ origin = plot;
+ } else {
+ origin = (Plot) meta.get(0).value();
+ }
+ if (this.lastRadius != 0) {
+ List nearby = event.getEntity().getNearbyEntities(this.lastRadius, this.lastRadius, this.lastRadius);
+ for (Entity near : nearby) {
+ if (near instanceof TNTPrimed || near.getType().equals(EntityType.MINECART_TNT)) {
+ if (!near.hasMetadata("plot")) {
+ near.setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.platform(), plot));
+ }
+ }
+ }
+ this.lastRadius = 0;
+ }
+ Iterator iterator = event.blockList().iterator();
+ while (iterator.hasNext()) {
+ Block block = iterator.next();
+ location = BukkitUtil.adapt(block.getLocation());
+ if (!area.contains(location.getX(), location.getZ()) || !origin.equals(area.getOwnedPlot(location))) {
+ iterator.remove();
+ }
+ }
+ return;
+ } else {
+ plot.debug("Explosion was cancelled because explosion = false");
+ }
+ }
+ event.setCancelled(true);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onPeskyMobsChangeTheWorldLikeWTFEvent(EntityChangeBlockEvent event) {
+ Entity e = event.getEntity();
+ if (!(e instanceof FallingBlock)) {
+ Location location = BukkitUtil.adapt(event.getBlock().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area != null) {
+ Plot plot = area.getOwnedPlot(location);
+ if (plot != null && plot.getFlag(MobPlaceFlag.class)) {
+ plot.debug(e.getType() + " could not change block because mob-place = false");
+ return;
+ }
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler public void onPrime(ExplosionPrimeEvent event) {
+ this.lastRadius = event.getRadius() + 1;
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onVehicleCreate(VehicleCreateEvent event) {
+ Vehicle entity = event.getVehicle();
+ Location location = BukkitUtil.adapt(entity.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getOwnedPlotAbs(location);
+ if (plot == null || BukkitEntityUtil.checkEntity(entity, plot)) {
+ entity.remove();
+ return;
+ }
+ if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
+ entity.setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.platform(), plot));
+ }
+ }
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java
index e32376d4d..24d22e6a0 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java
@@ -25,6 +25,7 @@
*/
package com.plotsquared.bukkit.listener;
+import com.plotsquared.bukkit.util.BukkitEntityUtil;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings;
@@ -66,8 +67,7 @@ public class EntitySpawnListener implements Listener {
public static void testNether(final Entity entity) {
@Nonnull World world = entity.getWorld();
- if (world.getEnvironment() != World.Environment.NETHER
- && world.getEnvironment() != World.Environment.THE_END) {
+ if (world.getEnvironment() != World.Environment.NETHER && world.getEnvironment() != World.Environment.THE_END) {
return;
}
test(entity);
@@ -91,8 +91,7 @@ public class EntitySpawnListener implements Listener {
List meta = entity.getMetadata(KEY);
if (meta.isEmpty()) {
if (PlotSquared.get().getPlotAreaManager().hasPlotArea(world.getName())) {
- entity.setMetadata(KEY,
- new FixedMetadataValue((Plugin) PlotSquared.platform(), entity.getLocation()));
+ entity.setMetadata(KEY, new FixedMetadataValue((Plugin) PlotSquared.platform(), entity.getLocation()));
}
} else {
org.bukkit.Location origin = (org.bukkit.Location) meta.get(0).value();
@@ -123,8 +122,7 @@ public class EntitySpawnListener implements Listener {
}
}
- @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
- public void creatureSpawnEvent(EntitySpawnEvent event) {
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void creatureSpawnEvent(EntitySpawnEvent event) {
Entity entity = event.getEntity();
Location location = BukkitUtil.adapt(entity.getLocation());
PlotArea area = location.getPlotArea();
@@ -155,13 +153,12 @@ public class EntitySpawnListener implements Listener {
}
switch (entity.getType()) {
case ENDER_CRYSTAL:
- if (PlayerEvents.checkEntity(entity, plot)) {
+ if (BukkitEntityUtil.checkEntity(entity, plot)) {
event.setCancelled(true);
}
case SHULKER:
if (!entity.hasMetadata("shulkerPlot")) {
- entity.setMetadata("shulkerPlot",
- new FixedMetadataValue((Plugin) PlotSquared.platform(), plot.getId()));
+ entity.setMetadata("shulkerPlot", new FixedMetadataValue((Plugin) PlotSquared.platform(), plot.getId()));
}
}
}
@@ -192,8 +189,7 @@ public class EntitySpawnListener implements Listener {
}
}
- @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
- public void vehicleMove(VehicleMoveEvent event) {
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void vehicleMove(VehicleMoveEvent event) {
testNether(event.getVehicle());
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEventListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEventListener.java
new file mode 100644
index 000000000..2678a7484
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEventListener.java
@@ -0,0 +1,1627 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.listener;
+
+import com.destroystokyo.paper.MaterialTags;
+import com.google.common.base.Charsets;
+import com.plotsquared.bukkit.player.BukkitPlayer;
+import com.plotsquared.bukkit.util.BukkitEntityUtil;
+import com.plotsquared.bukkit.util.BukkitUtil;
+import com.plotsquared.bukkit.util.UpdateUtility;
+import com.plotsquared.core.PlotSquared;
+import com.plotsquared.core.configuration.Settings;
+import com.plotsquared.core.configuration.caption.Caption;
+import com.plotsquared.core.configuration.caption.TranslatableCaption;
+import com.plotsquared.core.listener.PlayerBlockEventType;
+import com.plotsquared.core.listener.PlotListener;
+import com.plotsquared.core.location.Location;
+import com.plotsquared.core.permissions.Permission;
+import com.plotsquared.core.player.MetaDataAccess;
+import com.plotsquared.core.player.PlayerMetaDataKeys;
+import com.plotsquared.core.player.PlotPlayer;
+import com.plotsquared.core.plot.Plot;
+import com.plotsquared.core.plot.PlotArea;
+import com.plotsquared.core.plot.PlotId;
+import com.plotsquared.core.plot.PlotInventory;
+import com.plotsquared.core.plot.flag.FlagContainer;
+import com.plotsquared.core.plot.flag.implementations.AnimalInteractFlag;
+import com.plotsquared.core.plot.flag.implementations.BlockedCmdsFlag;
+import com.plotsquared.core.plot.flag.implementations.ChatFlag;
+import com.plotsquared.core.plot.flag.implementations.DenyTeleportFlag;
+import com.plotsquared.core.plot.flag.implementations.DoneFlag;
+import com.plotsquared.core.plot.flag.implementations.DropProtectionFlag;
+import com.plotsquared.core.plot.flag.implementations.HangingBreakFlag;
+import com.plotsquared.core.plot.flag.implementations.HangingPlaceFlag;
+import com.plotsquared.core.plot.flag.implementations.HostileInteractFlag;
+import com.plotsquared.core.plot.flag.implementations.ItemDropFlag;
+import com.plotsquared.core.plot.flag.implementations.KeepInventoryFlag;
+import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag;
+import com.plotsquared.core.plot.flag.implementations.PlayerInteractFlag;
+import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag;
+import com.plotsquared.core.plot.flag.implementations.TamedInteractFlag;
+import com.plotsquared.core.plot.flag.implementations.UntrustedVisitFlag;
+import com.plotsquared.core.plot.flag.implementations.UseFlag;
+import com.plotsquared.core.plot.flag.implementations.VehicleBreakFlag;
+import com.plotsquared.core.plot.flag.implementations.VehicleUseFlag;
+import com.plotsquared.core.plot.flag.implementations.VillagerInteractFlag;
+import com.plotsquared.core.plot.flag.types.BlockTypeWrapper;
+import com.plotsquared.core.plot.world.PlotAreaManager;
+import com.plotsquared.core.util.EventDispatcher;
+import com.plotsquared.core.util.MainUtil;
+import com.plotsquared.core.util.MathMan;
+import com.plotsquared.core.util.Permissions;
+import com.plotsquared.core.util.PremiumVerification;
+import com.plotsquared.core.util.RegExUtil;
+import com.plotsquared.core.util.entity.EntityCategories;
+import com.plotsquared.core.util.task.TaskManager;
+import com.plotsquared.core.util.task.TaskTime;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.bukkit.BukkitAdapter;
+import com.sk89q.worldedit.world.block.BlockType;
+import io.papermc.lib.PaperLib;
+import net.kyori.adventure.text.TextComponent;
+import net.kyori.adventure.text.minimessage.Template;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.FluidCollisionMode;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.ItemFrame;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.entity.Tameable;
+import org.bukkit.entity.Vehicle;
+import org.bukkit.event.Event;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.EntityPickupItemEvent;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.hanging.HangingBreakByEntityEvent;
+import org.bukkit.event.hanging.HangingPlaceEvent;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
+import org.bukkit.event.player.PlayerBucketEmptyEvent;
+import org.bukkit.event.player.PlayerBucketFillEvent;
+import org.bukkit.event.player.PlayerChangedWorldEvent;
+import org.bukkit.event.player.PlayerCommandPreprocessEvent;
+import org.bukkit.event.player.PlayerDropItemEvent;
+import org.bukkit.event.player.PlayerEggThrowEvent;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.event.player.PlayerInteractAtEntityEvent;
+import org.bukkit.event.player.PlayerInteractEntityEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.event.player.PlayerRespawnEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+import org.bukkit.event.vehicle.VehicleDestroyEvent;
+import org.bukkit.event.vehicle.VehicleEntityCollisionEvent;
+import org.bukkit.event.vehicle.VehicleMoveEvent;
+import org.bukkit.help.HelpTopic;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.PlayerInventory;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.metadata.MetadataValue;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.util.Vector;
+
+import javax.annotation.Nonnull;
+import javax.inject.Inject;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+/**
+ * Player Events involving plots.
+ */
+@SuppressWarnings("unused")
+public class PlayerEventListener extends PlotListener implements Listener {
+
+ private final EventDispatcher eventDispatcher;
+ private final WorldEdit worldEdit;
+ private final PlotAreaManager plotAreaManager;
+ // To prevent recursion
+ private boolean tmpTeleport = true;
+ private Field fieldPlayer;
+ private PlayerMoveEvent moveTmp;
+ private String internalVersion;
+
+ {
+ try {
+ fieldPlayer = PlayerEvent.class.getDeclaredField("player");
+ fieldPlayer.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Inject public PlayerEventListener(@Nonnull final PlotAreaManager plotAreaManager,
+ @Nonnull final EventDispatcher eventDispatcher,
+ @Nonnull final WorldEdit worldEdit) {
+ super(eventDispatcher);
+ this.eventDispatcher = eventDispatcher;
+ this.worldEdit = worldEdit;
+ this.plotAreaManager = plotAreaManager;
+ }
+
+ @EventHandler public void onVehicleEntityCollision(VehicleEntityCollisionEvent e) {
+ if (e.getVehicle().getType() == EntityType.BOAT) {
+ Location location = BukkitUtil.adapt(e.getEntity().getLocation());
+ if (location.isPlotArea()) {
+ if (e.getEntity() instanceof Player) {
+ PlotPlayer player = BukkitUtil.adapt((Player) e.getEntity());
+ Plot plot = player.getCurrentPlot();
+ if (plot != null) {
+ if (!plot.isAdded(player.getUUID())) {
+ //Here the event is only canceled if the player is not the owner
+ //of the property on which he is located.
+ e.setCancelled(true);
+ }
+ } else {
+ e.setCancelled(true);
+ }
+ } else {
+ //Here the event is cancelled too, otherwise you can move the
+ //boat with EchoPets or other mobs running around on the plot.
+ e.setCancelled(true);
+ }
+ }
+ }
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
+ public void playerCommand(PlayerCommandPreprocessEvent event) {
+ String msg = event.getMessage().toLowerCase().replaceAll("/", "").trim();
+ if (msg.isEmpty()) {
+ return;
+ }
+ Player player = event.getPlayer();
+ PlotPlayer plotPlayer = BukkitUtil.adapt(player);
+ Location location = plotPlayer.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ String[] parts = msg.split(" ");
+ Plot plot = plotPlayer.getCurrentPlot();
+ // Check WorldEdit
+ switch (parts[0].toLowerCase()) {
+ case "up":
+ case "/up":
+ case "worldedit:up":
+ case "worldedit:/up":
+ if (plot == null || (!plot.isAdded(plotPlayer.getUUID()) && !Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER, true))) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ if (plot == null && !area.isRoadFlags()) {
+ return;
+ }
+
+ List blockedCommands = plot != null ?
+ plot.getFlag(BlockedCmdsFlag.class) :
+ area.getFlag(BlockedCmdsFlag.class);
+ if (!blockedCommands.isEmpty() && !Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) {
+ String part = parts[0];
+ if (parts[0].contains(":")) {
+ part = parts[0].split(":")[1];
+ msg = msg.replace(parts[0].split(":")[0] + ':', "");
+ }
+ String s1 = part;
+ List aliases = new ArrayList<>();
+ for (HelpTopic cmdLabel : Bukkit.getServer().getHelpMap().getHelpTopics()) {
+ if (part.equals(cmdLabel.getName())) {
+ break;
+ }
+ String label = cmdLabel.getName().replaceFirst("/", "");
+ if (aliases.contains(label)) {
+ continue;
+ }
+ PluginCommand p;
+ if ((p = Bukkit.getPluginCommand(label)) != null) {
+ for (String a : p.getAliases()) {
+ if (aliases.contains(a)) {
+ continue;
+ }
+ aliases.add(a);
+ a = a.replaceFirst("/", "");
+ if (!a.equals(label) && a.equals(part)) {
+ part = label;
+ break;
+ }
+ }
+ }
+ }
+ if (!s1.equals(part)) {
+ msg = msg.replace(s1, part);
+ }
+ for (String s : blockedCommands) {
+ Pattern pattern;
+ if (!RegExUtil.compiledPatterns.containsKey(s)) {
+ RegExUtil.compiledPatterns.put(s, pattern = Pattern.compile(s));
+ } else {
+ pattern = RegExUtil.compiledPatterns.get(s);
+ }
+ if (pattern.matcher(msg).matches()) {
+ String perm;
+ if (plot != null && plot.isAdded(plotPlayer.getUUID())) {
+ perm = "plots.admin.command.blocked-cmds.shared";
+ } else {
+ perm = "plots.admin.command.blocked-cmds.road";
+ }
+ if (!Permissions.hasPermission(plotPlayer, perm)) {
+ plotPlayer.sendMessage(TranslatableCaption.of("blockedcmds.command_blocked"));
+ event.setCancelled(true);
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPreLogin(final AsyncPlayerPreLoginEvent event) {
+ final UUID uuid;
+ if (Settings.UUID.OFFLINE) {
+ if (Settings.UUID.FORCE_LOWERCASE) {
+ uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + event.getName().toLowerCase()).getBytes(Charsets.UTF_8));
+ } else {
+ uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + event.getName()).getBytes(Charsets.UTF_8));
+ }
+ } else {
+ uuid = event.getUniqueId();
+ }
+ PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), uuid);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onConnect(PlayerJoinEvent event) {
+ final Player player = event.getPlayer();
+ PlotSquared.platform().getPlayerManager().removePlayer(player.getUniqueId());
+ final PlotPlayer pp = BukkitUtil.adapt(player);
+
+ Location location = pp.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (area != null) {
+ Plot plot = area.getPlot(location);
+ if (plot != null) {
+ plotEntry(pp, plot);
+ }
+ }
+ // Delayed
+
+ // Async
+ TaskManager.runTaskLaterAsync(() -> {
+ if (!player.hasPlayedBefore() && player.isOnline()) {
+ player.saveData();
+ }
+ this.eventDispatcher.doJoinTask(pp);
+ }, TaskTime.seconds(1L));
+
+ if (pp.hasPermission(Permission.PERMISSION_ADMIN_UPDATE_NOTIFICATION.toString()) && Settings.Enabled_Components.UPDATE_NOTIFICATIONS
+ && PremiumVerification.isPremium() && UpdateUtility.hasUpdate) {
+ Caption boundary = TranslatableCaption.of("update.update_boundary");
+ Caption updateNotification = TranslatableCaption.of("update.update_notification");
+ Template internalVersion = Template.of("p2version", String.valueOf(UpdateUtility.internalVersion.versionString()));
+ Template spigotVersion = Template.of("spigotversion", UpdateUtility.spigotVersion);
+ Template downloadUrl = Template.of("downloadurl", "https://www.spigotmc.org/resources/77506/updates");
+ pp.sendMessage(boundary);
+ pp.sendMessage(updateNotification, internalVersion, spigotVersion, downloadUrl);
+ pp.sendMessage(boundary);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void playerRespawn(PlayerRespawnEvent event) {
+ Player player = event.getPlayer();
+ PlotPlayer pp = BukkitUtil.adapt(player);
+ this.eventDispatcher.doRespawnTask(pp);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onTeleport(PlayerTeleportEvent event) {
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ try (final MetaDataAccess lastPlotAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
+ Plot lastPlot = lastPlotAccess.get().orElse(null);
+ org.bukkit.Location to = event.getTo();
+ //noinspection ConstantConditions
+ if (to != null) {
+ Location location = BukkitUtil.adapt(to);
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ if (lastPlot != null) {
+ plotExit(pp, lastPlot);
+ lastPlotAccess.remove();
+ }
+ try (final MetaDataAccess lastLocationAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
+ lastLocationAccess.remove();
+ }
+ return;
+ }
+ Plot plot = area.getPlot(location);
+ if (plot != null) {
+ final boolean result = DenyTeleportFlag.allowsTeleport(pp, plot);
+ // there is one possibility to still allow teleportation:
+ // to is identical to the plot's home location, and untrusted-visit is true
+ // i.e. untrusted-visit can override deny-teleport
+ // this is acceptable, because otherwise it wouldn't make sense to have both flags set
+ if (!result && !(plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous().equals(BukkitUtil.adaptComplete(to)))) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.entry.denied")
+ );
+ event.setCancelled(true);}
+ }
+ }
+ }
+ playerMove(event);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void vehicleMove(VehicleMoveEvent event)
+ throws IllegalAccessException {
+ final org.bukkit.Location from = event.getFrom();
+ final org.bukkit.Location to = event.getTo();
+
+ int toX, toZ;
+ if ((toX = MathMan.roundInt(to.getX())) != MathMan.roundInt(from.getX()) | (toZ = MathMan.roundInt(to.getZ())) != MathMan
+ .roundInt(from.getZ())) {
+ Vehicle vehicle = event.getVehicle();
+
+ // Check allowed
+ if (!vehicle.getPassengers().isEmpty()) {
+ Entity passenger = vehicle.getPassengers().get(0);
+
+ if (passenger instanceof Player) {
+ final Player player = (Player) passenger;
+ // reset
+ if (moveTmp == null) {
+ moveTmp = new PlayerMoveEvent(null, from, to);
+ }
+ moveTmp.setFrom(from);
+ moveTmp.setTo(to);
+ moveTmp.setCancelled(false);
+ fieldPlayer.set(moveTmp, player);
+
+ List passengers = vehicle.getPassengers();
+
+ this.playerMove(moveTmp);
+ org.bukkit.Location dest;
+ if (moveTmp.isCancelled()) {
+ dest = from;
+ } else if (MathMan.roundInt(moveTmp.getTo().getX()) != toX || MathMan.roundInt(moveTmp.getTo().getZ()) != toZ) {
+ dest = to;
+ } else {
+ dest = null;
+ }
+ if (dest != null) {
+ vehicle.eject();
+ vehicle.setVelocity(new Vector(0d, 0d, 0d));
+ PaperLib.teleportAsync(vehicle, dest);
+ passengers.forEach(vehicle::addPassenger);
+ return;
+ }
+ }
+ if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
+ final com.sk89q.worldedit.world.entity.EntityType entityType = BukkitAdapter.adapt(vehicle.getType());
+ // Horses etc are vehicles, but they're also animals
+ // so this filters out all living entities
+ if (EntityCategories.VEHICLE.contains(entityType) && !EntityCategories.ANIMAL.contains(entityType)) {
+ List meta = vehicle.getMetadata("plot");
+ Plot toPlot = BukkitUtil.adapt(to).getPlot();
+ if (!meta.isEmpty()) {
+ Plot origin = (Plot) meta.get(0).value();
+ if (origin != null && !origin.getBasePlot(false).equals(toPlot)) {
+ vehicle.remove();
+ }
+ } else if (toPlot != null) {
+ vehicle.setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.platform(), toPlot));
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void playerMove(PlayerMoveEvent event) {
+ org.bukkit.Location from = event.getFrom();
+ org.bukkit.Location to = event.getTo();
+ int x2;
+ if (MathMan.roundInt(from.getX()) != (x2 = MathMan.roundInt(to.getX()))) {
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ // Cancel teleport
+ if (TaskManager.removeFromTeleportQueue(pp.getName())) {
+ pp.sendMessage(TranslatableCaption.of("teleport.teleport_failed"));
+ }
+ // Set last location
+ Location location = BukkitUtil.adapt(to);
+ try (final MetaDataAccess lastLocationAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
+ lastLocationAccess.remove();
+ }
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ try (final MetaDataAccess lastPlotAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
+ lastPlotAccess.remove();
+ }
+ return;
+ }
+ Plot now = area.getPlot(location);
+ Plot lastPlot;
+ try (final MetaDataAccess lastPlotAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
+ lastPlot = lastPlotAccess.get().orElse(null);
+ }
+ if (now == null) {
+ try (final MetaDataAccess kickAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) {
+ if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse(false)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.exit.denied")
+ );
+ this.tmpTeleport = false;
+ if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) {
+ player.teleport(from);
+ } else {
+ player.teleport(player.getWorld().getSpawnLocation());
+ }
+ this.tmpTeleport = true;
+ event.setCancelled(true);
+ return;}
+ }
+ } else if (now.equals(lastPlot)) {
+ ForceFieldListener.handleForcefield(player, pp, now);
+ } else if (!plotEntry(pp, now) && this.tmpTeleport) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.entry.denied")
+ );
+ this.tmpTeleport = false;
+ to.setX(from.getBlockX());
+ to.setY(from.getBlockY());
+ to.setZ(from.getBlockZ());
+ player.teleport(event.getTo());
+ this.tmpTeleport = true;
+ return;
+ }
+ int border = area.getBorder();
+ if (x2 > border && this.tmpTeleport) {
+ to.setX(border - 1);
+ this.tmpTeleport = false;
+ player.teleport(event.getTo());
+ this.tmpTeleport = true;
+ pp.sendMessage(TranslatableCaption.of("border.border"));
+ }
+ if (x2 < -border && this.tmpTeleport) {
+ to.setX(-border + 1);
+ this.tmpTeleport = false;
+ player.teleport(event.getTo());
+ this.tmpTeleport = true;
+ pp.sendMessage(TranslatableCaption.of("border.border"));
+ }
+ }
+ int z2;
+ if (MathMan.roundInt(from.getZ()) != (z2 = MathMan.roundInt(to.getZ()))) {
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ // Cancel teleport
+ if (TaskManager.removeFromTeleportQueue(pp.getName())) {
+ pp.sendMessage(TranslatableCaption.of("teleport.teleport_failed"));
+ }
+ // Set last location
+ Location location = BukkitUtil.adapt(to);
+ try (final MetaDataAccess lastLocationAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
+ lastLocationAccess.set(location);
+ }
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ try (final MetaDataAccess lastPlotAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
+ lastPlotAccess.remove();
+ }
+ return;
+ }
+ Plot now = area.getPlot(location);
+ Plot lastPlot;
+ try (final MetaDataAccess lastPlotAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
+ lastPlot = lastPlotAccess.get().orElse(null);
+ }
+ if (now == null) {
+ try (final MetaDataAccess kickAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) {
+ if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse(false)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.exit.denied")
+ );
+ this.tmpTeleport = false;
+ if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) {
+ player.teleport(from);
+ } else {
+ player.teleport(player.getWorld().getSpawnLocation());
+ }
+ this.tmpTeleport = true;
+ event.setCancelled(true);
+ return;}
+ }
+ } else if (now.equals(lastPlot)) {
+ ForceFieldListener.handleForcefield(player, pp, now);
+ } else if (!plotEntry(pp, now) && this.tmpTeleport) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.entry.denied")
+ );
+ this.tmpTeleport = false;
+ player.teleport(from);
+ to.setX(from.getBlockX());
+ to.setY(from.getBlockY());
+ to.setZ(from.getBlockZ());
+ player.teleport(event.getTo());
+ this.tmpTeleport = true;
+ return;
+ }
+ int border = area.getBorder();
+ if (z2 > border && this.tmpTeleport) {
+ to.setZ(border - 1);
+ this.tmpTeleport = false;
+ player.teleport(event.getTo());
+ this.tmpTeleport = true;
+ pp.sendMessage(TranslatableCaption.of("border.border"));
+ } else if (z2 < -border && this.tmpTeleport) {
+ to.setZ(-border + 1);
+ this.tmpTeleport = false;
+ player.teleport(event.getTo());
+ this.tmpTeleport = true;
+ pp.sendMessage(TranslatableCaption.of("border.border"));
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW) public void onChat(AsyncPlayerChatEvent event) {
+ if (event.isCancelled()) {
+ return;
+ }
+
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(event.getPlayer());
+ Location location = plotPlayer.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getPlot(location);
+ if (plot == null) {
+ return;
+ }
+ if (!((plot.getFlag(ChatFlag.class) && area.isPlotChat() && plotPlayer.getAttribute("chat"))
+ || area.isForcingPlotChat())) {
+ return;
+ }
+ if (plot.isDenied(plotPlayer.getUUID()) && !Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_CHAT_BYPASS)) {
+ return;
+ }
+ event.setCancelled(true);
+ Set recipients = event.getRecipients();
+ recipients.clear();
+ Set> spies = new HashSet<>();
+ Set> plotRecipients = new HashSet<>();
+ for (final PlotPlayer> pp : PlotSquared.platform().getPlayerManager().getPlayers()) {
+ if (pp.getAttribute("chatspy")) {
+ spies.add(pp);
+ } else {
+ Plot current = pp.getCurrentPlot();
+ if (current != null && current.getBasePlot(false).equals(plot)) {
+ plotRecipients.add(pp);
+ }
+ }
+ }
+ String message = event.getMessage();
+ String sender = event.getPlayer().getDisplayName();
+ PlotId id = plot.getId();
+ Caption msg = TranslatableCaption.of("chat.plot_chat_format");
+ Template msgTemplate;
+ Template plotTemplate = Template.of("plot_id", id.toString());
+ Template senderTemplate = Template.of("sender", sender);
+ // If we do/don't want colour, we need to be careful about how to go about it, as players could attempt either or &6 etc.
+ // In both cases, we want to use a Component Template to ensure that the player cannot use any placeholders in their message on purpose
+ // or accidentally, as component templates are done at the end. We also need to deserialize from legacy color codes to a Component if
+ // allowing colour.
+ if (plotPlayer.hasPermission("plots.chat.color")) {
+ msgTemplate = Template
+ .of("msg", BukkitUtil.LEGACY_COMPONENT_SERIALIZER.deserialize(ChatColor.translateAlternateColorCodes('&', message)));
+ } else {
+ msgTemplate = Template.of("msg", BukkitUtil.MINI_MESSAGE.deserialize(
+ ChatColor.stripColor(BukkitUtil.LEGACY_COMPONENT_SERIALIZER.serialize(TextComponent.builder(message).build()))));
+ }
+ for (PlotPlayer> receiver : plotRecipients) {
+ receiver.sendMessage(msg, msgTemplate, plotTemplate, senderTemplate);
+ }
+ if (!spies.isEmpty()) {
+ Caption spymsg = TranslatableCaption.of("chat.plot_chat_spy_format");
+ Template plotidTemplate = Template.of("plot_id", id.getX() + ";" + id.getY());
+ Template spysenderTemplate = Template.of("sender", sender);
+ Template spymessageTemplate = Template.of("msg", TextComponent.builder(message).build());
+ for (PlotPlayer> player : spies) {
+ player.sendMessage(spymsg, plotidTemplate, spysenderTemplate, spymessageTemplate);
+ }
+ }
+ // TODO: Re-implement
+ // PlotSquared.debug(full);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onWorldChanged(PlayerChangedWorldEvent event) {
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ // Delete last location
+ Plot plot;
+ try (final MetaDataAccess lastPlotAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
+ plot = lastPlotAccess.remove();
+ }
+ try (final MetaDataAccess lastLocationAccess =
+ pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
+ lastLocationAccess.remove();
+ }
+ if (plot != null) {
+ plotExit(pp, plot);
+ }
+ if (this.worldEdit != null) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_WORLDEDIT_BYPASS)) {
+ if (pp.getAttribute("worldedit")) {
+ pp.removeAttribute("worldedit");
+ }
+ }
+ }
+ Location location = pp.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (location.isPlotArea()) {
+ plot = location.getPlot();
+ if (plot != null) {
+ plotEntry(pp, plot);
+ }
+ }
+ }
+
+ @SuppressWarnings("deprecation") @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onInventoryClick(InventoryClickEvent event) {
+ /*if (!event.isLeftClick() || (event.getAction() != InventoryAction.PLACE_ALL) || event
+ .isShiftClick()) {
+ return;
+ }*/
+ HumanEntity entity = event.getWhoClicked();
+ if (!(entity instanceof Player) || !this.plotAreaManager
+ .hasPlotArea(entity.getWorld().getName())) {
+ return;
+ }
+
+ HumanEntity clicker = event.getWhoClicked();
+ if (!(clicker instanceof Player)) {
+ return;
+ }
+ Player player = (Player) clicker;
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ final PlotInventory inventory = PlotInventory.getOpenPlotInventory(pp);
+ if (inventory != null && event.getRawSlot() == event.getSlot()) {
+ if (!inventory.onClick(event.getSlot())) {
+ event.setResult(Event.Result.DENY);
+ event.setCancelled(true);
+ inventory.close();
+ }
+ }
+ PlayerInventory inv = player.getInventory();
+ int slot = inv.getHeldItemSlot();
+ if ((slot > 8) || !event.getEventName().equals("InventoryCreativeEvent")) {
+ return;
+ }
+ ItemStack current = inv.getItemInHand();
+ ItemStack newItem = event.getCursor();
+ ItemMeta newMeta = newItem.getItemMeta();
+ ItemMeta oldMeta = newItem.getItemMeta();
+
+ if (event.getClick() == ClickType.CREATIVE) {
+ final Plot plot = pp.getCurrentPlot();
+ if (plot != null) {
+ if (plot.getFlag(PreventCreativeCopyFlag.class) && !plot
+ .isAdded(player.getUniqueId()) && !Permissions
+ .hasPermission(pp, Permission.PERMISSION_ADMIN_INTERACT_OTHER)) {
+ final ItemStack newStack =
+ new ItemStack(newItem.getType(), newItem.getAmount());
+ event.setCursor(newStack);
+ plot.debug(player.getName()
+ + " could not creative-copy an item because prevent-creative-copy = true");
+ }
+ } else {
+ PlotArea area = pp.getPlotAreaAbs();
+ if (area != null && area.isRoadFlags() && area
+ .getRoadFlag(PreventCreativeCopyFlag.class)) {
+ final ItemStack newStack =
+ new ItemStack(newItem.getType(), newItem.getAmount());
+ event.setCursor(newStack);
+ }
+ }
+ return;
+ }
+
+ String newLore = "";
+ if (newMeta != null) {
+ List lore = newMeta.getLore();
+ if (lore != null) {
+ newLore = lore.toString();
+ }
+ }
+ String oldLore = "";
+ if (oldMeta != null) {
+ List lore = oldMeta.getLore();
+ if (lore != null) {
+ oldLore = lore.toString();
+ }
+ }
+ if (!"[(+NBT)]".equals(newLore) || (current.equals(newItem) && newLore.equals(oldLore))) {
+ switch (newItem.getType()) {
+ case LEGACY_BANNER:
+ case PLAYER_HEAD:
+ if (newMeta != null) {
+ break;
+ }
+ default:
+ return;
+ }
+ }
+ Block block = player.getTargetBlock(null, 7);
+ org.bukkit.block.BlockState state = block.getState();
+ Material stateType = state.getType();
+ Material itemType = newItem.getType();
+ if (stateType != itemType) {
+ switch (stateType) {
+ case LEGACY_STANDING_BANNER:
+ case LEGACY_WALL_BANNER:
+ if (itemType == Material.LEGACY_BANNER) {
+ break;
+ }
+ case LEGACY_SKULL:
+ if (itemType == Material.LEGACY_SKULL_ITEM) {
+ break;
+ }
+ default:
+ return;
+ }
+ }
+ Location location = BukkitUtil.adapt(state.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = area.getPlotAbs(location);
+ boolean cancelled = false;
+ if (plot == null) {
+ if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.road")
+ );
+ cancelled = true;
+ }
+ } else if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.unowned")
+ );
+ cancelled = true;
+ }
+ } else {
+ UUID uuid = pp.getUUID();
+ if (!plot.isAdded(uuid)) {
+ if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.other")
+ );
+ cancelled = true;
+ }
+ }
+ }
+ if (cancelled) {
+ if ((current.getType() == newItem.getType()) && (current.getDurability() == newItem
+ .getDurability())) {
+ event.setCursor(
+ new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability()));
+ event.setCancelled(true);
+ return;
+ }
+ event.setCursor(
+ new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability()));
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onInteract(PlayerInteractAtEntityEvent e) {
+ Entity entity = e.getRightClicked();
+ if (!(entity instanceof ArmorStand) && !(entity instanceof ItemFrame)) {
+ return;
+ }
+ Location location = BukkitUtil.adapt(e.getRightClicked().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ EntitySpawnListener.testNether(entity);
+ Plot plot = location.getPlotAbs();
+ BukkitPlayer pp = BukkitUtil.adapt(e.getPlayer());
+ if (plot == null) {
+ if (!area.isRoadFlags() && !area.getRoadFlag(MiscInteractFlag.class) && !Permissions
+ .hasPermission(pp, "plots.admin.interact.road")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.road")
+ );
+ e.setCancelled(true);
+ }
+ } else {
+ if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ e.setCancelled(true);
+ return;
+ }
+ }
+ if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.unowned")
+ );
+ e.setCancelled(true);
+ }
+ } else {
+ UUID uuid = pp.getUUID();
+ if (plot.isAdded(uuid)) {
+ return;
+ }
+ if (plot.getFlag(MiscInteractFlag.class)) {
+ return;
+ }
+ if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.other")
+ );
+ e.setCancelled(true);
+ plot.debug(pp.getName() + " could not interact with " + entity.getType()
+ + " because misc-interact = false");
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW) public void onCancelledInteract(PlayerInteractEvent event) {
+ if (event.isCancelled() && event.getAction() == Action.RIGHT_CLICK_AIR) {
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ PlotArea area = pp.getPlotAreaAbs();
+ if (area == null) {
+ return;
+ }
+ if (event.getAction() == Action.RIGHT_CLICK_AIR) {
+ Material item = event.getMaterial();
+ if (item.toString().toLowerCase().endsWith("_egg")) {
+ event.setCancelled(true);
+ event.setUseItemInHand(Event.Result.DENY);
+ }
+ }
+ ItemStack hand = player.getInventory().getItemInMainHand();
+ ItemStack offHand = player.getInventory().getItemInOffHand();
+ Material type = hand.getType();
+ Material offType = offHand.getType();
+ if (type == Material.AIR) {
+ type = offType;
+ }
+ if (type.toString().toLowerCase().endsWith("_egg")) {
+ Block block = player.getTargetBlockExact(5, FluidCollisionMode.SOURCE_ONLY);
+ if (block != null && block.getType() != Material.AIR) {
+ Location location = BukkitUtil.adapt(block.getLocation());
+ if (!this.eventDispatcher.checkPlayerBlockEvent(pp, PlayerBlockEventType.SPAWN_MOB, location, null, true)) {
+ event.setCancelled(true);
+ event.setUseItemInHand(Event.Result.DENY);
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onInteract(PlayerInteractEvent event) {
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ PlotArea area = pp.getPlotAreaAbs();
+ if (area == null) {
+ return;
+ }
+ PlayerBlockEventType eventType = null;
+ BlockType blocktype1;
+ Block block = event.getClickedBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ Action action = event.getAction();
+ outer:
+ switch (action) {
+ case PHYSICAL: {
+ eventType = PlayerBlockEventType.TRIGGER_PHYSICAL;
+ blocktype1 = BukkitAdapter.asBlockType(block.getType());
+ break;
+ }
+ //todo rearrange the right click code. it is all over the place.
+ case RIGHT_CLICK_BLOCK: {
+ Material blockType = block.getType();
+ eventType = PlayerBlockEventType.INTERACT_BLOCK;
+ blocktype1 = BukkitAdapter.asBlockType(block.getType());
+
+ if (blockType.isInteractable()) {
+ if (!player.isSneaking()) {
+ break;
+ }
+ ItemStack hand = player.getInventory().getItemInMainHand();
+ ItemStack offHand = player.getInventory().getItemInOffHand();
+
+ // sneaking players interact with blocks if both hands are empty
+ if (hand.getType() == Material.AIR && offHand.getType() == Material.AIR) {
+ break;
+ }
+ }
+
+ Material type = event.getMaterial();
+
+ // in the following, lb needs to have the material of the item in hand i.e. type
+ switch (type) {
+ case REDSTONE:
+ case STRING:
+ case PUMPKIN_SEEDS:
+ case MELON_SEEDS:
+ case COCOA_BEANS:
+ case WHEAT_SEEDS:
+ case BEETROOT_SEEDS:
+ case SWEET_BERRIES:
+ return;
+ default:
+ //eventType = PlayerBlockEventType.PLACE_BLOCK;
+ if (type.isBlock()) {
+ return;
+ }
+ }
+ if (PaperLib.isPaper()) {
+ if (MaterialTags.SPAWN_EGGS.isTagged(type) || Material.EGG.equals(type)) {
+ eventType = PlayerBlockEventType.SPAWN_MOB;
+ break outer;
+ }
+ } else {
+ if (type.toString().toLowerCase().endsWith("egg")) {
+ eventType = PlayerBlockEventType.SPAWN_MOB;
+ break outer;
+ }
+ }
+ if (type.isEdible()) {
+ //Allow all players to eat while also allowing the block place event ot be fired
+ return;
+ }
+ switch (type) {
+ case ACACIA_BOAT:
+ case BIRCH_BOAT:
+ case CHEST_MINECART:
+ case COMMAND_BLOCK_MINECART:
+ case DARK_OAK_BOAT:
+ case FURNACE_MINECART:
+ case HOPPER_MINECART:
+ case JUNGLE_BOAT:
+ case MINECART:
+ case OAK_BOAT:
+ case SPRUCE_BOAT:
+ case TNT_MINECART:
+ eventType = PlayerBlockEventType.PLACE_VEHICLE;
+ break outer;
+ case FIREWORK_ROCKET:
+ case FIREWORK_STAR:
+ eventType = PlayerBlockEventType.SPAWN_MOB;
+ break outer;
+ case BOOK:
+ case KNOWLEDGE_BOOK:
+ case WRITABLE_BOOK:
+ case WRITTEN_BOOK:
+ eventType = PlayerBlockEventType.READ;
+ break outer;
+ case ARMOR_STAND:
+ location = BukkitUtil.adapt(block.getRelative(event.getBlockFace()).getLocation());
+ eventType = PlayerBlockEventType.PLACE_MISC;
+ break outer;
+ }
+ break;
+ }
+ case LEFT_CLICK_BLOCK: {
+ location = BukkitUtil.adapt(block.getLocation());
+ //eventType = PlayerBlockEventType.BREAK_BLOCK;
+ blocktype1 = BukkitAdapter.asBlockType(block.getType());
+ if (block.getType() == Material.DRAGON_EGG) {
+ eventType = PlayerBlockEventType.TELEPORT_OBJECT;
+ break;
+ }
+
+ return;
+ }
+ default:
+ return;
+ }
+ if (this.worldEdit != null && pp.getAttribute("worldedit")) {
+ if (event.getMaterial() == Material.getMaterial(this.worldEdit.getConfiguration().wandItem)) {
+ return;
+ }
+ }
+ if (!this.eventDispatcher.checkPlayerBlockEvent(pp, eventType, location, blocktype1, true)) {
+ event.setCancelled(true);
+ event.setUseInteractedBlock(Event.Result.DENY);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onBucketEmpty(PlayerBucketEmptyEvent event) {
+ BlockFace bf = event.getBlockFace();
+ Block block =
+ event.getBlockClicked().getLocation().add(bf.getModX(), bf.getModY(), bf.getModZ())
+ .getBlock();
+ Location location = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ BukkitPlayer pp = BukkitUtil.adapt(event.getPlayer());
+ Plot plot = area.getPlot(location);
+ if (plot == null) {
+ if (Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_ROAD)) {
+ return;
+ }
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.road")
+ );
+ event.setCancelled(true);
+ } else if (!plot.hasOwner()) {
+ if (Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) {
+ return;
+ }
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.unowned")
+ );
+ event.setCancelled(true);
+ } else if (!plot.isAdded(pp.getUUID())) {
+ List use = plot.getFlag(UseFlag.class);
+ final BlockType blockType = BukkitAdapter.asBlockType(block.getType());
+ for (final BlockTypeWrapper blockTypeWrapper : use) {
+ if (blockTypeWrapper.accepts(blockType)) {
+ return;
+ }
+ }
+ if (Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ return;
+ }
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ } else if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST) public void onInventoryClose(InventoryCloseEvent event) {
+ HumanEntity closer = event.getPlayer();
+ if (!(closer instanceof Player)) {
+ return;
+ }
+ Player player = (Player) closer;
+ PlotInventory.removePlotInventoryOpen(BukkitUtil.adapt(player));
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR) public void onLeave(PlayerQuitEvent event) {
+ TaskManager.removeFromTeleportQueue(event.getPlayer().getName());
+ BukkitPlayer pp = BukkitUtil.adapt(event.getPlayer());
+ pp.unregister();
+ this.logout(pp.getUUID());
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onBucketFill(PlayerBucketFillEvent event) {
+ Block blockClicked = event.getBlockClicked();
+ Location location = BukkitUtil.adapt(blockClicked.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Player player = event.getPlayer();
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ Plot plot = area.getPlot(location);
+ if (plot == null) {
+ if (Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_ROAD)) {
+ return;
+ }
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.road")
+ );
+ event.setCancelled(true);
+ } else if (!plot.hasOwner()) {
+ if (Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) {
+ return;
+ }
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.unowned")
+ );
+ event.setCancelled(true);
+ } else if (!plot.isAdded(plotPlayer.getUUID())) {
+ List use = plot.getFlag(UseFlag.class);
+ Block block = event.getBlockClicked();
+ final BlockType blockType = BukkitAdapter.asBlockType(block.getType());
+ for (final BlockTypeWrapper blockTypeWrapper : use) {
+ if (blockTypeWrapper.accepts(blockType)) {
+ return;
+ }
+ }
+ if (Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ return;
+ }
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ } else if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
+ if (!Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onHangingPlace(HangingPlaceEvent event) {
+ Block block = event.getBlock().getRelative(event.getBlockFace());
+ Location location = BukkitUtil.adapt(block.getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Player p = event.getPlayer();
+ if (p == null) {
+ event.setCancelled(true);
+ return;
+ }
+ BukkitPlayer pp = BukkitUtil.adapt(p);
+ Plot plot = area.getPlot(location);
+ if (plot == null) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_ROAD)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.road")
+ );
+ event.setCancelled(true);
+ }
+ } else {
+ if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_UNOWNED)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.unwoned")
+ );
+ event.setCancelled(true);
+ }
+ return;
+ }
+ if (!plot.isAdded(pp.getUUID())) {
+ if (!plot.getFlag(HangingPlaceFlag.class)) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ event.setCancelled(true);
+ }
+ return;
+ }
+ }
+ if (BukkitEntityUtil.checkEntity(event.getEntity(), plot)) {
+ event.setCancelled(true);
+ }
+
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onHangingBreakByEntity(HangingBreakByEntityEvent event) {
+ Entity remover = event.getRemover();
+ if (remover instanceof Player) {
+ Player p = (Player) remover;
+ Location location = BukkitUtil.adapt(event.getEntity().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ BukkitPlayer pp = BukkitUtil.adapt(p);
+ Plot plot = area.getPlot(location);
+ if (plot == null) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_DESTROY_ROAD)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.road")
+ );
+ event.setCancelled(true);
+ }
+ } else if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_DESTROY_UNOWNED)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.unowned")
+ );
+ event.setCancelled(true);
+ }
+ } else if (!plot.isAdded(pp.getUUID())) {
+ if (plot.getFlag(HangingBreakFlag.class)) {
+ return;
+ }
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_DESTROY_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.other")
+ );
+ event.setCancelled(true);
+ plot.debug(p.getName()
+ + " could not break hanging entity because hanging-break = false");
+ }
+ }
+ } else if (remover instanceof Projectile) {
+ Projectile p = (Projectile) remover;
+ if (p.getShooter() instanceof Player) {
+ Player shooter = (Player) p.getShooter();
+ Location location = BukkitUtil.adapt(event.getEntity().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ BukkitPlayer player = BukkitUtil.adapt(shooter);
+ Plot plot = area.getPlot(BukkitUtil.adapt(event.getEntity().getLocation()));
+ if (plot != null) {
+ if (!plot.hasOwner()) {
+ if (!Permissions
+ .hasPermission(player, Permission.PERMISSION_ADMIN_DESTROY_UNOWNED)) {
+ player.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.unowned")
+ );
+ event.setCancelled(true);
+ }
+ } else if (!plot.isAdded(player.getUUID())) {
+ if (!plot.getFlag(HangingBreakFlag.class)) {
+ if (!Permissions
+ .hasPermission(player, Permission.PERMISSION_ADMIN_DESTROY_OTHER)) {
+ player.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy.other")
+ );
+ event.setCancelled(true);
+ plot.debug(player.getName()
+ + " could not break hanging entity because hanging-break = false");
+ }
+ }
+ }
+ }
+ }
+ } else {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
+ Location location = BukkitUtil.adapt(event.getRightClicked().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Player p = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(p);
+ Plot plot = area.getPlot(location);
+ if (plot == null && !area.isRoadFlags()) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_INTERACT_ROAD)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.road")
+ );
+ event.setCancelled(true);
+ }
+ } else if (plot != null && !plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_INTERACT_UNOWNED)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.unowned")
+ );
+ event.setCancelled(true);
+ }
+ } else if ((plot != null && !plot.isAdded(pp.getUUID())) || (plot == null && area
+ .isRoadFlags())) {
+ final Entity entity = event.getRightClicked();
+ final com.sk89q.worldedit.world.entity.EntityType entityType =
+ BukkitAdapter.adapt(entity.getType());
+
+ FlagContainer flagContainer;
+ if (plot == null) {
+ flagContainer = area.getRoadFlagContainer();
+ } else {
+ flagContainer = plot.getFlagContainer();
+ }
+
+ if (EntityCategories.HOSTILE.contains(entityType) && flagContainer
+ .getFlag(HostileInteractFlag.class).getValue()) {
+ return;
+ }
+
+ if (EntityCategories.ANIMAL.contains(entityType) && flagContainer
+ .getFlag(AnimalInteractFlag.class).getValue()) {
+ return;
+ }
+
+ // This actually makes use of the interface, so we don't use the
+ // category
+ if (entity instanceof Tameable && ((Tameable) entity).isTamed() && flagContainer
+ .getFlag(TamedInteractFlag.class).getValue()) {
+ return;
+ }
+
+ if (EntityCategories.VEHICLE.contains(entityType) && flagContainer
+ .getFlag(VehicleUseFlag.class).getValue()) {
+ return;
+ }
+
+ if (EntityCategories.PLAYER.contains(entityType) && flagContainer
+ .getFlag(PlayerInteractFlag.class).getValue()) {
+ return;
+ }
+
+ if (EntityCategories.VILLAGER.contains(entityType) && flagContainer
+ .getFlag(VillagerInteractFlag.class).getValue()) {
+ return;
+ }
+
+ if ((EntityCategories.HANGING.contains(entityType) || EntityCategories.OTHER
+ .contains(entityType)) && flagContainer.getFlag(MiscInteractFlag.class)
+ .getValue()) {
+ return;
+ }
+
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_INTERACT_OTHER)) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.interact.other")
+ );
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onVehicleDestroy(VehicleDestroyEvent event) {
+ Location location = BukkitUtil.adapt(event.getVehicle().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Entity attacker = event.getAttacker();
+ if (attacker instanceof Player) {
+ Player p = (Player) attacker;
+ BukkitPlayer pp = BukkitUtil.adapt(p);
+ Plot plot = area.getPlot(location);
+ if (plot == null) {
+ if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.road")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.vehicle.break.road")
+ );
+ event.setCancelled(true);
+ }
+ } else {
+ if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.unowned")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.vehicle.break.unowned")
+ );
+ event.setCancelled(true);
+ return;
+ }
+ return;
+ }
+ if (!plot.isAdded(pp.getUUID())) {
+ if (plot.getFlag(VehicleBreakFlag.class)) {
+ return;
+ }
+ if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.other")) {
+ pp.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.vehicle.break.other")
+ );
+ event.setCancelled(true);
+ plot.debug(pp.getName()
+ + " could not break vehicle because vehicle-break = false");
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onPlayerEggThrow(PlayerEggThrowEvent event) {
+ Location location = BukkitUtil.adapt(event.getEgg().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Player player = event.getPlayer();
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+ Plot plot = area.getPlot(location);
+ if (plot == null) {
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.road")) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.projectile.road")
+ );
+ event.setHatching(false);
+ }
+ } else if (!plot.hasOwner()) {
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.unowned")) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.projective.unowned")
+ );
+ event.setHatching(false);
+ }
+ } else if (!plot.isAdded(plotPlayer.getUUID())) {
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.other")) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.projectile.other")
+ );
+ event.setHatching(false);
+ }
+ }
+ }
+
+ @EventHandler public void onItemDrop(PlayerDropItemEvent event) {
+ Player player = event.getPlayer();
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ Location location = pp.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
+ if (plot == null) {
+ if (area.isRoadFlags() && !area.getRoadFlag(ItemDropFlag.class)) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ UUID uuid = pp.getUUID();
+ if (!plot.isAdded(uuid)) {
+ if (!plot.getFlag(ItemDropFlag.class)) {
+ plot.debug(player.getName() + " could not drop item because of item-drop = false");
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler public void onItemPickup(EntityPickupItemEvent event) {
+ LivingEntity ent = event.getEntity();
+ if (ent instanceof Player) {
+ Player player = (Player) ent;
+ BukkitPlayer pp = BukkitUtil.adapt(player);
+ Location location = pp.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
+ if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(DropProtectionFlag.class)) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ UUID uuid = pp.getUUID();
+ if (!plot.isAdded(uuid) && plot.getFlag(DropProtectionFlag.class)) {
+ plot.debug(player.getName() + " could not pick up item because of drop-protection = true");
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler public void onDeath(final PlayerDeathEvent event) {
+ Location location = BukkitUtil.adapt(event.getEntity().getLocation());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
+ if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(KeepInventoryFlag.class)) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ if (plot.getFlag(KeepInventoryFlag.class)) {
+ if (plot.getFlag(KeepInventoryFlag.class)) {
+ plot.debug(event.getEntity().getName() + " kept their inventory because of keep-inventory = true");
+ event.setKeepInventory(true);
+ }
+ }
+ }
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ProjectileEventListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ProjectileEventListener.java
new file mode 100644
index 000000000..4f16b390a
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ProjectileEventListener.java
@@ -0,0 +1,163 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.listener;
+
+import com.plotsquared.bukkit.util.BukkitEntityUtil;
+import com.plotsquared.bukkit.util.BukkitUtil;
+import com.plotsquared.core.location.Location;
+import com.plotsquared.core.permissions.Permission;
+import com.plotsquared.core.player.PlotPlayer;
+import com.plotsquared.core.plot.Plot;
+import com.plotsquared.core.plot.PlotArea;
+import com.plotsquared.core.plot.PlotHandler;
+import com.plotsquared.core.plot.world.PlotAreaManager;
+import com.plotsquared.core.util.Permissions;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.entity.ThrownPotion;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.LingeringPotionSplashEvent;
+import org.bukkit.event.entity.PotionSplashEvent;
+import org.bukkit.event.entity.ProjectileHitEvent;
+import org.bukkit.event.entity.ProjectileLaunchEvent;
+import org.bukkit.projectiles.BlockProjectileSource;
+import org.bukkit.projectiles.ProjectileSource;
+
+import javax.annotation.Nonnull;
+import javax.inject.Inject;
+
+@SuppressWarnings("unused")
+public class ProjectileEventListener implements Listener {
+
+ private final PlotAreaManager plotAreaManager;
+
+ @Inject public ProjectileEventListener(@Nonnull final PlotAreaManager plotAreaManager) {
+ this.plotAreaManager = plotAreaManager;
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPotionSplash(LingeringPotionSplashEvent event) {
+ Projectile entity = event.getEntity();
+ Location location = BukkitUtil.adapt(entity.getLocation());
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return;
+ }
+ if (!this.onProjectileHit(event)) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPotionSplash(PotionSplashEvent event) {
+ ThrownPotion damager = event.getPotion();
+ Location location = BukkitUtil.adapt(damager.getLocation());
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return;
+ }
+ int count = 0;
+ for (LivingEntity victim : event.getAffectedEntities()) {
+ if (!BukkitEntityUtil.entityDamage(damager, victim)) {
+ event.setIntensity(victim, 0);
+ count++;
+ }
+ }
+ if ((count > 0 && count == event.getAffectedEntities().size()) || !onProjectileHit(event)) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler public void onProjectileLaunch(ProjectileLaunchEvent event) {
+ Projectile entity = event.getEntity();
+ if (!(entity instanceof ThrownPotion)) {
+ return;
+ }
+ ProjectileSource shooter = entity.getShooter();
+ if (!(shooter instanceof Player)) {
+ return;
+ }
+ Location location = BukkitUtil.adapt(entity.getLocation());
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return;
+ }
+ PlotPlayer pp = BukkitUtil.adapt((Player) shooter);
+ Plot plot = location.getOwnedPlot();
+ if (plot != null && !plot.isAdded(pp.getUUID())) {
+ entity.remove();
+ event.setCancelled(true);
+ }
+ }
+
+ @SuppressWarnings({"BooleanMethodIsAlwaysInverted", "cos it's not... dum IntelliJ"}) @EventHandler
+ public boolean onProjectileHit(ProjectileHitEvent event) {
+ Projectile entity = event.getEntity();
+ Location location = BukkitUtil.adapt(entity.getLocation());
+ if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
+ return true;
+ }
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return true;
+ }
+ Plot plot = area.getPlot(location);
+ ProjectileSource shooter = entity.getShooter();
+ if (shooter instanceof Player) {
+ PlotPlayer> pp = BukkitUtil.adapt((Player) shooter);
+ if (plot == null) {
+ if (!Permissions.hasPermission(pp, Permission.PERMISSION_PROJECTILE_UNOWNED)) {
+ entity.remove();
+ return false;
+ }
+ return true;
+ }
+ if (plot.isAdded(pp.getUUID()) || Permissions
+ .hasPermission(pp, Permission.PERMISSION_PROJECTILE_OTHER)) {
+ return true;
+ }
+ entity.remove();
+ return false;
+ }
+ if (!(shooter instanceof Entity) && shooter != null) {
+ if (plot == null) {
+ entity.remove();
+ return false;
+ }
+ Location sLoc =
+ BukkitUtil.adapt(((BlockProjectileSource) shooter).getBlock().getLocation());
+ if (!area.contains(sLoc.getX(), sLoc.getZ())) {
+ entity.remove();
+ return false;
+ }
+ Plot sPlot = area.getOwnedPlotAbs(sLoc);
+ if (sPlot == null || !PlotHandler.sameOwners(plot, sPlot)) {
+ entity.remove();
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ServerListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ServerListener.java
new file mode 100644
index 000000000..ee824795e
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ServerListener.java
@@ -0,0 +1,52 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.listener;
+
+import com.plotsquared.bukkit.BukkitPlatform;
+import com.plotsquared.bukkit.placeholder.MVdWPlaceholders;
+import com.plotsquared.core.PlotSquared;
+import com.plotsquared.core.configuration.caption.TranslatableCaption;
+import com.plotsquared.core.player.ConsolePlayer;
+import org.bukkit.Bukkit;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.server.ServerLoadEvent;
+
+public class ServerListener implements Listener {
+
+ private final BukkitPlatform plugin;
+
+ public ServerListener(BukkitPlatform plugin) {
+ this.plugin = plugin;
+ }
+
+ @EventHandler public void onServerLoad(ServerLoadEvent event) {
+ if (Bukkit.getPluginManager().getPlugin("MVdWPlaceholderAPI") != null) {
+ new MVdWPlaceholders(this.plugin, PlotSquared.get().getPlaceholderRegistry());
+ ConsolePlayer.getConsole().sendMessage(TranslatableCaption.of("placeholder.hooked"));
+ }
+ }
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/MVdWPlaceholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/MVdWPlaceholders.java
new file mode 100644
index 000000000..66fcbf679
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/MVdWPlaceholders.java
@@ -0,0 +1,73 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.placeholder;
+
+import be.maximvdw.placeholderapi.PlaceholderAPI;
+import com.google.common.eventbus.Subscribe;
+import com.plotsquared.bukkit.util.BukkitUtil;
+import com.plotsquared.core.PlotSquared;
+import com.plotsquared.core.player.PlotPlayer;
+import com.plotsquared.core.util.placeholders.Placeholder;
+import com.plotsquared.core.util.placeholders.PlaceholderRegistry;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Placeholder support for MVdWPlaceholderAPI
+ */
+public class MVdWPlaceholders {
+
+ private static final String PREFIX = "plotsquared_";
+ private final Plugin plugin;
+ private final PlaceholderRegistry registry;
+
+ public MVdWPlaceholders(@Nonnull final Plugin plugin, @Nonnull final PlaceholderRegistry registry) {
+ this.plugin = plugin;
+ this.registry = registry;
+ for (final Placeholder placeholder : registry.getPlaceholders()) {
+ this.addPlaceholder(placeholder);
+ }
+ PlotSquared.get().getEventDispatcher().registerListener(this);
+ }
+
+ @Subscribe public void onNewPlaceholder(@Nonnull final PlaceholderRegistry.PlaceholderAddedEvent event) {
+ this.addPlaceholder(event.getPlaceholder());
+ }
+
+ private void addPlaceholder(@Nonnull final Placeholder placeholder) {
+ PlaceholderAPI.registerPlaceholder(plugin, PREFIX + String.format("%s", placeholder.getKey()), placeholderReplaceEvent -> {
+ if (!placeholderReplaceEvent.isOnline() || placeholderReplaceEvent.getPlayer() == null) {
+ return "";
+ }
+ final PlotPlayer player = BukkitUtil.adapt(placeholderReplaceEvent.getPlayer());
+ String key = placeholderReplaceEvent.getPlaceholder().substring(PREFIX.length());
+ return registry.getPlaceholderValue(key, player);
+ });
+ }
+
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/PAPIPlaceholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/PAPIPlaceholders.java
new file mode 100644
index 000000000..9a5ebdb82
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/PAPIPlaceholders.java
@@ -0,0 +1,89 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.placeholder;
+
+import com.plotsquared.core.PlotSquared;
+import com.plotsquared.core.player.PlotPlayer;
+import me.clip.placeholderapi.PlaceholderAPIPlugin;
+import me.clip.placeholderapi.expansion.PlaceholderExpansion;
+import org.bukkit.entity.Player;
+
+public class PAPIPlaceholders extends PlaceholderExpansion {
+
+ public PAPIPlaceholders() {
+ }
+
+ @Override public boolean persist() {
+ return true;
+ }
+
+ @Override public boolean canRegister() {
+ return true;
+ }
+
+ @Override public String getAuthor() {
+ return "IntellectualSites";
+ }
+
+ @Override public String getIdentifier() {
+ return "plotsquared";
+ }
+
+ @Override public String getVersion() {
+ return "3";
+ }
+
+ @Override public String onPlaceholderRequest(Player p, String identifier) {
+ final PlotPlayer> pl = PlotSquared.platform().getPlayerManager().getPlayerIfExists(p.getUniqueId());
+
+ if (pl == null) {
+ return "";
+ }
+
+ // PAPI specific ones that don't translate well over into other placeholder APIs
+ if (identifier.startsWith("has_plot_")) {
+ identifier = identifier.substring("has_plot_".length());
+ if (identifier.isEmpty())
+ return "";
+
+ return pl.getPlotCount(identifier) > 0 ?
+ PlaceholderAPIPlugin.booleanTrue() :
+ PlaceholderAPIPlugin.booleanFalse();
+ }
+
+ if (identifier.startsWith("plot_count_")) {
+ identifier = identifier.substring("plot_count_".length());
+ if (identifier.isEmpty())
+ return "";
+
+ return String.valueOf(pl.getPlotCount(identifier));
+ }
+
+ // PlotSquared placeholders
+ return PlotSquared.get().getPlaceholderRegistry().getPlaceholderValue(identifier, pl);
+ }
+
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java
deleted file mode 100644
index d79a7b4fb..000000000
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java
+++ /dev/null
@@ -1,213 +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 .
- */
-package com.plotsquared.bukkit.placeholder;
-
-import com.plotsquared.core.PlotSquared;
-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.PlayerManager;
-import me.clip.placeholderapi.PlaceholderAPIPlugin;
-import me.clip.placeholderapi.expansion.PlaceholderExpansion;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-
-import java.util.UUID;
-
-public class Placeholders extends PlaceholderExpansion {
-
- public Placeholders() {
- }
-
- @Override public boolean persist() {
- return true;
- }
-
- @Override public boolean canRegister() {
- return true;
- }
-
- @Override public String getAuthor() {
- return "NotMyFault";
- }
-
- @Override public String getIdentifier() {
- return "plotsquared";
- }
-
- @Override public String getVersion() {
- return "2.5";
- }
-
- @Override public String onPlaceholderRequest(Player p, String identifier) {
- final PlotPlayer pl = PlotSquared.platform().getPlayerManager().getPlayerIfExists(p.getUniqueId());
-
- if (pl == null) {
- return "";
- }
-
- if (identifier.startsWith("has_plot_")) {
- identifier = identifier.substring("has_plot_".length());
- if (identifier.isEmpty())
- return "";
-
- return pl.getPlotCount(identifier) > 0 ?
- PlaceholderAPIPlugin.booleanTrue() :
- PlaceholderAPIPlugin.booleanFalse();
- }
-
- if (identifier.startsWith("plot_count_")) {
- identifier = identifier.substring("plot_count_".length());
- if (identifier.isEmpty())
- return "";
-
- return String.valueOf(pl.getPlotCount(identifier));
- }
-
- switch (identifier) {
- case "currentplot_world": {
- return p.getWorld().getName();
- }
- case "has_plot": {
- return (pl.getPlotCount() > 0) ?
- PlaceholderAPIPlugin.booleanTrue() :
- PlaceholderAPIPlugin.booleanFalse();
- }
- case "allowed_plot_count": {
- return String.valueOf(pl.getAllowedPlots());
- }
- case "plot_count": {
- return String.valueOf(pl.getPlotCount());
- }
- }
-
- Plot plot = pl.getCurrentPlot();
-
- if (plot == null) {
- return "";
- }
-
- switch (identifier) {
- case "currentplot_alias": {
- return plot.getAlias();
- }
- case "currentplot_owner": {
- final UUID plotOwner = plot.getOwnerAbs();
- if (plotOwner == null) {
- return "";
- }
-
- try {
- return PlayerManager.getName(plotOwner, false);
- } catch (final Exception ignored) {}
-
- final String name = Bukkit.getOfflinePlayer(plotOwner).getName();
- return name != null ? name : "unknown";
- }
- case "currentplot_members": {
- if (plot.getMembers() == null && plot.getTrusted() == null) {
- return "0";
- }
- return String.valueOf(plot.getMembers().size() + plot.getTrusted().size());
- }
- case "currentplot_members_added": {
- if (plot.getMembers() == null) {
- return "0";
- }
- return String.valueOf(plot.getMembers().size());
- }
- case "currentplot_members_trusted": {
- if (plot.getTrusted() == null) {
- return "0";
- }
- return String.valueOf(plot.getTrusted().size());
- }
- case "currentplot_members_denied": {
- if (plot.getDenied() == null) {
- return "0";
- }
- return String.valueOf(plot.getDenied().size());
- }
- case "has_build_rights": {
- return plot.isAdded(pl.getUUID()) ?
- PlaceholderAPIPlugin.booleanTrue() :
- PlaceholderAPIPlugin.booleanFalse();
- }
- case "currentplot_x": {
- return String.valueOf(plot.getId().getX());
- }
- case "currentplot_y": {
- return String.valueOf(plot.getId().getY());
- }
- case "currentplot_xy": {
- return plot.getId().getX() + ";" + plot.getId().getY();
- }
- case "currentplot_rating": {
- return String.valueOf(plot.getAverageRating());
- }
- case "currentplot_biome": {
- return plot.getBiomeSynchronous() + "";
- }
- default:
- break;
- }
- if (identifier.startsWith("currentplot_localflag_")) {
- return getFlagValue(plot, identifier.substring("currentplot_localflag_".length()),
- false);
- }
- if (identifier.startsWith("currentplot_flag_")) {
- return getFlagValue(plot, identifier.substring("currentplot_flag_".length()), true);
- }
- return "";
- }
-
- /**
- * 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 currentplot or also inherited flag
- * @return The value of flag serialized in string
- */
- private String getFlagValue(final Plot plot, 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() : "";
- }
- }
-}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java
index 86ccc7fc0..4f526bc11 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java
@@ -73,10 +73,7 @@ public class BukkitPlayer extends PlotPlayer {
private static boolean CHECK_EFFECTIVE = true;
public final Player player;
- private final EconHandler econHandler;
private String name;
- private String lastMessage = "";
- private long lastMessageTime = 0L;
/**
* Please do not use this method. Instead use
* BukkitUtil.getPlayer(Player), as it caches player objects.
@@ -94,7 +91,6 @@ public class BukkitPlayer extends PlotPlayer {
@Nonnull final PermissionHandler permissionHandler) {
super(plotAreaManager, eventDispatcher, econHandler, permissionHandler);
this.player = player;
- this.econHandler = econHandler;
this.setupPermissionProfile();
if (realPlayer) {
super.populatePersistentMetaMap();
@@ -153,13 +149,6 @@ public class BukkitPlayer extends PlotPlayer {
}
}
- @Override public boolean hasPermission(@Nonnull final String permission) {
- if (this.offline && this.econHandler != null) {
- return this.econHandler.hasPermission(getName(), permission);
- }
- return this.player.hasPermission(permission);
- }
-
@Override @Nonnegative public int hasPermissionRange(@Nonnull final String stub,
@Nonnegative final int range) {
if (hasPermission(Permission.PERMISSION_ADMIN.toString())) {
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java
new file mode 100644
index 000000000..3ab6e31c0
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java
@@ -0,0 +1,225 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.queue;
+
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+import com.plotsquared.bukkit.BukkitPlatform;
+import com.plotsquared.core.queue.ChunkCoordinator;
+import com.plotsquared.core.util.task.TaskManager;
+import com.plotsquared.core.util.task.TaskTime;
+import com.sk89q.worldedit.math.BlockVector2;
+import com.sk89q.worldedit.world.World;
+import io.papermc.lib.PaperLib;
+import org.bukkit.Bukkit;
+import org.bukkit.Chunk;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import javax.annotation.Nonnull;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+
+/**
+ * Utility that allows for the loading and coordination of chunk actions
+ *
+ * The coordinator takes in collection of chunk coordinates, loads them
+ * and allows the caller to specify a sink for the loaded chunks. The
+ * coordinator will prevent the chunks from being unloaded until the sink
+ * has fully consumed the chunk
+ *
+ **/
+public final class BukkitChunkCoordinator extends ChunkCoordinator {
+
+ private final List progressSubscribers = new LinkedList<>();
+
+ private final Queue requestedChunks;
+ private final Queue availableChunks;
+ private final long maxIterationTime;
+ private final Plugin plugin;
+ private final Consumer chunkConsumer;
+ private final org.bukkit.World bukkitWorld;
+ private final Runnable whenDone;
+ private final Consumer throwableConsumer;
+ private final boolean unloadAfter;
+ private final int totalSize;
+
+ private final AtomicInteger expectedSize;
+ private int batchSize;
+
+ @Inject private BukkitChunkCoordinator(@Assisted final long maxIterationTime,
+ @Assisted final int initialBatchSize,
+ @Assisted @Nonnull final Consumer chunkConsumer,
+ @Assisted @Nonnull final World world,
+ @Assisted @Nonnull final Collection requestedChunks,
+ @Assisted @Nonnull final Runnable whenDone,
+ @Assisted @Nonnull final Consumer throwableConsumer,
+ @Assisted final boolean unloadAfter) {
+ this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
+ this.availableChunks = new LinkedBlockingQueue<>();
+ this.totalSize = requestedChunks.size();
+ this.expectedSize = new AtomicInteger(this.totalSize);
+ this.batchSize = initialBatchSize;
+ this.chunkConsumer = chunkConsumer;
+ this.maxIterationTime = maxIterationTime;
+ this.whenDone = whenDone;
+ this.throwableConsumer = throwableConsumer;
+ this.unloadAfter = unloadAfter;
+ this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
+ this.bukkitWorld = Bukkit.getWorld(world.getName());
+ }
+
+ @Override public void start() {
+ // Request initial batch
+ this.requestBatch();
+ // Wait until next tick to give the chunks a chance to be loaded
+ TaskManager.runTaskLater(() -> TaskManager.runTaskRepeat(this, TaskTime.ticks(1)), TaskTime.ticks(1));
+ }
+
+ @Override public void runTask() {
+ Chunk chunk = this.availableChunks.poll();
+ if (chunk == null) {
+ return;
+ }
+ long iterationTime;
+ int processedChunks = 0;
+ do {
+ final long start = System.currentTimeMillis();
+ try {
+ this.chunkConsumer.accept(BlockVector2.at(chunk.getX(), chunk.getZ()));
+ } catch (final Throwable throwable) {
+ this.throwableConsumer.accept(throwable);
+ }
+ if (unloadAfter) {
+ this.freeChunk(chunk);
+ }
+ processedChunks++;
+ final long end = System.currentTimeMillis();
+ // Update iteration time
+ iterationTime = end - start;
+ } while (2 * iterationTime /* last chunk + next chunk */ < this.maxIterationTime && (chunk = availableChunks.poll()) != null);
+ if (processedChunks < this.batchSize) {
+ // Adjust batch size based on the amount of processed chunks per tick
+ this.batchSize = processedChunks;
+ }
+
+ final int expected = this.expectedSize.addAndGet(-processedChunks);
+
+ final float progress = ((float) totalSize - (float) expected) / (float) totalSize;
+ for (final ProgressSubscriber subscriber : this.progressSubscribers) {
+ subscriber.notifyProgress(this, progress);
+ }
+
+ if (expected <= 0) {
+ try {
+ this.whenDone.run();
+ } catch (final Throwable throwable) {
+ this.throwableConsumer.accept(throwable);
+ }
+ this.cancel();
+ } else {
+ if (this.availableChunks.size() < processedChunks) {
+ this.requestBatch();
+ }
+ }
+ }
+
+ /**
+ * Requests a batch of chunks to be loaded
+ */
+ private void requestBatch() {
+ BlockVector2 chunk;
+ for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) {
+ // This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent
+ PaperLib.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true).whenComplete((chunkObject, throwable) -> {
+ if (throwable != null) {
+ throwable.printStackTrace();
+ // We want one less because this couldn't be processed
+ this.expectedSize.decrementAndGet();
+ } else {
+ this.processChunk(chunkObject);
+ }
+ });
+ }
+ }
+
+ /**
+ * Once a chunk has been loaded, process it (add a plugin ticket and add to available chunks list)
+ */
+ private void processChunk(@Nonnull final Chunk chunk) {
+ if (!chunk.isLoaded()) {
+ throw new IllegalArgumentException(String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ()));
+ }
+ chunk.addPluginChunkTicket(this.plugin);
+ this.availableChunks.add(chunk);
+ }
+
+ /**
+ * Once a chunk has been used, free it up for unload by removing the plugin ticket
+ */
+ private void freeChunk(@Nonnull final Chunk chunk) {
+ if (!chunk.isLoaded()) {
+ throw new IllegalArgumentException(String.format("Chunk %d;%d is is not loaded", chunk.getX(), chunk.getZ()));
+ }
+ chunk.removePluginChunkTicket(this.plugin);
+ }
+
+ @Override public int getRemainingChunks() {
+ return this.expectedSize.get();
+ }
+
+ @Override public int getTotalChunks() {
+ return this.totalSize;
+ }
+
+ /**
+ * Subscribe to coordinator progress updates
+ *
+ * @param subscriber Subscriber
+ */
+ public void subscribeToProgress(@Nonnull final BukkitChunkCoordinator.ProgressSubscriber subscriber) {
+ this.progressSubscribers.add(subscriber);
+ }
+
+ @FunctionalInterface
+ public interface ProgressSubscriber {
+
+ /**
+ * Notify about a progress update in the coordinator
+ *
+ * @param coordinator Coordinator instance that triggered the notification
+ * @param progress Progress in the range [0, 1]
+ */
+ void notifyProgress(@Nonnull final BukkitChunkCoordinator coordinator, final float progress);
+
+ }
+
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java
deleted file mode 100644
index a1bf7bee7..000000000
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java
+++ /dev/null
@@ -1,239 +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 .
- */
-package com.plotsquared.bukkit.queue;
-
-import com.plotsquared.bukkit.schematic.StateWrapper;
-import com.plotsquared.bukkit.util.BukkitBlockUtil;
-import com.plotsquared.core.queue.BasicLocalBlockQueue;
-import com.plotsquared.core.util.BlockUtil;
-import com.plotsquared.core.util.ChunkUtil;
-import com.sk89q.jnbt.CompoundTag;
-import com.sk89q.worldedit.EditSession;
-import com.sk89q.worldedit.WorldEdit;
-import com.sk89q.worldedit.bukkit.BukkitAdapter;
-import com.sk89q.worldedit.math.BlockVector3;
-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 io.papermc.lib.PaperLib;
-import org.bukkit.Bukkit;
-import org.bukkit.Chunk;
-import org.bukkit.Material;
-import org.bukkit.World;
-import org.bukkit.block.Biome;
-import org.bukkit.block.Block;
-import org.bukkit.block.Container;
-import org.bukkit.block.data.BlockData;
-
-import javax.annotation.Nonnull;
-import java.util.concurrent.ExecutionException;
-import java.util.function.Consumer;
-
-public class BukkitLocalQueue extends BasicLocalBlockQueue {
-
- public BukkitLocalQueue(String world) {
- super(world);
- }
-
- @Override public LocalChunk getLocalChunk(int x, int z) {
- return new BasicLocalChunk(this, x, z) {
- // Custom stuff?
- };
- }
-
- @Override public void optimize() {
-
- }
-
- @Override public BlockState getBlock(int x, int y, int z) {
- World worldObj = Bukkit.getWorld(getWorld());
- if (worldObj != null) {
- Block block = worldObj.getBlockAt(x, y, z);
- return BukkitBlockUtil.get(block);
- } else {
- return BlockUtil.get(0, 0);
- }
- }
-
- @Override public void refreshChunk(int x, int z) {
- World worldObj = Bukkit.getWorld(getWorld());
- if (worldObj != null) {
- worldObj.refreshChunk(x, z);
- }
- }
-
- @Override public void fixChunkLighting(int x, int z) {
- // Do nothing
- }
-
- @Override public final void regenChunk(int x, int z) {
- World worldObj = Bukkit.getWorld(getWorld());
- if (worldObj != null) {
- try {
- worldObj.regenerateChunk(x, z);
- } catch (UnsupportedOperationException e) {
- com.sk89q.worldedit.world.World world = BukkitAdapter.adapt(worldObj);
- try (EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
- .getEditSession(world, -1);) {
- CuboidRegion region =
- new CuboidRegion(world, BlockVector3.at((x << 4), 0, (z << 4)),
- BlockVector3.at((x << 4) + 15, 255, (z << 4) + 15));
- world.regenerate(region, editSession);
- }
- }
- }
- }
-
- @Override public final void setComponents(LocalChunk lc)
- throws ExecutionException, InterruptedException {
- setBaseBlocks(lc);
- }
-
- public void setBaseBlocks(LocalChunk localChunk) {
- World worldObj = Bukkit.getWorld(getWorld());
- if (worldObj == null) {
- throw new NullPointerException("World cannot be null.");
- }
- final Consumer chunkConsumer = chunk -> {
- for (int layer = 0; layer < localChunk.baseblocks.length; layer++) {
- BaseBlock[] blocksLayer = localChunk.baseblocks[layer];
- if (blocksLayer != null) {
- for (int j = 0; j < blocksLayer.length; j++) {
- if (blocksLayer[j] != null) {
- BaseBlock block = blocksLayer[j];
- int x = ChunkUtil.getX(j);
- int y = ChunkUtil.getY(layer, j);
- int z = ChunkUtil.getZ(j);
-
- BlockData blockData = BukkitAdapter.adapt(block);
-
- Block existing = chunk.getBlock(x, y, z);
- final BlockState existingBaseBlock =
- BukkitAdapter.adapt(existing.getBlockData());
- if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing
- .getBlockData().matches(blockData)) {
- continue;
- }
-
- if (existing.getState() instanceof Container) {
- ((Container) existing.getState()).getInventory().clear();
- }
-
- existing.setType(BukkitAdapter.adapt(block.getBlockType()), false);
- existing.setBlockData(blockData, false);
- if (block.hasNbtData()) {
- CompoundTag tag = block.getNbtData();
- StateWrapper sw = new StateWrapper(tag);
-
- sw.restoreTag(worldObj.getName(), existing.getX(), existing.getY(),
- existing.getZ());
- }
- }
- }
- }
- }
- if (setBiome() && localChunk.biomes != null) {
- for (int x = 0; x < localChunk.biomes.length; x++) {
- BiomeType[] biomeZ = localChunk.biomes[x];
- if (biomeZ != null) {
- for (int z = 0; z < biomeZ.length; z++) {
- if (biomeZ[z] != null) {
- BiomeType biomeType = biomeZ[z];
-
- Biome biome = BukkitAdapter.adapt(biomeType);
- worldObj.setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z,
- biome);
- }
- }
- }
- }
- }
- };
- if (isForceSync()) {
- chunkConsumer.accept(getChunk(worldObj, localChunk));
- } else {
- PaperLib.getChunkAtAsync(worldObj, localChunk.getX(), localChunk.getZ(), true)
- .thenAccept(chunkConsumer);
- }
- }
-
- private Chunk getChunk(final World world, final LocalChunk localChunk) {
- Chunk chunk = null;
- if (this.getChunkObject() != null && this.getChunkObject() instanceof Chunk) {
- chunk = (Chunk) this.getChunkObject();
- }
- if (chunk == null) {
- chunk = world.getChunkAt(localChunk.getX(), localChunk.getZ());
- }
- if (!chunk.isLoaded()) {
- chunk.load(true);
- }
- return chunk;
- }
-
- private void setMaterial(@Nonnull final BlockState plotBlock, @Nonnull final Block block) {
- Material material = BukkitAdapter.adapt(plotBlock.getBlockType());
- block.setType(material, false);
- }
-
- private boolean equals(@Nonnull final BlockState plotBlock, @Nonnull final Block block) {
- return plotBlock.equals(BukkitBlockUtil.get(block));
- }
-
- public void setBiomes(LocalChunk lc) {
- World worldObj = Bukkit.getWorld(getWorld());
- if (worldObj == null) {
- throw new NullPointerException("World cannot be null.");
- }
- if (lc.biomes == null) {
- throw new NullPointerException("Biomes cannot be null.");
- }
- final Consumer chunkConsumer = chunk -> {
- for (int x = 0; x < lc.biomes.length; x++) {
- BiomeType[] biomeZ = lc.biomes[x];
- if (biomeZ != null) {
- for (int z = 0; z < biomeZ.length; z++) {
- if (biomeZ[z] != null) {
- BiomeType biomeType = biomeZ[z];
-
- Biome biome = BukkitAdapter.adapt(biomeType);
- worldObj
- .setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, biome);
- }
- }
- }
- }
- };
- if (this.isForceSync()) {
- chunkConsumer.accept(getChunk(worldObj, lc));
- } else {
- PaperLib.getChunkAtAsync(worldObj, lc.getX(), lc.getZ(), true)
- .thenAccept(chunkConsumer);
- }
- }
-
-}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java
new file mode 100644
index 000000000..460d6ac1e
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitQueueCoordinator.java
@@ -0,0 +1,241 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.queue;
+
+import com.google.inject.Inject;
+import com.plotsquared.bukkit.schematic.StateWrapper;
+import com.plotsquared.bukkit.util.BukkitBlockUtil;
+import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
+import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
+import com.plotsquared.core.queue.BasicQueueCoordinator;
+import com.plotsquared.core.queue.ChunkCoordinator;
+import com.plotsquared.core.queue.LocalChunk;
+import com.plotsquared.core.util.BlockUtil;
+import com.plotsquared.core.util.ChunkUtil;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.worldedit.WorldEditException;
+import com.sk89q.worldedit.bukkit.BukkitAdapter;
+import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+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.util.SideEffect;
+import com.sk89q.worldedit.util.SideEffectSet;
+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 org.bukkit.Bukkit;
+import org.bukkit.Chunk;
+import org.bukkit.block.Block;
+import org.bukkit.block.Container;
+import org.bukkit.block.data.BlockData;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.function.Consumer;
+
+public class BukkitQueueCoordinator extends BasicQueueCoordinator {
+
+ private final SideEffectSet sideEffectSet;
+ private org.bukkit.World bukkitWorld;
+ @Inject private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory;
+ @Inject private ChunkCoordinatorFactory chunkCoordinatorFactory;
+ private ChunkCoordinator chunkCoordinator;
+
+ @Inject public BukkitQueueCoordinator(@Nonnull World world) {
+ super(world);
+ sideEffectSet = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF).with(SideEffect.NEIGHBORS, SideEffect.State.OFF);
+ }
+
+ @Override public BlockState getBlock(int x, int y, int z) {
+ org.bukkit.World worldObj = BukkitAdapter.adapt(getWorld());
+ if (worldObj != null) {
+ Block block = worldObj.getBlockAt(x, y, z);
+ return BukkitBlockUtil.get(block);
+ } else {
+ return BlockUtil.get(0, 0);
+ }
+ }
+
+ @Override public void start() {
+ chunkCoordinator.start();
+ }
+
+ //TODO: implement cancellation
+ @Override public void cancel() {
+ chunkCoordinator.cancel();
+ }
+
+ @Override public boolean enqueue() {
+ final Clipboard regenClipboard;
+ if (isRegen()) {
+ BlockVector3 start = BlockVector3.at(getRegenStart()[0] << 4, 0, getRegenStart()[1] << 4);
+ BlockVector3 end = BlockVector3.at((getRegenEnd()[0] << 4) + 15, 255, (getRegenEnd()[1] << 4) + 15);
+ Region region = new CuboidRegion(start, end);
+ regenClipboard = new BlockArrayClipboard(region);
+ regenClipboard.setOrigin(start);
+ getWorld().regenerate(region, regenClipboard);
+ } else if (getRegenRegion() != null) {
+ regenClipboard = new BlockArrayClipboard(getRegenRegion());
+ regenClipboard.setOrigin(getRegenRegion().getMinimumPoint());
+ getWorld().regenerate(getRegenRegion(), regenClipboard);
+ } else {
+ regenClipboard = null;
+ }
+ Consumer consumer = getChunkConsumer();
+ if (consumer == null) {
+ consumer = blockVector2 -> {
+ LocalChunk localChunk = getBlockChunks().get(blockVector2);
+ boolean isRegenChunk =
+ regenClipboard != null && blockVector2.getBlockX() > getRegenStart()[0] && blockVector2.getBlockZ() > getRegenStart()[1]
+ && blockVector2.getBlockX() < getRegenEnd()[0] && blockVector2.getBlockZ() < getRegenEnd()[1];
+ if (isRegenChunk) {
+ for (int layer = 0; layer < 16; layer++) {
+ for (int y = layer << 4; y < 16; y++) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ BaseBlock block = regenClipboard.getFullBlock(BlockVector3.at(x, y, z));
+ if (block != null) {
+ setWorldBlock(x, y, z, block, blockVector2);
+ }
+ }
+ }
+ }
+ }
+ }
+ // Allow regen and then blocks to be placed (plot schematic etc)
+ if (localChunk == null) {
+ return;
+ }
+ int sx = blockVector2.getX() << 4;
+ int sz = blockVector2.getZ() << 4;
+ for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) {
+ BaseBlock[] blocksLayer = localChunk.getBaseblocks()[layer];
+ if (blocksLayer == null) {
+ continue;
+ }
+ for (int j = 0; j < blocksLayer.length; j++) {
+ if (blocksLayer[j] == null) {
+ continue;
+ }
+ BaseBlock block = blocksLayer[j];
+
+ if (block != null) {
+ int x = sx + ChunkUtil.getX(j);
+ int y = ChunkUtil.getY(layer, j);
+ int z = sz + ChunkUtil.getZ(j);
+ setWorldBlock(x, y, z, block, blockVector2);
+ }
+ }
+ }
+ for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) {
+ BiomeType[] biomesLayer = localChunk.getBiomes()[layer];
+ if (biomesLayer == null) {
+ continue;
+ }
+ for (int j = 0; j < biomesLayer.length; j++) {
+ if (biomesLayer[j] == null) {
+ continue;
+ }
+ BiomeType biome = biomesLayer[j];
+ if (biome != null) {
+ int x = sx + ChunkUtil.getX(j);
+ int y = ChunkUtil.getY(layer, j);
+ int z = sz + ChunkUtil.getZ(j);
+ getWorld().setBiome(BlockVector3.at(x, y, z), biome);
+ }
+ }
+ }
+ if (localChunk.getTiles().size() > 0) {
+ localChunk.getTiles().forEach(((blockVector3, tag) -> {
+ try {
+ BaseBlock block = getWorld().getBlock(blockVector3).toBaseBlock(tag);
+ getWorld().setBlock(blockVector3, block, sideEffectSet);
+ } catch (WorldEditException ignored) {
+ StateWrapper sw = new StateWrapper(tag);
+ sw.restoreTag(getWorld().getName(), blockVector3.getX(), blockVector3.getY(), blockVector3.getZ());
+ }
+ }));
+ }
+ if (localChunk.getEntities().size() > 0) {
+ localChunk.getEntities().forEach((location, entity) -> {
+ getWorld().createEntity(location, entity);
+ });
+ }
+ };
+ }
+ Collection read = new ArrayList<>();
+ if (getReadChunks().size() > 0) {
+ read.addAll(getReadChunks());
+ }
+ chunkCoordinator =
+ chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(getWorld()).withChunks(getBlockChunks().keySet()).withChunks(read)
+ .withInitialBatchSize(3).withMaxIterationTime(40).withThrowableConsumer(Throwable::printStackTrace).withFinalAction(getCompleteTask())
+ .withConsumer(consumer).unloadAfter(isUnloadAfter()).build();
+ return super.enqueue();
+ }
+
+ /**
+ * Set a block to the world. First tries WNA but defaults to normal block setting methods if that fails
+ */
+ private void setWorldBlock(int x, int y, int z, @Nonnull BaseBlock block, @Nonnull BlockVector2 blockVector2) {
+ try {
+ getWorld().setBlock(BlockVector3.at(x, y, z), block, sideEffectSet);
+ } catch (WorldEditException ignored) {
+ // Fallback to not so nice method
+ BlockData blockData = BukkitAdapter.adapt(block);
+
+ if (bukkitWorld == null) {
+ bukkitWorld = Bukkit.getWorld(getWorld().getName());
+ }
+ Chunk chunk = bukkitWorld.getChunkAt(blockVector2.getX(), blockVector2.getZ());
+
+ Block existing = chunk.getBlock(x, y, z);
+ final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData());
+ if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing.getBlockData().matches(blockData)) {
+ return;
+ }
+
+ if (existing.getState() instanceof Container) {
+ ((Container) existing.getState()).getInventory().clear();
+ }
+
+ existing.setType(BukkitAdapter.adapt(block.getBlockType()), false);
+ existing.setBlockData(blockData, false);
+ if (block.hasNbtData()) {
+ CompoundTag tag = block.getNbtData();
+ StateWrapper sw = new StateWrapper(tag);
+
+ sw.restoreTag(getWorld().getName(), existing.getX(), existing.getY(), existing.getZ());
+ }
+ }
+ }
+
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java
index 9586ff7a6..ea22947dd 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/GenChunk.java
@@ -30,7 +30,7 @@ import com.plotsquared.bukkit.util.BukkitBlockUtil;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.location.Location;
-import com.plotsquared.core.queue.ScopedLocalBlockQueue;
+import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkUtil;
import com.plotsquared.core.util.PatternUtil;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
@@ -39,16 +39,17 @@ 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.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
-
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import java.util.Arrays;
-public class GenChunk extends ScopedLocalBlockQueue {
+public class GenChunk extends ScopedQueueCoordinator {
public final Biome[] biomes;
public BlockState[][] result;
@@ -64,7 +65,18 @@ public class GenChunk extends ScopedLocalBlockQueue {
this.biomes = Biome.values();
}
- public Chunk getChunk() {
+ @Nullable public ChunkData getChunkData() {
+ return this.chunkData;
+ }
+
+ /**
+ * Set the internal Bukkit chunk data
+ */
+ public void setChunkData(@Nonnull ChunkData chunkData) {
+ this.chunkData = chunkData;
+ }
+
+ @Nonnull public Chunk getChunk() {
if (chunk == null) {
World worldObj = BukkitUtil.getWorld(world);
if (worldObj != null) {
@@ -74,32 +86,40 @@ public class GenChunk extends ScopedLocalBlockQueue {
return chunk;
}
- public void setChunk(Chunk chunk) {
+ /**
+ * Set the chunk being represented
+ */
+ public void setChunk(@Nonnull Chunk chunk) {
this.chunk = chunk;
}
- public void setChunk(ChunkWrapper wrap) {
+
+ /**
+ * Set the world and XZ of the chunk being represented via {@link ChunkWrapper}
+ */
+ public void setChunk(@Nonnull ChunkWrapper wrap) {
chunk = null;
world = wrap.world;
chunkX = wrap.x;
chunkZ = wrap.z;
}
- @Override public void fillBiome(BiomeType biomeType) {
+ @Override public void fillBiome(@Nonnull BiomeType biomeType) {
if (biomeGrid == null) {
return;
}
Biome biome = BukkitAdapter.adapt(biomeType);
- for (int x = 0; x < 16; x++) {
- for (int z = 0; z < 16; z++) {
- this.biomeGrid.setBiome(x, z, biome);
+ for (int y = 0; y < 256; y++) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ this.biomeGrid.setBiome(x, y, z, biome);
+ }
}
}
}
- @Override public void setCuboid(Location pos1, Location pos2, BlockState block) {
- if (result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15
- && pos2.getZ() == 15) {
+ @Override public void setCuboid(@Nonnull Location pos1, @Nonnull Location pos2, @Nonnull BlockState block) {
+ if (result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15 && pos2.getZ() == 15) {
for (int y = pos1.getY(); y <= pos2.getY(); y++) {
int layer = y >> 4;
BlockState[] data = result[layer];
@@ -117,28 +137,39 @@ public class GenChunk extends ScopedLocalBlockQueue {
int maxX = Math.max(pos1.getX(), pos2.getX());
int maxY = Math.max(pos1.getY(), pos2.getY());
int maxZ = Math.max(pos1.getZ(), pos2.getZ());
- chunkData
- .setRegion(minX, minY, minZ, maxX + 1, maxY + 1, maxZ + 1, BukkitAdapter.adapt(block));
+ chunkData.setRegion(minX, minY, minZ, maxX + 1, maxY + 1, maxZ + 1, BukkitAdapter.adapt(block));
}
- @Override public boolean setBiome(int x, int z, BiomeType biomeType) {
+ @Override public boolean setBiome(int x, int z, @Nonnull BiomeType biomeType) {
return setBiome(x, z, BukkitAdapter.adapt(biomeType));
}
- public boolean setBiome(int x, int z, Biome biome) {
+ /**
+ * Set the in the whole column of XZ
+ */
+ public boolean setBiome(int x, int z, @Nonnull Biome biome) {
if (this.biomeGrid != null) {
- this.biomeGrid.setBiome(x, z, biome);
+ for (int y = 0; y < 256; y++) {
+ this.setBiome(x, y, z, biome);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public boolean setBiome(int x, int y, int z, @Nonnull Biome biome) {
+ if (this.biomeGrid != null) {
+ this.biomeGrid.setBiome(x, y, z, biome);
return true;
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
- return setBlock(x, y, z, PatternUtil
- .apply(Preconditions.checkNotNull(pattern, "Pattern may not be null"), x, y, z));
+ return setBlock(x, y, z, PatternUtil.apply(Preconditions.checkNotNull(pattern, "Pattern may not be null"), x, y, z));
}
- @Override public boolean setBlock(int x, int y, int z, BlockState id) {
+ @Override public boolean setBlock(int x, int y, int z, @Nonnull BlockState id) {
if (this.result == null) {
this.chunkData.setBlock(x, y, z, BukkitAdapter.adapt(id));
return true;
@@ -148,7 +179,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
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) {
int i = y >> 4;
BlockState[] v = this.result[i];
if (v == null) {
@@ -158,7 +189,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
v[j] = id;
}
- @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 (this.result == null) {
this.chunkData.setBlock(x, y, z, BukkitAdapter.adapt(id));
return true;
@@ -168,7 +199,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
return true;
}
- @Override public BlockState getBlock(int x, int y, int z) {
+ @Override @Nullable public BlockState getBlock(int x, int y, int z) {
int i = y >> 4;
if (result == null) {
return BukkitBlockUtil.get(chunkData.getType(x, y, z));
@@ -189,19 +220,19 @@ public class GenChunk extends ScopedLocalBlockQueue {
return chunk == null ? chunkZ : chunk.getZ();
}
- @Override public String getWorld() {
- return chunk == null ? world : chunk.getWorld().getName();
+ @Override @Nonnull public com.sk89q.worldedit.world.World getWorld() {
+ return chunk == null ? BukkitAdapter.adapt(Bukkit.getWorld(world)) : BukkitAdapter.adapt(chunk.getWorld());
}
- @Override public Location getMax() {
- return Location.at(getWorld(), 15 + (getX() << 4), 255, 15 + (getZ() << 4));
+ @Override @Nonnull public Location getMax() {
+ return Location.at(getWorld().getName(), 15 + (getX() << 4), 255, 15 + (getZ() << 4));
}
- @Override public Location getMin() {
- return Location.at(getWorld(), getX() << 4, 0, getZ() << 4);
+ @Override @Nonnull public Location getMin() {
+ return Location.at(getWorld().getName(), getX() << 4, 0, getZ() << 4);
}
- public GenChunk clone() {
+ @Nonnull public GenChunk clone() {
GenChunk toReturn = new GenChunk();
if (this.result != null) {
for (int i = 0; i < this.result.length; i++) {
@@ -215,12 +246,4 @@ public class GenChunk extends ScopedLocalBlockQueue {
toReturn.chunkData = this.chunkData;
return toReturn;
}
-
- public ChunkData getChunkData() {
- return this.chunkData;
- }
-
- public void setChunkData(ChunkData chunkData) {
- this.chunkData = chunkData;
- }
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java
index e6e8d625c..f03428726 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/schematic/BukkitSchematicHandler.java
@@ -27,7 +27,7 @@ package com.plotsquared.bukkit.schematic;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import com.plotsquared.core.queue.LocalBlockQueue;
+import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.WorldUtil;
import com.sk89q.jnbt.CompoundTag;
@@ -44,7 +44,7 @@ import javax.annotation.Nonnull;
}
@Override
- public boolean restoreTile(LocalBlockQueue queue, CompoundTag ct, int x, int y, int z) {
- return new StateWrapper(ct).restoreTag(queue.getWorld(), x, y, z);
+ public boolean restoreTile(QueueCoordinator queue, CompoundTag ct, int x, int y, int z) {
+ return new StateWrapper(ct).restoreTag(queue.getWorld().getName(), x, y, z);
}
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitChunkManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitChunkManager.java
index 325d47544..8086d805a 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitChunkManager.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitChunkManager.java
@@ -26,140 +26,23 @@
package com.plotsquared.bukkit.util;
import com.google.inject.Singleton;
-import com.plotsquared.core.PlotSquared;
-import com.plotsquared.core.listener.WEExtent;
-import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.util.ChunkManager;
-import com.plotsquared.core.util.entity.EntityCategories;
-import com.plotsquared.core.util.task.TaskManager;
-import com.sk89q.worldedit.bukkit.BukkitAdapter;
-import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.math.BlockVector2;
-import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
-import com.sk89q.worldedit.world.block.BaseBlock;
import io.papermc.lib.PaperLib;
-import org.bukkit.Chunk;
-import org.bukkit.World;
-import org.bukkit.block.Block;
-import org.bukkit.block.data.BlockData;
-import org.bukkit.entity.Entity;
import java.util.concurrent.CompletableFuture;
-import static com.plotsquared.core.util.entity.EntityCategories.CAP_ANIMAL;
-import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY;
-import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC;
-import static com.plotsquared.core.util.entity.EntityCategories.CAP_MOB;
-import static com.plotsquared.core.util.entity.EntityCategories.CAP_MONSTER;
-import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
-
-@Singleton public class BukkitChunkManager extends ChunkManager {
+@Singleton
+public class BukkitChunkManager extends ChunkManager {
public static boolean isIn(CuboidRegion region, int x, int z) {
- return x >= region.getMinimumPoint().getX() && x <= region.getMaximumPoint().getX()
- && z >= region.getMinimumPoint().getZ() && z <= region.getMaximumPoint().getZ();
+ return x >= region.getMinimumPoint().getX() && x <= region.getMaximumPoint().getX() && z >= region.getMinimumPoint().getZ() && z <= region
+ .getMaximumPoint().getZ();
}
- public static ContentMap swapChunk(World world1, World world2, Chunk pos1, Chunk pos2,
- CuboidRegion r1, CuboidRegion r2) {
- ContentMap map = new ContentMap();
- int relX = r2.getMinimumPoint().getX() - r1.getMinimumPoint().getX();
- int relZ = r2.getMinimumPoint().getZ() - r1.getMinimumPoint().getZ();
-
- map.saveEntitiesIn(pos1, r1, relX, relZ, true);
- map.saveEntitiesIn(pos2, r2, -relX, -relZ, true);
-
- int sx = pos1.getX() << 4;
- int sz = pos1.getZ() << 4;
-
- String worldName1 = world1.getName();
- String worldName2 = world2.getName();
-
- BukkitWorld bukkitWorld1 = new BukkitWorld(world1);
- BukkitWorld bukkitWorld2 = new BukkitWorld(world2);
-
- LocalBlockQueue queue1 = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(worldName1, false);
- LocalBlockQueue queue2 = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(worldName2, false);
-
- for (int x = Math.max(r1.getMinimumPoint().getX(), sx);
- x <= Math.min(r1.getMaximumPoint().getX(), sx + 15); x++) {
- for (int z = Math.max(r1.getMinimumPoint().getZ(), sz);
- z <= Math.min(r1.getMaximumPoint().getZ(), sz + 15); z++) {
- for (int y = 0; y < 256; y++) {
- Block block1 = world1.getBlockAt(x, y, z);
- BaseBlock baseBlock1 = bukkitWorld1.getFullBlock(BlockVector3.at(x, y, z));
- BlockData data1 = block1.getBlockData();
-
- int xx = x + relX;
- int zz = z + relZ;
-
- Block block2 = world2.getBlockAt(xx, y, zz);
- BaseBlock baseBlock2 = bukkitWorld2.getFullBlock(BlockVector3.at(xx, y, zz));
- BlockData data2 = block2.getBlockData();
-
- if (block1.isEmpty()) {
- if (!block2.isEmpty()) {
- queue1.setBlock(x, y, z, baseBlock2);
- queue2.setBlock(xx, y, zz, WEExtent.AIRBASE);
- }
- } else if (block2.isEmpty()) {
- queue1.setBlock(x, y, z, WEExtent.AIRBASE);
- queue2.setBlock(xx, y, zz, baseBlock1);
- } else if (block1.equals(block2)) {
- if (!data1.matches(data2)) {
- block1.setBlockData(data2);
- block2.setBlockData(data1);
- }
- } else {
- queue1.setBlock(x, y, z, baseBlock2);
- queue2.setBlock(xx, y, zz, baseBlock1);
- }
- }
- }
- }
- queue1.enqueue();
- queue2.enqueue();
- return map;
+ @Override public CompletableFuture> loadChunk(String world, BlockVector2 chunkLoc, boolean force) {
+ return PaperLib.getChunkAtAsync(BukkitUtil.getWorld(world), chunkLoc.getX(), chunkLoc.getZ(), force);
}
- @Override
- public CompletableFuture> loadChunk(String world, BlockVector2 chunkLoc, boolean force) {
- return PaperLib
- .getChunkAtAsync(BukkitUtil.getWorld(world), chunkLoc.getX(), chunkLoc.getZ(), force);
- }
-
- @Override
- public void unloadChunk(final String world, final BlockVector2 chunkLoc, final boolean save) {
- if (!PlotSquared.get().isMainThread(Thread.currentThread())) {
- TaskManager.runTask(() -> BukkitUtil.getWorld(world)
- .unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save));
- } else {
- BukkitUtil.getWorld(world).unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save);
- }
- }
-
- private void count(int[] count, Entity entity) {
- final com.sk89q.worldedit.world.entity.EntityType entityType =
- BukkitAdapter.adapt(entity.getType());
-
- if (EntityCategories.PLAYER.contains(entityType)) {
- return;
- } else if (EntityCategories.PROJECTILE.contains(entityType) || EntityCategories.OTHER
- .contains(entityType) || EntityCategories.HANGING.contains(entityType)) {
- count[CAP_MISC]++;
- } else if (EntityCategories.ANIMAL.contains(entityType) || EntityCategories.VILLAGER
- .contains(entityType) || EntityCategories.TAMEABLE.contains(entityType)) {
- count[CAP_MOB]++;
- count[CAP_ANIMAL]++;
- } else if (EntityCategories.VEHICLE.contains(entityType)) {
- count[CAP_VEHICLE]++;
- } else if (EntityCategories.HOSTILE.contains(entityType)) {
- count[CAP_MOB]++;
- count[CAP_MONSTER]++;
- }
- count[CAP_ENTITY]++;
- }
-
-
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEntityUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEntityUtil.java
new file mode 100644
index 000000000..d080d53f6
--- /dev/null
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEntityUtil.java
@@ -0,0 +1,381 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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 .
+ */
+package com.plotsquared.bukkit.util;
+
+import com.plotsquared.bukkit.player.BukkitPlayer;
+import com.plotsquared.core.configuration.Settings;
+import com.plotsquared.core.configuration.caption.TranslatableCaption;
+import com.plotsquared.core.location.Location;
+import com.plotsquared.core.permissions.Permission;
+import com.plotsquared.core.plot.Plot;
+import com.plotsquared.core.plot.PlotArea;
+import com.plotsquared.core.plot.flag.implementations.AnimalAttackFlag;
+import com.plotsquared.core.plot.flag.implementations.AnimalCapFlag;
+import com.plotsquared.core.plot.flag.implementations.DoneFlag;
+import com.plotsquared.core.plot.flag.implementations.EntityCapFlag;
+import com.plotsquared.core.plot.flag.implementations.HangingBreakFlag;
+import com.plotsquared.core.plot.flag.implementations.HostileAttackFlag;
+import com.plotsquared.core.plot.flag.implementations.HostileCapFlag;
+import com.plotsquared.core.plot.flag.implementations.MiscBreakFlag;
+import com.plotsquared.core.plot.flag.implementations.MiscCapFlag;
+import com.plotsquared.core.plot.flag.implementations.MobCapFlag;
+import com.plotsquared.core.plot.flag.implementations.PveFlag;
+import com.plotsquared.core.plot.flag.implementations.PvpFlag;
+import com.plotsquared.core.plot.flag.implementations.TamedAttackFlag;
+import com.plotsquared.core.plot.flag.implementations.VehicleCapFlag;
+import com.plotsquared.core.util.EntityUtil;
+import com.plotsquared.core.util.Permissions;
+import com.plotsquared.core.util.entity.EntityCategories;
+import com.sk89q.worldedit.bukkit.BukkitAdapter;
+import net.kyori.adventure.text.minimessage.Template;
+import org.bukkit.entity.Arrow;
+import org.bukkit.entity.Creature;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.projectiles.BlockProjectileSource;
+import org.bukkit.projectiles.ProjectileSource;
+
+import java.util.Objects;
+
+public class BukkitEntityUtil {
+
+ public static final com.sk89q.worldedit.world.entity.EntityType FAKE_ENTITY_TYPE =
+ new com.sk89q.worldedit.world.entity.EntityType("plotsquared:fake");
+
+ public static boolean entityDamage(Entity damager, Entity victim) {
+ return entityDamage(damager, victim, null);
+ }
+
+ public static boolean entityDamage(Entity damager, Entity victim, EntityDamageEvent.DamageCause cause) {
+ Location dloc = BukkitUtil.adapt(damager.getLocation());
+ Location vloc = BukkitUtil.adapt(victim.getLocation());
+ PlotArea dArea = dloc.getPlotArea();
+ PlotArea vArea;
+ if (dArea != null && dArea.contains(vloc.getX(), vloc.getZ())) {
+ vArea = dArea;
+ } else {
+ vArea = vloc.getPlotArea();
+ }
+ if (dArea == null && vArea == null) {
+ return true;
+ }
+
+ Plot dplot;
+ if (dArea != null) {
+ dplot = dArea.getPlot(dloc);
+ } else {
+ dplot = null;
+ }
+ Plot vplot;
+ if (vArea != null) {
+ vplot = vArea.getPlot(vloc);
+ } else {
+ vplot = null;
+ }
+
+ Plot plot;
+ String stub;
+ boolean isPlot = true;
+ if (dplot == null && vplot == null) {
+ if (dArea == null) {
+ return true;
+ }
+ plot = null;
+ stub = "road";
+ isPlot = false;
+ } else {
+ // Prioritize plots for close to seamless pvp zones
+ if (victim.getTicksLived() > damager.getTicksLived()) {
+ if (dplot == null || !(victim instanceof Player)) {
+ if (vplot == null) {
+ plot = dplot;
+ } else {
+ plot = vplot;
+ }
+ } else {
+ plot = dplot;
+ }
+ } else if (dplot == null || !(victim instanceof Player)) {
+ if (vplot == null) {
+ plot = dplot;
+ } else {
+ plot = vplot;
+ }
+ } else if (vplot == null) {
+ plot = dplot;
+ } else {
+ plot = vplot;
+ }
+ if (plot.hasOwner()) {
+ stub = "other";
+ } else {
+ stub = "unowned";
+ }
+ }
+ boolean roadFlags = vArea != null ? vArea.isRoadFlags() : dArea.isRoadFlags();
+ PlotArea area = vArea != null ? vArea : dArea;
+
+ Player player;
+ if (damager instanceof Player) { // attacker is player
+ player = (Player) damager;
+ } else if (damager instanceof Projectile) {
+ Projectile projectile = (Projectile) damager;
+ ProjectileSource shooter = projectile.getShooter();
+ if (shooter instanceof Player) { // shooter is player
+ player = (Player) shooter;
+ } else { // shooter is not player
+ if (shooter instanceof BlockProjectileSource) {
+ Location sLoc = BukkitUtil
+ .adapt(((BlockProjectileSource) shooter).getBlock().getLocation());
+ dplot = dArea.getPlot(sLoc);
+ }
+ player = null;
+ }
+ } else { // Attacker is not player
+ player = null;
+ }
+ if (player != null) {
+ BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
+
+ final com.sk89q.worldedit.world.entity.EntityType entityType;
+
+ // Create a fake entity type if the type does not have a name
+ if (victim.getType().getName() == null) {
+ entityType = FAKE_ENTITY_TYPE;
+ } else {
+ entityType = BukkitAdapter.adapt(victim.getType());
+ }
+
+ if (EntityCategories.HANGING.contains(entityType)) { // hanging
+ if (plot != null && (plot.getFlag(HangingBreakFlag.class) || plot
+ .isAdded(plotPlayer.getUUID()))) {
+ if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
+ if (!Permissions
+ .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.build.other")
+ );
+ return false;
+ }
+ }
+ return true;
+ }
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy." + stub)
+ );
+ return false;
+ }
+ } else if (victim.getType() == EntityType.ARMOR_STAND) {
+ if (plot != null && (plot.getFlag(MiscBreakFlag.class) || plot
+ .isAdded(plotPlayer.getUUID()))) {
+ return true;
+ }
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.destroy." + stub)
+ );
+ if (plot != null) {
+ plot.debug(player.getName()
+ + " could not break armor stand because misc-break = false");
+ }
+ return false;
+ }
+ } else if (EntityCategories.HOSTILE.contains(entityType)) {
+ if (isPlot) {
+ if (plot.getFlag(HostileAttackFlag.class) || plot.getFlag(PveFlag.class) || plot
+ .isAdded(plotPlayer.getUUID())) {
+ return true;
+ }
+ } else if (roadFlags && (area.getRoadFlag(HostileAttackFlag.class) || area
+ .getFlag(PveFlag.class))) {
+ return true;
+ }
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.pve." + stub)
+ );
+ if (plot != null) {
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false OR hostile-attack = false");
+ }
+ return false;
+ }
+ } else if (EntityCategories.TAMEABLE.contains(entityType)) { // victim is tameable
+ if (isPlot) {
+ if (plot.getFlag(TamedAttackFlag.class) || plot.getFlag(PveFlag.class) || plot
+ .isAdded(plotPlayer.getUUID())) {
+ return true;
+ }
+ } else if (roadFlags && (area.getRoadFlag(TamedAttackFlag.class) || area
+ .getFlag(PveFlag.class))) {
+ return true;
+ }
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.pve." + stub)
+ );
+ if (plot != null) {
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false OR tamed-attack = false");
+ }
+ return false;
+ }
+ } else if (EntityCategories.PLAYER.contains(entityType)) {
+ if (isPlot) {
+ if (!plot.getFlag(PvpFlag.class) && !Permissions
+ .hasPermission(plotPlayer, "plots.admin.pvp." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.pvp." + stub)
+ );
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false");
+ return false;
+ } else {
+ return true;
+ }
+ } else if (roadFlags && area.getRoadFlag(PvpFlag.class)) {
+ return true;
+ }
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.pvp." + stub)
+ );
+ return false;
+ }
+ } else if (EntityCategories.ANIMAL.contains(entityType)) { // victim is animal
+ if (isPlot) {
+ if (plot.getFlag(AnimalAttackFlag.class) || plot.getFlag(PveFlag.class) || plot
+ .isAdded(plotPlayer.getUUID())) {
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false OR animal-attack = false");
+ return true;
+ }
+ } else if (roadFlags && (area.getRoadFlag(AnimalAttackFlag.class) || area
+ .getFlag(PveFlag.class))) {
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.pve." + stub)
+ );
+ return false;
+ }
+ }
+ } else if (EntityCategories.VEHICLE
+ .contains(entityType)) { // Vehicles are managed in vehicle destroy event
+ return true;
+ } else { // victim is something else
+ if (isPlot) {
+ if (plot.getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID())) {
+ return true;
+ }
+ } else if (roadFlags && area.getRoadFlag(PveFlag.class)) {
+ return true;
+ }
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
+ plotPlayer.sendMessage(
+ TranslatableCaption.of("permission.no_permission_event"),
+ Template.of("node", "plots.admin.pve." + stub)
+ );
+ if (plot != null) {
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false");
+ }
+ return false;
+ }
+ }
+ return true;
+ } else if (dplot != null && (!dplot.equals(vplot) || Objects
+ .equals(dplot.getOwnerAbs(), vplot.getOwnerAbs()))) {
+ return vplot != null && vplot.getFlag(PveFlag.class);
+ }
+ //disable the firework damage. too much of a headache to support at the moment.
+ if (vplot != null) {
+ if (EntityDamageEvent.DamageCause.ENTITY_EXPLOSION == cause
+ && damager.getType() == EntityType.FIREWORK) {
+ return false;
+ }
+ }
+ if (vplot == null && roadFlags && area.getRoadFlag(PveFlag.class)) {
+ return true;
+ }
+ return ((vplot != null && vplot.getFlag(PveFlag.class)) || !(damager instanceof Arrow
+ && !(victim instanceof Creature)));
+ }
+
+ public static boolean checkEntity(Entity entity, Plot plot) {
+ if (plot == null || !plot.hasOwner() || plot.getFlags().isEmpty() && plot.getArea()
+ .getFlagContainer().getFlagMap().isEmpty()) {
+ return false;
+ }
+
+ final com.sk89q.worldedit.world.entity.EntityType entityType =
+ BukkitAdapter.adapt(entity.getType());
+
+ if (EntityCategories.PLAYER.contains(entityType)) {
+ return false;
+ }
+
+ if (EntityCategories.PROJECTILE.contains(entityType) || EntityCategories.OTHER
+ .contains(entityType) || EntityCategories.HANGING.contains(entityType)) {
+ return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
+ MiscCapFlag.MISC_CAP_UNLIMITED);
+ }
+
+ // Has to go go before vehicle as horses are both
+ // animals and vehicles
+ if (EntityCategories.ANIMAL.contains(entityType) || EntityCategories.VILLAGER
+ .contains(entityType) || EntityCategories.TAMEABLE.contains(entityType)) {
+ return EntityUtil
+ .checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED, MobCapFlag.MOB_CAP_UNLIMITED,
+ AnimalCapFlag.ANIMAL_CAP_UNLIMITED);
+ }
+
+ if (EntityCategories.HOSTILE.contains(entityType)) {
+ return EntityUtil
+ .checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED, MobCapFlag.MOB_CAP_UNLIMITED,
+ HostileCapFlag.HOSTILE_CAP_UNLIMITED);
+ }
+
+ if (EntityCategories.VEHICLE.contains(entityType)) {
+ return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED,
+ VehicleCapFlag.VEHICLE_CAP_UNLIMITED);
+ }
+
+ return EntityUtil.checkEntity(plot, EntityCapFlag.ENTITY_CAP_UNLIMITED);
+ }
+
+}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java
index d3ed2b53c..01e7bf769 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java
@@ -27,29 +27,24 @@ package com.plotsquared.bukkit.util;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import com.plotsquared.bukkit.BukkitPlatform;
-import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.generator.AugmentedUtils;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.location.PlotLoc;
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.queue.ScopedLocalBlockQueue;
+import com.plotsquared.core.queue.GlobalBlockQueue;
+import com.plotsquared.core.queue.QueueCoordinator;
+import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.RegionUtil;
import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.entity.EntityCategories;
import com.plotsquared.core.util.task.RunnableVal;
-import com.plotsquared.core.util.task.TaskManager;
-import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
-import com.sk89q.worldedit.math.BlockVector2;
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.BlockTypes;
import io.papermc.lib.PaperLib;
@@ -62,16 +57,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
-import java.util.Map.Entry;
-import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.Semaphore;
-import static com.google.common.base.Preconditions.checkNotNull;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ANIMAL;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC;
@@ -79,44 +69,17 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_MOB;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_MONSTER;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
-@Singleton public class BukkitRegionManager extends RegionManager {
+@Singleton
+public class BukkitRegionManager extends RegionManager {
- private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName());
+ private static final Logger logger =
+ LoggerFactory.getLogger("P2/" + BukkitRegionManager.class.getSimpleName());
+ private final GlobalBlockQueue blockQueue;
- @Inject public BukkitRegionManager(@Nonnull final ChunkManager chunkManager) {
- super(chunkManager);
- }
-
- public static boolean isIn(CuboidRegion region, int x, int z) {
- return x >= region.getMinimumPoint().getX() && x <= region.getMaximumPoint().getX()
- && z >= region.getMinimumPoint().getZ() && z <= region.getMaximumPoint().getZ();
- }
-
- @Override public Set getChunkChunks(String world) {
- Set chunks = super.getChunkChunks(world);
- if (Bukkit.isPrimaryThread()) {
- for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) {
- BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5);
- chunks.add(loc);
- }
- } else {
- final Semaphore semaphore = new Semaphore(1);
- try {
- semaphore.acquire();
- Bukkit.getScheduler().runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> {
- for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world))
- .getLoadedChunks()) {
- BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5);
- chunks.add(loc);
- }
- semaphore.release();
- });
- semaphore.acquireUninterruptibly();
- } catch (final Exception e) {
- e.printStackTrace();
- }
- }
- return chunks;
+ @Inject
+ public BukkitRegionManager(@Nonnull WorldUtil worldUtil, @Nonnull GlobalBlockQueue blockQueue) {
+ super(worldUtil, blockQueue);
+ this.blockQueue = blockQueue;
}
@Override public boolean handleClear(Plot plot, Runnable whenDone, PlotManager manager) {
@@ -131,7 +94,6 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
}
PlotArea area = plot.getArea();
World world = BukkitUtil.getWorld(area.getWorldName());
-
Location bot = plot.getBottomAbs();
Location top = plot.getTopAbs();
int bx = bot.getX() >> 4;
@@ -199,65 +161,9 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
return count;
}
- @Override
- public boolean copyRegion(Location pos1, Location pos2, Location newPos,
- final Runnable whenDone) {
- final int relX = newPos.getX() - pos1.getX();
- final int relZ = newPos.getZ() - pos1.getZ();
-
- final CuboidRegion region =
- RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
- final World oldWorld = Bukkit.getWorld(pos1.getWorldName());
- final BukkitWorld oldBukkitWorld = new BukkitWorld(oldWorld);
- final World newWorld = Bukkit.getWorld(newPos.getWorldName());
- assert newWorld != null;
- assert oldWorld != null;
- final String newWorldName = newWorld.getName();
- final ContentMap map = new ContentMap();
- final LocalBlockQueue queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(newWorldName, false);
- ChunkManager.chunkTask(pos1, pos2, new RunnableVal() {
- @Override public void run(int[] value) {
- int bx = value[2];
- int bz = value[3];
- int tx = value[4];
- int tz = value[5];
- BlockVector2 loc = BlockVector2.at(value[0], value[1]);
- int cxx = loc.getX() << 4;
- int czz = loc.getZ() << 4;
- PaperLib.getChunkAtAsync(oldWorld, loc.getX(), loc.getZ())
- .thenAccept(chunk1 -> map.saveEntitiesIn(chunk1, region)).thenRun(() -> {
- for (int x = bx & 15; x <= (tx & 15); x++) {
- for (int z = bz & 15; z <= (tz & 15); z++) {
- map.saveBlocks(oldBukkitWorld, 256, cxx + x, czz + z, relX, relZ);
- }
- }
- });
- }
- }, () -> {
- for (Entry entry : map.allBlocks.entrySet()) {
- PlotLoc loc = entry.getKey();
- BaseBlock[] blocks = entry.getValue();
- for (int y = 0; y < blocks.length; y++) {
- if (blocks[y] != null) {
- BaseBlock block = blocks[y];
- queue.setBlock(loc.getX(), y, loc.getZ(), block);
- }
- }
- }
- queue.enqueue();
- PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(() -> {
- //map.restoreBlocks(newWorld, 0, 0);
- map.restoreEntities(newWorld, relX, relZ);
- TaskManager.runTask(whenDone);
- });
- }, 5);
- return true;
- }
-
- @Override
- public boolean regenerateRegion(final Location pos1, final Location pos2,
+ @Override public boolean regenerateRegion(final Location pos1, final Location pos2,
final boolean ignoreAugment, final Runnable whenDone) {
- final String world = pos1.getWorldName();
+ final BukkitWorld world = new BukkitWorld((World) pos1.getWorld());
final int p1x = pos1.getX();
final int p1z = pos1.getZ();
@@ -268,144 +174,123 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
final int tcx = p2x >> 4;
final int tcz = p2z >> 4;
- final List chunks = new ArrayList<>();
+ final QueueCoordinator queue = blockQueue.getNewQueue(world);
+ final QueueCoordinator regenQueue = blockQueue.getNewQueue(world);
+ queue.addReadChunks(
+ new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks());
+ queue.setChunkConsumer(chunk -> {
- for (int x = bcx; x <= tcx; x++) {
- for (int z = bcz; z <= tcz; z++) {
- chunks.add(BlockVector2.at(x, z));
+ 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 (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
+ AugmentedUtils
+ .bypass(ignoreAugment, () -> regenQueue.regenChunk(chunk.getX(), chunk.getZ()));
+ return;
}
- }
- final World worldObj = Bukkit.getWorld(world);
- checkNotNull(worldObj, "Critical error during regeneration.");
- final BukkitWorld bukkitWorldObj = new BukkitWorld(worldObj);
- TaskManager.runTask(new Runnable() {
- @Override public void run() {
- long start = System.currentTimeMillis();
- while (!chunks.isEmpty() && System.currentTimeMillis() - start < 5) {
- final BlockVector2 chunk = chunks.remove(0);
- int x = chunk.getX();
- int z = chunk.getZ();
- int xxb = x << 4;
- int zzb = z << 4;
- int xxt = xxb + 15;
- int zzt = zzb + 15;
- PaperLib.getChunkAtAsync(worldObj, x, z, false).thenAccept(chunkObj -> {
- if (chunkObj == null) {
- return;
- }
- final LocalBlockQueue queue = PlotSquared.platform().getGlobalBlockQueue()
- .getNewQueue(world, false);
- if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
- AugmentedUtils.bypass(ignoreAugment,
- () -> queue.regenChunkSafe(chunk.getX(), chunk.getZ()));
- return;
- }
- boolean checkX1 = false;
+ boolean checkX1 = false;
- int xxb2;
+ int xxb2;
- if (x == bcx) {
- xxb2 = p1x - 1;
- checkX1 = true;
- } else {
- xxb2 = xxb;
- }
- boolean checkX2 = false;
- int xxt2;
- if (x == tcx) {
- xxt2 = p2x + 1;
- checkX2 = true;
- } else {
- xxt2 = xxt;
- }
- boolean checkZ1 = false;
- int zzb2;
- if (z == bcz) {
- zzb2 = p1z - 1;
- checkZ1 = true;
- } else {
- zzb2 = zzb;
- }
- boolean checkZ2 = false;
- int zzt2;
- if (z == tcz) {
- zzt2 = p2z + 1;
- checkZ2 = true;
- } else {
- zzt2 = zzt;
- }
- final ContentMap map = new ContentMap();
- if (checkX1) {
- map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); //
- }
- if (checkX2) {
- map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); //
- }
- if (checkZ1) {
- map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); //
- }
- if (checkZ2) {
- map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); //
- }
- if (checkX1 && checkZ1) {
- map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); //
- }
- if (checkX2 && checkZ1) {
- map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ?
- }
- if (checkX1 && checkZ2) {
- map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ?
- }
- if (checkX2 && checkZ2) {
- map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); //
- }
- CuboidRegion currentPlotClear = RegionUtil
- .createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
- map.saveEntitiesOut(chunkObj, currentPlotClear);
- AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager
- .setChunkInPlotArea(null, new RunnableVal() {
- @Override public void run(ScopedLocalBlockQueue value) {
- Location min = value.getMin();
- int bx = min.getX();
- int bz = min.getZ();
- for (int x1 = 0; x1 < 16; x1++) {
- for (int z1 = 0; z1 < 16; z1++) {
- PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
- BaseBlock[] ids = map.allBlocks.get(plotLoc);
- if (ids != null) {
- for (int y = 0;
- y < Math.min(128, ids.length); y++) {
- BaseBlock id = ids[y];
- if (id != null) {
- value.setBlock(x1, y, z1, id);
- } else {
- value.setBlock(x1, y, z1,
- BlockTypes.AIR.getDefaultState());
- }
- }
- for (int y = Math.min(128, ids.length);
- y < ids.length; y++) {
- BaseBlock id = ids[y];
- if (id != null) {
- value.setBlock(x1, y, z1, id);
- }
- }
- }
+ if (x == bcx) {
+ xxb2 = p1x - 1;
+ checkX1 = true;
+ } else {
+ xxb2 = xxb;
+ }
+ boolean checkX2 = false;
+ int xxt2;
+ if (x == tcx) {
+ xxt2 = p2x + 1;
+ checkX2 = true;
+ } else {
+ xxt2 = xxt;
+ }
+ boolean checkZ1 = false;
+ int zzb2;
+ if (z == bcz) {
+ zzb2 = p1z - 1;
+ checkZ1 = true;
+ } else {
+ zzb2 = zzb;
+ }
+ boolean checkZ2 = false;
+ int zzt2;
+ if (z == tcz) {
+ zzt2 = p2z + 1;
+ checkZ2 = true;
+ } else {
+ zzt2 = zzt;
+ }
+ final ContentMap map = new ContentMap();
+ if (checkX1) {
+ map.saveRegion(world, xxb, xxb2, zzb2, zzt2); //
+ }
+ if (checkX2) {
+ map.saveRegion(world, xxt2, xxt, zzb2, zzt2); //
+ }
+ if (checkZ1) {
+ map.saveRegion(world, xxb2, xxt2, zzb, zzb2); //
+ }
+ if (checkZ2) {
+ map.saveRegion(world, xxb2, xxt2, zzt2, zzt); //
+ }
+ if (checkX1 && checkZ1) {
+ map.saveRegion(world, xxb, xxb2, zzb, zzb2); //
+ }
+ if (checkX2 && checkZ1) {
+ map.saveRegion(world, xxt2, xxt, zzb, zzb2); // ?
+ }
+ if (checkX1 && checkZ2) {
+ map.saveRegion(world, xxb, xxb2, zzt2, zzt); // ?
+ }
+ if (checkX2 && checkZ2) {
+ map.saveRegion(world, xxt2, xxt, zzt2, zzt); //
+ }
+ CuboidRegion currentPlotClear =
+ RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
+ map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z),
+ currentPlotClear);
+ AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager
+ .setChunkInPlotArea(null, new RunnableVal() {
+ @Override public void run(ScopedQueueCoordinator value) {
+ Location min = value.getMin();
+ int bx = min.getX();
+ int bz = min.getZ();
+ for (int x1 = 0; x1 < 16; x1++) {
+ for (int z1 = 0; z1 < 16; z1++) {
+ PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
+ BaseBlock[] ids = map.allBlocks.get(plotLoc);
+ if (ids != null) {
+ for (int y = 0; y < Math.min(128, ids.length); y++) {
+ BaseBlock id = ids[y];
+ if (id != null) {
+ value.setBlock(x1, y, z1, id);
+ } else {
+ value.setBlock(x1, y, z1,
+ BlockTypes.AIR.getDefaultState());
+ }
+ }
+ for (int y = Math.min(128, ids.length); y < ids.length; y++) {
+ BaseBlock id = ids[y];
+ if (id != null) {
+ value.setBlock(x1, y, z1, id);
}
}
}
- }, world, chunk));
- //map.restoreBlocks(worldObj, 0, 0);
- map.restoreEntities(worldObj, 0, 0);
- });
- }
- if (!chunks.isEmpty()) {
- TaskManager.runTaskLater(this, TaskTime.ticks(1L));
- } else {
- TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L));
- }
- }
+ }
+ }
+ }
+ }, world.getName(), chunk));
+ //map.restoreBlocks(worldObj, 0, 0);
+ map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0);
});
+ regenQueue.setCompleteTask(whenDone);
+ queue.setCompleteTask(regenQueue::enqueue);
+ queue.enqueue();
return true;
}
@@ -438,59 +323,6 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
}
}
- @Override
- public void swap(Location bot1, Location top1, Location bot2, Location top2,
- final Runnable whenDone) {
- CuboidRegion region1 =
- RegionUtil.createRegion(bot1.getX(), top1.getX(), bot1.getZ(), top1.getZ());
- CuboidRegion region2 =
- RegionUtil.createRegion(bot2.getX(), top2.getX(), bot2.getZ(), top2.getZ());
- final World world1 = Bukkit.getWorld(bot1.getWorldName());
- final World world2 = Bukkit.getWorld(bot2.getWorldName());
- checkNotNull(world1, "Critical error during swap.");
- checkNotNull(world2, "Critical error during swap.");
- int relX = bot2.getX() - bot1.getX();
- int relZ = bot2.getZ() - bot1.getZ();
-
- final ArrayDeque maps = new ArrayDeque<>();
-
- for (int x = bot1.getX() >> 4; x <= top1.getX() >> 4; x++) {
- for (int z = bot1.getZ() >> 4; z <= top1.getZ() >> 4; z++) {
- Chunk chunk1 = world1.getChunkAt(x, z);
- Chunk chunk2 = world2.getChunkAt(x + (relX >> 4), z + (relZ >> 4));
- maps.add(
- BukkitChunkManager.swapChunk(world1, world2, chunk1, chunk2, region1, region2));
- }
- }
- PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(() -> {
- for (ContentMap map : maps) {
- map.restoreEntities(world1, 0, 0);
- TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L));
- }
- });
- }
-
- @Override
- public void setBiome(final CuboidRegion region, final int extendBiome, final BiomeType biome,
- final String world, final Runnable whenDone) {
- Location pos1 = Location.at(world, region.getMinimumPoint().getX() - extendBiome,
- region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome);
- Location pos2 = Location.at(world, region.getMaximumPoint().getX() + extendBiome,
- region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome);
- final LocalBlockQueue queue = PlotSquared.platform().getGlobalBlockQueue()
- .getNewQueue(world, false);
-
- ChunkManager.chunkTask(pos1, pos2, new RunnableVal() {
- @Override public void run(int[] value) {
- BlockVector2 loc = BlockVector2.at(value[0], value[1]);
- PlotSquared.platform().getChunkManager().loadChunk(world, loc, false).thenRun(() -> {
- WorldUtil.setBiome(world, value[2], value[3], value[4], value[5], biome);
- queue.refreshChunk(value[0], value[1]);
- });
- }
- }, whenDone, 5);
- }
-
private void count(int[] count, Entity entity) {
final com.sk89q.worldedit.world.entity.EntityType entityType =
BukkitAdapter.adapt(entity.getType());
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java
index 64ee7e724..962af3de8 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java
@@ -25,7 +25,6 @@
*/
package com.plotsquared.bukkit.util;
-import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.bukkit.player.BukkitPlayer;
@@ -38,7 +37,6 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.util.BlockUtil;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.PlayerManager;
-import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.StringComparison;
import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.task.TaskManager;
@@ -106,12 +104,14 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.Semaphore;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.stream.Stream;
@SuppressWarnings({"unused", "WeakerAccess"})
-@Singleton public class BukkitUtil extends WorldUtil {
+@Singleton
+public class BukkitUtil extends WorldUtil {
private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitUtil.class.getSimpleName());
@@ -121,10 +121,6 @@ import java.util.stream.Stream;
private final Collection tileEntityTypes = new HashSet<>();
- @Inject public BukkitUtil(@Nonnull final RegionManager regionManager) {
- super(regionManager);
- }
-
/**
* Turn a Bukkit {@link Player} into a PlotSquared {@link PlotPlayer}
*
@@ -144,8 +140,9 @@ import java.util.stream.Stream;
* @return PlotSquared location
*/
@Nonnull public static Location adapt(@Nonnull final org.bukkit.Location location) {
- return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()),
- MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ()));
+ return Location
+ .at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()), MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()),
+ MathMan.roundInt(location.getZ()));
}
/**
@@ -156,9 +153,9 @@ import java.util.stream.Stream;
* @return PlotSquared location
*/
@Nonnull public static Location adaptComplete(@Nonnull final org.bukkit.Location location) {
- return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()),
- MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ()), location.getYaw(),
- location.getPitch());
+ return Location
+ .at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()), MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()),
+ MathMan.roundInt(location.getZ()), location.getYaw(), location.getPitch());
}
/**
@@ -169,8 +166,7 @@ import java.util.stream.Stream;
* @return Bukkit location
*/
@Nonnull public static org.bukkit.Location adapt(@Nonnull final Location location) {
- return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(), location.getX(),
- location.getY(), location.getZ());
+ return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(), location.getX(), location.getY(), location.getZ());
}
/**
@@ -183,30 +179,24 @@ import java.util.stream.Stream;
return Bukkit.getWorld(string);
}
- private static void ensureLoaded(@Nonnull final String world, final int x, final int z,
- @Nonnull final Consumer chunkConsumer) {
- PaperLib.getChunkAtAsync(Objects.requireNonNull(getWorld(world)),
- x >> 4, z >> 4, true)
+ private static void ensureLoaded(@Nonnull final String world, final int x, final int z, @Nonnull final Consumer chunkConsumer) {
+ PaperLib.getChunkAtAsync(Objects.requireNonNull(getWorld(world)), x >> 4, z >> 4, true)
.thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
}
private static void ensureLoaded(@Nonnull final Location location, @Nonnull final Consumer chunkConsumer) {
- PaperLib.getChunkAtAsync(adapt(location), true)
- .thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
+ PaperLib.getChunkAtAsync(adapt(location), true).thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
}
- private static void ensureMainThread(@Nonnull final Consumer consumer,
- @Nonnull final T value) {
+ private static void ensureMainThread(@Nonnull final Consumer consumer, @Nonnull final T value) {
if (Bukkit.isPrimaryThread()) {
consumer.accept(value);
} else {
- Bukkit.getScheduler()
- .runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> consumer.accept(value));
+ Bukkit.getScheduler().runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> consumer.accept(value));
}
}
- @Override public boolean isBlockSame(@Nonnull final BlockState block1,
- @Nonnull final BlockState block2) {
+ @Override public boolean isBlockSame(@Nonnull final BlockState block1, @Nonnull final BlockState block2) {
if (block1.equals(block2)) {
return true;
}
@@ -219,20 +209,15 @@ import java.util.stream.Stream;
return getWorld(worldName) != null;
}
- @Override public void getBiome(@Nonnull final String world, final int x,
- final int z, @Nonnull final Consumer result) {
- ensureLoaded(world, x, z,
- chunk -> result.accept(BukkitAdapter.adapt(getWorld(world).getBiome(x, z))));
+ @Override public void getBiome(@Nonnull final String world, final int x, final int z, @Nonnull final Consumer result) {
+ ensureLoaded(world, x, z, chunk -> result.accept(BukkitAdapter.adapt(getWorld(world).getBiome(x, z))));
}
- @Override @Nonnull public BiomeType getBiomeSynchronous(@Nonnull final String world,
- final int x, final int z) {
+ @Override @Nonnull public BiomeType getBiomeSynchronous(@Nonnull final String world, final int x, final int z) {
return BukkitAdapter.adapt(Objects.requireNonNull(getWorld(world)).getBiome(x, z));
}
- @Override
- public void getHighestBlock(@Nonnull final String world, final int x, final int z,
- @Nonnull final IntConsumer result) {
+ @Override public void getHighestBlock(@Nonnull final String world, final int x, final int z, @Nonnull final IntConsumer result) {
ensureLoaded(world, x, z, chunk -> {
final World bukkitWorld = Objects.requireNonNull(getWorld(world));
// Skip top and bottom block
@@ -258,9 +243,7 @@ import java.util.stream.Stream;
});
}
- @Override @Nonnegative
- public int getHighestBlockSynchronous(@Nonnull final String world,
- final int x, final int z) {
+ @Override @Nonnegative public int getHighestBlockSynchronous(@Nonnull final String world, final int x, final int z) {
final World bukkitWorld = Objects.requireNonNull(getWorld(world));
// Skip top and bottom block
int air = 1;
@@ -282,10 +265,8 @@ import java.util.stream.Stream;
return bukkitWorld.getMaxHeight() - 1;
}
- @Override @Nonnull
- public String[] getSignSynchronous(@Nonnull final Location location) {
- Block block = Objects.requireNonNull(getWorld(location.getWorldName()))
- .getBlockAt(location.getX(), location.getY(), location.getZ());
+ @Override @Nonnull public String[] getSignSynchronous(@Nonnull final Location location) {
+ Block block = Objects.requireNonNull(getWorld(location.getWorldName())).getBlockAt(location.getX(), location.getY(), location.getZ());
try {
return TaskManager.getPlatformImplementation().sync(() -> {
if (block.getState() instanceof Sign) {
@@ -300,11 +281,9 @@ import java.util.stream.Stream;
return new String[0];
}
- @Override @Nonnull
- public Location getSpawn(@Nonnull final String world) {
+ @Override @Nonnull public Location getSpawn(@Nonnull final String world) {
final org.bukkit.Location temp = getWorld(world).getSpawnLocation();
- return Location.at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(),
- temp.getYaw(), temp.getPitch());
+ return Location.at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), temp.getYaw(), temp.getPitch());
}
@Override public void setSpawn(@Nonnull final Location location) {
@@ -362,16 +341,12 @@ import java.util.stream.Stream;
});
}
- @Override @Nonnull
- public StringComparison.ComparisonResult getClosestBlock(@Nonnull String name) {
+ @Override @Nonnull public StringComparison.ComparisonResult getClosestBlock(@Nonnull String name) {
BlockState state = BlockUtil.get(name);
return new StringComparison().new ComparisonResult(1, state);
}
- @Override
- public void setBiomes(@Nonnull final String worldName,
- @Nonnull final CuboidRegion region,
- @Nonnull final BiomeType biomeType) {
+ @Override public void setBiomes(@Nonnull final String worldName, @Nonnull final CuboidRegion region, @Nonnull final BiomeType biomeType) {
final World world = getWorld(worldName);
if (world == null) {
logger.warn("[P2] An error occured while setting the biome because the world was null", new RuntimeException());
@@ -379,8 +354,7 @@ import java.util.stream.Stream;
}
final Biome biome = BukkitAdapter.adapt(biomeType);
for (int x = region.getMinimumPoint().getX(); x <= region.getMaximumPoint().getX(); x++) {
- for (int z = region.getMinimumPoint().getZ();
- z <= region.getMaximumPoint().getZ(); z++) {
+ for (int z = region.getMinimumPoint().getZ(); z <= region.getMaximumPoint().getZ(); z++) {
if (world.getBiome(x, z) != biome) {
world.setBiome(x, z, biome);
}
@@ -392,50 +366,41 @@ import java.util.stream.Stream;
return new BukkitWorld(Bukkit.getWorld(world));
}
- @Override
- public void getBlock(@Nonnull final Location location,
- @Nonnull final Consumer result) {
+ @Override public void refreshChunk(int x, int z, String world) {
+ Bukkit.getWorld(world).refreshChunk(x, z);
+ }
+
+ @Override public void getBlock(@Nonnull final Location location, @Nonnull final Consumer result) {
ensureLoaded(location, chunk -> {
final World world = getWorld(location.getWorldName());
- final Block block = Objects.requireNonNull(world)
- .getBlockAt(location.getX(), location.getY(), location.getZ());
- result.accept(Objects.requireNonNull(BukkitAdapter
- .asBlockType(block.getType())).getDefaultState());
+ final Block block = Objects.requireNonNull(world).getBlockAt(location.getX(), location.getY(), location.getZ());
+ result.accept(Objects.requireNonNull(BukkitAdapter.asBlockType(block.getType())).getDefaultState());
});
}
@Override @Nonnull public BlockState getBlockSynchronous(@Nonnull final Location location) {
final World world = getWorld(location.getWorldName());
- final Block block = Objects.requireNonNull(world)
- .getBlockAt(location.getX(), location.getY(), location.getZ());
- return Objects.requireNonNull(BukkitAdapter
- .asBlockType(block.getType())).getDefaultState();
+ final Block block = Objects.requireNonNull(world).getBlockAt(location.getX(), location.getY(), location.getZ());
+ return Objects.requireNonNull(BukkitAdapter.asBlockType(block.getType())).getDefaultState();
}
@Override @Nonnegative public double getHealth(@Nonnull final PlotPlayer player) {
- return Objects.requireNonNull(Bukkit
- .getPlayer(player.getUUID())).getHealth();
+ return Objects.requireNonNull(Bukkit.getPlayer(player.getUUID())).getHealth();
}
@Override @Nonnegative public int getFoodLevel(@Nonnull final PlotPlayer> player) {
- return Objects.requireNonNull(Bukkit.getPlayer(player.getUUID()))
- .getFoodLevel();
+ return Objects.requireNonNull(Bukkit.getPlayer(player.getUUID())).getFoodLevel();
}
- @Override public void setHealth(@Nonnull final PlotPlayer> player,
- @Nonnegative final double health) {
- Objects.requireNonNull(Bukkit.getPlayer(player.getUUID()))
- .setHealth(health);
+ @Override public void setHealth(@Nonnull final PlotPlayer> player, @Nonnegative final double health) {
+ Objects.requireNonNull(Bukkit.getPlayer(player.getUUID())).setHealth(health);
}
- @Override public void setFoodLevel(@Nonnull final PlotPlayer> player,
- @Nonnegative final int foodLevel) {
+ @Override public void setFoodLevel(@Nonnull final PlotPlayer> player, @Nonnegative final int foodLevel) {
Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel);
}
- @Override @Nonnull
- public Set getTypesInCategory(
- @Nonnull final String category) {
+ @Override @Nonnull public Set getTypesInCategory(@Nonnull final String category) {
final Collection> allowedInterfaces = new HashSet<>();
switch (category) {
case "animal": {
@@ -524,28 +489,45 @@ import java.util.stream.Stream;
tileEntityTypes.addAll(BlockCategories.FLOWER_POTS.getAll());
// Individual Types
// Add these from strings
- Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace",
- "brewing_stand", "campfire", "chest", "ender_chest", "trapped_chest",
- "command_block", "end_gateway", "hopper", "jigsaw", "jubekox",
- "lectern", "note_block", "black_shulker_box", "blue_shulker_box",
- "brown_shulker_box", "cyan_shulker_box", "gray_shulker_box", "green_shulker_box",
- "light_blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box",
- "magenta_shulker_box", "orange_shulker_box", "pink_shulker_box",
- "purple_shulker_box", "red_shulker_box", "shulker_box", "white_shulker_box",
- "yellow_shulker_box", "smoker", "structure_block", "structure_void")
- .map(BlockTypes::get)
- .filter(Objects::nonNull)
- .forEach(tileEntityTypes::add);
+ Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace", "brewing_stand", "campfire", "chest", "ender_chest",
+ "trapped_chest", "command_block", "end_gateway", "hopper", "jigsaw", "jubekox", "lectern", "note_block", "black_shulker_box",
+ "blue_shulker_box", "brown_shulker_box", "cyan_shulker_box", "gray_shulker_box", "green_shulker_box", "light_blue_shulker_box",
+ "light_gray_shulker_box", "lime_shulker_box", "magenta_shulker_box", "orange_shulker_box", "pink_shulker_box", "purple_shulker_box",
+ "red_shulker_box", "shulker_box", "white_shulker_box", "yellow_shulker_box", "smoker", "structure_block", "structure_void")
+ .map(BlockTypes::get).filter(Objects::nonNull).forEach(tileEntityTypes::add);
}
return this.tileEntityTypes;
}
- @Override @Nonnegative
- public int getTileEntityCount(@Nonnull final String world,
- @Nonnull final BlockVector2 chunk) {
+ @Override @Nonnegative public int getTileEntityCount(@Nonnull final String world, @Nonnull final BlockVector2 chunk) {
return Objects.requireNonNull(getWorld(world)).
- getChunkAt(chunk.getBlockX(), chunk.getBlockZ())
- .getTileEntities().length;
+ getChunkAt(chunk.getBlockX(), chunk.getBlockZ()).getTileEntities().length;
+ }
+
+ @Override public Set getChunkChunks(String world) {
+ Set chunks = super.getChunkChunks(world);
+ if (Bukkit.isPrimaryThread()) {
+ for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) {
+ BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5);
+ chunks.add(loc);
+ }
+ } else {
+ final Semaphore semaphore = new Semaphore(1);
+ try {
+ semaphore.acquire();
+ Bukkit.getScheduler().runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> {
+ for (Chunk chunk : Objects.requireNonNull(Bukkit.getWorld(world)).getLoadedChunks()) {
+ BlockVector2 loc = BlockVector2.at(chunk.getX() >> 5, chunk.getZ() >> 5);
+ chunks.add(loc);
+ }
+ semaphore.release();
+ });
+ semaphore.acquireUninterruptibly();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return chunks;
}
}
diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/src/main/resources/plugin.yml
index 3cfa79a65..175f201c8 100644
--- a/Bukkit/src/main/resources/plugin.yml
+++ b/Bukkit/src/main/resources/plugin.yml
@@ -6,7 +6,7 @@ load: STARTUP
description: "Easy, yet powerful Plot World generation and management."
authors: [Citymonstret, Empire92, MattBDev, dordsor21, NotMyFault, SirYwell]
website: https://www.spigotmc.org/resources/77506/
-softdepend: [Vault, PlaceholderAPI, Essentials, LuckPerms, BungeePerms]
+softdepend: [Vault, PlaceholderAPI, Essentials, LuckPerms, BungeePerms, MVdWPlaceholderAPI]
loadbefore: [MultiWorld, Multiverse-Core]
depend: [WorldEdit]
database: false
diff --git a/Core/pom.xml b/Core/pom.xml
index 05142d3a8..bb7bfa913 100644
--- a/Core/pom.xml
+++ b/Core/pom.xml
@@ -48,16 +48,10 @@
1.0
compile
-
- org.projectlombok
- lombok
- 1.18.12
- runtime
-
com.sk89q.worldedit
worldedit-core
- 7.0.0
+ 7.2.0-SNAPSHOT
runtime
@@ -74,30 +68,6 @@
-
- net.kyori
- text-api
- 3.0.2
- runtime
-
-
- net.kyori
- text-serializer-gson
- 3.0.2
- runtime
-
-
- net.kyori
- text-serializer-legacy
- 3.0.2
- runtime
-
-
- net.kyori
- text-serializer-plain
- 3.0.2
- runtime
-
com.google.guava
guava
@@ -128,6 +98,18 @@
1.7.0-SNAPSHOT
runtime
+
+ net.kyori
+ adventure-api
+ 4.0.0-SNAPSHOT
+ runtime
+
+
+ net.kyori
+ adventure-text-minimessage
+ 3.0.0-SNAPSHOT
+ runtime
+
org.apache.logging.log4j
log4j-slf4j-impl
diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java
index 0b88ca931..9153d9215 100644
--- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java
+++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java
@@ -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
}
diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java
index f487df952..e918f8daa 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Area.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Area.java
@@ -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> 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]] [=]..."));
@@ -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]] [=]..."));
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() {
- @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 areas = this.plotAreaManager.getPlotAreasSet(pa.getWorldName());
+ Set 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 areas = new ArrayList<>(Arrays.asList(this.plotAreaManager.getAllPlotAreas()));
+ final List areas =
+ new ArrayList<>(Arrays.asList(this.plotAreaManager.getAllPlotAreas()));
paginate(player, areas, 8, page,
new RunnableVal3() {
@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() {
- @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":
diff --git a/Core/src/main/java/com/plotsquared/core/command/Clear.java b/Core/src/main/java/com/plotsquared/core/command/Clear.java
index 7faf174d3..bd9478cd6 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Clear.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Clear.java
@@ -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)) {
diff --git a/Core/src/main/java/com/plotsquared/core/command/CommandCaller.java b/Core/src/main/java/com/plotsquared/core/command/CommandCaller.java
index fe517fc9a..46720f24a 100644
--- a/Core/src/main/java/com/plotsquared/core/command/CommandCaller.java
+++ b/Core/src/main/java/com/plotsquared/core/command/CommandCaller.java
@@ -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
*
diff --git a/Core/src/main/java/com/plotsquared/core/command/Debug.java b/Core/src/main/java/com/plotsquared/core/command/Debug.java
index 2741ff1c4..19e59ecf9 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Debug.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Debug.java
@@ -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])) {
diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java b/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java
index 2b257047f..10e8b3f3e 100644
--- a/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java
+++ b/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java
@@ -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()))
diff --git a/Core/src/main/java/com/plotsquared/core/command/Relight.java b/Core/src/main/java/com/plotsquared/core/command/Relight.java
index 0488f1d14..3737902b1 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Relight.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Relight.java
@@ -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 execute(final PlotPlayer> player, String[] args,
RunnableVal3 confirm,
RunnableVal2 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() {
@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);
}
diff --git a/Core/src/main/java/com/plotsquared/core/command/Set.java b/Core/src/main/java/com/plotsquared/core/command/Set.java
index b63a8a8c1..90211a409 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Set.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Set.java
@@ -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;
}
diff --git a/Core/src/main/java/com/plotsquared/core/command/Template.java b/Core/src/main/java/com/plotsquared/core/command/Template.java
index 5cf788f9a..1cf1e8c33 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Template.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Template.java
@@ -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);
});
diff --git a/Core/src/main/java/com/plotsquared/core/command/Trim.java b/Core/src/main/java/com/plotsquared/core/command/Trim.java
index 4cdb5d82f..0c471dc9b 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Trim.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Trim.java
@@ -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() {
@Override public void run(BlockVector2 value) {
queue.regenChunk(value.getX(), value.getZ());
diff --git a/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java b/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java
index 80e894322..87fb16dac 100644
--- a/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java
+++ b/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java
@@ -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) o)
- .map(ComponentPreset::deserialize).collect(Collectors.toList());
+ this.presets = yamlConfiguration.getMapList("presets").stream().map(o -> (Map) o).map(ComponentPreset::deserialize)
+ .collect(Collectors.toList());
} else {
- final List defaultPreset =
- Collections.singletonList(new ComponentPreset(ClassicPlotManagerComponent.FLOOR,
- "##wool", 0, "", "&6D&ai&cs&ec&bo &2F&3l&do&9o&4r",
+ final List 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 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;
}
diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionHolder.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionHolder.java
index bf6477235..42605bcd8 100644
--- a/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionHolder.java
+++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionHolder.java
@@ -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 .
*/
-
package com.plotsquared.core.configuration.caption;
public class CaptionHolder {
diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionLoader.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionLoader.java
index 5e6ff6a87..a5d95296d 100644
--- a/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionLoader.java
+++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/CaptionLoader.java
@@ -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
diff --git a/Core/src/main/java/com/plotsquared/core/generator/AugmentedUtils.java b/Core/src/main/java/com/plotsquared/core/generator/AugmentedUtils.java
index 0574b2422..1b42889ca 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/AugmentedUtils.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/AugmentedUtils.java
@@ -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;
}
diff --git a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java
index 787376ea3..f4849dd4e 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java
@@ -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 componentOptional =
- ClassicPlotManagerComponent.fromString(component);
+ @Override public boolean setComponent(@Nonnull PlotId plotId,
+ @Nonnull String component,
+ @Nonnull Pattern blocks,
+ @Nullable QueueCoordinator queue) {
+ final Optional 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 plotIds) {
+ @Override public boolean finishPlotMerge(@Nonnull List 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 plotIds) {
+ @Override public boolean finishPlotUnlink(@Nonnull List 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 plotIds) {
+ @Override public boolean startPlotMerge(@Nonnull List plotIds, @Nullable QueueCoordinator queue) {
return true;
}
- @Override public boolean startPlotUnlink(List plotIds) {
+ @Override public boolean startPlotUnlink(@Nonnull List 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);
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotWorld.java
index ed6789cbb..5f4dd1f3c 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotWorld.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotWorld.java
@@ -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");
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java b/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java
index e29d38bd1..2eeb89e1a 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java
@@ -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);
diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java
index b4eaed95b..13e941d2f 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java
@@ -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 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 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.
*
*/
- @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() {
- @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);
}
diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java
index 98783887f..caa4cf2d3 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java
@@ -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) {
diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java
index 85ec460e4..2a1215074 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java
@@ -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 whenDone) {
+ public void analyzeRegion(final String world, final CuboidRegion region, final RunnableVal 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() {
- @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 regions = this.regionManager.getChunkChunks(area.getWorldName());
+ Set 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 regions,
- final int extend, Set chunks) {
+ public boolean scheduleRoadUpdate(final PlotArea area, Set regions, final int extend, Set 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 iterator =
- HybridUtils.regions.iterator();
+ Iterator 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 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 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 sideRoad = new HashSet<>(
- Collections.singletonList(RegionUtil.createRegion(sx, ex, sy, ey, sz, ez)));
- final Set intersection = new HashSet<>(
- Collections.singletonList(RegionUtil.createRegion(sx, ex, sy, ty, bz, tz)));
+ Set sideRoad = new HashSet<>(Collections.singletonList(RegionUtil.createRegion(sx, ex, sy, ey, sz, ez)));
+ final Set 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() {
@Override public void run(CompoundTag value) {
schematicHandler.save(value, dir + "sideroad.schem");
schematicHandler.getCompoundTag(world, intersection, new RunnableVal() {
- @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());
}
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java
index c42e54546..f3675ab40 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java
@@ -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.
diff --git a/Core/src/main/java/com/plotsquared/core/generator/SingleWorldGenerator.java b/Core/src/main/java/com/plotsquared/core/generator/SingleWorldGenerator.java
index 12df0288f..818fd654b 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/SingleWorldGenerator.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/SingleWorldGenerator.java
@@ -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();
diff --git a/Core/src/main/java/com/plotsquared/core/generator/SquarePlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/SquarePlotManager.java
index 389214029..0cfc21a95 100644
--- a/Core/src/main/java/com/plotsquared/core/generator/SquarePlotManager.java
+++ b/Core/src/main/java/com/plotsquared/core/generator/SquarePlotManager.java
@@ -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 regions = plot.getRegions();
Runnable run = new Runnable() {
@Override public void run() {
if (regions.isEmpty()) {
- whenDone.run();
+ if (whenDone != null) {
+ whenDone.run();
+ }
return;
}
Iterator 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);
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/OffsetLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorBuilderFactory.java
similarity index 64%
rename from Core/src/main/java/com/plotsquared/core/queue/OffsetLocalBlockQueue.java
rename to Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorBuilderFactory.java
index 06233277d..c526ae731 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/OffsetLocalBlockQueue.java
+++ b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorBuilderFactory.java
@@ -23,28 +23,17 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-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);
- }
}
diff --git a/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java
new file mode 100644
index 000000000..aeb62d659
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/inject/factory/ChunkCoordinatorFactory.java
@@ -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 .
+ */
+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 chunkConsumer,
+ @Nonnull final World world,
+ @Nonnull final Collection requestedChunks,
+ @Nonnull final Runnable whenDone,
+ @Nonnull final Consumer throwableConsumer,
+ final boolean unloadAfter);
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/permissions/Permission.java b/Core/src/main/java/com/plotsquared/core/permissions/Permission.java
index ff1b913ef..7df2b69a8 100644
--- a/Core/src/main/java/com/plotsquared/core/permissions/Permission.java
+++ b/Core/src/main/java/com/plotsquared/core/permissions/Permission.java
@@ -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
diff --git a/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java b/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java
index 5edf2d0ef..7ba30fdd3 100644
--- a/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java
+++ b/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java
@@ -139,10 +139,6 @@ public class ConsolePlayer extends PlotPlayer {
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);
diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java
index 718d3d97a..0e59b2024 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java
@@ -31,7 +31,6 @@ import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.command.Like;
-import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.configuration.ConfigurationUtil;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.Caption;
@@ -51,6 +50,7 @@ import com.plotsquared.core.location.BlockLoc;
import com.plotsquared.core.location.Direction;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.location.PlotLoc;
+import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.comment.PlotComment;
@@ -66,7 +66,7 @@ import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag;
import com.plotsquared.core.plot.flag.types.DoubleFlag;
import com.plotsquared.core.plot.schematic.Schematic;
import com.plotsquared.core.queue.GlobalBlockQueue;
-import com.plotsquared.core.queue.LocalBlockQueue;
+import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.Permissions;
@@ -142,15 +142,13 @@ public class Plot {
private static final Logger logger = LoggerFactory.getLogger("P2/" + Plot.class.getSimpleName());
private static final DecimalFormat FLAG_DECIMAL_FORMAT = new DecimalFormat("0");
- static {
- FLAG_DECIMAL_FORMAT.setMaximumFractionDigits(340);
- }
-
private static final MiniMessage MINI_MESSAGE = MiniMessage.builder().build();
private static Set connected_cache;
private static Set regions_cache;
-
+ static {
+ FLAG_DECIMAL_FORMAT.setMaximumFractionDigits(340);
+ }
/**
* Plot flag container
*/
@@ -275,9 +273,18 @@ public class Plot {
* @param merged an array giving merged plots
* @see Plot#getPlot(Location) for existing plots
*/
- public Plot(@Nonnull PlotId id, UUID owner, HashSet trusted, HashSet members,
- HashSet denied, String alias, BlockLoc position, Collection> flags,
- PlotArea area, boolean[] merged, long timestamp, int temp) {
+ public Plot(@Nonnull PlotId id,
+ UUID owner,
+ HashSet trusted,
+ HashSet members,
+ HashSet denied,
+ String alias,
+ BlockLoc position,
+ Collection> flags,
+ PlotArea area,
+ boolean[] merged,
+ long timestamp,
+ int temp) {
this.id = id;
this.area = area;
this.owner = owner;
@@ -309,8 +316,7 @@ public class Plot {
* @param message If a message should be sent to the player if a plot cannot be found
* @return The plot if only 1 result is found, or null
*/
- @Nullable public static Plot getPlotFromString(PlotPlayer> player, String arg,
- boolean message) {
+ @Nullable public static Plot getPlotFromString(PlotPlayer> player, String arg, boolean message) {
if (arg == null) {
if (player == null) {
if (message) {
@@ -332,8 +338,7 @@ public class Plot {
String[] split = arg.split(";|,");
PlotId id;
if (split.length == 4) {
- area = PlotSquared.get().getPlotAreaManager()
- .getPlotAreaByString(split[0] + ';' + split[1]);
+ area = PlotSquared.get().getPlotAreaManager().getPlotAreaByString(split[0] + ';' + split[1]);
id = PlotId.fromString(split[2] + ';' + split[3]);
} else if (split.length == 3) {
area = PlotSquared.get().getPlotAreaManager().getPlotAreaByString(split[0]);
@@ -412,8 +417,7 @@ public class Plot {
return null;
}
- @Nonnull private static Location[] getCorners(@Nonnull final String world,
- @Nonnull final CuboidRegion region) {
+ @Nonnull private static Location[] getCorners(@Nonnull final String world, @Nonnull final CuboidRegion region) {
final BlockVector3 min = region.getMinimumPoint();
final BlockVector3 max = region.getMaximumPoint();
return new Location[] {Location.at(world, min), Location.at(world, max)};
@@ -612,8 +616,7 @@ public class Plot {
UUID last = this.getOwner();
owners.add(this.getOwner());
for (Plot current : array) {
- if (last == null || current.getOwner().getMostSignificantBits() != last
- .getMostSignificantBits()) {
+ if (last == null || current.getOwner().getMostSignificantBits() != last.getMostSignificantBits()) {
owners.add(current.getOwner());
last = current.getOwner();
}
@@ -655,8 +658,8 @@ public class Plot {
* @return boolean false if the player is allowed to enter
*/
public boolean isDenied(UUID uuid) {
- return this.denied != null && (this.denied.contains(DBFunc.EVERYONE) && !this.isAdded(uuid)
- || !this.isAdded(uuid) && this.denied.contains(uuid));
+ return this.denied != null && (this.denied.contains(DBFunc.EVERYONE) && !this.isAdded(uuid) || !this.isAdded(uuid) && this.denied
+ .contains(uuid));
}
/**
@@ -780,8 +783,7 @@ public class Plot {
* @return true if this plot is merged, otherwise false
*/
public boolean isMerged() {
- return getSettings().getMerged(0) || getSettings().getMerged(2) || getSettings()
- .getMerged(1) || getSettings().getMerged(3);
+ return getSettings().getMerged(0) || getSettings().getMerged(2) || getSettings().getMerged(1) || getSettings().getMerged(3);
}
/**
@@ -832,10 +834,8 @@ public class Plot {
int i2 = 0;
if (this.getSettings().getMerged(i2)) {
if (this.getSettings().getMerged(i)) {
- if (this.area.getPlotAbs(this.id.getRelative(Direction.getFromIndex(i)))
- .getMerged(i2)) {
- return this.area.getPlotAbs(this.id.getRelative(Direction.getFromIndex(i2)))
- .getMerged(i);
+ if (this.area.getPlotAbs(this.id.getRelative(Direction.getFromIndex(i))).getMerged(i2)) {
+ return this.area.getPlotAbs(this.id.getRelative(Direction.getFromIndex(i2))).getMerged(i);
}
}
}
@@ -845,9 +845,8 @@ public class Plot {
case 6:
i = dir - 4;
i2 = dir - 3;
- return this.getSettings().getMerged(i2) && this.getSettings().getMerged(i)
- && this.area.getPlotAbs(this.id.getRelative(Direction.getFromIndex(i)))
- .getMerged(i2) && this.area
+ return this.getSettings().getMerged(i2) && this.getSettings().getMerged(i) && this.area
+ .getPlotAbs(this.id.getRelative(Direction.getFromIndex(i))).getMerged(i2) && this.area
.getPlotAbs(this.id.getRelative(Direction.getFromIndex(i2))).getMerged(i);
}
@@ -1049,8 +1048,7 @@ public class Plot {
this.removeSign();
}
PlotUnlinkEvent event = this.eventDispatcher
- .callUnlink(getArea(), this, true, !isDelete,
- isDelete ? PlotUnlinkEvent.REASON.DELETE : PlotUnlinkEvent.REASON.CLEAR);
+ .callUnlink(getArea(), this, true, !isDelete, isDelete ? PlotUnlinkEvent.REASON.DELETE : PlotUnlinkEvent.REASON.CLEAR);
if (event.getEventResult() != Result.DENY) {
this.unlinkPlot(event.isCreateRoad(), event.isCreateSign());
}
@@ -1065,28 +1063,31 @@ public class Plot {
}
TaskManager.runTask(whenDone);
};
+ QueueCoordinator queue = getArea().getQueue();
for (Plot current : plots) {
if (isDelete || !current.hasOwner()) {
- manager.unClaimPlot(current, null);
+ manager.unClaimPlot(current, null, queue);
} else {
- manager.claimPlot(current);
+ manager.claimPlot(current, queue);
}
}
- blockQueue.addEmptyTask(run);
+ if (queue.size() > 0) {
+ queue.enqueue();
+ }
+ TaskManager.runTask(run);
return;
}
Plot current = queue.poll();
if (Plot.this.area.getTerrain() != PlotAreaTerrainType.NONE) {
try {
- regionManager.regenerateRegion(current.getBottomAbs(), current.getTopAbs(), false,
- this);
+ regionManager.regenerateRegion(current.getBottomAbs(), current.getTopAbs(), false, this);
} catch (UnsupportedOperationException exception) {
logger.info("[P2] Please ask md_5 to fix regenerateChunk() because it breaks plugins. We apologize for the inconvenience.");
return;
}
return;
}
- manager.clearPlot(current, this);
+ manager.clearPlot(current, this, null);
}
};
run.run();
@@ -1138,26 +1139,28 @@ public class Plot {
ids.add(current.getId());
}
this.clearRatings();
+ QueueCoordinator queue = null;
if (createSign) {
this.removeSign();
+ queue = getArea().getQueue();
}
PlotManager manager = this.area.getPlotManager();
if (createRoad) {
- manager.startPlotUnlink(ids);
+ manager.startPlotUnlink(ids, queue);
}
if (this.area.getTerrain() != PlotAreaTerrainType.ALL && createRoad) {
for (Plot current : plots) {
if (current.getMerged(Direction.EAST)) {
- manager.createRoadEast(current);
+ manager.createRoadEast(current, queue);
if (current.getMerged(Direction.SOUTH)) {
- manager.createRoadSouth(current);
+ manager.createRoadSouth(current, queue);
if (current.getMerged(Direction.SOUTHEAST)) {
- manager.createRoadSouthEast(current);
+ manager.createRoadSouthEast(current, queue);
}
}
}
if (current.getMerged(Direction.SOUTH)) {
- manager.createRoadSouth(current);
+ manager.createRoadSouth(current, queue);
}
}
}
@@ -1166,16 +1169,14 @@ public class Plot {
current.setMerged(merged);
}
if (createSign) {
- blockQueue.addEmptyTask(() -> {
- TaskManager.runTaskAsync(() -> {
- for (Plot current : plots) {
- current.setSign(PlayerManager.getName(current.getOwnerAbs()));
- }
- });
- });
+ queue.setCompleteTask(() -> TaskManager.runTaskAsync(() -> {
+ for (Plot current : plots) {
+ current.setSign(PlayerManager.getName(current.getOwnerAbs()));
+ }
+ }));
}
if (createRoad) {
- manager.finishPlotUnlink(ids);
+ manager.finishPlotUnlink(ids, queue);
}
return true;
}
@@ -1281,14 +1282,12 @@ public class Plot {
* @param ignorePluginFlags Whether or not to ignore {@link InternalFlag internal flags}
* @return Collection containing all the flags that matched the given criteria
*/
- public Collection> getApplicableFlags(final boolean plotOnly,
- final boolean ignorePluginFlags) {
+ public Collection> getApplicableFlags(final boolean plotOnly, final boolean ignorePluginFlags) {
if (!hasOwner()) {
return Collections.emptyList();
}
final Map, PlotFlag, ?>> flags = new HashMap<>();
- if (!plotOnly && getArea() != null && !getArea().getFlagContainer().getFlagMap()
- .isEmpty()) {
+ if (!plotOnly && getArea() != null && !getArea().getFlagContainer().getFlagMap().isEmpty()) {
final Map, PlotFlag, ?>> flagMap = getArea().getFlagContainer().getFlagMap();
flags.putAll(flagMap);
}
@@ -1446,8 +1445,7 @@ public class Plot {
if (Settings.Backup.DELETE_ON_UNCLAIM) {
// Destroy all backups when the plot is unclaimed
- Objects.requireNonNull(PlotSquared.platform()).getBackupManager().getProfile(current)
- .destroy();
+ Objects.requireNonNull(PlotSquared.platform()).getBackupManager().getProfile(current).destroy();
}
getArea().removePlot(getId());
@@ -1475,8 +1473,8 @@ public class Plot {
Location[] corners = getCorners();
Location top = corners[0];
Location bot = corners[1];
- Location location = Location.at(this.getWorldName(), MathMan.average(bot.getX(), top.getX()),
- MathMan.average(bot.getY(), top.getY()), MathMan.average(bot.getZ(), top.getZ()));
+ Location location = Location.at(this.getWorldName(), MathMan.average(bot.getX(), top.getX()), MathMan.average(bot.getY(), top.getY()),
+ MathMan.average(bot.getZ(), top.getZ()));
if (!isLoaded()) {
result.accept(location);
return;
@@ -1497,8 +1495,8 @@ public class Plot {
Location[] corners = getCorners();
Location top = corners[0];
Location bot = corners[1];
- Location location = Location.at(this.getWorldName(), MathMan.average(bot.getX(), top.getX()),
- MathMan.average(bot.getY(), top.getY()), MathMan.average(bot.getZ(), top.getZ()));
+ Location location = Location.at(this.getWorldName(), MathMan.average(bot.getX(), top.getX()), MathMan.average(bot.getY(), top.getY()),
+ MathMan.average(bot.getZ(), top.getZ()));
if (!isLoaded()) {
return location;
}
@@ -1514,8 +1512,7 @@ public class Plot {
*/
@Deprecated public Location getSideSynchronous() {
CuboidRegion largest = getLargestRegion();
- int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1)
- + largest.getMinimumPoint().getX();
+ int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1) + largest.getMinimumPoint().getX();
int z = largest.getMinimumPoint().getZ() - 1;
PlotManager manager = getManager();
int y = isLoaded() ? this.worldUtil.getHighestBlockSynchronous(getWorldName(), x, z) : 62;
@@ -1527,8 +1524,7 @@ public class Plot {
public void getSide(Consumer result) {
CuboidRegion largest = getLargestRegion();
- int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1)
- + largest.getMinimumPoint().getX();
+ int x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1) + largest.getMinimumPoint().getX();
int z = largest.getMinimumPoint().getZ() - 1;
PlotManager manager = getManager();
if (isLoaded()) {
@@ -1557,15 +1553,15 @@ public class Plot {
return this.getDefaultHomeSynchronous(true);
} else {
Location bottom = this.getBottomAbs();
- Location location = Location.at(bottom.getWorldName(), bottom.getX() + home.getX(),
- bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(),
- home.getPitch());
+ Location location = Location
+ .at(bottom.getWorldName(), bottom.getX() + home.getX(), bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(),
+ home.getPitch());
if (!isLoaded()) {
return location;
}
if (!this.worldUtil.getBlockSynchronous(location).getBlockType().getMaterial().isAir()) {
- location = location.withY(Math.max(1 + this.worldUtil.getHighestBlockSynchronous(this.getWorldName(), location.getX(),
- location.getZ()), bottom.getY()));
+ location = location.withY(
+ Math.max(1 + this.worldUtil.getHighestBlockSynchronous(this.getWorldName(), location.getX(), location.getZ()), bottom.getY()));
}
return location;
}
@@ -1580,9 +1576,9 @@ public class Plot {
this.getDefaultHome(result);
} else {
Location bottom = this.getBottomAbs();
- Location location = Location.at(bottom.getWorldName(), bottom.getX() + home.getX(),
- bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(),
- home.getPitch());
+ Location location = Location
+ .at(bottom.getWorldName(), bottom.getX() + home.getX(), bottom.getY() + home.getY(), bottom.getZ() + home.getZ(), home.getYaw(),
+ home.getPitch());
if (!isLoaded()) {
result.accept(location);
return;
@@ -1590,7 +1586,7 @@ public class Plot {
this.worldUtil.getBlock(location, block -> {
if (!block.getBlockType().getMaterial().isAir()) {
this.worldUtil.getHighestBlock(this.getWorldName(), location.getX(), location.getZ(),
- y -> result.accept(location.withY(Math.max(1 + y, bottom.getY()))));
+ y -> result.accept(location.withY(Math.max(1 + y, bottom.getY()))));
} else {
result.accept(location);
}
@@ -1636,21 +1632,15 @@ public class Plot {
if (loc.getX() == Integer.MAX_VALUE && loc.getZ() == Integer.MAX_VALUE) {
// center
CuboidRegion largest = plot.getLargestRegion();
- x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX()
- >> 1) + largest.getMinimumPoint().getX();
- z = (largest.getMaximumPoint().getZ() >> 1) - (largest.getMinimumPoint().getZ()
- >> 1) + largest.getMinimumPoint().getZ();
+ x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1) + largest.getMinimumPoint().getX();
+ z = (largest.getMaximumPoint().getZ() >> 1) - (largest.getMinimumPoint().getZ() >> 1) + largest.getMinimumPoint().getZ();
} else {
// specific
Location bot = plot.getBottomAbs();
x = bot.getX() + loc.getX();
z = bot.getZ() + loc.getZ();
}
- int y = loc.getY() < 1 ?
- (isLoaded() ?
- this.worldUtil.getHighestBlockSynchronous(plot.getWorldName(), x, z) + 1 :
- 63) :
- loc.getY();
+ int y = loc.getY() < 1 ? (isLoaded() ? this.worldUtil.getHighestBlockSynchronous(plot.getWorldName(), x, z) + 1 : 63) : loc.getY();
return Location.at(plot.getWorldName(), x, y, z);
}
// Side
@@ -1666,10 +1656,8 @@ public class Plot {
if (loc.getX() == Integer.MAX_VALUE && loc.getZ() == Integer.MAX_VALUE) {
// center
CuboidRegion largest = plot.getLargestRegion();
- x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX()
- >> 1) + largest.getMinimumPoint().getX();
- z = (largest.getMaximumPoint().getZ() >> 1) - (largest.getMinimumPoint().getZ()
- >> 1) + largest.getMinimumPoint().getZ();
+ x = (largest.getMaximumPoint().getX() >> 1) - (largest.getMinimumPoint().getX() >> 1) + largest.getMinimumPoint().getX();
+ z = (largest.getMaximumPoint().getZ() >> 1) - (largest.getMinimumPoint().getZ() >> 1) + largest.getMinimumPoint().getZ();
} else {
// specific
Location bot = plot.getBottomAbs();
@@ -1678,8 +1666,7 @@ public class Plot {
}
if (loc.getY() < 1) {
if (isLoaded()) {
- this.worldUtil.getHighestBlock(plot.getWorldName(), x, z,
- y -> result.accept(Location.at(plot.getWorldName(), x, y + 1, z)));
+ this.worldUtil.getHighestBlock(plot.getWorldName(), x, z, y -> result.accept(Location.at(plot.getWorldName(), x, y + 1, z)));
} else {
result.accept(Location.at(plot.getWorldName(), x, 63, z));
}
@@ -1695,10 +1682,8 @@ public class Plot {
public double getVolume() {
double count = 0;
for (CuboidRegion region : getRegions()) {
- count +=
- (region.getMaximumPoint().getX() - (double) region.getMinimumPoint().getX() + 1) * (
- region.getMaximumPoint().getZ() - (double) region.getMinimumPoint().getZ() + 1)
- * MAX_HEIGHT;
+ count += (region.getMaximumPoint().getX() - (double) region.getMinimumPoint().getX() + 1) * (
+ region.getMaximumPoint().getZ() - (double) region.getMinimumPoint().getZ() + 1) * MAX_HEIGHT;
}
return count;
}
@@ -1781,15 +1766,13 @@ public class Plot {
* This should not need to be called
*/
public void refreshChunks() {
- LocalBlockQueue queue = this.blockQueue.getNewQueue(getWorldName(), false);
+ QueueCoordinator queue = this.blockQueue.getNewQueue(PlotSquared.platform().getWorldUtil().getWeWorld(getWorldName()));
HashSet chunks = new HashSet<>();
for (CuboidRegion region : Plot.this.getRegions()) {
- for (int x = region.getMinimumPoint().getX() >> 4;
- x <= region.getMaximumPoint().getX() >> 4; x++) {
- for (int z = region.getMinimumPoint().getZ() >> 4;
- z <= region.getMaximumPoint().getZ() >> 4; z++) {
+ for (int x = region.getMinimumPoint().getX() >> 4; x <= region.getMaximumPoint().getX() >> 4; x++) {
+ for (int z = region.getMinimumPoint().getZ() >> 4; z <= region.getMaximumPoint().getZ() >> 4; z++) {
if (chunks.add(BlockVector2.at(x, z))) {
- queue.refreshChunk(x, z);
+ worldUtil.refreshChunk(x, z, getWorldName());
}
}
}
@@ -1805,10 +1788,9 @@ public class Plot {
return;
}
Location location = manager.getSignLoc(this);
- LocalBlockQueue queue = this.blockQueue.getNewQueue(getWorldName(), false);
- queue.setBlock(location.getX(), location.getY(), location.getZ(),
- BlockTypes.AIR.getDefaultState());
- queue.flush();
+ QueueCoordinator queue = this.blockQueue.getNewQueue(worldUtil.getWeWorld(getWorldName()));
+ queue.setBlock(location.getX(), location.getY(), location.getZ(), BlockTypes.AIR.getDefaultState());
+ queue.enqueue();
}
/**
@@ -1819,8 +1801,7 @@ public class Plot {
this.setSign("unknown");
return;
}
- this.impromptuPipeline.getSingle(this.getOwnerAbs(), (username, sign) ->
- this.setSign(username));
+ this.impromptuPipeline.getSingle(this.getOwnerAbs(), (username, sign) -> this.setSign(username));
}
/**
@@ -1842,13 +1823,12 @@ public class Plot {
return claim(player, teleport, schematic, true);
}
- public boolean claim(@Nonnull final PlotPlayer player, boolean teleport, String schematic,
- boolean updateDB) {
+ public boolean claim(@Nonnull final PlotPlayer player, boolean teleport, String schematic, boolean updateDB) {
if (updateDB) {
if (!create(player.getUUID(), true)) {
- logger.error("[P2] Player {} attempted to claim plot {}, but the database failed to update",
- player.getName(), this.getId().toCommaSeparatedString());
+ logger.error("[P2] Player {} attempted to claim plot {}, but the database failed to update", player.getName(),
+ this.getId().toCommaSeparatedString());
return false;
}
} else {
@@ -1877,18 +1857,17 @@ public class Plot {
e.printStackTrace();
return true;
}
- schematicHandler.paste(sch, this, 0, 1, 0, Settings.Schematics.PASTE_ON_TOP,
- new RunnableVal() {
- @Override public void run(Boolean value) {
- if (value) {
- player.sendMessage(TranslatableCaption.of("schematics.schematic_paste_success"));
- } else {
- player.sendMessage(TranslatableCaption.of("schematics.schematic_paste_failed"));
- }
+ schematicHandler.paste(sch, this, 0, 1, 0, Settings.Schematics.PASTE_ON_TOP, new RunnableVal() {
+ @Override public void run(Boolean value) {
+ if (value) {
+ player.sendMessage(TranslatableCaption.of("schematics.schematic_paste_success"));
+ } else {
+ player.sendMessage(TranslatableCaption.of("schematics.schematic_paste_failed"));
}
- });
+ }
+ });
}
- plotworld.getPlotManager().claimPlot(this);
+ plotworld.getPlotManager().claimPlot(this, null);
return true;
}
@@ -1925,11 +1904,9 @@ public class Plot {
DBFunc.createPlotAndSettings(this, () -> {
PlotArea plotworld = Plot.this.area;
if (notify && plotworld.isAutoMerge()) {
- final PlotPlayer> player = PlotSquared.platform().getPlayerManager()
- .getPlayerIfExists(uuid);
+ final PlotPlayer> player = PlotSquared.platform().getPlayerManager().getPlayerIfExists(uuid);
- PlotMergeEvent event = this.eventDispatcher
- .callMerge(this, Direction.ALL, Integer.MAX_VALUE, player);
+ PlotMergeEvent event = this.eventDispatcher.callMerge(this, Direction.ALL, Integer.MAX_VALUE, player);
if (event.getEventResult() == Result.DENY) {
if (player != null) {
@@ -1943,8 +1920,7 @@ public class Plot {
});
return true;
}
- logger.info("[P2] Failed to add plot {} to plot area {}",
- this.getId().toCommaSeparatedString(), this.area.toString());
+ logger.info("[P2] Failed to add plot {} to plot area {}", this.getId().toCommaSeparatedString(), this.area.toString());
return false;
}
@@ -1952,12 +1928,12 @@ public class Plot {
* Sets components such as border, wall, floor.
* (components are generator specific)
*/
- @Deprecated public boolean setComponent(String component, String blocks) {
+ @Deprecated public boolean setComponent(String component, String blocks, QueueCoordinator queue) {
BlockBucket parsed = ConfigurationUtil.BLOCK_BUCKET.parseString(blocks);
if (parsed != null && parsed.isEmpty()) {
return false;
}
- return this.setComponent(component, parsed.toPattern());
+ return this.setComponent(component, parsed.toPattern(), queue);
}
//TODO Better documentation needed.
@@ -1966,8 +1942,7 @@ public class Plot {
* Retrieve the biome of the plot.
*/
public void getBiome(Consumer result) {
- this.getCenter(location -> this.worldUtil
- .getBiome(location.getWorldName(), location.getX(), location.getZ(), result));
+ this.getCenter(location -> this.worldUtil.getBiome(location.getWorldName(), location.getX(), location.getZ(), result));
}
//TODO Better documentation needed.
@@ -1977,8 +1952,7 @@ public class Plot {
*/
@Deprecated public BiomeType getBiomeSynchronous() {
final Location location = this.getCenterSynchronous();
- return this.worldUtil
- .getBiomeSynchronous(location.getWorldName(), location.getX(), location.getZ());
+ return this.worldUtil.getBiomeSynchronous(location.getWorldName(), location.getX(), location.getZ());
}
/**
@@ -2108,19 +2082,20 @@ public class Plot {
/**
* Remove the east road section of a plot
* - Used when a plot is merged
+ *
+ * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
+ * otherwise writes to the queue but does not enqueue.
*/
- public void removeRoadEast() {
- if (this.area.getType() != PlotAreaType.NORMAL
- && this.area.getTerrain() == PlotAreaTerrainType.ROAD) {
+ public void removeRoadEast(@Nullable QueueCoordinator queue) {
+ if (this.area.getType() != PlotAreaType.NORMAL && this.area.getTerrain() == PlotAreaTerrainType.ROAD) {
Plot other = this.getRelative(Direction.EAST);
Location bot = other.getBottomAbs();
Location top = this.getTopAbs();
Location pos1 = Location.at(this.getWorldName(), top.getX(), 0, bot.getZ());
Location pos2 = Location.at(this.getWorldName(), bot.getX(), MAX_HEIGHT, top.getZ());
this.regionManager.regenerateRegion(pos1, pos2, true, null);
- } else if (this.area.getTerrain()
- != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
- this.area.getPlotManager().removeRoadEast(this);
+ } else if (this.area.getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
+ this.area.getPlotManager().removeRoadEast(this, queue);
}
}
@@ -2279,10 +2254,8 @@ public class Plot {
}
} else {
TaskManager.runTaskAsync(() -> {
- String name = Plot.this.id + "," + Plot.this.area + ',' +
- PlayerManager.getName(Plot.this.getOwnerAbs());
- boolean result = schematicHandler.save(value,
- Settings.Paths.SCHEMATICS + File.separator + name + ".schem");
+ String name = Plot.this.id + "," + Plot.this.area + ',' + PlayerManager.getName(Plot.this.getOwnerAbs());
+ boolean result = schematicHandler.save(value, Settings.Paths.SCHEMATICS + File.separator + name + ".schem");
if (whenDone != null) {
whenDone.value = result;
TaskManager.runTask(whenDone);
@@ -2329,8 +2302,7 @@ public class Plot {
return false;
}
Plot other = (Plot) obj;
- return this.hashCode() == other.hashCode() && this.id.equals(other.id)
- && this.area == other.area;
+ return this.hashCode() == other.hashCode() && this.id.equals(other.id) && this.area == other.area;
}
/**
@@ -2351,7 +2323,7 @@ public class Plot {
*
* @return The plot alias
*/
- public String getAlias() {
+ @Nonnull public String getAlias() {
if (this.settings == null) {
return "";
}
@@ -2390,8 +2362,9 @@ public class Plot {
if (value) {
Plot other = this.getRelative(direction).getBasePlot(false);
if (!other.equals(this.getBasePlot(false))) {
- Plot base = other.id.getY() < this.id.getY()
- || other.id.getY() == this.id.getY() && other.id.getX() < this.id.getX() ? other : this.origin;
+ Plot base = other.id.getY() < this.id.getY() || other.id.getY() == this.id.getY() && other.id.getX() < this.id.getX() ?
+ other :
+ this.origin;
this.origin.origin = base;
other.origin = base;
this.origin = base;
@@ -2464,8 +2437,7 @@ public class Plot {
public boolean canClaim(@Nonnull PlotPlayer player) {
PlotCluster cluster = this.getCluster();
if (cluster != null) {
- if (!cluster.isAdded(player.getUUID()) && !Permissions
- .hasPermission(player, "plots.admin.command.claim")) {
+ if (!cluster.isAdded(player.getUUID()) && !Permissions.hasPermission(player, "plots.admin.command.claim")) {
return false;
}
}
@@ -2479,19 +2451,20 @@ public class Plot {
/**
* Remove the south road section of a plot
* - Used when a plot is merged
+ *
+ * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
+ * otherwise writes to the queue but does not enqueue.
*/
- public void removeRoadSouth() {
- if (this.area.getType() != PlotAreaType.NORMAL
- && this.area.getTerrain() == PlotAreaTerrainType.ROAD) {
+ public void removeRoadSouth(@Nullable QueueCoordinator queue) {
+ if (this.area.getType() != PlotAreaType.NORMAL && this.area.getTerrain() == PlotAreaTerrainType.ROAD) {
Plot other = this.getRelative(Direction.SOUTH);
Location bot = other.getBottomAbs();
Location top = this.getTopAbs();
Location pos1 = Location.at(this.getWorldName(), bot.getX(), 0, top.getZ());
Location pos2 = Location.at(this.getWorldName(), top.getX(), MAX_HEIGHT, bot.getZ());
this.regionManager.regenerateRegion(pos1, pos2, true, null);
- } else if (this.area.getTerrain()
- != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
- this.getManager().removeRoadSouth(this);
+ } else if (this.area.getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
+ this.getManager().removeRoadSouth(this, queue);
}
}
@@ -2510,12 +2483,12 @@ public class Plot {
return false;
}
Set connected = this.getConnectedPlots();
- HashSet merged =
- connected.stream().map(Plot::getId).collect(Collectors.toCollection(HashSet::new));
+ HashSet merged = connected.stream().map(Plot::getId).collect(Collectors.toCollection(HashSet::new));
ArrayDeque frontier = new ArrayDeque<>(connected);
Plot current;
boolean toReturn = false;
HashSet visited = new HashSet<>();
+ QueueCoordinator queue = getArea().getQueue();
while ((current = frontier.poll()) != null && max >= 0) {
if (visited.contains(current)) {
continue;
@@ -2524,11 +2497,9 @@ public class Plot {
Set plots;
if ((dir == Direction.ALL || dir == Direction.NORTH) && !getMerged(Direction.NORTH)) {
Plot other = current.getRelative(Direction.NORTH);
- if (other != null && other.isOwner(uuid) && (
- other.getBasePlot(false).equals(current.getBasePlot(false))
- || (plots = other.getConnectedPlots()).size() <= max && frontier
- .addAll(plots) && (max -= plots.size()) != -1)) {
- current.mergePlot(other, removeRoads);
+ if (other != null && other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false))
+ || (plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1)) {
+ current.mergePlot(other, removeRoads, queue);
merged.add(current.getId());
merged.add(other.getId());
toReturn = true;
@@ -2537,18 +2508,15 @@ public class Plot {
ArrayList ids = new ArrayList<>();
ids.add(current.getId());
ids.add(other.getId());
- this.getManager().finishPlotMerge(ids);
+ this.getManager().finishPlotMerge(ids, queue);
}
}
}
- if (max >= 0 && (dir == Direction.ALL || dir == Direction.EAST) && !current
- .getMerged(Direction.EAST)) {
+ if (max >= 0 && (dir == Direction.ALL || dir == Direction.EAST) && !current.getMerged(Direction.EAST)) {
Plot other = current.getRelative(Direction.EAST);
- if (other != null && other.isOwner(uuid) && (
- other.getBasePlot(false).equals(current.getBasePlot(false))
- || (plots = other.getConnectedPlots()).size() <= max && frontier
- .addAll(plots) && (max -= plots.size()) != -1)) {
- current.mergePlot(other, removeRoads);
+ if (other != null && other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false))
+ || (plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1)) {
+ current.mergePlot(other, removeRoads, queue);
merged.add(current.getId());
merged.add(other.getId());
toReturn = true;
@@ -2557,18 +2525,15 @@ public class Plot {
ArrayList ids = new ArrayList<>();
ids.add(current.getId());
ids.add(other.getId());
- this.getManager().finishPlotMerge(ids);
+ this.getManager().finishPlotMerge(ids, queue);
}
}
}
- if (max >= 0 && (dir == Direction.ALL || dir == Direction.SOUTH) && !getMerged(
- Direction.SOUTH)) {
+ if (max >= 0 && (dir == Direction.ALL || dir == Direction.SOUTH) && !getMerged(Direction.SOUTH)) {
Plot other = current.getRelative(Direction.SOUTH);
- if (other != null && other.isOwner(uuid) && (
- other.getBasePlot(false).equals(current.getBasePlot(false))
- || (plots = other.getConnectedPlots()).size() <= max && frontier
- .addAll(plots) && (max -= plots.size()) != -1)) {
- current.mergePlot(other, removeRoads);
+ if (other != null && other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false))
+ || (plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1)) {
+ current.mergePlot(other, removeRoads, queue);
merged.add(current.getId());
merged.add(other.getId());
toReturn = true;
@@ -2577,18 +2542,15 @@ public class Plot {
ArrayList ids = new ArrayList<>();
ids.add(current.getId());
ids.add(other.getId());
- this.getManager().finishPlotMerge(ids);
+ this.getManager().finishPlotMerge(ids, queue);
}
}
}
- if (max >= 0 && (dir == Direction.ALL || dir == Direction.WEST) && !getMerged(
- Direction.WEST)) {
+ if (max >= 0 && (dir == Direction.ALL || dir == Direction.WEST) && !getMerged(Direction.WEST)) {
Plot other = current.getRelative(Direction.WEST);
- if (other != null && other.isOwner(uuid) && (
- other.getBasePlot(false).equals(current.getBasePlot(false))
- || (plots = other.getConnectedPlots()).size() <= max && frontier
- .addAll(plots) && (max -= plots.size()) != -1)) {
- current.mergePlot(other, removeRoads);
+ if (other != null && other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false))
+ || (plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1)) {
+ current.mergePlot(other, removeRoads, queue);
merged.add(current.getId());
merged.add(other.getId());
toReturn = true;
@@ -2597,10 +2559,13 @@ public class Plot {
ArrayList ids = new ArrayList<>();
ids.add(current.getId());
ids.add(other.getId());
- this.getManager().finishPlotMerge(ids);
+ this.getManager().finishPlotMerge(ids, queue);
}
}
}
+ if (queue.size() > 0) {
+ queue.enqueue();
+ }
}
return toReturn;
}
@@ -2615,8 +2580,7 @@ public class Plot {
final FlagContainer flagContainer1 = this.getFlagContainer();
final FlagContainer flagContainer2 = plot.getFlagContainer();
if (!flagContainer1.equals(flagContainer2)) {
- boolean greater =
- flagContainer1.getFlagMap().size() > flagContainer2.getFlagMap().size();
+ boolean greater = flagContainer1.getFlagMap().size() > flagContainer2.getFlagMap().size();
if (greater) {
flagContainer1.addAll(flagContainer2.getFlagMap().values());
} else {
@@ -2657,17 +2621,18 @@ public class Plot {
/**
* Remove the SE road (only effects terrain)
+ *
+ * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
+ * otherwise writes to the queue but does not enqueue.
*/
- public void removeRoadSouthEast() {
- if (this.area.getType() != PlotAreaType.NORMAL
- && this.area.getTerrain() == PlotAreaTerrainType.ROAD) {
+ public void removeRoadSouthEast(@Nullable QueueCoordinator queue) {
+ if (this.area.getType() != PlotAreaType.NORMAL && this.area.getTerrain() == PlotAreaTerrainType.ROAD) {
Plot other = this.getRelative(1, 1);
Location pos1 = this.getTopAbs().add(1, 0, 1).withY(0);
Location pos2 = other.getBottomAbs().subtract(1, 0, 1).withY(MAX_HEIGHT);
this.regionManager.regenerateRegion(pos1, pos2, true, null);
- } else if (this.area.getTerrain()
- != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
- this.area.getPlotManager().removeRoadSouthEast(this);
+ } else if (this.area.getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
+ this.area.getPlotManager().removeRoadSouthEast(this, queue);
}
}
@@ -2854,14 +2819,12 @@ public class Plot {
PlotId top = PlotId.of(current.getId().getX(), current.getId().getY());
while (merge) {
merge = false;
- List ids = Lists.newArrayList((Iterable extends PlotId>)
- PlotId.PlotRangeIterator.range(PlotId.of(bot.getX(), bot.getY() - 1),
- PlotId.of(top.getX(), bot.getY() - 1)));
+ List ids = Lists.newArrayList((Iterable extends PlotId>) PlotId.PlotRangeIterator
+ .range(PlotId.of(bot.getX(), bot.getY() - 1), PlotId.of(top.getX(), bot.getY() - 1)));
boolean tmp = true;
for (PlotId id : ids) {
Plot plot = this.area.getPlotAbs(id);
- if (plot == null || !plot.getMerged(Direction.SOUTH) || visited
- .contains(plot.getId())) {
+ if (plot == null || !plot.getMerged(Direction.SOUTH) || visited.contains(plot.getId())) {
tmp = false;
}
}
@@ -2869,14 +2832,12 @@ public class Plot {
merge = true;
bot = PlotId.of(bot.getX(), bot.getY() - 1);
}
- ids = Lists.newArrayList((Iterable extends PlotId>)
- PlotId.PlotRangeIterator.range(PlotId.of(top.getX() + 1, bot.getY()),
- PlotId.of(top.getX() + 1, top.getY())));
+ ids = Lists.newArrayList((Iterable extends PlotId>) PlotId.PlotRangeIterator
+ .range(PlotId.of(top.getX() + 1, bot.getY()), PlotId.of(top.getX() + 1, top.getY())));
tmp = true;
for (PlotId id : ids) {
Plot plot = this.area.getPlotAbs(id);
- if (plot == null || !plot.getMerged(Direction.WEST) || visited
- .contains(plot.getId())) {
+ if (plot == null || !plot.getMerged(Direction.WEST) || visited.contains(plot.getId())) {
tmp = false;
}
}
@@ -2884,14 +2845,12 @@ public class Plot {
merge = true;
top = PlotId.of(top.getX() + 1, top.getY());
}
- ids = Lists.newArrayList((Iterable extends PlotId>)
- PlotId.PlotRangeIterator.range(PlotId.of(bot.getX(), top.getY() + 1),
- PlotId.of(top.getX(), top.getY() + 1)));
+ ids = Lists.newArrayList((Iterable extends PlotId>) PlotId.PlotRangeIterator
+ .range(PlotId.of(bot.getX(), top.getY() + 1), PlotId.of(top.getX(), top.getY() + 1)));
tmp = true;
for (PlotId id : ids) {
Plot plot = this.area.getPlotAbs(id);
- if (plot == null || !plot.getMerged(Direction.NORTH) || visited
- .contains(plot.getId())) {
+ if (plot == null || !plot.getMerged(Direction.NORTH) || visited.contains(plot.getId())) {
tmp = false;
}
}
@@ -2899,14 +2858,12 @@ public class Plot {
merge = true;
top = PlotId.of(top.getX(), top.getY() + 1);
}
- ids = Lists.newArrayList((Iterable extends PlotId>)
- PlotId.PlotRangeIterator.range(PlotId.of(bot.getX() - 1, bot.getY()),
- PlotId.of(bot.getX() - 1, top.getY())));
+ ids = Lists.newArrayList((Iterable extends PlotId>) PlotId.PlotRangeIterator
+ .range(PlotId.of(bot.getX() - 1, bot.getY()), PlotId.of(bot.getX() - 1, top.getY())));
tmp = true;
for (PlotId id : ids) {
Plot plot = this.area.getPlotAbs(id);
- if (plot == null || !plot.getMerged(Direction.EAST) || visited
- .contains(plot.getId())) {
+ if (plot == null || !plot.getMerged(Direction.EAST) || visited.contains(plot.getId())) {
tmp = false;
}
}
@@ -2917,8 +2874,7 @@ public class Plot {
}
Location gtopabs = this.area.getPlotAbs(top).getTopAbs();
Location gbotabs = this.area.getPlotAbs(bot).getBottomAbs();
- visited.addAll(Lists.newArrayList((Iterable extends PlotId>)
- PlotId.PlotRangeIterator.range(bot, top)));
+ visited.addAll(Lists.newArrayList((Iterable extends PlotId>) PlotId.PlotRangeIterator.range(bot, top)));
for (int x = bot.getX(); x <= top.getX(); x++) {
Plot plot = this.area.getPlotAbs(PlotId.of(x, top.getY()));
if (plot.getMerged(Direction.SOUTH)) {
@@ -2927,8 +2883,7 @@ public class Plot {
Location botabs = plot.getBottomAbs();
Location topabs = plot.getTopAbs();
BlockVector3 pos1 = BlockVector3.at(botabs.getX(), 0, topabs.getZ() + 1);
- BlockVector3 pos2 =
- BlockVector3.at(topabs.getX(), Plot.MAX_HEIGHT - 1, toploc.getZ());
+ BlockVector3 pos2 = BlockVector3.at(topabs.getX(), Plot.MAX_HEIGHT - 1, toploc.getZ());
regions.add(new CuboidRegion(pos1, pos2));
if (plot.getMerged(Direction.SOUTHEAST)) {
pos1 = BlockVector3.at(topabs.getX() + 1, 0, topabs.getZ() + 1);
@@ -2947,8 +2902,7 @@ public class Plot {
Location botabs = plot.getBottomAbs();
Location topabs = plot.getTopAbs();
BlockVector3 pos1 = BlockVector3.at(topabs.getX() + 1, 0, botabs.getZ());
- BlockVector3 pos2 =
- BlockVector3.at(toploc.getX(), Plot.MAX_HEIGHT - 1, topabs.getZ());
+ BlockVector3 pos2 = BlockVector3.at(toploc.getX(), Plot.MAX_HEIGHT - 1, topabs.getZ());
regions.add(new CuboidRegion(pos1, pos2));
if (plot.getMerged(Direction.SOUTHEAST)) {
pos1 = BlockVector3.at(topabs.getX() + 1, 0, topabs.getZ() + 1);
@@ -2959,8 +2913,7 @@ public class Plot {
}
}
BlockVector3 pos1 = BlockVector3.at(gbotabs.getX(), 0, gbotabs.getZ());
- BlockVector3 pos2 =
- BlockVector3.at(gtopabs.getX(), Plot.MAX_HEIGHT - 1, gtopabs.getZ());
+ BlockVector3 pos2 = BlockVector3.at(gtopabs.getX(), Plot.MAX_HEIGHT - 1, gtopabs.getZ());
regions.add(new CuboidRegion(pos1, pos2));
}
return regions;
@@ -2976,9 +2929,8 @@ public class Plot {
CuboidRegion max = null;
double area = Double.NEGATIVE_INFINITY;
for (CuboidRegion region : regions) {
- double current =
- (region.getMaximumPoint().getX() - (double) region.getMinimumPoint().getX() + 1) * (
- region.getMaximumPoint().getZ() - (double) region.getMinimumPoint().getZ() + 1);
+ double current = (region.getMaximumPoint().getX() - (double) region.getMinimumPoint().getX() + 1) * (
+ region.getMaximumPoint().getZ() - (double) region.getMinimumPoint().getZ() + 1);
if (current > area) {
max = region;
area = current;
@@ -3014,7 +2966,8 @@ public class Plot {
player.sendMessage(caption, plotTemplate, messageTemplate);
}
}
- } catch (final Exception ignored) {}
+ } catch (final Exception ignored) {
+ }
}
/**
@@ -3025,8 +2978,7 @@ public class Plot {
public List getAllCorners() {
Area area = new Area();
for (CuboidRegion region : this.getRegions()) {
- Rectangle2D rect = new Rectangle2D.Double(region.getMinimumPoint().getX() - 0.6,
- region.getMinimumPoint().getZ() - 0.6,
+ Rectangle2D rect = new Rectangle2D.Double(region.getMinimumPoint().getX() - 0.6, region.getMinimumPoint().getZ() - 0.6,
region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + 1.2,
region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + 1.2);
Area rectArea = new Area(rect);
@@ -3062,12 +3014,9 @@ public class Plot {
* @param cause the cause of the teleport
* @param resultConsumer Called with the result of the teleportation
*/
- public void teleportPlayer(final PlotPlayer player, TeleportCause cause,
- Consumer resultConsumer) {
+ public void teleportPlayer(final PlotPlayer player, TeleportCause cause, Consumer resultConsumer) {
Plot plot = this.getBasePlot(false);
- Result result =
- this.eventDispatcher.callTeleport(player, player.getLocation(), plot)
- .getEventResult();
+ Result result = this.eventDispatcher.callTeleport(player, player.getLocation(), plot).getEventResult();
if (result == Result.DENY) {
player.sendMessage(
TranslatableCaption.of("events.event_denied"),
@@ -3096,7 +3045,8 @@ public class Plot {
try {
player.sendMessage(TranslatableCaption.of("teleport.teleported_to_plot"));
player.teleport(location, cause);
- } catch (final Exception ignored) {}
+ } catch (final Exception ignored) {
+ }
}, TaskTime.seconds(Settings.Teleport.DELAY));
resultConsumer.accept(true);
};
@@ -3117,12 +3067,11 @@ public class Plot {
return false;
}
if (!isMerged()) {
- return PlotSquared.platform().getPlayerManager()
- .getPlayerIfExists(Objects.requireNonNull(this.getOwnerAbs())) != null;
+ return PlotSquared.platform().getPlayerManager().getPlayerIfExists(Objects.requireNonNull(this.getOwnerAbs())) != null;
}
for (final Plot current : getConnectedPlots()) {
- if (current.hasOwner() && PlotSquared.platform().getPlayerManager()
- .getPlayerIfExists(Objects.requireNonNull(current.getOwnerAbs())) != null) {
+ if (current.hasOwner()
+ && PlotSquared.platform().getPlayerManager().getPlayerIfExists(Objects.requireNonNull(current.getOwnerAbs())) != null) {
return true;
}
}
@@ -3138,19 +3087,17 @@ public class Plot {
* @param blocks Pattern to use the generation
* @return True if the component was set successfully
*/
- public boolean setComponent(String component, Pattern blocks) {
- PlotComponentSetEvent event =
- this.eventDispatcher.callComponentSet(this, component, blocks);
+ public boolean setComponent(String component, Pattern blocks, @Nullable QueueCoordinator queue) {
+ PlotComponentSetEvent event = this.eventDispatcher.callComponentSet(this, component, blocks);
component = event.getComponent();
blocks = event.getPattern();
- return this.getManager().setComponent(this.getId(), component, blocks);
+ return this.getManager().setComponent(this.getId(), component, blocks, queue);
}
public int getDistanceFromOrigin() {
Location bot = getManager().getPlotBottomLocAbs(id);
Location top = getManager().getPlotTopLocAbs(id);
- return Math.max(Math.max(Math.abs(bot.getX()), Math.abs(bot.getZ())),
- Math.max(Math.abs(top.getX()), Math.abs(top.getZ())));
+ return Math.max(Math.max(Math.abs(bot.getX()), Math.abs(bot.getZ())), Math.max(Math.abs(top.getX()), Math.abs(top.getZ())));
}
/**
@@ -3170,10 +3117,10 @@ public class Plot {
/**
* Merges two plots.
- Assumes plots are directly next to each other
- saves to DB
*
- * @param lesserPlot
- * @param removeRoads
+ * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
+ * otherwise writes to the queue but does not enqueue.
*/
- public void mergePlot(Plot lesserPlot, boolean removeRoads) {
+ public void mergePlot(Plot lesserPlot, boolean removeRoads, @Nullable QueueCoordinator queue) {
Plot greaterPlot = this;
lesserPlot.removeSign();
if (lesserPlot.getId().getX() == greaterPlot.getId().getX()) {
@@ -3190,14 +3137,14 @@ public class Plot {
lesserPlot.mergeData(greaterPlot);
if (removeRoads) {
//lesserPlot.removeSign();
- lesserPlot.removeRoadSouth();
+ lesserPlot.removeRoadSouth(queue);
Plot diagonal = greaterPlot.getRelative(Direction.EAST);
if (diagonal.getMerged(Direction.NORTHWEST)) {
- lesserPlot.removeRoadSouthEast();
+ lesserPlot.removeRoadSouthEast(queue);
}
Plot below = greaterPlot.getRelative(Direction.WEST);
if (below.getMerged(Direction.NORTHEAST)) {
- below.getRelative(Direction.NORTH).removeRoadSouthEast();
+ below.getRelative(Direction.NORTH).removeRoadSouthEast(queue);
}
}
}
@@ -3217,17 +3164,16 @@ public class Plot {
//lesserPlot.removeSign();
Plot diagonal = greaterPlot.getRelative(Direction.SOUTH);
if (diagonal.getMerged(Direction.NORTHWEST)) {
- lesserPlot.removeRoadSouthEast();
+ lesserPlot.removeRoadSouthEast(queue);
}
- lesserPlot.removeRoadEast();
+ lesserPlot.removeRoadEast(queue);
}
Plot below = greaterPlot.getRelative(Direction.NORTH);
if (below.getMerged(Direction.SOUTHWEST)) {
- below.getRelative(Direction.WEST).removeRoadSouthEast();
+ below.getRelative(Direction.WEST).removeRoadSouthEast(queue);
}
}
}
-
}
/**
@@ -3238,10 +3184,8 @@ public class Plot {
* @param allowSwap whether to swap plots
* @return success
*/
- public CompletableFuture move(final Plot destination, final Runnable whenDone,
- boolean allowSwap) {
- final PlotId offset = PlotId.of(destination.getId().getX() - this.getId().getX(),
- destination.getId().getY() - this.getId().getY());
+ public CompletableFuture move(final Plot destination, final Runnable whenDone, boolean allowSwap) {
+ final PlotId offset = PlotId.of(destination.getId().getX() - this.getId().getX(), destination.getId().getY() - this.getId().getY());
Location db = destination.getBottomAbs();
Location ob = this.getBottomAbs();
final int offsetX = db.getX() - ob.getX();
@@ -3308,8 +3252,7 @@ public class Plot {
Location pos1 = corners[0];
Location pos2 = corners[1];
Location pos3 = pos1.add(offsetX, 0, offsetZ).withWorld(destination.getWorldName());
- Location pos4 = pos2.add(offsetX, 0, offsetZ).withWorld(destination.getWorldName());
- regionManager.swap(pos1, pos2, pos3, pos4, this);
+ regionManager.swap(pos1, pos2, pos3, this);
}
}
}.run();
@@ -3318,11 +3261,14 @@ public class Plot {
@Override public void run() {
if (regions.isEmpty()) {
Plot plot = destination.getRelative(0, 0);
- Plot originPlot = originArea
- .getPlotAbs(PlotId.of(plot.id.getX() - offset.getX(), plot.id.getY() - offset.getY()));
+ Plot originPlot = originArea.getPlotAbs(PlotId.of(plot.id.getX() - offset.getX(), plot.id.getY() - offset.getY()));
final Runnable clearDone = () -> {
+ QueueCoordinator queue = getArea().getQueue();
for (final Plot current : plot.getConnectedPlots()) {
- getManager().claimPlot(current);
+ getManager().claimPlot(current, queue);
+ }
+ if (queue.size() > 0) {
+ queue.enqueue();
}
plot.setSign();
TaskManager.runTask(whenDone);
@@ -3356,8 +3302,7 @@ public class Plot {
* @return
*/
public boolean copy(final Plot destination, final Runnable whenDone) {
- PlotId offset = PlotId.of(destination.getId().getX() - this.getId().getX(),
- destination.getId().getY() - this.getId().getY());
+ PlotId offset = PlotId.of(destination.getId().getX() - this.getId().getX(), destination.getId().getY() - this.getId().getY());
Location db = destination.getBottomAbs();
Location ob = this.getBottomAbs();
final int offsetX = db.getX() - ob.getX();
@@ -3386,8 +3331,7 @@ public class Plot {
other.getFlagContainer().addAll(plot.getFlagContainer().getFlagMap().values());
// Update the database
for (final PlotFlag, ?> flag : existingFlags) {
- final PlotFlag, ?> newFlag =
- other.getFlagContainer().queryLocal(flag.getClass());
+ final PlotFlag, ?> newFlag = other.getFlagContainer().queryLocal(flag.getClass());
if (other.getFlagContainer().queryLocal(flag.getClass()) == null) {
DBFunc.removeFlag(other, flag);
} else {
@@ -3422,8 +3366,12 @@ public class Plot {
Runnable run = new Runnable() {
@Override public void run() {
if (regions.isEmpty()) {
+ QueueCoordinator queue = getArea().getQueue();
for (Plot current : getConnectedPlots()) {
- destination.getManager().claimPlot(current);
+ destination.getManager().claimPlot(current, queue);
+ }
+ if (queue.size() > 0) {
+ queue.enqueue();
}
destination.setSign();
TaskManager.runTask(whenDone);
@@ -3433,7 +3381,7 @@ public class Plot {
Location[] corners = getCorners(getWorldName(), region);
Location pos1 = corners[0];
Location pos2 = corners[1];
- Location newPos = pos1 .add(offsetX, 0, offsetZ).withWorld(destination.getWorldName());
+ Location newPos = pos1.add(offsetX, 0, offsetZ).withWorld(destination.getWorldName());
regionManager.copyRegion(pos1, pos2, newPos, this);
}
};
diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java
index 14abb33b8..dc2069368 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java
@@ -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 trusted = new HashSet<>();
final Set members = new HashSet<>();
final Set 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;
}
diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotItemStack.java b/Core/src/main/java/com/plotsquared/core/plot/PlotItemStack.java
index 56c691fdc..bb733868d 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/PlotItemStack.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/PlotItemStack.java
@@ -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) {
diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotManager.java b/Core/src/main/java/com/plotsquared/core/plot/PlotManager.java
index 236eeee0f..187e29ffd 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/PlotManager.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/PlotManager.java
@@ -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 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 plotIds);
+ public abstract boolean startPlotMerge(@Nonnull List plotIds, @Nullable QueueCoordinator queue);
- public abstract boolean finishPlotMerge(List plotIds);
+ public abstract boolean startPlotUnlink(@Nonnull List plotIds, @Nullable QueueCoordinator queue);
- public abstract boolean finishPlotUnlink(List 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 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 plotIds, @Nullable QueueCoordinator queue);
public void exportTemplate() throws IOException {
- HashSet files = new HashSet<>(Collections.singletonList(
- new FileBytes(Settings.Paths.TEMPLATES + "/tmp-data.yml",
- Template.getBytes(plotArea))));
+ HashSet 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;
diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/GlobalFlagContainer.java b/Core/src/main/java/com/plotsquared/core/plot/flag/GlobalFlagContainer.java
index b321fa1f2..f243e25ae 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/flag/GlobalFlagContainer.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/flag/GlobalFlagContainer.java
@@ -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> 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);
diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java
index 26e914558..7b91edfd3 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java
@@ -144,8 +144,7 @@ public abstract class PlotFlag> {
}
/**
- * 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}
*
* These categories are used to categorize the flags when outputting
* flag lists to players.
diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java
index 82aaa7a3f..cffa305a1 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotManager.java
@@ -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 plotIds) {
+ @Override public boolean startPlotMerge(@NotNull List plotIds, @Nullable QueueCoordinator queue) {
return false;
}
- @Override public boolean startPlotUnlink(List plotIds) {
+ @Override public boolean startPlotUnlink(@NotNull List plotIds, @Nullable QueueCoordinator queue) {
return false;
}
- @Override public boolean finishPlotMerge(List plotIds) {
+ @Override public boolean finishPlotMerge(@NotNull List plotIds, @Nullable QueueCoordinator queue) {
return false;
}
- @Override public boolean finishPlotUnlink(List plotIds) {
+ @Override public boolean finishPlotUnlink(@NotNull List plotIds, @Nullable QueueCoordinator queue) {
return false;
}
- @Override public boolean regenerateAllPlotWalls() {
+ @Override public boolean regenerateAllPlotWalls(@Nullable QueueCoordinator queue) {
return false;
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java
similarity index 67%
rename from Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateLocalBlockQueue.java
rename to Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java
index 7bafdfcfa..028f49223 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateLocalBlockQueue.java
+++ b/Core/src/main/java/com/plotsquared/core/queue/AreaBoundDelegateQueueCoordinator.java
@@ -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;
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java
deleted file mode 100644
index 487cfaf7a..000000000
--- a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java
+++ /dev/null
@@ -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 .
- */
-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 blockChunks = new ConcurrentHashMap<>();
- private final ConcurrentLinkedDeque 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;
- }
- }
-}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java
new file mode 100644
index 000000000..cca1899fe
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/queue/BasicQueueCoordinator.java
@@ -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 .
+ */
+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 blockChunks = new ConcurrentHashMap<>();
+ private final List 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 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 getReadChunks() {
+ return this.readRegion;
+ }
+
+ @Override public void addReadChunk(@Nonnull BlockVector2 chunk) {
+ this.readRegion.add(chunk);
+ }
+
+ @Override public void addReadChunks(@Nonnull Set 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 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 getChunkConsumer() {
+ return this.consumer;
+ }
+
+ @Override public final void setChunkConsumer(@Nonnull Consumer 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;
+ }
+}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java
new file mode 100644
index 000000000..28ed3dc74
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java
@@ -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 .
+ */
+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();
+}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java
new file mode 100644
index 000000000..2ead29881
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinatorBuilder.java
@@ -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 .
+ */
+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 requestedChunks = new LinkedList<>();
+ private final ChunkCoordinatorFactory chunkCoordinatorFactory;
+ private Consumer throwableConsumer = Throwable::printStackTrace;
+ private World world;
+ private Consumer 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 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 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 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 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);
+ }
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/ChunkBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/ChunkQueueCoordinator.java
similarity index 62%
rename from Core/src/main/java/com/plotsquared/core/queue/ChunkBlockQueue.java
rename to Core/src/main/java/com/plotsquared/core/queue/ChunkQueueCoordinator.java
index 4fb47ed90..d04a0c798 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/ChunkBlockQueue.java
+++ b/Core/src/main/java/com/plotsquared/core/queue/ChunkQueueCoordinator.java
@@ -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());
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/DelegateLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/DelegateLocalBlockQueue.java
deleted file mode 100644
index 22176671c..000000000
--- a/Core/src/main/java/com/plotsquared/core/queue/DelegateLocalBlockQueue.java
+++ /dev/null
@@ -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 .
- */
-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;
- }
-}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java
new file mode 100644
index 000000000..b3dea64e9
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/queue/DelegateQueueCoordinator.java
@@ -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 .
+ */
+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 getChunkConsumer() {
+ if (parent != null) {
+ return parent.getChunkConsumer();
+ }
+ return null;
+ }
+
+ @Override public void setChunkConsumer(@Nonnull Consumer consumer) {
+ if (parent != null) {
+ parent.setChunkConsumer(consumer);
+ }
+ }
+
+ @Override @Nonnull public List getReadChunks() {
+ if (parent != null) {
+ return parent.getReadChunks();
+ }
+ return new ArrayList<>();
+ }
+
+ @Override public void addReadChunks(@Nonnull Set 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);
+ }
+
+ }
+}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java
index 1ef62a4eb..a251aced7 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java
+++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java
@@ -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 activeQueues;
- private final ConcurrentLinkedDeque inactiveQueues;
- private final ConcurrentLinkedDeque runnables;
- private final AtomicBoolean running;
- private final int targetTime;
+ private final ConcurrentLinkedDeque 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 SET_TASK =
- new RunnableVal2() {
- @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 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 getAllQueues() {
- ArrayList list =
- new ArrayList<>(activeQueues.size() + inactiveQueues.size());
- list.addAll(inactiveQueues);
- list.addAll(activeQueues);
- return list;
- }
-
- public List getActiveQueues() {
+ @Nonnull public List getActiveQueues() {
return new ArrayList<>(activeQueues);
}
- public List 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 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 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 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;
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java
deleted file mode 100644
index c97013458..000000000
--- a/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java
+++ /dev/null
@@ -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 .
- */
-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;
- }
-}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java b/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java
new file mode 100644
index 000000000..999f36ccb
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/queue/LocalChunk.java
@@ -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 .
+ */
+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 tiles = new HashMap<>();
+ private final HashMap 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 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 getEntities() {
+ return this.entities;
+ }
+}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateQueueCoordinator.java
similarity index 57%
rename from Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateLocalBlockQueue.java
rename to Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateQueueCoordinator.java
index eefae99d3..fd86f7eb2 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateLocalBlockQueue.java
+++ b/Core/src/main/java/com/plotsquared/core/queue/LocationOffsetDelegateQueueCoordinator.java
@@ -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;
+ }
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java
new file mode 100644
index 000000000..b6a838990
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/queue/QueueCoordinator.java
@@ -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 .
+ */
+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 getReadChunks();
+
+ /**
+ * Add a set of {@link BlockVector2} Chunk coordinates to the Read Chunks list
+ */
+ public abstract void addReadChunks(@Nonnull Set 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 getChunkConsumer();
+
+ /**
+ * Set the Consumer that will
+ */
+ public abstract void setChunkConsumer(@Nonnull Consumer 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);
+ }
+ }
+ }
+ }
+}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java b/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java
index 2fee2fa99..b31a7da45 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java
+++ b/Core/src/main/java/com/plotsquared/core/queue/QueueProvider.java
@@ -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);
}
diff --git a/Core/src/main/java/com/plotsquared/core/queue/ScopedLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/ScopedQueueCoordinator.java
similarity index 59%
rename from Core/src/main/java/com/plotsquared/core/queue/ScopedLocalBlockQueue.java
rename to Core/src/main/java/com/plotsquared/core/queue/ScopedQueueCoordinator.java
index fc43e1ce0..b4fbc5e40 100644
--- a/Core/src/main/java/com/plotsquared/core/queue/ScopedLocalBlockQueue.java
+++ b/Core/src/main/java/com/plotsquared/core/queue/ScopedQueueCoordinator.java
@@ -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);
}
}
diff --git a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java
index 438f60940..91d7a282f 100644
--- a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java
+++ b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java
@@ -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> forceChunks =
- new ConcurrentHashMap<>();
- private static final Map> addChunks =
- new ConcurrentHashMap<>();
+ private static final Map> forceChunks = new ConcurrentHashMap<>();
+ private static final Map> addChunks = new ConcurrentHashMap<>();
- public static void setChunkInPlotArea(RunnableVal force,
- RunnableVal add, String world, BlockVector2 loc) {
- LocalBlockQueue queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(world, false);
+ public static void setChunkInPlotArea(RunnableVal force,
+ RunnableVal 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 forceChunk = forceChunks.get(loc);
+ public static boolean preProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) {
+ final RunnableVal 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 addChunk = forceChunks.get(loc);
+ public static boolean postProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) {
+ final RunnableVal 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 task,
- final Runnable whenDone, final int allocate) {
- final ArrayList 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 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 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);
}
diff --git a/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java b/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java
index 0a3b5f369..71fa058e0 100644
--- a/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java
+++ b/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java
@@ -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
* - Used for efficient world generation
*/
- 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;
+ }
}
diff --git a/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java b/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java
index 5429941c9..12421a71a 100644
--- a/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java
+++ b/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java
@@ -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(
diff --git a/Core/src/main/java/com/plotsquared/core/util/EventDispatcher.java b/Core/src/main/java/com/plotsquared/core/util/EventDispatcher.java
index 1234f05c6..931ed838f 100644
--- a/Core/src/main/java/com/plotsquared/core/util/EventDispatcher.java
+++ b/Core/src/main/java/com/plotsquared/core/util/EventDispatcher.java
@@ -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);
diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java
index 49444123c..00e4bb43a 100644
--- a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java
+++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java
@@ -107,7 +107,7 @@ public abstract class PlayerManager, 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
diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java
index 40906237d..f3e745c86 100644
--- a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java
+++ b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java
@@ -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 task, final Runnable whenDone) {
- TaskManager.runTaskAsync(() -> {
- HashSet chunks = new HashSet<>();
- Set 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() {
- @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 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 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 chunks) {
- deleteRegionFiles(world, chunks, null);
- }
-
- public void deleteRegionFiles(final String world, final Collection chunks,
- final Runnable whenDone) {
+ public void deleteRegionFiles(final String world, final Collection 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 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 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:
* - pos1 and pos2 are in the same plot
* It can be harmful to the world if parameters outside this scope are provided
- *
- * @param pos1
- * @param pos2
- * @param whenDone
- * @return
*/
- public abstract boolean regenerateRegion(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();
+ }
}
diff --git a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java
index 09aebcd84..d02284930 100644
--- a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java
+++ b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java
@@ -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 writeTask,
- @Nonnull final RunnableVal whenDone) {
+ public static void upload(@Nullable UUID uuid,
+ @Nullable final String file,
+ @Nonnull final String extension,
+ @Nullable final RunnableVal writeTask,
+ @Nonnull final RunnableVal 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 collection, final File outputDir,
- final String namingScheme, final Runnable ifSuccess) {
+ public boolean exportAll(Collection 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 whenDone) {
+ public void paste(final Schematic schematic,
+ final Plot plot,
+ final int xOffset,
+ final int yOffset,
+ final int zOffset,
+ final boolean autoHeight,
+ final RunnableVal 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() {
- @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 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 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 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() {
@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 regions,
- final RunnableVal whenDone) {
+ public void getCompoundTag(final String world, final Set regions, final RunnableVal 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 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 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 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 xiter =
- IntStream.range(p1x, p2x + 1).iterator();
+ Iterator 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 values =
- new HashMap<>();
- for (Map.Entry entry : block
- .getNbtData().getValue()
- .entrySet()) {
- values.put(entry.getKey(),
- entry.getValue());
+ Map values = new HashMap<>();
+ for (Map.Entry 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)) {
diff --git a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java
index b0d9b9158..0cd1f93cd 100644
--- a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java
+++ b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java
@@ -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.ComparisonResult getClosestBlock(
- @Nonnull String name);
+ @Nonnull public abstract StringComparison.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 result);
+ public abstract void getBiome(@Nonnull String world, int x, int z, @Nonnull Consumer 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 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 whenDone) {
plot.getHome(home -> SchematicHandler.upload(uuid, file, "zip", new RunnableVal() {
@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 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 files = regionManager.getChunkChunks(bot.getWorldName());
+ Set 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 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 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);
}
diff --git a/Core/src/main/java/com/plotsquared/core/util/placeholders/Placeholder.java b/Core/src/main/java/com/plotsquared/core/util/placeholders/Placeholder.java
new file mode 100644
index 000000000..a6e42fbdb
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/util/placeholders/Placeholder.java
@@ -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 .
+ */
+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;
+ }
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/util/placeholders/PlaceholderRegistry.java b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlaceholderRegistry.java
new file mode 100644
index 000000000..b45a1032f
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlaceholderRegistry.java
@@ -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 .
+ */
+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 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, 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, 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 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;
+ }
+
+ }
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/util/placeholders/PlotFlagPlaceholder.java b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlotFlagPlaceholder.java
new file mode 100644
index 000000000..4a3d1876a
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlotFlagPlaceholder.java
@@ -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 .
+ */
+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() : "";
+ }
+ }
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/util/placeholders/PlotSpecificPlaceholder.java b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlotSpecificPlaceholder.java
new file mode 100644
index 000000000..92285238d
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlotSpecificPlaceholder.java
@@ -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 .
+ */
+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);
+
+}
diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java
index e5a2e3ba8..426a6dc0b 100644
--- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java
+++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java
@@ -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) {
+ public void getSingle(@Nonnull final String username, @Nonnull final BiConsumer 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 username) {
+ public void getSingle(@Nonnull final UUID uuid, @Nonnull final BiConsumer 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> getNames(@Nonnull final Collection requests,
- final long timeout) {
+ public CompletableFuture> getNames(@Nonnull final Collection 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> getUUIDs(@Nonnull final Collection requests,
- final long timeout) {
+ public CompletableFuture> getUUIDs(@Nonnull final Collection 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> getUUIDs(
- @Nonnull final Collection requests) {
+ public CompletableFuture> getUUIDs(@Nonnull final Collection requests) {
if (requests.isEmpty()) {
return CompletableFuture.completedFuture(Collections.emptyList());
}
diff --git a/Core/src/main/resources/lang/messages_en.json b/Core/src/main/resources/lang/messages_en.json
index e933c2067..b944d20e0 100644
--- a/Core/src/main/resources/lang/messages_en.json
+++ b/Core/src/main/resources/lang/messages_en.json
@@ -181,6 +181,8 @@
"core.prefix": "[P2] ",
"core.enabled": " is now enabled.",
+
+ "placeholder.hooked": "PlotSquared hooked into MVdWPlaceholderAPI",
"reload.reloaded_configs": "Translations and world settings have been reloaded successfully.",
"reload.reload_failed": "Failed to reload file configurations.",
diff --git a/build.gradle b/build.gradle
index 32b17ef31..1806aa090 100644
--- a/build.gradle
+++ b/build.gradle
@@ -79,7 +79,7 @@ subprojects { subproject ->
dependencies {
compile group: 'org.json', name: 'json', version: '20200518'
- implementation("com.sk89q.worldedit:worldedit-core:7.0.0") {
+ implementation("com.sk89q.worldedit:worldedit-core:7.2.0-SNAPSHOT") {
exclude(module: "bukkit-classloader-check")
exclude(module: "mockito-core")
exclude(module: "dummypermscompat")
@@ -100,6 +100,7 @@ subprojects { subproject ->
}
repositories {
+ mavenLocal()
mavenCentral()
maven { url = "https://maven.enginehub.org/repo/" }
maven { url = "https://repo.maven.apache.org/maven2" }
@@ -110,6 +111,8 @@ subprojects { subproject ->
dependencies {
include(dependency("org.json:json:20200518"))
include(dependency("net.kyori:text-api:3.0.2"))
+ include(dependency("javax.inject:javax.inject:1"))
+ include(dependency("aopalliance:aopalliance:1.0"))
}
relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib")
relocate("org.json", "com.plotsquared.json") {