Files
EssentialsC/src/main/java/cn/infstar/essentialsC/commands/BlocksMenuCommand.java

318 lines
12 KiB
Java

package cn.infstar.essentialsC.commands;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class BlocksMenuCommand extends BaseCommand implements Listener {
private static final int MENU_SIZE = 36;
private static final int[] DIVIDER_SLOTS = {4, 13, 22, 31};
private static boolean listenerRegistered = false;
private final NamespacedKey blockKey;
private static final class BlocksMenuHolder implements InventoryHolder {
private final Inventory inventory;
private BlocksMenuHolder(String title) {
this.inventory = Bukkit.createInventory(this, MENU_SIZE, title);
}
@Override
public Inventory getInventory() {
return inventory;
}
}
public BlocksMenuCommand() {
super("essentialsc.command.blocks");
addConfigDefaults();
if (!listenerRegistered) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
listenerRegistered = true;
}
this.blockKey = new NamespacedKey(plugin, "block_key");
}
@Override
protected boolean execute(Player player, String[] args) {
openMenu(player);
return true;
}
private void openMenu(Player player) {
Inventory menu = new BlocksMenuHolder(getLang().getString("blocks-menu.title")).getInventory();
var sectionsConfig = plugin.getConfig().getConfigurationSection("blocks-menu.sections");
if (sectionsConfig != null) {
int visibleSections = renderSections(menu, player, sectionsConfig);
if (visibleSections > 1) {
renderDivider(menu);
}
if (menu.isEmpty()) {
player.sendMessage(getLang().getPrefixedString("messages.blocks-menu-empty"));
return;
}
player.openInventory(menu);
return;
}
var itemsConfig = plugin.getConfig().getConfigurationSection("blocks-menu.items");
if (itemsConfig == null) {
return;
}
renderItems(menu, player, itemsConfig);
if (menu.isEmpty()) {
player.sendMessage(getLang().getPrefixedString("messages.blocks-menu-empty"));
return;
}
player.openInventory(menu);
}
private int renderSections(Inventory menu, Player player, org.bukkit.configuration.ConfigurationSection sectionsConfig) {
int visibleSections = 0;
for (String sectionKey : sectionsConfig.getKeys(false)) {
var section = sectionsConfig.getConfigurationSection(sectionKey);
if (section == null) {
continue;
}
var itemsConfig = section.getConfigurationSection("items");
if (itemsConfig == null) {
continue;
}
List<MenuItem> visibleItems = collectVisibleItems(player, itemsConfig);
if (visibleItems.isEmpty()) {
continue;
}
visibleSections++;
for (MenuItem item : visibleItems) {
addItem(menu, item);
}
}
return visibleSections;
}
private void renderItems(Inventory menu, Player player, org.bukkit.configuration.ConfigurationSection itemsConfig) {
for (MenuItem item : collectVisibleItems(player, itemsConfig)) {
addItem(menu, item);
}
}
private List<MenuItem> collectVisibleItems(Player player, org.bukkit.configuration.ConfigurationSection itemsConfig) {
List<MenuItem> items = new ArrayList<>();
for (String key : itemsConfig.getKeys(false)) {
var section = itemsConfig.getConfigurationSection(key);
if (section == null) {
continue;
}
String permission = section.getString("permission");
if (permission != null && !permission.isBlank() && !player.hasPermission(permission)) {
continue;
}
String commandKey = section.getString("command", key);
if (!CommandRegistry.isAvailable(commandKey)) {
continue;
}
MenuItem item = createMenuItem(section, commandKey);
if (item != null) {
items.add(item);
}
}
return items;
}
private MenuItem createMenuItem(org.bukkit.configuration.ConfigurationSection section, String commandKey) {
int slot = section.getInt("slot", -1);
if (slot < 0 || slot >= MENU_SIZE) {
return null;
}
Material material = Material.matchMaterial(section.getString("material", "STONE"));
if (material == null) {
material = Material.STONE;
}
String name = getLang().getString("blocks-menu.items." + commandKey + ".name");
List<String> lore = getLang().getStringList("blocks-menu.items." + commandKey + ".lore");
return new MenuItem(slot, material, name, lore, commandKey);
}
private void addItem(Inventory inventory, MenuItem menuItem) {
ItemStack item = new ItemStack(menuItem.material());
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(menuItem.name());
meta.setLore(menuItem.lore().isEmpty() ? null : menuItem.lore());
if (menuItem.commandKey() != null && !menuItem.commandKey().isBlank()) {
meta.getPersistentDataContainer().set(blockKey, PersistentDataType.STRING, menuItem.commandKey());
}
item.setItemMeta(meta);
}
inventory.setItem(menuItem.slot(), item);
}
private void renderDivider(Inventory inventory) {
ItemStack divider = new ItemStack(Material.GRAY_STAINED_GLASS_PANE);
ItemMeta meta = divider.getItemMeta();
if (meta != null) {
meta.setDisplayName(" ");
divider.setItemMeta(meta);
}
for (int slot : DIVIDER_SLOTS) {
if (inventory.getItem(slot) == null) {
inventory.setItem(slot, divider);
}
}
}
@EventHandler
public void onMenuClick(InventoryClickEvent event) {
if (!(event.getView().getTopInventory().getHolder(false) instanceof BlocksMenuHolder)) {
return;
}
event.setCancelled(true);
if (!(event.getWhoClicked() instanceof Player player)) {
return;
}
if (event.getClickedInventory() != event.getView().getTopInventory()) {
return;
}
ItemStack clicked = event.getCurrentItem();
if (clicked == null || !clicked.hasItemMeta()) {
return;
}
ItemMeta meta = clicked.getItemMeta();
String key = meta.getPersistentDataContainer().get(blockKey, PersistentDataType.STRING);
if (key == null || key.isBlank()) {
return;
}
BaseCommand blockCommand = CommandRegistry.getCommand(key);
if (blockCommand == null) {
return;
}
String permission = blockCommand.getPermission();
if (permission != null && !permission.isBlank() && !player.hasPermission(permission)) {
player.sendMessage(getLang().getPrefixedString("messages.no-permission",
Map.of("permission", permission)));
return;
}
blockCommand.execute(player, new String[0]);
}
@EventHandler
public void onMenuDrag(InventoryDragEvent event) {
if (!(event.getView().getTopInventory().getHolder(false) instanceof BlocksMenuHolder)) {
return;
}
int topSize = event.getView().getTopInventory().getSize();
for (int rawSlot : event.getRawSlots()) {
if (rawSlot >= 0 && rawSlot < topSize) {
event.setCancelled(true);
return;
}
}
}
private String translateColor(String text) {
return text == null ? "" : ChatColor.translateAlternateColorCodes('&', text);
}
private void addConfigDefaults() {
plugin.getConfig().addDefault("blocks-menu.layout-version", 2);
addMenuItemDefaults("blocks-menu.sections.blocks.items.workbench", 10, "CRAFTING_TABLE",
"essentialsc.command.workbench", "workbench");
addMenuItemDefaults("blocks-menu.sections.blocks.items.enderchest", 11, "ENDER_CHEST",
"essentialsc.command.enderchest", "enderchest");
addMenuItemDefaults("blocks-menu.sections.blocks.items.anvil", 12, "ANVIL",
"essentialsc.command.anvil", "anvil");
addMenuItemDefaults("blocks-menu.sections.blocks.items.grindstone", 19, "GRINDSTONE",
"essentialsc.command.grindstone", "grindstone");
addMenuItemDefaults("blocks-menu.sections.blocks.items.smithingtable", 20, "SMITHING_TABLE",
"essentialsc.command.smithingtable", "smithingtable");
addMenuItemDefaults("blocks-menu.sections.blocks.items.stonecutter", 21, "STONECUTTER",
"essentialsc.command.stonecutter", "stonecutter");
addMenuItemDefaults("blocks-menu.sections.blocks.items.loom", 28, "LOOM",
"essentialsc.command.loom", "loom");
addMenuItemDefaults("blocks-menu.sections.blocks.items.cartographytable", 29, "CARTOGRAPHY_TABLE",
"essentialsc.command.cartographytable", "cartographytable");
addMenuItemDefaults("blocks-menu.sections.shortcuts.items.nightvision", 14, "TINTED_GLASS",
"essentialsc.command.nightvision", "nightvision");
addMenuItemDefaults("blocks-menu.sections.shortcuts.items.glow", 15, "GLOWSTONE",
"essentialsc.command.glow", "glow");
plugin.getConfig().options().copyDefaults(true);
migrateLayoutIfNeeded();
plugin.saveConfig();
}
private void migrateLayoutIfNeeded() {
boolean hasStoredLayoutVersion = plugin.getConfig().contains("blocks-menu.layout-version", true);
if (hasStoredLayoutVersion && plugin.getConfig().getInt("blocks-menu.layout-version", 0) >= 2) {
return;
}
applySlot("blocks", "workbench", 10);
applySlot("blocks", "enderchest", 11);
applySlot("blocks", "anvil", 12);
applySlot("blocks", "grindstone", 19);
applySlot("blocks", "smithingtable", 20);
applySlot("blocks", "stonecutter", 21);
applySlot("blocks", "loom", 28);
applySlot("blocks", "cartographytable", 29);
applySlot("shortcuts", "nightvision", 14);
applySlot("shortcuts", "glow", 15);
plugin.getConfig().set("blocks-menu.sections.blocks.title-item", null);
plugin.getConfig().set("blocks-menu.sections.shortcuts.title-item", null);
plugin.getConfig().set("blocks-menu.layout-version", 2);
}
private void applySlot(String section, String key, int slot) {
plugin.getConfig().set("blocks-menu.sections." + section + ".items." + key + ".slot", slot);
}
private void addMenuItemDefaults(String path, int slot, String material, String permission, String command) {
plugin.getConfig().addDefault(path + ".slot", slot);
plugin.getConfig().addDefault(path + ".material", material);
plugin.getConfig().addDefault(path + ".permission", permission);
plugin.getConfig().addDefault(path + ".command", command);
}
private record MenuItem(int slot, Material material, String name, List<String> lore, String commandKey) {
}
}