Compare commits

...

7 commits

37 changed files with 824 additions and 223 deletions

View file

@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.dependency.util
import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.inventory.ItemStack import org.bukkit.command.CommandSender
import org.bukkit.inventory.meta.ItemMeta import org.bukkit.inventory.meta.ItemMeta
// Mostly made for paper, spigot and folia support // Mostly made for paper, spigot and folia support
@ -100,4 +100,19 @@ 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
}
} }

View file

@ -11,6 +11,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.MetricsUtil; import xyz.alexcrea.cuanvil.util.MetricsUtil;
import java.util.Arrays; import java.util.Arrays;
@ -33,7 +34,7 @@ public class ConfirmActionGui extends AbstractAskGui {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
@ -47,7 +48,7 @@ public class ConfirmActionGui extends AbstractAskGui {
} }
if (!success) { if (!success) {
event.getWhoClicked().sendMessage("§cAction could not be completed. "); MsgUI.INSTANCE.getCONFIRM_ACTION_FAILED().send(player);
} }
backOnConfirm.show(player); backOnConfirm.show(player);

View file

@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.MaterialUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil;
import java.util.Arrays; import java.util.Arrays;
@ -36,7 +37,7 @@ public class SelectItemTypeGui extends AbstractAskGui {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }

View file

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

View file

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

View file

@ -18,6 +18,7 @@ import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui;
import xyz.alexcrea.cuanvil.gui.config.settings.DoubleSettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.DoubleSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -70,11 +71,11 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui<Namespaced
NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack); NamespacedKey type = MaterialUtil.INSTANCE.getCustomType(itemStack);
if (!(meta instanceof Damageable)) { if (!(meta instanceof Damageable)) {
player.sendMessage("§cThis item can't be damaged, so it can't be repaired."); MsgUI.INSTANCE.getUNIT_REPAIR_ELEMENT_CANNOT_REPAIR_NEW().send(player);
return; return;
} }
if (type.equals(this.parentMaterial)) { if (type.equals(this.parentMaterial)) {
player.sendMessage("§cItem can't repair something of the same type."); MsgUI.INSTANCE.getUNIT_REPAIR_ELEMENT_SAME_TYPE_NEW().send(player);
return; return;
} }

View file

@ -23,6 +23,7 @@ import xyz.alexcrea.cuanvil.gui.config.settings.MaterialSelectSettingGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.*; import java.util.*;
@ -113,7 +114,7 @@ public class GroupConfigSubSettingGui extends MappedToListSubSettingGui implemen
// Do not allow to open inventory if player do not have edit configuration permission // Do not allow to open inventory if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
// test if group is used & cancel & warn user if so // test if group is used & cancel & warn user if so

View file

