Last active
September 12, 2022 03:40
-
-
Save JohnnyJayJay/5ab455cd2c3c3c71a7cadcae563dde01 to your computer and use it in GitHub Desktop.
Event Waiter für Spigot und faule Menschen, die Inventar Menüs wollen
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github.johnnyjayjay.testplugin; | |
import org.bukkit.Bukkit; | |
import org.bukkit.event.Event; | |
import org.bukkit.event.EventPriority; | |
import org.bukkit.event.HandlerList; | |
import org.bukkit.event.Listener; | |
import org.bukkit.plugin.Plugin; | |
import java.util.function.Consumer; | |
import java.util.function.Predicate; | |
/** | |
* This is an adaptation of jagrosh's EventWaiter from jda utilities | |
* (https://github.com/JDA-Applications/JDA-Utilities) for Spigot. | |
* In order to work with Spigot's terrible event API, it has been restructured quite a bit. | |
* | |
* <p>The EventExpecter is capable of handling specialized forms of | |
* {@link org.bukkit.event.Event} that must meet criteria not normally specifiable | |
* without implementation of a {@link org.bukkit.event.Listener Listener}. | |
* | |
* <p>In contrast to the implementation in jda-utilities, this class uses the bukkit | |
* scheduler for timeouts instead of an own thread pool. | |
* | |
* <p>As a final note, if you intend to use the EventExpecter, it is highly recommended | |
* you reuse a single instance across your plugin. | |
* | |
* @author Johnny_JayJay / John Grosh (jagrosh) | |
*/ | |
public final class EventExpecter { | |
private final Plugin plugin; | |
/** | |
* Constructs an EventExpecter for the given plugin instance. | |
* | |
* @param plugin The plugin that uses this expecter. | |
* @throws java.lang.IllegalArgumentException If the plugin is {@code null} | |
*/ | |
public EventExpecter(Plugin plugin) { | |
checkNotNull(plugin, "Plugin"); | |
this.plugin = plugin; | |
} | |
/** | |
* Returns an instance of the builder-like class {@link ExpectationBuilder} to set up an event expectation conveniently. | |
* | |
* @param eventType The {@link java.lang.Class} of the Event to wait for. | |
* @param <T> The type of Event to wait for. | |
* @return A new instance of {@link ExpectationBuilder}. | |
*/ | |
public <T extends Event> ExpectationBuilder<T> expect(Class<T> eventType) { | |
return new ExpectationBuilder<>(eventType); | |
} | |
public static final class ExpectationListener<T extends Event> implements Listener { | |
private final Predicate<T> condition; | |
private final Consumer<T> action; | |
private ExpectationListener(Predicate<T> condition, Consumer<T> action) { | |
this.condition = condition; | |
this.action = action; | |
} | |
public void attempt(T event) { | |
if (condition.test(event)) { | |
action.accept(event); | |
HandlerList.unregisterAll(this); | |
} | |
} | |
} | |
/** | |
* Class that is mainly used for chaining convenience when calling {@link #expect(Class)}. | |
* | |
* @param <T> The type of the event to expect. | |
*/ | |
public class ExpectationBuilder<T extends Event> { | |
private final Class<T> eventType; | |
private Predicate<T> condition = (e) -> true; | |
private Consumer<T> action = (e) -> { | |
}; | |
private long timeout = -1; | |
private Runnable timeoutAction = () -> { | |
}; | |
private ExpectationBuilder(Class<T> eventType) { | |
this.eventType = eventType; | |
} | |
/** | |
* Sets the condition for this expectation. If the Predicate returns true for a corresponding event, | |
* the Consumer set in {@link #thenAccept(Consumer)} will be called and the Expectation will be completed. | |
* | |
* @param condition The Predicate to test when Events of the provided type are thrown. | |
* @return this. | |
*/ | |
public ExpectationBuilder<T> takeIf(Predicate<T> condition) { | |
this.condition = condition; | |
return this; | |
} | |
/** | |
* Sets the Consumer that will be called if the right event happens. | |
* | |
* @param action The Consumer to perform an action when the condition Predicate returns {@code true}. | |
* @return this. | |
*/ | |
public ExpectationBuilder<T> thenAccept(Consumer<T> action) { | |
this.action = action; | |
return this; | |
} | |
/** | |
* Sets a timeout for the Expectation, i.e. after the the specified amount of ticks, the Expecter | |
* will stop waiting for the event. By default, there is no timeout. | |
* | |
* @param ticks The amount of ticks to wait for, or {@code -1} if there is no timeout. | |
* @return this. | |
*/ | |
public ExpectationBuilder<T> timeoutAfter(long ticks) { | |
this.timeout = ticks; | |
return this; | |
} | |
/** | |
* Sets the action to perform if the Expectation times out. | |
* | |
* @param action The Runnable to run if the time runs out before a correct Event is thrown. | |
* The Runnable will be executed on the Bukkit server thread. | |
* @return this. | |
*/ | |
public ExpectationBuilder<T> runOnTimeout(Runnable action) { | |
this.timeoutAction = action; | |
return this; | |
} | |
/** | |
* Finishes the expectation setup and registers a listener. Schedules a timeout if one was specified. | |
* | |
* @return the listener for this expectation (can be used to trigger manually or to unregister early) | |
* @throws IllegalArgumentException if eventType, condition, action or timeOutAction are {@code null} | |
*/ | |
@SuppressWarnings("unchecked") | |
public ExpectationListener<T> register() { | |
checkNotNull(eventType, "The provided class type"); | |
checkNotNull(condition, "The provided condition predicate"); | |
checkNotNull(action, "The provided action consumer"); | |
checkNotNull(timeoutAction, "The provided timeout action"); | |
ExpectationListener<T> listener = new ExpectationListener<>(condition, action); | |
Bukkit.getPluginManager().registerEvent(eventType, listener, EventPriority.NORMAL, (lis, event) -> ((ExpectationListener<T>) lis).attempt((T) event), plugin); | |
if (timeout > 0) { | |
Bukkit.getScheduler().runTaskLater(plugin, () -> { | |
HandlerList.unregisterAll(listener); | |
timeoutAction.run(); | |
}, timeout); | |
} | |
return listener; | |
} | |
} | |
private static void check(boolean condition, String message) { | |
if (!condition) | |
throw new IllegalArgumentException(message); | |
} | |
private static void checkNotNull(Object argument, String name) { | |
check(argument != null, name + " may not be null"); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment