From 2bc825d3a393bab05657ccc6c335a57c063ff094 Mon Sep 17 00:00:00 2001 From: tastybento Date: Tue, 25 Apr 2023 17:45:48 -0700 Subject: [PATCH 1/5] WIP uses arrows; doesn't work --- .../bentobox/managers/IslandsManager.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java index ce585a6cb..b74b62730 100644 --- a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java @@ -20,19 +20,25 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.entity.AbstractArrow.PickupStatus; +import org.bukkit.entity.Arrow; import org.bukkit.entity.Boat; import org.bukkit.entity.Boat.Type; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.PufferFish; +import org.bukkit.entity.Zombie; import org.bukkit.inventory.ItemStack; import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.potion.PotionData; +import org.bukkit.potion.PotionType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import org.eclipse.jdt.annotation.NonNull; @@ -1642,7 +1648,26 @@ public void clearArea(Location loc) { && !(en instanceof PufferFish) && ((LivingEntity)en).getRemoveWhenFarAway()) .filter(en -> en.getCustomName() == null) - .forEach(Entity::remove); + .forEach(e -> fireArrowOfPower(e, loc)); + } + + private void fireArrowOfPower(Entity e, Location loc) { + Vector direction = e.getLocation().toVector().subtract(loc.toVector()).normalize(); + if (e instanceof Zombie z) { + plugin.logDebug("Health = " + z.getHealth() + " direction " + direction); + } + + Arrow arrow = loc.getWorld().spawnArrow(loc, direction, 0.7F, 0); + arrow.setDamage(0); + arrow.setPierceLevel(0); + PotionData pd = new PotionData(PotionType.INSTANT_HEAL, false, false); + arrow.setBasePotionData(pd); + arrow.setCritical(false); + arrow.setKnockbackStrength(50); + Color color = Color.AQUA; + //color.setAlpha(0); + arrow.setColor(color); + arrow.setPickupStatus(PickupStatus.DISALLOWED); } /** From 361a61da5dda7775dd87880876a313057ecfb529 Mon Sep 17 00:00:00 2001 From: tastybento Date: Tue, 25 Apr 2023 19:03:27 -0700 Subject: [PATCH 2/5] Flings hostile mobs away from player on teleport. --- .../world/bentobox/bentobox/Settings.java | 36 ++++++++++++++ .../bentobox/managers/IslandsManager.java | 47 ++++++++++--------- src/main/resources/config.yml | 8 +++- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/Settings.java b/src/main/java/world/bentobox/bentobox/Settings.java index 384447caf..4c0675a98 100644 --- a/src/main/java/world/bentobox/bentobox/Settings.java +++ b/src/main/java/world/bentobox/bentobox/Settings.java @@ -147,6 +147,14 @@ public class Settings implements ConfigObject { @ConfigComment("Add other fake player names here if required") @ConfigEntry(path = "general.fakeplayers", experimental = true) private Set fakePlayers = new HashSet<>(); + + @ConfigComment("Flingback power. How far hostile mobs will be flung back when a player teleports into them.") + @ConfigEntry(path = "general.flingback") + private double flingback = 5D; + + @ConfigComment("Kill mobs on teleport. If thw world flag is set, then they will be killed/removed instead of flung.") + @ConfigEntry(path = "general.teleport-remove-mobs") + private boolean teleportRemoveMobs = false; /* PANELS */ @@ -1038,4 +1046,32 @@ public void setSafeSpotSearchRange(int safeSpotSearchRange) { this.safeSpotSearchRange = safeSpotSearchRange; } + + /** + * @return the flingback + */ + public double getFlingback() { + return flingback; + } + + /** + * @param flingback the flingback to set + */ + public void setFlingback(double flingback) { + this.flingback = flingback; + } + + /** + * @return the teleportRemoveMobs + */ + public boolean isTeleportRemoveMobs() { + return teleportRemoveMobs; + } + + /** + * @param teleportRemoveMobs the teleportRemoveMobs to set + */ + public void setTeleportRemoveMobs(boolean teleportRemoveMobs) { + this.teleportRemoveMobs = teleportRemoveMobs; + } } diff --git a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java index b74b62730..2d3a62bcb 100644 --- a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java @@ -13,6 +13,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Queue; +import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -20,25 +21,20 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.entity.AbstractArrow.PickupStatus; -import org.bukkit.entity.Arrow; import org.bukkit.entity.Boat; import org.bukkit.entity.Boat.Type; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.PufferFish; -import org.bukkit.entity.Zombie; import org.bukkit.inventory.ItemStack; import org.bukkit.permissions.PermissionAttachmentInfo; -import org.bukkit.potion.PotionData; -import org.bukkit.potion.PotionType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import org.eclipse.jdt.annotation.NonNull; @@ -72,6 +68,7 @@ public class IslandsManager { private final BentoBox plugin; + private final Random rand = new Random(); // Tree species to boat material map private static final Map TREE_TO_BOAT = ImmutableMap.builder(). @@ -1639,6 +1636,7 @@ public void setOwner(User user, UUID targetUUID, Island island) { */ public void clearArea(Location loc) { if (!plugin.getIWM().inWorld(loc)) return; + loc.getWorld().getNearbyEntities(loc, plugin.getSettings().getClearRadius(), plugin.getSettings().getClearRadius(), plugin.getSettings().getClearRadius()).stream() @@ -1648,26 +1646,29 @@ public void clearArea(Location loc) { && !(en instanceof PufferFish) && ((LivingEntity)en).getRemoveWhenFarAway()) .filter(en -> en.getCustomName() == null) - .forEach(e -> fireArrowOfPower(e, loc)); + .forEach(e -> flingOrKill(e, loc)); } - private void fireArrowOfPower(Entity e, Location loc) { - Vector direction = e.getLocation().toVector().subtract(loc.toVector()).normalize(); - if (e instanceof Zombie z) { - plugin.logDebug("Health = " + z.getHealth() + " direction " + direction); + private void flingOrKill(Entity e, Location loc) { + if (plugin.getSettings().isTeleportRemoveMobs()) { + e.remove(); + return; } - - Arrow arrow = loc.getWorld().spawnArrow(loc, direction, 0.7F, 0); - arrow.setDamage(0); - arrow.setPierceLevel(0); - PotionData pd = new PotionData(PotionType.INSTANT_HEAL, false, false); - arrow.setBasePotionData(pd); - arrow.setCritical(false); - arrow.setKnockbackStrength(50); - Color color = Color.AQUA; - //color.setAlpha(0); - arrow.setColor(color); - arrow.setPickupStatus(PickupStatus.DISALLOWED); + Vector entVec = e.getLocation().toVector(); + double dist = plugin.getSettings().getFlingback() - entVec.distance(loc.toVector()); + if (dist < 1) { + dist = 1; + } + Vector direction = entVec.subtract(loc.toVector()); + if (direction.lengthSquared() < 3) { + // On top of us + direction.add(new Vector(rand.nextDouble(), 0, rand.nextDouble())); + } + // Add a bit of lift + direction.add(new Vector(0, rand.nextDouble(), 0)); + direction.multiply(dist); + loc.getWorld().playSound(e, Sound.ENTITY_ILLUSIONER_HURT, 1F, 5F); + e.setVelocity(direction); } /** diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 2911d5a8a..86bb109cc 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -82,8 +82,8 @@ general: prefix-character: '' # Custom connection datasource properties that will be applied to connection pool. # Check available values to your SQL driver implementation. - # Example: ") - # custom-properties: + # Example: + # custom-properties: # cachePrepStmts: 'true' # prepStmtCacheSize: '250' # prepStmtCacheSqlLimit: '2048' @@ -98,6 +98,10 @@ general: # /!\ This feature is experimental and might not work as expected or might not work at all. fakeplayers: - '[CoFH]' + # Flingback power. How far hostile mobs will be flung back when a player teleports into them. + flingback: 5.0 + # Remove mobs on teleport. + teleport-remove-mobs: false panel: # Toggle whether panels should be closed or not when the player clicks anywhere outside of the inventory view. close-on-click-outside: true From 255bd9abaa6a75a299e4989e4433d09bcd990a14 Mon Sep 17 00:00:00 2001 From: tastybento Date: Wed, 26 Apr 2023 15:54:37 -0700 Subject: [PATCH 3/5] Fix tests --- .../bentobox/managers/IslandsManagerTest.java | 52 ++++++++++++++++--- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java index 169551906..f266d9b4e 100644 --- a/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java @@ -6,6 +6,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyDouble; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -33,6 +34,7 @@ import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -51,6 +53,7 @@ import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.plugin.PluginManager; import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.util.Vector; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -76,7 +79,6 @@ import world.bentobox.bentobox.api.events.island.IslandDeleteEvent; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.Database; -import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.managers.island.IslandCache; @@ -140,6 +142,7 @@ public class IslandsManagerTest { // Class under test IslandsManager im; + private Settings s; /** */ @@ -163,9 +166,9 @@ public void setUp() throws Exception { when(plugin.getIslandChunkDeletionManager()).thenReturn(chunkDeletionManager); // Settings - Settings s = mock(Settings.class); + s = new Settings(); when(plugin.getSettings()).thenReturn(s); - when(s.getDatabaseType()).thenReturn(DatabaseType.JSON); + //when(s.getDatabaseType()).thenReturn(DatabaseType.JSON); // World when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); @@ -181,6 +184,7 @@ public void setUp() throws Exception { User.setPlugin(plugin); // Set up user already when(player.getUniqueId()).thenReturn(uuid); + when(player.getLocation()).thenReturn(location); User.getInstance(player); // Locales @@ -210,6 +214,8 @@ public void setUp() throws Exception { when(location.clone()).thenReturn(location); Chunk chunk = mock(Chunk.class); when(location.getChunk()).thenReturn(chunk); + // Vector + when(location.toVector()).thenReturn(new Vector(100D, 120D, 100D)); when(space1.getRelative(BlockFace.DOWN)).thenReturn(ground); when(space1.getRelative(BlockFace.UP)).thenReturn(space2); // A safe spot @@ -276,7 +282,6 @@ public void setUp() throws Exception { when(iwm.getRemoveMobsWhitelist(any())).thenReturn(whitelist); - // Monsters and animals when(zombie.getLocation()).thenReturn(location); when(zombie.getType()).thenReturn(EntityType.ZOMBIE); @@ -288,13 +293,17 @@ public void setUp() throws Exception { when(cow.getType()).thenReturn(EntityType.COW); when(wither.getType()).thenReturn(EntityType.WITHER); when(wither.getRemoveWhenFarAway()).thenReturn(true); + when(wither.getLocation()).thenReturn(location); when(creeper.getType()).thenReturn(EntityType.CREEPER); when(creeper.getRemoveWhenFarAway()).thenReturn(true); + when(creeper.getLocation()).thenReturn(location); when(pufferfish.getType()).thenReturn(EntityType.PUFFERFISH); + when(pufferfish.getLocation()).thenReturn(location); // Named monster when(skelly.getType()).thenReturn(EntityType.SKELETON); when(skelly.getCustomName()).thenReturn("Skelly"); when(skelly.getRemoveWhenFarAway()).thenReturn(true); + when(skelly.getLocation()).thenReturn(location); Collection collection = new ArrayList<>(); collection.add(player); @@ -305,9 +314,7 @@ public void setUp() throws Exception { collection.add(creeper); collection.add(pufferfish); collection.add(skelly); - when(world - .getNearbyEntities(any(Location.class), Mockito.anyDouble(), Mockito.anyDouble(), Mockito.anyDouble())) - .thenReturn(collection); + when(world.getNearbyEntities(any(Location.class), anyDouble(), anyDouble(), anyDouble())).thenReturn(collection); @@ -1105,7 +1112,8 @@ public void testClearAreaWrongWorld() { * Test method for {@link world.bentobox.bentobox.managers.IslandsManager#clearArea(Location)}. */ @Test - public void testClearArea() { + public void testClearAreaRemove() { + s.setTeleportRemoveMobs(true); im.clearArea(location); // Only the correct entities should be cleared verify(zombie).remove(); @@ -1117,6 +1125,34 @@ public void testClearArea() { verify(pufferfish, never()).remove(); verify(skelly, never()).remove(); } + + /** + * Test method for {@link world.bentobox.bentobox.managers.IslandsManager#clearArea(Location)}. + */ + @Test + public void testClearArea() { + im.clearArea(location); + // Only the correct entities should be cleared + verify(zombie, never()).remove(); + verify(player, never()).remove(); + verify(cow, never()).remove(); + verify(slime, never()).remove(); + verify(wither, never()).remove(); + verify(creeper, never()).remove(); + verify(pufferfish, never()).remove(); + verify(skelly, never()).remove(); + + verify(zombie).setVelocity(any(Vector.class)); + verify(slime).setVelocity(any(Vector.class)); + verify(creeper).setVelocity(any(Vector.class)); + verify(player, never()).setVelocity(any(Vector.class)); + verify(cow, never()).setVelocity(any(Vector.class)); + verify(wither, never()).setVelocity(any(Vector.class)); + verify(pufferfish, never()).setVelocity(any(Vector.class)); + verify(skelly, never()).setVelocity(any(Vector.class)); + + verify(world).playSound(zombie, Sound.ENTITY_ILLUSIONER_HURT, 1F, 5F); + } /** * Test method for {@link world.bentobox.bentobox.managers.IslandsManager#getIslandById(String)}. From e83a9fbbddc710b9077185c667ecec8ce6be5791 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 3 Jun 2023 16:40:59 -0700 Subject: [PATCH 4/5] Edited English and adjusted power of fling --- .../java/world/bentobox/bentobox/Settings.java | 15 ++++++++------- src/main/resources/locales/en-US.yml | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/Settings.java b/src/main/java/world/bentobox/bentobox/Settings.java index 4c0675a98..36b420627 100644 --- a/src/main/java/world/bentobox/bentobox/Settings.java +++ b/src/main/java/world/bentobox/bentobox/Settings.java @@ -147,14 +147,15 @@ public class Settings implements ConfigObject { @ConfigComment("Add other fake player names here if required") @ConfigEntry(path = "general.fakeplayers", experimental = true) private Set fakePlayers = new HashSet<>(); - + @ConfigComment("Flingback power. How far hostile mobs will be flung back when a player teleports into them.") + @ConfigComment("2.5 will push back a number of blocks, 5 will throw them far, 1 will not do much.") @ConfigEntry(path = "general.flingback") - private double flingback = 5D; - - @ConfigComment("Kill mobs on teleport. If thw world flag is set, then they will be killed/removed instead of flung.") + private double flingback = 2.5D; + + @ConfigComment("Kill mobs on teleport. If the world flag in Admin Settings is set, then they will be killed/removed instead of flung.") @ConfigEntry(path = "general.teleport-remove-mobs") - private boolean teleportRemoveMobs = false; + private boolean teleportRemoveMobs = false; /* PANELS */ @@ -991,8 +992,8 @@ public int getMaximumPoolSize() { return maximumPoolSize; } - - + + /** * Gets safe spot search range. * diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 122dc307b..af008b0ef 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -1292,9 +1292,9 @@ protection: name: "Remove end exit island" REMOVE_MOBS: description: |- - &a Remove monsters when + &a Push monsters away when &a teleporting to island - name: "Remove monsters" + name: "Fling back monsters" RIDING: description: "Toggle riding" name: "Animal riding" From 4d93856885129df480109b521f4b5ed2e0443ad1 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 3 Jun 2023 16:41:08 -0700 Subject: [PATCH 5/5] Fixed test --- .../bentobox/listeners/PanelListenerManagerTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java b/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java index b5448eca5..9e1403d60 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java @@ -171,6 +171,17 @@ public String getTitle() { return name; } + @Override + public String getOriginalTitle() { + return ""; + } + + @Override + public void setTitle(String title) { + // TODO Auto-generated method stub + + } + } @After