Compare commits

...

11 commits

Author SHA1 Message Date
fbd3bf2eb2
add lang debug command and fix found translation issue 2026-08-17 13:56:12 +02:00
f373cae100
ask gui translatable 2026-08-17 13:56:12 +02:00
1d402b1e76
a lot of progress inside the ui 2026-08-17 13:56:12 +02:00
ec40889118
progress on translation system 2026-08-17 13:56:12 +02:00
58d363c4c7
fix small translation issue 2026-08-17 13:56:12 +02:00
b0a34b6b14
rework multiline 2026-08-17 13:56:12 +02:00
47e38bd23b
finished adding command text to trans file 2026-08-17 13:56:12 +02:00
cb6040df10
better translation system 2026-08-17 13:56:12 +02:00
c636767078
translation key for load errors and warnings 2026-08-17 13:56:11 +02:00
1f00a32750
language backend logic 2026-08-17 13:56:11 +02:00
4b8e71c5e9
fix creating new unit repair not working
Some checks failed
Java CI with Gradle / build (push) Has been cancelled
2026-08-17 13:56:01 +02:00
52 changed files with 1416 additions and 364 deletions

View file

@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.dependency.util
import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.inventory.ItemStack import org.bukkit.command.CommandSender
import org.bukkit.inventory.meta.ItemMeta import org.bukkit.inventory.meta.ItemMeta
// Mostly made for paper, spigot and folia support // Mostly made for paper, spigot and folia support
@ -100,4 +100,39 @@ object PlatformUtil {
} }
} }
/**
* Try to send paper component to the player
*
* @param component The used component
* @return true if sent, else otherwise
*/
fun CommandSender.sendPaperMessage(component: Component): Boolean {
if(isPaper) {
this.sendMessage(component)
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<Component>): Boolean {
if(isPaper) {
this.lore(components)
return true
}
return false
}
} }

View file

