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

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

View File

@ -2,6 +2,7 @@ plugins {
id "com.github.johnrengelman.shadow" id "com.github.johnrengelman.shadow"
} }
repositories { repositories {
mavenLocal()
maven { url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" } maven { url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" }
maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url = "https://jitpack.io" } maven { url = "https://jitpack.io" }
@ -15,7 +16,7 @@ repositories {
maven { url = "https://mvn.intellectualsites.com/content/repositories/snapshots" } maven { url = "https://mvn.intellectualsites.com/content/repositories/snapshots" }
maven { url = "https://repo.wea-ondara.net/repository/public/" } maven { url = "https://repo.wea-ondara.net/repository/public/" }
maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" } 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(project(":PlotSquared-Core"))
compile("com.destroystokyo.paper:paper-api:1.16.1-R0.1-SNAPSHOT") compile("com.destroystokyo.paper:paper-api:1.16.1-R0.1-SNAPSHOT")
implementation("org.spigotmc:spigot-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") exclude(module: "bukkit")
} }
@ -44,8 +45,10 @@ dependencies {
implementation('net.kyori:adventure-text-minimessage:3.0.0-SNAPSHOT') implementation('net.kyori:adventure-text-minimessage:3.0.0-SNAPSHOT')
compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false }
compile('com.sk89q:squirrelid:1.0.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 // logging
implementation('org.apache.logging.log4j:log4j-slf4j-impl:2.8.1') implementation('org.apache.logging.log4j:log4j-slf4j-impl:2.8.1')
compile('be.maximvdw:MVdWPlaceholderAPI:3.1.1-SNAPSHOT'){ transitive = false }
} }
sourceCompatibility = 1.8 sourceCompatibility = 1.8

View File

@ -27,7 +27,7 @@
<dependency> <dependency>
<groupId>com.plotsquared</groupId> <groupId>com.plotsquared</groupId>
<artifactId>PlotSquared-Core</artifactId> <artifactId>PlotSquared-Core</artifactId>
<version>5.12.5</version> <version>6.0.0-SUPER-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -39,7 +39,7 @@
<dependency> <dependency>
<groupId>com.sk89q.worldedit</groupId> <groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId> <artifactId>worldedit-bukkit</artifactId>
<version>7.1.0</version> <version>7.2.0-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -90,10 +90,22 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>be.maximvdw</groupId>
<artifactId>MVdWPlaceholderAPI</artifactId>
<version>3.1.1-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>com.sk89q.worldedit</groupId> <groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-core</artifactId> <artifactId>worldedit-core</artifactId>
<version>7.0.0</version> <version>7.2.0-SNAPSHOT</version>
<scope>runtime</scope> <scope>runtime</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -110,30 +122,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-api</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-gson</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-legacy</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-plain</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
@ -182,6 +170,18 @@
<version>4.0-dev-106</version> <version>4.0-dev-106</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.0.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>3.0.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId> <artifactId>log4j-slf4j-impl</artifactId>

View File

