package com.zivilon.itemeffects; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import java.util.Map; import java.util.HashMap; import java.util.UUID; import java.util.ArrayList; import java.util.List; import java.util.Collections; import java.util.stream.Collectors; import com.zivilon.itemeffects.ItemEffects; public class AuraManager { private final ItemEffects plugin; private final Map runningAuras = new HashMap<>(); private Map> originalEffects = new HashMap<>(); public AuraManager(ItemEffects plugin) { this.plugin = plugin; } // Please don't break, this thing was a hell to set up and I don't want to ever look at it again public void startAuraTask(Aura aura) { // Cancel the old task if it exists BukkitTask oldTask = null; if (runningAuras.containsKey(aura.getOwner().getUniqueId())) { oldTask = runningAuras.get(aura.getOwner().getUniqueId()).getTask(); } if (oldTask != null) { oldTask.cancel(); } // Start a new repeating task BukkitTask newTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> { World world = aura.getOwner().getWorld(); for (Aura.AuraEffectSet effectSet : aura.getEffectSets()) { for (Player nearbyPlayer : world.getPlayers()) { if (nearbyPlayer.equals(aura.getOwner())) continue; // Skip the aura owner double distance = nearbyPlayer.getLocation().distance(aura.getOwner().getLocation()); // Check player distance within the task if (distance <= effectSet.getRadius()) { // 1. If player already has an effect of the same type and it's not ambient if (nearbyPlayer.hasPotionEffect(effectSet.getEffect().getType()) && !getPotionEffectOfType(nearbyPlayer, effectSet.getEffect().getType()).isAmbient()) { originalEffects.put(nearbyPlayer.getUniqueId(), new ArrayList<>(Collections.singletonList(getPotionEffectOfType(nearbyPlayer, effectSet.getEffect().getType())))); } // 2. Remove any existing conflicting effects nearbyPlayer.removePotionEffect(effectSet.getEffect().getType()); // 3. Apply the aura effect nearbyPlayer.addPotionEffect(effectSet.getEffect()); } } } }, 0L, 40L); // Run every 2 seconds (40 ticks) // Store the new task in our map runningAuras.put(aura.getOwner().getUniqueId(), new PlayerAuraTask(aura, newTask)); } private PotionEffect getPotionEffectOfType(Player player, PotionEffectType type) { for (PotionEffect effect : player.getActivePotionEffects()) { if (effect.getType().equals(type)) { return effect; } } return null; } public void stopAuraTask(Player player) { PlayerAuraTask auraTask = runningAuras.remove(player.getUniqueId()); if (auraTask == null) { return; } BukkitTask task = auraTask.getTask(); if (task != null) { task.cancel(); } // Immediately restore original effects to the aura owner if (originalEffects.containsKey(player.getUniqueId())) { List storedEffects = originalEffects.remove(player.getUniqueId()); for (PotionEffect effect : storedEffects) { player.addPotionEffect(effect, true); } } // Restore effects to all players affected by this aura restoreEffectsOnAuraEnd(auraTask.getAura()); } public void restoreEffectsOnAuraEnd(Aura aura) { // Iterate over all players in the aura's world for (Player player : aura.getOwner().getWorld().getPlayers()) { // Check if we stored any original effects for the player if (originalEffects.containsKey(player.getUniqueId())) { List storedEffects = originalEffects.get(player.getUniqueId()); // Just get the effects without removing them if(storedEffects != null) { // Iterate over each of the effect sets in the aura for (Aura.AuraEffectSet effectSet : aura.getEffectSets()) { for (PotionEffect effect : storedEffects) { player.removePotionEffect(effect.getType()); // Remove the current effect player.addPotionEffect(effect, true); // Apply the stored effect } } originalEffects.remove(player.getUniqueId()); // Now remove it after processing all effect sets } } } } }