add beheading enchant

This commit is contained in:
2024-10-26 11:30:03 +02:00
parent 86ccd3a410
commit 776359f355
4 changed files with 243 additions and 8 deletions
@@ -1,13 +1,7 @@
package me.youhavetrouble.enchantio;
import me.youhavetrouble.enchantio.enchants.ExecutionerEnchant;
import me.youhavetrouble.enchantio.enchants.ReplantingEnchant;
import me.youhavetrouble.enchantio.enchants.SoulboundEnchant;
import me.youhavetrouble.enchantio.enchants.TelepathyEnchant;
import me.youhavetrouble.enchantio.listeners.ExecutionerListener;
import me.youhavetrouble.enchantio.listeners.ReplantingListener;
import me.youhavetrouble.enchantio.listeners.SoulboundListener;
import me.youhavetrouble.enchantio.listeners.TelepathyListener;
import me.youhavetrouble.enchantio.enchants.*;
import me.youhavetrouble.enchantio.listeners.*;
import org.bukkit.plugin.java.JavaPlugin;
public final class Enchantio extends JavaPlugin {
@@ -26,6 +20,9 @@ public final class Enchantio extends JavaPlugin {
if (EnchantioConfig.ENCHANTS.containsKey(ExecutionerEnchant.KEY)) {
getServer().getPluginManager().registerEvents(new ExecutionerListener(), this);
}
if (EnchantioConfig.ENCHANTS.containsKey(BeheadingEnchant.KEY)) {
getServer().getPluginManager().registerEvents(new BeheadingListener(), this);
}
}
@Override
@@ -166,6 +166,38 @@ public class EnchantioConfig {
ENCHANTS.put(ExecutionerEnchant.KEY, executionerEnchant);
}
ConfigurationSection beheadingSection = enchantsSection.getConfigurationSection("beheading");
if (beheadingSection == null) {
beheadingSection = enchantsSection.createSection("beheading");
}
BeheadingEnchant beheadingEnchant = new BeheadingEnchant(
getInt(beheadingSection, "anvilCost", 1),
getInt(beheadingSection, "weight", 10),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(beheadingSection, "minimumCost.base", 40),
getInt(beheadingSection, "minimumCost.additionalPerLevel", 3)
),
EnchantmentRegistryEntry.EnchantmentCost.of(
getInt(beheadingSection, "maximumCost.base", 65),
getInt(beheadingSection, "maximumCost.additionalPerLevel", 1)
),
getBoolean(beheadingSection, "canGetFromEnchantingTable", true),
getTagsFromList(getStringList(
beheadingSection,
"supportedItemTags",
List.of(
"#minecraft:axes"
)
)),
getInt(beheadingSection, "maxLevel", 5),
getDouble(beheadingSection, "chanceToDropHeadPerLevel", 0.02)
);
if (getBoolean(beheadingSection, "enabled", true)) {
ENCHANTS.put(BeheadingEnchant.KEY, beheadingEnchant);
}
configuration.save(configFile);
}
@@ -0,0 +1,105 @@
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 BeheadingEnchant implements EnchantioEnchant {
public static final Key KEY = Key.key("enchantio:beheading");
private final int anvilCost, weight, maxLevel;
private final EnchantmentRegistryEntry.EnchantmentCost minimumCost;
private final EnchantmentRegistryEntry.EnchantmentCost maximumCost;
private final boolean canGetFromEnchantingTable;
private final Set<TagEntry<ItemType>> supportedItemTags;
private final double chanceToDropHeadPerLevel;
public BeheadingEnchant(
int anvilCost,
int weight,
EnchantmentRegistryEntry.EnchantmentCost minimumCost,
EnchantmentRegistryEntry.EnchantmentCost maximumCost,
boolean canGetFromEnchantingTable,
Set<TagEntry<ItemType>> supportedItemTags,
int maxLevel,
double chanceToDropHeadPerLevel
) {
this.anvilCost = anvilCost;
this.weight = weight;
this.minimumCost = minimumCost;
this.maximumCost = maximumCost;
this.canGetFromEnchantingTable = canGetFromEnchantingTable;
this.supportedItemTags = supportedItemTags;
this.maxLevel = maxLevel;
this.chanceToDropHeadPerLevel = chanceToDropHeadPerLevel;
}
@Override
public Key getKey() {
return KEY;
}
@Override
public Component getDescription() {
return Component.translatable("enchantio.enchant.beheading", "Beheading");
}
@Override
public int getAnvilCost() {
return anvilCost;
}
@Override
public int getMaxLevel() {
return maxLevel;
}
public double getChanceToDropHeadPerLevel() {
return chanceToDropHeadPerLevel;
}
@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:beheading_enchantable"));
}
@Override
public Set<TagEntry<ItemType>> getSupportedItems() {
return supportedItemTags;
}
}
@@ -0,0 +1,101 @@
package me.youhavetrouble.enchantio.listeners;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import me.youhavetrouble.enchantio.EnchantioConfig;
import me.youhavetrouble.enchantio.enchants.BeheadingEnchant;
import me.youhavetrouble.enchantio.enchants.EnchantioEnchant;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.ThreadLocalRandom;
@SuppressWarnings("UnstableApiUsage")
public class BeheadingListener implements Listener {
private final Registry<Enchantment> registry = RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT);
private final Enchantment beheading = registry.get(BeheadingEnchant.KEY);
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
public void onBeheading(EntityDeathEvent event) {
if (beheading == null) return;
EnchantioEnchant enchant = EnchantioConfig.ENCHANTS.get(BeheadingEnchant.KEY);
if (!(enchant instanceof BeheadingEnchant beheadingEnchant)) return;
if (event.getEntity().getKiller() == null) return;
if (event.getDamageSource().isIndirect()) return;
Entity killer = event.getDamageSource().getCausingEntity();
if (killer == null) return;
if (!(killer instanceof InventoryHolder inventoryHolder)) return;
if (!(inventoryHolder.getInventory() instanceof EntityEquipment entityEquipment)) return;
ItemStack weapon = entityEquipment.getItemInMainHand();
if (!weapon.containsEnchantment(beheading)) return;
double chance = weapon.getEnchantmentLevel(beheading) * beheadingEnchant.getChanceToDropHeadPerLevel();
if (ThreadLocalRandom.current().nextDouble() > chance) return;
switch (event.getEntity().getType()) {
case ZOMBIE -> {
if (listContainsItemType(event.getDrops(), Material.ZOMBIE_HEAD)) return;
event.getDrops().add(new ItemStack(org.bukkit.Material.ZOMBIE_HEAD));
}
case PIGLIN -> {
if (listContainsItemType(event.getDrops(), Material.PIGLIN_HEAD)) return;
event.getDrops().add(new ItemStack(org.bukkit.Material.PIGLIN_HEAD));
}
case WITHER_SKELETON -> {
if (listContainsItemType(event.getDrops(), Material.WITHER_SKELETON_SKULL)) return;
event.getDrops().add(new ItemStack(org.bukkit.Material.WITHER_SKELETON_SKULL));
}
case SKELETON -> {
if (listContainsItemType(event.getDrops(), Material.SKELETON_SKULL)) return;
event.getDrops().add(new ItemStack(org.bukkit.Material.SKELETON_SKULL));
}
case CREEPER -> {
if (listContainsItemType(event.getDrops(), Material.CREEPER_HEAD)) return;
event.getDrops().add(new ItemStack(org.bukkit.Material.CREEPER_HEAD));
}
case ENDER_DRAGON -> {
if (listContainsItemType(event.getDrops(), Material.DRAGON_HEAD)) return;
event.getDrops().add(new ItemStack(org.bukkit.Material.DRAGON_HEAD));
}
case PLAYER -> {
if (listContainsItemType(event.getDrops(), Material.PLAYER_HEAD)) return;
Player player = (Player) event.getEntity();
event.getDrops().add(getPlayerHead(player));
}
}
}
private boolean listContainsItemType(@NotNull Iterable<ItemStack> list, @NotNull Material type) {
for (ItemStack item : list) {
if (type.equals(item.getType())) return true;
}
return false;
}
private ItemStack getPlayerHead(@NotNull Player player) {
ItemStack head = new ItemStack(org.bukkit.Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) head.getItemMeta();
meta.setOwningPlayer(player);
head.setItemMeta(meta);
return head;
}
}