Prevents repeated portaling when nether is disabled. (#1826)

* Prevents repeated portaling when nether is disabled.

https://github.com/BentoBoxWorld/BentoBox/issues/1782

* Fix test
This commit is contained in:
tastybento 2021-08-15 17:05:20 -07:00 committed by GitHub
parent 233c058bfe
commit 32638e7a87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 30 deletions

View File

@ -20,8 +20,8 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPortalEnterEvent;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.NonNull;
@ -44,17 +44,12 @@ public class PortalTeleportationListener implements Listener {
private final BentoBox plugin;
private Set<UUID> inPortal;
private Set<UUID> inTeleport;
public PortalTeleportationListener(@NonNull BentoBox plugin) {
this.plugin = plugin;
inPortal = new HashSet<>();
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent e) {
// Remove player from inPortal after a teleport
inPortal.remove(e.getPlayer().getUniqueId());
inTeleport = new HashSet<>();
}
/**
@ -72,19 +67,13 @@ public class PortalTeleportationListener implements Listener {
if (inPortal.contains(uuid) || !plugin.getIWM().inWorld(Util.getWorld(e.getLocation().getWorld()))) {
return;
}
inPortal.add(uuid);
if (!Bukkit.getAllowNether() && type.equals(Material.NETHER_PORTAL)) {
inPortal.add(uuid);
// Schedule a time
Bukkit.getScheduler().runTaskLater(plugin, () -> {
// Check again if still in portal
if (entity.getLocation().getBlock().getType().equals(Material.NETHER_PORTAL)) {
PlayerPortalEvent en = new PlayerPortalEvent((Player)entity, e.getLocation(), null, TeleportCause.NETHER_PORTAL, 0, false, 0);
if (!this.onIslandPortal(en)) {
// Failed
inPortal.remove(uuid);
}
} else {
inPortal.remove(uuid);
if (inPortal.contains(uuid)) {
this.onIslandPortal(new PlayerPortalEvent((Player)entity, e.getLocation(), null, TeleportCause.NETHER_PORTAL, 0, false, 0));
}
}, 40);
return;
@ -129,6 +118,21 @@ public class PortalTeleportationListener implements Listener {
return false;
}
/**
* Remove inPortal flag only when player exits the portal
* @param e player move event
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onExitPortal(PlayerMoveEvent e) {
if (!inPortal.contains(e.getPlayer().getUniqueId())) {
return;
}
if (e.getTo() != null && !e.getTo().getBlock().getType().equals(Material.NETHER_PORTAL)) {
inPortal.remove(e.getPlayer().getUniqueId());
inTeleport.remove(e.getPlayer().getUniqueId());
}
}
/**
* Handles nether or end portals
* @param e - event
@ -136,9 +140,9 @@ public class PortalTeleportationListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public boolean onIslandPortal(PlayerPortalEvent e) {
return switch (e.getCause()) {
case END_GATEWAY, END_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.THE_END);
case NETHER_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.NETHER);
default -> false;
case END_GATEWAY, END_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.THE_END);
case NETHER_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.NETHER);
default -> false;
};
}
@ -150,18 +154,27 @@ public class PortalTeleportationListener implements Listener {
* @return true if portal happens, false if not
*/
private boolean processPortal(final PlayerEntityPortalEvent e, final Environment env) {
World fromWorld = e.getFrom().getWorld();
World overWorld = Util.getWorld(fromWorld);
if (fromWorld == null || !plugin.getIWM().inWorld(overWorld)) {
// Do nothing special
return false;
}
// 1.14.4 requires explicit cancellation to prevent teleporting to the normal nether
if (!isGenerate(overWorld, env)) {
e.setCancelled(true);
return false;
}
if (!Bukkit.getServer().getAllowNether()) {
e.setCancelled(true);
}
if (inTeleport.contains(e.getEntity().getUniqueId())) {
return false;
}
inTeleport.add(e.getEntity().getUniqueId());
// STANDARD NETHER OR END
if (!isIslands(overWorld, env)) {
handleStandardNetherOrEnd(e, fromWorld, overWorld, env);
@ -194,7 +207,6 @@ public class PortalTeleportationListener implements Listener {
&& e.getIsland().filter(i -> !hasPartnerIsland(i, env)).map(i -> {
// No nether island present so paste the default one
e.setCancelled(true);
inPortal.remove(e.getEntity().getUniqueId());
pasteNewIsland((Player)e.getEntity(), e.getTo(), i, env);
return true;
}).orElse(false)) {
@ -203,7 +215,6 @@ public class PortalTeleportationListener implements Listener {
}
if (e.getCanCreatePortal()) {
// Let the server teleport
inPortal.remove(e.getEntity().getUniqueId());
return true;
}
if (env.equals(Environment.THE_END)) {
@ -228,7 +239,6 @@ public class PortalTeleportationListener implements Listener {
.location(e.getTo())
.portal()
.thenRun(() -> {
inPortal.remove(e.getEntity().getUniqueId());
e.getEntity().setVelocity(new Vector(0,0,0));
e.getEntity().setFallDistance(0);
})
@ -357,7 +367,6 @@ public class PortalTeleportationListener implements Listener {
e.setTo(e.getFrom().toVector().toLocation(overWorld));
// Find distance from edge of island's protection
plugin.getIslands().getIslandAt(e.getFrom()).ifPresent(i -> setSeachRadius(e, i));
inPortal.remove(e.getEntity().getUniqueId());
return;
}
// Custom portals
@ -370,7 +379,6 @@ public class PortalTeleportationListener implements Listener {
.entity(e.getEntity())
.location(to)
.portal()
.thenRun(() -> inPortal.remove(e.getEntity().getUniqueId()))
.build();
}
@ -408,7 +416,7 @@ public class PortalTeleportationListener implements Listener {
// From standard nether or end
else if (e.getEntity() instanceof Player){
e.setCancelled(true);
plugin.getIslands().homeTeleportAsync(overWorld, (Player)e.getEntity()).thenAccept(b -> inPortal.remove(e.getEntity().getUniqueId()));
plugin.getIslands().homeTeleportAsync(overWorld, (Player)e.getEntity());
}
}

View File

@ -7,7 +7,6 @@ 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;
@ -19,6 +18,7 @@ import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
@ -154,6 +154,9 @@ public class PortalTeleportationListenerTest {
BukkitScheduler sch = mock(BukkitScheduler.class);
PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getScheduler()).thenReturn(sch);
Server server = mock(Server.class);
when(server.getAllowNether()).thenReturn(true);
when(Bukkit.getServer()).thenReturn(server);
// Locales
LocalesManager lm = mock(LocalesManager.class);
@ -284,7 +287,7 @@ public class PortalTeleportationListenerTest {
when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
np.onIslandPortal(e);
assertTrue(e.isCancelled());
verify(im, times(2)).homeTeleportAsync(any(), eq(player));
verify(im).homeTeleportAsync(any(), eq(player));
}
/**