@ -10,13 +10,15 @@ import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
public abstract class AbstractAskGui extends ChestGui { public abstract class AbstractAskGui extends ChestGui {
protected PatternPane pane; protected PatternPane pane;
AbstractAskGui(int rows, @NotNull String name, AbstractAskGui(int rows,
@NotNull Message name, @NotNull String param,
Gui backOnCancel){ Gui backOnCancel){
super(rows, name, CustomAnvil.instance); super(rows, name.textHolder(param), CustomAnvil.instance);
Pattern pattern = getGuiPattern(); Pattern pattern = getGuiPattern();
this.pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern); this.pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern);

View file

@ -9,20 +9,25 @@ import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.util.MetricsUtil; import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgError;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.Arrays; import java.awt.*;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.logging.Level; import java.util.logging.Level;
public class ConfirmActionGui extends AbstractAskGui { 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<Boolean> onConfirm, Gui backOnCancel, Gui backOnConfirm, Supplier<Boolean> onConfirm,
boolean permanent) { boolean permanent) {
super(3, title, backOnCancel); super(3, title, titleParam, backOnCancel);
// Save item // Save item
this.pane.bindItem('S', new GuiItem( this.pane.bindItem('S', new GuiItem(
@ -33,7 +38,7 @@ public class ConfirmActionGui extends AbstractAskGui {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
@ -41,13 +46,12 @@ public class ConfirmActionGui extends AbstractAskGui {
try { try {
success = onConfirm.get(); success = onConfirm.get();
} catch (Exception e) { } catch (Exception e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e); CustomAnvil.Companion.logError(MsgError.INSTANCE.getCONFIRM_ACTION_GENERIC().unformatted(), e, true, Level.WARNING);
MetricsUtil.INSTANCE.trackError(e);
success = false; success = false;
} }
if (!success) { if (!success) {
event.getWhoClicked().sendMessage("§cAction could not be completed. "); MsgUI.INSTANCE.getCONFIRM_ACTION_FAILED().send(player);
} }
backOnConfirm.show(player); backOnConfirm.show(player);
@ -56,19 +60,21 @@ public class ConfirmActionGui extends AbstractAskGui {
// Info item // Info item
ItemStack infoItem = new ItemStack(Material.PAPER); ItemStack infoItem = new ItemStack(Material.PAPER);
ItemMeta infoMeta = infoItem.getItemMeta(); 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){ if(actionDescription != null){
infoMeta.setLore(Arrays.asList(actionDescription.split("\n"))); ComponentUtil.INSTANCE.applyLore(actionDescription.formatted(actionParam), infoMeta);
} }
infoItem.setItemMeta(infoMeta); infoItem.setItemMeta(infoMeta);
pane.bindItem('I', new GuiItem(infoItem, GuiGlobalActions.stayInPlace, CustomAnvil.instance)); 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<Boolean> onConfirm){ Gui backOnCancel, Gui backOnConfirm, Supplier<Boolean> onConfirm){
this(title, actionDescription, backOnCancel, backOnConfirm, onConfirm, true); this(title, titleParam, actionDescription, actionParam, backOnCancel, backOnConfirm, onConfirm, true);
} }

View file

@ -9,24 +9,27 @@ import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; 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.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; 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 xyz.alexcrea.cuanvil.util.MaterialUtil;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
public class SelectItemTypeGui extends AbstractAskGui { public class SelectItemTypeGui extends AbstractAskGui {
private ItemStack selectedItem; private ItemStack selectedItem;
public SelectItemTypeGui(@NotNull String title, public SelectItemTypeGui(@NotNull Message title,
@NotNull String actionDescription, @NotNull String titleParam,
@NotNull Message actionDescription,
@NotNull String descriptionParam,
@NotNull Gui backOnCancel, @NotNull Gui backOnCancel,
@NotNull BiConsumer<ItemStack, HumanEntity> onSave, @NotNull BiConsumer<ItemStack, HumanEntity> onSave,
boolean materialOnly) { boolean materialOnly) {
super(3, title, backOnCancel); super(3, title, titleParam, backOnCancel);
this.selectedItem = null; this.selectedItem = null;
// Save item // Save item
@ -36,7 +39,7 @@ public class SelectItemTypeGui extends AbstractAskGui {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
@ -46,7 +49,7 @@ public class SelectItemTypeGui extends AbstractAskGui {
this.pane.bindItem('S', GuiGlobalItems.backgroundItem()); this.pane.bindItem('S', GuiGlobalItems.backgroundItem());
// Select item // Select item
ItemStack selectItem = setDisplayMeta(new ItemStack(Material.BARRIER), actionDescription); ItemStack selectItem = setDisplayMeta(new ItemStack(Material.BARRIER), actionDescription, descriptionParam);
AtomicReference<GuiItem> selectGuiItem = new AtomicReference<>(); AtomicReference<GuiItem> selectGuiItem = new AtomicReference<>();
selectGuiItem.set(new GuiItem(selectItem, event -> { selectGuiItem.set(new GuiItem(selectItem, event -> {
@ -57,7 +60,7 @@ public class SelectItemTypeGui extends AbstractAskGui {
ItemStack finalItem; ItemStack finalItem;
if(materialOnly){ if(materialOnly){
finalItem = setDisplayMeta(new ItemStack(cursor.getType()), actionDescription); finalItem = setDisplayMeta(new ItemStack(cursor.getType()), actionDescription, descriptionParam);
}else{ }else{
finalItem = cursor.clone(); finalItem = cursor.clone();
} }
@ -75,14 +78,19 @@ public class SelectItemTypeGui extends AbstractAskGui {
GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this); GuiItem temporaryLeave = GuiGlobalItems.temporaryCloseGuiToSelectItem(Material.YELLOW_STAINED_GLASS_PANE, this);
this.pane.bindItem('s', temporaryLeave); 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(); ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§ePlace an item here"); ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getSELECT_ITEM_TYPE_PLACE_HERE());
meta.setLore(Arrays.asList(actionDescription.split("\n"))); ComponentUtil.INSTANCE.applyLore(actionDescription.formatted(param), meta);
item.setItemMeta(meta); item.setItemMeta(meta);
return item; return item;

View file

@ -9,6 +9,7 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -27,11 +28,11 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
* *
* @param title Title of the gui. * @param title Title of the gui.
*/ */
protected AbstractEnchantConfigGui(String title) { protected AbstractEnchantConfigGui(Message title) {
super(title); super(title);
} }
protected AbstractEnchantConfigGui(String title, Gui parent) { protected AbstractEnchantConfigGui(Message title, Gui parent) {
super(title, parent); super(title, parent);
} }

View file

@ -12,6 +12,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.elements.CustomRecipeSubSettingGui; import xyz.alexcrea.cuanvil.gui.config.list.elements.CustomRecipeSubSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
@ -36,13 +37,13 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
} }
private CustomRecipeConfigGui() { private CustomRecipeConfigGui() {
super("Custom Recipe Config"); super(MsgUI.INSTANCE.getCUSTOM_RECIPE_TITLE());
init(); init();
} }
public CustomRecipeConfigGui(Gui parent) { public CustomRecipeConfigGui(Gui parent) {
super("Custom Recipe Config", parent); super(MsgUI.INSTANCE.getCUSTOM_RECIPE_TITLE(), parent);
} }
@Override @Override
@ -60,7 +61,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
ItemMeta meta = displayedItem.getItemMeta(); ItemMeta meta = displayedItem.getItemMeta();
assert meta != null; assert meta != null;
meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(recipe.toString()) + " §fCustom recipe"); meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(recipe.toString()) + " §fCustom recipe");//TODO MESSAGE
meta.addItemFlags(ItemFlag.values()); meta.addItemFlags(ItemFlag.values());
meta.setLore(getRecipeLore(recipe)); meta.setLore(getRecipeLore(recipe));
@ -72,7 +73,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
private static @NotNull ArrayList<String> getRecipeLore(AnvilCustomRecipe recipe) { private static @NotNull ArrayList<String> getRecipeLore(AnvilCustomRecipe recipe) {
boolean shouldWork = recipe.validate(); boolean shouldWork = recipe.validate();
ArrayList<String> lore = new ArrayList<>(); ArrayList<String> lore = new ArrayList<>();//TODO MESSAGE
lore.add("§7Is valid: §" + (shouldWork ? "aYes" : "cNo")); lore.add("§7Is valid: §" + (shouldWork ? "aYes" : "cNo"));
lore.add("§7Exact count: §" + (recipe.getExactCount() ? "aYes" : "cNo")); lore.add("§7Exact count: §" + (recipe.getExactCount() ? "aYes" : "cNo"));
lore.add("§7Recipe Level Cost: §e" + recipe.getLevelCostPerCraft()); lore.add("§7Recipe Level Cost: §e" + recipe.getLevelCostPerCraft());
@ -90,7 +91,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
@Override @Override
protected String genericDisplayedName() { protected String genericDisplayedName() {
return "custom recipe"; return "custom recipe";//TODO MESSAGE
} }
@Override @Override

View file

@ -14,6 +14,7 @@ import xyz.alexcrea.cuanvil.group.IncludeGroup;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.elements.EnchantConflictSubSettingGui; import xyz.alexcrea.cuanvil.gui.config.list.elements.EnchantConflictSubSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Arrays; import java.util.Arrays;
@ -38,11 +39,11 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
// Need to init myself // Need to init myself
public EnchantConflictGui(Gui parent) { public EnchantConflictGui(Gui parent) {
super("Conflict Config", parent); super(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_TITLE(), parent);
} }
private EnchantConflictGui() { private EnchantConflictGui() {
super("Conflict Config"); super(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_TITLE());
init(); init();
} }
@ -80,8 +81,8 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
assert meta != null; assert meta != null;
meta.addItemFlags(ItemFlag.values()); meta.addItemFlags(ItemFlag.values());
meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(conflict.toString()) + " §fConflict"); meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(conflict.toString()) + " §fConflict"); //TODO MESSAGE
meta.setLore(Arrays.asList( meta.setLore(Arrays.asList(//TODO MESSAGE
"§7Enchantment count: §e" + conflict.getEnchants().size(), "§7Enchantment count: §e" + conflict.getEnchants().size(),
"§7Group count: §e" + conflict.getCantConflictGroup().getGroups().size(), "§7Group count: §e" + conflict.getCantConflictGroup().getGroups().size(),
"§7Min enchantments count: §e" + conflict.getMinBeforeBlock() "§7Min enchantments count: §e" + conflict.getMinBeforeBlock()
@ -98,7 +99,7 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
@Override @Override
protected String genericDisplayedName() { protected String genericDisplayedName() {
return "conflict"; return "conflict";//TODO MESSAGE
} }
@Override @Override

View file

@ -11,6 +11,7 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -36,7 +37,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
* Constructor of this Global gui for enchantment cost settings. * Constructor of this Global gui for enchantment cost settings.
*/ */
public EnchantCostConfigGui() { public EnchantCostConfigGui() {
super("§8Enchantment Level Cost"); super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_TITLE());
if (INSTANCE == null) INSTANCE = this; if (INSTANCE == null) INSTANCE = this;
init(); init();
@ -46,7 +47,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
* Constructor of this Global gui for enchantment cost settings. * Constructor of this Global gui for enchantment cost settings.
*/ */
public EnchantCostConfigGui(Gui parent) { public EnchantCostConfigGui(Gui parent) {
super("§8Enchantment Level Cost", parent); super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_TITLE(), parent);
} }
@Override @Override
@ -58,6 +59,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
String key = enchant.getKey().toString().toLowerCase(Locale.ENGLISH); String key = enchant.getKey().toString().toLowerCase(Locale.ENGLISH);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_")); String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
//TODO MESSAGE
return new EnchantCostSettingsGui.EnchantCostSettingFactory(prettyKey + " Cost", parent, return new EnchantCostSettingsGui.EnchantCostSettingFactory(prettyKey + " Cost", parent,
ENCHANT_VALUES_ROOT + '.' + key, ConfigHolder.DEFAULT_CONFIG, ENCHANT_VALUES_ROOT + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList( Arrays.asList(

View file

@ -9,6 +9,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Collections; import java.util.Collections;
@ -32,14 +33,14 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
* Constructor of this Global gui for enchantment level limit settings. * Constructor of this Global gui for enchantment level limit settings.
*/ */
public EnchantLimitConfigGui() { public EnchantLimitConfigGui() {
super("§8Enchantment Level Limit"); super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_LIMIT_TITLE());
if(INSTANCE == null) INSTANCE = this; if(INSTANCE == null) INSTANCE = this;
init(); init();
} }
public EnchantLimitConfigGui(Gui parent) { public EnchantLimitConfigGui(Gui parent) {
super("§8Enchantment Level Limit", parent); super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_LIMIT_TITLE(), parent);
} }
@Override @Override

View file

@ -9,6 +9,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Arrays; import java.util.Arrays;
@ -29,7 +30,7 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
* Constructor of this Global gui for enchantment level limit settings. * Constructor of this Global gui for enchantment level limit settings.
*/ */
public EnchantMergeLimitConfigGui() { public EnchantMergeLimitConfigGui() {
super("§8Enchantment Maximum Merge Level"); super(MsgUI.INSTANCE.getENCHANTMENT_MERGE_LIMIT_TITLE());
if(INSTANCE == null) INSTANCE = this; if(INSTANCE == null) INSTANCE = this;
init(); init();
@ -39,7 +40,7 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
* Constructor of this Global gui for enchantment level limit settings. * Constructor of this Global gui for enchantment level limit settings.
*/ */
public EnchantMergeLimitConfigGui(Gui parent) { public EnchantMergeLimitConfigGui(Gui parent) {
super("§8Enchantment Maximum Merge Level", parent); super(MsgUI.INSTANCE.getENCHANTMENT_MERGE_LIMIT_TITLE(), parent);
} }
@ -52,6 +53,7 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT); String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_")); String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
//TODO MESSAGE
return new IntSettingsGui.IntSettingFactory(prettyKey + " Merge Limit", parent, return new IntSettingsGui.IntSettingFactory(prettyKey + " Merge Limit", parent,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG, SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList( Arrays.asList(

View file

@ -15,6 +15,7 @@ import xyz.alexcrea.cuanvil.group.IncludeGroup;
import xyz.alexcrea.cuanvil.group.ItemGroupManager; import xyz.alexcrea.cuanvil.group.ItemGroupManager;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.elements.GroupConfigSubSettingGui; import xyz.alexcrea.cuanvil.gui.config.list.elements.GroupConfigSubSettingGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.LazyValue; import xyz.alexcrea.cuanvil.util.LazyValue;
@ -39,13 +40,13 @@ public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, MappedG
} }
public GroupConfigGui() { public GroupConfigGui() {
super("Group Config"); super(MsgUI.INSTANCE.getMATERIAL_GROUP_TITLE());
init(); init();
} }
public GroupConfigGui(Gui parent) { public GroupConfigGui(Gui parent) {
super("Group Config", parent); super(MsgUI.INSTANCE.getMATERIAL_GROUP_TITLE(), parent);
} }
@Override @Override

View file

@ -13,6 +13,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui; import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui; import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -38,13 +39,13 @@ public class UnitRepairConfigGui extends
} }
private UnitRepairConfigGui() { private UnitRepairConfigGui() {
super("Unit Repair Config"); super(MsgUI.INSTANCE.getUNIT_REPAIR_TITLE());
init(); init();
} }
public UnitRepairConfigGui(Gui parent) { public UnitRepairConfigGui(Gui parent) {
super("Unit Repair Config", parent); super(MsgUI.INSTANCE.getUNIT_REPAIR_TITLE(), parent);
} }
@Override @Override
@ -128,9 +129,8 @@ public class UnitRepairConfigGui extends
clickEvent.setCancelled(true); clickEvent.setCancelled(true);
new SelectItemTypeGui( new SelectItemTypeGui(
"Select unit repair item.", MsgUI.INSTANCE.getUNIT_REPAIR_NEW_TITLE(), "",
"§7Click here with an item to set the item\n" + MsgUI.INSTANCE.getUNIT_REPAIR_NEW_DESCRIPTION(), "",
"§7You like to be an unit repair item",
this, this,
(itemStack, player) -> { (itemStack, player) -> {
NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack); NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack);

View file

@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -32,16 +33,18 @@ public abstract class ElementListConfigGui<T> extends ChestGui implements ValueU
public static final int LIST_FILLER_LENGTH = 7; public static final int LIST_FILLER_LENGTH = 7;
public static final int LIST_FILLER_HEIGHT = 4; public static final int LIST_FILLER_HEIGHT = 4;
private final String namePrefix; private final Message rawTitle;
private final String param;
protected PatternPane backgroundPane; protected PatternPane backgroundPane;
private Predicate<T> filter = (t) -> true; private Predicate<T> filter = (t) -> true;
private boolean hasDefaultFilter = true; private boolean hasDefaultFilter = true;
protected ElementListConfigGui(@NotNull String title, Gui parent) { protected ElementListConfigGui(@NotNull Message title, String param, Gui parent) {
super(6, title, CustomAnvil.instance); super(6, title.textHolder(param, "", ""), CustomAnvil.instance);
this.namePrefix = title; this.rawTitle = title;
this.param = param;
// Back item panel // Back item panel
Pattern pattern = getBackgroundPattern(); Pattern pattern = getBackgroundPattern();
@ -259,13 +262,10 @@ public abstract class ElementListConfigGui<T> extends ChestGui implements ValueU
// and add actual page // and add actual page
addPane(page); addPane(page);
// set title // intended parameter: (page/max_page) //TODO MESSAGE CHECK CHILDS
StringBuilder title = new StringBuilder(this.namePrefix);
int pagesSize = this.pages.size(); int pagesSize = this.pages.size();
if (pagesSize > 1) { var title = this.rawTitle.textHolder(param, pageID + 1, pagesSize);
title.append(" (").append(pageID + 1).append('/').append(pagesSize).append(')'); setTitle(title);
}
setTitle(title.toString());
super.show(humanEntity); super.show(humanEntity);

View file

@ -10,6 +10,8 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -19,14 +21,14 @@ public abstract class MappedElementListConfigGui<T, S> extends ElementListConfig
protected final HashMap<T, S> elementGuiMap; protected final HashMap<T, S> elementGuiMap;
protected MappedElementListConfigGui(@NotNull String title, @NotNull Gui parent) { protected MappedElementListConfigGui(@NotNull Message title, @NotNull String param, @NotNull Gui parent) {
super(title, parent); super(title, param, parent);
this.elementGuiMap = new HashMap<>(); this.elementGuiMap = new HashMap<>();
} }
protected MappedElementListConfigGui(@NotNull String title) { protected MappedElementListConfigGui(@NotNull Message title, @NotNull String param) {
this(title, MainConfigGui.getInstance()); this(title, param, MainConfigGui.getInstance());
} }
@Override @Override
@ -52,13 +54,12 @@ public abstract class MappedElementListConfigGui<T, S> extends ElementListConfig
// check permission // check permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
player.closeInventory(); player.closeInventory();
player.sendMessage("§eWrite the " + genericDisplayedName() + " name you want to create in the chat.\n" + MsgUI.INSTANCE.getELEMENT_LIST_INSTRUCTION_NEW().send(player, genericDisplayedName());
"§eOr write §ccancel §eto go back to " + genericDisplayedName() + " config menu");
CustomAnvil.Companion.getChatListener().setListenedCallback(player, prepareCreateItemConsumer(player)); CustomAnvil.Companion.getChatListener().setListenedCallback(player, prepareCreateItemConsumer(player));

View file

@ -8,6 +8,8 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui; import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; 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; import xyz.alexcrea.cuanvil.util.LazyValue;
import java.util.Locale; import java.util.Locale;
@ -18,12 +20,20 @@ import java.util.function.Supplier;
public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui.LazyElement<?>> public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui.LazyElement<?>>
extends MappedElementListConfigGui<T, S> { extends MappedElementListConfigGui<T, S> {
protected MappedGuiListConfigGui(@NotNull String title) { protected MappedGuiListConfigGui(@NotNull Message title, @NotNull String param) {
super(title); super(title, param);
} }
protected MappedGuiListConfigGui(@NotNull String title, @NotNull Gui parent) { protected MappedGuiListConfigGui(@NotNull Message title, @NotNull String param, @NotNull Gui parent) {
super(title, parent); super(title, param, parent);
}
protected MappedGuiListConfigGui(@NotNull Message title) {
super(title, "");
}
protected MappedGuiListConfigGui(@NotNull Message title, @NotNull Gui parent) {
super(title, "", parent);
} }
@Override @Override
@ -69,13 +79,13 @@ public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui
// check permission // check permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
message = message.toLowerCase(Locale.ROOT); message = message.toLowerCase(Locale.ROOT);
if ("cancel".equalsIgnoreCase(message)) { if ("cancel".equalsIgnoreCase(message)) {
player.sendMessage(genericDisplayedName() + " creation cancelled..."); MsgUI.INSTANCE.getELEMENT_LIST_CANCELLED_NEW().send(player, genericDisplayedName());
show(player); show(player);
return; return;
} }
@ -86,7 +96,7 @@ public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui
// Not the most efficient on large number of conflict, but it should not run often. // Not the most efficient on large number of conflict, but it should not run often.
for (T generic : getDisplayableInstanceOfGeneric()) { for (T generic : getDisplayableInstanceOfGeneric()) {
if (generic.toString().equalsIgnoreCase(message)) { if (generic.toString().equalsIgnoreCase(message)) {
player.sendMessage("§cPlease enter a " + genericDisplayedName() + " name that do not already exist..."); MsgUI.INSTANCE.getELEMENT_LIST_DUPLICATED_NEW().send(player, genericDisplayedName());
// wait next message. // wait next message.
CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get()); CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get());
return; return;

View file

@ -10,6 +10,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import xyz.alexcrea.cuanvil.lang.Message;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -20,16 +21,26 @@ public abstract class SettingGuiListConfigGui<T, S extends SettingGui.SettingGui
protected HashMap<T, GuiItem> guiItemMap; protected HashMap<T, GuiItem> guiItemMap;
protected HashMap<T, S> factoryMap; protected HashMap<T, S> factoryMap;
protected SettingGuiListConfigGui(@NotNull String title, Gui parent) { protected SettingGuiListConfigGui(@NotNull Message title, Gui parent) {
super(title, parent); super(title, "", parent);
this.guiItemMap = new HashMap<>(); this.guiItemMap = new HashMap<>();
this.factoryMap = new HashMap<>(); this.factoryMap = new HashMap<>();
} }
protected SettingGuiListConfigGui(@NotNull String title) { protected SettingGuiListConfigGui(@NotNull Message title) {
this(title, MainConfigGui.getInstance()); 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 @Override
protected GuiItem prepareCreateNewItem() { protected GuiItem prepareCreateNewItem() {
ItemStack createItem = new ItemStack(Material.PAPER); ItemStack createItem = new ItemStack(Material.PAPER);

View file

@ -18,6 +18,7 @@ import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui;
import xyz.alexcrea.cuanvil.gui.config.settings.DoubleSettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.DoubleSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -32,12 +33,16 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
private boolean shouldWork = true; private boolean shouldWork = true;
private static String prettifiedName(NamespacedKey parentMaterial) {
return CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.getKey().toLowerCase());
}
public UnitRepairElementListGui(@NotNull NamespacedKey parentMaterial, public UnitRepairElementListGui(@NotNull NamespacedKey parentMaterial,
@NotNull UnitRepairConfigGui parentGui) { @NotNull UnitRepairConfigGui parentGui) {
super("§e" + CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.getKey().toLowerCase()) + " §rUnit repair"); super(MsgUI.INSTANCE.getUNIT_REPAIR_ELEMENT_TITLE(), prettifiedName(parentMaterial));
this.parentMaterial = parentMaterial; this.parentMaterial = parentMaterial;
this.parentGui = parentGui; this.parentGui = parentGui;
this.materialName = CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.getKey().toLowerCase()); this.materialName = prettifiedName(parentMaterial);
GuiGlobalItems.addBackItem(this.backgroundPane, parentGui); GuiGlobalItems.addBackItem(this.backgroundPane, parentGui);
} }
@ -61,20 +66,19 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
event.setCancelled(true); event.setCancelled(true);
new SelectItemTypeGui( new SelectItemTypeGui(
"Select item to be repaired.", MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_TITLE(), this.materialName,
"§7Click here with an item to set the item\n" + MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_DESCRIPTION(), this.materialName,
"§7You like to be repaired by " + this.materialName,
this, this,
(itemStack, player) -> { (itemStack, player) -> {
ItemMeta meta = itemStack.getItemMeta(); ItemMeta meta = itemStack.getItemMeta();
NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack); NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack);
if (!(meta instanceof Damageable)) { if (!(meta instanceof Damageable)) {
player.sendMessage("§cThis item can't be damaged, so it can't be repaired."); MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_CANNOT_REPAIR().send(player);
return; return;
} }
if (type.equals(this.parentMaterial)) { if (type.equals(this.parentMaterial)) {
player.sendMessage("§cItem can't repair something of the same type."); MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_SAME_TYPE().send(player);
return; return;
} }
@ -93,7 +97,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
// Display material edit setting // Display material edit setting
this.factoryMap.get(materialName).create().show(player); this.factoryMap.get(type).create().show(player);
}, },
true true
).show(event.getWhoClicked()); ).show(event.getWhoClicked());

View file

@ -19,6 +19,7 @@ import xyz.alexcrea.cuanvil.gui.config.settings.ItemSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager; import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
@ -36,7 +37,7 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
public CustomRecipeSubSettingGui( public CustomRecipeSubSettingGui(
@NotNull CustomRecipeConfigGui parent, @NotNull CustomRecipeConfigGui parent,
@NotNull AnvilCustomRecipe anvilRecipe) { @NotNull AnvilCustomRecipe anvilRecipe) {
super(4, "§e" + CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.toString()) + " §8Config"); super(4, CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.toString()));
this.parent = parent; this.parent = parent;
this.anvilRecipe = anvilRecipe; this.anvilRecipe = anvilRecipe;
@ -73,19 +74,19 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
ItemMeta deleteMeta = deleteItem.getItemMeta(); ItemMeta deleteMeta = deleteItem.getItemMeta();
assert deleteMeta != null; assert deleteMeta != null;
deleteMeta.setDisplayName("§4DELETE RECIPE"); deleteMeta.setDisplayName("§4DELETE RECIPE");//TODO MESSAGE
deleteMeta.setLore(Collections.singletonList("§cCaution with this button !")); deleteMeta.setLore(Collections.singletonList("§cCaution with this button !"));//TODO MESSAGE
deleteItem.setItemMeta(deleteMeta); deleteItem.setItemMeta(deleteMeta);
this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance)); this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance));
// Displayed item will be updated later // Displayed item will be updated later
IntRange costRange = AnvilCustomRecipe.Companion.getXP_COST_CONFIG_RANGE(); IntRange costRange = AnvilCustomRecipe.Companion.getXP_COST_CONFIG_RANGE();
this.exactCountFactory = new BoolSettingsGui.BoolSettingFactory("§8Exact count ?", this, this.exactCountFactory = new BoolSettingsGui.BoolSettingFactory("§8Exact count ?", this,//TODO MESSAGE
ConfigHolder.CUSTOM_RECIPE_HOLDER, ConfigHolder.CUSTOM_RECIPE_HOLDER,
this.anvilRecipe + "." + AnvilCustomRecipe.EXACT_COUNT_CONFIG, AnvilCustomRecipe.DEFAULT_EXACT_COUNT_CONFIG); this.anvilRecipe + "." + AnvilCustomRecipe.EXACT_COUNT_CONFIG, AnvilCustomRecipe.DEFAULT_EXACT_COUNT_CONFIG);
this.removeExactLinearXpFactory = new BoolSettingsGui.BoolSettingFactory("§8Remove exact linear xp ?", this, this.removeExactLinearXpFactory = new BoolSettingsGui.BoolSettingFactory("§8Remove exact linear xp ?", this,//TODO MESSAGE
ConfigHolder.CUSTOM_RECIPE_HOLDER, ConfigHolder.CUSTOM_RECIPE_HOLDER,
this.anvilRecipe + "." + AnvilCustomRecipe.REMOVE_EXACT_XP_CONFIG, AnvilCustomRecipe.DEFAULT_REMOVE_EXACT_XP_CONFIG); this.anvilRecipe + "." + AnvilCustomRecipe.REMOVE_EXACT_XP_CONFIG, AnvilCustomRecipe.DEFAULT_REMOVE_EXACT_XP_CONFIG);
@ -93,18 +94,18 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
assert meta != null; assert meta != null;
meta.setDisplayName("§cRemove exact linear xp ?"); meta.setDisplayName("§cRemove exact linear xp ?");//TODO MESSAGE
meta.setLore(Collections.singletonList("§7Not usable if linear cost is 0")); meta.setLore(Collections.singletonList("§7Not usable if linear cost is 0"));//TODO MESSAGE
item.setItemMeta(meta); item.setItemMeta(meta);
this.noRemoveExactLinearXp = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); this.noRemoveExactLinearXp = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
this.levelCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Level Cost", this, this.levelCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Level Cost", this,//TODO MESSAGE
this.anvilRecipe + "." + AnvilCustomRecipe.XP_LEVEL_COST_CONFIG, this.anvilRecipe + "." + AnvilCustomRecipe.XP_LEVEL_COST_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER, ConfigHolder.CUSTOM_RECIPE_HOLDER,
null, null,
costRange.getFirst(), costRange.getLast(), AnvilCustomRecipe.DEFAULT_XP_LEVEL_COST_CONFIG, 1, 5, 10); costRange.getFirst(), costRange.getLast(), AnvilCustomRecipe.DEFAULT_XP_LEVEL_COST_CONFIG, 1, 5, 10);
this.linearXpCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Linear Xp Cost", this, this.linearXpCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Linear Xp Cost", this,//TODO MESSAGE
this.anvilRecipe + "." + AnvilCustomRecipe.LINEAR_XP_COST_CONFIG, this.anvilRecipe + "." + AnvilCustomRecipe.LINEAR_XP_COST_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER, ConfigHolder.CUSTOM_RECIPE_HOLDER,
null, null,
@ -117,21 +118,21 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
ConfigHolder.CUSTOM_RECIPE_HOLDER, ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG(), AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG(),
"§7Set the left item of the custom craft", "§7Set the left item of the custom craft",
"§7\u25A0 + \u25A1 = \u25A1"); "§7■ + □ = □");//TODO MESSAGE
this.rightItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Right §8Item", this, this.rightItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Right §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.RIGHT_ITEM_CONFIG, this.anvilRecipe + "." + AnvilCustomRecipe.RIGHT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER, ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG(), AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG(),
"§7Set the right item of the custom craft", "§7Set the right item of the custom craft",
"§7\u25A1 + \u25A0 = \u25A1"); "§7□ + ■ = □");//TODO MESSAGE
this.resultItemFactory = new ItemSettingGui.ItemSettingFactory("§aRecipe Result §8Item", this, this.resultItemFactory = new ItemSettingGui.ItemSettingFactory("§aRecipe Result §8Item", this,
this.anvilRecipe + "." + AnvilCustomRecipe.RESULT_ITEM_CONFIG, this.anvilRecipe + "." + AnvilCustomRecipe.RESULT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER, ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG(), AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG(),
"§7Set the result item of the custom craft", "§7Set the result item of the custom craft",
"§7\u25A1 + \u25A1 = \u25A0"); "§7□ + □ = ■");//TODO MESSAGE
// Now we update the items // Now we update the items
updateLocal(); updateLocal();
@ -162,8 +163,9 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
return success; return success;
}; };
return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.anvilRecipe.toString()) + "§c?", var type = CasedStringUtil.snakeToUpperSpacedCase(this.anvilRecipe.toString());
"§7Confirm that you want to delete this conflict.", return new ConfirmActionGui(MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_DELETE_TITLE(), type,
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_DELETE_DESCRIPTION(), type,
this, this.parent, deleteSupplier this, this.parent, deleteSupplier
); );
} }

View file

@ -24,6 +24,7 @@ import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MetricsUtil; import xyz.alexcrea.cuanvil.util.MetricsUtil;
@ -41,8 +42,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
public EnchantConflictSubSettingGui( public EnchantConflictSubSettingGui(
@NotNull EnchantConflictGui parent, @NotNull EnchantConflictGui parent,
@NotNull EnchantConflictGroup enchantConflict) { @NotNull EnchantConflictGroup enchantConflict) {
super(3, super(3, CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()));
"§e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + " §8Config");
this.parent = parent; this.parent = parent;
this.enchantConflict = enchantConflict; this.enchantConflict = enchantConflict;
@ -71,8 +71,8 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
ItemMeta deleteMeta = deleteItem.getItemMeta(); ItemMeta deleteMeta = deleteItem.getItemMeta();
assert deleteMeta != null; assert deleteMeta != null;
deleteMeta.setDisplayName("§4DELETE CONFLICT"); deleteMeta.setDisplayName("§4DELETE CONFLICT");//TODO MESSAGE
deleteMeta.setLore(Collections.singletonList("§cCaution with this button !")); deleteMeta.setLore(Collections.singletonList("§cCaution with this button !"));//TODO MESSAGE
deleteItem.setItemMeta(deleteMeta); deleteItem.setItemMeta(deleteMeta);
this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance)); this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance));
@ -80,22 +80,24 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
// Displayed item will be updated later // Displayed item will be updated later
this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), event -> { this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), event -> {
event.setCancelled(true); event.setCancelled(true);
var type = CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString());
EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui( EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui(
"§e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + "§5", MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_ENCHANTMENTS(), type,
this, this); this, this);
enchantGui.show(event.getWhoClicked()); enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance); }, CustomAnvil.instance);
this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), event -> { this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), event -> {
event.setCancelled(true); event.setCancelled(true);
var type = CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString());
GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( GroupSelectSettingGui enchantGui = new GroupSelectSettingGui(
"§e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + " §3Groups", MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_SUB_GROUPS(), type,
this, this, 0); this, this, 0);
enchantGui.show(event.getWhoClicked()); enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance); }, CustomAnvil.instance);
this.minBeforeActiveSettingFactory = new IntSettingsGui.IntSettingFactory( this.minBeforeActiveSettingFactory = new IntSettingsGui.IntSettingFactory(
"§8Minimum enchantment count", "§8Minimum enchantment count",//TODO MESSAGE
this, this.enchantConflict + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER, this, this.enchantConflict + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER,
Arrays.asList( Arrays.asList(
"§7Minimum enchantment count set to X mean only X enchantment can be put", "§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 success;
}; };
return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + "§c?", var type = CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString());
"§7Confirm that you want to delete this conflict.", return new ConfirmActionGui(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_TITLE(), type,
MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_DESCRIPTION(), type,
this, this.parent, deleteSupplier this, this.parent, deleteSupplier
); );
} }
@ -159,12 +162,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
// Prepare enchantment lore // Prepare enchantment lore
ArrayList<String> enchantLore = new ArrayList<>(); ArrayList<String> 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<CAEnchantment> enchants = getSelectedEnchantments(); Set<CAEnchantment> enchants = getSelectedEnchantments();
if (enchants.isEmpty()) { 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 { } else {
enchantLore.add("§7List of included enchantment for this conflict:"); enchantLore.add("§7List of included enchantment for this conflict:");//TODO MESSAGE
Iterator<CAEnchantment> enchantIterator = enchants.iterator(); Iterator<CAEnchantment> enchantIterator = enchants.iterator();
boolean greaterThanMax = enchants.size() > 5; boolean greaterThanMax = enchants.size() > 5;
@ -175,7 +178,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
enchantLore.add("§7- §5" + formattedName); enchantLore.add("§7- §5" + formattedName);
} }
if (greaterThanMax) { 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(); ItemMeta enchantMeta = enchantItem.getItemMeta();
assert enchantMeta != null; assert enchantMeta != null;
enchantMeta.setDisplayName("§aSelect included §5Enchantments §aSettings"); enchantMeta.setDisplayName("§aSelect included §5Enchantments §aSettings");//TODO MESSAGE
enchantMeta.setLore(enchantLore); enchantMeta.setLore(enchantLore);
enchantItem.setItemMeta(enchantMeta); enchantItem.setItemMeta(enchantMeta);
@ -200,7 +203,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
ItemMeta groupMeta = groupItem.getItemMeta(); ItemMeta groupMeta = groupItem.getItemMeta();
assert groupMeta != null; assert groupMeta != null;
groupMeta.setDisplayName("§aSelect Excluded §3Groups §aSettings"); groupMeta.setDisplayName("§aSelect Excluded §3Groups §aSettings");//TODO MESSAGE
groupMeta.setLore(groupLore); groupMeta.setLore(groupLore);
groupItem.setItemMeta(groupMeta); groupItem.setItemMeta(groupMeta);
@ -208,7 +211,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
this.groupSettingItem.setItem(groupItem); // Just in case this.groupSettingItem.setItem(groupItem); // Just in case
this.pane.bindItem('M', this.minBeforeActiveSettingFactory.getItem(Material.COMMAND_BLOCK, this.pane.bindItem('M', this.minBeforeActiveSettingFactory.getItem(Material.COMMAND_BLOCK,
"Minimum Enchantment Count")); "Minimum Enchantment Count"));//TODO MESSAGE
update(); update();
} }
@ -246,7 +249,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
@Override @Override
public boolean setSelectedEnchantments(Set<CAEnchantment> enchantments) { public boolean setSelectedEnchantments(Set<CAEnchantment> enchantments) {
if (!this.shouldWork) { 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; return false;
} }
@ -264,7 +267,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
try { try {
updateGuiValues(); updateGuiValues();
} catch (Exception e) { } 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); MetricsUtil.INSTANCE.trackError(e);
} }
@ -291,7 +294,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
@Override @Override
public boolean setSelectedGroups(Set<AbstractMaterialGroup> groups) { public boolean setSelectedGroups(Set<AbstractMaterialGroup> groups) {
if (!this.shouldWork) { 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; return false;
} }
@ -309,7 +312,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
try { try {
updateGuiValues(); updateGuiValues();
} catch (Exception e) { } 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); MetricsUtil.INSTANCE.trackError(e);
} }

