mirror of
https://github.com/SimplexDevelopment/SimplexSS.git
synced 2025-07-01 14:46:42 +00:00
Added Bukkit communication with BukkitScheduler
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
package io.github.simplex.api;
|
||||
package io.github.simplexdevelopment.api;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
@ -1,6 +1,6 @@
|
||||
package io.github.simplex.api;
|
||||
package io.github.simplexdevelopment.api;
|
||||
|
||||
import io.github.simplex.simplexss.ServicePool;
|
||||
import io.github.simplexdevelopment.scheduler.ServicePool;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
@ -1,7 +1,7 @@
|
||||
package io.github.simplex.api;
|
||||
package io.github.simplexdevelopment.api;
|
||||
|
||||
import io.github.simplex.simplexss.ServiceManager;
|
||||
import io.github.simplex.simplexss.ServicePool;
|
||||
import io.github.simplexdevelopment.scheduler.ServiceManager;
|
||||
import io.github.simplexdevelopment.scheduler.ServicePool;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface ISchedule {
|
@ -1,6 +1,6 @@
|
||||
package io.github.simplex.api;
|
||||
package io.github.simplexdevelopment.api;
|
||||
|
||||
import io.github.simplex.simplexss.ServicePool;
|
||||
import io.github.simplexdevelopment.scheduler.ServicePool;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.Contract;
|
@ -1,4 +1,4 @@
|
||||
package io.github.simplex.api;
|
||||
package io.github.simplexdevelopment.api;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.simplex.api;
|
||||
package io.github.simplexdevelopment.api;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -10,6 +10,10 @@ public class InvalidServicePoolException extends RuntimeException {
|
||||
super("There is no service pool associated with this service. The service will be automatically recycled.");
|
||||
}
|
||||
|
||||
public InvalidServicePoolException(@NotNull String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
public InvalidServicePoolException(Throwable ex) {
|
||||
super(ex);
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package io.github.simplex.impl;
|
||||
package io.github.simplexdevelopment.impl;
|
||||
|
||||
import io.github.simplex.api.IService;
|
||||
import io.github.simplex.simplexss.SchedulingSystem;
|
||||
import io.github.simplex.simplexss.ServiceManager;
|
||||
import io.github.simplex.simplexss.ServicePool;
|
||||
import io.github.simplexdevelopment.api.IService;
|
||||
import io.github.simplexdevelopment.scheduler.SchedulingSystem;
|
||||
import io.github.simplexdevelopment.scheduler.ServiceManager;
|
||||
import io.github.simplexdevelopment.scheduler.ServicePool;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.publisher.Flux;
|
||||
@ -17,8 +17,7 @@ public class Main extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
ServiceManager serviceManager = new ServiceManager();
|
||||
this.scheduler = new SchedulingSystem<>(serviceManager, this);
|
||||
this.scheduler = new SchedulingSystem<>(this);
|
||||
IService service = new ServiceImpl(this);
|
||||
service.getParentPool().subscribe(element -> disposables = element.startServices());
|
||||
}
|
||||
@ -28,7 +27,6 @@ public class Main extends JavaPlugin {
|
||||
scheduler.getServiceManager().subscribe(manager -> {
|
||||
manager.getServicePools().doOnEach(signal -> Objects.requireNonNull(signal.get())
|
||||
.stopServices(disposables)
|
||||
.subscribeOn(scheduler.getMainSchedulerThread())
|
||||
.subscribe());
|
||||
});
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package io.github.simplex.impl;
|
||||
package io.github.simplexdevelopment.impl;
|
||||
|
||||
import io.github.simplex.api.ExecutableService;
|
||||
import io.github.simplex.api.IService;
|
||||
import io.github.simplex.simplexss.ServicePool;
|
||||
import io.github.simplexdevelopment.api.ExecutableService;
|
||||
import io.github.simplexdevelopment.api.IService;
|
||||
import io.github.simplexdevelopment.scheduler.ServicePool;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
@ -0,0 +1,24 @@
|
||||
package io.github.simplexdevelopment.scheduler;
|
||||
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import reactor.core.Disposable;
|
||||
|
||||
public record BukkitDisposable(BukkitTask task) implements Disposable {
|
||||
/**
|
||||
* Disposes of the task upstream on the Bukkit scheduler.
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
task.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the task is cancelled.
|
||||
*
|
||||
* @return true if the task is cancelled, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDisposed() {
|
||||
return task.isCancelled();
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package io.github.simplexdevelopment.scheduler;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import reactor.core.Disposable;
|
||||
import reactor.core.scheduler.Scheduler;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public record ReactorBukkitScheduler(JavaPlugin plugin, BukkitScheduler scheduler)
|
||||
implements Scheduler, Scheduler.Worker {
|
||||
|
||||
/**
|
||||
* Delegates to the {@link BukkitScheduler}.
|
||||
*
|
||||
* @param task The task to delegate.
|
||||
* @return A disposable that can be used to cancel the task.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Disposable schedule(@NotNull Runnable task) {
|
||||
return new BukkitDisposable(scheduler.runTask(plugin, task));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the {@link BukkitScheduler} with a delay.
|
||||
*
|
||||
* @param task The task to delegate
|
||||
* @param delay The amount of time to wait before running the task
|
||||
* @param unit Unused parameter in this implementation.
|
||||
* Regardless of what value you use, this parameter will never be called.
|
||||
* @return A disposable that can be used to cancel the task.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Disposable schedule(@NotNull Runnable task, long delay, @Nullable TimeUnit unit) {
|
||||
return new BukkitDisposable(scheduler.runTaskLater(plugin, task, delay));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the {@link BukkitScheduler} with a delay and a period.
|
||||
* The initial delay may be 0L, but the period must be greater than 0L.
|
||||
*
|
||||
* @param task The task to delegate.
|
||||
* @param initialDelay The amount of time to wait before running the task.
|
||||
* @param period The amount of time to wait between each execution of the task.
|
||||
* @param unit Unused parameter in this implementation.
|
||||
* Regardless of what value you use, this parameter will never be called.
|
||||
* @return A disposable that can be used to cancel the task.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Disposable schedulePeriodically(@NotNull Runnable task, long initialDelay, long period, @Nullable TimeUnit unit) {
|
||||
if (period <= 0L) {
|
||||
throw new IllegalArgumentException("Period must be greater than 0L");
|
||||
}
|
||||
|
||||
return new BukkitDisposable(scheduler.runTaskTimer(plugin, task, initialDelay, period));
|
||||
}
|
||||
|
||||
/**
|
||||
* A new {@link Scheduler.Worker}.
|
||||
*
|
||||
* @return This class instance, as it implements {@link Scheduler.Worker}.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Worker createWorker() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does nothing and is unused.
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
package io.github.simplex.simplexss;
|
||||
package io.github.simplexdevelopment.scheduler;
|
||||
|
||||
import io.github.simplex.api.ISchedule;
|
||||
import io.github.simplex.api.IService;
|
||||
import io.github.simplexdevelopment.api.ISchedule;
|
||||
import io.github.simplexdevelopment.api.IService;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import reactor.core.publisher.Mono;
|
||||
@ -17,19 +18,18 @@ public final class SchedulingSystem<T extends JavaPlugin> implements ISchedule {
|
||||
private final ServiceManager serviceManager;
|
||||
private final T plugin;
|
||||
private final Set<ServicePool> repeatingPools;
|
||||
private final Scheduler mainScheduler;
|
||||
private final ReactorBukkitScheduler mainScheduler;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the scheduling system. This is used to manage the scheduling of services.
|
||||
*
|
||||
* @param serviceManager The service manager to use for this scheduling system.
|
||||
* @param plugin The plugin to use for this scheduling system. This should be an instance of your plugin.
|
||||
*/
|
||||
public SchedulingSystem(@NotNull ServiceManager serviceManager, T plugin) {
|
||||
this.serviceManager = serviceManager;
|
||||
public SchedulingSystem(T plugin) {
|
||||
this.serviceManager = new ServiceManager();
|
||||
this.plugin = plugin;
|
||||
this.repeatingPools = new HashSet<>();
|
||||
this.mainScheduler = Schedulers.boundedElastic();
|
||||
this.mainScheduler = new ReactorBukkitScheduler(plugin, plugin.getServer().getScheduler());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,7 +84,7 @@ public final class SchedulingSystem<T extends JavaPlugin> implements ISchedule {
|
||||
* @return The main thread which the scheduling system operates on.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public Scheduler getMainSchedulerThread() {
|
||||
public ReactorBukkitScheduler getMainScheduler() {
|
||||
return mainScheduler;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package io.github.simplex.simplexss;
|
||||
package io.github.simplexdevelopment.scheduler;
|
||||
|
||||
import io.github.simplex.api.IService;
|
||||
import io.github.simplexdevelopment.api.IService;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
@ -1,7 +1,9 @@
|
||||
package io.github.simplex.simplexss;
|
||||
package io.github.simplexdevelopment.scheduler;
|
||||
|
||||
import io.github.simplex.api.IService;
|
||||
import io.github.simplexdevelopment.api.IService;
|
||||
import io.github.simplexdevelopment.api.InvalidServicePoolException;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -13,10 +15,13 @@ import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class ServicePool {
|
||||
/**
|
||||
* The default {@link NamespacedKey} used to identify unmarked services. This will cause errors if left unchecked.
|
||||
*/
|
||||
private static final NamespacedKey DEFAULT = new NamespacedKey("simplex_ss", "default_service_pool");
|
||||
/**
|
||||
* A collection of services related to this service pool.
|
||||
*/
|
||||
@ -29,23 +34,37 @@ public final class ServicePool {
|
||||
* The key used to identify this service pool.
|
||||
*/
|
||||
private final NamespacedKey name;
|
||||
/**
|
||||
* The default {@link NamespacedKey} used to identify unmarked services. This will cause errors if left unchecked.
|
||||
*/
|
||||
private static final NamespacedKey DEFAULT = new NamespacedKey("simplex_ss", "default_service_pool");
|
||||
private final ReactorBukkitScheduler rbScheduler;
|
||||
|
||||
/**
|
||||
* @param name The name of this service pool.
|
||||
* This will create a new instance of a Service Pool with a {@link Scheduler} as its main scheduler.
|
||||
* This should be used if you'd like to execute tasks without communicating on the main server thread.
|
||||
*
|
||||
* @param name The name of this service pool.
|
||||
* @param multithreaded Whether this service pool should be multithreaded, or operate upon a single thread.
|
||||
*/
|
||||
public ServicePool(NamespacedKey name, boolean multithreaded) {
|
||||
this.name = name;
|
||||
this.associatedServices = new HashSet<>();
|
||||
if (multithreaded) {
|
||||
this.scheduler = Schedulers.newBoundedElastic(4, 10, "");
|
||||
this.scheduler = Schedulers.boundedElastic();
|
||||
} else {
|
||||
this.scheduler = Schedulers.fromExecutorService(Executors.newSingleThreadExecutor());
|
||||
this.scheduler = Schedulers.single();
|
||||
}
|
||||
this.rbScheduler = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will create a new instance of a Service Pool with the {@link ReactorBukkitScheduler} as its main scheduler.
|
||||
* This should be used if you'd like to execute tasks while communicating on the main server thread.
|
||||
*
|
||||
* @param name The name of this service pool.
|
||||
*/
|
||||
public ServicePool(NamespacedKey name, JavaPlugin plugin) {
|
||||
this.name = name;
|
||||
this.associatedServices = new HashSet<>();
|
||||
this.scheduler = null;
|
||||
this.rbScheduler = new ReactorBukkitScheduler(plugin, plugin.getServer().getScheduler());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,48 +99,52 @@ public final class ServicePool {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param service_name The name of the service to queue. This should be a service that is located within this service pool.
|
||||
* @param service The name of the service to queue. This should be a service that is located within this service pool.
|
||||
* If you name a service that is stored within another service pool,
|
||||
* this method will throw an error.
|
||||
* @return A {@link Mono} object which contains a {@link Disposable} element which can be used to destroy the registered service.
|
||||
*/
|
||||
public @NotNull Mono<Disposable> queueService(NamespacedKey service_name) {
|
||||
Mono<IService> service = getService(service_name);
|
||||
return service.map(s -> {
|
||||
public @NotNull Mono<Disposable> queueService(IService service) {
|
||||
return Mono.just(service).map(s -> {
|
||||
if (s.isPeriodic()) {
|
||||
return scheduler.schedulePeriodically(s,
|
||||
s.getDelay() * 50,
|
||||
s.getPeriod() * 50,
|
||||
TimeUnit.MILLISECONDS);
|
||||
if (scheduler != null) {
|
||||
return scheduler.schedulePeriodically(s,
|
||||
s.getDelay() * 50,
|
||||
s.getPeriod() * 50,
|
||||
TimeUnit.MILLISECONDS);
|
||||
} else if (rbScheduler != null) {
|
||||
return rbScheduler.schedulePeriodically(s,
|
||||
s.getDelay() * 50,
|
||||
s.getPeriod() * 50,
|
||||
TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
throw new InvalidServicePoolException("Service pool is not initialized properly.");
|
||||
}
|
||||
} else {
|
||||
if (scheduler != null) {
|
||||
return scheduler.schedule(s,
|
||||
s.getDelay() * 50,
|
||||
TimeUnit.MILLISECONDS);
|
||||
} else if (rbScheduler != null) {
|
||||
return rbScheduler.schedule(s,
|
||||
s.getDelay() * 50,
|
||||
TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
throw new InvalidServicePoolException("Service pool is not initialized properly.");
|
||||
}
|
||||
}
|
||||
return scheduler.schedule(s,
|
||||
s.getDelay() * 50,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link Flux} object which contains a collection of {@link Disposable} elements,
|
||||
* which can be used to destroy the registered services using {@link ServicePool#stopServices(Flux<Disposable>)}.
|
||||
* which can be used to destroy the registered services using {@link ServicePool#stopServices(Flux)}.
|
||||
*/
|
||||
public @NotNull Flux<Disposable> startServices() {
|
||||
return Mono.just(getAssociatedServices()).flatMapMany(services -> {
|
||||
Set<Disposable> disposables = new HashSet<>();
|
||||
for (IService service : services) {
|
||||
if (service.isPeriodic()) {
|
||||
disposables.add(scheduler.schedulePeriodically(service,
|
||||
service.getDelay() * 50,
|
||||
service.getPeriod() * 50,
|
||||
TimeUnit.MILLISECONDS));
|
||||
} else {
|
||||
disposables.add(scheduler.schedule(service,
|
||||
service.getDelay() * 50,
|
||||
TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
return Flux.fromIterable(disposables);
|
||||
});
|
||||
Set<Disposable> disposables = new HashSet<>();
|
||||
return Flux.fromIterable(getAssociatedServices())
|
||||
.doOnEach(service -> disposables.add(queueService(service.get()).block()))
|
||||
.flatMap(service -> Flux.fromIterable(disposables));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,7 +158,7 @@ public final class ServicePool {
|
||||
|
||||
/**
|
||||
* @param service_name The name of the service to stop.
|
||||
* @param disposable A {@link Disposable} object which contains the service that should be disposed.
|
||||
* @param disposable A {@link Disposable} object which contains the service that should be disposed.
|
||||
* @return A {@link Mono<Void>} object which can be used to stop the service.
|
||||
*/
|
||||
public @NotNull Mono<Void> stopService(@NotNull NamespacedKey service_name, @Nullable Mono<Disposable> disposable) {
|
Reference in New Issue
Block a user