diff --git a/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java b/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java index 91cf858..dfa3eb1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java @@ -1,7 +1,6 @@ package me.totalfreedom.display; import me.totalfreedom.service.Task; -import net.kyori.adventure.audience.Audience; import org.bukkit.Bukkit; import java.time.Duration; diff --git a/Patchwork/src/main/java/me/totalfreedom/security/Group.java b/Patchwork/src/main/java/me/totalfreedom/security/Group.java index d09ba61..41b2825 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/Group.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/Group.java @@ -2,17 +2,40 @@ package me.totalfreedom.security; import net.kyori.adventure.text.Component; +/** + * Represents a permissible group which holds a set of permissions that can then be applied to a User / Player. + */ public interface Group extends PermissionHolder { + /** + * @return The name of the group. + */ Component getName(); + /** + * @return The prefix of the group. + */ Component getPrefix(); + /** + * @return The abbreviation of the group. + */ Component getAbbreviation(); + /** + * @return The weight of the group. + */ int getWeight(); + /** + * If more than one group is marked as default, the first retrieved default group will be used. + * + * @return Whether this is the default group. + */ boolean isDefault(); + /** + * @return Whether the group is hidden. + */ boolean isHidden(); } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java index dcaff95..5724f09 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java @@ -4,13 +4,28 @@ import me.totalfreedom.base.CommonsBase; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +/** + * This is a holder class for {@link Executor} objects that are used to delegate runnable tasks to the Bukkit Scheduler. + * This class is here for both convenience purposes, and also for the sake of providing easy access to executors for + * {@link CompletableFuture} invocations. + */ public class FreedomExecutor { + /** + * An executor which runs tasks synchronously. + */ private final Executor syncExecutor; + /** + * An executor which runs tasks asynchronously. + */ private final Executor asyncExecutor; + /** + * Creates a new {@link FreedomExecutor} instance. + */ public FreedomExecutor() { syncExecutor = r -> Bukkit.getScheduler() @@ -19,47 +34,107 @@ public class FreedomExecutor .runTaskAsynchronously(CommonsBase.getInstance(), r); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, synchronously. + * + * @param plugin The plugin to run the task for. + * @return A new {@link Executor} instance. + */ public Executor singleExecutor(final JavaPlugin plugin) { return r -> Bukkit.getScheduler() .runTask(plugin, r); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, synchronously. This + * Executor will wait for the supplied delay before executing the runnable. + * + * @param plugin The plugin to run the task for. + * @param delay The delay to wait before executing the runnable. + * @return A new {@link Executor} instance. + */ public Executor delayedExecutor(final JavaPlugin plugin, final long delay) { return r -> Bukkit.getScheduler() .runTaskLater(plugin, r, delay); } - public Executor periodicExecutor(final JavaPlugin plugin, final long delay, final long period) + /** + * Creates a new {@link Executor} tthat is capable of executing a runnable on a periodic basis, synchronously. This + * executor can also be supplied a delay to indicate it should wait the specified amount of time before executing + * the runnable for the first time. + * + * @param plugin The plugin to run the task for. + * @param initialDelay The delay to wait before executing the runnable for the first time. + * @param period The period to wait between each execution of the runnable. + * @return A new {@link Executor} instance. + */ + public Executor periodicExecutor(final JavaPlugin plugin, final long initialDelay, final long period) { return r -> Bukkit.getScheduler() - .runTaskTimer(plugin, r, delay, period); + .runTaskTimer(plugin, r, initialDelay, period); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, asynchronously. + * + * @param plugin The plugin to run the task for. + * @return A new {@link Executor} instance. + */ public Executor asynchronousSingleExecutor(final JavaPlugin plugin) { return r -> Bukkit.getScheduler() .runTaskAsynchronously(plugin, r); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, asynchronously. This + * Executor will wait for the supplied delay before executing the runnable. + * + * @param plugin The plugin to run the task for. + * @param delay The delay to wait before executing the runnable. + * @return A new {@link Executor} instance. + */ public Executor asynchronousDelayedExecutor(final JavaPlugin plugin, final long delay) { return r -> Bukkit.getScheduler() .runTaskLaterAsynchronously(plugin, r, delay); } + /** + * Creates a new {@link Executor} tthat is capable of executing a runnable on a periodic basis, asynchronously. This + * executor can also be supplied a delay to indicate it should wait the specified amount of time before executing + * the runnable for the first time. + * + * @param plugin The plugin to run the task for. + * @param delay The delay to wait before executing the runnable for the first time. + * @param period The period to wait between each execution of the runnable. + * @return A new {@link Executor} instance. + */ public Executor asynchronousPeriodicExecutor(final JavaPlugin plugin, final long delay, final long period) { return r -> Bukkit.getScheduler() .runTaskTimerAsynchronously(plugin, r, delay, period); } + /** + * Gets the synchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, + * when defining a custom executor for the {@link CompletableFuture}. + * + * @return The synchronous executor instance. + */ public Executor getSync() { return syncExecutor; } + /** + * Gets the asynchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, + * when defining a custom executor for the {@link CompletableFuture}. + * + * @return The asynchronous executor instance. + */ public Executor getAsync() { return asyncExecutor; diff --git a/Patchwork/src/main/java/me/totalfreedom/service/Service.java b/Patchwork/src/main/java/me/totalfreedom/service/Service.java index 592eb9c..927fb36 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Service.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Service.java @@ -1,16 +1,45 @@ package me.totalfreedom.service; +/** + * Represents a ticking service. Services may be asynchronous or synchronous, however there are some restrictions: + *
+ * Subscriptions contain some information about the service itself and it's presence on the scheduler. For example,
+ * {@link #getServiceId()} will return the ID of the task which was returned by the scheduler. Subscriptions also manage
+ * the state of the service, using {@link #isActive()} to determine if the service is currently running.
+ *
+ *
+ * The subscription itself provides type inference to safely store the actual service instance. This is useful for when
+ * we need to access the service itself, without calling to the service directly.
+ *
+ * @param
+ * If you are trying to create an asynchronous service, use
+ * {@link #ServiceSubscription(JavaPlugin, Service, boolean)} instead.
+ *
+ * If you would like to define a custom interval, use either {@link #ServiceSubscription(JavaPlugin, Service, long)}
+ * or {@link #ServiceSubscription(JavaPlugin, Service, long, boolean)} (for asynchronous services).
+ *
+ * @param plugin The plugin which owns the service.
+ * @param service The service to subscribe to.
+ */
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service)
{
this(plugin, service, 1L, false);
}
+ /**
+ * Creates a new subscription for the given service. This will initialize the default interval to a single tick.
+ *
+ * If you would like to define a custom interval, use either {@link #ServiceSubscription(JavaPlugin, Service, long)}
+ * or {@link #ServiceSubscription(JavaPlugin, Service, long, boolean)} (for asynchronous services).
+ *
+ * @param plugin The plugin which owns the service.
+ * @param service The service to subscribe to.
+ * @param async Whether the service should be scheduled asynchronously.
+ */
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final boolean async)
{
this(plugin, service, 1L, async);
}
+ /**
+ * Creates a new subscription for the given service. By default, this will mark the service as synchronous. When
+ * defining a custom interval, the interval should be less than 20L (the number of ticks in a second). For anything
+ * that requires an interval greater than 1 second, use a {@link Task} instead.
+ *
+ * If you are trying to create an asynchronous service, use
+ * {@link #ServiceSubscription(JavaPlugin, Service, long, boolean)} instead.
+ *
+ * @param plugin The plugin which owns the service.
+ * @param service The service to subscribe to.
+ * @param interval The interval at which the service should be scheduled.
+ */
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final long interval)
{
this(plugin, service, interval, false);
}
+ /**
+ * Creates a new subscription for the given service. When defining a custom interval, the interval should be less
+ * than 20L (the number of ticks in a second). For anything that requires an interval greater than 1 second, use a
+ * {@link Task} instead.
+ *
+ * @param plugin The plugin which owns the service.
+ * @param service The service to subscribe to.
+ * @param interval The interval at which the service should be scheduled.
+ * @param async Whether the service should be scheduled asynchronously.
+ */
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service,
- final long interval, final boolean async)
+ final long interval, final boolean async)
{
this.service = service;
this.async = async;
@@ -60,12 +133,18 @@ public final class ServiceSubscription Type inference to maintain the service type.
+ * @return The new {@link ServiceSubscription} object.
+ */
@NotNull
@Contract(value = "_, _ -> new", pure = false)
public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin,
- @NotNull final S service)
+ @NotNull final S service)
{
return new ServiceSubscription<>(plugin, service);
}
+ /**
+ * Creates a new {@link ServiceSubscription} object that will run the given {@link Service} object on the main
+ * thread at the given interval.
+ *
+ * @param plugin The plugin that owns the service.
+ * @param interval The interval to run the service at.
+ * @param service The service to run.
+ * @param Type inference to maintain the service type.
+ * @return The new {@link ServiceSubscription} object.
+ */
@NotNull
@Contract(value = "_,_,_ -> new", pure = false)
public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin,
- final long interval,
- @NotNull final S service)
+ final long interval,
+ @NotNull final S service)
{
return new ServiceSubscription<>(plugin, service, interval);
}
+ /**
+ * Creates a new {@link ServiceSubscription} object that will run the given {@link Service} object on the default
+ * tick interval, which is a single tick. This method will create an asynchronous service.
+ *
+ * @param plugin The plugin that owns the service.
+ * @param service The service to run.
+ * @param Type inference to maintain the service type.
+ * @return The new {@link ServiceSubscription} object.
+ */
@NotNull
@Contract(value = "_, _ -> new", pure = false)
public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin,
- @NotNull final S service)
+ @NotNull final S service)
{
return new ServiceSubscription<>(plugin, service, true);
}
- @NotNull
- @Contract(value = "_, _ -> new", pure = false)
- public static final Type inference to maintain the service type.
+ * @return The new {@link ServiceSubscription} object.
+ */
@NotNull
@Contract(value = "_,_,_ -> new", pure = false)
public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin,
- final long interval,
- @NotNull final S service)
+ final long interval,
+ @NotNull final S service)
{
return new ServiceSubscription<>(plugin, service, interval, true);
}
+ /**
+ * Creates a new {@link TaskSubscription} object that will run the given {@link Task} object synchronously on the
+ * main thread.
+ *
+ * @param plugin The plugin that owns the task.
+ * @param task The task to run.
+ * @param
+ * It's important to note that the delay and interval are in ticks. One tick is equal to 1/20th of a second, which
+ * means there are 20 ticks are in one second. If your interval is intended to be anything less than 20 ticks, you
+ * should use a {@link Service} instead.
+ *
+ * @param name The name of the task.
+ * @param delay The delay of the task.
+ * @param interval The interval of the task.
+ */
protected Task(final String name, final long delay, final long interval)
{
this.name = name;
@@ -23,61 +51,102 @@ public abstract class Task extends BukkitRunnable
this.interval = interval;
}
+ /**
+ * Creates a new task with the given name and delay. This will intialize a single execute task with an
+ * initial delay before execution.
+ *
+ * @param name The name of the task.
+ * @param delay How long the task should wait before executing.
+ */
protected Task(final String name, final long delay)
{
this(name, delay, -1L);
}
+ /**
+ * Creates a new task with the given name and delay.
+ * This is the same as longs, except that here, we naturally support durations which are automatically converted to
+ * ticks for you. This means that using {@link Duration#ofSeconds(long)} will work as expected.
+ *
+ * @param name The name of the task.
+ * @param delay How long the task should wait before executing.
+ */
protected Task(final String name, final Duration delay)
{
this(name, DurationTools.getTickedSeconds(delay), -1L);
}
+ /**
+ * Creates a new task with the given name, delay, and interval.
+ * This is the same as longs, except that here, we naturally support durations which are automatically converted to
+ * ticks for you. This means that using {@link Duration#ofSeconds(long)} will work as expected.
+ *
+ * @param name The name of the task.
+ * @param delay How long the task should wait before executing.
+ * @param interval How long the task should wait between executions.
+ */
protected Task(final String name, final Duration delay, final Duration interval)
{
this(name, DurationTools.getTickedSeconds(delay), DurationTools.getTickedSeconds(interval));
}
+ /**
+ * Creates a new task with the given name, delay, and interval.
+ * This method is a convenience method to use a {@link Duration} for the interval, while also being able to
+ * specify the delay as -1L so the task does not have an initial delay before execution.
+ *
+ * @param name The name of the task.
+ * @param delay The delay of the task.
+ * @param interval The interval of the task.
+ */
protected Task(final String name, final long delay, final Duration interval)
{
this(name, delay, DurationTools.getTickedSeconds(interval));
}
+ /**
+ * @return True if the task is running, false otherwise.
+ */
public boolean isRunning()
{
return !isCancelled();
}
+ /**
+ * @return The name of the task.
+ */
public String getName()
{
return name;
}
+ /**
+ * @return True if the task is repeating, false otherwise.
+ */
public boolean isRepeating()
{
- return interval != -1L;
- }
-
- public void setRepeating(final long interval)
- {
- this.interval = interval;
+ return this.interval > 0L;
}
+ /**
+ * @return True if the task is delayed, false otherwise.
+ */
public boolean isDelayed()
{
- return this.delay != -1;
- }
-
- public void setDelayed(final long delay)
- {
- this.delay = delay;
+ return this.delay > 0L;
}
+ /**
+ * @return The interval between each task execution.
+ */
public long getInterval()
{
return interval;
}
+ /**
+ * @return The initial delay before the first execution of this task.
+ */
public long getDelay()
{
return delay;
diff --git a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java
index e8e4b8e..5d2b5e2 100644
--- a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java
+++ b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java
@@ -3,39 +3,82 @@ package me.totalfreedom.service;
import me.totalfreedom.utils.Pair;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import java.util.concurrent.Executor;
+/**
+ * Represents a subscription to a task. Task subscriptions offer a nice wrapper for managing tasks, which are
+ * inevitably just bukkit runnables with a bit more lenience in terms of instantiation modification and execution.
+ * It also offers a more intuitive way to manage our tasks; rather than having to keep track of task ids for each
+ * {@link BukkitTask} object that gets returned by the {@link BukkitScheduler}.
+ *
+ * @param
+ * This will return a Pair where {@link Pair#value()} is an asynchronous executor.
+ *
+ * @param plugin The plugin which owns the task.
+ * @param delay The delay of the task.
+ * @param period The period of the task.
+ * @return The executor and task id for an asynchronous task.
+ */
private Pair
+ * This will return a Pair where {@link Pair#value()} is a synchronous executor.
+ *
+ * @param plugin The plugin which owns the task.
+ * @param delay The delay of the task.
+ * @param period The period of the task.
+ * @return The executor and task id for a synchronous task.
+ */
private Pair