Better enchant limit & remove protocolib (#109)

Simplify item level limit code by deleting "default level" and using
enchantment's default level instead
allow max level 0 for "can't use it" and -1 for "default maximum"
made the enchantment limit gui reflect the above change

Also removed force protocolib in config as hopefully should be
unnecessary. It is still in the plugin in case something go wrong, which
seems unlikely as never been necessary as far as I remember
This commit is contained in:
alexcrea 2026-03-23 20:40:52 +01:00 committed by GitHub
commit 8ded2ae9c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 96 additions and 137 deletions

View file

@ -87,18 +87,14 @@ permission_needed_for_color: true
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits
#
# Valid values include 1 to 1000
default_limit: 5
# Override limits for specific enchants
#
# Enchantments not listed here will use the value of default_limit
#
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
#
# Valid range of 1 - 255 for each enchantment
# Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits:
minecraft:aqua_affinity: 1
minecraft:binding_curse: 1
@ -410,10 +406,4 @@ debug_log: false
# Whether to show verbose debug logging
debug_log_verbose: false
# In case something when wrong with CustomAnvil packet manager.
# If you see "missing class exception" or similar you may test this.
# If enabled and Protocolib absent or disabled "Replace to expensive" will not work.
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
force_protocolib: false
configVersion: 1.11.0

View file

@ -89,18 +89,14 @@ permission_needed_for_color: true
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits
#
# Valid values include 1 to 1000
default_limit: 5
# Override limits for specific enchants
#
# Enchantments not listed here will use the value of default_limit
#
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
#
# Valid range of 1 - 255 for each enchantment
# Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits:
minecraft:aqua_affinity: 1
minecraft:binding_curse: 1
@ -430,11 +426,5 @@ debug_log: false
# Whether to show verbose debug logging
debug_log_verbose: false
# In case something when wrong with CustomAnvil packet manager.
# If you see "missing class exception" or similar you may test this.
# If enabled and Protocolib absent or disabled "Replace to expensive" will not work.
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
force_protocolib: false
configVersion: 1.15.5
lowMinecraftVersion: 1.21.11

View file

@ -87,18 +87,14 @@ permission_needed_for_color: true
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits
#
# Valid values include 1 to 1000
default_limit: 5
# Override limits for specific enchants
#
# Enchantments not listed here will use the value of default_limit
#
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
#
# Valid range of 1 - 255 for each enchantment
# Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits:
minecraft:aqua_affinity: 1
minecraft:binding_curse: 1
@ -422,11 +418,5 @@ debug_log: false
# Whether to show verbose debug logging
debug_log_verbose: false
# In case something when wrong with CustomAnvil packet manager.
# If you see "missing class exception" or similar you may test this.
# If enabled and Protocolib absent or disabled "Replace to expensive" will not work.
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
force_protocolib: false
configVersion: 1.11.0
lowMinecraftVersion: 1.21.9

View file

@ -87,18 +87,14 @@ permission_needed_for_color: true
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits
#
# Valid values include 1 to 1000
default_limit: 5
# Override limits for specific enchants
#
# Enchantments not listed here will use the value of default_limit
#
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
#
# Valid range of 1 - 255 for each enchantment
# Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits:
minecraft:aqua_affinity: 1
minecraft:binding_curse: 1
@ -410,10 +406,4 @@ debug_log: false
# Whether to show verbose debug logging
debug_log_verbose: false
# In case something when wrong with CustomAnvil packet manager.
# If you see "missing class exception" or similar you may test this.
# If enabled and Protocolib absent or disabled "Replace to expensive" will not work.
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
force_protocolib: false
configVersion: 1.11.0

View file

@ -1,6 +1,7 @@
package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ConfigOptions;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
@ -180,13 +181,13 @@ public class EnchantmentApi {
private static boolean tryWriteDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment, boolean override) {
boolean hasChange = false;
String levelPath = "enchant_limits." + enchantment.getKey();
String levelPath = ConfigOptions.ENCHANT_LIMIT_ROOT + "." + enchantment.getKey();
if(override || !defaultConfig.isSet(levelPath)){
defaultConfig.set(levelPath, enchantment.defaultMaxLevel());
hasChange = true;
}
String basePath = "enchant_values." + enchantment.getKey();
String basePath = ConfigOptions.ENCHANT_VALUES_ROOT + "." + enchantment.getKey();
EnchantmentRarity rarity = enchantment.defaultRarity();
String itemPath = basePath + ".item";

View file

@ -17,7 +17,7 @@ import java.util.Locale;
*/
public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsGui.IntSettingFactory> {
private static final String SECTION_NAME = "enchant_limits";
private static final String SECTION_NAME = ConfigOptions.ENCHANT_LIMIT_ROOT;
private static EnchantLimitConfigGui INSTANCE = null;
@ -41,18 +41,34 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
var defaultValue = enchant.defaultMaxLevel();
return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", this,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
Collections.singletonList(
"§7Maximum applied level of " + prettyKey
),
0, 255,
enchant.defaultMaxLevel(),
-1, 255, -1,
1, 5, 10, 50, 100){
@Override
public int getConfiguredValue() {
return ConfigOptions.INSTANCE.enchantLimit(enchant);
var value = ConfigOptions.INSTANCE.rawEnchantLimit(enchant);
return Math.min(value, ConfigOptions.ENCHANT_LIMIT);
}
@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";
};
}
else return super.valueDisplayName(type, value);
}
};
}

