diff --git a/README.MD b/README.MD index 28c0c16..e98aa1a 100644 --- a/README.MD +++ b/README.MD @@ -60,6 +60,12 @@ When totem of undying is activated, player is teleported to their spawn point. I **Description**: When player takes damage, there is a chance that their hotbar items will be scrambled. +### Curse of Vampirism +**Translation key**: `enchantio.enchant.vampirism_curse` + +**Description**: +Player is set on fire when exposed to direct sunlight. + ## Configuration ### supportedItemTags diff --git a/src/main/java/me/youhavetrouble/enchantio/Enchantio.java b/src/main/java/me/youhavetrouble/enchantio/Enchantio.java index 1d0762b..1db51d6 100644 --- a/src/main/java/me/youhavetrouble/enchantio/Enchantio.java +++ b/src/main/java/me/youhavetrouble/enchantio/Enchantio.java @@ -44,6 +44,9 @@ public final class Enchantio extends JavaPlugin { if (EnchantioConfig.ENCHANTS.containsKey(PanicEnchant.KEY)) { getServer().getPluginManager().registerEvents(new PanicListener(), this); } + if (EnchantioConfig.ENCHANTS.containsKey(VampirismEnchant.KEY)) { + getServer().getPluginManager().registerEvents(new VampirismListener(), this); + } } @Override diff --git a/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java b/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java index 3039121..3825ab5 100644 --- a/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java +++ b/src/main/java/me/youhavetrouble/enchantio/EnchantioConfig.java @@ -366,6 +366,43 @@ public class EnchantioConfig { ENCHANTS.put(PanicEnchant.KEY, panicEnchant); } + ConfigurationSection vampirismSection = cursesSection.getConfigurationSection("vampirism"); + if (vampirismSection == null) { + vampirismSection = cursesSection.createSection("vampirism"); + } + + VampirismEnchant vampirismEnchant = new VampirismEnchant( + getInt(vampirismSection, "anvilCost", 1), + getInt(vampirismSection, "weight", 2), + EnchantmentRegistryEntry.EnchantmentCost.of( + getInt(vampirismSection, "minimumCost.base", 0), + getInt(vampirismSection, "minimumCost.additionalPerLevel", 3) + ), + EnchantmentRegistryEntry.EnchantmentCost.of( + getInt(vampirismSection, "maximumCost.base", 30), + getInt(vampirismSection, "maximumCost.additionalPerLevel", 1) + ), + getBoolean(vampirismSection, "canGetFromEnchantingTable", true), + getTagsFromList(getStringList( + vampirismSection, + "supportedItemTags", + List.of( + "#minecraft:enchantable/armor" + ) + )), + getEquipmentSlotGroups(getStringList( + vampirismSection, + "activeSlots", + List.of( + "ANY" + ) + )) + ); + + if (getBoolean(vampirismSection, "enabled", true)) { + ENCHANTS.put(VampirismEnchant.KEY, vampirismEnchant); + } + configuration.save(configFile); } diff --git a/src/main/java/me/youhavetrouble/enchantio/enchants/VampirismEnchant.java b/src/main/java/me/youhavetrouble/enchantio/enchants/VampirismEnchant.java new file mode 100644 index 0000000..3a0ddf1 --- /dev/null +++ b/src/main/java/me/youhavetrouble/enchantio/enchants/VampirismEnchant.java @@ -0,0 +1,101 @@ +package me.youhavetrouble.enchantio.enchants; + +import io.papermc.paper.registry.data.EnchantmentRegistryEntry; +import io.papermc.paper.registry.keys.tags.EnchantmentTagKeys; +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.enchantments.Enchantment; +import org.bukkit.inventory.EquipmentSlotGroup; +import org.bukkit.inventory.ItemType; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +@SuppressWarnings("UnstableApiUsage") +public class VampirismEnchant implements EnchantioEnchant { + + public static final Key KEY = Key.key("enchantio:vampirism_curse"); + + private final int anvilCost, weight; + private final EnchantmentRegistryEntry.EnchantmentCost minimumCost; + private final EnchantmentRegistryEntry.EnchantmentCost maximumCost; + private final Set> supportedItemTags; + private final Set> enchantTagKeys = new HashSet<>(); + private final Set activeSlots = new HashSet<>(); + + public VampirismEnchant( + int anvilCost, + int weight, + EnchantmentRegistryEntry.EnchantmentCost minimumCost, + EnchantmentRegistryEntry.EnchantmentCost maximumCost, + boolean canGetFromEnchantingTable, + Set> supportedItemTags, + Set activeSlots + ) { + this.anvilCost = anvilCost; + this.weight = weight; + this.minimumCost = minimumCost; + this.maximumCost = maximumCost; + this.supportedItemTags = supportedItemTags; + this.activeSlots.addAll(activeSlots); + if (canGetFromEnchantingTable) { + enchantTagKeys.add(EnchantmentTagKeys.IN_ENCHANTING_TABLE); + } + enchantTagKeys.add(EnchantmentTagKeys.CURSE); + } + + @Override + public @NotNull Key getKey() { + return KEY; + } + + @Override + public @NotNull Component getDescription() { + return Component.translatable("enchantio.enchant.vampirism_curse", "Curse of Vampirism"); + } + + @Override + public int getAnvilCost() { + return anvilCost; + } + + @Override + public int getMaxLevel() { + return 1; + } + + @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 activeSlots; + } + + @Override + public @NotNull Set> getSupportedItems() { + return supportedItemTags; + } + + @Override + public @NotNull Set> getEnchantTagKeys() { + return Collections.unmodifiableSet(enchantTagKeys); + } + +} diff --git a/src/main/java/me/youhavetrouble/enchantio/listeners/VampirismListener.java b/src/main/java/me/youhavetrouble/enchantio/listeners/VampirismListener.java new file mode 100644 index 0000000..cc53dc7 --- /dev/null +++ b/src/main/java/me/youhavetrouble/enchantio/listeners/VampirismListener.java @@ -0,0 +1,43 @@ +package me.youhavetrouble.enchantio.listeners; + +import io.papermc.paper.registry.RegistryAccess; +import io.papermc.paper.registry.RegistryKey; +import me.youhavetrouble.enchantio.Enchantio; +import me.youhavetrouble.enchantio.enchants.VampirismEnchant; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Registry; +import org.bukkit.block.Block; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; + +public class VampirismListener implements Listener { + + private final Registry registry = RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT); + private final Enchantment vampirism = registry.get(VampirismEnchant.KEY); + + public VampirismListener() { + if (vampirism == null) return; + Bukkit.getGlobalRegionScheduler().runAtFixedRate(Enchantio.getPlugin(Enchantio.class), (task) -> { + for (Player player : Bukkit.getOnlinePlayers()) { + boolean hasVampirism = Enchantio.getSumOfEnchantLevels(player.getEquipment(), vampirism) != 0; + if (!hasVampirism) return; + Location abovePlayer = player.getLocation().add(0, player.getEyeHeight() + 0.5, 0); + Block block = player.getWorld().getBlockAt(abovePlayer); + byte light = block.getLightFromSky(); + if (light < 15) return; + int fireTicks = player.getFireTicks(); + + // Prefent fire animation from disappearing on the client + if (player.getFireTicks() < 20) { + fireTicks = 25; + } + + player.setFireTicks(Math.max(fireTicks, player.getMaxFireTicks())); + } + + }, 1, 20); + } + +}