diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java index bca2b90f1..53e45d3aa 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitChunkCoordinator.java @@ -137,20 +137,23 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator { 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); + } finally { + for (final ProgressSubscriber subscriber : this.progressSubscribers) { + subscriber.notifyEnd(); + } + this.cancel(); } - this.cancel(); } else { if (this.availableChunks.size() < processedChunks) { + final double progress = ((double) totalSize - (double) expected) / (double) totalSize; + for (final ProgressSubscriber subscriber : this.progressSubscribers) { + subscriber.notifyProgress(this, progress); + } this.requestBatch(); } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Set.java b/Core/src/main/java/com/plotsquared/core/command/Set.java index 25d9b9b8d..c0d318c5f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Set.java +++ b/Core/src/main/java/com/plotsquared/core/command/Set.java @@ -26,10 +26,12 @@ package com.plotsquared.core.command; import com.google.inject.Inject; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.backup.BackupManager; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.caption.StaticCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption; +import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; import com.plotsquared.core.permissions.Permission; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; @@ -45,19 +47,18 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.world.block.BlockCategory; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; -import java.util.Collections; -import java.util.LinkedList; import net.kyori.adventure.text.minimessage.Template; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.stream.Collectors; -import java.util.stream.Stream; @CommandDeclaration(command = "set", aliases = {"s"}, @@ -158,7 +159,14 @@ public class Set extends SubCommand { for (final Plot current : plot.getConnectedPlots()) { current.getPlotModificationManager().setComponent(component, pattern, player, queue); } - queue.setCompleteTask(plot::removeRunning); + queue.setCompleteTask(() -> { + plot.removeRunning(); + player.sendMessage(TranslatableCaption.of("working.component_complete")); + }); + if (Settings.QUEUE.NOTIFY_PROGRESS) { + queue.addProgressSubscriber( + PlotSquared.platform().getInjector().getInstance(ProgressSubscriberFactory.class).createWithActor(player)); + } queue.enqueue(); player.sendMessage(TranslatableCaption.of("working.generating_component")); }); diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java index d6ec19f1d..11de8c99f 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java @@ -29,6 +29,7 @@ import com.google.common.collect.Sets; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.command.Template; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; @@ -62,11 +63,15 @@ public class HybridPlotManager extends ClassicPlotManager { private final HybridPlotWorld hybridPlotWorld; private final RegionManager regionManager; + private final ProgressSubscriberFactory subscriberFactory; - public HybridPlotManager(@Nonnull final HybridPlotWorld hybridPlotWorld, @Nonnull final RegionManager regionManager) { + public HybridPlotManager(@Nonnull final HybridPlotWorld hybridPlotWorld, + @Nonnull final RegionManager regionManager, + @Nonnull ProgressSubscriberFactory subscriberFactory) { super(hybridPlotWorld, regionManager); this.hybridPlotWorld = hybridPlotWorld; this.regionManager = regionManager; + this.subscriberFactory = subscriberFactory; } @Override public void exportTemplate() throws IOException { @@ -210,7 +215,6 @@ public class HybridPlotManager extends ClassicPlotManager { return true; } } - final String world = hybridPlotWorld.getWorldName(); final Location pos1 = plot.getBottomAbs(); final Location pos2 = plot.getExtendedTopAbs(); // If augmented @@ -245,6 +249,9 @@ public class HybridPlotManager extends ClassicPlotManager { queue.setRegenRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3())); } pastePlotSchematic(queue, pos1, pos2); + if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { + queue.addProgressSubscriber(subscriberFactory.createWithActor(actor)); + } if (whenDone != null) { queue.setCompleteTask(whenDone); } diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java index cff9f47d9..3062e8ea6 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -31,6 +31,7 @@ import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.inject.annotations.WorldConfig; +import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -138,7 +139,8 @@ public class HybridPlotWorld extends ClassicPlotWorld { } @Nonnull @Override protected PlotManager createManager() { - return new HybridPlotManager(this, PlotSquared.platform().getRegionManager()); + return new HybridPlotManager(this, PlotSquared.platform().getRegionManager(), + PlotSquared.platform().getInjector().getInstance(ProgressSubscriberFactory.class)); } public Location getSignLocation(@Nonnull Plot plot) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java b/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java index b8c569cbe..138c66e14 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java @@ -85,7 +85,6 @@ public final class PlotModificationManager { this.subscriberFactory = PlotSquared.platform().getInjector().getInstance(ProgressSubscriberFactory.class); } - /** * Copy a plot to a location, both physically and the settings * @@ -239,13 +238,10 @@ public final class PlotModificationManager { manager.claimPlot(current, queue); } } - if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { - queue.addProgressSubscriber(subscriberFactory.createWithActor(actor)); - } if (queue.size() > 0) { + queue.setCompleteTask(run); queue.enqueue(); } - TaskManager.runTask(run); return; } Plot current = queue.poll(); @@ -813,6 +809,7 @@ public final class PlotModificationManager { return true; } + /** /** * Sets components such as border, wall, floor. * (components are generator specific) diff --git a/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java index 65bd88eea..9eeacf82b 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java +++ b/Core/src/main/java/com/plotsquared/core/queue/ChunkCoordinator.java @@ -29,14 +29,16 @@ import com.plotsquared.core.util.task.PlotSquaredTask; public abstract class ChunkCoordinator implements PlotSquaredTask { + private boolean cancelled = false; + @Override public abstract void runTask(); @Override public boolean isCancelled() { - return false; + return cancelled; } @Override public void cancel() { - // Do nothing + this.cancelled = true; } /** diff --git a/Core/src/main/java/com/plotsquared/core/queue/subscriber/DefaultProgressSubscriber.java b/Core/src/main/java/com/plotsquared/core/queue/subscriber/DefaultProgressSubscriber.java index 68dee34e9..6279bbcee 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/subscriber/DefaultProgressSubscriber.java +++ b/Core/src/main/java/com/plotsquared/core/queue/subscriber/DefaultProgressSubscriber.java @@ -53,6 +53,7 @@ public class DefaultProgressSubscriber implements ProgressSubscriber { @Nonnull private final AtomicDouble progress = new AtomicDouble(0); @Nonnull private final AtomicBoolean started = new AtomicBoolean(false); + @Nonnull private final AtomicBoolean cancelled = new AtomicBoolean(false); @Nonnull private final TaskTime interval; @Nonnull private final TaskTime wait; @Nonnull private final PlotPlayer actor; @@ -91,7 +92,7 @@ public class DefaultProgressSubscriber implements ProgressSubscriber { } } - @Override public void notifyProgress(@Nonnull ChunkCoordinator coordinator, float progress) { + @Override public void notifyProgress(@Nonnull ChunkCoordinator coordinator, double progress) { this.progress.set(progress); if (coordinator.isCancelled() || progress >= 1) { if (task != null) { @@ -99,11 +100,25 @@ public class DefaultProgressSubscriber implements ProgressSubscriber { } } else if (started.compareAndSet(false, true)) { TaskManager.getPlatformImplementation().taskLater(() -> task = TaskManager.getPlatformImplementation().taskRepeat(() -> { - if (!started.get()) { - return; - } - actor.sendMessage(caption, Template.of("progress", String.valueOf((double) Math.round(this.progress.doubleValue() * 100) / 100))); + if (!started.get()) { + return; + } + if (cancelled.get()) { + task.cancel(); + } + actor.sendMessage(caption, Template.of("progress", String.valueOf((double) Math.round(this.progress.doubleValue() * 10000) / 100))); }, interval), wait); } } + + public void notifyEnd() { + cancel(); + } + + public void cancel() { + this.cancelled.set(true); + if (this.task != null) { + task.cancel(); + } + } } diff --git a/Core/src/main/java/com/plotsquared/core/queue/subscriber/ProgressSubscriber.java b/Core/src/main/java/com/plotsquared/core/queue/subscriber/ProgressSubscriber.java index be108ff76..fddda2d8d 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/subscriber/ProgressSubscriber.java +++ b/Core/src/main/java/com/plotsquared/core/queue/subscriber/ProgressSubscriber.java @@ -29,7 +29,6 @@ import com.plotsquared.core.queue.ChunkCoordinator; import javax.annotation.Nonnull; -@FunctionalInterface public interface ProgressSubscriber { /** @@ -38,6 +37,10 @@ public interface ProgressSubscriber { * @param coordinator Coordinator instance that triggered the notification * @param progress Progress in the range [0, 1] */ - void notifyProgress(@Nonnull final ChunkCoordinator coordinator, final float progress); + void notifyProgress(@Nonnull final ChunkCoordinator coordinator, final double progress); + /** + * Notify the subscriber that its parent ChunkCoordinator has finished + */ + void notifyEnd(); } diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java index c64472121..bfc09d9d8 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java @@ -29,6 +29,7 @@ import com.google.inject.Inject; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.caption.StaticCaption; +import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.PlotPlayer; @@ -247,22 +248,22 @@ public abstract class RegionManager { fromQueue1.setCompleteTask(fromQueue2::enqueue); if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { fromQueue1.addProgressSubscriber(subscriberFactory.createFull(actor, Settings.QUEUE.NOTIFY_INTERVAL, Settings.QUEUE.NOTIFY_WAIT, - StaticCaption.of("Current region 1 copy progress: %"))); + TranslatableCaption.of("swap.progress_region1_copy"))); } fromQueue2.setCompleteTask(toQueue1::enqueue); if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { fromQueue2.addProgressSubscriber(subscriberFactory.createFull(actor, Settings.QUEUE.NOTIFY_INTERVAL, Settings.QUEUE.NOTIFY_WAIT, - StaticCaption.of("Current region 2 copy progress: %"))); + TranslatableCaption.of("swap.progress_region2_copy"))); } toQueue1.setCompleteTask(toQueue2::enqueue); if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { toQueue1.addProgressSubscriber(subscriberFactory.createFull(actor, Settings.QUEUE.NOTIFY_INTERVAL, Settings.QUEUE.NOTIFY_WAIT, - StaticCaption.of("Current region 1 paste progress: %"))); + TranslatableCaption.of("swap.progress_region1_paste"))); } toQueue2.setCompleteTask(whenDone); if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { toQueue2.addProgressSubscriber(subscriberFactory.createFull(actor, Settings.QUEUE.NOTIFY_INTERVAL, Settings.QUEUE.NOTIFY_WAIT, - StaticCaption.of("Current region 2 paste progress: %"))); + TranslatableCaption.of("swap.progress_region2_paste"))); } fromQueue1.enqueue(); } diff --git a/Core/src/main/resources/lang/messages_en.json b/Core/src/main/resources/lang/messages_en.json index 052333a0a..b761e3070 100644 --- a/Core/src/main/resources/lang/messages_en.json +++ b/Core/src/main/resources/lang/messages_en.json @@ -74,7 +74,11 @@ "swap.swap_overlap": "The proposed areas are not allowed to overlap.", "swap.swap_success": "Successfully swapped plots.", "swap.swap_merged": "Merged plots may not be swapped. Please unmerge the plots before performing the swap.", - + "swap.progress_region1_copy": "Current region 1 copy progress: %", + "swap.progress_region2_copy": "Current region 2 copy progress: %Current region 1 paste progress: %", + "swap.progress_region2_paste": "Current region 2 paste progress: %", + "comment.inbox_notification": " unread messages. Use .", "comment.not_valid_inbox_index": "No comment at index .", "comment.inbox_item": " - ", @@ -412,7 +416,8 @@ "working.plot_is_claimed": "This plot is already claimed.", "working.claimed": "You successfully claimed the plot.", "working.progress": "Current progress: %", - + "working.component_complete": "Component generation has finished.", + "list.comment_list_header_paged": "(Page /) List of comments", "list.comment_list_comment": "[#[;][]\n", "list.comment_list_by_lister": "",