11package com .nisovin .magicspells .spells .passive ;
22
3+ import org .jetbrains .annotations .NotNull ;
4+
35import java .util .Set ;
46import java .util .UUID ;
57import 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
912import org .bukkit .entity .Arrow ;
10- import org .bukkit .entity .Entity ;
11- import org .bukkit .entity .Projectile ;
13+ import org .bukkit .event .Listener ;
1214import org .bukkit .event .EventHandler ;
1315import org .bukkit .entity .LivingEntity ;
16+ import org .bukkit .event .EventPriority ;
1417import org .bukkit .inventory .ItemStack ;
15- import org .bukkit .metadata . FixedMetadataValue ;
18+ import org .bukkit .event . entity . EntityRemoveEvent ;
1619import org .bukkit .event .entity .ProjectileHitEvent ;
1720import org .bukkit .event .entity .ProjectileLaunchEvent ;
1821import org .bukkit .event .entity .EntityDamageByEntityEvent ;
2831@ Name ("missarrow" )
2932public 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