progress subscriber

This commit is contained in:
dordsor21 2020-08-17 16:21:11 +01:00
parent 47d9895077
commit e8ffcaae46
No known key found for this signature in database
GPG Key ID: 1E53E88969FFCF0B
10 changed files with 222 additions and 21 deletions

View File

@ -49,12 +49,15 @@ import com.plotsquared.core.inject.annotations.DefaultGenerator;
import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; 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.inject.factory.ProgressSubscriberFactory;
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.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.queue.subscriber.DefaultProgressSubscriber;
import com.plotsquared.core.queue.subscriber.ProgressSubscriber;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.EconHandler;
import com.plotsquared.core.util.InventoryUtil; import com.plotsquared.core.util.InventoryUtil;
@ -105,6 +108,7 @@ public class BukkitModule extends AbstractModule {
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().implement(ChunkCoordinator.class, BukkitChunkCoordinator.class).build(ChunkCoordinatorFactory.class));
install(new FactoryModuleBuilder().build(ChunkCoordinatorBuilderFactory.class)); install(new FactoryModuleBuilder().build(ChunkCoordinatorBuilderFactory.class));
install(new FactoryModuleBuilder().implement(ProgressSubscriber.class, DefaultProgressSubscriber.class).build(ProgressSubscriberFactory.class));
} }
@Provides @Singleton @Nullable EconHandler provideEconHandler() { @Provides @Singleton @Nullable EconHandler provideEconHandler() {

View File

@ -29,6 +29,7 @@ import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.queue.subscriber.ProgressSubscriber;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
@ -82,7 +83,8 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
@Assisted @Nonnull final Collection<BlockVector2> requestedChunks, @Assisted @Nonnull final Collection<BlockVector2> requestedChunks,
@Assisted @Nonnull final Runnable whenDone, @Assisted @Nonnull final Runnable whenDone,
@Assisted @Nonnull final Consumer<Throwable> throwableConsumer, @Assisted @Nonnull final Consumer<Throwable> throwableConsumer,
@Assisted final boolean unloadAfter) { @Assisted final boolean unloadAfter,
@Assisted @Nonnull final Collection<ProgressSubscriber> progressSubscribers) {
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks); this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
this.availableChunks = new LinkedBlockingQueue<>(); this.availableChunks = new LinkedBlockingQueue<>();
this.totalSize = requestedChunks.size(); this.totalSize = requestedChunks.size();
@ -95,6 +97,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
this.unloadAfter = unloadAfter; this.unloadAfter = unloadAfter;
this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class); this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
this.bukkitWorld = Bukkit.getWorld(world.getName()); this.bukkitWorld = Bukkit.getWorld(world.getName());
this.progressSubscribers.addAll(progressSubscribers);
} }
@Override public void start() { @Override public void start() {
@ -205,21 +208,8 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
* *
* @param subscriber Subscriber * @param subscriber Subscriber
*/ */
public void subscribeToProgress(@Nonnull final BukkitChunkCoordinator.ProgressSubscriber subscriber) { public void subscribeToProgress(@Nonnull final ProgressSubscriber subscriber) {
this.progressSubscribers.add(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

@ -185,9 +185,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
})); }));
} }
if (localChunk.getEntities().size() > 0) { if (localChunk.getEntities().size() > 0) {
localChunk.getEntities().forEach((location, entity) -> { localChunk.getEntities().forEach((location, entity) -> getWorld().createEntity(location, entity));
getWorld().createEntity(location, entity);
});
} }
}; };
} }
@ -198,7 +196,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
chunkCoordinator = chunkCoordinator =
chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(getWorld()).withChunks(getBlockChunks().keySet()).withChunks(read) chunkCoordinatorBuilderFactory.create(chunkCoordinatorFactory).inWorld(getWorld()).withChunks(getBlockChunks().keySet()).withChunks(read)
.withInitialBatchSize(3).withMaxIterationTime(40).withThrowableConsumer(Throwable::printStackTrace).withFinalAction(getCompleteTask()) .withInitialBatchSize(3).withMaxIterationTime(40).withThrowableConsumer(Throwable::printStackTrace).withFinalAction(getCompleteTask())
.withConsumer(consumer).unloadAfter(isUnloadAfter()).build(); .withConsumer(consumer).unloadAfter(isUnloadAfter()).withProgressSubscribers(getProgressSubscribers()).build();
return super.enqueue(); return super.enqueue();
} }