@ -36,15 +36,19 @@ import com.plotsquared.bukkit.inject.BackupModule;
import com.plotsquared.bukkit.inject.BukkitModule; import com.plotsquared.bukkit.inject.BukkitModule;
import com.plotsquared.bukkit.inject.PermissionModule; import com.plotsquared.bukkit.inject.PermissionModule;
import com.plotsquared.bukkit.inject.WorldManagerModule; import com.plotsquared.bukkit.inject.WorldManagerModule;
import com.plotsquared.bukkit.listener.BlockEventListener;
import com.plotsquared.bukkit.listener.ChunkListener; import com.plotsquared.bukkit.listener.ChunkListener;
import com.plotsquared.bukkit.listener.EntityEventListener;
import com.plotsquared.bukkit.listener.EntitySpawnListener; import com.plotsquared.bukkit.listener.EntitySpawnListener;
import com.plotsquared.bukkit.listener.PaperListener; 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.SingleWorldListener;
import com.plotsquared.bukkit.listener.WorldEvents; import com.plotsquared.bukkit.listener.WorldEvents;
import com.plotsquared.bukkit.placeholder.PlaceholderFormatter; import com.plotsquared.bukkit.placeholder.PlaceholderFormatter;
import com.plotsquared.bukkit.placeholder.Placeholders;
import com.plotsquared.bukkit.player.BukkitPlayer; import com.plotsquared.bukkit.player.BukkitPlayer;
import com.plotsquared.bukkit.placeholder.PAPIPlaceholders;
import com.plotsquared.bukkit.player.BukkitPlayerManager; import com.plotsquared.bukkit.player.BukkitPlayerManager;
import com.plotsquared.bukkit.util.task.BukkitTaskManager; import com.plotsquared.bukkit.util.task.BukkitTaskManager;
import com.plotsquared.bukkit.util.BukkitUtil; 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.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotArea; import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotAreaManager;
import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.setup.PlotAreaBuilder;
import com.plotsquared.core.setup.SettingsNodesWrapper; import com.plotsquared.core.setup.SettingsNodesWrapper;
import com.plotsquared.core.util.ConsoleColors; 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.PremiumVerification.getUserID;
import static com.plotsquared.core.util.ReflectionUtils.getRefClass; import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
@SuppressWarnings("unused") public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPlatform<Player> { @SuppressWarnings("unused")
public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPlatform<Player> {
private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitPlatform.class.getSimpleName()); private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitPlatform.class.getSimpleName());
private static final int BSTATS_ID = 1404; 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"); final PlotSquared plotSquared = new PlotSquared(this, "Bukkit");
if (PlotSquared.platform().getServerVersion()[1] < 13) { if (PlotSquared.platform().getServerVersion()[1] < 13) {
System.out.println( System.out.println("You can't use this version of PlotSquared on a server less than Minecraft 1.13.2.");
"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("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."); System.out.println("The server will now be shutdown to prevent any corruption.");
Bukkit.shutdown(); Bukkit.shutdown();
return; 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 // We create the injector after PlotSquared has been initialized, so that we have access
// to generated instances and settings // to generated instances and settings
this.injector = Guice.createInjector(Stage.PRODUCTION, new PermissionModule(), this.injector = Guice
new WorldManagerModule(), .createInjector(Stage.PRODUCTION, new PermissionModule(), new WorldManagerModule(), new PlotSquaredModule(), new BukkitModule(this),
new PlotSquaredModule(), new BackupModule());
new BukkitModule(this),
new BackupModule());
this.injector.injectMembers(this); this.injector.injectMembers(this);
this.serverLocale = Locale.forLanguageTag(Settings.Enabled_Components.DEFAULT_LOCALE); 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 // Do stuff that was previously done in PlotSquared
// Kill entities // Kill entities
if (Settings.Enabled_Components.KILL_ROAD_MOBS if (Settings.Enabled_Components.KILL_ROAD_MOBS || Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
|| Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
this.runEntityTask(); this.runEntityTask();
} }
@ -311,7 +310,11 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
if (Settings.Enabled_Components.EVENTS) { 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); getServer().getPluginManager().registerEvents(getInjector().getInstance(EntitySpawnListener.class), this);
if (PaperLib.isPaper() && Settings.Paper_Components.PAPER_LISTENERS) { if (PaperLib.isPaper() && Settings.Paper_Components.PAPER_LISTENERS) {
getServer().getPluginManager().registerEvents(getInjector().getInstance(PaperListener.class), this); 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); getServer().getPluginManager().registerEvents(getInjector().getInstance(ChunkListener.class), this);
} }
// Start the global block queue
final GlobalBlockQueue globalBlockQueue = this.injector.getInstance(GlobalBlockQueue.class);
globalBlockQueue.runTask();
// Commands // Commands
if (Settings.Enabled_Components.COMMANDS) { if (Settings.Enabled_Components.COMMANDS) {
this.registerCommands(); this.registerCommands();
@ -372,9 +371,9 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
continue; continue;
} }
if (!worldUtil.isWorld(world) && !world.equals("*")) { if (!worldUtil.isWorld(world) && !world.equals("*")) {
logger.warn("[P2] `{}` was not properly loaded - {} will now try to load it properly", logger.warn("[P2] `{}` was not properly loaded - {} will now try to load it properly", world, this.getPluginName());
world, this.getPluginName()); logger.warn(
logger.warn("[P2] - Are you trying to delete this world? Remember to remove it from the worlds.yml, bukkit.yml and multiverse worlds.yml"); "[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] - 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."); logger.warn("[P2] This message may also be a false positive and could be ignored.");
this.setGenerator(world); 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 sqLiteUUIDService = new SQLiteUUIDService("user_cache.db");
final SQLiteUUIDService legacyUUIDService; final SQLiteUUIDService legacyUUIDService;
if (Settings.UUID.LEGACY_DATABASE_SUPPORT && if (Settings.UUID.LEGACY_DATABASE_SUPPORT && FileUtils.getFile(PlotSquared.platform().getDirectory(), "usercache.db").exists()) {
FileUtils.getFile(PlotSquared.platform().getDirectory(), "usercache.db").exists()) {
legacyUUIDService = new SQLiteUUIDService("usercache.db"); legacyUUIDService = new SQLiteUUIDService("usercache.db");
} else { } else {
legacyUUIDService = null; legacyUUIDService = null;
} }
final LuckPermsUUIDService luckPermsUUIDService; final LuckPermsUUIDService luckPermsUUIDService;
if (Settings.UUID.SERVICE_LUCKPERMS && if (Settings.UUID.SERVICE_LUCKPERMS && Bukkit.getPluginManager().getPlugin("LuckPerms") != null) {
Bukkit.getPluginManager().getPlugin("LuckPerms") != null) {
luckPermsUUIDService = new LuckPermsUUIDService(); luckPermsUUIDService = new LuckPermsUUIDService();
logger.info("[P2] (UUID) Using LuckPerms as a complementary UUID service"); logger.info("[P2] (UUID) Using LuckPerms as a complementary UUID service");
} else { } else {
@ -425,8 +422,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
final BungeePermsUUIDService bungeePermsUUIDService; final BungeePermsUUIDService bungeePermsUUIDService;
if (Settings.UUID.SERVICE_BUNGEE_PERMS && if (Settings.UUID.SERVICE_BUNGEE_PERMS && Bukkit.getPluginManager().getPlugin("BungeePerms") != null) {
Bukkit.getPluginManager().getPlugin("BungeePerms") != null) {
bungeePermsUUIDService = new BungeePermsUUIDService(); bungeePermsUUIDService = new BungeePermsUUIDService();
logger.info("[P2] (UUID) Using BungeePerms as a complementary UUID service"); logger.info("[P2] (UUID) Using BungeePerms as a complementary UUID service");
} else { } else {
@ -474,11 +470,9 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
this.backgroundPipeline.registerService(essentialsUUIDService); this.backgroundPipeline.registerService(essentialsUUIDService);
} }
final SquirrelIdUUIDService impromptuMojangService = final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT);
new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT);
this.impromptuPipeline.registerService(impromptuMojangService); this.impromptuPipeline.registerService(impromptuMojangService);
final SquirrelIdUUIDService backgroundMojangService = final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT);
new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT);
this.backgroundPipeline.registerService(backgroundMojangService); this.backgroundPipeline.registerService(backgroundMojangService);
} else { } else {
this.impromptuPipeline.registerService(sqLiteUUIDService); this.impromptuPipeline.registerService(sqLiteUUIDService);
@ -499,7 +493,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
injector.getInstance(Placeholders.class).register(); injector.getInstance(PAPIPlaceholders.class).register();
if (Settings.Enabled_Components.EXTERNAL_PLACEHOLDERS) { if (Settings.Enabled_Components.EXTERNAL_PLACEHOLDERS) {
ChatFormatter.formatters.add(getInjector().getInstance(PlaceholderFormatter.class)); ChatFormatter.formatters.add(getInjector().getInstance(PlaceholderFormatter.class));
} }
@ -537,8 +531,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
this.methodUnloadSetup = true; this.methodUnloadSetup = true;
try { try {
ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld"); ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
this.methodUnloadChunk0 = classCraftWorld.getRealClass() this.methodUnloadChunk0 = classCraftWorld.getRealClass().getDeclaredMethod("unloadChunk0", int.class, int.class, boolean.class);
.getDeclaredMethod("unloadChunk0", int.class, int.class, boolean.class);
this.methodUnloadChunk0.setAccessible(true); this.methodUnloadChunk0.setAccessible(true);
} catch (Throwable event) { } catch (Throwable event) {
event.printStackTrace(); event.printStackTrace();
@ -569,8 +562,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
final Plot plot = area.getOwnedPlot(id); final Plot plot = area.getOwnedPlot(id);
if (plot != null) { if (plot != null) {
if (!plot.getFlag(ServerPlotFlag.class) || PlotSquared.platform().getPlayerManager() if (!plot.getFlag(ServerPlotFlag.class) || PlotSquared.platform().getPlayerManager().getPlayerIfExists(plot.getOwner()) == null) {
.getPlayerIfExists(plot.getOwner()) == null) {
if (world.getKeepSpawnInMemory()) { if (world.getKeepSpawnInMemory()) {
world.setKeepSpawnInMemory(false); world.setKeepSpawnInMemory(false);
return; return;
@ -588,8 +580,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
boolean result; boolean result;
if (methodUnloadChunk0 != null) { if (methodUnloadChunk0 != null) {
try { try {
result = (boolean) methodUnloadChunk0 result = (boolean) methodUnloadChunk0.invoke(world, chunkI.getX(), chunkI.getZ(), true);
.invoke(world, chunkI.getX(), chunkI.getZ(), true);
} catch (Throwable e) { } catch (Throwable e) {
methodUnloadChunk0 = null; methodUnloadChunk0 = null;
e.printStackTrace(); e.printStackTrace();
@ -612,8 +603,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
} }
private void startUuidCaching(@Nonnull final SQLiteUUIDService sqLiteUUIDService, private void startUuidCaching(@Nonnull final SQLiteUUIDService sqLiteUUIDService, @Nonnull final CacheUUIDService cacheUUIDService) {
@Nonnull final CacheUUIDService cacheUUIDService) {
// Load all uuids into a big chunky boi queue // Load all uuids into a big chunky boi queue
final Queue<UUID> uuidQueue = new LinkedBlockingQueue<>(); final Queue<UUID> uuidQueue = new LinkedBlockingQueue<>();
PlotSquared.get().forEachPlotRaw(plot -> { PlotSquared.get().forEachPlotRaw(plot -> {
@ -653,8 +643,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
// fresh batch // fresh batch
secondRun = false; secondRun = false;
// Populate the request list // Populate the request list
for (int i = 0; for (int i = 0; i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) {
i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) {
uuidList.add(uuidQueue.poll()); uuidList.add(uuidQueue.poll());
read++; read++;
} }
@ -760,8 +749,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
case "MINECART_TNT": case "MINECART_TNT":
case "BOAT": case "BOAT":
if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
com.plotsquared.core.location.Location location = com.plotsquared.core.location.Location location = BukkitUtil.adapt(entity.getLocation());
BukkitUtil.adapt(entity.getLocation());
Plot plot = location.getPlot(); Plot plot = location.getPlot();
if (plot == null) { if (plot == null) {
if (location.isPlotArea()) { if (location.isPlotArea()) {
@ -791,9 +779,8 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
case "FIREBALL": case "FIREBALL":
case "DRAGON_FIREBALL": case "DRAGON_FIREBALL":
case "DROPPED_ITEM": case "DROPPED_ITEM":
if (Settings.Enabled_Components.KILL_ROAD_ITEMS && plotArea if (Settings.Enabled_Components.KILL_ROAD_ITEMS
.getOwnedPlotAbs(BukkitUtil.adapt(entity.getLocation())) && plotArea.getOwnedPlotAbs(BukkitUtil.adapt(entity.getLocation())) == null) {
== null) {
entity.remove(); entity.remove();
} }
// dropped item // dropped item
@ -817,15 +804,12 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
PlotId originalPlotId = (PlotId) meta.get(0).value(); PlotId originalPlotId = (PlotId) meta.get(0).value();
if (originalPlotId != null) { if (originalPlotId != null) {
com.plotsquared.core.location.Location pLoc = com.plotsquared.core.location.Location pLoc = BukkitUtil.adapt(entity.getLocation());
BukkitUtil.adapt(entity.getLocation());
PlotArea area = pLoc.getPlotArea(); PlotArea area = pLoc.getPlotArea();
if (area != null) { if (area != null) {
PlotId currentPlotId = area.getPlotAbs(pLoc).getId(); PlotId currentPlotId = area.getPlotAbs(pLoc).getId();
if (!originalPlotId.equals(currentPlotId) && ( if (!originalPlotId.equals(currentPlotId) && (currentPlotId == null || !area.getPlot(originalPlotId)
currentPlotId == null || !area .equals(area.getPlot(currentPlotId)))) {
.getPlot(originalPlotId)
.equals(area.getPlot(currentPlotId)))) {
if (entity.hasMetadata("ps-tmp-teleport")) { if (entity.hasMetadata("ps-tmp-teleport")) {
continue; continue;
} }
@ -836,15 +820,12 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
} else { } else {
//This is to apply the metadata to already spawned shulkers (see EntitySpawnListener.java) //This is to apply the metadata to already spawned shulkers (see EntitySpawnListener.java)
com.plotsquared.core.location.Location pLoc = com.plotsquared.core.location.Location pLoc = BukkitUtil.adapt(entity.getLocation());
BukkitUtil.adapt(entity.getLocation());
PlotArea area = pLoc.getPlotArea(); PlotArea area = pLoc.getPlotArea();
if (area != null) { if (area != null) {
PlotId currentPlotId = area.getPlotAbs(pLoc).getId(); PlotId currentPlotId = area.getPlotAbs(pLoc).getId();
if (currentPlotId != null) { if (currentPlotId != null) {
entity.setMetadata("shulkerPlot", entity.setMetadata("shulkerPlot", new FixedMetadataValue((Plugin) PlotSquared.platform(), currentPlotId));
new FixedMetadataValue(
(Plugin) PlotSquared.platform(), currentPlotId));
} }
} }
} }
@ -925,11 +906,9 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
if (BukkitUtil.adapt(location).isPlotRoad()) { if (BukkitUtil.adapt(location).isPlotRoad()) {
if (entity instanceof LivingEntity) { if (entity instanceof LivingEntity) {
LivingEntity livingEntity = (LivingEntity) entity; LivingEntity livingEntity = (LivingEntity) entity;
if (!livingEntity.isLeashed() || !entity if (!livingEntity.isLeashed() || !entity.hasMetadata("keep")) {
.hasMetadata("keep")) {
Entity passenger = entity.getPassenger(); Entity passenger = entity.getPassenger();
if (!(passenger instanceof Player) && entity if (!(passenger instanceof Player) && entity.getMetadata("keep").isEmpty()) {
.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) { if (entity.hasMetadata("ps-tmp-teleport")) {
continue; continue;
} }
@ -940,8 +919,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
} else { } else {
Entity passenger = entity.getPassenger(); Entity passenger = entity.getPassenger();
if (!(passenger instanceof Player) && entity if (!(passenger instanceof Player) && entity.getMetadata("keep").isEmpty()) {
.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) { if (entity.hasMetadata("ps-tmp-teleport")) {
continue; continue;
} }
@ -962,9 +940,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
}), TaskTime.seconds(1L)); }), TaskTime.seconds(1L));
} }
@Override @Nullable @Override @Nullable public final ChunkGenerator getDefaultWorldGenerator(@Nonnull final String worldName, final String id) {
public final ChunkGenerator getDefaultWorldGenerator(@Nonnull final String worldName,
final String id) {
final IndependentPlotGenerator result; final IndependentPlotGenerator result;
if (id != null && id.equalsIgnoreCase("single")) { if (id != null && id.equalsIgnoreCase("single")) {
result = getInjector().getInstance(SingleWorldGenerator.class); result = getInjector().getInstance(SingleWorldGenerator.class);
@ -977,8 +953,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
return (ChunkGenerator) result.specify(worldName); return (ChunkGenerator) result.specify(worldName);
} }
@Override @Nullable public GeneratorWrapper<?> getGenerator(@Nonnull final String world, @Override @Nullable public GeneratorWrapper<?> getGenerator(@Nonnull final String world, @Nullable final String name) {
@Nullable final String name) {
if (name == null) { if (name == null) {
return null; return null;
} }
@ -990,8 +965,8 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
return new BukkitPlotGenerator(world, gen, this.plotAreaManager); return new BukkitPlotGenerator(world, gen, this.plotAreaManager);
} else { } else {
return new BukkitPlotGenerator(world, getInjector() return new BukkitPlotGenerator(world, getInjector().getInstance(Key.get(IndependentPlotGenerator.class, DefaultGenerator.class)),
.getInstance(Key.get(IndependentPlotGenerator.class, DefaultGenerator.class)), this.plotAreaManager); this.plotAreaManager);
} }
} }
@ -1011,19 +986,14 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
map.put(plotAreaType.name().toLowerCase(), terrainTypes); map.put(plotAreaType.name().toLowerCase(), terrainTypes);
} }
for (final PlotArea plotArea : this.plotAreaManager.getAllPlotAreas()) { for (final PlotArea plotArea : this.plotAreaManager.getAllPlotAreas()) {
final Map<String, Integer> terrainTypeMap = final Map<String, Integer> terrainTypeMap = map.get(plotArea.getType().name().toLowerCase());
map.get(plotArea.getType().name().toLowerCase()); terrainTypeMap.put(plotArea.getTerrain().name().toLowerCase(), terrainTypeMap.get(plotArea.getTerrain().name().toLowerCase()) + 1);
terrainTypeMap.put(plotArea.getTerrain().name().toLowerCase(),
terrainTypeMap.get(plotArea.getTerrain().name().toLowerCase()) + 1);
} }
return map; return map;
})); }));
metrics.addCustomChart(new Metrics.SimplePie("premium", metrics.addCustomChart(new Metrics.SimplePie("premium", () -> PremiumVerification.isPremium() ? "Premium" : "Non-Premium"));
() -> PremiumVerification.isPremium() ? "Premium" : "Non-Premium"));
metrics.addCustomChart(new Metrics.SimplePie("worldedit_implementation", metrics.addCustomChart(new Metrics.SimplePie("worldedit_implementation",
() -> Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null ? () -> Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null ? "FastAsyncWorldEdit" : "WorldEdit"));
"FastAsyncWorldEdit" :
"WorldEdit"));
} }
@Override public void unregister(@Nonnull final PlotPlayer<?> player) { @Override public void unregister(@Nonnull final PlotPlayer<?> player) {
@ -1036,12 +1006,10 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
// create world // create world
ConfigurationSection worldConfig = this.worldConfiguration.getConfigurationSection("worlds." + worldName); ConfigurationSection worldConfig = this.worldConfiguration.getConfigurationSection("worlds." + worldName);
String manager = worldConfig.getString("generator.plugin", getPluginName()); String manager = worldConfig.getString("generator.plugin", getPluginName());
PlotAreaBuilder builder = PlotAreaBuilder.newBuilder().plotManager(manager) PlotAreaBuilder builder =
.generatorName(worldConfig.getString("generator.init", manager)) PlotAreaBuilder.newBuilder().plotManager(manager).generatorName(worldConfig.getString("generator.init", manager))
.plotAreaType(ConfigurationUtil.getType(worldConfig)) .plotAreaType(ConfigurationUtil.getType(worldConfig)).terrainType(ConfigurationUtil.getTerrain(worldConfig))
.terrainType(ConfigurationUtil.getTerrain(worldConfig)) .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)).worldName(worldName);
.settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null))
.worldName(worldName);
getInjector().getInstance(SetupUtils.class).setupWorld(builder); getInjector().getInstance(SetupUtils.class).setupWorld(builder);
world = Bukkit.getWorld(worldName); world = Bukkit.getWorld(worldName);
} else { } else {
@ -1071,16 +1039,14 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
return name.substring(name.lastIndexOf('.') + 1); return name.substring(name.lastIndexOf('.') + 1);
} }
@Override public GeneratorWrapper<?> wrapPlotGenerator(@Nullable final String world, @Override public GeneratorWrapper<?> wrapPlotGenerator(@Nullable final String world, @Nonnull final IndependentPlotGenerator generator) {
@Nonnull final IndependentPlotGenerator generator) {
return new BukkitPlotGenerator(world, generator, this.plotAreaManager); return new BukkitPlotGenerator(world, generator, this.plotAreaManager);
} }
@Override public List<Map.Entry<Map.Entry<String, String>, Boolean>> getPluginIds() { @Override public List<Map.Entry<Map.Entry<String, String>, Boolean>> getPluginIds() {
List<Map.Entry<Map.Entry<String, String>, Boolean>> names = new ArrayList<>(); List<Map.Entry<Map.Entry<String, String>, Boolean>> names = new ArrayList<>();
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) { for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
Map.Entry<String, String> id = new AbstractMap.SimpleEntry<>(plugin.getName(), Map.Entry<String, String> id = new AbstractMap.SimpleEntry<>(plugin.getName(), plugin.getDescription().getVersion());
plugin.getDescription().getVersion());
names.add(new AbstractMap.SimpleEntry<>(id, plugin.isEnabled())); names.add(new AbstractMap.SimpleEntry<>(id, plugin.isEnabled()));
} }
return names; return names;
@ -1115,11 +1081,11 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
} }
@Override @Nonnull public PlatformWorldManager<?> getWorldManager() { @Override @Nonnull public PlatformWorldManager<?> getWorldManager() {
return getInjector().getInstance(Key.get(new TypeLiteral<PlatformWorldManager<World>>() {})); return getInjector().getInstance(Key.get(new TypeLiteral<PlatformWorldManager<World>>() {
}));
} }
@Override @Nonnull @SuppressWarnings("ALL") @Override @Nonnull @SuppressWarnings("ALL") public PlayerManager<? extends PlotPlayer<Player>, ? extends Player> getPlayerManager() {
public PlayerManager<? extends PlotPlayer<Player>, ? extends Player> getPlayerManager() {
return (PlayerManager<BukkitPlayer, Player>) getInjector().getInstance(PlayerManager.class); return (PlayerManager<BukkitPlayer, Player>) getInjector().getInstance(PlayerManager.class);
} }

View File

@ -30,8 +30,9 @@ import com.plotsquared.core.generator.IndependentPlotGenerator;
import com.plotsquared.core.location.ChunkWrapper; import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedLocalBlockQueue; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
@ -44,30 +45,25 @@ final class BlockStatePopulator extends BlockPopulator {
private final IndependentPlotGenerator plotGenerator; private final IndependentPlotGenerator plotGenerator;
private final PlotAreaManager plotAreaManager; private final PlotAreaManager plotAreaManager;
private LocalBlockQueue queue; private QueueCoordinator queue;
public BlockStatePopulator(@Nonnull final IndependentPlotGenerator plotGenerator, public BlockStatePopulator(@Nonnull final IndependentPlotGenerator plotGenerator, @Nonnull final PlotAreaManager plotAreaManager) {
@Nonnull final PlotAreaManager plotAreaManager) {
this.plotGenerator = plotGenerator; this.plotGenerator = plotGenerator;
this.plotAreaManager = plotAreaManager; this.plotAreaManager = plotAreaManager;
} }
@Override @Override public void populate(@Nonnull final World world, @Nonnull final Random random, @Nonnull final Chunk source) {
public void populate(@Nonnull final World world, @Nonnull final Random random,
@Nonnull final Chunk source) {
if (this.queue == null) { if (this.queue == null) {
this.queue = PlotSquared.platform().getGlobalBlockQueue() this.queue = PlotSquared.platform().getGlobalBlockQueue().getNewQueue(new BukkitWorld(world));
.getNewQueue(world.getName(), false);
} }
final PlotArea area = this.plotAreaManager.getPlotArea(world.getName(), null); final PlotArea area = this.plotAreaManager.getPlotArea(world.getName(), null);
if (area == null) { if (area == null) {
return; return;
} }
final ChunkWrapper wrap = final ChunkWrapper wrap = new ChunkWrapper(area.getWorldName(), source.getX(), source.getZ());
new ChunkWrapper(area.getWorldName(), source.getX(), source.getZ()); final ScopedQueueCoordinator chunk = this.queue.getForChunk(wrap.x, wrap.z);
final ScopedLocalBlockQueue chunk = this.queue.getForChunk(wrap.x, wrap.z);
if (this.plotGenerator.populateChunk(chunk, area)) { if (this.plotGenerator.populateChunk(chunk, area)) {
this.queue.flush(); this.queue.enqueue();
} }
} }

View File

@ -34,7 +34,7 @@ import com.plotsquared.core.generator.SingleWorldGenerator;
import com.plotsquared.core.location.ChunkWrapper; import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager; 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.plotsquared.core.util.ChunkManager;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import org.bukkit.World; import org.bukkit.World;
@ -62,7 +62,7 @@ public class BukkitPlotGenerator extends ChunkGenerator
private final String levelName; private final String levelName;
public BukkitPlotGenerator(@Nonnull final String name, public BukkitPlotGenerator(@Nonnull final String name,
@Nonnull final IndependentPlotGenerator generator, @Nonnull final IndependentPlotGenerator generator,
@Nonnull final PlotAreaManager plotAreaManager) { @Nonnull final PlotAreaManager plotAreaManager) {
this.plotAreaManager = plotAreaManager; this.plotAreaManager = plotAreaManager;
@ -186,7 +186,7 @@ public class BukkitPlotGenerator extends ChunkGenerator
return result.getChunkData(); 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 // Load if improperly loaded
if (!this.loaded) { if (!this.loaded) {
String name = world.getName(); String name = world.getName();

View File

@ -31,7 +31,7 @@ import com.plotsquared.core.generator.IndependentPlotGenerator;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId; 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.plotsquared.core.util.MathMan;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import org.bukkit.World; import org.bukkit.World;
@ -63,7 +63,7 @@ final class DelegatePlotGenerator extends IndependentPlotGenerator {
return PlotSquared.platform().getDefaultGenerator().getNewPlotArea(world, id, min, max); 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); World world = BukkitUtil.getWorld(this.world);
Location min = result.getMin(); Location min = result.getMin();
int chunkX = min.getX() >> 4; int chunkX = min.getX() >> 4;
@ -71,11 +71,7 @@ final class DelegatePlotGenerator extends IndependentPlotGenerator {
Random random = new Random(MathMan.pair((short) chunkX, (short) chunkZ)); Random random = new Random(MathMan.pair((short) chunkX, (short) chunkZ));
try { try {
ChunkGenerator.BiomeGrid grid = new ChunkGenerator.BiomeGrid() { ChunkGenerator.BiomeGrid grid = new ChunkGenerator.BiomeGrid() {
@Override @Override public void setBiome(int x, int z, @Nonnull Biome biome) {
public void setBiome(
final int x,
final int z,
@Nonnull final Biome biome) {
result.setBiome(x, z, BukkitAdapter.adapt(biome)); result.setBiome(x, z, BukkitAdapter.adapt(biome));
} }

View File

@ -31,7 +31,8 @@ import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.bukkit.player.BukkitPlayerManager; 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.schematic.BukkitSchematicHandler;
import com.plotsquared.bukkit.util.BukkitChunkManager; import com.plotsquared.bukkit.util.BukkitChunkManager;
import com.plotsquared.bukkit.util.BukkitEconHandler; 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.generator.IndependentPlotGenerator;
import com.plotsquared.core.inject.annotations.ConsoleActor; import com.plotsquared.core.inject.annotations.ConsoleActor;
import com.plotsquared.core.inject.annotations.DefaultGenerator; 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.inject.factory.HybridPlotWorldFactory;
import com.plotsquared.core.plot.world.DefaultPlotAreaManager; import com.plotsquared.core.plot.world.DefaultPlotAreaManager;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotAreaManager;
import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueProvider; import com.plotsquared.core.queue.QueueProvider;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
@ -88,8 +92,7 @@ public class BukkitModule extends AbstractModule {
bind(InventoryUtil.class).to(BukkitInventoryUtil.class); bind(InventoryUtil.class).to(BukkitInventoryUtil.class);
bind(SetupUtils.class).to(BukkitSetupUtils.class); bind(SetupUtils.class).to(BukkitSetupUtils.class);
bind(WorldUtil.class).to(BukkitUtil.class); bind(WorldUtil.class).to(BukkitUtil.class);
bind(GlobalBlockQueue.class).toInstance(new GlobalBlockQueue( bind(GlobalBlockQueue.class).toInstance(new GlobalBlockQueue(QueueProvider.of(BukkitQueueCoordinator.class)));
QueueProvider.of(BukkitLocalQueue.class, BukkitLocalQueue.class), 1, Settings.QUEUE.TARGET_TIME));
bind(ChunkManager.class).to(BukkitChunkManager.class); bind(ChunkManager.class).to(BukkitChunkManager.class);
bind(RegionManager.class).to(BukkitRegionManager.class); bind(RegionManager.class).to(BukkitRegionManager.class);
bind(SchematicHandler.class).to(BukkitSchematicHandler.class); bind(SchematicHandler.class).to(BukkitSchematicHandler.class);
@ -99,6 +102,8 @@ public class BukkitModule extends AbstractModule {
bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class); bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class);
} }
install(new FactoryModuleBuilder().build(HybridPlotWorldFactory.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() { @Provides @Singleton @Nullable EconHandler provideEconHandler() {

File diff suppressed because it is too large Load Diff

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<MetadataValue> 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<MetadataValue> meta = event.getEntity().getMetadata("plot");
Plot origin;
if (meta.isEmpty()) {
origin = plot;
} else {
origin = (Plot) meta.get(0).value();
}
if (this.lastRadius != 0) {
List<Entity> 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<Block> 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));
}
}
}

View File

@ -25,6 +25,7 @@
*/ */
package com.plotsquared.bukkit.listener; package com.plotsquared.bukkit.listener;
import com.plotsquared.bukkit.util.BukkitEntityUtil;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
@ -66,8 +67,7 @@ public class EntitySpawnListener implements Listener {
public static void testNether(final Entity entity) { public static void testNether(final Entity entity) {
@Nonnull World world = entity.getWorld(); @Nonnull World world = entity.getWorld();
if (world.getEnvironment() != World.Environment.NETHER if (world.getEnvironment() != World.Environment.NETHER && world.getEnvironment() != World.Environment.THE_END) {
&& world.getEnvironment() != World.Environment.THE_END) {
return; return;
} }
test(entity); test(entity);
@ -91,8 +91,7 @@ public class EntitySpawnListener implements Listener {
List<MetadataValue> meta = entity.getMetadata(KEY); List<MetadataValue> meta = entity.getMetadata(KEY);
if (meta.isEmpty()) { if (meta.isEmpty()) {
if (PlotSquared.get().getPlotAreaManager().hasPlotArea(world.getName())) { if (PlotSquared.get().getPlotAreaManager().hasPlotArea(world.getName())) {
entity.setMetadata(KEY, entity.setMetadata(KEY, new FixedMetadataValue((Plugin) PlotSquared.platform(), entity.getLocation()));
new FixedMetadataValue((Plugin) PlotSquared.platform(), entity.getLocation()));
} }
} else { } else {
org.bukkit.Location origin = (org.bukkit.Location) meta.get(0).value(); 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) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void creatureSpawnEvent(EntitySpawnEvent event) {
public void creatureSpawnEvent(EntitySpawnEvent event) {
Entity entity = event.getEntity(); Entity entity = event.getEntity();
Location location = BukkitUtil.adapt(entity.getLocation()); Location location = BukkitUtil.adapt(entity.getLocation());
PlotArea area = location.getPlotArea(); PlotArea area = location.getPlotArea();
@ -155,13 +153,12 @@ public class EntitySpawnListener implements Listener {
} }
switch (entity.getType()) { switch (entity.getType()) {
case ENDER_CRYSTAL: case ENDER_CRYSTAL:
if (PlayerEvents.checkEntity(entity, plot)) { if (BukkitEntityUtil.checkEntity(entity, plot)) {
event.setCancelled(true); event.setCancelled(true);
} }
case SHULKER: case SHULKER:
if (!entity.hasMetadata("shulkerPlot")) { if (!entity.hasMetadata("shulkerPlot")) {
entity.setMetadata("shulkerPlot", entity.setMetadata("shulkerPlot", new FixedMetadataValue((Plugin) PlotSquared.platform(), plot.getId()));
new FixedMetadataValue((Plugin) PlotSquared.platform(), plot.getId()));
} }
} }
} }
@ -192,8 +189,7 @@ public class EntitySpawnListener implements Listener {
} }
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void vehicleMove(VehicleMoveEvent event) {
public void vehicleMove(VehicleMoveEvent event) {
testNether(event.getVehicle()); testNether(event.getVehicle());
} }

File diff suppressed because it is too large Load Diff

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Player> 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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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"));
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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> player = BukkitUtil.adapt(placeholderReplaceEvent.getPlayer());
String key = placeholderReplaceEvent.getPlaceholder().substring(PREFIX.length());
return registry.getPlaceholderValue(key, player);
});
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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() : "";
}
}
}

View File

@ -73,10 +73,7 @@ public class BukkitPlayer extends PlotPlayer<Player> {
private static boolean CHECK_EFFECTIVE = true; private static boolean CHECK_EFFECTIVE = true;
public final Player player; public final Player player;
private final EconHandler econHandler;
private String name; private String name;
private String lastMessage = "";
private long lastMessageTime = 0L;
/** /**
* <p>Please do not use this method. Instead use * <p>Please do not use this method. Instead use
* BukkitUtil.getPlayer(Player), as it caches player objects.</p> * BukkitUtil.getPlayer(Player), as it caches player objects.</p>
@ -94,7 +91,6 @@ public class BukkitPlayer extends PlotPlayer<Player> {
@Nonnull final PermissionHandler permissionHandler) { @Nonnull final PermissionHandler permissionHandler) {
super(plotAreaManager, eventDispatcher, econHandler, permissionHandler); super(plotAreaManager, eventDispatcher, econHandler, permissionHandler);
this.player = player; this.player = player;
this.econHandler = econHandler;
this.setupPermissionProfile(); this.setupPermissionProfile();
if (realPlayer) { if (realPlayer) {
super.populatePersistentMetaMap(); super.populatePersistentMetaMap();
@ -153,13 +149,6 @@ public class BukkitPlayer extends PlotPlayer<Player> {
} }
} }
@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, @Override @Nonnegative public int hasPermissionRange(@Nonnull final String stub,
@Nonnegative final int range) { @Nonnegative final int range) {
if (hasPermission(Permission.PERMISSION_ADMIN.toString())) { if (hasPermission(Permission.PERMISSION_ADMIN.toString())) {

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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
* <p>
* The coordinator takes in collection of chunk coordinates, loads them
* and allows the caller to specify a sink for the loaded chunks. The
* coordinator will prevent the chunks from being unloaded until the sink
* has fully consumed the chunk
* <p>
**/
public final class BukkitChunkCoordinator extends ChunkCoordinator {
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
private final Queue<BlockVector2> requestedChunks;
private final Queue<Chunk> availableChunks;
private final long maxIterationTime;
private final Plugin plugin;
private final Consumer<BlockVector2> chunkConsumer;
private final org.bukkit.World bukkitWorld;
private final Runnable whenDone;
private final Consumer<Throwable> 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<BlockVector2> chunkConsumer,
@Assisted @Nonnull final World world,
@Assisted @Nonnull final Collection<BlockVector2> requestedChunks,
@Assisted @Nonnull final Runnable whenDone,
@Assisted @Nonnull final Consumer<Throwable> 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);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Chunk> 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<Chunk> 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);
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<BlockVector2> 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<BlockVector2> 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());
}
}
}
}

View File

@ -30,7 +30,7 @@ import com.plotsquared.bukkit.util.BukkitBlockUtil;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.location.ChunkWrapper; import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.location.Location; 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.ChunkUtil;
import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.PatternUtil;
import com.sk89q.worldedit.bukkit.BukkitAdapter; 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.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid; import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData; import org.bukkit.generator.ChunkGenerator.ChunkData;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
public class GenChunk extends ScopedLocalBlockQueue { public class GenChunk extends ScopedQueueCoordinator {
public final Biome[] biomes; public final Biome[] biomes;
public BlockState[][] result; public BlockState[][] result;
@ -64,7 +65,18 @@ public class GenChunk extends ScopedLocalBlockQueue {
this.biomes = Biome.values(); 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) { if (chunk == null) {
World worldObj = BukkitUtil.getWorld(world); World worldObj = BukkitUtil.getWorld(world);
if (worldObj != null) { if (worldObj != null) {
@ -74,32 +86,40 @@ public class GenChunk extends ScopedLocalBlockQueue {
return chunk; return chunk;
} }
public void setChunk(Chunk chunk) { /**
* Set the chunk being represented
*/
public void setChunk(@Nonnull Chunk chunk) {
this.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; chunk = null;
world = wrap.world; world = wrap.world;
chunkX = wrap.x; chunkX = wrap.x;
chunkZ = wrap.z; chunkZ = wrap.z;
} }
@Override public void fillBiome(BiomeType biomeType) { @Override public void fillBiome(@Nonnull BiomeType biomeType) {
if (biomeGrid == null) { if (biomeGrid == null) {
return; return;
} }
Biome biome = BukkitAdapter.adapt(biomeType); Biome biome = BukkitAdapter.adapt(biomeType);
for (int x = 0; x < 16; x++) { for (int y = 0; y < 256; y++) {
for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) {
this.biomeGrid.setBiome(x, z, biome); for (int z = 0; z < 16; z++) {
this.biomeGrid.setBiome(x, y, z, biome);
}
} }
} }
} }
@Override public void setCuboid(Location pos1, Location pos2, BlockState block) { @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 if (result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15 && pos2.getZ() == 15) {
&& pos2.getZ() == 15) {
for (int y = pos1.getY(); y <= pos2.getY(); y++) { for (int y = pos1.getY(); y <= pos2.getY(); y++) {
int layer = y >> 4; int layer = y >> 4;
BlockState[] data = result[layer]; BlockState[] data = result[layer];
@ -117,28 +137,39 @@ public class GenChunk extends ScopedLocalBlockQueue {
int maxX = Math.max(pos1.getX(), pos2.getX()); int maxX = Math.max(pos1.getX(), pos2.getX());
int maxY = Math.max(pos1.getY(), pos2.getY()); int maxY = Math.max(pos1.getY(), pos2.getY());
int maxZ = Math.max(pos1.getZ(), pos2.getZ()); int maxZ = Math.max(pos1.getZ(), pos2.getZ());
chunkData chunkData.setRegion(minX, minY, minZ, maxX + 1, maxY + 1, maxZ + 1, BukkitAdapter.adapt(block));
.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)); 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) { 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 true;
} }
return false; return false;
} }
@Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) { @Override public boolean setBlock(int x, int y, int z, @Nonnull Pattern pattern) {
return setBlock(x, y, z, PatternUtil return setBlock(x, y, z, PatternUtil.apply(Preconditions.checkNotNull(pattern, "Pattern may not be null"), x, y, z));
.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) { if (this.result == null) {
this.chunkData.setBlock(x, y, z, BukkitAdapter.adapt(id)); this.chunkData.setBlock(x, y, z, BukkitAdapter.adapt(id));
return true; return true;
@ -148,7 +179,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
return true; 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; int i = y >> 4;
BlockState[] v = this.result[i]; BlockState[] v = this.result[i];
if (v == null) { if (v == null) {
@ -158,7 +189,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
v[j] = id; 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) { if (this.result == null) {
this.chunkData.setBlock(x, y, z, BukkitAdapter.adapt(id)); this.chunkData.setBlock(x, y, z, BukkitAdapter.adapt(id));
return true; return true;
@ -168,7 +199,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
return true; 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; int i = y >> 4;
if (result == null) { if (result == null) {
return BukkitBlockUtil.get(chunkData.getType(x, y, z)); return BukkitBlockUtil.get(chunkData.getType(x, y, z));
@ -189,19 +220,19 @@ public class GenChunk extends ScopedLocalBlockQueue {
return chunk == null ? chunkZ : chunk.getZ(); return chunk == null ? chunkZ : chunk.getZ();
} }
@Override public String getWorld() { @Override @Nonnull public com.sk89q.worldedit.world.World getWorld() {
return chunk == null ? world : chunk.getWorld().getName(); return chunk == null ? BukkitAdapter.adapt(Bukkit.getWorld(world)) : BukkitAdapter.adapt(chunk.getWorld());
} }
@Override public Location getMax() { @Override @Nonnull public Location getMax() {
return Location.at(getWorld(), 15 + (getX() << 4), 255, 15 + (getZ() << 4)); return Location.at(getWorld().getName(), 15 + (getX() << 4), 255, 15 + (getZ() << 4));
} }
@Override public Location getMin() { @Override @Nonnull public Location getMin() {
return Location.at(getWorld(), getX() << 4, 0, getZ() << 4); return Location.at(getWorld().getName(), getX() << 4, 0, getZ() << 4);
} }
public GenChunk clone() { @Nonnull public GenChunk clone() {
GenChunk toReturn = new GenChunk(); GenChunk toReturn = new GenChunk();
if (this.result != null) { if (this.result != null) {
for (int i = 0; i < this.result.length; i++) { for (int i = 0; i < this.result.length; i++) {
@ -215,12 +246,4 @@ public class GenChunk extends ScopedLocalBlockQueue {
toReturn.chunkData = this.chunkData; toReturn.chunkData = this.chunkData;
return toReturn; return toReturn;
} }
public ChunkData getChunkData() {
return this.chunkData;
}
public void setChunkData(ChunkData chunkData) {
this.chunkData = chunkData;
}
} }

View File

@ -27,7 +27,7 @@ package com.plotsquared.bukkit.schematic;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; 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.SchematicHandler;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
@ -44,7 +44,7 @@ import javax.annotation.Nonnull;
} }
@Override @Override
public boolean restoreTile(LocalBlockQueue queue, CompoundTag ct, int x, int y, int z) { public boolean restoreTile(QueueCoordinator queue, CompoundTag ct, int x, int y, int z) {
return new StateWrapper(ct).restoreTag(queue.getWorld(), x, y, z); return new StateWrapper(ct).restoreTag(queue.getWorld().getName(), x, y, z);
} }
} }

View File

@ -26,140 +26,23 @@
package com.plotsquared.bukkit.util; package com.plotsquared.bukkit.util;
import com.google.inject.Singleton; 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.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.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BaseBlock;
import io.papermc.lib.PaperLib; 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 java.util.concurrent.CompletableFuture;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ANIMAL; @Singleton
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY; public class BukkitChunkManager extends ChunkManager {
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 {
public static boolean isIn(CuboidRegion region, int x, int z) { public static boolean isIn(CuboidRegion region, int x, int z) {
return x >= region.getMinimumPoint().getX() && x <= region.getMaximumPoint().getX() return x >= region.getMinimumPoint().getX() && x <= region.getMaximumPoint().getX() && z >= region.getMinimumPoint().getZ() && z <= region
&& z >= region.getMinimumPoint().getZ() && z <= region.getMaximumPoint().getZ(); .getMaximumPoint().getZ();
} }
public static ContentMap swapChunk(World world1, World world2, Chunk pos1, Chunk pos2, @Override public CompletableFuture<?> loadChunk(String world, BlockVector2 chunkLoc, boolean force) {
CuboidRegion r1, CuboidRegion r2) { return PaperLib.getChunkAtAsync(BukkitUtil.getWorld(world), chunkLoc.getX(), chunkLoc.getZ(), force);
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 void unloadChunk(final String world, final BlockVector2 chunkLoc, final boolean save) {
if (!PlotSquared.get().isMainThread(Thread.currentThread())) {
TaskManager.runTask(() -> BukkitUtil.getWorld(world)
.unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save));
} else {
BukkitUtil.getWorld(world).unloadChunk(chunkLoc.getX(), chunkLoc.getZ(), save);
}
}
private void count(int[] count, Entity entity) {
final com.sk89q.worldedit.world.entity.EntityType entityType =
BukkitAdapter.adapt(entity.getType());
if (EntityCategories.PLAYER.contains(entityType)) {
return;
} else if (EntityCategories.PROJECTILE.contains(entityType) || EntityCategories.OTHER
.contains(entityType) || EntityCategories.HANGING.contains(entityType)) {
count[CAP_MISC]++;
} else if (EntityCategories.ANIMAL.contains(entityType) || EntityCategories.VILLAGER
.contains(entityType) || EntityCategories.TAMEABLE.contains(entityType)) {
count[CAP_MOB]++;
count[CAP_ANIMAL]++;
} else if (EntityCategories.VEHICLE.contains(entityType)) {
count[CAP_VEHICLE]++;
} else if (EntityCategories.HOSTILE.contains(entityType)) {
count[CAP_MOB]++;
count[CAP_MONSTER]++;
}
count[CAP_ENTITY]++;
}
} }

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -27,29 +27,24 @@ package com.plotsquared.bukkit.util;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.generator.AugmentedUtils; import com.plotsquared.core.generator.AugmentedUtils;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.location.PlotLoc; import com.plotsquared.core.location.PlotLoc;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotManager; import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.ScopedLocalBlockQueue; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.RegionUtil; import com.plotsquared.core.util.RegionUtil;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.entity.EntityCategories;
import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
@ -62,16 +57,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set; 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_ANIMAL;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY; import static com.plotsquared.core.util.entity.EntityCategories.CAP_ENTITY;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC; import static com.plotsquared.core.util.entity.EntityCategories.CAP_MISC;
@ -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_MONSTER;
import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE; 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) { @Inject
super(chunkManager); public BukkitRegionManager(@Nonnull WorldUtil worldUtil, @Nonnull GlobalBlockQueue blockQueue) {
} super(worldUtil, blockQueue);
this.blockQueue = blockQueue;
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<BlockVector2> getChunkChunks(String world) {
Set<BlockVector2> 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;
} }
@Override public boolean handleClear(Plot plot, Runnable whenDone, PlotManager manager) { @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(); PlotArea area = plot.getArea();
World world = BukkitUtil.getWorld(area.getWorldName()); World world = BukkitUtil.getWorld(area.getWorldName());
Location bot = plot.getBottomAbs(); Location bot = plot.getBottomAbs();
Location top = plot.getTopAbs(); Location top = plot.getTopAbs();
int bx = bot.getX() >> 4; int bx = bot.getX() >> 4;
@ -199,65 +161,9 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
return count; return count;
} }
@Override @Override public boolean regenerateRegion(final Location pos1, final Location pos2,
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<int[]>() {
@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<PlotLoc, BaseBlock[]> entry : map.allBlocks.entrySet()) {
PlotLoc loc = entry.getKey();
BaseBlock[] blocks = entry.getValue();
for (int y = 0; y < blocks.length; y++) {
if (blocks[y] != null) {
BaseBlock block = blocks[y];
queue.setBlock(loc.getX(), y, loc.getZ(), block);
}
}
}
queue.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,
final boolean ignoreAugment, final Runnable whenDone) { 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 p1x = pos1.getX();
final int p1z = pos1.getZ(); 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 tcx = p2x >> 4;
final int tcz = p2z >> 4; final int tcz = p2z >> 4;
final List<BlockVector2> chunks = new ArrayList<>(); final QueueCoordinator queue = blockQueue.getNewQueue(world);
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++) { int x = chunk.getX();
for (int z = bcz; z <= tcz; z++) { int z = chunk.getZ();
chunks.add(BlockVector2.at(x, z)); 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;
} }
} boolean checkX1 = false;
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;
int xxb2; int xxb2;
if (x == bcx) { if (x == bcx) {
xxb2 = p1x - 1; xxb2 = p1x - 1;
checkX1 = true; checkX1 = true;
} else { } else {
xxb2 = xxb; xxb2 = xxb;
} }
boolean checkX2 = false; boolean checkX2 = false;
int xxt2; int xxt2;
if (x == tcx) { if (x == tcx) {
xxt2 = p2x + 1; xxt2 = p2x + 1;
checkX2 = true; checkX2 = true;
} else { } else {
xxt2 = xxt; xxt2 = xxt;
} }
boolean checkZ1 = false; boolean checkZ1 = false;
int zzb2; int zzb2;
if (z == bcz) { if (z == bcz) {
zzb2 = p1z - 1; zzb2 = p1z - 1;
checkZ1 = true; checkZ1 = true;
} else { } else {
zzb2 = zzb; zzb2 = zzb;
} }
boolean checkZ2 = false; boolean checkZ2 = false;
int zzt2; int zzt2;
if (z == tcz) { if (z == tcz) {
zzt2 = p2z + 1; zzt2 = p2z + 1;
checkZ2 = true; checkZ2 = true;
} else { } else {
zzt2 = zzt; zzt2 = zzt;
} }
final ContentMap map = new ContentMap(); final ContentMap map = new ContentMap();
if (checkX1) { if (checkX1) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb2, zzt2); // map.saveRegion(world, xxb, xxb2, zzb2, zzt2); //
} }
if (checkX2) { if (checkX2) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb2, zzt2); // map.saveRegion(world, xxt2, xxt, zzb2, zzt2); //
} }
if (checkZ1) { if (checkZ1) {
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzb, zzb2); // map.saveRegion(world, xxb2, xxt2, zzb, zzb2); //
} }
if (checkZ2) { if (checkZ2) {
map.saveRegion(bukkitWorldObj, xxb2, xxt2, zzt2, zzt); // map.saveRegion(world, xxb2, xxt2, zzt2, zzt); //
} }
if (checkX1 && checkZ1) { if (checkX1 && checkZ1) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzb, zzb2); // map.saveRegion(world, xxb, xxb2, zzb, zzb2); //
} }
if (checkX2 && checkZ1) { if (checkX2 && checkZ1) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzb, zzb2); // ? map.saveRegion(world, xxt2, xxt, zzb, zzb2); // ?
} }
if (checkX1 && checkZ2) { if (checkX1 && checkZ2) {
map.saveRegion(bukkitWorldObj, xxb, xxb2, zzt2, zzt); // ? map.saveRegion(world, xxb, xxb2, zzt2, zzt); // ?
} }
if (checkX2 && checkZ2) { if (checkX2 && checkZ2) {
map.saveRegion(bukkitWorldObj, xxt2, xxt, zzt2, zzt); // map.saveRegion(world, xxt2, xxt, zzt2, zzt); //
} }
CuboidRegion currentPlotClear = RegionUtil CuboidRegion currentPlotClear =
.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
map.saveEntitiesOut(chunkObj, currentPlotClear); map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z),
AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager currentPlotClear);
.setChunkInPlotArea(null, new RunnableVal<ScopedLocalBlockQueue>() { AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager
@Override public void run(ScopedLocalBlockQueue value) { .setChunkInPlotArea(null, new RunnableVal<ScopedQueueCoordinator>() {
Location min = value.getMin(); @Override public void run(ScopedQueueCoordinator value) {
int bx = min.getX(); Location min = value.getMin();
int bz = min.getZ(); int bx = min.getX();
for (int x1 = 0; x1 < 16; x1++) { int bz = min.getZ();
for (int z1 = 0; z1 < 16; z1++) { for (int x1 = 0; x1 < 16; x1++) {
PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1); for (int z1 = 0; z1 < 16; z1++) {
BaseBlock[] ids = map.allBlocks.get(plotLoc); PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
if (ids != null) { BaseBlock[] ids = map.allBlocks.get(plotLoc);
for (int y = 0; if (ids != null) {
y < Math.min(128, ids.length); y++) { for (int y = 0; y < Math.min(128, ids.length); y++) {
BaseBlock id = ids[y]; BaseBlock id = ids[y];
if (id != null) { if (id != null) {
value.setBlock(x1, y, z1, id); value.setBlock(x1, y, z1, id);
} else { } else {
value.setBlock(x1, y, z1, value.setBlock(x1, y, z1,
BlockTypes.AIR.getDefaultState()); BlockTypes.AIR.getDefaultState());
} }
} }
for (int y = Math.min(128, ids.length); for (int y = Math.min(128, ids.length); y < ids.length; y++) {
y < ids.length; y++) { BaseBlock id = ids[y];
BaseBlock id = ids[y]; if (id != null) {
if (id != null) { value.setBlock(x1, y, z1, id);
value.setBlock(x1, y, z1, id);
}
}
}
} }
} }
} }
}, world, chunk)); }
//map.restoreBlocks(worldObj, 0, 0); }
map.restoreEntities(worldObj, 0, 0); }
}); }, world.getName(), chunk));
} //map.restoreBlocks(worldObj, 0, 0);
if (!chunks.isEmpty()) { map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0);
TaskManager.runTaskLater(this, TaskTime.ticks(1L));
} else {
TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L));
}
}
}); });
regenQueue.setCompleteTask(whenDone);
queue.setCompleteTask(regenQueue::enqueue);
queue.enqueue();
return true; 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<ContentMap> maps = new ArrayDeque<>();
for (int x = bot1.getX() >> 4; x <= top1.getX() >> 4; x++) {
for (int z = bot1.getZ() >> 4; z <= top1.getZ() >> 4; z++) {
Chunk chunk1 = world1.getChunkAt(x, z);
Chunk chunk2 = world2.getChunkAt(x + (relX >> 4), z + (relZ >> 4));
maps.add(
BukkitChunkManager.swapChunk(world1, world2, chunk1, chunk2, region1, region2));
}
}
PlotSquared.platform().getGlobalBlockQueue().addEmptyTask(() -> {
for (ContentMap map : maps) {
map.restoreEntities(world1, 0, 0);
TaskManager.runTaskLater(whenDone, TaskTime.ticks(1L));
}
});
}
@Override
public void setBiome(final CuboidRegion region, final int extendBiome, final BiomeType biome,
final String world, final Runnable whenDone) {
Location pos1 = Location.at(world, region.getMinimumPoint().getX() - extendBiome,
region.getMinimumPoint().getY(), region.getMinimumPoint().getZ() - extendBiome);
Location pos2 = Location.at(world, region.getMaximumPoint().getX() + extendBiome,
region.getMaximumPoint().getY(), region.getMaximumPoint().getZ() + extendBiome);
final LocalBlockQueue queue = PlotSquared.platform().getGlobalBlockQueue()
.getNewQueue(world, false);
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
@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) { private void count(int[] count, Entity entity) {
final com.sk89q.worldedit.world.entity.EntityType entityType = final com.sk89q.worldedit.world.entity.EntityType entityType =
BukkitAdapter.adapt(entity.getType()); BukkitAdapter.adapt(entity.getType());

View File

@ -25,7 +25,6 @@
*/ */
package com.plotsquared.bukkit.util; package com.plotsquared.bukkit.util;
import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.bukkit.player.BukkitPlayer; 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.BlockUtil;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.PlayerManager;
import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.StringComparison;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
@ -106,12 +104,14 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.IntConsumer; import java.util.function.IntConsumer;
import java.util.stream.Stream; import java.util.stream.Stream;
@SuppressWarnings({"unused", "WeakerAccess"}) @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()); private static final Logger logger = LoggerFactory.getLogger("P2/" + BukkitUtil.class.getSimpleName());
@ -121,10 +121,6 @@ import java.util.stream.Stream;
private final Collection<BlockType> tileEntityTypes = new HashSet<>(); private final Collection<BlockType> tileEntityTypes = new HashSet<>();
@Inject public BukkitUtil(@Nonnull final RegionManager regionManager) {
super(regionManager);
}
/** /**
* Turn a Bukkit {@link Player} into a PlotSquared {@link PlotPlayer} * Turn a Bukkit {@link Player} into a PlotSquared {@link PlotPlayer}
* *
@ -144,8 +140,9 @@ import java.util.stream.Stream;
* @return PlotSquared location * @return PlotSquared location
*/ */
@Nonnull public static Location adapt(@Nonnull final org.bukkit.Location location) { @Nonnull public static Location adapt(@Nonnull final org.bukkit.Location location) {
return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()), return Location
MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ())); .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 * @return PlotSquared location
*/ */
@Nonnull public static Location adaptComplete(@Nonnull final org.bukkit.Location location) { @Nonnull public static Location adaptComplete(@Nonnull final org.bukkit.Location location) {
return Location.at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()), return Location
MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ()), location.getYaw(), .at(com.plotsquared.bukkit.util.BukkitWorld.of(location.getWorld()), MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()),
location.getPitch()); MathMan.roundInt(location.getZ()), location.getYaw(), location.getPitch());
} }
/** /**
@ -169,8 +166,7 @@ import java.util.stream.Stream;
* @return Bukkit location * @return Bukkit location
*/ */
@Nonnull public static org.bukkit.Location adapt(@Nonnull final Location location) { @Nonnull public static org.bukkit.Location adapt(@Nonnull final Location location) {
return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(), location.getX(), return new org.bukkit.Location((World) location.getWorld().getPlatformWorld(), location.getX(), location.getY(), location.getZ());
location.getY(), location.getZ());
} }
/** /**
@ -183,30 +179,24 @@ import java.util.stream.Stream;
return Bukkit.getWorld(string); return Bukkit.getWorld(string);
} }
private static void ensureLoaded(@Nonnull final String world, final int x, final int z, private static void ensureLoaded(@Nonnull final String world, final int x, final int z, @Nonnull final Consumer<Chunk> chunkConsumer) {
@Nonnull final Consumer<Chunk> chunkConsumer) { PaperLib.getChunkAtAsync(Objects.requireNonNull(getWorld(world)), x >> 4, z >> 4, true)
PaperLib.getChunkAtAsync(Objects.requireNonNull(getWorld(world)),
x >> 4, z >> 4, true)
.thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk)); .thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
} }
private static void ensureLoaded(@Nonnull final Location location, @Nonnull final Consumer<Chunk> chunkConsumer) { private static void ensureLoaded(@Nonnull final Location location, @Nonnull final Consumer<Chunk> chunkConsumer) {
PaperLib.getChunkAtAsync(adapt(location), true) PaperLib.getChunkAtAsync(adapt(location), true).thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
.thenAccept(chunk -> ensureMainThread(chunkConsumer, chunk));
} }
private static <T> void ensureMainThread(@Nonnull final Consumer<T> consumer, private static <T> void ensureMainThread(@Nonnull final Consumer<T> consumer, @Nonnull final T value) {
@Nonnull final T value) {
if (Bukkit.isPrimaryThread()) { if (Bukkit.isPrimaryThread()) {
consumer.accept(value); consumer.accept(value);
} else { } else {
Bukkit.getScheduler() Bukkit.getScheduler().runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> consumer.accept(value));
.runTask(BukkitPlatform.getPlugin(BukkitPlatform.class), () -> consumer.accept(value));
} }
} }
@Override public boolean isBlockSame(@Nonnull final BlockState block1, @Override public boolean isBlockSame(@Nonnull final BlockState block1, @Nonnull final BlockState block2) {
@Nonnull final BlockState block2) {
if (block1.equals(block2)) { if (block1.equals(block2)) {
return true; return true;
} }
@ -219,20 +209,15 @@ import java.util.stream.Stream;
return getWorld(worldName) != null; return getWorld(worldName) != null;
} }
@Override public void getBiome(@Nonnull final String world, final int x, @Override public void getBiome(@Nonnull final String world, final int x, final int z, @Nonnull final Consumer<BiomeType> result) {
final int z, @Nonnull final Consumer<BiomeType> result) { ensureLoaded(world, x, z, chunk -> result.accept(BukkitAdapter.adapt(getWorld(world).getBiome(x, z))));
ensureLoaded(world, x, z,
chunk -> result.accept(BukkitAdapter.adapt(getWorld(world).getBiome(x, z))));
} }
@Override @Nonnull public BiomeType getBiomeSynchronous(@Nonnull final String world, @Override @Nonnull public BiomeType getBiomeSynchronous(@Nonnull final String world, final int x, final int z) {
final int x, final int z) {
return BukkitAdapter.adapt(Objects.requireNonNull(getWorld(world)).getBiome(x, z)); return BukkitAdapter.adapt(Objects.requireNonNull(getWorld(world)).getBiome(x, z));
} }
@Override @Override public void getHighestBlock(@Nonnull final String world, final int x, final int z, @Nonnull final IntConsumer result) {
public void getHighestBlock(@Nonnull final String world, final int x, final int z,
@Nonnull final IntConsumer result) {
ensureLoaded(world, x, z, chunk -> { ensureLoaded(world, x, z, chunk -> {
final World bukkitWorld = Objects.requireNonNull(getWorld(world)); final World bukkitWorld = Objects.requireNonNull(getWorld(world));
// Skip top and bottom block // Skip top and bottom block
@ -258,9 +243,7 @@ import java.util.stream.Stream;
}); });
} }
@Override @Nonnegative @Override @Nonnegative public int getHighestBlockSynchronous(@Nonnull final String world, final int x, final int z) {
public int getHighestBlockSynchronous(@Nonnull final String world,
final int x, final int z) {
final World bukkitWorld = Objects.requireNonNull(getWorld(world)); final World bukkitWorld = Objects.requireNonNull(getWorld(world));
// Skip top and bottom block // Skip top and bottom block
int air = 1; int air = 1;
@ -282,10 +265,8 @@ import java.util.stream.Stream;
return bukkitWorld.getMaxHeight() - 1; return bukkitWorld.getMaxHeight() - 1;
} }
@Override @Nonnull @Override @Nonnull public String[] getSignSynchronous(@Nonnull final Location location) {
public String[] getSignSynchronous(@Nonnull final Location location) { Block block = Objects.requireNonNull(getWorld(location.getWorldName())).getBlockAt(location.getX(), location.getY(), location.getZ());
Block block = Objects.requireNonNull(getWorld(location.getWorldName()))
.getBlockAt(location.getX(), location.getY(), location.getZ());
try { try {
return TaskManager.getPlatformImplementation().sync(() -> { return TaskManager.getPlatformImplementation().sync(() -> {
if (block.getState() instanceof Sign) { if (block.getState() instanceof Sign) {
@ -300,11 +281,9 @@ import java.util.stream.Stream;
return new String[0]; return new String[0];
} }
@Override @Nonnull @Override @Nonnull public Location getSpawn(@Nonnull final String world) {
public Location getSpawn(@Nonnull final String world) {
final org.bukkit.Location temp = getWorld(world).getSpawnLocation(); final org.bukkit.Location temp = getWorld(world).getSpawnLocation();
return Location.at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), return Location.at(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), temp.getYaw(), temp.getPitch());
temp.getYaw(), temp.getPitch());
} }
@Override public void setSpawn(@Nonnull final Location location) { @Override public void setSpawn(@Nonnull final Location location) {
@ -362,16 +341,12 @@ import java.util.stream.Stream;
}); });
} }
@Override @Nonnull @Override @Nonnull public StringComparison<BlockState>.ComparisonResult getClosestBlock(@Nonnull String name) {
public StringComparison<BlockState>.ComparisonResult getClosestBlock(@Nonnull String name) {
BlockState state = BlockUtil.get(name); BlockState state = BlockUtil.get(name);
return new StringComparison<BlockState>().new ComparisonResult(1, state); return new StringComparison<BlockState>().new ComparisonResult(1, state);
} }
@Override @Override public void setBiomes(@Nonnull final String worldName, @Nonnull final CuboidRegion region, @Nonnull final BiomeType biomeType) {
public void setBiomes(@Nonnull final String worldName,
@Nonnull final CuboidRegion region,
@Nonnull final BiomeType biomeType) {
final World world = getWorld(worldName); final World world = getWorld(worldName);
if (world == null) { if (world == null) {
logger.warn("[P2] An error occured while setting the biome because the world was null", new RuntimeException()); 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); final Biome biome = BukkitAdapter.adapt(biomeType);
for (int x = region.getMinimumPoint().getX(); x <= region.getMaximumPoint().getX(); x++) { for (int x = region.getMinimumPoint().getX(); x <= region.getMaximumPoint().getX(); x++) {
for (int z = region.getMinimumPoint().getZ(); for (int z = region.getMinimumPoint().getZ(); z <= region.getMaximumPoint().getZ(); z++) {
z <= region.getMaximumPoint().getZ(); z++) {
if (world.getBiome(x, z) != biome) { if (world.getBiome(x, z) != biome) {
world.setBiome(x, z, biome); world.setBiome(x, z, biome);
} }
@ -392,50 +366,41 @@ import java.util.stream.Stream;
return new BukkitWorld(Bukkit.getWorld(world)); return new BukkitWorld(Bukkit.getWorld(world));
} }
@Override @Override public void refreshChunk(int x, int z, String world) {
public void getBlock(@Nonnull final Location location, Bukkit.getWorld(world).refreshChunk(x, z);
@Nonnull final Consumer<BlockState> result) { }
@Override public void getBlock(@Nonnull final Location location, @Nonnull final Consumer<BlockState> result) {
ensureLoaded(location, chunk -> { ensureLoaded(location, chunk -> {
final World world = getWorld(location.getWorldName()); final World world = getWorld(location.getWorldName());
final Block block = Objects.requireNonNull(world) final Block block = Objects.requireNonNull(world).getBlockAt(location.getX(), location.getY(), location.getZ());
.getBlockAt(location.getX(), location.getY(), location.getZ()); result.accept(Objects.requireNonNull(BukkitAdapter.asBlockType(block.getType())).getDefaultState());
result.accept(Objects.requireNonNull(BukkitAdapter
.asBlockType(block.getType())).getDefaultState());
}); });
} }
@Override @Nonnull public BlockState getBlockSynchronous(@Nonnull final Location location) { @Override @Nonnull public BlockState getBlockSynchronous(@Nonnull final Location location) {
final World world = getWorld(location.getWorldName()); final World world = getWorld(location.getWorldName());
final Block block = Objects.requireNonNull(world) final Block block = Objects.requireNonNull(world).getBlockAt(location.getX(), location.getY(), location.getZ());
.getBlockAt(location.getX(), location.getY(), location.getZ()); return Objects.requireNonNull(BukkitAdapter.asBlockType(block.getType())).getDefaultState();
return Objects.requireNonNull(BukkitAdapter
.asBlockType(block.getType())).getDefaultState();
} }
@Override @Nonnegative public double getHealth(@Nonnull final PlotPlayer player) { @Override @Nonnegative public double getHealth(@Nonnull final PlotPlayer player) {
return Objects.requireNonNull(Bukkit return Objects.requireNonNull(Bukkit.getPlayer(player.getUUID())).getHealth();
.getPlayer(player.getUUID())).getHealth();
} }
@Override @Nonnegative public int getFoodLevel(@Nonnull final PlotPlayer<?> player) { @Override @Nonnegative public int getFoodLevel(@Nonnull final PlotPlayer<?> player) {
return Objects.requireNonNull(Bukkit.getPlayer(player.getUUID())) return Objects.requireNonNull(Bukkit.getPlayer(player.getUUID())).getFoodLevel();
.getFoodLevel();
} }
@Override public void setHealth(@Nonnull final PlotPlayer<?> player, @Override public void setHealth(@Nonnull final PlotPlayer<?> player, @Nonnegative final double health) {
@Nonnegative final double health) { Objects.requireNonNull(Bukkit.getPlayer(player.getUUID())).setHealth(health);
Objects.requireNonNull(Bukkit.getPlayer(player.getUUID()))
.setHealth(health);
} }
@Override public void setFoodLevel(@Nonnull final PlotPlayer<?> player, @Override public void setFoodLevel(@Nonnull final PlotPlayer<?> player, @Nonnegative final int foodLevel) {
@Nonnegative final int foodLevel) {
Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel); Bukkit.getPlayer(player.getUUID()).setFoodLevel(foodLevel);
} }
@Override @Nonnull @Override @Nonnull public Set<com.sk89q.worldedit.world.entity.EntityType> getTypesInCategory(@Nonnull final String category) {
public Set<com.sk89q.worldedit.world.entity.EntityType> getTypesInCategory(
@Nonnull final String category) {
final Collection<Class<?>> allowedInterfaces = new HashSet<>(); final Collection<Class<?>> allowedInterfaces = new HashSet<>();
switch (category) { switch (category) {
case "animal": { case "animal": {
@ -524,28 +489,45 @@ import java.util.stream.Stream;
tileEntityTypes.addAll(BlockCategories.FLOWER_POTS.getAll()); tileEntityTypes.addAll(BlockCategories.FLOWER_POTS.getAll());
// Individual Types // Individual Types
// Add these from strings // Add these from strings
Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace", Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace", "brewing_stand", "campfire", "chest", "ender_chest",
"brewing_stand", "campfire", "chest", "ender_chest", "trapped_chest", "trapped_chest", "command_block", "end_gateway", "hopper", "jigsaw", "jubekox", "lectern", "note_block", "black_shulker_box",
"command_block", "end_gateway", "hopper", "jigsaw", "jubekox", "blue_shulker_box", "brown_shulker_box", "cyan_shulker_box", "gray_shulker_box", "green_shulker_box", "light_blue_shulker_box",
"lectern", "note_block", "black_shulker_box", "blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box", "magenta_shulker_box", "orange_shulker_box", "pink_shulker_box", "purple_shulker_box",
"brown_shulker_box", "cyan_shulker_box", "gray_shulker_box", "green_shulker_box", "red_shulker_box", "shulker_box", "white_shulker_box", "yellow_shulker_box", "smoker", "structure_block", "structure_void")
"light_blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box", .map(BlockTypes::get).filter(Objects::nonNull).forEach(tileEntityTypes::add);
"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; return this.tileEntityTypes;
} }
@Override @Nonnegative @Override @Nonnegative public int getTileEntityCount(@Nonnull final String world, @Nonnull final BlockVector2 chunk) {
public int getTileEntityCount(@Nonnull final String world,
@Nonnull final BlockVector2 chunk) {
return Objects.requireNonNull(getWorld(world)). return Objects.requireNonNull(getWorld(world)).
getChunkAt(chunk.getBlockX(), chunk.getBlockZ()) getChunkAt(chunk.getBlockX(), chunk.getBlockZ()).getTileEntities().length;
.getTileEntities().length; }
@Override public Set<BlockVector2> getChunkChunks(String world) {
Set<BlockVector2> 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;
} }
} }

View File

@ -6,7 +6,7 @@ load: STARTUP
description: "Easy, yet powerful Plot World generation and management." description: "Easy, yet powerful Plot World generation and management."
authors: [Citymonstret, Empire92, MattBDev, dordsor21, NotMyFault, SirYwell] authors: [Citymonstret, Empire92, MattBDev, dordsor21, NotMyFault, SirYwell]
website: https://www.spigotmc.org/resources/77506/ website: https://www.spigotmc.org/resources/77506/
softdepend: [Vault, PlaceholderAPI, Essentials, LuckPerms, BungeePerms] softdepend: [Vault, PlaceholderAPI, Essentials, LuckPerms, BungeePerms, MVdWPlaceholderAPI]
loadbefore: [MultiWorld, Multiverse-Core] loadbefore: [MultiWorld, Multiverse-Core]
depend: [WorldEdit] depend: [WorldEdit]
database: false database: false

View File

@ -48,16 +48,10 @@
<version>1.0</version> <version>1.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>com.sk89q.worldedit</groupId> <groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-core</artifactId> <artifactId>worldedit-core</artifactId>
<version>7.0.0</version> <version>7.2.0-SNAPSHOT</version>
<scope>runtime</scope> <scope>runtime</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -74,30 +68,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-api</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-gson</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-legacy</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-plain</artifactId>
<version>3.0.2</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
@ -128,6 +98,18 @@
<version>1.7.0-SNAPSHOT</version> <version>1.7.0-SNAPSHOT</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.0.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>3.0.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId> <artifactId>log4j-slf4j-impl</artifactId>

View File

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

View File

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

View File

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

View File

@ -51,15 +51,6 @@ public interface CommandCaller {
*/ */
boolean hasPermission(@Nonnull String permission); 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 * Get the type of the caller
* *

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
* | | * | |
* |_| * |_|
* PlotSquared plot management system for Minecraft * 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 * 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 * 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 * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.plotsquared.core.configuration.caption; package com.plotsquared.core.configuration.caption;
public class CaptionHolder { public class CaptionHolder {

View File

@ -8,7 +8,7 @@
* | | * | |
* |_| * |_|
* PlotSquared plot management system for Minecraft * 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 * 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 * it under the terms of the GNU General Public License as published by

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
* | | * | |
* |_| * |_|
* PlotSquared plot management system for Minecraft * 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 * 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 * it under the terms of the GNU General Public License as published by

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -43,7 +43,7 @@ public class PlotItemStack {
* @param amount Amount of items in the stack * @param amount Amount of items in the stack
* @param name The display name of the item stack * @param name The display name of the item stack
* @param lore The item stack lore * @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, @Deprecated public PlotItemStack(final int id, final short data, final int amount,
final String name, final String... lore) { final String name, final String... lore) {

View File

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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@
package com.plotsquared.core.queue; package com.plotsquared.core.queue;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -35,45 +36,64 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Objects; 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; private final PlotArea area;
public AreaBoundDelegateLocalBlockQueue(@Nonnull final PlotArea area, public AreaBoundDelegateQueueCoordinator(@Nonnull final PlotArea area, @Nullable final QueueCoordinator parent) {
@Nullable final LocalBlockQueue parent) {
super(parent); super(parent);
this.area = Objects.requireNonNull(area); 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)) { if (area.contains(x, z)) {
return super.setBlock(x, y, z, id); return super.setBlock(x, y, z, id);
} }
return false; 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)) { if (area.contains(x, z)) {
return super.setBlock(x, y, z, id); return super.setBlock(x, y, z, id);
} }
return false; 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)) { if (area.contains(x, z)) {
return super.setBlock(x, y, z, pattern); return super.setBlock(x, y, z, pattern);
} }
return false; 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)) { if (area.contains(x, z)) {
return super.setBiome(x, z, biome); return super.setBiome(x, z, biome);
} }
return false; return false;
} }
public PlotArea getArea() { @Override public boolean setBiome(int x, int y, int z, @Nonnull BiomeType biome) {
return this.area; if (area.contains(x, z)) {
return super.setBiome(x, y, z, biome);
}
return false;
}
@Override public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) {
if (area.contains(x, z)) {
return super.setTile(x, y, z, tag);
}
return false;
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,25 +25,29 @@
*/ */
package com.plotsquared.core.queue; 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 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() { return new QueueProvider() {
private boolean failed = false; @Override public QueueCoordinator getNewQueue(@Nonnull World world) {
@Override public LocalBlockQueue getNewQueue(String world) {
if (!failed) {
try {
return (LocalBlockQueue) primary.getConstructors()[0].newInstance(world);
} catch (Throwable e) {
e.printStackTrace();
failed = true;
}
}
try { try {
return (LocalBlockQueue) fallback.getConstructors()[0].newInstance(world); return (QueueCoordinator) primary.getConstructors()[0].newInstance(world);
} catch (Throwable e) { } 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(); e.printStackTrace();
} }
return null; return null;
@ -51,5 +55,8 @@ public abstract class QueueProvider {
}; };
} }
public abstract LocalBlockQueue getNewQueue(String world); /**
* Get a queue for the given world
*/
public abstract QueueCoordinator getNewQueue(@Nonnull World world);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -107,7 +107,7 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
/** /**
* Get a list of names given a list of UUIDs. * 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 * @param uuids UUIDs
* @return Name list * @return Name list

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -79,7 +79,7 @@ subprojects { subproject ->
dependencies { dependencies {
compile group: 'org.json', name: 'json', version: '20200518' compile group: 'org.json', name: 'json', version: '20200518'
implementation("com.sk89q.worldedit:worldedit-core:7.0.0") { implementation("com.sk89q.worldedit:worldedit-core:7.2.0-SNAPSHOT") {
exclude(module: "bukkit-classloader-check") exclude(module: "bukkit-classloader-check")
exclude(module: "mockito-core") exclude(module: "mockito-core")
exclude(module: "dummypermscompat") exclude(module: "dummypermscompat")
@ -100,6 +100,7 @@ subprojects { subproject ->
} }
repositories { repositories {
mavenLocal()
mavenCentral() mavenCentral()
maven { url = "https://maven.enginehub.org/repo/" } maven { url = "https://maven.enginehub.org/repo/" }
maven { url = "https://repo.maven.apache.org/maven2" } maven { url = "https://repo.maven.apache.org/maven2" }
@ -110,6 +111,8 @@ subprojects { subproject ->
dependencies { dependencies {
include(dependency("org.json:json:20200518")) include(dependency("org.json:json:20200518"))
include(dependency("net.kyori:text-api:3.0.2")) 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("io.papermc.lib", "com.plotsquared.bukkit.paperlib")
relocate("org.json", "com.plotsquared.json") { relocate("org.json", "com.plotsquared.json") {