Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.bukkit.entity.Arrow;
import org.bukkit.event.EventHandler;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.event.entity.EntityDamageByEntityEvent;

import com.nisovin.magicspells.util.Name;
Expand Down Expand Up @@ -43,29 +43,23 @@ public void initialize(@NotNull String var) {
@OverridePriority
@EventHandler
public void onDamage(EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof LivingEntity attacked)) return;
if (!isCancelStateOk(event.isCancelled())) return;

LivingEntity caster = getAttacker(event);
if (caster == null || !canTrigger(caster)) return;
if (!(event.getDamager() instanceof Arrow arrow)) return;
if (!(event.getEntity() instanceof LivingEntity attacked)) return;
if (!(arrow.getShooter() instanceof LivingEntity caster) || !canTrigger(caster)) return;

if (!items.isEmpty()) {
EntityEquipment eq = caster.getEquipment();
if (eq == null) return;
ItemStack item = arrow.getWeapon();
if (item == null) return;

MagicItemData itemData = MagicItems.getMagicItemDataFromItemStack(eq.getItemInMainHand());
MagicItemData itemData = MagicItems.getMagicItemDataFromItemStack(item);
if (itemData == null || !contains(itemData)) return;
}

boolean casted = passiveSpell.activate(caster, attacked);
if (cancelDefaultAction(casted)) event.setCancelled(true);
}

private LivingEntity getAttacker(EntityDamageByEntityEvent event) {
if (!(event.getDamager() instanceof Arrow arrow)) return null;
if (arrow.getShooter() != null && arrow.getShooter() instanceof LivingEntity shooter) return shooter;
return null;
}