View File

@ -26,6 +26,7 @@
package com.plotsquared.core.inject.factory; package com.plotsquared.core.inject.factory;
import com.plotsquared.core.queue.ChunkCoordinator; import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.queue.subscriber.ProgressSubscriber;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -42,6 +43,7 @@ public interface ChunkCoordinatorFactory {
@Nonnull final Collection<BlockVector2> requestedChunks, @Nonnull final Collection<BlockVector2> requestedChunks,
@Nonnull final Runnable whenDone, @Nonnull final Runnable whenDone,
@Nonnull final Consumer<Throwable> throwableConsumer, @Nonnull final Consumer<Throwable> throwableConsumer,
final boolean unloadAfter); final boolean unloadAfter,
@Nonnull final Collection<ProgressSubscriber> progressSubscribers);
} }

View File

@ -0,0 +1,42 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* 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.google.inject.assistedinject.Assisted;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.queue.subscriber.ProgressSubscriber;
import com.plotsquared.core.util.task.TaskManager;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public interface ProgressSubscriberFactory {
@Nonnull ProgressSubscriber create(@Nullable @Assisted("subscriber") PlotPlayer actor,
@Assisted("progressInterval") final long interval,
@Nonnull TaskManager taskManager);
}

View File

@ -25,6 +25,7 @@
*/ */
package com.plotsquared.core.queue; package com.plotsquared.core.queue;
import com.plotsquared.core.queue.subscriber.ProgressSubscriber;
import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.PatternUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
@ -67,6 +68,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
private Consumer<BlockVector2> consumer = null; private Consumer<BlockVector2> consumer = null;
private boolean unloadAfter = true; private boolean unloadAfter = true;
private Runnable whenDone; private Runnable whenDone;
private List<ProgressSubscriber> progressSubscribers = new ArrayList<>();
public BasicQueueCoordinator(@Nonnull World world) { public BasicQueueCoordinator(@Nonnull World world) {
super(world); super(world);
@ -252,6 +254,17 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
this.consumer = consumer; this.consumer = consumer;
} }
/**
* Get the list of progress subscribers currently added to the queue to be added to the Chunk Coordinator
*/
public final List<ProgressSubscriber> getProgressSubscribers() {
return this.progressSubscribers;
}
@Override public final void addProgressSubscriber(@Nonnull ProgressSubscriber progressSubscriber) {
this.progressSubscribers.add(progressSubscriber);
}
@Override public Runnable getCompleteTask() { @Override public Runnable getCompleteTask() {
return this.whenDone; return this.whenDone;
} }

View File

