This commit is contained in:
alexcrea 2026-08-21 14:35:52 +00:00 committed by GitHub
commit ea0326719e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
63 changed files with 2381 additions and 755 deletions

View file

@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.dependency.util
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.inventory.ItemStack
import org.bukkit.command.CommandSender
import org.bukkit.inventory.meta.ItemMeta
// 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,18 @@ import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
public abstract class AbstractAskGui extends ChestGui {
protected PatternPane pane;
AbstractAskGui(int rows, @NotNull String name,
Gui backOnCancel){
super(rows, name, CustomAnvil.instance);
AbstractAskGui(
int rows,
@NotNull Message name, @NotNull String param,
Gui backOnCancel
) {
super(rows, name.textHolder(param), CustomAnvil.instance);
Pattern pattern = getGuiPattern();
this.pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern);

View file

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

View file

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

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.settings.SettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import java.util.Collection;
import java.util.Collections;
@ -20,18 +21,18 @@ import java.util.function.Consumer;
*
* @param <T> Type of the factory of the type of setting the gui should edit.
*/
public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFactory> extends SettingGuiListConfigGui<CAEnchantment, T>{
public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFactory> extends SettingGuiListConfigGui<CAEnchantment, T> {
/**
* Constructor for a gui displaying available enchantment to edit a enchantment setting.
*
* @param title Title of the gui.
*/
protected AbstractEnchantConfigGui(String title) {
protected AbstractEnchantConfigGui(Message title) {
super(title);
}
protected AbstractEnchantConfigGui(String title, Gui parent) {
protected AbstractEnchantConfigGui(Message title, Gui parent) {
super(title, parent);
}
@ -46,7 +47,7 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
}
@Override
protected Pattern getBackgroundPattern(){
protected Pattern getBackgroundPattern() {
return new Pattern(
GuiSharedConstant.UPPER_FILLER_FULL_PLANE,
GuiSharedConstant.EMPTY_FILLER_FULL_LINE,
@ -68,7 +69,7 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
return;
}
if(!this.factoryMap.containsKey(generic)){
if(!this.factoryMap.containsKey(generic)) {
// We need to sort elements again
super.updateValueForGeneric(generic, false);
@ -77,12 +78,12 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
this.pages.clear();
this.pages.add(this.firstPage);
for (CAEnchantment enchantment : getDisplayableInstanceOfGeneric()) {
for(CAEnchantment enchantment : getDisplayableInstanceOfGeneric()) {
GuiItem item = this.guiItemMap.get(enchantment);
if(item == null) {
updateValueForGeneric(enchantment, false, false);
}else {
} else {
addToPage(item);
}
@ -90,7 +91,7 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
if(shouldUpdate) update();
}else{
} else {
super.updateValueForGeneric(generic, shouldUpdate);
}
@ -108,6 +109,7 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
protected List<String> getCreateItemLore() {
return Collections.emptyList();
}
@Override
protected Consumer<InventoryClickEvent> getCreateClickConsumer() {
return null;

View file

@ -14,7 +14,6 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil;
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
@ -24,10 +23,11 @@ import xyz.alexcrea.cuanvil.gui.config.settings.WorkPenaltyTypeSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/**
* Global config to edit basic basic settings.
@ -42,11 +42,12 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
}
private final PacketManager packetManager;
/**
* Constructor of this Global gui for basic settings.
*/
public BasicConfigGui(PacketManager packetManager) {
super(4, "§8Basic Config", CustomAnvil.instance);
super(4, MsgUI.INSTANCE.getBASIC_TITLE().textHolder(), CustomAnvil.instance);
if(INSTANCE == null) INSTANCE = this;
this.packetManager = packetManager;
@ -101,61 +102,60 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
*/
protected void prepareValues() {
// cap anvil cost
this.capAnvilCost = new BoolSettingsGui.BoolSettingFactory("§8Cap Anvil Cost ?", this,
this.capAnvilCost = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getBASIC_CAP_ANVIL_COST_TITLE(), this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST,
"§7All anvil cost will be capped to §aMax Anvil Cost§7 if enabled.",
"§7In other words:",
"§7For any anvil cost greater than §aMax Anvil Cost§7, Cost will be set to §aMax Anvil Cost§7.");
null, MsgUI.INSTANCE.getBASIC_CAP_ANVIL_COST_DESCRIPTION()
);
// cap anvil cost not needed
ItemStack item = new ItemStack(Material.BARRIER);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§cCap Anvil Cost ?");
meta.setLore(Collections.singletonList("§7This config only work if §cLimit Repair Cost§7 is disabled."));
ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getBASIC_CAP_ANVIL_COST_DISABLED_TITLE());
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getBASIC_CAP_ANVIL_COST_DISABLED_DESCRIPTION().formatted(), meta);
item.setItemMeta(meta);
this.noCapRepairItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
// repair cost item
IntRange range = ConfigOptions.MAX_ANVIL_COST_RANGE;
this.maxAnvilCost = new IntSettingsGui.IntSettingFactory("§8Max Anvil Cost", this,
this.maxAnvilCost = new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getBASIC_MAX_ANVIL_COST_TITLE(), this,
ConfigOptions.MAX_ANVIL_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7Max cost the Anvil can get to.",
"§7Valid values include §e0 §7to §e1000§7.",
"§7Cost will be displayed as §cToo Expensive§7:",
"§7- If Cost is above §e39",
"§7- And §eReplace Too Expensive§7 is disabled"
),
MsgUI.INSTANCE.getBASIC_MAX_ANVIL_COST_DESCRIPTION(), null,
range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_MAX_ANVIL_COST,
1, 5, 10);
1, 5, 10
);
// max anvil cost not needed
item = new ItemStack(Material.BARRIER);
meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§cMax Anvil Cost");
meta.setLore(Collections.singletonList("§7This config only work if §cLimit Repair Cost§7 is disabled."));
ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getBASIC_MAX_ANVIL_COST_DISABLED_TITLE());
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getBASIC_MAX_ANVIL_COST_DISABLED_DESCRIPTION().formatted(), meta);
item.setItemMeta(meta);
this.noMaxCostItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
// remove repair limit item
this.removeAnvilCostLimit = new BoolSettingsGui.BoolSettingFactory("§8Remove Anvil Cost Limit ?", this,
this.removeAnvilCostLimit = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getBASIC_REMOVE_COST_LIMIT_TITLE(), this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.REMOVE_ANVIL_COST_LIMIT, ConfigOptions.DEFAULT_REMOVE_ANVIL_COST_LIMIT,
"§7Whether the anvil's cost limit should be removed entirely.",
"§7The anvil will still visually display §cToo Expensive§7 if §eReplace Too Expensive§7 is disabled.",
"§7However, the action will be completable if xp requirement is meet.");
null, MsgUI.INSTANCE.getBASIC_REMOVE_COST_LIMIT_DESCRIPTION()
);
// replace too expensive item
this.replaceTooExpensive = new BoolSettingsGui.BoolSettingFactory("§8Replace Too Expensive ?", this,
this.replaceTooExpensive = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getBASIC_REPLACE_TOO_EXPENSIVE_TITLE(), this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE,
getReplaceToExpensiveLore());
null, getReplaceToExpensiveLore()
);
// ------------
// Cost config
@ -163,132 +163,118 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// item repair cost
range = ConfigOptions.REPAIR_COST_RANGE;
this.itemRepairCost = new IntSettingsGui.IntSettingFactory("§8Item Repair Cost", this,
this.itemRepairCost = new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getBASIC_ITEM_REPAIR_COST_TITLE(), this,
ConfigOptions.ITEM_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when the item",
"§7is repaired by another item of the same type."
),
MsgUI.INSTANCE.getBASIC_ITEM_REPAIR_COST_DESCRIPTION(), null,
range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_ITEM_REPAIR_COST,
1, 5, 10, 50, 100);
1, 5, 10, 50, 100
);
// unit repair cost
this.unitRepairCost = new IntSettingsGui.IntSettingFactory("§8Unit Repair Cost", this,
this.unitRepairCost = new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getBASIC_UNIT_REPAIR_COST_TITLE(), this,
ConfigOptions.UNIT_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when the item is repaired by an §eunit§7.",
"§7For example: a Diamond on a Diamond Sword.",
"§7What's considered unit for what can be edited on the unit repair configuration."
),
MsgUI.INSTANCE.getBASIC_UNIT_REPAIR_COST_DESCRIPTION(), null,
range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_UNIT_REPAIR_COST,
1, 5, 10, 50, 100);
1, 5, 10, 50, 100
);
// item rename cost
range = ConfigOptions.ITEM_RENAME_COST_RANGE;
this.itemRenameCost = new IntSettingsGui.IntSettingFactory("§8Rename Cost", this,
this.itemRenameCost = new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getBASIC_ITEM_RENAME_COST_TITLE(), this,
ConfigOptions.ITEM_RENAME_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when the item is renamed."
),
MsgUI.INSTANCE.getBASIC_ITEM_RENAME_COST_DESCRIPTION(), null,
range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_ITEM_RENAME_COST,
1, 5, 10, 50, 100);
1, 5, 10, 50, 100
);
// sacrifice illegal enchant cost
range = ConfigOptions.SACRIFICE_ILLEGAL_COST_RANGE;
this.sacrificeIllegalEnchantCost = new IntSettingsGui.IntSettingFactory("§8Sacrifice Illegal Enchant Cost", this,
this.sacrificeIllegalEnchantCost = new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getBASIC_SACRIFICE_ILLEGAL_COST_TITLE(), this,
ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP Level amount added to the anvil when a sacrifice enchantment",
"§7conflict With one of the left item enchantment"
),
MsgUI.INSTANCE.getBASIC_SACRIFICE_ILLEGAL_COST_DESCRIPTION(), null,
range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST,
1, 5, 10, 50, 100);
1, 5, 10, 50, 100
);
// -------------
// Color config
// -------------
// Allow us of color code
this.allowColorCode = new BoolSettingsGui.BoolSettingFactory("§8Allow Use Of Color Code ?", this,
this.allowColorCode = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getBASIC_COLOR_CODE_LIMIT_TITLE(), this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE,
"§7Whether players can use color code.",
"§7Color code a formatted like §a&a§7 and is used in the rename field of the anvil.",
"§7Player may need permission to use color code if §ePlayer need permission to use color§7 is enabled.");
null, MsgUI.INSTANCE.getBASIC_COLOR_CODE_LIMIT_DESCRIPTION()
);
// Allow us of hexadecimal color
this.allowHexColor = new BoolSettingsGui.BoolSettingFactory("§8Allow Use Of Hexadecimal Color ?", this,
this.allowHexColor = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getBASIC_COLOR_HEX_LIMIT_TITLE(), this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR,
"§7Whether players can use hexadecimal color.",
"§7Color code a formatted like §2#012345 §7and is used in the rename field of the anvil.",
"§7Player may need permission to use color code if §ePermission Needed For Color§7 is enabled.");
null, MsgUI.INSTANCE.getBASIC_COLOR_HEX_LIMIT_DESCRIPTION()
);
// Permission needed for color
this.permissionNeededForColor = new BoolSettingsGui.BoolSettingFactory("§8Need Permission To Use Color ?", this,
this.permissionNeededForColor = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getBASIC_COLOR_PERMISSION_TITLE(), this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR,
"§7Whether players should have permission to be able to use colors.",
"§7Give player §eca.color.code§7 Permission to allow use of color code.",
"§7Give player §eca.color.hex§7 Permission to allow use of hexadecimal color.");
null, MsgUI.INSTANCE.getBASIC_COLOR_PERMISSION_DESCRIPTION()
);
// Permission needed for color not necessary
item = new ItemStack(Material.BARRIER);
meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§cNeed Permission To Use Color ?");
meta.setLore(Arrays.asList("§7This config can do something only if one of the following config is enabled:",
"§7- §aAllow Use Of Color Code",
"§7- §aAllow Use Of Hexadecimal Color"));
ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getBASIC_COLOR_PERMISSION_DISABLED_TITLE());
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getBASIC_COLOR_PERMISSION_DISABLED_DESCRIPTION().formatted(), meta);
item.setItemMeta(meta);
this.noPermissionNeededItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
// Cost of using color
range = ConfigOptions.USE_OF_COLOR_COST_RANGE;
this.useOfColorCost = new IntSettingsGui.IntSettingFactory("§8Cost Of Using Color", this,
this.useOfColorCost = new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getBASIC_COLOR_COST_TITLE(), this,
ConfigOptions.USE_OF_COLOR_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7XP level cost when using color code or hexadecimal color using the anvil.",
"§7conflict With one of the left item enchantment"
),
MsgUI.INSTANCE.getBASIC_COLOR_COST_DESCRIPTION(), null,
range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_USE_OF_COLOR_COST,
1, 5, 10, 50, 100);
1, 5, 10, 50, 100
);
// Permission needed for color not necessary
item = new ItemStack(Material.BARRIER);
meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§cCost Of Using Color");
meta.setLore(Arrays.asList("§7This config can do something only if one of the following config is enabled:",
"§7- §aAllow Use Of Color Code",
"§7- §aAllow Use Of Hexadecimal Color"));
ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getBASIC_COLOR_COST_DISABLED_TITLE());
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getBASIC_COLOR_COST_DISABLED_DESCRIPTION().formatted(), meta);
item.setItemMeta(meta);
this.noColorCostItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
}
@NotNull
private String[] getReplaceToExpensiveLore() {
ArrayList<String> lore = new ArrayList<>();
lore.add("§7Whenever anvil cost is above §e39§7 should display the true price and not §cToo Expensive§7.");
lore.add("§7However, when bypassing §cToo Expensive§7, anvil price will be displayed as §aGreen§7.");
lore.add("§7Even if cost is displayed as §aGreen§7:");
lore.add("§7If the player do not have the required xp level, the action will not be completable.");
private Message[] getReplaceToExpensiveLore() {
ArrayList<Message> lore = new ArrayList<>();
lore.add(MsgUI.INSTANCE.getBASIC_REPLACE_TOO_EXPENSIVE_DESCRIPTION());
if(!this.packetManager.getCanSetInstantBuild()){
lore.add("");
lore.add("§4/!\\§cCaution§4/!\\ §cYou need ProtocoLib installed and working or a paper server.");
lore.add("§cCurrently ProtocoLib is not detected.");
}
if(!this.packetManager.getCanSetInstantBuild())
lore.add(MsgUI.INSTANCE.getBASIC_REPLACE_TOO_EXPENSIVE_DESCRIPTION_NO_NMS());
String[] loreAsArray = new String[lore.size()];
Message[] loreAsArray = new Message[lore.size()];
return lore.toArray(loreAsArray);
}
@ -297,9 +283,14 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// limit and cap anvil cost item
GuiItem capAnvilCostItem;
GuiItem maxAnvilCostItem;
if (!this.removeAnvilCostLimit.getConfiguredValue()) {
capAnvilCostItem = this.capAnvilCost.getItem("Cap Anvil Cost");
maxAnvilCostItem = this.maxAnvilCost.getItem(Material.EXPERIENCE_BOTTLE, "Max Anvil Cost");
if(!this.removeAnvilCostLimit.getConfiguredValue()) {
capAnvilCostItem = this.capAnvilCost.getItem(
MsgUI.INSTANCE.getBASIC_CAP_ANVIL_COST_ITEM()
);
maxAnvilCostItem = this.maxAnvilCost.getItem(
Material.EXPERIENCE_BOTTLE,
MsgUI.INSTANCE.getBASIC_MAX_ANVIL_COST_ITEM()
);
} else {
capAnvilCostItem = this.noCapRepairItem;
maxAnvilCostItem = this.noMaxCostItem;
@ -309,7 +300,9 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
pane.bindItem('C', maxAnvilCostItem);
// remove repair limit item
GuiItem removeRepairLimitItem = this.removeAnvilCostLimit.getItem("Remove Anvil Cost Limit");
GuiItem removeRepairLimitItem = this.removeAnvilCostLimit.getItem(
MsgUI.INSTANCE.getBASIC_REMOVE_COST_LIMIT_ITEM()
);
pane.bindItem('R', removeRepairLimitItem);
// replace too expensive item
@ -334,7 +327,11 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
pane.bindItem('S', illegalCostItem);
// work penalty type
GuiItem workPenaltyType = WorkPenaltyTypeSettingGui.getDisplayItem(this, Material.DAMAGED_ANVIL, "§aWork Penalty Type");
GuiItem workPenaltyType = WorkPenaltyTypeSettingGui.getDisplayItem(
this,
Material.DAMAGED_ANVIL,
MsgUI.INSTANCE.getBASIC_WORK_PENALTY_ITEM()
);
pane.bindItem('W', workPenaltyType);
// allow color code
@ -346,20 +343,22 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
pane.bindItem('h', allowHexColorItem);
// True if player could place color
if(ConfigOptions.INSTANCE.getRenameColorPossible()){
if(ConfigOptions.INSTANCE.getRenameColorPossible()) {
// use permission for color
GuiItem permissionNeededItem = this.permissionNeededForColor.getItem();
pane.bindItem('p', permissionNeededItem);
// using color cost
GuiItem useColorCostItem = this.useOfColorCost.getItem(Material.EXPERIENCE_BOTTLE, "Use color");
GuiItem useColorCostItem = this.useOfColorCost.getItem(
Material.EXPERIENCE_BOTTLE,
MsgUI.INSTANCE.getBASIC_COLOR_COST_ITEM()
);
pane.bindItem('P', useColorCostItem);
}else{
} else {
pane.bindItem('p', this.noPermissionNeededItem);
pane.bindItem('P', this.noColorCostItem);
}
update();
}

View file

@ -2,6 +2,7 @@ package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
@ -12,11 +13,14 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.elements.CustomRecipeSubSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRecipe,
MappedGuiListConfigGui.LazyElement<CustomRecipeSubSettingGui>> {
@ -30,19 +34,19 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
@NotNull
public static CustomRecipeConfigGui getInstance() {
if (INSTANCE == null) INSTANCE = new CustomRecipeConfigGui();
if(INSTANCE == null) INSTANCE = new CustomRecipeConfigGui();
return INSTANCE;
}
private CustomRecipeConfigGui() {
super("Custom Recipe Config");
super(MsgUI.INSTANCE.getCUSTOM_RECIPE_TITLE());
init();
}
public CustomRecipeConfigGui(Gui parent) {
super("Custom Recipe Config", parent);
super(MsgUI.INSTANCE.getCUSTOM_RECIPE_TITLE(), parent);
}
@Override
@ -50,7 +54,7 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
// Get base item to display
ItemStack craftResultItem = recipe.getResultItem();
ItemStack displayedItem;
if (craftResultItem == null) {
if(craftResultItem == null) {
displayedItem = new ItemStack(Material.BARRIER);
} else {
displayedItem = craftResultItem.clone();
@ -60,25 +64,31 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
ItemMeta meta = displayedItem.getItemMeta();
assert meta != null;
meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(recipe.toString()) + " §fCustom recipe");
meta.addItemFlags(ItemFlag.values());
meta.setLore(getRecipeLore(recipe));
ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getCUSTOM_RECIPE_NAME());
ComponentUtil.INSTANCE.applyLore(getRecipeLore(recipe), meta);
displayedItem.setItemMeta(meta);
return displayedItem;
}
private static @NotNull ArrayList<String> getRecipeLore(AnvilCustomRecipe recipe) {
private static @NotNull List<Component> getRecipeLore(AnvilCustomRecipe recipe) {
boolean shouldWork = recipe.validate();
ArrayList<String> lore = new ArrayList<>();
lore.add("§7Is valid: §" + (shouldWork ? "aYes" : "cNo"));
lore.add("§7Exact count: §" + (recipe.getExactCount() ? "aYes" : "cNo"));
lore.add("§7Recipe Level Cost: §e" + recipe.getLevelCostPerCraft());
lore.add("§7Recipe Linear Xp Cost: §e" + recipe.getXpCostPerCraft());
if (recipe.getXpCostPerCraft() != 0) {
lore.add("§7Exact Linear xp remove: §" + (recipe.getRemoveExactLinearXp() ? "aYes" : "cNo"));
var shouldWorkMsg = MsgUI.INSTANCE.booleanMessage(shouldWork);
var exactCount = MsgUI.INSTANCE.booleanMessage(recipe.getExactCount());
ArrayList<Component> lore = new ArrayList<>(MsgUI.INSTANCE.getCUSTOM_RECIPE_LORE_DEFAULT()
.formatted(
shouldWorkMsg,
exactCount,
recipe.getLevelCostPerCraft(),
recipe.getXpCostPerCraft()
));
if(recipe.getXpCostPerCraft() != 0) {
var removeExact = MsgUI.INSTANCE.booleanMessage(recipe.getRemoveExactLinearXp());
lore.addAll(MsgUI.INSTANCE.getCUSTOM_RECIPE_LORE_LINEAR().formatted(removeExact));
}
return lore;
}
@ -89,8 +99,8 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
}
@Override
protected String genericDisplayedName() {
return "custom recipe";
protected Message genericDisplayedName() {
return MsgUI.INSTANCE.getCUSTOM_RECIPE_GENERIC_NAME();
}
@Override
@ -106,7 +116,8 @@ public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRec
AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG(),
AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG(),
AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG());
AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG()
);
ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanAddNew(recipe);

View file

@ -19,6 +19,8 @@ import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.HashMap;
import java.util.Set;
@ -37,9 +39,17 @@ public class EnchantConfigGui extends ChestGui implements ValueUpdatableGui {
private EnchantConflictGui enchantConflictGui;
private GroupConfigGui groupConfigGui;
private static String selectName(@NotNull Set<CAEnchantment> enchantments) {
if(enchantments.size() == 1) {
return enchantments.stream().findFirst().get().getPrettyName();
}
return MsgUI.INSTANCE.getENCHANT_CONFIG_MULTIPLES_NAME().unformatted();
}
public EnchantConfigGui(@NotNull Set<CAEnchantment> enchantments) {
super(3,
"Configuring Enchantments",
MsgUI.INSTANCE.getENCHANT_CONFIG_TITLE().textHolder(selectName(enchantments)),
CustomAnvil.instance);
this.enchantments = enchantments;
@ -57,7 +67,7 @@ public class EnchantConfigGui extends ChestGui implements ValueUpdatableGui {
ItemMeta displayMeta = displayItemstack.getItemMeta();
assert displayMeta != null;
displayMeta.setDisplayName("§aConfiguring Enchantments:");
ComponentUtil.INSTANCE.setMessageName(displayMeta, MsgUI.INSTANCE.getENCHANT_CONFIG_NAME(), selectName(enchantments));
displayItemstack.setItemMeta(displayMeta);
// Set enchantments

View file

@ -14,9 +14,11 @@ import xyz.alexcrea.cuanvil.group.IncludeGroup;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.elements.EnchantConflictSubSettingGui;
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.ComponentUtil;
import java.util.Arrays;
import java.util.Collection;
public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGroup,
@ -38,11 +40,11 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
// Need to init myself
public EnchantConflictGui(Gui parent) {
super("Conflict Config", parent);
super(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_TITLE(), parent);
}
private EnchantConflictGui() {
super("Conflict Config");
super(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_TITLE());
init();
}
@ -52,7 +54,7 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
// Create new empty conflict and display it to the admin
EnchantConflictGroup conflict = new EnchantConflictGroup(
name,
new IncludeGroup("new_group"),
new IncludeGroup(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_DEFAULT_NEW().unformatted()),
0);
ConfigHolder.CONFLICT_HOLDER.getConflictManager().addConflict(conflict);
@ -80,12 +82,14 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
assert meta != null;
meta.addItemFlags(ItemFlag.values());
meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(conflict.toString()) + " §fConflict");
meta.setLore(Arrays.asList(
"§7Enchantment count: §e" + conflict.getEnchants().size(),
"§7Group count: §e" + conflict.getCantConflictGroup().getGroups().size(),
"§7Min enchantments count: §e" + conflict.getMinBeforeBlock()
));
var name = CasedStringUtil.snakeToUpperSpacedCase(conflict.toString());
ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_NAME(), name);
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_LORE().formatted(
conflict.getEnchants().size(),
conflict.getCantConflictGroup().getGroups().size(),
conflict.getMinBeforeBlock()
), meta);
item.setItemMeta(meta);
return item;
@ -97,8 +101,8 @@ public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGr
}
@Override
protected String genericDisplayedName() {
return "conflict";
protected Message genericDisplayedName() {
return MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_GENERIC_NAME();
}
@Override

View file

@ -2,6 +2,7 @@ package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -11,8 +12,12 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -36,7 +41,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
* Constructor of this Global gui for enchantment cost settings.
*/
public EnchantCostConfigGui() {
super("§8Enchantment Level Cost");
super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_TITLE());
if (INSTANCE == null) INSTANCE = this;
init();
@ -46,7 +51,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
* Constructor of this Global gui for enchantment cost settings.
*/
public EnchantCostConfigGui(Gui parent) {
super("§8Enchantment Level Cost", parent);
super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_TITLE(), parent);
}
@Override
@ -58,12 +63,10 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
String key = enchant.getKey().toString().toLowerCase(Locale.ENGLISH);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
return new EnchantCostSettingsGui.EnchantCostSettingFactory(prettyKey + " Cost", parent,
return new EnchantCostSettingsGui.EnchantCostSettingFactory(
MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_ELEMENT_TITLE(), parent,
ENCHANT_VALUES_ROOT + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7How many level should " + prettyKey,
"§7cost when applied by book or by another item."
),
MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_ELEMENT_DESCRIPTION(), prettyKey,
enchant, 0, 255,
1, 10, 50);
}
@ -73,26 +76,26 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
// Get item properties
int itemCost = factory.getConfiguredValue();
int bookCost = factory.getConfiguredBookValue();
String itemName = "§a" + factory.getTitle();
Message itemName = factory.getTitle();
// Create item
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta itemMeta = item.getItemMeta();
assert itemMeta != null;
// Prepare lore
List<String> lore = new ArrayList<>();
lore.add("§7Item Cost: §e" + itemCost);
lore.add("§7Book Cost: §e" + bookCost);
List<Component> lore = new ArrayList<>();
lore.addAll(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_ELEMENT_ITEM_COST().formatted(itemCost));
lore.addAll(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_COST_ELEMENT_BOOK_COST().formatted(bookCost));
List<String> displayLore = factory.getDisplayLore();
if (!displayLore.isEmpty()) {
lore.add("");
lore.addAll(displayLore);
List<Message> displayLore = factory.getDisplayLore();
if (displayLore != null) {
lore.add(Component.empty());
lore.addAll(ComponentUtil.INSTANCE.asComponents(displayLore, factory.getParam()));
}
// Edit name and lore
itemMeta.setDisplayName(itemName);
itemMeta.setLore(lore);
ComponentUtil.INSTANCE.setMessageName(itemMeta, itemName, factory.getParam());
ComponentUtil.INSTANCE.applyLore(lore, itemMeta);
item.setItemMeta(itemMeta);

View file

@ -9,9 +9,9 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Collections;
import java.util.Locale;
/**
@ -32,14 +32,14 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
* Constructor of this Global gui for enchantment level limit settings.
*/
public EnchantLimitConfigGui() {
super("§8Enchantment Level Limit");
super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_LIMIT_TITLE());
if(INSTANCE == null) INSTANCE = this;
init();
}
public EnchantLimitConfigGui(Gui parent) {
super("§8Enchantment Level Limit", parent);
super(MsgUI.INSTANCE.getENCHANTMENT_LEVEL_LIMIT_TITLE(), parent);
}
@Override
@ -52,12 +52,12 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
var defaultValue = enchant.defaultMaxLevel();
var defaultValueStr = String.valueOf(enchant.defaultMaxLevel());
return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", parent,
return new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getENCHANTMENT_LEVEL_LIMIT_ELEMENT_TITLE(), parent,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Collections.singletonList(
"§7Maximum applied level of " + prettyKey
),
MsgUI.INSTANCE.getENCHANTMENT_LEVEL_LIMIT_ELEMENT_DESCRIPTION(), prettyKey,
-1, 255, -1,
1, 5, 10, 50, 100){
@ -69,12 +69,11 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
@Override
public String valueDisplayName(IntSettingsGui.ValueDisplayType type, int value) {
if(value < 0) {
return switch (type) {
case CURRENT -> "Default (" + defaultValue + ")";
case RESET -> String.valueOf(defaultValue);
default -> "Default";
case CURRENT -> MsgUI.INSTANCE.getSHARED_VALUED_DEFAULT().unformatted(defaultValueStr);
case RESET -> defaultValueStr;
default -> MsgUI.INSTANCE.getSHARED_DEFAULT().unformatted();
};
}
@ -87,7 +86,9 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
public GuiItem itemFromFactory(CAEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) {
return inventoryFactory.getItem(
Material.ENCHANTED_BOOK,
inventoryFactory.getTitle());
inventoryFactory.getTitle(),
inventoryFactory.getParam()
);
}
}