View file

@ -20,10 +20,11 @@ import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui;
import xyz.alexcrea.cuanvil.gui.config.global.GroupConfigGui; import xyz.alexcrea.cuanvil.gui.config.global.GroupConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.GroupSelectSettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.GroupSelectSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.MaterialSelectSettingGui; 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.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -39,8 +40,7 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
public GroupConfigSubSettingGui( public GroupConfigSubSettingGui(
@NotNull GroupConfigGui parent, @NotNull GroupConfigGui parent,
@NotNull IncludeGroup group) { @NotNull IncludeGroup group) {
super(3, super(3, CasedStringUtil.snakeToUpperSpacedCase(group.getName()));
"§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName()) + " §rConfig");
this.parent = parent; this.parent = parent;
this.group = group; this.group = group;
@ -64,39 +64,49 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
// Delete item // Delete item
ItemStack deleteItem = new ItemStack(Material.RED_TERRACOTTA); ItemStack deleteItem = new ItemStack(Material.RED_TERRACOTTA);
ItemMeta deleteMeta = deleteItem.getItemMeta(); ItemMeta deleteMeta = deleteItem.getItemMeta();
assert deleteMeta != null;
deleteMeta.setDisplayName("§4DELETE GROUP"); ComponentUtil.INSTANCE.setMessageName(deleteMeta, MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_BUTTON_NAME());
deleteMeta.setLore(Collections.singletonList("§cCaution with this button !")); ComponentUtil.INSTANCE.applyLore(
MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_BUTTON_LORE().formatted(),
deleteMeta
);
deleteItem.setItemMeta(deleteMeta); deleteItem.setItemMeta(deleteMeta);
this.pane.bindItem('D', new GuiItem(deleteItem, openGuiAndCheckAction(), CustomAnvil.instance)); this.pane.bindItem('D', new GuiItem(deleteItem, openGuiAndCheckAction(), CustomAnvil.instance));
// Displayed item will be updated later // 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); ItemStack selectItem = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta selectItemMeta = selectItem.getItemMeta(); ItemMeta selectItemMeta = selectItem.getItemMeta();
selectItemMeta.setDisplayName(materialSelectionName); assert selectItemMeta != null;
ComponentUtil.INSTANCE.setMessageName(selectItemMeta, materialSelectionName, name);
selectItem.setItemMeta(selectItemMeta); selectItem.setItemMeta(selectItemMeta);
this.materialSelection = new GuiItem(selectItem, (event) -> { this.materialSelection = new GuiItem(selectItem, (event) -> {
event.setCancelled(true); event.setCancelled(true);
MaterialSelectSettingGui selectGui = new MaterialSelectSettingGui(this, MaterialSelectSettingGui selectGui = new MaterialSelectSettingGui(this,
materialSelectionName materialSelectionName, name
, this); , this);
selectGui.show(event.getWhoClicked()); selectGui.show(event.getWhoClicked());
}, CustomAnvil.instance); }, 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); ItemStack selectGroup = new ItemStack(Material.CHEST);
ItemMeta selectGroupMeta = selectGroup.getItemMeta(); ItemMeta selectGroupMeta = selectGroup.getItemMeta();
selectGroupMeta.setDisplayName(selectGroupName); assert selectGroupMeta != null;
ComponentUtil.INSTANCE.setMessageName(selectGroupMeta, selectGroupName, name);
selectGroup.setItemMeta(selectGroupMeta); selectGroup.setItemMeta(selectGroupMeta);
this.groupSelection = new GuiItem(selectGroup, (event) -> { this.groupSelection = new GuiItem(selectGroup, (event) -> {
event.setCancelled(true); event.setCancelled(true);
GroupSelectSettingGui enchantGui = new GroupSelectSettingGui( GroupSelectSettingGui enchantGui = new GroupSelectSettingGui(
selectGroupName, selectGroupName, name,
this, this, 0); this, this, 0);
enchantGui.show(event.getWhoClicked()); enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance); }, CustomAnvil.instance);
@ -113,7 +123,7 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
// Do not allow to open inventory if player do not have edit configuration permission // Do not allow to open inventory if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
// test if group is used & cancel & warn user if so // test if group is used & cancel & warn user if so
@ -151,8 +161,9 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
return success; return success;
}; };
return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.group.toString()) + "§c?", var type = CasedStringUtil.snakeToUpperSpacedCase(this.group.toString());
"§7Confirm that you want to delete this group.", return new ConfirmActionGui(MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_TITLE(), type,
MsgUI.INSTANCE.getMATERIAL_GROUP_ELEMENT_DELETE_DESCRIPTION(), type,
this, this.parent, deleteSupplier this, this.parent, deleteSupplier
); );
} }
@ -225,7 +236,8 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
ItemStack matSelectItem = this.materialSelection.getItem(); ItemStack matSelectItem = this.materialSelection.getItem();
ItemMeta matSelectMeta = matSelectItem.getItemMeta(); 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.setLore(matLore);
matSelectMeta.addItemFlags(ItemFlag.values()); matSelectMeta.addItemFlags(ItemFlag.values());
@ -237,7 +249,8 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
ItemStack groupSelectItem = this.groupSelection.getItem(); ItemStack groupSelectItem = this.groupSelection.getItem();
ItemMeta groupSelectMeta = groupSelectItem.getItemMeta(); ItemMeta groupSelectMeta = groupSelectItem.getItemMeta();
groupSelectMeta.setDisplayName("§aSelect included §3Groups §aSettings"); assert groupSelectMeta != null;
groupSelectMeta.setDisplayName("§aSelect included §3Groups §aSettings");//TODO MESSAGE
groupSelectMeta.setLore(groupLore); groupSelectMeta.setLore(groupLore);
groupSelectItem.setItemMeta(groupSelectMeta); groupSelectItem.setItemMeta(groupSelectMeta);

