ExpShopMenu

ExpShopMenu.java v1.0
基于玩家经验点数的四分类分页商店菜单,左键出售右键收购,农作物/方块/工具/防具四页,支持经验点交易。
作者: Scriptirc

命令列表

  • shopmenu打开经验点商店菜单

权限列表

  • expshopmenu.use允许玩家使用经验点商店菜单
package com.scriptirc.shopmenu;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
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.util.*;

/**
 * @pluginName ExpShopMenu
 * @author Scriptirc
 * @version 1.0
 * @description 基于玩家经验点数的四分类分页商店菜单,左键出售右键收购,农作物/方块/工具/防具四页,支持经验点交易。
 * [command]shopmenu|打开经验点商店菜单[/command]
 * [Permission]expshopmenu.use|允许玩家使用经验点商店菜单[/Permission]
 */
public class ExpShopMenu extends JavaPlugin implements Listener {
    private enum ShopCategory {
        CROPS, BLOCKS, TOOLS, ARMOR
    }
    private static class ShopItem {
        public final Material material;
        public final String name;
        public final int buyExp;
        public final int sellExp;
        public final int amount;
        public ShopItem(Material material, String name, int buyExp, int sellExp, int amount) {
            this.material = material;
            this.name = name;
            this.buyExp = buyExp;
            this.sellExp = sellExp;
            this.amount = amount;
        }
    }
    private static final Map<ShopCategory, List<ShopItem>> SHOP_ITEMS = new HashMap<>();
    private static final int ITEMS_PER_PAGE = 21;
    private static final Map<ShopCategory, String> CATEGORY_TITLES = new HashMap<>();
    static {
        SHOP_ITEMS.put(ShopCategory.CROPS, Arrays.asList(
                new ShopItem(Material.WHEAT, "小麦", 8, 4, 16),
                new ShopItem(Material.CARROT, "胡萝卜", 8, 4, 16),
                new ShopItem(Material.POTATO, "马铃薯", 8, 4, 16),
                new ShopItem(Material.BEETROOT, "甜菜根", 10, 5, 16),
                new ShopItem(Material.MELON_SLICE, "西瓜片", 6, 3, 16),
                new ShopItem(Material.PUMPKIN, "南瓜", 12, 6, 8),
                new ShopItem(Material.SUGAR_CANE, "甘蔗", 7, 3, 16),
                new ShopItem(Material.BAMBOO, "竹子", 5, 2, 16)
        ));
        SHOP_ITEMS.put(ShopCategory.BLOCKS, Arrays.asList(
                new ShopItem(Material.STONE, "石头", 10, 5, 32),
                new ShopItem(Material.COBBLESTONE, "圆石", 8, 4, 32),
                new ShopItem(Material.OAK_LOG, "橡木原木", 16, 8, 16),
                new ShopItem(Material.SAND, "沙子", 8, 4, 32),
                new ShopItem(Material.DIRT, "泥土", 6, 3, 32),
                new ShopItem(Material.GLASS, "玻璃", 12, 6, 16),
                new ShopItem(Material.BRICKS, "砖块", 20, 10, 8)
        ));
        SHOP_ITEMS.put(ShopCategory.TOOLS, Arrays.asList(
                new ShopItem(Material.IRON_PICKAXE, "铁镐", 80, 40, 1),
                new ShopItem(Material.IRON_AXE, "铁斧", 80, 40, 1),
                new ShopItem(Material.IRON_SHOVEL, "铁锹", 60, 30, 1),
                new ShopItem(Material.DIAMOND_PICKAXE, "钻石镐", 320, 160, 1),
                new ShopItem(Material.DIAMOND_AXE, "钻石斧", 320, 160, 1),
                new ShopItem(Material.DIAMOND_SHOVEL, "钻石锹", 240, 120, 1)
        ));
        SHOP_ITEMS.put(ShopCategory.ARMOR, Arrays.asList(
                new ShopItem(Material.IRON_HELMET, "铁头盔", 70, 35, 1),
                new ShopItem(Material.IRON_CHESTPLATE, "铁胸甲", 120, 60, 1),
                new ShopItem(Material.IRON_LEGGINGS, "铁护腿", 100, 50, 1),
                new ShopItem(Material.IRON_BOOTS, "铁靴子", 70, 35, 1),
                new ShopItem(Material.DIAMOND_HELMET, "钻石头盔", 280, 140, 1),
                new ShopItem(Material.DIAMOND_CHESTPLATE, "钻石胸甲", 480, 240, 1),
                new ShopItem(Material.DIAMOND_LEGGINGS, "钻石护腿", 400, 200, 1),
                new ShopItem(Material.DIAMOND_BOOTS, "钻石靴子", 280, 140, 1)
        ));
        CATEGORY_TITLES.put(ShopCategory.CROPS, "§a农作物商店");
        CATEGORY_TITLES.put(ShopCategory.BLOCKS, "§e方块商店");
        CATEGORY_TITLES.put(ShopCategory.TOOLS, "§b工具商店");
        CATEGORY_TITLES.put(ShopCategory.ARMOR, "§d防具商店");
    }
    private final Map<UUID, MenuSession> menuSessionMap = new HashMap<>();
    @Override
    public void onEnable() {
        Bukkit.getPluginManager().registerEvents(this, this);
        getLogger().info("经验点商店菜单插件已启用!");
    }
    @Override
    public void onDisable() {
        menuSessionMap.clear();
    }
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("§c只有玩家才能使用商店菜单!");
            return true;
        }
        Player player = (Player) sender;
        if (!player.hasPermission("expshopmenu.use")) {
            player.sendMessage("§c你没有权限使用经验点商店菜单!");
            return true;
        }
        openMainMenu(player);
        return true;
    }
    private void openMainMenu(Player player) {
        Inventory inv = Bukkit.createInventory(null, 27, "§6经验点商店 §7- 分类选择");
        inv.setItem(10, createMenuItem(Material.WHEAT, "§a农作物商店", Arrays.asList("§7出售/收购农作物", "§e点击进入")));
        inv.setItem(12, createMenuItem(Material.STONE, "§e方块商店", Arrays.asList("§7出售/收购方块", "§e点击进入")));
        inv.setItem(14, createMenuItem(Material.IRON_PICKAXE, "§b工具商店", Arrays.asList("§7出售/收购工具", "§e点击进入")));
        inv.setItem(16, createMenuItem(Material.IRON_CHESTPLATE, "§d防具商店", Arrays.asList("§7出售/收购防具", "§e点击进入")));
        player.openInventory(inv);
        menuSessionMap.put(player.getUniqueId(), new MenuSession(null, 0));
    }
    private void openShopMenu(Player player, ShopCategory category, int page) {
        List<ShopItem> items = SHOP_ITEMS.get(category);
        int totalPages = (items.size() - 1) / ITEMS_PER_PAGE + 1;
        int start = page * ITEMS_PER_PAGE;
        int end = Math.min(start + ITEMS_PER_PAGE, items.size());
        Inventory inv = Bukkit.createInventory(null, 27, CATEGORY_TITLES.get(category) + " §7- 第" + (page + 1) + "/" + totalPages + "页");
        for (int i = start; i < end; i++) {
            ShopItem si = items.get(i);
            List<String> lore = new ArrayList<>();
            lore.add("§a左键§7出售: §e+" + si.sellExp + "§7经验点/" + si.amount + "件");
            lore.add("§b右键§7收购: §e-" + si.buyExp + "§7经验点/" + si.amount + "件");
            lore.add("§8点击交易");
            inv.setItem(9 + (i - start), createMenuItem(si.material, "§f" + si.name, lore));
        }
        if (page > 0)
            inv.setItem(21, createMenuItem(Material.ARROW, "§a上一页", Arrays.asList("§7点击返回上一页")));
        if (page < totalPages - 1)
            inv.setItem(23, createMenuItem(Material.ARROW, "§a下一页", Arrays.asList("§7点击前往下一页")));
        inv.setItem(26, createMenuItem(Material.BARRIER, "§c返回主菜单", Arrays.asList("§7点击返回分类选择")));
        player.openInventory(inv);
        menuSessionMap.put(player.getUniqueId(), new MenuSession(category, page));
    }
    private ItemStack createMenuItem(Material mat, String name, List<String> lore) {
        ItemStack item = new ItemStack(mat);
        ItemMeta meta = item.getItemMeta();
        meta.setDisplayName(name);
        if (lore != null) meta.setLore(lore);
        item.setItemMeta(meta);
        return item;
    }
    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {
        if (!(event.getWhoClicked() instanceof Player)) return;
        Player player = (Player) event.getWhoClicked();
        String title = event.getView().getTitle(); // 修正为通过 InventoryView 获取标题
        if (title == null) return;
        if (title.contains("经验点商店") && title.contains("分类选择")) {
            event.setCancelled(true);
            ItemStack clicked = event.getCurrentItem();
            if (clicked == null || clicked.getType() == Material.AIR) return;
            switch (clicked.getType()) {
                case WHEAT:
                    openShopMenu(player, ShopCategory.CROPS, 0); break;
                case STONE:
                    openShopMenu(player, ShopCategory.BLOCKS, 0); break;
                case IRON_PICKAXE:
                    openShopMenu(player, ShopCategory.TOOLS, 0); break;
                case IRON_CHESTPLATE:
                    openShopMenu(player, ShopCategory.ARMOR, 0); break;
                default: break;
            }
            return;
        }
        for (ShopCategory cat : ShopCategory.values()) {
            if (title.contains(CATEGORY_TITLES.get(cat))) {
                event.setCancelled(true);
                ItemStack clicked = event.getCurrentItem();
                if (clicked == null || clicked.getType() == Material.AIR) return;
                int slot = event.getRawSlot();
                MenuSession session = menuSessionMap.get(player.getUniqueId());
                if (session == null) return;
                int page = session.page;
                List<ShopItem> items = SHOP_ITEMS.get(cat);
                int totalPages = (items.size() - 1) / ITEMS_PER_PAGE + 1;
                if (clicked.getType() == Material.ARROW) {
                    if (clicked.getItemMeta().getDisplayName().contains("上一页") && page > 0) {
                        openShopMenu(player, cat, page - 1);
                    } else if (clicked.getItemMeta().getDisplayName().contains("下一页") && page < totalPages - 1) {
                        openShopMenu(player, cat, page + 1);
                    }
                    return;
                }
                if (clicked.getType() == Material.BARRIER) {
                    openMainMenu(player);
                    return;
                }
                int itemIndex = page * ITEMS_PER_PAGE + (slot - 9);
                if (itemIndex >= 0 && itemIndex < items.size()) {
                    ShopItem si = items.get(itemIndex);
                    if (event.getClick() == ClickType.LEFT) {
                        if (hasItems(player, si.material, si.amount)) {
                            removeItems(player, si.material, si.amount);
                            addExp(player, si.sellExp);
                            player.sendMessage("§a出售成功!获得§e" + si.sellExp + "§a经验点。");
                        } else {
                            player.sendMessage("§c你背包中没有足够的 " + si.name + "!");
                        }
                    } else if (event.getClick() == ClickType.RIGHT) {
                        if (getTotalExp(player) >= si.buyExp) {
                            if (player.getInventory().firstEmpty() != -1) {
                                addExp(player, -si.buyExp);
                                player.getInventory().addItem(new ItemStack(si.material, si.amount));
                                player.sendMessage("§b收购成功!消耗§e" + si.buyExp + "§b经验点,获得 " + si.amount + " 个 " + si.name + "。");
                            } else {
                                player.sendMessage("§c你的背包已满,无法收购!");
                            }
                        } else {
                            player.sendMessage("§c你的经验点不足,无法收购!");
                        }
                    }
                }
                return;
            }
        }
    }
    private static class MenuSession {
        public final ShopCategory category;
        public final int page;
        public MenuSession(ShopCategory category, int page) {
            this.category = category;
            this.page = page;
        }
    }
    private boolean hasItems(Player player, Material mat, int amount) {
        int count = 0;
        for (ItemStack is : player.getInventory().getContents()) {
            if (is != null && is.getType() == mat) count += is.getAmount();
            if (count >= amount) return true;
        }
        return false;
    }
    private void removeItems(Player player, Material mat, int amount) {
        int left = amount;
        ItemStack[] contents = player.getInventory().getContents();
        for (int i = 0; i < contents.length; i++) {
            ItemStack is = contents[i];
            if (is != null && is.getType() == mat) {
                if (is.getAmount() > left) {
                    is.setAmount(is.getAmount() - left);
                    break;
                } else {
                    left -= is.getAmount();
                    contents[i] = null;
                }
            }
            if (left <= 0) break;
        }
        player.getInventory().setContents(contents);
    }
    private int getTotalExp(Player player) {
        return player.getTotalExperience();
    }
    private void addExp(Player player, int exp) {
        int total = getTotalExp(player) + exp;
        if (total < 0) total = 0;
        player.setTotalExperience(total);
    }
}

上一篇: CobbleOreGenerator下一篇: IgnoreChat

举报内容

意见反馈