private boolean contains(MagicItemData itemData) {
for (MagicItemData data : items) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package com.nisovin.magicspells.spells.passive;

import org.jetbrains.annotations.NotNull;

import java.util.Set;
import java.util.UUID;
import java.util.HashSet;

import org.jetbrains.annotations.NotNull;
import com.google.common.collect.Multimap;
import com.google.common.collect.HashMultimap;

import org.bukkit.entity.Arrow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.event.EventPriority;
import org.bukkit.inventory.ItemStack;
import org.bukkit.event.entity.EntityRemoveEvent;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
Expand All @@ -28,11 +31,19 @@
@Name("missarrow")
public class MissArrowListener extends PassiveListener {

private static ArrowTracker tracker;

private final Set<MagicItemData> items = new HashSet<>();

@Override
public void initialize(@NotNull String var) {
if (tracker == null) {
tracker = new ArrowTracker();
MagicSpells.registerEvents(tracker);
}

if (var.isEmpty()) return;

for (String s : var.split(MagicItemDataParser.DATA_REGEX)) {
s = s.trim();

Expand All @@ -45,99 +56,74 @@ public void initialize(@NotNull String var) {
items.add(itemData);
}
}

@OverridePriority
@EventHandler
public void onHitEntity(EntityDamageByEntityEvent event) {
LivingEntity attacker = getAttacker(event);
if (attacker == null) return;
String name = attacker.getName();
UUID id = attacker.getUniqueId();
if (event.getDamager() instanceof Arrow && event.getDamager().hasMetadata("mal-" + id + '-' + name)
&& !event.getEntity().getMetadata("mal-" + id + '-' + name).isEmpty()) {
((ArrowParticle) event.getDamager().getMetadata("mal-" + id + '-' + name).get(0).value()).setHitEntity(true);
}

@Override
public void turnOff() {
tracker = null;
}

@OverridePriority
@EventHandler
public void onDamage(ProjectileHitEvent event) {
if (!(event.getEntity() instanceof Arrow)) return;

LivingEntity caster = getAttacker(event);
if (caster == null || !canTrigger(caster)) return;
public void onHit(ProjectileHitEvent event) {
if (event.getHitBlock() == null) return;
if (!(event.getEntity() instanceof Arrow arrow) || !tracker.isTracking(arrow, this)) return;
if (!(arrow.getShooter() instanceof LivingEntity caster) || !canTrigger(caster)) return;

String name = caster.getName();
UUID id = caster.getUniqueId();

if (!event.getEntity().hasMetadata("mal-" + id + '-' + name)) return;
if (event.getEntity().getMetadata("mal-" + id + '-' + name).isEmpty()) return;

ArrowParticle arrowParticle = (ArrowParticle) event.getEntity().getMetadata("mal-" + id + '-' + name).get(0).value();
if (arrowParticle.isHitEntity()) return;
tracker.removeTracking(arrow, this);

if (!items.isEmpty()) {
EntityEquipment eq = caster.getEquipment();
if (eq == null) return;
ItemStack weapon = arrow.getWeapon();
if (weapon == null) return;

MagicItemData itemData = MagicItems.getMagicItemDataFromItemStack(eq.getItemInMainHand());
if (!contains(itemData)) return;
MagicItemData itemData = MagicItems.getMagicItemDataFromItemStack(weapon);
if (itemData == null || !contains(itemData)) return;
}

passiveSpell.activate(caster, event.getEntity().getLocation());
passiveSpell.activate(caster, arrow.getLocation());
}

private boolean contains(MagicItemData itemData) {
for (MagicItemData data : items) {
if (data.matches(itemData)) return true;
}
for (MagicItemData data : items)
if (data.matches(itemData))
return true;

return false;
}

private LivingEntity getAttacker(ProjectileHitEvent event) {
Projectile e = event.getEntity();
if (!(e instanceof Arrow)) return null;
if (e.getShooter() != null && e.getShooter() instanceof LivingEntity) {
return (LivingEntity) e.getShooter();
}
return null;
}

private LivingEntity getAttacker(EntityDamageByEntityEvent event) {
Entity e = event.getDamager();
if (!(e instanceof Arrow)) return null;
if (((Arrow) e).getShooter() != null && ((Arrow) e).getShooter() instanceof LivingEntity) {
return (LivingEntity) ((Arrow) e).getShooter();
private static class ArrowTracker implements Listener {

private final Multimap<UUID, MissArrowListener> untracked = HashMultimap.create();
private final Set<UUID> tracking = new HashSet<>();

@EventHandler
public void onShoot(ProjectileLaunchEvent event) {
if (!(event.getEntity() instanceof Arrow arrow)) return;
if (!(arrow.getShooter() instanceof LivingEntity)) return;

tracking.add(arrow.getUniqueId());
}
return null;
}

@EventHandler
public void shoot(ProjectileLaunchEvent event) {
if (event.getEntity().getShooter() == null || !(event.getEntity().getShooter() instanceof LivingEntity p) || !(event.getEntity() instanceof Arrow)) return;
ArrowParticle arrowParticle = new ArrowParticle(p);
event.getEntity().setMetadata("mal-" + p.getUniqueId() + '-' + p.getName(), new FixedMetadataValue(MagicSpells.getInstance(), arrowParticle));
}

private static class ArrowParticle {

private LivingEntity origCaster;
private boolean hitEntity;

private ArrowParticle(LivingEntity origCaster) {
this.origCaster = origCaster;

@EventHandler
public void onRemove(EntityRemoveEvent event) {
UUID uuid = event.getEntity().getUniqueId();
tracking.remove(uuid);
untracked.removeAll(uuid);
}

public LivingEntity getOrigCaster() {
return origCaster;

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onDamage(EntityDamageByEntityEvent event) {
UUID uuid = event.getEntity().getUniqueId();
tracking.remove(uuid);
untracked.removeAll(uuid);
}

public boolean isHitEntity() {
return hitEntity;

public boolean isTracking(Arrow arrow, MissArrowListener instance) {
UUID uuid = arrow.getUniqueId();
return tracking.contains(uuid) && !untracked.containsEntry(uuid, instance);
}
public void setHitEntity(boolean hitEntity) {
this.hitEntity = hitEntity;

public void removeTracking(Arrow arrow, MissArrowListener instance) {
untracked.put(arrow.getUniqueId(), instance);
}

}
Expand Down