Skip to content

Commit 1b0b439

Browse files
Properly track arrow misses
1 parent f163984 commit 1b0b439

File tree

1 file changed

+65
-79
lines changed

1 file changed

+65
-79
lines changed

core/src/main/java/com/nisovin/magicspells/spells/passive/MissArrowListener.java

Lines changed: 65 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package com.nisovin.magicspells.spells.passive;
22

3+
import org.jetbrains.annotations.NotNull;
4+
35
import java.util.Set;
46
import java.util.UUID;
57
import java.util.HashSet;
68

7-
import org.jetbrains.annotations.NotNull;
9+
import com.google.common.collect.Multimap;
10+
import com.google.common.collect.HashMultimap;
811

912
import org.bukkit.entity.Arrow;
10-
import org.bukkit.entity.Entity;
11-
import org.bukkit.entity.Projectile;
13+
import org.bukkit.event.Listener;
1214
import org.bukkit.event.EventHandler;
1315
import org.bukkit.entity.LivingEntity;
16+
import org.bukkit.event.EventPriority;
1417
import org.bukkit.inventory.ItemStack;
15-
import org.bukkit.metadata.FixedMetadataValue;
18+
import org.bukkit.event.entity.EntityRemoveEvent;
1619
import org.bukkit.event.entity.ProjectileHitEvent;
1720
import org.bukkit.event.entity.ProjectileLaunchEvent;
1821
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@@ -28,11 +31,19 @@
2831
@Name("missarrow")
2932
public class MissArrowListener extends PassiveListener {
3033

34+
private static ArrowTracker tracker;
35+
3136
private final Set<MagicItemData> items = new HashSet<>();
32-
37+
3338
@Override
3439
public void initialize(@NotNull String var) {
40+
if (tracker == null) {
41+
tracker = new ArrowTracker();
42+
MagicSpells.registerEvents(tracker);
43+
}
44+
3545
if (var.isEmpty()) return;
46+
3647
for (String s : var.split(MagicItemDataParser.DATA_REGEX)) {
3748
s = s.trim();
3849

@@ -45,99 +56,74 @@ public void initialize(@NotNull String var) {
4556
items.add(itemData);
4657
}
4758
}
48-
49-
@OverridePriority
50-
@EventHandler
51-
public void onHitEntity(EntityDamageByEntityEvent event) {
52-
LivingEntity attacker = getAttacker(event);
53-
if (attacker == null) return;
54-
String name = attacker.getName();
55-
UUID id = attacker.getUniqueId();
56-
if (event.getDamager() instanceof Arrow && event.getDamager().hasMetadata("mal-" + id + '-' + name)
57-
&& !event.getEntity().getMetadata("mal-" + id + '-' + name).isEmpty()) {
58-
((ArrowParticle) event.getDamager().getMetadata("mal-" + id + '-' + name).get(0).value()).setHitEntity(true);
59-
}
59+
60+
@Override
61+
public void turnOff() {
62+
tracker = null;
6063
}
61-
64+
6265
@OverridePriority
6366
@EventHandler
64-
public void onDamage(ProjectileHitEvent event) {
65-
if (!(event.getEntity() instanceof Arrow arrow)) return;
66-
67-
LivingEntity caster = getAttacker(event);
68-
if (caster == null || !canTrigger(caster)) return;
67+
public void onHit(ProjectileHitEvent event) {
68+
if (event.getHitBlock() == null) return;
69+
if (!(event.getEntity() instanceof Arrow arrow) || !tracker.isTracking(arrow, this)) return;
70+
if (!(arrow.getShooter() instanceof LivingEntity caster) || !canTrigger(caster)) return;
6971

70-
String name = caster.getName();
71-
UUID id = caster.getUniqueId();
72-
73-
if (!event.getEntity().hasMetadata("mal-" + id + '-' + name)) return;
74-
if (event.getEntity().getMetadata("mal-" + id + '-' + name).isEmpty()) return;
75-
76-
ArrowParticle arrowParticle = (ArrowParticle) event.getEntity().getMetadata("mal-" + id + '-' + name).get(0).value();
77-
if (arrowParticle.isHitEntity()) return;
72+
tracker.removeTracking(arrow, this);
7873

7974
if (!items.isEmpty()) {
80-
ItemStack item = arrow.getWeapon();
81-
if (item == null) return;
75+
ItemStack weapon = arrow.getWeapon();
76+
if (weapon == null) return;
8277

83-
MagicItemData itemData = MagicItems.getMagicItemDataFromItemStack(item);
84-
if (!contains(itemData)) return;
78+
MagicItemData itemData = MagicItems.getMagicItemDataFromItemStack(weapon);
79+
if (itemData == null || !contains(itemData)) return;
8580
}
8681

87-
passiveSpell.activate(caster, event.getEntity().getLocation());
82+
passiveSpell.activate(caster, arrow.getLocation());
8883
}
8984

9085
private boolean contains(MagicItemData itemData) {
91-
for (MagicItemData data : items) {
92-
if (data.matches(itemData)) return true;
93-
}
86+
for (MagicItemData data : items)
87+
if (data.matches(itemData))
88+
return true;
89+
9490
return false;
9591
}
96-
97-
private LivingEntity getAttacker(ProjectileHitEvent event) {
98-
Projectile e = event.getEntity();
99-
if (!(e instanceof Arrow)) return null;
100-
if (e.getShooter() != null && e.getShooter() instanceof LivingEntity) {
101-
return (LivingEntity) e.getShooter();
102-
}
103-
return null;
104-
}
10592

106-
private LivingEntity getAttacker(EntityDamageByEntityEvent event) {
107-
Entity e = event.getDamager();
108-
if (!(e instanceof Arrow)) return null;
109-
if (((Arrow) e).getShooter() != null && ((Arrow) e).getShooter() instanceof LivingEntity) {
110-
return (LivingEntity) ((Arrow) e).getShooter();
93+
private static class ArrowTracker implements Listener {
94+
95+
private final Multimap<UUID, MissArrowListener> untracked = HashMultimap.create();
96+
private final Set<UUID> tracking = new HashSet<>();
97+
98+
@EventHandler
99+
public void onShoot(ProjectileLaunchEvent event) {
100+
if (!(event.getEntity() instanceof Arrow arrow)) return;
101+
if (!(arrow.getShooter() instanceof LivingEntity)) return;
102+
103+
tracking.add(arrow.getUniqueId());
111104
}
112-
return null;
113-
}
114-
115-
@EventHandler
116-
public void shoot(ProjectileLaunchEvent event) {
117-
if (event.getEntity().getShooter() == null || !(event.getEntity().getShooter() instanceof LivingEntity p) || !(event.getEntity() instanceof Arrow)) return;
118-
ArrowParticle arrowParticle = new ArrowParticle(p);
119-
event.getEntity().setMetadata("mal-" + p.getUniqueId() + '-' + p.getName(), new FixedMetadataValue(MagicSpells.getInstance(), arrowParticle));
120-
}
121-
122-
private static class ArrowParticle {
123-
124-
private LivingEntity origCaster;
125-
private boolean hitEntity;
126-
127-
private ArrowParticle(LivingEntity origCaster) {
128-
this.origCaster = origCaster;
105+
106+
@EventHandler
107+
public void onRemove(EntityRemoveEvent event) {
108+
UUID uuid = event.getEntity().getUniqueId();
109+
tracking.remove(uuid);
110+
untracked.removeAll(uuid);
129111
}
130-
131-
public LivingEntity getOrigCaster() {
132-
return origCaster;
112+
113+
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
114+
public void onDamage(EntityDamageByEntityEvent event) {
115+
UUID uuid = event.getEntity().getUniqueId();
116+
tracking.remove(uuid);
117+
untracked.removeAll(uuid);
133118
}
134-
135-
public boolean isHitEntity() {
136-
return hitEntity;
119+
120+
public boolean isTracking(Arrow arrow, MissArrowListener instance) {
121+
UUID uuid = arrow.getUniqueId();
122+
return tracking.contains(uuid) && !untracked.containsEntry(uuid, instance);
137123
}
138-
139-
public void setHitEntity(boolean hitEntity) {
140-
this.hitEntity = hitEntity;
124+
125+
public void removeTracking(Arrow arrow, MissArrowListener instance) {
126+
untracked.put(arrow.getUniqueId(), instance);
141127
}
142128

143129
}

0 commit comments

Comments
 (0)