add smelting enchantment

This commit is contained in:
2024-10-27 21:44:35 +01:00
parent b199b31cd7
commit 32bef26538
4 changed files with 195 additions and 0 deletions
@@ -23,6 +23,9 @@ public final class Enchantio extends JavaPlugin {
if (EnchantioConfig.ENCHANTS.containsKey(BeheadingEnchant.KEY)) {
getServer().getPluginManager().registerEvents(new BeheadingListener(), this);
}
if (EnchantioConfig.ENCHANTS.containsKey(SmeltingEnchant.KEY)) {
getServer().getPluginManager().registerEvents(new SmeltingListener(), this);
}
}
@Override
@@ -198,6 +198,36 @@ public class EnchantioConfig {
ENCHANTS.put(BeheadingEnchant.KEY, beheadingEnchant);
}
ConfigurationSection smeltingSection = enchantsSection.getConfigurationSection("smelting");
if (smeltingSection == null) {
smeltingSection = enchantsSection.createSection("smelting");
}
SmeltingEnchant smeltingEnchant = new SmeltingEnchant(
getInt(smeltingSection, "anvilCost", 1),
getInt(smeltingSection, "weight", 10),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(smeltingSection, "minimumCost.base", 40),
getInt(smeltingSection, "minimumCost.additionalPerLevel", 3)
),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(smeltingSection, "maximumCost.base", 65),
getInt(smeltingSection, "maximumCost.additionalPerLevel", 1)
),
getBoolean(smeltingSection, "canGetFromEnchantingTable", true),
getTagsFromList(getStringList(
smeltingSection,
"supportedItemTags",
List.of(
"#minecraft:enchantable/mining"
)
))
);
if (getBoolean(smeltingSection, "enabled", true)) {
ENCHANTS.put(SmeltingEnchant.KEY, smeltingEnchant);
}
configuration.save(configFile);
}
@@ -0,0 +1,96 @@
package me.youhavetrouble.enchantio.enchants;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
import io.papermc.paper.registry.tag.TagKey;
import io.papermc.paper.tag.TagEntry;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component;
import org.bukkit.inventory.EquipmentSlotGroup;
import org.bukkit.inventory.ItemType;
import java.util.Set;
@SuppressWarnings("UnstableApiUsage")
public class SmeltingEnchant implements EnchantioEnchant {
public static final Key KEY = Key.key("enchantio:smelting");
private final int anvilCost, weight;
private final EnchantmentRegistryEntry.EnchantmentCost minimumCost;
private final EnchantmentRegistryEntry.EnchantmentCost maximumCost;
private final boolean canGetFromEnchantingTable;
private final Set<TagEntry<ItemType>> supportedItemTags;
public SmeltingEnchant(
int anvilCost,
int weight,
EnchantmentRegistryEntry.EnchantmentCost minimumCost,
EnchantmentRegistryEntry.EnchantmentCost maximumCost,
boolean canGetFromEnchantingTable,
Set<TagEntry<ItemType>> supportedItemTags
) {
this.anvilCost = anvilCost;
this.weight = weight;
this.minimumCost = minimumCost;
this.maximumCost = maximumCost;
this.canGetFromEnchantingTable = canGetFromEnchantingTable;
this.supportedItemTags = supportedItemTags;
}
@Override
public Key getKey() {
return KEY;
}
@Override
public Component getDescription() {
return Component.translatable("enchantio.enchant.smelting", "Smelting");
}
@Override
public int getAnvilCost() {
return anvilCost;
}
@Override
public int getMaxLevel() {
return 1;
}
@Override
public int getWeight() {
return weight;
}
@Override
public EnchantmentRegistryEntry.EnchantmentCost getMinimumCost() {
return minimumCost;
}
@Override
public EnchantmentRegistryEntry.EnchantmentCost getMaximumCost() {
return maximumCost;
}
@Override
public Iterable<EquipmentSlotGroup> getActiveSlots() {
return Set.of(EquipmentSlotGroup.ANY);
}
@Override
public boolean canGetFromEnchantingTable() {
return canGetFromEnchantingTable;
}
@Override
public TagKey<ItemType> getTagForSupportedItems() {
return TagKey.create(RegistryKey.ITEM, Key.key("enchantio:smelting_enchantable"));
}
@Override
public Set<TagEntry<ItemType>> getSupportedItems() {
return supportedItemTags;
}
}
@@ -0,0 +1,66 @@
package me.youhavetrouble.enchantio.listeners;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import me.youhavetrouble.enchantio.enchants.SmeltingEnchant;
import org.bukkit.Bukkit;
import org.bukkit.Registry;
import org.bukkit.block.BlockState;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Item;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.inventory.BlockInventoryHolder;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class SmeltingListener implements Listener {
private final Registry<Enchantment> registry = RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT);
private final Enchantment smelting = registry.get(SmeltingEnchant.KEY);
private final Map<ItemStack, ItemStack> smeltingCache = new HashMap<>();
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
public void onSmeltingEnchantSmelt(BlockDropItemEvent event) {
if (smelting == null) return;
ItemStack tool = event.getPlayer().getInventory().getItemInMainHand();
if (!tool.containsEnchantment(smelting)) return;
BlockState block = event.getBlockState();
if (block instanceof BlockInventoryHolder) return;
for (Item item : event.getItems()) {
int amount = item.getItemStack().getAmount();
ItemStack smeltedItem = getSmeltedItem(item.getItemStack());
if (smeltedItem == null) continue;
item.setItemStack(smeltedItem.asQuantity(amount));
}
}
/**
* Gets the smelted item from the given item stack. If item stack is not smeltable, returns the item stack itself.
*/
private ItemStack getSmeltedItem(@NotNull ItemStack itemStack) {
ItemStack singleItem = itemStack.asOne();
if (smeltingCache.containsKey(singleItem)) return smeltingCache.get(singleItem);
for (@NotNull Iterator<Recipe> it = Bukkit.recipeIterator(); it.hasNext(); ) {
Recipe recipe = it.next();
if (!(recipe instanceof FurnaceRecipe furnaceRecipe)) continue;
if (!furnaceRecipe.getInputChoice().test(singleItem)) continue;
ItemStack result = furnaceRecipe.getResult();
smeltingCache.put(singleItem, result);
return result;
}
return null;
}
}