mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-09-30 23:57:30 +02:00
Add protection for firework explosions from crossbows.
https://github.com/BentoBoxWorld/BentoBox/issues/1027
This commit is contained in:
parent
c9b0c74d08
commit
f67baf6501
@ -1,10 +1,14 @@
|
||||
package world.bentobox.bentobox.listeners.flags.protection;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Parrot;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -14,6 +18,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.entity.LingeringPotionSplashEvent;
|
||||
import org.bukkit.event.entity.PotionSplashEvent;
|
||||
import org.bukkit.event.player.PlayerFishEvent;
|
||||
@ -35,7 +40,8 @@ import world.bentobox.bentobox.versions.ServerCompatibility;
|
||||
*/
|
||||
public class HurtingListener extends FlagListener {
|
||||
|
||||
private HashMap<Integer, Player> thrownPotions = new HashMap<>();
|
||||
private Map<Integer, Player> thrownPotions = new HashMap<>();
|
||||
private Map<Entity, Entity> firedFireworks = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Handles mob and monster protection
|
||||
@ -173,6 +179,11 @@ public class HurtingListener extends FlagListener {
|
||||
public void onLingeringPotionDamage(final EntityDamageByEntityEvent e) {
|
||||
if (e.getCause().equals(DamageCause.ENTITY_ATTACK) && thrownPotions.containsKey(e.getDamager().getEntityId())) {
|
||||
Player attacker = thrownPotions.get(e.getDamager().getEntityId());
|
||||
processDamage(e, attacker);
|
||||
}
|
||||
}
|
||||
|
||||
private void processDamage(EntityDamageByEntityEvent e, Player attacker) {
|
||||
// Self damage
|
||||
if (attacker == null || attacker.equals(e.getEntity())) {
|
||||
return;
|
||||
@ -190,6 +201,21 @@ public class HurtingListener extends FlagListener {
|
||||
if (entity instanceof Villager) {
|
||||
checkIsland(e, attacker, entity.getLocation(), Flags.HURT_VILLAGERS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
|
||||
public void onFireworkDamage(final EntityDamageByEntityEvent e) {
|
||||
if (e.getDamager() instanceof Firework && firedFireworks.containsKey(e.getDamager())) {
|
||||
processDamage(e, (Player)firedFireworks.get(e.getDamager()));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
|
||||
public void onPlayerShootEvent(final EntityShootBowEvent e) {
|
||||
// Only care about players shooting fireworks
|
||||
if (e.getEntityType().equals(EntityType.PLAYER) && (e.getProjectile() instanceof Firework)) {
|
||||
firedFireworks.put(e.getProjectile(), e.getEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
package world.bentobox.bentobox.listeners.flags.settings;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
@ -16,6 +19,7 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.AreaEffectCloudApplyEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.entity.LingeringPotionSplashEvent;
|
||||
import org.bukkit.event.entity.PotionSplashEvent;
|
||||
import org.bukkit.event.player.PlayerFishEvent;
|
||||
@ -32,7 +36,8 @@ import world.bentobox.bentobox.lists.Flags;
|
||||
*/
|
||||
public class PVPListener extends FlagListener {
|
||||
|
||||
private HashMap<Integer, UUID> thrownPotions = new HashMap<>();
|
||||
private Map<Integer, UUID> thrownPotions = new HashMap<>();
|
||||
private Map<Entity, Player> firedFireworks = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* This method protects players from PVP if it is not allowed and from
|
||||
@ -79,21 +84,29 @@ public class PVPListener extends FlagListener {
|
||||
} else if (damager instanceof Projectile) {
|
||||
// Find out who fired the arrow
|
||||
Projectile p = (Projectile) damager;
|
||||
Entity entity =(Entity)p.getShooter();
|
||||
if (entity instanceof Player) {
|
||||
Entity shooter =(Entity)p.getShooter();
|
||||
if (shooter instanceof Player) {
|
||||
processDamage(e, damager, (Player)shooter, hurtEntity, flag);
|
||||
}
|
||||
} else if (damager instanceof Firework && firedFireworks.containsKey(damager)) {
|
||||
Player shooter = firedFireworks.get(damager);
|
||||
processDamage(e, damager, shooter, hurtEntity, flag);
|
||||
}
|
||||
}
|
||||
|
||||
private void processDamage(Cancellable e, Entity damager, Player shooter, Entity hurtEntity, Flag flag) {
|
||||
// Allow self damage
|
||||
if (hurtEntity.equals(entity)) {
|
||||
if (hurtEntity.equals(shooter)) {
|
||||
return;
|
||||
}
|
||||
User user = User.getInstance((Player)p.getShooter());
|
||||
if (!checkIsland((Event)e, (Player)entity, damager.getLocation(), flag)) {
|
||||
User user = User.getInstance(shooter);
|
||||
if (!checkIsland((Event)e, shooter, damager.getLocation(), flag)) {
|
||||
damager.setFireTicks(0);
|
||||
hurtEntity.setFireTicks(0);
|
||||
user.notify(Flags.PVP_OVERWORLD.getHintReference());
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
@ -191,4 +204,11 @@ public class PVPListener extends FlagListener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled=true)
|
||||
public void onPlayerShootFireworkEvent(final EntityShootBowEvent e) {
|
||||
// Only care about players shooting fireworks
|
||||
if (e.getEntity() instanceof Player && (e.getProjectile() instanceof Firework)) {
|
||||
firedFireworks.put(e.getProjectile(), (Player)e.getEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.listeners.flags.protection;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
@ -3,13 +3,13 @@ package world.bentobox.bentobox.listeners.flags.settings;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -22,10 +22,14 @@ import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.AreaEffectCloud;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.FishHook;
|
||||
import org.bukkit.entity.LingeringPotion;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
@ -37,7 +41,9 @@ import org.bukkit.entity.Zombie;
|
||||
import org.bukkit.event.entity.AreaEffectCloudApplyEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
|
||||
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.entity.LingeringPotionSplashEvent;
|
||||
import org.bukkit.event.entity.PotionSplashEvent;
|
||||
import org.bukkit.event.player.PlayerFishEvent;
|
||||
@ -49,6 +55,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
@ -87,15 +94,25 @@ import world.bentobox.bentobox.util.Util;
|
||||
@PrepareForTest({BentoBox.class, Util.class, Bukkit.class })
|
||||
public class PVPListenerTest {
|
||||
|
||||
@Mock
|
||||
private IslandWorldManager iwm;
|
||||
@Mock
|
||||
private IslandsManager im;
|
||||
@Mock
|
||||
private Island island;
|
||||
@Mock
|
||||
private Player player;
|
||||
@Mock
|
||||
private Player player2;
|
||||
@Mock
|
||||
private Location loc;
|
||||
@Mock
|
||||
private Zombie zombie;
|
||||
@Mock
|
||||
private Creeper creeper;
|
||||
@Mock
|
||||
private World world;
|
||||
@Mock
|
||||
private Notifier notifier;
|
||||
|
||||
/**
|
||||
@ -109,7 +126,6 @@ public class PVPListenerTest {
|
||||
// Make sure you set the plung for the User class otherwise it'll use an old object
|
||||
User.setPlugin(plugin);
|
||||
// Island World Manager
|
||||
iwm = mock(IslandWorldManager.class);
|
||||
when(iwm.inWorld(any(World.class))).thenReturn(true);
|
||||
when(iwm.inWorld(any(Location.class))).thenReturn(true);
|
||||
when(iwm.getPermissionPrefix(Mockito.any())).thenReturn("bskyblock.");
|
||||
@ -120,23 +136,23 @@ public class PVPListenerTest {
|
||||
Panel panel = mock(Panel.class);
|
||||
when(panel.getInventory()).thenReturn(mock(Inventory.class));
|
||||
|
||||
// Sometimes use Mockito.withSettings().verboseLogging()
|
||||
player = mock(Player.class);
|
||||
UUID uuid = UUID.randomUUID();
|
||||
when(player.getUniqueId()).thenReturn(uuid);
|
||||
|
||||
world = mock(World.class);
|
||||
// World
|
||||
when(world.getEnvironment()).thenReturn(World.Environment.NORMAL);
|
||||
when(player.getWorld()).thenReturn(world);
|
||||
|
||||
loc = mock(Location.class);
|
||||
// Location
|
||||
when(loc.getWorld()).thenReturn(world);
|
||||
|
||||
// Sometimes use Mockito.withSettings().verboseLogging()
|
||||
// Player
|
||||
UUID uuid = UUID.randomUUID();
|
||||
when(player.getUniqueId()).thenReturn(uuid);
|
||||
when(player.getLocation()).thenReturn(loc);
|
||||
when(player.getWorld()).thenReturn(world);
|
||||
User.getInstance(player);
|
||||
|
||||
// Sometimes use Mockito.withSettings().verboseLogging()
|
||||
player2 = mock(Player.class);
|
||||
// Player 2
|
||||
UUID uuid2 = UUID.randomUUID();
|
||||
when(player2.getUniqueId()).thenReturn(uuid2);
|
||||
|
||||
@ -144,9 +160,11 @@ public class PVPListenerTest {
|
||||
when(player2.getLocation()).thenReturn(loc);
|
||||
User.getInstance(player2);
|
||||
|
||||
// Util
|
||||
PowerMockito.mockStatic(Util.class);
|
||||
when(Util.getWorld(any())).thenReturn(mock(World.class));
|
||||
|
||||
// Flags Manager
|
||||
FlagsManager fm = mock(FlagsManager.class);
|
||||
Flag flag = mock(Flag.class);
|
||||
when(flag.isSetForWorld(any())).thenReturn(false);
|
||||
@ -156,7 +174,7 @@ public class PVPListenerTest {
|
||||
when(fm.getFlag(Mockito.anyString())).thenReturn(Optional.of(flag));
|
||||
when(plugin.getFlagsManager()).thenReturn(fm);
|
||||
|
||||
im = mock(IslandsManager.class);
|
||||
// Island Manager
|
||||
// Default is that player in on their island
|
||||
when(im.userIsOnIsland(any(), any())).thenReturn(true);
|
||||
island = mock(Island.class);
|
||||
@ -182,12 +200,12 @@ public class PVPListenerTest {
|
||||
when(placeholdersManager.replacePlaceholders(any(), any())).thenAnswer(answer);
|
||||
|
||||
// Create some entities
|
||||
zombie = mock(Zombie.class);
|
||||
when(zombie.getWorld()).thenReturn(world);
|
||||
when(zombie.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||
creeper = mock(Creeper.class);
|
||||
when(zombie.getType()).thenReturn(EntityType.ZOMBIE);
|
||||
when(creeper.getWorld()).thenReturn(world);
|
||||
when(creeper.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||
when(creeper.getType()).thenReturn(EntityType.CREEPER);
|
||||
|
||||
// Scheduler
|
||||
BukkitScheduler sch = mock(BukkitScheduler.class);
|
||||
@ -204,7 +222,6 @@ public class PVPListenerTest {
|
||||
when(iwm.getAddon(any())).thenReturn(opGma);
|
||||
|
||||
// Notifier
|
||||
notifier = mock(Notifier.class);
|
||||
when(plugin.getNotifier()).thenReturn(notifier);
|
||||
|
||||
// Addon
|
||||
@ -1000,4 +1017,102 @@ public class PVPListenerTest {
|
||||
assertFalse(ae.getAffectedEntities().contains(player2));
|
||||
verify(notifier).notify(any(), eq(Flags.INVINCIBLE_VISITORS.getHintReference()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link PVPListener#onPlayerShootFireworkEvent(org.bukkit.event.entity.EntityShootBowEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnPlayerShootFireworkEventNotPlayer() {
|
||||
PVPListener listener = new PVPListener();
|
||||
ItemStack bow = new ItemStack(Material.CROSSBOW);
|
||||
Firework firework = mock(Firework.class);
|
||||
when(firework.getEntityId()).thenReturn(123);
|
||||
EntityShootBowEvent e = new EntityShootBowEvent(creeper, bow, firework, 0);
|
||||
listener.onPlayerShootFireworkEvent(e);
|
||||
|
||||
// Now damage
|
||||
EntityDamageByEntityEvent en = new EntityDamageByEntityEvent(firework, player, DamageCause.ENTITY_ATTACK, 0);
|
||||
listener.onEntityDamage(en);
|
||||
assertFalse(en.isCancelled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link PVPListener#onPlayerShootFireworkEvent(org.bukkit.event.entity.EntityShootBowEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnPlayerShootFireworkEventNotFirework() {
|
||||
PVPListener listener = new PVPListener();
|
||||
ItemStack bow = new ItemStack(Material.CROSSBOW);
|
||||
Arrow arrow = mock(Arrow.class);
|
||||
EntityShootBowEvent e = new EntityShootBowEvent(creeper, bow, arrow, 0);
|
||||
listener.onPlayerShootFireworkEvent(e);
|
||||
// Now damage
|
||||
EntityDamageByEntityEvent en = new EntityDamageByEntityEvent(arrow, player, DamageCause.ENTITY_ATTACK, 0);
|
||||
listener.onEntityDamage(en);
|
||||
assertFalse(en.isCancelled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link PVPListener#onPlayerShootFireworkEvent(org.bukkit.event.entity.EntityShootBowEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnPlayerShootFireworkEventNoPVPSelfDamage() {
|
||||
// Disallow PVP
|
||||
when(island.isAllowed(any())).thenReturn(false);
|
||||
PVPListener listener = new PVPListener();
|
||||
ItemStack bow = new ItemStack(Material.CROSSBOW);
|
||||
Firework firework = mock(Firework.class);
|
||||
when(firework.getEntityId()).thenReturn(123);
|
||||
when(firework.getLocation()).thenReturn(loc);
|
||||
EntityShootBowEvent e = new EntityShootBowEvent(player, bow, firework, 0);
|
||||
listener.onPlayerShootFireworkEvent(e);
|
||||
|
||||
// Now damage
|
||||
EntityDamageByEntityEvent en = new EntityDamageByEntityEvent(firework, player, DamageCause.ENTITY_EXPLOSION, 0);
|
||||
listener.onEntityDamage(en);
|
||||
assertFalse(en.isCancelled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link PVPListener#onPlayerShootFireworkEvent(org.bukkit.event.entity.EntityShootBowEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnPlayerShootFireworkEventNoPVP() {
|
||||
// Disallow PVP
|
||||
when(island.isAllowed(any())).thenReturn(false);
|
||||
PVPListener listener = new PVPListener();
|
||||
ItemStack bow = new ItemStack(Material.CROSSBOW);
|
||||
Firework firework = mock(Firework.class);
|
||||
when(firework.getEntityId()).thenReturn(123);
|
||||
when(firework.getLocation()).thenReturn(loc);
|
||||
EntityShootBowEvent e = new EntityShootBowEvent(player, bow, firework, 0);
|
||||
listener.onPlayerShootFireworkEvent(e);
|
||||
|
||||
// Now damage
|
||||
EntityDamageByEntityEvent en = new EntityDamageByEntityEvent(firework, player2, DamageCause.ENTITY_EXPLOSION, 0);
|
||||
listener.onEntityDamage(en);
|
||||
assertTrue(en.isCancelled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link PVPListener#onPlayerShootFireworkEvent(org.bukkit.event.entity.EntityShootBowEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnPlayerShootFireworkEventPVPAllowed() {
|
||||
// Allow PVP
|
||||
when(island.isAllowed(any())).thenReturn(true);
|
||||
PVPListener listener = new PVPListener();
|
||||
ItemStack bow = new ItemStack(Material.CROSSBOW);
|
||||
Firework firework = mock(Firework.class);
|
||||
when(firework.getEntityId()).thenReturn(123);
|
||||
when(firework.getLocation()).thenReturn(loc);
|
||||
EntityShootBowEvent e = new EntityShootBowEvent(player, bow, firework, 0);
|
||||
listener.onPlayerShootFireworkEvent(e);
|
||||
|
||||
// Now damage
|
||||
EntityDamageByEntityEvent en = new EntityDamageByEntityEvent(firework, player2, DamageCause.ENTITY_EXPLOSION, 0);
|
||||
listener.onEntityDamage(en);
|
||||
assertFalse(en.isCancelled());
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user