diff --git a/README.md b/README.md
index b9ed228..c2ed7d8 100644
--- a/README.md
+++ b/README.md
@@ -12,43 +12,18 @@
### [开发示例](src/test/java/DemoPlugin.java)
-您可以点击这里访问项目的 [JavaDoc](https://carmjos.github.io/EasyListener) 。
+相关开发示例请 [点击这里](src/test/java/DemoPlugin.java),您也可以直接访问项目的 [JavaDoc](https://carmjos.github.io/EasyListener) 。
```java
public class DemoPlugin extends JavaPlugin {
- protected final EasyListener listeners = EasyListener.create(this);
-
@Override
public void onEnable() {
- listeners // 基本用法
- .handle(PlayerInteractAtEntityEvent.class, (event) -> {
- Entity clicked = event.getRightClicked();
- Player player = event.getPlayer();
-
- if (clicked instanceof Player) {
- player.sendMessage("你点了 " + clicked.getName() + " 一下!");
- }
-
- }) // 处理一个事件
- .cancel(PlayerPickupArrowEvent.class) // 取消一个事件
- .cancel(
- EntityDamageEvent.class, EventPriority.HIGHEST,
- (event) -> event.getCause() != EntityDamageEvent.DamageCause.ENTITY_ATTACK
- ); // 有条件的取消一个事件
-
- listeners // 额外提供的快捷方法
- .cancelDeath(null) // 所有玩家取消死亡
- .cancelBreak(player -> !player.isOp()) // 禁止非OP玩家破坏方块/接水或岩浆
- .cancelPlace(player -> !player.isOp()) // 禁止非OP玩家放置方块/放水或岩浆
- .cancelPVP((attacker, victim) -> !attacker.isOp()) // 禁止非op玩家PVP
- .cancelWeatherChange() // 取消天气变更
- .cancelJoinMessage() // 取消加入消息
-// .cancelQuitMessage()
-// .handleJoinMessage(player -> "玩家 " + player.getName() + " 加入了服务器。")
- .handleQuitMessage(player -> "玩家 " + player.getName() + " 退出了服务器。"); // 设定退出消息
+ EasyListener listeners = EasyListener.create(this);
+ // listeners...; // Do something...
}
+
}
```
diff --git a/pom.xml b/pom.xml
index b337927..e2d8754 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
cc.carm.lib
easylistener
- 1.2.0
+ 2.0.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 61702a1..5fcea80 100644
--- a/src/main/java/cc/carm/lib/easylistener/EasyListener.java
+++ b/src/main/java/cc/carm/lib/easylistener/EasyListener.java
@@ -1,27 +1,17 @@
package cc.carm.lib.easylistener;
-import org.bukkit.Location;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.Player;
+import cc.carm.lib.easylistener.handler.BundleEventHandler;
+import cc.carm.lib.easylistener.handler.MultiEventHandler;
+import cc.carm.lib.easylistener.handler.SingleEventHandler;
+import org.bukkit.Bukkit;
import org.bukkit.event.*;
-import org.bukkit.event.block.BlockBreakEvent;
-import org.bukkit.event.block.BlockPlaceEvent;
-import org.bukkit.event.entity.EntityDamageByEntityEvent;
-import org.bukkit.event.entity.EntitySpawnEvent;
-import org.bukkit.event.entity.PlayerDeathEvent;
-import org.bukkit.event.player.PlayerBucketEmptyEvent;
-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.Plugin;
+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.BiPredicate;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
/**
@@ -29,7 +19,13 @@ import java.util.function.Predicate;
*
* @author CarmJos
*/
-public interface EasyListener extends Listener {
+public class EasyListener implements Listener {
+
+ protected final Plugin plugin;
+
+ public EasyListener(Plugin plugin) {
+ this.plugin = plugin;
+ }
/**
* 创建一个新的 {@link EasyListener} 实例
@@ -37,18 +33,35 @@ public interface EasyListener extends Listener {
* @param plugin {@link Plugin}插件实例
* @return {@link EasyListener} 实例
*/
- static @NotNull ListenerManager create(@NotNull Plugin plugin) {
- return new ListenerManager(plugin);
+ public static @NotNull EasyListener create(@NotNull Plugin plugin) {
+ return new EasyListener(plugin);
}
/**
* 注销本监听器内的全部监听器。
*
也可以通过 {@link HandlerList#unregister(Listener)} 方法注销本监听器。
*/
- default void unregisterAll() {
+ public void unregisterAll() {
HandlerList.unregisterAll(this);
}
+ public @NotNull SingleEventHandler handleEvent(@NotNull Class eventClass) {
+ return new SingleEventHandler<>(this, eventClass);
+ }
+
+ public @NotNull MultiEventHandler handleEvents(@NotNull Class eventType) {
+ return new MultiEventHandler<>(this, eventType);
+ }
+
+ public @NotNull BundleEventHandler handleBundle(@NotNull Class elementClass) {
+ return handleBundle(elementClass, Event.class);
+ }
+
+ public @NotNull BundleEventHandler handleBundle(@NotNull Class elementClass,
+ @NotNull Class eventType) {
+ return new BundleEventHandler<>(this, elementClass, eventType);
+ }
+
/**
* 处理一个事件。
*
@@ -59,9 +72,40 @@ public interface EasyListener extends Listener {
* @param {@link Event} 事件的类型
* @return 本实例
*/
- EasyListener handle(@NotNull Class eventClass,
- @Nullable EventPriority priority, boolean ignoreCancelled,
- @NotNull Consumer eventConsumer);
+ 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;
+ }
+
+ /**
+ * 有条件地取消一个事件。
+ *
本方法在条件满足时对事件进行取消,不会改变事件取消的状态。
+ *
因此,已经被取消的事件将不再进行判断和取消。。
+ *
+ * @param eventClass {@link Event} 事件类
+ * @param priority {@link EventPriority} 事件处理优先级
+ * @param eventPredicate 判断事件是否可以取消的条件
+ * @param afterCancelled 当事件被取消后执行的方法
+ * @param {@link Event} 事件的类型,必须实现 {@link Cancellable} 。
+ * @return 本实例
+ * @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常
+ */
+ public EasyListener cancel(@NotNull Class eventClass,
+ @Nullable EventPriority priority,
+ @Nullable Predicate super T> eventPredicate,
+ @Nullable Consumer super T> afterCancelled) {
+ requireType(Cancellable.class, eventClass, "Event class " + eventClass.getName() + " is not cancellable");
+
+ final Predicate super T> predicate = Optional.ofNullable(eventPredicate).orElse(t -> true);
+ return handle(eventClass, priority, true, (event) -> {
+ if (predicate.test(event)) {
+ ((Cancellable) event).setCancelled(true);
+ if (afterCancelled != null) afterCancelled.accept(event);
+ }
+ });
+ }
/**
* 有条件地取消一个事件。
@@ -75,9 +119,11 @@ public interface EasyListener extends Listener {
* @return 本实例
* @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常
*/
- EasyListener cancel(@NotNull Class eventClass,
- @Nullable EventPriority priority,
- @Nullable Predicate eventPredicate);
+ public EasyListener cancel(@NotNull Class eventClass,
+ @Nullable EventPriority priority,
+ @Nullable Predicate super T> eventPredicate) {
+ return cancel(eventClass, priority, eventPredicate, null);
+ }
/**
* 处理一个事件。
@@ -87,8 +133,8 @@ public interface EasyListener extends Listener {
* @param {@link Event} 事件的类型
* @return 本实例
*/
- default EasyListener handle(@NotNull Class eventClass,
- @NotNull Consumer eventConsumer) {
+ public EasyListener handle(@NotNull Class eventClass,
+ @NotNull Consumer eventConsumer) {
return handle(eventClass, null, eventConsumer);
}
@@ -101,9 +147,9 @@ public interface EasyListener extends Listener {
* @param {@link Event} 事件的类型
* @return 本实例
*/
- default EasyListener handle(@NotNull Class eventClass,
- boolean ignoreCancelled,
- @NotNull Consumer eventConsumer) {
+ public EasyListener handle(@NotNull Class eventClass,
+ boolean ignoreCancelled,
+ @NotNull Consumer eventConsumer) {
return handle(eventClass, null, ignoreCancelled, eventConsumer);
}
@@ -116,9 +162,9 @@ public interface EasyListener extends Listener {
* @param {@link Event} 事件的类型
* @return 本实例
*/
- default EasyListener handle(@NotNull Class eventClass,
- @Nullable EventPriority priority,
- @NotNull Consumer eventConsumer) {
+ public EasyListener handle(@NotNull Class eventClass,
+ @Nullable EventPriority priority,
+ @NotNull Consumer eventConsumer) {
return handle(eventClass, priority, false, eventConsumer);
}
@@ -130,7 +176,7 @@ public interface EasyListener extends Listener {
* @return 本实例
* @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常
*/
- default EasyListener cancel(@NotNull Class eventClass) {
+ public EasyListener cancel(@NotNull Class eventClass) {
return cancel(eventClass, null, null);
}
@@ -143,115 +189,70 @@ public interface EasyListener extends Listener {
* @return 本实例
* @throws IllegalArgumentException 如果事件没有实现 {@link Cancellable} 则抛出此异常
*/
- default EasyListener cancel(@NotNull Class eventClass,
- @Nullable Predicate eventPredicate) {
+ public EasyListener cancel(@NotNull Class eventClass,
+ @Nullable Predicate eventPredicate) {
return cancel(eventClass, null, eventPredicate);
}
- // >---------------------------
- // 预设快捷操作方法
-
- default EasyListener cancelJoinMessage() {
- return handleJoinMessage(null);
- }
-
- 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())));
- }
-
- default EasyListener cancelQuitMessage() {
- return handleQuitMessage(null);
- }
-
- 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())));
- }
-
- default EasyListener cancelWeatherChange() {
- return cancelWeatherChange(null);
- }
-
- default EasyListener cancelWeatherChange(@Nullable Predicate weatherPredicate) {
- return cancel(WeatherChangeEvent.class, weatherPredicate);
- }
-
- default EasyListener cancelBreak(@Nullable Predicate player) {
- final Predicate predicate = Optional.ofNullable(player).orElse(t -> true);
- return cancelBreak(
- (event) -> predicate.test(event.getPlayer()),
- (event) -> predicate.test(event.getPlayer())
- );
- }
-
- default EasyListener cancelBreak(@Nullable Predicate blockBreakPredicate,
- @Nullable Predicate bucketFillPredicate) {
- return cancel(BlockBreakEvent.class, blockBreakPredicate)
- .cancel(PlayerBucketFillEvent.class, bucketFillPredicate);
- }
-
- default EasyListener cancelPlace(@Nullable Predicate player) {
- final Predicate predicate = Optional.ofNullable(player).orElse(t -> true);
- return cancelPlace(
- (event) -> predicate.test(event.getPlayer()),
- (event) -> predicate.test(event.getPlayer())
- );
- }
-
- default EasyListener cancelPlace(@Nullable Predicate blockBreakPredicate,
- @Nullable Predicate bucketEmptyPredicate) {
- return cancel(BlockPlaceEvent.class, blockBreakPredicate)
- .cancel(PlayerBucketEmptyEvent.class, bucketEmptyPredicate);
+ public Plugin getPlugin() {
+ return plugin;
}
/**
- * 有条件的取消玩家PVP。
+ * 通过 {@link SimplePluginManager} 获取到一个事件类的 {@link HandlerList} 。
*
- * @param predicate 判断器,返回true则取消事件。两参数分别为 attacker 与 victim 。
- * @return 当前实例
+ * @param eventClass 事件类
+ * @return 事件类的 {@link HandlerList}
*/
- 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;
- else return p.test((Player) attacker, (Player) damager);
- });
+ private @NotNull HandlerList getEventListeners(@NotNull Class extends Event> 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 predicate 判断器,返回true则取消事件。两参数分别为 attacker 与 victim 。
- * @return 当前实例
+ * @param eventClass 事件类
+ * @param eventConsumer 事件执行内容
+ * @param 事件类型
+ * @return 事件的执行器实例
*/
- 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()));
+ 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);
+ }
+ };
}
- default EasyListener cancelDeath(@Nullable Predicate predicate) {
- return cancelDeath(predicate, (event) -> {
- event.setDeathMessage(null);
- event.setKeepInventory(true);
- event.setKeepLevel(true);
- });
+ 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);
}
- @SuppressWarnings("deprecation")
- 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;
- event.getEntity().setHealth(event.getEntity().getMaxHealth());
- Optional.ofNullable(handler).ifPresent(consumer -> consumer.accept(event));
- });
+ protected void register(@NotNull Class extends Event> eventClass, @NotNull RegisteredListener listener) {
+ getEventListeners(eventClass).register(listener);
}
- 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()));
+ protected void register(@NotNull Class extends Event> 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);
}
}
diff --git a/src/main/java/cc/carm/lib/easylistener/ListenerManager.java b/src/main/java/cc/carm/lib/easylistener/ListenerManager.java
deleted file mode 100644
index 1b71f4f..0000000
--- a/src/main/java/cc/carm/lib/easylistener/ListenerManager.java
+++ /dev/null
@@ -1,103 +0,0 @@
-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 extends Event> 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 extends Event> eventClass, @NotNull RegisteredListener listener) {
- getEventListeners(eventClass).register(listener);
- }
-
- protected void register(@NotNull Class extends Event> 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/main/java/cc/carm/lib/easylistener/defaults/CommonListeners.java b/src/main/java/cc/carm/lib/easylistener/defaults/CommonListeners.java
new file mode 100644
index 0000000..436ccd2
--- /dev/null
+++ b/src/main/java/cc/carm/lib/easylistener/defaults/CommonListeners.java
@@ -0,0 +1,123 @@
+package cc.carm.lib.easylistener.defaults;
+
+import cc.carm.lib.easylistener.EasyListener;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntitySpawnEvent;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.player.PlayerBucketEmptyEvent;
+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.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Optional;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class CommonListeners {
+
+ public static void cancelJoinMessage(@NotNull EasyListener source) {
+ handleJoinMessage(source, null);
+ }
+
+ public static void handleJoinMessage(@NotNull EasyListener source, @Nullable Function joinMessage) {
+ final Function message = Optional.ofNullable(joinMessage).orElse(t -> "");
+ source.handle(PlayerJoinEvent.class, (event) -> event.setJoinMessage(message.apply(event.getPlayer())));
+ }
+
+ public static void cancelQuitMessage(@NotNull EasyListener source) {
+ handleQuitMessage(source, null);
+ }
+
+ public static void handleQuitMessage(@NotNull EasyListener source, @Nullable Function quitMessage) {
+ final Function message = Optional.ofNullable(quitMessage).orElse(t -> "");
+ source.handle(PlayerQuitEvent.class, (event) -> event.setQuitMessage(message.apply(event.getPlayer())));
+ }
+
+ public static void cancelWeatherChange(@NotNull EasyListener source) {
+ cancelWeatherChange(source, null);
+ }
+
+ public static void cancelWeatherChange(@NotNull EasyListener source,
+ @Nullable Predicate weatherPredicate) {
+ source.cancel(WeatherChangeEvent.class, weatherPredicate);
+ }
+
+ public static void cancelBreak(@NotNull EasyListener source, @Nullable Predicate playerPredicate) {
+ source.handleBundle(Player.class)
+ .from(BlockBreakEvent.class, BlockBreakEvent::getPlayer)
+ .from(PlayerBucketFillEvent.class, PlayerBucketFillEvent::getPlayer)
+ .filter(playerPredicate).cancel();
+ }
+
+ public static void cancelPlace(@NotNull EasyListener source, @Nullable Predicate playerPredicate) {
+ source.handleBundle(Player.class)
+ .from(BlockPlaceEvent.class, BlockPlaceEvent::getPlayer)
+ .from(PlayerBucketEmptyEvent.class, PlayerBucketEmptyEvent::getPlayer)
+ .filter(playerPredicate).cancel();
+ }
+
+ /**
+ * 有条件的取消玩家PVP。
+ *
+ * @param source 用于注册的源 {@link EasyListener} 对象。
+ * @param predicate 判断器,返回true则取消事件。两参数分别为 attacker 与 victim 。
+ */
+ public static void cancelPVP(@NotNull EasyListener source,
+ @Nullable BiPredicate predicate) {
+ final BiPredicate p = Optional.ofNullable(predicate).orElse((attacker, victim) -> true);
+ cancelAttack(source, (attacker, damager) -> {
+ if (!(attacker instanceof Player) || !(damager instanceof Player)) return false;
+ else return p.test((Player) attacker, (Player) damager);
+ });
+ }
+
+ /**
+ * 有条件的取消两个实体间的伤害。
+ *
+ * @param source 用于注册的源 {@link EasyListener} 对象。
+ * @param predicate 判断器,返回true则取消事件。两参数分别为 attacker 与 victim 。
+ */
+ public static void cancelAttack(@NotNull EasyListener source,
+ @Nullable BiPredicate predicate) {
+ final BiPredicate p = Optional.ofNullable(predicate).orElse((attacker, victim) -> true);
+ source.cancel(EntityDamageByEntityEvent.class, (event) -> p.test(event.getDamager(), event.getEntity()));
+ }
+
+ public static void cancelDeath(@NotNull EasyListener source,
+ @Nullable Predicate predicate) {
+ cancelDeath(source, predicate, event -> {
+ event.setDeathMessage(null);
+ event.setKeepInventory(true);
+ event.setKeepLevel(true);
+ });
+ }
+
+ @SuppressWarnings("deprecation")
+ public static void cancelDeath(@NotNull EasyListener source,
+ @Nullable Predicate predicate,
+ @Nullable Consumer handler) {
+ final Predicate p = Optional.ofNullable(predicate).orElse((player) -> true);
+ source.handle(PlayerDeathEvent.class, (event) -> {
+ if (!p.test(event.getEntity())) return;
+ event.getEntity().setHealth(event.getEntity().getMaxHealth());
+ Optional.ofNullable(handler).ifPresent(consumer -> consumer.accept(event));
+ });
+ }
+
+ public static void cancelSpawn(@NotNull EasyListener source,
+ @Nullable BiPredicate predicate) {
+ final BiPredicate p = Optional.ofNullable(predicate).orElse((entity, location) -> !(entity instanceof Player));
+ source.cancel(EntitySpawnEvent.class, (event) -> p.test(event.getEntity(), event.getLocation()));
+ }
+
+}
diff --git a/src/main/java/cc/carm/lib/easylistener/defaults/EventFilters.java b/src/main/java/cc/carm/lib/easylistener/defaults/EventFilters.java
new file mode 100644
index 0000000..aae8855
--- /dev/null
+++ b/src/main/java/cc/carm/lib/easylistener/defaults/EventFilters.java
@@ -0,0 +1,82 @@
+package cc.carm.lib.easylistener.defaults;
+
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.block.BlockEvent;
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.world.WorldEvent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.function.Predicate;
+
+public class EventFilters {
+
+ public Predicate isCancelled() {
+ return Cancellable::isCancelled;
+ }
+
+ public Predicate notCancelled() {
+ return e -> !e.isCancelled();
+ }
+
+ public Predicate moveInSameBlock() {
+ return e -> {
+ if (e.getTo() == null) return false;
+
+ World fromWorld = e.getFrom().getWorld();
+ World toWorld = e.getTo().getWorld();
+ if (!Objects.equals(fromWorld, toWorld)) return false;
+
+ return e.getFrom().getBlockX() != e.getTo().getBlockX() ||
+ e.getFrom().getBlockZ() != e.getTo().getBlockZ() ||
+ e.getFrom().getBlockY() != e.getTo().getBlockY();
+ };
+ }
+
+ public static Predicate interactAction(Action... actionType) {
+ return e -> Arrays.stream(actionType).anyMatch(a -> a == e.getAction());
+ }
+
+ public static Predicate invClickType(ClickType... clickTypes) {
+ return e -> Arrays.stream(clickTypes).anyMatch(a -> a == e.getClick());
+ }
+
+ public static Predicate playerIsOp() {
+ return e -> e.getPlayer().isOp();
+ }
+
+ public static Predicate playerHasPerm(@NotNull String permission) {
+ return e -> e.getPlayer().hasPermission(permission);
+ }
+
+ public static Predicate playerInWorld(@NotNull String worldName) {
+ return e -> e.getPlayer().getWorld().getName().equals(worldName);
+ }
+
+ public Predicate entityOf(@NotNull EntityType type) {
+ return e -> e.getEntityType() == type;
+ }
+
+ public Predicate worldOf(@NotNull String worldName) {
+ return e -> e.getWorld().getName().equals(worldName);
+ }
+
+ public Predicate blockOf(@NotNull Material material) {
+ return e -> e.getBlock().getType() == material;
+ }
+
+ public Predicate blockInWorld(@NotNull String worldName) {
+ return e -> e.getBlock().getWorld().getName().equals(worldName);
+ }
+
+}
diff --git a/src/main/java/cc/carm/lib/easylistener/defaults/EventHandlers.java b/src/main/java/cc/carm/lib/easylistener/defaults/EventHandlers.java
new file mode 100644
index 0000000..b4c16f5
--- /dev/null
+++ b/src/main/java/cc/carm/lib/easylistener/defaults/EventHandlers.java
@@ -0,0 +1,34 @@
+package cc.carm.lib.easylistener.defaults;
+
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.player.PlayerMoveEvent;
+
+import java.util.function.Consumer;
+
+public class EventHandlers {
+
+ private EventHandlers() {
+ }
+
+ public static final Consumer extends Cancellable> SET_CANCELLED = event -> event.setCancelled(true);
+ public static final Consumer extends Cancellable> UNSET_CANCELLED = event -> event.setCancelled(false);
+
+ public static final Consumer extends PlayerMoveEvent> CANCEL_MOVE_BY_TELEPORT = event -> event.getPlayer().teleport(event.getFrom());
+
+ public static Consumer extends Cancellable> setCancelled() {
+ return SET_CANCELLED;
+ }
+
+ public static Consumer extends Cancellable> unsetCancelled() {
+ return UNSET_CANCELLED;
+ }
+
+ public static Consumer extends Cancellable> setCancelled(boolean cancelled) {
+ return cancelled ? SET_CANCELLED : UNSET_CANCELLED;
+ }
+
+ public static Consumer extends PlayerMoveEvent> cancelMoveByTeleport() {
+ return CANCEL_MOVE_BY_TELEPORT;
+ }
+
+}
diff --git a/src/main/java/cc/carm/lib/easylistener/handler/BaseEventHandler.java b/src/main/java/cc/carm/lib/easylistener/handler/BaseEventHandler.java
new file mode 100644
index 0000000..e8126db
--- /dev/null
+++ b/src/main/java/cc/carm/lib/easylistener/handler/BaseEventHandler.java
@@ -0,0 +1,50 @@
+package cc.carm.lib.easylistener.handler;
+
+import cc.carm.lib.easylistener.EasyListener;
+import org.bukkit.event.EventPriority;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Optional;
+import java.util.function.Predicate;
+
+public abstract class BaseEventHandler> {
+
+ protected final @NotNull EasyListener source;
+
+ protected EventPriority priority = null;
+ protected boolean ignoreCancelled = false;
+
+ protected Predicate predicate;
+
+ public BaseEventHandler(@NotNull EasyListener source) {
+ this.source = source;
+ }
+
+ protected abstract S getThis();
+
+ public S priority(@Nullable EventPriority priority) {
+ this.priority = priority;
+ return getThis();
+ }
+
+ public S setIgnoreCancelled(boolean ignore) {
+ this.ignoreCancelled = ignore;
+ return getThis();
+ }
+
+ public S acceptCancelled() {
+ return setIgnoreCancelled(false);
+ }
+
+ public S ignoreCancelled() {
+ return setIgnoreCancelled(true);
+ }
+
+ public S filter(@Nullable Predicate predicate) {
+ if (predicate == null) return getThis();
+ this.predicate = Optional.ofNullable(this.predicate).map(p -> p.and(predicate)).orElse(predicate);
+ return getThis();
+ }
+
+}
diff --git a/src/main/java/cc/carm/lib/easylistener/handler/BundleEventHandler.java b/src/main/java/cc/carm/lib/easylistener/handler/BundleEventHandler.java
new file mode 100644
index 0000000..dac2e79
--- /dev/null
+++ b/src/main/java/cc/carm/lib/easylistener/handler/BundleEventHandler.java
@@ -0,0 +1,117 @@
+package cc.carm.lib.easylistener.handler;
+
+import cc.carm.lib.easylistener.EasyListener;
+import org.bukkit.event.Event;
+import org.bukkit.event.EventPriority;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.*;
+
+public class BundleEventHandler {
+
+ protected final EasyListener source;
+
+ protected final Class eventType;
+ protected final Class handleClass;
+ protected final Map, EventWrapper extends E, T>> wrappers = new HashMap<>();
+
+ protected BiPredicate predicate;
+
+ public BundleEventHandler(EasyListener source, Class handleClass, Class eventType) {
+ this.source = source;
+ this.eventType = eventType;
+ this.handleClass = handleClass;
+ }
+
+ public BundleEventHandler from(@NotNull Class eventClass,
+ @NotNull Function wrapFunction) {
+ return from(eventClass, null, wrapFunction);
+ }
+
+ public BundleEventHandler from(@NotNull Class eventClass,
+ @Nullable EventPriority priority,
+ @NotNull Function wrapFunction) {
+ this.wrappers.put(eventClass, new EventWrapper<>(eventClass, priority, wrapFunction));
+ return this;
+ }
+
+ public BundleEventHandler filter(@Nullable BiPredicate predicate) {
+ if (predicate == null) return this;
+
+ this.predicate = Optional.ofNullable(this.predicate).map(p -> p.and(predicate)).orElse(predicate);
+ return this;
+ }
+
+ public BundleEventHandler filter(@Nullable Predicate predicate) {
+ if (predicate == null) return this;
+ BiPredicate append = (t, e) -> predicate.test(t);
+ this.predicate = Optional.ofNullable(this.predicate).map(p -> p.and(append)).orElse(append);
+ return this;
+ }
+
+ public EasyListener handle(@NotNull BiConsumer consumer) {
+ BiPredicate predicate = Optional.ofNullable(this.predicate).orElse((t, e) -> true);
+ this.wrappers.values().forEach(wrapper -> wrapper.handle(source, predicate, consumer));
+ return source;
+ }
+
+ public EasyListener handle(@NotNull Consumer consumer) {
+ return handle((t, e) -> consumer.accept(t));
+ }
+
+ public EasyListener cancel() {
+ return cancel((BiConsumer) null);
+ }
+
+ public EasyListener cancel(@Nullable BiConsumer afterCancelled) {
+ BiConsumer consumer = Optional.ofNullable(afterCancelled).orElse((t, e) -> {
+ //Do nothing
+ });
+ this.wrappers.values().forEach(wrapper -> wrapper.cancel(source, predicate, consumer));
+ return source;
+ }
+
+ public EasyListener cancel(@Nullable Consumer afterCancelled) {
+ return cancel((t, e) -> Optional.ofNullable(afterCancelled).ifPresent(c -> c.accept(t)));
+ }
+
+ protected static class EventWrapper {
+
+ protected final @NotNull Class eventClass;
+ protected final @NotNull Function wrapper;
+
+ protected final EventPriority priority;
+
+ public EventWrapper(@NotNull Class eventClass, EventPriority priority,
+ @NotNull Function wrapper) {
+ this.eventClass = eventClass;
+ this.wrapper = wrapper;
+ this.priority = priority;
+ }
+
+ public void handle(@NotNull EasyListener source,
+ @NotNull BiPredicate predicate, @NotNull BiConsumer consumer) {
+ source.handle(this.eventClass, this.priority, event -> {
+ T wrapper = this.wrapper.apply(event);
+ if (predicate.test(wrapper, event)) consumer.accept(wrapper, event);
+ });
+ }
+
+ public void cancel(@NotNull EasyListener source,
+ @NotNull BiPredicate predicate,
+ @NotNull BiConsumer afterCancelled) {
+ source.cancel(
+ this.eventClass, this.priority,
+ event -> predicate.test(this.wrapper.apply(event), event),
+ event -> afterCancelled.accept(this.wrapper.apply(event), event)
+ );
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/cc/carm/lib/easylistener/handler/MultiEventHandler.java b/src/main/java/cc/carm/lib/easylistener/handler/MultiEventHandler.java
new file mode 100644
index 0000000..be2b01e
--- /dev/null
+++ b/src/main/java/cc/carm/lib/easylistener/handler/MultiEventHandler.java
@@ -0,0 +1,58 @@
+package cc.carm.lib.easylistener.handler;
+
+import cc.carm.lib.easylistener.EasyListener;
+import org.bukkit.event.Event;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public class MultiEventHandler extends BaseEventHandler> {
+
+ protected final Class eventType;
+
+ protected final Set> eventClasses = new HashSet<>();
+ protected Predicate eventPredicate;
+
+ public MultiEventHandler(EasyListener source, Class eventType) {
+ super(source);
+ this.eventType = eventType;
+ }
+
+ @Override
+ protected MultiEventHandler getThis() {
+ return this;
+ }
+
+ public MultiEventHandler from(@NotNull Class extends T> eventClass) {
+ this.eventClasses.add(eventClass);
+ return this;
+ }
+
+ public EasyListener handle(@NotNull Consumer eventConsumer) {
+
+ for (Class extends T> clazz : this.eventClasses) {
+ source.handle(clazz, priority, ignoreCancelled, (event) -> {
+ Predicate predicate = Optional.ofNullable(eventPredicate).orElse(t -> true);
+ if (predicate.test(event)) eventConsumer.accept(event);
+ });
+ }
+
+ return source;
+ }
+
+ public EasyListener cancel() {
+ return cancel(null);
+ }
+
+ public EasyListener cancel(@Nullable Consumer afterCancelled) {
+ this.eventClasses.forEach(clazz -> source.cancel(clazz, priority, eventPredicate, afterCancelled));
+ return source;
+ }
+
+
+}
diff --git a/src/main/java/cc/carm/lib/easylistener/handler/SingleEventHandler.java b/src/main/java/cc/carm/lib/easylistener/handler/SingleEventHandler.java
new file mode 100644
index 0000000..44a9c24
--- /dev/null
+++ b/src/main/java/cc/carm/lib/easylistener/handler/SingleEventHandler.java
@@ -0,0 +1,42 @@
+package cc.carm.lib.easylistener.handler;
+
+import cc.carm.lib.easylistener.EasyListener;
+import org.bukkit.event.Event;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public class SingleEventHandler extends BaseEventHandler> {
+
+ protected final Class eventClass;
+
+ public SingleEventHandler(EasyListener source, Class eventClass) {
+ super(source);
+ this.eventClass = eventClass;
+ }
+
+ @Override
+ protected SingleEventHandler getThis() {
+ return this;
+ }
+
+ public EasyListener handle(@NotNull Consumer eventConsumer) {
+ return source.handle(eventClass, priority, ignoreCancelled, (event) -> {
+ Predicate predicate = Optional.ofNullable(this.predicate).orElse(t -> true);
+ if (predicate.test(event)) eventConsumer.accept(event);
+ });
+ }
+
+ public EasyListener cancel() {
+ return cancel(null);
+ }
+
+ public EasyListener cancel(@Nullable Consumer afterCancelled) {
+ return source.cancel(eventClass, priority, predicate, afterCancelled);
+ }
+
+
+}
diff --git a/src/test/java/DemoPlugin.java b/src/test/java/DemoPlugin.java
index dfcdf0d..83270a4 100644
--- a/src/test/java/DemoPlugin.java
+++ b/src/test/java/DemoPlugin.java
@@ -1,21 +1,21 @@
import cc.carm.lib.easylistener.EasyListener;
+import cc.carm.lib.easylistener.defaults.CommonListeners;
+import cc.carm.lib.easylistener.defaults.EventFilters;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageEvent;
-import org.bukkit.event.player.PlayerInteractAtEntityEvent;
-import org.bukkit.event.player.PlayerPickupArrowEvent;
+import org.bukkit.event.player.*;
import org.bukkit.plugin.java.JavaPlugin;
public class DemoPlugin extends JavaPlugin {
- protected final EasyListener listeners = EasyListener.create(this);
+ protected final EasyListener source = EasyListener.create(this);
@Override
public void onEnable() {
-
- listeners // 基本用法
- .handle(PlayerInteractAtEntityEvent.class, (event) -> {
+ // 基本用法
+ source.handle(PlayerInteractAtEntityEvent.class, (event) -> {
Entity clicked = event.getRightClicked();
Player player = event.getPlayer();
@@ -30,16 +30,40 @@ public class DemoPlugin extends JavaPlugin {
(event) -> event.getCause() != EntityDamageEvent.DamageCause.ENTITY_ATTACK
); // 有条件的取消一个事件
- listeners // 额外提供的快捷方法
- .cancelDeath(null) // 所有玩家取消死亡
- .cancelBreak(player -> !player.isOp()) // 禁止非OP玩家破坏方块/接水或岩浆
- .cancelPlace(player -> !player.isOp()) // 禁止非OP玩家放置方块/放水或岩浆
- .cancelPVP((attacker, victim) -> !attacker.isOp()) // 禁止非op玩家PVP
- .cancelWeatherChange() // 取消天气变更
- .cancelJoinMessage() // 取消加入消息
-// .cancelQuitMessage()
-// .handleJoinMessage(player -> "玩家 " + player.getName() + " 加入了服务器。")
- .handleQuitMessage(player -> "玩家 " + player.getName() + " 退出了服务器。"); // 设定退出消息
+
+ // Functional 用法
+ source.handleEvent(PlayerInteractAtEntityEvent.class)
+ .filter(e -> e.getRightClicked() instanceof Player)
+ .filter(EventFilters.playerHasPerm("yc.admin"))
+ .handle(e -> {
+ Player player = e.getPlayer();
+ player.sendMessage("你点了 " + e.getRightClicked().getName() + " 一下!");
+ });
+
+ source.handleEvents(PlayerEvent.class)
+ .from(PlayerJoinEvent.class)
+ .from(PlayerQuitEvent.class)
+ .filter(EventFilters.playerHasPerm("yc.admin"))
+ .handle(playerEvent -> System.out.println(playerEvent.getPlayer().getName()));
+
+ source.handleBundle(Player.class)
+ .from(PlayerJoinEvent.class, PlayerEvent::getPlayer)
+ .from(PlayerInteractEvent.class, PlayerEvent::getPlayer)
+ .filter(p -> p.hasPermission("yc.admin"))
+ .handle((p, e) -> p.sendMessage("hi!"));
+
+
+ // 预设的快捷方法
+ CommonListeners.cancelDeath(source, null); // 所有玩家取消死亡
+ CommonListeners.cancelBreak(source, player -> !player.isOp()); // 禁止非OP玩家破坏方块/接水或岩浆
+ CommonListeners.cancelPlace(source, player -> !player.isOp()); // 禁止非OP玩家建造方块/接水或岩浆
+
+ CommonListeners.cancelPVP(source, (attacker, victim) -> !attacker.isOp()); // 禁止非op玩家攻击别人
+ CommonListeners.cancelWeatherChange(source); // 取消天气变化
+ CommonListeners.cancelJoinMessage(source); // 取消加入消息
+// CommonListeners.cancelQuitMessage(listeners);
+// CommonListeners.handleJoinMessage(listeners, player -> "玩家 " + player.getName() + " 加入了服务器。");
+ CommonListeners.handleQuitMessage(source, player -> "玩家 " + player.getName() + " 退出了服务器。"); // 设定退出消息
}