View file

@ -72,7 +72,8 @@ public class IntSettingsGui extends AbstractSettingGui {
assert meta != null;
meta.setDisplayName("§eReset to default value");
meta.setLore(Collections.singletonList("§7Default value is §e" + holder.defaultVal));
meta.setLore(Collections.singletonList("§7Default value is §e" +
holder.valueDisplayName(ValueDisplayType.RESET, holder.defaultVal)));
item.setItemMeta(meta);
returnToDefault = new GuiItem(item, event -> {
event.setCancelled(true);
@ -86,41 +87,23 @@ public class IntSettingsGui extends AbstractSettingGui {
* Update item using the setting value to match the new value.
*/
protected void updateValueDisplay() {
PatternPane pane = getPane();
// minus item
GuiItem minusItem;
if (now > holder.min) {
int planned = Math.max(holder.min, now - step);
ItemStack item = new ItemStack(Material.RED_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§e" + now + " §f-> §e" + planned + " §r(§c-" + (now - planned) + "§r)");
meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE));
item.setItemMeta(meta);
minusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
int planned = Math.min(holder.max, now + step);
minusItem = valueEditItem(Material.RED_TERRACOTTA, ValueDisplayType.REMOVE, planned);
} else {
minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
pane.bindItem('-', minusItem);
//plus item
// may do a function to generalise ?
GuiItem plusItem;
if (now < holder.max) {
int planned = Math.min(holder.max, now + step);
ItemStack item = new ItemStack(Material.GREEN_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("§e" + now + " §f-> §e" + planned + " §r(§a+" + (planned - now) + "§r)");
meta.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE));
item.setItemMeta(meta);
plusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
plusItem = valueEditItem(Material.GREEN_TERRACOTTA, ValueDisplayType.ADD, planned);
} else {
plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
@ -131,7 +114,7 @@ public class IntSettingsGui extends AbstractSettingGui {
ItemMeta resultMeta = resultPaper.getItemMeta();
assert resultMeta != null;
resultMeta.setDisplayName("§fValue: §e" + now);
resultMeta.setDisplayName("§fValue: §e" + holder.valueDisplayName(ValueDisplayType.CURRENT, now));
resultMeta.setLore(holder.displayLore);
resultPaper.setItemMeta(resultMeta);
@ -149,7 +132,21 @@ public class IntSettingsGui extends AbstractSettingGui {
}
pane.bindItem('D', returnToDefault);
}
private GuiItem valueEditItem(Material mat, ValueDisplayType type, int planned) {
ItemStack item = new ItemStack(mat);
ItemMeta meta = item.getItemMeta();
assert meta != null;
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.setLore(Collections.singletonList(AbstractSettingGui.CLICK_LORE));
item.setItemMeta(meta);
return new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
}
/**
@ -389,6 +386,23 @@ public class IntSettingsGui extends AbstractSettingGui {
return getItem(itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath));
}
protected String valueDisplayName(ValueDisplayType type, int value) {
return String.valueOf(value);
}
protected String deltaDisplay(ValueDisplayType type, int now, int planned) {
var delta = planned - now;
if(delta < 0) return "§c" + delta;
else return "§a+" + delta;
}
}
public enum ValueDisplayType {
ADD,
CURRENT,
REMOVE,
RESET,
}
}

View file

@ -30,7 +30,6 @@ public class PluginSetDefault {
nbSet += trySetDefault(config, ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR);
nbSet += trySetDefault(config, PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR);
nbSet += trySetDefault(config, USE_OF_COLOR_COST, DEFAULT_USE_OF_COLOR_COST);
nbSet += trySetDefault(config, DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT);
// Lore Edit defaults
for (@NotNull LoreEditType value : LoreEditType.values()) {

View file

@ -57,8 +57,6 @@ object ConfigOptions {
const val ENCHANT_COUNT_LIMIT_DEFAULT = "$ENCHANT_COUNT_LIMIT_ROOT.default"
const val ENCHANT_COUNT_LIMIT_ITEMS = "$ENCHANT_COUNT_LIMIT_ROOT.items"
const val DEFAULT_LIMIT_PATH = "default_limit"
const val ENCHANT_LIMIT_ROOT = "enchant_limits"
const val ENCHANT_VALUES_ROOT = "enchant_values"
@ -102,8 +100,6 @@ object ConfigOptions {
const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true
const val DEFAULT_USE_OF_COLOR_COST = 0
const val DEFAULT_ENCHANT_LIMIT = 5
// Debug flag
private const val DEFAULT_DEBUG_LOG = false
private const val DEFAULT_VERBOSE_DEBUG_LOG = false
@ -133,8 +129,7 @@ object ConfigOptions {
val USE_OF_COLOR_COST_RANGE = 0..1000
// Valid range for an enchantment limit
@JvmField
val ENCHANT_LIMIT_RANGE = 1..255
const val ENCHANT_LIMIT = 255
// Valid range for an enchantment count limit
@JvmField
@ -348,16 +343,6 @@ object ConfigOptions {
return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive)
}
/**
* Default enchantment limit
*/
private val defaultEnchantLimit: Int
get() {
return ConfigHolder.DEFAULT_CONFIG
.config
.getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT)
}
/**
* Get material enchantment count limit
*
@ -422,42 +407,37 @@ object ConfigOptions {
* Get the given [enchantment]'s limit
*/
fun enchantLimit(enchantment: CAEnchantment): Int {
val limit = rawEnchantLimit(enchantment)
if(limit >= 0) return limit.coerceAtMost(ENCHANT_LIMIT)
// get default
return enchantment.defaultMaxLevel()
}
/**
* Get the given [enchantment]'s limit
*/
fun rawEnchantLimit(enchantment: CAEnchantment): Int {
// Test namespace
var limit = enchantLimit(enchantment.key.toString())
if (limit != null) return limit
if (limit >= 0) return limit
// Test legacy (name only)
limit = enchantLimit(enchantment.enchantmentName)
if (limit != null) return limit
if (limit >= 0) return limit
// get default (and test old legacy if present)
return getDefaultLevel(enchantment.enchantmentName)
// Default to negative
return -1
}
/**
* Get the given [enchantmentName]'s limit
*/
private fun enchantLimit(enchantmentName: String): Int? {
private fun enchantLimit(enchantmentName: String): Int {
val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName"
return CustomAnvil.instance
.config
.getInt(path, ENCHANT_LIMIT_RANGE.first - 1)
.takeIf { it in ENCHANT_LIMIT_RANGE }
}
/**
* Get default value if enchantment do not exist on config
*/
private fun getDefaultLevel(
enchantmentName: String, // compatibility with 1.20.5. TODO better update system
): Int {
if (enchantmentName == "sweeping_edge") {
val limit = enchantLimit("sweeping")
if (limit != null) return limit
}
return defaultEnchantLimit
return CustomAnvil.instance.config
.getInt(path, -1)
}
/**
@ -529,20 +509,20 @@ object ConfigOptions {
fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int {
val key = enchantment.key.toString()
var value = maxBeforeMergeDisabled(key)
if (value != null) return value
if (value >= 0) return value
// Legacy name
val legacy = enchantment.enchantmentName
value = maxBeforeMergeDisabled(legacy)
if (value != null) return value
if (value >= 0) return value
if (key == "minecraft:sweeping_edge") {
value = maxBeforeMergeDisabled("minecraft:sweeping")
if (value != null) return value
if (value >= 0) return value
// legacy name of legacy enchantment name
value = maxBeforeMergeDisabled("sweeping")
if (value != null) return value
if (value >= 0) return value
}
return DEFAULT_MAX_BEFORE_MERGE_DISABLED
@ -552,14 +532,13 @@ object ConfigOptions {
* Get the given [enchantmentName]'s level before merge is disabled
* a negative value would mean never disabled
*/
private fun maxBeforeMergeDisabled(enchantmentName: String): Int? {
private fun maxBeforeMergeDisabled(enchantmentName: String): Int {
// find if set
val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName"
return CustomAnvil.instance
.config
.getInt(path, ENCHANT_LIMIT_RANGE.min() - 1)
.takeIf { it in ENCHANT_LIMIT_RANGE }
.getInt(path, -1)
}
fun isImmutable(key: NamespacedKey): Boolean {

View file

@ -16,7 +16,7 @@ abstract class CASubCommand: CommandExecutor {
): Boolean {
if(!alreadySaid){
sender.sendMessage(ChatColor.RED.toString() +
"Please not that this command will be replaced as a subcommand of `/customanvil`")
"Please not that this command will be replaced as a subcommand of `/customanvil` or `/ca`")
alreadySaid = true
}

View file

@ -89,18 +89,14 @@ permission_needed_for_color: true
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits
#
# Valid values include 1 to 1000
default_limit: 5
# Override limits for specific enchants
#
# Enchantments not listed here will use the value of default_limit
#
# Overrides provided default from aqua_affinity to depth_strider won't change effect with extra levels
#
# Valid range of 1 - 255 for each enchantment
# Valid range of 0 - 255 for each enchantment
# -1 mean keep default
enchant_limits:
minecraft:aqua_affinity: 1
minecraft:binding_curse: 1
@ -412,10 +408,4 @@ debug_log: false
# Whether to show verbose debug logging
debug_log_verbose: false
# In case something when wrong with CustomAnvil packet manager.
# If you see "missing class exception" or similar you may test this.
# If enabled and Protocolib absent or disabled "Replace to expensive" will not work.
# ProtocoLib may also be used if the server is in an "unsupported" version even if this option is disabled.
force_protocolib: false
configVersion: 1.11.0