View file

@ -9,6 +9,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Arrays;
@ -29,7 +30,7 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
* Constructor of this Global gui for enchantment level limit settings.
*/
public EnchantMergeLimitConfigGui() {
super("§8Enchantment Maximum Merge Level");
super(MsgUI.INSTANCE.getENCHANTMENT_MERGE_LIMIT_TITLE());
if(INSTANCE == null) INSTANCE = this;
init();
@ -39,7 +40,7 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
* Constructor of this Global gui for enchantment level limit settings.
*/
public EnchantMergeLimitConfigGui(Gui parent) {
super("§8Enchantment Maximum Merge Level", parent);
super(MsgUI.INSTANCE.getENCHANTMENT_MERGE_LIMIT_TITLE(), parent);
}
@ -52,18 +53,12 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
return new IntSettingsGui.IntSettingFactory(prettyKey + " Merge Limit", parent,
return new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getENCHANTMENT_MERGE_LIMIT_ELEMENT_TITLE(), parent,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"§7Maximum merge level for for " + prettyKey,
"",
"§7For example, if set to §e2§7, §alvl1 §7+ §alvl1 §7of will give a §alvl2",
"§7But §alvl2 §7+ §alvl2 §7will not give a §clv3§7.",
"§7Will still not merge above max enchantment level",
"§e-1 §7(default) will set the merge limit to enchantment's maximum level"
),
MsgUI.INSTANCE.getENCHANTMENT_MERGE_LIMIT_ELEMENT_DESCRIPTION(), prettyKey,
-1, 255, -1,
1, 5, 10, 50, 100){
1, 5, 10, 50, 100) {
@Override
public int getConfiguredValue() {
@ -76,6 +71,8 @@ public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSett
public GuiItem itemFromFactory(CAEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) {
return inventoryFactory.getItem(
Material.ENCHANTED_BOOK,
inventoryFactory.getTitle());
inventoryFactory.getTitle(),
inventoryFactory.getParam()
);
}
}

View file

