diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PlatformUtil.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PlatformUtil.kt index 3b47adaa..f1d6fe42 100644 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PlatformUtil.kt +++ b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PlatformUtil.kt @@ -112,6 +112,26 @@ object PlatformUtil { return true } + return false + } /** + * Try to send paper component to the player + * + * @param component The used component + * @return true if sent, else otherwise + */ + + /** + * Try to set component lore of an item + * + * @param components The used component lore + * @return true if sent, else otherwise + */ + fun ItemMeta.setPaperLore(components: List): Boolean { + if(isPaper) { + this.lore(components) + return true + } + return false } 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 index 66dd9363..75cdf236 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/AbstractAskGui.java @@ -10,13 +10,15 @@ 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 xyz.alexcrea.cuanvil.lang.Message; public abstract class AbstractAskGui extends ChestGui { protected PatternPane pane; - AbstractAskGui(int rows, @NotNull String name, + AbstractAskGui(int rows, + @NotNull Message name, @NotNull String param, Gui backOnCancel){ - super(rows, name, CustomAnvil.instance); + super(rows, name.textHolder(param), CustomAnvil.instance); Pattern pattern = getGuiPattern(); this.pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java index 0b5a08e7..b570e1d5 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java @@ -9,21 +9,25 @@ import org.bukkit.entity.HumanEntity; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.lang.Message; +import xyz.alexcrea.cuanvil.lang.MsgError; import xyz.alexcrea.cuanvil.lang.MsgUI; -import xyz.alexcrea.cuanvil.util.MetricsUtil; +import xyz.alexcrea.cuanvil.util.ComponentUtil; -import java.util.Arrays; +import java.awt.*; import java.util.function.Supplier; import java.util.logging.Level; public class ConfirmActionGui extends AbstractAskGui { - public ConfirmActionGui(@NotNull String title, String actionDescription, + public ConfirmActionGui(@NotNull Message title, @NotNull String titleParam, + @Nullable Message actionDescription, @NotNull String actionParam, Gui backOnCancel, Gui backOnConfirm, Supplier onConfirm, boolean permanent) { - super(3, title, backOnCancel); + super(3, title, titleParam, backOnCancel); // Save item this.pane.bindItem('S', new GuiItem( @@ -42,8 +46,7 @@ public class ConfirmActionGui extends AbstractAskGui { try { success = onConfirm.get(); } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e); - MetricsUtil.INSTANCE.trackError(e); + CustomAnvil.Companion.logError(MsgError.INSTANCE.getCONFIRM_ACTION_GENERIC().unformatted(), e, true, Level.WARNING); success = false; } @@ -57,19 +60,21 @@ public class ConfirmActionGui extends AbstractAskGui { // Info item ItemStack infoItem = new ItemStack(Material.PAPER); ItemMeta infoMeta = infoItem.getItemMeta(); + assert infoMeta != null; - infoMeta.setDisplayName("§eAre you sure ?"); + ComponentUtil.INSTANCE.setMessageName(infoMeta, MsgUI.INSTANCE.getCONFIRM_ACTION_ARE_YOU_SURE()); if(actionDescription != null){ - infoMeta.setLore(Arrays.asList(actionDescription.split("\n"))); + ComponentUtil.INSTANCE.applyLore(actionDescription.formatted(actionParam), infoMeta); } infoItem.setItemMeta(infoMeta); pane.bindItem('I', new GuiItem(infoItem, GuiGlobalActions.stayInPlace, CustomAnvil.instance)); } - public ConfirmActionGui(@NotNull String title, String actionDescription, + public ConfirmActionGui(@NotNull Message title, @NotNull String titleParam, + @Nullable Message actionDescription, @NotNull String actionParam, Gui backOnCancel, Gui backOnConfirm, Supplier onConfirm){ - this(title, actionDescription, backOnCancel, backOnConfirm, onConfirm, true); + this(title, titleParam, actionDescription, actionParam, backOnCancel, backOnConfirm, onConfirm, true); } 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 index f0369e6d..fc96c282 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java @@ -9,25 +9,27 @@ 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 xyz.alexcrea.cuanvil.lang.Message; import xyz.alexcrea.cuanvil.lang.MsgUI; +import xyz.alexcrea.cuanvil.util.ComponentUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil; -import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; public class SelectItemTypeGui extends AbstractAskGui { private ItemStack selectedItem; - public SelectItemTypeGui(@NotNull String title, - @NotNull String actionDescription, + public SelectItemTypeGui(@NotNull Message title, + @NotNull String titleParam, + @NotNull Message actionDescription, + @NotNull String descriptionParam, @NotNull Gui backOnCancel, @NotNull BiConsumer onSave, boolean materialOnly) { - super(3, title, backOnCancel); + super(3, title, titleParam, backOnCancel); this.selectedItem = null; // Save item @@ -47,7 +49,7 @@ public class SelectItemTypeGui extends AbstractAskGui { this.pane.bindItem('S', GuiGlobalItems.backgroundItem()); // Select item - ItemStack selectItem = setDisplayMeta(new ItemStack(Material.BARRIER), actionDescription); + ItemStack selectItem = setDisplayMeta(new ItemStack(Material.BARRIER), actionDescription, descriptionParam); AtomicReference selectGuiItem = new AtomicReference<>(); selectGuiItem.set(new GuiItem(selectItem, event -> { @@ -58,7 +60,7 @@ public class SelectItemTypeGui extends AbstractAskGui { ItemStack finalItem; if(materialOnly){ - finalItem = setDisplayMeta(new ItemStack(cursor.getType()), actionDescription); + finalItem = setDisplayMeta(new ItemStack(cursor.getType()), actionDescription, descriptionParam); }else{ finalItem = cursor.clone(); } @@ -76,14 +78,19 @@ public class SelectItemTypeGui extends AbstractAskGui { GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this); this.pane.bindItem('s', temporaryLeave); - } - private ItemStack setDisplayMeta(ItemStack item, String actionDescription){ + @NotNull + private ItemStack setDisplayMeta( + @NotNull ItemStack item, + @NotNull Message actionDescription, + @NotNull String param + ){ ItemMeta meta = item.getItemMeta(); + assert meta != null; - meta.setDisplayName("§ePlace an item here"); - meta.setLore(Arrays.asList(actionDescription.split("\n"))); + ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getSELECT_ITEM_TYPE_PLACE_HERE()); + ComponentUtil.INSTANCE.applyLore(actionDescription.formatted(param), meta); item.setItemMeta(meta); return item; diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java index 5583b382..198f2149 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/AbstractEnchantConfigGui.java @@ -9,6 +9,7 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry; import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.lang.Message; import java.util.Collection; import java.util.Collections; @@ -27,11 +28,11 @@ public abstract class AbstractEnchantConfigGui getRecipeLore(AnvilCustomRecipe recipe) { boolean shouldWork = recipe.validate(); - ArrayList lore = new ArrayList<>(); + ArrayList lore = new ArrayList<>();//TODO MESSAGE lore.add("§7Is valid: §" + (shouldWork ? "aYes" : "cNo")); lore.add("§7Exact count: §" + (recipe.getExactCount() ? "aYes" : "cNo")); lore.add("§7Recipe Level Cost: §e" + recipe.getLevelCostPerCraft()); @@ -90,7 +91,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui { NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java index 19d31d9f..673c2ec8 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/ElementListConfigGui.java @@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.lang.Message; import java.util.ArrayList; import java.util.Collection; @@ -32,16 +33,18 @@ public abstract class ElementListConfigGui extends ChestGui implements ValueU public static final int LIST_FILLER_LENGTH = 7; public static final int LIST_FILLER_HEIGHT = 4; - private final String namePrefix; + private final Message rawTitle; + private final String param; protected PatternPane backgroundPane; private Predicate filter = (t) -> true; private boolean hasDefaultFilter = true; - protected ElementListConfigGui(@NotNull String title, Gui parent) { - super(6, title, CustomAnvil.instance); - this.namePrefix = title; + protected ElementListConfigGui(@NotNull Message title, String param, Gui parent) { + super(6, title.textHolder(param, "", ""), CustomAnvil.instance); + this.rawTitle = title; + this.param = param; // Back item panel Pattern pattern = getBackgroundPattern(); @@ -259,13 +262,10 @@ public abstract class ElementListConfigGui extends ChestGui implements ValueU // and add actual page addPane(page); - // set title - StringBuilder title = new StringBuilder(this.namePrefix); + // intended parameter: (page/max_page) //TODO MESSAGE CHECK CHILDS int pagesSize = this.pages.size(); - if (pagesSize > 1) { - title.append(" (").append(pageID + 1).append('/').append(pagesSize).append(')'); - } - setTitle(title.toString()); + var title = this.rawTitle.textHolder(param, pageID + 1, pagesSize); + setTitle(title); super.show(humanEntity); 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 index 7bfffdf8..2406fddc 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java @@ -10,6 +10,7 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.lang.Message; import xyz.alexcrea.cuanvil.lang.MsgUI; import java.util.Arrays; @@ -20,14 +21,14 @@ public abstract class MappedElementListConfigGui extends ElementListConfig protected final HashMap elementGuiMap; - protected MappedElementListConfigGui(@NotNull String title, @NotNull Gui parent) { - super(title, parent); + protected MappedElementListConfigGui(@NotNull Message title, @NotNull String param, @NotNull Gui parent) { + super(title, param, parent); this.elementGuiMap = new HashMap<>(); } - protected MappedElementListConfigGui(@NotNull String title) { - this(title, MainConfigGui.getInstance()); + protected MappedElementListConfigGui(@NotNull Message title, @NotNull String param) { + this(title, param, MainConfigGui.getInstance()); } @Override 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 index d25d6e72..5d346a43 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java @@ -8,6 +8,7 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.lang.Message; import xyz.alexcrea.cuanvil.lang.MsgUI; import xyz.alexcrea.cuanvil.util.LazyValue; @@ -19,12 +20,20 @@ import java.util.function.Supplier; public abstract class MappedGuiListConfigGui> extends MappedElementListConfigGui { - protected MappedGuiListConfigGui(@NotNull String title) { - super(title); + protected MappedGuiListConfigGui(@NotNull Message title, @NotNull String param) { + super(title, param); } - protected MappedGuiListConfigGui(@NotNull String title, @NotNull Gui parent) { - super(title, parent); + protected MappedGuiListConfigGui(@NotNull Message title, @NotNull String param, @NotNull Gui parent) { + super(title, param, parent); + } + + protected MappedGuiListConfigGui(@NotNull Message title) { + super(title, ""); + } + + protected MappedGuiListConfigGui(@NotNull Message title, @NotNull Gui parent) { + super(title, "", parent); } @Override 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 index cb55ed08..b7bf0002 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/SettingGuiListConfigGui.java @@ -10,6 +10,7 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; +import xyz.alexcrea.cuanvil.lang.Message; import java.util.HashMap; import java.util.List; @@ -20,16 +21,26 @@ public abstract class SettingGuiListConfigGui guiItemMap; protected HashMap factoryMap; - protected SettingGuiListConfigGui(@NotNull String title, Gui parent) { - super(title, parent); + protected SettingGuiListConfigGui(@NotNull Message title, Gui parent) { + super(title, "", parent); this.guiItemMap = new HashMap<>(); this.factoryMap = new HashMap<>(); } - protected SettingGuiListConfigGui(@NotNull String title) { + protected SettingGuiListConfigGui(@NotNull Message title) { this(title, MainConfigGui.getInstance()); } + protected SettingGuiListConfigGui(@NotNull Message title, @NotNull String param, Gui parent) { + super(title, param, parent); + this.guiItemMap = new HashMap<>(); + this.factoryMap = new HashMap<>(); + } + + protected SettingGuiListConfigGui(@NotNull Message title, @NotNull String param) { + this(title, param, MainConfigGui.getInstance()); + } + @Override protected GuiItem prepareCreateNewItem() { ItemStack createItem = new ItemStack(Material.PAPER); 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 index be9a032d..fcbfa733 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java @@ -33,12 +33,16 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui { ItemMeta meta = itemStack.getItemMeta(); NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack); if (!(meta instanceof Damageable)) { - MsgUI.INSTANCE.getUNIT_REPAIR_ELEMENT_CANNOT_REPAIR_NEW().send(player); + MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_CANNOT_REPAIR().send(player); return; } if (type.equals(this.parentMaterial)) { - MsgUI.INSTANCE.getUNIT_REPAIR_ELEMENT_SAME_TYPE_NEW().send(player); + MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_SAME_TYPE().send(player); return; } @@ -94,7 +97,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui { event.setCancelled(true); + var type = CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()); EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui( - "§e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + "§5", + MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_ENCHANTMENTS(), type, this, this); enchantGui.show(event.getWhoClicked()); }, CustomAnvil.instance); this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), event -> { event.setCancelled(true); + var type = CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()); GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( - "§e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + " §3Groups", + MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_SUB_GROUPS(), type, this, this, 0); enchantGui.show(event.getWhoClicked()); }, CustomAnvil.instance); this.minBeforeActiveSettingFactory = new IntSettingsGui.IntSettingFactory( - "§8Minimum enchantment count", + "§8Minimum enchantment count",//TODO MESSAGE this, this.enchantConflict + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER, Arrays.asList( "§7Minimum enchantment count set to X mean only X enchantment can be put", @@ -137,8 +139,9 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl return success; }; - return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + "§c?", - "§7Confirm that you want to delete this conflict.", + var type = CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()); + return new ConfirmActionGui(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_TITLE(), type, + MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_DESCRIPTION(), type, this, this.parent, deleteSupplier ); } @@ -159,12 +162,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl // Prepare enchantment lore ArrayList enchantLore = new ArrayList<>(); - enchantLore.add("§7Allow you to select a list of §5Enchantments §7that this conflict should include"); + enchantLore.add("§7Allow you to select a list of §5Enchantments §7that this conflict should include");//TODO MESSAGE Set enchants = getSelectedEnchantments(); if (enchants.isEmpty()) { - enchantLore.add("§7There is no included enchantment for this conflict."); + enchantLore.add("§7There is no included enchantment for this conflict.");//TODO MESSAGE } else { - enchantLore.add("§7List of included enchantment for this conflict:"); + enchantLore.add("§7List of included enchantment for this conflict:");//TODO MESSAGE Iterator enchantIterator = enchants.iterator(); boolean greaterThanMax = enchants.size() > 5; @@ -175,7 +178,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl enchantLore.add("§7- §5" + formattedName); } if (greaterThanMax) { - enchantLore.add("§7And " + (enchants.size() - 4) + " more..."); + enchantLore.add("§7And " + (enchants.size() - 4) + " more...");//TODO MESSAGE } } @@ -188,7 +191,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl ItemMeta enchantMeta = enchantItem.getItemMeta(); assert enchantMeta != null; - enchantMeta.setDisplayName("§aSelect included §5Enchantments §aSettings"); + enchantMeta.setDisplayName("§aSelect included §5Enchantments §aSettings");//TODO MESSAGE enchantMeta.setLore(enchantLore); enchantItem.setItemMeta(enchantMeta); @@ -200,7 +203,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl ItemMeta groupMeta = groupItem.getItemMeta(); assert groupMeta != null; - groupMeta.setDisplayName("§aSelect Excluded §3Groups §aSettings"); + groupMeta.setDisplayName("§aSelect Excluded §3Groups §aSettings");//TODO MESSAGE groupMeta.setLore(groupLore); groupItem.setItemMeta(groupMeta); @@ -208,7 +211,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl this.groupSettingItem.setItem(groupItem); // Just in case this.pane.bindItem('M', this.minBeforeActiveSettingFactory.getItem(Material.COMMAND_BLOCK, - "Minimum Enchantment Count")); + "Minimum Enchantment Count"));//TODO MESSAGE update(); } @@ -246,7 +249,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl @Override public boolean setSelectedEnchantments(Set enchantments) { if (!this.shouldWork) { - CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed"); + CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed");//TODO MESSAGE return false; } @@ -264,7 +267,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl try { updateGuiValues(); } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, e); + CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, e);//TODO MESSAGE MetricsUtil.INSTANCE.trackError(e); } @@ -291,7 +294,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl @Override public boolean setSelectedGroups(Set groups) { if (!this.shouldWork) { - CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.toString() + " groups but sub config is destroyed"); + CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.toString() + " groups but sub config is destroyed");//TODO MESSAGE return false; } @@ -309,7 +312,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl try { updateGuiValues(); } catch (Exception e) { - CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, e); + CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, e);//TODO MESSAGE MetricsUtil.INSTANCE.trackError(e); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/GroupConfigSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/GroupConfigSubSettingGui.java index d26c33fe..ec8f8617 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/GroupConfigSubSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/GroupConfigSubSettingGui.java @@ -20,11 +20,11 @@ import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui; import xyz.alexcrea.cuanvil.gui.config.global.GroupConfigGui; import xyz.alexcrea.cuanvil.gui.config.settings.GroupSelectSettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.MaterialSelectSettingGui; -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.lang.MsgUI; import xyz.alexcrea.cuanvil.util.CasedStringUtil; +import xyz.alexcrea.cuanvil.util.ComponentUtil; import java.util.*; import java.util.function.Consumer; @@ -40,8 +40,7 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen public GroupConfigSubSettingGui( @NotNull GroupConfigGui parent, @NotNull IncludeGroup group) { - super(3, - "§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " §rConfig"); + super(3, CasedStringUtil.snakeToUpperSpacedCase(group.getName())); this.parent = parent; this.group = group; @@ -65,39 +64,49 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen // Delete item ItemStack deleteItem = new ItemStack(Material.RED_TERRACOTTA); ItemMeta deleteMeta = deleteItem.getItemMeta(); + assert deleteMeta != null; - deleteMeta.setDisplayName("§4DELETE GROUP"); - deleteMeta.setLore(Collections.singletonList("§cCaution with this button !")); + ComponentUtil.INSTANCE.setMessageName(deleteMeta, MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_BUTTON_NAME()); + ComponentUtil.INSTANCE.applyLore( + MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_BUTTON_LORE().formatted(), + deleteMeta + ); deleteItem.setItemMeta(deleteMeta); this.pane.bindItem('D', new GuiItem(deleteItem, openGuiAndCheckAction(), CustomAnvil.instance)); // Displayed item will be updated later - String materialSelectionName = "§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " §rMaterials"; + var materialSelectionName = MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_SELECTED_MATERIALS(); + var name = CasedStringUtil.snakeToUpperSpacedCase(group.getName()); + ItemStack selectItem = new ItemStack(Material.DIAMOND_SWORD); ItemMeta selectItemMeta = selectItem.getItemMeta(); - selectItemMeta.setDisplayName(materialSelectionName); + assert selectItemMeta != null; + + ComponentUtil.INSTANCE.setMessageName(selectItemMeta, materialSelectionName, name); selectItem.setItemMeta(selectItemMeta); this.materialSelection = new GuiItem(selectItem, (event) -> { event.setCancelled(true); MaterialSelectSettingGui selectGui = new MaterialSelectSettingGui(this, - materialSelectionName + materialSelectionName, name , this); selectGui.show(event.getWhoClicked()); }, CustomAnvil.instance); - String selectGroupName = "§e" + CasedStringUtil.snakeToUpperSpacedCase(this.group.getName()) + " §rGroups"; + var selectGroupName = MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_SELECTED_SUB_GROUPS(); ItemStack selectGroup = new ItemStack(Material.CHEST); ItemMeta selectGroupMeta = selectGroup.getItemMeta(); - selectGroupMeta.setDisplayName(selectGroupName); + assert selectGroupMeta != null; + + ComponentUtil.INSTANCE.setMessageName(selectGroupMeta, selectGroupName, name); selectGroup.setItemMeta(selectGroupMeta); this.groupSelection = new GuiItem(selectGroup, (event) -> { event.setCancelled(true); GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( - selectGroupName, + selectGroupName, name, this, this, 0); enchantGui.show(event.getWhoClicked()); }, CustomAnvil.instance); @@ -152,8 +161,9 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen return success; }; - return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.group.toString()) + "§c?", - "§7Confirm that you want to delete this group.", + var type = CasedStringUtil.snakeToUpperSpacedCase(this.group.toString()); + return new ConfirmActionGui(MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_TITLE(), type, + MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_DESCRIPTION(), type, this, this.parent, deleteSupplier ); } @@ -226,7 +236,8 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen ItemStack matSelectItem = this.materialSelection.getItem(); ItemMeta matSelectMeta = matSelectItem.getItemMeta(); - matSelectMeta.setDisplayName("§aSelect included §eMaterials §aSettings"); + assert matSelectMeta != null; + matSelectMeta.setDisplayName("§aSelect included §eMaterials §aSettings");//TODO MESSAGE matSelectMeta.setLore(matLore); matSelectMeta.addItemFlags(ItemFlag.values()); @@ -238,7 +249,8 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen ItemStack groupSelectItem = this.groupSelection.getItem(); ItemMeta groupSelectMeta = groupSelectItem.getItemMeta(); - groupSelectMeta.setDisplayName("§aSelect included §3Groups §aSettings"); + assert groupSelectMeta != null; + groupSelectMeta.setDisplayName("§aSelect included §3Groups §aSettings");//TODO MESSAGE groupSelectMeta.setLore(groupLore); groupSelectItem.setItemMeta(groupSelectMeta); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java index 1d867812..935e8671 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/elements/MappedToListSubSettingGui.java @@ -1,18 +1,18 @@ package xyz.alexcrea.cuanvil.gui.config.list.elements; -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 io.delilaheve.CustomAnvil; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; +import xyz.alexcrea.cuanvil.lang.MsgUI; public abstract class MappedToListSubSettingGui extends ChestGui implements ValueUpdatableGui, ElementMappedToListGui { protected MappedToListSubSettingGui( int rows, - @NotNull String title) { - super(rows, title, CustomAnvil.instance); + @NotNull String type) { + super(rows, MsgUI.INSTANCE.getSHARED_TYPED_CONFIG_TITLE().textHolder(type), CustomAnvil.instance); } @Override diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java index 4473eb29..54251a61 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantSelectSettingGui.java @@ -20,6 +20,7 @@ import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer; import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.lang.Message; import xyz.alexcrea.cuanvil.util.CasedStringUtil; import java.util.*; @@ -35,8 +36,10 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui(enchantContainer.getSelectedEnchantments()); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/GroupSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/GroupSelectSettingGui.java index 578ca89e..2db12c20 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/GroupSelectSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/GroupSelectSettingGui.java @@ -19,6 +19,7 @@ import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer; import xyz.alexcrea.cuanvil.gui.config.list.ElementListConfigGui; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.lang.Message; import xyz.alexcrea.cuanvil.util.CasedStringUtil; import java.util.Collections; @@ -34,8 +35,10 @@ public class GroupSelectSettingGui extends AbstractSettingGui { Set selectedGroups; - public GroupSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectGroupContainer groupContainer, int page) { - super(6, title, parent); + public GroupSelectSettingGui( + @NotNull Message title, @NotNull String param, + ValueUpdatableGui parent, SelectGroupContainer groupContainer, int page) { + super(6, title.textHolder(param), parent); this.groupContainer = groupContainer; //Not used but planned this.page = page; diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java index 0f5759e0..102e1c9f 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/MaterialSelectSettingGui.java @@ -18,6 +18,7 @@ import xyz.alexcrea.cuanvil.gui.config.list.MappedElementListConfigGui; 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.lang.Message; import xyz.alexcrea.cuanvil.lang.MsgUI; import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil; @@ -38,9 +39,10 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui { removeMaterial(material); diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index 7ff46191..d9dfa0a4 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -161,7 +161,7 @@ open class CustomAnvil : JavaPlugin() { // Load language try { - Lang.reload() + Lang.loadDefault() } catch (e: Exception) { logError("error occurred loading language file", e) if(tryDirtyStart()) return diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt index 7d1b745c..8503fc74 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt @@ -23,10 +23,8 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe import xyz.alexcrea.cuanvil.util.CasedStringUtil import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeLegacy -import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir -import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair import xyz.alexcrea.cuanvil.util.anvil.AnvilColorUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt index 5c7bfee6..d42c8d22 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt @@ -9,11 +9,16 @@ import net.md_5.bungee.api.chat.hover.content.Text import org.bukkit.command.Command import org.bukkit.command.CommandSender import org.bukkit.entity.Player +import xyz.alexcrea.cuanvil.lang.Lang import xyz.alexcrea.cuanvil.lang.Message import xyz.alexcrea.cuanvil.lang.MsgCommand +import xyz.alexcrea.cuanvil.lang.MsgError +import xyz.alexcrea.cuanvil.lang.MsgUI +import xyz.alexcrea.cuanvil.lang.MsgWarning import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain +import java.util.Locale -class DebugToggleExecutor : CASubCommand { +class DebugToggleExecutor: CASubCommand { override fun description(): Message { return MsgCommand.DEBUG_DESCRIPTION @@ -51,6 +56,10 @@ class DebugToggleExecutor : CASubCommand { MsgCommand.DEBUG_LOG_CLEARED.send(sender) } + "lang" -> { + executeLanguageDebug(sender, args) + } + else -> { MsgCommand.SHARED_UNKNOWN_SUB_COMMAND.send(sender) return false @@ -106,14 +115,142 @@ class DebugToggleExecutor : CASubCommand { } } + private fun executeLanguageDebug(sender: CommandSender, args: Array) { + if(args.size > 1 && "details".contentEquals(args[1], ignoreCase = true)) + detailedLangDebug(sender) + else + simpleLangDebug(sender) + + } + + private fun simpleLangDebug(sender: CommandSender) { + var validCount = 0 + // load key from all provider class + MsgCommand.DEBUG_DATA_HEADER + MsgUI.SHARED_CONFIG_NO_EDIT_PERM + MsgError.LOAD_LISTENERS + MsgWarning.ANVIL_GENERIC_EXCEPTION + + val registeredKeys = Message.getValues() + + for(message in registeredKeys) + if(Lang.has(message.key)) validCount++ + + val valid = (100.0 * validCount) / registeredKeys.size + sender.sendMessage("Translated (${Lang.currentLang()}): ${"%.1f".format(Locale.ROOT, valid)}% ($validCount/${registeredKeys.size})") + } + + private fun detailedLangDebug(sender: CommandSender) { + simpleLangDebug(sender) + + val stb = StringBuilder("Report of potential issue for language ${Lang.currentLang()}:\n") + + var hadAny = false + val keySet = mutableSetOf() + val registeredKeys = Message.getValues() + + for(message in registeredKeys) { + val key = message.key + if(!Lang.has(key)) { + stb.append("Missing key inside translation file: $key\n") + hadAny = true + } else if(hashParamIssue(message, stb)) + hadAny = true + + if(keySet.contains(key)) { + stb.append("Duplicate registered key: $key\n") + hadAny = true + } else keySet.add(key) + } + + for(key in Lang.getKeys()) { + if(!keySet.contains(key)) { + stb.append("Found unregistered key: $key\n") + hadAny = true + } + } + + if(hadAny) { + val message = TextComponent(MsgCommand.DEBUG_LANG_COPY.legacy()) + + message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString()) + message.hoverEvent = HoverEvent( + HoverEvent.Action.SHOW_TEXT, + Text(MsgCommand.SHARED_HOVER_COPY.legacy()) + ) + + sender.spigot().sendMessage(message); + } else { + sender.sendMessage("No additional issue found") + } + } + + private fun hashParamIssue(message: Message, stb: StringBuilder): Boolean { + val section = Lang.getSection(message.key) + val texts = if(section == null) + listOf(Lang.getTranslated(message.key)) + else + section.getValues(false).map { it.value.toString() } + + val textParams = ArrayList() + + for(text in texts) { + var index = 0 + while(true) { + index = text.indexOf('%', index) + //TODO add \% to "ignore" % as param inside param finder + if(index > 0 && text[index-1] == '\\') { + index++ + continue + } + if(index++ < 0) break + + var end = text.indexOf(' ', index) + if(end == -1) end = text.length + val param = text.substring(index, end) + if(!textParams.contains(param)) textParams.add(param) + } + } + + var hadIssue = false + // Check all parameter are valid + val usedParam = mutableSetOf() + for(textParam in textParams) { + var found = false + for(param in message.params) { + if(param.isEmpty()) continue + if(textParam.startsWith(param)) { + found = true + usedParam.add(param) + break + } + } + + if(!found) { + hadIssue = true + stb.append("Did not found param %$textParam in register list for ${message.key}\n") + } + } + + for(param in message.params) { + if(usedParam.contains(param)) continue + if("unused".contentEquals(param)) continue + hadIssue = true + stb.append("Param %$param is not used for key ${message.key}\n") + } + + return hadIssue + } + override fun tabCompleter(sender: CommandSender, args: Array, list: MutableList) { if(!allowed(sender)) return list.addAll( when(args.size) { - 1 -> listOf("toggle", "get", "get-and-clear", "clear") + 1 -> listOf("toggle", "get", "get-and-clear", "clear", "lang") 2 -> when(args[0].lowercase()) { "toggle" -> listOf("default", "verbose") + "lang" -> listOf("details") else -> listOf() } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt index f5b92b62..9b0bae17 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -62,7 +62,7 @@ class ReloadExecutor : CASubCommand { if(!ConfigHolder.reloadAllFromDisk(hardfail)) return false // reload language config - Lang.reload() + if(!Lang.reload()) return false // Then update all global gui containing value from config BasicConfigGui.getInstance()?.updateGuiValues() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt index e12aed14..8c22d880 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt @@ -3,7 +3,6 @@ package xyz.alexcrea.cuanvil.dependency import io.delilaheve.CustomAnvil import net.kyori.adventure.text.Component import org.bukkit.Bukkit -import org.bukkit.ChatColor import org.bukkit.command.CommandSender import org.bukkit.entity.HumanEntity import org.bukkit.entity.Player @@ -32,7 +31,6 @@ import xyz.alexcrea.cuanvil.lang.MsgWarning import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError import java.lang.IllegalStateException -import java.util.logging.Level @Suppress("UnstableApiUsage") object DependencyManager { @@ -166,7 +164,7 @@ object DependencyManager { trackError(e) // Finally, warn the player - MsgWarning.DEPENDENCY_GENERIC_EXCEPTION.send(target) + MsgWarning.ANVIL_GENERIC_EXCEPTION.send(target) } private fun logExceptionAndClear(view: AnvilView, e: Exception) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt index 18be75f6..b559af19 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt @@ -3,13 +3,30 @@ package xyz.alexcrea.cuanvil.lang import io.delilaheve.CustomAnvil import org.bukkit.configuration.ConfigurationSection import xyz.alexcrea.cuanvil.config.ConfigHolder +import java.util.stream.Stream object Lang { - private val default = Language(DEFAULT_LANG, false) - private var lang = default + private lateinit var default: Language + private lateinit var lang: Language - fun reload() { + fun loadDefault() { + default = Language(DEFAULT_LANG, false) + lang = default + reload() + } + + fun reload(): Boolean { + try { + unsafeReload() + return true + } catch(e: Exception) { + CustomAnvil.logError("Error loading language $langID", e, false) + return false + } + } + + private fun unsafeReload() { val langID = langID if(lang.name == langID && lang != default) lang.reload() @@ -35,6 +52,18 @@ object Lang { return default.getSection(key) } + fun currentLang(): String { + return lang.name + } + + fun has(key: String): Boolean { + return lang.has(key) + } + + fun getKeys(): Collection { + return lang.getFilteredKeys() + } + /* * Config Options & get */ diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt index 0a008bf0..88b36b99 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt @@ -55,6 +55,45 @@ class Language(private val id: String, private val default: Boolean = false) { return conf.getConfigurationSection(key) } + fun has(key: String): Boolean { + if(conf.isString(key)) return true + + // we want at all child key as valid numbers and valid key if claimed to be multi line + val section = getSection(key) ?: return false + for(key in section.getKeys(false)) { + if(key.toUIntOrNull() == null) return false + if(!section.isString(key)) return false + } + + return true + } + + fun getFilteredKeys(): Collection { + val result = ArrayList() + + // First pass we ignore key from root + for(root in conf.getKeys(false)) { + val section = conf.getConfigurationSection(root) ?: continue + + exploreDeeper(section, root, result) + } + + return result + } + + private fun exploreDeeper(section: ConfigurationSection, root: String, result: ArrayList) { + for(key in section.getKeys(false)) { + val newRoot = "$root.$key" + if(has(key)) { + result.add(newRoot) + continue + } + + val newSection = section.getConfigurationSection(key) ?: continue + exploreDeeper(newSection, newRoot, result) + } + } + val name: String get() = conf.getString("name", id)!! } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt index 5e9276d3..64d9242d 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt @@ -1,5 +1,7 @@ package xyz.alexcrea.cuanvil.lang +import com.github.stefvanschie.inventoryframework.adventuresupport.ComponentHolder +import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder import io.delilaheve.CustomAnvil import net.kyori.adventure.text.Component import org.bukkit.command.CommandSender @@ -8,10 +10,23 @@ import xyz.alexcrea.cuanvil.util.ComponentUtil.send import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeLegacy import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.MiniMessageUtil +import java.util.Collections import java.util.logging.Level import kotlin.math.min -open class Message(val key: String, vararg val params: String) { +open class Message(val key: String, vararg val params: String, register: Boolean = true) { + + companion object { + private val values = ArrayList() + + fun getValues(): Collection { + return Collections.unmodifiableCollection(values) + } + } + + init { + if(register) values.add(this) + } protected fun replaceParameters(stb: StringBuilder, vararg values: Any) { // replace all placeholder thingy %key -> value @@ -22,6 +37,7 @@ open class Message(val key: String, vararg val params: String) { for(i in 0 until min(params.size, values.size)) { val key = params[i] val replacement = values[i].toString() + if(replacement.isEmpty()) continue //May not be good but can be changed if cause an issue var current = 0 while(true) { @@ -77,9 +93,11 @@ open class Message(val key: String, vararg val params: String) { result.add(MiniMessageUtil.mm.deserialize(stb.toString())) } + if(result.isEmpty()) return listOf(Component.text(key)) return result } + // return a list of AT LEAST 1 element. calling first is safe fun formatted(vararg params: Any): List { val section = Lang.getSection(key) if(section != null) return formattedMultiline(section, *params) @@ -89,6 +107,21 @@ open class Message(val key: String, vararg val params: String) { return listOf(MiniMessageUtil.mm.deserialize(translated)) } + fun formattedConcatenated(vararg params: Any): Component { + val formated = formatted(*params) + + var result = formated.first() + for(i in 1 until formated.size) { + result = result.appendNewline().append(formated[i]) + } + + return result + } + + fun textHolder(vararg params: Any): TextHolder { + return ComponentHolder.of(formattedConcatenated(*params)) + } + fun legacy(vararg params: Any): String { val formated = formatted(*params) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt deleted file mode 100644 index 7823f79d..00000000 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt +++ /dev/null @@ -1,4 +0,0 @@ -package xyz.alexcrea.cuanvil.lang - -object Msg { -} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt index 2eed326b..d135634e 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt @@ -20,6 +20,7 @@ object MsgCommand { val DEBUG_LOG_CLEARED = Message("debug.log-cleared") val DEBUG_TOGGLED = Message("debug.toggled", "type") val DEBUG_COPY = Message("debug.copy") + val DEBUG_LANG_COPY = Message("debug.copy-lang") val DEBUG_DATA_HEADER = Message("debug.data.header") val DEBUG_DATA_LINE_COUNT = Message("debug.data.line-count", "count") @@ -45,8 +46,8 @@ object MsgCommand { // Enchant val ENCHANT_DESCRIPTION = Message("enchant.description") - val ENCHANT_REMOVE = Message("enchant.remove.", "name") - val ENCHANT_SET = Message("enchant.set.", "name", "level") + val ENCHANT_REMOVE = Message("enchant.removed", "name") + val ENCHANT_SET = Message("enchant.set", "name", "level") val ENCHANT_MISSING_PARAMETER_WARNING = Message("enchant.warning.missing_parameter") val ENCHANT_NOT_FOUND_WARNING = Message("enchant.warning.not_found", "path") diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt index 6e5e26fb..f5d6e826 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt @@ -16,11 +16,14 @@ object MsgError { val LOAD_NON_DEFAULT_CONFIG = ErrorMessage("load.non-default-config") val RELOAD_FAIL = ErrorMessage("reload.resource.fail", "path") - val RELOAD_HARD_FAIL = ErrorMessage("reload.resource.hardfail") + val RELOAD_HARD_FAIL = ErrorMessage("reload.resource.hard-fail") /* - * ---------- - * Commands - * ---------- + * ---- + * UI + * ---- */ + val CONFIRM_ACTION_GENERIC = ErrorMessage("confirm-action.generic") + + } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt index c144f1fc..1a876e6e 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt @@ -5,17 +5,55 @@ import xyz.alexcrea.cuanvil.lang.UIMessage as Message object MsgUI { val SHARED_CONFIG_NO_EDIT_PERM = Message("shared.no-permission") + val SHARED_TYPED_CONFIG_TITLE = Message("shared.typed-config-title", "type") val CONFIRM_ACTION_FAILED = Message("confirm-action.fail") + val CONFIRM_ACTION_ARE_YOU_SURE = Message("confirm-action.is-user-sure") + + val SELECT_ITEM_TYPE_PLACE_HERE = Message("select-item-type.place-here") val ELEMENT_LIST_INSTRUCTION_NEW = Message("element-list.instruction-new", "type") val ELEMENT_LIST_CANCELLED_NEW = Message("element-list.cancelled-new", "type") val ELEMENT_LIST_DUPLICATED_NEW = Message("element-list.duplicated-new", "type") - val UNIT_REPAIR_ELEMENT_TITLE = Message("unit-repair.element.title") - val UNIT_REPAIR_ELEMENT_DESCRIPTION = Message("unit-repair.element.description") - val UNIT_REPAIR_ELEMENT_CANNOT_REPAIR_NEW = Message("unit-repair.element.cannot-damage-new") - val UNIT_REPAIR_ELEMENT_SAME_TYPE_NEW = Message("unit-repair.element.same-type-new") + val UNIT_REPAIR_TITLE = Message("unit-repair.title", "unused", "page", "max_page") + val UNIT_REPAIR_ELEMENT_TITLE = Message("unit-repair.element.title", "type", "page", "max_page") + val UNIT_REPAIR_NEW_TITLE = Message("unit-repair.new.title") + val UNIT_REPAIR_NEW_DESCRIPTION = Message("unit-repair.new.description") + val UNIT_REPAIR_NEW_ELEMENT_TITLE = Message("unit-repair.element.new.title", "unused") + val UNIT_REPAIR_NEW_ELEMENT_DESCRIPTION = Message("unit-repair.element.new.description", "name") + val UNIT_REPAIR_NEW_ELEMENT_CANNOT_REPAIR = Message("unit-repair.element.new.cannot-damage") + val UNIT_REPAIR_NEW_ELEMENT_SAME_TYPE = Message("unit-repair.element.new.same-type") + + val CUSTOM_RECIPE_TITLE = Message("custom-recipe.title", "unused", "page", "max_page") + + val CUSTOM_RECIPE_ELEMENT_DELETE_TITLE = Message("custom-recipe.element.delete.title", "type") + val CUSTOM_RECIPE_ELEMENT_DELETE_DESCRIPTION = Message("custom-recipe.element.delete.description", "unused") + + val ENCHANTMENT_LEVEL_COST_TITLE = Message("enchant-level-cost.title", "unused", "page", "max_page") + + val ENCHANTMENT_LEVEL_LIMIT_TITLE = Message("enchant-level-limit.title", "unused", "page", "max_page") + + val ENCHANTMENT_MERGE_LIMIT_TITLE = Message("enchant-merge-limit.title", "unused", "page", "max_page") + + val ENCHANTMENT_CONFLICT_TITLE = Message("enchant-conflict.title", "unused", "page", "max_page") + val ENCHANTMENT_CONFLICT_ELEMENT_ENCHANTMENTS = Message("enchant-conflict.element.selected-enchantments", "group") + val ENCHANTMENT_CONFLICT_ELEMENT_SUB_GROUPS = Message("enchant-conflict.element.selected-sub-groups", "group") + + val ENCHANTMENT_CONFLICT_ELEMENT_DELETE_TITLE = Message("enchant-conflict.element.delete.title", "type") + val ENCHANTMENT_CONFLICT_ELEMENT_DELETE_DESCRIPTION = Message("enchant-conflict.element.delete.description", "unused") + + val MATERIAL_GROUP_TITLE = Message("material-group.title", "unused", "page", "max_page") + val MATERIAL_GROUP_ELEMENT_SELECTED_MATERIALS = Message("material-group.element.selected-materials", "group") + val MATERIAL_GROUP_ELEMENT_SELECTED_SUB_GROUPS = Message("material-group.element.selected-sub-groups", "group") + + val MATERIAL_GROUP_ELEMENT_DELETE_TITLE = Message("material-group.element.delete.title", "type") + val MATERIAL_GROUP_ELEMENT_DELETE_DESCRIPTION = Message("material-group.element.delete.description", "unused") + val MATERIAL_GROUP_ELEMENT_DELETE_BUTTON_NAME = Message("material-group.element.delete.button.name") + val MATERIAL_GROUP_ELEMENT_DELETE_BUTTON_LORE = Message("material-group.element.delete.button.lore") + + val MATERIAL_SELECT_CONFIRM_TITLE = Message("material-select.new.confirm.title","name") + val MATERIAL_SELECT_CONFIRM_DESCRIPTION = Message("material-select.new.confirm.description","name") } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt index 486f589d..fb9d6e64 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt @@ -15,6 +15,6 @@ object MsgWarning { val LOAD_LEGACY_SPIGOT = Message("load.legacy.spigot") val LOAD_LEGACY_SPIGOT_OLD = Message("load.legacy.spigot-old") - val DEPENDENCY_GENERIC_EXCEPTION = Message("config-ui.shared.no-permission") + val ANVIL_GENERIC_EXCEPTION = Message("anvil.generic") } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt index 5f192c51..56f4e689 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt @@ -33,7 +33,6 @@ import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir -import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt index 2d9ec351..261e085a 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt @@ -2,10 +2,30 @@ package xyz.alexcrea.cuanvil.util import net.kyori.adventure.text.Component import org.bukkit.command.CommandSender +import org.bukkit.inventory.meta.ItemMeta import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.sendPaperMessage +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setPaperLore +import xyz.alexcrea.cuanvil.lang.Message object ComponentUtil { + fun Component.serializeMM(): String { + return MiniMessageUtil.mm.serialize(this) + } + + fun Component.serializeMMColor(): String { + return MiniMessageUtil.color_only_mm.serialize(this) + } + + fun Component.serializeLegacy(): String { + return MiniMessageUtil.legacy_mm.serialize(this) + } + + fun Component.serializePlain(): String { + return MiniMessageUtil.plain_text_mm.serialize(this) + } + fun Component.send(destination: CommandSender) { if(!destination.sendPaperMessage(this)) destination.sendMessage(this.serializeLegacy()) @@ -16,18 +36,13 @@ object ComponentUtil { component.send(destination) } - fun Component.serializeMM(): String { - return MiniMessageUtil.mm.serialize(this) - } - fun Component.serializeMMColor(): String { - return MiniMessageUtil.color_only_mm.serialize(this) - } - fun Component.serializeLegacy(): String { - return MiniMessageUtil.legacy_mm.serialize(this) - } - fun Component.serializePlain(): String { - return MiniMessageUtil.plain_text_mm.serialize(this) + fun List.applyLore(meta: ItemMeta) { + if(!meta.setPaperLore(this)) + meta.lore = this.map {obj -> obj.serializeLegacy()} } + fun ItemMeta.setMessageName(message: Message, vararg params: Any) { + this.setComponentDisplayName(message.formattedConcatenated(*params)) + } } \ No newline at end of file diff --git a/src/main/resources/lang/en.yml b/src/main/resources/lang/en.yml index 75483d16..87527ea1 100644 --- a/src/main/resources/lang/en.yml +++ b/src/main/resources/lang/en.yml @@ -14,6 +14,8 @@ warning: 1: "If replace too expensive is not working this is likely because of spigot" 2: "As native nms is not supported for spigot starting 26.1" update.available: "An update may be available: %version" + anvil: + generic: "[CustomAnvil] Error while handling the anvil." error: load: @@ -24,11 +26,15 @@ error: listeners: "error registering listeners" enchant-system: "error initializing enchantment system" non-default-config: "Plugin has an issue while trying to load non default config... exiting..." + reload: resource: fail: "Resource %path Could not be loaded or reloaded." hard-fail: "Disabling plugin." + confirm-action: + generic: "Could not process confirmation supplier." + command: shared: no-diag-permission: "You do not have permission to diagnostic this server" @@ -37,16 +43,19 @@ command: no-permission: "No permission to execute this command" warning: missing-subcmd: "Need to specify a subcommand. for example %example1 or %example2" + root: warning: unknown-sub: "Invalid subcommand. run `%command help` to see available commands" error: generic: "Error running this command" + debug: description: "Used to toggle debug logs and retrieve them" log-cleared: "Log Cleared" toggled: "Debug toggled to %type" copy: "Click to copy log data" + copy-lang: "Click to copy detailed lang issues" data: header: "Debug Log data:" line-count: "Found %count lines" @@ -54,10 +63,12 @@ command: unspecified-type: "Need to specify which type of debug to toggle: \"default\" or \"verbose\"" invalid-type: "Invalid debug type \"%type\"" no-log: "No log to show ? make sure you tried with debug log toggled (%command)" + diagnostic: description: "Basic diagnostic of this plugin" had-error: "There was an error running the diagnostic" copy: "Click to copy diagnostic data" + config: description: "Used to edit the configuration of the plugin" folia-issue: @@ -72,6 +83,7 @@ command: warning: legacy-name: "/ca gui has been moved to /ca config" cannot_configure: "Cannot configure the item in hand" + enchant: description: "Allows to set enchantment to holden item" warning: @@ -81,9 +93,11 @@ command: cannot_enchant: "Cannot enchant this item" removed: "%name removed" set: "%name set to level %level" + help: description: "Help command" header: "List of available commands:" + reload: description: "Reload the configuration of this plugin" start: "Reloading config..." @@ -94,19 +108,78 @@ command: config-ui: shared: no-permission: "You do not have permission to edit the config" + typed-config-title: "%type Config" + confirm-action: fail: "Action could not be completed." + is-user-sure: "Are you sure ?" + + select-item-type: + place-here: "Place an item here" + element-list: instruction-new: 1: "Write the %type name you want to create in the chat." 2: "Or write cancel to go back to %type config menu" cancelled-new: "%type creation cancelled..." duplicated-new: "Please enter a %type name that do not already exist..." + unit-repair: - element: - title: "Select item to be repaired." + title: "Unit Repair Config (%page/%max_page)" + new: + title: "Select unit repair item." description: 1: "Click here with an item to set the item" - 2: "You like to be repaired by %name" - cannot-damage-new: "This item can't be damaged, so it can't be repaired." - same-type-new: "Item can't repair something of the same type." \ No newline at end of file + 2: "You like to be an unit repair item" + element: + title: "%type Unit repair (%page/%max_page)" + new: + title: "Select item to be repaired." + description: + 1: "Click here with an item to set the item" + 2: "You like to be repaired by %name" + cannot-damage: "This item can't be damaged, so it can't be repaired." + same-type: "Item can't repair something of the same type." + + custom-recipe: + title: "Custom Recipe Config (%page/%max_page)" + element: + delete: + title: "Delete %type?" + description: "Confirm that you want to delete this recipe." + + enchant-level-cost: + title: "Enchantment Level Limit (%page/%max_page)" + + enchant-level-limit: + title: "Enchantment Level Limit (%page/%max_page)" + + enchant-merge-limit: + title: "Enchantment Maximum Merge Level (%page/%max_page)" + + enchant-conflict: + title: "Conflict Config (%page/%max_page)" + element: + selected-enchantments: "%group" # likely need page and max page + selected-sub-groups: "%group Groups" + delete: + title: "Delete %type?" + description: "Confirm that you want to delete this conflict." + + material-group: + title: "Group Config (%page/%max_page)" + element: + selected-materials: "%group Materials" + selected-sub-groups: "%group Groups" + delete: + title: "Delete %type?" + description: "Confirm that you want to delete this group." + button: + name: "DELETE GROUP" + lore: "Caution with this button !" + + material-select: + new: + confirm: + title: "Remove %name" + description: "Confirm Remove %name from this list."