2018-07-31 18:03:32 +02:00
|
|
|
package world.bentobox.bentobox.listeners;
|
2018-02-11 17:18:50 +01:00
|
|
|
|
2021-02-03 02:19:22 +01:00
|
|
|
import java.util.Arrays;
|
2020-10-11 16:38:21 +02:00
|
|
|
import java.util.HashSet;
|
2021-10-12 02:55:04 +02:00
|
|
|
import java.util.Objects;
|
2019-06-10 01:20:08 +02:00
|
|
|
import java.util.Optional;
|
2020-10-11 16:38:21 +02:00
|
|
|
import java.util.Set;
|
|
|
|
import java.util.UUID;
|
2019-06-10 01:20:08 +02:00
|
|
|
|
2020-10-11 16:38:21 +02:00
|
|
|
import org.bukkit.Bukkit;
|
2018-02-11 17:18:50 +01:00
|
|
|
import org.bukkit.Location;
|
2020-10-11 16:38:21 +02:00
|
|
|
import org.bukkit.Material;
|
2018-02-11 17:18:50 +01:00
|
|
|
import org.bukkit.World;
|
2018-05-25 21:19:46 +02:00
|
|
|
import org.bukkit.World.Environment;
|
2021-02-03 02:19:22 +01:00
|
|
|
import org.bukkit.block.BlockFace;
|
2021-02-17 20:53:22 +01:00
|
|
|
import org.bukkit.entity.Entity;
|
2021-02-03 02:19:22 +01:00
|
|
|
import org.bukkit.entity.EntityType;
|
2019-06-10 01:20:08 +02:00
|
|
|
import org.bukkit.entity.Player;
|
2018-02-11 17:18:50 +01:00
|
|
|
import org.bukkit.event.EventHandler;
|
|
|
|
import org.bukkit.event.EventPriority;
|
|
|
|
import org.bukkit.event.Listener;
|
2021-02-03 02:19:22 +01:00
|
|
|
import org.bukkit.event.entity.EntityPortalEnterEvent;
|
2018-02-11 17:18:50 +01:00
|
|
|
import org.bukkit.event.entity.EntityPortalEvent;
|
2021-08-16 02:05:20 +02:00
|
|
|
import org.bukkit.event.player.PlayerMoveEvent;
|
2018-02-11 17:18:50 +01:00
|
|
|
import org.bukkit.event.player.PlayerPortalEvent;
|
|
|
|
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
2020-01-11 00:41:59 +01:00
|
|
|
import org.bukkit.util.Vector;
|
2019-02-16 10:58:25 +01:00
|
|
|
import org.eclipse.jdt.annotation.NonNull;
|
2019-04-17 18:35:55 +02:00
|
|
|
|
2018-07-31 18:03:32 +02:00
|
|
|
import world.bentobox.bentobox.BentoBox;
|
2021-02-03 02:19:22 +01:00
|
|
|
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
2019-09-15 23:10:52 +02:00
|
|
|
import world.bentobox.bentobox.blueprints.Blueprint;
|
2019-05-30 17:22:39 +02:00
|
|
|
import world.bentobox.bentobox.blueprints.BlueprintPaster;
|
2019-09-15 23:10:52 +02:00
|
|
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
|
2019-06-10 01:20:08 +02:00
|
|
|
import world.bentobox.bentobox.database.objects.Island;
|
2019-07-05 01:54:05 +02:00
|
|
|
import world.bentobox.bentobox.util.Util;
|
|
|
|
import world.bentobox.bentobox.util.teleport.SafeSpotTeleport;
|
2018-02-11 17:18:50 +01:00
|
|
|
|
2019-02-16 11:17:48 +01:00
|
|
|
/**
|
|
|
|
* Handles teleportation via the Nether/End portals to the Nether and End dimensions of the worlds added by the GameModeAddons.
|
|
|
|
*
|
|
|
|
* @author tastybento
|
|
|
|
*/
|
|
|
|
public class PortalTeleportationListener implements Listener {
|
2019-02-16 11:09:34 +01:00
|
|
|
|
2018-07-29 22:21:46 +02:00
|
|
|
private final BentoBox plugin;
|
2021-08-30 03:17:21 +02:00
|
|
|
private final Set<UUID> inPortal;
|
|
|
|
private final Set<UUID> inTeleport;
|
2018-02-11 17:18:50 +01:00
|
|
|
|
2019-02-16 11:17:48 +01:00
|
|
|
public PortalTeleportationListener(@NonNull BentoBox plugin) {
|
2018-02-11 17:18:50 +01:00
|
|
|
this.plugin = plugin;
|
2020-10-11 16:38:21 +02:00
|
|
|
inPortal = new HashSet<>();
|
2021-08-16 02:05:20 +02:00
|
|
|
inTeleport = new HashSet<>();
|
2020-10-11 16:38:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fires the event if nether or end is disabled at the system level
|
2021-06-01 01:01:21 +02:00
|
|
|
* @param e - EntityPortalEnterEvent
|
2020-10-11 16:38:21 +02:00
|
|
|
*/
|
2021-10-24 01:39:36 +02:00
|
|
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
2021-02-03 02:19:22 +01:00
|
|
|
public void onPlayerPortal(EntityPortalEnterEvent e) {
|
|
|
|
if (!(e.getEntity() instanceof Player)) {
|
2020-10-11 16:38:21 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-02-17 20:53:22 +01:00
|
|
|
Entity entity = e.getEntity();
|
2021-02-03 02:19:22 +01:00
|
|
|
Material type = e.getLocation().getBlock().getType();
|
2021-02-17 20:53:22 +01:00
|
|
|
UUID uuid = entity.getUniqueId();
|
2021-02-03 02:19:22 +01:00
|
|
|
if (inPortal.contains(uuid) || !plugin.getIWM().inWorld(Util.getWorld(e.getLocation().getWorld()))) {
|
|
|
|
return;
|
|
|
|
}
|
2021-08-16 02:05:20 +02:00
|
|
|
inPortal.add(uuid);
|
2021-02-03 02:19:22 +01:00
|
|
|
if (!Bukkit.getAllowNether() && type.equals(Material.NETHER_PORTAL)) {
|
2020-10-11 16:38:21 +02:00
|
|
|
// Schedule a time
|
|
|
|
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
|
|
|
// Check again if still in portal
|
2021-08-16 02:05:20 +02:00
|
|
|
if (inPortal.contains(uuid)) {
|
|
|
|
this.onIslandPortal(new PlayerPortalEvent((Player)entity, e.getLocation(), null, TeleportCause.NETHER_PORTAL, 0, false, 0));
|
2020-10-11 16:38:21 +02:00
|
|
|
}
|
|
|
|
}, 40);
|
|
|
|
return;
|
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// End portals are instant transfer
|
|
|
|
if (!Bukkit.getAllowEnd() && (type.equals(Material.END_PORTAL) || type.equals(Material.END_GATEWAY))) {
|
2021-02-17 20:53:22 +01:00
|
|
|
PlayerPortalEvent en = new PlayerPortalEvent((Player)entity,
|
2021-02-03 02:19:22 +01:00
|
|
|
e.getLocation(),
|
|
|
|
null,
|
|
|
|
type.equals(Material.END_PORTAL) ? TeleportCause.END_PORTAL : TeleportCause.END_GATEWAY,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
0);
|
|
|
|
this.onIslandPortal(en);
|
2020-10-11 16:38:21 +02:00
|
|
|
}
|
2018-02-11 17:18:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-02-16 11:17:48 +01:00
|
|
|
* Handles non-player portal use.
|
|
|
|
*
|
|
|
|
* @param e - event
|
|
|
|
*/
|
2021-10-27 05:49:38 +02:00
|
|
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
2021-02-03 02:19:22 +01:00
|
|
|
public boolean onEntityPortal(EntityPortalEvent e) {
|
2019-02-16 11:17:48 +01:00
|
|
|
if (plugin.getIWM().inWorld(e.getFrom())) {
|
2021-02-03 02:19:22 +01:00
|
|
|
Optional<Material> mat = Arrays.stream(BlockFace.values())
|
|
|
|
.map(bf -> e.getFrom().getBlock().getRelative(bf).getType())
|
|
|
|
.filter(m -> m.equals(Material.NETHER_PORTAL)
|
|
|
|
|| m.equals(Material.END_PORTAL)
|
|
|
|
|| m.equals(Material.END_GATEWAY))
|
|
|
|
.findFirst();
|
2021-07-31 17:48:26 +02:00
|
|
|
if (mat.isEmpty()) {
|
2021-02-03 02:19:22 +01:00
|
|
|
e.setCancelled(true);
|
|
|
|
return false;
|
|
|
|
} else if (mat.get().equals(Material.NETHER_PORTAL)){
|
|
|
|
return processPortal(new PlayerEntityPortalEvent(e), Environment.NETHER);
|
|
|
|
} else {
|
|
|
|
return processPortal(new PlayerEntityPortalEvent(e), Environment.THE_END);
|
|
|
|
}
|
2019-02-16 11:17:48 +01:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
return false;
|
2019-02-16 11:17:48 +01:00
|
|
|
}
|
|
|
|
|
2021-08-16 02:05:20 +02:00
|
|
|
/**
|
|
|
|
* 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-16 11:17:48 +01:00
|
|
|
/**
|
2021-02-03 02:19:22 +01:00
|
|
|
* Handles nether or end portals
|
2018-02-18 02:01:25 +01:00
|
|
|
* @param e - event
|
2018-02-11 17:18:50 +01:00
|
|
|
*/
|
2020-02-07 23:07:12 +01:00
|
|
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
2021-02-03 02:19:22 +01:00
|
|
|
public boolean onIslandPortal(PlayerPortalEvent e) {
|
2021-07-31 17:48:26 +02:00
|
|
|
return switch (e.getCause()) {
|
2021-08-16 02:05:20 +02:00
|
|
|
case END_GATEWAY, END_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.THE_END);
|
|
|
|
case NETHER_PORTAL -> processPortal(new PlayerEntityPortalEvent(e), Environment.NETHER);
|
|
|
|
default -> false;
|
2021-07-31 17:48:26 +02:00
|
|
|
};
|
2021-02-03 02:19:22 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process the portal action
|
|
|
|
* @param e - event
|
|
|
|
* @param env - environment that this relates to - NETHER or THE_END
|
|
|
|
* @return true if portal happens, false if not
|
|
|
|
*/
|
|
|
|
private boolean processPortal(final PlayerEntityPortalEvent e, final Environment env) {
|
2019-02-17 14:29:12 +01:00
|
|
|
World fromWorld = e.getFrom().getWorld();
|
2019-04-17 18:35:55 +02:00
|
|
|
World overWorld = Util.getWorld(fromWorld);
|
2021-10-12 02:48:41 +02:00
|
|
|
if (overWorld == null || fromWorld == null || !plugin.getIWM().inWorld(overWorld)) {
|
2019-02-17 14:29:12 +01:00
|
|
|
// Do nothing special
|
|
|
|
return false;
|
2018-02-11 17:18:50 +01:00
|
|
|
}
|
2021-08-16 02:05:20 +02:00
|
|
|
|
2021-02-03 02:19:22 +01:00
|
|
|
if (!isGenerate(overWorld, env)) {
|
2019-11-21 02:08:04 +01:00
|
|
|
e.setCancelled(true);
|
|
|
|
return false;
|
|
|
|
}
|
2021-08-16 02:05:20 +02:00
|
|
|
|
|
|
|
if (!Bukkit.getServer().getAllowNether()) {
|
|
|
|
e.setCancelled(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inTeleport.contains(e.getEntity().getUniqueId())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
inTeleport.add(e.getEntity().getUniqueId());
|
|
|
|
|
2021-02-03 02:19:22 +01:00
|
|
|
// STANDARD NETHER OR END
|
|
|
|
if (!isIslands(overWorld, env)) {
|
|
|
|
handleStandardNetherOrEnd(e, fromWorld, overWorld, env);
|
|
|
|
return true;
|
2018-02-11 17:18:50 +01:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// FROM NETHER OR END
|
|
|
|
// If entering a portal in the other world, teleport to a portal in overworld if there is one
|
|
|
|
if (fromWorld.getEnvironment().equals(env)) {
|
|
|
|
handleFromNetherOrEnd(e, overWorld, env);
|
2019-02-17 14:29:12 +01:00
|
|
|
return true;
|
2018-05-25 21:19:46 +02:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// TO NETHER OR END
|
|
|
|
World toWorld = getNetherEndWorld(overWorld, env);
|
|
|
|
// Set whether portals should be created or not
|
|
|
|
e.setCanCreatePortal(plugin.getIWM().getAddon(overWorld).map(gm -> isMakePortals(gm, env)).orElse(false));
|
|
|
|
// Set the destination location
|
|
|
|
// If portals cannot be created, then destination is the spawn point, otherwise it's the vector
|
|
|
|
e.setTo(getTo(e, env, toWorld));
|
2019-05-30 17:22:39 +02:00
|
|
|
|
2021-02-03 02:19:22 +01:00
|
|
|
// Find the distance from edge of island's protection and set the search radius
|
|
|
|
e.getIsland().ifPresent(i -> setSeachRadius(e, i));
|
|
|
|
|
|
|
|
// Check if there is an island there or not
|
|
|
|
if (e.getEntity().getType().equals(EntityType.PLAYER)
|
|
|
|
&& plugin.getIWM().isPasteMissingIslands(overWorld)
|
2019-12-16 01:03:43 +01:00
|
|
|
&& !plugin.getIWM().isUseOwnGenerator(overWorld)
|
2021-02-03 02:19:22 +01:00
|
|
|
&& isGenerate(overWorld, env)
|
|
|
|
&& isIslands(overWorld, env)
|
|
|
|
&& getNetherEndWorld(overWorld, env) != null
|
|
|
|
&& e.getIsland().filter(i -> !hasPartnerIsland(i, env)).map(i -> {
|
|
|
|
// No nether island present so paste the default one
|
|
|
|
e.setCancelled(true);
|
|
|
|
pasteNewIsland((Player)e.getEntity(), e.getTo(), i, env);
|
2020-01-15 00:01:19 +01:00
|
|
|
return true;
|
|
|
|
}).orElse(false)) {
|
2021-02-03 02:19:22 +01:00
|
|
|
// All done here
|
2019-06-10 01:20:08 +02:00
|
|
|
return true;
|
2019-05-30 17:22:39 +02:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
if (e.getCanCreatePortal()) {
|
|
|
|
// Let the server teleport
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (env.equals(Environment.THE_END)) {
|
|
|
|
// Prevent death from hitting the ground
|
|
|
|
e.getEntity().setVelocity(new Vector(0,0,0));
|
|
|
|
e.getEntity().setFallDistance(0);
|
|
|
|
}
|
2021-03-17 03:07:36 +01:00
|
|
|
|
2021-08-30 03:17:38 +02:00
|
|
|
// If we do not generate portals, teleportation should happen manually with safe spot builder.
|
|
|
|
// Otherwise, we could end up with situations when player is placed in mid air, if teleportation
|
2021-03-17 03:07:36 +01:00
|
|
|
// is done instantly.
|
2021-08-30 03:17:38 +02:00
|
|
|
// Our safe spot task is triggered in next tick, however, end teleportation happens in the same tick.
|
2021-03-17 03:07:36 +01:00
|
|
|
// It is placed outside THE_END check, as technically it could happen with the nether portal too.
|
|
|
|
e.setCancelled(true);
|
|
|
|
|
2021-02-03 02:19:22 +01:00
|
|
|
// If there is a portal to go to already, then the player will go there
|
|
|
|
Bukkit.getScheduler().runTask(plugin, () -> {
|
|
|
|
if (!e.getEntity().getWorld().equals(toWorld)) {
|
|
|
|
// Else manually teleport entity
|
|
|
|
new SafeSpotTeleport.Builder(plugin)
|
|
|
|
.entity(e.getEntity())
|
|
|
|
.location(e.getTo())
|
|
|
|
.portal()
|
|
|
|
.thenRun(() -> {
|
|
|
|
e.getEntity().setVelocity(new Vector(0,0,0));
|
|
|
|
e.getEntity().setFallDistance(0);
|
|
|
|
})
|
|
|
|
.build();
|
|
|
|
}
|
|
|
|
});
|
2019-02-17 14:29:12 +01:00
|
|
|
return true;
|
2018-02-11 17:18:50 +01:00
|
|
|
}
|
|
|
|
|
2021-02-03 02:19:22 +01:00
|
|
|
|
2018-02-11 17:18:50 +01:00
|
|
|
/**
|
2021-02-03 02:19:22 +01:00
|
|
|
* Set the destination of this portal action
|
2018-02-18 02:01:25 +01:00
|
|
|
* @param e - event
|
2021-02-03 02:19:22 +01:00
|
|
|
* @param env - environment
|
|
|
|
* @param toWorld - to world
|
2018-02-11 17:18:50 +01:00
|
|
|
*/
|
2021-02-03 02:19:22 +01:00
|
|
|
Location getTo(PlayerEntityPortalEvent e, Environment env, World toWorld) {
|
|
|
|
// Null check - not that useful
|
|
|
|
if (e.getFrom().getWorld() == null || toWorld == null) {
|
|
|
|
return null;
|
2018-09-26 07:20:30 +02:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
if (!e.getCanCreatePortal()) {
|
|
|
|
// Legacy portaling
|
|
|
|
return e.getIsland().map(i -> i.getSpawnPoint(env)).orElse(e.getFrom().toVector().toLocation(toWorld));
|
2018-02-11 17:18:50 +01:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// Make portals
|
|
|
|
// For anywhere other than the end - it is the player's location that is used
|
|
|
|
if (!env.equals(Environment.THE_END)) {
|
|
|
|
return e.getFrom().toVector().toLocation(toWorld);
|
2019-11-21 02:08:04 +01:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// If the-end then we want the platform to always be generated in the same place no matter where
|
|
|
|
// they enter the portal
|
|
|
|
final int x = e.getFrom().getBlockX();
|
|
|
|
final int z = e.getFrom().getBlockZ();
|
|
|
|
final int y = e.getFrom().getBlockY();
|
|
|
|
int i = x;
|
|
|
|
int j = z;
|
|
|
|
int k = y;
|
|
|
|
// If the from is not a portal, then we have to find it
|
|
|
|
if (!e.getFrom().getBlock().getType().equals(Material.END_PORTAL)) {
|
|
|
|
// Find the portal - due to speed, it is possible that the player will be below or above the portal
|
|
|
|
for (k = 0; (k < e.getWorld().getMaxHeight()) && !e.getWorld().getBlockAt(x, k, z).getType().equals(Material.END_PORTAL); k++);
|
2018-09-26 06:20:09 +02:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// Find the maximum x and z corner
|
|
|
|
for (; (i < x + 5) && e.getWorld().getBlockAt(i, k, z).getType().equals(Material.END_PORTAL); i++);
|
|
|
|
for (; (j < z + 5) && e.getWorld().getBlockAt(x, k, j).getType().equals(Material.END_PORTAL); j++);
|
2021-03-28 00:57:15 +01:00
|
|
|
|
2021-03-15 14:23:25 +01:00
|
|
|
// Mojang end platform generation is:
|
|
|
|
// AIR
|
|
|
|
// AIR
|
|
|
|
// OBSIDIAN
|
|
|
|
// and player is placed on second air block above obsidian.
|
|
|
|
// If Y coordinate is below 2, then obsidian platform is not generated and player falls in void.
|
|
|
|
return new Location(toWorld, i, Math.max(2, k), j);
|
2021-02-03 02:19:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if vanilla portals should be used
|
|
|
|
* @param gm - game mode
|
|
|
|
* @param env - environment
|
|
|
|
* @return true or false
|
|
|
|
*/
|
|
|
|
private boolean isMakePortals(GameModeAddon gm, Environment env) {
|
|
|
|
return env.equals(Environment.NETHER) ? gm.getWorldSettings().isMakeNetherPortals() : gm.getWorldSettings().isMakeEndPortals();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if nether or end are generated
|
2021-06-01 01:01:21 +02:00
|
|
|
* @param overWorld - game world
|
2021-02-03 02:19:22 +01:00
|
|
|
* @param env - environment
|
|
|
|
* @return true or false
|
|
|
|
*/
|
|
|
|
private boolean isGenerate(World overWorld, Environment env) {
|
|
|
|
return env.equals(Environment.NETHER) ? plugin.getIWM().isNetherGenerate(overWorld) : plugin.getIWM().isEndGenerate(overWorld);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if nether or end islands are generated
|
2021-06-01 01:01:21 +02:00
|
|
|
* @param overWorld - over world
|
2021-02-03 02:19:22 +01:00
|
|
|
* @param env - environment
|
|
|
|
* @return true or false
|
|
|
|
*/
|
|
|
|
private boolean isIslands(World overWorld, Environment env) {
|
|
|
|
return env.equals(Environment.NETHER) ? plugin.getIWM().isNetherIslands(overWorld) : plugin.getIWM().isEndIslands(overWorld);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the nether or end world
|
2021-06-01 01:01:21 +02:00
|
|
|
* @param overWorld - over world
|
2021-02-03 02:19:22 +01:00
|
|
|
* @param env - environment
|
|
|
|
* @return nether or end world
|
|
|
|
*/
|
|
|
|
private World getNetherEndWorld(World overWorld, Environment env) {
|
|
|
|
return env.equals(Environment.NETHER) ? plugin.getIWM().getNetherWorld(overWorld) : plugin.getIWM().getEndWorld(overWorld);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the island has a nether or end island already
|
2021-06-01 01:01:21 +02:00
|
|
|
* @param i - island
|
2021-02-03 02:19:22 +01:00
|
|
|
* @param env - environment
|
|
|
|
* @return true or false
|
|
|
|
*/
|
|
|
|
private boolean hasPartnerIsland(Island i, Environment env) {
|
|
|
|
return env.equals(Environment.NETHER) ? i.hasNetherIsland() : i.hasEndIsland();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the default nether or end are allowed by the server settings
|
|
|
|
* @param env - environment
|
|
|
|
* @return true or false
|
|
|
|
*/
|
|
|
|
private boolean isAllowedOnServer(Environment env) {
|
|
|
|
return env.equals(Environment.NETHER) ? Bukkit.getAllowNether() : Bukkit.getAllowEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle teleport from nether or end to overworld
|
|
|
|
* @param e - event
|
|
|
|
* @param overWorld - over world
|
|
|
|
* @param env - environment
|
|
|
|
*/
|
|
|
|
private void handleFromNetherOrEnd(PlayerEntityPortalEvent e, World overWorld, Environment env) {
|
|
|
|
// Standard portals
|
|
|
|
if (plugin.getIWM().getAddon(overWorld).map(gm -> isMakePortals(gm, env)).orElse(false)) {
|
|
|
|
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));
|
|
|
|
return;
|
2018-02-11 17:18:50 +01:00
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// Custom portals
|
2018-09-26 06:20:09 +02:00
|
|
|
e.setCancelled(true);
|
2021-02-03 02:19:22 +01:00
|
|
|
// If this is from the island nether or end, then go to the same vector, otherwise try island home location
|
|
|
|
Location to = plugin.getIslands().getIslandAt(e.getFrom()).map(i -> i.getSpawnPoint(Environment.NORMAL)).orElse(e.getFrom().toVector().toLocation(overWorld));
|
|
|
|
e.setTo(to);
|
2018-09-26 06:20:09 +02:00
|
|
|
// Else other worlds teleport to the nether
|
|
|
|
new SafeSpotTeleport.Builder(plugin)
|
2021-02-03 02:19:22 +01:00
|
|
|
.entity(e.getEntity())
|
2019-06-10 01:20:08 +02:00
|
|
|
.location(to)
|
|
|
|
.portal()
|
|
|
|
.build();
|
2021-02-03 02:19:22 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle teleport from or to standard nether or end
|
2021-06-01 01:01:21 +02:00
|
|
|
* @param e - PlayerEntityPortalEvent
|
|
|
|
* @param fromWorld - from world
|
|
|
|
* @param overWorld - over world
|
|
|
|
* @param env - environment involved
|
2021-02-03 02:19:22 +01:00
|
|
|
*/
|
|
|
|
private void handleStandardNetherOrEnd(PlayerEntityPortalEvent e, World fromWorld, World overWorld, Environment env) {
|
|
|
|
if (fromWorld.getEnvironment() != env) {
|
2021-10-12 02:55:04 +02:00
|
|
|
World toWorld = Objects.requireNonNull(getNetherEndWorld(overWorld, env));
|
2021-02-03 02:19:22 +01:00
|
|
|
Location spawnPoint = toWorld.getSpawnLocation();
|
2022-01-22 22:14:34 +01:00
|
|
|
// If going to the nether and nether portals are active then just teleport to approx location
|
|
|
|
if (env.equals(Environment.NETHER) && plugin.getIWM().getWorldSettings(overWorld).isMakeNetherPortals()) {
|
|
|
|
spawnPoint = e.getFrom().toVector().toLocation(toWorld);
|
|
|
|
}
|
2021-02-03 02:19:22 +01:00
|
|
|
// If spawn is set as 0,63,0 in the End then move it to 100, 50 ,0.
|
2021-03-17 03:07:05 +01:00
|
|
|
if (env.equals(Environment.THE_END) && spawnPoint.getBlockX() == 0 && spawnPoint.getBlockZ() == 0) {
|
2021-02-03 02:19:22 +01:00
|
|
|
// Set to the default end spawn
|
|
|
|
spawnPoint = new Location(toWorld, 100, 50, 0);
|
|
|
|
toWorld.setSpawnLocation(100, 50, 0);
|
|
|
|
}
|
|
|
|
if (isAllowedOnServer(env)) {
|
|
|
|
// To Standard Nether or end
|
|
|
|
e.setTo(spawnPoint);
|
|
|
|
} else {
|
|
|
|
// Teleport to standard nether or end
|
|
|
|
new SafeSpotTeleport.Builder(plugin)
|
|
|
|
.entity(e.getEntity())
|
|
|
|
.location(spawnPoint)
|
|
|
|
.portal()
|
|
|
|
.build();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// From standard nether or end
|
|
|
|
else if (e.getEntity() instanceof Player){
|
|
|
|
e.setCancelled(true);
|
2021-08-16 02:05:20 +02:00
|
|
|
plugin.getIslands().homeTeleportAsync(overWorld, (Player)e.getEntity());
|
2021-02-03 02:19:22 +01:00
|
|
|
}
|
|
|
|
|
2018-02-11 17:18:50 +01:00
|
|
|
}
|
2019-06-10 01:20:08 +02:00
|
|
|
|
2021-02-03 02:19:22 +01:00
|
|
|
|
|
|
|
void setSeachRadius(PlayerEntityPortalEvent e, Island i) {
|
|
|
|
if (!i.onIsland(e.getFrom())) return;
|
|
|
|
// Find max x or max z
|
2021-03-28 00:57:15 +01:00
|
|
|
int x = Math.abs(i.getProtectionCenter().getBlockX() - e.getFrom().getBlockX());
|
|
|
|
int z = Math.abs(i.getProtectionCenter().getBlockZ() - e.getFrom().getBlockZ());
|
2021-04-24 17:45:05 +02:00
|
|
|
int diff = Math.max(plugin.getSettings().getMinPortalSearchRadius(), i.getProtectionRange() - Math.max(x, z));
|
2021-02-03 02:19:22 +01:00
|
|
|
if (diff > 0 && diff < 128) {
|
|
|
|
e.setSearchRadius(diff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-10 01:20:08 +02:00
|
|
|
/**
|
|
|
|
* Pastes the default nether or end island and teleports the player to the island's spawn point
|
|
|
|
* @param player - player to teleport after pasting
|
|
|
|
* @param to - the fallback location if a spawn point is not part of the blueprint
|
|
|
|
* @param island - the island
|
|
|
|
* @param env - NETHER or THE_END
|
|
|
|
*/
|
|
|
|
private void pasteNewIsland(Player player, Location to, Island island, Environment env) {
|
|
|
|
// Paste then teleport player
|
2019-09-15 23:10:52 +02:00
|
|
|
plugin.getIWM().getAddon(island.getWorld()).ifPresent(addon -> {
|
|
|
|
// Get the default bundle's nether or end blueprint
|
|
|
|
BlueprintBundle bb = plugin.getBlueprintsManager().getDefaultBlueprintBundle(addon);
|
|
|
|
if (bb != null) {
|
|
|
|
Blueprint bp = plugin.getBlueprintsManager().getBlueprints(addon).get(bb.getBlueprint(env));
|
|
|
|
if (bp != null) {
|
|
|
|
new BlueprintPaster(plugin, bp,
|
|
|
|
to.getWorld(),
|
2020-06-22 00:01:30 +02:00
|
|
|
island).paste().thenAccept(b -> new SafeSpotTeleport.Builder(plugin)
|
|
|
|
.entity(player)
|
|
|
|
.location(island.getSpawnPoint(env) == null ? to : island.getSpawnPoint(env))
|
|
|
|
// No need to use portal because there will be no portal on the other end
|
|
|
|
.build());
|
2019-09-15 23:10:52 +02:00
|
|
|
} else {
|
|
|
|
plugin.logError("Could not paste default island in nether or end. Is there a nether-island or end-island blueprint?");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2019-06-10 01:20:08 +02:00
|
|
|
}
|
2019-02-27 14:25:32 +01:00
|
|
|
}
|