Compare commits

..

9 commits

Author SHA1 Message Date
eeff628da6
update from v1.x.x 2026-07-08 03:58:03 +02:00
b56782b234
remove legacy command 2026-07-08 03:53:23 +02:00
8078e54b15
rebase on news update 2026-07-08 03:52:39 +02:00
5e5493b0e8
prepare for v2 2026-07-08 03:52:37 +02:00
b5843756c7
rebase on new update 2026-07-08 03:52:16 +02:00
fba34fecb8
1.21 cleanup and fix
also random cleanup
2026-07-08 03:52:14 +02:00
aeda3d7112
fix from rebase 2026-07-08 03:51:50 +02:00
7ecfc12b5c
progress on 1.21 transition 2026-07-08 03:51:47 +02:00
007a664db1
initial 1.21 transition 2026-07-08 03:51:41 +02:00
35 changed files with 95 additions and 186 deletions

View file

@ -40,8 +40,6 @@ Custom Items support is considered unstable. If you find issue please report it
- [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/) by H7KZ - [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/) by H7KZ
Partially use Custom Anvil maximum XP settings (>= 6.1.5) Partially use Custom Anvil maximum XP settings (>= 6.1.5)
- [EnchantedBook](https://modrinth.com/plugin/enchantedbook) by Minacle
- [HavenBags](https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/) by hyperdefined - [HavenBags](https://www.spigotmc.org/resources/havenbags-shulker-like-player-bound-bags-1-17-1-21-4.110420/) by hyperdefined
For bag upgrade and skin via anvil. (version >= 1.31.0) For bag upgrade and skin via anvil. (version >= 1.31.0)

View file

@ -58,7 +58,7 @@ dependencies {
compileOnly("org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT")
// fast stats // fast stats
implementation("dev.faststats.metrics:bukkit:0.27.2") implementation("dev.faststats.metrics:bukkit:0.27.0")
// minimessage // minimessage
implementation("net.kyori:adventure-text-minimessage:4.25.0") implementation("net.kyori:adventure-text-minimessage:4.25.0")

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #
@ -275,7 +275,10 @@ restriction_sweeping_edge:
- enchanted_book - enchanted_book
- swords - swords
# Do not exist in 1.18, that mean useInFuture will be set to true
# useInFuture set to true also mean it will not warn if there is an issue
restriction_swift_sneak: restriction_swift_sneak:
useInFuture: true
enchantments: enchantments:
- minecraft:swift_sneak - minecraft:swift_sneak
notAffectedGroups: notAffectedGroups:

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #
@ -272,7 +272,10 @@ restriction_sweeping_edge:
- enchanted_book - enchanted_book
- swords - swords
# Do not exist in 1.18, that mean useInFuture will be set to true
# useInFuture set to true also mean it will not warn if there is an issue
restriction_swift_sneak: restriction_swift_sneak:
useInFuture: true
enchantments: enchantments:
- minecraft:swift_sneak - minecraft:swift_sneak
notAffectedGroups: notAffectedGroups:

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -18,8 +18,8 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView
import org.bukkit.craftbukkit.inventory.view.CraftAnvilView import org.bukkit.craftbukkit.inventory.view.CraftAnvilView
import org.bukkit.entity.HumanEntity import org.bukkit.entity.HumanEntity
import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.InventoryView
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.view.AnvilView
import org.bukkit.persistence.PersistentDataType import org.bukkit.persistence.PersistentDataType
import org.bukkit.plugin.Plugin import org.bukkit.plugin.Plugin
import java.util.* import java.util.*
@ -121,7 +121,7 @@ class AnvilRenameDialogImpl(
} }
} }
private fun setResult(player: HumanEntity, view: AnvilView, result: String?) { private fun setResult(player: HumanEntity, view: InventoryView, result: String?) {
val defaultName = itemDefaultName(view.getItem(0)) val defaultName = itemDefaultName(view.getItem(0))
if (defaultName == result) { if (defaultName == result) {
setName(player, view, "", null) setName(player, view, "", null)
@ -129,7 +129,7 @@ class AnvilRenameDialogImpl(
} else setName(player, view, result, result) } else setName(player, view, result, result)
} }
private fun setName(player: HumanEntity, view: AnvilView, name: String?, rename: String?) { private fun setName(player: HumanEntity, view: InventoryView, name: String?, rename: String?) {
val menu = (containerField.get(view) as AnvilMenu) val menu = (containerField.get(view) as AnvilMenu)
val isSameName = menu.itemName == name val isSameName = menu.itemName == name
menu.itemName = rename menu.itemName = rename

View file

@ -2,18 +2,17 @@ package xyz.alexcrea.cuanvil.util
import io.papermc.paper.threadedregions.scheduler.ScheduledTask import io.papermc.paper.threadedregions.scheduler.ScheduledTask
import org.bukkit.entity.HumanEntity import org.bukkit.entity.HumanEntity
import org.bukkit.inventory.view.AnvilView import org.bukkit.inventory.InventoryView
import org.bukkit.plugin.Plugin import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog
import java.util.HashMap import java.util.HashMap
import java.util.UUID import java.util.UUID
@Suppress("UnstableApiUsage")
object AnvilTitleUtil { object AnvilTitleUtil {
private val runTaskMap = HashMap<UUID, ScheduledTask>() private val runTaskMap = HashMap<UUID, ScheduledTask>()
private fun actualRename(view: AnvilView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog) { private fun actualRename(view: InventoryView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog) {
runTaskMap.remove(player.uniqueId) runTaskMap.remove(player.uniqueId)
if (view.title == name) return if (view.title == name) return
@ -25,7 +24,7 @@ object AnvilTitleUtil {
// We don't want to rename instantly it is causing issue with rename text // We don't want to rename instantly it is causing issue with rename text
// especially as it can "override" current ui when it is rename ui time but rename ui also need some delay // especially as it can "override" current ui when it is rename ui time but rename ui also need some delay
fun rename(view: AnvilView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog, plugin: Plugin) { fun rename(view: InventoryView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog, plugin: Plugin) {
runTaskMap.remove(player.uniqueId)?.cancel() runTaskMap.remove(player.uniqueId)?.cancel()
val task = player.scheduler.runDelayed( val task = player.scheduler.runDelayed(

View file

@ -128,7 +128,7 @@ public class EnchantmentApi {
* @return The custom anvil enchantment of this key. null if not found. * @return The custom anvil enchantment of this key. null if not found.
*/ */
@Nullable @Nullable
public static CAEnchantment getByKey(@Nullable NamespacedKey key) { public static CAEnchantment getByKey(@NotNull NamespacedKey key) {
return CAEnchantment.getByKey(key); return CAEnchantment.getByKey(key);
} }

View file

@ -230,7 +230,7 @@ public interface CAEnchantment {
* @param key The enchantment key * @param key The enchantment key
* @return Array of enchantment. * @return Array of enchantment.
*/ */
static @Nullable CAEnchantment getByKey(@Nullable NamespacedKey key){ static @Nullable CAEnchantment getByKey(@NotNull NamespacedKey key){
return CAEnchantmentRegistry.getInstance().getByKey(key); return CAEnchantmentRegistry.getInstance().getByKey(key);
} }

View file

@ -151,7 +151,7 @@ public class CAEnchantmentRegistry {
* @return Registered enchantment. null if absent. * @return Registered enchantment. null if absent.
*/ */
@Nullable @Nullable
public CAEnchantment getByKey(@Nullable NamespacedKey key) { public CAEnchantment getByKey(@NotNull NamespacedKey key) {
return byKeyMap.get(key); return byKeyMap.get(key);
} }

View file

@ -30,11 +30,10 @@ public class UpdateHandler {
new Version(1, 11, 0), PUpdate_1_11_0::handleUpdate, new Version(1, 11, 0), PUpdate_1_11_0::handleUpdate,
new Version(1, 15, 5), PUpdate_1_15_5::handleUpdate, new Version(1, 15, 5), PUpdate_1_15_5::handleUpdate,
new Version(1, 15, 6), PUpdate_1_15_6::handleUpdate, new Version(1, 15, 6), PUpdate_1_15_6::handleUpdate,
new Version(1, 18, 0), PUpdate_1_18::handleUpdate new Version(1, 17, 7), PUpdate_1_17_7::handleUpdate
); );
private static final List<MCUpdate> mcUpdateMap = List.of( private static final List<MCUpdate> mcUpdateMap = List.of(
new Update_1_19(),
new Update_1_20_5(), new Update_1_20_5(),
new Update_1_21(), new Update_1_21(),
new Update_1_21_9(), new Update_1_21_9(),

View file

@ -1,40 +0,0 @@
package xyz.alexcrea.cuanvil.update.minecraft;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.update.Version;
import java.util.HashSet;
import java.util.Set;
import static xyz.alexcrea.cuanvil.update.UpdateUtils.addAbsentToList;
public class Update_1_19 extends MCUpdate {
public Update_1_19() {
super(new Version(1, 19));
}
@Override
protected void doUpdate() {
var tosave = new HashSet<ConfigHolder>();
updateName(tosave);
for (ConfigHolder holder : tosave) {
holder.saveToDisk(true);
}
}
public static void updateName(@NotNull Set<ConfigHolder> tosave) {
var conflict = ConfigHolder.CONFLICT_HOLDER.getConfig();
addAbsentToList(conflict, "restriction_swift_sneak.enchantments", "minecraft:swift_sneak");
addAbsentToList(conflict, "restriction_swift_sneak.notAffectedGroups", "leggings", "enchanted_book");
ConfigHolder.ITEM_GROUP_HOLDER.reload();
tosave.add(ConfigHolder.DEFAULT_CONFIG);
tosave.add(ConfigHolder.CONFLICT_HOLDER);
}
}

View file

@ -3,20 +3,19 @@ package xyz.alexcrea.cuanvil.update.plugin;
import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.update.UpdateUtils; import xyz.alexcrea.cuanvil.update.UpdateUtils;
import xyz.alexcrea.cuanvil.update.Version; import xyz.alexcrea.cuanvil.update.Version;
import xyz.alexcrea.cuanvil.update.minecraft.Update_1_19;
import xyz.alexcrea.cuanvil.update.minecraft.Update_1_20_5; import xyz.alexcrea.cuanvil.update.minecraft.Update_1_20_5;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Set; import java.util.Set;
public class PUpdate_1_18 { public class PUpdate_1_17_7 {
public static void handleUpdate(@Nonnull Set<ConfigHolder> toSave) { public static void handleUpdate(@Nonnull Set<ConfigHolder> toSave) {
// fix only needed for 1.20.5 and above
Version current = UpdateUtils.currentMinecraftVersion(); Version current = UpdateUtils.currentMinecraftVersion();
if (new Version(1, 19, 0).greaterThan(current)) return;
Update_1_19.updateName(toSave);
if (new Version(1, 20, 5).greaterThan(current)) return; if (new Version(1, 20, 5).greaterThan(current)) return;
Update_1_20_5.updateName(toSave); Update_1_20_5.updateName(toSave);
} }
} }

View file

@ -1,10 +1,9 @@
package io.delilaheve.util package io.delilaheve.util
import org.bukkit.Material
import org.bukkit.Material.ENCHANTED_BOOK import org.bukkit.Material.ENCHANTED_BOOK
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.Damageable import org.bukkit.inventory.meta.Damageable
import xyz.alexcrea.cuanvil.update.UpdateUtils import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.util.MaterialUtil.customType import xyz.alexcrea.cuanvil.util.MaterialUtil.customType
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.max import kotlin.math.max
@ -20,13 +19,6 @@ object ItemUtil {
*/ */
fun ItemStack.isEnchantedBook() = type == ENCHANTED_BOOK fun ItemStack.isEnchantedBook() = type == ENCHANTED_BOOK
private fun maxDamage(type: Material, damageable: Damageable): Int {
val ver = UpdateUtils.currentMinecraftVersion()
if(ver.major <= 1 && ver.minor <= 20 && ver.patch < 5) return type.maxDurability.toInt()
return if(damageable.hasMaxDamage()) damageable.maxDamage else type.maxDurability.toInt()
}
/** /**
* Set this [ItemStack]s durability from a combination of the * Set this [ItemStack]s durability from a combination of the
* [first] and [second] item's durability values * [first] and [second] item's durability values
@ -36,23 +28,24 @@ object ItemUtil {
first: ItemStack, first: ItemStack,
second: ItemStack second: ItemStack
): Boolean { ): Boolean {
val meta = itemMeta (itemMeta as? Damageable)?.let {
if(meta !is Damageable) return false val durability = type.maxDurability.toInt()
val firstDamage = (first.itemMeta as? Damageable)?.damage ?: 0
if (firstDamage == 0) return false
val maxDamage = maxDamage(type, meta) val firstDurability = durability - firstDamage
val damage = (first.itemMeta as? Damageable)?.damage ?: 0
if (damage == 0) return false
val firstDurability = maxDamage - damage
val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0 val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0
val secondDurability = maxDamage - secondDamage val secondDurability = durability - secondDamage
val combinedDurability = firstDurability + secondDurability val combinedDurability = firstDurability + secondDurability
val newDurability = min(combinedDurability, maxDamage) val newDurability = min(combinedDurability, durability)
val maxDamage = if(it.hasMaxDamage()) it.maxDamage else Int.MAX_VALUE
meta.damage = min(maxDamage - newDurability, maxDamage) it.damage = min(durability - newDurability, maxDamage)
this.itemMeta = meta itemMeta = it
return true return true
} }
return false
}
fun ItemStack.unitRepair( fun ItemStack.unitRepair(
unitAmount: Int, unitAmount: Int,

View file

@ -129,9 +129,9 @@ class DiagnosticExecutor : CASubCommand {
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("§7Click to copy"))
sender.spigot().sendMessage(message) sender.spigot().sendMessage(message);
} else { } else {
sender.sendMessage(stb.toString()) sender.sendMessage(stb.toString());
} }
return true return true
@ -266,8 +266,8 @@ class DiagnosticExecutor : CASubCommand {
try { try {
val fakeInv = Bukkit.createInventory(player, InventoryType.ANVIL) val fakeInv = Bukkit.createInventory(player, InventoryType.ANVIL)
invView = player.openInventory(fakeInv)!! as AnvilView invView = player.openInventory(fakeInv)!! as AnvilView
event = DependencyManager.createFakeEvent(invView, result) event = PrepareAnvilEvent(invView, result)
} catch (_: Throwable) { } catch (e: Throwable) {
// Help // Help
val menuTypeClazz = Class.forName("org.bukkit.inventory.MenuType") val menuTypeClazz = Class.forName("org.bukkit.inventory.MenuType")
val anvilTypeField = menuTypeClazz.getField("ANVIL") val anvilTypeField = menuTypeClazz.getField("ANVIL")

View file

@ -2,14 +2,10 @@ package xyz.alexcrea.cuanvil.command
import io.delilaheve.CustomAnvil import io.delilaheve.CustomAnvil
import io.delilaheve.util.ConfigOptions import io.delilaheve.util.ConfigOptions
import io.delilaheve.util.ItemUtil.isEnchantedBook
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.command.Command import org.bukkit.command.Command
import org.bukkit.command.CommandSender 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.util.MaterialUtil.isAir import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
class EnchantExecutor : CASubCommand { class EnchantExecutor : CASubCommand {
@ -41,18 +37,22 @@ class EnchantExecutor : CASubCommand {
sender.sendMessage("Missing enchantment parameter") sender.sendMessage("Missing enchantment parameter")
return true return true
} }
1 -> {
sender.sendMessage("Missing level parameter")
return true
}
} }
val enchant = firstEnchantment(args[0]) val enchants = EnchantmentApi.getByName(args[0].lowercase())
if (enchant == null) { if (enchants.isEmpty()) {
sender.sendMessage("Enchantment not found: ${args[0]}") sender.sendMessage("Enchantment not found: ${args[0]}")
return true return true
} }
val level = if (args.size > 1) val enchant = enchants.iterator().next()
args[1].toIntOrNull()?.coerceIn(0, ConfigOptions.ENCHANT_LIMIT)
else 1
val level = args[1].toIntOrNull()?.coerceIn(0, ConfigOptions.ENCHANT_LIMIT)
if (level == null) { if (level == null) {
sender.sendMessage("Invalid number: ${args[1]}") sender.sendMessage("Invalid number: ${args[1]}")
return true return true
@ -66,15 +66,8 @@ class EnchantExecutor : CASubCommand {
if (level == 0) { if (level == 0) {
enchant.removeFrom(inHand) enchant.removeFrom(inHand)
if (inHand.isEnchantedBook() && EnchantmentApi.getEnchantments(inHand).isEmpty())
inHand.type = Material.BOOK
sender.sendMessage("${enchant.prettyName} removed") sender.sendMessage("${enchant.prettyName} removed")
} else { } else {
if (Material.BOOK == inHand.type)
inHand.type = Material.ENCHANTED_BOOK
enchant.addEnchantmentUnsafe(inHand, level) enchant.addEnchantmentUnsafe(inHand, level)
sender.sendMessage("${enchant.prettyName} set to level $level") sender.sendMessage("${enchant.prettyName} set to level $level")
} }
@ -99,8 +92,10 @@ class EnchantExecutor : CASubCommand {
sender: HumanEntity, sender: HumanEntity,
name: String name: String
): Collection<String> { ): Collection<String> {
val enchant = firstEnchantment(name) ?: return listOf() val enchants = EnchantmentApi.getByName(name.lowercase())
if (enchants.isEmpty()) return listOf()
val enchant = enchants.iterator().next()
val limit = ConfigOptions.enchantLimit(enchant) val limit = ConfigOptions.enchantLimit(enchant)
val result = mutableListOf<String>() val result = mutableListOf<String>()
@ -115,12 +110,4 @@ class EnchantExecutor : CASubCommand {
return result return result
} }
private fun firstEnchantment(name: String): CAEnchantment? {
val enchants = EnchantmentApi.getByName(name.lowercase())
if (!enchants.isEmpty())
return enchants.iterator().next()
return EnchantmentApi.getByKey(NamespacedKey.fromString(name))
}
} }

View file

@ -30,7 +30,6 @@ 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.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.reflect.Constructor
import java.util.logging.Level import java.util.logging.Level
@Suppress("UnstableApiUsage") @Suppress("UnstableApiUsage")
@ -121,10 +120,6 @@ object DependencyManager {
genericDependencies.add(compatibility) genericDependencies.add(compatibility)
} }
if (pluginManager.isPluginEnabled("EnchantedBook")) {
genericDependencies.add(EnchantedBookDependency(pluginManager.getPlugin("EnchantedBook")!!))
}
for (dependency in genericDependencies) for (dependency in genericDependencies)
dependency.redirectListeners() dependency.redirectListeners()
@ -330,12 +325,4 @@ object DependencyManager {
enchantmentSquaredCompatibility?.updateLore(item) enchantmentSquaredCompatibility?.updateLore(item)
} }
private val prepareAnvilConstructor =
PrepareAnvilEvent::class.java.constructors.first() as Constructor<PrepareAnvilEvent>
fun createFakeEvent(view: AnvilView, result: ItemStack?): PrepareAnvilEvent {
return prepareAnvilConstructor.newInstance(view, result)
}
} }

View file

@ -1,11 +1,10 @@
package xyz.alexcrea.cuanvil.dependency.gui package xyz.alexcrea.cuanvil.dependency.gui
import org.bukkit.inventory.view.AnvilView import org.bukkit.inventory.InventoryView
import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil
import java.lang.reflect.Method import java.lang.reflect.Method
@Suppress("UnstableApiUsage")
class GenericExternGuiTester { class GenericExternGuiTester {
companion object { companion object {
@ -22,7 +21,7 @@ class GenericExternGuiTester {
var testedClass: String? = null var testedClass: String? = null
lateinit var getHandleMethod: Method lateinit var getHandleMethod: Method
private fun getContainerClass(view: AnvilView): Class<Any>? { private fun getContainerClass(view: InventoryView): Class<Any>? {
if(!testedClass.contentEquals(view.javaClass.name)) if(!testedClass.contentEquals(view.javaClass.name))
return null return null
@ -65,7 +64,7 @@ class GenericExternGuiTester {
} }
// Try if were in another plugin anvil inventory // Try if were in another plugin anvil inventory
fun testIfGui(view: AnvilView): Boolean { fun testIfGui(view: InventoryView): Boolean {
// In case we are in a test environment // In case we are in a test environment
if(isInTest()) return false if(isInTest()) return false

View file

@ -1,34 +0,0 @@
package xyz.alexcrea.cuanvil.dependency.plugins
import org.bukkit.event.Event
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.inventory.view.AnvilView
import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
@Suppress("UnstableApiUsage")
class EnchantedBookDependency(plugin: Plugin) : GenericPluginDependency(plugin) {
override fun testAnvilResult(event: InventoryClickEvent): Boolean {
val view = event.view as? AnvilView ?: return false
val inv = event.inventory
//TODO use view here (v2)
val current = inv.getItem(ANVIL_OUTPUT_SLOT)
inv.setItem(ANVIL_OUTPUT_SLOT, null)
val fakeEvent = DependencyManager.createFakeEvent(view, null)
if (testPrepareAnvil(fakeEvent)) {
event.result = Event.Result.DEFAULT
inv.setItem(ANVIL_INPUT_LEFT, fakeEvent.result)
return true
}
inv.setItem(ANVIL_INPUT_LEFT, current)
return false
}
}

View file

@ -8,12 +8,12 @@ import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.RegisteredListener import org.bukkit.plugin.RegisteredListener
import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.api.EnchantmentApi
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResultEvent import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResultEvent
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEPreV5Enchantment import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEPreV5Enchantment
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEV5Enchantment import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEV5Enchantment
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEV5_4Enchantment import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEV5_4Enchantment
import xyz.alexcrea.cuanvil.enchant.wrapped.CALegacyEEEnchantment import xyz.alexcrea.cuanvil.enchant.wrapped.CALegacyEEEnchantment
import java.lang.reflect.Constructor
import java.lang.reflect.Method import java.lang.reflect.Method
import su.nightexpress.excellentenchants.api.EnchantRegistry as V5EnchantRegistry import su.nightexpress.excellentenchants.api.EnchantRegistry as V5EnchantRegistry
import su.nightexpress.excellentenchants.enchantment.impl.universal.CurseOfFragilityEnchant as LegacyCurseOfFragilityEnchant import su.nightexpress.excellentenchants.enchantment.impl.universal.CurseOfFragilityEnchant as LegacyCurseOfFragilityEnchant
@ -47,7 +47,7 @@ class ExcellentEnchantsDependency {
listenerVersion = value listenerVersion = value
break break
} catch (_: ClassNotFoundException) { } catch (ignored: ClassNotFoundException) {
} }
} }
@ -60,7 +60,7 @@ class ExcellentEnchantsDependency {
var isModernCurseOfFragility = true var isModernCurseOfFragility = true
try { try {
Class.forName("su.nightexpress.excellentenchants.enchantment.universal.CurseOfFragilityEnchant") Class.forName("su.nightexpress.excellentenchants.enchantment.universal.CurseOfFragilityEnchant")
} catch (_: ClassNotFoundException) { } catch (ignored: ClassNotFoundException) {
isModernCurseOfFragility = false isModernCurseOfFragility = false
} }
@ -118,6 +118,8 @@ class ExcellentEnchantsDependency {
private lateinit var handleRechargeMethod: Method private lateinit var handleRechargeMethod: Method
private lateinit var handleCombineMethod: Method private lateinit var handleCombineMethod: Method
private val prepareAnvilConstructor = PrepareAnvilEvent::class.java.constructors.first() as Constructor<PrepareAnvilEvent>
fun redirectListeners() { fun redirectListeners() {
val toUnregister = ArrayList<RegisteredListener>() val toUnregister = ArrayList<RegisteredListener>()
// get required PrepareAnvilEvent listener // get required PrepareAnvilEvent listener
@ -225,7 +227,7 @@ class ExcellentEnchantsDependency {
val first: ItemStack = treatInput(event.leftItem) val first: ItemStack = treatInput(event.leftItem)
val second: ItemStack = treatInput(event.rightItem) val second: ItemStack = treatInput(event.rightItem)
val fakeEvent = DependencyManager.createFakeEvent(event.view, result) val fakeEvent = prepareAnvilConstructor.newInstance(event.view, result)
handleCombineMethod.invoke(this.usedAnvilListener, fakeEvent, first, second, result) handleCombineMethod.invoke(this.usedAnvilListener, fakeEvent, first, second, result)

View file

@ -3,6 +3,7 @@ package xyz.alexcrea.cuanvil.group
import io.delilaheve.CustomAnvil import io.delilaheve.CustomAnvil
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.ConfigurationSection
import org.bukkit.enchantments.Enchantment
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.api.EnchantmentApi
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment
@ -31,6 +32,10 @@ class EnchantConflictManager {
// Path for the maximum number of enchantment before validating the conflict // Path for the maximum number of enchantment before validating the conflict
const val ENCH_MAX_PATH = "maxEnchantmentBeforeConflict" const val ENCH_MAX_PATH = "maxEnchantmentBeforeConflict"
// Path for a flag: if the enchantment will be used in the last supported version
// TODO maybe replace this system by a list of "future" enchantment.
private const val FUTURE_USE_PATH = "useInFuture"
// Default name for a joining group // Default name for a joining group
const val DEFAULT_GROUP_NAME = "joinedGroup" const val DEFAULT_GROUP_NAME = "joinedGroup"
} }
@ -95,6 +100,8 @@ class EnchantConflictManager {
itemManager: ItemGroupManager, itemManager: ItemGroupManager,
conflictName: String conflictName: String
): EnchantConflictGroup { ): EnchantConflictGroup {
// Is it planed for the future
val futureUse = section.getBoolean(FUTURE_USE_PATH, false)
// Create conflict // Create conflict
val conflict = createConflictObject(section, itemManager, conflictName) val conflict = createConflictObject(section, itemManager, conflictName)
// Read and add enchantment to conflict // Read and add enchantment to conflict
@ -102,14 +109,18 @@ class EnchantConflictManager {
for (enchantName in enchantList) { for (enchantName in enchantList) {
val enchants = getEnchantByIdentifier(enchantName) val enchants = getEnchantByIdentifier(enchantName)
if (enchants.isEmpty()) { if (enchants.isEmpty()) {
if (!futureUse) { //TODO future use will be deprecated once the new update system is finished
CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName") CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName")
}
continue continue
} }
conflict.addEnchantments(enchants) conflict.addEnchantments(enchants)
} }
if (conflict.getEnchants().isEmpty()) { if (conflict.getEnchants().isEmpty()) {
if (!futureUse) { //TODO future use will be deprecated once the new update system is finished
CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything") CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything")
} }
}
val conflictsAfterLevel = section.getConfigurationSection(CONFLICT_AFTER_LEVEL_LIST_PATH) val conflictsAfterLevel = section.getConfigurationSection(CONFLICT_AFTER_LEVEL_LIST_PATH)
val conflictsAfterMap = conflict.getConflictAfters() val conflictsAfterMap = conflict.getConflictAfters()

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit most of these config. # It is recommended that you use /configanvil to edit most of these config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #
@ -160,6 +160,10 @@ restriction_sweeping_edge:
enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ] enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ]
notAffectedGroups: [ enchanted_book, swords ] notAffectedGroups: [ enchanted_book, swords ]
restriction_swift_sneak:
enchantments: [ minecraft:swift_sneak ]
notAffectedGroups: [ enchanted_book, leggings ]
restriction_thorns: restriction_thorns:
enchantments: [ minecraft:thorns ] enchantments: [ minecraft:thorns ]
notAffectedGroups: [ enchanted_book, armors ] notAffectedGroups: [ enchanted_book, armors ]

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #

View file

@ -72,4 +72,3 @@ softdepend:
- ExcellentEnchants - ExcellentEnchants
- HavenBags - HavenBags
- SuperEnchants - SuperEnchants
- EnchantedBook

View file

@ -1,5 +1,5 @@
# #
# It is recommended that you use /ca config to edit theses config. # It is recommended that you use /configanvil to edit theses config.
# You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes ! # You can still manually edit here if you like to. but if you do, don't forget to /ca reload after you changes !
# #