Skip to content

事件监听系统

概述

事件监听系统负责处理游戏中的各种事件,包括玩家交互、游戏保护、聊天管理和玩家退出等。系统采用 Bukkit 事件监听机制,通过注册监听器来响应游戏事件。

监听器列表

监听器路径描述
PlayerQuitListenercn.enderrealm.disaster.listeners.PlayerQuitListener处理玩家退出事件
PlayerInteractListenercn.enderrealm.disaster.listeners.PlayerInteractListener处理玩家交互事件
GameProtectionListenercn.enderrealm.disaster.listeners.GameProtectionListener游戏保护机制
GameEventListenercn.enderrealm.disaster.listeners.GameEventListener游戏事件处理
ChatListenercn.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();
            }
        }
    }
}

处理流程

  1. 检测玩家退出

    • 监听 PlayerQuitEvent 事件
    • 获取退出的玩家对象
  2. 查找玩家房间

    • 通过 RoomManager 获取玩家所在的房间
    • 如果玩家不在房间中,直接返回
  3. 移除玩家

    • 调用 Room.removePlayer() 移除玩家
    • 清理玩家相关的游戏状态
  4. 检查房间状态

    • 如果房间为空,触发房间清理
    • 如果游戏正在进行,检查是否需要结束游戏

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退出房间的粘液球
放置型 TNTTNT放置 TNT 方块
投掷型 TNTTNT投掷 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);
    
    // ...
}

事件优先级

监听器优先级描述
ChatListenerHIGH确保在其他插件之前处理聊天
GameProtectionListenerNORMAL标准优先级处理保护
GameEventListenerNORMAL标准优先级处理游戏事件
PlayerInteractListenerNORMAL标准优先级处理交互
PlayerQuitListenerNORMAL标准优先级处理退出

相关文档