@ -29,6 +29,7 @@ import com.google.common.base.Preconditions;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.queue.subscriber.ProgressSubscriber;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -46,6 +47,7 @@ import java.util.function.Consumer;
public class ChunkCoordinatorBuilder { public class ChunkCoordinatorBuilder {
private final List<BlockVector2> requestedChunks = new LinkedList<>(); private final List<BlockVector2> requestedChunks = new LinkedList<>();
private final List<ProgressSubscriber> progressSubscribers = new ArrayList<>();
private final ChunkCoordinatorFactory chunkCoordinatorFactory; private final ChunkCoordinatorFactory chunkCoordinatorFactory;
private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace; private Consumer<Throwable> throwableConsumer = Throwable::printStackTrace;
private World world; private World world;
@ -193,6 +195,16 @@ public class ChunkCoordinatorBuilder {
return this; return this;
} }
@Nonnull public ChunkCoordinatorBuilder withProgressSubscriber(ProgressSubscriber progressSubscriber) {
this.progressSubscribers.add(progressSubscriber);
return this;
}
@Nonnull public ChunkCoordinatorBuilder withProgressSubscribers(Collection<ProgressSubscriber> progressSubscribers) {
this.progressSubscribers.addAll(progressSubscribers);
return this;
}
/** /**
* Create a new {@link ChunkCoordinator} instance based on the values in the Builder instance. * Create a new {@link ChunkCoordinator} instance based on the values in the Builder instance.
* *
@ -205,7 +217,7 @@ public class ChunkCoordinatorBuilder {
Preconditions.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied"); Preconditions.checkNotNull(this.throwableConsumer, "No throwable consumer was supplied");
return chunkCoordinatorFactory return chunkCoordinatorFactory
.create(this.maxIterationTime, this.initialBatchSize, this.chunkConsumer, this.world, this.requestedChunks, this.whenDone, .create(this.maxIterationTime, this.initialBatchSize, this.chunkConsumer, this.world, this.requestedChunks, this.whenDone,
this.throwableConsumer, this.unloadAfter); this.throwableConsumer, this.unloadAfter, this.progressSubscribers);
} }
} }

View File

@ -28,6 +28,7 @@ package com.plotsquared.core.queue;
import com.google.inject.Inject; 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.queue.subscriber.ProgressSubscriber;
import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.PatternUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
@ -353,6 +354,11 @@ public abstract class QueueCoordinator {
*/ */
public abstract void setChunkConsumer(@Nonnull Consumer<BlockVector2> consumer); public abstract void setChunkConsumer(@Nonnull Consumer<BlockVector2> consumer);
/**
* Add a {@link ProgressSubscriber} to the Queue to subscribe to the relevant Chunk Processor
*/
public abstract void addProgressSubscriber(@Nonnull ProgressSubscriber progressSubscriber);
/** /**
* Fill a cuboid between two positions with a BlockState * Fill a cuboid between two positions with a BlockState
* *

View File

@ -0,0 +1,90 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) ${year} 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.subscriber;
import com.google.common.util.concurrent.AtomicDouble;
import com.plotsquared.core.configuration.caption.Caption;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.queue.ChunkCoordinator;
import com.plotsquared.core.util.task.PlotSquaredTask;
import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime;
import net.kyori.adventure.text.minimessage.Template;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* The default PlotSquared Progress Subscriber. Can be used for both console and player tasks.
* It is the {@link ProgressSubscriber} returned by {@link com.plotsquared.core.inject.factory.ProgressSubscriberFactory}.
* Runs a repeating synchronous task notifying the given actor about any updates, saving updates notified by the ChunkCoordinator.
*/
public class DefaultProgressSubscriber implements ProgressSubscriber {
@Nonnull private final AtomicDouble progress = new AtomicDouble(0);
@Nonnull private final AtomicBoolean started = new AtomicBoolean(false);
@Nonnull private final TaskManager taskManager;
@Nonnull private final TaskTime interval;
@Nonnull private final PlotPlayer<?> actor;
@Nonnull private final Caption caption;
private PlotSquaredTask task;
public DefaultProgressSubscriber(@Nullable final PlotPlayer<?> actor,
@Nonnull final TaskTime interval,
@Nonnull TaskManager taskManager,
@Nullable Caption caption) {
if (actor == null) {
throw new NullPointerException(
"Actor cannot be null when using DefaultProgressSubscriber! Make sure if attempting to use custom Subscribers it is correctly parsed to the queue!");
}
if (caption == null) {
throw new NullPointerException(
"Caption cannot be null when using DefaultProgressSubscriber! Make sure if attempting to use custom Subscribers it is correctly parsed to the queue!");
}
this.interval = interval;
this.taskManager = taskManager;
this.actor = actor;
this.caption = caption;
}
@Override public void notifyProgress(@Nonnull ChunkCoordinator coordinator, float progress) {
this.progress.set((double) Math.round(progress * 100) / 100);
if (coordinator.isCancelled() || progress == 1) {
if (task != null) {
task.cancel();
}
} else if (started.compareAndSet(false, true)) {
taskManager.taskLater(() -> task = taskManager.taskRepeat(() -> {
if (!started.get()) {
return;
}
actor.sendMessage(caption, Template.of("%s", this.progress.toString()));
}, interval), interval);
}
}
}

View File

@ -0,0 +1,44 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) ${year} 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.subscriber;
import com.plotsquared.core.queue.ChunkCoordinator;
import javax.annotation.Nonnull;
@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 ChunkCoordinator coordinator, final float progress);
}