@ -18,6 +18,7 @@ import xyz.alexcrea.cuanvil.gui.config.list.MappedElementListConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.lang.MsgUI;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import xyz.alexcrea.cuanvil.util.MaterialUtil; import xyz.alexcrea.cuanvil.util.MaterialUtil;
@ -156,7 +157,7 @@ public class MaterialSelectSettingGui extends MappedElementListConfigGui<Namespa
// Do not allow to save configuration if player do not have edit configuration permission // Do not allow to save configuration if player do not have edit configuration permission
if (!player.hasPermission(CustomAnvil.editConfigPermission)) { if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory(); player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player);
return; return;
} }
if(testCantSave()) return; if(testCantSave()) return;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -28,6 +28,7 @@ import xyz.alexcrea.cuanvil.dependency.scheduler.FoliaScheduler
import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore
import xyz.alexcrea.cuanvil.lang.MsgWarning
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError
import java.lang.IllegalStateException import java.lang.IllegalStateException
@ -158,18 +159,14 @@ object DependencyManager {
} }
private fun logException(target: CommandSender, e: Exception) { private fun logException(target: CommandSender, e: Exception) {
CustomAnvil.instance.logger.log( CustomAnvil.logError(
Level.SEVERE,
"Error while trying to handle custom anvil supported plugin: ", "Error while trying to handle custom anvil supported plugin: ",
e e
) )
trackError(e) trackError(e)
// Finally, warn the player // Finally, warn the player
target.sendMessage( MsgWarning.DEPENDENCY_GENERIC_EXCEPTION.send(target)
"[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " +
ChatColor.RED.toString() + "Error while handling the anvil."
)
} }
private fun logExceptionAndClear(view: AnvilView, e: Exception) { private fun logExceptionAndClear(view: AnvilView, e: Exception) {

View file

@ -0,0 +1,54 @@
package xyz.alexcrea.cuanvil.lang
import io.delilaheve.CustomAnvil
import org.bukkit.configuration.ConfigurationSection
import xyz.alexcrea.cuanvil.config.ConfigHolder
object Lang {
private val default = Language(DEFAULT_LANG, false)
private var lang = default
fun reload() {
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)
}
/*
* 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,60 @@
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)
}
val name: String
get() = conf.getString("name", id)!!
}

View file

@ -0,0 +1,147 @@
package xyz.alexcrea.cuanvil.lang
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.logging.Level
import kotlin.math.min
open class Message(val key: String, vararg val params: String) {
protected fun replaceParameters(stb: StringBuilder, vararg values: Any) {
// replace all placeholder thingy %key -> value
if(params.size != values.size) {
CustomAnvil.log("Wrong number of argument for parameter for key $key (${params.size}/${values.size})")
}
for(i in 0 until min(params.size, values.size)) {
val key = params[i]
val replacement = values[i].toString()
var current = 0
while(true) {
current = stb.indexOf('%', current) + 1
if(current <= 0 || current + key.length > stb.length) break // may be able to be removed if bound checked in startsWith ?
if(!stb.startsWith(key, current, false)) continue
stb.replace(current - 1, current + key.length, replacement)
current = current - 1 + replacement.length
}
}
}
private fun unformattedMonoline(vararg params: Any): String {
val translated = Lang.getTranslated(key)
if(params.isEmpty() && this.params.isEmpty()) return translated
val stb = StringBuilder(translated)
replaceParameters(stb, *params)
return stb.toString()
}
private fun unformattedMultiline(section: ConfigurationSection, vararg params: Any): String {
val stb = StringBuilder()
for(key in section.getKeys(false)) {
if(!section.isString(key)) continue
if(!stb.isEmpty()) stb.append('\n')
stb.append(section.getString(key))
}
replaceParameters(stb, *params)
return stb.toString()
}
fun unformatted(vararg params: Any): String {
val section = Lang.getSection(key)
if(section != null) return unformattedMultiline(section, *params)
return unformattedMonoline(*params)
}
private fun formattedMultiline(section: ConfigurationSection, vararg params: Any): List<Component> {
val result = ArrayList<Component>()
for(key in section.getKeys(false)) {
if(!section.isString(key)) continue
val stb = StringBuilder(section.getString(key))
replaceParameters(stb, *params)
result.add(MiniMessageUtil.mm.deserialize(stb.toString()))
}
return result
}
fun formatted(vararg params: Any): List<Component> {
val section = Lang.getSection(key)
if(section != null) return formattedMultiline(section, *params)
val translated = unformattedMonoline(*params)
return listOf(MiniMessageUtil.mm.deserialize(translated))
}
fun 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,4 @@
package xyz.alexcrea.cuanvil.lang
object Msg {
}

View file

@ -0,0 +1,68 @@
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_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.remove.", "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,26 @@
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.hardfail")
/*
* ----------
* Commands
* ----------
*/
}

View file

@ -0,0 +1,21 @@
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 CONFIRM_ACTION_FAILED = Message("confirm-action.fail")
val ELEMENT_LIST_INSTRUCTION_NEW = Message("element-list.instruction-new", "type")
val ELEMENT_LIST_CANCELLED_NEW = Message("element-list.cancelled-new", "type")
val ELEMENT_LIST_DUPLICATED_NEW = Message("element-list.duplicated-new", "type")
val UNIT_REPAIR_ELEMENT_TITLE = Message("unit-repair.element.title")
val UNIT_REPAIR_ELEMENT_DESCRIPTION = Message("unit-repair.element.description")
val UNIT_REPAIR_ELEMENT_CANNOT_REPAIR_NEW = Message("unit-repair.element.cannot-damage-new")
val UNIT_REPAIR_ELEMENT_SAME_TYPE_NEW = Message("unit-repair.element.same-type-new")
}

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 DEPENDENCY_GENERIC_EXCEPTION = Message("config-ui.shared.no-permission")
}

View file

