diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java b/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java index 6874f262..d98855a8 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPerm.java @@ -7,6 +7,8 @@ import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.zcore.fperms.Access; import com.massivecraft.factions.zcore.fperms.Permissable; import com.massivecraft.factions.zcore.fperms.PermissableAction; +import com.massivecraft.factions.zcore.fperms.gui.PermissableActionGUI; +import com.massivecraft.factions.zcore.fperms.gui.PermissableRelationGUI; import com.massivecraft.factions.zcore.util.TL; import java.util.*; @@ -36,9 +38,10 @@ public class CmdPerm extends FCommand { @Override public void perform() { if (args.size() == 0) { - for (String s : getLines()) { - msg(s); - } + me.openInventory(new PermissableRelationGUI(fme).getInventory()); + return; + } else if (args.size() == 1 && getPermissable(argAsString(0)) != null) { + me.openInventory(new PermissableActionGUI(fme, getPermissable(argAsString(0))).getInventory()); return; } @@ -109,35 +112,6 @@ public class CmdPerm extends FCommand { return null; } - private List getLines() { - List lines = new ArrayList<>(); - - lines.add(TL.COMMAND_PERM_TOP.toString()); - - for (PermissableAction action : PermissableAction.values()) { - StringBuilder sb = new StringBuilder(); - sb.append(action.getName()).append(" "); - - // Roles except admin - for (Role role : Role.values()) { - if (role != Role.ADMIN) { - sb.append(myFaction.getAccess(role, action).getName()).append(" "); - } - } - - // Relations except Member - for (Relation relation : Relation.values()) { - if (relation != Relation.MEMBER) { - sb.append(myFaction.getAccess(relation, action).getName()).append(" "); - } - } - - lines.add(sb.toString().trim()); - } - - return lines; - } - @Override public TL getUsageTranslation() { return TL.COMMAND_PERM_DESCRIPTION; diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java index f6829b7a..455950de 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -12,6 +12,7 @@ import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.util.VisualizeUtil; import com.massivecraft.factions.zcore.fperms.Access; import com.massivecraft.factions.zcore.fperms.PermissableAction; +import com.massivecraft.factions.zcore.fperms.gui.PermissionGUI; import com.massivecraft.factions.zcore.persist.MemoryFPlayer; import com.massivecraft.factions.zcore.util.TL; import com.massivecraft.factions.zcore.util.TextUtil; @@ -24,6 +25,8 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.player.*; import org.bukkit.util.NumberConversions; @@ -601,6 +604,25 @@ public class FactionsPlayerListener implements Listener { return false; } + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerInteractGUI(InventoryClickEvent event) { + if (event.getClickedInventory() == null) { + return; + } + if (event.getClickedInventory().getHolder() instanceof PermissionGUI) { + event.setCancelled(true); + ((PermissionGUI) event.getClickedInventory().getHolder()).onClick(event.getRawSlot(), event.getClick()); + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerMoveGUI(InventoryDragEvent event) { + if (event.getInventory().getHolder() instanceof PermissionGUI) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onPlayerKick(PlayerKickEvent event) { FPlayer badGuy = FPlayers.getInstance().getByPlayer(event.getPlayer()); diff --git a/src/main/java/com/massivecraft/factions/struct/Relation.java b/src/main/java/com/massivecraft/factions/struct/Relation.java index 2332bb58..b37081d1 100644 --- a/src/main/java/com/massivecraft/factions/struct/Relation.java +++ b/src/main/java/com/massivecraft/factions/struct/Relation.java @@ -1,9 +1,17 @@ package com.massivecraft.factions.struct; import com.massivecraft.factions.Conf; +import com.massivecraft.factions.P; import com.massivecraft.factions.zcore.fperms.Permissable; import com.massivecraft.factions.zcore.util.TL; import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; public enum Relation implements Permissable { @@ -21,11 +29,6 @@ public enum Relation implements Permissable { this.nicename = nicename; } - @Override - public String toString() { - return this.nicename; - } - public static Relation fromString(String s) { // Because Java 6 doesn't allow String switches :( if (s.equalsIgnoreCase(MEMBER.nicename)) { @@ -41,6 +44,11 @@ public enum Relation implements Permissable { } } + @Override + public String toString() { + return this.nicename; + } + public String getTranslation() { try { return TL.valueOf("RELATION_" + name() + "_SINGULAR").toString(); @@ -184,4 +192,42 @@ public enum Relation implements Permissable { return Conf.econCostNeutral; } } + + // Utility method to build items for F Perm GUI + @Override + public ItemStack buildItem() { + final ConfigurationSection RELATION_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.relation"); + + String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); + List lore = new ArrayList<>(); + + Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase())); + if (material == null) { + return null; + } + + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); + + for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine)); + } + + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); + + return item; + } + + public String replacePlaceholders(String string) { + string = ChatColor.translateAlternateColorCodes('&', string); + + String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); + + string = string.replace("{relation-color}", getColor().toString()); + string = string.replace("{relation}", permissableName); + + return string; + } } diff --git a/src/main/java/com/massivecraft/factions/struct/Role.java b/src/main/java/com/massivecraft/factions/struct/Role.java index dfe0a7b8..f2875a8c 100644 --- a/src/main/java/com/massivecraft/factions/struct/Role.java +++ b/src/main/java/com/massivecraft/factions/struct/Role.java @@ -1,8 +1,17 @@ package com.massivecraft.factions.struct; import com.massivecraft.factions.Conf; +import com.massivecraft.factions.P; import com.massivecraft.factions.zcore.fperms.Permissable; import com.massivecraft.factions.zcore.util.TL; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; public enum Role implements Permissable { ADMIN(3, TL.ROLE_ADMIN), @@ -13,6 +22,8 @@ public enum Role implements Permissable { public final int value; public final String nicename; public final TL translation; + private final ConfigurationSection RELATION_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.relation"); + Role(final int value, final TL translation) { this.value = value; @@ -93,4 +104,44 @@ public enum Role implements Permissable { return ""; } + + + // Utility method to build items for F Perm GUI + @Override + public ItemStack buildItem() { + final ConfigurationSection RELATION_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.relation"); + + String displayName = replacePlaceholders(RELATION_CONFIG.getString("placeholder-item.name", "")); + List lore = new ArrayList<>(); + + Material material = Material.matchMaterial(RELATION_CONFIG.getString("materials." + name().toLowerCase())); + if (material == null) { + return null; + } + + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); + + for (String loreLine : RELATION_CONFIG.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholders(loreLine)); + } + + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); + + return item; + } + + public String replacePlaceholders(String string) { + string = ChatColor.translateAlternateColorCodes('&', string); + + String permissableName = nicename.substring(0, 1).toUpperCase() + nicename.substring(1); + + string = string.replace("{relation-color}", ChatColor.GREEN.toString()); + string = string.replace("{relation}", permissableName); + + return string; + } + } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java b/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java index 62e5b652..48b4370a 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/Access.java @@ -3,14 +3,16 @@ package com.massivecraft.factions.zcore.fperms; import org.bukkit.ChatColor; public enum Access { - ALLOW("&aALLOW"), - DENY("&4DENY"), - UNDEFINED("&7UND"); + ALLOW("Allow", ChatColor.GREEN), + DENY("Deny", ChatColor.DARK_RED), + UNDEFINED("Undefined", ChatColor.GRAY); private String name; + private ChatColor color; - Access(String name) { + Access(String name, ChatColor color) { this.name = name; + this.color = color; } /** @@ -30,12 +32,16 @@ public enum Access { } public String getName() { - return ChatColor.translateAlternateColorCodes('&', this.name); + return this.name; } + public ChatColor getColor() { + return color; + } @Override public String toString() { return name(); } + } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java b/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java index 44e2ce93..ea7a4c37 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/Permissable.java @@ -1,4 +1,13 @@ package com.massivecraft.factions.zcore.fperms; +import org.bukkit.inventory.ItemStack; + public interface Permissable { + + public ItemStack buildItem(); + + public String replacePlaceholders(String string); + + public String name(); + } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java index 7c3f357c..a451e01e 100644 --- a/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/PermissableAction.java @@ -1,5 +1,16 @@ package com.massivecraft.factions.zcore.fperms; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.P; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; + public enum PermissableAction { BAN("ban"), BUILD("build"), @@ -58,4 +69,65 @@ public enum PermissableAction { public String toString() { return name; } + + // Utility method to build items for F Perm GUI + public ItemStack buildItem(FPlayer fme, Permissable permissable) { + final ConfigurationSection ACTION_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.action"); + + String displayName = replacePlaceholers(ACTION_CONFIG.getString("placeholder-item.name"), fme, permissable); + List lore = new ArrayList<>(); + + if (ACTION_CONFIG.getString("materials." + name().toLowerCase().replace('_', '-')) == null) { + return null; + } + Material material = Material.matchMaterial(ACTION_CONFIG.getString("materials." + name().toLowerCase().replace('_', '-'))); + if (material == null) { + material = Material.STAINED_CLAY; + } + + Access access = fme.getFaction().getAccess(permissable, this); + if (access == null) { + access = Access.UNDEFINED; + } + DyeColor dyeColor = null; + try { + dyeColor = DyeColor.valueOf(ACTION_CONFIG.getString("access." + access.name().toLowerCase())); + } catch (Exception exception) {} + + ItemStack item = new ItemStack(material); + ItemMeta itemMeta = item.getItemMeta(); + + if (dyeColor != null) { + item.setDurability(dyeColor.getWoolData()); + } + + for (String loreLine : ACTION_CONFIG.getStringList("placeholder-item.lore")) { + lore.add(replacePlaceholers(loreLine, fme, permissable)); + } + + itemMeta.setDisplayName(displayName); + itemMeta.setLore(lore); + item.setItemMeta(itemMeta); + + return item; + } + + public String replacePlaceholers(String string, FPlayer fme, Permissable permissable) { + // Run Permissable placeholders + string = permissable.replacePlaceholders(string); + + String actionName = name.substring(0, 1).toUpperCase() + name.substring(1); + string = string.replace("{action}", actionName); + + Access access = fme.getFaction().getAccess(permissable, this); + if (access == null) { + access = Access.UNDEFINED; + } + String actionAccess = access.getName(); + string = string.replace("{action-access}", actionAccess); + string = string.replace("{action-access-color}", access.getColor().toString()); + + return string; + } + } diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java new file mode 100644 index 00000000..982c313d --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableActionGUI.java @@ -0,0 +1,244 @@ +package com.massivecraft.factions.zcore.fperms.gui; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.P; +import com.massivecraft.factions.zcore.fperms.Access; +import com.massivecraft.factions.zcore.fperms.Permissable; +import com.massivecraft.factions.zcore.fperms.PermissableAction; +import com.massivecraft.factions.zcore.util.TL; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.*; +import java.util.logging.Level; + +public class PermissableActionGUI implements InventoryHolder, PermissionGUI { + + private Inventory actionGUI; + private FPlayer fme; + + private int guiSize; + + private Permissable permissable; + + private HashMap actionSlots = new HashMap<>(); + private HashMap specialSlots = new HashMap<>(); + private ArrayList usedDummySlots = new ArrayList<>(); + + private final ConfigurationSection ACTION_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.action"); + + public PermissableActionGUI(FPlayer fme, Permissable permissable) { + this.fme = fme; + this.permissable = permissable; + + guiSize = ACTION_CONFIG.getInt("rows", 3); + if (guiSize > 5) { + guiSize = 5; + P.p.log(Level.INFO, "Action GUI size out of bounds, defaulting to 5"); + } + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', ACTION_CONFIG.getString("name", "FactionPerms")); + actionGUI = Bukkit.createInventory(this, guiSize, guiName); + + for (String key : ACTION_CONFIG.getConfigurationSection("slots").getKeys(false)) { + int slot = ACTION_CONFIG.getInt("slots." + key); + if (slot + 1 > guiSize || slot < 0) { + P.p.log(Level.WARNING, "Invalid slot for: " + key.toUpperCase()); + continue; + } + + if (SpecialItem.isSpecial(key)) { + specialSlots.put(slot, SpecialItem.fromString(key)); + continue; + } + + PermissableAction permissableAction = PermissableAction.fromString(key.toUpperCase().replace('-', '_')); + if (permissableAction == null) { + P.p.log(Level.WARNING, "Invalid permissable action: " + key.toUpperCase()); + continue; + } + + actionSlots.put(ACTION_CONFIG.getInt("slots." + key), permissableAction); + } + + buildDummyItems(); + + if (actionSlots.values().toArray().length != PermissableAction.values().length) { + // Missing actions add them forcefully to the GUI and log error + Set missingActions = new HashSet<>(Arrays.asList(PermissableAction.values())); + missingActions.removeAll(actionSlots.values()); + + for (PermissableAction action : missingActions) { + if (!usedDummySlots.isEmpty()) { + int slot = usedDummySlots.get(0); + actionSlots.put(slot, action); + } else { + int slot = actionGUI.firstEmpty(); + if (slot != -1) { + actionSlots.put(slot, action); + } + } + P.p.log(Level.WARNING, "Missing action: " + action.name()); + } + + } + + buildSpecialItems(); + buildItems(); + } + + @Override + public Inventory getInventory() { + return actionGUI; + } + + @Override + public void onClick(int slot, ClickType click) { + if (specialSlots.containsKey(slot)) { + if (specialSlots.get(slot) == SpecialItem.BACK) { + fme.getPlayer().openInventory(new PermissableRelationGUI(fme).getInventory()); + } + return; + } + if (!actionSlots.containsKey(slot)) { + return; + } + + PermissableAction action = actionSlots.get(slot); + Access access; + if (click == ClickType.LEFT) { + access = Access.ALLOW; + fme.getFaction().setPermission(permissable, action, access); + } else if (click == ClickType.RIGHT) { + access = Access.DENY; + fme.getFaction().setPermission(permissable, action, access); + } else if (click == ClickType.MIDDLE) { + access = Access.UNDEFINED; + fme.getFaction().setPermission(permissable, action, access); + } else { + return; + } + + actionGUI.setItem(slot, action.buildItem(fme, permissable)); + fme.msg(TL.COMMAND_PERM_SET, action.name(), access.name(), permissable.name()); + P.p.log(String.format(TL.COMMAND_PERM_SET.toString(), action.name(), access.name(), permissable.name()) + " for faction " + fme.getTag()); + } + + private void buildItems() { + for (Map.Entry entry : actionSlots.entrySet()) { + PermissableAction permissableAction = entry.getValue(); + + ItemStack item = permissableAction.buildItem(fme, permissable); + + if (item == null) { + P.p.log(Level.WARNING, "Invalid item for: " + permissableAction.toString().toUpperCase()); + continue; + } + + actionGUI.setItem(entry.getKey(), item); + } + } + + private void buildSpecialItems() { + for (Map.Entry entry : specialSlots.entrySet()) { + actionGUI.setItem(entry.getKey(), getSpecialItem(entry.getValue())); + } + } + + private ItemStack getSpecialItem(SpecialItem specialItem) { + switch (specialItem) { + case RELATION: + return permissable.buildItem(); + case BACK: + ConfigurationSection backButtonConfig = P.p.getConfig().getConfigurationSection("fperm-gui.back-item"); + + ItemStack backButton = new ItemStack(Material.matchMaterial(backButtonConfig.getString("material"))); + ItemMeta backButtonMeta = backButton.getItemMeta(); + + backButtonMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', backButtonConfig.getString("name"))); + List lore = new ArrayList<>(); + for (String loreLine : backButtonConfig.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } + backButtonMeta.setLore(lore); + + backButton.setItemMeta(backButtonMeta); + + return backButton; + default: + return null; + } + } + + private void buildDummyItems() { + for (String key : ACTION_CONFIG.getConfigurationSection("dummy-items").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + P.p.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } + + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } + + List dummySlots = ACTION_CONFIG.getIntegerList("dummy-items." + key); + for (Integer slot : dummySlots) { + if (slot+1 > guiSize || slot < 0) { + P.p.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + usedDummySlots.add(slot); + actionGUI.setItem(slot, dummyItem); + } + } + } + + private ItemStack buildDummyItem(int id) { + final ConfigurationSection DUMMY_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); + + Material material = Material.matchMaterial(DUMMY_CONFIG.getString("material", "")); + if (material == null) { + P.p.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } + + ItemStack itemStack = new ItemStack(material); + + DyeColor color; + try { + color = DyeColor.valueOf(DUMMY_CONFIG.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } + + ItemMeta itemMeta = itemStack.getItemMeta(); + + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', DUMMY_CONFIG.getString("name", " "))); + + List lore = new ArrayList<>(); + for (String loreLine : DUMMY_CONFIG.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } + itemMeta.setLore(lore); + + itemStack.setItemMeta(itemMeta); + + return itemStack; + } + +} diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java new file mode 100644 index 00000000..55ded11a --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissableRelationGUI.java @@ -0,0 +1,173 @@ +package com.massivecraft.factions.zcore.fperms.gui; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.P; +import com.massivecraft.factions.struct.Relation; +import com.massivecraft.factions.struct.Role; +import com.massivecraft.factions.zcore.fperms.Permissable; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +public class PermissableRelationGUI implements InventoryHolder, PermissionGUI { + + private Inventory relationGUI; + private FPlayer fme; + + private int guiSize; + + private HashMap relationSlots = new HashMap<>(); + + private final ConfigurationSection RELATION_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.relation"); + + + public PermissableRelationGUI(FPlayer fme) { + this.fme = fme; + + // Build basic Inventory info + guiSize = RELATION_CONFIG.getInt("rows", 3); + if (guiSize > 5) { + guiSize = 5; + P.p.log(Level.INFO, "Relation GUI size out of bounds, defaulting to 5"); + } + guiSize *= 9; + String guiName = ChatColor.translateAlternateColorCodes('&', RELATION_CONFIG.getString("name", "FactionPermissions")); + relationGUI = Bukkit.createInventory(this, guiSize, guiName); + + for (String key : RELATION_CONFIG.getConfigurationSection("slots").getKeys(false)) { + int slot = RELATION_CONFIG.getInt("slots." + key); + if (slot + 1 > guiSize && slot > 0) { + P.p.log(Level.WARNING, "Invalid slot of " + key.toUpperCase() + " in relation GUI skipping it"); + continue; + } + + if (getPermissable(key) == null) { + P.p.log(Level.WARNING, "Invalid permissable " + key.toUpperCase() + " skipping it"); + continue; + } + + relationSlots.put(slot, getPermissable(key)); + } + + buildDummyItems(); + buildItems(); + } + + @Override + public Inventory getInventory() { + return relationGUI; + } + + @Override + public void onClick(int slot, ClickType clickType) { + if (!relationSlots.containsKey(slot)) { + return; + } + + fme.getPlayer().openInventory(new PermissableActionGUI(fme, relationSlots.get(slot)).getInventory()); + } + + private Permissable getPermissable(String name) { + try { + return Relation.valueOf(name.toUpperCase()); + } catch (Exception e) { + } + try { + return Role.valueOf(name.toUpperCase()); + } catch (Exception e) { + } + + return null; + } + + private void buildItems() { + for (Map.Entry entry : relationSlots.entrySet()) { + Permissable permissable = entry.getValue(); + + ItemStack item = permissable.buildItem(); + + if (item == null) { + P.p.log(Level.WARNING, "Invalid material for " + permissable.toString().toUpperCase() + " skipping it"); + continue; + } + + relationGUI.setItem(entry.getKey(), item); + } + } + + private void buildDummyItems() { + for (String key : RELATION_CONFIG.getConfigurationSection("dummy-items").getKeys(false)) { + int dummyId; + try { + dummyId = Integer.parseInt(key); + } catch (NumberFormatException exception) { + P.p.log(Level.WARNING, "Invalid dummy item id: " + key.toUpperCase()); + continue; + } + + ItemStack dummyItem = buildDummyItem(dummyId); + if (dummyItem == null) { + continue; + } + + List dummySlots = RELATION_CONFIG.getIntegerList("dummy-items." + key); + for (Integer slot : dummySlots) { + if (slot+1 > guiSize || slot < 0) { + P.p.log(Level.WARNING, "Invalid slot: " + slot + " for dummy item: " + key); + continue; + } + relationGUI.setItem(slot, dummyItem); + } + } + } + + private ItemStack buildDummyItem(int id) { + final ConfigurationSection DUMMY_CONFIG = P.p.getConfig().getConfigurationSection("fperm-gui.dummy-items." + id); + + Material material = Material.matchMaterial(DUMMY_CONFIG.getString("material", "")); + if (material == null) { + P.p.log(Level.WARNING, "Invalid material for dummy item: " + id); + return null; + } + + ItemStack itemStack = new ItemStack(material); + + DyeColor color; + try { + color = DyeColor.valueOf(DUMMY_CONFIG.getString("color", "")); + } catch (Exception exception) { + color = null; + } + if (color != null) { + itemStack.setDurability(color.getWoolData()); + } + + ItemMeta itemMeta = itemStack.getItemMeta(); + + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', DUMMY_CONFIG.getString("name", " "))); + + List lore = new ArrayList<>(); + for (String loreLine : DUMMY_CONFIG.getStringList("lore")) { + lore.add(ChatColor.translateAlternateColorCodes('&', loreLine)); + } + itemMeta.setLore(lore); + + itemStack.setItemMeta(itemMeta); + + return itemStack; + } + +} diff --git a/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissionGUI.java b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissionGUI.java new file mode 100644 index 00000000..82474b8d --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/fperms/gui/PermissionGUI.java @@ -0,0 +1,28 @@ +package com.massivecraft.factions.zcore.fperms.gui; + +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryAction; + +public interface PermissionGUI { + + public void onClick(int slot, ClickType action); + + public enum SpecialItem { + BACK, + RELATION; + + static boolean isSpecial(String string) { + return fromString(string) != null; + } + + static SpecialItem fromString(String string) { + for (SpecialItem specialItem : SpecialItem.values()) { + if (string.equalsIgnoreCase(specialItem.name())) { + return specialItem; + } + } + return null; + } + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ed0a90e1..db179482 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -333,6 +333,192 @@ help: - '&3/f version &e>> &7Display version information' - '&e&m--------------&r&2 End of /f help &e&m-----------------' +############################################################ +# +------------------------------------------------------+ # +# | F Permission GUI | # +# +------------------------------------------------------+ # +############################################################ + +# This is the Faction permissions GUI, it consists of 2 inventories +# +# 1st: The Relation GUI, here you choose which relation you want to set the permission of +# 2nd: The Action GUI, here you define the permission of the clicked Action using click types, +# depending on the click type it will set the permission differently: +# Left Click: ALLOW +# Middle Click: UNDEFINED +# Right Click: DENY +# +# +# The GUI configuration is based off of item placeholders these have specific placeholders that are +# replaced, for example {relation} will be replaced with the relation that the GUI/Item is based on. +# There is also 2 other types of GUI items +# +# 1st: Special items, these include Back button (Has its own item below), and Relation Item +# indicating the current relation (Uses relation item placeholder) +# 2nd: Dummy items, these items server no other purpose than to look good, they have their own +# items defined in dummy items, and can later be assigned to specific slots in the GUI's +fperm-gui: + relation: + # GUI Name + name: 'Factions Permissions' + # Amount of inventory rows, No larger than 5 + rows: 3 + + # These are the slots where the relations are going to be placed on the first GUI + # Note: Slots start at 0 and end at one less that GUI size + slots: + recruit: 10 + member: 11 + moderator: 12 + truce: 13 + ally: 14 + enemy: 15 + neutral: 16 + # Material to be displayed + materials: + recruit: WOOD_SWORD + member: STONE_SWORD + moderator: IRON_SWORD + truce: IRON_AXE + ally: DIAMOND_SWORD + enemy: DIAMOND_AXE + neutral: STONE + # Dummy items using the Items lower down + dummy-items: + '0': + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 17 + - 18 + - 19 + - 20 + - 21 + - 22 + - 23 + - 24 + - 25 + - 26 + # This is the item that all relation items are based off of + # Replacing {relation} with relation name eg: Moderator, Ally + # also replaces {relation-color} with relation color eg: Enemy;RED + placeholder-item: + name: '&8[{relation-color}{relation}&8]' + lore: + - + action: + name: 'Factions Permissions' + rows: 4 + # If this field exists colorable materials will be updated + # https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/DyeColor.html + access: + allow: LIME + deny: RED + undefined: CYAN + slots: + # Uses same format as above to inform the player of clicked relation + relation: 4 + # Back button slot + back: 0 + + # Start action slots + build: 9 + destroy: 10 + frost-walk: 11 + pain-build: 12 + door: 13 + button: 14 + lever: 15 + container: 16 + invite: 17 + kick: 18 + item: 19 + sethome: 20 + withdraw: 21 + territory: 22 + access: 23 + promote: 24 + setwarp: 25 + warp: 26 + ban: 27 + disband: 28 + perms: 29 + # Material to show, if the material is colorable eg: Wool, Stained Clay it will update with it's access color + materials: + build: STAINED_CLAY + destroy: STAINED_CLAY + frost-walk: STAINED_CLAY + pain-build: STAINED_CLAY + door: STAINED_CLAY + button: STAINED_CLAY + lever: STAINED_CLAY + container: STAINED_CLAY + invite: STAINED_CLAY + kick: STAINED_CLAY + item: STAINED_CLAY + sethome: STAINED_CLAY + withdraw: STAINED_CLAY + territory: STAINED_CLAY + access: STAINED_CLAY + promote: STAINED_CLAY + setwarp: STAINED_CLAY + warp: STAINED_CLAY + ban: STAINED_CLAY + disband: STAINED_CLAY + perms: STAINED_CLAY + # Same dummy items format as above + dummy-items: + '0': + - 1 + - 2 + - 3 + - 5 + - 6 + - 7 + - 8 + - 29 + - 30 + - 31 + - 32 + - 33 + - 34 + - 35 + # {action} Action name eg: Setwarp, Kick + # {action-access} Access name eg: Allow, Deny + # {action-access-color} Access color eg: Allow;GREEN + placeholder-item: + name: '&8[&7{action}&8]' + lore: + - '&8Access:' + - '&8[{action-access-color}{action-access}&8]' + - '' + - '&8Left click to &lAllow' + - '&8Right click to &lDeny' + - '&8Middle click to &lUndefine' + # Back item will be take you to the previous GUI + back-item: + name: '&8&lBack' + material: ARROW + lore: + - '&7Back button' + # Dummy Items + dummy-items: + # Dummy Item id, used to set the slots above + '0': + material: STAINED_GLASS_PANE + # Color will only work on colorable materials + color: BLACK + name: ' ' + lore: + - + ############################################################ # +------------------------------------------------------+ # # | Big List of variables | # @@ -374,6 +560,12 @@ help: # - {faction-kills} : # of kills the faction has # - {faction-deaths}: # of deaths the faction has # - {faction-bancount} : # of bans the faction has +# Faction Permissions GUI variables. Can only be used in GUI +# - {relation} : Shows relation name (Can be used in action and relation) +# - {relation-color} : Relation color +# - {action} : Shows action name (Can only be used in action) +# - {action-access} : Shows the action's access with current relation +# - {action-access-color} : Access color # General variables. Can be used anywhere. # - {total-online} : Total # of players on the server # - {max-warps} : Max # of warps a faction can set