From 1bc70d184d1702afe96c056fb4e66a5fe9bfa979 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Sun, 22 Oct 2023 09:55:43 -0700 Subject: [PATCH 01/20] Class-Based Casting, Class Selection --- src/main/java/me/zenox/evocraft/EvoCraft.java | 3 +- .../evocraft/abilities/AbilityRegistry.java | 7 +- .../zenox/evocraft/abilities/ItemAbility.java | 26 ++-- .../me/zenox/evocraft/command/Command.java | 7 ++ .../zenox/evocraft/data/TranslatableText.java | 3 +- .../me/zenox/evocraft/events/OtherEvent.java | 9 +- .../evocraft/events/PlayerUseItemEvent.java | 5 + .../gameclass/ClassAbilityListener.java | 101 ++++++++++++++++ .../zenox/evocraft/gameclass/GameClass.java | 111 ++++++++++++++++++ .../evocraft/gameclass/PassiveEffect.java | 4 + .../zenox/evocraft/gameclass/SkillNode.java | 80 +++++++++++++ .../zenox/evocraft/gameclass/SkillTree.java | 48 ++++++++ .../me/zenox/evocraft/gui/item/ClassItem.java | 46 ++++++++ .../me/zenox/evocraft/item/ItemRegistry.java | 2 +- src/main/resources/languages/en_US.yml | 79 +++++++++++++ 15 files changed, 502 insertions(+), 29 deletions(-) create mode 100644 src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java create mode 100644 src/main/java/me/zenox/evocraft/gameclass/GameClass.java create mode 100644 src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java create mode 100644 src/main/java/me/zenox/evocraft/gameclass/SkillNode.java create mode 100644 src/main/java/me/zenox/evocraft/gameclass/SkillTree.java create mode 100644 src/main/java/me/zenox/evocraft/gui/item/ClassItem.java diff --git a/src/main/java/me/zenox/evocraft/EvoCraft.java b/src/main/java/me/zenox/evocraft/EvoCraft.java index dd0f236..b82ec6e 100644 --- a/src/main/java/me/zenox/evocraft/EvoCraft.java +++ b/src/main/java/me/zenox/evocraft/EvoCraft.java @@ -16,6 +16,7 @@ import me.zenox.evocraft.data.LanguageLoader; import me.zenox.evocraft.enchant.EnchantRegistry; import me.zenox.evocraft.events.*; +import me.zenox.evocraft.gameclass.ClassAbilityListener; import me.zenox.evocraft.item.ItemRegistry; import me.zenox.evocraft.item.VanillaItem; import me.zenox.evocraft.network.GlowFilter; @@ -101,7 +102,6 @@ public void onEnable() { new Command(plugin); registerListeners(); - } private void registerListeners() { @@ -110,6 +110,7 @@ private void registerListeners() { new InventoryListener(plugin); new DimensionLocker(plugin); new DeathManager(plugin); + new ClassAbilityListener(plugin); } private boolean setupEconomy() { diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 313441e..a111fe5 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -80,7 +80,7 @@ public class AbilityRegistry { .setSlot(Slot.ARMOR), FullSetAttackAbility::testFullSetAbility); public static final ItemAbility TERRA_STRIKE = new ItemAbility(new AbilitySettings() .setId("terra_strike") - .setAbilityAction(ItemAbility.AbilityAction.SHIFT_RIGHT_CLICK) + .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) .setManaCost(10) .setCooldown(5), ItemAbility::terraStrikeAbility); public static final FullSetAttackAbility ROARING_FLAME = new FullSetAttackAbility(new AbilitySettings() @@ -110,11 +110,6 @@ public class AbilityRegistry { .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) .setManaCost(100) .setCooldown(1), ItemAbility::voidWarpAbility); - public static final ItemAbility VOIDULAR_RECALL= new ItemAbility(new AbilitySettings() - .setId("voidular_recall") - .setAbilityAction(ItemAbility.AbilityAction.SHIFT_RIGHT_CLICK) - .setManaCost(10) - .setCooldown(1), ItemAbility::voidularRecallAbility); public static final ItemAbility START_BUTTON = new ItemAbility(new AbilitySettings() .setId("start_button") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) diff --git a/src/main/java/me/zenox/evocraft/abilities/ItemAbility.java b/src/main/java/me/zenox/evocraft/abilities/ItemAbility.java index 610ecd6..7bbc9d1 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ItemAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ItemAbility.java @@ -96,7 +96,7 @@ public AbilityAction getAction() { @Override public boolean checkEvent(PlayerInteractEvent event) { - return action.isAction(event.getAction(), event.getPlayer().isSneaking()); + return action.isAction(event.getAction()) && !event.getPlayer().isSneaking(); } /** @@ -1078,32 +1078,28 @@ public void run() { } public enum AbilityAction { - LEFT_CLICK_BLOCK("LEFT CLICK", new Action[]{Action.LEFT_CLICK_BLOCK}, false), - LEFT_CLICK_AIR("LEFT CLICK", new Action[]{Action.LEFT_CLICK_AIR}, false), - LEFT_CLICK_ALL("LEFT CLICK", new Action[]{Action.LEFT_CLICK_AIR, Action.LEFT_CLICK_BLOCK}, false), - SHIFT_LEFT_CLICK("SHIFT LEFT CLICK", new Action[]{Action.LEFT_CLICK_AIR, Action.LEFT_CLICK_BLOCK}, true), - RIGHT_CLICK_BLOCK("RIGHT CLICK", new Action[]{Action.RIGHT_CLICK_AIR}, false), - RIGHT_CLICK_AIR("RIGHT CLICK", new Action[]{Action.RIGHT_CLICK_BLOCK}, false), - RIGHT_CLICK_ALL("RIGHT CLICK", new Action[]{Action.RIGHT_CLICK_BLOCK, Action.RIGHT_CLICK_AIR}, false), - SHIFT_RIGHT_CLICK("SHIFT RIGHT CLICK", new Action[]{Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK}, true), - NONE("", new Action[]{}, false); + LEFT_CLICK_BLOCK("LEFT CLICK", new Action[]{Action.LEFT_CLICK_BLOCK}), + LEFT_CLICK_AIR("LEFT CLICK", new Action[]{Action.LEFT_CLICK_AIR}), + LEFT_CLICK_ALL("LEFT CLICK", new Action[]{Action.LEFT_CLICK_AIR, Action.LEFT_CLICK_BLOCK}), + RIGHT_CLICK_BLOCK("RIGHT CLICK", new Action[]{Action.RIGHT_CLICK_AIR}), + RIGHT_CLICK_AIR("RIGHT CLICK", new Action[]{Action.RIGHT_CLICK_BLOCK}), + RIGHT_CLICK_ALL("RIGHT CLICK", new Action[]{Action.RIGHT_CLICK_BLOCK, Action.RIGHT_CLICK_AIR}), + + NONE("", new Action[]{}); private final String name; private final Action[] actionList; - private final boolean requiresShift; - AbilityAction(String name, Action[] actionList, boolean requiresShift) { + AbilityAction(String name, Action[] actionList) { this.name = name; this.actionList = actionList; - this.requiresShift = requiresShift; } public String getName() { return this.name; } - public boolean isAction(Action action, boolean isCrouching) { - if (this.requiresShift && !isCrouching) return false; + public boolean isAction(Action action) { return Arrays.asList(actionList).contains(action); diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index 07f1319..e1e37a5 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -1,8 +1,10 @@ package me.zenox.evocraft.command; import com.google.common.primitives.Ints; +import de.studiocode.invui.window.impl.single.SimpleWindow; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.enchant.ComplexEnchantment; +import me.zenox.evocraft.gameclass.GameClass; import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; @@ -225,6 +227,8 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman EvoCraft.getChapterManager().setChapter(player, chapter); return true; } + case "class" -> // Open the class selection GUI + new SimpleWindow(((Player) sender), "Class Selection", GameClass.getGui(), true, true).show(); default -> Util.sendMessage(sender, "EvoCraft Help Page."); } return true; @@ -243,6 +247,9 @@ public List onTabComplete(CommandSender sender, org.bukkit.command.Comma arguments.add("enchant"); arguments.add("reload"); arguments.add("removechapterdata"); + arguments.add("removemetadata"); + arguments.add("setchapter"); + arguments.add("class"); } if (items.isEmpty()) { diff --git a/src/main/java/me/zenox/evocraft/data/TranslatableText.java b/src/main/java/me/zenox/evocraft/data/TranslatableText.java index 4e60ec3..dd6dfc9 100644 --- a/src/main/java/me/zenox/evocraft/data/TranslatableText.java +++ b/src/main/java/me/zenox/evocraft/data/TranslatableText.java @@ -26,7 +26,8 @@ public enum Type { ITEM_NAME("item-name"), ITEM_LORE("item-lore"), ABILITY_NAME("ability-name"), ABILITY_LORE("ability-lore"), COMMAND("cmd"), MISC_MSG("msg"), ENCHANT_NAME("enchant-name"), - ATTRIBUTE("attribute"), GUI("gui"); + ATTRIBUTE("attribute"), GUI("gui"), + CLASS_NAME("class-name"), CLASS_DESC("class-desc"); private final String key; diff --git a/src/main/java/me/zenox/evocraft/events/OtherEvent.java b/src/main/java/me/zenox/evocraft/events/OtherEvent.java index 7b11c82..9b09ad8 100644 --- a/src/main/java/me/zenox/evocraft/events/OtherEvent.java +++ b/src/main/java/me/zenox/evocraft/events/OtherEvent.java @@ -45,11 +45,10 @@ public OtherEvent(EvoCraft plugin) { @EventHandler public void tileEntityInteract(PlayerInteractEvent e){ if(e.getAction() == Action.RIGHT_CLICK_BLOCK){ - switch(e.getClickedBlock().getType()){ - case ENCHANTING_TABLE -> new SimpleWindow(e.getPlayer(), "Enchantment Table", EnchantingGUI.getGui(e.getPlayer(), e.getClickedBlock()), true, true).show(); - default -> { - return; - } + if (e.getClickedBlock().getType() == Material.ENCHANTING_TABLE) { + new SimpleWindow(e.getPlayer(), "Enchantment Table", EnchantingGUI.getGui(e.getPlayer(), e.getClickedBlock()), true, true).show(); + } else { + return; } e.setCancelled(true); } diff --git a/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java b/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java index f3df5e2..157fb8c 100644 --- a/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java +++ b/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java @@ -4,6 +4,7 @@ import me.zenox.evocraft.abilities.Ability; import me.zenox.evocraft.abilities.ItemAbility; import me.zenox.evocraft.enchant.ComplexEnchantment; +import me.zenox.evocraft.gameclass.ClassAbilityListener; import me.zenox.evocraft.item.ComplexItemStack; import org.bukkit.event.*; import org.bukkit.event.player.PlayerInteractEvent; @@ -47,6 +48,10 @@ public PlayerUseItemEvent(EvoCraft plugin) { @EventHandler public void useEvent(Event event) { + // check for class abilities + if (event instanceof PlayerInteractEvent && ClassAbilityListener.playerInitiated(((PlayerInteractEvent) event).getPlayer())) + return; + // PERFORMANCE ISSUE: This is called for every event, and every single ability is called. List relevantAbilities = eventToAbilitiesMap.get(event.getClass()); if (relevantAbilities != null) { diff --git a/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java new file mode 100644 index 0000000..d9a15d6 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java @@ -0,0 +1,101 @@ +package me.zenox.evocraft.gameclass; + +import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.item.ComplexItemStack; +import me.zenox.evocraft.util.Util; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerToggleSneakEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashMap; + +public class ClassAbilityListener implements Listener { + private final EvoCraft plugin; + // null = SHIFT, l = LEFT_CLICK, r = RIGHT_CLICK + private static final HashMap actionMap = new HashMap<>(); + + public ClassAbilityListener(EvoCraft plugin) { + this.plugin = plugin; + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onClassSneak(PlayerToggleSneakEvent event) { + + if (event.isSneaking()){ + // initiator + Player player = event.getPlayer(); + + // filter by player's class + if (GameClass.getClass(player) == null) return; + if (!GameClass.getClass(player).items().contains(ComplexItemStack.of(player.getEquipment().getItemInMainHand()).getComplexItem().getType())) return; + // Prime the ability action bar for PlayerInteractEvent + Util.sendActionBar(event.getPlayer(), "&bSHIFT&7-&b_&7-&b_"); + player.playSound(player.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 2, 0.5f); + actionMap.put(player, null); + + // remove after 1 second unless another action is taken + new BukkitRunnable(){ + @Override + public void run() { + if (actionMap.get(player) == null) + actionMap.remove(player); + } + }.runTaskLater(plugin, 20); + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Action action = event.getAction(); + + // filter by player's class + if (GameClass.getClass(player) == null) return; + if (!GameClass.getClass(player).items().contains(ComplexItemStack.of(event.getItem()).getComplexItem().getType())) return; + + if (actionMap.containsKey(player) && (action.isLeftClick() || action.isRightClick())) { + if (actionMap.get(player) != null){ + // Second Action, has first action + // Effects + player.playSound(player.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 2, 1.5f); + player.playSound(player.getLocation(), Sound.ENTITY_EVOKER_CAST_SPELL, 2, 1); + + Character firstAction = actionMap.get(player); + Util.sendActionBar(event.getPlayer(), "&bSHIFT&7-&b%s&7-&b%s&r".formatted(firstAction, action.toString().charAt(0))); + Util.sendTitle(player, "", "&7Class Ability: &b&l%s&f-&b&l%s&r".formatted(firstAction, action.toString().charAt(0)), 10, 20, 5); + actionMap.remove(player); // Clear the action after processing the combo + } else { + // First Action + + player.playSound(player.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 2, 1f); + + Util.sendActionBar(event.getPlayer(), "&bSHIFT&7-&b%s&7-&b_".formatted(action.toString().charAt(0))); + actionMap.put(player, action.toString().charAt(0)); + + // remove after 1 second + new BukkitRunnable(){ + @Override + public void run() { + actionMap.remove(player); + } + }.runTaskLater(plugin, 20); + } + } + } + + /** + * Whether a player has initiated the casting of a class ability + * @param player The player to check + * @return Whether the player has initiated the casting of a class ability + */ + public static boolean playerInitiated(Player player){ + return actionMap.containsKey(player); + } + +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java new file mode 100644 index 0000000..f4f7997 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java @@ -0,0 +1,111 @@ +package me.zenox.evocraft.gameclass; + +import de.studiocode.invui.gui.GUI; +import de.studiocode.invui.gui.builder.GUIBuilder; +import de.studiocode.invui.gui.builder.guitype.GUIType; +import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.data.TranslatableText; +import me.zenox.evocraft.gui.item.ClassItem; +import me.zenox.evocraft.gui.item.CloseItem; +import me.zenox.evocraft.item.ComplexItem; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.persistence.PersistentDataType; + +import java.util.List; + +/** + * Represents a class the player may choose + */ +public enum GameClass { + MAGE("mage", ChatColor.BLUE, + List.of(ComplexItem.Type.STAFF, ComplexItem.Type.WAND), Material.BLAZE_ROD, + new SkillTree()), + WARRIOR("warrior", ChatColor.RED, + List.of(ComplexItem.Type.SWORD), Material.IRON_SWORD, + new SkillTree()), + TANK("tank", ChatColor.GREEN, + List.of(ComplexItem.Type.AXE), Material.IRON_AXE, + new SkillTree()), + ARCHER("archer", ChatColor.YELLOW, + List.of(ComplexItem.Type.BOW), Material.BOW, + new SkillTree()); + + private static final NamespacedKey KEY = new NamespacedKey(EvoCraft.getPlugin(), "class"); + private final String id; + private final String name; + private final ChatColor color; + private final String description; + private final List items; + private final Material icon; + private final SkillTree tree; + + GameClass(String id, ChatColor color, List items, Material icon, SkillTree tree) { + this.id = id; + this.name = new TranslatableText(TranslatableText.Type.CLASS_NAME + "-" + id).toString(); + this.color = color; + this.description = new TranslatableText(TranslatableText.Type.CLASS_DESC + "-" + id).toString(); + this.items = items; + this.icon = icon; + this.tree = tree; + } + + public static void setClass(Player player, GameClass gameClass) { + player.getPersistentDataContainer().set(GameClass.KEY, PersistentDataType.STRING, gameClass.id()); + } + + public static GameClass getClass(Player player) { + return GameClass.getFromID(player.getPersistentDataContainer().get(GameClass.KEY, PersistentDataType.STRING)); + } + + private static GameClass getFromID(String id) { + return switch (id) { + case "mage" -> GameClass.MAGE; + case "warrior" -> GameClass.WARRIOR; + case "tank" -> GameClass.TANK; + case "archer" -> GameClass.ARCHER; + default -> null; + }; + } + + public static GUI getGui() { + return new GUIBuilder<>(GUIType.NORMAL) + .setStructure( + "# # # # # # # # #", + "# M # W # T # A #", + "# # # # # # # # #" + ) + .addIngredient('M', new ClassItem(GameClass.MAGE)) + .addIngredient('W', new ClassItem(GameClass.WARRIOR)) + .addIngredient('T', new ClassItem(GameClass.TANK)) + .addIngredient('A', new ClassItem(GameClass.ARCHER)) + .addIngredient('C', new CloseItem()) + .build(); + } + + private String id() { + return id; + } + + public ChatColor color() { + return color; + } + + public String description() { + return description; + } + + public List items() { + return items; + } + + public Material icon() { + return icon; + } + + public SkillTree tree() { + return tree; + } +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java b/src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java new file mode 100644 index 0000000..c9c5f42 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java @@ -0,0 +1,4 @@ +package me.zenox.evocraft.gameclass; + +public class PassiveEffect { +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/SkillNode.java b/src/main/java/me/zenox/evocraft/gameclass/SkillNode.java new file mode 100644 index 0000000..4485eb1 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/SkillNode.java @@ -0,0 +1,80 @@ +package me.zenox.evocraft.gameclass; + +import me.zenox.evocraft.abilities.Ability; + +import java.util.List; +import java.util.Objects; + +public final class SkillNode { + private final String id; + private final String name; + private final String description; + private final List prerequisiteSkills; + private final List children; + private final Ability ability; + private final PassiveEffect passiveEffect; + + public SkillNode(String id, String name, String description, List prerequisiteSkills, List children, Ability ability, PassiveEffect passiveEffect) { + this.id = id; + this.name = name; + this.description = description; + this.prerequisiteSkills = prerequisiteSkills; + this.children = children; + this.ability = ability; + this.passiveEffect = passiveEffect; + } + + public String id() { + return id; + } + + public String name() { + return name; + } + + public String description() { + return description; + } + + public List prerequisiteSkills() { + return prerequisiteSkills; + } + + public List children() { + return children; + } + + public Ability ability() { + return ability; + } + + public PassiveEffect passiveEffect() { + return passiveEffect; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (SkillNode) obj; + return Objects.equals(this.id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, description, prerequisiteSkills, children, ability, passiveEffect); + } + + @Override + public String toString() { + return "SkillNode[" + + "id=" + id + ", " + + "name=" + name + ", " + + "description=" + description + ", " + + "prerequisiteSkills=" + prerequisiteSkills + ", " + + "children=" + children + ", " + + "ability=" + ability + ", " + + "passiveEffect=" + passiveEffect + ']'; + } + +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/SkillTree.java b/src/main/java/me/zenox/evocraft/gameclass/SkillTree.java new file mode 100644 index 0000000..ff00ca2 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/SkillTree.java @@ -0,0 +1,48 @@ +package me.zenox.evocraft.gameclass; + +import java.util.List; +import java.util.Objects; + +public final class SkillTree { + private final SkillNode root; + private final List nodes; + + public SkillTree(SkillNode root, List nodes) { + this.root = root; + this.nodes = nodes; + } + + public SkillTree() { + this(new SkillNode("test", "BANG", "boom boom shot", List.of(), List.of(), null, null), List.of()); + } + + public SkillNode root() { + return root; + } + + public List nodes() { + return nodes; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (SkillTree) obj; + return Objects.equals(this.root, that.root) && + Objects.equals(this.nodes, that.nodes); + } + + @Override + public int hashCode() { + return Objects.hash(root, nodes); + } + + @Override + public String toString() { + return "SkillTree[" + + "root=" + root + ", " + + "nodes=" + nodes + ']'; + } + +} diff --git a/src/main/java/me/zenox/evocraft/gui/item/ClassItem.java b/src/main/java/me/zenox/evocraft/gui/item/ClassItem.java new file mode 100644 index 0000000..2df5591 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gui/item/ClassItem.java @@ -0,0 +1,46 @@ +package me.zenox.evocraft.gui.item; + +import de.studiocode.invui.item.ItemProvider; +import de.studiocode.invui.item.builder.ItemBuilder; +import de.studiocode.invui.item.impl.BaseItem; +import de.studiocode.invui.window.Window; +import me.zenox.evocraft.data.TranslatableList; +import me.zenox.evocraft.data.TranslatableText; +import me.zenox.evocraft.gameclass.GameClass; +import me.zenox.evocraft.util.Util; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemFlag; +import org.jetbrains.annotations.NotNull; + +public class ClassItem extends BaseItem { + private final GameClass gameClass; + private final TranslatableText NAME; + private final TranslatableList LORE; + + public ClassItem(GameClass gameClass){ + super(); + this.gameClass = gameClass; + this.NAME = new TranslatableText(TranslatableText.Type.GUI + "-class-action-title-" + gameClass.name().toLowerCase()); + this.LORE = new TranslatableList(TranslatableText.Type.GUI + "-class-action-lore-" + gameClass.name().toLowerCase()); + } + + @Override + public ItemProvider getItemProvider() { + return new ItemBuilder(gameClass.icon()).setDisplayName(NAME.toString()).setLegacyLore(LORE.getList()).addItemFlags(ItemFlag.HIDE_ATTRIBUTES); + } + + @Override + public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) { + // set the class of a player + Util.sendMessage(player, "You have selected the " + gameClass.name() + " class!"); + GameClass.setClass(player, gameClass); + for (Window window : getWindows()) { + if(window.getCurrentViewer().equals(player)){ + window.closeForViewer(); + } + } + } +} + diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index 59c0652..8e195af 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -224,7 +224,7 @@ public class ItemRegistry { .modifier(AttributeRegistry.ATTACK_DAMAGE, 15) .modifier(AttributeRegistry.ATTACK_SPEED, -3) .modifier(AttributeRegistry.WISDOM, 50) - .abilities(AbilityRegistry.VOID_WARP, AbilityRegistry.VOIDULAR_RECALL) + .abilities(AbilityRegistry.VOID_WARP) .rarity(ComplexItem.Rarity.EPIC) .material(Material.NETHERITE_SHOVEL) .type(ComplexItem.Type.STAFF) diff --git a/src/main/resources/languages/en_US.yml b/src/main/resources/languages/en_US.yml index 1ade682..aea3c20 100644 --- a/src/main/resources/languages/en_US.yml +++ b/src/main/resources/languages/en_US.yml @@ -702,6 +702,85 @@ gui-enchant-action-lore-3: - "" - "&c&nRequires enchanting level 25!" +gui-class-action-title-mage: "&b&lMage &7→ &eClick to Select" +gui-class-action-lore-mage: + - "&fHarness the power of &bmana&f and &bmagic&f." + - "" + - "&7Weapons: &fStaffs, Wands, Potions" + - "" + - "&7Subclasses: " + - "&eRunecaster, Arcanist, Lightweaver" + - "" + - "&8(Low health, high damage, medium speed)" + +gui-class-action-title-warrior: "&c&lWarrior &7→ &eClick to Select" +gui-class-action-lore-warrior: + - "&fA mobile melee combatant," + - "excelling in close quarters." + - "" + - "&7Weapons: &fSwords, Axes" + - "" + - "&7Subclasses: " + - "&eGladiator, Rogue, Bladestorm" + - "" + - "&8(Fast, agile, low health siphon)" + +gui-class-action-title-tank: "&a&lTank &7→ &eClick to Select" +gui-class-action-lore-tank: + - "&fBecome the shield of your team," + - "&fand deal massive blows." + - "" + - "&7Weapons: &fMaces, Greatswords, Hammers" + - "" + - "&7Subclasses: " + - "&eStoneheart, Warden, Centurion" + - "" + - "&8(High health, slower, high damage)" + +gui-class-action-title-archer: "&6&lArcher &7→ &eClick to Select" +gui-class-action-lore-archer: + - "&fMaster the art of ranged combat," + - "&fand deal damage from afar." + - "" + - "&7Weapons: &fBows, Blasters" + - "" + - "&7Subclasses: " + - "&eDeadeye, Skirmisher, Fusillade" + - "" + - "&8(Medium health, good speed, medium damage)" + +########################################################################## +## CLASSES ## +########################################################################## +class-name-mage: "&b&lMage" +class-desc-mage: + - "&7Harness the mystical arts and control the battlefield with your spells." + - "&7Wield powerful &fStaffs, Wands &7and craft potent &fPotions." + - "&8Subclasses: &eRunecaster, Arcanist, Lightweaver" + - "&8(Low health, high damage, medium speed)" + +class-name-warrior: "&c&lWarrior" +class-desc-warrior: + - "&7Engage in close combat with agility and precision." + - "&7Brandish deadly &fSwords &7and swift &fAxes." + - "&8Subclasses: &eGladiator, Rogue, Bladestorm" + - "&8(Fast, agile, low health siphon)" + +class-name-tank: "&a&lTank" +class-desc-tank: + - "&7Hold the front line and protect your allies with might." + - "&7Swing devastating &fMaces, Greatswords &7and crushing &fHammers." + - "&8Subclasses: &eStoneheart, Warden, Centurion" + - "&8(High health, slower, high damage)" + +class-name-archer: "&6&lArcher" +class-desc-archer: + - "&7Take down foes from a distance, mastering the bow's art." + - "&7Equip versatile &fBows &7and modern &fBlasters." + - "&8Subclasses: &eDeadeye, Skirmisher, Fusillade" + - "&8(Medium health, good speed, medium damage)" + + ########################################################################## ## ATTRIBUTES ## ########################################################################## From c71e15f4e5b2481816ab1f046ad4ee0e9ccb292d Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Sun, 22 Oct 2023 10:32:46 -0700 Subject: [PATCH 02/20] Ability + ComplexItem.of() Refactor --- .../me/zenox/evocraft/abilities/Ability.java | 7 +-- .../me/zenox/evocraft/abilities/Crucify.java | 3 +- .../abilities/FullSetArmorAbility.java | 4 +- .../me/zenox/evocraft/command/Command.java | 11 ++-- .../evocraft/events/InventoryListener.java | 15 +++-- .../evocraft/events/PlayerUseItemEvent.java | 15 ----- .../gameclass/ClassAbilityListener.java | 6 +- .../me/zenox/evocraft/gui/EnchantingGUI.java | 2 +- .../me/zenox/evocraft/item/ComplexItem.java | 57 +++++++------------ .../zenox/evocraft/item/ComplexItemMeta.java | 16 +----- .../zenox/evocraft/item/ComplexItemStack.java | 4 +- .../me/zenox/evocraft/item/ItemRegistry.java | 29 +--------- .../me/zenox/evocraft/item/VanillaItem.java | 2 +- .../zenox/evocraft/recipe/ComplexChoice.java | 6 +- 14 files changed, 51 insertions(+), 126 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/Ability.java b/src/main/java/me/zenox/evocraft/abilities/Ability.java index 586ab3e..c177d29 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Ability.java +++ b/src/main/java/me/zenox/evocraft/abilities/Ability.java @@ -1,11 +1,11 @@ package me.zenox.evocraft.abilities; import com.archyx.aureliumskills.api.AureliumAPI; -import me.zenox.evocraft.Slot; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.Slot; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; -import me.zenox.evocraft.item.ComplexItemStack; +import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; @@ -18,7 +18,6 @@ import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.Nullable; -import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; @@ -144,7 +143,7 @@ public void useAbility(Event event) { // Perhaps change this in the future to support passing multiple items to the consumer for(ItemStack i : items) { if (i == null || i.getType() == Material.AIR || i.getItemMeta() == null) continue; - if (!ComplexItemStack.of(i).getAbilities().contains(this)) continue; + if (!ComplexItem.of(i).getAbilities().contains(this)) continue; item = i; break; } diff --git a/src/main/java/me/zenox/evocraft/abilities/Crucify.java b/src/main/java/me/zenox/evocraft/abilities/Crucify.java index c533688..e498440 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Crucify.java +++ b/src/main/java/me/zenox/evocraft/abilities/Crucify.java @@ -2,7 +2,6 @@ import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.item.ComplexItem; -import me.zenox.evocraft.item.ItemRegistry; import org.bukkit.*; import org.bukkit.entity.Damageable; import org.bukkit.entity.Entity; @@ -103,7 +102,7 @@ public void onPlayerDeath(PlayerDeathEvent e) { p.setMetadata("crucify_active", new FixedMetadataValue(EvoCraft.getPlugin(), false)); Inventory inv = p.getInventory(); for (ItemStack item : inv.getContents()) { - ComplexItem complexItemMaterial = ItemRegistry.byItem(item); + ComplexItem complexItemMaterial = ComplexItem.of(item); if (complexItemMaterial != null && complexItemMaterial.getId().equals(CRUCIFIED_AMULET.getId())) { item.setAmount(item.getAmount() - 1); diff --git a/src/main/java/me/zenox/evocraft/abilities/FullSetArmorAbility.java b/src/main/java/me/zenox/evocraft/abilities/FullSetArmorAbility.java index 0653050..dd0f861 100644 --- a/src/main/java/me/zenox/evocraft/abilities/FullSetArmorAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/FullSetArmorAbility.java @@ -1,7 +1,7 @@ package me.zenox.evocraft.abilities; import me.zenox.evocraft.Slot; -import me.zenox.evocraft.item.ComplexItemStack; +import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.util.TriConsumer; import org.bukkit.entity.Player; import org.bukkit.event.Event; @@ -27,7 +27,7 @@ public FullSetArmorAbility(String id, int manaCost, double cooldown, TriConsumer protected boolean checkEvent(T e) { return checkEventExec(e) && Slot.ARMOR.item(getPlayerOfEvent(e)).stream().allMatch(itemStack -> { try { - return ComplexItemStack.of(itemStack).getAbilities().contains(this); + return ComplexItem.of(itemStack).getAbilities().contains(this); } catch (NullPointerException exception){ return false; } diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index e1e37a5..bc70c18 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -8,7 +8,6 @@ import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; -import me.zenox.evocraft.item.ItemRegistry; import me.zenox.evocraft.loot.LootTable; import me.zenox.evocraft.loot.LootTableRegistry; import me.zenox.evocraft.story.Chapter; @@ -56,7 +55,7 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman Util.sendMessage(p, "Please specify a item to give."); return true; } - ComplexItem itemtype = ItemRegistry.byId(args[2]); + ComplexItem itemtype = ComplexItem.itemRegistry.get(args[2]); if (itemtype == null) { Util.sendMessage(p, "This item could not be found!"); } else { @@ -108,7 +107,7 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman Util.sendMessage(sender, "Please specify a item to drop."); return true; } - ComplexItem itemtypetodrop = ItemRegistry.byId(args[2]); + ComplexItem itemtypetodrop = ComplexItem.itemRegistry.get(args[2]); if (itemtypetodrop == null) { Util.sendMessage(sender, "This item could not be found!"); } else { @@ -187,7 +186,7 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman Util.sendMessage(sender, ChatColor.WHITE + "This item has no CustomModelData (that is created by EvoCraft)"); return true; } - Util.sendMessage(sender, ChatColor.WHITE + "The CustomModelData of " + item.getItemMeta().getDisplayName() + ChatColor.WHITE + " is " + ComplexItemStack.of(item).getComplexItem().getCustomModelData()); + Util.sendMessage(sender, ChatColor.WHITE + "The CustomModelData of " + item.getItemMeta().getDisplayName() + ChatColor.WHITE + " is " + ComplexItem.of(item).getCustomModelData()); return true; } case "removechapterdata" -> { @@ -253,9 +252,7 @@ public List onTabComplete(CommandSender sender, org.bukkit.command.Comma } if (items.isEmpty()) { - for (ComplexItem item : ComplexItem.itemRegistry) { - items.add(item.getId()); - } + items.addAll(ComplexItem.itemRegistry.keySet()); } List results = new ArrayList<>(); diff --git a/src/main/java/me/zenox/evocraft/events/InventoryListener.java b/src/main/java/me/zenox/evocraft/events/InventoryListener.java index 61886a4..28c5da2 100644 --- a/src/main/java/me/zenox/evocraft/events/InventoryListener.java +++ b/src/main/java/me/zenox/evocraft/events/InventoryListener.java @@ -32,38 +32,37 @@ public void inventoryOpenEvent(InventoryOpenEvent event) { ArrayList contents = new ArrayList<>(); contents.addAll(Arrays.asList(event.getPlayer().getInventory().getContents())); contents.addAll(Arrays.asList(event.getPlayer().getInventory().getArmorContents())); - updateInventory(contents); + updateItems(contents); } @EventHandler(priority = EventPriority.HIGHEST) public void inventoryInteractEvent(InventoryClickEvent event) { ArrayList contents = new ArrayList<>(); contents.add(event.getCurrentItem()); - if(!event.isCancelled()) updateInventory(contents); + if(!event.isCancelled()) updateItems(contents); } @EventHandler public void inventoryPickupEvent(EntityPickupItemEvent event) { ArrayList contents = new ArrayList<>(); contents.add(event.getItem().getItemStack()); - updateInventory(contents); + updateItems(contents); } @EventHandler public void itemDropEvent(EntityDropItemEvent event){ ArrayList contents = new ArrayList<>(); contents.add(event.getItemDrop().getItemStack()); - updateInventory(contents); + updateItems(contents); } @EventHandler public void itemDropEvent(BlockDropItemEvent event){ - ArrayList contents = new ArrayList<>(); - contents.addAll(event.getItems().stream().map(Item::getItemStack).toList()); - updateInventory(contents); + ArrayList contents = new ArrayList<>(event.getItems().stream().map(Item::getItemStack).toList()); + updateItems(contents); } - private void updateInventory(List contents) { + private void updateItems(List contents) { contents.removeIf(Objects::isNull); // Update ComplexItems diff --git a/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java b/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java index 157fb8c..8fc4ee9 100644 --- a/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java +++ b/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java @@ -2,13 +2,10 @@ import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.Ability; -import me.zenox.evocraft.abilities.ItemAbility; import me.zenox.evocraft.enchant.ComplexEnchantment; import me.zenox.evocraft.gameclass.ClassAbilityListener; -import me.zenox.evocraft.item.ComplexItemStack; import org.bukkit.event.*; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.RegisteredListener; import java.util.ArrayList; @@ -67,16 +64,4 @@ public void useEvent(Event event) { } } } - - private void interact(PlayerInteractEvent event) { - ItemStack item = event.getItem(); - if (item == null) return; - ComplexItemStack complexItem = ComplexItemStack.of(item); - for (Ability ability : complexItem.getAbilities()) { - if (ability instanceof ItemAbility) ability.useAbility(event); - } - } - - - } diff --git a/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java index d9a15d6..89c0531 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java +++ b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java @@ -1,7 +1,7 @@ package me.zenox.evocraft.gameclass; import me.zenox.evocraft.EvoCraft; -import me.zenox.evocraft.item.ComplexItemStack; +import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.util.Util; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -33,7 +33,7 @@ public void onClassSneak(PlayerToggleSneakEvent event) { // filter by player's class if (GameClass.getClass(player) == null) return; - if (!GameClass.getClass(player).items().contains(ComplexItemStack.of(player.getEquipment().getItemInMainHand()).getComplexItem().getType())) return; + if (!GameClass.getClass(player).items().contains(ComplexItem.of(player.getEquipment().getItemInMainHand()).getType())) return; // Prime the ability action bar for PlayerInteractEvent Util.sendActionBar(event.getPlayer(), "&bSHIFT&7-&b_&7-&b_"); player.playSound(player.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 2, 0.5f); @@ -57,7 +57,7 @@ public void onPlayerInteract(PlayerInteractEvent event) { // filter by player's class if (GameClass.getClass(player) == null) return; - if (!GameClass.getClass(player).items().contains(ComplexItemStack.of(event.getItem()).getComplexItem().getType())) return; + if (!GameClass.getClass(player).items().contains(ComplexItem.of(event.getItem()).getType())) return; if (actionMap.containsKey(player) && (action.isLeftClick() || action.isRightClick())) { if (actionMap.get(player) != null){ diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java b/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java index 574d052..eba9b4d 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java @@ -209,7 +209,7 @@ public static boolean enchantValid(EnchantingGUI gui, int power, int XPRequired) private static boolean itemValid(ItemStack item) { try { - ComplexItem.Type type = ComplexItemStack.of(item).getComplexItem().getType(); + ComplexItem.Type type = ComplexItem.of(item).getType(); return item.getType() != Material.AIR && ComplexEnchantment.getRegisteredEnchants() .stream() .filter(complexEnchantment -> diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItem.java b/src/main/java/me/zenox/evocraft/item/ComplexItem.java index 8fc6a4e..d567ab6 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItem.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItem.java @@ -15,6 +15,8 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; import java.io.Serializable; import java.util.ArrayList; @@ -25,7 +27,7 @@ @SuppressWarnings("UnstableApiUsage") public class ComplexItem { - public static final List itemRegistry = new ArrayList<>(); + public static final HashMap itemRegistry = new HashMap<>(); public static final NamespacedKey GLOBAL_ID = new NamespacedKey(EvoCraft.getPlugin(), "evocraft"); public static final NamespacedKey GLOW_ID = new NamespacedKey(EvoCraft.getPlugin(), "glow"); @@ -68,7 +70,7 @@ public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type this.abilities = abilities; this.variableMap.putAll(variableMap); - register(false); + register(); } public ComplexItem(String id, Boolean unique, Rarity rarity, Type type, Material material, Map stats, List abilities) { @@ -106,46 +108,29 @@ public ComplexItem(ItemSettings settings) { this.variableMap.putAll(settings.getVariableMap()); this.attributeModifiers = settings.getAttributeModifiers(); - register(false); + register(); } - protected ComplexItem(ItemSettings settings, boolean override) { - this.name = new TranslatableText(TranslatableText.Type.ITEM_NAME + "-" + settings.getId()); - this.id = settings.getId(); - this.lore = new TranslatableList(TranslatableText.Type.ITEM_LORE + "-" + id); - this.key = new NamespacedKey(EvoCraft.getPlugin(), id); - String str = String.valueOf(Math.abs(id.hashCode())); - this.customModelData = Ints.tryParse(str.substring(0, Math.min(7, str.length()))); - this.unique = settings.isUnique(); - this.glow = settings.doesGlow(); - this.rarity = settings.getRarity(); - this.type = settings.getType(); - this.material = settings.getMaterial(); - this.meta = settings.getMeta(); - this.stats = settings.getStats(); - this.skullURL = ""; - this.abilities = settings.getAbilities() == null ? new ArrayList<>() : new ArrayList<>(settings.getAbilities()); - this.variableMap.putAll(settings.getVariableMap()); - this.attributeModifiers = settings.getAttributeModifiers(); - - register(true); + /** + * Faster, more streamlined method to fetch the ComplexItem attribute without having to read or update ComplexItemMeta + * + * @param item The item to get the ComplexItem from + * @return The ComplexItem object of the item + */ + public static ComplexItem of(ItemStack item) { + PersistentDataContainer container = item.getItemMeta().getPersistentDataContainer(); + if (container.has(GLOBAL_ID, PersistentDataType.STRING)) + return itemRegistry.get(container.get(GLOBAL_ID, PersistentDataType.STRING)); + else return ComplexItemStack.of(item).getComplexItem(); } - private void register(boolean override){ - for (ComplexItem item: - new ArrayList<>(itemRegistry)) { - if (item.getId().equalsIgnoreCase(id)) { - if (!override) { - Util.logToConsole("Duplicate ComplexItem ID: " + id + " | Exact Match: " + item.equals(this)); - throw new IllegalArgumentException("ComplexItem ID cannot be duplicate"); - } else { - itemRegistry.remove(item); - break; - } - } + private void register(){ + if (itemRegistry.containsKey(id)) { + Util.logToConsole("Duplicate ComplexItem ID: " + id + " | Exact Match: " + itemRegistry.get(id).equals(this)); + throw new IllegalArgumentException("ComplexItem ID cannot be duplicate"); } - itemRegistry.add(this); + itemRegistry.put(id, this); } diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java index 4a28d1f..0aebbb8 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java @@ -41,7 +41,6 @@ */ public class ComplexItemMeta { - public static final NamespacedKey ABILITY_ID = new NamespacedKey(EvoCraft.getPlugin(), "ability"); public static final String VAR_PREFIX = "var_"; public static final String ATTRIBUTE_BASE_KEY = "base"; public static final VariableType RARITY_VAR = new VariableType<>("rarity", new LoreEntry("rarity", List.of("Rarity Lore")), VariableType.Priority.BELOW, (loreEntry, variable) -> loreEntry.setLore(List.of(((ComplexItem.Rarity) variable.getValue()).color() + ((ComplexItem.Rarity) variable.getValue()).getName()))); @@ -52,22 +51,16 @@ public class ComplexItemMeta { })), VariableType.Priority.BELOW, (loreEntry, variable) -> loreEntry.setLore(List.of(((ComplexItem.Type) variable.getValue()).getName()))); public static final NamespacedKey ENCHANT_KEY = new NamespacedKey(EvoCraft.getPlugin(), "complexEnchants"); private static final NamespacedKey ATTRIBUTE_KEY = new NamespacedKey(EvoCraft.getPlugin(), "attributes"); - private List abilities; private final List variableList = new ArrayList<>(); private HashMap complexEnchantments = new HashMap<>(); private List modifierList = new ArrayList<>(); private final ComplexItemStack complexItemStack; - public ComplexItemMeta(ComplexItemStack complexItemStack, List abilities) { - this.abilities = abilities == null ? new ArrayList<>() : new ArrayList<>(abilities); + public ComplexItemMeta(ComplexItemStack complexItemStack) { this.complexItemStack = complexItemStack; this.read(); } - public ComplexItemMeta(ComplexItemStack complexItemStack) { - this(complexItemStack, complexItemStack.getComplexItem().getAbilities()); - } - /** * Updates the ItemStack to match the current ComplexItemMeta */ @@ -159,7 +152,6 @@ public void updateItem() { // Write Abilities writeAbilityLore(lore); - dataContainer.set(ABILITY_ID, new ArrayListType(), new ArrayList<>(abilities.stream().map(Ability::getId).toList())); writeVariables(VariableType.Priority.BELOW_ABILITIES, dataContainer, lore, true); @@ -257,7 +249,7 @@ private void writeVariables(VariableType.Priority priority, PersistentDataContai } private void writeAbilityLore(LoreBuilder loreBuilder) { - for (Ability ability : this.abilities) { + for (Ability ability : complexItemStack.getComplexItem().getAbilities()) { List lore = new ArrayList<>(); lore.add(ChatColor.GOLD + (ability.isPassive() ? "Passive " : "") + (ability instanceof FullSetArmorAbility ? "Full Set " : "") + "Ability: " + ability.getDisplayName() + ChatColor.YELLOW + ChatColor.BOLD + " " + (ability instanceof ItemAbility ? ((ItemAbility) ability).getAction().getName() : "")); lore.addAll(ability.getLore()); @@ -358,10 +350,6 @@ public List getVariableList() { return variableList; } - public List getAbilities() { - return abilities; - } - public List getModifierList() { return modifierList; } diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java b/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java index 5e35bff..82b88c0 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java @@ -77,7 +77,7 @@ public static ComplexItemStack of(@NotNull ItemStack item) { Map vanillaEnchantments = item.getEnchantments(); - ComplexItem complexItem = Objects.requireNonNullElse(ItemRegistry.byItem(item), VanillaItem.of(item.getType())); + ComplexItem complexItem = Objects.requireNonNullElse(ComplexItem.of(item), VanillaItem.of(item.getType())); ComplexItemStack cItem = new ComplexItemStack(complexItem, item); // add vanilla variables??? @@ -175,7 +175,7 @@ public NamespacedKey getKey() { } public List getAbilities() { - return this.complexMeta.getAbilities(); + return this.complexItem.getAbilities(); } public ComplexItem getComplexItem() { diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index 8e195af..a444da9 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -15,15 +15,10 @@ import org.bukkit.Material; import org.bukkit.attribute.AttributeModifier; import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; -import java.util.Objects; public class ItemRegistry { @@ -737,7 +732,7 @@ public class ItemRegistry { @Deprecated public static List registerRecipes() { - for (ComplexItem item : ComplexItem.itemRegistry) { + for (ComplexItem item : ComplexItem.itemRegistry.values()) { registeredRecipes.addAll(item.getRecipes()); } @@ -759,26 +754,4 @@ public static List registerRecipes() { public static void registerItems() { Util.logToConsole(ChatColor.WHITE + "Registering " + ChatColor.GOLD + ComplexItem.itemRegistry.size() + ChatColor.WHITE + " items."); } - - @Nullable - public static ComplexItem byItem(ItemStack item) { - try { - PersistentDataContainer container = Objects.requireNonNull(item.getItemMeta()).getPersistentDataContainer(); - String id = container.get(ComplexItem.GLOBAL_ID, PersistentDataType.STRING); - return byId(id); - } catch (NullPointerException e) { - return null; - } - } - - @Nullable - public static ComplexItem byId(String id) { - for (ComplexItem item : ComplexItem.itemRegistry) { - if (id == null) return null; - if (id.equals(item.getId())) { - return item; - } - } - return null; - } } diff --git a/src/main/java/me/zenox/evocraft/item/VanillaItem.java b/src/main/java/me/zenox/evocraft/item/VanillaItem.java index 07af797..4fe7138 100644 --- a/src/main/java/me/zenox/evocraft/item/VanillaItem.java +++ b/src/main/java/me/zenox/evocraft/item/VanillaItem.java @@ -84,7 +84,7 @@ public VanillaItem(Material material) { * @param settings The settings to override. */ public VanillaItem(ItemSettings settings) { - super(settings.id(settings.getMaterial().getKey().getKey()), true); + super(settings.id(settings.getMaterial().getKey().getKey())); if (!settings.getMaterial().isItem()) throw new IllegalArgumentException("Material must have an item form"); for (VanillaItem item : new ArrayList<>(vanillaItemList)) { // remove the old item diff --git a/src/main/java/me/zenox/evocraft/recipe/ComplexChoice.java b/src/main/java/me/zenox/evocraft/recipe/ComplexChoice.java index 8e4bd8d..a63d028 100644 --- a/src/main/java/me/zenox/evocraft/recipe/ComplexChoice.java +++ b/src/main/java/me/zenox/evocraft/recipe/ComplexChoice.java @@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableMap; import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.item.ComplexItemStack; -import me.zenox.evocraft.item.ItemRegistry; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.RecipeChoice; import org.jetbrains.annotations.NotNull; @@ -39,7 +38,8 @@ public ComplexChoice(@NotNull Map choices) { @NotNull @Override public ItemStack getItemStack() { - return new ComplexItemStack(ItemRegistry.byId(((Map.Entry) choices.entrySet().toArray()[0]).getKey()), ((Map.Entry) choices.entrySet().toArray()[0]).getValue()).getItem(); + return new ComplexItemStack(ComplexItem.itemRegistry.get(((Map.Entry) choices.entrySet().toArray()[0]).getKey()), + ((Map.Entry) choices.entrySet().toArray()[0]).getValue()).getItem(); } public Map getChoices() { @@ -60,7 +60,7 @@ public ComplexChoice clone() { @Override public boolean test(@NotNull ItemStack t) { for (Map.Entry match : choices.entrySet()) { - if (ComplexItemStack.of(t).getComplexItem().equals(match.getKey()) && (t.getAmount() == match.getValue() || match.getValue() == -1)) { + if (ComplexItem.of(t).equals(match.getKey()) && (t.getAmount() == match.getValue() || match.getValue() == -1)) { return true; } } From 2475e417a2557a598bc7e2cbc08ef7bda0608f6a Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Thu, 2 Nov 2023 12:04:01 -0700 Subject: [PATCH 03/20] Ability Refactors and Class Abilities ClassAbility - modifiers - states - example: teleport Ability Refactor - Item Abilities renamed to EventAbility - Ability is new superclass without event related items - might need further refactoring to completly remove paramaterized type of consumer Cleanup of Abilities - Refactor useAbility method - Remove raw usage of Ability --- src/main/java/me/zenox/evocraft/EvoCraft.java | 1 + src/main/java/me/zenox/evocraft/Slot.java | 4 +- .../me/zenox/evocraft/abilities/Ability.java | 188 ++++++--------- .../evocraft/abilities/AbilityRegistry.java | 220 ++++++++++-------- .../evocraft/abilities/AbilitySettings.java | 29 ++- .../evocraft/abilities/ClassAbility.java | 207 ++++++++++++++++ .../evocraft/abilities/EventAbility.java | 121 ++++++++++ .../me/zenox/evocraft/abilities/Modifier.java | 109 +++++++++ .../{ => itemabilities}/AttackAbility.java | 10 +- .../FullSetArmorAbility.java | 6 +- .../FullSetAttackAbility.java | 7 +- .../FullSetDamagedAbility.java | 7 +- .../FullSetEntityDamagedAbility.java | 7 +- .../{ => itemabilities}/ItemAbility.java | 11 +- .../{ => itemabilities}/MoveAbility.java | 10 +- .../{ => itemabilities/specific}/Crucify.java | 3 +- .../specific}/EmberAttune.java | 3 +- .../{ => itemabilities/specific}/Psychic.java | 3 +- .../specific}/Transcendence.java | 3 +- .../zenox/evocraft/data/TranslatableText.java | 4 +- .../evocraft/events/PlayerUseItemEvent.java | 9 +- .../gameclass/ClassAbilityListener.java | 2 + .../evocraft/gameclass/ClickCombination.java | 18 ++ .../zenox/evocraft/gameclass/GameClass.java | 14 +- .../evocraft/gameclass/PassiveEffect.java | 4 - .../zenox/evocraft/gameclass/SkillNode.java | 80 ------- .../zenox/evocraft/gameclass/SkillTree.java | 48 ---- .../me/zenox/evocraft/item/ComplexItem.java | 14 +- .../zenox/evocraft/item/ComplexItemMeta.java | 6 +- .../zenox/evocraft/item/ComplexItemStack.java | 4 +- .../me/zenox/evocraft/item/ItemRegistry.java | 4 + .../me/zenox/evocraft/item/ItemSettings.java | 16 +- 32 files changed, 759 insertions(+), 413 deletions(-) create mode 100644 src/main/java/me/zenox/evocraft/abilities/ClassAbility.java create mode 100644 src/main/java/me/zenox/evocraft/abilities/EventAbility.java create mode 100644 src/main/java/me/zenox/evocraft/abilities/Modifier.java rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities}/AttackAbility.java (93%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities}/FullSetArmorAbility.java (88%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities}/FullSetAttackAbility.java (86%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities}/FullSetDamagedAbility.java (88%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities}/FullSetEntityDamagedAbility.java (89%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities}/ItemAbility.java (99%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities}/MoveAbility.java (86%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities/specific}/Crucify.java (98%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities/specific}/EmberAttune.java (95%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities/specific}/Psychic.java (98%) rename src/main/java/me/zenox/evocraft/abilities/{ => itemabilities/specific}/Transcendence.java (95%) create mode 100644 src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java delete mode 100644 src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java delete mode 100644 src/main/java/me/zenox/evocraft/gameclass/SkillNode.java delete mode 100644 src/main/java/me/zenox/evocraft/gameclass/SkillTree.java diff --git a/src/main/java/me/zenox/evocraft/EvoCraft.java b/src/main/java/me/zenox/evocraft/EvoCraft.java index b82ec6e..ccc195a 100644 --- a/src/main/java/me/zenox/evocraft/EvoCraft.java +++ b/src/main/java/me/zenox/evocraft/EvoCraft.java @@ -98,6 +98,7 @@ public void onEnable() { ItemRegistry.registerItems(); RecipeRegistry.registerRecipes(); EnchantRegistry.registerEnchants(); + TreeRegistry.registerNodes(); new Command(plugin); diff --git a/src/main/java/me/zenox/evocraft/Slot.java b/src/main/java/me/zenox/evocraft/Slot.java index d5e0966..7ae2cfe 100644 --- a/src/main/java/me/zenox/evocraft/Slot.java +++ b/src/main/java/me/zenox/evocraft/Slot.java @@ -42,10 +42,10 @@ public enum Slot { * @return The list of unique abilities that the player possesses */ @Deprecated - public static List uniqueEquipped(Player p) { + public static List> uniqueEquipped(Player p) { List items = Arrays.stream(new ItemStack[]{MAIN_HAND.item(p).get(0), OFF_HAND.item(p).get(0), HEAD.item(p).get(0), CHEST.item(p).get(0), LEGS.item(p).get(0), FEET.item(p).get(0)}) .filter(Objects::nonNull).toList(); - List abilities = new ArrayList<>(); + List> abilities = new ArrayList<>(); items.stream() .map(ComplexItemStack::of) .forEach((complexItemStack) -> abilities.addAll(complexItemStack.getAbilities())); diff --git a/src/main/java/me/zenox/evocraft/abilities/Ability.java b/src/main/java/me/zenox/evocraft/abilities/Ability.java index c177d29..b8437b9 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Ability.java +++ b/src/main/java/me/zenox/evocraft/abilities/Ability.java @@ -2,14 +2,11 @@ import com.archyx.aureliumskills.api.AureliumAPI; import me.zenox.evocraft.EvoCraft; -import me.zenox.evocraft.Slot; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; -import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; import org.bukkit.event.Event; @@ -23,74 +20,55 @@ import java.util.ArrayList; import java.util.List; +import static me.zenox.evocraft.abilities.ClassAbility.*; public abstract class Ability { - public static final List registeredAbilities = new ArrayList<>(); + public static final List> registeredAbilities = new ArrayList<>(); private final TranslatableText name; private final String id; - private final int manaCost; - private final double cooldown; - - private final Class eventType; - private final Slot slot; - private TranslatableList lore; + @SaveState + private int manaCost; + @SaveState + private double cooldown; private final boolean isPassive; + private TranslatableList lore; + @SaveState + protected TriConsumer executable; - private TriConsumer executable; - - protected Ability(String id, int manaCost, double cooldown, Slot slot) { - this(id, manaCost, cooldown, slot, false); - this.executable = this::runExecutable; - } - - protected Ability(String id, int manaCost, double cooldown, Slot slot, TriConsumer executable) { - this(id, manaCost, cooldown, slot, false); - this.executable = executable; - } - - protected Ability(AbilitySettings settings){ - this(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.getSlot(), settings.isPassive()); + public Ability(String id, int manaCost, double cooldown, boolean isPassive) { + this.name = new TranslatableText(TranslatableText.Type.ABILITY_NAME + "-" + id); + this.id = id; + this.manaCost = manaCost; + this.cooldown = cooldown; + this.lore = new TranslatableList(TranslatableText.Type.ABILITY_LORE + "-" + id); + this.isPassive = isPassive; } - protected Ability(AbilitySettings settings, TriConsumer executable){ - this(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.getSlot(), settings.isPassive()); + public Ability(String id, int manaCost, double cooldown, boolean isPassive, TriConsumer executable) { + this.name = new TranslatableText(TranslatableText.Type.ABILITY_NAME + "-" + id); + this.id = id; + this.manaCost = manaCost; + this.cooldown = cooldown; + this.lore = new TranslatableList(TranslatableText.Type.ABILITY_LORE + "-" + id); + this.isPassive = isPassive; this.executable = executable; } /** - * Internal constructor because exectuable go brr + * method getAbility
+ * gets the ability corresponding to the id * - * @param id The unique identifier of the ability - * @param manaCost The mana cost-per usage of the ability - * @param cooldown The cooldown of the ability, how long before it can be used again - * @param slot The slot that the item that contains the ability has to be in, i.e. main hand, head, etc - * @param isPassive Whether the ability is passive + * @param id the id to search for + * @return the ability- null if not found */ - private Ability(String id, int manaCost, double cooldown, Slot slot, boolean isPassive) { - this.id = id; - this.name = new TranslatableText(TranslatableText.Type.ABILITY_NAME + "-" + id); - this.lore = new TranslatableList(TranslatableText.Type.ABILITY_LORE + "-" + id); - this.cooldown = cooldown; - this.manaCost = manaCost; - this.slot = slot; - this.isPassive = isPassive; - - this.eventType = (Class) getType(); - if(this.eventType == null) throw new NullPointerException("Event type is null"); - - for (Ability ability : - registeredAbilities) { - if (ability.getId().equalsIgnoreCase(id)) { - Util.logToConsole("Duplicate Ability ID: " + id + " | Exact Match: " + ability.equals(this)); - throw new IllegalArgumentException("Ability ID cannot be duplicate"); - } - } - - Ability.registeredAbilities.add(this); + @Nullable + public static Ability getAbility(String id) { + for (Ability ability : registeredAbilities) if (ability.getId().equals(id)) return ability; + return null; } - private Type getType() { + protected Type getType() { Class clazz = getClass(); while (clazz != null) { Type type = clazz.getGenericSuperclass(); @@ -102,19 +80,6 @@ private Type getType() { return null; } - /** - * method getAbility
- * gets the ability corresponding to the id - * - * @param id the id to search for - * @return the ability- null if not found - */ - @Nullable - public static Ability getAbility(String id) { - for (Ability ability : registeredAbilities) if (ability.getId().equals(id)) return ability; - return null; - } - public String getDisplayName() { return name.toString(); } @@ -132,24 +97,9 @@ protected void setLore(TranslatableList list) { this.lore = list; } - public void useAbility(Event event) { - if (!this.eventType.isInstance(event)) return; - T e = (T) event; - if (!checkEvent(e)) return; - Player p = getPlayerOfEvent(e); - List items = getItem(p, e); - ItemStack item = null; - - // Perhaps change this in the future to support passing multiple items to the consumer - for(ItemStack i : items) { - if (i == null || i.getType() == Material.AIR || i.getItemMeta() == null) continue; - if (!ComplexItem.of(i).getAbilities().contains(this)) continue; - item = i; - break; - } - - if(item == null) return; + public abstract void useAbility(Event event); + protected boolean isAbilityOnCooldown(Player p) { PersistentDataContainer container = p.getPersistentDataContainer(); NamespacedKey cooldownKey = new NamespacedKey(EvoCraft.getPlugin(), getId() + "_cooldown"); Double cooldown; @@ -161,28 +111,38 @@ public void useAbility(Event event) { container.set(cooldownKey, PersistentDataType.DOUBLE, cooldown); } - // If the ability is on cooldown, return - if (cooldown != null && Math.ceil((cooldown - System.currentTimeMillis()) / 1000) > 0) { - if (!isPassive) Util.sendActionBar(p, ChatColor.WHITE + "" + ChatColor.BOLD + "ABILITY ON COOLDOWN (" + ChatColor.RED + Math.ceil((cooldown - System.currentTimeMillis()) / 100)/10 + "s" + ChatColor.WHITE + ")"); - return; - } + return cooldown != null && Math.ceil((cooldown - System.currentTimeMillis()) / 1000) > 0; + } - if (this.manaCost > 0) { - int resultingMana = ((int) AureliumAPI.getMana(p)) - manaCost; - if (resultingMana < 0) { - if (!isPassive) Util.sendActionBar(p, ChatColor.RED + "" + ChatColor.BOLD + "NOT ENOUGH MANA"); - return; - } else { - AureliumAPI.setMana(p, AureliumAPI.getMana(p) - manaCost); - } + protected void sendCooldownMessage(Player p) { + if (!isPassive) { + Util.sendActionBar(p, ChatColor.WHITE + "" + ChatColor.BOLD + "ABILITY ON COOLDOWN (" + ChatColor.RED + Math.ceil((getCooldownEndTime(p) - System.currentTimeMillis()) / 100) / 10 + "s" + ChatColor.WHITE + ")"); } + } - //AureliumAPI.getPlugin().getActionBar().setPaused(p, 20); - String manaMessage = this.manaCost > 0 ? ChatColor.AQUA + "-" + manaCost + " Mana " + "(" + ChatColor.GOLD + name + ChatColor.AQUA + ")" : ChatColor.GOLD + "Used " + name; - if(!isPassive) Util.sendActionBar(p, manaMessage); + protected double getCooldownEndTime(Player p) { + PersistentDataContainer container = p.getPersistentDataContainer(); + NamespacedKey cooldownKey = new NamespacedKey(EvoCraft.getPlugin(), getId() + "_cooldown"); + return container.get(cooldownKey, PersistentDataType.DOUBLE); + } - this.executable.accept(e, p, item); + protected boolean notEnoughMana(Player p, int requiredMana) { + return ((int) AureliumAPI.getMana(p)) < requiredMana; + } + protected void sendManaInsufficientMessage(Player p) { + if (!isPassive) Util.sendActionBar(p, ChatColor.RED + "" + ChatColor.BOLD + "NOT ENOUGH MANA"); + } + + protected void deductMana(Player p, int manaCost) { + AureliumAPI.setMana(p, AureliumAPI.getMana(p) - manaCost); + String manaMessage = manaCost > 0 ? ChatColor.AQUA + "-" + manaCost + " Mana " + "(" + ChatColor.GOLD + name + ChatColor.AQUA + ")" : ChatColor.GOLD + "Used " + name; + if (!isPassive) Util.sendActionBar(p, manaMessage); + } + + protected void setAbilityCooldown(Player p) { + PersistentDataContainer container = p.getPersistentDataContainer(); + NamespacedKey cooldownKey = new NamespacedKey(EvoCraft.getPlugin(), getId() + "_cooldown"); container.set(cooldownKey, PersistentDataType.DOUBLE, System.currentTimeMillis() + (getCooldown() * 1000)); } @@ -190,12 +150,6 @@ protected void runExecutable(T e, Player p, ItemStack itemStack) { Util.sendMessage(p, "Used the " + this.id + " ability"); } - abstract boolean checkEvent(T e); - - abstract Player getPlayerOfEvent(T e); - - abstract List getItem(Player p, T e); - public double getCooldown() { return this.cooldown; } @@ -208,15 +162,23 @@ public String getId() { return this.id; } - public Slot getSlot() { - return this.slot; - } - public boolean isPassive() { return isPassive; } - public Class getEventType() { - return eventType; + public TriConsumer getExecutable() { + return this.executable; + } + + public void setManaCost(int manaCost) { + this.manaCost = manaCost; + } + + public void setCooldown(double cooldown) { + this.cooldown = cooldown; + } + + public void setExecutable(TriConsumer executable) { + this.executable = executable; } } diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index a111fe5..25496f7 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -1,6 +1,7 @@ package me.zenox.evocraft.abilities; import me.zenox.evocraft.Slot; +import me.zenox.evocraft.abilities.itemabilities.*; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -12,161 +13,176 @@ public class AbilityRegistry { public static final ItemAbility SOUL_RIFT = new ItemAbility(new AbilitySettings() - .setId("soul_rift") + .id("soul_rift") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(100) - .setCooldown(50), ItemAbility::soulRiftAbility); + .manaCost(100) + .cooldown(50), ItemAbility::soulRiftAbility); public static final ItemAbility MAGIC_MISSILE_COMBUST_6 = new ItemAbility(new AbilitySettings() - .setId("magic_missile") + .id("magic_missile") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(0) - .setCooldown(0), + .manaCost(0) + .cooldown(0), (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.magicMissileAbility(event, p, item,true, 6)); public static final ItemAbility MAGIC_MISSILE_DEV = new ItemAbility(new AbilitySettings() - .setId("magic_missile_dev") + .id("magic_missile_dev") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(0) - .setCooldown(0), (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.magicMissileAbility(event, p, item, false, 15)); + .manaCost(0) + .cooldown(0), (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.magicMissileAbility(event, p, item, false, 15)); public static final ItemAbility SMALL_EMBER_SHOOT = new ItemAbility(new AbilitySettings() - .setId("small_ember_shoot") + .id("small_ember_shoot") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(10) - .setCooldown(0), ItemAbility::smallEmberShootAbility); + .manaCost(10) + .cooldown(0), ItemAbility::smallEmberShootAbility); public static final ItemAbility EMBER_SHOOT = new ItemAbility(new AbilitySettings() - .setId("ember_shoot") + .id("ember_shoot") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(50) - .setCooldown(0), ItemAbility::emberShootAbility); + .manaCost(50) + .cooldown(0), ItemAbility::emberShootAbility); public static final ItemAbility CENTRALIZE = new ItemAbility(new AbilitySettings() - .setId("centralize") + .id("centralize") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(150) - .setCooldown(0), (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.centralizeAbility(event, p, item, false, 30)); + .manaCost(150) + .cooldown(0), (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.centralizeAbility(event, p, item, false, 30)); public static final ItemAbility CENTRALIZE_CORRUPT = new ItemAbility(new AbilitySettings()/*"centralize_corrupt", ItemAbility.AbilityAction.RIGHT_CLICK_ALL, 250, 0, (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.centralizeAbility(event, p, item, true, 45)*/ - .setId("centralize_corrupt") + .id("centralize_corrupt") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(250) - .setCooldown(0), (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.centralizeAbility(event, p, item, true, 45)); + .manaCost(250) + .cooldown(0), (PlayerInteractEvent event, Player p, ItemStack item) -> ItemAbility.centralizeAbility(event, p, item, true, 45)); public static final ItemAbility OBSIDIAN_SHARD = new ItemAbility(new AbilitySettings() - .setId("obsidian_shard") + .id("obsidian_shard") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(25) - .setCooldown(0), ItemAbility::obsidianShardAbility); + .manaCost(25) + .cooldown(0), ItemAbility::obsidianShardAbility); public static final ItemAbility TARHELM = new ItemAbility(new AbilitySettings() - .setId("tarhelm") + .id("tarhelm") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(150) - .setCooldown(30), ItemAbility::tarhelmAbility); + .manaCost(150) + .cooldown(30), ItemAbility::tarhelmAbility); public static final AttackAbility JUSTICE = new AttackAbility(new AbilitySettings() - .setId("justice") - .setManaCost(0) - .setCooldown(0) - .setSlot(Slot.MAIN_HAND), AttackAbility::justiceAbility); + .id("justice") + .manaCost(0) + .cooldown(0) + .slot(Slot.MAIN_HAND), AttackAbility::justiceAbility); public static final AttackAbility VERTEX_ABILITY = new AttackAbility(new AbilitySettings() - .setId("vertex_ability") - .setManaCost(20) - .setCooldown(0) - .setSlot(Slot.MAIN_HAND), AttackAbility::vertexAbility); + .id("vertex_ability") + .manaCost(20) + .cooldown(0) + .slot(Slot.MAIN_HAND), AttackAbility::vertexAbility); public static final AttackAbility DARK_FURY = new AttackAbility(new AbilitySettings() - .setId("dark_fury") - .setManaCost(20) - .setCooldown(0) - .setSlot(Slot.MAIN_HAND), AttackAbility::darkFuryAbility); + .id("dark_fury") + .manaCost(20) + .cooldown(0) + .slot(Slot.MAIN_HAND), AttackAbility::darkFuryAbility); public static final FullSetAttackAbility TEST_FULLSET = new FullSetAttackAbility(new AbilitySettings() - .setId("test_fullset") - .setManaCost(10) - .setCooldown(0) - .setSlot(Slot.ARMOR), FullSetAttackAbility::testFullSetAbility); + .id("test_fullset") + .manaCost(10) + .cooldown(0) + .slot(Slot.ARMOR), FullSetAttackAbility::testFullSetAbility); public static final ItemAbility TERRA_STRIKE = new ItemAbility(new AbilitySettings() - .setId("terra_strike") + .id("terra_strike") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(10) - .setCooldown(5), ItemAbility::terraStrikeAbility); + .manaCost(10) + .cooldown(5), ItemAbility::terraStrikeAbility); public static final FullSetAttackAbility ROARING_FLAME = new FullSetAttackAbility(new AbilitySettings() - .setId("roaring_flame") - .setPassive(true) - .setManaCost(0) - .setCooldown(0) - .setSlot(Slot.ARMOR), FullSetAttackAbility::roaringFlameAbility); + .id("roaring_flame") + .passive(true) + .manaCost(0) + .cooldown(0) + .slot(Slot.ARMOR), FullSetAttackAbility::roaringFlameAbility); public static final MoveAbility LAVA_GLIDER = new MoveAbility(new AbilitySettings() - .setId("lava_glider") - .setPassive(true) - .setManaCost(0) - .setCooldown(0) - .setSlot(Slot.ARMOR), MoveAbility::lavaGliderAbility); + .id("lava_glider") + .passive(true) + .manaCost(0) + .cooldown(0) + .slot(Slot.ARMOR), MoveAbility::lavaGliderAbility); public static final ItemAbility DARKCALL = new ItemAbility(new AbilitySettings() - .setId("darkcall") + .id("darkcall") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(0) - .setCooldown(60), ItemAbility::darkcallerAbility); + .manaCost(0) + .cooldown(60), ItemAbility::darkcallerAbility); public static final ItemAbility GILDED_CONSUME = new ItemAbility(new AbilitySettings() - .setId("gilded_consume") + .id("gilded_consume") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(0) - .setCooldown(0), ItemAbility::consumeAbility); + .manaCost(0) + .cooldown(0), ItemAbility::consumeAbility); public static final ItemAbility VOID_WARP = new ItemAbility(new AbilitySettings() - .setId("void_warp") + .id("void_warp") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(100) - .setCooldown(1), ItemAbility::voidWarpAbility); + .manaCost(100) + .cooldown(1), ItemAbility::voidWarpAbility); public static final ItemAbility START_BUTTON = new ItemAbility(new AbilitySettings() - .setId("start_button") + .id("start_button") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(0) - .setCooldown(0), ItemAbility::startButtonAbility); + .manaCost(0) + .cooldown(0), ItemAbility::startButtonAbility); public static final ItemAbility PORTALIZER = new ItemAbility(new AbilitySettings() - .setId("portalizer") + .id("portalizer") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(0) - .setCooldown(0), ItemAbility::portalizerAbility); + .manaCost(0) + .cooldown(0), ItemAbility::portalizerAbility); public static final ItemAbility SNOW_SHOT = new ItemAbility(new AbilitySettings() - .setId("snow_shot") + .id("snow_shot") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(5) - .setCooldown(0), ItemAbility::snowShotAbility); + .manaCost(5) + .cooldown(0), ItemAbility::snowShotAbility); public static final FullSetEntityDamagedAbility DIAMANTINE_SHIELD = new FullSetEntityDamagedAbility(new AbilitySettings() - .setId("diamantine_shield") - .setPassive(true) - .setManaCost(0) - .setCooldown(0) - .setSlot(Slot.ARMOR), FullSetEntityDamagedAbility::diamantineShieldAbility); + .id("diamantine_shield") + .passive(true) + .manaCost(0) + .cooldown(0) + .slot(Slot.ARMOR), FullSetEntityDamagedAbility::diamantineShieldAbility); public static final FullSetDamagedAbility GOLEMS_HEART = new FullSetDamagedAbility(new AbilitySettings() - .setId("golems_heart") - .setPassive(true) - .setManaCost(0) - .setCooldown(0) - .setSlot(Slot.ARMOR), FullSetDamagedAbility::golemsHeartAbility, List.of(EntityDamageEvent.DamageCause.ENTITY_EXPLOSION, EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)); + .id("golems_heart") + .passive(true) + .manaCost(0) + .cooldown(0) + .slot(Slot.ARMOR), FullSetDamagedAbility::golemsHeartAbility, List.of(EntityDamageEvent.DamageCause.ENTITY_EXPLOSION, EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)); public static final FullSetDamagedAbility TITANS_HEART = new FullSetDamagedAbility(new AbilitySettings() - .setId("titans_heart") - .setPassive(true) - .setManaCost(0) - .setCooldown(0) - .setSlot(Slot.ARMOR), FullSetDamagedAbility::titansHeartAbility, List.of(EntityDamageEvent.DamageCause.ENTITY_EXPLOSION, EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)); + .id("titans_heart") + .passive(true) + .manaCost(0) + .cooldown(0) + .slot(Slot.ARMOR), FullSetDamagedAbility::titansHeartAbility, List.of(EntityDamageEvent.DamageCause.ENTITY_EXPLOSION, EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)); public static final ItemAbility CRYSTAL_SPIKE = new ItemAbility(new AbilitySettings() - .setId("crystal_spike") + .id("crystal_spike") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(75) - .setCooldown(1), ItemAbility::crystalSpikeAbility); + .manaCost(75) + .cooldown(1), ItemAbility::crystalSpikeAbility); public static final ItemAbility MANA_BOOST = new ItemAbility(new AbilitySettings() - .setId("mana_boost") + .id("mana_boost") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(0) - .setCooldown(0), ItemAbility::manaBoostAbility); + .manaCost(0) + .cooldown(0), ItemAbility::manaBoostAbility); public static final ItemAbility COLOSSAL_SWEEP = new ItemAbility(new AbilitySettings() - .setId("colossal_sweep") + .id("colossal_sweep") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(100) - .setCooldown(0), ItemAbility::colossalSweepAbility); + .manaCost(100) + .cooldown(0), ItemAbility::colossalSweepAbility); public static final ItemAbility THUNDERSTRIKE = new ItemAbility(new AbilitySettings() - .setId("thunderstrike") + .id("thunderstrike") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .setManaCost(50) - .setCooldown(0), ItemAbility::thunderstrikeAbility); + .manaCost(50) + .cooldown(0), ItemAbility::thunderstrikeAbility); + // Class Abilities + public static final ClassAbility TELEPORT = new ClassAbility(new AbilitySettings() + .id("mage_teleport") + .manaCost(35) + .cooldown(0) + .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_1", +2)) + .modifier(Modifier.of(Modifier.Type.MANA_COST, "teleport_mana_1", -5)) + .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_1", +1)) + .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_dark", ClassAbility::darkTeleport)) + .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_2", +2)) + .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_surge", ClassAbility::surgeTeleport)) + .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_4", +4)) + .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_arcane", ClassAbility::arcaneTeleport)) + , ClassAbility::teleportAbility); + public static void registerAbilities(){ - Util.logToConsole("Registering %s abilities.".formatted(ChatColor.GOLD + "" + Ability.registeredAbilities.size() + "" + ChatColor.RESET)); + Util.logToConsole("Registering %s abilities.".formatted(ChatColor.GOLD + "" + Ability.registeredAbilities.size() + ChatColor.RESET)); } } diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java index 1c43ec6..140bfb9 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java @@ -1,7 +1,10 @@ package me.zenox.evocraft.abilities; import me.zenox.evocraft.Slot; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -13,6 +16,7 @@ public class AbilitySettings { private double cooldown; private Slot slot; private boolean isPassive; + private List modifiers; // Ability-Specific Settings private ItemAbility.AbilityAction abilityAction; @@ -24,13 +28,14 @@ public AbilitySettings() { this.slot = Slot.EITHER_HAND; this.isPassive = false; this.abilityAction = ItemAbility.AbilityAction.NONE; + this.modifiers = new ArrayList<>(); } public String getId() { return id; } - public AbilitySettings setId(String id) { + public AbilitySettings id(String id) { this.id = id; return this; } @@ -39,7 +44,7 @@ public int getManaCost() { return manaCost; } - public AbilitySettings setManaCost(int manaCost) { + public AbilitySettings manaCost(int manaCost) { this.manaCost = manaCost; return this; } @@ -48,7 +53,7 @@ public double getCooldown() { return cooldown; } - public AbilitySettings setCooldown(double cooldown) { + public AbilitySettings cooldown(double cooldown) { this.cooldown = cooldown; return this; } @@ -57,7 +62,7 @@ public Slot getSlot() { return slot; } - public AbilitySettings setSlot(Slot slot) { + public AbilitySettings slot(Slot slot) { this.slot = slot; return this; } @@ -66,7 +71,7 @@ public boolean isPassive() { return isPassive; } - public AbilitySettings setPassive(boolean passive) { + public AbilitySettings passive(boolean passive) { isPassive = passive; return this; } @@ -79,4 +84,18 @@ public AbilitySettings setAbilityAction(ItemAbility.AbilityAction abilityAction) this.abilityAction = abilityAction; return this; } + + public List getModifiers() { + return modifiers; + } + + public AbilitySettings modifiers(List modifiers) { + this.modifiers = modifiers; + return this; + } + + public AbilitySettings modifier(Modifier modifier) { + this.modifiers.add(modifier); + return this; + } } diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java new file mode 100644 index 0000000..991816f --- /dev/null +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -0,0 +1,207 @@ +package me.zenox.evocraft.abilities; + +import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.util.Geo; +import me.zenox.evocraft.util.TriConsumer; +import org.bukkit.Particle; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.Vector; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ClassAbility extends Ability { + final List modifiers; + + @SaveState + private int strength; + + @SaveState + private int charges; + + @SaveState + private int range; + + private final Map baseState; + + public ClassAbility(AbilitySettings settings, TriConsumer executable) { + super(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.isPassive(), executable); + this.modifiers = settings.getModifiers(); + this.baseState = getState(); + } + + public Map getState(){ + Map map = new HashMap<>(); + for (Class clazz = this.getClass(); clazz != null; clazz = clazz.getSuperclass()){ + for (Field f : clazz.getDeclaredFields()){ + if (f.isAnnotationPresent(SaveState.class)){ + try { + f.setAccessible(true); + map.put(f.getName(), f.get(this)); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + } + return map; + } + + + // Override the useAbility method to consider the modified mana cost, actually dont use this for now + // TODO: should abilities only be used through the directUseAbility method? + @Override + public void useAbility(Event event) { + PlayerInteractEvent e = (PlayerInteractEvent) event; + Player p = e.getPlayer(); + + // TODO: fetch level from player's ability tree + applyModifiers(modifiers.size()); // apply modifiers to the ability + + // Check if ability is on cooldown + if (isAbilityOnCooldown(p)) { + sendCooldownMessage(p); + return; + } + + if (notEnoughMana(p, this.getManaCost())) { + sendManaInsufficientMessage(p); + return; + } + + deductMana(p, this.getManaCost()); + this.runExecutable(null, p, null); + setAbilityCooldown(p); + + reset(); // reset the ability to its original state + + } + + public void applyModifiers(int level){ + for(int i = 0; i < level; i++){ + modifiers.get(i).modify(this); + } + } + + // Recreate the ability to its original state + public void reset(){ + for (Class clazz = this.getClass(); clazz != null; clazz = clazz.getSuperclass()) { + for (Field f : clazz.getDeclaredFields()) { + if (f.isAnnotationPresent(SaveState.class)) { + try { + f.setAccessible(true); + f.set(this, baseState.get(f.getName())); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + } + } + + public List getModifiers() { + return modifiers; + } + + public int getStrength() { + return strength; + } + + public void setStrength(int strength) { + this.strength = strength; + } + + public int getCharges() { + return charges; + } + + public void setCharges(int charges) { + this.charges = charges; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public static void teleportAbility(PlayerInteractEvent event, Player player, ItemStack itemStack) { + // Teleport the player up to 5 blocks forward, but less if it's a block + int maxDistance = 5; + int distance = 0; + while (distance < maxDistance) { + if (player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).getBlock().getType().isSolid()) { + break; + } + distance++; + } + player.teleport(player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance))); + + // Create particles along the path + List tracedPath = Geo.lerpEdges(List.of(player.getLocation().toVector(), player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).toVector()), 15); + new BukkitRunnable(){ + int a = 0; + @Override + public void run() { + if (a > tracedPath.size()) { + cancel(); + return; + } + player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 1.8, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 123, 255), 3)); + a++; + } + }.runTaskTimer(EvoCraft.getPlugin(), 0, 1); + } + + /** + * Dark Teleport Executable that damages entities along the path + * @param event + * @param player + * @param itemStack + */ + public static void darkTeleport(PlayerInteractEvent event, Player player, ItemStack itemStack) { + // Teleport the player up to 5 blocks forward, but less if it's a block + int maxDistance = 5; + int distance = 0; + while (distance < maxDistance) { + if (player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).getBlock().getType().isSolid()) { + break; + } + distance++; + } + player.teleport(player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance))); + + // Create particles along the path + List tracedPath = Geo.lerpEdges(List.of(player.getLocation().toVector(), player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).toVector()), 15); + new BukkitRunnable(){ + int a = 0; + @Override + public void run() { + if (a > tracedPath.size()) { + cancel(); + return; + } + player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 1.8, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 123, 255), 3)); + a++; + } + }.runTaskTimer(EvoCraft.getPlugin(), 0, 1); + + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface SaveState { + } +} \ No newline at end of file diff --git a/src/main/java/me/zenox/evocraft/abilities/EventAbility.java b/src/main/java/me/zenox/evocraft/abilities/EventAbility.java new file mode 100644 index 0000000..6f9fff3 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/abilities/EventAbility.java @@ -0,0 +1,121 @@ +package me.zenox.evocraft.abilities; + +import me.zenox.evocraft.Slot; +import me.zenox.evocraft.item.ComplexItem; +import me.zenox.evocraft.util.TriConsumer; +import me.zenox.evocraft.util.Util; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + + +public abstract class EventAbility extends Ability { + + private final Class eventType; + private final Slot slot; + + protected EventAbility(String id, int manaCost, double cooldown, Slot slot) { + this(id, manaCost, cooldown, slot, false); + this.executable = this::runExecutable; + } + + protected EventAbility(String id, int manaCost, double cooldown, Slot slot, TriConsumer executable) { + this(id, manaCost, cooldown, slot, false); + this.executable = executable; + } + + protected EventAbility(@NotNull AbilitySettings settings){ + this(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.getSlot(), settings.isPassive()); + } + + protected EventAbility(@NotNull AbilitySettings settings, TriConsumer executable){ + this(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.getSlot(), settings.isPassive()); + this.executable = executable; + } + + /** + * Internal constructor because exectuable go brr + * + * @param id The unique identifier of the ability + * @param manaCost The mana cost-per usage of the ability + * @param cooldown The cooldown of the ability, how long before it can be used again + * @param slot The slot that the item that contains the ability has to be in, i.e. main hand, head, etc + * @param isPassive Whether the ability is passive + */ + private EventAbility(String id, int manaCost, double cooldown, Slot slot, boolean isPassive) { + super(id, manaCost, cooldown, isPassive); + this.slot = slot; + + this.eventType = (Class) getType(); + if(this.eventType == null) throw new NullPointerException("Event type is null"); + + for (Ability ability : + registeredAbilities) { + if (ability.getId().equalsIgnoreCase(id)) { + Util.logToConsole("Duplicate Ability ID: " + id + " | Exact Match: " + ability.equals(this)); + throw new IllegalArgumentException("Ability ID cannot be duplicate"); + } + } + + Ability.registeredAbilities.add(this); + } + + @Override + public void useAbility(Event event) { + if (!isValidEvent(event)) return; + T e = (T) event; + Player p = getPlayerOfEvent(e); + ItemStack item = getValidItem(p, e); + + if (item == null) return; + + if (isAbilityOnCooldown(p)) { + sendCooldownMessage(p); + return; + } + + if (notEnoughMana(p, this.getManaCost())) { + sendManaInsufficientMessage(p); + return; + } + + deductMana(p, this.getManaCost()); + this.executable.accept(e, p, item); + setAbilityCooldown(p); + } + + protected boolean isValidEvent(Event event) { + if (!this.eventType.isInstance(event)) return false; + T e = (T) event; + return checkEvent(e); + } + + protected ItemStack getValidItem(Player p, T e) { + List items = getItem(p, e); + for (ItemStack i : items) { + if (i == null || i.getType() == Material.AIR || i.getItemMeta() == null) continue; + if (!ComplexItem.of(i).getAbilities().contains(this)) continue; + return i; + } + return null; + } + + protected abstract boolean checkEvent(T e); + + protected abstract Player getPlayerOfEvent(T e); + + protected abstract List getItem(Player p, T e); + + public Slot getSlot() { + return this.slot; + } + + public Class getEventType() { + return eventType; + } + +} diff --git a/src/main/java/me/zenox/evocraft/abilities/Modifier.java b/src/main/java/me/zenox/evocraft/abilities/Modifier.java new file mode 100644 index 0000000..4f12945 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/abilities/Modifier.java @@ -0,0 +1,109 @@ +package me.zenox.evocraft.abilities; + +import me.zenox.evocraft.data.TranslatableList; +import me.zenox.evocraft.data.TranslatableText; +import me.zenox.evocraft.util.TriConsumer; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public abstract class Modifier { + + private final String id; + private final TranslatableText name; + private final TranslatableList lore; + + public enum Type { + MANA_COST { + @Override + Modifier create(String id, double value) { + return new Modifier(id) { + @Override + void modify(ClassAbility ability) { + ability.setManaCost(ability.getManaCost() + (int) value); + } + }; + } + }, + COOLDOWN { + @Override + Modifier create(String id, double value) { + return new Modifier(id) { + @Override + void modify(ClassAbility ability) { + ability.setCooldown(ability.getCooldown() + value); + } + }; + } + }, + EXECUTABLE { + @Override + Modifier create(String id, TriConsumer executable) { + return new Modifier(id) { + @Override + void modify(ClassAbility ability) { + ability.setExecutable(executable); + } + }; + } + }, + RANGE { + @Override + Modifier create(String id, double value) { + return new Modifier(id) { + @Override + void modify(ClassAbility ability) { + ability.setRange(ability.getRange() + (int) value); + } + }; + } + }, + CHARGE { + @Override + Modifier create(String id, double value) { + return new Modifier(id) { + @Override + void modify(ClassAbility ability) { + ability.setCharges(ability.getCharges() + (int) value); + } + }; + } + }; + + Modifier create(String id, double value) { + throw new UnsupportedOperationException("This operation is not supported for type: " + this); + } + + Modifier create(String id, TriConsumer executable) { + throw new UnsupportedOperationException("This operation is not supported for type: " + this); + } + } + + private Modifier(String id) { + this.id = id; + this.name = new TranslatableText(TranslatableText.Type.MODIFIER_NAME + "-" + id); + this.lore = new TranslatableList(TranslatableText.Type.MODIFIER_LORE + "-" + id); + } + + public static Modifier of(Type type, String id, double value) { + return type.create(id, value); + } + + public static Modifier of(Type type, String id, TriConsumer executable) { + return type.create(id, executable); + } + + abstract void modify(ClassAbility ability); + + public String id() { + return id; + } + + public TranslatableText name() { + return name; + } + + public TranslatableList lore() { + return lore; + } +} diff --git a/src/main/java/me/zenox/evocraft/abilities/AttackAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/AttackAbility.java similarity index 93% rename from src/main/java/me/zenox/evocraft/abilities/AttackAbility.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/AttackAbility.java index 932fefe..13273ee 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AttackAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/AttackAbility.java @@ -1,7 +1,9 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities; import me.zenox.evocraft.Slot; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.AbilitySettings; +import me.zenox.evocraft.abilities.EventAbility; import me.zenox.evocraft.util.Geo; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; @@ -20,7 +22,7 @@ import java.util.List; import java.util.Random; -public class AttackAbility extends Ability { +public class AttackAbility extends EventAbility { public AttackAbility(AbilitySettings settings) { @@ -41,12 +43,12 @@ protected boolean checkEvent(EntityDamageByEntityEvent event) { } @Override - Player getPlayerOfEvent(EntityDamageByEntityEvent e) { + protected Player getPlayerOfEvent(EntityDamageByEntityEvent e) { return ((Player) e.getDamager()); } @Override - List getItem(Player p, EntityDamageByEntityEvent e) { + protected List getItem(Player p, EntityDamageByEntityEvent e) { return this.getSlot().item(p); } diff --git a/src/main/java/me/zenox/evocraft/abilities/FullSetArmorAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetArmorAbility.java similarity index 88% rename from src/main/java/me/zenox/evocraft/abilities/FullSetArmorAbility.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetArmorAbility.java index dd0f861..d8aa863 100644 --- a/src/main/java/me/zenox/evocraft/abilities/FullSetArmorAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetArmorAbility.java @@ -1,6 +1,8 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities; import me.zenox.evocraft.Slot; +import me.zenox.evocraft.abilities.AbilitySettings; +import me.zenox.evocraft.abilities.EventAbility; import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.util.TriConsumer; import org.bukkit.entity.Player; @@ -10,7 +12,7 @@ /** * General Armor Ability with no class */ -public abstract class FullSetArmorAbility extends Ability { +public abstract class FullSetArmorAbility extends EventAbility { public FullSetArmorAbility(AbilitySettings settings) { super(settings); } diff --git a/src/main/java/me/zenox/evocraft/abilities/FullSetAttackAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetAttackAbility.java similarity index 86% rename from src/main/java/me/zenox/evocraft/abilities/FullSetAttackAbility.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetAttackAbility.java index 7eee2f2..bce86fc 100644 --- a/src/main/java/me/zenox/evocraft/abilities/FullSetAttackAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetAttackAbility.java @@ -1,5 +1,6 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities; +import me.zenox.evocraft.abilities.AbilitySettings; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.entity.Player; @@ -29,12 +30,12 @@ protected boolean checkEventExec(EntityDamageByEntityEvent e) { } @Override - Player getPlayerOfEvent(EntityDamageByEntityEvent e) { + protected Player getPlayerOfEvent(EntityDamageByEntityEvent e) { return ((Player) e.getDamager()); } @Override - List getItem(Player p, EntityDamageByEntityEvent e) { + protected List getItem(Player p, EntityDamageByEntityEvent e) { return this.getSlot().item(p); } diff --git a/src/main/java/me/zenox/evocraft/abilities/FullSetDamagedAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetDamagedAbility.java similarity index 88% rename from src/main/java/me/zenox/evocraft/abilities/FullSetDamagedAbility.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetDamagedAbility.java index d2dbdcc..46d3ec9 100644 --- a/src/main/java/me/zenox/evocraft/abilities/FullSetDamagedAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetDamagedAbility.java @@ -1,5 +1,6 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities; +import me.zenox.evocraft.abilities.AbilitySettings; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.entity.Player; @@ -36,12 +37,12 @@ protected boolean checkEventExec(EntityDamageEvent e) { } @Override - Player getPlayerOfEvent(EntityDamageEvent e) { + protected Player getPlayerOfEvent(EntityDamageEvent e) { return ((Player) e.getEntity()); } @Override - List getItem(Player p, EntityDamageEvent e) { + protected List getItem(Player p, EntityDamageEvent e) { return this.getSlot().item(p); } diff --git a/src/main/java/me/zenox/evocraft/abilities/FullSetEntityDamagedAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetEntityDamagedAbility.java similarity index 89% rename from src/main/java/me/zenox/evocraft/abilities/FullSetEntityDamagedAbility.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetEntityDamagedAbility.java index fed346a..95c9fd1 100644 --- a/src/main/java/me/zenox/evocraft/abilities/FullSetEntityDamagedAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/FullSetEntityDamagedAbility.java @@ -1,5 +1,6 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities; +import me.zenox.evocraft.abilities.AbilitySettings; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.Color; @@ -30,12 +31,12 @@ protected boolean checkEventExec(EntityDamageByEntityEvent e) { } @Override - Player getPlayerOfEvent(EntityDamageByEntityEvent e) { + protected Player getPlayerOfEvent(EntityDamageByEntityEvent e) { return ((Player) e.getEntity()); } @Override - List getItem(Player p, EntityDamageByEntityEvent e) { + protected List getItem(Player p, EntityDamageByEntityEvent e) { return this.getSlot().item(p); } diff --git a/src/main/java/me/zenox/evocraft/abilities/ItemAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java similarity index 99% rename from src/main/java/me/zenox/evocraft/abilities/ItemAbility.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java index 7bbc9d1..7e90ba6 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ItemAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java @@ -1,4 +1,4 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities; import com.archyx.aureliumskills.api.AureliumAPI; import com.comphenix.protocol.PacketType; @@ -15,6 +15,9 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import me.zenox.evocraft.Slot; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.AbilitySettings; +import me.zenox.evocraft.abilities.EventAbility; +import me.zenox.evocraft.abilities.itemabilities.specific.EmberAttune; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.item.ItemRegistry; @@ -44,7 +47,7 @@ import static me.zenox.evocraft.item.ItemRegistry.TOTEM_POLE; import static me.zenox.evocraft.util.Util.getNearbyBlocks; -public class ItemAbility extends Ability { +public class ItemAbility extends EventAbility { private static final int SHARD_SPEED = 3; private static final int SHARD_RADIUS = 3; private final AbilityAction action; @@ -81,12 +84,12 @@ public ItemAbility(String id, AbilityAction action, int manaCost, double cooldow } @Override - Player getPlayerOfEvent(PlayerInteractEvent e) { + protected Player getPlayerOfEvent(PlayerInteractEvent e) { return e.getPlayer(); } @Override - List getItem(Player p, PlayerInteractEvent e) { + protected List getItem(Player p, PlayerInteractEvent e) { return Arrays.stream(new ItemStack[]{e.getItem()}).filter(Objects::nonNull).toList(); } diff --git a/src/main/java/me/zenox/evocraft/abilities/MoveAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/MoveAbility.java similarity index 86% rename from src/main/java/me/zenox/evocraft/abilities/MoveAbility.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/MoveAbility.java index a0eb7c2..bc95408 100644 --- a/src/main/java/me/zenox/evocraft/abilities/MoveAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/MoveAbility.java @@ -1,7 +1,9 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities; import me.zenox.evocraft.Slot; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.AbilitySettings; +import me.zenox.evocraft.abilities.EventAbility; import me.zenox.evocraft.util.TriConsumer; import org.bukkit.Location; import org.bukkit.Material; @@ -14,7 +16,7 @@ import java.util.List; import java.util.Random; -public class MoveAbility extends Ability { +public class MoveAbility extends EventAbility { public MoveAbility(AbilitySettings settings) { super(settings); @@ -34,12 +36,12 @@ protected boolean checkEvent(PlayerMoveEvent e) { } @Override - Player getPlayerOfEvent(PlayerMoveEvent e) { + protected Player getPlayerOfEvent(PlayerMoveEvent e) { return ((PlayerMoveEvent) e).getPlayer(); } @Override - List getItem(Player p, PlayerMoveEvent e) { + protected List getItem(Player p, PlayerMoveEvent e) { return this.getSlot().item(p); } diff --git a/src/main/java/me/zenox/evocraft/abilities/Crucify.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Crucify.java similarity index 98% rename from src/main/java/me/zenox/evocraft/abilities/Crucify.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Crucify.java index e498440..7dc3beb 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Crucify.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Crucify.java @@ -1,6 +1,7 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities.specific; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.item.ComplexItem; import org.bukkit.*; import org.bukkit.entity.Damageable; diff --git a/src/main/java/me/zenox/evocraft/abilities/EmberAttune.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/EmberAttune.java similarity index 95% rename from src/main/java/me/zenox/evocraft/abilities/EmberAttune.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/EmberAttune.java index fabbcae..4394b74 100644 --- a/src/main/java/me/zenox/evocraft/abilities/EmberAttune.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/EmberAttune.java @@ -1,5 +1,6 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities.specific; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.item.LoreEntry; diff --git a/src/main/java/me/zenox/evocraft/abilities/Psychic.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Psychic.java similarity index 98% rename from src/main/java/me/zenox/evocraft/abilities/Psychic.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Psychic.java index 708e0e7..a66175e 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Psychic.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Psychic.java @@ -1,4 +1,4 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities.specific; import com.archyx.aureliumskills.api.AureliumAPI; import com.archyx.aureliumskills.stats.Stats; @@ -12,6 +12,7 @@ import com.sk89q.worldguard.protection.regions.RegionQuery; import me.zenox.evocraft.Slot; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.util.Util; import org.bukkit.Bukkit; import org.bukkit.ChatColor; diff --git a/src/main/java/me/zenox/evocraft/abilities/Transcendence.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Transcendence.java similarity index 95% rename from src/main/java/me/zenox/evocraft/abilities/Transcendence.java rename to src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Transcendence.java index 0fdfb43..a9cbb6d 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Transcendence.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Transcendence.java @@ -1,5 +1,6 @@ -package me.zenox.evocraft.abilities; +package me.zenox.evocraft.abilities.itemabilities.specific; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.item.LoreEntry; diff --git a/src/main/java/me/zenox/evocraft/data/TranslatableText.java b/src/main/java/me/zenox/evocraft/data/TranslatableText.java index dd6dfc9..0c18b86 100644 --- a/src/main/java/me/zenox/evocraft/data/TranslatableText.java +++ b/src/main/java/me/zenox/evocraft/data/TranslatableText.java @@ -27,7 +27,9 @@ public enum Type { ABILITY_NAME("ability-name"), ABILITY_LORE("ability-lore"), COMMAND("cmd"), MISC_MSG("msg"), ENCHANT_NAME("enchant-name"), ATTRIBUTE("attribute"), GUI("gui"), - CLASS_NAME("class-name"), CLASS_DESC("class-desc"); + CLASS_NAME("class-name"), CLASS_DESC("class-desc"), + SKILL_NAME("skill-name"), SKILL_DESC("skill-desc"), + MODIFIER_NAME("modifier-name"), MODIFIER_LORE("modifier-lore"); private final String key; diff --git a/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java b/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java index 8fc4ee9..e1bcb36 100644 --- a/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java +++ b/src/main/java/me/zenox/evocraft/events/PlayerUseItemEvent.java @@ -2,6 +2,7 @@ import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.Ability; +import me.zenox.evocraft.abilities.EventAbility; import me.zenox.evocraft.enchant.ComplexEnchantment; import me.zenox.evocraft.gameclass.ClassAbilityListener; import org.bukkit.event.*; @@ -16,7 +17,7 @@ public class PlayerUseItemEvent implements Listener { private final EvoCraft plugin; - private final Map, List> eventToAbilitiesMap = new HashMap<>(); + private final Map, List>> eventToAbilitiesMap = new HashMap<>(); private final Map, List> eventToEnchantmentsMap = new HashMap<>(); @@ -24,7 +25,7 @@ public PlayerUseItemEvent(EvoCraft plugin) { this.plugin = plugin; // Populate eventToAbilitiesMap based on registered abilities - for (Ability ability : Ability.registeredAbilities) { + for (EventAbility ability : Ability.registeredAbilities.stream().filter((x) -> x instanceof EventAbility).map((x) -> (EventAbility) x).toList()) { Class eventType = ability.getEventType(); // Assuming you have a method to get the event type eventToAbilitiesMap .computeIfAbsent(eventType, k -> new ArrayList<>()) @@ -50,9 +51,9 @@ public void useEvent(Event event) { return; // PERFORMANCE ISSUE: This is called for every event, and every single ability is called. - List relevantAbilities = eventToAbilitiesMap.get(event.getClass()); + List> relevantAbilities = eventToAbilitiesMap.get(event.getClass()); if (relevantAbilities != null) { - for (Ability ability : relevantAbilities) { + for (Ability ability : relevantAbilities) { ability.useAbility(event); } } diff --git a/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java index 89c0531..84eb701 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java +++ b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java @@ -56,6 +56,8 @@ public void onPlayerInteract(PlayerInteractEvent event) { Action action = event.getAction(); // filter by player's class + if (event.getItem() == null) return; + if (GameClass.getClass(player) == null) return; if (!GameClass.getClass(player).items().contains(ComplexItem.of(event.getItem()).getType())) return; diff --git a/src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java b/src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java new file mode 100644 index 0000000..e33f277 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java @@ -0,0 +1,18 @@ +package me.zenox.evocraft.gameclass; + +import org.bukkit.event.block.Action; + +public enum ClickCombination { + LEFT_LEFT, + LEFT_RIGHT, + RIGHT_LEFT, + RIGHT_RIGHT; + + private ClickCombination detectCombination(Action first, Action second) { + if (first.isLeftClick() && second.isLeftClick()) return ClickCombination.LEFT_LEFT; + if (first.isLeftClick() && second.isRightClick()) return ClickCombination.LEFT_RIGHT; + if (first.isRightClick() && second.isLeftClick()) return ClickCombination.RIGHT_LEFT; + if (first.isRightClick() && second.isRightClick()) return ClickCombination.RIGHT_RIGHT; + return null; // Default case, should ideally not be reached + } +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java index f4f7997..947b122 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java +++ b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java @@ -22,16 +22,16 @@ public enum GameClass { MAGE("mage", ChatColor.BLUE, List.of(ComplexItem.Type.STAFF, ComplexItem.Type.WAND), Material.BLAZE_ROD, - new SkillTree()), + TreeRegistry.MAGE_TELEPORT_TREE), WARRIOR("warrior", ChatColor.RED, List.of(ComplexItem.Type.SWORD), Material.IRON_SWORD, - new SkillTree()), + new AbilityTree()), TANK("tank", ChatColor.GREEN, List.of(ComplexItem.Type.AXE), Material.IRON_AXE, - new SkillTree()), + new AbilityTree()), ARCHER("archer", ChatColor.YELLOW, List.of(ComplexItem.Type.BOW), Material.BOW, - new SkillTree()); + new AbilityTree()); private static final NamespacedKey KEY = new NamespacedKey(EvoCraft.getPlugin(), "class"); private final String id; @@ -40,9 +40,9 @@ public enum GameClass { private final String description; private final List items; private final Material icon; - private final SkillTree tree; + private final AbilityTree tree; - GameClass(String id, ChatColor color, List items, Material icon, SkillTree tree) { + GameClass(String id, ChatColor color, List items, Material icon, AbilityTree tree) { this.id = id; this.name = new TranslatableText(TranslatableText.Type.CLASS_NAME + "-" + id).toString(); this.color = color; @@ -105,7 +105,7 @@ public Material icon() { return icon; } - public SkillTree tree() { + public AbilityTree tree() { return tree; } } diff --git a/src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java b/src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java deleted file mode 100644 index c9c5f42..0000000 --- a/src/main/java/me/zenox/evocraft/gameclass/PassiveEffect.java +++ /dev/null @@ -1,4 +0,0 @@ -package me.zenox.evocraft.gameclass; - -public class PassiveEffect { -} diff --git a/src/main/java/me/zenox/evocraft/gameclass/SkillNode.java b/src/main/java/me/zenox/evocraft/gameclass/SkillNode.java deleted file mode 100644 index 4485eb1..0000000 --- a/src/main/java/me/zenox/evocraft/gameclass/SkillNode.java +++ /dev/null @@ -1,80 +0,0 @@ -package me.zenox.evocraft.gameclass; - -import me.zenox.evocraft.abilities.Ability; - -import java.util.List; -import java.util.Objects; - -public final class SkillNode { - private final String id; - private final String name; - private final String description; - private final List prerequisiteSkills; - private final List children; - private final Ability ability; - private final PassiveEffect passiveEffect; - - public SkillNode(String id, String name, String description, List prerequisiteSkills, List children, Ability ability, PassiveEffect passiveEffect) { - this.id = id; - this.name = name; - this.description = description; - this.prerequisiteSkills = prerequisiteSkills; - this.children = children; - this.ability = ability; - this.passiveEffect = passiveEffect; - } - - public String id() { - return id; - } - - public String name() { - return name; - } - - public String description() { - return description; - } - - public List prerequisiteSkills() { - return prerequisiteSkills; - } - - public List children() { - return children; - } - - public Ability ability() { - return ability; - } - - public PassiveEffect passiveEffect() { - return passiveEffect; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (SkillNode) obj; - return Objects.equals(this.id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id, name, description, prerequisiteSkills, children, ability, passiveEffect); - } - - @Override - public String toString() { - return "SkillNode[" + - "id=" + id + ", " + - "name=" + name + ", " + - "description=" + description + ", " + - "prerequisiteSkills=" + prerequisiteSkills + ", " + - "children=" + children + ", " + - "ability=" + ability + ", " + - "passiveEffect=" + passiveEffect + ']'; - } - -} diff --git a/src/main/java/me/zenox/evocraft/gameclass/SkillTree.java b/src/main/java/me/zenox/evocraft/gameclass/SkillTree.java deleted file mode 100644 index ff00ca2..0000000 --- a/src/main/java/me/zenox/evocraft/gameclass/SkillTree.java +++ /dev/null @@ -1,48 +0,0 @@ -package me.zenox.evocraft.gameclass; - -import java.util.List; -import java.util.Objects; - -public final class SkillTree { - private final SkillNode root; - private final List nodes; - - public SkillTree(SkillNode root, List nodes) { - this.root = root; - this.nodes = nodes; - } - - public SkillTree() { - this(new SkillNode("test", "BANG", "boom boom shot", List.of(), List.of(), null, null), List.of()); - } - - public SkillNode root() { - return root; - } - - public List nodes() { - return nodes; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (SkillTree) obj; - return Objects.equals(this.root, that.root) && - Objects.equals(this.nodes, that.nodes); - } - - @Override - public int hashCode() { - return Objects.hash(root, nodes); - } - - @Override - public String toString() { - return "SkillTree[" + - "root=" + root + ", " + - "nodes=" + nodes + ']'; - } - -} diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItem.java b/src/main/java/me/zenox/evocraft/item/ComplexItem.java index d567ab6..e2c894e 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItem.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItem.java @@ -4,7 +4,7 @@ import com.google.common.primitives.Ints; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.Ability; -import me.zenox.evocraft.abilities.ItemAbility; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.attribute.AttributeModifier; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; @@ -44,14 +44,14 @@ public class ComplexItem { private final Material material; private final ItemMeta meta; private final Map stats; - private final List abilities; + private final List> abilities; private final HashMap variableMap = new HashMap<>(); private final List attributeModifiers; private String skullURL; - public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type type, Material material, Map stats, List abilities, HashMap variableMap, List attributeModifiers) { + public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type type, Material material, Map stats, List> abilities, HashMap variableMap, List attributeModifiers) { this.id = id; this.name = new TranslatableText(TranslatableText.Type.ITEM_NAME + "-" + id); this.lore = new TranslatableList(TranslatableText.Type.ITEM_LORE + "-" + id); @@ -73,11 +73,11 @@ public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type register(); } - public ComplexItem(String id, Boolean unique, Rarity rarity, Type type, Material material, Map stats, List abilities) { + public ComplexItem(String id, Boolean unique, Rarity rarity, Type type, Material material, Map stats, List> abilities) { this(id, unique, false, rarity, type, material, stats, abilities, new HashMap<>(), new ArrayList<>()); } - public ComplexItem(String id, Rarity rarity, Type type, Material material, Map stats, List abilities) { + public ComplexItem(String id, Rarity rarity, Type type, Material material, Map stats, List> abilities) { this(id, false, rarity, type, material, stats, abilities); } @@ -144,7 +144,7 @@ public ItemStack getItemStack(Integer amount) { } protected void writeAbilityLore(List lore) { - for (Ability ability : this.abilities) { + for (Ability ability : this.abilities) { lore.add(""); lore.add(ChatColor.GOLD + "Ability: " + ability.getDisplayName() + ChatColor.YELLOW + ChatColor.BOLD + " " + (ability instanceof ItemAbility ? ((ItemAbility) ability).getAction().getName() : "")); lore.addAll(ability.getLore()); @@ -217,7 +217,7 @@ public void setSkullURL(String URL) { this.skullURL = URL; } - public List getAbilities() { + public List> getAbilities() { return this.abilities; } diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java index 0aebbb8..af51f2a 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java @@ -5,8 +5,8 @@ import com.archyx.aureliumskills.stats.Stats; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.Ability; -import me.zenox.evocraft.abilities.FullSetArmorAbility; -import me.zenox.evocraft.abilities.ItemAbility; +import me.zenox.evocraft.abilities.itemabilities.FullSetArmorAbility; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.attribute.AttributeModifier; import me.zenox.evocraft.attribute.types.AureliumAttribute; import me.zenox.evocraft.enchant.ComplexEnchantment; @@ -249,7 +249,7 @@ private void writeVariables(VariableType.Priority priority, PersistentDataContai } private void writeAbilityLore(LoreBuilder loreBuilder) { - for (Ability ability : complexItemStack.getComplexItem().getAbilities()) { + for (Ability ability : complexItemStack.getComplexItem().getAbilities()) { List lore = new ArrayList<>(); lore.add(ChatColor.GOLD + (ability.isPassive() ? "Passive " : "") + (ability instanceof FullSetArmorAbility ? "Full Set " : "") + "Ability: " + ability.getDisplayName() + ChatColor.YELLOW + ChatColor.BOLD + " " + (ability instanceof ItemAbility ? ((ItemAbility) ability).getAction().getName() : "")); lore.addAll(ability.getLore()); diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java b/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java index 82b88c0..4887faf 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java @@ -36,7 +36,7 @@ public class ComplexItemStack { private ItemStack item; private ComplexItemMeta complexMeta; - private String skullURL; + private final String skullURL; public ComplexItemStack(ComplexItem complexItem, int amount) { this(complexItem, new ItemStack(complexItem.getMaterial())); @@ -174,7 +174,7 @@ public NamespacedKey getKey() { return this.complexItem.getKey(); } - public List getAbilities() { + public List> getAbilities() { return this.complexItem.getAbilities(); } diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index a444da9..3ce1c5b 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -2,6 +2,10 @@ import com.archyx.aureliumskills.stats.Stats; import me.zenox.evocraft.abilities.*; +import me.zenox.evocraft.abilities.itemabilities.specific.Crucify; +import me.zenox.evocraft.abilities.itemabilities.specific.EmberAttune; +import me.zenox.evocraft.abilities.itemabilities.specific.Psychic; +import me.zenox.evocraft.abilities.itemabilities.specific.Transcendence; import me.zenox.evocraft.attribute.AttributeRegistry; import me.zenox.evocraft.gui.EnchantingGUI; import me.zenox.evocraft.item.basicitems.CorruptPearl; diff --git a/src/main/java/me/zenox/evocraft/item/ItemSettings.java b/src/main/java/me/zenox/evocraft/item/ItemSettings.java index 3bb25bd..40f9304 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemSettings.java +++ b/src/main/java/me/zenox/evocraft/item/ItemSettings.java @@ -28,7 +28,7 @@ public class ItemSettings { private ItemMeta meta; private Map stats; private String skullURL; - private List abilities; + private List> abilities; private HashMap variableMap; private List attributeModifiers; @@ -47,7 +47,7 @@ public ItemSettings() { this.attributeModifiers = new ArrayList<>(); } - public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List abilities, HashMap variableMap, List attributeModifiers) { + public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List> abilities, HashMap variableMap, List attributeModifiers) { this.id = id; this.unique = unique; this.glow = glow; @@ -62,7 +62,7 @@ public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity this.attributeModifiers = attributeModifiers; } - public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List abilities){ + public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List> abilities){ this(id, unique, glow, rarity, type, material, meta, stats, skullURL, abilities, new HashMap<>(), new ArrayList<>()); } @@ -113,7 +113,7 @@ public String getSkullURL() { return skullURL; } - public List getAbilities() { + public List> getAbilities() { return abilities; } @@ -206,22 +206,22 @@ public ItemSettings skullURL(String skullURL) { return this; } - public ItemSettings abilities(List abilities) { + public ItemSettings abilities(List> abilities) { this.abilities = abilities; return this; } - public ItemSettings abilities(Ability... abilities) { + public ItemSettings abilities(Ability... abilities) { this.abilities = List.of(abilities); return this; } - public ItemSettings addAbilities(Ability... abilities) { + public ItemSettings addAbilities(Ability... abilities) { this.abilities.addAll(List.of(abilities)); return this; } - public ItemSettings ability(Ability ability) { + public ItemSettings ability(Ability ability) { this.abilities.add(ability); return this; } From 03370bec27486c322409f3f06e8a23d6a68a374f Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Fri, 3 Nov 2023 18:32:34 -0700 Subject: [PATCH 04/20] PlayerData Manager --- src/main/java/me/zenox/evocraft/EvoCraft.java | 6 +- .../evocraft/abilities/ClassAbility.java | 17 ++- .../me/zenox/evocraft/data/PlayerData.java | 67 +++++++++++ .../evocraft/data/PlayerDataManager.java | 113 ++++++++++++++++++ .../zenox/evocraft/gameclass/GameClass.java | 7 +- .../evocraft/gameclass/tree/AbilityPath.java | 26 ++++ .../evocraft/gameclass/tree/AbilityTree.java | 21 ++++ .../zenox/evocraft/gameclass/tree/Path.java | 45 +++++++ src/main/resources/config.yml | 4 +- src/main/resources/playerdata.yml | 0 10 files changed, 299 insertions(+), 7 deletions(-) create mode 100644 src/main/java/me/zenox/evocraft/data/PlayerData.java create mode 100644 src/main/java/me/zenox/evocraft/data/PlayerDataManager.java create mode 100644 src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java create mode 100644 src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java create mode 100644 src/main/java/me/zenox/evocraft/gameclass/tree/Path.java create mode 100644 src/main/resources/playerdata.yml diff --git a/src/main/java/me/zenox/evocraft/EvoCraft.java b/src/main/java/me/zenox/evocraft/EvoCraft.java index ccc195a..9efe81b 100644 --- a/src/main/java/me/zenox/evocraft/EvoCraft.java +++ b/src/main/java/me/zenox/evocraft/EvoCraft.java @@ -14,6 +14,7 @@ import me.zenox.evocraft.command.Command; import me.zenox.evocraft.data.ConfigLoader; import me.zenox.evocraft.data.LanguageLoader; +import me.zenox.evocraft.data.PlayerDataManager; import me.zenox.evocraft.enchant.EnchantRegistry; import me.zenox.evocraft.events.*; import me.zenox.evocraft.gameclass.ClassAbilityListener; @@ -43,6 +44,7 @@ public final class EvoCraft extends JavaPlugin { private static ProtocolManager protocolManager; private static ChapterManager chapterManager; private static ActionBar actionBar; + private static PlayerDataManager playerDataManager; public static EvoCraft getPlugin() { return plugin; @@ -79,6 +81,7 @@ public void onEnable() { return; } + playerDataManager = new PlayerDataManager(); modifiers = new Modifiers(AureliumAPI.getPlugin()); actionBar = AureliumAPI.getPlugin().getActionBar(); @@ -98,7 +101,6 @@ public void onEnable() { ItemRegistry.registerItems(); RecipeRegistry.registerRecipes(); EnchantRegistry.registerEnchants(); - TreeRegistry.registerNodes(); new Command(plugin); @@ -179,6 +181,6 @@ public void reload() { @Override public void onDisable() { - // Plugin shutdown logic + playerDataManager.shutdown(); } } diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 991816f..e2a097a 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -4,6 +4,7 @@ import me.zenox.evocraft.util.Geo; import me.zenox.evocraft.util.TriConsumer; import org.bukkit.Particle; +import org.bukkit.entity.Damageable; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.player.PlayerInteractEvent; @@ -193,13 +194,27 @@ public void run() { cancel(); return; } - player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 1.8, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 123, 255), 3)); + player.getWorld().getNearbyEntities(tracedPath.get(a).toLocation(player.getWorld()), 1, 1, 1).forEach(entity -> { + if (entity instanceof Damageable) { + ((Damageable) entity).damage(5); + } + }); + player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 1.8, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 12, 89), 3)); a++; } }.runTaskTimer(EvoCraft.getPlugin(), 0, 1); } + public static void surgeTeleport(PlayerInteractEvent event, Player player, ItemStack item) { + darkTeleport(event, player, item); + } + + public static void arcaneTeleport(PlayerInteractEvent event, Player player, ItemStack item) { + + darkTeleport(event, player, item); + } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface SaveState { diff --git a/src/main/java/me/zenox/evocraft/data/PlayerData.java b/src/main/java/me/zenox/evocraft/data/PlayerData.java new file mode 100644 index 0000000..cde4a70 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/data/PlayerData.java @@ -0,0 +1,67 @@ +package me.zenox.evocraft.data; + +import me.zenox.evocraft.gameclass.GameClass; +import me.zenox.evocraft.gameclass.tree.Path; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PlayerData { + + private final UUID uuid; + + private GameClass playerClass; + private final Map pathLevelMap; + + public PlayerData(UUID uuid, GameClass playerClass, Map pathLevelMap) { + this.uuid = uuid; + this.playerClass = playerClass; + this.pathLevelMap = pathLevelMap; + } + + public PlayerData(UUID uuid, GameClass playerClass) { + this(uuid, playerClass, new HashMap<>()); + playerClass.tree().paths().forEach(path -> pathLevelMap.put(path, 0)); + } + + public UUID getUuid() { + return uuid; + } + + // Getter and Setter for playerClass + public GameClass getPlayerClass() { + return playerClass; + } + + public void setPlayerClass(GameClass playerClass) { + this.playerClass = playerClass; + } + + public HashMap getPathLevelMap() { + return pathLevelMap; + } + + // Method to get ability level + public int getPathLevel(Path path) { + return pathLevelMap.getOrDefault(path, 0); + } + + // Method to set ability level + public void setPathLevel(Path path, int level) { + pathLevelMap.put(path, level); + } + + // Progress the level of a specific ability + public void progressAbility(Path path) { + int currentLevel = getPathLevel(path); + setPathLevel(path, currentLevel + 1); + } + + // Display all abilities and their levels + public void displayAbilities() { + for (Path path : pathLevelMap.keySet()) { + System.out.println(path.getId() + ": Level " + pathLevelMap.get(path)); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/zenox/evocraft/data/PlayerDataManager.java b/src/main/java/me/zenox/evocraft/data/PlayerDataManager.java new file mode 100644 index 0000000..b1c3e01 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/data/PlayerDataManager.java @@ -0,0 +1,113 @@ +package me.zenox.evocraft.data; + +import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.gameclass.GameClass; +import me.zenox.evocraft.gameclass.tree.Path; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class PlayerDataManager { + private final File playerDataFile; + private final FileConfiguration playerDataConfig; + + private final Map loadedPlayerData = new ConcurrentHashMap<>(); + + public PlayerDataManager() { + playerDataFile = new File(EvoCraft.getPlugin().getDataFolder(), "playerdata.yml"); + if (!playerDataFile.exists()) { + try { + playerDataFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + playerDataConfig = YamlConfiguration.loadConfiguration(playerDataFile); + + startAutoSave(); + } + + private void startAutoSave() { + long delay = 20L*60L*EvoCraft.getPlugin().getConfig().getLong("autosave-minutes"); + + Bukkit.getScheduler().runTaskTimer(EvoCraft.getPlugin(), this::saveAllPlayerData, delay, delay); + } + + public PlayerData getPlayerData(UUID uuid) { + return loadedPlayerData.computeIfAbsent(uuid, this::loadPlayerData); + } + + public void saveAllPlayerData() { + loadedPlayerData.values().forEach(this::savePlayerData); + } + + // Call this method when a critical change has occurred + public void savePlayerDataImmediately(PlayerData playerData) { + savePlayerData(playerData); + loadedPlayerData.put(playerData.getUuid(), playerData); // Update the in-memory cache + } + + // Call this method during server shutdown + public void shutdown() { + saveAllPlayerData(); + } + + public void savePlayerData(PlayerData playerData) { + // Serialize PlayerData object to YAML + // You will need to implement serialization for your complex types + playerDataConfig.createSection(playerData.getUuid().toString(), serializePlayerData(playerData)); + try { + playerDataConfig.save(playerDataFile); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public PlayerData loadPlayerData(@NotNull UUID uuid) { + // Deserialize from YAML to PlayerData + // You will need to implement deserialization for your complex types + return deserializePlayerData(Objects.requireNonNull(playerDataConfig.getConfigurationSection(uuid.toString()))); + } + + private @NotNull @Unmodifiable Map serializePlayerData(@NotNull PlayerData playerData) { + Map pathMap = new HashMap<>(); + for (Map.Entry entry: playerData.getPathLevelMap().entrySet()) + pathMap.put(entry.getKey().getId(), entry.getValue()); + return Map.of( + "data_version", 0, + "class", playerData.getPlayerClass().id(), + "paths", pathMap + ); + } + + private PlayerData deserializePlayerData(@NotNull ConfigurationSection section) { + return switch (((int) section.get("data_version", 0))) { + case 0 -> new PlayerData( + UUID.fromString(section.getName()), + GameClass.getFromID(section.getString("class")), + deserializePathMap(section.getConfigurationSection("paths")) + ); + default -> throw new IllegalArgumentException("Invalid data version"); + }; + } + + private @NotNull Map deserializePathMap(@NotNull ConfigurationSection paths) { + Map pathMap = new HashMap<>(); + for (String key: paths.getKeys(false)){ + pathMap.put(Path.getFromID(key), paths.getInt(key)); + } + return pathMap; + + } +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java index 947b122..7ffe190 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java +++ b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java @@ -5,6 +5,7 @@ import de.studiocode.invui.gui.builder.guitype.GUIType; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.data.TranslatableText; +import me.zenox.evocraft.gameclass.tree.AbilityTree; import me.zenox.evocraft.gui.item.ClassItem; import me.zenox.evocraft.gui.item.CloseItem; import me.zenox.evocraft.item.ComplexItem; @@ -22,7 +23,7 @@ public enum GameClass { MAGE("mage", ChatColor.BLUE, List.of(ComplexItem.Type.STAFF, ComplexItem.Type.WAND), Material.BLAZE_ROD, - TreeRegistry.MAGE_TELEPORT_TREE), + new AbilityTree()), WARRIOR("warrior", ChatColor.RED, List.of(ComplexItem.Type.SWORD), Material.IRON_SWORD, new AbilityTree()), @@ -60,7 +61,7 @@ public static GameClass getClass(Player player) { return GameClass.getFromID(player.getPersistentDataContainer().get(GameClass.KEY, PersistentDataType.STRING)); } - private static GameClass getFromID(String id) { + public static GameClass getFromID(String id) { return switch (id) { case "mage" -> GameClass.MAGE; case "warrior" -> GameClass.WARRIOR; @@ -85,7 +86,7 @@ public static GUI getGui() { .build(); } - private String id() { + public String id() { return id; } diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java new file mode 100644 index 0000000..eff952b --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java @@ -0,0 +1,26 @@ +package me.zenox.evocraft.gameclass.tree; + +import me.zenox.evocraft.abilities.ClassAbility; +import me.zenox.evocraft.data.PlayerData; + +/** + * Represents an ability path, which is a linear progression of ability upgrades + */ +public class AbilityPath extends Path { + + public final ClassAbility ability; + + public AbilityPath(String id, ClassAbility ability) { + super(id); + this.ability = ability; + } + + public ClassAbility getAbility() { + return ability; + } + + @Override + public void apply(PlayerData playerData) { + + } +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java new file mode 100644 index 0000000..021fc8e --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java @@ -0,0 +1,21 @@ +package me.zenox.evocraft.gameclass.tree; + +import me.zenox.evocraft.abilities.ClassAbility; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a global ability tree, including GUI and all + *

+ * Player information can be found in the PlayerData class + */ +public record AbilityTree (ClassAbility LL_Ability, ClassAbility LR_Ability, + ClassAbility RL_Ability, ClassAbility RR_Ability, List paths){ + + public AbilityTree(ClassAbility LL_Ability, ClassAbility LR_Ability, ClassAbility RL_Ability, ClassAbility RR_Ability) { + this(LL_Ability, LR_Ability, RL_Ability, RR_Ability, new ArrayList<>()); + } + + +} diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/Path.java b/src/main/java/me/zenox/evocraft/gameclass/tree/Path.java new file mode 100644 index 0000000..71d8829 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/Path.java @@ -0,0 +1,45 @@ +package me.zenox.evocraft.gameclass.tree; + +import me.zenox.evocraft.data.PlayerData; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a player's path on the AbilityTree + */ +public abstract class Path { + + private String id; + + public static final List registeredPaths = new ArrayList<>(); + + // Constructor + public Path(String id) { + this.id = id; + registeredPaths.add(this); + } + + public static Path getFromID(String key) { + return registeredPaths.stream() + .filter(path -> path.getId().equals(key)).findFirst() + .orElseThrow(() -> new IllegalArgumentException("No path with ID " + key + " found")); + } + + // Getter for ID + public String getId() { + return id; + } + + // Method to progress the ability + public void progress(PlayerData playerData) { + int currentLevel = playerData.getPathLevel(this); + playerData.setPathLevel(this, currentLevel + 1); + + // Apply the effects to the PlayerData + apply(playerData); + } + + // Abstract method to apply stats, metadata, etc. to player + public abstract void apply(PlayerData playerData); +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index e41ef3c..3df492b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -4,4 +4,6 @@ force_update_default: true # Locale -locale: en_US \ No newline at end of file +locale: en_US + +autosave-minutes: 5 \ No newline at end of file diff --git a/src/main/resources/playerdata.yml b/src/main/resources/playerdata.yml new file mode 100644 index 0000000..e69de29 From 373eb991cea40a32f5c3c6145815ce1ce7730aee Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Sat, 4 Nov 2023 00:48:14 -0700 Subject: [PATCH 05/20] CLASS ABILITY FUNCTIONALITY --- .../me/zenox/evocraft/abilities/Ability.java | 22 +---- .../evocraft/abilities/AbilityRegistry.java | 3 + .../evocraft/abilities/AbilitySettings.java | 33 +++++++ .../evocraft/abilities/ClassAbility.java | 87 +++++++++++++------ .../evocraft/abilities/EventAbility.java | 9 ++ .../me/zenox/evocraft/abilities/Modifier.java | 7 +- .../me/zenox/evocraft/command/Command.java | 26 ++++++ .../me/zenox/evocraft/data/PlayerData.java | 4 +- .../evocraft/data/PlayerDataManager.java | 34 +++++++- .../gameclass/ClassAbilityListener.java | 13 +++ .../evocraft/gameclass/ClickCombination.java | 20 ++++- .../zenox/evocraft/gameclass/GameClass.java | 19 ++-- .../evocraft/gameclass/tree/AbilityPath.java | 2 +- .../evocraft/gameclass/tree/AbilityTree.java | 31 ++++++- .../me/zenox/evocraft/item/ComplexItem.java | 16 ++-- .../me/zenox/evocraft/item/VanillaItem.java | 5 +- 16 files changed, 256 insertions(+), 75 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/Ability.java b/src/main/java/me/zenox/evocraft/abilities/Ability.java index b8437b9..3a2de5c 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Ability.java +++ b/src/main/java/me/zenox/evocraft/abilities/Ability.java @@ -4,7 +4,6 @@ import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; -import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; import org.bukkit.NamespacedKey; @@ -20,7 +19,7 @@ import java.util.ArrayList; import java.util.List; -import static me.zenox.evocraft.abilities.ClassAbility.*; +import static me.zenox.evocraft.abilities.ClassAbility.SaveState; public abstract class Ability { public static final List> registeredAbilities = new ArrayList<>(); @@ -33,8 +32,6 @@ public abstract class Ability { private double cooldown; private final boolean isPassive; private TranslatableList lore; - @SaveState - protected TriConsumer executable; public Ability(String id, int manaCost, double cooldown, boolean isPassive) { this.name = new TranslatableText(TranslatableText.Type.ABILITY_NAME + "-" + id); @@ -45,16 +42,6 @@ public Ability(String id, int manaCost, double cooldown, boolean isPassive) { this.isPassive = isPassive; } - public Ability(String id, int manaCost, double cooldown, boolean isPassive, TriConsumer executable) { - this.name = new TranslatableText(TranslatableText.Type.ABILITY_NAME + "-" + id); - this.id = id; - this.manaCost = manaCost; - this.cooldown = cooldown; - this.lore = new TranslatableList(TranslatableText.Type.ABILITY_LORE + "-" + id); - this.isPassive = isPassive; - this.executable = executable; - } - /** * method getAbility
* gets the ability corresponding to the id @@ -166,10 +153,6 @@ public boolean isPassive() { return isPassive; } - public TriConsumer getExecutable() { - return this.executable; - } - public void setManaCost(int manaCost) { this.manaCost = manaCost; } @@ -178,7 +161,4 @@ public void setCooldown(double cooldown) { this.cooldown = cooldown; } - public void setExecutable(TriConsumer executable) { - this.executable = executable; - } } diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 25496f7..f944062 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -172,6 +172,9 @@ public class AbilityRegistry { .id("mage_teleport") .manaCost(35) .cooldown(0) + .range(5) + .strength(1) + .charges(1) .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_1", +2)) .modifier(Modifier.of(Modifier.Type.MANA_COST, "teleport_mana_1", -5)) .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_1", +1)) diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java index 140bfb9..49bb863 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java @@ -20,6 +20,9 @@ public class AbilitySettings { // Ability-Specific Settings private ItemAbility.AbilityAction abilityAction; + private int strength; + private int charges; + private int range; public AbilitySettings() { this.id = "default" + UUID.randomUUID(); @@ -29,6 +32,9 @@ public AbilitySettings() { this.isPassive = false; this.abilityAction = ItemAbility.AbilityAction.NONE; this.modifiers = new ArrayList<>(); + this.strength = 0; + this.charges = 0; + this.range = 0; } public String getId() { @@ -98,4 +104,31 @@ public AbilitySettings modifier(Modifier modifier) { this.modifiers.add(modifier); return this; } + + public int getStrength() { + return strength; + } + + public AbilitySettings strength(int strength) { + this.strength = strength; + return this; + } + + public int getCharges() { + return charges; + } + + public AbilitySettings charges(int charges) { + this.charges = charges; + return this; + } + + public int getRange() { + return range; + } + + public AbilitySettings range(int range) { + this.range = range; + return this; + } } diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index e2a097a..a90578e 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -1,14 +1,17 @@ package me.zenox.evocraft.abilities; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.data.PlayerData; +import me.zenox.evocraft.data.PlayerDataManager; import me.zenox.evocraft.util.Geo; import me.zenox.evocraft.util.TriConsumer; +import me.zenox.evocraft.util.Util; +import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.entity.Damageable; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; @@ -23,21 +26,29 @@ public class ClassAbility extends Ability { final List modifiers; + @SaveState + protected TriConsumer executable; @SaveState private int strength; - @SaveState private int charges; - @SaveState private int range; private final Map baseState; - public ClassAbility(AbilitySettings settings, TriConsumer executable) { - super(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.isPassive(), executable); + public ClassAbility(AbilitySettings settings, TriConsumer executable) { + super(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.isPassive()); + this.executable = executable; this.modifiers = settings.getModifiers(); + + // stats + this.strength = settings.getStrength(); + this.charges = settings.getCharges(); + this.range = settings.getRange(); + + // save basestate snapshot this.baseState = getState(); } @@ -66,8 +77,18 @@ public void useAbility(Event event) { PlayerInteractEvent e = (PlayerInteractEvent) event; Player p = e.getPlayer(); + PlayerData data = PlayerDataManager.getInstance().getPlayerData(p.getUniqueId()); + // TODO: fetch level from player's ability tree - applyModifiers(modifiers.size()); // apply modifiers to the ability + int level = data.getPathLevel(data.getPlayerClass().tree().path(this)); + if(level == -1) { + Util.sendMessage(p, "&cYou have not unlocked ability %s yet!".formatted(this.getId())); + return; // ability is not unlocked + } + + Util.sendMessage(p, "&aUsing ability %s at level %d".formatted(this.getId(), level)); + + applyModifiers(level); // apply modifiers to the ability // Check if ability is on cooldown if (isAbilityOnCooldown(p)) { @@ -81,7 +102,7 @@ public void useAbility(Event event) { } deductMana(p, this.getManaCost()); - this.runExecutable(null, p, null); + this.executable.accept(e, p, this); setAbilityCooldown(p); reset(); // reset the ability to its original state @@ -138,10 +159,13 @@ public void setRange(int range) { this.range = range; } - public static void teleportAbility(PlayerInteractEvent event, Player player, ItemStack itemStack) { + public static void teleportAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { // Teleport the player up to 5 blocks forward, but less if it's a block - int maxDistance = 5; + int maxDistance = ability.getRange(); + Util.sendMessage(player, "&aTeleporting %d blocks".formatted(maxDistance)); int distance = 0; + Location prev = player.getLocation(); + while (distance < maxDistance) { if (player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).getBlock().getType().isSolid()) { break; @@ -151,16 +175,18 @@ public static void teleportAbility(PlayerInteractEvent event, Player player, Ite player.teleport(player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance))); // Create particles along the path - List tracedPath = Geo.lerpEdges(List.of(player.getLocation().toVector(), player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).toVector()), 15); + List tracedPath = Geo.lerpEdges(List.of(prev.toVector(), player.getLocation().toVector()), (int) (1.3*ability.getRange())); new BukkitRunnable(){ int a = 0; @Override public void run() { - if (a > tracedPath.size()) { + if (a >= tracedPath.size()/2) { cancel(); return; } - player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 1.8, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 123, 255), 3)); + player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), + 5, 0, 0.5, 0, 0, + new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 123, 255), 2)); a++; } }.runTaskTimer(EvoCraft.getPlugin(), 0, 1); @@ -168,14 +194,14 @@ public void run() { /** * Dark Teleport Executable that damages entities along the path - * @param event - * @param player - * @param itemStack */ - public static void darkTeleport(PlayerInteractEvent event, Player player, ItemStack itemStack) { + public static void darkTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { // Teleport the player up to 5 blocks forward, but less if it's a block - int maxDistance = 5; + int maxDistance = ability.getRange(); + Util.sendMessage(player, "&aTeleporting %d blocks".formatted(maxDistance)); int distance = 0; + Location prev = player.getLocation(); + while (distance < maxDistance) { if (player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).getBlock().getType().isSolid()) { break; @@ -185,34 +211,43 @@ public static void darkTeleport(PlayerInteractEvent event, Player player, ItemSt player.teleport(player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance))); // Create particles along the path - List tracedPath = Geo.lerpEdges(List.of(player.getLocation().toVector(), player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).toVector()), 15); + List tracedPath = Geo.lerpEdges(List.of(prev.toVector(), player.getLocation().toVector()), (int) (1.3*ability.getRange())); new BukkitRunnable(){ int a = 0; @Override public void run() { - if (a > tracedPath.size()) { + if (a >= tracedPath.size()/2) { cancel(); return; } player.getWorld().getNearbyEntities(tracedPath.get(a).toLocation(player.getWorld()), 1, 1, 1).forEach(entity -> { - if (entity instanceof Damageable) { - ((Damageable) entity).damage(5); + if (entity instanceof Damageable && !entity.equals(player)) { + ((Damageable) entity).damage(5 * ability.getStrength()); } }); - player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 1.8, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 12, 89), 3)); + player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 0.5, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 12, 89), 3)); a++; } }.runTaskTimer(EvoCraft.getPlugin(), 0, 1); } - public static void surgeTeleport(PlayerInteractEvent event, Player player, ItemStack item) { - darkTeleport(event, player, item); + + public static void surgeTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { + darkTeleport(event, player, ability); } - public static void arcaneTeleport(PlayerInteractEvent event, Player player, ItemStack item) { + public static void arcaneTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { - darkTeleport(event, player, item); + darkTeleport(event, player, ability); + } + + public TriConsumer getExecutable() { + return this.executable; + } + + public void setExecutable(TriConsumer executable) { + this.executable = executable; } @Retention(RetentionPolicy.RUNTIME) diff --git a/src/main/java/me/zenox/evocraft/abilities/EventAbility.java b/src/main/java/me/zenox/evocraft/abilities/EventAbility.java index 6f9fff3..65891c4 100644 --- a/src/main/java/me/zenox/evocraft/abilities/EventAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/EventAbility.java @@ -17,6 +17,8 @@ public abstract class EventAbility extends Ability { private final Class eventType; private final Slot slot; + @ClassAbility.SaveState + protected TriConsumer executable; protected EventAbility(String id, int manaCost, double cooldown, Slot slot) { this(id, manaCost, cooldown, slot, false); @@ -118,4 +120,11 @@ public Class getEventType() { return eventType; } + public TriConsumer getExecutable() { + return this.executable; + } + + public void setExecutable(TriConsumer executable) { + this.executable = executable; + } } diff --git a/src/main/java/me/zenox/evocraft/abilities/Modifier.java b/src/main/java/me/zenox/evocraft/abilities/Modifier.java index 4f12945..96c2eaa 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Modifier.java +++ b/src/main/java/me/zenox/evocraft/abilities/Modifier.java @@ -5,7 +5,6 @@ import me.zenox.evocraft.util.TriConsumer; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.ItemStack; public abstract class Modifier { @@ -38,7 +37,7 @@ void modify(ClassAbility ability) { }, EXECUTABLE { @Override - Modifier create(String id, TriConsumer executable) { + Modifier create(String id, TriConsumer executable) { return new Modifier(id) { @Override void modify(ClassAbility ability) { @@ -74,7 +73,7 @@ Modifier create(String id, double value) { throw new UnsupportedOperationException("This operation is not supported for type: " + this); } - Modifier create(String id, TriConsumer executable) { + Modifier create(String id, TriConsumer executable) { throw new UnsupportedOperationException("This operation is not supported for type: " + this); } } @@ -89,7 +88,7 @@ public static Modifier of(Type type, String id, double value) { return type.create(id, value); } - public static Modifier of(Type type, String id, TriConsumer executable) { + public static Modifier of(Type type, String id, TriConsumer executable) { return type.create(id, executable); } diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index bc70c18..8601072 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -3,8 +3,11 @@ import com.google.common.primitives.Ints; import de.studiocode.invui.window.impl.single.SimpleWindow; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.data.PlayerData; +import me.zenox.evocraft.data.PlayerDataManager; import me.zenox.evocraft.enchant.ComplexEnchantment; import me.zenox.evocraft.gameclass.GameClass; +import me.zenox.evocraft.gameclass.tree.Path; import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; @@ -228,6 +231,21 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman } case "class" -> // Open the class selection GUI new SimpleWindow(((Player) sender), "Class Selection", GameClass.getGui(), true, true).show(); + case "progresspath" -> { + if (args.length < 2) { + Util.sendMessage(sender, "Please specify a valid path."); + return true; + } + Player player = ((Player) sender); + PlayerData data = PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()); + Path path = data.getPlayerClass().tree().path(args[1]); + if (path == null) { + Util.sendMessage(sender, "This path does not exist!"); + return true; + } + data.progressAbility(path); + return true; + } default -> Util.sendMessage(sender, "EvoCraft Help Page."); } return true; @@ -249,6 +267,7 @@ public List onTabComplete(CommandSender sender, org.bukkit.command.Comma arguments.add("removemetadata"); arguments.add("setchapter"); arguments.add("class"); + arguments.add("progresspath"); } if (items.isEmpty()) { @@ -263,6 +282,13 @@ public List onTabComplete(CommandSender sender, org.bukkit.command.Comma } } return results; + } else if (args.length == 2 && args[0].equalsIgnoreCase("progresspath")){ + GameClass gameClass = PlayerDataManager.getInstance().getPlayerData(((Player) sender).getUniqueId()).getPlayerClass(); + for (Path path: gameClass.tree().paths()){ + if (path.getId().toLowerCase().startsWith(args[1].toLowerCase())){ + results.add(path.getId()); + } + } } else if (args.length == 3 && args[0].equalsIgnoreCase("give")) { for (String b : items) { if (b.toLowerCase().startsWith(args[2].toLowerCase())) { diff --git a/src/main/java/me/zenox/evocraft/data/PlayerData.java b/src/main/java/me/zenox/evocraft/data/PlayerData.java index cde4a70..17fd822 100644 --- a/src/main/java/me/zenox/evocraft/data/PlayerData.java +++ b/src/main/java/me/zenox/evocraft/data/PlayerData.java @@ -38,13 +38,13 @@ public void setPlayerClass(GameClass playerClass) { this.playerClass = playerClass; } - public HashMap getPathLevelMap() { + public Map getPathLevelMap() { return pathLevelMap; } // Method to get ability level public int getPathLevel(Path path) { - return pathLevelMap.getOrDefault(path, 0); + return pathLevelMap.getOrDefault(path, -1); } // Method to set ability level diff --git a/src/main/java/me/zenox/evocraft/data/PlayerDataManager.java b/src/main/java/me/zenox/evocraft/data/PlayerDataManager.java index b1c3e01..0f70aff 100644 --- a/src/main/java/me/zenox/evocraft/data/PlayerDataManager.java +++ b/src/main/java/me/zenox/evocraft/data/PlayerDataManager.java @@ -14,7 +14,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.Objects; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -24,7 +23,12 @@ public class PlayerDataManager { private final Map loadedPlayerData = new ConcurrentHashMap<>(); + private static PlayerDataManager instance; + public PlayerDataManager() { + if (instance != null) throw new IllegalStateException("PlayerDataManager already initialized"); + instance = this; + playerDataFile = new File(EvoCraft.getPlugin().getDataFolder(), "playerdata.yml"); if (!playerDataFile.exists()) { try { @@ -44,8 +48,27 @@ private void startAutoSave() { Bukkit.getScheduler().runTaskTimer(EvoCraft.getPlugin(), this::saveAllPlayerData, delay, delay); } + private PlayerData createPlayerData(UUID uuid) { + PlayerData newPlayerData = new PlayerData(uuid, GameClass.NONE, new HashMap<>()); + if (newPlayerData.getPlayerClass().tree() != null) + newPlayerData.getPlayerClass().tree().paths().forEach(path -> newPlayerData.setPathLevel(path, -1)); + + savePlayerDataImmediately(newPlayerData); + loadedPlayerData.put(uuid, newPlayerData); + + return newPlayerData; + } + public PlayerData getPlayerData(UUID uuid) { - return loadedPlayerData.computeIfAbsent(uuid, this::loadPlayerData); + PlayerData data = loadedPlayerData.get(uuid); + if(data == null) { + data = loadPlayerData(uuid); + if(data == null) { + data = createPlayerData(uuid); + } + loadedPlayerData.put(uuid, data); + } + return data; } public void saveAllPlayerData() { @@ -77,7 +100,9 @@ public void savePlayerData(PlayerData playerData) { public PlayerData loadPlayerData(@NotNull UUID uuid) { // Deserialize from YAML to PlayerData // You will need to implement deserialization for your complex types - return deserializePlayerData(Objects.requireNonNull(playerDataConfig.getConfigurationSection(uuid.toString()))); + ConfigurationSection section = playerDataConfig.getConfigurationSection(uuid.toString()); + if (section == null) return null; + return deserializePlayerData(section); } private @NotNull @Unmodifiable Map serializePlayerData(@NotNull PlayerData playerData) { @@ -108,6 +133,9 @@ private PlayerData deserializePlayerData(@NotNull ConfigurationSection section) pathMap.put(Path.getFromID(key), paths.getInt(key)); } return pathMap; + } + public static PlayerDataManager getInstance() { + return instance; } } diff --git a/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java index 84eb701..8ff7987 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java +++ b/src/main/java/me/zenox/evocraft/gameclass/ClassAbilityListener.java @@ -1,6 +1,9 @@ package me.zenox.evocraft.gameclass; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.ClassAbility; +import me.zenox.evocraft.data.PlayerData; +import me.zenox.evocraft.data.PlayerDataManager; import me.zenox.evocraft.item.ComplexItem; import me.zenox.evocraft.util.Util; import org.bukkit.Sound; @@ -71,6 +74,16 @@ public void onPlayerInteract(PlayerInteractEvent event) { Character firstAction = actionMap.get(player); Util.sendActionBar(event.getPlayer(), "&bSHIFT&7-&b%s&7-&b%s&r".formatted(firstAction, action.toString().charAt(0))); Util.sendTitle(player, "", "&7Class Ability: &b&l%s&f-&b&l%s&r".formatted(firstAction, action.toString().charAt(0)), 10, 20, 5); + + PlayerData data = PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()); + ClickCombination cc = ClickCombination.getFromChars(firstAction, action.toString().charAt(0)); + + if (cc == null) throw new IllegalStateException("ClickCombination for ability casting is null"); + + GameClass gameClass = data.getPlayerClass(); + ClassAbility ability = gameClass.tree().getAbility(cc); + ability.useAbility(event); + actionMap.remove(player); // Clear the action after processing the combo } else { // First Action diff --git a/src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java b/src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java index e33f277..a2e52c8 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java +++ b/src/main/java/me/zenox/evocraft/gameclass/ClickCombination.java @@ -1,6 +1,8 @@ package me.zenox.evocraft.gameclass; import org.bukkit.event.block.Action; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public enum ClickCombination { LEFT_LEFT, @@ -8,7 +10,23 @@ public enum ClickCombination { RIGHT_LEFT, RIGHT_RIGHT; - private ClickCombination detectCombination(Action first, Action second) { + public static @Nullable ClickCombination getFromChars(char first, char second) { + return switch (Character.toLowerCase(first)) { + case 'l' -> switch (Character.toLowerCase(second)) { + case 'l' -> LEFT_LEFT; + case 'r' -> LEFT_RIGHT; + default -> null; + }; + case 'r' -> switch (Character.toLowerCase(second)) { + case 'l' -> RIGHT_LEFT; + case 'r' -> RIGHT_RIGHT; + default -> null; + }; + default -> null; + }; + } + + private @Nullable ClickCombination detectCombination(@NotNull Action first, Action second) { if (first.isLeftClick() && second.isLeftClick()) return ClickCombination.LEFT_LEFT; if (first.isLeftClick() && second.isRightClick()) return ClickCombination.LEFT_RIGHT; if (first.isRightClick() && second.isLeftClick()) return ClickCombination.RIGHT_LEFT; diff --git a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java index 7ffe190..91e6f64 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java +++ b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java @@ -4,6 +4,8 @@ import de.studiocode.invui.gui.builder.GUIBuilder; import de.studiocode.invui.gui.builder.guitype.GUIType; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.AbilityRegistry; +import me.zenox.evocraft.data.PlayerDataManager; import me.zenox.evocraft.data.TranslatableText; import me.zenox.evocraft.gameclass.tree.AbilityTree; import me.zenox.evocraft.gui.item.ClassItem; @@ -13,7 +15,6 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; -import org.bukkit.persistence.PersistentDataType; import java.util.List; @@ -23,16 +24,20 @@ public enum GameClass { MAGE("mage", ChatColor.BLUE, List.of(ComplexItem.Type.STAFF, ComplexItem.Type.WAND), Material.BLAZE_ROD, - new AbilityTree()), + new AbilityTree(AbilityRegistry.TELEPORT, null, null, null)), WARRIOR("warrior", ChatColor.RED, List.of(ComplexItem.Type.SWORD), Material.IRON_SWORD, - new AbilityTree()), + null), TANK("tank", ChatColor.GREEN, List.of(ComplexItem.Type.AXE), Material.IRON_AXE, - new AbilityTree()), + null), ARCHER("archer", ChatColor.YELLOW, List.of(ComplexItem.Type.BOW), Material.BOW, - new AbilityTree()); + null), + + NONE("none", ChatColor.WHITE, + List.of(), Material.BARRIER, + null); private static final NamespacedKey KEY = new NamespacedKey(EvoCraft.getPlugin(), "class"); private final String id; @@ -54,11 +59,11 @@ public enum GameClass { } public static void setClass(Player player, GameClass gameClass) { - player.getPersistentDataContainer().set(GameClass.KEY, PersistentDataType.STRING, gameClass.id()); + PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()).setPlayerClass(gameClass); } public static GameClass getClass(Player player) { - return GameClass.getFromID(player.getPersistentDataContainer().get(GameClass.KEY, PersistentDataType.STRING)); + return PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()).getPlayerClass(); } public static GameClass getFromID(String id) { diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java index eff952b..76328e6 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java @@ -21,6 +21,6 @@ public ClassAbility getAbility() { @Override public void apply(PlayerData playerData) { - + // Nothing, this is just a linear progression with no side effects } } diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java index 021fc8e..fae2877 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java @@ -1,6 +1,7 @@ package me.zenox.evocraft.gameclass.tree; import me.zenox.evocraft.abilities.ClassAbility; +import me.zenox.evocraft.gameclass.ClickCombination; import java.util.ArrayList; import java.util.List; @@ -13,9 +14,35 @@ public record AbilityTree (ClassAbility LL_Ability, ClassAbility LR_Ability, ClassAbility RL_Ability, ClassAbility RR_Ability, List paths){ - public AbilityTree(ClassAbility LL_Ability, ClassAbility LR_Ability, ClassAbility RL_Ability, ClassAbility RR_Ability) { - this(LL_Ability, LR_Ability, RL_Ability, RR_Ability, new ArrayList<>()); + public AbilityTree(ClassAbility LL_Ability, ClassAbility LR_Ability, ClassAbility RL_Ability, ClassAbility RR_Ability, Path ... paths) { + this(LL_Ability, LR_Ability, RL_Ability, RR_Ability, new ArrayList<>(List.of( + new AbilityPath(LL_Ability.getId(), LL_Ability), + new AbilityPath(LL_Ability.getId(), LR_Ability), + new AbilityPath(LL_Ability.getId(), RL_Ability), + new AbilityPath(LL_Ability.getId(), RR_Ability)))); + this.paths.addAll(List.of(paths)); } + public ClassAbility getAbility(ClickCombination cc){ + return switch(cc){ + case LEFT_LEFT -> LL_Ability; + case LEFT_RIGHT -> LR_Ability; + case RIGHT_LEFT -> RL_Ability; + case RIGHT_RIGHT -> RR_Ability; + }; + } + + public Path path(ClassAbility ability) { + return paths.stream() + .filter(path -> (path instanceof AbilityPath) && ((AbilityPath) path).ability.equals(ability)) + .findFirst() + .orElse(null); + } + public Path path(String id) { + return paths.stream() + .filter(path -> path.getId().equals(id)) + .findFirst() + .orElse(null); + } } diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItem.java b/src/main/java/me/zenox/evocraft/item/ComplexItem.java index e2c894e..6ce53b2 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItem.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItem.java @@ -70,7 +70,7 @@ public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type this.abilities = abilities; this.variableMap.putAll(variableMap); - register(); + register(false); } public ComplexItem(String id, Boolean unique, Rarity rarity, Type type, Material material, Map stats, List> abilities) { @@ -89,7 +89,7 @@ public ComplexItem(String id, Rarity rarity, Type type, Material material) { this(id, false, rarity, type, material, Map.of(), List.of()); } - public ComplexItem(ItemSettings settings) { + public ComplexItem(ItemSettings settings, boolean override) { this.name = new TranslatableText(TranslatableText.Type.ITEM_NAME + "-" + settings.getId()); this.id = settings.getId(); this.lore = new TranslatableList(TranslatableText.Type.ITEM_LORE + "-" + id); @@ -108,7 +108,11 @@ public ComplexItem(ItemSettings settings) { this.variableMap.putAll(settings.getVariableMap()); this.attributeModifiers = settings.getAttributeModifiers(); - register(); + register(override); + } + + public ComplexItem(ItemSettings settings) { + this(settings, false); } /** @@ -121,11 +125,11 @@ public static ComplexItem of(ItemStack item) { PersistentDataContainer container = item.getItemMeta().getPersistentDataContainer(); if (container.has(GLOBAL_ID, PersistentDataType.STRING)) return itemRegistry.get(container.get(GLOBAL_ID, PersistentDataType.STRING)); - else return ComplexItemStack.of(item).getComplexItem(); + else return VanillaItem.of(item.getType()); } - private void register(){ - if (itemRegistry.containsKey(id)) { + private void register(boolean override){ + if (itemRegistry.containsKey(id) && !override) { Util.logToConsole("Duplicate ComplexItem ID: " + id + " | Exact Match: " + itemRegistry.get(id).equals(this)); throw new IllegalArgumentException("ComplexItem ID cannot be duplicate"); } diff --git a/src/main/java/me/zenox/evocraft/item/VanillaItem.java b/src/main/java/me/zenox/evocraft/item/VanillaItem.java index 4fe7138..61ed918 100644 --- a/src/main/java/me/zenox/evocraft/item/VanillaItem.java +++ b/src/main/java/me/zenox/evocraft/item/VanillaItem.java @@ -6,6 +6,7 @@ import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -83,8 +84,8 @@ public VanillaItem(Material material) { * Vanilla item constructor to override the default settings of a vanilla item. * @param settings The settings to override. */ - public VanillaItem(ItemSettings settings) { - super(settings.id(settings.getMaterial().getKey().getKey())); + public VanillaItem(@NotNull ItemSettings settings) { + super(settings.id(settings.getMaterial().getKey().getKey()), true); if (!settings.getMaterial().isItem()) throw new IllegalArgumentException("Material must have an item form"); for (VanillaItem item : new ArrayList<>(vanillaItemList)) { // remove the old item From 3b84a43eb5157c9f6d618caf9a31ce00a6cf6631 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Fri, 10 Nov 2023 14:33:17 -0800 Subject: [PATCH 06/20] CooldownManager (Charges) --- .../me/zenox/evocraft/abilities/Ability.java | 11 +- .../evocraft/abilities/AbilityRegistry.java | 9 +- .../evocraft/abilities/AbilitySettings.java | 16 +++ .../evocraft/abilities/ClassAbility.java | 113 ++++++++++++++---- .../evocraft/abilities/CooldownManager.java | 97 +++++++++++++++ .../abilities/itemabilities/MoveAbility.java | 73 ----------- .../me/zenox/evocraft/item/ItemRegistry.java | 49 +------- .../item/basicitems/GardenerSapling.java | 30 ----- 8 files changed, 211 insertions(+), 187 deletions(-) create mode 100644 src/main/java/me/zenox/evocraft/abilities/CooldownManager.java delete mode 100644 src/main/java/me/zenox/evocraft/abilities/itemabilities/MoveAbility.java delete mode 100644 src/main/java/me/zenox/evocraft/item/basicitems/GardenerSapling.java diff --git a/src/main/java/me/zenox/evocraft/abilities/Ability.java b/src/main/java/me/zenox/evocraft/abilities/Ability.java index 3a2de5c..c0721b5 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Ability.java +++ b/src/main/java/me/zenox/evocraft/abilities/Ability.java @@ -12,6 +12,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.ParameterizedType; @@ -23,6 +24,7 @@ public abstract class Ability { public static final List> registeredAbilities = new ArrayList<>(); + public static final CooldownManager cooldownManager = new CooldownManager(); private final TranslatableText name; private final String id; @@ -86,7 +88,7 @@ protected void setLore(TranslatableList list) { public abstract void useAbility(Event event); - protected boolean isAbilityOnCooldown(Player p) { + protected boolean isAbilityOnCooldown(@NotNull Player p) { PersistentDataContainer container = p.getPersistentDataContainer(); NamespacedKey cooldownKey = new NamespacedKey(EvoCraft.getPlugin(), getId() + "_cooldown"); Double cooldown; @@ -107,7 +109,7 @@ protected void sendCooldownMessage(Player p) { } } - protected double getCooldownEndTime(Player p) { + protected double getCooldownEndTime(@NotNull Player p) { PersistentDataContainer container = p.getPersistentDataContainer(); NamespacedKey cooldownKey = new NamespacedKey(EvoCraft.getPlugin(), getId() + "_cooldown"); return container.get(cooldownKey, PersistentDataType.DOUBLE); @@ -123,8 +125,11 @@ protected void sendManaInsufficientMessage(Player p) { protected void deductMana(Player p, int manaCost) { AureliumAPI.setMana(p, AureliumAPI.getMana(p) - manaCost); + } + + protected void showMessage(Player p, String msg) { String manaMessage = manaCost > 0 ? ChatColor.AQUA + "-" + manaCost + " Mana " + "(" + ChatColor.GOLD + name + ChatColor.AQUA + ")" : ChatColor.GOLD + "Used " + name; - if (!isPassive) Util.sendActionBar(p, manaMessage); + if (!isPassive) Util.sendActionBar(p, manaMessage + " " + msg); } protected void setAbilityCooldown(Player p) { diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index f944062..6107046 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -90,12 +90,6 @@ public class AbilityRegistry { .manaCost(0) .cooldown(0) .slot(Slot.ARMOR), FullSetAttackAbility::roaringFlameAbility); - public static final MoveAbility LAVA_GLIDER = new MoveAbility(new AbilitySettings() - .id("lava_glider") - .passive(true) - .manaCost(0) - .cooldown(0) - .slot(Slot.ARMOR), MoveAbility::lavaGliderAbility); public static final ItemAbility DARKCALL = new ItemAbility(new AbilitySettings() .id("darkcall") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) @@ -172,9 +166,10 @@ public class AbilityRegistry { .id("mage_teleport") .manaCost(35) .cooldown(0) - .range(5) + .range(10) .strength(1) .charges(1) + .chargeTime(15) .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_1", +2)) .modifier(Modifier.of(Modifier.Type.MANA_COST, "teleport_mana_1", -5)) .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_1", +1)) diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java index 49bb863..df52fec 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java @@ -23,6 +23,7 @@ public class AbilitySettings { private int strength; private int charges; private int range; + private int chargeTime; public AbilitySettings() { this.id = "default" + UUID.randomUUID(); @@ -35,6 +36,7 @@ public AbilitySettings() { this.strength = 0; this.charges = 0; this.range = 0; + this.chargeTime = 0; } public String getId() { @@ -131,4 +133,18 @@ public AbilitySettings range(int range) { this.range = range; return this; } + + public int getChargeTime() { + return chargeTime; + } + + /** + * Sets the charge time of the ability + * @param chargeTime Charge time in seconds + * @return The ability settings + */ + public AbilitySettings chargeTime(int chargeTime) { + this.chargeTime = chargeTime; + return this; + } } diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index a90578e..66d6338 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -14,6 +14,7 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -23,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; public class ClassAbility extends Ability { final List modifiers; @@ -34,9 +36,12 @@ public class ClassAbility extends Ability { @SaveState private int charges; @SaveState + private int chargeTime; + @SaveState private int range; private final Map baseState; + private boolean modified = false; public ClassAbility(AbilitySettings settings, TriConsumer executable) { super(settings.getId(), settings.getManaCost(), settings.getCooldown(), settings.isPassive()); @@ -46,6 +51,7 @@ public ClassAbility(AbilitySettings settings, TriConsumer getState(){ return map; } - - // Override the useAbility method to consider the modified mana cost, actually dont use this for now - // TODO: should abilities only be used through the directUseAbility method? @Override public void useAbility(Event event) { - PlayerInteractEvent e = (PlayerInteractEvent) event; - Player p = e.getPlayer(); + try { + PlayerInteractEvent e = (PlayerInteractEvent) event; + Player p = e.getPlayer(); - PlayerData data = PlayerDataManager.getInstance().getPlayerData(p.getUniqueId()); + PlayerData data = PlayerDataManager.getInstance().getPlayerData(p.getUniqueId()); - // TODO: fetch level from player's ability tree - int level = data.getPathLevel(data.getPlayerClass().tree().path(this)); - if(level == -1) { - Util.sendMessage(p, "&cYou have not unlocked ability %s yet!".formatted(this.getId())); - return; // ability is not unlocked - } + int level = data.getPathLevel(data.getPlayerClass().tree().path(this)); + if (level == -1) { + Util.sendActionBar(p, "&cABILITY %s LOCKED!".formatted(this.getId().replace('_', ' ').toUpperCase())); + return; // ability is not unlocked + } - Util.sendMessage(p, "&aUsing ability %s at level %d".formatted(this.getId(), level)); + Util.sendMessage(p, "&aUsing ability %s at level %d".formatted(this.getId(), level)); - applyModifiers(level); // apply modifiers to the ability + applyModifiers(level); // apply modifiers to the ability - // Check if ability is on cooldown - if (isAbilityOnCooldown(p)) { - sendCooldownMessage(p); - return; - } + // Check if ability is on cooldown + if (isAbilityOnCooldown(p)) { + sendCooldownMessage(p); + return; + } - if (notEnoughMana(p, this.getManaCost())) { - sendManaInsufficientMessage(p); - return; + if (noCharges(p)) { + sendNoChargesMessage(p); + return; + } + + if (notEnoughMana(p, this.getManaCost())) { + sendManaInsufficientMessage(p); + return; + } + + deductMana(p, this.getManaCost()); + int chargesLeft = Ability.cooldownManager.consumeCharge(p, this); + + String chargeMsg = "&6(&e%d&6/%d) (-1)".formatted(chargesLeft, this.getCharges()); + showMessage(p, chargeMsg); + + this.executable.accept(e, p, this); + setAbilityCooldown(p); + } finally { + reset(); } - deductMana(p, this.getManaCost()); - this.executable.accept(e, p, this); - setAbilityCooldown(p); + } - reset(); // reset the ability to its original state + protected boolean noCharges(Player p) { + return cooldownManager.isOnCooldown(p, this); + } + protected void sendNoChargesMessage(Player p) { + Util.sendActionBar(p, "&c&lNO CHARGES LEFT"); + } + + + + /** + * Execute a code block with the context of the ability's modifiers applied + * @param level the level of the ability + * @param code the code to execute + */ + public void executeWithLevel(int level, @NotNull Consumer code){ + applyModifiers(level); + try { + code.accept(this); + } finally { + reset(); + } + } + + /** + * Execute a code block with the context of the ability's modifiers applied + * @param p the player to fetch the level from + * @param code the code to execute + */ + public void executeAsPlayer(@NotNull Player p, Consumer code){ + PlayerData data = PlayerDataManager.getInstance().getPlayerData(p.getUniqueId()); + int level = data.getPathLevel(data.getPlayerClass().tree().path(this)); + executeWithLevel(level, code); } public void applyModifiers(int level){ + if (modified) throw new IllegalStateException("You may not modify the ability while it is already being modified."); for(int i = 0; i < level; i++){ modifiers.get(i).modify(this); } + modified = true; } // Recreate the ability to its original state @@ -129,6 +180,7 @@ public void reset(){ } } } + modified = false; } public List getModifiers() { @@ -151,6 +203,15 @@ public void setCharges(int charges) { this.charges = charges; } + public int getChargeTime() { + return chargeTime; + } + + public ClassAbility setChargeTime(int chargeTime) { + this.chargeTime = chargeTime; + return this; + } + public int getRange() { return range; } diff --git a/src/main/java/me/zenox/evocraft/abilities/CooldownManager.java b/src/main/java/me/zenox/evocraft/abilities/CooldownManager.java new file mode 100644 index 0000000..1277f36 --- /dev/null +++ b/src/main/java/me/zenox/evocraft/abilities/CooldownManager.java @@ -0,0 +1,97 @@ +package me.zenox.evocraft.abilities; + +import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.util.Util; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Manages the cooldowns and charges for abilities + */ +public class CooldownManager implements Listener { + private final Map> chargeMap = new HashMap<>(); + private final Map> rechargeTasks = new HashMap<>(); + + public CooldownManager() { + Bukkit.getPluginManager().registerEvents(this, EvoCraft.getPlugin()); + } + + public boolean isOnCooldown(Player player, ClassAbility ability) { + return getCharges(player, ability) == 0; + } + + public int getCharges(@NotNull Player player, ClassAbility ability) { + chargeMap.putIfAbsent(player.getUniqueId(), new HashMap<>()); + return chargeMap.get(player.getUniqueId()).getOrDefault(ability, ability.getCharges()); + } + + /** + * Consumes a charge of the ability and returns the amount of charges left + * @param player + * @param ability + * @return the amount of charges left + */ + public int consumeCharge(@NotNull Player player, ClassAbility ability) { + if (isOnCooldown(player, ability)) + throw new IllegalStateException("You cannot use an ability when you have zero charges left."); + Map playerCharges = chargeMap.get(player.getUniqueId()); + playerCharges.put(ability, getCharges(player, ability) - 1); + rechargeAbility(player, ability); + return getCharges(player, ability); + } + + public void rechargeAbility(Player player, @NotNull ClassAbility ability) { + UUID playerId = player.getUniqueId(); + chargeMap.putIfAbsent(playerId, new HashMap<>()); + rechargeTasks.putIfAbsent(playerId, new HashMap<>()); + + if (rechargeTasks.get(playerId).containsKey(ability)) { + // A recharge task is already running for this ability + return; + } + + int chargeTime = ability.getChargeTime() * 20; + BukkitRunnable task = new BukkitRunnable() { + @Override + public void run() { + if (getCharges(player, ability) < ability.getCharges()) { + chargeMap.get(playerId).put(ability, getCharges(player, ability) + 1); + Util.sendActionBar(player, " &6(+1 %s charge) (%d/%d)".formatted(ability.getDisplayName(), getCharges(player, ability), ability.getCharges())); + } else { + cancel(); + rechargeTasks.get(playerId).remove(ability); + } + + if (ability.getChargeTime() * 20 != chargeTime) { + cancel(); + rechargeTasks.get(playerId).remove(ability); + this.runTaskTimer(EvoCraft.getPlugin(), ability.getChargeTime(), ability.getChargeTime()); + } + } + }; + + rechargeTasks.get(playerId).put(ability, task); + task.runTaskTimer(EvoCraft.getPlugin(), chargeTime, chargeTime); + } + + @EventHandler + public void onPlayerLeave(PlayerQuitEvent e) { + UUID playerId = e.getPlayer().getUniqueId(); + chargeMap.remove(playerId); + if (rechargeTasks.containsKey(playerId)) { + for (BukkitRunnable task : rechargeTasks.get(playerId).values()) { + task.cancel(); // Cancel any running tasks + } + rechargeTasks.remove(playerId); + } + } +} diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/MoveAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/MoveAbility.java deleted file mode 100644 index bc95408..0000000 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/MoveAbility.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.zenox.evocraft.abilities.itemabilities; - -import me.zenox.evocraft.Slot; -import me.zenox.evocraft.EvoCraft; -import me.zenox.evocraft.abilities.AbilitySettings; -import me.zenox.evocraft.abilities.EventAbility; -import me.zenox.evocraft.util.TriConsumer; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.List; -import java.util.Random; - -public class MoveAbility extends EventAbility { - - public MoveAbility(AbilitySettings settings) { - super(settings); - } - - public MoveAbility(AbilitySettings settings, TriConsumer executable) { - super(settings, executable); - } - - public MoveAbility(String id, int manaCost, double cooldown, TriConsumer executable) { - super(id, manaCost, cooldown, Slot.ARMOR, executable); - } - - @Override - protected boolean checkEvent(PlayerMoveEvent e) { - return e instanceof PlayerMoveEvent; - } - - @Override - protected Player getPlayerOfEvent(PlayerMoveEvent e) { - return ((PlayerMoveEvent) e).getPlayer(); - } - - @Override - protected List getItem(Player p, PlayerMoveEvent e) { - return this.getSlot().item(p); - } - - // Static ability executables - public static void lavaGliderAbility(PlayerMoveEvent e, Player p, ItemStack item) { - // If the player is in lava - if (p.getWorld().getBlockAt(p.getLocation()).getType().equals(Material.LAVA) - || p.getWorld().getBlockAt(p.getLocation().subtract(0, 1, 0)).getType().equals(Material.LAVA)){ - p.setWalkSpeed(0.5f); - - Random r = new Random(); - for (int i = 0; i < 2; i++) { - // Spawn a LAVA particle that is randomized but near player's location - Location loc = p.getLocation(); - loc.add(r.nextDouble() - 0.5d, r.nextDouble() - 0.5d, r.nextDouble() - 0.5d); - p.getWorld().spawnParticle(Particle.LAVA, loc, 1); - } - new BukkitRunnable() { - @Override - public void run() { - p.setWalkSpeed(0.2f); - } - }.runTaskLater(EvoCraft.getPlugin(), 1); - } - else p.setWalkSpeed(0.2f); - - } - -} diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index 3ce1c5b..7f06179 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -1,7 +1,7 @@ package me.zenox.evocraft.item; import com.archyx.aureliumskills.stats.Stats; -import me.zenox.evocraft.abilities.*; +import me.zenox.evocraft.abilities.AbilityRegistry; import me.zenox.evocraft.abilities.itemabilities.specific.Crucify; import me.zenox.evocraft.abilities.itemabilities.specific.EmberAttune; import me.zenox.evocraft.abilities.itemabilities.specific.Psychic; @@ -9,7 +9,6 @@ import me.zenox.evocraft.attribute.AttributeRegistry; import me.zenox.evocraft.gui.EnchantingGUI; import me.zenox.evocraft.item.basicitems.CorruptPearl; -import me.zenox.evocraft.item.basicitems.GardenerSapling; import me.zenox.evocraft.item.basicitems.RavagerSkin; import me.zenox.evocraft.item.basicitems.TormentedSoul; import me.zenox.evocraft.util.Util; @@ -26,8 +25,6 @@ public class ItemRegistry { - - public static final ComplexItem GARDENER_SAPLING = new GardenerSapling(); public static final ComplexItem ENCHANTED_MAGMA_BLOCK = new ComplexItem(new ItemSettings() .id("enchanted_magma_block") .material(Material.MAGMA_BLOCK)); @@ -387,50 +384,6 @@ public class ItemRegistry { .stat(Stats.STRENGTH, 50d) .ability(AbilityRegistry.TERRA_STRIKE)); - public static final ComplexItem BURNING_HELMET = new ComplexItem(new ItemSettings() - .id("burning_helmet") - .material(Material.LEATHER_HELMET) - .rarity(ComplexItem.Rarity.RARE) - .type(ComplexItem.Type.HELMET) - .modifier(AttributeRegistry.HEALTH, 5) - .modifier(AttributeRegistry.MOVEMENT_SPEED, 0.05, AttributeModifier.Operation.ADD_SCALAR) - .modifier(AttributeRegistry.ARMOR, 4) - .modifier(AttributeRegistry.ARMOR_TOUGHNESS, 1) - .abilities(AbilityRegistry.ROARING_FLAME)); - - public static final ComplexItem BURNING_CHESTPLATE = new ComplexItem(new ItemSettings() - .id("burning_chestplate") - .material(Material.LEATHER_CHESTPLATE) - .rarity(ComplexItem.Rarity.RARE) - .type(ComplexItem.Type.CHESTPLATE) - .modifier(AttributeRegistry.HEALTH, 12) - .modifier(AttributeRegistry.MOVEMENT_SPEED, 0.05, AttributeModifier.Operation.ADD_SCALAR) - .modifier(AttributeRegistry.ARMOR, 10) - .modifier(AttributeRegistry.ARMOR_TOUGHNESS, 1) - .abilities(AbilityRegistry.ROARING_FLAME)); - - public static final ComplexItem BURNING_LEGGINGS = new ComplexItem(new ItemSettings() - .id("burning_leggings") - .material(Material.LEATHER_LEGGINGS) - .rarity(ComplexItem.Rarity.RARE) - .type(ComplexItem.Type.LEGGINGS) - .modifier(AttributeRegistry.HEALTH, 10) - .modifier(AttributeRegistry.MOVEMENT_SPEED, 0.05, AttributeModifier.Operation.ADD_SCALAR) - .modifier(AttributeRegistry.ARMOR, 8) - .modifier(AttributeRegistry.ARMOR_TOUGHNESS, 1) - .abilities(AbilityRegistry.ROARING_FLAME)); - - public static final ComplexItem BURNING_BOOTS = new ComplexItem(new ItemSettings() - .id("burning_boots") - .material(Material.LEATHER_BOOTS) - .rarity(ComplexItem.Rarity.RARE) - .type(ComplexItem.Type.BOOTS) - .modifier(AttributeRegistry.HEALTH, 5) - .modifier(AttributeRegistry.MOVEMENT_SPEED, 0.05, AttributeModifier.Operation.ADD_SCALAR) - .modifier(AttributeRegistry.ARMOR, 3) - .modifier(AttributeRegistry.ARMOR_TOUGHNESS, 1) - .abilities(AbilityRegistry.ROARING_FLAME, AbilityRegistry.LAVA_GLIDER)); - public static final ComplexItem DARKCALLER = new ComplexItem(new ItemSettings() .id("darkcaller") .material(Material.BEACON) diff --git a/src/main/java/me/zenox/evocraft/item/basicitems/GardenerSapling.java b/src/main/java/me/zenox/evocraft/item/basicitems/GardenerSapling.java deleted file mode 100644 index d3608de..0000000 --- a/src/main/java/me/zenox/evocraft/item/basicitems/GardenerSapling.java +++ /dev/null @@ -1,30 +0,0 @@ -package me.zenox.evocraft.item.basicitems; - -import me.zenox.evocraft.item.ComplexItem; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.ItemFlag; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class GardenerSapling extends ComplexItem { - public GardenerSapling() { - super("gardener_sapling", Rarity.VERY_SPECIAL, Type.MISC, Material.OAK_SAPLING, Map.of()); - - List lore = new ArrayList<>(); - lore.add(ChatColor.GRAY + "A sapling, that can when cared for"); - lore.add(ChatColor.GRAY + "can grow into something beautiful."); - lore.add(""); - lore.add(ChatColor.GRAY + "A thanks to the beta testers who helped along the way."); - lore.add(""); - lore.add(ChatColor.GRAY + "Issued to: " + ChatColor.YELLOW + "%s"); - lore.add(ChatColor.GRAY + "Issued From: " + ChatColor.YELLOW + "%s"); - lore.add(ChatColor.GRAY + "Date Issued: " + ChatColor.YELLOW + "%s"); - this.getMeta().setLore(lore); - this.getMeta().addEnchant(Enchantment.DAMAGE_ALL, 1, true); - this.getMeta().addItemFlags(ItemFlag.HIDE_ENCHANTS); - } -} From 73157f503c497d267b9f80790617a81031ee46fc Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Fri, 10 Nov 2023 19:02:02 -0800 Subject: [PATCH 07/20] Mage Abilities + TabCompletion --- .../evocraft/abilities/AbilityRegistry.java | 30 +++- .../evocraft/abilities/ClassAbility.java | 162 ++++++++++++------ .../evocraft/abilities/CooldownManager.java | 26 +-- .../me/zenox/evocraft/abilities/Modifier.java | 11 ++ .../me/zenox/evocraft/command/Command.java | 102 ++++++----- .../me/zenox/evocraft/events/OtherEvent.java | 13 +- .../zenox/evocraft/gameclass/GameClass.java | 2 +- .../evocraft/gameclass/tree/AbilityTree.java | 6 +- src/main/resources/languages/en_US.yml | 7 + 9 files changed, 233 insertions(+), 126 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 6107046..91d3114 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -174,12 +174,38 @@ public class AbilityRegistry { .modifier(Modifier.of(Modifier.Type.MANA_COST, "teleport_mana_1", -5)) .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_1", +1)) .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_dark", ClassAbility::darkTeleport)) - .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_2", +2)) + .modifier(Modifier.of(Modifier.Type.STRENGTH, "teleport_strength_1", +1)) + .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_2", +1)) .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_surge", ClassAbility::surgeTeleport)) - .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_4", +4)) + .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_2", +4)) .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_arcane", ClassAbility::arcaneTeleport)) , ClassAbility::teleportAbility); + public static final ClassAbility MANA_BALL = new ClassAbility(new AbilitySettings() + .id("mage_mana_ball") + .manaCost(10) + .cooldown(0) + .range(20) + .strength(1) + .charges(-1) + .chargeTime(-1) + .modifier(Modifier.of(Modifier.Type.MANA_COST, "mana_ball_mana_1", -5)) + , ClassAbility::manaBallAbility); + public static final ClassAbility RIFT_BEAM = new ClassAbility(new AbilitySettings() + .id("mage_rift_beam") + .manaCost(50) + .cooldown(0) + .range(20) + .strength(1) + , ClassAbility::riftBeamAbility); + public static final ClassAbility RUNE_SHIELD = new ClassAbility(new AbilitySettings() + .id("mage_rune_shield") + .manaCost(50) + .cooldown(0) + .range(20) + .strength(1) + , ClassAbility::runeShieldAbility); + public static void registerAbilities(){ Util.logToConsole("Registering %s abilities.".formatted(ChatColor.GOLD + "" + Ability.registeredAbilities.size() + ChatColor.RESET)); } diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 66d6338..4a4ddea 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -6,12 +6,14 @@ import me.zenox.evocraft.util.Geo; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; +import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Particle; -import org.bukkit.entity.Damageable; -import org.bukkit.entity.Player; +import org.bukkit.entity.*; import org.bukkit.event.Event; +import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; @@ -99,7 +101,7 @@ public void useAbility(Event event) { return; } - if (noCharges(p)) { + if (this.getCharges() > 0 && noCharges(p)) { sendNoChargesMessage(p); return; } @@ -220,24 +222,42 @@ public void setRange(int range) { this.range = range; } - public static void teleportAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { - // Teleport the player up to 5 blocks forward, but less if it's a block - int maxDistance = ability.getRange(); - Util.sendMessage(player, "&aTeleporting %d blocks".formatted(maxDistance)); - int distance = 0; - Location prev = player.getLocation(); + public TriConsumer getExecutable() { + return this.executable; + } + + public void setExecutable(TriConsumer executable) { + this.executable = executable; + } - while (distance < maxDistance) { - if (player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).getBlock().getType().isSolid()) { + /* + * Ability Executables + */ + private static void teleport(Player player, int distance) { + Location currentLocation = player.getLocation(); + Vector direction = currentLocation.getDirection().normalize(); + + // This will check each block along the path, up to the distance + for (int i = 1; i <= distance; i++) { + Location targetLocation = currentLocation.clone().add(direction.clone().multiply(1)); // Move 1 block at a time in the direction + // Check for solid blocks at the player's feet or head level + if (targetLocation.getBlock().getType().isSolid() || targetLocation.clone().add(0, 1, 0).getBlock().getType().isSolid()) { + // If a solid block is found, stop and teleport the player to the last safe location break; } - distance++; + // Update currentLocation to the last checked location + currentLocation = targetLocation; } - player.teleport(player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance))); - // Create particles along the path - List tracedPath = Geo.lerpEdges(List.of(prev.toVector(), player.getLocation().toVector()), (int) (1.3*ability.getRange())); - new BukkitRunnable(){ + // Perform the actual teleportation + player.teleport(currentLocation.add(0, 0.1, 0)); // Slightly raise the Y value to prevent suffocation + } + + private static void teleportEffect(Location startLoc, Location endLoc, Color color, Player player, int damage, double width) { + List tracedPath = Geo.lerpEdges(List.of(startLoc.toVector(), endLoc.toVector()), (int) (1.3 * startLoc.distance(endLoc))); + Vector direction = endLoc.toVector().subtract(startLoc.toVector()).normalize(); + + new BukkitRunnable() { int a = 0; @Override public void run() { @@ -245,71 +265,111 @@ public void run() { cancel(); return; } - player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), - 5, 0, 0.5, 0, 0, - new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 123, 255), 2)); + + Location currentLoc = tracedPath.get(a).toLocation(player.getWorld()); + Vector perpendicular = new Vector(-direction.getZ(), 0, direction.getX()).normalize().multiply(width / 2); + + for (double i = -width / 2; i <= width / 2; i += width / 10) { + Location effectLoc = currentLoc.clone().add(perpendicular.clone().multiply(i)); + player.getWorld().getNearbyEntities(effectLoc, 0.5, 0.5, 0.5).forEach(entity -> { + if (entity instanceof Damageable && !entity.equals(player)) { + ((Damageable) entity).damage(damage); + } + }); + player.getWorld().spawnParticle(Particle.REDSTONE, effectLoc, 1, 0.1, 0, 0.1, new Particle.DustOptions(color, 1)); + } + a++; } }.runTaskTimer(EvoCraft.getPlugin(), 0, 1); } + + public static void teleportAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + Location prev = player.getLocation(); + teleport(player, ability.getRange()); + + // Create particles along the path + teleportEffect(prev, player.getLocation(), Color.fromRGB(0, 123, 255), player, 0, 1); + } + /** * Dark Teleport Executable that damages entities along the path */ public static void darkTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { - // Teleport the player up to 5 blocks forward, but less if it's a block - int maxDistance = ability.getRange(); - Util.sendMessage(player, "&aTeleporting %d blocks".formatted(maxDistance)); - int distance = 0; Location prev = player.getLocation(); - while (distance < maxDistance) { - if (player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance)).getBlock().getType().isSolid()) { - break; - } - distance++; - } - player.teleport(player.getLocation().clone().add(player.getLocation().getDirection().multiply(distance))); + // Teleport the player using the helper method + teleport(player, ability.getRange()); + + // Create particles along the path and damage entities using the helper method + teleportEffect(prev, player.getLocation(), org.bukkit.Color.fromRGB(0, 12, 89), player, 5 * ability.getStrength(), 1); + } + + + public static void surgeTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { + Location prev = player.getLocation(); + + teleport(player, ability.getRange()); + + teleportEffect(prev, player.getLocation(), org.bukkit.Color.fromRGB(102, 0, 126), player, 10 * ability.getStrength(), 2); + + } + + public static void arcaneTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { + + darkTeleport(event, player, ability); + } + + public static void manaBallAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + // Create the projectile + Snowball projectile = player.launchProjectile(Snowball.class); + + // Set projectile properties + projectile.setVelocity(player.getLocation().getDirection().multiply(1.5)); // Speed of the projectile + + // Apply metadata to the projectile so we can identify it later as a mana projectile + projectile.setMetadata("mana_projectile", new FixedMetadataValue(EvoCraft.getPlugin(), ability.getStrength())); - // Create particles along the path - List tracedPath = Geo.lerpEdges(List.of(prev.toVector(), player.getLocation().toVector()), (int) (1.3*ability.getRange())); new BukkitRunnable(){ int a = 0; + final Location start = player.getLocation().clone(); + final int range = ability.getRange(); @Override public void run() { - if (a >= tracedPath.size()/2) { + if (a >= 20 || start.distance(projectile.getLocation()) > range) { cancel(); return; } - player.getWorld().getNearbyEntities(tracedPath.get(a).toLocation(player.getWorld()), 1, 1, 1).forEach(entity -> { - if (entity instanceof Damageable && !entity.equals(player)) { - ((Damageable) entity).damage(5 * ability.getStrength()); - } - }); - player.getWorld().spawnParticle(Particle.REDSTONE, tracedPath.get(a).toLocation(player.getWorld()), 5, 0, 0.5, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(0, 12, 89), 3)); + // spawn some end rod particles and some teal colored "mana" redstone particles + + player.getWorld().spawnParticle(Particle.END_ROD, projectile.getLocation(), 1, 0, 0, 0, 0); + player.getWorld().spawnParticle(Particle.REDSTONE, projectile.getLocation(), 1, 0, 0, 0, + new Particle.DustOptions(Color.fromRGB(0, 255, 255), 1)); a++; } - }.runTaskTimer(EvoCraft.getPlugin(), 0, 1); + }.runTaskTimer(EvoCraft.getPlugin(), 0, 3); + } + public static void manaBallDamage(@NotNull ProjectileHitEvent event, int strength){ + // Logic to deal damage + if (event.getHitEntity() instanceof LivingEntity) { + LivingEntity target = (LivingEntity) event.getHitEntity(); + target.damage(5.0*strength, (Entity) event.getEntity().getShooter()); // Deal 5 points of damage, customize as needed + // Additional effects can be added here, like knockback or status effects + } + // Remove the projectile upon impact + event.getEntity().remove(); } + public static void riftBeamAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { - public static void surgeTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { - darkTeleport(event, player, ability); } - public static void arcaneTeleport(PlayerInteractEvent event, Player player, ClassAbility ability) { - - darkTeleport(event, player, ability); - } + public static void runeShieldAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { - public TriConsumer getExecutable() { - return this.executable; } - public void setExecutable(TriConsumer executable) { - this.executable = executable; - } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) diff --git a/src/main/java/me/zenox/evocraft/abilities/CooldownManager.java b/src/main/java/me/zenox/evocraft/abilities/CooldownManager.java index 1277f36..78d04be 100644 --- a/src/main/java/me/zenox/evocraft/abilities/CooldownManager.java +++ b/src/main/java/me/zenox/evocraft/abilities/CooldownManager.java @@ -63,19 +63,21 @@ public void rechargeAbility(Player player, @NotNull ClassAbility ability) { BukkitRunnable task = new BukkitRunnable() { @Override public void run() { - if (getCharges(player, ability) < ability.getCharges()) { - chargeMap.get(playerId).put(ability, getCharges(player, ability) + 1); - Util.sendActionBar(player, " &6(+1 %s charge) (%d/%d)".formatted(ability.getDisplayName(), getCharges(player, ability), ability.getCharges())); - } else { - cancel(); - rechargeTasks.get(playerId).remove(ability); - } + ability.executeAsPlayer(player, (ability) -> { + if (getCharges(player, ability) < ability.getCharges()) { + chargeMap.get(playerId).put(ability, getCharges(player, ability) + 1); + Util.sendActionBar(player, " &6(+1 %s charge) (%d/%d)".formatted(ability.getDisplayName(), getCharges(player, ability), ability.getCharges())); + } else { + cancel(); + rechargeTasks.get(playerId).remove(ability); + } - if (ability.getChargeTime() * 20 != chargeTime) { - cancel(); - rechargeTasks.get(playerId).remove(ability); - this.runTaskTimer(EvoCraft.getPlugin(), ability.getChargeTime(), ability.getChargeTime()); - } + if (ability.getChargeTime() * 20 != chargeTime) { + cancel(); + rechargeTasks.get(playerId).remove(ability); + this.runTaskTimer(EvoCraft.getPlugin(), ability.getChargeTime(), ability.getChargeTime()); + } + }); } }; diff --git a/src/main/java/me/zenox/evocraft/abilities/Modifier.java b/src/main/java/me/zenox/evocraft/abilities/Modifier.java index 96c2eaa..658ae57 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Modifier.java +++ b/src/main/java/me/zenox/evocraft/abilities/Modifier.java @@ -67,6 +67,17 @@ void modify(ClassAbility ability) { } }; } + }, + STRENGTH { + @Override + Modifier create(String id, double value) { + return new Modifier(id) { + @Override + void modify(ClassAbility ability) { + ability.setStrength(ability.getStrength() + (int) value); + } + }; + } }; Modifier create(String id, double value) { diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index 8601072..cad2898 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -24,9 +24,8 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import java.util.*; +import java.util.stream.Collectors; public class Command implements CommandExecutor, TabCompleter { @@ -256,60 +255,59 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman @Override public List onTabComplete(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args) { - if (arguments.isEmpty()) { - arguments.add("give"); - arguments.add("loottable"); - arguments.add("droploottable"); - arguments.add("dropitematplayer"); - arguments.add("enchant"); - arguments.add("reload"); - arguments.add("removechapterdata"); - arguments.add("removemetadata"); - arguments.add("setchapter"); - arguments.add("class"); - arguments.add("progresspath"); + if (args.length == 1) { + return getCommandSuggestions(args[0]); + } else if (args.length == 2 && "progresspath".equalsIgnoreCase(args[0]) && sender instanceof Player) { + return getPathSuggestions((Player) sender, args[1]); + } else if (args.length == 3) { + return getThirdArgumentSuggestions(args[0], args[2]); + } else if (args.length == 4 && "enchant".equalsIgnoreCase(args[0])) { + return Collections.singletonList(""); + } else if (args.length == 4 && "give".equalsIgnoreCase(args[0])) { + return Collections.singletonList(""); + } + return Collections.emptyList(); + } + + private List getCommandSuggestions(String arg) { + List commands = Arrays.asList("give", "loottable", "droploottable", "dropitematplayer", + "enchant", "reload", "removechapterdata", "removemetadata", + "setchapter", "class", "progresspath"); + return commands.stream() + .filter(a -> a.toLowerCase().startsWith(arg.toLowerCase())) + .collect(Collectors.toList()); + } + + private List getPathSuggestions(Player player, String arg) { + GameClass gameClass = PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()).getPlayerClass(); + return gameClass.tree().paths().stream() + .map(Path::getId) + .filter(path -> path.toLowerCase().startsWith(arg.toLowerCase())) + .collect(Collectors.toList()); + } + + private List getThirdArgumentSuggestions(String arg0, String arg2) { + if ("give".equalsIgnoreCase(arg0)) { + return getItemSuggestions(arg2); + } else if ("enchant".equalsIgnoreCase(arg0)) { + return getEnchantmentSuggestions(arg2); } + return Collections.emptyList(); + } + private List getItemSuggestions(String arg) { if (items.isEmpty()) { items.addAll(ComplexItem.itemRegistry.keySet()); } + return items.stream() + .filter(b -> b.toLowerCase().startsWith(arg.toLowerCase())) + .collect(Collectors.toList()); + } - List results = new ArrayList<>(); - if (args.length == 1) { - for (String a : arguments) { - if (a.toLowerCase().startsWith(args[0].toLowerCase())) { - results.add(a); - } - } - return results; - } else if (args.length == 2 && args[0].equalsIgnoreCase("progresspath")){ - GameClass gameClass = PlayerDataManager.getInstance().getPlayerData(((Player) sender).getUniqueId()).getPlayerClass(); - for (Path path: gameClass.tree().paths()){ - if (path.getId().toLowerCase().startsWith(args[1].toLowerCase())){ - results.add(path.getId()); - } - } - } else if (args.length == 3 && args[0].equalsIgnoreCase("give")) { - for (String b : items) { - if (b.toLowerCase().startsWith(args[2].toLowerCase())) { - results.add(b); - } - } - return results; - } else if (args.length == 3 && args[0].equalsIgnoreCase("enchant")) { - for (ComplexEnchantment b : ComplexEnchantment.getRegisteredEnchants()) { - if (b.getId().toLowerCase().startsWith(args[2].toLowerCase())) { - results.add(b.getId()); - } - } - return results; - } else if (args.length == 4 && args[0].equalsIgnoreCase("enchant")) { - results.add(""); - return results; - } else if (args.length == 4 && args[0].equalsIgnoreCase("give")) { - results.add(""); - return results; - } - return null; + private List getEnchantmentSuggestions(String arg) { + return ComplexEnchantment.getRegisteredEnchants().stream() + .map(ComplexEnchantment::getId) + .filter(id -> id.toLowerCase().startsWith(arg.toLowerCase())) + .collect(Collectors.toList()); } } diff --git a/src/main/java/me/zenox/evocraft/events/OtherEvent.java b/src/main/java/me/zenox/evocraft/events/OtherEvent.java index 9b09ad8..8e176e2 100644 --- a/src/main/java/me/zenox/evocraft/events/OtherEvent.java +++ b/src/main/java/me/zenox/evocraft/events/OtherEvent.java @@ -3,6 +3,7 @@ import com.destroystokyo.paper.event.inventory.PrepareResultEvent; import de.studiocode.invui.window.impl.single.SimpleWindow; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.abilities.ClassAbility; import me.zenox.evocraft.enchant.ComplexEnchantment; import me.zenox.evocraft.gui.EnchantingGUI; import me.zenox.evocraft.item.ComplexItemMeta; @@ -75,19 +76,21 @@ public void projectileExplode(EntityExplodeEvent e) { } @EventHandler - public void projectileCollide(ProjectileHitEvent e){ + public void projectileCollide(ProjectileHitEvent e) { Projectile entity = e.getEntity(); - if(Objects.isNull(entity)) return; - if(Objects.isNull(e.getHitEntity())) return; + if (Objects.isNull(entity)) return; + if (Objects.isNull(e.getHitEntity())) return; List snowballValues = entity.getMetadata("super_snowball"); - if (!snowballValues.isEmpty()) { + if (entity.hasMetadata("super_snowball")) { Entity hitEntity = e.getHitEntity(); - if (!Util.isInvulnerable(hitEntity)){ + if (!Util.isInvulnerable(hitEntity)) { hitEntity.setVelocity(hitEntity.getVelocity().add(hitEntity.getLocation().toVector().subtract(entity.getLocation().add(0, -0.3, 0).toVector()).normalize().multiply(0.5))); hitEntity.setFreezeTicks(Math.max(0, hitEntity.getFreezeTicks()) + 20); if (hitEntity instanceof Player player) player.damage(1); } + } else if (entity.hasMetadata("mana_projectile")) { + ClassAbility.manaBallDamage(e, entity.getMetadata("mana_projectile").get(0).asInt()); } } diff --git a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java index 91e6f64..be67fab 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java +++ b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java @@ -24,7 +24,7 @@ public enum GameClass { MAGE("mage", ChatColor.BLUE, List.of(ComplexItem.Type.STAFF, ComplexItem.Type.WAND), Material.BLAZE_ROD, - new AbilityTree(AbilityRegistry.TELEPORT, null, null, null)), + new AbilityTree(AbilityRegistry.TELEPORT, AbilityRegistry.MANA_BALL, AbilityRegistry.RIFT_BEAM, AbilityRegistry.RUNE_SHIELD)), WARRIOR("warrior", ChatColor.RED, List.of(ComplexItem.Type.SWORD), Material.IRON_SWORD, null), diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java index fae2877..ca73a29 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityTree.java @@ -17,9 +17,9 @@ public record AbilityTree (ClassAbility LL_Ability, ClassAbility LR_Ability, public AbilityTree(ClassAbility LL_Ability, ClassAbility LR_Ability, ClassAbility RL_Ability, ClassAbility RR_Ability, Path ... paths) { this(LL_Ability, LR_Ability, RL_Ability, RR_Ability, new ArrayList<>(List.of( new AbilityPath(LL_Ability.getId(), LL_Ability), - new AbilityPath(LL_Ability.getId(), LR_Ability), - new AbilityPath(LL_Ability.getId(), RL_Ability), - new AbilityPath(LL_Ability.getId(), RR_Ability)))); + new AbilityPath(LR_Ability.getId(), LR_Ability), + new AbilityPath(RL_Ability.getId(), RL_Ability), + new AbilityPath(RR_Ability.getId(), RR_Ability)))); this.paths.addAll(List.of(paths)); } diff --git a/src/main/resources/languages/en_US.yml b/src/main/resources/languages/en_US.yml index aea3c20..11b1959 100644 --- a/src/main/resources/languages/en_US.yml +++ b/src/main/resources/languages/en_US.yml @@ -628,6 +628,13 @@ ability-lore-thunderstrike: - "" - "Deals &cdamage &7to all enemies in a &a5 block &7radius." +########################################################################## +## CLASS ABILITIES ## +########################################################################## +ability-name-mage_teleport: Teleport +abilit-name-mage_mana_ball: Mana Ball + + ########################################################################## ## ENCHANTMENTS ## ########################################################################## From 91c29f400475c20098370ee183c6d3afb5e1a8d1 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Fri, 10 Nov 2023 19:04:16 -0800 Subject: [PATCH 08/20] Remove Story System --- src/main/java/me/zenox/evocraft/EvoCraft.java | 7 -- .../evocraft/abilities/AbilityRegistry.java | 10 -- .../abilities/itemabilities/ItemAbility.java | 76 ------------ .../me/zenox/evocraft/command/Command.java | 39 ------- .../me/zenox/evocraft/item/ItemRegistry.java | 12 -- .../java/me/zenox/evocraft/story/Action.java | 7 -- .../java/me/zenox/evocraft/story/Chapter.java | 70 ----------- .../zenox/evocraft/story/ChapterManager.java | 109 ------------------ .../evocraft/story/chapters/ChapterOne.java | 35 ------ .../evocraft/story/chapters/ChapterTwo.java | 37 ------ .../evocraft/story/chapters/ChapterZero.java | 41 ------- 11 files changed, 443 deletions(-) delete mode 100644 src/main/java/me/zenox/evocraft/story/Action.java delete mode 100644 src/main/java/me/zenox/evocraft/story/Chapter.java delete mode 100644 src/main/java/me/zenox/evocraft/story/ChapterManager.java delete mode 100644 src/main/java/me/zenox/evocraft/story/chapters/ChapterOne.java delete mode 100644 src/main/java/me/zenox/evocraft/story/chapters/ChapterTwo.java delete mode 100644 src/main/java/me/zenox/evocraft/story/chapters/ChapterZero.java diff --git a/src/main/java/me/zenox/evocraft/EvoCraft.java b/src/main/java/me/zenox/evocraft/EvoCraft.java index 9efe81b..29de920 100644 --- a/src/main/java/me/zenox/evocraft/EvoCraft.java +++ b/src/main/java/me/zenox/evocraft/EvoCraft.java @@ -22,7 +22,6 @@ import me.zenox.evocraft.item.VanillaItem; import me.zenox.evocraft.network.GlowFilter; import me.zenox.evocraft.recipe.RecipeRegistry; -import me.zenox.evocraft.story.ChapterManager; import me.zenox.evocraft.util.Util; import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.permission.Permission; @@ -42,7 +41,6 @@ public final class EvoCraft extends JavaPlugin { private static LanguageLoader languageLoader; private static ConfigLoader configLoader; private static ProtocolManager protocolManager; - private static ChapterManager chapterManager; private static ActionBar actionBar; private static PlayerDataManager playerDataManager; @@ -87,7 +85,6 @@ public void onEnable() { configLoader = new ConfigLoader(plugin); languageLoader = new LanguageLoader(plugin); - chapterManager = new ChapterManager(plugin); registerGlobalGUIItems(); @@ -167,10 +164,6 @@ public static Permission getPermissions() { return perms; } - public static ChapterManager getChapterManager() { - return chapterManager; - } - public static ActionBar getActionBar() { return actionBar; } diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 91d3114..8e15e6f 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -105,16 +105,6 @@ public class AbilityRegistry { .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) .manaCost(100) .cooldown(1), ItemAbility::voidWarpAbility); - public static final ItemAbility START_BUTTON = new ItemAbility(new AbilitySettings() - .id("start_button") - .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .manaCost(0) - .cooldown(0), ItemAbility::startButtonAbility); - public static final ItemAbility PORTALIZER = new ItemAbility(new AbilitySettings() - .id("portalizer") - .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) - .manaCost(0) - .cooldown(0), ItemAbility::portalizerAbility); public static final ItemAbility SNOW_SHOT = new ItemAbility(new AbilitySettings() .id("snow_shot") .setAbilityAction(ItemAbility.AbilityAction.RIGHT_CLICK_ALL) diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java index 7e90ba6..1b174ee 100644 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java @@ -862,82 +862,6 @@ public static void smallEmberShootAbility(PlayerInteractEvent event, Player p, I f.setShooter(p); } - public static void startButtonAbility(PlayerInteractEvent playerInteractEvent, Player player, ItemStack itemStack) { - // Check if the player has started using the "hasStarted" metadata value - try { - if (player.getMetadata("hasStarted").size() > 0 || player.getMetadata("hasStarted").get(0).asBoolean()) - return; - } catch (IndexOutOfBoundsException ignored){ - - } - - player.setMetadata("hasStarted", new FixedMetadataValue(EvoCraft.getPlugin(), true)); - - BukkitRunnable startup = new BukkitRunnable(){ - @Override - public void run() { - Util.sendMessage(player, "&aStarting Windows XP... &a&l(" + 100 + ")%", false); - EvoCraft.getChapterManager().getChapter(player).progress(player, playerInteractEvent); - } - }; - - new BukkitRunnable(){ - int a = 0; - @Override - public void run() { - if(a == 0) Util.sendMessage(player, "&aStarting Windows XP...", false); - else Util.sendMessage(player, "&aStarting Windows XP... &7(" + Math.min(100, a) + ")%", false); - a += Util.round(new Random().nextDouble()*10, 1); - if(a >= 100) { - cancel(); - player.playSound(player.getLocation(), "story.0.startup", 1, 1); - startup.runTaskLater(EvoCraft.getPlugin(), 120); - } - } - }.runTaskTimer(EvoCraft.getPlugin(), 5, 4); - } - - public static void portalizerAbility(PlayerInteractEvent playerInteractEvent, Player player, ItemStack itemStack) { - if(playerInteractEvent.getAction() == Action.RIGHT_CLICK_BLOCK) { - Block block = playerInteractEvent.getClickedBlock(); - if(block != null) { - if(block.getType() == Material.WHITE_STAINED_GLASS) { - itemStack.setAmount(0); - player.playSound(player.getLocation(), Sound.BLOCK_BEACON_ACTIVATE, 1, 1); - player.playSound(player.getLocation(), Sound.BLOCK_BEACON_POWER_SELECT, 1, 1f); - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mm m spawn -s LightCrystalCharger 1 " + player.getWorld() + "," + -347 + "," + -61 + "," + -511); - new BukkitRunnable(){ - @Override - public void run() { - player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 0.5f, 0.8f); - player.teleport(new Location(player.getServer().getWorld("flat"), -369, -53, -594)); - player.setBedSpawnLocation(new Location(player.getServer().getWorld("flat"), -369, -53, -594), true); - Util.sendMessage(player, "&b100BCE | &8The Desolated Temple", false); - // Play second voiceover sounds - player.playSound(player.getLocation(), "story.chapter.1.backstory_2", 20f, 1f); - } - }.runTaskLater(EvoCraft.getPlugin(), 80); - - } else if (block.getType() == Material.TINTED_GLASS) { - itemStack.setAmount(0); - player.playSound(player.getLocation(), Sound.BLOCK_BEACON_ACTIVATE, 1, 0.5f); - player.playSound(player.getLocation(), Sound.BLOCK_BEACON_POWER_SELECT, 1, 0.5f); - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mm m spawn -s DarkCrystalCharger 1 " + player.getWorld() + "," + -369 + "," + -61 + "," + -594); - new BukkitRunnable(){ - @Override - public void run() { - player.playSound(player.getLocation(), Sound.BLOCK_PORTAL_TRAVEL, 1, 1); - player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1, 0.8f); - - Util.sendMessage(player, "&bPresent Day | &aEnsildia", false); - EvoCraft.getChapterManager().getChapter(player).progress(player, playerInteractEvent); - } - }.runTaskLater(EvoCraft.getPlugin(), 80); - } - } - } - } - public static void snowShotAbility(PlayerInteractEvent playerInteractEvent, @NotNull Player player, ItemStack itemStack) { // Summon a snowball and shoot it, then apply a metadata tag that will be used to check if the snowball is a snowball shot by the player Snowball snowball = player.launchProjectile(Snowball.class, player.getLocation().getDirection().multiply(3)); diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index cad2898..67f497b 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -13,8 +13,6 @@ import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.loot.LootTable; import me.zenox.evocraft.loot.LootTableRegistry; -import me.zenox.evocraft.story.Chapter; -import me.zenox.evocraft.story.ChapterManager; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -191,43 +189,6 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman Util.sendMessage(sender, ChatColor.WHITE + "The CustomModelData of " + item.getItemMeta().getDisplayName() + ChatColor.WHITE + " is " + ComplexItem.of(item).getCustomModelData()); return true; } - case "removechapterdata" -> { - if (sender instanceof Player){ - ((Player) sender).getPersistentDataContainer().remove(ChapterManager.CHAPTER_KEY); - Util.sendMessage(sender, "All chapter data has been removed."); - } - else { - Util.sendMessage(sender, "You must be a player to use this command!"); - } - } - case "removemetadata" -> { - if (sender instanceof Player){ - sender.getServer().getPlayer(args[1]).removeMetadata("hasStarted", EvoCraft.getPlugin()); - Util.sendMessage(sender, "All chapter data has been removed."); - } - else { - Util.sendMessage(sender, "You must be a player to use this command!"); - } - } - case "setchapter" -> { - // Set the chapter given the player and the chapter's id - if (args.length < 2 || sender.getServer().getPlayer(args[1]) == null) { - Util.sendMessage(sender, "Please specify a valid user to set the chapter of."); - return true; - } - if (args.length < 3) { - Util.sendMessage(sender, "Please specify a valid chapter."); - return true; - } - Player player = sender.getServer().getPlayer(args[1]); - Chapter chapter = EvoCraft.getChapterManager().getChapter(Ints.tryParse(args[2])); - if (chapter == null) { - Util.sendMessage(sender, "This chapter does not exist!"); - return true; - } - EvoCraft.getChapterManager().setChapter(player, chapter); - return true; - } case "class" -> // Open the class selection GUI new SimpleWindow(((Player) sender), "Class Selection", GameClass.getGui(), true, true).show(); case "progresspath" -> { diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index 7f06179..91ef88c 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -403,18 +403,6 @@ public class ItemRegistry { .ability(AbilityRegistry.GILDED_CONSUME) .rarity(ComplexItem.Rarity.RARE)); - public static final ComplexItem START_BUTTON = new ComplexItem(new ItemSettings() - .id("start_button") - .material(Material.REDSTONE) - .ability(AbilityRegistry.START_BUTTON) - .rarity(ComplexItem.Rarity.MYTHIC)); - - public static final ComplexItem SOUL_STONE = new ComplexItem(new ItemSettings() - .id("soul_stone") - .material(Material.NETHER_STAR) - .ability(AbilityRegistry.PORTALIZER) - .rarity(ComplexItem.Rarity.MYTHIC)); - public static final ComplexItem ARCANE_JEWEL = new ComplexItem(new ItemSettings() .id("arcane_jewel") .material(Material.AMETHYST_SHARD) diff --git a/src/main/java/me/zenox/evocraft/story/Action.java b/src/main/java/me/zenox/evocraft/story/Action.java deleted file mode 100644 index 69f3e99..0000000 --- a/src/main/java/me/zenox/evocraft/story/Action.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.zenox.evocraft.story; - -import org.bukkit.event.Event; - -public class Action{ - -} diff --git a/src/main/java/me/zenox/evocraft/story/Chapter.java b/src/main/java/me/zenox/evocraft/story/Chapter.java deleted file mode 100644 index 035117c..0000000 --- a/src/main/java/me/zenox/evocraft/story/Chapter.java +++ /dev/null @@ -1,70 +0,0 @@ -package me.zenox.evocraft.story; - -import me.zenox.evocraft.EvoCraft; -import me.zenox.evocraft.data.TranslatableText; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.Listener; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -/** - * A chapter is a part of the story. It is a collection of actions that are executed when the chapter starts and ends. - * @param The event that triggers the chapter. - * @param The event that triggers the end of the chapter (the event that triggers the next chapter). - */ -public abstract class Chapter implements Listener { - private final int id; - private final TranslatableText name; - /** - * Whether the chapter is a "solo" chapter. A solo chapter is a chapter that the player has to perform alone, without any other players, hiding them from all other players. - */ - private final boolean solo; - - public Chapter(int id, boolean solo) { - this.id = id; - this.name = new TranslatableText("chapter-" + id); - this.solo = solo; - } - - private Type getType(int index) { - Class clazz = getClass(); - while (clazz != null) { - Type type = clazz.getGenericSuperclass(); - if (type instanceof ParameterizedType) { - return ((ParameterizedType) type).getActualTypeArguments()[index]; - } - clazz = clazz.getSuperclass(); - } - return null; - } - - /** - * Method that detects when a chapter should start and executes - */ - public abstract void onChapterStart(T event); - - /** - * Method that executes when a chapter ends - */ - public abstract void onChapterEnd(U event); - - public void progress(Player player, U event) { - EvoCraft.getChapterManager().setChapter(player, id + 1); - onChapterEnd(event); - EvoCraft.getChapterManager().getChapter(id + 1).onChapterStart(event); - } - - public int getId() { - return id; - } - - public TranslatableText getName() { - return name; - } - - public boolean isSolo() { - return solo; - } -} diff --git a/src/main/java/me/zenox/evocraft/story/ChapterManager.java b/src/main/java/me/zenox/evocraft/story/ChapterManager.java deleted file mode 100644 index 7f8281c..0000000 --- a/src/main/java/me/zenox/evocraft/story/ChapterManager.java +++ /dev/null @@ -1,109 +0,0 @@ -package me.zenox.evocraft.story; - -import me.zenox.evocraft.EvoCraft; -import me.zenox.evocraft.story.chapters.ChapterOne; -import me.zenox.evocraft.story.chapters.ChapterTwo; -import me.zenox.evocraft.story.chapters.ChapterZero; -import me.zenox.evocraft.util.Util; -import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.persistence.PersistentDataType; -import org.bukkit.scheduler.BukkitRunnable; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class ChapterManager implements Listener { - public static NamespacedKey CHAPTER_KEY = new NamespacedKey(EvoCraft.getPlugin(), "chapter"); - - private EvoCraft plugin; - - public List chapters = new ArrayList<>(); - - static { - // Runnable that hides players for solo chapters - new BukkitRunnable(){ - @Override - public void run() { - ChapterManager manager = EvoCraft.getPlugin().getChapterManager(); - for(Player p : Bukkit.getOnlinePlayers()){ - try { - if (manager.getChapter(p).isSolo()) { - for (Player p2 : Bukkit.getOnlinePlayers()) { - if (p != p2) { - p.hidePlayer(EvoCraft.getPlugin(), p2); - if (!p2.getEffectivePermissions().contains("evocraft.admin")) - p2.hidePlayer(EvoCraft.getPlugin(), p); - } - } - } else { - for (Player p2 : Bukkit.getOnlinePlayers()) { - p.showPlayer(EvoCraft.getPlugin(), p2); - p2.showPlayer(EvoCraft.getPlugin(), p); - } - } - } catch (NullPointerException e){ - Util.logToConsole("Player " + p.getName() + " has no chapter data!"); - manager.setChapter(p, manager.getChapter(2)); - //p.kickPlayer("You have no chapter data! Please rejoin."); - } - } - } - }.runTaskTimer(EvoCraft.getPlugin(), 1, 10); - } - - public ChapterManager(EvoCraft plugin) { - this.plugin = plugin; - registerChapters(); - Bukkit.getPluginManager().registerEvents(this, plugin); - } - - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - Player player = event.getPlayer(); - Chapter chapter = getChapter(player); - Util.logToConsole("Player " + player.getName() + " joined with chapter " + chapter.getId()); - if(chapter == null) { - chapter = ChapterZero.getInstance(); - player.getPersistentDataContainer().set(CHAPTER_KEY, PersistentDataType.INTEGER, chapter.getId()); - } - - if(chapter.equals(ChapterZero.getInstance())) chapter.onChapterStart(event); - } - - @Nullable - public Chapter getChapter(@NotNull Player player){ - return player.getPersistentDataContainer().has(CHAPTER_KEY, PersistentDataType.INTEGER) ? chapters.get(player.getPersistentDataContainer().get(CHAPTER_KEY, PersistentDataType.INTEGER)) : null; - } - - @Nullable - public Chapter getChapter(int id){ - return chapters.get(id); - } - - public void setChapter(Player p, Chapter chapter){ - p.getPersistentDataContainer().set(CHAPTER_KEY, PersistentDataType.INTEGER, chapter.getId()); - } - - public void setChapter(Player p, int id){ - Util.sendMessage(p, "Setting chapter of player %s to %s.".formatted(p.getName(), id)); - try{ - setChapter(p, chapters.get(id)); - } catch (IndexOutOfBoundsException e){ - throw(new IndexOutOfBoundsException("Chapter with id " + id + " does not exist!")); - } - } - - public void registerChapters() { - // Register all chapters here - chapters.add(ChapterZero.getInstance()); - chapters.add(ChapterOne.getInstance()); - chapters.add(ChapterTwo.getInstance()); - } -} diff --git a/src/main/java/me/zenox/evocraft/story/chapters/ChapterOne.java b/src/main/java/me/zenox/evocraft/story/chapters/ChapterOne.java deleted file mode 100644 index b88748f..0000000 --- a/src/main/java/me/zenox/evocraft/story/chapters/ChapterOne.java +++ /dev/null @@ -1,35 +0,0 @@ -package me.zenox.evocraft.story.chapters; - -import me.zenox.evocraft.story.Chapter; -import me.zenox.evocraft.util.Romans; -import me.zenox.evocraft.util.Util; -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.event.player.PlayerInteractEvent; - -public class ChapterOne extends Chapter { - - private static ChapterOne instance = null; - - private ChapterOne() { - super(1, true); - } - - @Override - public void onChapterStart(PlayerInteractEvent event) { - Util.sendTitle(event.getPlayer(), "&b&lChapter " + Romans.encode(this.getId()), "&lThe Guardian's Keep", 10, 40, 10); - event.getPlayer().teleport(new Location(event.getPlayer().getServer().getWorld("flat"), -346, -54, -510)); - event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 0.5f, 0.8f); - // Begin Voiceover - event.getPlayer().playSound(event.getPlayer().getLocation(), "story.chapter.1.backstory_1", 20f, 1f); - } - - @Override - public void onChapterEnd(PlayerInteractEvent event) { - } - - public static ChapterOne getInstance() { - if(instance == null) instance = new ChapterOne(); - return instance; - } -} diff --git a/src/main/java/me/zenox/evocraft/story/chapters/ChapterTwo.java b/src/main/java/me/zenox/evocraft/story/chapters/ChapterTwo.java deleted file mode 100644 index ad3ed6e..0000000 --- a/src/main/java/me/zenox/evocraft/story/chapters/ChapterTwo.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.zenox.evocraft.story.chapters; - -import me.zenox.evocraft.story.Chapter; -import me.zenox.evocraft.util.Romans; -import me.zenox.evocraft.util.Util; -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.event.player.PlayerInteractEvent; - -public class ChapterTwo extends Chapter { - private static ChapterTwo instance = null; - - private ChapterTwo() { - super(2, false); - } - - @Override - public void onChapterStart(PlayerInteractEvent event) { - Util.sendTitle(event.getPlayer(), "&b&lChapter " + Romans.encode(this.getId()), "&lHumble Beginnings", 10, 40, 10); - event.getPlayer().teleport(new Location(event.getPlayer().getServer().getWorld("flat"), -134, 78, -466)); - event.getPlayer().setBedSpawnLocation(new Location(event.getPlayer().getServer().getWorld("flat"), -134, 78, -466), true); - event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.BLOCK_PORTAL_TRAVEL, 1, 1.5f); - Util.sendMessage(event.getPlayer(), "&b&lQUICK TIP: &fExplore the island! Head to the portal at the center of the island once you would like to begin your adventure."); - - } - - @Override - public void onChapterEnd(PlayerInteractEvent event) { - // Clear the player's inventory - event.getPlayer().getInventory().clear(); - } - - public static ChapterTwo getInstance() { - if(instance == null) instance = new ChapterTwo(); - return instance; - } -} diff --git a/src/main/java/me/zenox/evocraft/story/chapters/ChapterZero.java b/src/main/java/me/zenox/evocraft/story/chapters/ChapterZero.java deleted file mode 100644 index 50b2931..0000000 --- a/src/main/java/me/zenox/evocraft/story/chapters/ChapterZero.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zenox.evocraft.story.chapters; - -import me.zenox.evocraft.item.ComplexItemStack; -import me.zenox.evocraft.item.ItemRegistry; -import me.zenox.evocraft.story.Chapter; -import me.zenox.evocraft.util.Util; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerJoinEvent; - -public class ChapterZero extends Chapter { - - private static ChapterZero instance = null; - - private ChapterZero() { - super(0, true); - } - - @Override - public void onChapterStart(PlayerJoinEvent event) { - Player player = event.getPlayer(); - player.teleport(new Location(event.getPlayer().getServer().getWorld("flat"), -367, 17, -593)); - Util.sendTitle(player, "&b&lChapter Ω", "&d&lPress Start", 10, 150, 10); - Util.sendMessage(player, "&eNote: &bEvoCraft &fis best experienced with sounds turned on. If you have sounds turned off, you may miss elemental effects, voiceovers, and other important sounds."); - player.getInventory().setHeldItemSlot(4); - player.getInventory().setItem(4, new ComplexItemStack(ItemRegistry.START_BUTTON).getItem()); - } - - @Override - public void onChapterEnd(PlayerInteractEvent event) { - // Clear the player's inventory - event.getPlayer().getInventory().clear(); - } - - public static ChapterZero getInstance() { - if(instance == null) instance = new ChapterZero(); - return instance; - } -} - From e5ae20177a822726040ace65784110d089fff0be Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Fri, 10 Nov 2023 19:28:51 -0800 Subject: [PATCH 09/20] Creative Item Handling, ComplexItem#of null --- .../java/me/zenox/evocraft/abilities/ClassAbility.java | 10 ++++++---- .../me/zenox/evocraft/events/InventoryListener.java | 9 +++++++++ src/main/java/me/zenox/evocraft/item/ComplexItem.java | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 4a4ddea..8fc2433 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -324,6 +324,7 @@ public static void arcaneTeleport(PlayerInteractEvent event, Player player, Clas public static void manaBallAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { // Create the projectile Snowball projectile = player.launchProjectile(Snowball.class); + projectile.setGravity(false); // Set projectile properties projectile.setVelocity(player.getLocation().getDirection().multiply(1.5)); // Speed of the projectile @@ -337,18 +338,19 @@ public static void manaBallAbility(PlayerInteractEvent event, Player player, Cla final int range = ability.getRange(); @Override public void run() { - if (a >= 20 || start.distance(projectile.getLocation()) > range) { + if (a >= 20 || start.distance(projectile.getLocation()) > range || projectile.isDead()) { + projectile.remove(); cancel(); return; } // spawn some end rod particles and some teal colored "mana" redstone particles - player.getWorld().spawnParticle(Particle.END_ROD, projectile.getLocation(), 1, 0, 0, 0, 0); - player.getWorld().spawnParticle(Particle.REDSTONE, projectile.getLocation(), 1, 0, 0, 0, + player.getWorld().spawnParticle(Particle.END_ROD, projectile.getLocation(), 1, 0.1, 0, 0.1, 0); + player.getWorld().spawnParticle(Particle.REDSTONE, projectile.getLocation(), 1, 0, 0.1, 0, new Particle.DustOptions(Color.fromRGB(0, 255, 255), 1)); a++; } - }.runTaskTimer(EvoCraft.getPlugin(), 0, 3); + }.runTaskTimer(EvoCraft.getPlugin(), 0, 2); } public static void manaBallDamage(@NotNull ProjectileHitEvent event, int strength){ diff --git a/src/main/java/me/zenox/evocraft/events/InventoryListener.java b/src/main/java/me/zenox/evocraft/events/InventoryListener.java index 28c5da2..b11bde7 100644 --- a/src/main/java/me/zenox/evocraft/events/InventoryListener.java +++ b/src/main/java/me/zenox/evocraft/events/InventoryListener.java @@ -11,6 +11,7 @@ import org.bukkit.event.entity.EntityDropItemEvent; import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCreativeEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.ItemStack; @@ -39,6 +40,7 @@ public void inventoryOpenEvent(InventoryOpenEvent event) { public void inventoryInteractEvent(InventoryClickEvent event) { ArrayList contents = new ArrayList<>(); contents.add(event.getCurrentItem()); + contents.add(event.getCursor()); if(!event.isCancelled()) updateItems(contents); } @@ -62,6 +64,13 @@ public void itemDropEvent(BlockDropItemEvent event){ updateItems(contents); } + @EventHandler + public void creativeEvent(InventoryCreativeEvent event) { + ArrayList contents = new ArrayList<>(); + contents.add(event.getCursor()); + updateItems(contents); + } + private void updateItems(List contents) { contents.removeIf(Objects::isNull); diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItem.java b/src/main/java/me/zenox/evocraft/item/ComplexItem.java index 6ce53b2..affbd6a 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItem.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItem.java @@ -122,6 +122,8 @@ public ComplexItem(ItemSettings settings) { * @return The ComplexItem object of the item */ public static ComplexItem of(ItemStack item) { + if (item == null) return null; + if (item.getItemMeta() == null) return VanillaItem.of(item.getType()); PersistentDataContainer container = item.getItemMeta().getPersistentDataContainer(); if (container.has(GLOBAL_ID, PersistentDataType.STRING)) return itemRegistry.get(container.get(GLOBAL_ID, PersistentDataType.STRING)); From 2f1cac65fc18053d6482685f6ef55bf4613183be Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Sat, 11 Nov 2023 01:57:16 -0800 Subject: [PATCH 10/20] Mage Ball Ability --- .../me/zenox/evocraft/abilities/Ability.java | 2 +- .../evocraft/abilities/AbilityRegistry.java | 7 +- .../evocraft/abilities/ClassAbility.java | 123 +++++++++++++++--- src/main/resources/languages/en_US.yml | 4 +- 4 files changed, 114 insertions(+), 22 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/Ability.java b/src/main/java/me/zenox/evocraft/abilities/Ability.java index c0721b5..6934d1c 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Ability.java +++ b/src/main/java/me/zenox/evocraft/abilities/Ability.java @@ -129,7 +129,7 @@ protected void deductMana(Player p, int manaCost) { protected void showMessage(Player p, String msg) { String manaMessage = manaCost > 0 ? ChatColor.AQUA + "-" + manaCost + " Mana " + "(" + ChatColor.GOLD + name + ChatColor.AQUA + ")" : ChatColor.GOLD + "Used " + name; - if (!isPassive) Util.sendActionBar(p, manaMessage + " " + msg); + if (!isPassive) Util.sendActionBar(p, manaMessage + msg); } protected void setAbilityCooldown(Player p) { diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 8e15e6f..a51cac4 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -173,13 +173,18 @@ public class AbilityRegistry { public static final ClassAbility MANA_BALL = new ClassAbility(new AbilitySettings() .id("mage_mana_ball") - .manaCost(10) + .manaCost(15) .cooldown(0) .range(20) .strength(1) .charges(-1) .chargeTime(-1) .modifier(Modifier.of(Modifier.Type.MANA_COST, "mana_ball_mana_1", -5)) + .modifier(Modifier.of(Modifier.Type.RANGE, "mana_ball_range_1", +2)) + .modifier(Modifier.of(Modifier.Type.STRENGTH, "mana_ball_strength_1", +1)) + .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "mana_ball_homing", ClassAbility::homingManaBall)) + .modifier(Modifier.of(Modifier.Type.MANA_COST, "mana_ball_strength_2", +2)) + .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "mana_ball_multishot", ClassAbility::multishotManaBall)) , ClassAbility::manaBallAbility); public static final ClassAbility RIFT_BEAM = new ClassAbility(new AbilitySettings() .id("mage_rift_beam") diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 8fc2433..37ad6ed 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -87,7 +87,7 @@ public void useAbility(Event event) { int level = data.getPathLevel(data.getPlayerClass().tree().path(this)); if (level == -1) { - Util.sendActionBar(p, "&cABILITY %s LOCKED!".formatted(this.getId().replace('_', ' ').toUpperCase())); + Util.sendActionBar(p, "&c&l%s LOCKED!".formatted(this.getDisplayName().toUpperCase())); return; // ability is not unlocked } @@ -112,9 +112,12 @@ public void useAbility(Event event) { } deductMana(p, this.getManaCost()); - int chargesLeft = Ability.cooldownManager.consumeCharge(p, this); - String chargeMsg = "&6(&e%d&6/%d) (-1)".formatted(chargesLeft, this.getCharges()); + String chargeMsg = ""; + if (this.getCharges() > 0) { + int chargesLeft = Ability.cooldownManager.consumeCharge(p, this); + chargeMsg = " &6(&e%d&6/%d) (-1)".formatted(chargesLeft, this.getCharges()); + } showMessage(p, chargeMsg); this.executable.accept(e, p, this); @@ -321,36 +324,117 @@ public static void arcaneTeleport(PlayerInteractEvent event, Player player, Clas darkTeleport(event, player, ability); } + // Constants for the homing behavior + private static final double ACCELERATION_RATE = 0.2; + private static final double MAX_TURN_RATE = Math.toRadians(7); + public static void manaBallAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { - // Create the projectile - Snowball projectile = player.launchProjectile(Snowball.class); - projectile.setGravity(false); + Snowball projectile = createProjectile(player, ability); + startParticleTask(player, projectile, ability.getRange()).runTaskTimer(EvoCraft.getPlugin(), 0, 2); + } - // Set projectile properties - projectile.setVelocity(player.getLocation().getDirection().multiply(1.5)); // Speed of the projectile + public static void homingManaBall(PlayerInteractEvent event, Player player, ClassAbility ability) { + Snowball projectile = createProjectile(player, ability); + startHomingTask(player, projectile, ability.getRange()).runTaskTimer(EvoCraft.getPlugin(), 0, 1); + } - // Apply metadata to the projectile so we can identify it later as a mana projectile + public static void multishotManaBall(PlayerInteractEvent event, Player player, ClassAbility ability) { + // Here you can define how many projectiles you want to shoot + int numberOfProjectiles = 3; + for (int i = 0; i < numberOfProjectiles; i++) { + Snowball projectile = createProjectile(player, ability); + // Let's keep the projectiles straight but instead shoot them in parallel with offsets + Vector direction = projectile.getLocation().getDirection().setY(0).normalize(); + Vector perpendicular = direction.rotateAroundY(Math.toRadians(90)); + Vector offset = perpendicular.multiply(((i - numberOfProjectiles/2)*1.5)); + projectile.teleport(projectile.getLocation().add(offset)); + startHomingTask(player, projectile, ability.getRange()).runTaskTimer(EvoCraft.getPlugin(), 0, 2); + } + } + + private static Snowball createProjectile(Player player, ClassAbility ability) { + Snowball projectile = player.launchProjectile(Snowball.class); + projectile.setGravity(false); + projectile.setVelocity(player.getLocation().getDirection().multiply(1.5)); projectile.setMetadata("mana_projectile", new FixedMetadataValue(EvoCraft.getPlugin(), ability.getStrength())); + return projectile; + } - new BukkitRunnable(){ - int a = 0; + private static BukkitRunnable startParticleTask(Player player, Snowball projectile, int range) { + return new BukkitRunnable() { final Location start = player.getLocation().clone(); - final int range = ability.getRange(); @Override public void run() { - if (a >= 20 || start.distance(projectile.getLocation()) > range || projectile.isDead()) { + if (start.distance(projectile.getLocation()) > range || !projectile.isValid()) { projectile.remove(); cancel(); return; } - // spawn some end rod particles and some teal colored "mana" redstone particles + spawnParticles(projectile.getLocation()); + } + }; + } - player.getWorld().spawnParticle(Particle.END_ROD, projectile.getLocation(), 1, 0.1, 0, 0.1, 0); - player.getWorld().spawnParticle(Particle.REDSTONE, projectile.getLocation(), 1, 0, 0.1, 0, - new Particle.DustOptions(Color.fromRGB(0, 255, 255), 1)); - a++; + private static BukkitRunnable startHomingTask(Player player, Snowball projectile, int range) { + return new BukkitRunnable() { + final Location start = player.getLocation().clone(); + @Override + public void run() { + if (start.distance(projectile.getLocation()) > range || !projectile.isValid()) { + projectile.remove(); + cancel(); + return; + } + LivingEntity target = findNearestTarget(projectile, player); + if (target != null) { + adjustProjectileVelocity(projectile, target); + } + spawnParticles(projectile.getLocation()); + } + }; + } + + private static void spawnParticles(Location location) { + location.getWorld().spawnParticle(Particle.END_ROD, location, 1, 0.1, 0, 0.1, 0); + location.getWorld().spawnParticle(Particle.REDSTONE, location, 1, 0, 0.1, 0, + new Particle.DustOptions(Color.fromRGB(0, 255, 255), 1)); + } + + private static void adjustProjectileVelocity(Snowball projectile, LivingEntity target) { + Vector currentVelocity = projectile.getVelocity(); + Vector toTarget = target.getEyeLocation().toVector().subtract(projectile.getLocation().toVector()).normalize(); + Vector newVelocity = currentVelocity.clone().add(toTarget.clone().subtract(currentVelocity).normalize().multiply(ACCELERATION_RATE)); + if (currentVelocity.angle(newVelocity) > MAX_TURN_RATE) { + newVelocity = rotateVectorTowards(currentVelocity, toTarget, MAX_TURN_RATE); + } + projectile.setVelocity(newVelocity.normalize().multiply(currentVelocity.length())); + } + + private static Vector rotateVectorTowards(Vector source, Vector target, double maxAngle) { + double angle = source.angle(target); + if (angle < maxAngle) return target; // No need to rotate if within max angle + + double theta = Math.min(angle, maxAngle) / angle; + return source.clone().multiply(1 - theta).add(target.clone().multiply(theta)).normalize(); + } + + private static LivingEntity findNearestTarget(Entity projectile, Player caster) { + Location location = projectile.getLocation(); + double minDistance = Double.MAX_VALUE; + LivingEntity nearest = null; + + for (Entity entity : location.getWorld().getNearbyEntities(location, 10, 10, 10) + .stream() + .filter(entity -> entity instanceof LivingEntity && ((LivingEntity) entity).hasLineOfSight(projectile)).toList()) { + if (entity instanceof LivingEntity && !entity.equals(caster)) { + double distance = entity.getLocation().distance(location); + if (distance < minDistance) { + minDistance = distance; + nearest = (LivingEntity) entity; + } } - }.runTaskTimer(EvoCraft.getPlugin(), 0, 2); + } + return nearest; } public static void manaBallDamage(@NotNull ProjectileHitEvent event, int strength){ @@ -358,6 +442,7 @@ public static void manaBallDamage(@NotNull ProjectileHitEvent event, int strengt if (event.getHitEntity() instanceof LivingEntity) { LivingEntity target = (LivingEntity) event.getHitEntity(); target.damage(5.0*strength, (Entity) event.getEntity().getShooter()); // Deal 5 points of damage, customize as needed + target.setNoDamageTicks(0); // Additional effects can be added here, like knockback or status effects } // Remove the projectile upon impact diff --git a/src/main/resources/languages/en_US.yml b/src/main/resources/languages/en_US.yml index 11b1959..d4a60f8 100644 --- a/src/main/resources/languages/en_US.yml +++ b/src/main/resources/languages/en_US.yml @@ -632,7 +632,9 @@ ability-lore-thunderstrike: ## CLASS ABILITIES ## ########################################################################## ability-name-mage_teleport: Teleport -abilit-name-mage_mana_ball: Mana Ball +ability-name-mage_mana_ball: Mana Ball +ability-name-mage_rift_beam: Rift Beam +ability-name-mage_rune_shield: Rune Shield ########################################################################## From 17072cc696b7ab542804ca3577534932808c81ba Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Mon, 13 Nov 2023 17:47:25 -0800 Subject: [PATCH 11/20] limit abilities to their max --- .../java/me/zenox/evocraft/abilities/ElementalFlux.java | 1 + .../evocraft/abilities/itemabilities/ItemAbility.java | 3 ++- src/main/java/me/zenox/evocraft/command/Command.java | 7 ++++++- src/main/java/me/zenox/evocraft/data/PlayerData.java | 4 +++- .../me/zenox/evocraft/gameclass/tree/AbilityPath.java | 2 +- src/main/java/me/zenox/evocraft/gameclass/tree/Path.java | 8 +++++++- src/main/java/me/zenox/evocraft/item/ItemRegistry.java | 1 + 7 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java b/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java index d745a55..920e4c8 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java +++ b/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java @@ -1,5 +1,6 @@ package me.zenox.evocraft.abilities; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.item.LoreEntry; diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java index 875435e..3a1fee9 100644 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java @@ -13,9 +13,10 @@ import com.ticxo.modelengine.api.ModelEngineAPI; import com.ticxo.modelengine.api.model.ModeledEntity; import it.unimi.dsi.fastutil.ints.IntArrayList; -import me.zenox.evocraft.Slot; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.Slot; import me.zenox.evocraft.abilities.AbilitySettings; +import me.zenox.evocraft.abilities.ElementalFlux; import me.zenox.evocraft.abilities.EventAbility; import me.zenox.evocraft.abilities.itemabilities.specific.EmberAttune; import me.zenox.evocraft.item.ComplexItemMeta; diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index 67f497b..c0bba5a 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -203,7 +203,12 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman Util.sendMessage(sender, "This path does not exist!"); return true; } - data.progressAbility(path); + try { + data.progressAbility(path); + } catch (IllegalArgumentException e) { + Util.sendMessage(sender, e.getMessage()); + return true; + } return true; } default -> Util.sendMessage(sender, "EvoCraft Help Page."); diff --git a/src/main/java/me/zenox/evocraft/data/PlayerData.java b/src/main/java/me/zenox/evocraft/data/PlayerData.java index 17fd822..e670d22 100644 --- a/src/main/java/me/zenox/evocraft/data/PlayerData.java +++ b/src/main/java/me/zenox/evocraft/data/PlayerData.java @@ -55,7 +55,9 @@ public void setPathLevel(Path path, int level) { // Progress the level of a specific ability public void progressAbility(Path path) { int currentLevel = getPathLevel(path); - setPathLevel(path, currentLevel + 1); + if (getPathLevel(path) < path.getMaxLevel()) + setPathLevel(path, currentLevel + 1); + else throw new IllegalArgumentException("Ability " + path.getId() + " is already at max level!"); } // Display all abilities and their levels diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java index 76328e6..a93151a 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/AbilityPath.java @@ -11,7 +11,7 @@ public class AbilityPath extends Path { public final ClassAbility ability; public AbilityPath(String id, ClassAbility ability) { - super(id); + super(id, ability.getModifiers().size()); this.ability = ability; } diff --git a/src/main/java/me/zenox/evocraft/gameclass/tree/Path.java b/src/main/java/me/zenox/evocraft/gameclass/tree/Path.java index 71d8829..709fb6b 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/tree/Path.java +++ b/src/main/java/me/zenox/evocraft/gameclass/tree/Path.java @@ -13,10 +13,12 @@ public abstract class Path { private String id; public static final List registeredPaths = new ArrayList<>(); + private final int maxLevel; // Constructor - public Path(String id) { + public Path(String id, int maxLevel) { this.id = id; + this.maxLevel = maxLevel; registeredPaths.add(this); } @@ -42,4 +44,8 @@ public void progress(PlayerData playerData) { // Abstract method to apply stats, metadata, etc. to player public abstract void apply(PlayerData playerData); + + public int getMaxLevel() { + return maxLevel; + } } \ No newline at end of file diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index a5b566e..a951a8e 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -2,6 +2,7 @@ import com.archyx.aureliumskills.stats.Stats; import me.zenox.evocraft.abilities.AbilityRegistry; +import me.zenox.evocraft.abilities.ElementalFlux; import me.zenox.evocraft.abilities.itemabilities.specific.Crucify; import me.zenox.evocraft.abilities.itemabilities.specific.EmberAttune; import me.zenox.evocraft.abilities.itemabilities.specific.Psychic; From 2852c34c68e8ed759446ee9134ffe9619f9869c6 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Mon, 13 Nov 2023 17:47:48 -0800 Subject: [PATCH 12/20] new multi operator --- .../evocraft/abilities/AbilityRegistry.java | 57 ++-- .../evocraft/abilities/AbilitySettings.java | 5 + .../evocraft/abilities/ClassAbility.java | 309 +++++++++++++++++- .../me/zenox/evocraft/abilities/Modifier.java | 21 ++ 4 files changed, 357 insertions(+), 35 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 677730d..f0b1f94 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -164,15 +164,15 @@ public class AbilityRegistry { .strength(1) .charges(1) .chargeTime(15) - .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_1", +2)) - .modifier(Modifier.of(Modifier.Type.MANA_COST, "teleport_mana_1", -5)) - .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_1", +1)) - .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_dark", ClassAbility::darkTeleport)) - .modifier(Modifier.of(Modifier.Type.STRENGTH, "teleport_strength_1", +1)) - .modifier(Modifier.of(Modifier.Type.CHARGE, "teleport_charge_2", +1)) - .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_surge", ClassAbility::surgeTeleport)) - .modifier(Modifier.of(Modifier.Type.RANGE, "teleport_range_2", +4)) - .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "teleport_arcane", ClassAbility::arcaneTeleport)) + .modifiers(Modifier.of(Modifier.Type.RANGE, "teleport_range_1", +2), + Modifier.of(Modifier.Type.MANA_COST, "teleport_mana_1", -5), + Modifier.of(Modifier.Type.CHARGE, "teleport_charge_1", +1), + Modifier.of(Modifier.Type.EXECUTABLE, "teleport_dark", ClassAbility::darkTeleport), + Modifier.of(Modifier.Type.STRENGTH, "teleport_strength_1", +1), + Modifier.of(Modifier.Type.CHARGE, "teleport_charge_2", +1), + Modifier.of(Modifier.Type.EXECUTABLE, "teleport_surge", ClassAbility::surgeTeleport), + Modifier.of(Modifier.Type.RANGE, "teleport_range_2", +4), + Modifier.of(Modifier.Type.EXECUTABLE, "teleport_arcane", ClassAbility::arcaneTeleport)) , ClassAbility::teleportAbility); public static final ClassAbility MANA_BALL = new ClassAbility(new AbilitySettings() @@ -183,27 +183,44 @@ public class AbilityRegistry { .strength(1) .charges(-1) .chargeTime(-1) - .modifier(Modifier.of(Modifier.Type.MANA_COST, "mana_ball_mana_1", -5)) - .modifier(Modifier.of(Modifier.Type.RANGE, "mana_ball_range_1", +2)) - .modifier(Modifier.of(Modifier.Type.STRENGTH, "mana_ball_strength_1", +1)) - .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "mana_ball_homing", ClassAbility::homingManaBall)) - .modifier(Modifier.of(Modifier.Type.MANA_COST, "mana_ball_strength_2", +2)) - .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "mana_ball_multishot", ClassAbility::multishotManaBall)) + .modifiers(Modifier.of(Modifier.Type.MANA_COST, "mana_ball_mana_1", -5), + Modifier.of(Modifier.Type.RANGE, "mana_ball_range_1", +2), + Modifier.of(Modifier.Type.STRENGTH, "mana_ball_strength_1", +1), + Modifier.of(Modifier.Type.EXECUTABLE, "mana_ball_homing", ClassAbility::homingManaBall), + Modifier.of(Modifier.Type.MANA_COST, "mana_ball_strength_2", +1), + Modifier.of(Modifier.Type.RANGE, "mana_ball_range", +5), + Modifier.of(Modifier.Type.EXECUTABLE, "mana_ball_multishot", ClassAbility::multishotManaBall), + Modifier.of(Modifier.Type.MANA_COST, "mana_ball_strength_2", +1), + Modifier.of(Modifier.Type.MULTI, "mana_ball_am", + Modifier.of(Modifier.Type.MANA_COST, "mana_ball_am_mana_boost", +50), + Modifier.of(Modifier.Type.EXECUTABLE, "mana_ball_am_arcane_multishot", ClassAbility::multishotArcaneSingularity), + Modifier.of(Modifier.Type.RANGE, "mana_ball_am_range", +15))) , ClassAbility::manaBallAbility); public static final ClassAbility RIFT_BEAM = new ClassAbility(new AbilitySettings() .id("mage_rift_beam") - .manaCost(50) - .cooldown(0) + .manaCost(40) + .cooldown(10) .range(20) - .strength(1) - , ClassAbility::riftBeamAbility); + .strength(2) + .charges(0) + .chargeTime(0) + .modifiers( + Modifier.of(Modifier.Type.RANGE, "rift_beam_extend", +5), + Modifier.of(Modifier.Type.STRENGTH, "rift_beam_energize", +1), + Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_mark", ClassAbility::riftBeamMark), + Modifier.of(Modifier.Type.MANA_COST, "rift_beam_efficiency", -10), + Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_chain", ClassAbility::riftBeamChain), + Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_dimensional_rupture", ClassAbility::riftBeamDimensionalRupture), + Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_apex", ClassAbility::riftBeamApex) + ), ClassAbility::riftBeamAbility); public static final ClassAbility RUNE_SHIELD = new ClassAbility(new AbilitySettings() .id("mage_rune_shield") .manaCost(50) .cooldown(0) .range(20) .strength(1) - , ClassAbility::runeShieldAbility); +, + ClassAbility::runeShieldAbility); public static void registerAbilities(){ Util.logToConsole("Registering %s abilities.".formatted(ChatColor.GOLD + "" + Ability.registeredAbilities.size() + ChatColor.RESET)); diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java index df52fec..0f9c718 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilitySettings.java @@ -102,6 +102,11 @@ public AbilitySettings modifiers(List modifiers) { return this; } + public AbilitySettings modifiers(Modifier... modifiers) { + this.modifiers.addAll(List.of(modifiers)); + return this; + } + public AbilitySettings modifier(Modifier modifier) { this.modifiers.add(modifier); return this; diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 37ad6ed..560331d 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -6,14 +6,15 @@ import me.zenox.evocraft.util.Geo; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Particle; +import org.bukkit.*; import org.bukkit.entity.*; import org.bukkit.event.Event; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; @@ -335,7 +336,7 @@ public static void manaBallAbility(PlayerInteractEvent event, Player player, Cla public static void homingManaBall(PlayerInteractEvent event, Player player, ClassAbility ability) { Snowball projectile = createProjectile(player, ability); - startHomingTask(player, projectile, ability.getRange()).runTaskTimer(EvoCraft.getPlugin(), 0, 1); + startHomingTask(player, projectile, ability.getRange(), false).runTaskTimer(EvoCraft.getPlugin(), 0, 2); } public static void multishotManaBall(PlayerInteractEvent event, Player player, ClassAbility ability) { @@ -348,7 +349,7 @@ public static void multishotManaBall(PlayerInteractEvent event, Player player, C Vector perpendicular = direction.rotateAroundY(Math.toRadians(90)); Vector offset = perpendicular.multiply(((i - numberOfProjectiles/2)*1.5)); projectile.teleport(projectile.getLocation().add(offset)); - startHomingTask(player, projectile, ability.getRange()).runTaskTimer(EvoCraft.getPlugin(), 0, 2); + startHomingTask(player, projectile, ability.getRange(), false).runTaskTimer(EvoCraft.getPlugin(), 0, 2); } } @@ -375,7 +376,7 @@ public void run() { }; } - private static BukkitRunnable startHomingTask(Player player, Snowball projectile, int range) { + private static BukkitRunnable startHomingTask(Player player, Snowball projectile, int range, boolean down) { return new BukkitRunnable() { final Location start = player.getLocation().clone(); @Override @@ -387,7 +388,7 @@ public void run() { } LivingEntity target = findNearestTarget(projectile, player); if (target != null) { - adjustProjectileVelocity(projectile, target); + adjustProjectileVelocity(projectile, target, down); } spawnParticles(projectile.getLocation()); } @@ -400,16 +401,29 @@ private static void spawnParticles(Location location) { new Particle.DustOptions(Color.fromRGB(0, 255, 255), 1)); } - private static void adjustProjectileVelocity(Snowball projectile, LivingEntity target) { + private static void adjustProjectileVelocity(Snowball projectile, LivingEntity target, boolean downwards) { Vector currentVelocity = projectile.getVelocity(); - Vector toTarget = target.getEyeLocation().toVector().subtract(projectile.getLocation().toVector()).normalize(); - Vector newVelocity = currentVelocity.clone().add(toTarget.clone().subtract(currentVelocity).normalize().multiply(ACCELERATION_RATE)); - if (currentVelocity.angle(newVelocity) > MAX_TURN_RATE) { - newVelocity = rotateVectorTowards(currentVelocity, toTarget, MAX_TURN_RATE); + Vector targetDirection = target.getEyeLocation().toVector().subtract(projectile.getLocation().toVector()); + double currentHorizontalSpeed = Math.sqrt(currentVelocity.getX() * currentVelocity.getX() + currentVelocity.getZ() * currentVelocity.getZ()); + + Vector velocityAdjustment = targetDirection.clone().subtract(currentVelocity).normalize(); + Vector adjustedVelocity = currentVelocity.clone().add(velocityAdjustment); + + if (downwards) { + // Keep the horizontal velocity components the same to maintain horizontal speed + double adjustedY = adjustedVelocity.getY() - ACCELERATION_RATE * 1.1; // Slightly increase the downward acceleration + adjustedVelocity = new Vector(currentVelocity.getX(), adjustedY, currentVelocity.getZ()); + } else { + if (currentVelocity.angle(adjustedVelocity) > MAX_TURN_RATE) { + adjustedVelocity = rotateVectorTowards(currentVelocity, targetDirection.normalize(), MAX_TURN_RATE); + } + adjustedVelocity = adjustedVelocity.normalize().multiply(currentHorizontalSpeed).setY(adjustedVelocity.getY()); } - projectile.setVelocity(newVelocity.normalize().multiply(currentVelocity.length())); + + projectile.setVelocity(adjustedVelocity); } + private static Vector rotateVectorTowards(Vector source, Vector target, double maxAngle) { double angle = source.angle(target); if (angle < maxAngle) return target; // No need to rotate if within max angle @@ -423,7 +437,7 @@ private static LivingEntity findNearestTarget(Entity projectile, Player caster) double minDistance = Double.MAX_VALUE; LivingEntity nearest = null; - for (Entity entity : location.getWorld().getNearbyEntities(location, 10, 10, 10) + for (Entity entity : location.getWorld().getNearbyEntities(location, 10, 20, 10) .stream() .filter(entity -> entity instanceof LivingEntity && ((LivingEntity) entity).hasLineOfSight(projectile)).toList()) { if (entity instanceof LivingEntity && !entity.equals(caster)) { @@ -443,16 +457,281 @@ public static void manaBallDamage(@NotNull ProjectileHitEvent event, int strengt LivingEntity target = (LivingEntity) event.getHitEntity(); target.damage(5.0*strength, (Entity) event.getEntity().getShooter()); // Deal 5 points of damage, customize as needed target.setNoDamageTicks(0); - // Additional effects can be added here, like knockback or status effects + target.setFreezeTicks(target.getFreezeTicks()+strength*20); } // Remove the projectile upon impact event.getEntity().remove(); } + public static void multishotArcaneSingularity(PlayerInteractEvent event, Player player, ClassAbility ability) { + int numberOfProjectiles = 3; + double spreadAngle = 15; // Angle between each projectile + + Vector baseDirection = player.getLocation().getDirection().normalize(); + double basePitch = baseDirection.getY(); // Store the original pitch + + for (int i = 0; i < numberOfProjectiles; i++) { + // Calculate the yaw offset by spreading the projectiles evenly + double yawOffsetDegrees = spreadAngle * (i - (numberOfProjectiles - 1) / 2.0); + Vector direction = rotateVectorAroundY(baseDirection.setY(0).normalize(), yawOffsetDegrees); + direction.setY(basePitch); // Set the original pitch back to the direction vector + direction.normalize(); // Normalize the vector after adjusting pitch + + Snowball projectile = player.launchProjectile(Snowball.class); + projectile.setVelocity(direction.multiply(3.0)); + projectile.setMetadata("arcane_singularity", new FixedMetadataValue(EvoCraft.getPlugin(), true)); + Location prev = projectile.getLocation().clone(); + + new BukkitRunnable() { + final int abilityRange = ability.getRange(); + @Override + public void run() { + if (projectile.isDead() || projectile.isOnGround() || reachMaxRange(projectile, prev, abilityRange)) { + createSingularity(projectile.getLocation(), ability, player); + this.cancel(); // Stop the task after the singularity has been created + } + spawnParticles(projectile.getLocation()); + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 1L); + + startHomingTask(player, projectile, ability.getRange(), true).runTaskTimer(EvoCraft.getPlugin(), 0, 2); + } + } + + private static Vector rotateVectorAroundY(Vector vector, double angleDegrees) { + double angleRadians = Math.toRadians(angleDegrees); + double cos = Math.cos(angleRadians); + double sin = Math.sin(angleRadians); + double x = vector.getX() * cos + vector.getZ() * sin; + double z = vector.getX() * -sin + vector.getZ() * cos; + return new Vector(x, vector.getY(), z); + } + + private static boolean reachMaxRange(Projectile projectile, Location initial, int range) { + return projectile.getLocation().distance(initial) >= range; + } + + private static void createSingularity(Location location, ClassAbility ability, Player player) { + // Create a singularity effect at the location + int range = ability.getRange()/3; + int duration = ability.getRange()*20/3; + spawnSingularityParticles(location, duration, range); + applySingularityEffects(location, duration, range, player); + + // Schedule to end the singularity effect after its lifetime + Bukkit.getScheduler().runTaskLater(EvoCraft.getPlugin(), () -> { + endSingularity(location, ability); + }, duration); // Duration based on ability settings + } + + private static void spawnSingularityParticles(Location loc, int duration, int range) { + // Spawn particles to indicate the singularity + // Placeholder for actual particle effect code + final double RADIUS = range; + final double DELTA_ANGLE = Math.PI / 16; + + Location location = loc.clone().add(0, 1, 0).setDirection(new Vector(0, 0, 0)); + new BukkitRunnable(){ + double angle = 0; + int a = 0; + @Override + public void run(){ + if (a > duration) { + cancel(); + return; + } + spawnParticles(location.clone().add(Math.cos(angle) * RADIUS, 0, Math.sin(angle) * RADIUS)); + spawnParticles(location.clone().add(Math.cos(angle + Math.PI) * RADIUS, 0, Math.sin(angle + Math.PI) * RADIUS)); + spawnParticles(location.clone().add(0, RADIUS + Math.sin(angle) * RADIUS / 2, 0)); + angle += DELTA_ANGLE; + + if (angle % (Math.PI / 2) < DELTA_ANGLE) + location.getWorld().playSound(location.clone().add(0, RADIUS + Math.sin(angle) * RADIUS / 2, 0), Sound.ENTITY_FIREWORK_ROCKET_TWINKLE, 1, 0); + a++; + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 1L); + } + + + private static void applySingularityEffects(Location location, int duration, int range, Player p) { + final int radius = range; + final double pullStrength = 0.2; // Example pull strength + final double gravityEffect = 0.3; // Example additional gravity effect + + new BukkitRunnable() { + int a = 0; + @Override + public void run() { + if (a > duration) { + cancel(); + return; + } + location.getWorld().getNearbyEntities(location, radius, radius, radius).forEach(entity -> { + if (entity instanceof LivingEntity livingEntity && !entity.equals(p)) { + double distance = location.distance(livingEntity.getLocation()); + + // Apply slowness effect + int effectStrength = (int) (distance / radius * 4); // Scale from 0 to 4 + if (effectStrength > 0) { + livingEntity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 10, effectStrength, false, false, false)); + } + + livingEntity.setFreezeTicks(livingEntity.getFreezeTicks()+15); + + // Apply a grounding effect + if (livingEntity.isOnGround()) { + // Player is on the ground, possibly apply a minor pull + if (distance > radius) { + Vector towardsCenter = location.toVector().subtract(livingEntity.getLocation().toVector()).normalize(); + livingEntity.setVelocity(towardsCenter.multiply(pullStrength)); + } + } else { + // Player is in the air, apply downward force to simulate increased gravity + Vector currentVelocity = livingEntity.getVelocity(); + livingEntity.setVelocity(new Vector(currentVelocity.getX(), + Math.max(-gravityEffect, currentVelocity.getY() - gravityEffect), + currentVelocity.getZ())); + } + } + }); + a+= 5; + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 5L); // Repeat every second + } + + + private static void endSingularity(Location location, ClassAbility ability) { + // Logic to remove the singularity effects and clean up + // For example, removing potion effects from players in the area + location.getWorld().getNearbyEntities(location, ability.getRange(), ability.getRange(), ability.getRange()) + .stream() + .filter(entity -> entity instanceof Player) + .map(entity -> (Player) entity) + .forEach(player -> player.removePotionEffect(PotionEffectType.SLOW)); + } + + /** + * Casts the base Rift Beam ability. + * The beam damages and pierces through enemies in a straight line from the player's position. + * + * @param event The player interaction event. + * @param player The player casting the ability. + * @param ability The class ability information. + */ public static void riftBeamAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + // 1. Calculate the beam trajectory from the player's eye location in the direction they are looking. + Vector start = player.getEyeLocation().toVector(); + Vector end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange())).toVector(); + // 2. Spawn particles along this line to simulate the beam effect. + // 3. Check for entities in the beam's path and apply damage to them. + List tracedPath = Geo.lerpEdges(List.of(start, end), (int) (1.3 * start.distance(end))); + tracedPath = tracedPath.subList(0, tracedPath.size()/2); + tracedPath.forEach(vector -> { + player.getWorld().spawnParticle(Particle.END_ROD, vector.toLocation(player.getWorld()), 1, 0.1, 0.1, 0.1); + player.getWorld().spawnParticle(Particle.REDSTONE, vector.toLocation(player.getWorld()), 2, 0, 0, 0, + new Particle.DustOptions(Color.fromRGB(144, 0, 255), 1)); + player.getWorld().getNearbyEntities(vector.toLocation(player.getWorld()), 0.5, 0.5, 0.5).forEach(entity -> { + if (entity instanceof Damageable && !entity.equals(player)) { + ((Damageable) entity).damage(ability.getStrength()*5); + } + }); + }); + } + + /** + * Applies a mark to enemies hit by the Rift Beam. + * Marked enemies take increased damage from all sources for a short duration. + * + * @param event The player interaction event. + * @param player The player casting the ability. + * @param ability The class ability information. + */ + public static void riftBeamMark(PlayerInteractEvent event, Player player, ClassAbility ability) { + + Vector start = player.getEyeLocation().toVector(); + Vector end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange())).toVector(); + // Spawn particles along this line to simulate the beam effect. + // Check for entities in the beam's path and apply damage to them. + List tracedPath = Geo.lerpEdges(List.of(start, end), (int) (1.3 * start.distance(end))); + tracedPath = tracedPath.subList(0, tracedPath.size()/2); + tracedPath.forEach(vector -> { + player.getWorld().spawnParticle(Particle.END_ROD, vector.toLocation(player.getWorld()), 1, 0.1, 0.1, 0.1); + player.getWorld().spawnParticle(Particle.REDSTONE, vector.toLocation(player.getWorld()), 2, 0, 0, 0, + new Particle.DustOptions(Color.fromRGB(144, 0, 255), 1)); + player.getWorld().getNearbyEntities(vector.toLocation(player.getWorld()), 0.5, 0.5, 0.5).forEach(entity -> { + if (entity instanceof LivingEntity lEntity && !entity.equals(player)) { + lEntity.damage(ability.getStrength()*5); + + // Apply a potion effect to the target + lEntity.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 20*ability.getStrength(), 0)); + lEntity.broadcastSlotBreak(EquipmentSlot.CHEST); + + } + }); + }); + } + + /** + * Chains the Rift Beam to additional nearby enemies after hitting the initial target. + * + * @param event The player interaction event. + * @param player The player casting the ability. + * @param ability The class ability information. + */ + public static void riftBeamChain(PlayerInteractEvent event, Player player, ClassAbility ability) { + // Pseudocode: + // 1. After hitting an entity, identify additional enemies within a certain radius. + // 2. Spawn a new set of particles from the hit entity to the next target to simulate chaining. + // 3. Apply damage to the new target and continue chaining as per the ability parameters. + + Location start = player.getEyeLocation(); + // loop forward until we hit an entity + Location end = start.clone(); + for (int i = 0; i < ability.getRange(); i++){ + Location newLoc = start.clone().add(player.getLocation().getDirection().multiply(i)); + List entities = (List) newLoc.getNearbyLivingEntities(0.5); + if (!entities.isEmpty()) + end = entities.get(0).getLocation(); + } + + // Spawn particles along this line to simulate the beam effect. + } + /** + * Enemies defeated by the Rift Beam have a chance to spawn a mini-rift, dealing AOE damage to nearby enemies. + * + * @param event The player interaction event. + * @param player The player casting the ability. + * @param ability The class ability information. + */ + public static void riftBeamDimensionalRupture(PlayerInteractEvent event, Player player, ClassAbility ability) { + // Pseudocode: + // 1. When an enemy is defeated by the Rift Beam, randomly decide if a mini-rift will spawn. + // 2. If so, spawn area effect clouds or invisible armor stands at the location. + // 3. Apply AOE damage to entities near the mini-rift periodically. + // 4. After a short duration, remove the mini-rift and its effects. + } + + /** + * The ultimate upgrade of the Rift Beam ability. + * Charges up to unleash a devastating blast, with residual effects in its path. + * + * @param event The player interaction event. + * @param player The player casting the ability. + * @param ability The class ability information. + */ + public static void riftBeamApex(PlayerInteractEvent event, Player player, ClassAbility ability) { + // Pseudocode: + // 1. Initiate a charging mechanic, perhaps by holding down the right-click. + // 2. Once fully charged, release the Rift Beam with enhanced visual effects. + // 3. Deal significant damage to the first enemy hit and apply a powerful slow effect. + // 4. Leave a trail of particles that simulates a residual rift, slowing and damaging enemies. + } + + + public static void runeShieldAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { } diff --git a/src/main/java/me/zenox/evocraft/abilities/Modifier.java b/src/main/java/me/zenox/evocraft/abilities/Modifier.java index 658ae57..61bfa20 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Modifier.java +++ b/src/main/java/me/zenox/evocraft/abilities/Modifier.java @@ -78,6 +78,19 @@ void modify(ClassAbility ability) { } }; } + }, + MULTI { + @Override + Modifier create(String id, Modifier ... modifiers) { + return new Modifier(id) { + @Override + void modify(ClassAbility ability) { + for (Modifier modifier : modifiers) { + modifier.modify(ability); + } + } + }; + } }; Modifier create(String id, double value) { @@ -87,6 +100,10 @@ Modifier create(String id, double value) { Modifier create(String id, TriConsumer executable) { throw new UnsupportedOperationException("This operation is not supported for type: " + this); } + + Modifier create(String id, Modifier ... modifiers) { + throw new UnsupportedOperationException("This operation is not supported for type: " + this); + } } private Modifier(String id) { @@ -103,6 +120,10 @@ public static Modifier of(Type type, String id, TriConsumer Date: Thu, 16 Nov 2023 21:43:29 -0800 Subject: [PATCH 13/20] FrostFire Bow --- .../evocraft/abilities/AbilityRegistry.java | 30 +++++++++++++- .../evocraft/abilities/ClassAbility.java | 39 ++++++++++++++++++- .../evocraft/abilities/ElementalFlux.java | 1 + .../abilities/itemabilities/ItemAbility.java | 1 + .../me/zenox/evocraft/events/OtherEvent.java | 16 ++++++++ .../zenox/evocraft/gameclass/GameClass.java | 2 +- .../me/zenox/evocraft/item/ItemRegistry.java | 1 + src/main/resources/languages/en_US.yml | 5 ++- 8 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 677730d..a405cb4 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -4,7 +4,6 @@ import me.zenox.evocraft.abilities.itemabilities.*; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; -import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.player.PlayerInteractEvent; @@ -204,6 +203,35 @@ public class AbilityRegistry { .range(20) .strength(1) , ClassAbility::runeShieldAbility); + public static final ClassAbility BLOODLUST = new ClassAbility(new AbilitySettings() + .id("bloodlust") + .manaCost(35) + .cooldown(100) + .strength(1) + .charges(1) + .modifier(Modifier.of(Modifier.Type.EXECUTABLE, "bloodlust_agility", ClassAbility::agilityBloodlust)) + , ClassAbility::bloodlustAbility); + public static final ClassAbility TRIPLE_SLASH = new ClassAbility(new AbilitySettings() + .id("triple_slash") + .manaCost(35) + .cooldown(100) + .strength(1) + .charges(1) + , ClassAbility::tripleSlashAbility); + public static final ClassAbility BULL_RUSH = new ClassAbility(new AbilitySettings() + .id("bull_rush") + .manaCost(35) + .cooldown(100) + .strength(1) + .charges(1) + , ClassAbility::bullRushAbility); + public static final ClassAbility COUNTERSTRIKE = new ClassAbility(new AbilitySettings() + .id("counterstrike") + .manaCost(15) + .cooldown(5) + .strength(10) + .charges(3) + , ClassAbility::counterstrikeAbility); public static void registerAbilities(){ Util.logToConsole("Registering %s abilities.".formatted(ChatColor.GOLD + "" + Ability.registeredAbilities.size() + ChatColor.RESET)); diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 37ad6ed..884934b 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -1,5 +1,7 @@ package me.zenox.evocraft.abilities; +import com.archyx.aureliumskills.listeners.DamageListener; +import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.data.PlayerData; import me.zenox.evocraft.data.PlayerDataManager; @@ -12,20 +14,25 @@ import org.bukkit.entity.*; import org.bukkit.event.Event; import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import java.awt.*; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Array; import java.lang.reflect.Field; -import java.util.HashMap; +import java.util.*; import java.util.List; -import java.util.Map; import java.util.function.Consumer; public class ClassAbility extends Ability { @@ -455,6 +462,34 @@ public static void riftBeamAbility(PlayerInteractEvent event, Player player, Cla public static void runeShieldAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + } + public static void bloodlustAbility(PlayerInteractEvent event, Player player, ClassAbility ability){ + player.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 1200, 1) ); + } + + public static void tripleSlashAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + + } + + public static void bullRushAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + + } + public static ArrayList counterStrikeActive = new ArrayList<>(); + public static void counterstrikeAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + counterStrikeActive.add(player); + player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 50, 200)); + player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 50, 200)); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS, 50, 200)); + new BukkitRunnable(){ + @Override + public void run() { + counterStrikeActive.remove(player); + } + }.runTaskLater(EvoCraft.getPlugin(), 50); + } + + public static void agilityBloodlust(PlayerInteractEvent event, Player player, ClassAbility ability) { + } diff --git a/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java b/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java index d745a55..920e4c8 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java +++ b/src/main/java/me/zenox/evocraft/abilities/ElementalFlux.java @@ -1,5 +1,6 @@ package me.zenox.evocraft.abilities; +import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.item.LoreEntry; diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java index 875435e..5af6fd6 100644 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java @@ -16,6 +16,7 @@ import me.zenox.evocraft.Slot; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.AbilitySettings; +import me.zenox.evocraft.abilities.ElementalFlux; import me.zenox.evocraft.abilities.EventAbility; import me.zenox.evocraft.abilities.itemabilities.specific.EmberAttune; import me.zenox.evocraft.item.ComplexItemMeta; diff --git a/src/main/java/me/zenox/evocraft/events/OtherEvent.java b/src/main/java/me/zenox/evocraft/events/OtherEvent.java index b47566a..2216075 100644 --- a/src/main/java/me/zenox/evocraft/events/OtherEvent.java +++ b/src/main/java/me/zenox/evocraft/events/OtherEvent.java @@ -1,10 +1,13 @@ package me.zenox.evocraft.events; import com.destroystokyo.paper.event.inventory.PrepareResultEvent; +import com.sk89q.worldguard.bukkit.cause.Cause; +import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent; import de.studiocode.invui.window.impl.single.SimpleWindow; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.ClassAbility; import me.zenox.evocraft.enchant.ComplexEnchantment; +import me.zenox.evocraft.gameclass.GameClass; import me.zenox.evocraft.gui.EnchantingGUI; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; @@ -77,6 +80,19 @@ public void projectileExplode(EntityExplodeEvent e) { } } } + @EventHandler + public void damageEventCounterstrike(EntityDamageByEntityEvent entityDamageByEntityEvent, Player player, Entity entity){ + if(ClassAbility.counterStrikeActive.contains(player)) { + if (((entityDamageByEntityEvent.getDamager() instanceof LivingEntity))) { + ((LivingEntity) entityDamageByEntityEvent.getDamager()).damage(entityDamageByEntityEvent.getDamage()/2); + } + entityDamageByEntityEvent.setCancelled(true); + ClassAbility.counterStrikeActive.remove(player); + player.removePotionEffect(PotionEffectType.SLOW); + player.removePotionEffect(PotionEffectType.SLOW_FALLING); + player.removePotionEffect(PotionEffectType.WEAKNESS); + } + } @EventHandler public void projectileCollide(ProjectileHitEvent e) { diff --git a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java index be67fab..7872995 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java +++ b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java @@ -27,7 +27,7 @@ public enum GameClass { new AbilityTree(AbilityRegistry.TELEPORT, AbilityRegistry.MANA_BALL, AbilityRegistry.RIFT_BEAM, AbilityRegistry.RUNE_SHIELD)), WARRIOR("warrior", ChatColor.RED, List.of(ComplexItem.Type.SWORD), Material.IRON_SWORD, - null), + new AbilityTree(AbilityRegistry.TRIPLE_SLASH, AbilityRegistry.BLOODLUST, AbilityRegistry.BULL_RUSH, AbilityRegistry.COUNTERSTRIKE)), TANK("tank", ChatColor.GREEN, List.of(ComplexItem.Type.AXE), Material.IRON_AXE, null), diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index a5b566e..a951a8e 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -2,6 +2,7 @@ import com.archyx.aureliumskills.stats.Stats; import me.zenox.evocraft.abilities.AbilityRegistry; +import me.zenox.evocraft.abilities.ElementalFlux; import me.zenox.evocraft.abilities.itemabilities.specific.Crucify; import me.zenox.evocraft.abilities.itemabilities.specific.EmberAttune; import me.zenox.evocraft.abilities.itemabilities.specific.Psychic; diff --git a/src/main/resources/languages/en_US.yml b/src/main/resources/languages/en_US.yml index ae21f05..6477b2d 100644 --- a/src/main/resources/languages/en_US.yml +++ b/src/main/resources/languages/en_US.yml @@ -646,7 +646,10 @@ ability-name-mage_mana_ball: Mana Ball ability-name-mage_rift_beam: Rift Beam ability-name-mage_rune_shield: Rune Shield - +ability-name-warrior_bloodlust: Bloodlust +ability-name-warrior_triple_slash: Triple Slash +ability-name-warrior_bull_rush: Triple Slash +ability-name-warrior_counterstrike: Triple Slash ########################################################################## ## ENCHANTMENTS ## ########################################################################## From aad98b2ac8a2e66969a073f6817d6674d8ee0b57 Mon Sep 17 00:00:00 2001 From: pikapower2 Date: Thu, 16 Nov 2023 21:47:20 -0800 Subject: [PATCH 14/20] FrostFire Bow --- src/main/java/me/zenox/evocraft/abilities/ClassAbility.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 34e9553..333026d 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -7,6 +7,7 @@ import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.*; +import org.bukkit.Color; import org.bukkit.entity.*; import org.bukkit.event.Event; import org.bukkit.event.entity.ProjectileHitEvent; From cf9a30e95c5394ae21c43e851aa10b52594db945 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Fri, 17 Nov 2023 16:12:25 -0800 Subject: [PATCH 15/20] Rift Beam Chaining --- .vscode/settings.json | 3 + .../evocraft/abilities/AbilityRegistry.java | 9 +- .../evocraft/abilities/ClassAbility.java | 169 ++++++++++++++---- 3 files changed, 142 insertions(+), 39 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7b016a8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} \ No newline at end of file diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index f0b1f94..20bc117 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -4,7 +4,6 @@ import me.zenox.evocraft.abilities.itemabilities.*; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; -import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.player.PlayerInteractEvent; @@ -160,18 +159,18 @@ public class AbilityRegistry { .id("mage_teleport") .manaCost(35) .cooldown(0) - .range(10) + .range(20) .strength(1) .charges(1) .chargeTime(15) - .modifiers(Modifier.of(Modifier.Type.RANGE, "teleport_range_1", +2), + .modifiers(Modifier.of(Modifier.Type.RANGE, "teleport_range_1", +5), Modifier.of(Modifier.Type.MANA_COST, "teleport_mana_1", -5), Modifier.of(Modifier.Type.CHARGE, "teleport_charge_1", +1), Modifier.of(Modifier.Type.EXECUTABLE, "teleport_dark", ClassAbility::darkTeleport), Modifier.of(Modifier.Type.STRENGTH, "teleport_strength_1", +1), Modifier.of(Modifier.Type.CHARGE, "teleport_charge_2", +1), Modifier.of(Modifier.Type.EXECUTABLE, "teleport_surge", ClassAbility::surgeTeleport), - Modifier.of(Modifier.Type.RANGE, "teleport_range_2", +4), + Modifier.of(Modifier.Type.RANGE, "teleport_range_2", +10), Modifier.of(Modifier.Type.EXECUTABLE, "teleport_arcane", ClassAbility::arcaneTeleport)) , ClassAbility::teleportAbility); @@ -199,7 +198,7 @@ public class AbilityRegistry { public static final ClassAbility RIFT_BEAM = new ClassAbility(new AbilitySettings() .id("mage_rift_beam") .manaCost(40) - .cooldown(10) + .cooldown(0) .range(20) .strength(2) .charges(0) diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 560331d..9559c5d 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -11,7 +11,6 @@ import org.bukkit.event.Event; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.EquipmentSlot; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -24,9 +23,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Consumer; public class ClassAbility extends Ability { @@ -620,17 +617,15 @@ private static void endSingularity(Location location, ClassAbility ability) { */ public static void riftBeamAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { // 1. Calculate the beam trajectory from the player's eye location in the direction they are looking. - Vector start = player.getEyeLocation().toVector(); - Vector end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange())).toVector(); + Location start = player.getEyeLocation(); + Location end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange())); // 2. Spawn particles along this line to simulate the beam effect. // 3. Check for entities in the beam's path and apply damage to them. - List tracedPath = Geo.lerpEdges(List.of(start, end), (int) (1.3 * start.distance(end))); - tracedPath = tracedPath.subList(0, tracedPath.size()/2); - tracedPath.forEach(vector -> { - player.getWorld().spawnParticle(Particle.END_ROD, vector.toLocation(player.getWorld()), 1, 0.1, 0.1, 0.1); - player.getWorld().spawnParticle(Particle.REDSTONE, vector.toLocation(player.getWorld()), 2, 0, 0, 0, + alongPath(start, end, location -> { + location.getWorld().spawnParticle(Particle.END_ROD, location, 1, 0.1, 0, 0.1, 0); + player.getWorld().spawnParticle(Particle.REDSTONE, location, 2, 0, 0, 0, new Particle.DustOptions(Color.fromRGB(144, 0, 255), 1)); - player.getWorld().getNearbyEntities(vector.toLocation(player.getWorld()), 0.5, 0.5, 0.5).forEach(entity -> { + player.getWorld().getNearbyEntities(location, 0.5, 0.5, 0.5).forEach(entity -> { if (entity instanceof Damageable && !entity.equals(player)) { ((Damageable) entity).damage(ability.getStrength()*5); } @@ -638,6 +633,14 @@ public static void riftBeamAbility(PlayerInteractEvent event, Player player, Cla }); } + private static void alongPath(Location start, Location end, Consumer loc){ + List tracedPath = Geo.lerpEdges(List.of(start.toVector(), end.toVector()), (int) (1.3 * start.distance(end))); + tracedPath = tracedPath.subList(0, tracedPath.size()/2); + tracedPath.forEach(vector -> { + loc.accept(vector.toLocation(start.getWorld())); + }); + } + /** * Applies a mark to enemies hit by the Rift Beam. * Marked enemies take increased damage from all sources for a short duration. @@ -648,23 +651,20 @@ public static void riftBeamAbility(PlayerInteractEvent event, Player player, Cla */ public static void riftBeamMark(PlayerInteractEvent event, Player player, ClassAbility ability) { - Vector start = player.getEyeLocation().toVector(); - Vector end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange())).toVector(); + Location start = player.getEyeLocation(); + Location end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange())); // Spawn particles along this line to simulate the beam effect. // Check for entities in the beam's path and apply damage to them. - List tracedPath = Geo.lerpEdges(List.of(start, end), (int) (1.3 * start.distance(end))); - tracedPath = tracedPath.subList(0, tracedPath.size()/2); - tracedPath.forEach(vector -> { - player.getWorld().spawnParticle(Particle.END_ROD, vector.toLocation(player.getWorld()), 1, 0.1, 0.1, 0.1); - player.getWorld().spawnParticle(Particle.REDSTONE, vector.toLocation(player.getWorld()), 2, 0, 0, 0, + alongPath(start, end, location -> { + location.getWorld().spawnParticle(Particle.END_ROD, location, 1, 0.1, 0, 0.1, 0); + player.getWorld().spawnParticle(Particle.REDSTONE, location, 2, 0, 0, 0, new Particle.DustOptions(Color.fromRGB(144, 0, 255), 1)); - player.getWorld().getNearbyEntities(vector.toLocation(player.getWorld()), 0.5, 0.5, 0.5).forEach(entity -> { + player.getWorld().getNearbyEntities(location, 0.5, 0.5, 0.5).forEach(entity -> { if (entity instanceof LivingEntity lEntity && !entity.equals(player)) { lEntity.damage(ability.getStrength()*5); // Apply a potion effect to the target lEntity.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 20*ability.getStrength(), 0)); - lEntity.broadcastSlotBreak(EquipmentSlot.CHEST); } }); @@ -679,24 +679,125 @@ public static void riftBeamMark(PlayerInteractEvent event, Player player, ClassA * @param ability The class ability information. */ public static void riftBeamChain(PlayerInteractEvent event, Player player, ClassAbility ability) { - // Pseudocode: - // 1. After hitting an entity, identify additional enemies within a certain radius. - // 2. Spawn a new set of particles from the hit entity to the next target to simulate chaining. - // 3. Apply damage to the new target and continue chaining as per the ability parameters. + double distance = ability.getRange(); + Set explored = new HashSet<>(); Location start = player.getEyeLocation(); - // loop forward until we hit an entity - Location end = start.clone(); - for (int i = 0; i < ability.getRange(); i++){ - Location newLoc = start.clone().add(player.getLocation().getDirection().multiply(i)); - List entities = (List) newLoc.getNearbyLivingEntities(0.5); - if (!entities.isEmpty()) - end = entities.get(0).getLocation(); + Vector direction = start.getDirection().normalize(); + + Optional hitEntity = findFirstEntity(start, direction, distance, player); + + if (hitEntity.isPresent()) { + LivingEntity target = hitEntity.get(); + target.damage(ability.getStrength() * 5); + explored.add(target); + createParticlePath(start, target.getLocation(), player); + new BukkitRunnable() { + @Override + public void run() { + chainToClosestEntities(target, player, ability, explored, distance, 1); + } + }.runTaskLater(EvoCraft.getPlugin(), 5L); + + // create visual particle path to show that it was casted, but nothing was hit + } else { + Location end = findBeamHitLocation(start, direction, distance); + createParticlePath(start, findBeamHitLocation(start, direction, distance), player); + end.getWorld().spawnParticle(Particle.REDSTONE, end, 10, 0.2, 0.2, 0.2, + new Particle.DustOptions(Color.fromRGB(144, 0, 255), 1)); + end.getWorld().spawnParticle(Particle.END_ROD, end, 10, 0.2, 0.2, 0.2); } - // Spawn particles along this line to simulate the beam effect. - + } + + private static Optional findFirstEntity(Location start, Vector direction, double distance, Player player) { + double stepSize = 0.5; + Vector stepVector = direction.clone().normalize().multiply(stepSize); + + for (double i = 0; i <= distance; i += stepSize) { + Location currentLoc = start.clone().add(stepVector.clone().multiply(i)); + // Check if a block is hit + if (currentLoc.getBlock().getType() != Material.AIR) { + return Optional.empty(); + } + + List nearbyEntities = (List) currentLoc.getNearbyLivingEntities(1); + for (LivingEntity entity : nearbyEntities) { + if (!entity.equals(player)) { + return Optional.of(entity); + } + } + } + return Optional.empty(); + } + + private static Location findBeamHitLocation(Location start, Vector direction, double distance) { + double stepSize = 0.5; + Vector stepVector = direction.clone().normalize().multiply(stepSize); + Location currentLoc = start.clone(); + + for (double i = 0; i <= distance; i += stepSize) { + currentLoc.add(stepVector); + if (currentLoc.getBlock().getType() != Material.AIR) { + return currentLoc; + } + } + return start.clone().add(direction.multiply(distance)); + } + + private static void chainToClosestEntities(LivingEntity initialTarget, Player player, ClassAbility ability, Set explored, double remainingDistance, double damageMultiplier) { + + double closestDistanceSquared = Double.MAX_VALUE; + LivingEntity closestEntity = null; + + // Find the closest entity within the remaining distance + for (LivingEntity entity : initialTarget.getLocation().getWorld().getNearbyLivingEntities(initialTarget.getLocation(), remainingDistance)) { + if (!entity.equals(player) && !explored.contains(entity)) { + double distanceSquared = entity.getLocation().distanceSquared(initialTarget.getLocation()); + if (distanceSquared < closestDistanceSquared) { + closestDistanceSquared = distanceSquared; + closestEntity = entity; + } + } + } + + // If a valid closest entity is found + if (closestEntity != null && initialTarget.hasLineOfSight(closestEntity)) { + // Apply reduced damage to the closest entity + closestEntity.damage(ability.getStrength() * 5 * damageMultiplier); + explored.add(closestEntity); + + // Create particle effects from the last target to the new one + createParticlePath(initialTarget.getEyeLocation(), closestEntity.getEyeLocation(), player); + final LivingEntity finalClosestEntity = closestEntity; + + // Calculate remaining distance and continue chaining if possible + double distanceToNextTarget = Math.sqrt(closestDistanceSquared); + if (remainingDistance - distanceToNextTarget > 0) { + new BukkitRunnable() { + @Override + public void run() { + chainToClosestEntities(finalClosestEntity, player, ability, explored, remainingDistance - distanceToNextTarget, damageMultiplier * 0.8); // reduce damage by 10% each chain + } + }.runTaskLater(EvoCraft.getPlugin(), 5L); + } + } + + new BukkitRunnable() { + @Override + public void run() { + } + }.runTaskLater(EvoCraft.getPlugin(), 5L); // 20L represents a delay of 1 second (20 ticks) + } + + private static void createParticlePath(Location start, Location end, Player player) { + alongPath(start, end, location -> { + + location.getWorld().spawnParticle(Particle.END_ROD, location, 1, 0.1, 0, 0.1, 0); + location.getWorld().spawnParticle(Particle.REDSTONE, location, 2, 0, 0, 0, + new Particle.DustOptions(Color.fromRGB(144, 0, 255), 1)); + }); } /** From ae045df735bbebb130666ee01becf76a297aefb2 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Tue, 21 Nov 2023 22:48:19 -0800 Subject: [PATCH 16/20] Update to Minecraft 1.20.2 Update dependencies and libraries as well --- pom.xml | 38 ++++++++---- src/main/java/me/zenox/evocraft/EvoCraft.java | 4 +- .../evocraft/abilities/AbilityRegistry.java | 1 - .../evocraft/abilities/ClassAbility.java | 60 +++++++++++++------ .../me/zenox/evocraft/command/Command.java | 20 +++++-- .../zenox/evocraft/data/LanguageLoader.java | 1 + .../me/zenox/evocraft/data/PlayerData.java | 2 +- .../me/zenox/evocraft/events/OtherEvent.java | 24 ++++---- .../zenox/evocraft/gameclass/GameClass.java | 9 +-- .../zenox/evocraft/gui/EnchantGUIBuilder.java | 46 -------------- .../me/zenox/evocraft/gui/EnchantGUIType.java | 37 ------------ .../zenox/evocraft/gui/EnchantGuiBuilder.java | 34 +++++++++++ .../me/zenox/evocraft/gui/EnchantingGUI.java | 34 +++++------ .../java/me/zenox/evocraft/gui/GUITypes.java | 6 -- .../evocraft/gui/item/BookshelfItem.java | 6 +- .../zenox/evocraft/gui/item/BooleanItem.java | 6 +- .../me/zenox/evocraft/gui/item/ClassItem.java | 12 ++-- .../me/zenox/evocraft/gui/item/CloseItem.java | 18 +++--- .../me/zenox/evocraft/gui/item/EmptyItem.java | 8 +-- .../zenox/evocraft/gui/item/EnchantItem.java | 6 +- .../java/me/zenox/evocraft/util/Util.java | 23 +++---- src/main/resources/plugin.yml | 2 +- 22 files changed, 193 insertions(+), 204 deletions(-) delete mode 100644 src/main/java/me/zenox/evocraft/gui/EnchantGUIBuilder.java delete mode 100644 src/main/java/me/zenox/evocraft/gui/EnchantGUIType.java create mode 100644 src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java delete mode 100644 src/main/java/me/zenox/evocraft/gui/GUITypes.java diff --git a/pom.xml b/pom.xml index fc52ce1..cbc6214 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.zenox evocraft - 1.2.0-ALPHA + 1.3.0-ALPHA jar EvoCraft @@ -96,25 +96,25 @@ io.papermc.paper paper-api - 1.19.3-R0.1-SNAPSHOT + 1.20.2-R0.1-SNAPSHOT provided org.spigotmc spigot - 1.19-R0.1-SNAPSHOT + 1.20.2-R0.1-SNAPSHOT provided com.sk89q.worldguard worldguard-bukkit - 7.0.7 + 7.0.9 provided com.github.Archy-X AureliumSkills - Beta1.3.6 + Beta1.3.23 provided @@ -122,6 +122,11 @@ commons-lang3 3.12.0 + + commons-io + commons-io + 2.7 + com.moandjiezana.toml toml4j @@ -130,24 +135,30 @@ com.comphenix.protocol ProtocolLib - 4.7.0 + 5.1.0 provided com.ticxo.modelengine api - R3.0.1 + R3.1.6 provided - de.studiocode.invui - InvUI - 0.8.2 + xyz.xenondevs.invui + invui + 1.23 + pom + + + com.google.guava + guava + 23.5-jre net.citizensnpcs citizens-main - 2.0.30-SNAPSHOT + 2.0.33-SNAPSHOT jar provided @@ -163,5 +174,10 @@ 1.7 provided + + com.mojang + authlib + 3.5.41 + diff --git a/src/main/java/me/zenox/evocraft/EvoCraft.java b/src/main/java/me/zenox/evocraft/EvoCraft.java index 29de920..824e04c 100644 --- a/src/main/java/me/zenox/evocraft/EvoCraft.java +++ b/src/main/java/me/zenox/evocraft/EvoCraft.java @@ -7,8 +7,8 @@ import com.comphenix.protocol.ProtocolManager; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import de.studiocode.invui.gui.structure.Structure; -import de.studiocode.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.gui.structure.Structure; +import xyz.xenondevs.invui.item.builder.ItemBuilder; import me.zenox.evocraft.abilities.AbilityRegistry; import me.zenox.evocraft.attribute.AttributeRegistry; import me.zenox.evocraft.command.Command; diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index 487f4e6..d78c8ed 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -209,7 +209,6 @@ public class AbilityRegistry { Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_mark", ClassAbility::riftBeamMark), Modifier.of(Modifier.Type.MANA_COST, "rift_beam_efficiency", -10), Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_chain", ClassAbility::riftBeamChain), - Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_dimensional_rupture", ClassAbility::riftBeamDimensionalRupture), Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_apex", ClassAbility::riftBeamApex) ), ClassAbility::riftBeamAbility); public static final ClassAbility RUNE_SHIELD = new ClassAbility(new AbilitySettings() diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 7573127..fafd7aa 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -804,34 +804,56 @@ private static void createParticlePath(Location start, Location end, Player play } /** - * Enemies defeated by the Rift Beam have a chance to spawn a mini-rift, dealing AOE damage to nearby enemies. + * The ultimate upgrade of the Rift Beam ability. + * Charges up to unleash a devastating blast, with two chaining beams and one main beam. * * @param event The player interaction event. * @param player The player casting the ability. * @param ability The class ability information. */ - public static void riftBeamDimensionalRupture(PlayerInteractEvent event, Player player, ClassAbility ability) { + public static void riftBeamApex(PlayerInteractEvent event, Player player, ClassAbility ability) { + // Start charging + startCharge(player); + + // Schedule task to check for charge completion + new BukkitRunnable() { + @Override + public void run() { + if (isFullyCharged(player)) { + // On full charge, release the beams + releaseMainBeam(player, ability); + releaseChainingBeams(player, ability); + + this.cancel(); // Stop the task + } + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 1L); // Check every tick + } + + private static void startCharge(Player player) { // Pseudocode: - // 1. When an enemy is defeated by the Rift Beam, randomly decide if a mini-rift will spawn. - // 2. If so, spawn area effect clouds or invisible armor stands at the location. - // 3. Apply AOE damage to entities near the mini-rift periodically. - // 4. After a short duration, remove the mini-rift and its effects. + // Display charging particles or effects around the player. + // Record the start time of the charge. + // Possibly play a charging sound. } - /** - * The ultimate upgrade of the Rift Beam ability. - * Charges up to unleash a devastating blast, with residual effects in its path. - * - * @param event The player interaction event. - * @param player The player casting the ability. - * @param ability The class ability information. - */ - public static void riftBeamApex(PlayerInteractEvent event, Player player, ClassAbility ability) { + private static boolean isFullyCharged(Player player) { + // Pseudocode: + // Check if the required charge time has elapsed. + // Return true if fully charged, false otherwise. + return false; // Placeholder + } + + private static void releaseMainBeam(Player player, ClassAbility ability) { + // Pseudocode: + // Create and launch the main beam. + // This beam could have higher damage and range compared to normal rift beams. + } + + private static void releaseChainingBeams(Player player, ClassAbility ability) { // Pseudocode: - // 1. Initiate a charging mechanic, perhaps by holding down the right-click. - // 2. Once fully charged, release the Rift Beam with enhanced visual effects. - // 3. Deal significant damage to the first enemy hit and apply a powerful slow effect. - // 4. Leave a trail of particles that simulates a residual rift, slowing and damaging enemies. + // Launch additional beams that chain to nearby enemies. + // These beams could originate from the player or the main beam's hit location. } diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index c0bba5a..ac84812 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -1,7 +1,6 @@ package me.zenox.evocraft.command; import com.google.common.primitives.Ints; -import de.studiocode.invui.window.impl.single.SimpleWindow; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.data.PlayerData; import me.zenox.evocraft.data.PlayerDataManager; @@ -21,6 +20,7 @@ import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import xyz.xenondevs.invui.window.Window; import java.util.*; import java.util.stream.Collectors; @@ -190,7 +190,13 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman return true; } case "class" -> // Open the class selection GUI - new SimpleWindow(((Player) sender), "Class Selection", GameClass.getGui(), true, true).show(); + Window.single() + .setViewer((Player) sender) + .setTitle("Class Selection") + .setGui(GameClass.getGui()) + .setCloseable(true) + .build() + .open(); case "progresspath" -> { if (args.length < 2) { Util.sendMessage(sender, "Please specify a valid path."); @@ -200,15 +206,21 @@ public boolean onCommand(CommandSender sender, org.bukkit.command.Command comman PlayerData data = PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()); Path path = data.getPlayerClass().tree().path(args[1]); if (path == null) { - Util.sendMessage(sender, "This path does not exist!"); + Util.sendMessage(sender, "&cThis path does not exist!"); return true; } try { - data.progressAbility(path); + if (args.length < 3) + data.progressPath(path); + else { + int level = Integer.parseInt(args[2]); + data.setPathLevel(path, level); + } } catch (IllegalArgumentException e) { Util.sendMessage(sender, e.getMessage()); return true; } + Util.sendMessage(sender, "&aYou have progressed on the " + path.getId() + " path to level " + data.getPathLevel(path) + "!"); return true; } default -> Util.sendMessage(sender, "EvoCraft Help Page."); diff --git a/src/main/java/me/zenox/evocraft/data/LanguageLoader.java b/src/main/java/me/zenox/evocraft/data/LanguageLoader.java index 5115d0e..6705ce1 100644 --- a/src/main/java/me/zenox/evocraft/data/LanguageLoader.java +++ b/src/main/java/me/zenox/evocraft/data/LanguageLoader.java @@ -25,6 +25,7 @@ public LanguageLoader(EvoCraft plugin) { languageDirectory.mkdir(); try { InputStream stream = plugin.getResource("languages/en_US.yml"); + assert stream != null; FileUtils.copyInputStreamToFile(stream, defaultLanguageFile); } catch (IOException e) { e.printStackTrace(); diff --git a/src/main/java/me/zenox/evocraft/data/PlayerData.java b/src/main/java/me/zenox/evocraft/data/PlayerData.java index e670d22..c62c2e6 100644 --- a/src/main/java/me/zenox/evocraft/data/PlayerData.java +++ b/src/main/java/me/zenox/evocraft/data/PlayerData.java @@ -53,7 +53,7 @@ public void setPathLevel(Path path, int level) { } // Progress the level of a specific ability - public void progressAbility(Path path) { + public void progressPath(Path path) { int currentLevel = getPathLevel(path); if (getPathLevel(path) < path.getMaxLevel()) setPathLevel(path, currentLevel + 1); diff --git a/src/main/java/me/zenox/evocraft/events/OtherEvent.java b/src/main/java/me/zenox/evocraft/events/OtherEvent.java index 2216075..92c1294 100644 --- a/src/main/java/me/zenox/evocraft/events/OtherEvent.java +++ b/src/main/java/me/zenox/evocraft/events/OtherEvent.java @@ -1,13 +1,9 @@ package me.zenox.evocraft.events; import com.destroystokyo.paper.event.inventory.PrepareResultEvent; -import com.sk89q.worldguard.bukkit.cause.Cause; -import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent; -import de.studiocode.invui.window.impl.single.SimpleWindow; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.ClassAbility; import me.zenox.evocraft.enchant.ComplexEnchantment; -import me.zenox.evocraft.gameclass.GameClass; import me.zenox.evocraft.gui.EnchantingGUI; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; @@ -33,6 +29,7 @@ import org.bukkit.metadata.MetadataValue; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import xyz.xenondevs.invui.window.Window; import java.util.HashMap; import java.util.List; @@ -52,12 +49,17 @@ public OtherEvent(EvoCraft plugin) { @EventHandler public void tileEntityInteract(PlayerInteractEvent e){ if(e.getAction() == Action.RIGHT_CLICK_BLOCK){ - if (e.getClickedBlock().getType() == Material.ENCHANTING_TABLE) { - new SimpleWindow(e.getPlayer(), "Enchantment Table", EnchantingGUI.getGui(e.getPlayer(), e.getClickedBlock()), true, true).show(); - } else { - return; + if (Objects.requireNonNull(e.getClickedBlock()).getType() == Material.ENCHANTING_TABLE) { + e.setCancelled(true); + Window.single() + .setViewer(e.getPlayer()) + .setTitle("Enchantment Table") + .setGui(EnchantingGUI.getGui(e.getPlayer(), e.getClickedBlock())) + .setCloseable(true) + .build() + .open(); } - e.setCancelled(true); + } } @@ -81,7 +83,9 @@ public void projectileExplode(EntityExplodeEvent e) { } } @EventHandler - public void damageEventCounterstrike(EntityDamageByEntityEvent entityDamageByEntityEvent, Player player, Entity entity){ + public void damageEventCounterstrike(EntityDamageByEntityEvent entityDamageByEntityEvent){ + if(!(entityDamageByEntityEvent.getEntity() instanceof Player)) return; + Player player = (Player) entityDamageByEntityEvent.getEntity(); if(ClassAbility.counterStrikeActive.contains(player)) { if (((entityDamageByEntityEvent.getDamager() instanceof LivingEntity))) { ((LivingEntity) entityDamageByEntityEvent.getDamager()).damage(entityDamageByEntityEvent.getDamage()/2); diff --git a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java index 7872995..02347b1 100644 --- a/src/main/java/me/zenox/evocraft/gameclass/GameClass.java +++ b/src/main/java/me/zenox/evocraft/gameclass/GameClass.java @@ -1,8 +1,5 @@ package me.zenox.evocraft.gameclass; -import de.studiocode.invui.gui.GUI; -import de.studiocode.invui.gui.builder.GUIBuilder; -import de.studiocode.invui.gui.builder.guitype.GUIType; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.AbilityRegistry; import me.zenox.evocraft.data.PlayerDataManager; @@ -15,6 +12,7 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; +import xyz.xenondevs.invui.gui.Gui; import java.util.List; @@ -76,9 +74,8 @@ public static GameClass getFromID(String id) { }; } - public static GUI getGui() { - return new GUIBuilder<>(GUIType.NORMAL) - .setStructure( + public static Gui getGui() { + return Gui.normal().setStructure( "# # # # # # # # #", "# M # W # T # A #", "# # # # # # # # #" diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantGUIBuilder.java b/src/main/java/me/zenox/evocraft/gui/EnchantGUIBuilder.java deleted file mode 100644 index 035224b..0000000 --- a/src/main/java/me/zenox/evocraft/gui/EnchantGUIBuilder.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.zenox.evocraft.gui; - -import de.studiocode.invui.gui.GUI; -import de.studiocode.invui.gui.builder.GUIBuilder; -import de.studiocode.invui.gui.builder.GUIContext; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.lang.reflect.Field; - - -/** - * hhahahh enchant gui code go brr - */ -public class EnchantGUIBuilder extends GUIBuilder { - - private final EnchantGUIType guiType; - private final GUIContext context; - private final Player p; - private final Block block; - - public EnchantGUIBuilder(@NotNull EnchantGUIType guiType, Player p, Block block) { - super(guiType); - this.guiType = guiType; - this.context = new GUIContext(); - try { - Field f = getClass().getSuperclass().getDeclaredField("context"); - f.setAccessible(true); - f.set(this, context); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } - - this.p = p; - this.block = block; - } - - @Override - public EnchantingGUI build() { - if (context.getStructure() == null) throw new IllegalStateException("GUIContext has not been set yet."); - return guiType.createGUI(context, p, block); - } - -} - diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantGUIType.java b/src/main/java/me/zenox/evocraft/gui/EnchantGUIType.java deleted file mode 100644 index b0a189e..0000000 --- a/src/main/java/me/zenox/evocraft/gui/EnchantGUIType.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.zenox.evocraft.gui; - -import de.studiocode.invui.gui.builder.GUIContext; -import de.studiocode.invui.gui.builder.guitype.GUIType; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; - -class EnchantGUIType implements GUIType { - - public EnchantingGUI createGUI(GUIContext context, Player p, Block block) { - EnchantingGUI gui = new EnchantingGUI(context.getStructure(), p, block); - gui.setBackground(context.getBackground()); - return gui; - } - - @Override - public EnchantingGUI createGUI(GUIContext context) { - throw new IllegalStateException("You cannot use EnchantGUIType with the normal GUI builder."); - } - - @Override - public boolean acceptsGUIs() { - return false; - } - - @Override - public boolean acceptsItems() { - return false; - } - - @Override - public boolean acceptsInventory() { - return false; - } - -} - diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java b/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java new file mode 100644 index 0000000..540fbba --- /dev/null +++ b/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java @@ -0,0 +1,34 @@ +package me.zenox.evocraft.gui; + +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.gui.AbstractGui; +import xyz.xenondevs.invui.gui.Gui; + + +/** + * hhahahh enchant gui code go brr + */ +public class EnchantGuiBuilder extends AbstractGui.AbstractBuilder { + + private final Player p; + private final Block block; + + public EnchantGuiBuilder(Player p, Block block) { + this.p = p; + this.block = block; + } + + @Override + public @NotNull EnchantingGUI build() { + if (structure == null) + throw new IllegalStateException("Structure is not defined."); + EnchantingGUI gui = new EnchantingGUI(structure, p, block); + gui.setBackground(background); + return gui; + } + + interface Enchanting extends Gui.Builder {} +} + diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java b/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java index eba9b4d..a43e72e 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java @@ -2,12 +2,6 @@ import com.archyx.aureliumskills.api.AureliumAPI; import com.archyx.aureliumskills.skills.Skills; -import de.studiocode.invui.gui.GUI; -import de.studiocode.invui.gui.SlotElement; -import de.studiocode.invui.gui.impl.SimpleGUI; -import de.studiocode.invui.gui.structure.Structure; -import de.studiocode.invui.item.builder.ItemBuilder; -import de.studiocode.invui.virtualinventory.VirtualInventoryManager; import me.zenox.evocraft.enchant.ComplexEnchantment; import me.zenox.evocraft.gui.item.BookshelfItem; import me.zenox.evocraft.gui.item.BooleanItem; @@ -26,6 +20,12 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.gui.AbstractGui; +import xyz.xenondevs.invui.gui.Gui; +import xyz.xenondevs.invui.gui.SlotElement; +import xyz.xenondevs.invui.gui.structure.Structure; +import xyz.xenondevs.invui.inventory.VirtualInventoryManager; +import xyz.xenondevs.invui.item.builder.ItemBuilder; import java.util.*; @@ -34,7 +34,7 @@ /** * Enchantment GUI that is shown to players */ -public class EnchantingGUI extends SimpleGUI { +public class EnchantingGUI extends AbstractGui { public static final VariableType ENCHANT_FUEL_VAR = new VariableType<>("enchant_fuel", new LoreEntry("enchant_fuel", @@ -151,9 +151,9 @@ public boolean enchantItem(int level, int xpRequired) { fuelItem.getItem().setAmount(fuelItem.getItem().getAmount() - 1); // Set fuel to be empty - VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1).setItemStack(null, 0, fuelItem.getItem()); + VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1).setItem(null, 0, fuelItem.getItem()); // update virtual container with enchanted version - VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1).setItemStack(null, 0, item.getItem()); + VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1).setItem(null, 0, item.getItem()); this.eTable.getWorld().playSound(this.eTable.getLocation(), ENCHANT_SOUND, 1f + level, 1f - level * 0.15f); @@ -177,7 +177,7 @@ public boolean enchantItem(int level, int xpRequired) { * @return the item being enchanted */ private ItemStack getEItem() { - return VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1).getItemStack(0); + return VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1).getItem(0); } /** @@ -186,7 +186,7 @@ private ItemStack getEItem() { * @return the fuel item */ private ItemStack getFuelItem() { - return VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1).getItemStack(0); + return VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1).getItem(0); } public Block getETable() { @@ -210,10 +210,10 @@ public static boolean enchantValid(EnchantingGUI gui, int power, int XPRequired) private static boolean itemValid(ItemStack item) { try { ComplexItem.Type type = ComplexItem.of(item).getType(); - return item.getType() != Material.AIR && ComplexEnchantment.getRegisteredEnchants() + return item.getType() != Material.AIR && !ComplexEnchantment.getRegisteredEnchants() .stream() .filter(complexEnchantment -> - complexEnchantment.getTypes().contains(type)).toList().size() > 0; + complexEnchantment.getTypes().contains(type)).toList().isEmpty(); } catch (NullPointerException e) { return false; } @@ -275,8 +275,8 @@ private static int combineEnchantLevels(int maxLevel, int enchantLevel1, int enc return Math.min(maxLevel, result); } - public static GUI getGui(Player p, Block block) { - return new EnchantGUIBuilder(GUITypes.ENCHANT, p, block) + public static Gui getGui(Player p, Block block) { + return new EnchantGuiBuilder(p, block) .setStructure( "# # # # # $ $ 1 #", "# # # # # $ # # #", @@ -285,8 +285,8 @@ public static GUI getGui(Player p, Block block) { "# # # # # ^ ^ 3 #", "# # # # C B # # #" ) - .addIngredient('E', new SlotElement.VISlotElement(VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1), 0, new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE))) - .addIngredient('F', new SlotElement.VISlotElement(VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1), 0, new ItemBuilder(Material.BLUE_STAINED_GLASS_PANE))) + .addIngredient('E', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1), 0, new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE))) + .addIngredient('F', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1), 0, new ItemBuilder(Material.BLUE_STAINED_GLASS_PANE))) .addIngredient('R', new ItemBuilder(Material.RED_STAINED_GLASS_PANE).setDisplayName("")) .addIngredient('1', new EnchantItem(1, 0)) .addIngredient('2', new EnchantItem(2, 10)) diff --git a/src/main/java/me/zenox/evocraft/gui/GUITypes.java b/src/main/java/me/zenox/evocraft/gui/GUITypes.java deleted file mode 100644 index 2be3ebf..0000000 --- a/src/main/java/me/zenox/evocraft/gui/GUITypes.java +++ /dev/null @@ -1,6 +0,0 @@ -package me.zenox.evocraft.gui; - -public class GUITypes { - - public static EnchantGUIType ENCHANT = new EnchantGUIType(); -} diff --git a/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java b/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java index 5bf74f4..d2afbac 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java @@ -1,8 +1,8 @@ package me.zenox.evocraft.gui.item; -import de.studiocode.invui.item.ItemProvider; -import de.studiocode.invui.item.builder.ItemBuilder; -import de.studiocode.invui.item.impl.controlitem.ControlItem; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.controlitem.ControlItem; import me.zenox.evocraft.gui.EnchantingGUI; import me.zenox.evocraft.util.Util; import org.bukkit.Material; diff --git a/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java b/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java index e9a4479..87a9084 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java @@ -1,8 +1,8 @@ package me.zenox.evocraft.gui.item; -import de.studiocode.invui.item.ItemProvider; -import de.studiocode.invui.item.builder.ItemBuilder; -import de.studiocode.invui.item.impl.controlitem.ControlItem; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.controlitem.ControlItem; import me.zenox.evocraft.gui.EnchantingGUI; import org.bukkit.Material; import org.bukkit.entity.Player; diff --git a/src/main/java/me/zenox/evocraft/gui/item/ClassItem.java b/src/main/java/me/zenox/evocraft/gui/item/ClassItem.java index 2df5591..fc014d1 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/ClassItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/ClassItem.java @@ -1,9 +1,9 @@ package me.zenox.evocraft.gui.item; -import de.studiocode.invui.item.ItemProvider; -import de.studiocode.invui.item.builder.ItemBuilder; -import de.studiocode.invui.item.impl.BaseItem; -import de.studiocode.invui.window.Window; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.AbstractItem; +import xyz.xenondevs.invui.window.Window; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; import me.zenox.evocraft.gameclass.GameClass; @@ -14,7 +14,7 @@ import org.bukkit.inventory.ItemFlag; import org.jetbrains.annotations.NotNull; -public class ClassItem extends BaseItem { +public class ClassItem extends AbstractItem { private final GameClass gameClass; private final TranslatableText NAME; private final TranslatableList LORE; @@ -38,7 +38,7 @@ public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @N GameClass.setClass(player, gameClass); for (Window window : getWindows()) { if(window.getCurrentViewer().equals(player)){ - window.closeForViewer(); + window.close(); } } } diff --git a/src/main/java/me/zenox/evocraft/gui/item/CloseItem.java b/src/main/java/me/zenox/evocraft/gui/item/CloseItem.java index 2652a72..b76a1fb 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/CloseItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/CloseItem.java @@ -1,25 +1,25 @@ package me.zenox.evocraft.gui.item; -import de.studiocode.invui.gui.impl.SimpleGUI; -import de.studiocode.invui.item.ItemProvider; -import de.studiocode.invui.item.builder.ItemBuilder; -import de.studiocode.invui.item.impl.controlitem.ControlItem; -import de.studiocode.invui.window.Window; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.invui.gui.AbstractGui; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.controlitem.ControlItem; +import xyz.xenondevs.invui.window.Window; /** * "Empty" item that can be replaced with another item via clicking on it */ -public class CloseItem extends ControlItem { +public class CloseItem extends ControlItem { - private SimpleGUI gui; + private AbstractGui gui; @Override - public ItemProvider getItemProvider(SimpleGUI gui) { + public ItemProvider getItemProvider(AbstractGui gui) { this.gui = gui; return new ItemBuilder(Material.BARRIER).setDisplayName("§cClose Menu"); } @@ -29,7 +29,7 @@ public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @N for (Window window : getWindows()) { if(window.getCurrentViewer().equals(player)){ - window.closeForViewer(); + window.close(); } } } diff --git a/src/main/java/me/zenox/evocraft/gui/item/EmptyItem.java b/src/main/java/me/zenox/evocraft/gui/item/EmptyItem.java index 67fa81a..a782197 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/EmptyItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/EmptyItem.java @@ -1,8 +1,8 @@ package me.zenox.evocraft.gui.item; -import de.studiocode.invui.item.ItemProvider; -import de.studiocode.invui.item.builder.ItemBuilder; -import de.studiocode.invui.item.impl.BaseItem; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.AbstractItem; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -13,7 +13,7 @@ /** * "Empty" item that can be replaced with another item via clicking on it */ -public class EmptyItem extends BaseItem { +public class EmptyItem extends AbstractItem { private ItemStack item = new ItemStack(Material.AIR); diff --git a/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java b/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java index f4518d9..7b04f63 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java @@ -1,8 +1,8 @@ package me.zenox.evocraft.gui.item; -import de.studiocode.invui.item.ItemProvider; -import de.studiocode.invui.item.builder.ItemBuilder; -import de.studiocode.invui.item.impl.controlitem.ControlItem; +import xyz.xenondevs.invui.item.ItemProvider; +import xyz.xenondevs.invui.item.builder.ItemBuilder; +import xyz.xenondevs.invui.item.impl.controlitem.ControlItem; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; import me.zenox.evocraft.gui.EnchantingGUI; diff --git a/src/main/java/me/zenox/evocraft/util/Util.java b/src/main/java/me/zenox/evocraft/util/Util.java index fd7ca4d..9b89224 100644 --- a/src/main/java/me/zenox/evocraft/util/Util.java +++ b/src/main/java/me/zenox/evocraft/util/Util.java @@ -5,8 +5,8 @@ import com.archyx.aureliumskills.modifier.Modifiers; import com.archyx.aureliumskills.modifier.StatModifier; import com.archyx.aureliumskills.stats.Stat; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; +import com.destroystokyo.paper.profile.PlayerProfile; +import com.destroystokyo.paper.profile.ProfileProperty; import me.zenox.evocraft.EvoCraft; import org.bukkit.*; import org.bukkit.block.Block; @@ -17,7 +17,6 @@ import org.bukkit.inventory.meta.SkullMeta; import org.jetbrains.annotations.NotNull; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -74,15 +73,9 @@ public static ItemStack makeSkull(@NotNull ItemStack item, String base64EncodedS r.nextBytes(array); UUID id = UUID.nameUUIDFromBytes(array); - GameProfile profile = new GameProfile(id, null); - profile.getProperties().put("textures", new Property("textures", base64EncodedString)); - try { - Field profileField = meta.getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - profileField.set(meta, profile); - } catch (NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } + PlayerProfile profile = Bukkit.createProfile(id, null); + profile.getProperties().add(new ProfileProperty("textures", base64EncodedString)); + meta.setPlayerProfile(profile); item.setItemMeta(meta); return item; } @@ -104,9 +97,9 @@ public static UUID constantUUID(String str){ /** * Gets nearby blocks given a radius and location * @param loc The location - * @param radius The radius - * @param yradius The y radius - * @return + * @param radius The radius in the orthogonal horizontal directions + * @param yradius The radius in the y direction + * @return the list of blocks */ public static List getNearbyBlocks(Location loc, int radius, int yradius) { List nearbyBlocks = new ArrayList(); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 6368357..3cdd851 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: EvoCraft version: '${project.version}' main: me.zenox.evocraft.EvoCraft -api-version: 1.19 +api-version: 1.20 authors: [ ZenoX ] description: Transforms your game into an highly specialized MMORPG experience. softdepend: [ Citizens, WorldGuard, WorldEdit ] From b617e374ded8c9d3eb1a17d6a483389787a47e36 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Mon, 4 Dec 2023 01:15:00 -0800 Subject: [PATCH 17/20] Minor Logging and Performance Changers --- src/main/java/me/zenox/evocraft/EvoCraft.java | 5 +++++ .../me/zenox/evocraft/events/OtherEvent.java | 6 +++--- .../me/zenox/evocraft/gui/EnchantGuiBuilder.java | 9 +++------ .../{EnchantingGUI.java => EnchantingGui.java} | 10 ++++++---- .../zenox/evocraft/gui/item/BookshelfItem.java | 8 ++++---- .../me/zenox/evocraft/gui/item/BooleanItem.java | 16 ++++++++-------- .../me/zenox/evocraft/gui/item/EnchantItem.java | 10 +++++----- .../me/zenox/evocraft/item/ComplexItemMeta.java | 2 +- .../me/zenox/evocraft/item/ItemRegistry.java | 8 ++++---- .../evocraft/item/basicitems/CorruptPearl.java | 8 ++++---- 10 files changed, 43 insertions(+), 39 deletions(-) rename src/main/java/me/zenox/evocraft/gui/{EnchantingGUI.java => EnchantingGui.java} (97%) diff --git a/src/main/java/me/zenox/evocraft/EvoCraft.java b/src/main/java/me/zenox/evocraft/EvoCraft.java index 824e04c..440836e 100644 --- a/src/main/java/me/zenox/evocraft/EvoCraft.java +++ b/src/main/java/me/zenox/evocraft/EvoCraft.java @@ -51,6 +51,7 @@ public static EvoCraft getPlugin() { @Override public void onEnable() { + long startTime = System.currentTimeMillis(); plugin = this; plugin.getLogger().info("EvoCraft v" + plugin.getDescription().getVersion() + " loaded."); @@ -102,6 +103,8 @@ public void onEnable() { new Command(plugin); registerListeners(); + + Util.logToConsole("v" + plugin.getDescription().getVersion() + " enabled in &e" + (System.currentTimeMillis() - startTime) + "&fms."); } private void registerListeners() { @@ -174,6 +177,8 @@ public void reload() { @Override public void onDisable() { + long startTime = System.currentTimeMillis(); playerDataManager.shutdown(); + Util.logToConsole("v" + plugin.getDescription().getVersion() + " disabled in &e" + (System.currentTimeMillis() - startTime) + "&fms."); } } diff --git a/src/main/java/me/zenox/evocraft/events/OtherEvent.java b/src/main/java/me/zenox/evocraft/events/OtherEvent.java index 92c1294..978acd6 100644 --- a/src/main/java/me/zenox/evocraft/events/OtherEvent.java +++ b/src/main/java/me/zenox/evocraft/events/OtherEvent.java @@ -4,7 +4,7 @@ import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.ClassAbility; import me.zenox.evocraft.enchant.ComplexEnchantment; -import me.zenox.evocraft.gui.EnchantingGUI; +import me.zenox.evocraft.gui.EnchantingGui; import me.zenox.evocraft.item.ComplexItemMeta; import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.item.VanillaItem; @@ -54,7 +54,7 @@ public void tileEntityInteract(PlayerInteractEvent e){ Window.single() .setViewer(e.getPlayer()) .setTitle("Enchantment Table") - .setGui(EnchantingGUI.getGui(e.getPlayer(), e.getClickedBlock())) + .setGui(EnchantingGui.getGui(e.getPlayer(), e.getClickedBlock())) .setCloseable(true) .build() .open(); @@ -198,7 +198,7 @@ public void grindstoneUse(PrepareResultEvent e){ // Get the enchantmaps of both of the items in the AnvilInventory HashMap firstEnchants = (HashMap) ComplexItemStack.of(inventory.getFirstItem()).getComplexMeta().getComplexEnchants(); HashMap secondEnchants = (HashMap) ComplexItemStack.of(inventory.getSecondItem()).getComplexMeta().getComplexEnchants(); - resultMeta.setComplexEnchantments(EnchantingGUI.combineEnchantMaps(firstEnchants, secondEnchants)); + resultMeta.setComplexEnchantments(EnchantingGui.combineEnchantMaps(firstEnchants, secondEnchants)); resultMeta.updateItem(); e.setResult(resultStack.getItem()); diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java b/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java index 540fbba..cf7af93 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java @@ -4,13 +4,12 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import xyz.xenondevs.invui.gui.AbstractGui; -import xyz.xenondevs.invui.gui.Gui; /** * hhahahh enchant gui code go brr */ -public class EnchantGuiBuilder extends AbstractGui.AbstractBuilder { +public class EnchantGuiBuilder extends AbstractGui.AbstractBuilder implements EnchantingGui.Enchanting { private final Player p; private final Block block; @@ -21,14 +20,12 @@ public EnchantGuiBuilder(Player p, Block block) { } @Override - public @NotNull EnchantingGUI build() { + public @NotNull EnchantingGui build() { if (structure == null) throw new IllegalStateException("Structure is not defined."); - EnchantingGUI gui = new EnchantingGUI(structure, p, block); + EnchantingGui gui = new EnchantingGui(structure, p, block); gui.setBackground(background); return gui; } - - interface Enchanting extends Gui.Builder {} } diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java similarity index 97% rename from src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java rename to src/main/java/me/zenox/evocraft/gui/EnchantingGui.java index a43e72e..8f5fa04 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantingGUI.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java @@ -34,7 +34,7 @@ /** * Enchantment GUI that is shown to players */ -public class EnchantingGUI extends AbstractGui { +public class EnchantingGui extends AbstractGui { public static final VariableType ENCHANT_FUEL_VAR = new VariableType<>("enchant_fuel", new LoreEntry("enchant_fuel", @@ -52,13 +52,13 @@ public class EnchantingGUI extends AbstractGui { private final Block eTable; private int bookshelfPower = 0; - public EnchantingGUI(int width, int height, Player p, Block eTable) { + public EnchantingGui(int width, int height, Player p, Block eTable) { super(width, height); this.p = p; this.eTable = eTable; } - public EnchantingGUI(@NotNull Structure structure, Player p, Block eTable) { + public EnchantingGui(@NotNull Structure structure, Player p, Block eTable) { super(structure.getWidth(), structure.getHeight()); applyStructure(structure); this.p = p; @@ -197,7 +197,7 @@ public void setBookshelfPower(int bookshelfPower) { this.bookshelfPower = bookshelfPower; } - public static boolean enchantValid(EnchantingGUI gui, int power, int XPRequired) { + public static boolean enchantValid(EnchantingGui gui, int power, int XPRequired) { int skillRequirement = 0; switch (power) { case 2 -> skillRequirement = 10; @@ -299,4 +299,6 @@ public static Gui getGui(Player p, Block block) { .addIngredient('C', new CloseItem()) .build(); } + + interface Enchanting extends Gui.Builder {} } diff --git a/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java b/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java index d2afbac..eebbc98 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/BookshelfItem.java @@ -3,7 +3,7 @@ import xyz.xenondevs.invui.item.ItemProvider; import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.impl.controlitem.ControlItem; -import me.zenox.evocraft.gui.EnchantingGUI; +import me.zenox.evocraft.gui.EnchantingGui; import me.zenox.evocraft.util.Util; import org.bukkit.Material; import org.bukkit.block.Block; @@ -17,12 +17,12 @@ /** * Bookshelf Counter Item for EnchantingTable */ -public class BookshelfItem extends ControlItem { +public class BookshelfItem extends ControlItem { - private EnchantingGUI gui; + private EnchantingGui gui; @Override - public ItemProvider getItemProvider(EnchantingGUI gui) { + public ItemProvider getItemProvider(EnchantingGui gui) { this.gui = gui; int bookshelfPower = 0; for (Block block : Util.getNearbyBlocks(gui.getETable().getLocation(), 5, 5)) diff --git a/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java b/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java index 87a9084..40b2c4e 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java @@ -3,7 +3,7 @@ import xyz.xenondevs.invui.item.ItemProvider; import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.impl.controlitem.ControlItem; -import me.zenox.evocraft.gui.EnchantingGUI; +import me.zenox.evocraft.gui.EnchantingGui; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -15,34 +15,34 @@ /** * Item that represents a boolean and changes based on boolean */ -public class BooleanItem extends ControlItem { +public class BooleanItem extends ControlItem { - private Predicate supplier; + private Predicate supplier; private ItemProvider trueItem = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE).setDisplayName("§r"); private ItemProvider falseItem = new ItemBuilder(Material.RED_STAINED_GLASS_PANE).setDisplayName("§r"); - public BooleanItem(Predicate supplier, ItemProvider trueItem, ItemProvider falseItem){ + public BooleanItem(Predicate supplier, ItemProvider trueItem, ItemProvider falseItem){ super(); this.supplier = supplier; this.trueItem = trueItem; this.falseItem = falseItem; } - public BooleanItem(Predicate supplier, ItemProvider trueItem){ + public BooleanItem(Predicate supplier, ItemProvider trueItem){ super(); this.supplier = supplier; this.trueItem = trueItem; } - public BooleanItem(Predicate supplier){ + public BooleanItem(Predicate supplier){ super(); this.supplier = supplier; } - private EnchantingGUI gui; + private EnchantingGui gui; @Override - public ItemProvider getItemProvider(EnchantingGUI gui) { + public ItemProvider getItemProvider(EnchantingGui gui) { this.gui = gui; return supplier.test(gui) ? trueItem : falseItem; } diff --git a/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java b/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java index 7b04f63..94a7716 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/EnchantItem.java @@ -5,14 +5,14 @@ import xyz.xenondevs.invui.item.impl.controlitem.ControlItem; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; -import me.zenox.evocraft.gui.EnchantingGUI; +import me.zenox.evocraft.gui.EnchantingGui; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.jetbrains.annotations.NotNull; -public class EnchantItem extends ControlItem { +public class EnchantItem extends ControlItem { private final int level; private final int skillreq; @@ -27,17 +27,17 @@ public EnchantItem(int level, int skillreq){ this.LORE = new TranslatableList(TranslatableText.Type.GUI + "-enchant-action-lore-" + level); } - private EnchantingGUI gui; + private EnchantingGui gui; @Override - public ItemProvider getItemProvider(EnchantingGUI gui) { + public ItemProvider getItemProvider(EnchantingGui gui) { this.gui = gui; return new ItemBuilder(Material.EXPERIENCE_BOTTLE).setDisplayName(NAME.toString()).setLegacyLore(LORE.getList()).setAmount(level); } @Override public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) { - if(EnchantingGUI.enchantValid(gui, level, getXPRequired())) gui.enchantItem(level, getXPRequired()); + if(EnchantingGui.enchantValid(gui, level, getXPRequired())) gui.enchantItem(level, getXPRequired()); } public int getXPRequired(){ diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java index af51f2a..1eca9b0 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java @@ -126,7 +126,7 @@ public void updateItem() { } // Write ComplexEnchants - dataContainer.set(ENCHANT_KEY, new SerializedPersistentType(), complexEnchMap); + dataContainer.set(ENCHANT_KEY, new SerializedPersistentType<>(), complexEnchMap); // Clear vanilla enchantments for (Enchantment enchant: diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index a951a8e..623e50c 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -8,7 +8,7 @@ import me.zenox.evocraft.abilities.itemabilities.specific.Psychic; import me.zenox.evocraft.abilities.itemabilities.specific.Transcendence; import me.zenox.evocraft.attribute.AttributeRegistry; -import me.zenox.evocraft.gui.EnchantingGUI; +import me.zenox.evocraft.gui.EnchantingGui; import me.zenox.evocraft.item.basicitems.CorruptPearl; import me.zenox.evocraft.item.basicitems.RavagerSkin; import me.zenox.evocraft.item.basicitems.TormentedSoul; @@ -339,7 +339,7 @@ public class ItemRegistry { .rarity(ComplexItem.Rarity.COMMON) .type(ComplexItem.Type.ENCHANTING_FUEL) .glow() - .variable(EnchantingGUI.ENCHANT_FUEL_VAR, 5)); + .variable(EnchantingGui.ENCHANT_FUEL_VAR, 5)); public static final ComplexItem INFUSED_ORBITEX = new ComplexItem(new ItemSettings() .id("infused_orbitex") @@ -347,7 +347,7 @@ public class ItemRegistry { .rarity(ComplexItem.Rarity.UNCOMMON) .type(ComplexItem.Type.ENCHANTING_FUEL) .glow() - .variable(EnchantingGUI.ENCHANT_FUEL_VAR, 15)); + .variable(EnchantingGui.ENCHANT_FUEL_VAR, 15)); public static final ComplexItem CREATIVE_MIND = new ComplexItem((new ItemSettings() .id("creative_mind") @@ -652,7 +652,7 @@ public class ItemRegistry { // Vanilla Items public static final VanillaItem LAPIS_LAZULI = new VanillaItem(new ItemSettings() .material(Material.LAPIS_LAZULI) - .variable(EnchantingGUI.ENCHANT_FUEL_VAR, 1)); + .variable(EnchantingGui.ENCHANT_FUEL_VAR, 1)); public static final ComplexItem VERTEXICAL_BLADE = new ComplexItem(new ItemSettings() .id("vertex_blade") diff --git a/src/main/java/me/zenox/evocraft/item/basicitems/CorruptPearl.java b/src/main/java/me/zenox/evocraft/item/basicitems/CorruptPearl.java index 90fb4f4..b34ac06 100644 --- a/src/main/java/me/zenox/evocraft/item/basicitems/CorruptPearl.java +++ b/src/main/java/me/zenox/evocraft/item/basicitems/CorruptPearl.java @@ -3,7 +3,6 @@ import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.item.ComplexItem; -import me.zenox.evocraft.persistence.SerializedPersistentType; import org.bukkit.*; import org.bukkit.entity.Enderman; import org.bukkit.entity.EntityType; @@ -12,6 +11,7 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; import java.util.List; import java.util.Map; @@ -49,11 +49,11 @@ public void dropEvent(EntityDeathEvent event) { Enderman specialEnderman = (Enderman) w.spawnEntity(loc.clone().add(Math.sin(r.nextDouble(2) * Math.PI) * r.nextDouble(2), 1, Math.sin(r.nextDouble(2) * Math.PI) * r.nextDouble(2)), EntityType.ENDERMAN); specialEnderman.setCarriedBlock(Material.END_PORTAL_FRAME.createBlockData()); - specialEnderman.getPersistentDataContainer().set(new NamespacedKey(EvoCraft.getPlugin(), "corrupted"), new SerializedPersistentType<>(), true); + specialEnderman.getPersistentDataContainer().set(new NamespacedKey(EvoCraft.getPlugin(), "corrupted"), PersistentDataType.BOOLEAN, true); } - boolean isCorrupted = entity.getPersistentDataContainer().has(new NamespacedKey(EvoCraft.getPlugin(), "corrupted"), new SerializedPersistentType<>()) ? - entity.getPersistentDataContainer().get(new NamespacedKey(EvoCraft.getPlugin(), "corrupted"), new SerializedPersistentType<>()) : false; + boolean isCorrupted = entity.getPersistentDataContainer().has(new NamespacedKey(EvoCraft.getPlugin(), "corrupted"), PersistentDataType.BOOLEAN) ? + entity.getPersistentDataContainer().get(new NamespacedKey(EvoCraft.getPlugin(), "corrupted"), PersistentDataType.BOOLEAN) : false; if (isCorrupted) { event.getDrops().removeIf((ItemStack item) -> item.getType().equals(Material.END_PORTAL_FRAME)); w.dropItemNaturally(loc, CORRUPT_PEARL.getItemStack(1)); From c2ad882c24127cfb2fb63dfb60873e96fdf7b6c1 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Sat, 9 Dec 2023 10:59:57 -0800 Subject: [PATCH 18/20] apex beam --- .../evocraft/abilities/ClassAbility.java | 71 ++++++++++++++----- .../zenox/evocraft/gui/EnchantGuiBuilder.java | 2 +- .../me/zenox/evocraft/gui/EnchantingGui.java | 15 +++- .../zenox/evocraft/gui/item/BooleanItem.java | 2 +- 4 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index fafd7aa..8b6493c 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -805,7 +805,7 @@ private static void createParticlePath(Location start, Location end, Player play /** * The ultimate upgrade of the Rift Beam ability. - * Charges up to unleash a devastating blast, with two chaining beams and one main beam. + * Charges up to unleash a devastating blast with one main beam. * * @param event The player interaction event. * @param player The player casting the ability. @@ -822,7 +822,6 @@ public void run() { if (isFullyCharged(player)) { // On full charge, release the beams releaseMainBeam(player, ability); - releaseChainingBeams(player, ability); this.cancel(); // Stop the task } @@ -830,34 +829,72 @@ public void run() { }.runTaskTimer(EvoCraft.getPlugin(), 0L, 1L); // Check every tick } - private static void startCharge(Player player) { - // Pseudocode: + public static void startCharge(Player player) { // Display charging particles or effects around the player. + player.getWorld().spawnParticle(Particle.END_ROD, player.getLocation(), 10, 0.5, 0.5, 0.5, 0); // Record the start time of the charge. - // Possibly play a charging sound. + player.setMetadata("charge_start_time", new FixedMetadataValue(EvoCraft.getPlugin(), System.currentTimeMillis())); + + // Start a task that increases the pitch of the sound and sends a message to the action bar as the charge progresses + new BukkitRunnable() { + float pitch = 0.5f; // Start pitch + @Override + public void run() { + if (!isFullyCharged(player)) { + // Increase the pitch and play the sound + pitch += 0.05f; // Increase pitch + player.playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1.0f, pitch); + + // Send a message to the action bar + player.sendActionBar(ChatColor.GREEN + "Charging... " + Math.round(pitch * 100) + "%"); + } else { + // Stop the task when the charge is complete + this.cancel(); + } + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 20L); // Run every second (20 ticks) } - private static boolean isFullyCharged(Player player) { - // Pseudocode: + public static boolean isFullyCharged(Player player) { // Check if the required charge time has elapsed. + long chargeStartTime = player.getMetadata("charge_start_time").get(0).asLong(); + long chargeDuration = System.currentTimeMillis() - chargeStartTime; // Return true if fully charged, false otherwise. - return false; // Placeholder + return chargeDuration >= 5000; // Assuming 5 seconds as the required charge time } - private static void releaseMainBeam(Player player, ClassAbility ability) { - // Pseudocode: + public static void releaseMainBeam(Player player, ClassAbility ability) { // Create and launch the main beam. - // This beam could have higher damage and range compared to normal rift beams. - } + Location start = player.getEyeLocation(); + Location end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange() * 2)); // Assuming the main beam has twice the range - private static void releaseChainingBeams(Player player, ClassAbility ability) { - // Pseudocode: - // Launch additional beams that chain to nearby enemies. - // These beams could originate from the player or the main beam's hit location. + new BukkitRunnable() { + int ticks = 0; // Count the number of ticks + @Override + public void run() { + if (ticks < 20) { // Run for 20 ticks (1 second) + alongPath(start, end, location -> { + // Spawn particles for visual effects + location.getWorld().spawnParticle(Particle.END_ROD, location, 10, 0.5, 0.5, 0.5, 0); // Increase the count and speed for a bigger beam + location.getWorld().spawnParticle(Particle.SQUID_INK, location, 10, 0.5, 0.5, 0.5, 0); // Use SQUID_INK particles for sonic effect + + // Deal damage to nearby entities + player.getWorld().getNearbyEntities(location, 0.5, 0.5, 0.5).forEach(entity -> { + if (entity instanceof Damageable && !entity.equals(player)) { + ((Damageable) entity).damage(ability.getStrength() * 10); // Assuming the main beam deals 10 times the ability's strength as damage + } + }); + }); + ticks++; + } else { + // Stop the task after 1 second + this.cancel(); + } + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 1L); // Run every tick (1/20th of a second) } - public static void runeShieldAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { } diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java b/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java index cf7af93..30ef939 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantGuiBuilder.java @@ -7,7 +7,7 @@ /** - * hhahahh enchant gui code go brr + * A builder class for {@link EnchantingGui}. */ public class EnchantGuiBuilder extends AbstractGui.AbstractBuilder implements EnchantingGui.Enchanting { diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java index 8f5fa04..935d110 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java @@ -12,6 +12,8 @@ import me.zenox.evocraft.item.LoreEntry; import me.zenox.evocraft.item.VariableType; import me.zenox.evocraft.util.Util; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.Particle; @@ -20,6 +22,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import xyz.xenondevs.inventoryaccess.component.ComponentWrapper; import xyz.xenondevs.invui.gui.AbstractGui; import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.SlotElement; @@ -285,8 +288,16 @@ public static Gui getGui(Player p, Block block) { "# # # # # ^ ^ 3 #", "# # # # C B # # #" ) - .addIngredient('E', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1), 0, new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE))) - .addIngredient('F', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance().getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1), 0, new ItemBuilder(Material.BLUE_STAINED_GLASS_PANE))) + .addIngredient('E', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance() + .getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1), 0, + new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE) + .setDisplayName((ComponentWrapper) Component.text("Enchant Item").color(NamedTextColor.GRAY)) + .setLore(List.of((ComponentWrapper) Component.text().content("→ Place an item here to enchant it").color(NamedTextColor.YELLOW))))) + .addIngredient('F', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance() + .getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1), 0, + new ItemBuilder(Material.BLUE_STAINED_GLASS_PANE) + .setDisplayName((ComponentWrapper) Component.text("Enchant Fuel").color(NamedTextColor.GRAY)) + .setLore(List.of((ComponentWrapper) Component.text().content("→ Place an item here to use it as enchant fuel").color(NamedTextColor.YELLOW))))) .addIngredient('R', new ItemBuilder(Material.RED_STAINED_GLASS_PANE).setDisplayName("")) .addIngredient('1', new EnchantItem(1, 0)) .addIngredient('2', new EnchantItem(2, 10)) diff --git a/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java b/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java index 40b2c4e..e30370c 100644 --- a/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java +++ b/src/main/java/me/zenox/evocraft/gui/item/BooleanItem.java @@ -17,7 +17,7 @@ */ public class BooleanItem extends ControlItem { - private Predicate supplier; + private final Predicate supplier; private ItemProvider trueItem = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE).setDisplayName("§r"); private ItemProvider falseItem = new ItemBuilder(Material.RED_STAINED_GLASS_PANE).setDisplayName("§r"); From e92af01787c26935050b2216055145e969845710 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Wed, 25 Dec 2024 13:54:15 -0800 Subject: [PATCH 19/20] smol --- .../evocraft/abilities/AbilityRegistry.java | 33 +- .../evocraft/abilities/ClassAbility.java | 206 +++++++- .../itemabilities/AttackAbility.java | 4 +- .../abilities/itemabilities/ItemAbility.java | 4 +- .../me/zenox/evocraft/command/Command.java | 469 +++++++++--------- .../me/zenox/evocraft/gui/EnchantingGui.java | 23 +- .../util/{Geo.java => GeometryUtils.java} | 2 +- .../java/me/zenox/evocraft/util/Util.java | 6 + 8 files changed, 481 insertions(+), 266 deletions(-) rename src/main/java/me/zenox/evocraft/util/{Geo.java => GeometryUtils.java} (98%) diff --git a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java index d78c8ed..e7c795f 100644 --- a/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java +++ b/src/main/java/me/zenox/evocraft/abilities/AbilityRegistry.java @@ -209,15 +209,26 @@ public class AbilityRegistry { Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_mark", ClassAbility::riftBeamMark), Modifier.of(Modifier.Type.MANA_COST, "rift_beam_efficiency", -10), Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_chain", ClassAbility::riftBeamChain), + Modifier.of(Modifier.Type.MULTI, "rift_beam_concentrate", Modifier.of(Modifier.Type.COOLDOWN, "rift_beam_concentrate_cooldown", 0), + Modifier.of(Modifier.Type.MANA_COST, "rift_beam_concentrate_mana_cost", +250)), Modifier.of(Modifier.Type.EXECUTABLE, "rift_beam_apex", ClassAbility::riftBeamApex) - ), ClassAbility::riftBeamAbility); + ), ClassAbility::riftBeamAbility); public static final ClassAbility RUNE_SHIELD = new ClassAbility(new AbilitySettings() .id("mage_rune_shield") .manaCost(50) - .cooldown(0) - .range(20) - .strength(1) - , ClassAbility::runeShieldAbility); + .cooldown(30) + .range(0) // Assuming the shield is self-cast and does not have a range. + .strength(1) // This could represent the base level of damage reduction. + .charges(0) + .chargeTime(0) + .modifiers( + Modifier.of(Modifier.Type.RANGE, "rune_shield_duration", +2), // Enhanced Durability + Modifier.of(Modifier.Type.STRENGTH, "rune_shield_barrier", +10), // Reinforced Barrier + Modifier.of(Modifier.Type.MANA_COST, "rune_shield_efficiency", -5), // Mana Efficiency + Modifier.of(Modifier.Type.EXECUTABLE, "rune_shield_illumination", ClassAbility::runeIlluminatingAura), // Illuminating Aura + Modifier.of(Modifier.Type.COOLDOWN, "rune_shield_recovery", -5), // Rapid Recovery + Modifier.of(Modifier.Type.EXECUTABLE, "rune_shield_resonance", ClassAbility::arcaneResonance) // Arcane Resonance + ), ClassAbility::runeShieldAbility); public static final ClassAbility BLOODLUST = new ClassAbility(new AbilitySettings() .id("bloodlust") .manaCost(35) @@ -248,6 +259,18 @@ public class AbilityRegistry { .charges(3) , ClassAbility::counterstrikeAbility); +// public static final ClassAbility PRECISION_SHOT = new ClassAbility(new AbilitySettings() +// .id("precision_shot") +// .manaCost(15) +// .cooldown(5) +// .strength(10) +// .charges(3) +// .modifiers( +// Modifier.of(Modifier.Type.RANGE, "precision_shot_range", +20), +// Modifier.of(Modifier.Type.MANA_COST, "precision_cheaper_1", -20) +// ) +// , ClassAbility::precisionShotAbility); + public static void registerAbilities(){ Util.logToConsole("Registering %s abilities.".formatted(ChatColor.GOLD + "" + Ability.registeredAbilities.size() + ChatColor.RESET)); } diff --git a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java index 8b6493c..3cc4e8b 100644 --- a/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/ClassAbility.java @@ -1,15 +1,22 @@ package me.zenox.evocraft.abilities; +import com.ticxo.modelengine.api.ModelEngineAPI; +import com.ticxo.modelengine.api.model.ActiveModel; +import com.ticxo.modelengine.api.model.ModeledEntity; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.data.PlayerData; import me.zenox.evocraft.data.PlayerDataManager; -import me.zenox.evocraft.util.Geo; +import me.zenox.evocraft.util.GeometryUtils; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.*; -import org.bukkit.Color; import org.bukkit.entity.*; import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.metadata.FixedMetadataValue; @@ -25,11 +32,11 @@ import java.lang.annotation.Target; import java.lang.reflect.Field; import java.util.*; -import java.util.List; import java.util.function.Consumer; public class ClassAbility extends Ability { final List modifiers; + @SaveState protected TriConsumer executable; @@ -257,7 +264,7 @@ private static void teleport(Player player, int distance) { } private static void teleportEffect(Location startLoc, Location endLoc, Color color, Player player, int damage, double width) { - List tracedPath = Geo.lerpEdges(List.of(startLoc.toVector(), endLoc.toVector()), (int) (1.3 * startLoc.distance(endLoc))); + List tracedPath = GeometryUtils.lerpEdges(List.of(startLoc.toVector(), endLoc.toVector()), (int) (1.3 * startLoc.distance(endLoc))); Vector direction = endLoc.toVector().subtract(startLoc.toVector()).normalize(); new BukkitRunnable() { @@ -636,7 +643,7 @@ public static void riftBeamAbility(PlayerInteractEvent event, Player player, Cla } private static void alongPath(Location start, Location end, Consumer loc){ - List tracedPath = Geo.lerpEdges(List.of(start.toVector(), end.toVector()), (int) (1.3 * start.distance(end))); + List tracedPath = GeometryUtils.lerpEdges(List.of(start.toVector(), end.toVector()), (int) (1.3 * start.distance(end))); tracedPath = tracedPath.subList(0, tracedPath.size()/2); tracedPath.forEach(vector -> { loc.accept(vector.toLocation(start.getWorld())); @@ -837,22 +844,41 @@ public static void startCharge(Player player) { // Start a task that increases the pitch of the sound and sends a message to the action bar as the charge progresses new BukkitRunnable() { - float pitch = 0.5f; // Start pitch @Override public void run() { - if (!isFullyCharged(player)) { - // Increase the pitch and play the sound - pitch += 0.05f; // Increase pitch - player.playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1.0f, pitch); - // Send a message to the action bar - player.sendActionBar(ChatColor.GREEN + "Charging... " + Math.round(pitch * 100) + "%"); + long chargeStartTime = player.getMetadata("charge_start_time").get(0).asLong(); + long elapsedTime = System.currentTimeMillis() - chargeStartTime; + if (elapsedTime < 5000) { + // Calculate the percentage of the elapsed time relative to the total charge time + float percentage = (float) elapsedTime / 5000; // Assuming 5 seconds as the total charge time + + // Calculate the pitch based on the percentage + float pitch = 0.5f + 0.5f * percentage; // Assuming the pitch ranges from 0.5 to 1.0 + + // Play the sound with the calculated pitch + if ((int) (percentage * 100) % 10 == 0) player.playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1.0f, pitch); + + // Summon particle effects to look like the player is drawing power from the ground + // particles should move from the ground towards the player + Location loc = player.getLocation().clone().add(0, 0.5, 0); + Vector direction = loc.toVector().subtract(player.getLocation().toVector()).normalize(); + Vector perpendicular = direction.clone().rotateAroundY(Math.toRadians(90)); + Vector offset = perpendicular.multiply(0.5); + loc.add(offset); + player.getWorld().spawnParticle(Particle.END_ROD, loc, 1, 0.1, 0.1, 0.1, 0); + + // Send a message to the action bar with the calculated percentage + Component message = Component.text("Charging... ", NamedTextColor.GREEN) + .append(Component.text(Math.round(percentage * 100) + "%")); + + Util.sendActionBar(player, message); } else { // Stop the task when the charge is complete this.cancel(); } } - }.runTaskTimer(EvoCraft.getPlugin(), 0L, 20L); // Run every second (20 ticks) + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 5L); } public static boolean isFullyCharged(Player player) { @@ -867,37 +893,167 @@ public static void releaseMainBeam(Player player, ClassAbility ability) { // Create and launch the main beam. Location start = player.getEyeLocation(); Location end = player.getEyeLocation().add(player.getEyeLocation().getDirection().multiply(ability.getRange() * 2)); // Assuming the main beam has twice the range + double totalDistance = start.distance(end); new BukkitRunnable() { int ticks = 0; // Count the number of ticks @Override public void run() { if (ticks < 20) { // Run for 20 ticks (1 second) + double currentDistance = totalDistance * (ticks / 20.0); // Calculate the current distance based on the elapsed time alongPath(start, end, location -> { - // Spawn particles for visual effects - location.getWorld().spawnParticle(Particle.END_ROD, location, 10, 0.5, 0.5, 0.5, 0); // Increase the count and speed for a bigger beam - location.getWorld().spawnParticle(Particle.SQUID_INK, location, 10, 0.5, 0.5, 0.5, 0); // Use SQUID_INK particles for sonic effect - - // Deal damage to nearby entities - player.getWorld().getNearbyEntities(location, 0.5, 0.5, 0.5).forEach(entity -> { - if (entity instanceof Damageable && !entity.equals(player)) { - ((Damageable) entity).damage(ability.getStrength() * 10); // Assuming the main beam deals 10 times the ability's strength as damage - } - }); + double distanceFromStart = start.distance(location); + if (distanceFromStart <= currentDistance) { + // Spawn particles for visual effects + location.getWorld().spawnParticle(Particle.END_ROD, location, 1, 0.5, 0.5, 0.5, 0); // Increase the count and speed for a bigger beam + location.getWorld().spawnParticle(Particle.REDSTONE, location, 1, 0.5, 0.5, 0.5, 0, + new Particle.DustOptions(Color.fromRGB(144, 0, 255), 1)); + if (ticks % 8 == 0) location.getWorld().spawnParticle(Particle.SONIC_BOOM, location, 1); + + // Deal damage to nearby entities + player.getWorld().getNearbyEntities(location, 1, 1, 1).forEach(entity -> { + if (entity instanceof Damageable dEntity && !entity.equals(player)) { + dEntity.damage(ability.getStrength() * 10); // Assuming the main beam deals 10 times the ability's strength as damage + // knock the entity back and play a sound + entity.setVelocity(entity.getLocation().toVector().subtract(location.toVector()).normalize().multiply(0.5)); + entity.getWorld().playSound(entity.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1, 0); + // particle impact + entity.getWorld().spawnParticle(Particle.EXPLOSION_NORMAL, entity.getLocation(), 1, 0.5, 0.5, 0.5, 0); + } + }); + } }); - ticks++; + ticks += 4; } else { // Stop the task after 1 second this.cancel(); } } - }.runTaskTimer(EvoCraft.getPlugin(), 0L, 1L); // Run every tick (1/20th of a second) + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 4L); // Run every tick (1/20th of a second) + } + + public static class ShieldListener implements Listener { + private static final Map shields = new HashMap<>(); + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + ArmorStand shield = shields.get(player); + if (shield != null && isInFront(player, event.getDamager())) { + event.setCancelled(true); + // Decrease shield health + shield.setHealth(shield.getHealth() - event.getFinalDamage()); + + player.playSound(player.getLocation(), Sound.BLOCK_GLASS_BREAK, 1.0f, 0f); + + // Play sound effect with pitch relative to shield's health + float pitch = (float) shield.getHealth() / 20f; // Assuming max health is 20 + + if (shield.getHealth() <= 0) { + shields.remove(player); + shield.remove(); + + // Play breaking sound effect + + player.playSound(player.getLocation(), Sound.BLOCK_BEACON_DEACTIVATE, 1, pitch); + + // Play break animation + ActiveModel model = ModelEngineAPI.createActiveModel("mana_rune"); + ModeledEntity entity = ModelEngineAPI.createModeledEntity(shield); + entity.addModel(model, true); + model.getAnimationHandler().playAnimation("death", 1, 1, 1, false); + } + } + } + } + + public static void addShield(Player player, ArmorStand shield) { + shields.put(player, shield); + } + + public static void removeShield(Player player) { + shields.remove(player); + } } public static void runeShieldAbility(PlayerInteractEvent event, Player player, ClassAbility ability) { + // Spawn the rune shield model in front of the player + Location shieldLocation = player.getLocation().add(player.getLocation().getDirection().multiply(1)); + ActiveModel model = ModelEngineAPI.createActiveModel("mana_rune"); + + ArmorStand stand = player.getWorld().spawn(shieldLocation, ArmorStand.class); + stand.setGravity(false); + stand.setVisible(false); + stand.setCollidable(true); // Prevent entities from passing through + stand.setHealth(20); // Set shield health (10 seconds * 20 health per second) + ModeledEntity entity = ModelEngineAPI.createModeledEntity(stand); + entity.addModel(model, true); + model.getAnimationHandler().playAnimation("idle", 1, 1, 1, true); + + // Add the shield to the listener + ShieldListener.addShield(player, stand); + + new BukkitRunnable() { + @Override + public void run() { + if (stand.isValid()) { + double newHealth = stand.getHealth() - 1; // Decrease health by 1 each second + if (newHealth <= 0) { + // If health is 0 or less, remove the shield + ShieldListener.removeShield(player); + stand.remove(); + } else { + // Otherwise, update the shield's health + stand.setHealth(newHealth); + } + } else { + this.cancel(); + } + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 20L); + + // Task to make the shield follow the player + new BukkitRunnable() { + @Override + public void run() { + if (stand.isValid()) { + stand.teleport(player.getLocation().add(player.getLocation().getDirection().multiply(1))); + } else { + this.cancel(); + } + } + }.runTaskTimer(EvoCraft.getPlugin(), 0L, 1L); // Update every tick + // Remove the shield after a certain duration + new BukkitRunnable() { + @Override + public void run() { + if (stand.isValid()) { + ShieldListener.removeShield(player); + stand.remove(); + } + } + }.runTaskLater(EvoCraft.getPlugin(), 20 * 10); // Remove the shield after 10 seconds + } + + private static boolean isInFront(Player player, Entity entity) { + Vector toEntity = entity.getLocation().toVector().subtract(player.getLocation().toVector()).normalize(); + Vector direction = player.getLocation().getDirection(); + return direction.dot(toEntity) >= 0; // This checks if the entity is in front of the player } + + public static void runeIlluminatingAura(PlayerInteractEvent event, Player player, ClassAbility ability) { + runeShieldAbility(event, player, ability); + // Create a light source at the player's location + + } + + public static void arcaneResonance(PlayerInteractEvent event, Player player, ClassAbility ability) { + + } + public static void bloodlustAbility(PlayerInteractEvent event, Player player, ClassAbility ability){ player.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 1200, 1) ); } diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/AttackAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/AttackAbility.java index 13273ee..8429dde 100644 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/AttackAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/AttackAbility.java @@ -4,7 +4,7 @@ import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.AbilitySettings; import me.zenox.evocraft.abilities.EventAbility; -import me.zenox.evocraft.util.Geo; +import me.zenox.evocraft.util.GeometryUtils; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.*; @@ -124,7 +124,7 @@ public void run() { if (stacks >= 3) { // Create Dodecahedron - List edgedDodecahedron = Geo.lerpEdges(Geo.makeDodecahedron(p.getLocation().toVector(), 2), 7); + List edgedDodecahedron = GeometryUtils.lerpEdges(GeometryUtils.makeDodecahedron(p.getLocation().toVector(), 2), 7); for (Vector v : edgedDodecahedron) { Particle.DustOptions dustOptions = new Particle.DustOptions(Color.fromRGB(5, 165, 255), 0.6F); diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java index 3a1fee9..1b487df 100644 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java @@ -23,7 +23,7 @@ import me.zenox.evocraft.item.ComplexItemStack; import me.zenox.evocraft.item.ItemRegistry; import me.zenox.evocraft.persistence.NBTEditor; -import me.zenox.evocraft.util.Geo; +import me.zenox.evocraft.util.GeometryUtils; import me.zenox.evocraft.util.TriConsumer; import me.zenox.evocraft.util.Util; import org.bukkit.*; @@ -142,7 +142,7 @@ public static void soulRiftAbility(PlayerInteractEvent event, Player p, ItemStac @Override public void run() { // Particle Magic - List dodecahedron = Geo.makeDodecahedron(loc.toVector(), 2); + List dodecahedron = GeometryUtils.makeDodecahedron(loc.toVector(), 2); for (Vector v : dodecahedron) { Particle.DustOptions dustOptions = new Particle.DustOptions(Color.fromRGB(0, 187, 215), 0.5F); w.spawnParticle(Particle.REDSTONE, v.toLocation(w).add(0, 0.5 + Math.sin(count) / 4, 0), 1, dustOptions); diff --git a/src/main/java/me/zenox/evocraft/command/Command.java b/src/main/java/me/zenox/evocraft/command/Command.java index ac84812..d33084e 100644 --- a/src/main/java/me/zenox/evocraft/command/Command.java +++ b/src/main/java/me/zenox/evocraft/command/Command.java @@ -14,7 +14,6 @@ import me.zenox.evocraft.loot.LootTableRegistry; import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; @@ -23,269 +22,287 @@ import xyz.xenondevs.invui.window.Window; import java.util.*; +import java.util.function.Consumer; import java.util.stream.Collectors; public class Command implements CommandExecutor, TabCompleter { private final EvoCraft plugin; + private final Map> subcommands = new HashMap<>(); public Command(EvoCraft plugin) { this.plugin = plugin; + + // Register subcommands + subcommands.put("give", this::handleGive); + subcommands.put("loottable", this::handleLootTable); + subcommands.put("dropitematplayer", this::handleDropItemAtPlayer); + subcommands.put("droploottable", this::handleDropLootTable); + subcommands.put("enchant", this::handleEnchant); + subcommands.put("reload", this::handleReload); + subcommands.put("model", this::handleModel); + subcommands.put("class", this::handleClass); + subcommands.put("progresspath", this::handleProgressPath); + plugin.getCommand("evocraft").setExecutor(this); plugin.getCommand("evocraft").setTabCompleter(this); } @Override public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) { - if (args.length == 0) { - Util.sendMessage(sender, "EvoCraft Help Page."); + Util.sendMessage(sender, "EvoCraft Help Page. Available commands: " + String.join(", ", subcommands.keySet())); return true; } - switch (args[0]) { - case "give" -> { - if (args.length < 2 || sender.getServer().getPlayer(args[1]) == null) { - Util.sendMessage(sender, "Please specify a valid user to give an item."); - return true; - } - Player p = (Player) sender; - Player givento = sender.getServer().getPlayer(args[1]); - if (args.length < 3) { - Util.sendMessage(p, "Please specify a item to give."); - return true; - } - ComplexItem itemtype = ComplexItem.itemRegistry.get(args[2]); - if (itemtype == null) { - Util.sendMessage(p, "This item could not be found!"); - } else { - Object amount; - if (args.length >= 4) { - amount = Ints.tryParse(args[3]); - if (amount == null) { - Util.sendMessage(p, args[3] + " is not a valid integer! Please specify an integer for argument ."); - return true; - } - } else { - amount = 1; - } + Consumer subcommand = subcommands.get(args[0].toLowerCase()); + if (subcommand == null) { + Util.sendMessage(sender, "Unknown subcommand. Type /evocraft for help."); + return true; + } - givento.getInventory().addItem(new ComplexItemStack(itemtype, (int) amount).getItem()); - Util.sendMessage(p, "You gave " + givento.getDisplayName() + " x" + amount + " [" + itemtype.getDisplayName() + ChatColor.GOLD + "]"); - } - return true; - } - case "loottable" -> { - if (args.length < 2 || sender.getServer().getPlayer(args[1]) == null) { - Util.sendMessage(sender, "Please specify a valid user to give a loottable for."); - return true; - } - if (args.length < 3) { - Util.sendMessage(sender, "Please specify a valid loottable."); - return true; - } - int threatlevel; - if (args.length < 4 || Ints.tryParse(args[3]) == null) { - threatlevel = 1; - } else { - threatlevel = Ints.tryParse(args[3]); - } - for (LootTable lootTable : LootTableRegistry.lootTableList) { - if (args[2].equalsIgnoreCase(lootTable.getId())) { - lootTable.openLootGUI(sender.getServer().getPlayer(args[1]), threatlevel); - return true; - } - } - } - case "dropitematplayer" -> { - if (args.length < 2 || sender.getServer().getPlayer(args[1]) == null) { - Util.sendMessage(sender, "Please specify a valid user to drop an item at."); - return true; - } - Player dropgivento = sender.getServer().getPlayer(args[1]); - if (args.length < 3) { - Util.sendMessage(sender, "Please specify a item to drop."); - return true; - } - ComplexItem itemtypetodrop = ComplexItem.itemRegistry.get(args[2]); - if (itemtypetodrop == null) { - Util.sendMessage(sender, "This item could not be found!"); - } else { - Object amount; - if (args.length >= 4) { - amount = Ints.tryParse(args[3]); - if (amount == null) { - Util.sendMessage(sender, args[3] + " is not a valid integer! Please specify an integer for argument ."); - return true; - } - } else { - amount = 1; - } + CommandContext context = new CommandContext(sender, args); + try { + subcommand.accept(context); + } catch (IllegalArgumentException e) { + Util.sendMessage(sender, ChatColor.RED + "Error: " + e.getMessage()); + } + return true; + } - dropgivento.getWorld().dropItemNaturally(dropgivento.getLocation(), new ComplexItemStack(itemtypetodrop, (int) amount).getItem()); - Util.sendMessage(sender, "You gave " + dropgivento.getDisplayName() + " x" + amount + " [" + itemtypetodrop.getDisplayName() + ChatColor.GOLD + "]"); - } - } - case "droploottable" -> { - if (args.length < 2 || sender.getServer().getEntity(UUID.fromString(args[1])) == null) { - Util.sendMessage(sender, "Please specify a valid entity to give a loot table for."); - return true; - } - if (args.length < 3) { - Util.sendMessage(sender, "Please specify a valid loot table."); - return true; - } - for (LootTable lootTable : LootTableRegistry.lootTableList) { - if (args[2].equalsIgnoreCase(lootTable.getId())) { - lootTable.dropLoot(sender.getServer().getEntity(UUID.fromString(args[1])).getLocation(), 1); - return true; + private void handleGive(CommandContext context) { + Player giver = context.requirePlayer(); + Player recipient = context.requirePlayerArgument(1, "Please specify a valid player to give an item."); + String itemId = context.requireStringArgument(2, "Please specify an item to give."); + ComplexItem item = ComplexItem.itemRegistry.get(itemId); + if (item == null) throw new IllegalArgumentException("Item not found: " + itemId); + + int amount = context.optionalIntArgument(3, 1); + recipient.getInventory().addItem(new ComplexItemStack(item, amount).getItem()); + Util.sendMessage(giver, "Gave " + recipient.getDisplayName() + " x" + amount + " [" + item.getDisplayName() + "]"); + } + + private void handleLootTable(CommandContext context) { + Player player = context.requirePlayer(); + Player recipient = context.requirePlayerArgument(1, "Please specify a valid player."); + String lootTableId = context.requireStringArgument(2, "Please specify a valid loot table."); + int threatLevel = context.optionalIntArgument(3, 1); + + LootTable lootTable = LootTableRegistry.lootTableList.stream() + .filter(lt -> lootTableId.equalsIgnoreCase(lt.getId())) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Loot table not found: " + lootTableId)); + + lootTable.openLootGUI(recipient, threatLevel); + Util.sendMessage(player, "Opened loot table " + lootTableId + " for " + recipient.getDisplayName()); + } + + private void handleDropItemAtPlayer(CommandContext context) { + Player player = context.requirePlayer(); + Player target = context.requirePlayerArgument(1, "Please specify a valid player."); + String itemId = context.requireStringArgument(2, "Please specify an item to drop."); + ComplexItem item = ComplexItem.itemRegistry.get(itemId); + if (item == null) throw new IllegalArgumentException("Item not found: " + itemId); + + int amount = context.optionalIntArgument(3, 1); + target.getWorld().dropItemNaturally(target.getLocation(), new ComplexItemStack(item, amount).getItem()); + Util.sendMessage(player, "Dropped x" + amount + " [" + item.getDisplayName() + "] at " + target.getDisplayName()); + } + + private void handleDropLootTable(CommandContext context) { + String entityUUID = context.requireStringArgument(1, "Please specify a valid entity UUID."); + String lootTableId = context.requireStringArgument(2, "Please specify a valid loot table."); + int amount = context.optionalIntArgument(3, 1); + + LootTable lootTable = LootTableRegistry.lootTableList.stream() + .filter(lt -> lootTableId.equalsIgnoreCase(lt.getId())) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Loot table not found: " + lootTableId)); + + lootTable.dropLoot(context.getSender().getServer().getEntity(UUID.fromString(entityUUID)).getLocation(), 1); + } + + private void handleReload(CommandContext context) { + plugin.reload(); + Util.sendMessage(context.getSender(), ChatColor.GREEN + "EvoCraft has been reloaded."); + } + + private void handleProgressPath(CommandContext context) { + Player player = context.requirePlayer(); + String pathId = context.requireStringArgument(1, "Please specify a valid path."); + int level = context.optionalIntArgument(2, -1); + + PlayerData data = PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()); + Path path = data.getPlayerClass().tree().path(pathId); + if (path == null) throw new IllegalArgumentException("Path not found: " + pathId); + + if (level == -1) { + data.progressPath(path); + Util.sendMessage(player, "Progressed on path " + path.getId() + " to level " + data.getPathLevel(path) + "."); + } else { + data.setPathLevel(path, level); + Util.sendMessage(player, "Set path " + path.getId() + " to level " + level + "."); + } + } + + private void handleEnchant(CommandContext context) { + Player player = context.requirePlayer(); + Player target = context.requirePlayerArgument(1, "Please specify a valid player."); + String enchantmentId = context.requireStringArgument(2, "Please specify an enchantment."); + ComplexEnchantment enchantment = ComplexEnchantment.byId(enchantmentId); + if (enchantment == null) throw new IllegalArgumentException("Enchantment not found: " + enchantmentId); + + int level = context.optionalIntArgument(3, 1); + ItemStack item = target.getInventory().getItemInMainHand(); + if (item == null || item.getType().isAir()) throw new IllegalArgumentException("The target's main hand is empty."); + + ComplexItemMeta meta = ComplexItemStack.of(item).getComplexMeta(); + if (level > 0) { + meta.addEnchantment(enchantment, level); + } else { + meta.removeEnchantment(enchantment); + } + Util.sendMessage(player, "Enchanted " + target.getDisplayName() + "'s item with " + enchantment.getName() + " (level " + level + ")."); + } + + private void handleModel(CommandContext context) { + Player player = context.requirePlayer(); + ItemStack item = player.getEquipment().getItemInMainHand(); + if (item.getType().isAir()) { + Util.sendMessage(player, "This item has no CustomModelData (that is created by EvoCraft)."); + return; + } + + ComplexItem complexItem = ComplexItem.of(item); + if (complexItem == null) { + Util.sendMessage(player, "This item is not a valid EvoCraft item."); + return; + } + + Util.sendMessage(player, "The CustomModelData of " + item.getItemMeta().getDisplayName() + " is " + complexItem.getCustomModelData()); + } + + private void handleClass(CommandContext context) { + Player player = context.requirePlayer(); + Window.single() + .setViewer(player) + .setTitle("Class Selection") + .setGui(GameClass.getGui()) + .setCloseable(true) + .build() + .open(); + } + + + + // Additional handlers... + + @Override + public List onTabComplete(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) { + if (args.length == 1) { + return subcommands.keySet().stream() + .filter(cmd -> cmd.startsWith(args[0].toLowerCase())) + .sorted() + .collect(Collectors.toList()); + } + + if (args.length >= 2) { + switch (args[0].toLowerCase()) { + case "give", "dropitematplayer" -> { + if (args.length == 2) { + // Suggest player names + return getOnlinePlayers(sender).stream() + .filter(name -> name.toLowerCase().startsWith(args[1].toLowerCase())) + .sorted() + .collect(Collectors.toList()); + } else if (args.length == 3) { + // Suggest item IDs + return ComplexItem.itemRegistry.keySet().stream() + .filter(item -> item.toLowerCase().startsWith(args[2].toLowerCase())) + .sorted() + .collect(Collectors.toList()); } } - return false; - } - case "enchant" -> { - if (args.length < 2 || sender.getServer().getPlayer(args[1]) == null) { - Util.sendMessage(sender, "Please specify a valid user to give an item."); - return true; - } - if (args.length < 3) { - Util.sendMessage(sender, "Please specify a item to give."); - return true; - } - Player enchanted = sender.getServer().getPlayer(args[1]); - ComplexEnchantment enchant = ComplexEnchantment.byId(args[2]); - if (enchant == null) { - Util.sendMessage(sender, "Enchantment " + ChatColor.WHITE + args[2] + " doesn't exist."); - } else { - Object level; - if (args.length >= 4) { - level = Ints.tryParse(args[3]); - if (level == null) { - Util.sendMessage(sender, args[3] + " is not a valid integer! Please specify an integer for argument ."); - return true; - } - } else { - level = 1; + case "loottable", "droploottable" -> { + if (args.length == 2) { + // Suggest player or entity UUIDs + return getOnlinePlayers(sender).stream() + .filter(name -> name.toLowerCase().startsWith(args[1].toLowerCase())) + .sorted() + .collect(Collectors.toList()); + } else if (args.length == 3) { + // Suggest loot table IDs + return LootTableRegistry.lootTableList.stream() + .map(LootTable::getId) + .filter(id -> id.toLowerCase().startsWith(args[2].toLowerCase())) + .sorted() + .collect(Collectors.toList()); } - - ComplexItemMeta meta = ComplexItemStack.of(enchanted.getInventory().getItemInMainHand()).getComplexMeta(); - if(((int) level) > 0) meta.addEnchantment(enchant, (Integer) level); - else meta.removeEnchantment(enchant); - Util.sendMessage(sender, "You enchanted " + enchanted.getDisplayName() + " with " + ChatColor.WHITE + enchant.getName() + " " + level); - } - return true; - } - case "reload" -> { - plugin.reload(); - Util.sendMessage(sender, ChatColor.WHITE + "EvoCraft " + ChatColor.GREEN + "v" + plugin.getDescription().getVersion() + ChatColor.WHITE + " has been reloaded."); - return true; - } - case "model" -> { - ItemStack item = ((Player) sender).getEquipment().getItemInMainHand(); - if(item.getType() == Material.AIR) { - Util.sendMessage(sender, ChatColor.WHITE + "This item has no CustomModelData (that is created by EvoCraft)"); - return true; } - Util.sendMessage(sender, ChatColor.WHITE + "The CustomModelData of " + item.getItemMeta().getDisplayName() + ChatColor.WHITE + " is " + ComplexItem.of(item).getCustomModelData()); - return true; - } - case "class" -> // Open the class selection GUI - Window.single() - .setViewer((Player) sender) - .setTitle("Class Selection") - .setGui(GameClass.getGui()) - .setCloseable(true) - .build() - .open(); - case "progresspath" -> { - if (args.length < 2) { - Util.sendMessage(sender, "Please specify a valid path."); - return true; - } - Player player = ((Player) sender); - PlayerData data = PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()); - Path path = data.getPlayerClass().tree().path(args[1]); - if (path == null) { - Util.sendMessage(sender, "&cThis path does not exist!"); - return true; - } - try { - if (args.length < 3) - data.progressPath(path); - else { - int level = Integer.parseInt(args[2]); - data.setPathLevel(path, level); + case "progresspath" -> { + if (args.length == 2 && sender instanceof Player) { + // Suggest paths + Player player = (Player) sender; + GameClass gameClass = PlayerDataManager.getInstance() + .getPlayerData(player.getUniqueId()).getPlayerClass(); + return gameClass.tree().paths().stream() + .map(Path::getId) + .filter(path -> path.toLowerCase().startsWith(args[1].toLowerCase())) + .sorted() + .collect(Collectors.toList()); } - } catch (IllegalArgumentException e) { - Util.sendMessage(sender, e.getMessage()); - return true; } - Util.sendMessage(sender, "&aYou have progressed on the " + path.getId() + " path to level " + data.getPathLevel(path) + "!"); - return true; } - default -> Util.sendMessage(sender, "EvoCraft Help Page."); } - return true; - } - - final List arguments = new ArrayList<>(); - final List items = new ArrayList<>(); - @Override - public List onTabComplete(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args) { - if (args.length == 1) { - return getCommandSuggestions(args[0]); - } else if (args.length == 2 && "progresspath".equalsIgnoreCase(args[0]) && sender instanceof Player) { - return getPathSuggestions((Player) sender, args[1]); - } else if (args.length == 3) { - return getThirdArgumentSuggestions(args[0], args[2]); - } else if (args.length == 4 && "enchant".equalsIgnoreCase(args[0])) { - return Collections.singletonList(""); - } else if (args.length == 4 && "give".equalsIgnoreCase(args[0])) { - return Collections.singletonList(""); - } return Collections.emptyList(); } - private List getCommandSuggestions(String arg) { - List commands = Arrays.asList("give", "loottable", "droploottable", "dropitematplayer", - "enchant", "reload", "removechapterdata", "removemetadata", - "setchapter", "class", "progresspath"); - return commands.stream() - .filter(a -> a.toLowerCase().startsWith(arg.toLowerCase())) + private List getOnlinePlayers(CommandSender sender) { + return sender.getServer().getOnlinePlayers().stream() + .map(Player::getName) .collect(Collectors.toList()); } - private List getPathSuggestions(Player player, String arg) { - GameClass gameClass = PlayerDataManager.getInstance().getPlayerData(player.getUniqueId()).getPlayerClass(); - return gameClass.tree().paths().stream() - .map(Path::getId) - .filter(path -> path.toLowerCase().startsWith(arg.toLowerCase())) - .collect(Collectors.toList()); - } + private static class CommandContext { + private final CommandSender sender; + private final String[] args; - private List getThirdArgumentSuggestions(String arg0, String arg2) { - if ("give".equalsIgnoreCase(arg0)) { - return getItemSuggestions(arg2); - } else if ("enchant".equalsIgnoreCase(arg0)) { - return getEnchantmentSuggestions(arg2); + public CommandContext(CommandSender sender, String[] args) { + this.sender = sender; + this.args = args; } - return Collections.emptyList(); - } - private List getItemSuggestions(String arg) { - if (items.isEmpty()) { - items.addAll(ComplexItem.itemRegistry.keySet()); + public CommandSender getSender() { + return sender; } - return items.stream() - .filter(b -> b.toLowerCase().startsWith(arg.toLowerCase())) - .collect(Collectors.toList()); - } - private List getEnchantmentSuggestions(String arg) { - return ComplexEnchantment.getRegisteredEnchants().stream() - .map(ComplexEnchantment::getId) - .filter(id -> id.toLowerCase().startsWith(arg.toLowerCase())) - .collect(Collectors.toList()); + public Player requirePlayer() { + if (!(sender instanceof Player)) throw new IllegalArgumentException("This command can only be used by a player."); + return (Player) sender; + } + + public Player requirePlayerArgument(int index, String errorMessage) { + if (args.length <= index) throw new IllegalArgumentException(errorMessage); + Player player = sender.getServer().getPlayer(args[index]); + if (player == null) throw new IllegalArgumentException("Player not found: " + args[index]); + return player; + } + + public String requireStringArgument(int index, String errorMessage) { + if (args.length <= index) throw new IllegalArgumentException(errorMessage); + return args[index]; + } + + public int optionalIntArgument(int index, int defaultValue) { + if (args.length <= index) return defaultValue; + Integer value = Ints.tryParse(args[index]); + if (value == null) throw new IllegalArgumentException("Invalid number: " + args[index]); + return value; + } + + public org.bukkit.Server requireServer() { + return sender.getServer(); + } } -} +} \ No newline at end of file diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java index 935d110..79760d6 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java @@ -14,6 +14,7 @@ import me.zenox.evocraft.util.Util; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.Particle; @@ -22,7 +23,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import xyz.xenondevs.inventoryaccess.component.ComponentWrapper; +import xyz.xenondevs.inventoryaccess.component.AdventureComponentWrapper; import xyz.xenondevs.invui.gui.AbstractGui; import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.SlotElement; @@ -291,13 +292,25 @@ public static Gui getGui(Player p, Block block) { .addIngredient('E', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance() .getOrCreate(Util.constantUUID(ENCHANT_GUI_ITEM_KEY + p.getName()), 1), 0, new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE) - .setDisplayName((ComponentWrapper) Component.text("Enchant Item").color(NamedTextColor.GRAY)) - .setLore(List.of((ComponentWrapper) Component.text().content("→ Place an item here to enchant it").color(NamedTextColor.YELLOW))))) + .setDisplayName(new AdventureComponentWrapper( + Component.text("Enchanting Slot").color(NamedTextColor.LIGHT_PURPLE))) + .setLore(List.of( + new AdventureComponentWrapper( + Component.text("The enchanting table funnels its energy through this slot, adding mystical properties to the item.") + .color(NamedTextColor.GRAY).decorate(TextDecoration.ITALIC) + ), + new AdventureComponentWrapper(Component.text("")), + new AdventureComponentWrapper( + Component.text("→ Place an item here to enchant it.").color(NamedTextColor.YELLOW) + ) + )))) .addIngredient('F', new SlotElement.InventorySlotElement(VirtualInventoryManager.getInstance() .getOrCreate(Util.constantUUID(ENCHANT_GUI_FUEL_KEY + p.getName()), 1), 0, new ItemBuilder(Material.BLUE_STAINED_GLASS_PANE) - .setDisplayName((ComponentWrapper) Component.text("Enchant Fuel").color(NamedTextColor.GRAY)) - .setLore(List.of((ComponentWrapper) Component.text().content("→ Place an item here to use it as enchant fuel").color(NamedTextColor.YELLOW))))) + .setDisplayName(new AdventureComponentWrapper( + Component.text("Enchant Fuel").color(NamedTextColor.BLUE))) + .setLore(List.of(new AdventureComponentWrapper( + Component.text("→ Place an item here to use it as enchant fuel").color(NamedTextColor.YELLOW)))))) .addIngredient('R', new ItemBuilder(Material.RED_STAINED_GLASS_PANE).setDisplayName("")) .addIngredient('1', new EnchantItem(1, 0)) .addIngredient('2', new EnchantItem(2, 10)) diff --git a/src/main/java/me/zenox/evocraft/util/Geo.java b/src/main/java/me/zenox/evocraft/util/GeometryUtils.java similarity index 98% rename from src/main/java/me/zenox/evocraft/util/Geo.java rename to src/main/java/me/zenox/evocraft/util/GeometryUtils.java index 0f134f5..bdd097d 100644 --- a/src/main/java/me/zenox/evocraft/util/Geo.java +++ b/src/main/java/me/zenox/evocraft/util/GeometryUtils.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import java.util.List; -public class Geo { +public class GeometryUtils { /// Generates a list of vertices (in arbitrary order) for a tetrahedron centered on the origin. public static List makeDodecahedron(Vector vec, double r) { diff --git a/src/main/java/me/zenox/evocraft/util/Util.java b/src/main/java/me/zenox/evocraft/util/Util.java index 9b89224..8789a15 100644 --- a/src/main/java/me/zenox/evocraft/util/Util.java +++ b/src/main/java/me/zenox/evocraft/util/Util.java @@ -8,6 +8,8 @@ import com.destroystokyo.paper.profile.PlayerProfile; import com.destroystokyo.paper.profile.ProfileProperty; import me.zenox.evocraft.EvoCraft; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.command.CommandSender; @@ -45,6 +47,10 @@ public static void sendActionBar(@NotNull Player p, String message) { EvoCraft.getActionBar().sendAbilityActionBar(p, ChatColor.translateAlternateColorCodes('&', message)); } + public static void sendActionBar(@NotNull Player p, Component message) { + EvoCraft.getActionBar().sendAbilityActionBar(p, LegacyComponentSerializer.legacySection().serialize(message)); + } + public static void sendTitle(@NotNull Player p, String title, String subtitle, int fadeIn, int stay, int fadeOut) { p.sendTitle(ChatColor.translateAlternateColorCodes('&', title), ChatColor.translateAlternateColorCodes('&', subtitle), fadeIn, stay, fadeOut); } From 871cd5bacd30e46c3a2731d4692903e27687d0c2 Mon Sep 17 00:00:00 2001 From: ZenoCoding Date: Sat, 28 Dec 2024 21:42:12 -0800 Subject: [PATCH 20/20] update to auraskills 2.0 --- pom.xml | 6 +-- src/main/java/me/zenox/evocraft/EvoCraft.java | 21 ++++------ .../me/zenox/evocraft/abilities/Ability.java | 8 ++-- .../abilities/itemabilities/ItemAbility.java | 22 ++++++---- .../itemabilities/specific/Psychic.java | 15 ++++--- .../zenox/evocraft/attribute/Attribute.java | 1 + .../evocraft/attribute/AttributeModifier.java | 8 ++-- .../evocraft/attribute/AttributeRegistry.java | 4 +- .../attribute/types/AureliumAttribute.java | 26 +++++++----- .../me/zenox/evocraft/gui/EnchantingGui.java | 12 +++--- .../me/zenox/evocraft/item/ComplexItem.java | 14 +++---- .../zenox/evocraft/item/ComplexItemMeta.java | 16 +++++--- .../zenox/evocraft/item/ComplexItemStack.java | 18 +++++--- .../me/zenox/evocraft/item/ItemRegistry.java | 2 +- .../me/zenox/evocraft/item/ItemSettings.java | 14 +++---- .../java/me/zenox/evocraft/util/Util.java | 41 +++++-------------- 16 files changed, 119 insertions(+), 109 deletions(-) diff --git a/pom.xml b/pom.xml index cbc6214..ec1bec2 100644 --- a/pom.xml +++ b/pom.xml @@ -112,9 +112,9 @@ provided - com.github.Archy-X - AureliumSkills - Beta1.3.23 + dev.aurelium + auraskills-api-bukkit + 2.2.4 provided diff --git a/src/main/java/me/zenox/evocraft/EvoCraft.java b/src/main/java/me/zenox/evocraft/EvoCraft.java index 440836e..cfb9680 100644 --- a/src/main/java/me/zenox/evocraft/EvoCraft.java +++ b/src/main/java/me/zenox/evocraft/EvoCraft.java @@ -1,14 +1,11 @@ package me.zenox.evocraft; -import com.archyx.aureliumskills.api.AureliumAPI; -import com.archyx.aureliumskills.modifier.Modifiers; -import com.archyx.aureliumskills.ui.ActionBar; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolManager; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import xyz.xenondevs.invui.gui.structure.Structure; -import xyz.xenondevs.invui.item.builder.ItemBuilder; +import dev.aurelium.auraskills.api.AuraSkillsApi; +import dev.aurelium.auraskills.api.AuraSkillsBukkit; import me.zenox.evocraft.abilities.AbilityRegistry; import me.zenox.evocraft.attribute.AttributeRegistry; import me.zenox.evocraft.command.Command; @@ -28,6 +25,8 @@ import org.bukkit.Material; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; +import xyz.xenondevs.invui.gui.structure.Structure; +import xyz.xenondevs.invui.item.builder.ItemBuilder; public final class EvoCraft extends JavaPlugin { @@ -37,12 +36,12 @@ public final class EvoCraft extends JavaPlugin { private static Permission perms = null; public boolean isUsingWorldGuard; - public static Modifiers modifiers; private static LanguageLoader languageLoader; private static ConfigLoader configLoader; private static ProtocolManager protocolManager; - private static ActionBar actionBar; private static PlayerDataManager playerDataManager; + private static AuraSkillsApi auraSkillsApi; + private static AuraSkillsBukkit auraSkillsBukkit; public static EvoCraft getPlugin() { return plugin; @@ -80,9 +79,10 @@ public void onEnable() { return; } + auraSkillsApi = AuraSkillsApi.get(); + auraSkillsBukkit = AuraSkillsBukkit.get(); + playerDataManager = new PlayerDataManager(); - modifiers = new Modifiers(AureliumAPI.getPlugin()); - actionBar = AureliumAPI.getPlugin().getActionBar(); configLoader = new ConfigLoader(plugin); languageLoader = new LanguageLoader(plugin); @@ -167,9 +167,6 @@ public static Permission getPermissions() { return perms; } - public static ActionBar getActionBar() { - return actionBar; - } public void reload() { this.reloadConfig(); this.languageLoader = new LanguageLoader(this); diff --git a/src/main/java/me/zenox/evocraft/abilities/Ability.java b/src/main/java/me/zenox/evocraft/abilities/Ability.java index 6934d1c..bf3063a 100644 --- a/src/main/java/me/zenox/evocraft/abilities/Ability.java +++ b/src/main/java/me/zenox/evocraft/abilities/Ability.java @@ -1,6 +1,6 @@ package me.zenox.evocraft.abilities; -import com.archyx.aureliumskills.api.AureliumAPI; +import dev.aurelium.auraskills.api.user.SkillsUser; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.data.TranslatableList; import me.zenox.evocraft.data.TranslatableText; @@ -116,7 +116,8 @@ protected double getCooldownEndTime(@NotNull Player p) { } protected boolean notEnoughMana(Player p, int requiredMana) { - return ((int) AureliumAPI.getMana(p)) < requiredMana; + SkillsUser user = Util.getSkillsUser(p); + return ((int) user.getMana()) < requiredMana; } protected void sendManaInsufficientMessage(Player p) { @@ -124,7 +125,8 @@ protected void sendManaInsufficientMessage(Player p) { } protected void deductMana(Player p, int manaCost) { - AureliumAPI.setMana(p, AureliumAPI.getMana(p) - manaCost); + SkillsUser user = Util.getSkillsUser(p); + user.setMana(user.getMana() - manaCost); } protected void showMessage(Player p, String msg) { diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java index 1b487df..0058946 100644 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/ItemAbility.java @@ -1,6 +1,5 @@ package me.zenox.evocraft.abilities.itemabilities; -import com.archyx.aureliumskills.api.AureliumAPI; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketContainer; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -12,6 +11,8 @@ import com.sk89q.worldguard.protection.regions.RegionQuery; import com.ticxo.modelengine.api.ModelEngineAPI; import com.ticxo.modelengine.api.model.ModeledEntity; +import dev.aurelium.auraskills.api.trait.Traits; +import dev.aurelium.auraskills.api.user.SkillsUser; import it.unimi.dsi.fastutil.ints.IntArrayList; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.Slot; @@ -813,6 +814,9 @@ public void run() { } public static void emberShootAbility(PlayerInteractEvent event, Player p, ItemStack item) { + + SkillsUser user = Util.getSkillsUser(p); + ComplexItemMeta complexMeta = ComplexItemStack.of(item).getComplexMeta(); Location eyeLoc = p.getEyeLocation(); @@ -821,11 +825,11 @@ public static void emberShootAbility(PlayerInteractEvent event, Player p, ItemSt if (complexMeta.getVariable(EmberAttune.ATTUNEMENT_VARIABLE_TYPE).getValue().equals(EmberAttune.Attunement.BLAZEBORN)) { Fireball f = (Fireball) eyeLoc.getWorld().spawnEntity(eyeLoc.add(eyeLoc.getDirection()), EntityType.FIREBALL); - f.setVelocity(eyeLoc.getDirection().normalize().multiply(Math.min(5, AureliumAPI.getMaxMana(event.getPlayer()) / 75))); + f.setVelocity(eyeLoc.getDirection().normalize().multiply(Math.min(5, user.getMaxMana() / 75))); f.setMetadata("dmgEnv", new FixedMetadataValue(EvoCraft.getPlugin(), false)); f.setMetadata("knockback", new FixedMetadataValue(EvoCraft.getPlugin(), 2)); f.setShooter(p); - f.setYield(((float) Math.sqrt(AureliumAPI.getMaxMana(p))) / 10f); + f.setYield(((float) Math.sqrt(user.getMaxMana())) / 10f); // get rid of the fireball after 10 seconds new BukkitRunnable() { @@ -837,10 +841,10 @@ public void run() { } else if (complexMeta.getVariable(EmberAttune.ATTUNEMENT_VARIABLE_TYPE).getValue().equals(EmberAttune.Attunement.DARKSOUL)) { WitherSkull f = (WitherSkull) eyeLoc.getWorld().spawnEntity(eyeLoc.add(eyeLoc.getDirection()), EntityType.WITHER_SKULL); - f.setVelocity(eyeLoc.getDirection().normalize().multiply(Math.min(5, AureliumAPI.getMaxMana(event.getPlayer()) / 50))); + f.setVelocity(eyeLoc.getDirection().normalize().multiply(Math.min(5, user.getMaxMana() / 50))); f.setMetadata("dmgEnv", new FixedMetadataValue(EvoCraft.getPlugin(), false)); f.setShooter(p); - f.setYield((float) Math.sqrt(AureliumAPI.getMaxMana(p)) / 6f); + f.setYield((float) Math.sqrt(user.getMaxMana()) / 6f); // get rid of the fireball after 10 seconds new BukkitRunnable() { @@ -904,8 +908,10 @@ public void run() { } public static void manaBoostAbility(PlayerInteractEvent event, Player player, ItemStack itemStack) { + SkillsUser user = Util.getSkillsUser(player); + // An ability that refuels the player to full mana instantaneously, and grants them 2x mana regeneration for the next 10 seconds - AureliumAPI.setMana(player, AureliumAPI.getMaxMana(player)); + user.setMana(user.getMaxMana()); // Send and action bar Util.sendActionBar(player, "&b&lMana Refueled!"); // Play a sound @@ -930,9 +936,9 @@ public void run() { cancel(); } // Get the players current mana regeneration - double manaRegen = AureliumAPI.getManaRegen(player); + double manaRegen = user.getEffectiveTraitLevel(Traits.MANA_REGEN); // Add that amount to the player's mana - AureliumAPI.setMana(player, Math.min(AureliumAPI.getMaxMana(player), AureliumAPI.getMana(player) + manaRegen)); + user.setMana(Math.min(user.getMaxMana(), user.getMana() + manaRegen)); } }.runTaskTimer(EvoCraft.getPlugin(), 0, 20); diff --git a/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Psychic.java b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Psychic.java index a66175e..7cab6c0 100644 --- a/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Psychic.java +++ b/src/main/java/me/zenox/evocraft/abilities/itemabilities/specific/Psychic.java @@ -1,7 +1,5 @@ package me.zenox.evocraft.abilities.itemabilities.specific; -import com.archyx.aureliumskills.api.AureliumAPI; -import com.archyx.aureliumskills.stats.Stats; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.util.Location; import com.sk89q.worldguard.LocalPlayer; @@ -10,8 +8,12 @@ import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.regions.RegionContainer; import com.sk89q.worldguard.protection.regions.RegionQuery; -import me.zenox.evocraft.Slot; +import dev.aurelium.auraskills.api.AuraSkillsApi; +import dev.aurelium.auraskills.api.stat.StatModifier; +import dev.aurelium.auraskills.api.stat.Stats; +import dev.aurelium.auraskills.api.user.SkillsUser; import me.zenox.evocraft.EvoCraft; +import me.zenox.evocraft.Slot; import me.zenox.evocraft.abilities.itemabilities.ItemAbility; import me.zenox.evocraft.util.Util; import org.bukkit.Bukkit; @@ -36,6 +38,8 @@ public class Psychic extends ItemAbility implements Listener { + private static final AuraSkillsApi skillsApi = AuraSkillsApi.get(); + public Psychic() { super("psychic", AbilityAction.RIGHT_CLICK_ALL, 0, 0, Slot.MAIN_HAND); @@ -104,7 +108,7 @@ public void run() { dataContainer.set(key, PersistentDataType.INTEGER, count); p.playSound(p.getLocation(), Sound.ENTITY_ZOMBIE_VILLAGER_CONVERTED, 1, 1.2f); - AureliumAPI.addStatModifier(p, "evocraft:psychic_wisdom_buff_" + count, Stats.WISDOM, 50d); + skillsApi.getUser(p.getUniqueId()).addStatModifier(new StatModifier("evocraft:psychic_wisdom_buff_" + count, Stats.WISDOM , 50d)); } private void killPlayer(Player p, NamespacedKey key, PersistentDataContainer dataContainer) { @@ -112,6 +116,7 @@ private void killPlayer(Player p, NamespacedKey key, PersistentDataContainer dat p.setMetadata("evocraft:death_psychic", new FixedMetadataValue(EvoCraft.getPlugin(), true)); p.setHealth(0); p.damage(10, p); + SkillsUser user = skillsApi.getUser(p.getUniqueId()); new BukkitRunnable() { int count = 0; @@ -125,7 +130,7 @@ public void run() { } }.runTaskTimer(EvoCraft.getPlugin(), 0, 20); for (int i = 0; i < 20; i++) { - AureliumAPI.removeStatModifier(p, "evocraft:psychic_wisdom_buff_" + i); + user.removeStatModifier("evocraft:psychic_wisdom_buff_" + i); } } diff --git a/src/main/java/me/zenox/evocraft/attribute/Attribute.java b/src/main/java/me/zenox/evocraft/attribute/Attribute.java index 089f12a..9e5c12f 100644 --- a/src/main/java/me/zenox/evocraft/attribute/Attribute.java +++ b/src/main/java/me/zenox/evocraft/attribute/Attribute.java @@ -24,6 +24,7 @@ public abstract class Attribute implements Serializable { public Attribute(String id, ChatColor color, AttributeSource source, Function valueFormatter) { this.id = id; + this.name = new TranslatableText(TranslatableText.Type.ATTRIBUTE + "-" + id); this.color = color; this.source = source; diff --git a/src/main/java/me/zenox/evocraft/attribute/AttributeModifier.java b/src/main/java/me/zenox/evocraft/attribute/AttributeModifier.java index f2fdbe5..11d6cc5 100644 --- a/src/main/java/me/zenox/evocraft/attribute/AttributeModifier.java +++ b/src/main/java/me/zenox/evocraft/attribute/AttributeModifier.java @@ -1,6 +1,6 @@ package me.zenox.evocraft.attribute; -import com.archyx.aureliumskills.modifier.StatModifier; +import dev.aurelium.auraskills.api.stat.StatModifier; import me.zenox.evocraft.Slot; import me.zenox.evocraft.attribute.types.AureliumAttribute; import me.zenox.evocraft.attribute.types.MinecraftAttribute; @@ -50,10 +50,10 @@ public static AttributeModifier of(org.bukkit.attribute.Attribute attribute, org public static AttributeModifier of(StatModifier modifier){ try { - return new AttributeModifier(modifier.getName(), UUID.randomUUID(), + return new AttributeModifier(modifier.name(), UUID.randomUUID(), ((Attribute) Attribute.attributeRegistry.stream() - .filter(attribute1 -> attribute1 instanceof AureliumAttribute && ((AureliumAttribute) attribute1).getStat() == modifier.getStat()) - .toArray()[0]), modifier.getValue(), Operation.ADD_NUMBER, modifier.getName().contains("item") && !modifier.getName().contains("armor") ? Slot.MAIN_HAND : Slot.ARMOR); + .filter(attribute1 -> attribute1 instanceof AureliumAttribute && ((AureliumAttribute) attribute1).getStat() == modifier.stat()) + .toArray()[0]), modifier.value(), Operation.ADD_NUMBER, modifier.name().contains("item") && !modifier.name().contains("armor") ? Slot.MAIN_HAND : Slot.ARMOR); } catch (IndexOutOfBoundsException e){ throw new IllegalArgumentException("AttributeModifier " + modifier + " was"); } diff --git a/src/main/java/me/zenox/evocraft/attribute/AttributeRegistry.java b/src/main/java/me/zenox/evocraft/attribute/AttributeRegistry.java index 838c725..b315407 100644 --- a/src/main/java/me/zenox/evocraft/attribute/AttributeRegistry.java +++ b/src/main/java/me/zenox/evocraft/attribute/AttributeRegistry.java @@ -1,6 +1,6 @@ package me.zenox.evocraft.attribute; -import com.archyx.aureliumskills.stats.Stats; +import dev.aurelium.auraskills.api.stat.Stats; import me.zenox.evocraft.attribute.types.AureliumAttribute; import me.zenox.evocraft.attribute.types.MinecraftAttribute; import me.zenox.evocraft.util.Util; @@ -25,6 +25,8 @@ public class AttributeRegistry { public static final Attribute AS_LUCK = new AureliumAttribute("as-luck", ChatColor.GREEN, Stats.LUCK); public static final Attribute WISDOM = new AureliumAttribute("as-wisdom", ChatColor.BLUE, Stats.WISDOM); public static final Attribute TOUGHNESS = new AureliumAttribute("as-toughness", ChatColor.DARK_PURPLE, Stats.TOUGHNESS); + public static final Attribute CRIT_CHANCE = new AureliumAttribute("as-crit_chance", ChatColor.GOLD, Stats.CRIT_CHANCE); + public static final Attribute CRIT_DAMAGE = new AureliumAttribute("as-crit_damage", ChatColor.GOLD, Stats.CRIT_DAMAGE); public static void registerAttributes(){ Util.logToConsole(ChatColor.WHITE + "Registering " + ChatColor.GOLD + Attribute.attributeRegistry.size() + ChatColor.WHITE + " attributes"); diff --git a/src/main/java/me/zenox/evocraft/attribute/types/AureliumAttribute.java b/src/main/java/me/zenox/evocraft/attribute/types/AureliumAttribute.java index a906061..a45c078 100644 --- a/src/main/java/me/zenox/evocraft/attribute/types/AureliumAttribute.java +++ b/src/main/java/me/zenox/evocraft/attribute/types/AureliumAttribute.java @@ -1,13 +1,13 @@ package me.zenox.evocraft.attribute.types; -import com.archyx.aureliumskills.api.AureliumAPI; -import com.archyx.aureliumskills.modifier.ModifierType; -import com.archyx.aureliumskills.modifier.StatModifier; -import com.archyx.aureliumskills.stats.Stat; +import dev.aurelium.auraskills.api.AuraSkillsBukkit; +import dev.aurelium.auraskills.api.item.ItemManager; +import dev.aurelium.auraskills.api.item.ModifierType; +import dev.aurelium.auraskills.api.stat.Stat; +import dev.aurelium.auraskills.api.stat.StatModifier; import me.zenox.evocraft.Slot; import me.zenox.evocraft.attribute.Attribute; import me.zenox.evocraft.attribute.AttributeModifier; -import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -17,8 +17,12 @@ public class AureliumAttribute extends Attribute { + private static final ItemManager itemManager = AuraSkillsBukkit.get().getItemManager(); + private final Stat stat; + + public AureliumAttribute(String id, ChatColor color, Stat stat) { this(id, color, stat, (value) -> (value > 0 ? "+" : "") + value); } @@ -31,12 +35,12 @@ public AureliumAttribute(String id, ChatColor color, Stat stat, Function stat.equals(statModifier.getStat())) - .mapToDouble(StatModifier::getValue) + .filter(statModifier -> stat.equals(statModifier.stat())) + .mapToDouble(StatModifier::value) .sum(); if (modifier.getOperation().equals(org.bukkit.attribute.AttributeModifier.Operation.ADD_SCALAR)){ @@ -47,15 +51,15 @@ public ItemStack apply(ItemStack item, @NotNull AttributeModifier modifier) { // Returns an armor modifier if the item's type is a valid armor type, otherwise adds an item modifier if(List.of(Slot.HEAD, Slot.CHEST, Slot.LEGS, Slot.FEET, Slot.ARMOR).contains(modifier.getSlot())){ - return AureliumAPI.addArmorModifier(item, stat, curValue, false); + return itemManager.addStatModifier(item, ModifierType.ARMOR, stat, curValue, false); } else { - return AureliumAPI.addItemModifier(item, stat, curValue, false); + return itemManager.addStatModifier(item, ModifierType.ITEM, stat, curValue, false); } } @Override public ItemStack remove(ItemStack item, @NotNull AttributeModifier modifier) { - return Util.removeAureliumModifier(item, List.of(Slot.HEAD, Slot.CHEST, Slot.LEGS, Slot.FEET, Slot.ARMOR) + return itemManager.removeStatModifier(item, List.of(Slot.HEAD, Slot.CHEST, Slot.LEGS, Slot.FEET, Slot.ARMOR) .contains(modifier.getSlot()) ? ModifierType.ARMOR : ModifierType.ITEM, stat); } diff --git a/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java index 79760d6..968897a 100644 --- a/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java +++ b/src/main/java/me/zenox/evocraft/gui/EnchantingGui.java @@ -1,7 +1,7 @@ package me.zenox.evocraft.gui; -import com.archyx.aureliumskills.api.AureliumAPI; -import com.archyx.aureliumskills.skills.Skills; +import dev.aurelium.auraskills.api.skill.Skills; +import dev.aurelium.auraskills.api.user.SkillsUser; import me.zenox.evocraft.enchant.ComplexEnchantment; import me.zenox.evocraft.gui.item.BookshelfItem; import me.zenox.evocraft.gui.item.BooleanItem; @@ -86,11 +86,12 @@ public boolean enchantItem(int level, int xpRequired) { ComplexItemStack item = ComplexItemStack.of(getEItem()); ComplexItemStack fuelItem = ComplexItemStack.of(getFuelItem()); Random r = new Random(); + SkillsUser user = Util.getSkillsUser(p); int fuelStrength = (int) (fuelItem.getComplexMeta().getVariable(ENCHANT_FUEL_VAR).getValue()); double variety = calculateVariety(bookshelfPower); - double strength = calculateStrength(level, fuelStrength, AureliumAPI.getSkillLevel(p, Skills.ENCHANTING)); + double strength = calculateStrength(level, fuelStrength, user.getSkillLevel(Skills.ENCHANTING)); // Util.sendMessage(p, "Enchant | Strength: " + strength + " | Variety: " + variety); @@ -171,7 +172,7 @@ public boolean enchantItem(int level, int xpRequired) { p.setLevel(p.getLevel() - xpRequired - level + 1); // Update player's Skill XP - AureliumAPI.addXp(p, Skills.ENCHANTING, calculateSkillXP(level, strength, calculateVariety(bookshelfPower))); + user.addSkillXp(Skills.ENCHANTING, calculateSkillXP(level, strength, calculateVariety(bookshelfPower))); return true; } @@ -202,13 +203,14 @@ public void setBookshelfPower(int bookshelfPower) { } public static boolean enchantValid(EnchantingGui gui, int power, int XPRequired) { + SkillsUser user = Util.getSkillsUser(gui.p); int skillRequirement = 0; switch (power) { case 2 -> skillRequirement = 10; case 3 -> skillRequirement = 25; } // Check XP and skill level - return fuelValid(gui.getFuelItem()) && itemValid(gui.getEItem()) && AureliumAPI.getSkillLevel(gui.p, Skills.ENCHANTING) >= skillRequirement && gui.p.getLevel() >= XPRequired; + return fuelValid(gui.getFuelItem()) && itemValid(gui.getEItem()) && user.getSkillLevel(Skills.ENCHANTING) >= skillRequirement && gui.p.getLevel() >= XPRequired; } private static boolean itemValid(ItemStack item) { diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItem.java b/src/main/java/me/zenox/evocraft/item/ComplexItem.java index affbd6a..181308d 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItem.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItem.java @@ -1,7 +1,7 @@ package me.zenox.evocraft.item; -import com.archyx.aureliumskills.stats.Stat; import com.google.common.primitives.Ints; +import dev.aurelium.auraskills.api.stat.Stats; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.Ability; import me.zenox.evocraft.abilities.itemabilities.ItemAbility; @@ -43,7 +43,7 @@ public class ComplexItem { private final Type type; private final Material material; private final ItemMeta meta; - private final Map stats; + private final Map stats; private final List> abilities; private final HashMap variableMap = new HashMap<>(); private final List attributeModifiers; @@ -51,7 +51,7 @@ public class ComplexItem { private String skullURL; - public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type type, Material material, Map stats, List> abilities, HashMap variableMap, List attributeModifiers) { + public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type type, Material material, Map stats, List> abilities, HashMap variableMap, List attributeModifiers) { this.id = id; this.name = new TranslatableText(TranslatableText.Type.ITEM_NAME + "-" + id); this.lore = new TranslatableList(TranslatableText.Type.ITEM_LORE + "-" + id); @@ -73,15 +73,15 @@ public ComplexItem(String id, Boolean unique, Boolean glow, Rarity rarity, Type register(false); } - public ComplexItem(String id, Boolean unique, Rarity rarity, Type type, Material material, Map stats, List> abilities) { + public ComplexItem(String id, Boolean unique, Rarity rarity, Type type, Material material, Map stats, List> abilities) { this(id, unique, false, rarity, type, material, stats, abilities, new HashMap<>(), new ArrayList<>()); } - public ComplexItem(String id, Rarity rarity, Type type, Material material, Map stats, List> abilities) { + public ComplexItem(String id, Rarity rarity, Type type, Material material, Map stats, List> abilities) { this(id, false, rarity, type, material, stats, abilities); } - public ComplexItem(String id, Rarity rarity, Type type, Material material, Map stats) { + public ComplexItem(String id, Rarity rarity, Type type, Material material, Map stats) { this(id, false, rarity, type, material, stats, List.of()); } @@ -207,7 +207,7 @@ public Type getType() { return this.type; } - public Map getStats() { + public Map getStats() { return stats; } diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java index 1eca9b0..f6f86bd 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItemMeta.java @@ -1,8 +1,10 @@ package me.zenox.evocraft.item; -import com.archyx.aureliumskills.modifier.ModifierType; -import com.archyx.aureliumskills.modifier.StatModifier; -import com.archyx.aureliumskills.stats.Stats; +import dev.aurelium.auraskills.api.AuraSkillsBukkit; +import dev.aurelium.auraskills.api.item.ItemManager; +import dev.aurelium.auraskills.api.item.ModifierType; +import dev.aurelium.auraskills.api.stat.StatModifier; +import dev.aurelium.auraskills.api.stat.Stats; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.Ability; import me.zenox.evocraft.abilities.itemabilities.FullSetArmorAbility; @@ -13,7 +15,6 @@ import me.zenox.evocraft.persistence.ArrayListType; import me.zenox.evocraft.persistence.SerializedPersistentType; import me.zenox.evocraft.util.Romans; -import me.zenox.evocraft.util.Util; import org.bukkit.ChatColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; @@ -51,6 +52,9 @@ public class ComplexItemMeta { })), VariableType.Priority.BELOW, (loreEntry, variable) -> loreEntry.setLore(List.of(((ComplexItem.Type) variable.getValue()).getName()))); public static final NamespacedKey ENCHANT_KEY = new NamespacedKey(EvoCraft.getPlugin(), "complexEnchants"); private static final NamespacedKey ATTRIBUTE_KEY = new NamespacedKey(EvoCraft.getPlugin(), "attributes"); + + private static final ItemManager itemManager = AuraSkillsBukkit.get().getItemManager(); + private final List variableList = new ArrayList<>(); private HashMap complexEnchantments = new HashMap<>(); private List modifierList = new ArrayList<>(); @@ -88,7 +92,7 @@ public void updateItem() { Arrays.stream(Attribute.values()).forEach(meta::removeAttributeModifier); item.setItemMeta(meta); - Arrays.stream(Stats.values()).forEach(stats -> item.setItemMeta(Util.removeAureliumModifier(item, ((ComplexItem.Type) getVariable(TYPE_VAR).getValue()).isWearable() ? ModifierType.ARMOR : ModifierType.ITEM, stats).getItemMeta())); + Arrays.stream(Stats.values()).forEach(stats -> item.setItemMeta(itemManager.removeStatModifier(item, ((ComplexItem.Type) getVariable(TYPE_VAR).getValue()).isWearable() ? ModifierType.ARMOR : ModifierType.ITEM, stats).getItemMeta())); meta = item.getItemMeta(); @@ -279,7 +283,7 @@ private void writeAbilityLore(LoreBuilder loreBuilder) { // Read AureliumSkills Modifiers for(StatModifier modifier : - Util.getAureliumModifiers(stack.getItem(), + itemManager.getStatModifiers(stack.getItem(), ((ComplexItem.Type) meta.getVariable(ComplexItemMeta.TYPE_VAR).getValue()).isWearable() ? ModifierType.ARMOR : ModifierType.ITEM)){ modifiers.add(AttributeModifier.of(modifier)); } diff --git a/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java b/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java index 6ec2a84..7ab7243 100644 --- a/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java +++ b/src/main/java/me/zenox/evocraft/item/ComplexItemStack.java @@ -1,7 +1,9 @@ package me.zenox.evocraft.item; -import com.archyx.aureliumskills.api.AureliumAPI; -import com.archyx.aureliumskills.stats.Stat; +import dev.aurelium.auraskills.api.AuraSkillsBukkit; +import dev.aurelium.auraskills.api.item.ItemManager; +import dev.aurelium.auraskills.api.item.ModifierType; +import dev.aurelium.auraskills.api.stat.Stats; import me.zenox.evocraft.EvoCraft; import me.zenox.evocraft.abilities.Ability; import me.zenox.evocraft.enchant.ComplexEnchantment; @@ -17,7 +19,10 @@ import org.jetbrains.annotations.NotNull; import java.io.Serializable; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; /** * Class that represents a "custom" ItemStack. @@ -37,6 +42,8 @@ public class ComplexItemStack { private final String skullURL; + private final static ItemManager itemManager = AuraSkillsBukkit.get().getItemManager(); + public ComplexItemStack(ComplexItem complexItem, int amount) { this(complexItem, new ItemStack(complexItem.getMaterial())); this.item = buildItem(amount); @@ -126,8 +133,9 @@ private ItemStack buildItem(int amount) { item.setItemMeta(meta); // Set stats and clone - for (Map.Entry entry : complexItem.getStats().entrySet()) { - item = complexItem.getType().isWearable() ? AureliumAPI.addArmorModifier(item, entry.getKey(), entry.getValue(), false) : AureliumAPI.addItemModifier(item, entry.getKey(), entry.getValue(), false); + for (Map.Entry entry : complexItem.getStats().entrySet()) { + ModifierType type = complexItem.getType().isWearable() ? ModifierType.ARMOR : ModifierType.ITEM; + item = itemManager.addStatModifier(item, type, entry.getKey(), entry.getValue(), false); } meta = item.getItemMeta(); diff --git a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java index 623e50c..e4a767b 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemRegistry.java +++ b/src/main/java/me/zenox/evocraft/item/ItemRegistry.java @@ -1,6 +1,6 @@ package me.zenox.evocraft.item; -import com.archyx.aureliumskills.stats.Stats; +import dev.aurelium.auraskills.api.stat.Stats; import me.zenox.evocraft.abilities.AbilityRegistry; import me.zenox.evocraft.abilities.ElementalFlux; import me.zenox.evocraft.abilities.itemabilities.specific.Crucify; diff --git a/src/main/java/me/zenox/evocraft/item/ItemSettings.java b/src/main/java/me/zenox/evocraft/item/ItemSettings.java index 40f9304..babdffc 100644 --- a/src/main/java/me/zenox/evocraft/item/ItemSettings.java +++ b/src/main/java/me/zenox/evocraft/item/ItemSettings.java @@ -1,6 +1,6 @@ package me.zenox.evocraft.item; -import com.archyx.aureliumskills.stats.Stat; +import dev.aurelium.auraskills.api.stat.Stats; import me.zenox.evocraft.Slot; import me.zenox.evocraft.abilities.Ability; import me.zenox.evocraft.attribute.Attribute; @@ -26,7 +26,7 @@ public class ItemSettings { private ComplexItem.Type type; private Material material; private ItemMeta meta; - private Map stats; + private Map stats; private String skullURL; private List> abilities; private HashMap variableMap; @@ -47,7 +47,7 @@ public ItemSettings() { this.attributeModifiers = new ArrayList<>(); } - public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List> abilities, HashMap variableMap, List attributeModifiers) { + public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List> abilities, HashMap variableMap, List attributeModifiers) { this.id = id; this.unique = unique; this.glow = glow; @@ -62,7 +62,7 @@ public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity this.attributeModifiers = attributeModifiers; } - public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List> abilities){ + public ItemSettings(String id, Boolean unique, Boolean glow, ComplexItem.Rarity rarity, ComplexItem.Type type, Material material, ItemMeta meta, Map stats, String skullURL, List> abilities){ this(id, unique, glow, rarity, type, material, meta, stats, skullURL, abilities, new HashMap<>(), new ArrayList<>()); } @@ -105,7 +105,7 @@ public ItemMeta getMeta() { return meta; } - public Map getStats() { + public Map getStats() { return stats; } @@ -179,12 +179,12 @@ public ItemSettings attribute(org.bukkit.attribute.Attribute attribute, org.bukk return this; } - public ItemSettings stats(Map stats) { + public ItemSettings stats(Map stats) { this.stats = stats; return this; } - public ItemSettings stat(Stat stat, Double num) { + public ItemSettings stat(Stats stat, Double num) { Attribute attr; try { attr = ((Attribute) Attribute.attributeRegistry.stream() diff --git a/src/main/java/me/zenox/evocraft/util/Util.java b/src/main/java/me/zenox/evocraft/util/Util.java index 8789a15..4ce3df2 100644 --- a/src/main/java/me/zenox/evocraft/util/Util.java +++ b/src/main/java/me/zenox/evocraft/util/Util.java @@ -1,13 +1,9 @@ package me.zenox.evocraft.util; -import com.archyx.aureliumskills.AureliumSkills; -import com.archyx.aureliumskills.modifier.ModifierType; -import com.archyx.aureliumskills.modifier.Modifiers; -import com.archyx.aureliumskills.modifier.StatModifier; -import com.archyx.aureliumskills.stats.Stat; import com.destroystokyo.paper.profile.PlayerProfile; import com.destroystokyo.paper.profile.ProfileProperty; -import me.zenox.evocraft.EvoCraft; +import dev.aurelium.auraskills.api.AuraSkillsApi; +import dev.aurelium.auraskills.api.user.SkillsUser; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.*; @@ -44,11 +40,11 @@ public static void sendMessage(@NotNull CommandSender p, String message, boolean } public static void sendActionBar(@NotNull Player p, String message) { - EvoCraft.getActionBar().sendAbilityActionBar(p, ChatColor.translateAlternateColorCodes('&', message)); + AuraSkillsApi.get().getUserManager().getUser(p.getUniqueId()).sendActionBar(ChatColor.translateAlternateColorCodes('&', message)); } public static void sendActionBar(@NotNull Player p, Component message) { - EvoCraft.getActionBar().sendAbilityActionBar(p, LegacyComponentSerializer.legacySection().serialize(message)); + AuraSkillsApi.get().getUserManager().getUser(p.getUniqueId()).sendActionBar( LegacyComponentSerializer.legacySection().serialize(message)); } public static void sendTitle(@NotNull Player p, String title, String subtitle, int fadeIn, int stay, int fadeOut) { @@ -128,29 +124,6 @@ public static boolean isInvulnerable(Entity entity){ return (entity.hasMetadata("NPC") || (entity instanceof Player player && player.getGameMode() == GameMode.CREATIVE)); } - /** - * Gets all the modifiers an item has - * @param item the item to check - * @param type the type of modifier to check - * @return the list of modifiers - */ - public static List getAureliumModifiers(ItemStack item, ModifierType type){ - Modifiers modifiers = new Modifiers(AureliumSkills.getPlugin(AureliumSkills.class)); - return modifiers.getModifiers(type, item); - } - - /** - * Removes all modifiers of a certain type from an item - * @param item the item to remove the modifiers from - * @param type the type of modifiers to remove - * @param stat the stat to remove the modifiers from - * @return the item with the modifiers removed - */ - public static ItemStack removeAureliumModifier(ItemStack item, ModifierType type, Stat stat){ - Modifiers modifiers = new Modifiers(AureliumSkills.getPlugin(AureliumSkills.class)); - return modifiers.removeModifier(type, item, stat); - } - /** * Rounds a given double to the specified number of decimal places. * @param value the value to round @@ -161,4 +134,10 @@ public static double round(double value, int digits) { double factor = Math.pow(10, digits); return Math.round(value * factor) / factor; } + + private static final AuraSkillsApi api = AuraSkillsApi.get(); + + public static SkillsUser getSkillsUser(Player player) { + return api.getUser(player.getUniqueId()); + } }