From b573192990e15523f780eb62431c7068813172a1 Mon Sep 17 00:00:00 2001 From: YouHaveTrouble Date: Fri, 25 Sep 2026 19:43:45 +0200 Subject: [PATCH] some work on tunnelling enchant --- .../enchantio/EnchantioConfig.java | 28 ++++ .../enchantio/enchants/TunnellingEnchant.java | 147 ++++++++++++++++++ .../listeners/TunnellingListener.java | 63 ++++++++ 3 files changed, 238 insertions(+) create mode 100644 src/main/java/me/youhavetrouble/enchantio/enchants/TunnellingEnchant.java create mode 100644 src/main/java/me/youhavetrouble/enchantio/listeners/TunnellingListener.java diff --git a/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java b/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java index 90e1f62..f04e572 100644 --- a/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java +++ b/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java @@ -2,12 +2,14 @@ package me.youhavetrouble.enchantio; import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.TypedKey; +import io.papermc.paper.registry.keys.tags.BlockTypeTagKeys; import io.papermc.paper.registry.keys.tags.EnchantmentTagKeys; import io.papermc.paper.registry.keys.tags.ItemTypeTagKeys; import io.papermc.paper.registry.tag.TagKey; import io.papermc.paper.tag.TagEntry; import me.youhavetrouble.enchantio.enchants.*; import net.kyori.adventure.key.Key; +import org.bukkit.block.BlockType; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -210,6 +212,32 @@ public class EnchantioConfig { return enchantTagKeys; } + public static Set> getBlockTagKeysFromList(@NotNull List tags) { + Set> blockTagKeys = new HashSet<>(); + for (String blockTag : tags) { + if (blockTag == null) continue; + if (blockTag.startsWith("#")) { + blockTag = blockTag.substring(1); + try { + Key key = Key.key(blockTag); + TagKey tagKey = BlockTypeTagKeys.create(key); + TagEntry tagEntry = TagEntry.tagEntry(tagKey); + blockTagKeys.add(tagEntry); + } catch (IllegalArgumentException ignored) { + } + continue; + } + try { + Key key = Key.key(blockTag); + TagKey tagKey = BlockTypeTagKeys.create(key); + TagEntry tagEntry = TagEntry.tagEntry(tagKey); + blockTagKeys.add(tagEntry); + } catch (IllegalArgumentException | NullPointerException ignored) { + } + } + return blockTagKeys; + } + public static ConfigurationSection getConfigSection(ConfigurationSection section, String key) { ConfigurationSection value = section.getConfigurationSection(key); if (value == null) { diff --git a/src/main/java/me/youhavetrouble/enchantio/enchants/TunnellingEnchant.java b/src/main/java/me/youhavetrouble/enchantio/enchants/TunnellingEnchant.java new file mode 100644 index 0000000..2e233a6 --- /dev/null +++ b/src/main/java/me/youhavetrouble/enchantio/enchants/TunnellingEnchant.java @@ -0,0 +1,147 @@ +package me.youhavetrouble.enchantio.enchants; + +import io.papermc.paper.registry.data.EnchantmentRegistryEntry; +import io.papermc.paper.registry.tag.TagKey; +import io.papermc.paper.tag.TagEntry; +import me.youhavetrouble.enchantio.EnchantioConfig; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import org.bukkit.block.BlockType; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.EquipmentSlotGroup; +import org.bukkit.inventory.ItemType; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +import static me.youhavetrouble.enchantio.EnchantioConfig.ENCHANTS; + +@SuppressWarnings("UnstableApiUsage") +public class TunnellingEnchant implements EnchantioEnchant { + + public static final Key KEY = Key.key("enchantio:tunnelling"); + + private final int anvilCost, weight, maxLevel; + private final EnchantmentRegistryEntry.EnchantmentCost minimumCost; + private final EnchantmentRegistryEntry.EnchantmentCost maximumCost; + private final Set> supportedItemTags = new HashSet<>(); + private final Set> enchantTagKeys = new HashSet<>(); + private final Set> blockTagKeys = new HashSet<>(); + + public TunnellingEnchant( + int anvilCost, + int weight, + EnchantmentRegistryEntry.EnchantmentCost minimumCost, + EnchantmentRegistryEntry.EnchantmentCost maximumCost, + Collection> enchantTagKeys, + Collection> supportedItemTags, + Collection> supportedBlockTags, + int maxLevel + ) { + this.anvilCost = anvilCost; + this.weight = weight; + this.minimumCost = minimumCost; + this.maximumCost = maximumCost; + this.maxLevel = maxLevel; + this.supportedItemTags.addAll(supportedItemTags); + this.enchantTagKeys.addAll(enchantTagKeys); + this.blockTagKeys.addAll(supportedBlockTags); + } + + @Override + public @NotNull Key getKey() { + return KEY; + } + + @Override + public @NotNull Component getDescription() { + return Component.translatable("enchantio.enchant.tunnelling", "Tunnelling"); + } + + @Override + public int getAnvilCost() { + return anvilCost; + } + + @Override + public int getMaxLevel() { + return maxLevel; + } + + @Override + public int getWeight() { + return weight; + } + + @Override + public EnchantmentRegistryEntry.@NotNull EnchantmentCost getMinimumCost() { + return minimumCost; + } + + @Override + public EnchantmentRegistryEntry.@NotNull EnchantmentCost getMaximumCost() { + return maximumCost; + } + + @Override + public @NotNull Iterable getActiveSlots() { + return Set.of(EquipmentSlotGroup.MAINHAND); + } + + @Override + public @NotNull Set> getSupportedItems() { + return supportedItemTags; + } + + @Override + public @NotNull Set> getEnchantTagKeys() { + return Collections.unmodifiableSet(enchantTagKeys); + } + + + public static TunnellingEnchant create(ConfigurationSection configurationSection) { + TunnellingEnchant tunnellingEnchant = new TunnellingEnchant( + EnchantioConfig.getInt(configurationSection, "anvilCost", 1), + EnchantioConfig.getInt(configurationSection, "weight", 10), + EnchantmentRegistryEntry.EnchantmentCost.of( + EnchantioConfig.getInt(configurationSection, "minimumCost.base", 40), + EnchantioConfig.getInt(configurationSection, "minimumCost.additionalPerLevel", 3) + ), + EnchantmentRegistryEntry.EnchantmentCost.of( + EnchantioConfig.getInt(configurationSection, "maximumCost.base", 65), + EnchantioConfig.getInt(configurationSection, "maximumCost.additionalPerLevel", 1) + ), + EnchantioConfig.getEnchantmentTagKeysFromList(EnchantioConfig.getStringList( + configurationSection, + "enchantmentTags", + List.of("#in_enchanting_table") + )), + EnchantioConfig.getItemTagEntriesFromList(EnchantioConfig.getStringList( + configurationSection, + "supportedItemTags", + List.of( + "#minecraft:enchantable/mining" + ) + )), + EnchantioConfig.getBlockTagKeysFromList(EnchantioConfig.getStringList( + configurationSection, + "mineableBlockTags", + List.of( + "#minecraft:base_stone_overworld", + "#minecraft:base_stone_nether", + "#minecraft:ores", + "minecraft:end_stone" + ) + )), + EnchantioConfig.getInt(configurationSection, "maxLevel", 1) + ); + + if (EnchantioConfig.getBoolean(configurationSection, "enabled", true)) { + ENCHANTS.put(TunnellingEnchant.KEY, tunnellingEnchant); + } + + return tunnellingEnchant; + } + +} diff --git a/src/main/java/me/youhavetrouble/enchantio/listeners/TunnellingListener.java b/src/main/java/me/youhavetrouble/enchantio/listeners/TunnellingListener.java new file mode 100644 index 0000000..fea796e --- /dev/null +++ b/src/main/java/me/youhavetrouble/enchantio/listeners/TunnellingListener.java @@ -0,0 +1,63 @@ +package me.youhavetrouble.enchantio.listeners; + +import io.papermc.paper.registry.RegistryAccess; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.keys.tags.BlockTypeTagKeys; +import me.youhavetrouble.enchantio.EnchantioConfig; +import me.youhavetrouble.enchantio.enchants.EnchantioEnchant; +import me.youhavetrouble.enchantio.enchants.TunnellingEnchant; +import org.bukkit.GameMode; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; +import org.bukkit.block.Block; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; + +@SuppressWarnings("UnstableApiUsage") +public class TunnellingListener implements Listener { + + private final Enchantment tunnelling = RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT).get(TunnellingEnchant.KEY); + private final NamespacedKey tunnellingKey = new NamespacedKey("enchantio", "tunnelling"); + private final NamespacedKey tunnellingBlockFaceKey = new NamespacedKey("enchantio", "tunellingblockface"); + + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onTunnelBlockSideCheck(PlayerInteractEvent event) { + if (tunnelling == null) return; + if (event.getHand() != EquipmentSlot.OFF_HAND) return; + if (event.getAction() != Action.LEFT_CLICK_BLOCK) return; + Player player = event.getPlayer(); + if (player.isSneaking() || GameMode.CREATIVE.equals(player.getGameMode())) return; + ItemStack item = event.getItem(); + if (item == null) return; + if (!item.containsEnchantment(tunnelling)) return; + event.getPlayer().getPersistentDataContainer().set(tunnellingBlockFaceKey, PersistentDataType.STRING, event.getBlockFace().toString()); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onTunnelBlockBreak(BlockBreakEvent event) { + if (tunnelling == null) return; + Player player = event.getPlayer(); + if (GameMode.CREATIVE.equals(player.getGameMode())) return; + EnchantioEnchant enchant = EnchantioConfig.ENCHANTS.get(TunnellingEnchant.KEY); + if (!(enchant instanceof TunnellingEnchant tunnellingEnchant)) return; + ItemStack item = event.getPlayer().getInventory().getItemInMainHand(); + if (!item.containsEnchantment(tunnelling)) return; + Block block = event.getBlock(); + // TODO register a block tag and flatten it to check the block against it + Registry.BLOCK.getTagValues(BlockTypeTagKeys.create(tunnellingKey)).contains(block.getType().asBlockType()); + + + + } + +}