@ -15,11 +15,12 @@ import xyz.alexcrea.cuanvil.group.IncludeGroup;
import xyz.alexcrea.cuanvil.group.ItemGroupManager;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.elements.GroupConfigSubSettingGui;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.LazyValue;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, MappedGuiListConfigGui.LazyElement<GroupConfigSubSettingGui>> {
@ -39,13 +40,13 @@ public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, MappedG
}
public GroupConfigGui() {
super("Group Config");
super(MsgUI.INSTANCE.getMATERIAL_GROUP_TITLE());
init();
}
public GroupConfigGui(Gui parent) {
super("Group Config", parent);
super(MsgUI.INSTANCE.getMATERIAL_GROUP_TITLE(), parent);
}
@Override
@ -55,12 +56,19 @@ public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, MappedG
assert meta != null;
meta.addItemFlags(ItemFlag.values());
meta.setDisplayName("§e" + CasedStringUtil.snakeToUpperSpacedCase(group.getName())+ " §fGroup");
meta.setLore(Arrays.asList(
"§7Number of selected groups : " + group.getGroups().size(),
"§7Number of included material : " + group.getNonGroupInheritedMaterials().size(),
"",
"§7Total number of included material "+group.getMaterials().size()));
ComponentUtil.INSTANCE.setMessageName(
meta,
MsgUI.INSTANCE.getMATERIAL_GROUP_NAME(),
CasedStringUtil.snakeToUpperSpacedCase(group.getName())
);
ComponentUtil.INSTANCE.applyLore(
MsgUI.INSTANCE.getMATERIAL_GROUP_LORE().formatted(
group.getGroups().size(),
group.getNonGroupInheritedMaterials().size(),
group.getMaterials().size()
),
meta
);
item.setItemMeta(meta);
return item;
@ -84,8 +92,8 @@ public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, MappedG
}
@Override
protected String genericDisplayedName() {
return "material group";
protected Message genericDisplayedName() {
return MsgUI.INSTANCE.getMATERIAL_GROUP_GENERIC_NAME();
}
@Override

View file

@ -15,7 +15,9 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil;
import xyz.alexcrea.cuanvil.util.UnitRepairUtil;
@ -27,10 +29,10 @@ public class ItemConfigGui extends ChestGui {
private CustomRecipeConfigGui customRecipeConfigGui;
public ItemConfigGui(@NotNull Material display, @NotNull NamespacedKey material) {
super(3,
super(3, MsgUI.INSTANCE.getITEM_CONFIG_TITLE().textHolder(
CasedStringUtil.snakeToUpperSpacedCase(
material.getKey().toLowerCase()
) + " Config",
)),
CustomAnvil.instance);
Pattern pattern = new Pattern(
@ -47,7 +49,7 @@ public class ItemConfigGui extends ChestGui {
ItemMeta displayMeta = displayItemstack.getItemMeta();
assert displayMeta != null;
displayMeta.setDisplayName("§aConfiguring " + material);
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getITEM_CONFIG_TITLE().formatted(material), displayMeta);
displayItemstack.setItemMeta(displayMeta);
pane.bindItem('D', new GuiItem(displayItemstack, GuiGlobalActions.stayInPlace, CustomAnvil.instance));

View file

@ -13,6 +13,8 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.config.ask.SelectItemTypeGui;
import xyz.alexcrea.cuanvil.gui.config.list.MappedGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -38,13 +40,13 @@ public class UnitRepairConfigGui extends
}
private UnitRepairConfigGui() {
super("Unit Repair Config");
super(MsgUI.INSTANCE.getUNIT_REPAIR_TITLE());
init();
}
public UnitRepairConfigGui(Gui parent) {
super("Unit Repair Config", parent);
super(MsgUI.INSTANCE.getUNIT_REPAIR_TITLE(), parent);
}
@Override
@ -128,9 +130,8 @@ public class UnitRepairConfigGui extends
clickEvent.setCancelled(true);
new SelectItemTypeGui(
"Select unit repair item.",
"§7Click here with an item to set the item\n" +
"§7You like to be an unit repair item",
MsgUI.INSTANCE.getUNIT_REPAIR_NEW_TITLE(), "",
MsgUI.INSTANCE.getUNIT_REPAIR_NEW_DESCRIPTION(), "",
this,
(itemStack, player) -> {
NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack);
@ -157,14 +158,14 @@ public class UnitRepairConfigGui extends
return element;
}
@Override // Not used in this implementation.
protected String genericDisplayedName() {
return "this function Should not be used.";
@Override
protected Message genericDisplayedName() {
throw new RuntimeException("SHOULD NOT BE USED IN THIS IMPLEMENTATION");
}
@Override // Not used in this implementation.
@Override
protected NamespacedKey createAndSaveNewEmptyGeneric(String name) {
return null;
throw new RuntimeException("SHOULD NOT BE USED IN THIS IMPLEMENTATION");
}
}

View file

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

View file

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

View file

@ -8,6 +8,8 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.LazyValue;
import java.util.Locale;
@ -18,12 +20,20 @@ import java.util.function.Supplier;
public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui.LazyElement<?>>
extends MappedElementListConfigGui<T, S> {
protected MappedGuiListConfigGui(@NotNull String title) {
super(title);
protected MappedGuiListConfigGui(@NotNull Message title, @NotNull String param) {
super(title, param);
}
protected MappedGuiListConfigGui(@NotNull String title, @NotNull Gui parent) {
super(title, parent);
protected MappedGuiListConfigGui(@NotNull Message title, @NotNull String param, @NotNull Gui parent) {
super(title, param, parent);
}
protected MappedGuiListConfigGui(@NotNull Message title) {
super(title, "");
}
protected MappedGuiListConfigGui(@NotNull Message title, @NotNull Gui parent) {
super(title, "", parent);
}
@Override
@ -69,13 +79,13 @@ public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui
// check permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM);
MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return;
}
message = message.toLowerCase(Locale.ROOT);
if ("cancel".equalsIgnoreCase(message)) {
player.sendMessage(genericDisplayedName() + " creation cancelled...");
MsgUI.INSTANCE.getELEMENT_LIST_CANCELLED_NEW().send(player, genericDisplayedName());
show(player);
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.
for (T generic : getDisplayableInstanceOfGeneric()) {
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.
CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get());
return;
@ -113,7 +123,7 @@ public abstract class MappedGuiListConfigGui<T, S extends MappedGuiListConfigGui
protected abstract S newInstanceOfGui(T generic, GuiItem item);
protected abstract String genericDisplayedName();
protected abstract Message genericDisplayedName();
protected abstract T createAndSaveNewEmptyGeneric(String name);

View file

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

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.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -32,12 +33,16 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
private boolean shouldWork = true;
private static String prettifiedName(NamespacedKey parentMaterial) {
return CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.getKey().toLowerCase());
}
public UnitRepairElementListGui(@NotNull NamespacedKey parentMaterial,
@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.parentGui = parentGui;
this.materialName = CasedStringUtil.snakeToUpperSpacedCase(parentMaterial.getKey().toLowerCase());
this.materialName = prettifiedName(parentMaterial);
GuiGlobalItems.addBackItem(this.backgroundPane, parentGui);
}
@ -45,7 +50,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
// SettingGuiListConfigGui methods
@Override
protected List<String> getCreateItemLore() {
return Arrays.asList(
return Arrays.asList(//TODO MESSAGE
"§7Select a new item to be repairable.",
"§7You will be asked the material to use."
);
@ -55,26 +60,25 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
protected Consumer<InventoryClickEvent> getCreateClickConsumer() {
return event -> {
event.setCancelled(true);
if (!this.shouldWork) {
if(!this.shouldWork) {
return;
}
event.setCancelled(true);
new SelectItemTypeGui(
"Select item to be repaired.",
"§7Click here with an item to set the item\n" +
"§7You like to be repaired by " + this.materialName,
MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_TITLE(), this.materialName,
MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_DESCRIPTION(), this.materialName,
this,
(itemStack, player) -> {
ItemMeta meta = itemStack.getItemMeta();
NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack);
if (!(meta instanceof Damageable)) {
player.sendMessage("§cThis item can't be damaged, so it can't be repaired.");
if(!(meta instanceof Damageable)) {
MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_CANNOT_REPAIR().send(player);
return;
}
if (type.equals(this.parentMaterial)) {
player.sendMessage("§cItem can't repair something of the same type.");
if(type.equals(this.parentMaterial)) {
MsgUI.INSTANCE.getUNIT_REPAIR_NEW_ELEMENT_SAME_TYPE().send(player);
return;
}
@ -83,7 +87,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
// Add new material
ConfigHolder.UNIT_REPAIR_HOLDER.getConfig().set(parentMaterial.toString().toLowerCase() + "." + materialName, 0.25);
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
@ -103,7 +107,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
@Override
protected String createItemName() {
return "§aAdd a new item reparable by " + this.materialName;
return "§aAdd a new item reparable by " + this.materialName; //TODO MESSAGE ?
}
@Override
@ -111,14 +115,12 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
String materialDisplayName = CasedStringUtil.snakeToUpperSpacedCase(materialName.getKey());
return new DoubleSettingGui.DoubleSettingFactory(
"§0%§8" + materialDisplayName + " Repair",
MsgUI.INSTANCE.getUNIT_REPAIR_ELEMENT_VALUE_TITLE(),
this,
ConfigHolder.UNIT_REPAIR_HOLDER,
this.parentMaterial.toString().toLowerCase() + "." + materialName,
Arrays.asList(
"§7Click here to change how many §e% §7of §a" + materialDisplayName,
"§7Should get repaired by §e" + this.materialName
),
MsgUI.INSTANCE.getUNIT_REPAIR_ELEMENT_VALUE_DESCRIPTION(),
materialDisplayName, this.materialName,
2,
true, true,
0,
@ -130,14 +132,18 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
@Override
protected GuiItem itemFromFactory(NamespacedKey materialName, DoubleSettingGui.DoubleSettingFactory factory) {
return factory.getItem(materialFromName(materialName),
"§7%§a" + CasedStringUtil.snakeToUpperSpacedCase(materialName.getKey()) + " §erepaired by §a" + this.materialName);
return factory.getItem(
materialFromName(materialName),
MsgUI.INSTANCE.getUNIT_REPAIR_ITEM(),
CasedStringUtil.snakeToUpperSpacedCase(materialName.getKey()),
this.materialName
);
}
@Override
protected Collection<NamespacedKey> getEveryInstanceOfGeneric() {
Set<NamespacedKey> keys = new HashSet<>();
if (!this.shouldWork) {
if(!this.shouldWork) {
return keys;
}
@ -151,10 +157,10 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
}
private void addAllKeys(@Nullable ConfigurationSection section, @NotNull Set<NamespacedKey> keys) {
if (section == null) return;
for (var key : section.getKeys(false)) {
if(section == null) return;
for(var key : section.getKeys(false)) {
var material = NamespacedKey.fromString(key);
if (material == null) continue;
if(material == null) continue;
keys.add(material);
}
@ -162,7 +168,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
private Material materialFromName(NamespacedKey material) {
Material mat = MaterialUtil.INSTANCE.getMatFromKey(material);
if (mat == null || mat.isAir()) return Material.BARRIER;
if(mat == null || mat.isAir()) return Material.BARRIER;
return mat;
}
@ -185,7 +191,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
this.backgroundPane.bindItem('L', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE));
this.backgroundPane.bindItem('R', GuiGlobalItems.backgroundItem(Material.BLACK_STAINED_GLASS_PANE));
for (HumanEntity viewer : getViewers()) {
for(HumanEntity viewer : getViewers()) {
viewer.sendMessage("This config do not exist anymore");
this.parentGui.show(viewer);
}
@ -198,7 +204,7 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
@Override
public void show(@NotNull HumanEntity humanEntity) {
if (!this.shouldWork) {
if(!this.shouldWork) {
humanEntity.closeInventory();
return;
}

View file

@ -19,10 +19,13 @@ import xyz.alexcrea.cuanvil.gui.config.settings.ItemSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
import xyz.alexcrea.cuanvil.recipe.CustomAnvilRecipeManager;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.awt.*;
import java.util.Collections;
import java.util.function.Supplier;
@ -36,7 +39,7 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
public CustomRecipeSubSettingGui(
@NotNull CustomRecipeConfigGui parent,
@NotNull AnvilCustomRecipe anvilRecipe) {
super(4, "§e" + CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.toString()) + " §8Config");
super(4, CasedStringUtil.snakeToUpperSpacedCase(anvilRecipe.toString()));
this.parent = parent;
this.anvilRecipe = anvilRecipe;
@ -73,65 +76,79 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
ItemMeta deleteMeta = deleteItem.getItemMeta();
assert deleteMeta != null;
deleteMeta.setDisplayName("§4DELETE RECIPE");
deleteMeta.setLore(Collections.singletonList("§cCaution with this button !"));
ComponentUtil.INSTANCE.setMessageName(deleteMeta, MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_DELETE_BUTTON_NAME());
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_DELETE_BUTTON_LORE().formatted(), deleteMeta);
deleteItem.setItemMeta(deleteMeta);
this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance));
// Displayed item will be updated later
IntRange costRange = AnvilCustomRecipe.Companion.getXP_COST_CONFIG_RANGE();
this.exactCountFactory = new BoolSettingsGui.BoolSettingFactory("§8Exact count ?", this,
this.exactCountFactory = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_EXACT_COUNT_TITLE(), this,
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,
null
);
this.removeExactLinearXpFactory = new BoolSettingsGui.BoolSettingFactory("§8Remove exact linear xp ?", this,
this.removeExactLinearXpFactory = new BoolSettingsGui.BoolSettingFactory(
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_LINEAR_XP_TITLE(), this,
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,
null
);
ItemStack item = new ItemStack(Material.BARRIER);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§cRemove exact linear xp ?");
meta.setLore(Collections.singletonList("§7Not usable if linear cost is 0"));
ComponentUtil.INSTANCE.setMessageName(meta, MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_LINEAR_XP_NAME());
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_LINEAR_XP_LORE().formatted(), meta);
item.setItemMeta(meta);
this.noRemoveExactLinearXp = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
this.levelCostFactory = new IntSettingsGui.IntSettingFactory("§8Recipe Level Cost", this,
this.levelCostFactory = new IntSettingsGui.IntSettingFactory(
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_COST_LEVEL_XP(), this,
this.anvilRecipe + "." + AnvilCustomRecipe.XP_LEVEL_COST_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
null,
costRange.getFirst(), costRange.getLast(), AnvilCustomRecipe.DEFAULT_XP_LEVEL_COST_CONFIG, 1, 5, 10);
null, null,
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(
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_COST_LINEAR_XP(), this,
this.anvilRecipe + "." + AnvilCustomRecipe.LINEAR_XP_COST_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
null,
0, Integer.MAX_VALUE, AnvilCustomRecipe.DEFAULT_LINEAR_XP_COST_CONFIG, 1, 10, 100, 1000, 10000);
null, null,
0, Integer.MAX_VALUE, AnvilCustomRecipe.DEFAULT_LINEAR_XP_COST_CONFIG, 1, 10, 100, 1000, 10000
);
// Right part of the gui
this.leftItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Left §8Item", this,
this.leftItemFactory = new ItemSettingGui.ItemSettingFactory(
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_ITEM_LEFT_TITLE(), this,
this.anvilRecipe + "." + AnvilCustomRecipe.LEFT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_LEFT_ITEM_CONFIG(),
"§7Set the left item of the custom craft",
"§7\u25A0 + \u25A1 = \u25A1");
null, MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_ITEM_LEFT_DESCRIPTION()
);
this.rightItemFactory = new ItemSettingGui.ItemSettingFactory("§eRecipe Right §8Item", this,
this.rightItemFactory = new ItemSettingGui.ItemSettingFactory(
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_ITEM_RIGHT_TITLE(), this,
this.anvilRecipe + "." + AnvilCustomRecipe.RIGHT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_RIGHT_ITEM_CONFIG(),
"§7Set the right item of the custom craft",
"§7\u25A1 + \u25A0 = \u25A1");
null, MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_ITEM_RIGHT_DESCRIPTION()
);
this.resultItemFactory = new ItemSettingGui.ItemSettingFactory("§aRecipe Result §8Item", this,
this.resultItemFactory = new ItemSettingGui.ItemSettingFactory(
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_ITEM_RESULT_TITLE(), this,
this.anvilRecipe + "." + AnvilCustomRecipe.RESULT_ITEM_CONFIG,
ConfigHolder.CUSTOM_RECIPE_HOLDER,
AnvilCustomRecipe.Companion.getDEFAULT_RESULT_ITEM_CONFIG(),
"§7Set the result item of the custom craft",
"§7\u25A1 + \u25A1 = \u25A0");
null, MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_ITEM_RESULT_DESCRIPTION()
);
// Now we update the items
updateLocal();
@ -162,8 +179,9 @@ public class CustomRecipeSubSettingGui extends MappedToListSubSettingGui {
return success;
};
return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.anvilRecipe.toString()) + "§c?",
"§7Confirm that you want to delete this conflict.",
var type = CasedStringUtil.snakeToUpperSpacedCase(this.anvilRecipe.toString());
return new ConfirmActionGui(MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_DELETE_TITLE(), type,
MsgUI.INSTANCE.getCUSTOM_RECIPE_ELEMENT_DELETE_DESCRIPTION(), type,
this, this.parent, deleteSupplier
);
}

View file

@ -24,7 +24,9 @@ import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import xyz.alexcrea.cuanvil.util.MetricsUtil;
import java.util.*;
@ -41,8 +43,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
public EnchantConflictSubSettingGui(
@NotNull EnchantConflictGui parent,
@NotNull EnchantConflictGroup enchantConflict) {
super(3,
"§e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + " §8Config");
super(3, CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()));
this.parent = parent;
this.enchantConflict = enchantConflict;
@ -71,8 +72,8 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
ItemMeta deleteMeta = deleteItem.getItemMeta();
assert deleteMeta != null;
deleteMeta.setDisplayName("§4DELETE CONFLICT");
deleteMeta.setLore(Collections.singletonList("§cCaution with this button !"));
ComponentUtil.INSTANCE.setMessageName(deleteMeta, MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_BUTTON_NAME());
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_BUTTON_LORE().formatted(), deleteMeta);
deleteItem.setItemMeta(deleteMeta);
this.pane.bindItem('D', new GuiItem(deleteItem, GuiGlobalActions.openGuiAction(createDeleteGui()), CustomAnvil.instance));
@ -80,27 +81,26 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
// Displayed item will be updated later
this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), event -> {
event.setCancelled(true);
var type = CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString());
EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui(
"§e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.toString()) + "§5",
MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_ENCHANTMENTS(), type,
this, this);
enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance);
this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), event -> {
event.setCancelled(true);
var type = CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString());
GroupSelectSettingGui enchantGui = new GroupSelectSettingGui(
"§e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + " §3Groups",
MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_SUB_GROUPS(), type,
this, this, 0);
enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance);
this.minBeforeActiveSettingFactory = new IntSettingsGui.IntSettingFactory(
"§8Minimum enchantment count",
MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_MIN_BEFORE_COUNT_TITLE(),
this, this.enchantConflict + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER,
Arrays.asList(
"§7Minimum enchantment count set to X mean only X enchantment can be put",
"§7on an item before the conflict is active."
),
MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_MIN_BEFORE_COUNT_DESCRIPTION(), null,
0, 255, 0, 1
);
@ -137,8 +137,9 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
return success;
};
return new ConfirmActionGui("§cDelete §e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString()) + "§c?",
"§7Confirm that you want to delete this conflict.",
var type = CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.toString());
return new ConfirmActionGui(MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_TITLE(), type,
MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_DELETE_DESCRIPTION(), type,
this, this.parent, deleteSupplier
);
}
@ -159,12 +160,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
// Prepare enchantment lore
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();
if (enchants.isEmpty()) {
enchantLore.add("§7There is no included enchantment for this conflict.");
enchantLore.add("§7There is no included enchantment for this conflict.");//TODO MESSAGE
} else {
enchantLore.add("§7List of included enchantment for this conflict:");
enchantLore.add("§7List of included enchantment for this conflict:");//TODO MESSAGE
Iterator<CAEnchantment> enchantIterator = enchants.iterator();
boolean greaterThanMax = enchants.size() > 5;
@ -175,7 +176,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
enchantLore.add("§7- §5" + formattedName);
}
if (greaterThanMax) {
enchantLore.add("§7And " + (enchants.size() - 4) + " more...");
enchantLore.add("§7And " + (enchants.size() - 4) + " more...");//TODO MESSAGE
}
}
@ -188,7 +189,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
ItemMeta enchantMeta = enchantItem.getItemMeta();
assert enchantMeta != null;
enchantMeta.setDisplayName("§aSelect included §5Enchantments §aSettings");
enchantMeta.setDisplayName("§aSelect included §5Enchantments §aSettings");//TODO MESSAGE
enchantMeta.setLore(enchantLore);
enchantItem.setItemMeta(enchantMeta);
@ -200,15 +201,17 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
ItemMeta groupMeta = groupItem.getItemMeta();
assert groupMeta != null;
groupMeta.setDisplayName("§aSelect Excluded §3Groups §aSettings");
groupMeta.setDisplayName("§aSelect Excluded §3Groups §aSettings");//TODO MESSAGE
groupMeta.setLore(groupLore);
groupItem.setItemMeta(groupMeta);
this.groupSettingItem.setItem(groupItem); // Just in case
this.pane.bindItem('M', this.minBeforeActiveSettingFactory.getItem(Material.COMMAND_BLOCK,
"Minimum Enchantment Count"));
this.pane.bindItem('M', this.minBeforeActiveSettingFactory.getItem(
Material.COMMAND_BLOCK,
MsgUI.INSTANCE.getENCHANTMENT_CONFLICT_ELEMENT_MIN_BEFORE_COUNT_ITEM()
));
update();
}
@ -246,7 +249,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
@Override
public boolean setSelectedEnchantments(Set<CAEnchantment> enchantments) {
if (!this.shouldWork) {
CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed");
CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed");//TODO MESSAGE
return false;
}
@ -264,7 +267,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
try {
updateGuiValues();
} catch (Exception e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, e);
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict, e);//TODO MESSAGE
MetricsUtil.INSTANCE.trackError(e);
}
@ -291,7 +294,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
@Override
public boolean setSelectedGroups(Set<AbstractMaterialGroup> groups) {
if (!this.shouldWork) {
CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.toString() + " groups but sub config is destroyed");
CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.toString() + " groups but sub config is destroyed");//TODO MESSAGE
return false;
}
@ -309,7 +312,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
try {
updateGuiValues();
} catch (Exception e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, e);
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict, e);//TODO MESSAGE
MetricsUtil.INSTANCE.trackError(e);
}

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

View file

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

View file

@ -8,17 +8,17 @@ import com.github.stefvanschie.inventoryframework.pane.PatternPane;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import io.delilaheve.CustomAnvil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.lang.Message;
/**
* An instance gui used to edit a setting.
*/
public abstract class AbstractSettingGui extends ChestGui implements SettingGui {
public static final String CLICK_LORE = "§7Click Here to change the value";
private PatternPane pane;
/**
@ -40,8 +40,13 @@ public abstract class AbstractSettingGui extends ChestGui implements SettingGui
* @param title Title of this gui.
* @param parent Parent gui to go back when completed.
*/
protected AbstractSettingGui(int rows, @NotNull String title, ValueUpdatableGui parent) {
this(rows, StringHolder.of(title), parent);
protected AbstractSettingGui(
int rows,
@NotNull Message title,
ValueUpdatableGui parent,
@Nullable Object... params
) {
this(rows, title.textHolder(params), parent);
}
protected GuiItem saveItem;

View file

@ -5,16 +5,21 @@ import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.PatternPane;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import io.delilaheve.CustomAnvil;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.ArrayList;
import java.util.Arrays;
@ -38,7 +43,7 @@ public class BoolSettingsGui extends AbstractSettingGui {
* @param now The defined value of this setting.
*/
protected BoolSettingsGui(BoolSettingFactory holder, boolean now) {
super(3, holder.getTitle(), holder.parent);
super(3, holder.getTitle(), holder.parent, holder.param);
this.holder = holder;
this.before = now;
this.now = now;
@ -105,20 +110,21 @@ public class BoolSettingsGui extends AbstractSettingGui {
}
// create & set Value item
ArrayList<String> valueLore = new ArrayList<>();
if(!holder.displayLore.isEmpty()){
valueLore.addAll(holder.displayLore);
valueLore.add("");
ArrayList<Component> valueLore = new ArrayList<>();
if(holder.displayLore != null){
valueLore.addAll(ComponentUtil.INSTANCE.asComponents(holder.displayLore, holder.param));
valueLore.add(Component.empty());
}
valueLore.add(AbstractSettingGui.CLICK_LORE);
valueLore.addAll(MsgUI.INSTANCE.getSHARED_CLICK_TO_CHANGE().formatted());
ItemStack valueItemStack = new ItemStack(displayedMat);
ItemMeta valueMeta = valueItemStack.getItemMeta();
assert valueMeta != null;
valueMeta.setDisplayName(displayedName);
valueMeta.setLore(valueLore);
valueMeta.setDisplayName(displayedName);//TODO MESSAGE ?
ComponentUtil.INSTANCE.applyLore(valueLore, valueMeta);
valueItemStack.setItemMeta(valueMeta);
GuiItem resultItem = new GuiItem(valueItemStack, inverseNowConsumer(), CustomAnvil.instance);
pane.bindItem('v', resultItem);
@ -166,13 +172,15 @@ public class BoolSettingsGui extends AbstractSettingGui {
*/
public static class BoolSettingFactory extends SettingGuiFactory {
@NotNull
String title;
Message title;
@NotNull
ValueUpdatableGui parent;
boolean defaultVal;
@NotNull
List<String> displayLore;
@Nullable
List<Message> displayLore;
@Nullable
Object param;
/**
* Constructor for a boolean setting gui factory.
@ -185,22 +193,25 @@ public class BoolSettingsGui extends AbstractSettingGui {
* @param displayLore Gui display item lore.
*/
public BoolSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull Message title, @NotNull ValueUpdatableGui parent,
@NotNull ConfigHolder config, @NotNull String configPath,
boolean defaultVal, String... displayLore) {
boolean defaultVal,
@Nullable Object param, @Nullable Message... displayLore) {
super(configPath, config);
this.title = title;
this.parent = parent;
this.defaultVal = defaultVal;
this.displayLore = Arrays.asList(displayLore);
this.displayLore = displayLore == null ? null : Arrays.asList(displayLore);
this.param = param;
}
/**
* @return Get setting's gui title.
*/
@NotNull
public String getTitle() {
public Message getTitle() {
return title;
}
@ -225,25 +236,36 @@ public class BoolSettingsGui extends AbstractSettingGui {
* The item will have its value written in the lore part of the item.
*
* @param name Name of the item.
* @param params parameters for the given name.
* @return A formatted GuiItem that will create and open a GUI for the boolean setting.
*/
public GuiItem getItem(String name){
public GuiItem getItem(
@NotNull Message name,
Object... params
){
// Get item properties
boolean value = getConfiguredValue();
Material itemMat;
StringBuilder itemName = new StringBuilder("§e");
Component itemName = name.formattedConcatenated(params);
String finalValue;
if (value) {
itemMat = Material.GREEN_TERRACOTTA;
finalValue = "§aYes";
finalValue = "<green>Yes";//TODO MESSAGE
} else {
itemMat = Material.RED_TERRACOTTA;
finalValue = "§cNo";
finalValue = "<red>No";//TODO MESSAGE
}
itemName.append(name);
return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName, finalValue, this.displayLore, false);
return GuiGlobalItems.createGuiItemFromProperties(
this,
itemMat, itemName,
finalValue,
this.displayLore,
false,
this.param
);
}
/**
@ -258,7 +280,7 @@ public class BoolSettingsGui extends AbstractSettingGui {
// Get item properties
String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath());
return getItem(CasedStringUtil.detectToUpperSpacedCase(configPath));
return getItem(MsgUI.INSTANCE.getSHARED_YELLOW_GET_ITEM(), CasedStringUtil.detectToUpperSpacedCase(configPath));
}
}

View file

@ -5,6 +5,7 @@ import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.PatternPane;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import io.delilaheve.CustomAnvil;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -17,7 +18,10 @@ import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.math.BigDecimal;
import java.math.RoundingMode;
@ -48,7 +52,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
*/
protected DoubleSettingGui(DoubleSettingFactory holder, @NotNull BigDecimal now,
boolean asPercentage, boolean nullOnZero) {
super(3, holder.getTitle(), holder.parent);
super(3, holder.getTitle(), holder.parent, holder.param, holder.param2);
assert holder.steps.length > 0 && holder.steps.length <= 9;
this.holder = holder;
this.asPercentage = asPercentage;
@ -166,7 +170,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
ItemMeta resultMeta = resultPaper.getItemMeta();
assert resultMeta != null;
resultMeta.setDisplayName("§fValue: §e" + displayValue(now));
resultMeta.setDisplayName("<white>Value: <yellow>" + displayValue(now));
resultPaper.setItemMeta(resultMeta);
GuiItem resultItem = new GuiItem(resultPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
@ -185,12 +189,12 @@ public class DoubleSettingGui extends AbstractSettingGui {
private GuiItem getSetValueItem(Material mat, BigDecimal planned, String numberPrefix){
// Create set item lore
ArrayList<String> setLoreItem = new ArrayList<>();
if(!holder.displayLore.isEmpty()){
setLoreItem.addAll(holder.displayLore);
setLoreItem.add("");
ArrayList<Component> setLoreItem = new ArrayList<>();
if(holder.displayLore != null){
setLoreItem.addAll(holder.displayLore.formatted(holder.param, holder.param2));
setLoreItem.add(Component.empty());
}
setLoreItem.add(AbstractSettingGui.CLICK_LORE);
setLoreItem.addAll(MsgUI.INSTANCE.getSHARED_CLICK_TO_CHANGE().formatted());
// Create & return set value item
ItemStack item = new ItemStack(mat);
@ -199,7 +203,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
meta.setDisplayName("§e" + displayValue(now) + " §f-> §e" + displayValue(planned)
+ " §r(" + numberPrefix + (displayValue(planned.subtract(now).abs()) + "§r)"));
meta.setLore(setLoreItem);
ComponentUtil.INSTANCE.applyLore(setLoreItem, meta);
item.setItemMeta(meta);
return new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
@ -357,7 +361,7 @@ public class DoubleSettingGui extends AbstractSettingGui {
*/
public static class DoubleSettingFactory extends SettingGuiFactory {
@NotNull
String title;
Message title;
@NotNull
ValueUpdatableGui parent;
@ -369,8 +373,12 @@ public class DoubleSettingGui extends AbstractSettingGui {
BigDecimal defaultVal;
BigDecimal[] steps;
@NotNull
List<String> displayLore;
@Nullable
Message displayLore;
@Nullable
Object param;
@Nullable
Object param2;
/**
* Constructor for a double setting gui factory.
@ -392,10 +400,11 @@ public class DoubleSettingGui extends AbstractSettingGui {
* If step only contain 1 value, no step item should be displayed.
*/
public DoubleSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull Message title, @NotNull ValueUpdatableGui parent,
@NotNull ConfigHolder config,
@NotNull String configPath,
@Nullable List<String> displayLore,
@Nullable Message displayLore,
@Nullable Object param, @Nullable Object param2,
int scale, boolean asPercentage, boolean nullOnZero,
double min, double max, double defaultVal, double... steps) {
super(configPath, config);
@ -413,18 +422,16 @@ public class DoubleSettingGui extends AbstractSettingGui {
this.steps[i] = BigDecimal.valueOf(steps[i]).setScale(scale, RoundingMode.HALF_UP);
}
if(displayLore == null){
this.displayLore = Collections.emptyList();
}else {
this.displayLore = displayLore;
}
this.param = param;
this.param2 = param2;
}
/**
* @return Get setting's gui title
*/
@NotNull
public String getTitle() {
public Message getTitle() {
return title;
}
@ -448,21 +455,29 @@ public class DoubleSettingGui extends AbstractSettingGui {
}
public GuiItem getItem(Material itemMat, String name){
public GuiItem getItem(
@NotNull Material itemMat,
@NotNull Message name,
Object... params
){
// Get item properties
BigDecimal value = getConfiguredValue();
StringBuilder itemName = new StringBuilder("§a").append(name);
return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName,
"§e" + displayValue(value, this.asPercentage),
this.displayLore, true);
var itemName = name.formattedConcatenated(params);
return GuiGlobalItems.createGuiItemFromProperties(
this, itemMat, itemName,
"<yellow>" + displayValue(value, this.asPercentage), //TODO MESSAGE ? maybe ?
Collections.singletonList(this.displayLore), true,
this.param, this.param2
);
}
public GuiItem getItem(Material itemMat){
// Get item properties
String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath());
return getItem(itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath));
return getItem(itemMat, MsgUI.INSTANCE.getSHARED_GREEN_GET_ITEM(), CasedStringUtil.detectToUpperSpacedCase(configPath));
}
}

View file

@ -19,6 +19,9 @@ import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.Arrays;
import java.util.Collections;
@ -150,7 +153,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
assert meta != null;
meta.setDisplayName("§e" + nowBook + " §f-> §e" + planned + " §r(§c-" + (nowBook - planned) + "§r)");
meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE));
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getSHARED_CLICK_TO_CHANGE().formatted(), meta);
item.setItemMeta(meta);
minusItem = new GuiItem(item, updateNowBookConsumer(planned), CustomAnvil.instance);
@ -167,8 +170,8 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§e" + nowBook + " §f-> §e" + planned + " §r(§a+" + (planned - nowBook) + "§r)");
meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE));
meta.setDisplayName("§e" + nowBook + " §f-> §e" + planned + " §r(§a+" + (planned - nowBook) + "§r)");//TODO MESSAGE
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getSHARED_CLICK_TO_CHANGE().formatted(), meta);
item.setItemMeta(meta);
plusItem = new GuiItem(item, updateNowBookConsumer(planned), CustomAnvil.instance);
@ -182,9 +185,9 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
ItemMeta nowMeta = nowPaper.getItemMeta();
assert nowMeta != null;
nowMeta.setDisplayName("§fValue: §e" + nowBook);
if (!holder.displayLore.isEmpty()) {
nowMeta.setLore(holder.displayLore);
nowMeta.setDisplayName("<white>Value: <yellow>" + nowBook);//TODO MESSAGE
if (holder.displayLore != null) {
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(holder.displayLore, holder.param), nowMeta);
}
nowPaper.setItemMeta(nowMeta);
@ -263,15 +266,15 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
* If step only contain 1 value, no step item should be displayed.
*/
public EnchantCostSettingFactory(
@NotNull String title, ValueUpdatableGui parent,
@NotNull Message title, ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config,
@Nullable List<String> displayLore,
@Nullable Message displayLore, @Nullable Object param,
@NotNull CAEnchantment enchantment,
int min, int max, int... steps) {
super(title, parent,
configPath, config,
displayLore,
displayLore, param,
min, max, enchantment.defaultRarity().getItemValue(),
steps);
@ -302,7 +305,8 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
return new EnchantCostSettingsGui(this, nowItem);
}
public List<String> getDisplayLore() {
@Nullable
public List<Message> getDisplayLore() {
return this.displayLore;
}
}

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

View file

@ -11,10 +11,12 @@ import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import java.util.Collections;
import java.util.List;
@ -33,7 +35,7 @@ public class EnumSettingGui<T extends Enum<T> & EnumSettingGui.ConfigurableEnum>
* @param now The defined value of this setting.
*/
protected EnumSettingGui(EnumSettingFactory<T> holder, T now) {
super(3, holder.getTitle(), holder.parent);
super(3, holder.getTitle(), holder.parent, holder.param);
this.holder = holder;
this.before = now;
this.now = now;
@ -137,7 +139,9 @@ public class EnumSettingGui<T extends Enum<T> & EnumSettingGui.ConfigurableEnum>
*/
public abstract static class EnumSettingFactory<T extends Enum<T> & ConfigurableEnum> extends SettingGuiFactory {
@NotNull
String title;
Message title;
@Nullable
Object param;
@NotNull
ValueUpdatableGui parent;
@ -150,18 +154,20 @@ public class EnumSettingGui<T extends Enum<T> & EnumSettingGui.ConfigurableEnum>
* @param config Configuration holder of this setting.
*/
protected EnumSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull Message title, @Nullable Object param,
@NotNull ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config) {
super(configPath, config);
this.title = title;
this.parent = parent;
this.param = param;
this.parent = parent;
}
/**
* @return Get setting's gui title.
*/
@NotNull
public String getTitle() {
public Message getTitle() {
return title;
}

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

View file

@ -5,6 +5,9 @@ import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.PatternPane;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import io.delilaheve.CustomAnvil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
@ -16,7 +19,10 @@ import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.Collections;
import java.util.List;
@ -39,7 +45,7 @@ public class IntSettingsGui extends AbstractSettingGui {
* @param now The defined value of this setting.
*/
protected IntSettingsGui(IntSettingFactory holder, int now) {
super(3, holder.getTitle(), holder.parent);
super(3, holder.getTitle(), holder.parent, holder.param);
assert holder.steps.length > 0 && holder.steps.length <= 9;
this.holder = holder;
this.before = now;
@ -71,8 +77,8 @@ public class IntSettingsGui extends AbstractSettingGui {
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§eReset to default value");
meta.setLore(Collections.singletonList("§7Default value is §e" +
meta.setDisplayName("§eReset to default value");//TODO MESSAGE
meta.setLore(Collections.singletonList("§7Default value is §e" +//TODO MESSAGE
holder.valueDisplayName(ValueDisplayType.RESET, holder.defaultVal)));
item.setItemMeta(meta);
returnToDefault = new GuiItem(item, event -> {
@ -91,7 +97,7 @@ public class IntSettingsGui extends AbstractSettingGui {
// minus item
GuiItem minusItem;
if (now > holder.min) {
if(now > holder.min) {
int planned = Math.max(holder.min, now - step);
minusItem = valueEditItem(Material.RED_TERRACOTTA, ValueDisplayType.REMOVE, planned);
} else {
@ -101,7 +107,7 @@ public class IntSettingsGui extends AbstractSettingGui {
//plus item
GuiItem plusItem;
if (now < holder.max) {
if(now < holder.max) {
int planned = Math.min(holder.max, now + step);
plusItem = valueEditItem(Material.GREEN_TERRACOTTA, ValueDisplayType.ADD, planned);
} else {
@ -114,8 +120,9 @@ public class IntSettingsGui extends AbstractSettingGui {
ItemMeta resultMeta = resultPaper.getItemMeta();
assert resultMeta != null;
resultMeta.setDisplayName("§fValue: §e" + holder.valueDisplayName(ValueDisplayType.CURRENT, now));
resultMeta.setLore(holder.displayLore);
resultMeta.setDisplayName("<white>Value: <yellow>" + holder.valueDisplayName(ValueDisplayType.CURRENT, now));//TODO MESSAGE
if(holder.displayLore != null)
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(holder.displayLore, holder.param), resultMeta);
resultPaper.setItemMeta(resultMeta);
@ -125,7 +132,7 @@ public class IntSettingsGui extends AbstractSettingGui {
// reset to default
GuiItem returnToDefault;
if (now != holder.defaultVal) {
if(now != holder.defaultVal) {
returnToDefault = this.returnToDefault;
} else {
returnToDefault = GuiGlobalItems.backgroundItem();
@ -142,9 +149,9 @@ public class IntSettingsGui extends AbstractSettingGui {
var nowDisplay = holder.valueDisplayName(type, now);
var plannedDisplay = holder.valueDisplayName(type, planned);
var deltaDisplay = holder.deltaDisplay(type, now, planned);
meta.setDisplayName("§e" + nowDisplay + " §f-> §e" + plannedDisplay + " §r(§c" + deltaDisplay + "§r)");
meta.setDisplayName("§e" + nowDisplay + " §f-> §e" + plannedDisplay + " §r(§c" + deltaDisplay + "§r)");//TODO MESSAGE
meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE));
ComponentUtil.INSTANCE.applyLore(MsgUI.INSTANCE.getSHARED_CLICK_TO_CHANGE().formatted(), meta);
item.setItemMeta(meta);
return new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
}
@ -170,7 +177,7 @@ public class IntSettingsGui extends AbstractSettingGui {
GuiItem background = GuiGlobalItems.backgroundItem();
PatternPane pane = getPane();
for (char i = 'a'; i < (getMidStepChar() - 'a') * 2 + 1; i++) {
for(char i = 'a'; i < (getMidStepChar() - 'a') * 2 + 1; i++) {
pane.bindItem(i, background);
}
// Then update legit step values
@ -181,7 +188,7 @@ public class IntSettingsGui extends AbstractSettingGui {
* Update steps items value.
*/
protected void updateStepValue() {
if (holder.steps.length <= 1) return;
if(holder.steps.length <= 1) return;
// We assume steps have a length of 2k+1 cause its more pretty
char val = getMidStepChar();
// Offset to start (not the best way to do it)
@ -189,7 +196,7 @@ public class IntSettingsGui extends AbstractSettingGui {
// Then place items
PatternPane pane = getPane();
for (int i = 0; i < holder.steps.length; i++) {
for(int i = 0; i < holder.steps.length; i++) {
pane.bindItem(val + i, stepGuiItem(i));
}
@ -218,7 +225,7 @@ public class IntSettingsGui extends AbstractSettingGui {
StringBuilder stepName = new StringBuilder("§");
List<String> stepLore;
Consumer<InventoryClickEvent> clickEvent;
if (stepValue == step) {
if(stepValue == step) {
stepMat = Material.GREEN_STAINED_GLASS_PANE;
stepName.append('a');
stepLore = Collections.singletonList("§7Value is changing by " + stepValue);
@ -261,7 +268,7 @@ public class IntSettingsGui extends AbstractSettingGui {
public boolean onSave() {
holder.config.getConfig().set(holder.configPath, now);
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
return true;
@ -278,7 +285,7 @@ public class IntSettingsGui extends AbstractSettingGui {
public static class IntSettingFactory extends SettingGuiFactory {
@NotNull
String title;
Message title;
@NotNull
ValueUpdatableGui parent;
int min;
@ -286,8 +293,11 @@ public class IntSettingsGui extends AbstractSettingGui {
int defaultVal;
int[] steps;
@NotNull
List<String> displayLore;
@Nullable
List<Message> displayLore;
@Nullable
Object param;
/**
* Constructor for an int setting gui factory.
@ -306,9 +316,9 @@ public class IntSettingsGui extends AbstractSettingGui {
* If step only contain 1 value, no step item should be displayed.
*/
public IntSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull Message title, @NotNull ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config,
@Nullable List<String> displayLore,
@Nullable Message displayLore, @Nullable Object param,
int min, int max, int defaultVal, int... steps) {
super(configPath, config);
this.title = title;
@ -317,19 +327,15 @@ public class IntSettingsGui extends AbstractSettingGui {
this.max = max;
this.defaultVal = defaultVal;
this.steps = steps;
if (displayLore == null) {
this.displayLore = Collections.emptyList();
} else {
this.displayLore = displayLore;
}
this.displayLore = displayLore == null ? null : Collections.singletonList(displayLore);
this.param = param;
}
/**
* @return Get setting's gui title
*/
@NotNull
public String getTitle() {
public Message getTitle() {
return title;
}
@ -355,19 +361,24 @@ public class IntSettingsGui extends AbstractSettingGui {
*
* @param itemMat Displayed material of the item.
* @param name Name of the item.
* @param params parameters for the given name.
* @return A formatted GuiItem that will create and open a GUI for the int setting.
*/
public GuiItem getItem(
@NotNull Material itemMat,
@NotNull String name
@NotNull Message name,
Object... params
) {
// Get item properties
int value = getConfiguredValue();
StringBuilder itemName = new StringBuilder("§a").append(name);
var itemName = name.formattedConcatenated(params);
return GuiGlobalItems.createGuiItemFromProperties(this, itemMat, itemName,
"§e" + value,
this.displayLore, true);
return GuiGlobalItems.createGuiItemFromProperties(
this, itemMat, itemName,
"<yellow>" + value, //TODO MESSAGE ? maybe ?
this.displayLore, true,
this.param
);
}
/**
@ -383,7 +394,7 @@ public class IntSettingsGui extends AbstractSettingGui {
@NotNull Material itemMat
) {
String configPath = GuiGlobalItems.getConfigNameFromPath(getConfigPath());
return getItem(itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath));
return getItem(itemMat, MsgUI.INSTANCE.getSHARED_GREEN_GET_ITEM(), CasedStringUtil.detectToUpperSpacedCase(configPath));
}
protected String valueDisplayName(ValueDisplayType type, int value) {
@ -392,10 +403,13 @@ public class IntSettingsGui extends AbstractSettingGui {
protected String deltaDisplay(ValueDisplayType type, int now, int planned) {
var delta = planned - now;
if (delta < 0) return "§c" + delta;
if(delta < 0) return "§c" + delta;
else return "§a+" + delta;
}
public @Nullable Object getParam() {
return param;
}
}
public enum ValueDisplayType {

View file

@ -17,8 +17,11 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.awt.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -40,7 +43,7 @@ public class ItemSettingGui extends AbstractSettingGui {
* @param now The defined value of this setting.
*/
protected ItemSettingGui(ItemSettingFactory holder, ItemStack now) {
super(3, holder.getTitle(), holder.parent);
super(3, holder.getTitle(), holder.parent, holder.param);
this.holder = holder;
this.before = now;
this.now = now;
@ -168,13 +171,15 @@ public class ItemSettingGui extends AbstractSettingGui {
*/
public static class ItemSettingFactory extends SettingGuiFactory {
@NotNull
String title;
Message title;
@NotNull
ValueUpdatableGui parent;
@Nullable
ItemStack defaultVal;
@NotNull
List<String> displayLore;
List<Message> displayLore;
@Nullable
Object param;
/**
* Constructor for an item setting gui factory.
@ -187,23 +192,24 @@ public class ItemSettingGui extends AbstractSettingGui {
* @param displayLore Gui display item lore.
*/
public ItemSettingFactory(
@NotNull String title, @NotNull ValueUpdatableGui parent,
@NotNull Message title, @NotNull ValueUpdatableGui parent,
@NotNull String configPath, @NotNull ConfigHolder config,
@Nullable ItemStack defaultVal,
String... displayLore) {
@Nullable Object param, Message... displayLore) {
super(configPath, config);
this.title = title;
this.parent = parent;
this.defaultVal = defaultVal;
this.displayLore = Arrays.asList(displayLore);
this.param = param;
}
/**
* @return Get setting's gui title.
*/
@NotNull
public String getTitle() {
public Message getTitle() {
return title;
}
@ -215,7 +221,7 @@ public class ItemSettingGui extends AbstractSettingGui {
}
@NotNull
public List<String> getDisplayLore() {
public List<Message> getDisplayLore() {
return this.displayLore;
}
@ -245,8 +251,9 @@ public class ItemSettingGui extends AbstractSettingGui {
ItemMeta meta = item.getItemMeta();
assert meta != null;
//TODO MESSAGE name ?
meta.setDisplayName("§a" + name);
meta.setLore(getDisplayLore());
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(getDisplayLore(), param), meta);
meta.addItemFlags(ItemFlag.values());
item.setItemMeta(meta);

View file

@ -15,9 +15,10 @@ import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.config.SelectMaterialContainer;
import xyz.alexcrea.cuanvil.gui.config.ask.ConfirmActionGui;
import xyz.alexcrea.cuanvil.gui.config.list.MappedElementListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -37,9 +38,10 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
public MaterialSelectSettingGui(
@NotNull SelectMaterialContainer selector,
@NotNull String title,
@NotNull Message title,
@NotNull String param,
@NotNull Gui backGui) {
super(title);
super(title, param);
this.selector = selector;
this.backGui = backGui;
this.instantRemove = false;
@ -156,7 +158,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
// Do not allow to save configuration if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM);
MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return;
}
if(testCantSave()) return;
@ -236,8 +238,8 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
// Create and show confirm remove gui.
ConfirmActionGui confirmGui = new ConfirmActionGui(
"Remove " + materialName,
"§7Confirm Remove " + materialName.toLowerCase() + " from this list.",
MsgUI.INSTANCE.getMATERIAL_SELECT_CONFIRM_TITLE(), materialName,
MsgUI.INSTANCE.getMATERIAL_SELECT_CONFIRM_DESCRIPTION(), materialName.toLowerCase(),
this, this,
() -> {
removeMaterial(material);
@ -303,7 +305,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
}
@Override
protected String genericDisplayedName() {// Not Used
protected Message genericDisplayedName() {// Not Used
return null;
}
}

View file

@ -15,54 +15,48 @@ import xyz.alexcrea.cuanvil.anvil.AnvilUseType;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.config.WorkPenaltyType;
import xyz.alexcrea.cuanvil.gui.config.global.BasicConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
private static final String INCREASING_EXPLANATION = "§eIncreasing§7: will penalty be increased (in item)";
private static final String ADDING_EXPLANATION = "§eAdditive§7: will penalty be added to the cost";
private static final String SHARED_EXPLANATION = "§eShared§7: Vanilla, shared penalty. it will be kept from before the plugin installation.";
private static final String EXCLUSIVE_EXPLANATION = "§eExclusive§7: Custom, per anvil use type penalty. it will be lost after plugin uninstallation";
private final @NotNull WorkPenaltyType currentType;
private final @NotNull Map<AnvilUseType, WorkPenaltyType.WorkPenaltyPart> items;
public WorkPenaltyTypeSettingGui(@NotNull BasicConfigGui parent) {
super(4, "§8Work Penalty Type", parent);
super(4, MsgUI.INSTANCE.getBASIC_WORK_PENALTY_TITLE(), parent);
this.currentType = ConfigOptions.INSTANCE.getWorkPenaltyType();
this.items = new EnumMap<>(this.currentType.getPartMap());
for (AnvilUseType type : useTypes.keySet()) {
for(AnvilUseType type : useTypes.keySet()) {
updateGuiForType(type);
}
}
public static GuiItem getDisplayItem(@NotNull BasicConfigGui parent,
@NotNull Material itemMat,
@NotNull String name) {
List<String> displayLore = new ArrayList<>();
@NotNull Message name) {
var item = new ItemStack(itemMat);
displayLore.add("§7Work penalty increase the price for every anvil use.");
displayLore.add("§7This config allow you to choose the comportment of work penalty.");
displayLore.add(INCREASING_EXPLANATION);
displayLore.add(ADDING_EXPLANATION);
displayLore.add("");
displayLore.add("§7About shared/exclusive penalty:");
displayLore.add(SHARED_EXPLANATION);
displayLore.add(EXCLUSIVE_EXPLANATION);
var meta = item.getItemMeta();
assert meta != null;
ItemStack item = new ItemStack(itemMat);
var lore = new ArrayList<Message>();
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_LORE());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_INCREASING());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_ADDITIVE());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_LORE_BREAK());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_SHARED());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_EXCLUSIVE());
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(name);
meta.setLore(displayLore);
ComponentUtil.INSTANCE.setMessageName(meta, name);
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(lore), meta);
item.setItemMeta(meta);
@ -71,9 +65,9 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
HumanEntity player = event.getWhoClicked();
// 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.sendMessage(GuiGlobalActions.NO_EDIT_PERM);
MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return;
}
new WorkPenaltyTypeSettingGui(parent).show(player);
@ -110,6 +104,7 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
char exclusiveAdditive = typeVals.charAt(4);
WorkPenaltyType.WorkPenaltyPart part = items.get(type);
//TODO MESSAGE
String increasingStr = (part.penaltyIncrease() ? "§a" : "§c") + "Increasing";
String additiveStr = (part.penaltyAdditive() ? "§a" : "§c") + "Additive";
String exclusiveIncreasingStr = (part.exclusivePenaltyIncrease() ? "§a" : "§c") + "Increasing";
@ -123,6 +118,7 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
displayLore.add("§eExclusive§7: " + exclusiveAdditiveStr + " §7| " + exclusiveIncreasingStr);
ItemMeta meta = displayItem.getItemMeta();
assert meta != null;
meta.setDisplayName("§e" + type.getDisplayName());
meta.setLore(displayLore);
displayItem.setItemMeta(meta);
@ -136,9 +132,14 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
ItemStack incrementItem = new ItemStack(part.penaltyIncrease() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA);
meta = incrementItem.getItemMeta();
assert meta != null;
meta.setDisplayName(increasingStr);
meta.setLore(List.of(INCREASING_EXPLANATION));
meta.setLore(List.of(SHARED_EXPLANATION));
var lore = new ArrayList<Message>();
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_INCREASING());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_SHARED());
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(lore), meta);
incrementItem.setItemMeta(meta);
pane.bindItem(increment, new GuiItem(incrementItem, (event) -> {
@ -156,9 +157,14 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
ItemStack additiveItem = new ItemStack(part.penaltyAdditive() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA);
meta = additiveItem.getItemMeta();
assert meta != null;
meta.setDisplayName(additiveStr);
meta.setLore(List.of(ADDING_EXPLANATION));
meta.setLore(List.of(SHARED_EXPLANATION));
lore.clear();
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_ADDITIVE());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_SHARED());
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(lore), meta);
additiveItem.setItemMeta(meta);
pane.bindItem(additive, new GuiItem(additiveItem, (event) -> {
@ -176,9 +182,14 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
ItemStack exclusiveIncrementItem = new ItemStack(part.exclusivePenaltyIncrease() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA);
meta = exclusiveIncrementItem.getItemMeta();
assert meta != null;
meta.setDisplayName(exclusiveIncreasingStr);
meta.setLore(List.of(INCREASING_EXPLANATION));
meta.setLore(List.of(EXCLUSIVE_EXPLANATION));
lore.clear();
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_INCREASING());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_EXCLUSIVE());
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(lore), meta);
exclusiveIncrementItem.setItemMeta(meta);
pane.bindItem(exclusiveIncrement, new GuiItem(exclusiveIncrementItem, (event) -> {
@ -196,9 +207,14 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
ItemStack exclusiveAdditiveItem = new ItemStack(part.exclusivePenaltyAdditive() ? Material.GREEN_TERRACOTTA : Material.RED_TERRACOTTA);
meta = exclusiveAdditiveItem.getItemMeta();
assert meta != null;
meta.setDisplayName(exclusiveAdditiveStr);
meta.setLore(List.of(ADDING_EXPLANATION));
meta.setLore(List.of(EXCLUSIVE_EXPLANATION));
lore.clear();
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_ADDITIVE());
lore.add(MsgUI.INSTANCE.getBASIC_WORK_PENALTY_EXPLAIN_EXCLUSIVE());
ComponentUtil.INSTANCE.applyLore(ComponentUtil.INSTANCE.asComponents(lore), meta);
exclusiveAdditiveItem.setItemMeta(meta);
pane.bindItem(exclusiveAdditive, new GuiItem(exclusiveAdditiveItem, (event) -> {
@ -225,7 +241,7 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
partEnum.forEach((key, value) -> {
String partPath = key.getPath();
if (key.getDefaultPenalty().equals(value)) {
if(key.getDefaultPenalty().equals(value)) {
config.set(partPath, null);
return;
}
@ -241,8 +257,8 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
@Override
public boolean hadChange() {
for (AnvilUseType type : items.keySet()) {
if (!currentType.getPenaltyInfo(type).equals(items.get(type))) {
for(AnvilUseType type : items.keySet()) {
if(!currentType.getPenaltyInfo(type).equals(items.get(type))) {
return true;
}
}

View file

@ -7,6 +7,7 @@ import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@ -17,8 +18,6 @@ import java.util.function.Consumer;
*/
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.
*/
@ -44,7 +43,7 @@ public class GuiGlobalActions {
// Do not allow to open inventory if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(NO_EDIT_PERM);
MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return;
}
try {
@ -102,7 +101,7 @@ public class GuiGlobalActions {
// Do not allow to open inventory if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(NO_EDIT_PERM);
MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return;
}
goal.show(player);
@ -127,7 +126,7 @@ public class GuiGlobalActions {
// Do not allow to save configuration if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(NO_EDIT_PERM);
MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return;
}

View file

@ -4,14 +4,20 @@ import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.PatternPane;
import io.delilaheve.CustomAnvil;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import xyz.alexcrea.cuanvil.lang.Message;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.ComponentUtil;
import java.util.ArrayList;
import java.util.Collections;
@ -184,9 +190,6 @@ public class GuiGlobalItems {
return new GuiItem(item, GuiGlobalActions.openSettingGuiAction(factory), CustomAnvil.instance);
}
// Prefix of the one line lore that will be added to setting's item.
public static final String SETTING_ITEM_LORE_PREFIX = "§7value: ";
/**
* Create an arbitrary GuiItem from a unique setting and item's property.
*
@ -201,17 +204,23 @@ public class GuiGlobalItems {
public static GuiItem createGuiItemFromProperties(
@NotNull SettingGui.SettingGuiFactory factory,
@NotNull Material itemMat,
@NotNull StringBuilder itemName,
@NotNull Object value,
@NotNull List<String> displayLore,
boolean displayValuePrefix
@NotNull Component itemName,
@NotNull Object value,//TODO ????
@Nullable List<Message> displayLore,
boolean displayValuePrefix,
@Nullable Object... params
) {
// Prepare lore
ArrayList<String> lore = new ArrayList<>();
lore.add((displayValuePrefix ? SETTING_ITEM_LORE_PREFIX : "") + value);
if(!displayLore.isEmpty()){
lore.add("");
lore.addAll(displayLore);
var loreHeader = (displayValuePrefix ?
MsgUI.INSTANCE.getGLOBAL_ITEM_ITEM_LORE_PREFIX() :
MsgUI.INSTANCE.getGLOBAL_ITEM_ITEM_LORE_PREFIX_ALONE());
List<Component> lore = loreHeader.formatted(value);
if(displayLore != null){
lore.add(Component.empty());
for(Message message : displayLore) {
lore.addAll(message.formatted(params));
}
}
// Create & initialise item
@ -219,8 +228,8 @@ public class GuiGlobalItems {
ItemMeta itemMeta = item.getItemMeta();
assert itemMeta != null;
itemMeta.setDisplayName(itemName.toString());
itemMeta.setLore(lore);
PlatformUtil.INSTANCE.setComponentDisplayName(itemMeta, itemName, null);
ComponentUtil.INSTANCE.applyLore(lore, itemMeta);
itemMeta.addItemFlags(ItemFlag.values());
item.setItemMeta(itemMeta);

View file

@ -1,14 +1,13 @@
package io.delilaheve
import io.delilaheve.util.ConfigOptions
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.plugin.java.JavaPlugin
import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent
import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent
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.dependency.DependencyManager
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.gui.config.MainConfigGui
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.AnvilResultListener
import xyz.alexcrea.cuanvil.listener.ChatEventListener
@ -75,7 +77,7 @@ open class CustomAnvil : JavaPlugin() {
var latestVer: String? = null
// Debug
val debugStorageQueue = ArrayDeque<String>()
val debugStorageQueue = ArrayDeque<Component>()
private fun addToLogQueue(message: String) {
if(debugStorageQueue.size >= 200) {
@ -83,7 +85,7 @@ open class CustomAnvil : JavaPlugin() {
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)
// Return true if start was stopped
private fun tryDirtyStart(): Boolean {
if(ConfigHolder.DEFAULT_CONFIG == null) return false
if(!ConfigHolder.DEFAULT_CONFIG.config.getBoolean("dirty_start", false)) {
Bukkit.getPluginManager().disablePlugin(this)
return true
@ -123,6 +137,7 @@ open class CustomAnvil : JavaPlugin() {
// stop plugin if we force a safe start (false by default)
// Return true if start was stopped
private fun trySafeStart(): Boolean {
if(ConfigHolder.DEFAULT_CONFIG == null) return false
if(ConfigHolder.DEFAULT_CONFIG.config.getBoolean("safe_start", false)) {
Bukkit.getPluginManager().disablePlugin(this)
return true
@ -135,39 +150,45 @@ open class CustomAnvil : JavaPlugin() {
*/
override fun onEnable() {
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
try {
if(!ConfigHolder.loadDefaultConfig())
throw RuntimeException("Error loading configuration file")
} catch (e: Exception) {
logger.log(Level.SEVERE, "error occurred loading default configuration", e)
MetricsUtil.trackError(e)
logError("error occurred loading default configuration", e)
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
try {
DependencyManager.loadDependency()
} catch (e: Exception) {
logger.log(Level.SEVERE, "error loading dependency compatibility", e)
MetricsUtil.trackError(e)
MsgError.LOAD_COMPATIBILITY.log(e)
if(tryDirtyStart()) return
}
@ -175,8 +196,7 @@ open class CustomAnvil : JavaPlugin() {
try {
registerListeners()
} catch (e: Exception) {
logger.log(Level.SEVERE, "error registering listeners", e)
MetricsUtil.trackError(e)
MsgError.LOAD_LISTENERS.log(e)
if(tryDirtyStart()) return
}
@ -192,33 +212,20 @@ open class CustomAnvil : JavaPlugin() {
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() {
// Disable old plugin name if exist
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
if (potentialPlugin != null) {
Bukkit.getPluginManager().disablePlugin(potentialPlugin)
logger.warning("An old version of this plugin was detected")
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
MsgWarning.LOAD_LEGACY_OLD_NAME.log()
}
val isPaper = PlatformUtil.isPaper
if(!isPaper) {
logger.warning("It seems you are using spigot")
logger.warning("Please take notice that spigot is less supported than paper and derivatives")
if(MinecraftVersionUtil.isTooNewForSpigot) {
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")
}
MsgWarning.LOAD_LEGACY_SPIGOT.log()
if(MinecraftVersionUtil.isTooNewForSpigot)
MsgWarning.LOAD_LEGACY_SPIGOT_OLD.log()
}
val loader = if(isPaper) "paper" else "spigot"
@ -230,13 +237,13 @@ open class CustomAnvil : JavaPlugin() {
UpdateUtils.currentMinecraftVersion().toString())
.setFeatured(featured)
.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? ->
CustomAnvil.latestVer = latestVer
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)
}
private fun loadEnchantmentSystemDirty() {
try {
loadEnchantmentSystem()
} catch (e: Exception) {
MsgError.LOAD_ENCHANT_SYSTEM.log(e)
tryDirtyStart()
}
}
private fun loadEnchantmentSystem(){
// Register enchantments
CAEnchantmentRegistry.getInstance().registerBukkit()
@ -261,7 +277,7 @@ open class CustomAnvil : JavaPlugin() {
// Load config
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)
return
}
@ -315,16 +331,15 @@ open class CustomAnvil : JavaPlugin() {
try {
val configReader = FileReader(resourceFile)
yamlConfig.load(configReader)
} catch (test: Exception) {
} catch (e: Exception) {
MsgError.RELOAD_FAIL.log(e, resourceFile.path)
if (hardFailSafe) {
// This is important and may impact gameplay if it does not load.
// Failsafe is to stop the plugin
logger.severe("Resource ${resourceFile.path} Could not be load or reload.")
logger.severe("Disabling plugin.")
MsgError.RELOAD_HARD_FAIL.log()
Bukkit.getPluginManager().disablePlugin(this)
} else {
logger.warning("Resource ${resourceFile.path} Could not be load or reload.")
}
return null
}
return yamlConfig

View file

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

View file

@ -3,6 +3,7 @@ package xyz.alexcrea.cuanvil.command
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.lang.Message
interface CASubCommand {
@ -21,7 +22,7 @@ interface CASubCommand {
list: MutableList<String>
)
fun description(): String
fun description(): Message
fun allEnchantmentsByName(): Collection<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.CommandSender
import org.bukkit.command.TabCompleter
import xyz.alexcrea.cuanvil.util.MetricsUtil
import xyz.alexcrea.cuanvil.lang.MsgCommand
class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
@ -57,15 +57,15 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter {
}
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
}
try {
return subcmd.executeCommand(sender, cmd, subcmdStr, newargs)
} catch (e: Throwable) {
MetricsUtil.trackError(e)
sender.sendMessage("§cError running this command")
CustomAnvil.logError("Error running /$cmdstr ${args.joinToString(" ")}", e)
MsgCommand.ROOT_ERROR_SUBCOMMAND.send(sender)
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.TextComponent
import net.md_5.bungee.api.chat.hover.content.Text
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
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 {
return "Used to toggle debug logs and retrieve it"
override fun description(): Message {
return MsgCommand.DEBUG_DESCRIPTION
}
override fun allowed(sender: CommandSender): Boolean {
@ -26,18 +32,18 @@ class DebugToggleExecutor : CASubCommand {
sender: CommandSender,
cmd: Command,
cmdstr: String,
args: Array<out String>
args: Array<out String>,
): Boolean {
if (!allowed(sender)) {
sender.sendMessage(NO_DIAG_PERM)
if(!allowed(sender)) {
MsgCommand.SHARED_NO_DIAG_PERM.send(sender)
return false
}
if (args.isEmpty()) {
sender.sendMessage("Need to specify a subcommand: \"toggle\" or \"get\"")
if(args.isEmpty()) {
MsgCommand.SHARED_MISSING_SUBCOMMAND.send(sender, "\"toggle\"", "\"get\"")
return true
}
when (args[0].lowercase()) {
when(args[0].lowercase()) {
"toggle" -> executeToggle(sender, args)
"get" -> executeGet(sender)
"get-and-clear" -> {
@ -47,67 +53,216 @@ class DebugToggleExecutor : CASubCommand {
"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
}
private fun executeToggle(sender: CommandSender, args: Array<out String>) {
if (args.size < 2) {
sender.sendMessage("Need to specify which type of debug to toggle: \"default\" or \"verbose\"")
if(args.size < 2) {
MsgCommand.DEBUG_WARNING_UNSPECIFIED_TYPE.send(sender)
return
}
when (args[1].lowercase()) {
when(args[1].lowercase()) {
"default" -> {
ConfigOptions.OVERRIDE_DEBUG_LOG = !ConfigOptions.debugLog
sender.sendMessage("Debug toggle to: ${ConfigOptions.debugLog}")
MsgCommand.DEBUG_TOGGLED.send(sender, ConfigOptions.debugLog)
}
"verbose" -> {
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) {
val stb = StringBuilder("Debug Log data:")
if (CustomAnvil.debugStorageQueue.isEmpty()) {
sender.sendMessage("No log to show ? make sure you tried with debug log toggled (/ca debug toggle)")
if(CustomAnvil.debugStorageQueue.isEmpty()) {
MsgCommand.DEBUG_WARNING_NO_LOG.send(sender, "/ca debug toggle")
return
}
stb.append("\nFound ${CustomAnvil.debugStorageQueue.size} lines\n")
for (log in CustomAnvil.debugStorageQueue) {
stb.append('\n').append(log)
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) {
stb.append('\n').append(log.serializePlain())
}
if (sender is Player) {
val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy log data")
if(sender is Player) {
val message = TextComponent(MsgCommand.DEBUG_COPY.legacy())
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 {
sender.sendMessage(stb.toString())
}
}
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)
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 == null) continue
if(textParam.startsWith(param)) {
found = true
usedParam.add(param)
break
}
}
if(found) continue
hadIssue = true
stb.append("Did not found param %$textParam in register list for ${message.key}\n")
}
for(param in message.params) {
if(param == null) continue
var found = false
for(used in usedParam) {
if(!used.startsWith(param)) continue
found = true
break
}
if(found) 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>) {
if (!allowed(sender)) return
if(!allowed(sender)) return
list.addAll(
when (args.size) {
1 -> listOf("toggle", "get", "get-and-clear", "clear")
2 -> when (args[0].lowercase()) {
when(args.size) {
1 -> listOf("toggle", "get", "get-and-clear", "clear", "lang")
2 -> when(args[0].lowercase()) {
"toggle" -> listOf("default", "verbose")
"lang" -> listOf("details")
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.hover.content.Text
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.Material
import org.bukkit.command.Command
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.ProtocoLibWrapper
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.util.MetricsUtil
import java.util.*
import java.util.stream.Collectors
@Suppress("UnstableApiUsage")
class DiagnosticExecutor : CASubCommand {
companion object {
const val NO_DIAG_PERM = "You do not have permission to diagnostic this server"
fun fetchNMSType(): String {
val packetManager = DependencyManager.packetManager
@ -101,7 +102,7 @@ class DiagnosticExecutor : CASubCommand {
args: Array<out String>
): Boolean {
if (!allowed(sender)) {
sender.sendMessage(NO_DIAG_PERM)
MsgCommand.SHARED_NO_DIAG_PERM.send(sender)
return false
}
@ -122,12 +123,11 @@ class DiagnosticExecutor : CASubCommand {
if (sender is HumanEntity) {
if (hasError)
sender.spigot()
.sendMessage(TextComponent(ChatColor.RED.toString() + "There was an error running the diagnostic"))
val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy diagnostic data")
MsgCommand.DIAGNOSTIC_ERROR_GENERIC.send(sender)
val message = TextComponent(MsgCommand.DIAGNOSTIC_COPY.legacy())
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)
} else {
@ -214,13 +214,13 @@ class DiagnosticExecutor : CASubCommand {
return this.name + " v" + this.description.version
}
override fun description(): String {
return "Basic diagnostic of this plugin"
override fun description(): Message {
return MsgCommand.DIAGNOSTIC_DESCRIPTION
}
private fun pluginListDiag(sender: CommandSender, stb: StringBuilder) {
val enabledPlugins: MutableList<Plugin?> = ArrayList<Plugin?>()
val disabledPlugins: MutableList<Plugin?> = ArrayList<Plugin?>()
val enabledPlugins: MutableList<Plugin?> = ArrayList()
val disabledPlugins: MutableList<Plugin?> = ArrayList()
for (plugin in Bukkit.getPluginManager().plugins) {
if (plugin.isEnabled) {
enabledPlugins.add(plugin)

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.global.EnchantConfigGui
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.isAir
@ -20,42 +22,38 @@ class EditConfigExecutor : CASubCommand {
return sender.hasPermission(CustomAnvil.editConfigPermission)
}
override fun description(): String {
return "Gui to edit the plugin's config"
override fun description(): Message {
return MsgCommand.CONFIG_DESCRIPTION
}
override fun executeCommand(
sender: CommandSender,
cmd: Command,
cmdstr: String,
args: Array<out String>
args: Array<out String>,
): Boolean {
if (sender !is HumanEntity) return false
if(sender !is HumanEntity) return false
if (!allowed(sender)) {
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM)
if(!allowed(sender)) {
MsgUI.SHARED_CONFIG_NO_EDIT_PERM.send(sender)
return false
}
if (PlatformUtil.isFolia) {
sender.sendMessage("§cIt look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia.")
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")
if(PlatformUtil.isFolia) {
MsgCommand.CONFIG_FOLIA_ISSUE.send(sender)
return false
}
if ("gui".equals(cmdstr, ignoreCase = true)) {
sender.sendMessage("§c/ca gui has been moved to /ca config")
if("gui".equals(cmdstr, ignoreCase = true)) {
MsgCommand.CONFIG_LEGACY_NAME_WARNING.send(sender)
}
if (args.isEmpty())
if(args.isEmpty())
processOpen(sender)
else when (args[0].lowercase()) {
else when(args[0].lowercase()) {
"open" -> processOpen(sender)
"enchant" -> processEnchant(sender, args)
"item" -> processItem(sender)
else -> sender.sendMessage("Unknown subcommand \"${args[0]}\"")
else -> MsgCommand.SHARED_UNKNOWN_SUB_COMMAND.send(sender)
}
return true
@ -63,31 +61,30 @@ class EditConfigExecutor : CASubCommand {
private fun processEnchant(sender: HumanEntity, args: Array<out String>) {
val enchantToFilter: Set<CAEnchantment>
if (args.size <= 1) {
if(args.size <= 1) {
val item = sender.inventory.itemInMainHand
enchantToFilter = EnchantmentApi.getEnchantments(item).keys
if (enchantToFilter.isEmpty()) {
sender.sendMessage("No enchantment found in the item you are holding")
if(enchantToFilter.isEmpty()) {
MsgCommand.CONFIG_ENCHANTMENT_NO_IN_HAND.send(sender)
return
}
} else {
enchantToFilter = HashSet(EnchantmentApi.getByName(args[1].lowercase()))
if (enchantToFilter.isEmpty()) {
sender.sendMessage("No enchantment found with the name \"${args[1]}\"")
if(enchantToFilter.isEmpty()) {
MsgCommand.CONFIG_ENCHANTMENT_NO_NAME.send(sender, args[1])
return
}
}
EnchantConfigGui(enchantToFilter).show(sender)
}
private fun processItem(sender: HumanEntity) {
val item = sender.inventory.itemInMainHand
if (item.isAir) {
sender.sendMessage("Cannot configure the item in hand")
if(item.isAir) {
MsgCommand.CONFIG_CANNOT_CONFIGURE_WARNING.send(sender)
return
}
@ -104,10 +101,10 @@ class EditConfigExecutor : CASubCommand {
override fun tabCompleter(sender: CommandSender, args: Array<out String>, list: MutableList<String>) {
list.addAll(
when (args.size) {
when(args.size) {
1 -> listOf("item", "enchant", "open")
2 -> {
when (args[0].lowercase()) {
when(args[0].lowercase()) {
"enchant" -> allEnchantmentsByName()
else -> listOf()
}

View file

@ -10,6 +10,8 @@ import org.bukkit.command.CommandSender
import org.bukkit.entity.HumanEntity
import xyz.alexcrea.cuanvil.api.EnchantmentApi
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
class EnchantExecutor : CASubCommand {
@ -19,74 +21,74 @@ class EnchantExecutor : CASubCommand {
return sender.hasPermission(CustomAnvil.giveEnchantmentPermission)
}
override fun description(): String {
return "Allows to set enchantment to holden item"
override fun description(): Message {
return MsgCommand.ENCHANT_DESCRIPTION
}
override fun executeCommand(
sender: CommandSender,
cmd: Command,
cmdstr: String,
args: Array<out String>
args: Array<out String>,
): Boolean {
if (sender !is HumanEntity) return true
if(sender !is HumanEntity) return true
if (!allowed(sender)) {
sender.sendMessage("No permission to execute this command")
if(!allowed(sender)) {
MsgCommand.SHARED_NO_PERMISSION.send(sender)
return true
}
when (args.size) {
when(args.size) {
0 -> {
sender.sendMessage("Missing enchantment parameter")
MsgCommand.ENCHANT_MISSING_PARAMETER_WARNING.send(sender)
return true
}
}
val enchant = firstEnchantment(args[0])
if (enchant == null) {
sender.sendMessage("Enchantment not found: ${args[0]}")
if(enchant == null) {
MsgCommand.ENCHANT_NOT_FOUND_WARNING.send(sender, args[0])
return true
}
val level = if (args.size > 1)
val level = if(args.size > 1)
args[1].toIntOrNull()?.coerceIn(0, ConfigOptions.ENCHANT_LIMIT)
else 1
if (level == null) {
sender.sendMessage("Invalid number: ${args[1]}")
if(level == null) {
MsgCommand.ENCHANT_MALFORMED_NUMBER_WARNING.send(sender, args[1])
return true
}
val inHand = sender.inventory.itemInMainHand
if (inHand.isAir) {
sender.sendMessage("Cannot enchant this item")
if(inHand.isAir) {
MsgCommand.ENCHANT_CANNOT_ENCHANT_WARNING.send(sender)
return true
}
if (level == 0) {
if(level == 0) {
enchant.removeFrom(inHand)
if (inHand.isEnchantedBook() && EnchantmentApi.getEnchantments(inHand).isEmpty())
if(inHand.isEnchantedBook() && EnchantmentApi.getEnchantments(inHand).isEmpty())
inHand.type = Material.BOOK
sender.sendMessage("${enchant.prettyName} removed")
MsgCommand.ENCHANT_REMOVE.send(sender, enchant.prettyName)
} else {
if (Material.BOOK == inHand.type)
if(Material.BOOK == inHand.type)
inHand.type = Material.ENCHANTED_BOOK
enchant.addEnchantmentUnsafe(inHand, level)
sender.sendMessage("${enchant.prettyName} set to level $level")
MsgCommand.ENCHANT_SET.send(sender, enchant.prettyName, level)
}
return true
}
override fun tabCompleter(sender: CommandSender, args: Array<out String>, list: MutableList<String>) {
if (sender !is HumanEntity) return
if(sender !is HumanEntity) return
list.addAll(
when (args.size) {
when(args.size) {
1 -> allEnchantmentsByName()
2 -> findEnchantmentLevels(sender, args[0])
@ -97,19 +99,19 @@ class EnchantExecutor : CASubCommand {
private fun findEnchantmentLevels(
sender: HumanEntity,
name: String
name: String,
): Collection<String> {
val enchant = firstEnchantment(name) ?: return listOf()
val limit = ConfigOptions.enchantLimit(enchant)
val result = mutableListOf<String>()
for (i in 1 until limit + 1) {
for(i in 1 until limit + 1) {
result.add(i.toString())
}
val inHand = sender.inventory.itemInMainHand
if (enchant.isEnchantmentPresent(inHand))
if(enchant.isEnchantmentPresent(inHand))
result.add("0")
return result
@ -117,7 +119,7 @@ class EnchantExecutor : CASubCommand {
private fun firstEnchantment(name: String): CAEnchantment? {
val enchants = EnchantmentApi.getByName(name.lowercase())
if (!enchants.isEmpty())
if(!enchants.isEmpty())
return enchants.iterator().next()
return EnchantmentApi.getByKey(NamespacedKey.fromString(name))

View file

@ -1,29 +1,37 @@
package xyz.alexcrea.cuanvil.command
import com.google.common.collect.ImmutableMap
import net.kyori.adventure.text.Component
import org.bukkit.command.Command
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 {
override fun description(): Message {
return MsgCommand.HELP_DESCRIPTION
}
lateinit var commands: ImmutableMap<String, CASubCommand>
override fun executeCommand(
sender: CommandSender,
cmd: Command,
cmdstr: String,
args: Array<out String>
args: Array<out String>,
): Boolean {
var text = MsgCommand.HELP_HEADER.formatted().first()
for((key, cmd) in commands) {
if(!cmd.allowed(sender)) continue
val stb = StringBuilder("List of available commands:")
for ((key, cmd) in commands) {
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
}
@ -34,12 +42,8 @@ class HelpExecutor : CASubCommand {
override fun tabCompleter(
sender: CommandSender,
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.dependency.DependencyManager
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
class ReloadExecutor : CASubCommand {
override fun description(): Message {
return MsgCommand.RELOAD_DESCRIPTION
}
override fun executeCommand(
sender: CommandSender,
cmd: Command,
cmdstr: String,
args: Array<out String>
args: Array<out String>,
): Boolean {
if (!allowed(sender)) {
sender.sendMessage("§cYou do not have permission to reload the config")
if(!allowed(sender)) {
MsgCommand.SHARED_NO_PERMISSION.send(sender)
return false
}
sender.sendMessage("§eReloading config...")
MsgCommand.RELOAD_START.send(sender)
val hardfail = args.isNotEmpty() && ("hard".equals(args[0], true))
val commandSuccess = commandBody(hardfail)
if (commandSuccess) {
sender.sendMessage("§aConfig reloaded !")
if(commandSuccess) {
MsgCommand.RELOAD_SUCCESS.send(sender)
} else {
sender.sendMessage("§cConfig was not able to be reloaded...")
if (hardfail) {
sender.sendMessage("§4Hard fail, plugin disabled")
MsgCommand.RELOAD_FAIL.send(sender)
if(hardfail) {
MsgCommand.RELOAD_HARD_FAIL.send(sender)
}
}
return commandSuccess
@ -43,20 +50,19 @@ class ReloadExecutor : CASubCommand {
override fun tabCompleter(
sender: CommandSender,
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
*/
private fun commandBody(hardfail: Boolean): Boolean {
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
BasicConfigGui.getInstance()?.updateGuiValues()
@ -79,7 +85,7 @@ class ReloadExecutor : CASubCommand {
Bukkit.getServer().pluginManager.callEvent(configReadyEvent)
return true
} catch (e: Exception) {
} catch(e: Exception) {
e.printStackTrace()
return false
}

View file

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

View file

@ -0,0 +1,84 @@
package xyz.alexcrea.cuanvil.lang
import io.delilaheve.CustomAnvil
import org.bukkit.configuration.ConfigurationSection
import xyz.alexcrea.cuanvil.config.ConfigHolder
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 {
val previousLang = lang
try {
unsafeReload()
return true
} catch(e: Exception) {
CustomAnvil.logError("Error loading language $langID. going back to ${lang.name}", e, false)
lang = previousLang
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,212 @@
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.max
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 max(params.size, values.size)) {
val key = if(i >= params.size) "NOT KEY"
else params[i]
val value = if(i >= values.size) "NOT VALUE"
else values[i]
CustomAnvil.log("Parameter ${i + 1} is $key with value $value")
}
}
var foundBackslashPercent = false
for(i in 0 until min(params.size, values.size)) {
val key = params[i] ?: continue
val value = values[i]
if(value == null) {
CustomAnvil.log("Passed a null value for key ${this.key} for Parameter $key (${i + 1})")
continue
}
val replacement = value.toString()
var current = 0
while(true) {
current = stb.indexOf('%', current)
if(current > 0 && stb[current - 1] == '\\') {
foundBackslashPercent = true
current++
continue
}
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
}
}
if(foundBackslashPercent) {
// Remove the \% to \
var current = 0
while(true) {
current = stb.indexOf("\\%", current)
if(current < 0) break
stb.replace(current, current + 2, "%")
current++
}
}
}
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?): MutableList<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 mutableListOf(Component.text(key))
return result
}
// return a list of AT LEAST 1 element. calling first is safe
fun formatted(vararg params: Any?): MutableList<Component> {
val section = Lang.getSection(key)
if(section != null) return formattedMultiline(section, *params)
val translated = unformattedMonoline(*params)
return mutableListOf(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,192 @@
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 SHARED_CLICK_TO_CHANGE = Message("shared.click-to-change")
val SHARED_GREEN_GET_ITEM = Message("shared.green-get-item", "name")
val SHARED_YELLOW_GET_ITEM = Message("shared.yellow-get-item", "name")
val SHARED_FORMATED_YES = Message("shared.formated-yes")
val SHARED_FORMATED_NO = Message("shared.formated-no")
val SHARED_DEFAULT = Message("shared.default")
val SHARED_VALUED_DEFAULT = Message("shared.valued-default", "value")
fun booleanMessage(bool: Boolean): Message {
return if(bool) SHARED_FORMATED_YES else SHARED_FORMATED_NO
}
val GLOBAL_ITEM_ITEM_LORE_PREFIX = Message("global-item.item-lore-prefix", "value")
val GLOBAL_ITEM_ITEM_LORE_PREFIX_ALONE = Message("global-item.item-lore-prefix-alone", "value")
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", null, "page", "max_page")
val UNIT_REPAIR_ITEM = Message("unit-repair.item", "name", "unit")
val UNIT_REPAIR_ELEMENT_TITLE = Message("unit-repair.element.title", "type", "page", "max_page")
val UNIT_REPAIR_NEW_TITLE = Message("unit-repair.new.title", null)
val UNIT_REPAIR_NEW_DESCRIPTION = Message("unit-repair.new.description", null)
val UNIT_REPAIR_ELEMENT_VALUE_TITLE = Message("unit-repair.element.value.title", "name", null)
val UNIT_REPAIR_ELEMENT_VALUE_DESCRIPTION = Message("unit-repair.element.value.description", "name", "unit")
val UNIT_REPAIR_NEW_ELEMENT_TITLE = Message("unit-repair.element.new.title", null)
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", null, "page", "max_page")
val CUSTOM_RECIPE_NAME = Message("custom-recipe.name", "name")
val CUSTOM_RECIPE_GENERIC_NAME = Message("custom-recipe.generic-name")
val CUSTOM_RECIPE_LORE_DEFAULT = Message("custom-recipe.lore.default",
"should_work", "exact_count", "per_craft_lv_cost", "per_craft_xp_cost")
val CUSTOM_RECIPE_LORE_LINEAR = Message("custom-recipe.lore.linear", "exact_linear")
val CUSTOM_RECIPE_ELEMENT_EXACT_COUNT_TITLE = Message("custom-recipe.element.exact-count", null)
val CUSTOM_RECIPE_ELEMENT_LINEAR_XP_TITLE = Message("custom-recipe.element.linear-xp.title", null)
val CUSTOM_RECIPE_ELEMENT_LINEAR_XP_NAME = Message("custom-recipe.element.linear-xp.name")
val CUSTOM_RECIPE_ELEMENT_LINEAR_XP_LORE = Message("custom-recipe.element.linear-xp.lore")
val CUSTOM_RECIPE_ELEMENT_COST_LEVEL_XP = Message("custom-recipe.element.recipe-cost.level", null)
val CUSTOM_RECIPE_ELEMENT_COST_LINEAR_XP = Message("custom-recipe.element.recipe-cost.xp", null)
val CUSTOM_RECIPE_ELEMENT_ITEM_LEFT_TITLE = Message("custom-recipe.element.item.left.title", null)
val CUSTOM_RECIPE_ELEMENT_ITEM_LEFT_DESCRIPTION = Message("custom-recipe.element.item.left.description", null)
val CUSTOM_RECIPE_ELEMENT_ITEM_RIGHT_TITLE = Message("custom-recipe.element.item.right.title", null)
val CUSTOM_RECIPE_ELEMENT_ITEM_RIGHT_DESCRIPTION = Message("custom-recipe.element.item.right.description", null)
val CUSTOM_RECIPE_ELEMENT_ITEM_RESULT_TITLE = Message("custom-recipe.element.item.result.title", null)
val CUSTOM_RECIPE_ELEMENT_ITEM_RESULT_DESCRIPTION = Message("custom-recipe.element.item.result.description", null)
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", null)
val CUSTOM_RECIPE_ELEMENT_DELETE_BUTTON_NAME = Message("custom-recipe.element.delete.button.name")
val CUSTOM_RECIPE_ELEMENT_DELETE_BUTTON_LORE = Message("custom-recipe.element.delete.button.lore")
val ENCHANTMENT_LEVEL_COST_TITLE = Message("enchant-level-cost.title", null, "page", "max_page")
val ENCHANTMENT_LEVEL_COST_ELEMENT_TITLE = Message("enchant-level-cost.element.title", "name")
val ENCHANTMENT_LEVEL_COST_ELEMENT_DESCRIPTION = Message("enchant-level-cost.element.description", "name")
val ENCHANTMENT_LEVEL_COST_ELEMENT_ITEM_COST = Message("enchant-level-cost.element.item-cost", "cost")
val ENCHANTMENT_LEVEL_COST_ELEMENT_BOOK_COST = Message("enchant-level-cost.element.book-cost", "cost")
val ENCHANTMENT_LEVEL_LIMIT_TITLE = Message("enchant-level-limit.title", null, "page", "max_page")
val ENCHANTMENT_LEVEL_LIMIT_ELEMENT_TITLE = Message("enchant-level-limit.element.title", "name")
val ENCHANTMENT_LEVEL_LIMIT_ELEMENT_DESCRIPTION = Message("enchant-level-limit.element.description", "name")
val ENCHANTMENT_MERGE_LIMIT_TITLE = Message("enchant-merge-limit.title", null, "page", "max_page")
val ENCHANTMENT_MERGE_LIMIT_ELEMENT_TITLE = Message("enchant-merge-limit.element.title", "name")
val ENCHANTMENT_MERGE_LIMIT_ELEMENT_DESCRIPTION = Message("enchant-merge-limit.element.description", "name")
val ENCHANTMENT_CONFLICT_TITLE = Message("enchant-conflict.title", null, "page", "max_page")
val ENCHANTMENT_CONFLICT_GENERIC_NAME = Message("enchant-conflict.generic-name")
val ENCHANTMENT_CONFLICT_NAME = Message("enchant-conflict.name", "name")
val ENCHANTMENT_CONFLICT_LORE = Message("enchant-conflict.lore", "enchantment_count", "group_count", "min_count")
val ENCHANTMENT_CONFLICT_DEFAULT_NEW = Message("enchant-conflict.default-new")
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", null)
val ENCHANTMENT_CONFLICT_ELEMENT_DELETE_BUTTON_NAME = Message("enchant-conflict.element.delete.button.name")
val ENCHANTMENT_CONFLICT_ELEMENT_DELETE_BUTTON_LORE = Message("enchant-conflict.element.delete.button.lore")
val ENCHANTMENT_CONFLICT_ELEMENT_MIN_BEFORE_COUNT_TITLE = Message("enchant-conflict.element.min-before-count.title", null)
val ENCHANTMENT_CONFLICT_ELEMENT_MIN_BEFORE_COUNT_DESCRIPTION = Message("enchant-conflict.element.min-before-count.description", null)
val ENCHANTMENT_CONFLICT_ELEMENT_MIN_BEFORE_COUNT_ITEM = Message("enchant-conflict.element.min-before-count.item")
val MATERIAL_GROUP_TITLE = Message("material-group.title", null, "page", "max_page")
val MATERIAL_GROUP_GENERIC_NAME = Message("material-group.generic-name")
val MATERIAL_GROUP_NAME = Message("material-group.name", "name")
val MATERIAL_GROUP_LORE = Message("material-group.lore", "groups", "materials", "size")
val MATERIAL_GROUP_ELEMENT_SELECTED_MATERIALS = Message("material-group.element.selected-materials", "group", null, null)
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", null)
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")
val ENCHANT_CONFIG_TITLE = Message("enchant-config.title", "name")
val ENCHANT_CONFIG_NAME = Message("enchant-config.name", "name")
val ENCHANT_CONFIG_MULTIPLES_NAME = Message("enchant-config.multiples-name")
val ITEM_CONFIG_TITLE = Message("item-config.title", "name")
val ITEM_CONFIG_NAME = Message("item-config.name", "name")
/*
* ------------------
* Basic Config Gui
* ------------------
*/
val BASIC_TITLE = Message("basic-config.title")
val BASIC_CAP_ANVIL_COST_TITLE = Message("basic-config.cap-anvil-cost.title", null)
val BASIC_CAP_ANVIL_COST_DESCRIPTION = Message("basic-config.cap-anvil-cost.description", null)
val BASIC_CAP_ANVIL_COST_ITEM = Message("basic-config.cap-anvil-cost.item")
val BASIC_CAP_ANVIL_COST_DISABLED_TITLE = Message("basic-config.cap-anvil-cost.disabled.title")
val BASIC_CAP_ANVIL_COST_DISABLED_DESCRIPTION = Message("basic-config.cap-anvil-cost.disabled.description")
val BASIC_MAX_ANVIL_COST_TITLE = Message("basic-config.max-anvil-cost.title", null)
val BASIC_MAX_ANVIL_COST_DESCRIPTION = Message("basic-config.max-anvil-cost.description", null)
val BASIC_MAX_ANVIL_COST_ITEM = Message("basic-config.max-anvil-cost.item")
val BASIC_MAX_ANVIL_COST_DISABLED_TITLE = Message("basic-config.max-anvil-cost.disabled.title")
val BASIC_MAX_ANVIL_COST_DISABLED_DESCRIPTION = Message("basic-config.max-anvil-cost.disabled.description")
val BASIC_REMOVE_COST_LIMIT_TITLE = Message("basic-config.remove-cost-limit.title", null)
val BASIC_REMOVE_COST_LIMIT_DESCRIPTION = Message("basic-config.remove-cost-limit.description", null)
val BASIC_REMOVE_COST_LIMIT_ITEM = Message("basic-config.remove-cost-limit.item")
val BASIC_REPLACE_TOO_EXPENSIVE_TITLE = Message("basic-config.remove-too-expensive.title", null)
val BASIC_REPLACE_TOO_EXPENSIVE_DESCRIPTION = Message("basic-config.remove-too-expensive.description", null)
val BASIC_REPLACE_TOO_EXPENSIVE_DESCRIPTION_NO_NMS = Message("basic-config.remove-too-expensive.description-no-nms")
val BASIC_ITEM_REPAIR_COST_TITLE = Message("basic-config.item-repair-cost.title", null)
val BASIC_ITEM_REPAIR_COST_DESCRIPTION = Message("basic-config.item-repair-cost.description", null)
val BASIC_ITEM_RENAME_COST_TITLE = Message("basic-config.item-rename-cost.title", null)
val BASIC_ITEM_RENAME_COST_DESCRIPTION = Message("basic-config.item-rename-cost.description", null)
val BASIC_UNIT_REPAIR_COST_TITLE = Message("basic-config.unit-repair-cost.title", null)
val BASIC_UNIT_REPAIR_COST_DESCRIPTION = Message("basic-config.unit-repair-cost.description", null)
val BASIC_SACRIFICE_ILLEGAL_COST_TITLE = Message("basic-config.sacrifice-illegal-cost.title", null)
val BASIC_SACRIFICE_ILLEGAL_COST_DESCRIPTION = Message("basic-config.sacrifice-illegal-cost.description", null)
val BASIC_COLOR_CODE_LIMIT_TITLE = Message("basic-config.color-code.title", null)
val BASIC_COLOR_CODE_LIMIT_DESCRIPTION = Message("basic-config.color-code.description", null)
val BASIC_COLOR_HEX_LIMIT_TITLE = Message("basic-config.color-hex.title", null)
val BASIC_COLOR_HEX_LIMIT_DESCRIPTION = Message("basic-config.color-hex.description", null)
val BASIC_COLOR_PERMISSION_TITLE = Message("basic-config.color-permission.title", null)
val BASIC_COLOR_PERMISSION_DESCRIPTION = Message("basic-config.color-permission.description", null)
val BASIC_COLOR_PERMISSION_DISABLED_TITLE = Message("basic-config.color-permission.disabled.title")
val BASIC_COLOR_PERMISSION_DISABLED_DESCRIPTION = Message("basic-config.color-permission.disabled.description")
val BASIC_COLOR_COST_TITLE = Message("basic-config.color-cost.title", null)
val BASIC_COLOR_COST_DESCRIPTION = Message("basic-config.color-cost.description", null)
val BASIC_COLOR_COST_ITEM = Message("basic-config.color-cost.item")
val BASIC_COLOR_COST_DISABLED_TITLE = Message("basic-config.color-cost.disabled.title")
val BASIC_COLOR_COST_DISABLED_DESCRIPTION = Message("basic-config.color-cost.disabled.description")
val BASIC_WORK_PENALTY_TITLE = Message("basic-config.work-penalty.title")
val BASIC_WORK_PENALTY_ITEM = Message("basic-config.work-penalty.item")
val BASIC_WORK_PENALTY_LORE = Message("basic-config.work-penalty.lore")
val BASIC_WORK_PENALTY_LORE_BREAK = Message("basic-config.work-penalty.lore-break")
val BASIC_WORK_PENALTY_EXPLAIN_INCREASING = Message("basic-config.work-penalty.explanation.increasing")
val BASIC_WORK_PENALTY_EXPLAIN_ADDITIVE = Message("basic-config.work-penalty.explanation.additive")
val BASIC_WORK_PENALTY_EXPLAIN_SHARED = Message("basic-config.work-penalty.explanation.shared")
val BASIC_WORK_PENALTY_EXPLAIN_EXCLUSIVE = Message("basic-config.work-penalty.explanation.exclusive")
}

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_RIGHT
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.MaterialUtil.isAir
import xyz.alexcrea.cuanvil.util.MiniMessageUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil
@ -541,7 +541,7 @@ class AnvilResultListener : Listener {
if (bookPage.isNotEmpty()) bookPage.append('\n')
if (it == null) return@forEach
bookPage.append(MiniMessageUtil.plain_text_mm.serialize(it))
bookPage.append(it.serializePlain())
}
val resultPage = bookPage.toString()

View file

@ -0,0 +1,65 @@
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 Collection<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))
}
fun List<Message>.asComponents(vararg params: Any?): List<Component> {
val result = ArrayList<Component>()
for(message in this) {
result.addAll(message.formatted(*params))
}
return result
}
fun Array<Message>.asComponents(vararg params: Any?): List<Component> {
val result = ArrayList<Component>()
for(message in this) {
result.addAll(message.formatted(*params))
}
return result
}
}

View file

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

View file

@ -25,9 +25,4 @@ object MiniMessageUtil {
val legacy_mm = LegacyComponentSerializer.legacySection()
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 net.kyori.adventure.text.Component
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 java.util.regex.Matcher
import java.util.regex.Pattern
@ -103,10 +106,10 @@ object AnvilColorUtil {
var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr)
if (permission.canUseMinimessage) {
// we dance with formats here
val toMinimessage = MiniMessageUtil.mm.serialize(result)
val toMinimessage = result.serializeMM()
val hackySolution = toMinimessage.replace("\\<", "<")
val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution)
val asPlain = MiniMessageUtil.plain_text_mm.serialize(fromMinimessage)
val asPlain = fromMinimessage.serializePlain()
if (previousStr != asPlain) {
useColor = true
@ -145,8 +148,8 @@ object AnvilColorUtil {
): String? {
if (!permission.allowed() || component == null) return null
val transformed = MiniMessageUtil.mm.serialize(component)
val plainTransform = MiniMessageUtil.plain_text_mm.serialize(component)
val transformed = component.serializeMM()
val plainTransform = component.serializePlain()
if (transformed == plainTransform) return null
if (permission.onlyMinimessage()) {
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
val coloredMessage = MiniMessageUtil.color_only_mm.deserialize(transformed)
val legacyMessage = StringBuilder(MiniMessageUtil.legacy_mm.serialize(coloredMessage))
val legacyMessage = StringBuilder(coloredMessage.serializeLegacy())
// Reverse hex pattern
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.util.PlatformUtil.componentLore
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.config.LoreEditConfigUtil
import xyz.alexcrea.cuanvil.util.config.LoreEditType
@ -320,7 +321,7 @@ object AnvilLoreEditUtil {
hasUndidColor = true
result = clearedLine
} else {
result = MiniMessageUtil.plain_text_mm.serialize(line)
result = line.serializePlain()
}
lines[index] = MiniMessageUtil.plain_text_mm.deserialize(result)
@ -354,7 +355,7 @@ object AnvilLoreEditUtil {
result = clearedLine
} else {
// Remove extra tags
result = MiniMessageUtil.plain_text_mm.serialize(coloredComponent)
result = coloredComponent.serializePlain()
}
line.set(MiniMessageUtil.plain_text_mm.deserialize(result))

View file

@ -16,6 +16,11 @@ metric_type: auto
# Accept true or false (true by default)
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.
#
# In other words:

View file

@ -0,0 +1,414 @@
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"
warning.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..."
error.reload:
resource:
fail: "Resource %path Could not be loaded or reloaded."
hard-fail: "Disabling plugin."
error.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"
command.root:
warning:
unknown-sub: "<red>Invalid subcommand. run <yellow>`%command help` <red>to see available commands"
error:
generic: "<red>Error running this command"
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)"
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"
command.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"
command.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"
command.help:
description: "Help command"
header: "List of available commands:"
command.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"
click-to-change: "<gray>Click Here to change the value"
green-get-item: "<green>%name"
yellow-get-item: "<yellow>%name"
formated-yes: "<green>Yes"
formated-no: "<red>No"
default: "Default"
valued-default: "Default (%value)"
config-ui.global-item:
item-lore-prefix: "<gray>value: %value"
item-lore-prefix-alone: "%value"
config-ui.confirm-action:
fail: "<red>Action could not be completed."
is-user-sure: "<yellow>Are you sure ?"
config-ui.select-item-type:
place-here: "<yellow>Place an item here"
config-ui.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..."
config-ui.unit-repair:
title: "Unit Repair Config <reset>(%page/%max_page)"
item: "<gray>\\%<green>%name <yellow>repaired by <green>%unit"
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)"
value:
title: "<black>\\%<dark_gray>%name Repair"
description:
1: "<gray>Click here to change how many <yellow>\\% <gray>of <green>%name"
2: "<gray>Should get repaired by <yellow>%unit"
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."
config-ui.custom-recipe:
title: "Custom Recipe Config <reset>(%page/%max_page)"
generic-name: "custom recipe"
name: "<yellow>%name <white>Custom recipe"
lore:
default:
1: "<gray>Is valid: %should_work"
2: "<gray>Exact count: %exact_count"
3: "<gray>Recipe Level Cost: <yellow>%per_craft_lv_cost"
4: "<gray>Recipe Linear Xp Cost: <yellow>%per_craft_xp_cost"
linear: "<gray>Exact Linear xp remove: %exact_linear"
element:
exact-count: "<dark_gray>Exact count ?"
linear-xp:
title: "<dark_gray>Remove exact linear xp ?"
name: "<red>Remove exact linear xp ?"
lore: "<gray>Not usable if linear cost is 0"
recipe-cost:
level: "<dark_gray>recipe Level Cost"
xp: "<dark_gray>Recipe Linear Xp Cost"
item:
left:
title: "<yellow>Recipe Left <dark_gray>Item"
description:
1: "<gray>Set the left item of the custom craft"
2: "<gray>■ + □ = □"
right:
title: "<yellow>Recipe Right <dark_gray>Item"
description:
1: "<gray>Set the right item of the custom craft"
2: "<gray>□ + ■ = □"
result:
title: "<green>Recipe Result <dark_gray>Item"
description:
1: "<gray>Set the result item of the custom craft"
2: "<gray>□ + □ = ■"
delete:
title: "<red>Delete <yellow>%type<red>?"
description: "<gray>Confirm that you want to delete this recipe."
button:
name: "<dark_red>DELETE RECIPE"
lore: "<red>Caution with this button !"
config-ui.enchant-level-cost:
title: "<dark_gray>Enchantment Level Limit <reset>(%page/%max_page)"
element:
title: "<green>%name Cost"
description:
1: "<gray>How many level should %name"
2: "<gray>cost when applied by book or by another item."
item-cost: "<gray>Item Cost: <yellow>%cost"
book-cost: "<gray>Book Cost: <yellow>%cost"
config-ui.enchant-level-limit:
title: "<dark_gray>Enchantment Level Limit <reset>(%page/%max_page)"
element:
title: "<green>%name Limit"
description:
1: "<gray>Maximum applied level of %name"
config-ui.enchant-merge-limit:
title: "<dark_gray>Enchantment Maximum Merge Level <reset>(%page/%max_page)"
element:
title: "<green>%name Merge Limit"
description:
1: "<gray>Maximum merge level for for %name"
2: ""
3: "<gray>For example, if set to <yellow>2<gray>, <green>lvl1 <gray>+ <green>lvl1 <gray>of will give a <green>lvl2"
4: "<gray>But <green>lvl2 <gray>+ <green>lvl2 <gray>will not give a <red>lv3<gray>."
5: "<gray>Will still not merge above max enchantment level"
6: "<yellow>-1 <gray>(default) will set the merge limit to enchantment's maximum level"
config-ui.enchant-conflict:
title: "Conflict Config <reset>(%page/%max_page)"
name: "<yellow>%name <white>Conflict"
lore:
1: "<gray>Enchantment count: <yellow>%enchantment_count"
2: "<gray>Group count: <yellow>%group_count"
3: "<gray>Min enchantments count: <yellow>%min_count"
generic-name: "conflict"
default-new: "new_group"
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."
button:
name: "<dark_red>DELETE CONFLICT"
lore: "<red>Caution with this button !"
min-before-count:
item: "<green>Minimum Enchantment Count"
title: "<dark_gray>Minimum enchantment count"
description:
1: "<gray>Minimum enchantment count set to X mean only X enchantment can be put"
2: "<gray>on an item before the conflict is active."
config-ui.material-group:
title: "Group Config <reset>(%page/%max_page)"
generic-name: "material group"
name: "<yellow>%name <white>Group"
lore:
1: "<gray>Number of selected groups : %groups"
2: "<gray>Number of included material : %materials"
3: ""
4: "<gray>Total number of included material %size"
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 !"
config-ui.material-select:
new:
confirm:
title: "Remove %name"
description: "<dark_gray>Confirm Remove %name from this list."
config-ui.enchant-config:
title: "Configuring %name"
name: "<green>Configuring %name:"
multiples-name: "Enchantments"
config-ui.item-config:
title: "%name Config"
name: "<green>Configuring %name"
config-ui.basic-config:
title: "<dark_gray>Basic Config"
config-ui.basic-config.cap-anvil-cost:
item: "<yellow>Cap Anvil Cost"
title: "<dark_gray>Cap Anvil Cost ?"
description:
1: "<gray>All anvil cost will be capped to <green>Max Anvil Cost<gray> if enabled."
2: "<gray>In other words:"
3: "<gray>For any anvil cost greater than <green>Max Anvil Cost<gray>, Cost will be set to <green>Max Anvil Cost<gray>."
disabled:
title: "<red>Cap Anvil Cost ?"
description: "<gray>This config only work if <red>Limit Repair Cost<gray> is disabled."
config-ui.basic-config.max-anvil-cost:
item: "<green>Max Anvil Cost"
title: "<dark_gray>Max Anvil Cost"
description:
1: "<gray>Max cost the Anvil can get to."
2: "<gray>Valid values include <yellow>0 <gray>to <yellow>1000<gray>."
3: "<gray>Cost will be displayed as <red>Too Expensive<gray>:"
4: "<gray>- If Cost is above <yellow>39"
5: "<gray>- And <yellow>Replace Too Expensive<gray> is disabled"
disabled:
title: "<red>Max Anvil Cost"
description: "<gray>This config only work if <red>Limit Repair Cost<gray> is disabled."
config-ui.basic-config.remove-cost-limit:
item: "<yellow>Remove Anvil Cost Limit"
title: "<dark_gray>Remove Anvil Cost Limit ?"
description:
1: "<gray>Whether the anvil's cost limit should be removed entirely."
2: "<gray>The anvil will still visually display <red>Too Expensive<gray> if <yellow>Replace Too Expensive<gray> is disabled."
3: "<gray>However, the action will be completable if xp requirement is meet."
config-ui.basic-config.remove-too-expensive:
title: "<dark_gray>Replace Too Expensive ?"
description:
1: "<gray>Whenever anvil cost is above <yellow>39<gray> should display the true price and not <red>Too Expensive<gray>."
2: "<gray>However, when bypassing <red>Too Expensive<gray>, anvil price will be displayed as <green>Green<gray>."
3: "<gray>Even if cost is displayed as <green>Green<gray>:"
4: "<gray>If the player do not have the required xp level, the action will not be completable."
description-no-nms:
1: ""
2: "<dark_red>/!\\<red>Caution<dark_red>/!\\ <red>You need ProtocoLib installed and working, or a paper server."
3: "<red>Currently ProtocoLib is not detected."
config-ui.basic-config.item-repair-cost:
title: "<dark_gray>Item Repair Cost"
description:
1: "<gray>XP Level amount added to the anvil when the item"
2: "<gray>is repaired by another item of the same type."
config-ui.basic-config.item-rename-cost:
title: "<dark_gray>Rename Cost"
description:
1: "<gray>XP Level amount added to the anvil when the item is renamed."
config-ui.basic-config.unit-repair-cost:
title: "<dark_gray>Unit Repair Cost"
description:
1: "<gray>XP Level amount added to the anvil when the item is repaired by an <yello<>unit<gray>."
2: "<gray>For example: a Diamond on a Diamond Sword."
3: "<gray>What's considered unit for what can be edited on the unit repair configuration."
config-ui.basic-config.sacrifice-illegal-cost:
title: "<dark_gray>Sacrifice Illegal Enchant Cost"
description:
1: "<gray>XP Level amount added to the anvil when a sacrifice enchantment"
2: "<gray>conflict With one of the left item enchantment"
config-ui.basic-config.color-code:
title: "<dark_gray>Allow Use Of Color Code ?"
description:
1: "<gray>Whether players can use color code."
2: "<gray>Color code a formatted like <green>&a<gray> and is used in the rename field of the anvil."
3: "<gray>Player may need permission to use color code if <yellow>Player need permission to use color<gray> is enabled."
config-ui.basic-config.color-hex:
title: "<dark_gray>Allow Use Of Hexadecimal Color ?"
description:
1: "<gray>Whether players can use hexadecimal color."
2: "<gray>Color code a formatted like <gray>#012345 <gray>and is used in the rename field of the anvil."
3: "<gray>Player may need permission to use color code if <yellow>Permission Needed For Color<gray> is enabled."
config-ui.basic-config.color-permission:
title: "<dark_gray>Need Permission To Use Color ?"
description:
1: "<gray>Whether players should have permission to be able to use colors."
2: "<gray>Give player <yellow>ca.color.code <gray>Permission to allow use of color code."
3: "<gray>Give player <yellow>ca.color.hex <gray>Permission to allow use of hexadecimal color."
disabled:
title: "<red>Need Permission To Use Color ?"
description:
1: "<gray>This config can do something only if one of the following config is enabled:"
2: "<gray>- <green>Allow Use Of Color Code"
3: "<gray>- <green>Allow Use Of Hexadecimal Color"
config-ui.basic-config.color-cost:
item: "<green>Cost Of Using Color"
title: "<dark_gray>Cost Of Using Color"
description:
1: "<gray>XP level cost when using color code or hexadecimal color using the anvil."
2: "<gray>conflict With one of the left item enchantment"
disabled:
title: "<red>Cost Of Using Color"
description:
1: "<gray>This config can do something only if one of the following config is enabled:"
2: "<gray>- <green>Allow Use Of Color Code"
3: "<gray>- <green>Allow Use Of Hexadecimal Color"
config-ui.basic-config.work-penalty:
title: "<dark_gray>Work Penalty Type"
item: "<green>Work Penalty Type"
lore:
1: "<gray>Work penalty increase the price for every anvil use."
2: "<gray>This config allow you to choose the comportment of work penalty."
lore-break:
1: ""
2: "<gray>About shared/exclusive penalty:"
explanation:
increasing: "<yellow>Increasing<gray>: will penalty be increased (in item)"
additive: "<yellow>Additive<gray>: will penalty be added to the cost"
shared: "<yellow>Shared<gray>: Vanilla, shared penalty. it will be kept from before the plugin installation."
exclusive: "<yellow>Exclusive<gray>: Custom, per anvil use type penalty. it will be lost after plugin uninstallation"