MenuBackpack

MenuBackpack.java v1.0
在玩家生存模式背包内定义"菜单格",配置物品lore和点击执行命令,支持自定义配置与reload命令
作者: ScriptIrc

命令列表

  • menuinvreload重载菜单背包配置

权限列表

  • menuinv.reload允许重载插件配置
package com.menu.backpack;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.io.IOException;
import java.util.*;
import org.bukkit.configuration.file.YamlConfiguration;

/**
 * @pluginName MenuBackpack
 * @author ScriptIrc
 * @version 1.0
 * @description 在玩家生存模式背包内定义"菜单格",配置物品lore和点击执行命令,支持自定义配置与reload命令
 * [command]menuinvreload|重载菜单背包配置[/command]
 * [Permission]menuinv.reload|允许重载插件配置[/Permission]
 */
public class MenuBackpackPlugin extends JavaPlugin implements Listener {

    // 配置文件对象
    private YamlConfiguration config;

    // 菜单格子配置:格编号->MenuSlot信息
    private Map<Integer, MenuSlot> menuSlots = new HashMap<>();

    // 菜单格自定义结构体
    public static class MenuSlot {
        public Material material;
        public String displayName;
        public List<String> lore;
        public String command;
        public MenuSlot(Material m, String name, List<String> lore, String cmd) {
            this.material = m;
            this.displayName = name;
            this.lore = lore;
            this.command = cmd;
        }
    }

    @Override
    public void onEnable() {
        getLogger().info("MenuBackpack插件正在启用...");
        saveDefaultConfigFile();
        reloadMenuConfig();
        Bukkit.getPluginManager().registerEvents(this, this);
        getLogger().info("已注册事件监听器和菜单配置加载完成!");
    }

    @Override
    public void onDisable() {
        getLogger().info("MenuBackpack插件已关闭。");
    }

    /**
     * 保存默认配置文件,如果不存在则生成并写入样板
     */
    private void saveDefaultConfigFile() {
        File file = new File(getDataFolder(), "menu_backpack.yml");
        if (!file.exists()) {
            try {
                getDataFolder().mkdirs();
                file.createNewFile();
                // 写入配置样板,方便用户修改
                YamlConfiguration yc = new YamlConfiguration();
                // 格子编号如0为第一格,8为第一排第9格
                Map<String, Object> slot0 = new HashMap<>();
                slot0.put("material", "DIAMOND");
                slot0.put("display", "§b钻石菜单按钮");
                slot0.put("lore", Arrays.asList("§7点击执行命令", "§a/say Hello!"));
                slot0.put("command", "say §e你点击了钻石菜单!");
                yc.set("slots.0", slot0);
                yc.set("slots.8.material", "GOLD_INGOT");
                yc.set("slots.8.display", "§6黄金按钮");
                yc.set("slots.8.lore", Arrays.asList("§e点我获得金币", "§a/give <player> gold_ingot 1"));
                yc.set("slots.8.command", "give %player% gold_ingot 1");
                yc.save(file);
            } catch (IOException e) {
                getLogger().warning("默认配置文件生成失败!");
            }
        }
    }

    /**
     * 重载菜单配置,供reload命令和onEnable使用
     */
    private void reloadMenuConfig() {
        File file = new File(getDataFolder(), "menu_backpack.yml");
        config = YamlConfiguration.loadConfiguration(file);
        menuSlots.clear();
        // slots可指定多个格
        if (config.isConfigurationSection("slots")) {
            Set<String> keys = config.getConfigurationSection("slots").getKeys(false);
            for (String key : keys) {
                try {
                    int slot = Integer.parseInt(key); // 背包格编号 0~35 (玩家主背包36格)
                    Material material = Material.matchMaterial(config.getString("slots." + key + ".material", "STONE"));
                    String display = config.getString("slots." + key + ".display", "§f菜单按钮");
                    List<String> lore = config.getStringList("slots." + key + ".lore");
                    String command = config.getString("slots." + key + ".command", "say %player% 点击了菜单!");
                    if (material != null) {
                        menuSlots.put(slot, new MenuSlot(material, display, lore, command));
                    }
                } catch (Exception e) {
                    getLogger().warning("读取菜单格配置失败: " + key);
                }
            }
            getLogger().info("已加载菜单格配置: "+menuSlots.size()+" 个格子");
        } else {
            getLogger().warning("未找到菜单格配置,请检查 menu_backpack.yml!");
        }
    }

    /**
     * 实现命令/menuinvreload 用于管理员手动重载配置
     */
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        if ("menuinvreload".equalsIgnoreCase(label)) {
            if (sender.hasPermission("menuinv.reload")) {
                reloadMenuConfig();
                sender.sendMessage("§a菜单背包配置已重载!");
            } else {
                sender.sendMessage("§c你没有重载权限!");
            }
            return true;
        }
        return false;
    }

    /**
     * 玩家打开背包事件,为其指定菜单格自动填充菜单物品
     */
    @EventHandler
    public void onInventoryOpen(InventoryOpenEvent event) {
        // 只处理主背包界面
        if (!(event.getPlayer() instanceof Player)) return;
        if (event.getInventory().getType() != InventoryType.PLAYER) return;
        Player player = (Player) event.getPlayer();
        Inventory inv = player.getInventory();
        for (Map.Entry<Integer, MenuSlot> entry : menuSlots.entrySet()) {
            int slot = entry.getKey();
            MenuSlot ms = entry.getValue();
            ItemStack is = new ItemStack(ms.material);
            ItemMeta meta = is.getItemMeta();
            if (meta != null) {
                meta.setDisplayName(ms.displayName);
                meta.setLore(ms.lore);
                is.setItemMeta(meta);
            }
            inv.setItem(slot, is); // 填充菜单格
        }
    }

    /**
     * 玩家背包点击事件,判断点击格并处理
     */
    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {
        if (!(event.getWhoClicked() instanceof Player)) return;
        Inventory inv = event.getInventory();
        // 只处理玩家背包
        if (inv.getType() != InventoryType.PLAYER) return;
        int slot = event.getRawSlot();
        if (menuSlots.containsKey(slot)) {
            event.setCancelled(true); // 阻止菜单格物品被拖动或替换
            MenuSlot ms = menuSlots.get(slot);
            Player player = (Player) event.getWhoClicked();
            // 执行菜单格命令,支持%player%变量替换为玩家名
            String cmd = ms.command.replace("%player%", player.getName());
            Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd);
            player.sendMessage("§a你点击了菜单按钮!");
        }
    }

    /**
     * 玩家加入时同步菜单物品以防以奇异Bug丢失
     */
    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        Inventory inv = player.getInventory();
        Bukkit.getScheduler().runTaskLater(this, () -> {
            for (Map.Entry<Integer, MenuSlot> entry : menuSlots.entrySet()) {
                int slot = entry.getKey();
                MenuSlot ms = entry.getValue();
                ItemStack is = new ItemStack(ms.material);
                ItemMeta meta = is.getItemMeta();
                if (meta != null) {
                    meta.setDisplayName(ms.displayName);
                    meta.setLore(ms.lore);
                    is.setItemMeta(meta);
                }
                inv.setItem(slot, is);
            }
        }, 20L); // 延迟1秒执行以保证同步
    }
}
上一篇: ServerRemoteControl下一篇: ItemShow

举报内容

意见反馈