summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2025-10-19 04:03:10 -0400
committerCarson Fleming <cflems@cflems.net>2025-10-19 04:03:10 -0400
commita3d2a1ab030a3c97dd4eb705dac8b880bcc7d8f5 (patch)
treea2cffdd33511f9f10524b8b1cdc7ed5103074efd /src/main
downloadpenguin-dust-a3d2a1ab030a3c97dd4eb705dac8b880bcc7d8f5.tar.gz
hell yea this shit works
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/PenguinDust.java20
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/Spell.java22
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/SpellExecutor.java8
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/exceptions/DustException.java7
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/exceptions/SpellException.java7
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/listener/CraftingListener.java111
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/listener/DamageListener.java31
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/listener/ItemUseListener.java28
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/listener/PlayerXPListener.java21
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/spells/Fireball.java18
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/spells/Lightning.java48
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/utils/DustUtils.java44
-rw-r--r--src/main/java/net/cflems/mc/penguin_dust/utils/SpellUtils.java145
-rw-r--r--src/main/resources/plugin.yml10
14 files changed, 520 insertions, 0 deletions
diff --git a/src/main/java/net/cflems/mc/penguin_dust/PenguinDust.java b/src/main/java/net/cflems/mc/penguin_dust/PenguinDust.java
new file mode 100644
index 0000000..c24aad3
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/PenguinDust.java
@@ -0,0 +1,20 @@
+package net.cflems.mc.penguin_dust;
+
+import net.cflems.mc.penguin_dust.listener.CraftingListener;
+import net.cflems.mc.penguin_dust.listener.DamageListener;
+import net.cflems.mc.penguin_dust.listener.ItemUseListener;
+import net.cflems.mc.penguin_dust.listener.PlayerXPListener;
+
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public final class PenguinDust extends JavaPlugin {
+ @Override
+ public void onEnable() {
+ PluginManager pluginManager = getServer().getPluginManager();
+ pluginManager.registerEvents(new PlayerXPListener(), this);
+ pluginManager.registerEvents(new CraftingListener(), this);
+ pluginManager.registerEvents(new ItemUseListener(), this);
+ pluginManager.registerEvents(new DamageListener(), this);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/Spell.java b/src/main/java/net/cflems/mc/penguin_dust/Spell.java
new file mode 100644
index 0000000..5f493c5
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/Spell.java
@@ -0,0 +1,22 @@
+package net.cflems.mc.penguin_dust;
+
+import net.cflems.mc.penguin_dust.spells.Fireball;
+import net.cflems.mc.penguin_dust.spells.Lightning;
+
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public enum Spell {
+ FIREBALL(new Fireball()),
+ LIGHTNING(new Lightning());
+
+ private final SpellExecutor executor;
+
+ Spell(SpellExecutor executor) {
+ this.executor = executor;
+ }
+
+ public boolean execute(@NotNull Player player, int strength) {
+ return executor.execute(player, strength);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/SpellExecutor.java b/src/main/java/net/cflems/mc/penguin_dust/SpellExecutor.java
new file mode 100644
index 0000000..3bc25b3
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/SpellExecutor.java
@@ -0,0 +1,8 @@
+package net.cflems.mc.penguin_dust;
+
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public interface SpellExecutor {
+ boolean execute(@NotNull Player player, int strength);
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/exceptions/DustException.java b/src/main/java/net/cflems/mc/penguin_dust/exceptions/DustException.java
new file mode 100644
index 0000000..68907b6
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/exceptions/DustException.java
@@ -0,0 +1,7 @@
+package net.cflems.mc.penguin_dust.exceptions;
+
+public class DustException extends RuntimeException {
+ public DustException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/exceptions/SpellException.java b/src/main/java/net/cflems/mc/penguin_dust/exceptions/SpellException.java
new file mode 100644
index 0000000..1986f96
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/exceptions/SpellException.java
@@ -0,0 +1,7 @@
+package net.cflems.mc.penguin_dust.exceptions;
+
+public class SpellException extends RuntimeException {
+ public SpellException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/listener/CraftingListener.java b/src/main/java/net/cflems/mc/penguin_dust/listener/CraftingListener.java
new file mode 100644
index 0000000..1f7052c
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/listener/CraftingListener.java
@@ -0,0 +1,111 @@
+package net.cflems.mc.penguin_dust.listener;
+
+import net.cflems.mc.penguin_dust.Spell;
+import net.cflems.mc.penguin_dust.utils.DustUtils;
+import net.cflems.mc.penguin_dust.utils.SpellUtils;
+
+import org.bukkit.Material;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.inventory.PrepareItemCraftEvent;
+import org.bukkit.inventory.CraftingInventory;
+import org.bukkit.inventory.ItemStack;
+
+public final class CraftingListener implements Listener {
+ @EventHandler(priority = EventPriority.NORMAL)
+ public void onPrepareItemCraft(PrepareItemCraftEvent event) {
+ CraftingInventory craftingInventory = event.getInventory();
+ ItemStack extraneousItem = null;
+ int dustCount = 0, blazePowderCount = 0, copperIngotCount = 0;
+
+ for (ItemStack item : craftingInventory.getMatrix()) {
+ if (item == null) continue;
+
+ switch (item.getType()) {
+ case BLAZE_POWDER:
+ blazePowderCount += item.getAmount();
+ break;
+ case COPPER_INGOT:
+ copperIngotCount += item.getAmount();
+ break;
+ case PUMPKIN_SEEDS:
+ if (DustUtils.isDust(item)) {
+ dustCount += item.getAmount();
+ break;
+ }
+ default:
+ if (item.getAmount() != 1 || extraneousItem != null) return;
+ extraneousItem = item;
+ }
+ }
+
+ if (dustCount <= 0) return;
+ if (extraneousItem == null || (blazePowderCount > 0 && copperIngotCount > 0)) {
+ craftingInventory.setResult(null);
+ return;
+ }
+
+ ItemStack enchantedItem = extraneousItem.clone();
+ boolean success;
+ if (blazePowderCount > 0) {
+ success =
+ SpellUtils.addSpell(
+ enchantedItem,
+ Spell.FIREBALL,
+ dustCount,
+ Math.min(blazePowderCount, dustCount));
+ } else if (copperIngotCount > 0) {
+ success =
+ SpellUtils.addSpell(
+ enchantedItem,
+ Spell.LIGHTNING,
+ dustCount,
+ Math.min(copperIngotCount, dustCount));
+ } else {
+ success = SpellUtils.reloadSpell(enchantedItem, dustCount);
+ }
+
+ if (success) craftingInventory.setResult(enchantedItem);
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onInventoryClick(InventoryClickEvent event) {
+ if (!(event.getClickedInventory() instanceof CraftingInventory craftingInventory)
+ || event.getSlotType() != InventoryType.SlotType.RESULT) return;
+ int dustCount = 0, blazePowderCount = 0, copperIngotCount = 0;
+
+ for (ItemStack stack : craftingInventory.getMatrix()) {
+ if (stack == null) continue;
+ switch (stack.getType()) {
+ case BLAZE_POWDER:
+ blazePowderCount += stack.getAmount();
+ stack.setAmount(0);
+ break;
+ case COPPER_INGOT:
+ copperIngotCount += stack.getAmount();
+ stack.setAmount(0);
+ break;
+ case PUMPKIN_SEEDS:
+ if (DustUtils.isDust(stack)) {
+ dustCount += stack.getAmount();
+ stack.setAmount(0);
+ }
+ break;
+ }
+ }
+
+ if (blazePowderCount - dustCount > 0) {
+ event.getWhoClicked()
+ .getInventory()
+ .addItem(new ItemStack(Material.BLAZE_POWDER, blazePowderCount - dustCount));
+ }
+ if (copperIngotCount - dustCount > 0) {
+ event.getWhoClicked()
+ .getInventory()
+ .addItem(new ItemStack(Material.COPPER_INGOT, copperIngotCount - dustCount));
+ }
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/listener/DamageListener.java b/src/main/java/net/cflems/mc/penguin_dust/listener/DamageListener.java
new file mode 100644
index 0000000..5e8a35e
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/listener/DamageListener.java
@@ -0,0 +1,31 @@
+package net.cflems.mc.penguin_dust.listener;
+
+import com.google.common.collect.MoreCollectors;
+
+import net.cflems.mc.penguin_dust.PenguinDust;
+import net.cflems.mc.penguin_dust.utils.SpellUtils;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.metadata.MetadataValue;
+
+import java.util.List;
+import java.util.Optional;
+
+public final class DamageListener implements Listener {
+ @EventHandler(priority = EventPriority.NORMAL)
+ public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
+ Entity damager = event.getDamager();
+ List<MetadataValue> damageMetadata = damager.getMetadata(SpellUtils.DAMAGE_KEY);
+ Optional<MetadataValue> damageValue =
+ damageMetadata.stream()
+ .filter(md -> md.getOwningPlugin() instanceof PenguinDust)
+ .collect(MoreCollectors.toOptional());
+ if (damageValue.isEmpty()) return;
+
+ event.setDamage(damageValue.get().asInt());
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/listener/ItemUseListener.java b/src/main/java/net/cflems/mc/penguin_dust/listener/ItemUseListener.java
new file mode 100644
index 0000000..3dcf2c0
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/listener/ItemUseListener.java
@@ -0,0 +1,28 @@
+package net.cflems.mc.penguin_dust.listener;
+
+import net.cflems.mc.penguin_dust.utils.SpellUtils;
+
+import org.bukkit.event.Event;
+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.player.PlayerInteractEvent;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Set;
+
+public final class ItemUseListener implements Listener {
+ private static final Set<Action> TARGET_ACTIONS =
+ Set.of(Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK);
+
+ @EventHandler(priority = EventPriority.NORMAL)
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ ItemStack itemInHand = event.getItem();
+ if (itemInHand == null
+ || event.useItemInHand().equals(Event.Result.DENY)
+ || !TARGET_ACTIONS.contains(event.getAction())) return;
+
+ if (SpellUtils.invokeSpell(event.getPlayer(), itemInHand)) event.setCancelled(true);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/listener/PlayerXPListener.java b/src/main/java/net/cflems/mc/penguin_dust/listener/PlayerXPListener.java
new file mode 100644
index 0000000..2ef7b6f
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/listener/PlayerXPListener.java
@@ -0,0 +1,21 @@
+package net.cflems.mc.penguin_dust.listener;
+
+import net.cflems.mc.penguin_dust.utils.DustUtils;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerExpChangeEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+public final class PlayerXPListener implements Listener {
+
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onPlayerExpChange(@NotNull PlayerExpChangeEvent event) {
+ if (event.getAmount() < 1) return;
+
+ ItemStack dust = DustUtils.createDust(event.getAmount());
+ event.getPlayer().getInventory().addItem(dust);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/spells/Fireball.java b/src/main/java/net/cflems/mc/penguin_dust/spells/Fireball.java
new file mode 100644
index 0000000..ca96609
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/spells/Fireball.java
@@ -0,0 +1,18 @@
+package net.cflems.mc.penguin_dust.spells;
+
+import net.cflems.mc.penguin_dust.SpellExecutor;
+
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public final class Fireball implements SpellExecutor {
+ private static final float MAX_YIELD = 128f;
+
+ @Override
+ public boolean execute(@NotNull Player player, int strength) {
+ org.bukkit.entity.Fireball fireball =
+ player.launchProjectile(org.bukkit.entity.Fireball.class);
+ fireball.setYield(Math.min(strength / 2.0f, MAX_YIELD));
+ return true;
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/spells/Lightning.java b/src/main/java/net/cflems/mc/penguin_dust/spells/Lightning.java
new file mode 100644
index 0000000..610921d
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/spells/Lightning.java
@@ -0,0 +1,48 @@
+package net.cflems.mc.penguin_dust.spells;
+
+import net.cflems.mc.penguin_dust.PenguinDust;
+import net.cflems.mc.penguin_dust.SpellExecutor;
+import net.cflems.mc.penguin_dust.utils.SpellUtils;
+
+import org.bukkit.FluidCollisionMode;
+import org.bukkit.World;
+import org.bukkit.entity.LightningStrike;
+import org.bukkit.entity.Player;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.util.RayTraceResult;
+import org.jetbrains.annotations.NotNull;
+
+public final class Lightning implements SpellExecutor {
+ private static final int MAX_DISTANCE = 128;
+
+ @Override
+ public boolean execute(@NotNull Player player, int strength) {
+ World world = player.getWorld();
+ RayTraceResult rayTraceResult =
+ world.rayTrace(
+ player.getEyeLocation(),
+ player.getEyeLocation().getDirection(),
+ MAX_DISTANCE,
+ FluidCollisionMode.NEVER,
+ true,
+ 0,
+ entity -> !player.equals(entity));
+ if (rayTraceResult == null) return false;
+
+ LightningStrike lightningStrike =
+ world.strikeLightning(rayTraceResult.getHitPosition().toLocation(world));
+ lightningStrike.setCausingPlayer(player);
+
+ JavaPlugin providingPlugin = JavaPlugin.getProvidingPlugin(PenguinDust.class);
+ lightningStrike.setMetadata(
+ SpellUtils.DAMAGE_KEY,
+ new FixedMetadataValue(providingPlugin, calculateDamage(strength)));
+ return true;
+ }
+
+ private static int calculateDamage(int spellStrength) {
+ double spellDamage = spellStrength * Math.sqrt(spellStrength) / 8.0;
+ return (int) spellDamage;
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/utils/DustUtils.java b/src/main/java/net/cflems/mc/penguin_dust/utils/DustUtils.java
new file mode 100644
index 0000000..55e06e5
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/utils/DustUtils.java
@@ -0,0 +1,44 @@
+package net.cflems.mc.penguin_dust.utils;
+
+import com.google.common.base.Preconditions;
+
+import net.cflems.mc.penguin_dust.exceptions.DustException;
+
+import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataType;
+import org.jetbrains.annotations.NotNull;
+
+public final class DustUtils {
+ private static final NamespacedKey IS_DUST_KEY =
+ Preconditions.checkNotNull(NamespacedKey.fromString("penguin-dust:is-penguin-dust"));
+
+ private DustUtils() {}
+
+ @NotNull
+ public static ItemStack createDust(int amount) {
+ if (amount <= 0) throw new DustException("Cannot have zero dust");
+
+ ItemStack base = new ItemStack(Material.PUMPKIN_SEEDS, amount);
+ ItemMeta meta =
+ Preconditions.checkNotNull(
+ base.getItemMeta(), "this plugin doesn't work if we can't set metadata");
+ meta.setItemName("Penguin Dust");
+ meta.getPersistentDataContainer().set(IS_DUST_KEY, PersistentDataType.BOOLEAN, true);
+
+ if (!base.setItemMeta(meta)) throw new DustException("Failed to set dust metadata");
+ return base;
+ }
+
+ public static boolean isDust(@NotNull ItemStack itemStack) {
+ if (itemStack.getType() != Material.PUMPKIN_SEEDS) return false;
+
+ ItemMeta meta = itemStack.getItemMeta();
+ if (meta == null) return false;
+
+ return meta.getPersistentDataContainer()
+ .getOrDefault(IS_DUST_KEY, PersistentDataType.BOOLEAN, false);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/penguin_dust/utils/SpellUtils.java b/src/main/java/net/cflems/mc/penguin_dust/utils/SpellUtils.java
new file mode 100644
index 0000000..7b9d166
--- /dev/null
+++ b/src/main/java/net/cflems/mc/penguin_dust/utils/SpellUtils.java
@@ -0,0 +1,145 @@
+package net.cflems.mc.penguin_dust.utils;
+
+import com.google.common.base.Preconditions;
+
+import net.cflems.mc.penguin_dust.Spell;
+import net.cflems.mc.penguin_dust.exceptions.SpellException;
+
+import org.bukkit.NamespacedKey;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.persistence.PersistentDataType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public final class SpellUtils {
+ public static final String DAMAGE_KEY = "penguin-dust:damage";
+ private static final NamespacedKey SPELL_NAME_KEY =
+ Preconditions.checkNotNull(NamespacedKey.fromString("penguin-dust:spell"));
+ private static final NamespacedKey SPELL_REMAINING_CAPACITY_KEY =
+ Preconditions.checkNotNull(
+ NamespacedKey.fromString("penguin-dust:spell-remaining-capacity"));
+ private static final NamespacedKey SPELL_MAX_CAPACITY_KEY =
+ Preconditions.checkNotNull(NamespacedKey.fromString("penguin-dust:spell-max-capacity"));
+ private static final NamespacedKey SPELL_THROUGHPUT_KEY =
+ Preconditions.checkNotNull(NamespacedKey.fromString("penguin-dust:spell-throughput"));
+
+ private SpellUtils() {}
+
+ public static boolean invokeSpell(@NotNull Player player, @NotNull ItemStack itemStack) {
+ ItemMeta meta = itemStack.getItemMeta();
+ if (meta == null) return false;
+
+ SpellData spellData = getSpellData(meta);
+ if (spellData == null) return false;
+
+ int spellStrength = Math.min(spellData.remainingCapacity, spellData.throughput);
+
+ if (!spellData.spell.execute(player, spellStrength)) return false;
+
+ int newRemainingCapacity = Math.max(spellData.remainingCapacity - spellStrength, 0);
+
+ if (newRemainingCapacity == 0) {
+ player.getInventory().remove(itemStack);
+ } else {
+ meta.getPersistentDataContainer()
+ .set(
+ SPELL_REMAINING_CAPACITY_KEY,
+ PersistentDataType.INTEGER,
+ newRemainingCapacity);
+
+ setLore(
+ meta,
+ spellData.spell,
+ spellData.throughput,
+ newRemainingCapacity,
+ spellData.maxCapacity);
+
+ if (!itemStack.setItemMeta(meta))
+ throw new SpellException("Failed to set spell metadata");
+ }
+
+ return true;
+ }
+
+ public static boolean addSpell(
+ @NotNull ItemStack itemStack, @NotNull Spell spell, int maxCapacity, int throughput) {
+ ItemMeta meta = itemStack.getItemMeta();
+ if (meta == null) return false;
+
+ PersistentDataContainer persistentDataContainer = meta.getPersistentDataContainer();
+ persistentDataContainer.set(SPELL_NAME_KEY, PersistentDataType.STRING, spell.toString());
+ persistentDataContainer.set(
+ SPELL_REMAINING_CAPACITY_KEY, PersistentDataType.INTEGER, maxCapacity);
+ persistentDataContainer.set(
+ SPELL_MAX_CAPACITY_KEY, PersistentDataType.INTEGER, maxCapacity);
+ persistentDataContainer.set(SPELL_THROUGHPUT_KEY, PersistentDataType.INTEGER, throughput);
+
+ setLore(meta, spell, throughput, maxCapacity, maxCapacity);
+ return itemStack.setItemMeta(meta);
+ }
+
+ public static boolean reloadSpell(@NotNull ItemStack itemStack, int additionalCapacity) {
+ ItemMeta meta = itemStack.getItemMeta();
+ if (meta == null) return false;
+
+ SpellData spellData = getSpellData(meta);
+ if (spellData == null) return false;
+
+ int newRemainingCapacity = spellData.remainingCapacity + additionalCapacity;
+ int newMaxCapacity = Math.max(newRemainingCapacity, spellData.maxCapacity);
+
+ PersistentDataContainer persistentDataContainer = meta.getPersistentDataContainer();
+ persistentDataContainer.set(
+ SPELL_REMAINING_CAPACITY_KEY, PersistentDataType.INTEGER, newRemainingCapacity);
+ persistentDataContainer.set(
+ SPELL_MAX_CAPACITY_KEY, PersistentDataType.INTEGER, newMaxCapacity);
+
+ setLore(meta, spellData.spell, spellData.throughput, newRemainingCapacity, newMaxCapacity);
+ return itemStack.setItemMeta(meta);
+ }
+
+ private record SpellData(
+ @NotNull Spell spell, int throughput, int remainingCapacity, int maxCapacity) {}
+
+ @Nullable
+ private static SpellData getSpellData(@NotNull ItemMeta meta) {
+ PersistentDataContainer persistentDataContainer = meta.getPersistentDataContainer();
+
+ String spellName = persistentDataContainer.get(SPELL_NAME_KEY, PersistentDataType.STRING);
+ if (spellName == null) return null;
+ Spell spell = Spell.valueOf(spellName);
+
+ Integer throughput =
+ persistentDataContainer.get(SPELL_THROUGHPUT_KEY, PersistentDataType.INTEGER);
+ if (throughput == null) return null;
+
+ Integer remainingCapacity =
+ persistentDataContainer.get(
+ SPELL_REMAINING_CAPACITY_KEY, PersistentDataType.INTEGER);
+ if (remainingCapacity == null) return null;
+
+ Integer maxCapacity =
+ persistentDataContainer.get(SPELL_MAX_CAPACITY_KEY, PersistentDataType.INTEGER);
+ if (maxCapacity == null) return null;
+
+ return new SpellData(spell, throughput, remainingCapacity, maxCapacity);
+ }
+
+ private static void setLore(
+ @NotNull ItemMeta meta,
+ @NotNull Spell spell,
+ int throughput,
+ int remainingCapacity,
+ int maxCapacity) {
+ meta.setLore(
+ List.of(
+ "Enchanted with: " + spell,
+ "Magical Durability: " + remainingCapacity + "/" + maxCapacity,
+ "Spell Strength: " + throughput));
+ }
+}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..29ab7d6
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,10 @@
+name: PenguinDust
+website: https://penguinland.io/penguindust
+author: cflems
+version: 0.0.0
+description: Brings magic to Penguinland with PenguinDust.
+main: net.cflems.mc.penguin_dust.PenguinDust
+load: POSTWORLD
+api-version: '1.21.9'
+depend: []
+commands: {}