You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Minecraft插件CommandExecutor使用HashMap执行undo时表为空如何解决

问题根源

你现在的核心问题是bloques HashMap的作用域定义错误:

  • 你把bloques声明在了onCommand方法内部,每次服务器触发命令执行调用onCommand方法时,都会重新创建一个全新的空HashMap,方法执行结束后这个局部变量就会被回收,下一次执行undo命令时拿到的是新创建的空Map,自然读不到之前存储的数据。
  • 额外你还存在语法错误:方法内部的局部变量不能加public修饰符,而且代码里没有声明player变量就直接使用了。

修复方案

第一步:调整HashMap的作用域

将bloques从onCommand方法里移到类层级定义,这样整个类实例的生命周期内,这个Map都是复用的,不会每次调用命令就重置。如果要支持多玩家独立撤销,还可以把Map嵌套一层,键为玩家UUID,值为对应该玩家的操作记录:

// 定义在你的CommandExecutor类内部、所有方法的外面
private final Map<UUID, Map<Location, Material>> playerBlockRecords = new HashMap<>();

第二步:修改命令逻辑

适配新的存储结构,调整column和undo命令的逻辑:

public boolean onCommand(CommandSender sender, Command cmd, String s, String[] arg) {
    // 先判断发送者类型,强转为Player
    if (!(sender instanceof Player player)) {
        sender.sendMessage(ChatColor.RED + "该命令仅能由玩家执行。");
        return true ;
    }
    UUID playerId = player.getUniqueId();
    if (cmd.getName().equalsIgnoreCase("column")) {
        // 初始化当前玩家的本次操作记录容器
        Map<Location, Material> bloques = new HashMap<>();
        int x = player.getLocation().getBlockX() ;
        int y = player.getLocation().getBlockY() ;
        int z = player.getLocation().getBlockZ() ;
        for (int j=0 ; j<=2 ; j++) {
            for (int i = Integer.parseInt(arg[0]); i > 0; i--) {
                Block targetBlock = player.getWorld().getBlockAt(x+j-1, y + 2+ i, z);
                Material originalType = targetBlock.getType();
                bloques.put(targetBlock.getLocation(), originalType) ;
                targetBlock.setType(Material.getMaterial(arg[1].toUpperCase()));
            }
        }
        // 把本次操作记录存到全局玩家记录里
        playerBlockRecords.put(playerId, bloques);
        return true ;
    }
    if (cmd.getName().equalsIgnoreCase("undo")){
        // 取出当前玩家最近的操作记录
        Map<Location, Material> bloques = playerBlockRecords.get(playerId);
        if (bloques == null || bloques.isEmpty()) {
            player.sendMessage(ChatColor.RED + "没有可撤销的操作");
            return true;
        }
        for (Map.Entry<Location, Material> entry : bloques.entrySet()) {
            player.getWorld().getBlockAt(entry.getKey()).setType(entry.getValue());
        }
        // 撤销完成后清理记录,避免重复撤销
        playerBlockRecords.remove(playerId);
        player.sendMessage(ChatColor.GREEN + "操作已撤销");
        return true ;
    }
    return true;
}

拓展提示

如果需要支持多步撤销,可以把玩家对应的存储结构换成栈/队列存储多次操作记录即可;如果需要跨服务器重启支持撤销,可以将记录持久化到本地文件或数据库。

内容的提问来源于stack exchange,提问作者Alex Ramos Peña

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:15:03