diff --git a/README.md b/README.md index 379da4e..b9ed228 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ public class DemoPlugin extends JavaPlugin { - protected final EasyListener listeners = new EasyListener(this); + protected final EasyListener listeners = EasyListener.create(this); @Override public void onEnable() { @@ -37,7 +37,7 @@ public class DemoPlugin extends JavaPlugin { EntityDamageEvent.class, EventPriority.HIGHEST, (event) -> event.getCause() != EntityDamageEvent.DamageCause.ENTITY_ATTACK ); // 有条件的取消一个事件 - + listeners // 额外提供的快捷方法 .cancelDeath(null) // 所有玩家取消死亡 .cancelBreak(player -> !player.isOp()) // 禁止非OP玩家破坏方块/接水或岩浆 diff --git a/pom.xml b/pom.xml index 0c363cb..f7d8b86 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ cc.carm.lib easylistener - 1.1.0 + 1.2.0 jar EasyListener diff --git a/src/main/java/cc/carm/lib/easylistener/EasyListener.java b/src/main/java/cc/carm/lib/easylistener/EasyListener.java index 53a6379..61702a1 100644 --- a/src/main/java/cc/carm/lib/easylistener/EasyListener.java +++ b/src/main/java/cc/carm/lib/easylistener/EasyListener.java @@ -1,6 +1,5 @@ package cc.carm.lib.easylistener; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -15,11 +14,10 @@ import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.weather.WeatherChangeEvent; -import org.bukkit.plugin.*; +import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Method; import java.util.Optional; import java.util.function.BiPredicate; import java.util.function.Consumer; @@ -30,110 +28,27 @@ import java.util.function.Predicate; * 轻松(做)监听,简单快捷的通用Bukkit插件监听器类库。 * * @author CarmJos - * @since 1.0.0 */ -public class EasyListener implements Listener { +public interface EasyListener extends Listener { - protected final Plugin plugin; - - public EasyListener(Plugin plugin) { - this.plugin = plugin; + /** + * 创建一个新的 {@link EasyListener} 实例 + * + * @param plugin {@link Plugin}插件实例 + * @return {@link EasyListener} 实例 + */ + static @NotNull ListenerManager create(@NotNull Plugin plugin) { + return new ListenerManager(plugin); } /** * 注销本监听器内的全部监听器。 *
也可以通过 {@link HandlerList#unregister(Listener)} 方法注销本监听器。 */ - public void unregisterAll() { + default void unregisterAll() { HandlerList.unregisterAll(this); } - /** - * 通过 {@link SimplePluginManager} 获取到一个事件类的 {@link HandlerList} 。 - * - * @param eventClass 事件类 - * @return 事件类的 {@link HandlerList} - */ - private @NotNull HandlerList getEventListeners(@NotNull Class eventClass) { - try { - Method method = SimplePluginManager.class.getDeclaredMethod("getEventListeners", Class.class); - method.setAccessible(true); - return (HandlerList) method.invoke(Bukkit.getPluginManager(), eventClass); - } catch (Exception e) { - throw new IllegalPluginAccessException(e.toString()); - } - } - - /** - * 创建一个事件的执行器实例。 - * - * @param eventClass 事件类 - * @param eventConsumer 事件执行内容 - * @param 事件类型 - * @return 事件的执行器实例 - */ - private EventExecutor createExecutor(@NotNull Class eventClass, - @NotNull Consumer eventConsumer) { - return (listener, event) -> { - try { - if (!eventClass.isAssignableFrom(event.getClass())) return; - eventConsumer.accept(eventClass.cast(event)); - } catch (Throwable t) { - throw new EventException(t); - } - }; - } - - protected void register(@NotNull Class eventClass, @NotNull RegisteredListener listener) { - getEventListeners(eventClass).register(listener); - } - - protected void register(@NotNull Class eventClass, @NotNull EventExecutor executor, - @NotNull EventPriority priority, boolean ignoreCancelled) { - register(eventClass, new RegisteredListener(this, executor, priority, this.plugin, ignoreCancelled)); - } - - /** - * 处理一个事件。 - * - * @param eventClass {@link Event} 事件类 - * @param eventConsumer 处理方法 - * @param {@link Event} 事件的类型 - * @return 本实例 - */ - public EasyListener handle(@NotNull Class eventClass, - @NotNull Consumer eventConsumer) { - return handle(eventClass, null, eventConsumer); - } - - /** - * 处理一个事件。 - * - * @param eventClass {@link Event} 事件类 - * @param ignoreCancelled 是否忽略掉已经被取消的事件 - * @param eventConsumer 处理方法 - * @param {@link Event} 事件的类型 - * @return 本实例 - */ - public EasyListener handle(@NotNull Class eventClass, boolean ignoreCancelled, - @NotNull Consumer eventConsumer) { - return handle(eventClass, null, ignoreCancelled, eventConsumer); - } - - /** - * 处理一个事件。 - * - * @param eventClass {@link Event} 事件类 - * @param priority {@link EventPriority} 事件处理优先级 - * @param eventConsumer 处理方法 - * @param {@link Event} 事件的类型 - * @return 本实例 - */ - public EasyListener handle(@NotNull Class eventClass, @Nullable EventPriority priority, - @NotNull Consumer eventConsumer) { - return handle(eventClass, priority, false, eventConsumer); - } - /** * 处理一个事件。 * @@ -144,13 +59,67 @@ public class EasyListener implements Listener { * @param {@link Event} 事件的类型 * @return 本实例 */ - public EasyListener handle(@NotNull Class eventClass, - @Nullable EventPriority priority, boolean ignoreCancelled, - @NotNull Consumer eventConsumer) { - final EventPriority eventPriority = Optional.ofNullable(priority).orElse(EventPriority.NORMAL); - final EventExecutor executor = createExecutor(eventClass, eventConsumer); - register(eventClass, executor, eventPriority, ignoreCancelled); - return this; + EasyListener handle(@NotNull Class eventClass, + @Nullable EventPriority priority, boolean ignoreCancelled, + @NotNull Consumer eventConsumer); + + /** + * 有条件地取消一个事件。 + *
本方法在条件满足时对事件进行取消,不会改变事件取消的状态。 + *
因此,已经被取消的事件将不再进行判断和取消。。 + * + * @param eventClass {@link Event} 事件类 + * @param priority {@link EventPriority} 事件处理优先级 + * @param eventPredicate 判断事件是否可以取消的条件 + * @param {@link Event} 事件的类型,必须实现 {@link Cancellable} 。 + * @return 本实例 + * @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常 + */ + EasyListener cancel(@NotNull Class eventClass, + @Nullable EventPriority priority, + @Nullable Predicate eventPredicate); + + /** + * 处理一个事件。 + * + * @param eventClass {@link Event} 事件类 + * @param eventConsumer 处理方法 + * @param {@link Event} 事件的类型 + * @return 本实例 + */ + default EasyListener handle(@NotNull Class eventClass, + @NotNull Consumer eventConsumer) { + return handle(eventClass, null, eventConsumer); + } + + /** + * 处理一个事件。 + * + * @param eventClass {@link Event} 事件类 + * @param ignoreCancelled 是否忽略掉已经被取消的事件 + * @param eventConsumer 处理方法 + * @param {@link Event} 事件的类型 + * @return 本实例 + */ + default EasyListener handle(@NotNull Class eventClass, + boolean ignoreCancelled, + @NotNull Consumer eventConsumer) { + return handle(eventClass, null, ignoreCancelled, eventConsumer); + } + + /** + * 处理一个事件。 + * + * @param eventClass {@link Event} 事件类 + * @param priority {@link EventPriority} 事件处理优先级 + * @param eventConsumer 处理方法 + * @param {@link Event} 事件的类型 + * @return 本实例 + */ + default EasyListener handle(@NotNull Class eventClass, + @Nullable EventPriority priority, + @NotNull Consumer eventConsumer) { + return handle(eventClass, priority, false, eventConsumer); } /** @@ -161,7 +130,7 @@ public class EasyListener implements Listener { * @return 本实例 * @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常 */ - public EasyListener cancel(@NotNull Class eventClass) { + default EasyListener cancel(@NotNull Class eventClass) { return cancel(eventClass, null, null); } @@ -174,59 +143,41 @@ public class EasyListener implements Listener { * @return 本实例 * @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常 */ - public EasyListener cancel(@NotNull Class eventClass, @Nullable Predicate eventPredicate) { + default EasyListener cancel(@NotNull Class eventClass, + @Nullable Predicate eventPredicate) { return cancel(eventClass, null, eventPredicate); } - /** - * 有条件地取消一个事件。 - * - * @param eventClass {@link Event} 事件类 - * @param priority {@link EventPriority} 事件处理优先级 - * @param eventPredicate 判断事件是否可以取消的条件 - * @param {@link Event} 事件的类型,必须实现 {@link Cancellable} 。 - * @return 本实例 - * @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常 - */ - public EasyListener cancel(@NotNull Class eventClass, @Nullable EventPriority priority, - @Nullable Predicate eventPredicate) { - if (!Cancellable.class.isAssignableFrom(eventClass)) { - throw new IllegalArgumentException("Event class " + eventClass.getName() + " is not cancellable"); - } + // >--------------------------- + // 预设快捷操作方法 - Predicate predicate = Optional.ofNullable(eventPredicate).orElse(t -> true); - return handle(eventClass, priority, (event) -> { - if (predicate.test(event)) ((Cancellable) event).setCancelled(true); - }); - } - - public EasyListener cancelJoinMessage() { + default EasyListener cancelJoinMessage() { return handleJoinMessage(null); } - public EasyListener handleJoinMessage(@Nullable Function joinMessage) { + default EasyListener handleJoinMessage(@Nullable Function joinMessage) { final Function message = Optional.ofNullable(joinMessage).orElse(t -> ""); return handle(PlayerJoinEvent.class, (event) -> event.setJoinMessage(message.apply(event.getPlayer()))); } - public EasyListener cancelQuitMessage() { + default EasyListener cancelQuitMessage() { return handleQuitMessage(null); } - public EasyListener handleQuitMessage(@Nullable Function quitMessage) { + default EasyListener handleQuitMessage(@Nullable Function quitMessage) { final Function message = Optional.ofNullable(quitMessage).orElse(t -> ""); return handle(PlayerQuitEvent.class, (event) -> event.setQuitMessage(message.apply(event.getPlayer()))); } - public EasyListener cancelWeatherChange() { + default EasyListener cancelWeatherChange() { return cancelWeatherChange(null); } - public EasyListener cancelWeatherChange(@Nullable Predicate weatherPredicate) { + default EasyListener cancelWeatherChange(@Nullable Predicate weatherPredicate) { return cancel(WeatherChangeEvent.class, weatherPredicate); } - public EasyListener cancelBreak(@Nullable Predicate player) { + default EasyListener cancelBreak(@Nullable Predicate player) { final Predicate predicate = Optional.ofNullable(player).orElse(t -> true); return cancelBreak( (event) -> predicate.test(event.getPlayer()), @@ -234,13 +185,13 @@ public class EasyListener implements Listener { ); } - public EasyListener cancelBreak(@Nullable Predicate blockBreakPredicate, - @Nullable Predicate bucketFillPredicate) { + default EasyListener cancelBreak(@Nullable Predicate blockBreakPredicate, + @Nullable Predicate bucketFillPredicate) { return cancel(BlockBreakEvent.class, blockBreakPredicate) .cancel(PlayerBucketFillEvent.class, bucketFillPredicate); } - public EasyListener cancelPlace(@Nullable Predicate player) { + default EasyListener cancelPlace(@Nullable Predicate player) { final Predicate predicate = Optional.ofNullable(player).orElse(t -> true); return cancelPlace( (event) -> predicate.test(event.getPlayer()), @@ -248,8 +199,8 @@ public class EasyListener implements Listener { ); } - public EasyListener cancelPlace(@Nullable Predicate blockBreakPredicate, - @Nullable Predicate bucketEmptyPredicate) { + default EasyListener cancelPlace(@Nullable Predicate blockBreakPredicate, + @Nullable Predicate bucketEmptyPredicate) { return cancel(BlockPlaceEvent.class, blockBreakPredicate) .cancel(PlayerBucketEmptyEvent.class, bucketEmptyPredicate); } @@ -260,7 +211,7 @@ public class EasyListener implements Listener { * @param predicate 判断器,返回true则取消事件。两参数分别为 attacker 与 victim 。 * @return 当前实例 */ - public EasyListener cancelPVP(@Nullable BiPredicate predicate) { + default EasyListener cancelPVP(@Nullable BiPredicate predicate) { final BiPredicate p = Optional.ofNullable(predicate).orElse((attacker, victim) -> true); return cancelAttack((attacker, damager) -> { if (!(attacker instanceof Player) || !(damager instanceof Player)) return false; @@ -274,12 +225,12 @@ public class EasyListener implements Listener { * @param predicate 判断器,返回true则取消事件。两参数分别为 attacker 与 victim 。 * @return 当前实例 */ - public EasyListener cancelAttack(@Nullable BiPredicate predicate) { + default EasyListener cancelAttack(@Nullable BiPredicate predicate) { final BiPredicate p = Optional.ofNullable(predicate).orElse((attacker, victim) -> true); return cancel(EntityDamageByEntityEvent.class, (event) -> p.test(event.getDamager(), event.getEntity())); } - public EasyListener cancelDeath(@Nullable Predicate predicate) { + default EasyListener cancelDeath(@Nullable Predicate predicate) { return cancelDeath(predicate, (event) -> { event.setDeathMessage(null); event.setKeepInventory(true); @@ -288,8 +239,8 @@ public class EasyListener implements Listener { } @SuppressWarnings("deprecation") - public EasyListener cancelDeath(@Nullable Predicate predicate, - @Nullable Consumer handler) { + default EasyListener cancelDeath(@Nullable Predicate predicate, + @Nullable Consumer handler) { final Predicate p = Optional.ofNullable(predicate).orElse((player) -> true); return handle(PlayerDeathEvent.class, (event) -> { if (!p.test(event.getEntity())) return; @@ -298,7 +249,7 @@ public class EasyListener implements Listener { }); } - public EasyListener cancelSpawn(@Nullable BiPredicate predicate) { + default EasyListener cancelSpawn(@Nullable BiPredicate predicate) { final BiPredicate p = Optional.ofNullable(predicate).orElse((entity, location) -> !(entity instanceof Player)); return cancel(EntitySpawnEvent.class, (event) -> p.test(event.getEntity(), event.getLocation())); } diff --git a/src/main/java/cc/carm/lib/easylistener/ListenerManager.java b/src/main/java/cc/carm/lib/easylistener/ListenerManager.java new file mode 100644 index 0000000..1b71f4f --- /dev/null +++ b/src/main/java/cc/carm/lib/easylistener/ListenerManager.java @@ -0,0 +1,103 @@ +package cc.carm.lib.easylistener; + +import org.bukkit.Bukkit; +import org.bukkit.event.*; +import org.bukkit.plugin.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Method; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Predicate; + +@SuppressWarnings("SameParameterValue") +public class ListenerManager implements EasyListener { + + protected final Plugin plugin; + + public ListenerManager(Plugin plugin) { + this.plugin = plugin; + } + + public Plugin getPlugin() { + return plugin; + } + + /** + * 通过 {@link SimplePluginManager} 获取到一个事件类的 {@link HandlerList} 。 + * + * @param eventClass 事件类 + * @return 事件类的 {@link HandlerList} + */ + private @NotNull HandlerList getEventListeners(@NotNull Class eventClass) { + try { + Method method = SimplePluginManager.class.getDeclaredMethod("getEventListeners", Class.class); + method.setAccessible(true); + return (HandlerList) method.invoke(Bukkit.getPluginManager(), eventClass); + } catch (Exception e) { + throw new IllegalPluginAccessException(e.toString()); + } + } + + /** + * 创建一个事件的执行器实例。 + * + * @param eventClass 事件类 + * @param eventConsumer 事件执行内容 + * @param 事件类型 + * @return 事件的执行器实例 + */ + protected EventExecutor createExecutor(@NotNull Class eventClass, + @NotNull Consumer eventConsumer) { + return (listener, event) -> { + try { + if (!eventClass.isAssignableFrom(event.getClass())) return; + eventConsumer.accept(eventClass.cast(event)); + } catch (Throwable t) { + throw new EventException(t); + } + }; + } + + protected void requireType(@NotNull Class target, @NotNull Class value, + @Nullable String message) throws IllegalArgumentException { + if (target.isAssignableFrom(value)) return; + if (message == null) throw new IllegalArgumentException(); + else throw new IllegalArgumentException(message); + } + + protected void register(@NotNull Class eventClass, @NotNull RegisteredListener listener) { + getEventListeners(eventClass).register(listener); + } + + protected void register(@NotNull Class eventClass, @NotNull EventExecutor executor, + @NotNull EventPriority priority, boolean ignoreCancelled) { + register(eventClass, new RegisteredListener(this, executor, priority, getPlugin(), ignoreCancelled)); + } + + protected void register(@NotNull Class eventClass, @NotNull Consumer eventConsumer, + @NotNull EventPriority priority, boolean ignoreCancelled) { + register(eventClass, createExecutor(eventClass, eventConsumer), priority, ignoreCancelled); + } + + @Override + public EasyListener handle(@NotNull Class eventClass, + @Nullable EventPriority priority, boolean ignoreCancelled, + @NotNull Consumer eventConsumer) { + register(eventClass, eventConsumer, Optional.ofNullable(priority).orElse(EventPriority.NORMAL), ignoreCancelled); + return this; + } + + @Override + public EasyListener cancel(@NotNull Class eventClass, @Nullable EventPriority priority, + @Nullable Predicate eventPredicate) { + requireType(Cancellable.class, eventClass, "Event class " + eventClass.getName() + " is not cancellable"); + + final Predicate predicate = Optional.ofNullable(eventPredicate).orElse(t -> true); + return handle(eventClass, priority, true, (event) -> { + if (predicate.test(event)) ((Cancellable) event).setCancelled(true); + }); + } + +} diff --git a/src/test/java/DemoPlugin.java b/src/test/java/DemoPlugin.java index e57d111..dfcdf0d 100644 --- a/src/test/java/DemoPlugin.java +++ b/src/test/java/DemoPlugin.java @@ -9,7 +9,7 @@ import org.bukkit.plugin.java.JavaPlugin; public class DemoPlugin extends JavaPlugin { - protected final EasyListener listeners = new EasyListener(this); + protected final EasyListener listeners = EasyListener.create(this); @Override public void onEnable() {