@ -30,6 +30,7 @@ import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.MiniMessageUtil
@ -536,7 +537,7 @@ class AnvilResultListener : Listener {
if (bookPage.isNotEmpty()) bookPage.append('\n') if (bookPage.isNotEmpty()) bookPage.append('\n')
if (it == null) return@forEach if (it == null) return@forEach
bookPage.append(MiniMessageUtil.plain_text_mm.serialize(it)) bookPage.append(it.serializePlain())
} }
val resultPage = bookPage.toString() val resultPage = bookPage.toString()

View file

@ -0,0 +1,33 @@
package xyz.alexcrea.cuanvil.util
import net.kyori.adventure.text.Component
import org.bukkit.command.CommandSender
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.sendPaperMessage
object ComponentUtil {
fun Component.send(destination: CommandSender) {
if(!destination.sendPaperMessage(this))
destination.sendMessage(this.serializeLegacy())
}
fun List<Component>.send(destination: CommandSender) {
for(component in this)
component.send(destination)
}
fun 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)
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,112 @@
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"
error:
load:
legacy.failed: "error trying to check for legacy system"
update.check-fail: "error trying to fetch latest update"
command-register: "error trying to register commands"
compatibility: "error loading dependency compatibility"
listeners: "error registering listeners"
enchant-system: "error initializing enchantment system"
non-default-config: "Plugin has an issue while trying to load non default config... exiting..."
reload:
resource:
fail: "Resource %path Could not be loaded or reloaded."
hard-fail: "Disabling plugin."
command:
shared:
no-diag-permission: "<red>You do not have permission to diagnostic this server"
hover-copy: "<gray>Click to copy"
unknown-subcmd: "Unknown subcommand %command"
no-permission: "No permission to execute this command"
warning:
missing-subcmd: "Need to specify a subcommand. for example %example1 or %example2"
root:
warning:
unknown-sub: "<red>Invalid subcommand. run <yellow>`%command help` <red>to see available commands"
error:
generic: "<red>Error running this command"
debug:
description: "Used to toggle debug logs and retrieve them"
log-cleared: "Log Cleared"
toggled: "Debug toggled to %type"
copy: "<green>Click to copy log data"
data:
header: "Debug Log data:"
line-count: "Found %count lines"
warning:
unspecified-type: "Need to specify which type of debug to toggle: \"default\" or \"verbose\""
invalid-type: "Invalid debug type \"%type\""
no-log: "No log to show ? make sure you tried with debug log toggled (%command)"
diagnostic:
description: "Basic diagnostic of this plugin"
had-error: "<red>There was an error running the diagnostic"
copy: "<green>Click to copy diagnostic data"
config:
description: "Used to edit the configuration of the plugin"
folia-issue:
1: "<red>It look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia."
2: "<yellow>It is may come in a future version."
3: ""
4: "<yellow>Currently you need to edit manually the config or copy from another server (spigot or better)"
5: "<yellow>Then /ca reload after config file is edited"
enchantment:
no_hand: "No enchantment found in the item you are holding"
no_name: "No enchantment found with the name %name"
warning:
legacy-name: "<red>/ca gui has been moved to /ca config"
cannot_configure: "Cannot configure the item in hand"
enchant:
description: "Allows to set enchantment to holden item"
warning:
missing_parameter: "Missing enchantment parameter"
not_found: "Enchantment not found: %path"
malformed_number: "Invalid number: %num"
cannot_enchant: "Cannot enchant this item"
removed: "%name removed"
set: "%name set to level %level"
help:
description: "Help command"
header: "List of available commands:"
reload:
description: "Reload the configuration of this plugin"
start: "<yellow>Reloading config..."
success: "<green>Config reloaded !"
fail: "<red>Config was not able to be reloaded..."
hard-fail: "<red>Hard fail, plugin disabled"
config-ui:
shared:
no-permission: "<red>You do not have permission to edit the config"
confirm-action:
fail: "<red>Action could not be completed."
element-list:
instruction-new:
1: "<yellow>Write the %type name you want to create in the chat."
2: "<yellow>Or write <red>cancel <yellow>to go back to %type config menu"
cancelled-new: "%type creation cancelled..."
duplicated-new: "<red>Please enter a %type name that do not already exist..."
unit-repair:
element:
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-new: "<red>This item can't be damaged, so it can't be repaired."
same-type-new: "<red>Item can't repair something of the same type."