View file

@ -1,18 +1,18 @@
package xyz.alexcrea.cuanvil.gui.config.list.elements; 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.ChestGui;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui; import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import io.delilaheve.CustomAnvil; import io.delilaheve.CustomAnvil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
public abstract class MappedToListSubSettingGui extends ChestGui implements ValueUpdatableGui, ElementMappedToListGui { public abstract class MappedToListSubSettingGui extends ChestGui implements ValueUpdatableGui, ElementMappedToListGui {
protected MappedToListSubSettingGui( protected MappedToListSubSettingGui(
int rows, int rows,
@NotNull String title) { @NotNull String type) {
super(rows, title, CustomAnvil.instance); super(rows, MsgUI.INSTANCE.getSHARED_TYPED_CONFIG_TITLE().textHolder(type), CustomAnvil.instance);
} }
@Override @Override

View file

@ -20,6 +20,7 @@ import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.*; import java.util.*;
@ -35,8 +36,10 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<CAEnchantme
private boolean displayUnselected; private boolean displayUnselected;
public EnchantSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectEnchantmentContainer enchantContainer) { public EnchantSelectSettingGui(
super(title, parent instanceof Gui parentGui ? parentGui : MainConfigGui.getInstance()) ; @NotNull Message title, @NotNull String param,
ValueUpdatableGui parent, SelectEnchantmentContainer enchantContainer) {
super(title, param, parent instanceof Gui parentGui ? parentGui : MainConfigGui.getInstance()) ;
this.enchantContainer = enchantContainer; this.enchantContainer = enchantContainer;
this.selectedEnchant = new HashSet<>(enchantContainer.getSelectedEnchantments()); this.selectedEnchant = new HashSet<>(enchantContainer.getSelectedEnchantments());

View file

@ -19,6 +19,7 @@ import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer; import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer;
import xyz.alexcrea.cuanvil.gui.config.list.ElementListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.ElementListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Collections; import java.util.Collections;
@ -34,8 +35,10 @@ public class GroupSelectSettingGui extends AbstractSettingGui {
Set<AbstractMaterialGroup> selectedGroups; Set<AbstractMaterialGroup> selectedGroups;
public GroupSelectSettingGui(@NotNull String title, ValueUpdatableGui parent, SelectGroupContainer groupContainer, int page) { public GroupSelectSettingGui(
super(6, title, parent); @NotNull Message title, @NotNull String param,
ValueUpdatableGui parent, SelectGroupContainer groupContainer, int page) {
super(6, title.textHolder(param), parent);
this.groupContainer = groupContainer; this.groupContainer = groupContainer;
//Not used but planned //Not used but planned
this.page = page; this.page = page;

View file

@ -18,6 +18,8 @@ import xyz.alexcrea.cuanvil.gui.config.list.MappedElementListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; 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.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -37,9 +39,10 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
public MaterialSelectSettingGui( public MaterialSelectSettingGui(
@NotNull SelectMaterialContainer selector, @NotNull SelectMaterialContainer selector,
@NotNull String title, @NotNull Message title,
@NotNull String param,
@NotNull Gui backGui) { @NotNull Gui backGui) {
super(title); super(title, param);//TODO MESSAGE make param go down
this.selector = selector; this.selector = selector;
this.backGui = backGui; this.backGui = backGui;
this.instantRemove = false; this.instantRemove = false;
@ -156,7 +159,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
// Do not allow to save configuration if player do not have edit configuration permission // Do not allow to save configuration if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
if(testCantSave()) return; if(testCantSave()) return;
@ -236,8 +239,8 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
// Create and show confirm remove gui. // Create and show confirm remove gui.
ConfirmActionGui confirmGui = new ConfirmActionGui( ConfirmActionGui confirmGui = new ConfirmActionGui(
"Remove " + materialName, MsgUI.INSTANCE.getMATERIAL_SELECT_CONFIRM_TITLE(), materialName,
"§7Confirm Remove " + materialName.toLowerCase() + " from this list.", MsgUI.INSTANCE.getMATERIAL_SELECT_CONFIRM_DESCRIPTION(), materialName.toLowerCase(),
this, this, this, this,
() -> { () -> {
removeMaterial(material); removeMaterial(material);

View file

@ -16,6 +16,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.config.WorkPenaltyType; import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui; import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
@ -73,7 +74,7 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
// Do not allow to open inventory if player do not have edit configuration permission // Do not allow to open inventory if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
new WorkPenaltyTypeSettingGui(parent).show(player); new WorkPenaltyTypeSettingGui(parent).show(player);

View file

@ -7,6 +7,7 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -17,8 +18,6 @@ import java.util.function.Consumer;
*/ */
public class GuiGlobalActions { public class GuiGlobalActions {
public static final String NO_EDIT_PERM = "§cYou do not have permission to edit the config";
/** /**
* A Consumer that should be used if the item goal is to do nothing on click. * A Consumer that should be used if the item goal is to do nothing on click.
*/ */
@ -44,7 +43,7 @@ public class GuiGlobalActions {
// Do not allow to open inventory if player do not have edit configuration permission // Do not allow to open inventory if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
try { try {
@ -102,7 +101,7 @@ public class GuiGlobalActions {
// Do not allow to open inventory if player do not have edit configuration permission // Do not allow to open inventory if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
goal.show(player); goal.show(player);
@ -127,7 +126,7 @@ public class GuiGlobalActions {
// Do not allow to save configuration if player do not have edit configuration permission // Do not allow to save configuration if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }

View file

@ -1,14 +1,13 @@
package io.delilaheve package io.delilaheve
import io.delilaheve.util.ConfigOptions import io.delilaheve.util.ConfigOptions
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent
import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent
import xyz.alexcrea.cuanvil.command.CustomAnvilCommand import xyz.alexcrea.cuanvil.command.CustomAnvilCommand
import xyz.alexcrea.cuanvil.command.EditConfigExecutor
import xyz.alexcrea.cuanvil.command.ReloadExecutor
import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil
@ -17,6 +16,9 @@ import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant
import xyz.alexcrea.cuanvil.lang.Lang
import xyz.alexcrea.cuanvil.lang.MsgError
import xyz.alexcrea.cuanvil.lang.MsgWarning
import xyz.alexcrea.cuanvil.listener.AnvilCloseListener import xyz.alexcrea.cuanvil.listener.AnvilCloseListener
import xyz.alexcrea.cuanvil.listener.AnvilResultListener import xyz.alexcrea.cuanvil.listener.AnvilResultListener
import xyz.alexcrea.cuanvil.listener.ChatEventListener import xyz.alexcrea.cuanvil.listener.ChatEventListener
@ -75,7 +77,7 @@ open class CustomAnvil : JavaPlugin() {
var latestVer: String? = null var latestVer: String? = null
// Debug // Debug
val debugStorageQueue = ArrayDeque<String>() val debugStorageQueue = ArrayDeque<Component>()
private fun addToLogQueue(message: String) { private fun addToLogQueue(message: String) {
if(debugStorageQueue.size >= 200) { if(debugStorageQueue.size >= 200) {
@ -83,7 +85,7 @@ open class CustomAnvil : JavaPlugin() {
debugStorageQueue.removeFirst() debugStorageQueue.removeFirst()
} }
debugStorageQueue.addLast(message) debugStorageQueue.addLast(Component.text(message))
} }
/** /**
@ -108,11 +110,23 @@ open class CustomAnvil : JavaPlugin() {
} }
} }
/**
* Error Logging handler
*/
@JvmStatic fun logError(message: String, throwable: Throwable? = null, track: Boolean = true, level: Level = Level.SEVERE) {
instance.logger.log(level, message, throwable)
addToLogQueue("Error: $message")
if(track) {
MetricsUtil.trackError(message, throwable)
}
}
} }
// stop plugin if we do not force a dirty start (true by default) // stop plugin if we do not force a dirty start (true by default)
// Return true if start was stopped // Return true if start was stopped
private fun tryDirtyStart(): Boolean { private fun tryDirtyStart(): Boolean {
if(ConfigHolder.DEFAULT_CONFIG == null) return false
if(!ConfigHolder.DEFAULT_CONFIG.config.getBoolean("dirty_start", false)) { if(!ConfigHolder.DEFAULT_CONFIG.config.getBoolean("dirty_start", false)) {
Bukkit.getPluginManager().disablePlugin(this) Bukkit.getPluginManager().disablePlugin(this)
return true return true
@ -123,6 +137,7 @@ open class CustomAnvil : JavaPlugin() {
// stop plugin if we force a safe start (false by default) // stop plugin if we force a safe start (false by default)
// Return true if start was stopped // Return true if start was stopped
private fun trySafeStart(): Boolean { private fun trySafeStart(): Boolean {
if(ConfigHolder.DEFAULT_CONFIG == null) return false
if(ConfigHolder.DEFAULT_CONFIG.config.getBoolean("safe_start", false)) { if(ConfigHolder.DEFAULT_CONFIG.config.getBoolean("safe_start", false)) {
Bukkit.getPluginManager().disablePlugin(this) Bukkit.getPluginManager().disablePlugin(this)
return true return true
@ -135,39 +150,45 @@ open class CustomAnvil : JavaPlugin() {
*/ */
override fun onEnable() { override fun onEnable() {
instance = this instance = this
try {
legacyCheck()
} catch (e: Exception) {
logger.log(Level.SEVERE, "error trying to check for legacy system", e)
MetricsUtil.trackError(e)
if(trySafeStart()) return
}
// Add commands
try {
CustomAnvilCommand(this)
} catch (e: Exception) {
logger.log(Level.SEVERE, "error trying to register commands", e)
MetricsUtil.trackError(e)
if(trySafeStart()) return
}
// Load default configuration // Load default configuration
try { try {
if(!ConfigHolder.loadDefaultConfig()) if(!ConfigHolder.loadDefaultConfig())
throw RuntimeException("Error loading configuration file") throw RuntimeException("Error loading configuration file")
} catch (e: Exception) { } catch (e: Exception) {
logger.log(Level.SEVERE, "error occurred loading default configuration", e) logError("error occurred loading default configuration", e)
MetricsUtil.trackError(e)
if(tryDirtyStart()) return if(tryDirtyStart()) return
} }
// Load language
try {
Lang.loadDefault()
} catch (e: Exception) {
logError("error occurred loading language file", e)
if(tryDirtyStart()) return
}
try {
legacyCheck()
} catch (e: Exception) {
MsgError.LOAD_LEGACY_FAILED.log(e)
if(trySafeStart()) return
}
// Add commands
try {
CustomAnvilCommand(this)
} catch (e: Exception) {
MsgError.LOAD_COMMAND_REGISTER.log(e)
if(trySafeStart()) return
}
// Load dependency // Load dependency
try { try {
DependencyManager.loadDependency() DependencyManager.loadDependency()
} catch (e: Exception) { } catch (e: Exception) {
logger.log(Level.SEVERE, "error loading dependency compatibility", e) MsgError.LOAD_COMPATIBILITY.log(e)
MetricsUtil.trackError(e)
if(tryDirtyStart()) return if(tryDirtyStart()) return
} }
@ -175,8 +196,7 @@ open class CustomAnvil : JavaPlugin() {
try { try {
registerListeners() registerListeners()
} catch (e: Exception) { } catch (e: Exception) {
logger.log(Level.SEVERE, "error registering listeners", e) MsgError.LOAD_LISTENERS.log(e)
MetricsUtil.trackError(e)
if(tryDirtyStart()) return if(tryDirtyStart()) return
} }
@ -192,33 +212,20 @@ open class CustomAnvil : JavaPlugin() {
MetricsUtil.shutdownMetrics() MetricsUtil.shutdownMetrics()
} }
private fun loadEnchantmentSystemDirty() {
try {
loadEnchantmentSystem()
} catch (e: Exception) {
logger.log(Level.SEVERE, "error initializing enchantment system", e)
MetricsUtil.trackError(e)
tryDirtyStart()
}
}
private fun legacyCheck() { private fun legacyCheck() {
// Disable old plugin name if exist // Disable old plugin name if exist
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus") val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
if (potentialPlugin != null) { if (potentialPlugin != null) {
Bukkit.getPluginManager().disablePlugin(potentialPlugin) Bukkit.getPluginManager().disablePlugin(potentialPlugin)
logger.warning("An old version of this plugin was detected") MsgWarning.LOAD_LEGACY_OLD_NAME.log()
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
} }
val isPaper = PlatformUtil.isPaper val isPaper = PlatformUtil.isPaper
if(!isPaper) { if(!isPaper) {
logger.warning("It seems you are using spigot") MsgWarning.LOAD_LEGACY_SPIGOT.log()
logger.warning("Please take notice that spigot is less supported than paper and derivatives") if(MinecraftVersionUtil.isTooNewForSpigot)
if(MinecraftVersionUtil.isTooNewForSpigot) { MsgWarning.LOAD_LEGACY_SPIGOT_OLD.log()
logger.warning("If replace too expensive is not working this is likely because of spigot")
logger.warning("As native nms is not supported for spigot starting 26.1")
}
} }
val loader = if(isPaper) "paper" else "spigot" val loader = if(isPaper) "paper" else "spigot"
@ -230,13 +237,13 @@ open class CustomAnvil : JavaPlugin() {
UpdateUtils.currentMinecraftVersion().toString()) UpdateUtils.currentMinecraftVersion().toString())
.setFeatured(featured) .setFeatured(featured)
.setOnError { .setOnError {
logger.log(Level.WARNING, "error trying to fetch latest update", it) MsgError.LOAD_UPDATE_CHECK_FAIL.log(it, level = Level.WARNING, track = false)
} }
.checkVersion { latestVer: String? -> .checkVersion { latestVer: String? ->
CustomAnvil.latestVer = latestVer CustomAnvil.latestVer = latestVer
if(latestVer == null || version.contains(latestVer)) return@checkVersion if(latestVer == null || version.contains(latestVer)) return@checkVersion
logger.warning("An update may be available: $latestVer") MsgWarning.LOAD_UPDATE_AVAILABLE.log(latestVer)
} }
} }
@ -251,6 +258,15 @@ open class CustomAnvil : JavaPlugin() {
server.pluginManager.registerEvents(AnvilCloseListener(DependencyManager.packetManager), this) server.pluginManager.registerEvents(AnvilCloseListener(DependencyManager.packetManager), this)
} }
private fun loadEnchantmentSystemDirty() {
try {
loadEnchantmentSystem()
} catch (e: Exception) {
MsgError.LOAD_ENCHANT_SYSTEM.log(e)
tryDirtyStart()
}
}
private fun loadEnchantmentSystem(){ private fun loadEnchantmentSystem(){
// Register enchantments // Register enchantments
CAEnchantmentRegistry.getInstance().registerBukkit() CAEnchantmentRegistry.getInstance().registerBukkit()
@ -261,7 +277,7 @@ open class CustomAnvil : JavaPlugin() {
// Load config // Load config
if (!ConfigHolder.loadNonDefaultConfig()) { if (!ConfigHolder.loadNonDefaultConfig()) {
logger.log(Level.SEVERE,"Plugin has an issue while trying to load non default config... exiting...") MsgError.LOAD_NON_DEFAULT_CONFIG.log()
server.pluginManager.disablePlugin(this) server.pluginManager.disablePlugin(this)
return return
} }
@ -315,16 +331,15 @@ open class CustomAnvil : JavaPlugin() {
try { try {
val configReader = FileReader(resourceFile) val configReader = FileReader(resourceFile)
yamlConfig.load(configReader) yamlConfig.load(configReader)
} catch (test: Exception) { } catch (e: Exception) {
MsgError.RELOAD_FAIL.log(e, resourceFile.path)
if (hardFailSafe) { if (hardFailSafe) {
// This is important and may impact gameplay if it does not load. // This is important and may impact gameplay if it does not load.
// Failsafe is to stop the plugin // Failsafe is to stop the plugin
logger.severe("Resource ${resourceFile.path} Could not be load or reload.") MsgError.RELOAD_HARD_FAIL.log()
logger.severe("Disabling plugin.")
Bukkit.getPluginManager().disablePlugin(this) Bukkit.getPluginManager().disablePlugin(this)
} else {
logger.warning("Resource ${resourceFile.path} Could not be load or reload.")
} }
return null return null
} }
return yamlConfig return yamlConfig

View file

@ -22,9 +22,9 @@ import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog
import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
import xyz.alexcrea.cuanvil.util.CasedStringUtil import xyz.alexcrea.cuanvil.util.CasedStringUtil
import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeLegacy
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir 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.UnitRepairUtil.getRepair
import xyz.alexcrea.cuanvil.util.anvil.AnvilColorUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilColorUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil
@ -151,7 +151,7 @@ object AnvilMergeLogic {
) )
if (component != null) { if (component != null) {
renameText = MiniMessageUtil.legacy_mm.serialize(component) renameText = component.serializeLegacy()
sumCost += ConfigOptions.useOfColorCost sumCost += ConfigOptions.useOfColorCost
useColor = true useColor = true

View file

@ -3,6 +3,7 @@ package xyz.alexcrea.cuanvil.command
import org.bukkit.command.Command import org.bukkit.command.Command
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.lang.Message
interface CASubCommand { interface CASubCommand {
@ -21,7 +22,7 @@ interface CASubCommand {
list: MutableList<String> list: MutableList<String>
) )
fun description(): String fun description(): Message
fun allEnchantmentsByName(): Collection<String> { fun allEnchantmentsByName(): Collection<String> {
val names = mutableSetOf<String>() val names = mutableSetOf<String>()

View file

@ -6,7 +6,7 @@ import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import org.bukkit.command.TabCompleter import org.bukkit.command.TabCompleter
import xyz.alexcrea.cuanvil.util.MetricsUtil import xyz.alexcrea.cuanvil.lang.MsgCommand
class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter { class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
@ -57,15 +57,15 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
} }
if (subcmd == null || !subcmd.allowed(sender)) { if (subcmd == null || !subcmd.allowed(sender)) {
sender.sendMessage("Invalid subcommand. run `$cmdstr help` to see available commands") MsgCommand.ROOT_UNKNOWN_SUBCOMMAND.send(sender, cmdstr)
return true return true
} }
try { try {
return subcmd.executeCommand(sender, cmd, subcmdStr, newargs) return subcmd.executeCommand(sender, cmd, subcmdStr, newargs)
} catch (e: Throwable) { } catch (e: Throwable) {
MetricsUtil.trackError(e) CustomAnvil.logError("Error running /$cmdstr ${args.joinToString(" ")}", e)
sender.sendMessage("§cError running this command") MsgCommand.ROOT_ERROR_SUBCOMMAND.send(sender)
return false return false
} }
} }

View file

@ -6,16 +6,22 @@ import net.md_5.bungee.api.chat.ClickEvent
import net.md_5.bungee.api.chat.HoverEvent import net.md_5.bungee.api.chat.HoverEvent
import net.md_5.bungee.api.chat.TextComponent import net.md_5.bungee.api.chat.TextComponent
import net.md_5.bungee.api.chat.hover.content.Text import net.md_5.bungee.api.chat.hover.content.Text
import org.bukkit.ChatColor
import org.bukkit.command.Command import org.bukkit.command.Command
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import org.bukkit.entity.Player import org.bukkit.entity.Player
import xyz.alexcrea.cuanvil.command.DiagnosticExecutor.Companion.NO_DIAG_PERM 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(): String { override fun description(): Message {
return "Used to toggle debug logs and retrieve it" return MsgCommand.DEBUG_DESCRIPTION
} }
override fun allowed(sender: CommandSender): Boolean { override fun allowed(sender: CommandSender): Boolean {
@ -26,15 +32,15 @@ class DebugToggleExecutor : CASubCommand {
sender: CommandSender, sender: CommandSender,
cmd: Command, cmd: Command,
cmdstr: String, cmdstr: String,
args: Array<out String> args: Array<out String>,
): Boolean { ): Boolean {
if(!allowed(sender)) { if(!allowed(sender)) {
sender.sendMessage(NO_DIAG_PERM) MsgCommand.SHARED_NO_DIAG_PERM.send(sender)
return false return false
} }
if(args.isEmpty()) { if(args.isEmpty()) {
sender.sendMessage("Need to specify a subcommand: \"toggle\" or \"get\"") MsgCommand.SHARED_MISSING_SUBCOMMAND.send(sender, "\"toggle\"", "\"get\"")
return true return true
} }
when(args[0].lowercase()) { when(args[0].lowercase()) {
@ -47,52 +53,61 @@ class DebugToggleExecutor : CASubCommand {
"clear" -> { "clear" -> {
CustomAnvil.debugStorageQueue.clear() CustomAnvil.debugStorageQueue.clear()
sender.sendMessage("Log Cleared") MsgCommand.DEBUG_LOG_CLEARED.send(sender)
} }
else -> return false "lang" -> {
executeLanguageDebug(sender, args)
}
else -> {
MsgCommand.SHARED_UNKNOWN_SUB_COMMAND.send(sender)
return false
}
} }
return true return true
} }
private fun executeToggle(sender: CommandSender, args: Array<out String>) { private fun executeToggle(sender: CommandSender, args: Array<out String>) {
if(args.size < 2) { if(args.size < 2) {
sender.sendMessage("Need to specify which type of debug to toggle: \"default\" or \"verbose\"") MsgCommand.DEBUG_WARNING_UNSPECIFIED_TYPE.send(sender)
return return
} }
when(args[1].lowercase()) { when(args[1].lowercase()) {
"default" -> { "default" -> {
ConfigOptions.OVERRIDE_DEBUG_LOG = !ConfigOptions.debugLog ConfigOptions.OVERRIDE_DEBUG_LOG = !ConfigOptions.debugLog
sender.sendMessage("Debug toggle to: ${ConfigOptions.debugLog}") MsgCommand.DEBUG_TOGGLED.send(sender, ConfigOptions.debugLog)
} }
"verbose" -> { "verbose" -> {
ConfigOptions.OVERRIDE_VERBOSE_DEBUG_LOG = !ConfigOptions.verboseDebugLog ConfigOptions.OVERRIDE_VERBOSE_DEBUG_LOG = !ConfigOptions.verboseDebugLog
sender.sendMessage("Debug toggle to: ${ConfigOptions.verboseDebugLog}") MsgCommand.DEBUG_TOGGLED.send(sender, ConfigOptions.debugLog)
} }
else -> sender.sendMessage("Invalid debug type: ${args[1]}") else -> MsgCommand.DEBUG_WARNING_INVALID_TYPE.send(sender, ConfigOptions.debugLog)
} }
} }
private fun executeGet(sender: CommandSender) { private fun executeGet(sender: CommandSender) {
val stb = StringBuilder("Debug Log data:")
if(CustomAnvil.debugStorageQueue.isEmpty()) { if(CustomAnvil.debugStorageQueue.isEmpty()) {
sender.sendMessage("No log to show ? make sure you tried with debug log toggled (/ca debug toggle)") MsgCommand.DEBUG_WARNING_NO_LOG.send(sender, "/ca debug toggle")
return return
} }
stb.append("\nFound ${CustomAnvil.debugStorageQueue.size} lines\n") val stb = StringBuilder(MsgCommand.DEBUG_DATA_HEADER.unformatted()).append(' ')
stb.append(MsgCommand.DEBUG_DATA_LINE_COUNT.unformatted(CustomAnvil.debugStorageQueue.size))
for(log in CustomAnvil.debugStorageQueue) { for(log in CustomAnvil.debugStorageQueue) {
stb.append('\n').append(log) stb.append('\n').append(log.serializePlain())
} }
if(sender is Player) { if(sender is Player) {
val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy log data") val message = TextComponent(MsgCommand.DEBUG_COPY.legacy())
message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString()) message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString())
message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text("§7Click to copy")) message.hoverEvent = HoverEvent(
HoverEvent.Action.SHOW_TEXT,
Text(MsgCommand.SHARED_HOVER_COPY.legacy())
)
sender.spigot().sendMessage(message); sender.spigot().sendMessage(message);
} else { } else {
@ -100,14 +115,142 @@ class DebugToggleExecutor : CASubCommand {
} }
} }
private fun executeLanguageDebug(sender: CommandSender, args: Array<out String>) {
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<String>()
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<String>()
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<String>()
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<out String>, list: MutableList<String>) { override fun tabCompleter(sender: CommandSender, args: Array<out String>, list: MutableList<String>) {
if(!allowed(sender)) return if(!allowed(sender)) return
list.addAll( list.addAll(
when(args.size) { 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()) { 2 -> when(args[0].lowercase()) {
"toggle" -> listOf("default", "verbose") "toggle" -> listOf("default", "verbose")
"lang" -> listOf("details")
else -> listOf() else -> listOf()
} }

View file

@ -6,7 +6,6 @@ import net.md_5.bungee.api.chat.HoverEvent
import net.md_5.bungee.api.chat.TextComponent import net.md_5.bungee.api.chat.TextComponent
import net.md_5.bungee.api.chat.hover.content.Text import net.md_5.bungee.api.chat.hover.content.Text
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.command.Command import org.bukkit.command.Command
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
@ -25,15 +24,17 @@ import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.dependency.packet.NoPacketManager import xyz.alexcrea.cuanvil.dependency.packet.NoPacketManager
import xyz.alexcrea.cuanvil.dependency.packet.ProtocoLibWrapper import xyz.alexcrea.cuanvil.dependency.packet.ProtocoLibWrapper
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.lang.Message
import xyz.alexcrea.cuanvil.lang.MsgCommand
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener
import xyz.alexcrea.cuanvil.util.MetricsUtil import xyz.alexcrea.cuanvil.util.MetricsUtil
import java.util.* import java.util.*
import java.util.stream.Collectors import java.util.stream.Collectors
@Suppress("UnstableApiUsage")
class DiagnosticExecutor : CASubCommand { class DiagnosticExecutor : CASubCommand {
companion object { companion object {
const val NO_DIAG_PERM = "You do not have permission to diagnostic this server"
fun fetchNMSType(): String { fun fetchNMSType(): String {
val packetManager = DependencyManager.packetManager val packetManager = DependencyManager.packetManager
@ -101,7 +102,7 @@ class DiagnosticExecutor : CASubCommand {
args: Array<out String> args: Array<out String>
): Boolean { ): Boolean {
if (!allowed(sender)) { if (!allowed(sender)) {
sender.sendMessage(NO_DIAG_PERM) MsgCommand.SHARED_NO_DIAG_PERM.send(sender)
return false return false
} }
@ -122,12 +123,11 @@ class DiagnosticExecutor : CASubCommand {
if (sender is HumanEntity) { if (sender is HumanEntity) {
if (hasError) if (hasError)
sender.spigot() MsgCommand.DIAGNOSTIC_ERROR_GENERIC.send(sender)
.sendMessage(TextComponent(ChatColor.RED.toString() + "There was an error running the diagnostic")) val message = TextComponent(MsgCommand.DIAGNOSTIC_COPY.legacy())
val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy diagnostic data")
message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString()) message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString())
message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text("§7Click to copy")) message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text(MsgCommand.SHARED_HOVER_COPY.legacy()))
sender.spigot().sendMessage(message) sender.spigot().sendMessage(message)
} else { } else {
@ -214,8 +214,8 @@ class DiagnosticExecutor : CASubCommand {
return this.name + " v" + this.description.version return this.name + " v" + this.description.version
} }
override fun description(): String { override fun description(): Message {
return "Basic diagnostic of this plugin" return MsgCommand.DIAGNOSTIC_DESCRIPTION
} }
private fun pluginListDiag(sender: CommandSender, stb: StringBuilder) { private fun pluginListDiag(sender: CommandSender, stb: StringBuilder) {

View file

@ -10,7 +10,9 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.config.global.EnchantConfigGui import xyz.alexcrea.cuanvil.gui.config.global.EnchantConfigGui
import xyz.alexcrea.cuanvil.gui.config.global.ItemConfigGui import xyz.alexcrea.cuanvil.gui.config.global.ItemConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions import xyz.alexcrea.cuanvil.lang.Message
import xyz.alexcrea.cuanvil.lang.MsgCommand
import xyz.alexcrea.cuanvil.lang.MsgUI
import xyz.alexcrea.cuanvil.util.MaterialUtil.customType import xyz.alexcrea.cuanvil.util.MaterialUtil.customType
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
@ -20,33 +22,29 @@ class EditConfigExecutor : CASubCommand {
return sender.hasPermission(CustomAnvil.editConfigPermission) return sender.hasPermission(CustomAnvil.editConfigPermission)
} }
override fun description(): String { override fun description(): Message {
return "Gui to edit the plugin's config" return MsgCommand.CONFIG_DESCRIPTION
} }
override fun executeCommand( override fun executeCommand(
sender: CommandSender, sender: CommandSender,
cmd: Command, cmd: Command,
cmdstr: String, cmdstr: String,
args: Array<out String> args: Array<out String>,
): Boolean { ): Boolean {
if(sender !is HumanEntity) return false if(sender !is HumanEntity) return false
if(!allowed(sender)) { if(!allowed(sender)) {
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM) MsgUI.SHARED_CONFIG_NO_EDIT_PERM.send(sender)
return false return false
} }
if(PlatformUtil.isFolia) { if(PlatformUtil.isFolia) {
sender.sendMessage("§cIt look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia.") MsgCommand.CONFIG_FOLIA_ISSUE.send(sender)
sender.sendMessage("§eIt is may come in a future version.")
sender.sendMessage("")
sender.sendMessage("§eCurrently you need to edit manually the config or copy from another server (spigot or better)")
sender.sendMessage("§eThen /ca reload after config file is edited")
return false return false
} }
if("gui".equals(cmdstr, ignoreCase = true)) { if("gui".equals(cmdstr, ignoreCase = true)) {
sender.sendMessage("§c/ca gui has been moved to /ca config") MsgCommand.CONFIG_LEGACY_NAME_WARNING.send(sender)
} }
if(args.isEmpty()) if(args.isEmpty())
@ -55,7 +53,7 @@ class EditConfigExecutor : CASubCommand {
"open" -> processOpen(sender) "open" -> processOpen(sender)
"enchant" -> processEnchant(sender, args) "enchant" -> processEnchant(sender, args)
"item" -> processItem(sender) "item" -> processItem(sender)
else -> sender.sendMessage("Unknown subcommand \"${args[0]}\"") else -> MsgCommand.SHARED_UNKNOWN_SUB_COMMAND.send(sender)
} }
return true return true
@ -68,26 +66,25 @@ class EditConfigExecutor : CASubCommand {
enchantToFilter = EnchantmentApi.getEnchantments(item).keys enchantToFilter = EnchantmentApi.getEnchantments(item).keys
if(enchantToFilter.isEmpty()) { if(enchantToFilter.isEmpty()) {
sender.sendMessage("No enchantment found in the item you are holding") MsgCommand.CONFIG_ENCHANTMENT_NO_IN_HAND.send(sender)
return return
} }
} else { } else {
enchantToFilter = HashSet(EnchantmentApi.getByName(args[1].lowercase())) enchantToFilter = HashSet(EnchantmentApi.getByName(args[1].lowercase()))
if(enchantToFilter.isEmpty()) { if(enchantToFilter.isEmpty()) {
sender.sendMessage("No enchantment found with the name \"${args[1]}\"") MsgCommand.CONFIG_ENCHANTMENT_NO_NAME.send(sender, args[1])
return return
} }
} }
EnchantConfigGui(enchantToFilter).show(sender) EnchantConfigGui(enchantToFilter).show(sender)
} }
private fun processItem(sender: HumanEntity) { private fun processItem(sender: HumanEntity) {
val item = sender.inventory.itemInMainHand val item = sender.inventory.itemInMainHand
if(item.isAir) { if(item.isAir) {
sender.sendMessage("Cannot configure the item in hand") MsgCommand.CONFIG_CANNOT_CONFIGURE_WARNING.send(sender)
return return
} }

View file

@ -10,6 +10,8 @@ import org.bukkit.command.CommandSender
import org.bukkit.entity.HumanEntity import org.bukkit.entity.HumanEntity
import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.api.EnchantmentApi
import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.lang.Message
import xyz.alexcrea.cuanvil.lang.MsgCommand
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
class EnchantExecutor : CASubCommand { class EnchantExecutor : CASubCommand {
@ -19,33 +21,33 @@ class EnchantExecutor : CASubCommand {
return sender.hasPermission(CustomAnvil.giveEnchantmentPermission) return sender.hasPermission(CustomAnvil.giveEnchantmentPermission)
} }
override fun description(): String { override fun description(): Message {
return "Allows to set enchantment to holden item" return MsgCommand.ENCHANT_DESCRIPTION
} }
override fun executeCommand( override fun executeCommand(
sender: CommandSender, sender: CommandSender,
cmd: Command, cmd: Command,
cmdstr: String, cmdstr: String,
args: Array<out String> args: Array<out String>,
): Boolean { ): Boolean {
if(sender !is HumanEntity) return true if(sender !is HumanEntity) return true
if(!allowed(sender)) { if(!allowed(sender)) {
sender.sendMessage("No permission to execute this command") MsgCommand.SHARED_NO_PERMISSION.send(sender)
return true return true
} }
when(args.size) { when(args.size) {
0 -> { 0 -> {
sender.sendMessage("Missing enchantment parameter") MsgCommand.ENCHANT_MISSING_PARAMETER_WARNING.send(sender)
return true return true
} }
} }
val enchant = firstEnchantment(args[0]) val enchant = firstEnchantment(args[0])
if(enchant == null) { if(enchant == null) {
sender.sendMessage("Enchantment not found: ${args[0]}") MsgCommand.ENCHANT_NOT_FOUND_WARNING.send(sender, args[0])
return true return true
} }
@ -54,13 +56,13 @@ class EnchantExecutor : CASubCommand {
else 1 else 1
if(level == null) { if(level == null) {
sender.sendMessage("Invalid number: ${args[1]}") MsgCommand.ENCHANT_MALFORMED_NUMBER_WARNING.send(sender, args[1])
return true return true
} }
val inHand = sender.inventory.itemInMainHand val inHand = sender.inventory.itemInMainHand
if(inHand.isAir) { if(inHand.isAir) {
sender.sendMessage("Cannot enchant this item") MsgCommand.ENCHANT_CANNOT_ENCHANT_WARNING.send(sender)
return true return true
} }
@ -70,13 +72,13 @@ class EnchantExecutor : CASubCommand {
if(inHand.isEnchantedBook() && EnchantmentApi.getEnchantments(inHand).isEmpty()) if(inHand.isEnchantedBook() && EnchantmentApi.getEnchantments(inHand).isEmpty())
inHand.type = Material.BOOK inHand.type = Material.BOOK
sender.sendMessage("${enchant.prettyName} removed") MsgCommand.ENCHANT_REMOVE.send(sender, enchant.prettyName)
} else { } else {
if(Material.BOOK == inHand.type) if(Material.BOOK == inHand.type)
inHand.type = Material.ENCHANTED_BOOK inHand.type = Material.ENCHANTED_BOOK
enchant.addEnchantmentUnsafe(inHand, level) enchant.addEnchantmentUnsafe(inHand, level)
sender.sendMessage("${enchant.prettyName} set to level $level") MsgCommand.ENCHANT_SET.send(sender, enchant.prettyName, level)
} }
return true return true
@ -97,7 +99,7 @@ class EnchantExecutor : CASubCommand {
private fun findEnchantmentLevels( private fun findEnchantmentLevels(
sender: HumanEntity, sender: HumanEntity,
name: String name: String,
): Collection<String> { ): Collection<String> {
val enchant = firstEnchantment(name) ?: return listOf() val enchant = firstEnchantment(name) ?: return listOf()

View file

@ -1,29 +1,37 @@
package xyz.alexcrea.cuanvil.command package xyz.alexcrea.cuanvil.command
import com.google.common.collect.ImmutableMap import com.google.common.collect.ImmutableMap
import net.kyori.adventure.text.Component
import org.bukkit.command.Command import org.bukkit.command.Command
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import xyz.alexcrea.cuanvil.lang.Message
import xyz.alexcrea.cuanvil.lang.MsgCommand
import xyz.alexcrea.cuanvil.util.ComponentUtil.send
class HelpExecutor : CASubCommand { class HelpExecutor : CASubCommand {
override fun description(): Message {
return MsgCommand.HELP_DESCRIPTION
}
lateinit var commands: ImmutableMap<String, CASubCommand> lateinit var commands: ImmutableMap<String, CASubCommand>
override fun executeCommand( override fun executeCommand(
sender: CommandSender, sender: CommandSender,
cmd: Command, cmd: Command,
cmdstr: String, cmdstr: String,
args: Array<out String> args: Array<out String>,
): Boolean { ): Boolean {
var text = MsgCommand.HELP_HEADER.formatted().first()
val stb = StringBuilder("List of available commands:")
for((key, cmd) in commands) { for((key, cmd) in commands) {
if(!cmd.allowed(sender)) continue if(!cmd.allowed(sender)) continue
stb.append("\n- $key: ").append(cmd.description()) text = text.appendNewline()
.append(Component.text("- $key: "))
.append(cmd.description().formatted())
} }
sender.sendMessage(stb.toString()) text.send(sender)
return true return true
} }
@ -34,12 +42,8 @@ class HelpExecutor : CASubCommand {
override fun tabCompleter( override fun tabCompleter(
sender: CommandSender, sender: CommandSender,
args: Array<out String>, args: Array<out String>,
list: MutableList<String> list: MutableList<String>,
) { ) {
} }
override fun description(): String {
return "Help command"
}
} }

View file

@ -8,29 +8,36 @@ import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent
import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.gui.config.global.* import xyz.alexcrea.cuanvil.gui.config.global.*
import xyz.alexcrea.cuanvil.lang.Lang
import xyz.alexcrea.cuanvil.lang.Message
import xyz.alexcrea.cuanvil.lang.MsgCommand
import xyz.alexcrea.cuanvil.update.UpdateHandler import xyz.alexcrea.cuanvil.update.UpdateHandler
class ReloadExecutor : CASubCommand { class ReloadExecutor : CASubCommand {
override fun description(): Message {
return MsgCommand.RELOAD_DESCRIPTION
}
override fun executeCommand( override fun executeCommand(
sender: CommandSender, sender: CommandSender,
cmd: Command, cmd: Command,
cmdstr: String, cmdstr: String,
args: Array<out String> args: Array<out String>,
): Boolean { ): Boolean {
if(!allowed(sender)) { if(!allowed(sender)) {
sender.sendMessage("§cYou do not have permission to reload the config") MsgCommand.SHARED_NO_PERMISSION.send(sender)
return false return false
} }
sender.sendMessage("§eReloading config...") MsgCommand.RELOAD_START.send(sender)
val hardfail = args.isNotEmpty() && ("hard".equals(args[0], true)) val hardfail = args.isNotEmpty() && ("hard".equals(args[0], true))
val commandSuccess = commandBody(hardfail) val commandSuccess = commandBody(hardfail)
if(commandSuccess) { if(commandSuccess) {
sender.sendMessage("§aConfig reloaded !") MsgCommand.RELOAD_SUCCESS.send(sender)
} else { } else {
sender.sendMessage("§cConfig was not able to be reloaded...") MsgCommand.RELOAD_FAIL.send(sender)
if(hardfail) { if(hardfail) {
sender.sendMessage("§4Hard fail, plugin disabled") MsgCommand.RELOAD_HARD_FAIL.send(sender)
} }
} }
return commandSuccess return commandSuccess
@ -43,14 +50,10 @@ class ReloadExecutor : CASubCommand {
override fun tabCompleter( override fun tabCompleter(
sender: CommandSender, sender: CommandSender,
args: Array<out String>, args: Array<out String>,
list: MutableList<String> list: MutableList<String>,
) { ) {
} }
override fun description(): String {
return "Reload the configuration of this plugin"
}
/** /**
* Execute the command, return true if success or false otherwise * Execute the command, return true if success or false otherwise
*/ */
@ -58,6 +61,9 @@ class ReloadExecutor : CASubCommand {
try { try {
if(!ConfigHolder.reloadAllFromDisk(hardfail)) return false if(!ConfigHolder.reloadAllFromDisk(hardfail)) return false
// reload language config
if(!Lang.reload()) return false
// Then update all global gui containing value from config // Then update all global gui containing value from config
BasicConfigGui.getInstance()?.updateGuiValues() BasicConfigGui.getInstance()?.updateGuiValues()
EnchantCostConfigGui.getInstance()?.updateGuiValues() EnchantCostConfigGui.getInstance()?.updateGuiValues()

View file

@ -3,7 +3,6 @@ package xyz.alexcrea.cuanvil.dependency
import io.delilaheve.CustomAnvil import io.delilaheve.CustomAnvil
import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
import org.bukkit.entity.HumanEntity import org.bukkit.entity.HumanEntity
import org.bukkit.entity.Player import org.bukkit.entity.Player
@ -28,10 +27,10 @@ import xyz.alexcrea.cuanvil.dependency.scheduler.FoliaScheduler
import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore
import xyz.alexcrea.cuanvil.lang.MsgWarning
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError
import java.lang.IllegalStateException import java.lang.IllegalStateException
import java.util.logging.Level
@Suppress("UnstableApiUsage") @Suppress("UnstableApiUsage")
object DependencyManager { object DependencyManager {
@ -158,18 +157,14 @@ object DependencyManager {
} }
private fun logException(target: CommandSender, e: Exception) { private fun logException(target: CommandSender, e: Exception) {
CustomAnvil.instance.logger.log( CustomAnvil.logError(
Level.SEVERE,
"Error while trying to handle custom anvil supported plugin: ", "Error while trying to handle custom anvil supported plugin: ",
e e
) )
trackError(e) trackError(e)
// Finally, warn the player // Finally, warn the player
target.sendMessage( MsgWarning.ANVIL_GENERIC_EXCEPTION.send(target)
"[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " +
ChatColor.RED.toString() + "Error while handling the anvil."
)
} }
private fun logExceptionAndClear(view: AnvilView, e: Exception) { private fun logExceptionAndClear(view: AnvilView, e: Exception) {

View file

@ -0,0 +1,83 @@
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 lateinit var default: Language
private lateinit var lang: Language
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()
else
lang = Language(langID)
if(default != lang) default.reload()
}
fun getTranslated(key: String): String {
val value = lang.get(key)
if(value != null) return value
CustomAnvil.log("Missing language data for ${lang.name} using default")
return default.get(key) ?: key
}
fun getSection(key: String): ConfigurationSection? {
val value = lang.getSection(key)
if(value != null) return value
return default.getSection(key)
}
fun currentLang(): String {
return lang.name
}
fun has(key: String): Boolean {
return lang.has(key)
}
fun getKeys(): Collection<String> {
return lang.getFilteredKeys()
}
/*
* Config Options & get
*/
const val LANG_PATH = "language"
const val DEFAULT_LANG = "en"
/**
* Value of an item rename
*/
private val langID: String
get() {
return ConfigHolder.DEFAULT_CONFIG
.config
.getString(LANG_PATH, DEFAULT_LANG)!!
}
}

View file

@ -0,0 +1,99 @@
package xyz.alexcrea.cuanvil.lang
import io.delilaheve.CustomAnvil
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.FileConfiguration
import org.bukkit.configuration.file.YamlConfiguration
import java.io.File
import java.io.InputStreamReader
import java.util.logging.Level
class Language(private val id: String, private val default: Boolean = false) {
private val resourcePath: String
private val file: File
private val conf: FileConfiguration
init {
conf = YamlConfiguration()
resourcePath = "lang/$id.yml"
file = File(CustomAnvil.instance.dataFolder, resourcePath)
reload()
}
fun reload() {
if(file.exists() && !default) try {
conf.load(file)
return
} catch(e: Exception) {
CustomAnvil.instance.logger.log(
Level.SEVERE,
"Could not load custom Anvil config file. using to internal resource",
e
)
}
loadInternalResource()
}
private fun loadInternalResource() {
val input = CustomAnvil.instance.getResource(resourcePath)
if(input != null)
conf.load(InputStreamReader(input))
else
CustomAnvil.instance.logger.log(Level.SEVERE, "Language $id not found")
}
fun get(key: String): String? {
return conf.getString(key)
}
fun getSection(key: String): ConfigurationSection? {
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<String> {
val result = ArrayList<String>()
// 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<String>) {
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)!!
}

View file

@ -0,0 +1,180 @@
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
import org.bukkit.configuration.ConfigurationSection
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, register: Boolean = true) {
companion object {
private val values = ArrayList<Message>()
fun getValues(): Collection<Message> {
return Collections.unmodifiableCollection(values)
}
}
init {
if(register) values.add(this)
}
protected fun replaceParameters(stb: StringBuilder, vararg values: Any) {
// replace all placeholder thingy %key -> value
if(params.size != values.size) {
CustomAnvil.log("Wrong number of argument for parameter for key $key (${params.size}/${values.size})")
}
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) {
current = stb.indexOf('%', current) + 1
if(current <= 0 || current + key.length > stb.length) break // may be able to be removed if bound checked in startsWith ?
if(!stb.startsWith(key, current, false)) continue
stb.replace(current - 1, current + key.length, replacement)
current = current - 1 + replacement.length
}
}
}
private fun unformattedMonoline(vararg params: Any): String {
val translated = Lang.getTranslated(key)
if(params.isEmpty() && this.params.isEmpty()) return translated
val stb = StringBuilder(translated)
replaceParameters(stb, *params)
return stb.toString()
}
private fun unformattedMultiline(section: ConfigurationSection, vararg params: Any): String {
val stb = StringBuilder()
for(key in section.getKeys(false)) {
if(!section.isString(key)) continue
if(!stb.isEmpty()) stb.append('\n')
stb.append(section.getString(key))
}
replaceParameters(stb, *params)
return stb.toString()
}
fun unformatted(vararg params: Any): String {
val section = Lang.getSection(key)
if(section != null) return unformattedMultiline(section, *params)
return unformattedMonoline(*params)
}
private fun formattedMultiline(section: ConfigurationSection, vararg params: Any): List<Component> {
val result = ArrayList<Component>()
for(key in section.getKeys(false)) {
if(!section.isString(key)) continue
val stb = StringBuilder(section.getString(key))
replaceParameters(stb, *params)
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<Component> {
val section = Lang.getSection(key)
if(section != null) return formattedMultiline(section, *params)
val translated = unformattedMonoline(*params)
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)
val stb = StringBuilder()
for(component in formated) {
if(!stb.isEmpty()) stb.append('\n')
stb.append(component.serializeLegacy())
}
return stb.toString()
}
open fun log(vararg params: Any) {
val texts = formatted(*params)
for(component in texts) {
CustomAnvil.instance.logger.info(component.serializePlain())
}
}
open fun send(destination: CommandSender, vararg params: Any) {
formatted(*params).send(destination)
}
}
class WarningMessage(key: String, vararg params: String) : Message("warning.$key", *params) {
override fun log(vararg params: Any) {
val texts = formatted(*params)
for(component in texts) {
CustomAnvil.instance.logger.warning(component.serializePlain())
}
}
}
class ErrorMessage(key: String, vararg params: String) : Message("error.$key", *params) {
override fun log(vararg params: Any) {
val texts = formatted(*params)
for(component in texts) {
CustomAnvil.logError(component.serializePlain())
}
}
fun log(e: Throwable, vararg params: Any, level: Level = Level.SEVERE, track: Boolean = true) {
val texts = formatted(*params)
for(component in texts) {
CustomAnvil.logError(component.serializePlain(), e, track, level)
}
}
}
class CommandMessage(key: String, vararg params: String) : Message("command.$key", *params)
class UIMessage(key: String, vararg params: String) : Message("config-ui.$key", *params)

View file

@ -0,0 +1,69 @@
package xyz.alexcrea.cuanvil.lang
import xyz.alexcrea.cuanvil.lang.CommandMessage as Message
object MsgCommand {
// Root
val ROOT_UNKNOWN_SUBCOMMAND = Message("root.warning.unknown-sub", "command")
val ROOT_ERROR_SUBCOMMAND = Message("root.error.generic")
// Shared
val SHARED_NO_DIAG_PERM = Message("shared.no-diag-permission")
val SHARED_HOVER_COPY = Message("shared.hover-copy")
val SHARED_MISSING_SUBCOMMAND = Message("shared.warning.missing-subcmd", "example1", "example2")
val SHARED_UNKNOWN_SUB_COMMAND = Message("shared.unknown-subcmd", "command")
val SHARED_NO_PERMISSION = Message("shared.no-permission")
// Debug
val DEBUG_DESCRIPTION = Message("debug.description")
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")
val DEBUG_WARNING_UNSPECIFIED_TYPE = Message("debug.warning.unspecified-type")
val DEBUG_WARNING_INVALID_TYPE = Message("debug.warning.invalid-type", "type")
val DEBUG_WARNING_NO_LOG = Message("debug.warning.no-log", "command")
// Diagnostic
val DIAGNOSTIC_DESCRIPTION = Message("diagnostic.description")
val DIAGNOSTIC_ERROR_GENERIC = Message("diagnostic.had-error")
val DIAGNOSTIC_COPY = Message("diagnostic.copy")
// Config
val CONFIG_DESCRIPTION = Message("config.description")
val CONFIG_LEGACY_NAME_WARNING = Message("config.warning.legacy-name")
val CONFIG_FOLIA_ISSUE = Message("config.folia-issue")
val CONFIG_ENCHANTMENT_NO_IN_HAND = Message("config.enchantment.no_hand")
val CONFIG_ENCHANTMENT_NO_NAME = Message("config.enchantment.no_name", "name")
val CONFIG_CANNOT_CONFIGURE_WARNING = Message("config.warning.cannot_configure")
// Enchant
val ENCHANT_DESCRIPTION = Message("enchant.description")
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")
val ENCHANT_MALFORMED_NUMBER_WARNING = Message("enchant.warning.malformed_number", "num")
val ENCHANT_CANNOT_ENCHANT_WARNING = Message("enchant.warning.cannot_enchant")
// Help
val HELP_DESCRIPTION = Message("help.description")
val HELP_HEADER = Message("help.header")
// Reload
val RELOAD_DESCRIPTION = Message("reload.description")
val RELOAD_START = Message("reload.start")
val RELOAD_SUCCESS = Message("reload.success")
val RELOAD_FAIL = Message("reload.fail")
val RELOAD_HARD_FAIL = Message("reload.hard-fail")
}

View file

@ -0,0 +1,29 @@
package xyz.alexcrea.cuanvil.lang
object MsgError {
/*
* -----------------
* Load and reload
* -----------------
*/
val LOAD_UPDATE_CHECK_FAIL = ErrorMessage("load.update.check-fail")
val LOAD_LEGACY_FAILED = ErrorMessage("load.legacy.failed")
val LOAD_COMMAND_REGISTER = ErrorMessage("load.command-register")
val LOAD_COMPATIBILITY = ErrorMessage("load.compatibility")
val LOAD_LISTENERS = ErrorMessage("load.listeners")
val LOAD_ENCHANT_SYSTEM = ErrorMessage("load.enchant-system")
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.hard-fail")
/*
* ----
* UI
* ----
*/
val CONFIRM_ACTION_GENERIC = ErrorMessage("confirm-action.generic")
}

View file

@ -0,0 +1,59 @@
package xyz.alexcrea.cuanvil.lang
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_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")
}

View file

@ -0,0 +1,20 @@
package xyz.alexcrea.cuanvil.lang
import xyz.alexcrea.cuanvil.lang.WarningMessage as Message
object MsgWarning {
/*
* -----------------
* Load and reload
* -----------------
*/
val LOAD_UPDATE_AVAILABLE = Message("load.update.available", "version")
val LOAD_LEGACY_OLD_NAME = Message("load.legacy.old-name")
val LOAD_LEGACY_SPIGOT = Message("load.legacy.spigot")
val LOAD_LEGACY_SPIGOT_OLD = Message("load.legacy.spigot-old")
val ANVIL_GENERIC_EXCEPTION = Message("anvil.generic")
}

View file

@ -30,9 +30,9 @@ import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir 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.AnvilLoreEditUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil
@ -536,7 +536,7 @@ class AnvilResultListener : Listener {
if (bookPage.isNotEmpty()) bookPage.append('\n') if (bookPage.isNotEmpty()) bookPage.append('\n')
if (it == null) return@forEach if (it == null) return@forEach
bookPage.append(MiniMessageUtil.plain_text_mm.serialize(it)) bookPage.append(it.serializePlain())
} }
val resultPage = bookPage.toString() val resultPage = bookPage.toString()

View file

@ -0,0 +1,48 @@
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())
}
fun List<Component>.send(destination: CommandSender) {
for(component in this)
component.send(destination)
}
fun List<Component>.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))
}
}

View file

@ -74,8 +74,8 @@ object MetricsUtil {
lastError = e lastError = e
} }
fun trackError(message: String) { fun trackError(message: String, cause: Throwable? = null) {
ERROR_TRACKER?.trackError(message) trackError(RuntimeException(message, cause))
} }
} }

View file

@ -25,9 +25,4 @@ object MiniMessageUtil {
val legacy_mm = LegacyComponentSerializer.legacySection() val legacy_mm = LegacyComponentSerializer.legacySection()
val plain_text_mm = PlainTextComponentSerializer.plainText() val plain_text_mm = PlainTextComponentSerializer.plainText()
// Keeping track of this as most use of this can be replaced later on v2 with pure component alternative
fun fromLegacy(legacyText: String): TextComponent {
return legacy_mm.deserialize(legacyText)
}
} }

View file

@ -3,6 +3,9 @@ package xyz.alexcrea.cuanvil.util.anvil
import io.delilaheve.util.ConfigOptions import io.delilaheve.util.ConfigOptions
import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component
import org.bukkit.permissions.Permissible import org.bukkit.permissions.Permissible
import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeLegacy
import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeMM
import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain
import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.MiniMessageUtil
import java.util.regex.Matcher import java.util.regex.Matcher
import java.util.regex.Pattern import java.util.regex.Pattern
@ -103,10 +106,10 @@ object AnvilColorUtil {
var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr) var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr)
if (permission.canUseMinimessage) { if (permission.canUseMinimessage) {
// we dance with formats here // we dance with formats here
val toMinimessage = MiniMessageUtil.mm.serialize(result) val toMinimessage = result.serializeMM()
val hackySolution = toMinimessage.replace("\\<", "<") val hackySolution = toMinimessage.replace("\\<", "<")
val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution) val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution)
val asPlain = MiniMessageUtil.plain_text_mm.serialize(fromMinimessage) val asPlain = fromMinimessage.serializePlain()
if (previousStr != asPlain) { if (previousStr != asPlain) {
useColor = true useColor = true
@ -145,8 +148,8 @@ object AnvilColorUtil {
): String? { ): String? {
if (!permission.allowed() || component == null) return null if (!permission.allowed() || component == null) return null
val transformed = MiniMessageUtil.mm.serialize(component) val transformed = component.serializeMM()
val plainTransform = MiniMessageUtil.plain_text_mm.serialize(component) val plainTransform = component.serializePlain()
if (transformed == plainTransform) return null if (transformed == plainTransform) return null
if (permission.onlyMinimessage()) { if (permission.onlyMinimessage()) {
return transformed return transformed
@ -154,7 +157,7 @@ object AnvilColorUtil {
// smol dance so we transform the component that may contain other tag into only decoration & color for legacy // smol dance so we transform the component that may contain other tag into only decoration & color for legacy
val coloredMessage = MiniMessageUtil.color_only_mm.deserialize(transformed) val coloredMessage = MiniMessageUtil.color_only_mm.deserialize(transformed)
val legacyMessage = StringBuilder(MiniMessageUtil.legacy_mm.serialize(coloredMessage)) val legacyMessage = StringBuilder(coloredMessage.serializeLegacy())
// Reverse hex pattern // Reverse hex pattern
if (permission.canUseHexColor) { if (permission.canUseHexColor) {

View file

@ -10,6 +10,7 @@ import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.LoreEditResult
import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentLore import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentLore
import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain
import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.MiniMessageUtil
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil
import xyz.alexcrea.cuanvil.util.config.LoreEditType import xyz.alexcrea.cuanvil.util.config.LoreEditType
@ -320,7 +321,7 @@ object AnvilLoreEditUtil {
hasUndidColor = true hasUndidColor = true
result = clearedLine result = clearedLine
} else { } else {
result = MiniMessageUtil.plain_text_mm.serialize(line) result = line.serializePlain()
} }
lines[index] = MiniMessageUtil.plain_text_mm.deserialize(result) lines[index] = MiniMessageUtil.plain_text_mm.deserialize(result)
@ -354,7 +355,7 @@ object AnvilLoreEditUtil {
result = clearedLine result = clearedLine
} else { } else {
// Remove extra tags // Remove extra tags
result = MiniMessageUtil.plain_text_mm.serialize(coloredComponent) result = coloredComponent.serializePlain()
} }
line.set(MiniMessageUtil.plain_text_mm.deserialize(result)) line.set(MiniMessageUtil.plain_text_mm.deserialize(result))

View file

@ -16,6 +16,11 @@ metric_type: auto
# Accept true or false (true by default) # Accept true or false (true by default)
metric_collect_errors: true metric_collect_errors: true
# Which language should the plugin should be
# If you like to add language yourself see TODO link to guide
# Currently available languages: en
language: en
# All anvil cost will be capped to limit_repair_value if enabled. # All anvil cost will be capped to limit_repair_value if enabled.
# #
# In other words: # In other words:

View file

@ -0,0 +1,185 @@
name: English
last-updated: 2.1.0
warning:
load:
legacy:
old-name:
1: "An old version of this plugin was detected"
2: "Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus"
spigot:
1: "It seems you are using spigot"
2: "Please take notice that spigot is less supported than paper and derivatives"
spigot-old:
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: "<white>[<yellow>CustomAnvil<white>] <red>Error while handling the anvil."
error:
load:
legacy.failed: "error trying to check for legacy system"
update.check-fail: "error trying to fetch latest update"
command-register: "error trying to register commands"
compatibility: "error loading dependency compatibility"
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: "<red>You do not have permission to diagnostic this server"
hover-copy: "<gray>Click to copy"
unknown-subcmd: "Unknown subcommand %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: "<red>Invalid subcommand. run <yellow>`%command help` <red>to see available commands"
error:
generic: "<red>Error running this command"
debug:
description: "Used to toggle debug logs and retrieve them"
log-cleared: "Log Cleared"
toggled: "Debug toggled to %type"
copy: "<green>Click to copy log data"
copy-lang: "<green>Click to copy detailed lang issues"
data:
header: "Debug Log data:"
line-count: "Found %count lines"
warning:
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: "<red>There was an error running the diagnostic"
copy: "<green>Click to copy diagnostic data"
config:
description: "Used to edit the configuration of the plugin"
folia-issue:
1: "<red>It look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia."
2: "<yellow>It is may come in a future version."
3: ""
4: "<yellow>Currently you need to edit manually the config or copy from another server (spigot or better)"
5: "<yellow>Then /ca reload after config file is edited"
enchantment:
no_hand: "No enchantment found in the item you are holding"
no_name: "No enchantment found with the name %name"
warning:
legacy-name: "<red>/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:
missing_parameter: "Missing enchantment parameter"
not_found: "Enchantment not found: %path"
malformed_number: "Invalid number: %num"
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: "<yellow>Reloading config..."
success: "<green>Config reloaded !"
fail: "<red>Config was not able to be reloaded..."
hard-fail: "<red>Hard fail, plugin disabled"
config-ui:
shared:
no-permission: "<red>You do not have permission to edit the config"
typed-config-title: "<yellow>%type <white>Config"
confirm-action:
fail: "<red>Action could not be completed."
is-user-sure: "<yellow>Are you sure ?"
select-item-type:
place-here: "<yellow>Place an item here"
element-list:
instruction-new:
1: "<yellow>Write the %type name you want to create in the chat."
2: "<yellow>Or write <red>cancel <yellow>to go back to %type config menu"
cancelled-new: "%type creation cancelled..."
duplicated-new: "<red>Please enter a %type name that do not already exist..."
unit-repair:
title: "Unit Repair Config <reset>(%page/%max_page)"
new:
title: "Select unit repair item."
description:
1: "<gray>Click here with an item to set the item"
2: "<gray>You like to be an unit repair item"
element:
title: "<yellow>%type <red>Unit repair <reset>(%page/%max_page)"
new:
title: "Select item to be repaired."
description:
1: "<gray>Click here with an item to set the item"
2: "<gray>You like to be repaired by %name"
cannot-damage: "<red>This item can't be damaged, so it can't be repaired."
same-type: "<red>Item can't repair something of the same type."
custom-recipe:
title: "Custom Recipe Config <reset>(%page/%max_page)"
element:
delete:
title: "<red>Delete <yellow>%type<red>?"
description: "<gray>Confirm that you want to delete this recipe."
enchant-level-cost:
title: "<dark_gray>Enchantment Level Limit <reset>(%page/%max_page)"
enchant-level-limit:
title: "<dark_gray>Enchantment Level Limit <reset>(%page/%max_page)"
enchant-merge-limit:
title: "<dark_gray>Enchantment Maximum Merge Level <reset>(%page/%max_page)"
enchant-conflict:
title: "Conflict Config <reset>(%page/%max_page)"
element:
selected-enchantments: "<yellow>%group<dark_purple>" # likely need page and max page
selected-sub-groups: "<yellow>%group <red>Groups"
delete:
title: "<red>Delete <yellow>%type<red>?"
description: "<gray>Confirm that you want to delete this conflict."
material-group:
title: "Group Config <reset>(%page/%max_page)"
element:
selected-materials: "<yellow>%group <red>Materials"
selected-sub-groups: "<yellow>%group <red>Groups"
delete:
title: "<red>Delete <yellow>%type<red>?"
description: "<gray>Confirm that you want to delete this group."
button:
name: "<dark_red>DELETE GROUP"
lore: "<red>Caution with this button !"
material-select:
new:
confirm:
title: "Remove %name"
description: "<dark_gray>Confirm Remove %name from this list."