diff --git a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java index 6a5cfe4c2..b0ea1348a 100755 --- a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java +++ b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java @@ -11,6 +11,7 @@ import us.tastybento.bskyblock.database.managers.PlayersManager; import us.tastybento.bskyblock.database.managers.island.IslandsManager; import us.tastybento.bskyblock.generators.IslandWorld; import us.tastybento.bskyblock.listeners.JoinLeaveListener; +import us.tastybento.bskyblock.listeners.NetherPortals; import us.tastybento.bskyblock.listeners.PanelListenerManager; import us.tastybento.bskyblock.managers.AddonsManager; import us.tastybento.bskyblock.managers.CommandsManager; @@ -118,11 +119,17 @@ public class BSkyBlock extends JavaPlugin { + /** + * Register listeners + */ private void registerListeners() { PluginManager manager = getServer().getPluginManager(); // Player join events manager.registerEvents(new JoinLeaveListener(this), this); + // Panel listener manager manager.registerEvents(new PanelListenerManager(), this); + // Nether portals + manager.registerEvents(new NetherPortals(this), this); } @Override diff --git a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java index 661a22b4b..6f14c89d6 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/admin/AdminTeleportCommand.java @@ -1,6 +1,9 @@ package us.tastybento.bskyblock.commands.admin; +import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.UUID; import org.bukkit.Location; @@ -9,6 +12,7 @@ import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.util.SafeTeleportBuilder; +import us.tastybento.bskyblock.util.Util; public class AdminTeleportCommand extends CompositeCommand { @@ -56,5 +60,17 @@ public class AdminTeleportCommand extends CompositeCommand { return false; } } + + @Override + public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + List options = new ArrayList<>(); + String lastArg = (!args.isEmpty() ? args.getLast() : ""); + if (args.isEmpty()) { + // Don't show every player on the server. Require at least the first letter + return Optional.empty(); + } + options.addAll(Util.getOnlinePlayerList(user)); + return Optional.of(Util.tabLimit(options, lastArg)); + } } diff --git a/src/main/java/us/tastybento/bskyblock/database/managers/island/IslandsManager.java b/src/main/java/us/tastybento/bskyblock/database/managers/island/IslandsManager.java index 202f35248..26337fe84 100644 --- a/src/main/java/us/tastybento/bskyblock/database/managers/island/IslandsManager.java +++ b/src/main/java/us/tastybento/bskyblock/database/managers/island/IslandsManager.java @@ -627,7 +627,6 @@ public class IslandsManager { // Try to fix this teleport location and teleport the player if possible new SafeTeleportBuilder(plugin).entity(player) .island(plugin.getIslands().getIsland(player.getUniqueId())) - .portal(false) .homeNumber(number) .build(); return; diff --git a/src/main/java/us/tastybento/bskyblock/listeners/NetherPortals.java b/src/main/java/us/tastybento/bskyblock/listeners/NetherPortals.java new file mode 100644 index 000000000..e43621e74 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/NetherPortals.java @@ -0,0 +1,238 @@ +package us.tastybento.bskyblock.listeners; + +import java.util.Iterator; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityPortalEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerPortalEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.util.Vector; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.commands.User; +import us.tastybento.bskyblock.util.SafeTeleportBuilder; + +public class NetherPortals implements Listener { + private final BSkyBlock plugin; + private World world; + private World nether; + private World the_end; + + public NetherPortals(BSkyBlock plugin) { + this.plugin = plugin; + world = plugin.getIslandWorldManager().getIslandWorld(); + nether = plugin.getIslandWorldManager().getNetherWorld(); + the_end = plugin.getIslandWorldManager().getEndWorld(); + } + + /** + * Function to check proximity to nether spawn location + * + * @param location + * @return true if in the spawn area, false if not + */ + private boolean awayFromSpawn(Location location) { + Vector p = location.toVector().multiply(new Vector(1, 0, 1)); + Vector spawn = location.getWorld().getSpawnLocation().toVector().multiply(new Vector(1, 0, 1)); + if (spawn.distanceSquared(p) < (plugin.getSettings().getNetherSpawnRadius() * plugin.getSettings().getNetherSpawnRadius())) { + return false; + } else { + return true; + } + } + + private boolean inWorlds(Location from) { + return (from.getWorld().equals(world) || from.getWorld().equals(nether) || from.getWorld().equals(the_end)) ? true : false; + } + + private boolean noAction(Player player) { + if (player.isOp() + || (!player.getWorld().equals(nether) && !player.getWorld().equals(the_end)) + || (player.getWorld().equals(nether) && plugin.getSettings().isNetherIslands()) + || (player.getWorld().equals(the_end) && plugin.getSettings().isEndIslands())) { + return true; + } + return false; + } + + + /** + * Prevents blocks from being broken + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + if (noAction(event.getPlayer())) { + return; + } + if (!awayFromSpawn(event.getBlock().getLocation())) { + User.getInstance(event.getPlayer()).sendMessage("errors.general.no-permission"); + event.setCancelled(true); + } + } + + // Nether portal spawn protection + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBucketEmpty(PlayerBucketEmptyEvent event) { + if (noAction(event.getPlayer())) { + return; + } + if (!awayFromSpawn(event.getBlockClicked().getLocation())) { + User.getInstance(event.getPlayer()).sendMessage("errors.general.no-permission"); + event.setCancelled(true); + } + } + + /** + * Handle end portals + * @param event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEndIslandPortal(PlayerPortalEvent event) { + if (!event.getCause().equals(TeleportCause.END_PORTAL) || !plugin.getSettings().isEndGenerate()) { + return; + } + if (!inWorlds(event.getFrom())) { + return; + } + // If entering a portal in the end, teleport home if you have one, else do nothing + if (event.getFrom().getWorld().equals(the_end)) { + if (plugin.getIslands().hasIsland(event.getPlayer().getUniqueId())) { + plugin.getIslands().homeTeleport(event.getPlayer()); + } + return; + } + // If this is island end, then go to the same location, otherwise try spawn + Location to = plugin.getSettings().isEndIslands() ? event.getFrom().toVector().toLocation(the_end) : the_end.getSpawnLocation(); + // Else other worlds teleport to the end + new SafeTeleportBuilder(plugin) + .entity(event.getPlayer()) + .location(to) + .build(); + return; + } + + /** + * This handles non-player portal use + * Currently disables portal use by entities + * + * @param event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEntityPortal(EntityPortalEvent event) { + if (inWorlds(event.getFrom())) { + // Disable entity portal transfer due to dupe glitching + event.setCancelled(true); + } + } + + /** + * Prevent spawns from being blown up + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onExplosion(EntityExplodeEvent event) { + if (!inWorlds(event.getLocation())) { + return; + } + if ((event.getLocation().getWorld().equals(nether) && plugin.getSettings().isNetherIslands()) + || (event.getLocation().getWorld().equals(the_end) && plugin.getSettings().isEndIslands())) { + // Not used in island worlds + return; + } + // Find out what is exploding + Entity expl = event.getEntity(); + if (expl == null) { + return; + } + Iterator it = event.blockList().iterator(); + while (it.hasNext()) { + Block b = it.next(); + if (!awayFromSpawn(b.getLocation())) { + it.remove(); + } + } + } + + /** + * Handle nether portals + * @param event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onNetherPortal(PlayerPortalEvent event) { + if (!event.getCause().equals(TeleportCause.NETHER_PORTAL)) { + return; + } + if (!inWorlds(event.getFrom())) { + return; + } + // If entering a portal in the nether or end, teleport home if you have one, else do nothing + if (!event.getFrom().getWorld().equals(world)) { + if (plugin.getIslands().hasIsland(event.getPlayer().getUniqueId())) { + plugin.getIslands().homeTeleport(event.getPlayer()); + } + return; + } + // If this is island nether, then go to the same vector, otherwise try spawn + Location to = plugin.getSettings().isNetherIslands() ? event.getFrom().toVector().toLocation(nether) : nether.getSpawnLocation(); + // Else other worlds teleport to the nether + new SafeTeleportBuilder(plugin) + .entity(event.getPlayer()) + .location(to) + .portal() + .build(); + return; + } + + /** + * Prevents placing of blocks + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerBlockPlace(BlockPlaceEvent event) { + if (noAction(event.getPlayer())) { + return; + } + if (!awayFromSpawn(event.getBlock().getLocation())) { + User.getInstance(event.getPlayer()).sendMessage("errors.general.no-permission"); + event.setCancelled(true); + } + } + + /** + * Converts trees to gravel and glowstone + * + * @param event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onTreeGrow(StructureGrowEvent event) { + if (!plugin.getSettings().isNetherTrees() || !event.getWorld().equals(nether)) { + return; + } + for (BlockState b : event.getBlocks()) { + if (b.getType() == Material.LOG || b.getType() == Material.LOG_2) { + b.setType(Material.GRAVEL); + } else if (b.getType() == Material.LEAVES || b.getType() == Material.LEAVES_2) { + b.setType(Material.GLOWSTONE); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java b/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java index 6f116e74c..bd40da15d 100644 --- a/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java +++ b/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java @@ -257,8 +257,6 @@ public class SafeSpotTeleport { */ private boolean checkBlock(ChunkSnapshot chunk, int x, int y, int z, int worldHeight) { World world = location.getWorld(); - - Bukkit.getLogger().info("checking " + x + " " + y + " "+ z); Material type = chunk.getBlockType(x, y, z); if (!type.equals(Material.AIR)) { // AIR Material space1 = chunk.getBlockType(x, Math.min(y + 1, worldHeight), z); diff --git a/src/main/java/us/tastybento/bskyblock/util/SafeTeleportBuilder.java b/src/main/java/us/tastybento/bskyblock/util/SafeTeleportBuilder.java index 0489ca453..7915bde5f 100644 --- a/src/main/java/us/tastybento/bskyblock/util/SafeTeleportBuilder.java +++ b/src/main/java/us/tastybento/bskyblock/util/SafeTeleportBuilder.java @@ -55,8 +55,8 @@ public class SafeTeleportBuilder { * @param setHome * @return */ - public SafeTeleportBuilder portal(boolean portal) { - this.portal = portal; + public SafeTeleportBuilder portal() { + this.portal = true; return this; }