diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/MainConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java similarity index 87% rename from src/main/java/xyz/alexcrea/cuanvil/gui/config/global/MainConfigGui.java rename to src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java index a69cc7a..d466a75 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/MainConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java @@ -1,4 +1,4 @@ -package xyz.alexcrea.cuanvil.gui.config.global; +package xyz.alexcrea.cuanvil.gui.config; import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; @@ -8,6 +8,7 @@ import io.delilaheve.CustomAnvil; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import xyz.alexcrea.cuanvil.gui.config.global.*; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; @@ -87,11 +88,20 @@ public class MainConfigGui extends ChestGui { wipMeta.setDisplayName("\u00A7cWIP"); wipItemstack.setItemMeta(wipMeta); - GuiItem wip5 = new GuiItem(wipItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - GuiItem wip6 = new GuiItem(wipItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance); + GuiItem wip = new GuiItem(wipItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance); - pane.bindItem('5', wip5); - pane.bindItem('6', wip6); + pane.bindItem('5', wip); + + // Unit repair item + ItemStack unirRepairItemstack = new ItemStack(Material.DIAMOND); + ItemMeta unitRepairMeta = unirRepairItemstack.getItemMeta(); + + unitRepairMeta.setDisplayName("\u00A7aUnit Repair"); + unitRepairMeta.setLore(Collections.singletonList("\u00A77Click here to open anvil custom recipe menu")); + unirRepairItemstack.setItemMeta(unitRepairMeta); + + GuiItem unitRepairItem = GuiGlobalItems.goToGuiItem(unirRepairItemstack, UnitRepairConfigGui.INSTANCE); + pane.bindItem('6', unitRepairItem); // Custom recipe item ItemStack customRecipeItemstack = new ItemStack(Material.CRAFTING_TABLE); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java new file mode 100644 index 0000000..66dd936 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java @@ -0,0 +1,42 @@ +package xyz.alexcrea.cuanvil.gui.config.ask; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; +import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; +import com.github.stefvanschie.inventoryframework.pane.PatternPane; +import com.github.stefvanschie.inventoryframework.pane.util.Pattern; +import io.delilaheve.CustomAnvil; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; +import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; + +public abstract class AbstractAskGui extends ChestGui { + + protected PatternPane pane; + AbstractAskGui(int rows, @NotNull String name, + Gui backOnCancel){ + super(rows, name, CustomAnvil.instance); + + Pattern pattern = getGuiPattern(); + this.pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern); + addPane(this.pane); + + this.pane.bindItem('0', GuiGlobalItems.backgroundItem()); + this.pane.bindItem('B', new GuiItem(GuiSharedConstant.CANCEL_ITEM, GuiGlobalActions.openGuiAction(backOnCancel), CustomAnvil.instance)); + + } + + /** + * Used to get the gui pattern. + * Reserved character are: + * + * + * @return The gui's pattern. + */ + protected abstract Pattern getGuiPattern(); + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ConfirmActionGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java similarity index 58% rename from src/main/java/xyz/alexcrea/cuanvil/gui/config/ConfirmActionGui.java rename to src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java index 96f08c9..5b962ed 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ConfirmActionGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java @@ -1,9 +1,7 @@ -package xyz.alexcrea.cuanvil.gui.config; +package xyz.alexcrea.cuanvil.gui.config.ask; import com.github.stefvanschie.inventoryframework.gui.GuiItem; -import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; -import com.github.stefvanschie.inventoryframework.pane.PatternPane; import com.github.stefvanschie.inventoryframework.pane.util.Pattern; import io.delilaheve.CustomAnvil; import org.bukkit.Material; @@ -12,50 +10,20 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import java.util.Arrays; -import java.util.Collections; import java.util.function.Supplier; import java.util.logging.Level; -public class ConfirmActionGui extends ChestGui { - - private static final ItemStack CANCEL_ITEM; - private static final ItemStack CONFIRM_ITEM; - - static { - CANCEL_ITEM = new ItemStack(Material.RED_TERRACOTTA); - ItemMeta meta = CANCEL_ITEM.getItemMeta(); - meta.setDisplayName("\u00A7cCancel"); - meta.setLore(Collections.singletonList("\u00A77Cancel current action and return to previous menu.")); - CANCEL_ITEM.setItemMeta(meta); - - CONFIRM_ITEM = new ItemStack(Material.GREEN_TERRACOTTA); - meta = CONFIRM_ITEM.getItemMeta(); - meta.setDisplayName("\u00A7aConfirm"); - meta.setLore(Arrays.asList("\u00A77Confirm current action.", - "\u00A74Cation: This action can't be canceled.")); - CONFIRM_ITEM.setItemMeta(meta); - } +public class ConfirmActionGui extends AbstractAskGui { public ConfirmActionGui(@NotNull String title, String actionDescription, Gui backOnCancel, Gui backOnConfirm, Supplier onConfirm) { - super(3, title, CustomAnvil.instance); + super(3, title, backOnCancel); - Pattern pattern = new Pattern( - GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "00B0I0S00", - GuiSharedConstant.EMPTY_GUI_FULL_LINE - ); - PatternPane pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern); - addPane(pane); - - pane.bindItem('0', GuiGlobalItems.backgroundItem()); - - pane.bindItem('B', new GuiItem(CANCEL_ITEM, GuiGlobalActions.openGuiAction(backOnCancel), CustomAnvil.instance)); - pane.bindItem('S', new GuiItem(CONFIRM_ITEM, event -> { + // Save item + this.pane.bindItem('S', new GuiItem(GuiSharedConstant.CONFIRM_ITEM, event -> { event.setCancelled(true); HumanEntity player = event.getWhoClicked(); @@ -80,6 +48,7 @@ public class ConfirmActionGui extends ChestGui { }, CustomAnvil.instance)); + // Info item ItemStack infoItem = new ItemStack(Material.PAPER); ItemMeta infoMeta = infoItem.getItemMeta(); @@ -91,4 +60,13 @@ public class ConfirmActionGui extends ChestGui { pane.bindItem('I', new GuiItem(infoItem, GuiGlobalActions.stayInPlace, CustomAnvil.instance)); } + @Override + protected Pattern getGuiPattern() { + return new Pattern( + GuiSharedConstant.EMPTY_GUI_FULL_LINE, + "00B0I0S00", + GuiSharedConstant.EMPTY_GUI_FULL_LINE + ); + } + } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java new file mode 100644 index 0000000..0ca2a38 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java @@ -0,0 +1,99 @@ +package xyz.alexcrea.cuanvil.gui.config.ask; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; +import com.github.stefvanschie.inventoryframework.pane.util.Pattern; +import io.delilaheve.CustomAnvil; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; +import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public class SelectItemTypeGui extends AbstractAskGui { + + private ItemStack selectedItem; + public SelectItemTypeGui(@NotNull String title, + @NotNull String actionDescription, + @NotNull Gui backOnCancel, + @NotNull BiConsumer onSave, + boolean materialOnly) { + super(3, title, backOnCancel); + this.selectedItem = null; + + // Save item + GuiItem confirmItem = new GuiItem(GuiSharedConstant.CONFIRM_ITEM, event -> { + event.setCancelled(true); + HumanEntity player = event.getWhoClicked(); + + if (!player.hasPermission(CustomAnvil.editConfigPermission)) { + player.closeInventory(); + player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); + return; + } + + onSave.accept(this.selectedItem, player); + + }, CustomAnvil.instance); + this.pane.bindItem('S', GuiGlobalItems.backgroundItem()); + + // Select item + ItemStack selectItem = setDisplayMeta(new ItemStack(Material.BARRIER), actionDescription); + + AtomicReference selectGuiItem = new AtomicReference<>(); + selectGuiItem.set(new GuiItem(selectItem, event -> { + event.setCancelled(true); + + ItemStack cursor = event.getWhoClicked().getItemOnCursor(); + if(cursor.getType().isAir()) return; + + ItemStack finalItem; + if(materialOnly){ + finalItem = setDisplayMeta(new ItemStack(cursor.getType()), actionDescription); + }else{ + finalItem = cursor.clone(); + } + this.selectedItem = finalItem.clone(); + + selectGuiItem.get().setItem(finalItem); + this.pane.bindItem('S', confirmItem); + + update(); + }, CustomAnvil.instance)); + + this.pane.bindItem('V', selectGuiItem.get()); + + // Temporary leave item + GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_TERRACOTTA, this); + + this.pane.bindItem('s', temporaryLeave); + + } + + private ItemStack setDisplayMeta(ItemStack item, String actionDescription){ + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName("\u00A7ePlace an item here"); + meta.setLore(Arrays.asList(actionDescription.split("\n"))); + + item.setItemMeta(meta); + return item; + } + + @Override + protected Pattern getGuiPattern() { + return new Pattern( + GuiSharedConstant.EMPTY_GUI_FULL_LINE, + "0000V000s", + "B0000000S" + ); + } +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java index 89c4c34..684e90f 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; +import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.config.settings.BoolSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java index 11cbaed..6aeb596 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/CustomRecipeConfigGui.java @@ -6,14 +6,15 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.config.settings.subsetting.CustomRecipeSubSettingGui; +import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; +import xyz.alexcrea.cuanvil.gui.config.list.elements.CustomRecipeSubSettingGui; import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; import xyz.alexcrea.cuanvil.util.CasedStringUtil; import java.util.Arrays; import java.util.List; -public class CustomRecipeConfigGui extends MappedElementListConfigGui { +public class CustomRecipeConfigGui extends MappedGuiListConfigGui { public final static CustomRecipeConfigGui INSTANCE = new CustomRecipeConfigGui(); @@ -41,7 +42,7 @@ public class CustomRecipeConfigGui extends MappedElementListConfigGui { +public class EnchantConflictGui extends MappedGuiListConfigGui { public final static EnchantConflictGui INSTANCE = new EnchantConflictGui(); @@ -57,7 +58,7 @@ public class EnchantConflictGui extends MappedElementListConfigGui extends ElementListGlobalConfigGui< T > { - - - protected final HashMap elementGuiMap; - public MappedElementListConfigGui(@NotNull String title) { - super(title); - this.elementGuiMap = new HashMap<>(); - - } - - @Override - protected GuiItem prepareCreateNewItem(){ - // Create new conflict item - ItemStack createItem = new ItemStack(Material.PAPER); - ItemMeta createMeta = createItem.getItemMeta(); - - createMeta.setDisplayName("\u00A7aCreate new "+genericDisplayedName()); - createMeta.setLore(Arrays.asList( - "\u00A77Create a new "+genericDisplayedName()+".", - "\u00A77You will be asked to name the "+genericDisplayedName()+" in chat.", - "\u00A77Then, you should edit the "+genericDisplayedName()+" config as you need" - )); - - createItem.setItemMeta(createMeta); - - return new GuiItem(createItem, (clickEvent) -> { - clickEvent.setCancelled(true); - HumanEntity player = clickEvent.getWhoClicked(); - - // check permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - player.closeInventory(); - - player.sendMessage("\u00A7eWrite the "+genericDisplayedName()+" name you want to create in the chat.\n" + - "\u00A7eOr write \u00A7ccancel \u00A7eto go back to "+genericDisplayedName()+" config menu"); - - CustomAnvil.Companion.getChatListener().setListenedCallback(player, prepareCreateItemConsumer(player)); - - }, CustomAnvil.instance); - } - - @Override - public void reloadValues() { - this.elementGuiMap.forEach((conflict, gui) -> gui.cleanUnused()); - this.elementGuiMap.clear(); - - super.reloadValues(); - } - - @Override - protected void updateGeneric(T generic, ItemStack usedItem) { - S gui = this.elementGuiMap.get(generic); - - GuiItem guiItem; - if (gui == null) { - // Create new sub setting gui - guiItem = new GuiItem(usedItem, CustomAnvil.instance); - gui = newInstanceOfGui(generic, guiItem); - - guiItem.setAction(GuiGlobalActions.openGuiAction(gui)); - - this.elementGuiMap.put(generic, gui); - addToPage(guiItem); - } else { - // Replace item with the updated one - guiItem = gui.getParentItemForThisGui(); - guiItem.setItem(usedItem); - } - gui.updateLocal(); - - } - - @Override - protected GuiItem findGuiItemForRemoval(T generic) { - S gui = this.elementGuiMap.get(generic); - if (gui == null) return null; - - this.elementGuiMap.remove(generic); - return gui.getParentItemForThisGui(); - } - - protected Consumer prepareCreateItemConsumer(HumanEntity player){ - AtomicReference> selfRef = new AtomicReference<>(); - Consumer selfCallback = (message) -> { - if (message == null) return; - - // check permission - if (!player.hasPermission(CustomAnvil.editConfigPermission)) { - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); - return; - } - - message = message.toLowerCase(Locale.ROOT); - if ("cancel".equalsIgnoreCase(message)) { - player.sendMessage(genericDisplayedName()+" creation cancelled..."); - show(player); - return; - } - - message = message.replace(' ', '_'); - - // Try to find if it already exists in a for loop - // Not the most efficient on large number of conflict, but it should not run often. - for (T generic : getEveryDisplayableInstanceOfGeneric()) { - if (generic.getName().equalsIgnoreCase(message)) { - player.sendMessage("\u00A7cPlease enter a "+genericDisplayedName()+" name that do not already exist..."); - // wait next message. - CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get()); - return; - } - } - - T generic = createAndSaveNewEmptyGeneric(message); - - updateValueForGeneric(generic, true); - - // show the new conflict config to the player - this.elementGuiMap.get(generic).show(player); - - update(); - }; - - selfRef.set(selfCallback); - return selfCallback; - } - - protected abstract S newInstanceOfGui(T generic, GuiItem item); - - protected abstract String genericDisplayedName(); - - protected abstract T createAndSaveNewEmptyGeneric(String name); - -} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/UnitRepairConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/UnitRepairConfigGui.java new file mode 100644 index 0000000..d872def --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/UnitRepairConfigGui.java @@ -0,0 +1,119 @@ +package xyz.alexcrea.cuanvil.gui.config.global; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import io.delilaheve.CustomAnvil; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import xyz.alexcrea.cuanvil.config.ConfigHolder; +import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui; +import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; +import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui; +import xyz.alexcrea.cuanvil.util.CasedStringUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class UnitRepairConfigGui extends MappedGuiListConfigGui { + + public final static UnitRepairConfigGui INSTANCE = new UnitRepairConfigGui(); + + static { + INSTANCE.init(); + } + + private UnitRepairConfigGui() { + super("Unit Repair Config"); + } + + @Override + protected UnitRepairElementListGui newInstanceOfGui(Material material, GuiItem item) { + UnitRepairElementListGui element = new UnitRepairElementListGui(material, this, item); + element.init(); + return element; + } + + @Override + protected ItemStack createItemForGeneric(Material material) { + ConfigurationSection materialSection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(material.name().toLowerCase()); + String materialName = CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase()); + + if(material.isAir()){ + material = Material.BARRIER; + } + + int reparableItemCount = materialSection == null ? 0 : materialSection.getKeys(false).size(); // Probably an expensive call but... why not + + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName("\u00A7eRepaired by " +materialName); + meta.setLore(Arrays.asList( + "\u00A77There is currently \u00A7e" +reparableItemCount+ " \u00A77reparable item with "+materialName, + "\u00A77Click here to open the menu to edit reparable item by " + materialName + )); + + item.setItemMeta(meta); + + return item; + } + + @Override + protected List getEveryDisplayableInstanceOfGeneric() { + ArrayList materials = new ArrayList<>(); + + for (String matName : ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getKeys(false)) { + Material mat = Material.getMaterial(matName.toUpperCase()); + if(mat != null){ + materials.add(mat); + } + } + return materials; + } + + @Override + protected GuiItem prepareCreateNewItem() { + // Create new conflict item + ItemStack createItem = new ItemStack(Material.PAPER); + ItemMeta createMeta = createItem.getItemMeta(); + + createMeta.setDisplayName("\u00A7aSelect a new unit material"); + createMeta.setLore(Arrays.asList( + "\u00A77Select a new unit material to be used.", + "\u00A77You will be asked the material to use." + )); + + createItem.setItemMeta(createMeta); + + return new GuiItem(createItem, (clickEvent) -> { + clickEvent.setCancelled(true); + + new SelectItemTypeGui( + "Select unit repair item.", + "\u00A77Click here with an item to set the item\n" + + "\u00A77You like to be an unit repair item", + this, + (itemStack, player) -> { + Material type = itemStack.getType(); + // Add new material + updateValueForGeneric(type, true); + + // Display material edit setting + this.elementGuiMap.get(type).getMappedGui().show(player); + }, + true + ).show(clickEvent.getWhoClicked()); + }, CustomAnvil.instance); + } + + @Override // Not used in this implementation. + protected String genericDisplayedName() { + return "this function Should not be used."; + } + @Override // Not used in this implementation. + protected Material createAndSaveNewEmptyGeneric(String name) { + return null; + } +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/ElementListGlobalConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java similarity index 96% rename from src/main/java/xyz/alexcrea/cuanvil/gui/config/global/ElementListGlobalConfigGui.java rename to src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java index c37daa4..cb2ccf5 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/ElementListGlobalConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java @@ -1,4 +1,4 @@ -package xyz.alexcrea.cuanvil.gui.config.global; +package xyz.alexcrea.cuanvil.gui.config.list; import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.pane.Orientable; @@ -14,6 +14,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; +import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; @@ -22,22 +23,16 @@ import java.util.HashMap; import java.util.List; import java.util.UUID; -public abstract class ElementListGlobalConfigGui< T > extends ValueUpdatableGui { +public abstract class ElementListConfigGui< T > extends ValueUpdatableGui { private final String namePrefix; - public ElementListGlobalConfigGui(@NotNull String title) { - super(6, title, CustomAnvil.instance); - this.namePrefix = title; - } - - - protected OutlinePane firstPage; - protected ArrayList pages; - protected HashMap pageMap; protected PatternPane backgroundPane; - public void init() { + public ElementListConfigGui(@NotNull String title) { + super(6, title, CustomAnvil.instance); + this.namePrefix = title; + // Back item panel Pattern pattern = new Pattern( GuiSharedConstant.EMPTY_GUI_FULL_LINE, @@ -48,9 +43,16 @@ public abstract class ElementListGlobalConfigGui< T > extends ValueUpdatableGui "B11L1R11C" ); this.backgroundPane = new PatternPane(0, 0, 9, 6, Pane.Priority.LOW, pattern); - GuiGlobalItems.addBackItem(this.backgroundPane, MainConfigGui.INSTANCE); + } + + + protected OutlinePane firstPage; + protected ArrayList pages; + protected HashMap pageMap; + + public void init() { // Why I'm using an init function ? GuiGlobalItems.addBackgroundItem(this.backgroundPane); this.backgroundPane.bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM); addPane(this.backgroundPane); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementMappedToListGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementMappedToListGui.java new file mode 100644 index 0000000..11dad8d --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementMappedToListGui.java @@ -0,0 +1,16 @@ +package xyz.alexcrea.cuanvil.gui.config.list; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; + +public interface ElementMappedToListGui { + + GuiItem getParentItemForThisGui(); + + void updateLocal(); + + void cleanAndBeUnusable(); + + Gui getMappedGui(); + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java new file mode 100644 index 0000000..9f5c2a5 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java @@ -0,0 +1,104 @@ +package xyz.alexcrea.cuanvil.gui.config.list; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import io.delilaheve.CustomAnvil; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.function.Consumer; + +public abstract class MappedElementListConfigGui< T, S > extends ElementListConfigGui< T > { + + protected final HashMap elementGuiMap; + public MappedElementListConfigGui(@NotNull String title) { + super(title); + this.elementGuiMap = new HashMap<>(); + + } + + @Override + protected GuiItem prepareCreateNewItem(){ + // Create new conflict item + ItemStack createItem = new ItemStack(Material.PAPER); + ItemMeta createMeta = createItem.getItemMeta(); + + createMeta.setDisplayName("\u00A7aCreate new "+genericDisplayedName()); + createMeta.setLore(Arrays.asList( + "\u00A77Create a new "+genericDisplayedName()+".", + "\u00A77You will be asked to name the "+genericDisplayedName()+" in chat.", + "\u00A77Then, you should edit the "+genericDisplayedName()+" config as you need" + )); + + createItem.setItemMeta(createMeta); + + return new GuiItem(createItem, (clickEvent) -> { + clickEvent.setCancelled(true); + HumanEntity player = clickEvent.getWhoClicked(); + + // check permission + if (!player.hasPermission(CustomAnvil.editConfigPermission)) { + player.closeInventory(); + player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); + return; + } + player.closeInventory(); + + player.sendMessage("\u00A7eWrite the "+genericDisplayedName()+" name you want to create in the chat.\n" + + "\u00A7eOr write \u00A7ccancel \u00A7eto go back to "+genericDisplayedName()+" config menu"); + + CustomAnvil.Companion.getChatListener().setListenedCallback(player, prepareCreateItemConsumer(player)); + + }, CustomAnvil.instance); + } + + @Override + protected void updateGeneric(T generic, ItemStack usedItem) { + S element = this.elementGuiMap.get(generic); + + GuiItem guiItem; + if (element == null) { + // Create new sub setting element + guiItem = new GuiItem(usedItem, CustomAnvil.instance); + + element = newElementRequested(generic, guiItem); + + this.elementGuiMap.put(generic, element); + + addToPage(guiItem); + } else { + // Replace item with the updated one + guiItem = findItemFromElement(generic, element); + guiItem.setItem(usedItem); + } + updateElement(generic, element); + + } + + protected abstract void updateElement(T generic, S element); + + protected abstract S newElementRequested(T generic, GuiItem newItem); + + protected abstract GuiItem findItemFromElement(T generic, S element); + + @Override + protected GuiItem findGuiItemForRemoval(T generic) { + S element = this.elementGuiMap.get(generic); + if (element == null) return null; + + this.elementGuiMap.remove(generic); + return findGuiItemForRemoval(generic, element); + } + + protected abstract GuiItem findGuiItemForRemoval(T generic, S element); + + protected abstract Consumer prepareCreateItemConsumer(HumanEntity player); + + protected abstract String genericDisplayedName(); + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java new file mode 100644 index 0000000..8b81fff --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java @@ -0,0 +1,103 @@ +package xyz.alexcrea.cuanvil.gui.config.list; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import io.delilaheve.CustomAnvil; +import org.bukkit.entity.HumanEntity; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; + +import java.util.Locale; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +public abstract class MappedGuiListConfigGui< T, S extends ElementMappedToListGui> extends MappedElementListConfigGui< T, S > { + + public MappedGuiListConfigGui(@NotNull String title) { + super(title); + + } + + @Override + public void reloadValues() { + this.elementGuiMap.forEach((conflict, gui) -> gui.cleanAndBeUnusable()); + this.elementGuiMap.clear(); + + super.reloadValues(); + } + + @Override + protected S newElementRequested(T generic, GuiItem newItem) { + S element = newInstanceOfGui(generic, newItem); + + newItem.setAction(GuiGlobalActions.openGuiAction(element.getMappedGui())); + return element; + } + + @Override + protected GuiItem findItemFromElement(T generic, S element) { + return element.getParentItemForThisGui(); + } + + @Override + protected void updateElement(T generic, S element) { + element.updateLocal(); + } + + @Override + protected GuiItem findGuiItemForRemoval(T generic, S element) { + return element.getParentItemForThisGui(); + } + + @Override + protected Consumer prepareCreateItemConsumer(HumanEntity player){ + AtomicReference> selfRef = new AtomicReference<>(); + Consumer selfCallback = (message) -> { + if (message == null) return; + + // check permission + if (!player.hasPermission(CustomAnvil.editConfigPermission)) { + player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); + return; + } + + message = message.toLowerCase(Locale.ROOT); + if ("cancel".equalsIgnoreCase(message)) { + player.sendMessage(genericDisplayedName()+" creation cancelled..."); + show(player); + return; + } + + message = message.replace(' ', '_'); + + // Try to find if it already exists in a for loop + // Not the most efficient on large number of conflict, but it should not run often. + for (T generic : getEveryDisplayableInstanceOfGeneric()) { + if (generic.toString().equalsIgnoreCase(message)) { + player.sendMessage("\u00A7cPlease enter a "+genericDisplayedName()+" name that do not already exist..."); + // wait next message. + CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get()); + return; + } + } + + T generic = createAndSaveNewEmptyGeneric(message); + + updateValueForGeneric(generic, true); + + // show the new conflict config to the player + this.elementGuiMap.get(generic).getMappedGui().show(player); + + update(); + }; + + selfRef.set(selfCallback); + return selfCallback; + } + + protected abstract S newInstanceOfGui(T generic, GuiItem item); + + protected abstract String genericDisplayedName(); + + protected abstract T createAndSaveNewEmptyGeneric(String name); + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java new file mode 100644 index 0000000..328743c --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java @@ -0,0 +1,95 @@ +package xyz.alexcrea.cuanvil.gui.config.list; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import io.delilaheve.CustomAnvil; +import org.bukkit.Material; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui; + +import java.util.HashMap; +import java.util.List; +import java.util.function.Consumer; + +public abstract class SettingGuiListConfigGui< T, S extends AbstractSettingGui.SettingGuiFactory> extends ElementListConfigGui< T >{ + + protected HashMap guiItemMap; + protected HashMap factoryMap; + public SettingGuiListConfigGui(@NotNull String title) { + super(title); + this.guiItemMap = new HashMap<>(); + this.factoryMap = new HashMap<>(); + } + + @Override + protected GuiItem prepareCreateNewItem() { + ItemStack createItem = new ItemStack(Material.PAPER); + ItemMeta createMeta = createItem.getItemMeta(); + + createMeta.setDisplayName(createItemName()); + createMeta.setLore(getCreateItemLore()); + + createItem.setItemMeta(createMeta); + return new GuiItem(createItem, getCreateClickConsumer(), CustomAnvil.instance); + } + + @Override + public void updateValueForGeneric(T generic, boolean shouldUpdate) { + S factory = this.factoryMap.get(generic); + if(factory == null){ + // Create new item & factory + factory = createFactory(generic); + GuiItem newItem = itemFromFactory(generic, factory); + + addToPage(newItem); + this.guiItemMap.put(generic, newItem); + this.factoryMap.put(generic, factory); + }else{ + // Update old item + GuiItem oldItem = this.guiItemMap.get(generic); + + GuiItem newItem = itemFromFactory(generic, factory); + updateGuiItem(oldItem, newItem); + } + + if(shouldUpdate){ + update(); + } + } + + @Override + protected void reloadValues() { + this.guiItemMap.clear(); + this.factoryMap.clear(); + + super.reloadValues(); + } + + private void updateGuiItem(GuiItem oldITem, GuiItem newItem){ + oldITem.setItem(newItem.getItem()); + oldITem.setProperties(newItem.getProperties()); + oldITem.setVisible(newItem.isVisible()); + } + @Override + protected GuiItem findGuiItemForRemoval(T generic) { + return this.guiItemMap.get(generic); + } + + @Override // Not used + protected void updateGeneric(T generic, ItemStack usedItem) {} + @Override // Not used + protected ItemStack createItemForGeneric(T generic) { + return null; + } + + protected abstract List getCreateItemLore(); + protected abstract Consumer getCreateClickConsumer(); + protected abstract String createItemName(); + + protected abstract S createFactory(T generic); + protected abstract GuiItem itemFromFactory(T generic, S factory); + + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java new file mode 100644 index 0000000..fdbc7d8 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java @@ -0,0 +1,197 @@ +package xyz.alexcrea.cuanvil.gui.config.list; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.config.ConfigHolder; +import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui; +import xyz.alexcrea.cuanvil.gui.config.global.UnitRepairConfigGui; +import xyz.alexcrea.cuanvil.gui.config.settings.DoubleSettingGui; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; +import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.util.CasedStringUtil; +import xyz.alexcrea.cuanvil.util.MetricsUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +public class UnitRepairElementListGui extends SettingGuiListConfigGui implements ElementMappedToListGui { + + private final GuiItem parentItem; + private final Material material; + private final UnitRepairConfigGui parentGui; + private final String materialName; + + private boolean shouldWork = true; + public UnitRepairElementListGui(@NotNull Material material, + @NotNull UnitRepairConfigGui parentGui, + @NotNull GuiItem parentItem) { + super("\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase()) + " \u00A7rUnit repair"); + this.parentItem = parentItem; + this.material = material; + this.parentGui = parentGui; + this.materialName = CasedStringUtil.snakeToUpperSpacedCase(material.name().toLowerCase()); + + GuiGlobalItems.addBackItem(this.backgroundPane, parentGui); + } + + // SettingGuiListConfigGui methods + @Override + protected List getCreateItemLore() { + return Arrays.asList( + "\u00A77Select a new item to be repairable.", + "\u00A77You will be asked the material to use." + ); + } + + @Override + protected Consumer getCreateClickConsumer() { + return event -> { + event.setCancelled(true); + if(!this.shouldWork){ + return; + } + event.setCancelled(true); + + new SelectItemTypeGui( + "Select item to be repaired.", + "\u00A77Click here with an item to set the item\n" + + "\u00A77You like to be repaired by " + this.materialName, + this, + (itemStack, player) -> { + ItemMeta meta = itemStack.getItemMeta(); + Material type = itemStack.getType(); + + if(!(meta instanceof Damageable) || (type.getMaxDurability() <= 0)) { + player.sendMessage("\u00A7cThis item can't be damaged, so it can't be repaired."); + return; + } + if(type == this.material){ + player.sendMessage("\u00A7cItem can't repair something of the same type."); + return; + } + + String materialName = type.name().toLowerCase(); + + // Add new material + ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().set(material.name().toLowerCase()+"."+materialName,0.25); + + MetricsUtil.INSTANCE.notifyChange(ConfigHolder.UNIT_REPAIR_HOLDER, ""); + if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { + ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); + } + + // Update gui + updateValueForGeneric(materialName, true); + this.parentGui.updateValueForGeneric(this.material, true); + + + // Display material edit setting + this.factoryMap.get(materialName).create().show(player); + }, + true + ).show(event.getWhoClicked()); + + }; + } + + @Override + protected String createItemName() { + return "\u00A7aAdd a new item reparable by " + this.materialName; + } + + @Override + protected DoubleSettingGui.DoubleSettingFactory createFactory(String materialName) { + return DoubleSettingGui.doubleFactory( + "\u00A70%\u00A78" +CasedStringUtil.snakeToUpperSpacedCase(materialName)+" Repair", + this, + material.name().toLowerCase()+"."+materialName, + ConfigHolder.UNIT_REPAIR_HOLDER, + 2, + true, true, + 0, + 1, + 0.25, + 0.01, 0.05, 0.25 + ); + } + + @Override + protected GuiItem itemFromFactory(String materialName, DoubleSettingGui.DoubleSettingFactory factory) { + return factory.getItem(materialFromName(materialName), + "\u00A77%\u00A7a" + CasedStringUtil.snakeToUpperSpacedCase(materialName)+ " \u00A7erepaired by \u00A7a" + this.materialName); + } + + @Override + protected List getEveryDisplayableInstanceOfGeneric() { + ArrayList keys = new ArrayList<>(); + if(!this.shouldWork){ + return keys; + } + + ConfigurationSection materialSection = ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().getConfigurationSection(material.name().toLowerCase()); + if(materialSection == null){ + return keys; + } + keys.addAll(materialSection.getKeys(false)); + return keys; + } + + private Material materialFromName(String materialName){ + Material mat = Material.getMaterial(materialName.toUpperCase()); + if(mat == null || mat.isAir()) return Material.BARRIER; + return mat; + } + + @Override + public void updateGuiValues() { + super.updateGuiValues(); + this.parentGui.updateValueForGeneric(this.material, true); + } + + // ElementMappedToListGui methods + + @Override + public GuiItem getParentItemForThisGui() { + return this.parentItem; + } + + @Override // Not used in this implementation + public void updateLocal() {} + + @Override + public void cleanAndBeUnusable() { + this.shouldWork = false; + this.backgroundPane.bindItem('S', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE)); + this.backgroundPane.bindItem('L', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE)); + this.backgroundPane.bindItem('R', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE)); + + for (HumanEntity viewer : getViewers()) { + viewer.sendMessage("This config do not exist anymore"); + this.parentGui.show(viewer); + } + } + + @Override + public Gui getMappedGui() { + return this; + } + + @Override + public void show(@NotNull HumanEntity humanEntity) { + if(!this.shouldWork){ + humanEntity.closeInventory(); + return; + } + super.show(humanEntity); + } + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/CustomRecipeSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/CustomRecipeSubSettingGui.java similarity index 87% rename from src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/CustomRecipeSubSettingGui.java rename to src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/CustomRecipeSubSettingGui.java index 148330c..ff1249b 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/CustomRecipeSubSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/CustomRecipeSubSettingGui.java @@ -1,4 +1,4 @@ -package xyz.alexcrea.cuanvil.gui.config.settings.subsetting; +package xyz.alexcrea.cuanvil.gui.config.list.elements; import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.pane.PatternPane; @@ -11,7 +11,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.config.ConfigHolder; -import xyz.alexcrea.cuanvil.gui.config.ConfirmActionGui; +import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui; import xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui; import xyz.alexcrea.cuanvil.gui.config.settings.BoolSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; @@ -37,7 +37,7 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { @NotNull CustomRecipeConfigGui parent, @NotNull AnvilCustomRecipe anvilRecipe, @NotNull GuiItem parentItemForThisGui) { - super(parentItemForThisGui, 3, "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.getName()) + " \u00A78Config"); + super(parentItemForThisGui, 3, "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.toString()) + " \u00A78Config"); this.parent = parent; this.anvilRecipe = anvilRecipe; @@ -77,24 +77,24 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { IntRange costRange = AnvilCustomRecipe.Companion.getXP_COST_CONFIG_RANGE(); this.exactCountFactory = BoolSettingsGui.boolFactory("\u00A78Exact count ?", this, - this.anvilRecipe.getName()+"."+AnvilCustomRecipe.EXACT_COUNT_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, + this.anvilRecipe + "." + AnvilCustomRecipe.EXACT_COUNT_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, AnvilCustomRecipe.Companion.getDEFAULT_EXACT_COUNT_CONFIG()); this.xpCostFactory = IntSettingsGui.intFactory("\u00A78Recipe Xp Cost", this, - this.anvilRecipe.getName()+"."+AnvilCustomRecipe.XP_COST_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, + this.anvilRecipe +"."+AnvilCustomRecipe.XP_COST_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, costRange.getFirst(), costRange.getLast(), AnvilCustomRecipe.Companion.getDEFAULT_XP_COST_CONFIG(), 1, 5, 10); this.leftItemFactory = ItemSettingGui.itemFactory("\u00A7eRecipe Left \u00A78Item", this, - this.anvilRecipe.getName()+"."+AnvilCustomRecipe.LEFT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, + this.anvilRecipe + "." + AnvilCustomRecipe.LEFT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG()); this.rightItemFactory = ItemSettingGui.itemFactory("\u00A7eRecipe Right \u00A78Item", this, - this.anvilRecipe.getName()+"."+AnvilCustomRecipe.RIGHT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, + this.anvilRecipe + "." + AnvilCustomRecipe.RIGHT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG()); this.resultItemFactory = ItemSettingGui.itemFactory("\u00A7aRecipe Result \u00A78Item", this, - this.anvilRecipe.getName()+"."+AnvilCustomRecipe.RESULT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, + this.anvilRecipe + "." + AnvilCustomRecipe.RESULT_ITEM_CONFIG, ConfigHolder.CUSTOM_RECIPE_HOLDER, AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG()); } @@ -109,10 +109,10 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { this.parent.removeGeneric(this.anvilRecipe); // Remove self - cleanUnused(); + cleanAndBeUnusable(); // Update config file storage - ConfigHolder.CUSTOM_RECIPE_HOLDER.getConfig().set(this.anvilRecipe.getName(), null); + ConfigHolder.CUSTOM_RECIPE_HOLDER.getConfig().set(this.anvilRecipe.toString(), null); // Save boolean success = true; @@ -123,7 +123,7 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { return success; }; - return new ConfirmActionGui("\u00A7cDelete \u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.anvilRecipe.getName()) + "\u00A7c?", + return new ConfirmActionGui("\u00A7cDelete \u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.anvilRecipe.toString()) + "\u00A7c?", "\u00A77Confirm that you want to delete this conflict.", this, this.parent, deleteSupplier ); @@ -159,7 +159,7 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui { update(); } - public void cleanUnused() { + public void cleanAndBeUnusable() { for (HumanEntity viewer : getViewers()) { this.parent.show(viewer); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/EnchantConflictSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java similarity index 92% rename from src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/EnchantConflictSubSettingGui.java rename to src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java index b9cfefa..9a64977 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/EnchantConflictSubSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/EnchantConflictSubSettingGui.java @@ -1,4 +1,4 @@ -package xyz.alexcrea.cuanvil.gui.config.settings.subsetting; +package xyz.alexcrea.cuanvil.gui.config.list.elements; import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.pane.PatternPane; @@ -14,9 +14,9 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; import xyz.alexcrea.cuanvil.group.EnchantConflictManager; -import xyz.alexcrea.cuanvil.gui.config.ConfirmActionGui; import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer; import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer; +import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui; import xyz.alexcrea.cuanvil.gui.config.global.EnchantConflictGui; import xyz.alexcrea.cuanvil.gui.config.settings.EnchantSelectSettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.GroupSelectSettingGui; @@ -46,7 +46,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl @NotNull GuiItem parentItemForThisGui) { super(parentItemForThisGui, 3, - "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.getName()) + " \u00A78Config"); + "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + " \u00A78Config"); this.parent = parent; this.enchantConflict = enchantConflict; @@ -85,7 +85,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), (event) -> { event.setCancelled(true); EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui( - "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.getName()) + " \u00A75Enchantments", + "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + " \u00A75Enchantments", this, this, 0); enchantGui.show(event.getWhoClicked()); }, CustomAnvil.instance); @@ -93,14 +93,14 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), (event) -> { event.setCancelled(true); GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( - "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.getName()) + " \u00A73Groups", + "\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + " \u00A73Groups", this, this, 0); enchantGui.show(event.getWhoClicked()); }, CustomAnvil.instance); this.minBeforeActiveSettingFactory = IntSettingsGui.intFactory( "\u00A78Minimum enchantment count", - this, this.enchantConflict.getName() + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER, + this, this.enchantConflict + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER, 0, 255, 0, 1 ); @@ -126,10 +126,10 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl this.parent.removeGeneric(this.enchantConflict); // Remove self - cleanUnused(); + cleanAndBeUnusable(); // Update config file storage - ConfigHolder.CONFLICT_HOLDER.getConfig().set(this.enchantConflict.getName(), null); + ConfigHolder.CONFLICT_HOLDER.getConfig().set(this.enchantConflict.toString(), null); // Save boolean success = true; @@ -140,7 +140,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl return success; }; - return new ConfirmActionGui("\u00A7cDelete \u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.getName()) + "\u00A7c?", + return new ConfirmActionGui("\u00A7cDelete \u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + "\u00A7c?", "\u00A77Confirm that you want to delete this conflict.", this, this.parent, deleteSupplier ); @@ -149,7 +149,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl @Override public void updateGuiValues() { // update value from config to conflict - int minBeforeBlock = ConfigHolder.CONFLICT_HOLDER.getConfig().getInt(this.enchantConflict.getName()+'.'+EnchantConflictManager.ENCH_MAX_PATH, 0); + int minBeforeBlock = ConfigHolder.CONFLICT_HOLDER.getConfig().getInt(this.enchantConflict.toString()+'.'+EnchantConflictManager.ENCH_MAX_PATH, 0); this.enchantConflict.setMinBeforeBlock(minBeforeBlock); // Parent should call updateLocal with this call @@ -234,7 +234,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl } @Override - public void cleanUnused() { + public void cleanAndBeUnusable() { for (HumanEntity viewer : getViewers()) { this.parent.show(viewer); } @@ -267,7 +267,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl @Override public boolean setSelectedEnchantments(Set enchantments) { if (!this.shouldWork) { - CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.getName() + " enchants but sub config is destroyed"); + CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed"); return false; } @@ -280,12 +280,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl for (Enchantment enchantment : enchantments) { enchantKeys[index++] = enchantment.getKey().getKey(); } - ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict.getName() + ".enchantments", enchantKeys); + ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict + ".enchantments", enchantKeys); try { updateGuiValues(); } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict.getName(), e); + CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, e); } @@ -312,7 +312,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl @Override public boolean setSelectedGroups(Set groups) { if (!this.shouldWork) { - CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.getName() + " groups but sub config is destroyed"); + CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.toString() + " groups but sub config is destroyed"); return false; } @@ -325,12 +325,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl for (AbstractMaterialGroup group : groups) { groupsNames[index++] = group.getName(); } - ConfigHolder.CONFLICT_HOLDER.getConfig().set(this.enchantConflict.getName() + ".notAffectedGroups", groupsNames); + ConfigHolder.CONFLICT_HOLDER.getConfig().set(this.enchantConflict + ".notAffectedGroups", groupsNames); try { updateGuiValues(); } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict.getName(), e); + CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, e); } // Save file configuration to disk diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/MappedToListSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java similarity index 63% rename from src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/MappedToListSubSettingGui.java rename to src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java index bcadc73..08b4a2f 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/subsetting/MappedToListSubSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java @@ -1,11 +1,13 @@ -package xyz.alexcrea.cuanvil.gui.config.settings.subsetting; +package xyz.alexcrea.cuanvil.gui.config.list.elements; import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; import io.delilaheve.CustomAnvil; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; +import xyz.alexcrea.cuanvil.gui.config.list.ElementMappedToListGui; -public abstract class MappedToListSubSettingGui extends ValueUpdatableGui { +public abstract class MappedToListSubSettingGui extends ValueUpdatableGui implements ElementMappedToListGui { private final GuiItem item; public MappedToListSubSettingGui( @@ -16,13 +18,15 @@ public abstract class MappedToListSubSettingGui extends ValueUpdatableGui { this.item = item; } - + @Override public GuiItem getParentItemForThisGui() { return item; } + @Override + public Gui getMappedGui() { + return this; + } - public abstract void updateLocal(); // TODO - public abstract void cleanUnused(); // TODO } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/AbstractSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/AbstractSettingGui.java index 21a291f..0248c9d 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/AbstractSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/AbstractSettingGui.java @@ -55,7 +55,7 @@ public abstract class AbstractSettingGui extends ChestGui { * * @param parent Parent gui to go back when completed. */ - private void initBase(ValueUpdatableGui parent) { + protected void initBase(ValueUpdatableGui parent) { Pattern pattern = getGuiPattern(); pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern); addPane(pane); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/DoubleSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/DoubleSettingGui.java new file mode 100644 index 0000000..772f473 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/DoubleSettingGui.java @@ -0,0 +1,464 @@ +package xyz.alexcrea.cuanvil.gui.config.settings; + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.pane.PatternPane; +import com.github.stefvanschie.inventoryframework.pane.util.Pattern; +import io.delilaheve.CustomAnvil; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import xyz.alexcrea.cuanvil.config.ConfigHolder; +import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; +import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.util.CasedStringUtil; +import xyz.alexcrea.cuanvil.util.MetricsUtil; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +public class DoubleSettingGui extends AbstractSettingGui { + + protected final DoubleSettingFactory holder; + protected final boolean asPercentage; + protected final boolean nullOnZero; + @NotNull + protected final BigDecimal before; + @NotNull + protected BigDecimal now; + protected BigDecimal step; + + /** + * Create a double setting config gui. + * + * @param holder Configuration factory of this setting. + * @param now The defined value of this setting. + * @param asPercentage If the value represent a % + * @param nullOnZero If the value should be set as null on zero + */ + protected DoubleSettingGui(DoubleSettingFactory holder, @NotNull BigDecimal now, + boolean asPercentage, boolean nullOnZero) { + super(3, holder.getTitle(), holder.parent); + assert holder.steps.length > 0 && holder.steps.length <= 9; + this.holder = holder; + this.asPercentage = asPercentage; + this.nullOnZero = nullOnZero; + + this.before = now; + this.now = now; + this.step = holder.steps[0]; + + initStepsValue(); + prepareReturnToDefault(); + updateValueDisplay(); + } + + private static final ItemStack DELETE_ITEM_STACK = new ItemStack(Material.RED_TERRACOTTA); + static { + ItemMeta meta = DELETE_ITEM_STACK.getItemMeta(); + + meta.setDisplayName("\u00A7cDisable item being repaired ?"); + meta.setLore(Arrays.asList("\u00A77Confirm disabling unit repair for this item..", + "\u00A74Cation: This action can't be canceled.")); + + DELETE_ITEM_STACK.setItemMeta(meta); + } + + private GuiItem askDelete; + + @Override + protected void initBase(ValueUpdatableGui parent) { + super.initBase(parent); + + this.askDelete = new GuiItem(DELETE_ITEM_STACK, + GuiGlobalActions.saveSettingAction(this, parent), + CustomAnvil.instance); + } + + @Override + public void update() { + boolean shouldDelete = isNull() && hadChange(); + + GuiItem tempSaveItem = this.saveItem; + if(shouldDelete){ + this.saveItem = this.askDelete; + } + + super.update(); + + if(shouldDelete){ + this.saveItem = tempSaveItem; + } + } + + @Override + public Pattern getGuiPattern() { + return new Pattern( + "abcdefghi", + "D0-0v0+00", + "B0000000S" + ); + } + + protected GuiItem returnToDefault; + + /** + * Prepare "return to default value" gui item. + */ + protected void prepareReturnToDefault() { + ItemStack item = new ItemStack(Material.COMMAND_BLOCK); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName("\u00A7eReset to default value"); + meta.setLore(Collections.singletonList("\u00A77Default value is " + displayValue(holder.defaultVal))); + item.setItemMeta(meta); + returnToDefault = new GuiItem(item, event -> { + event.setCancelled(true); + now = holder.defaultVal; + updateValueDisplay(); + update(); + }, CustomAnvil.instance); + } + + /** + * Update item using the setting value to match the new value. + */ + protected void updateValueDisplay() { + + PatternPane pane = getPane(); + + //minus item + GuiItem minusItem; + if (now.compareTo(holder.min) > 0) { + BigDecimal planned = holder.min.max(now.subtract(step)); + + minusItem = getSetValueItem(Material.RED_TERRACOTTA, planned, "\u00A7c-"); + } else { + minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); + } + pane.bindItem('-', minusItem); + + //plus item + GuiItem plusItem; + if (now.compareTo(holder.max) < 0) { + BigDecimal planned = holder.max.min(now.add(step)); + + plusItem = getSetValueItem(Material.GREEN_TERRACOTTA, planned, "\u00A7a+"); + } else { + plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER); + } + pane.bindItem('+', plusItem); + + // "result" display + ItemStack resultPaper = new ItemStack(Material.PAPER); + ItemMeta resultMeta = resultPaper.getItemMeta(); + resultMeta.setDisplayName("\u00A7eValue: " + displayValue(now)); + resultPaper.setItemMeta(resultMeta); + GuiItem resultItem = new GuiItem(resultPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance); + + pane.bindItem('v', resultItem); + + // reset to default + GuiItem returnToDefault; + if (now.compareTo(holder.defaultVal) != 0) { + returnToDefault = this.returnToDefault; + } else { + returnToDefault = GuiGlobalItems.backgroundItem(); + } + pane.bindItem('D', returnToDefault); + + } + + private GuiItem getSetValueItem(Material mat, BigDecimal planned, String numberPrefix){ + ItemStack item = new ItemStack(mat); + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName("\u00A7e" + displayValue(now) + " -> " + displayValue(planned) + + " \u00A7r(" + numberPrefix + (displayValue(planned.subtract(now).abs()) + "\u00A7r)")); + meta.setLore(AbstractSettingGui.CLICK_LORE); + item.setItemMeta(meta); + + return new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance); + } + + /** + * @param planned Value to change current setting to. + * @return A consumer to update the current setting's value. + */ + protected Consumer updateNowConsumer(BigDecimal planned) { + return event -> { + event.setCancelled(true); + now = planned; + updateValueDisplay(); + update(); + }; + } + + /** + * Initialise step items. + */ + protected void initStepsValue() { + // Put background glass on the background of 'a' to 'b' + GuiItem background = GuiGlobalItems.backgroundItem(); + PatternPane pane = getPane(); + + for (char i = 'a'; i < (getMidStepChar() - 'a') * 2 + 1; i++) { + pane.bindItem(i, background); + } + // Then update legit step values + updateStepValue(); + } + + /** + * Update steps items value. + */ + protected void updateStepValue() { + if (holder.steps.length <= 1) return; + // We assume steps have a length of 2k+1 cause its more pretty + char val = getMidStepChar(); + // Offset to start (not the best way to do it) + val -= (char) ((holder.steps.length - 1) / 2); + + // Then place items + PatternPane pane = getPane(); + for (int i = 0; i < holder.steps.length; i++) { + pane.bindItem(val + i, stepGuiItem(i)); + } + + } + + /** + * Step use lower case character from 'a' to a certain char. + * + * @return The middle value of the character set for steps. + */ + protected char getMidStepChar() { + return 'e'; + } + + /** + * Create a step item from a step value. + * + * @param stepIndex the index of the step item. + * @return A step item corresponding to its index value. + */ + protected GuiItem stepGuiItem(int stepIndex) { + BigDecimal stepValue = holder.steps[stepIndex]; + + // Get material properties + Material stepMat; + StringBuilder stepName = new StringBuilder("\u00A7"); + List stepLore; + Consumer clickEvent; + if (stepValue.compareTo(step) == 0) { + stepMat = Material.GREEN_STAINED_GLASS_PANE; + stepName.append('a'); + stepLore = Collections.singletonList("\u00A77Value is changing by " + displayValue(stepValue)); + clickEvent = GuiGlobalActions.stayInPlace; + } else { + stepMat = Material.RED_STAINED_GLASS_PANE; + stepName.append('c'); + stepLore = Collections.singletonList("\u00A77Click here to change the value by " + displayValue(stepValue)); + clickEvent = updateStepValue(stepValue); + } + stepName.append("Step of ").append(displayValue(stepValue)); + + // Create item stack then gui item + ItemStack item = new ItemStack(stepMat); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(stepName.toString()); + meta.setLore(stepLore); + item.setItemMeta(meta); + + return new GuiItem(item, clickEvent, CustomAnvil.instance); + } + + /** + * @param stepValue Value to change current step to. + * @return A consumer to update the current step of this setting. + */ + protected Consumer updateStepValue(BigDecimal stepValue) { + return event -> { + event.setCancelled(true); + this.step = stepValue; + updateStepValue(); + updateValueDisplay(); + update(); + }; + } + + @Override + public boolean onSave() { + if(isNull()){ + this.holder.config.getConfig().set(this.holder.configPath, null); + }else{ + this.holder.config.getConfig().set(this.holder.configPath, now.doubleValue()); + } + + MetricsUtil.INSTANCE.notifyChange(this.holder.config, this.holder.configPath); + if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { + return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE); + } + return true; + } + + @Override + public boolean hadChange() { + return now.compareTo(before) != 0; + } + + public boolean isNull(){ + return this.nullOnZero && (this.now.compareTo(BigDecimal.ZERO) == 0); + } + + private static final BigDecimal PERCENTAGE_OFFSET = BigDecimal.valueOf(100); + public String displayValue(BigDecimal value){ + return displayValue(value, this.asPercentage); + } + + public static String displayValue(BigDecimal value, boolean isAsPercentage){ + if(isAsPercentage){ + return value.multiply(PERCENTAGE_OFFSET).setScale(value.scale()-2, RoundingMode.HALF_UP) + "%"; + } + return value.toString(); + } + + /** + * Create a double setting factory from setting's parameters. + * + * @param title The title of the gui. + * @param parent Parent gui to go back when completed. + * @param configPath Configuration path of this setting. + * @param config Configuration holder of this setting. + * @param scale The scale of the decimal. + * @param asPercentage If we should display the value as a %. + * @param nullOnZero Set the value as null (deleting it) when equal to 0 + * @param min Minimum value of this setting. + * @param max Maximum value of this setting. + * @param defaultVal Default value if not found on the config. + * @param steps List of step the value can increment/decrement. + * List's size should be between 1 (included) and 5 (included). + * it is visually preferable to have an odd number of step. + * If step only contain 1 value, no step item should be displayed. + * @return A factory for a double setting gui. + */ + public static DoubleSettingFactory doubleFactory(@NotNull String title, ValueUpdatableGui parent, + String configPath, ConfigHolder config, + int scale, boolean asPercentage, boolean nullOnZero, + double min, double max, double defaultVal, double... steps) { + return new DoubleSettingFactory( + title, parent, + configPath, config, + scale, asPercentage, nullOnZero, + min, max, defaultVal, steps); + } + + /** + * A factory for a double setting gui that hold setting's information. + */ + public static class DoubleSettingFactory extends SettingGuiFactory { + @NotNull + String title; + ValueUpdatableGui parent; + + int scale; + boolean asPercentage; + boolean nullOnZero; + BigDecimal min; + BigDecimal max; + BigDecimal defaultVal; + BigDecimal[] steps; + + /** + * Constructor for a double setting gui factory. + * + * @param title The title of the gui. + * @param parent Parent gui to go back when completed. + * @param configPath Configuration path of this setting. + * @param config Configuration holder of this setting. + * @param scale The scale of the decimal. + * @param asPercentage If we should display the value as a %. + * @param nullOnZero Set the value as null (deleting it) when equal to 0 + * @param min Minimum value of this setting. + * @param max Maximum value of this setting. + * @param defaultVal Default value if not found on the config. + * @param steps List of step the value can increment/decrement. + * List's size should be between 1 (included) and 5 (included). + * it is visually preferable to have an odd number of step. + * If step only contain 1 value, no step item should be displayed. + */ + protected DoubleSettingFactory( + @NotNull String title, ValueUpdatableGui parent, + String configPath, ConfigHolder config, + int scale, boolean asPercentage, boolean nullOnZero, + double min, double max, double defaultVal, double... steps) { + super(configPath, config); + this.title = title; + this.parent = parent; + this.scale = scale; + this.asPercentage = asPercentage; + this.nullOnZero = nullOnZero; + this.min = BigDecimal.valueOf(min).setScale(scale, RoundingMode.HALF_UP); + this.max = BigDecimal.valueOf(max).setScale(scale, RoundingMode.HALF_UP); + this.defaultVal = BigDecimal.valueOf(defaultVal).setScale(scale, RoundingMode.HALF_UP); + + this.steps = new BigDecimal[steps.length]; + for (int i = 0; i < steps.length; i++) { + this.steps[i] = BigDecimal.valueOf(steps[i]).setScale(scale, RoundingMode.HALF_UP); + } + } + + /** + * @return Get setting's gui title + */ + @NotNull + public String getTitle() { + return title; + } + + /** + * @return The configured value for the associated setting. + */ + public BigDecimal getConfiguredValue() { + ConfigurationSection section = this.config.getConfig(); + if(section.isDouble(this.configPath)){ + return BigDecimal.valueOf(section.getDouble(this.configPath)).setScale(2, RoundingMode.HALF_UP); + } + return this.defaultVal; + } + + @Override + public AbstractSettingGui create() { + // Get value or default + BigDecimal now = getConfiguredValue(); + // create new gui + return new DoubleSettingGui(this, now, this.asPercentage, this.nullOnZero); + } + + + public GuiItem getItem(Material itemMat, String name){ + // Get item properties + BigDecimal value = getConfiguredValue(); + StringBuilder itemName = new StringBuilder("\u00A7a").append(name); + + return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName, displayValue(value, this.asPercentage)); + } + + public GuiItem getItem(Material itemMat){ + // Get item properties + String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath()); + + return getItem(itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath)); + } + + } + +} \ No newline at end of file diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java index 8f44e5e..d88452a 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java @@ -58,29 +58,8 @@ public class ItemSettingGui extends AbstractSettingGui { public void prepareStaticItems(){ prepareReturnToDefault(); - ItemStack item = new ItemStack(Material.YELLOW_TERRACOTTA); - ItemMeta meta = item.getItemMeta(); - - meta.setDisplayName("\u00A7eTemporary close this menu"); - meta.setLore(Collections.singletonList("\u00A77Allow you to chose other item then return here.")); - item.setItemMeta(meta); - GuiItem guiItem = new GuiItem(item, event -> { - event.setCancelled(true); - - HumanEntity player = event.getWhoClicked(); - - CustomAnvil.Companion.getChatListener().setListenedCallback(player, (message) ->{ - - if(message == null) return; - show(player); - - }); - - player.sendMessage("\u00A7eWrite something in chat to return to the item config menu."); - player.closeInventory(); - }, CustomAnvil.instance); - - getPane().bindItem('s', guiItem); + GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_TERRACOTTA, this); + getPane().bindItem('s', temporaryLeave); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalItems.java b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalItems.java index f8b4656..d72a988 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalItems.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiGlobalItems.java @@ -5,6 +5,8 @@ import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; import com.github.stefvanschie.inventoryframework.pane.PatternPane; import io.delilaheve.CustomAnvil; import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; @@ -15,7 +17,6 @@ import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.ItemSettingGui; import xyz.alexcrea.cuanvil.util.CasedStringUtil; -import java.nio.charset.MalformedInputException; import java.util.Collections; /** @@ -318,7 +319,7 @@ public class GuiGlobalItems { * Will not update automatically, if the setting's value change, the item need to be created again. * @return A formatted GuiItem that will create and open a GUI for the setting. */ - private static GuiItem createGuiItemFromProperties( + public static GuiItem createGuiItemFromProperties( @NotNull AbstractSettingGui.SettingGuiFactory factory, @NotNull Material itemMat, @NotNull StringBuilder itemName, @@ -330,6 +331,7 @@ public class GuiGlobalItems { itemMeta.setDisplayName(itemName.toString()); itemMeta.setLore(Collections.singletonList(SETTING_ITEM_LORE_PREFIX + value)); + itemMeta.addItemFlags(ItemFlag.values()); item.setItemMeta(itemMeta); // Create GuiItem @@ -350,4 +352,29 @@ public class GuiGlobalItems { return path.substring(indexOfDot + 1); } + public static GuiItem temporaryCloseGuiToSelectItem(Material itemMaterial, Gui openBack){ + ItemStack item = new ItemStack(itemMaterial); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName("\u00A7eTemporary close this menu"); + meta.setLore(Collections.singletonList("\u00A77Allow you to chose other item then return here.")); + item.setItemMeta(meta); + + return new GuiItem(item, event -> { + event.setCancelled(true); + + HumanEntity player = event.getWhoClicked(); + + CustomAnvil.Companion.getChatListener().setListenedCallback(player, (message) ->{ + + if(message == null) return; + openBack.show(player); + + }); + + player.sendMessage("\u00A7eWrite something in chat to return to the item config menu."); + player.closeInventory(); + }, CustomAnvil.instance); + } + } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java index b52401b..0ad90a6 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java @@ -6,9 +6,12 @@ import com.github.stefvanschie.inventoryframework.pane.PatternPane; import com.github.stefvanschie.inventoryframework.pane.util.Pattern; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; -import xyz.alexcrea.cuanvil.gui.config.global.MainConfigGui; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -50,4 +53,23 @@ public class GuiSharedConstant { } + public static final ItemStack CANCEL_ITEM; + public static final ItemStack CONFIRM_ITEM; + + static { + CANCEL_ITEM = new ItemStack(Material.RED_TERRACOTTA); + ItemMeta meta = CANCEL_ITEM.getItemMeta(); + meta.setDisplayName("\u00A7cCancel"); + meta.setLore(Collections.singletonList("\u00A77Cancel current action and return to previous menu.")); + CANCEL_ITEM.setItemMeta(meta); + + CONFIRM_ITEM = new ItemStack(Material.GREEN_TERRACOTTA); + meta = CONFIRM_ITEM.getItemMeta(); + meta.setDisplayName("\u00A7aConfirm"); + meta.setLore(Arrays.asList("\u00A77Confirm current action.", + "\u00A74Cation: This action can't be canceled.")); + CONFIRM_ITEM.setItemMeta(meta); + } + + } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt index c45da8c..8b188ab 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt @@ -5,7 +5,7 @@ import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.entity.HumanEntity -import xyz.alexcrea.cuanvil.gui.config.global.MainConfigGui +import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions class EditConfigExecutor : CommandExecutor { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt index 459db0f..c9db197 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -9,6 +9,7 @@ import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui import xyz.alexcrea.cuanvil.gui.config.global.EnchantConflictGui import xyz.alexcrea.cuanvil.gui.config.global.EnchantCostConfigGui import xyz.alexcrea.cuanvil.gui.config.global.EnchantLimitConfigGui +import xyz.alexcrea.cuanvil.gui.config.global.UnitRepairConfigGui import xyz.alexcrea.cuanvil.util.MetricsUtil class ReloadExecutor : CommandExecutor { @@ -43,6 +44,7 @@ class ReloadExecutor : CommandExecutor { EnchantCostConfigGui.INSTANCE.updateGuiValues() EnchantLimitConfigGui.INSTANCE.updateGuiValues() EnchantConflictGui.INSTANCE.reloadValues() + UnitRepairConfigGui.INSTANCE.reloadValues() // & update metric MetricsUtil.testIfConfigIsDefault() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt index 44a4bef..76a07d8 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictGroup.kt @@ -3,13 +3,12 @@ package xyz.alexcrea.cuanvil.group import io.delilaheve.CustomAnvil import org.bukkit.Material import org.bukkit.enchantments.Enchantment -import xyz.alexcrea.cuanvil.interfaces.Named class EnchantConflictGroup( private val name: String, private val cantConflict: AbstractMaterialGroup, var minBeforeBlock: Int -): Named { +) { private val enchantments = HashSet() @@ -63,7 +62,7 @@ class EnchantConflictGroup( return Material.ENCHANTED_BOOK } - override fun getName(): String { + override fun toString(): String { return name } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt index 45a9f36..e4ce6f8 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt @@ -139,9 +139,9 @@ class EnchantConflictManager { var result = ConflictType.NO_CONFLICT for (conflict in conflictList) { - CustomAnvil.verboseLog("Is against ${conflict.getName()}") + CustomAnvil.verboseLog("Is against $conflict") val conflicting = conflict.allowed(base, mat) - CustomAnvil.verboseLog("Was against ${conflict.getName()} and conflicting: $conflicting ") + CustomAnvil.verboseLog("Was against $conflict and conflicting: $conflicting ") if (!conflicting) { if (conflict.getEnchants().size <= 1) { result = ConflictType.SMALL_CONFLICT diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/interfaces/Named.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/interfaces/Named.kt deleted file mode 100644 index e3cd288..0000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/interfaces/Named.kt +++ /dev/null @@ -1,7 +0,0 @@ -package xyz.alexcrea.cuanvil.interfaces - -interface Named { - - fun getName(): String - -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt index fbd2866..9be7c67 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt @@ -5,7 +5,6 @@ import org.bukkit.configuration.ConfigurationSection import org.bukkit.inventory.ItemStack import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant -import xyz.alexcrea.cuanvil.interfaces.Named class AnvilCustomRecipe( private val name: String, @@ -18,7 +17,7 @@ class AnvilCustomRecipe( var leftItem: ItemStack?, var rightItem: ItemStack?, var resultItem: ItemStack?, -): Named { +) { // Static config name companion object { @@ -162,7 +161,7 @@ class AnvilCustomRecipe( return true } - override fun getName(): String { + override fun toString(): String { return name } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt index 614116d..6e0e270 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt @@ -127,7 +127,10 @@ object MetricsUtil { isDefaultItemGroupsConfig = false } else if (ConfigHolder.UNIT_REPAIR_HOLDER.equals(holder)) { isDefaultUnitRepairItemConfig = false + } else if (ConfigHolder.CUSTOM_RECIPE_HOLDER.equals(holder)) { + isDefaultCustomAnvilCraftConfig = false } + } fun addCustomMetric(metric: Metrics) {