事件监听系统
概述
事件监听系统负责处理游戏中的各种事件,包括玩家交互、游戏保护、聊天管理和玩家退出等。系统采用 Bukkit 事件监听机制,通过注册监听器来响应游戏事件。
监听器列表
| 监听器 | 路径 | 描述 |
|---|---|---|
PlayerQuitListener | cn.enderrealm.disaster.listeners.PlayerQuitListener | 处理玩家退出事件 |
PlayerInteractListener | cn.enderrealm.disaster.listeners.PlayerInteractListener | 处理玩家交互事件 |
GameProtectionListener | cn.enderrealm.disaster.listeners.GameProtectionListener | 游戏保护机制 |
GameEventListener | cn.enderrealm.disaster.listeners.GameEventListener | 游戏事件处理 |
ChatListener | cn.enderrealm.disaster.listeners.ChatListener | 聊天系统 |
监听器详解
PlayerQuitListener(玩家退出监听器)
路径:cn.enderrealm.disaster.listeners.PlayerQuitListener
处理玩家退出服务器的事件,确保正确清理房间状态。
java
public class PlayerQuitListener implements Listener {
private final disaster plugin;
public PlayerQuitListener(disaster plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
// 获取玩家所在的房间
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room != null) {
// 从房间中移除玩家
room.removePlayer(player);
// 如果房间为空,清理房间
if (room.isEmpty()) {
plugin.getRoomManager().checkEmptyRooms();
}
}
}
}处理流程
检测玩家退出
- 监听
PlayerQuitEvent事件 - 获取退出的玩家对象
- 监听
查找玩家房间
- 通过
RoomManager获取玩家所在的房间 - 如果玩家不在房间中,直接返回
- 通过
移除玩家
- 调用
Room.removePlayer()移除玩家 - 清理玩家相关的游戏状态
- 调用
检查房间状态
- 如果房间为空,触发房间清理
- 如果游戏正在进行,检查是否需要结束游戏
PlayerInteractListener(玩家交互监听器)
路径:cn.enderrealm.disaster.listeners.PlayerInteractListener
处理玩家与物品的交互事件,特别是特殊道具的使用。
java
public class PlayerInteractListener implements Listener {
private final disaster plugin;
public PlayerInteractListener(disaster plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
ItemStack item = event.getItem();
if (item == null) return;
// 检查是否是退出物品(粘液球)
if (item.getType() == Material.SLIME_BALL) {
// 检查是否是插件创建的退出物品
ItemMeta meta = item.getItemMeta();
if (meta != null) {
org.bukkit.NamespacedKey key = new org.bukkit.NamespacedKey(plugin, "quit-item");
if (meta.getPersistentDataContainer().has(key, org.bukkit.persistence.PersistentDataType.BYTE)) {
// 处理退出房间逻辑
handleQuitItem(player);
event.setCancelled(true);
}
}
}
}
private void handleQuitItem(Player player) {
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room != null) {
room.removePlayer(player);
player.sendMessage(plugin.getLanguageManager().getText("left-room", player));
}
}
}处理的物品类型
| 物品 | 类型 | 描述 |
|---|---|---|
| 退出物品 | SLIME_BALL | 退出房间的粘液球 |
| 放置型 TNT | TNT | 放置 TNT 方块 |
| 投掷型 TNT | TNT | 投掷 TNT 实体 |
| 火球 | FIRE_CHARGE | 投掷火球 |
| 随机传送 | ENDER_EYE | 随机传送 |
| 替死鬼 | BONE | 与最近玩家交换位置 |
GameProtectionListener(游戏保护监听器)
路径:cn.enderrealm.disaster.listeners.GameProtectionListener
提供游戏中的保护机制,防止玩家在特定情况下受到伤害。
java
public class GameProtectionListener implements Listener {
private final disaster plugin;
public GameProtectionListener(disaster plugin) {
this.plugin = plugin;
}
@EventHandler
public void onEntityDamage(EntityDamageEvent event) {
if (!(event.getEntity() instanceof Player)) return;
Player player = (Player) event.getEntity();
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room == null) return;
// 等待阶段保护
if (room.isWaiting()) {
event.setCancelled(true);
return;
}
// 游戏开始后的保护(可选)
// ...
}
@EventHandler
public void onFoodLevelChange(FoodLevelChangeEvent event) {
if (!(event.getEntity() instanceof Player)) return;
Player player = (Player) event.getEntity();
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room == null) return;
// 等待阶段禁止饥饿
if (room.isWaiting()) {
event.setCancelled(true);
}
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room == null) return;
// 等待阶段禁止破坏方块
if (room.isWaiting()) {
event.setCancelled(true);
}
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room == null) return;
// 等待阶段禁止放置方块
if (room.isWaiting()) {
event.setCancelled(true);
}
}
}保护规则
| 阶段 | 保护内容 |
|---|---|
| 等待阶段 | 禁止伤害、禁止饥饿、禁止破坏/放置方块 |
| 游戏阶段 | 根据灾难效果允许伤害 |
| 游戏结束 | 禁止所有交互 |
GameEventListener(游戏事件监听器)
路径:cn.enderrealm.disaster.listeners.GameEventListener
处理游戏中的特殊事件,如玩家死亡、被淘汰等。
java
public class GameEventListener implements Listener {
private final disaster plugin;
public GameEventListener(disaster plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
Player player = event.getEntity();
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room == null || !room.isStarted()) return;
// 标记玩家被淘汰
player.setMetadata("eliminated", new FixedMetadataValue(plugin, true));
// 设置玩家为旁观者模式
player.setGameMode(GameMode.SPECTATOR);
// 通知其他玩家
for (Player p : room.getPlayers()) {
p.sendMessage(plugin.getLanguageManager().getText("player-eliminated", p, player.getName()));
}
// 检查游戏是否应该结束
checkGameEnd(room);
}
@EventHandler
public void onPlayerRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room == null || !room.isStarted()) return;
// 如果玩家被淘汰,设置重生位置为旁观者位置
if (player.hasMetadata("eliminated")) {
event.setRespawnLocation(room.getWorld().getSpawnLocation());
}
}
private void checkGameEnd(Room room) {
int survivors = 0;
for (Player player : room.getPlayers()) {
if (!player.hasMetadata("eliminated")) {
survivors++;
}
}
// 如果只剩一个玩家或没有玩家,结束游戏
if (survivors <= 1) {
// 获取游戏管理器并结束游戏
GameManager gameManager = plugin.getRoomManager().getGameManager(room);
if (gameManager != null) {
gameManager.forceEndGame();
}
}
}
}处理的事件
| 事件 | 描述 |
|---|---|
PlayerDeathEvent | 玩家死亡时标记为被淘汰 |
PlayerRespawnEvent | 玩家重生时设置位置 |
EntityDamageByEntityEvent | 处理玩家间伤害 |
FoodLevelChangeEvent | 处理饥饿变化 |
ChatListener(聊天监听器)
路径:cn.enderrealm.disaster.listeners.ChatListener
实现房间内聊天系统,确保玩家消息只在房间内可见。
java
public class ChatListener implements Listener {
private final disaster plugin;
public ChatListener(disaster plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGH)
public void onAsyncPlayerChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
Room room = plugin.getRoomManager().getPlayerRoom(player);
if (room == null) return;
// 取消原始聊天事件
event.setCancelled(true);
// 获取房间内玩家列表
Set<Player> roomPlayers = room.getPlayers();
// 格式化消息
String message = event.getMessage();
String formattedMessage = String.format("§7[房间] §f%s: §7%s", player.getName(), message);
// 只发送给房间内玩家
for (Player roomPlayer : roomPlayers) {
roomPlayer.sendMessage(formattedMessage);
}
// 记录日志
plugin.getLogger().info("[Chat] " + player.getName() + ": " + message);
}
}聊天格式
[房间] 玩家名: 消息内容- 前缀:
§7[房间] - 玩家名:
§f玩家名 - 消息内容:
§7消息内容
事件注册
在主类 disaster.java 中注册所有监听器:
java
@Override
public void onEnable() {
// ...
// 注册监听器
getServer().getPluginManager().registerEvents(new PlayerQuitListener(this), this);
getServer().getPluginManager().registerEvents(new PlayerInteractListener(this), this);
getServer().getPluginManager().registerEvents(new GameProtectionListener(this), this);
getServer().getPluginManager().registerEvents(new GameEventListener(this), this);
getServer().getPluginManager().registerEvents(new ChatListener(this), this);
// ...
}事件优先级
| 监听器 | 优先级 | 描述 |
|---|---|---|
ChatListener | HIGH | 确保在其他插件之前处理聊天 |
GameProtectionListener | NORMAL | 标准优先级处理保护 |
GameEventListener | NORMAL | 标准优先级处理游戏事件 |
PlayerInteractListener | NORMAL | 标准优先级处理交互 |
PlayerQuitListener | NORMAL | 标准优先级处理退出 |