Completed nether portals

Also fixed some issues around admin commands and the teleport admin
commands in particular.
This commit is contained in:
Tastybento 2018-02-11 11:12:56 -08:00
parent b9c262fd5c
commit c07b649488
13 changed files with 123 additions and 139 deletions

View File

@ -19,6 +19,7 @@ general:
use-in-game: "&cThis command is only available in game."
no-team: "&cYou do not have a team!"
no-island: "&cYou do not have an island!"
player-has-no-island: "&cThat player has no island!"
already-have-island: "&cYou already have an island!"
no-safe-location: "&cNo safe location found on island!"
not-leader: "&cYou are not the leader of your island!"
@ -31,17 +32,26 @@ general:
commands:
help:
header: "&7=========== &c%bsb_plugin_name% &7==========="
syntax: "&b[usage] &a[parameters] &7: &e[description]"
syntax: "&b[usage] &a[parameters]&7: &e[description]"
end: "&7================================="
parameters: "[command]"
description: "help command"
admin:
help:
description: "Admin command"
description: "admin command"
parameters: ""
version:
description: "display %bsb_plugin_name% and addons versions"
setrange:
parameters: "[player] [range]"
description: "set the range of player's island"
range-updated: "Island range updated to [number]"
reload:
description: "reload the plugin"
tp:
parameters: "[player]"
description: "teleport to a player's island"
manual: "&cNo safe warp found! Manually tp near to &b[location] &cand check it out"
island:
about:
description: "display info about %bsb_plugin_name%"

View File

