diff --git a/pom.xml b/pom.xml
index 04c7c0c..1b7e25d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,12 +46,12 @@
5.10.2
5.11.0
- 1.21.10-R0.1-SNAPSHOT
+ 1.21.11-R0.1-SNAPSHOT
3.10.0
${build.version}-SNAPSHOT
- 4.6.0
+ 4.7.0
-LOCAL
BentoBoxWorld_Border
@@ -210,6 +210,11 @@
3.14.1
${java.version}
+ true
+
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+
diff --git a/src/main/java/world/bentobox/border/Border.java b/src/main/java/world/bentobox/border/Border.java
index 78d7d65..7c0e7d5 100644
--- a/src/main/java/world/bentobox/border/Border.java
+++ b/src/main/java/world/bentobox/border/Border.java
@@ -19,7 +19,7 @@
import world.bentobox.border.listeners.BorderShower;
import world.bentobox.border.listeners.PlayerListener;
import world.bentobox.border.listeners.ShowBarrier;
-import world.bentobox.border.listeners.ShowVirtualWorldBorder;
+import world.bentobox.border.listeners.ShowWorldBorder;
public class Border extends Addon {
@@ -71,7 +71,7 @@ public void onDisable() {
private BorderShower createBorder() {
BorderShower customBorder = new ShowBarrier(this);
- BorderShower wbapiBorder = new ShowVirtualWorldBorder(this);
+ BorderShower wbapiBorder = new ShowWorldBorder(this);
return new PerPlayerBorderProxy(this, customBorder, wbapiBorder);
}
@@ -131,4 +131,5 @@ private void registerPlaceholders()
orElse(getSettings().getType()).
getCommandLabel());
}
+
}
diff --git a/src/main/java/world/bentobox/border/PerPlayerBorderProxy.java b/src/main/java/world/bentobox/border/PerPlayerBorderProxy.java
index f5b2901..b53bfee 100644
--- a/src/main/java/world/bentobox/border/PerPlayerBorderProxy.java
+++ b/src/main/java/world/bentobox/border/PerPlayerBorderProxy.java
@@ -1,13 +1,15 @@
package world.bentobox.border;
+import java.util.Optional;
+
+import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
+
import world.bentobox.bentobox.api.metadata.MetaDataValue;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.border.listeners.BorderShower;
-import java.util.Optional;
-
public final class PerPlayerBorderProxy implements BorderShower {
public static final String BORDER_BORDERTYPE_META_DATA = "Border_bordertype";
@@ -76,11 +78,11 @@ private BorderType getDefaultBorderType() {
}
@Override
- public void teleportPlayer(Player player) {
+ public void teleportEntity(Border addon, Entity player) {
if (getBorderType(User.getInstance(player)) == BorderType.BARRIER) {
- customBorder.teleportPlayer(player);
+ customBorder.teleportEntity(addon, player);
} else {
- vanillaBorder.teleportPlayer(player);
+ vanillaBorder.teleportEntity(addon, player);
}
}
diff --git a/src/main/java/world/bentobox/border/Settings.java b/src/main/java/world/bentobox/border/Settings.java
index 5fd7ed8..c53a802 100644
--- a/src/main/java/world/bentobox/border/Settings.java
+++ b/src/main/java/world/bentobox/border/Settings.java
@@ -22,13 +22,28 @@ public class Settings implements ConfigObject {
private Set disabledGameModes = new HashSet<>();
@ConfigComment("")
- @ConfigComment("Border type. Options are VANILLA, which uses the vanillia-style board or BARRIER,")
+ @ConfigComment("Border type. Options are VANILLA, which uses the vanilla-style boarder or BARRIER,")
@ConfigComment("which uses particles and barrier blocks. If players have permission to use the barrier type")
@ConfigComment("they may override this option. If they do not have permission or lose the permission")
@ConfigComment("then this setting will be used.")
@ConfigEntry(path = "type")
private BorderType type = BorderType.VANILLA;
+ public enum BorderColor {
+ RED, GREEN, BLUE
+ }
+ @ConfigComment("")
+ @ConfigComment("Vanilla border color. Only applies if the border type is VANILLA.")
+ @ConfigComment("Selection is RED, GREEN, BLUE.")
+ @ConfigEntry(path = "color")
+ private BorderColor color = BorderColor.BLUE;
+
+ @ConfigComment("")
+ @ConfigComment("Bounce items back inside the border if they are thrown by a player.")
+ @ConfigComment("Without this, items can be thrown outside the border.")
+ @ConfigEntry(path = "bounce-back")
+ private boolean bounceBack = true;
+
@ConfigComment("")
@ConfigComment("Teleport players back inside the border if they somehow get outside.")
@ConfigComment("This will teleport players back inside if they toggle the border with a command.")
@@ -192,4 +207,32 @@ public boolean isReturnTeleportBlock() {
public void setReturnTeleportBlock(boolean returnTeleportBlock) {
this.returnTeleportBlock = returnTeleportBlock;
}
+
+ /**
+ * @return the bounceBack
+ */
+ public boolean isBounceBack() {
+ return bounceBack;
+ }
+
+ /**
+ * @param bounceBack the bounceBack to set
+ */
+ public void setBounceBack(boolean bounceBack) {
+ this.bounceBack = bounceBack;
+ }
+
+ /**
+ * @return the color
+ */
+ public BorderColor getColor() {
+ return color;
+ }
+
+ /* *
+ * @param color the color to set
+ */
+ public void setColor(BorderColor color) {
+ this.color = color;
+ }
}
diff --git a/src/main/java/world/bentobox/border/listeners/BorderShower.java b/src/main/java/world/bentobox/border/listeners/BorderShower.java
index e42d5da..6c25d47 100644
--- a/src/main/java/world/bentobox/border/listeners/BorderShower.java
+++ b/src/main/java/world/bentobox/border/listeners/BorderShower.java
@@ -1,9 +1,15 @@
package world.bentobox.border.listeners;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
+import org.bukkit.util.Vector;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
+import world.bentobox.bentobox.util.Util;
+import world.bentobox.border.Border;
/**
* A border shower class
@@ -44,9 +50,19 @@ public default void refreshView(User user, Island island){
}
/**
- * Teleports player back within the island space they are in
- * @param player player
+ * Teleports an entity, typically a player back within the island space they are in
+ * @param entity entity
*/
- public void teleportPlayer(Player player);
+ public default void teleportEntity(Border addon, Entity entity) {
+ addon.getIslands().getIslandAt(entity.getLocation()).ifPresent(i -> {
+ Vector unitVector = i.getCenter().toVector().subtract(entity.getLocation().toVector()).normalize()
+ .multiply(new Vector(1, 0, 1));
+ // Get distance from border
+ Location to = entity.getLocation().toVector().add(unitVector).toLocation(entity.getWorld());
+ to.setPitch(entity.getLocation().getPitch());
+ to.setYaw(entity.getLocation().getYaw());
+ Util.teleportAsync(entity, to, TeleportCause.PLUGIN);
+ });
+ }
}
diff --git a/src/main/java/world/bentobox/border/listeners/PlayerListener.java b/src/main/java/world/bentobox/border/listeners/PlayerListener.java
index ebcc91f..8b4f3d1 100644
--- a/src/main/java/world/bentobox/border/listeners/PlayerListener.java
+++ b/src/main/java/world/bentobox/border/listeners/PlayerListener.java
@@ -14,6 +14,7 @@
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
+import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -22,6 +23,8 @@
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDismountEvent;
import org.bukkit.event.entity.EntityMountEvent;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
@@ -29,16 +32,17 @@
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.event.vehicle.VehicleMoveEvent;
+import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.NumberConversions;
import org.bukkit.util.RayTraceResult;
import org.bukkit.util.Vector;
-import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.island.IslandProtectionRangeChangeEvent;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.metadata.MetaDataValue;
import world.bentobox.bentobox.api.user.User;
+import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;
import world.bentobox.border.Border;
import world.bentobox.border.BorderType;
@@ -111,7 +115,7 @@ public void onPlayerDamage(EntityDamageEvent e) {
}
Material type = p.getLocation().getBlock().getRelative(BlockFace.DOWN).getType();
if (type == Material.AIR) {
- ((BorderShower) show).teleportPlayer(p);
+ ((BorderShower) show).teleportEntity(addon, p);
e.setCancelled(true);
}
}
@@ -204,8 +208,13 @@ public void onPlayerLeaveIsland(PlayerMoveEvent e) {
Util.teleportAsync(p, from).thenRun(() -> inTeleport.remove(p.getUniqueId()));
return;
}
- // Backtrack
- addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> {
+ // Backtrack - try to find island at current location, or fall back to the player's own island
+ Optional optionalIsland = addon.getIslands().getIslandAt(p.getLocation());
+ if (optionalIsland.isEmpty()) {
+ optionalIsland = Optional
+ .ofNullable(addon.getIslands().getIsland(p.getWorld(), User.getInstance(p)));
+ }
+ optionalIsland.ifPresent(i -> {
Vector unitVector = i.getProtectionCenter().toVector().subtract(p.getLocation().toVector()).normalize()
.multiply(new Vector(1,0,1));
if (unitVector.lengthSquared() <= 0D) {
@@ -259,7 +268,10 @@ private boolean outsideCheck(Player player, Location from, Location to) {
|| !user.getMetaData(BorderShower.BORDER_STATE_META_DATA).map(MetaDataValue::asBoolean).orElse(addon.getSettings().isShowByDefault())) {
return false;
}
- return addon.getIslands().getIslandAt(to).filter(i -> !i.onIsland(to)).isPresent();
+ Optional islandAt = addon.getIslands().getIslandAt(to);
+ // Player is outside if they are on an island but not within its protection zone,
+ // or if they are not on any island at all (e.g., pushed out by piston)
+ return islandAt.isEmpty() || islandAt.filter(i -> !i.onIsland(to)).isPresent();
}
/**
@@ -338,8 +350,8 @@ public void onVehicleMove(VehicleMoveEvent e) {
// Remove head movement
if (!e.getFrom().toVector().equals(e.getTo().toVector())) {
e.getVehicle().getPassengers().stream().filter(Player.class::isInstance).map(Player.class::cast)
- .filter(this::isOn).forEach(p -> addon.getIslands().getIslandAt(p.getLocation())
- .ifPresent(i -> show.refreshView(User.getInstance(p), i)));
+ .filter(this::isOn).forEach(p -> addon.getIslands().getIslandAt(p.getLocation())
+ .ifPresent(i -> show.refreshView(User.getInstance(p), i)));
}
}
@@ -357,4 +369,61 @@ public void onProtectionRangeChange(IslandProtectionRangeChangeEvent e) {
}
});
}
+
+ /**
+ * Bounces items back to inside the barrier if thrown by a player
+ * @param event event
+ */
+ @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
+ public void onItemDrop(PlayerDropItemEvent event) {
+ if (addon.getSettings().isBounceBack()
+ && addon.inGameWorld(event.getPlayer().getWorld())
+ && isOn(event.getPlayer())
+ ) {
+ // Get this island
+ addon.getIslands().getIslandAt(event.getPlayer().getLocation()).ifPresent(is -> trackItem(event.getItemDrop(), is));
+ }
+ }
+
+ /**
+ * Bounces items back to inside the barrier if dropped when a player dies
+ * @param event event
+ */
+ @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
+ public void onPlayerDeath(PlayerDeathEvent event) {
+ if (addon.getSettings().isBounceBack()
+ && addon.inGameWorld(event.getPlayer().getWorld())
+ && isOn(event.getPlayer())) {
+ // Get this island
+ addon.getIslands().getIslandAt(event.getPlayer().getLocation()).ifPresent(is -> {
+ event.getDrops().forEach(item -> trackItem(event.getPlayer().getWorld().dropItemNaturally(event.getPlayer().getLocation(), item), is));
+ event.getDrops().clear(); // We handled them
+ });
+ }
+ }
+
+ private void trackItem(Item item, Island island) {
+ new BukkitRunnable() {
+ int ticksActive = 0;
+
+ @Override
+ public void run() {
+ // Stop tracking if the item is picked up, despawned, or 20 seconds have passed
+ if (!item.isValid() || ticksActive > 400) {
+ this.cancel();
+ return;
+ }
+
+ Location loc = item.getLocation();
+ // Check if the item is going outside the border
+ if (!island.onIsland(loc)) {
+ // Reverse the direction
+ item.setVelocity(item.getVelocity().multiply(-0.5));
+ this.cancel();
+ }
+ ticksActive++;
+ }
+ }.runTaskTimer(addon.getPlugin(), 1L, 2L); // Check every 2 ticks (0.1 seconds)
+ }
+
}
diff --git a/src/main/java/world/bentobox/border/listeners/ShowBarrier.java b/src/main/java/world/bentobox/border/listeners/ShowBarrier.java
index f235c4d..05673fb 100644
--- a/src/main/java/world/bentobox/border/listeners/ShowBarrier.java
+++ b/src/main/java/world/bentobox/border/listeners/ShowBarrier.java
@@ -12,13 +12,13 @@
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.data.BlockData;
+import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
import com.google.common.base.Enums;
-import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.metadata.MetaDataValue;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
@@ -136,7 +136,7 @@ private void showPlayer(Player player, int i, int j, int k, boolean max) {
if (addon.getSettings().isUseBarrierBlocks()
&& player.getLocation().getBlockX() == i
&& player.getLocation().getBlockZ() == k) {
- teleportPlayer(player);
+ teleportEntity(player);
}
Location l = new Location(player.getWorld(), i, j, k);
@@ -157,17 +157,17 @@ private void showPlayer(Player player, int i, int j, int k, boolean max) {
/**
* Teleport player back within the island space they are in
- * @param p player
+ * @param entity player or entity
*/
- public void teleportPlayer(Player p) {
- addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> {
- Vector unitVector = i.getCenter().toVector().subtract(p.getLocation().toVector()).normalize()
+ public void teleportEntity(Entity entity) {
+ addon.getIslands().getIslandAt(entity.getLocation()).ifPresent(i -> {
+ Vector unitVector = i.getCenter().toVector().subtract(entity.getLocation().toVector()).normalize()
.multiply(new Vector(1, 0, 1));
// Get distance from border
- Location to = p.getLocation().toVector().add(unitVector).toLocation(p.getWorld());
- to.setPitch(p.getLocation().getPitch());
- to.setYaw(p.getLocation().getYaw());
- Util.teleportAsync(p, to, TeleportCause.PLUGIN);
+ Location to = entity.getLocation().toVector().add(unitVector).toLocation(entity.getWorld());
+ to.setPitch(entity.getLocation().getPitch());
+ to.setYaw(entity.getLocation().getYaw());
+ Util.teleportAsync(entity, to, TeleportCause.PLUGIN);
});
}
diff --git a/src/main/java/world/bentobox/border/listeners/ShowVirtualWorldBorder.java b/src/main/java/world/bentobox/border/listeners/ShowWorldBorder.java
similarity index 67%
rename from src/main/java/world/bentobox/border/listeners/ShowVirtualWorldBorder.java
rename to src/main/java/world/bentobox/border/listeners/ShowWorldBorder.java
index 45f9359..4ac93e9 100644
--- a/src/main/java/world/bentobox/border/listeners/ShowVirtualWorldBorder.java
+++ b/src/main/java/world/bentobox/border/listeners/ShowWorldBorder.java
@@ -6,6 +6,7 @@
import org.bukkit.Location;
import org.bukkit.World.Environment;
import org.bukkit.WorldBorder;
+import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
@@ -21,11 +22,12 @@
* @author tastybento
*
*/
-public class ShowVirtualWorldBorder implements BorderShower {
+public class ShowWorldBorder implements BorderShower {
+ private static final long MAX_TICKS = 107374182;
private final Border addon;
- public ShowVirtualWorldBorder(Border addon) {
+ public ShowWorldBorder(Border addon) {
this.addon = addon;
}
@@ -45,6 +47,16 @@ public void showBorder(Player player, Island island) {
double size = Math.min(island.getRange() * 2D, (island.getProtectionRange() + addon.getSettings().getBarrierOffset()) * 2D);
wb.setSize(size);
wb.setWarningDistance(0);
+ switch(addon.getSettings().getColor()) {
+ case RED:
+ wb.changeSize(wb.getSize() - 0.1, MAX_TICKS);
+ break;
+ case GREEN:
+ wb.changeSize(wb.getSize() + 0.1, MAX_TICKS);
+ break;
+ case BLUE:
+ break;
+ }
player.setWorldBorder(wb);
}
@@ -55,17 +67,17 @@ public void hideBorder(User user) {
/**
* Teleport player back within the island space they are in
- * @param p player
+ * @param entity player
*/
- public void teleportPlayer(Player p) {
- addon.getIslands().getIslandAt(p.getLocation()).ifPresent(i -> {
- Vector unitVector = i.getCenter().toVector().subtract(p.getLocation().toVector()).normalize()
+ public void teleportEntity(Entity entity) {
+ addon.getIslands().getIslandAt(entity.getLocation()).ifPresent(i -> {
+ Vector unitVector = i.getCenter().toVector().subtract(entity.getLocation().toVector()).normalize()
.multiply(new Vector(1, 0, 1));
// Get distance from border
- Location to = p.getLocation().toVector().add(unitVector).toLocation(p.getWorld());
- to.setPitch(p.getLocation().getPitch());
- to.setYaw(p.getLocation().getYaw());
- Util.teleportAsync(p, to, TeleportCause.PLUGIN);
+ Location to = entity.getLocation().toVector().add(unitVector).toLocation(entity.getWorld());
+ to.setPitch(entity.getLocation().getPitch());
+ to.setYaw(entity.getLocation().getYaw());
+ Util.teleportAsync(entity, to, TeleportCause.PLUGIN);
});
}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index b19ac3b..7e4a657 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -1,4 +1,4 @@
-# Border addon configuration file {$version}
+# Border addon configuration file
# See the documentation at https://docs.bentobox.world/en/latest/addons/Border/
#
# This list stores GameModes in which Border addon should not work.
@@ -13,6 +13,10 @@ disabled-gamemodes: []
# then this setting will be used.
type: VANILLA
#
+# Bounce items back inside the border if they are thrown by a player.
+# Without this, items can be thrown outside the border.
+bounce-back: true
+#
# Teleport players back inside the border if they somehow get outside.
# This will teleport players back inside if they toggle the border with a command.
return-teleport: true
diff --git a/src/test/java/world/bentobox/border/listeners/PlayerListenerTest.java b/src/test/java/world/bentobox/border/listeners/PlayerListenerTest.java
index 794c024..e505e1f 100644
--- a/src/test/java/world/bentobox/border/listeners/PlayerListenerTest.java
+++ b/src/test/java/world/bentobox/border/listeners/PlayerListenerTest.java
@@ -72,6 +72,8 @@ public class PlayerListenerTest extends CommonTestSetup {
private Vehicle vehicle;
@Mock
private GameModeAddon gma;
+
+ private MockedStatic mockedUser;
/**
@@ -81,7 +83,7 @@ public class PlayerListenerTest extends CommonTestSetup {
@BeforeEach
public void setUp() throws Exception {
super.setUp();
- MockedStatic mockedUser = Mockito.mockStatic(User.class, Mockito.RETURNS_MOCKS);
+ mockedUser = Mockito.mockStatic(User.class, Mockito.RETURNS_MOCKS);
mockedUser.when(() -> User.getInstance(any(Player.class))).thenReturn(user);
// Border Shower
@@ -142,6 +144,7 @@ public void setUp() throws Exception {
@Override
@AfterEach
public void tearDown() throws Exception {
+ mockedUser.closeOnDemand();
super.tearDown();
}
@@ -314,6 +317,27 @@ public void testOnPlayerLeaveIslandReturnTeleportWaaayOutsideIsland() {
mockedUtil.verify(() -> Util.teleportAsync(any(), any()), times(2));
}
+ /**
+ * Test method for {@link world.bentobox.border.listeners.PlayerListener#onPlayerLeaveIsland(org.bukkit.event.player.PlayerMoveEvent)}.
+ * Tests the scenario where a player is pushed completely outside any island (e.g., by a piston)
+ * and getIslandAt returns empty. The plugin should fall back to the player's own island.
+ */
+ @Test
+ public void testOnPlayerLeaveIslandTeleportsWhenCompletelyOutsideIsland() {
+ // Player is completely outside any island - getIslandAt returns empty
+ when(im.getIslandAt(any())).thenReturn(Optional.empty());
+ when(im.getProtectedIslandAt(any())).thenReturn(Optional.empty());
+ // But the player has their own island
+ when(im.getIsland(any(), any(User.class))).thenReturn(island);
+ when(island.onIsland(any())).thenReturn(false);
+ settings.setReturnTeleport(true);
+ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
+ pl.onPlayerLeaveIsland(event);
+ assertFalse(event.isCancelled());
+ // Verify teleportAsync was called to teleport the player back
+ mockedUtil.verify(() -> Util.teleportAsync(any(), any()), times(2));
+ }
+
/**
* Test method for {@link world.bentobox.border.listeners.PlayerListener#onPlayerMove(org.bukkit.event.player.PlayerMoveEvent)}.
*/
diff --git a/src/test/java/world/bentobox/border/listeners/ShowBarrierTest.java b/src/test/java/world/bentobox/border/listeners/ShowBarrierTest.java
index 392c851..814284e 100644
--- a/src/test/java/world/bentobox/border/listeners/ShowBarrierTest.java
+++ b/src/test/java/world/bentobox/border/listeners/ShowBarrierTest.java
@@ -47,6 +47,8 @@ public class ShowBarrierTest extends CommonTestSetup {
@Mock
private @NonNull Location center;
+ private MockedStatic mockedUser;
+
/**
* @throws java.lang.Exception
*/
@@ -77,7 +79,7 @@ public void setUp() throws Exception {
when(im.getIslandAt(any(Location.class))).thenReturn(Optional.of(island));
// User
- MockedStatic mockedUser = Mockito.mockStatic(User.class, Mockito.RETURNS_MOCKS);
+ mockedUser = Mockito.mockStatic(User.class, Mockito.RETURNS_MOCKS);
mockedUser.when(() -> User.getInstance(any(Player.class))).thenReturn(user);
when(user.getMetaData(anyString())).thenReturn(Optional.empty());
when(user.getPlayer()).thenReturn(player);
@@ -98,6 +100,9 @@ public void setUp() throws Exception {
@Override
@AfterEach
public void tearDown() throws Exception {
+ if (mockedUser != null) {
+ mockedUser.close();
+ }
super.tearDown();
}
diff --git a/src/test/java/world/bentobox/border/listeners/ShowVirtualWorldBorderTest.java b/src/test/java/world/bentobox/border/listeners/ShowVirtualWorldBorderTest.java
index c8872e7..57b5d63 100644
--- a/src/test/java/world/bentobox/border/listeners/ShowVirtualWorldBorderTest.java
+++ b/src/test/java/world/bentobox/border/listeners/ShowVirtualWorldBorderTest.java
@@ -2,10 +2,12 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.bukkit.Bukkit;
+import org.bukkit.World.Environment;
import org.bukkit.WorldBorder;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@@ -30,7 +32,7 @@ public class ShowVirtualWorldBorderTest extends CommonTestSetup {
@Mock
private Border addon;
private Settings settings;
- private ShowVirtualWorldBorder svwb;
+ private ShowWorldBorder svwb;
@Mock
private @NonNull User user;
@Mock
@@ -64,7 +66,7 @@ public void setUp() throws Exception {
// Bukkit
mockedBukkit.when(() -> Bukkit.createWorldBorder()).thenReturn(wb);
- svwb = new ShowVirtualWorldBorder(addon);
+ svwb = new ShowWorldBorder(addon);
}
@Override
@@ -74,7 +76,7 @@ public void tearDown() throws Exception {
}
/**
- * Test method for {@link world.bentobox.border.listeners.ShowVirtualWorldBorder#ShowVirtualWorldBorder(world.bentobox.border.Border)}.
+ * Test method for {@link world.bentobox.border.listeners.ShowWorldBorder#ShowVirtualWorldBorder(world.bentobox.border.Border)}.
*/
@Test
public void testShowVirtualWorldBorder() {
@@ -82,7 +84,7 @@ public void testShowVirtualWorldBorder() {
}
/**
- * Test method for {@link world.bentobox.border.listeners.ShowVirtualWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
+ * Test method for {@link world.bentobox.border.listeners.ShowWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
*/
@Test
public void testShowBorder() {
@@ -92,7 +94,7 @@ public void testShowBorder() {
}
/**
- * Test method for {@link world.bentobox.border.listeners.ShowVirtualWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
+ * Test method for {@link world.bentobox.border.listeners.ShowWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
*/
@Test
public void testShowBorderWithOffset() {
@@ -103,7 +105,7 @@ public void testShowBorderWithOffset() {
}
/**
- * Test method for {@link world.bentobox.border.listeners.ShowVirtualWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
+ * Test method for {@link world.bentobox.border.listeners.ShowWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
*/
@Test
public void testShowBorderWithLargeOffset() {
@@ -114,7 +116,7 @@ public void testShowBorderWithLargeOffset() {
}
/**
- * Test method for {@link world.bentobox.border.listeners.ShowVirtualWorldBorder#hideBorder(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.border.listeners.ShowWorldBorder#hideBorder(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testHideBorder() {
@@ -123,4 +125,39 @@ public void testHideBorder() {
verify(mockPlayer).setWorldBorder(null);
}
+ /**
+ * Test method for {@link world.bentobox.border.listeners.ShowWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
+ * Tests that border is shown when player is in an island nether world.
+ */
+ @Test
+ public void testShowBorderInIslandNetherWorld() {
+ // Setup: Player is in a nether environment that IS an island nether world
+ when(world.getEnvironment()).thenReturn(Environment.NETHER);
+ when(iwm.isIslandNether(world)).thenReturn(true);
+ when(addon.getPlugin()).thenReturn(plugin);
+
+ svwb.showBorder(mockPlayer, island);
+
+ // Verify that the border was set (border should show in island nether worlds)
+ verify(mockPlayer).setWorldBorder(wb);
+ verify(wb).setSize(200.0D);
+ }
+
+ /**
+ * Test method for {@link world.bentobox.border.listeners.ShowWorldBorder#showBorder(org.bukkit.entity.Player, world.bentobox.bentobox.database.objects.Island)}.
+ * Tests that border is NOT shown when player is in a non-island nether world.
+ */
+ @Test
+ public void testShowBorderInNonIslandNetherWorld() {
+ // Setup: Player is in a nether environment that is NOT an island nether world
+ when(world.getEnvironment()).thenReturn(Environment.NETHER);
+ when(iwm.isIslandNether(world)).thenReturn(false);
+ when(addon.getPlugin()).thenReturn(plugin);
+
+ svwb.showBorder(mockPlayer, island);
+
+ // Verify that the border was NOT set (border should not show in non-island nether worlds)
+ verify(mockPlayer, never()).setWorldBorder(any());
+ }
+
}