@ -162,7 +162,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
return true;
}
// Check perms, but only if this isn't the console
if ((sender instanceof Player) && !cmd.getPermission().isEmpty() && !sender.hasPermission(cmd.getPermission())) {
if ((sender instanceof Player) && !sender.isOp() && !cmd.getPermission().isEmpty() && !sender.hasPermission(cmd.getPermission())) {
user.sendMessage("general.errors.no-permission");
return true;
}
@ -469,12 +469,11 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
* Show help
* @param command
* @param user
* @param args
*/
protected void showHelp(CompositeCommand command, User user, List<String> args) {
protected void showHelp(CompositeCommand command, User user) {
Optional<CompositeCommand> helpCommand = command.getSubCommand("help");
if (helpCommand.isPresent()) {
helpCommand.get().execute(user, args);
helpCommand.get().execute(user, new ArrayList<>());
}
}
}

View File

@ -19,16 +19,19 @@ public class AdminCommand extends CompositeCommand {
public void setup() {
setPermission(Constants.PERMPREFIX + "admin.*");
setOnlyPlayer(false);
setParameters("commands.admin.help.parameters");
setDescription("commands.admin.help.description");
new AdminVersionCommand(this);
new AdminReloadCommand(this);
new AdminTeleportCommand(this);
new AdminTeleportCommand(this, "tp");
new AdminTeleportCommand(this, "tpnether");
new AdminTeleportCommand(this, "tpend");
}
@Override
public boolean execute(User user, List<String> args) {
// By default run the attached help command, if it exists (it should)
showHelp(this, user, args);
showHelp(this, user);
return false;
}

View File

@ -1,4 +0,0 @@
package us.tastybento.bskyblock.commands.admin;
public class AdminDeleteCommand {
}

View File

@ -11,33 +11,34 @@ import org.bukkit.Location;
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;
import us.tastybento.bskyblock.util.teleport.SafeTeleportBuilder;
public class AdminTeleportCommand extends CompositeCommand {
public AdminTeleportCommand(CompositeCommand parent) {
super(parent, "tp", "tpnether", "tpend");
public AdminTeleportCommand(CompositeCommand parent, String tpCommand) {
super(parent, tpCommand);
}
@Override
public void setup() {
setPermission(Constants.PERMPREFIX + "admin.tp");
setOnlyPlayer(true);
setParameters("commands.admin.tp.parameters");
setDescription("commands.admin.tp.description");
}
@Override
public boolean execute(User user, List<String> args) {
if (args.isEmpty()) {
user.sendMessage("commands.admin.tp.help");
this.showHelp(this, user);
return true;
}
// Convert name to a UUID
final UUID targetUUID = getPlayers().getUUID(args.get(0));
if (targetUUID == null) {
user.sendMessage("errors.unknown-player");
user.sendMessage("general.errors.unknown-player");
return false;
} else {
if (getPlayers().hasIsland(targetUUID) || getPlayers().inTeam(targetUUID)) {
@ -56,7 +57,7 @@ public class AdminTeleportCommand extends CompositeCommand {
.build();
return true;
}
user.sendMessage("command.admin.tp.no-island");
user.sendMessage("general.errors.player-has-no-island");
return false;
}
}

View File

@ -51,7 +51,7 @@ public class IslandSetnameCommand extends CompositeCommand {
}
// Explain command
if (args.isEmpty()) {
showHelp(this, user, args);
showHelp(this, user);
return false;
}

View File

@ -53,7 +53,7 @@ public class IslandTeamInviteCommand extends AbstractIslandTeamCommand {
return true;
}
// Show help
showHelp(this, user, args);
showHelp(this, user);
return false;
} else {
// Only online players can be invited

View File

@ -39,7 +39,7 @@ public class IslandTeamKickCommand extends AbstractIslandTeamCommand {
}
// If args are not right, show help
if (args.size() != 1) {
showHelp(this, user, args);
showHelp(this, user);
return false;
}
// Get target

View File

@ -42,7 +42,7 @@ public class IslandTeamSetownerCommand extends AbstractIslandTeamCommand {
}
// If args are not right, show help
if (args.size() != 1) {
showHelp(this, user, args);
showHelp(this, user);
return false;
}
//getPlugin().getLogger().info("DEBUG: arg[0] = " + args.get(0));

View File

@ -27,8 +27,8 @@ import us.tastybento.bskyblock.database.BSBDatabase;
import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.util.DeleteIslandChunks;
import us.tastybento.bskyblock.util.SafeTeleportBuilder;
import us.tastybento.bskyblock.util.Util;
import us.tastybento.bskyblock.util.teleport.SafeTeleportBuilder;
/**
* The job of this class is manage all island related data.

View File

@ -24,7 +24,7 @@ import org.bukkit.util.Vector;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.util.SafeTeleportBuilder;
import us.tastybento.bskyblock.util.teleport.SafeTeleportBuilder;
public class NetherPortals implements Listener {
private final BSkyBlock plugin;
@ -194,14 +194,19 @@ public class NetherPortals implements Listener {
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)) {
plugin.getLogger().info("Entered portal in nether or end");
if (plugin.getIslands().hasIsland(event.getPlayer().getUniqueId())) {
plugin.getLogger().info("player has island - teleporting home");
event.setCancelled(true);
plugin.getIslands().homeTeleport(event.getPlayer());
}
// If entering a portal in the nether, teleport to portal in overworld if there is one
if (event.getFrom().getWorld().equals(nether)) {
plugin.getLogger().info("Entered portal in nether");
// If this is island nether, then go to the same vector, otherwise try spawn
Location to = plugin.getSettings().isNetherIslands() ? event.getFrom().toVector().toLocation(world) : plugin.getIslands().getIslandLocation(event.getPlayer().getUniqueId());
plugin.getLogger().info("Going to " + to);
event.setCancelled(true);
// Else other worlds teleport to the nether
new SafeTeleportBuilder(plugin)
.entity(event.getPlayer())
.location(to)
.portal()
.build();
return;
}
plugin.getLogger().info("Entering nether portal in overworld");

View File

@ -1,4 +1,4 @@
package us.tastybento.bskyblock.util;
package us.tastybento.bskyblock.util.teleport;
import java.util.ArrayList;
import java.util.Iterator;
@ -18,6 +18,7 @@ import org.bukkit.util.Vector;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.util.Pair;
/**
* A class that calculates finds a safe spot asynchronously and then teleports the player there.
@ -26,8 +27,8 @@ import us.tastybento.bskyblock.database.objects.Island;
*/
public class SafeSpotTeleport {
private static final int MAX_CHUNKS = 10;
private static final long SPEED = 10;
private static final int MAX_CHUNKS = 50;
private static final long SPEED = 5;
private boolean checking = true;
private BukkitTask task;
@ -49,11 +50,11 @@ public class SafeSpotTeleport {
* @param plugin
* @param entity
* @param location
* @param failureMessage
* @param failureMessage - already translated failure message
* @param portal
* @param homeNumber
*/
public SafeSpotTeleport(BSkyBlock plugin, Entity entity, Location location, String failureMessage, boolean portal,
protected SafeSpotTeleport(BSkyBlock plugin, Entity entity, Location location, String failureMessage, boolean portal,
int homeNumber) {
this.plugin = plugin;
this.entity = entity;
@ -61,10 +62,8 @@ public class SafeSpotTeleport {
this.portal = portal;
this.homeNumber = homeNumber;
plugin.getLogger().info("Safe teleport called");
// Put player into spectator mode
if (entity instanceof Player && ((Player)entity).getGameMode().equals(GameMode.SURVIVAL)) {
Bukkit.getLogger().info("Put player into spectator mode");
((Player)entity).setGameMode(GameMode.SPECTATOR);
}
@ -78,11 +77,8 @@ public class SafeSpotTeleport {
task = plugin.getServer().getScheduler().runTaskTimer(plugin, () -> {
List<ChunkSnapshot> chunkSnapshot = new ArrayList<>();
if (checking) {
Bukkit.getLogger().info("Checking");
Iterator<Pair<Integer, Integer>> it = chunksToScan.iterator();
if (!it.hasNext()) {
// TODO REMOVE
Bukkit.getLogger().info("Nothing left!");
// Nothing left
tidyUp(entity, failureMessage);
return;
@ -96,8 +92,6 @@ public class SafeSpotTeleport {
// Move to next step
checking = false;
checkChunks(chunkSnapshot);
} else {
Bukkit.getLogger().info("Not checking");
}
}, 0L, SPEED);
}
@ -164,18 +158,15 @@ public class SafeSpotTeleport {
* @param chunkSnapshot
*/
private void checkChunks(List<ChunkSnapshot> chunkSnapshot) {
Bukkit.getLogger().info("Chunksnapshot = " + chunkSnapshot.size());
// Run async task to scan chunks
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
for (ChunkSnapshot chunk: chunkSnapshot) {
if (scanChunk(chunk)) {
Bukkit.getLogger().info("Safe sport found!");
task.cancel();
return;
}
}
Bukkit.getLogger().info("not found in initial list");
// Nothing happened, change state
checking = true;
});
@ -187,7 +178,6 @@ public class SafeSpotTeleport {
* @return true if a safe spot was found
*/
private boolean scanChunk(ChunkSnapshot chunk) {
Bukkit.getLogger().info("Scanning chunk " + chunk.getX() + " " + chunk.getZ());
// Max height
int maxHeight = location.getWorld().getMaxHeight() - 20;
// Run through the chunk
@ -196,7 +186,6 @@ public class SafeSpotTeleport {
// Work down from the entry point up
for (int y = Math.min(chunk.getHighestBlockYAt(x, z), maxHeight); y >= 0; y--) {
if (checkBlock(chunk, x,y,z, maxHeight)) {
Bukkit.getLogger().info("Check block returned true");
return true;
}
} // end y
@ -209,17 +198,14 @@ public class SafeSpotTeleport {
* Teleports entity to the safe spot
*/
private void teleportEntity(Location loc) {
Bukkit.getLogger().info("Teleporting!");
task.cancel();
// Return to main thread and teleport the player
plugin.getServer().getScheduler().runTask(plugin, () -> {
if (!portal && entity instanceof Player) {
Bukkit.getLogger().info("Setting home");
// Set home
plugin.getPlayers().setHomeLocation(entity.getUniqueId(), loc, homeNumber);
}
Vector velocity = entity.getVelocity();
Bukkit.getLogger().info("Teleported!");
entity.teleport(loc);
// Exit spectator mode if in it
if (entity instanceof Player) {
@ -234,34 +220,6 @@ public class SafeSpotTeleport {
}
/**
* Subscan to find the bottom of the portal
*/
/*
private Location checkPortal() {
if (portalPart == null) {
return;
}
// There is a portal available, but is it safe?
// Get the lowest portal spot
int x = portalPart.getBlockX();
int y = portalPart.getBlockY();
int z = portalPart.getBlockZ();
while (portalChunk.getBlockType(x,y,z).equals(Material.PORTAL)) {
y--;
}
//System.out.print("DEBUG: Portal teleport loc = " + (16 * portalChunk.getX() + x) + "," + (y) + "," + (16 * portalChunk.getZ() + z));
// Now check if this is a safe location
if (checkBlock(portalChunk,x,y,z, worldHeight)) {
// Yes, so use this instead of the highest location
//System.out.print("DEBUG: Portal is safe");
safeSpotFound = true;
safeSpotInChunk = new Vector(x,y,z);
safeChunk = portalChunk;
}
}*/
/**
* Returns true if the location is a safe one.
* @param chunk
@ -277,64 +235,62 @@ public class SafeSpotTeleport {
if (!type.equals(Material.AIR)) { // AIR
Material space1 = chunk.getBlockType(x, Math.min(y + 1, worldHeight), z);
Material space2 = chunk.getBlockType(x, Math.min(y + 2, worldHeight), z);
if ((space1.equals(Material.AIR) && space2.equals(Material.AIR)) || (space1.equals(Material.PORTAL) && space2.equals(Material.PORTAL))) {
if (!type.toString().contains("FENCE") && !type.toString().contains("DOOR") && !type.toString().contains("GATE") && !type.toString().contains("PLATE")) {
Bukkit.getLogger().info("Checking " + type);
switch (type) {
// Unsafe
case ANVIL:
case BARRIER:
case BOAT:
case CACTUS:
case DOUBLE_PLANT:
case ENDER_PORTAL:
case FIRE:
case FLOWER_POT:
case LADDER:
case LAVA:
case LEVER:
case LONG_GRASS:
case PISTON_EXTENSION:
case PISTON_MOVING_PIECE:
case SIGN_POST:
case SKULL:
case STANDING_BANNER:
case STATIONARY_LAVA:
case STATIONARY_WATER:
case STONE_BUTTON:
case TORCH:
case TRIPWIRE:
case WATER:
case WEB:
case WOOD_BUTTON:
//Block is dangerous
break;
case PORTAL:
if (portal) {
Bukkit.getLogger().info("Portal found");
Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D);
// Teleport as soon as we find a portal
teleportEntity(newSpot.toLocation(world));
return true;
}
break;
default:
// Safe
if ((space1.equals(Material.AIR) && space2.equals(Material.AIR)) || (space1.equals(Material.PORTAL) && space2.equals(Material.PORTAL))
&& (!type.toString().contains("FENCE") && !type.toString().contains("DOOR") && !type.toString().contains("GATE") && !type.toString().contains("PLATE"))) {
switch (type) {
// Unsafe
case ANVIL:
case BARRIER:
case BOAT:
case CACTUS:
case DOUBLE_PLANT:
case ENDER_PORTAL:
case FIRE:
case FLOWER_POT:
case LADDER:
case LAVA:
case LEVER:
case LONG_GRASS:
case PISTON_EXTENSION:
case PISTON_MOVING_PIECE:
case SIGN_POST:
case SKULL:
case STANDING_BANNER:
case STATIONARY_LAVA:
case STATIONARY_WATER:
case STONE_BUTTON:
case TORCH:
case TRIPWIRE:
case WATER:
case WEB:
case WOOD_BUTTON:
//Block is dangerous
break;
case PORTAL:
if (portal) {
Bukkit.getLogger().info("Portal found");
Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D);
// Check for portal
if (portal) {
if (bestSpot == null) {
Bukkit.getLogger().info("Best spot found = " + bestSpot);
// Stash the best spot
bestSpot = newSpot.toLocation(world);
return false;
}
} else {
// Regular search - teleport as soon as we find something
Bukkit.getLogger().info("Safe spot found, teleporting to new spot");
teleportEntity(newSpot.toLocation(world));
return true;
// Teleport as soon as we find a portal
teleportEntity(newSpot.toLocation(world));
return true;
}
break;
default:
// Safe
Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D);
// Check for portal
if (portal) {
if (bestSpot == null) {
Bukkit.getLogger().info("Best spot found = " + bestSpot);
// Stash the best spot
bestSpot = newSpot.toLocation(world);
return false;
}
} else {
// Regular search - teleport as soon as we find something
Bukkit.getLogger().info("Safe spot found, teleporting to new spot");
teleportEntity(newSpot.toLocation(world));
return true;
}
}
}

View File

@ -1,9 +1,11 @@
package us.tastybento.bskyblock.util;
package us.tastybento.bskyblock.util.teleport;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.database.objects.Island;
public class SafeTeleportBuilder {
@ -12,7 +14,7 @@ public class SafeTeleportBuilder {
private Entity entity;
private int homeNumber = 0;
private boolean portal = false;
private String failureMessage = "general.errors.warp-not-safe";
private String failureMessage = "";
private Location location;
@ -84,7 +86,19 @@ public class SafeTeleportBuilder {
* Try to teleport the player
* @return
*/
public SafeSpotTeleport build() {
public SafeSpotTeleport build() {
// Error checking
if (entity == null) {
plugin.getLogger().severe("Attempt to safe teleport a null entity!");
return null;
}
if (location == null) {
plugin.getLogger().severe("Attempt to safe teleport to a null location!");
return null;
}
if (failureMessage.isEmpty() && entity instanceof Player) {
failureMessage = User.getInstance(entity).getTranslation("general.errors.warp-not-safe");
}
return new SafeSpotTeleport(plugin, entity, location, failureMessage, portal, homeNumber);
}