/*
* Copyright (C) 2016 eccentric_nz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.eccentric_nz.TARDIS.commands;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import me.eccentric_nz.TARDIS.TARDIS;
import me.eccentric_nz.TARDIS.advanced.TARDISSerializeInventory;
import me.eccentric_nz.TARDIS.api.Parameters;
import me.eccentric_nz.TARDIS.database.QueryFactory;
import me.eccentric_nz.TARDIS.database.ResultSetAreas;
import me.eccentric_nz.TARDIS.database.ResultSetBackLocation;
import me.eccentric_nz.TARDIS.database.ResultSetCurrentLocation;
import me.eccentric_nz.TARDIS.database.ResultSetDestinations;
import me.eccentric_nz.TARDIS.database.ResultSetDiskStorage;
import me.eccentric_nz.TARDIS.database.ResultSetHomeLocation;
import me.eccentric_nz.TARDIS.database.ResultSetPlayerPrefs;
import me.eccentric_nz.TARDIS.database.ResultSetTardis;
import me.eccentric_nz.TARDIS.database.ResultSetTravellers;
import me.eccentric_nz.TARDIS.database.data.Tardis;
import me.eccentric_nz.TARDIS.enumeration.DIFFICULTY;
import me.eccentric_nz.TARDIS.enumeration.FLAG;
import me.eccentric_nz.TARDIS.flight.TARDISLand;
import me.eccentric_nz.TARDIS.listeners.TARDISBiomeReaderListener;
import me.eccentric_nz.TARDIS.travel.TARDISCaveFinder;
import me.eccentric_nz.TARDIS.travel.TARDISRescue;
import me.eccentric_nz.TARDIS.travel.TARDISTimeTravel;
import me.eccentric_nz.TARDIS.travel.TARDISTravelRequest;
import me.eccentric_nz.TARDIS.travel.TARDISVillageTravel;
import me.eccentric_nz.TARDIS.utility.TARDISMessage;
import me.eccentric_nz.TARDIS.utility.TARDISNumberParsers;
import me.eccentric_nz.TARDIS.utility.TARDISWorldBorderChecker;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/**
* Command /tardistravel [arguments].
*
* Time travel is the process of travelling through time, even in a non-linear
* direction.
*
* @author eccentric_nz
*/
public class TARDISTravelCommands implements CommandExecutor {
private final TARDIS plugin;
private final List<String> BIOME_SUBS = new ArrayList<String>();
private final List<String> mustUseAdvanced = Arrays.asList("area", "biome", "dest");
private final List<String> costs = Arrays.asList("random", "random_circuit", "travel", "comehere", "hide", "rebuild", "autonomous", "backdoor");
public TARDISTravelCommands(TARDIS plugin) {
this.plugin = plugin;
for (Biome bi : Biome.values()) {
if (!bi.equals(Biome.HELL) && !bi.equals(Biome.SKY) && !bi.equals(Biome.VOID)) {
BIOME_SUBS.add(bi.toString());
}
}
}
@Override
@SuppressWarnings("deprecation")
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
Player player = null;
if (sender instanceof Player) {
player = (Player) sender;
}
// If the player typed /tardistravel then do the following...
// check there is the right number of arguments
if (cmd.getName().equalsIgnoreCase("tardistravel")) {
if (player == null) {
TARDISMessage.send(sender, "CMD_PLAYER");
return true;
}
if (player.hasPermission("tardis.timetravel")) {
if (args.length < 1) {
new TARDISCommandHelper(plugin).getCommand("tardistravel", sender);
return true;
}
QueryFactory qf = new QueryFactory(plugin);
TARDISTimeTravel tt = new TARDISTimeTravel(plugin);
// get tardis data
HashMap<String, Object> where = new HashMap<String, Object>();
where.put("uuid", player.getUniqueId().toString());
ResultSetTardis rs = new ResultSetTardis(plugin, where, "", false, 0);
if (!rs.resultSet()) {
TARDISMessage.send(player, "NO_TARDIS");
return true;
}
Tardis tardis = rs.getTardis();
int id = tardis.getTardis_id();
if (plugin.getTrackerKeeper().getInSiegeMode().contains(id)) {
TARDISMessage.send(player, "SIEGE_NO_CMD");
return true;
}
int level = tardis.getArtron_level();
boolean powered = tardis.isPowered_on();
if (!tardis.isHandbrake_on() && !plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
TARDISMessage.send(player, "NOT_WHILE_TRAVELLING");
return true;
}
HashMap<String, Object> wheret = new HashMap<String, Object>();
wheret.put("uuid", player.getUniqueId().toString());
ResultSetTravellers rst = new ResultSetTravellers(plugin, wheret, false);
if (!rst.resultSet()) {
TARDISMessage.send(player, "NOT_IN_TARDIS");
return true;
}
int tardis_id = rst.getTardis_id();
if (tardis_id != id) {
TARDISMessage.send(player, "CMD_ONLY_TL");
return true;
}
if (plugin.getConfig().getBoolean("allow.power_down") && !powered) {
TARDISMessage.send(player, "POWER_DOWN");
return true;
}
int travel = plugin.getArtronConfig().getInt("travel");
if (level < travel) {
TARDISMessage.send(player, "NOT_ENOUGH_ENERGY");
return true;
}
HashMap<String, Object> tid = new HashMap<String, Object>();
HashMap<String, Object> set = new HashMap<String, Object>();
tid.put("tardis_id", id);
if (player.hasPermission("tardis.exile") && plugin.getConfig().getBoolean("travel.exile")) {
// get the exile area
String permArea = plugin.getTardisArea().getExileArea(player);
TARDISMessage.send(player, "EXILE", permArea);
Location l = plugin.getTardisArea().getNextSpot(permArea);
if (l == null) {
TARDISMessage.send(player, "NO_MORE_SPOTS");
return true;
}
set.put("world", l.getWorld().getName());
set.put("x", l.getBlockX());
set.put("y", l.getBlockY());
set.put("z", l.getBlockZ());
set.put("submarine", 0);
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "TRAVEL_APPROVED", permArea);
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
return true;
} else {
if (args.length == 1) {
if (args[0].equalsIgnoreCase("cancel")) {
if (plugin.getTrackerKeeper().getHasDestination().containsKey(id)) {
plugin.getTrackerKeeper().getHasDestination().remove(id);
TARDISMessage.send(player, "TRAVEL_CANCEL");
} else {
TARDISMessage.send(player, "TRAVEL_NEED_DEST");
}
return true;
}
if (args[0].equalsIgnoreCase("costs")) {
TARDISMessage.send(player, "TRAVEL_COSTS");
for (String s : costs) {
String c = (s.equals("rebuild")) ? plugin.getArtronConfig().getString("random") : plugin.getArtronConfig().getString(s);
TARDISMessage.message(player, " " + s + ": " + ChatColor.AQUA + c);
}
return true;
}
// we're thinking this is a player's name or home / back / cave
if (args[0].equalsIgnoreCase("home") || args[0].equalsIgnoreCase("back") || args[0].equalsIgnoreCase("cave") || args[0].equalsIgnoreCase("village")) {
String which;
if (args[0].equalsIgnoreCase("home")) {
// get home location
HashMap<String, Object> wherehl = new HashMap<String, Object>();
wherehl.put("tardis_id", id);
ResultSetHomeLocation rsh = new ResultSetHomeLocation(plugin, wherehl);
if (!rsh.resultSet()) {
TARDISMessage.send(player, "HOME_NOT_FOUND");
return true;
}
set.put("world", rsh.getWorld().getName());
set.put("x", rsh.getX());
set.put("y", rsh.getY());
set.put("z", rsh.getZ());
set.put("direction", rsh.getDirection().toString());
set.put("submarine", (rsh.isSubmarine()) ? 1 : 0);
which = "Home";
} else if (args[0].equalsIgnoreCase("back")) {
// get fast return location
HashMap<String, Object> wherebl = new HashMap<String, Object>();
wherebl.put("tardis_id", id);
ResultSetBackLocation rsb = new ResultSetBackLocation(plugin, wherebl);
if (!rsb.resultSet()) {
TARDISMessage.send(player, "PREV_NOT_FOUND");
return true;
}
set.put("world", rsb.getWorld().getName());
set.put("x", rsb.getX());
set.put("y", rsb.getY());
set.put("z", rsb.getZ());
set.put("direction", rsb.getDirection().toString());
set.put("submarine", (rsb.isSubmarine()) ? 1 : 0);
which = "Fast Return to " + ChatColor.GREEN + "(" + rsb.getWorld().getName() + ":" + rsb.getX() + ":" + rsb.getY() + ":" + rsb.getZ() + ")" + ChatColor.RESET;
} else if (args[0].equalsIgnoreCase("cave")) {
if (!player.hasPermission("tardis.timetravel.cave")) {
TARDISMessage.send(player, "TRAVEL_NO_PERM_CAVE");
return true;
}
// find a cave
Location cave = new TARDISCaveFinder(plugin).searchCave(player, id);
if (cave == null) {
TARDISMessage.send(player, "CAVE_NOT_FOUND");
return true;
}
// check respect
if (!plugin.getPluginRespect().getRespect(cave, new Parameters(player, FLAG.getDefaultFlags()))) {
if (plugin.getConfig().getBoolean("travel.no_destination_malfunctions")) {
plugin.getTrackerKeeper().getMalfunction().put(id, true);
} else {
return true;
}
}
set.put("world", cave.getWorld().getName());
set.put("x", cave.getBlockX());
set.put("y", cave.getBlockY());
set.put("z", cave.getBlockZ());
set.put("submarine", 0);
which = "Cave";
} else {
if (!plugin.getConfig().getBoolean("allow.village_travel")) {
TARDISMessage.send(player, "TRAVEL_NO_VILLAGE");
return true;
}
if (!player.hasPermission("tardis.timetravel.village")) {
TARDISMessage.send(player, "TRAVEL_NO_PERM_VILLAGE");
return true;
}
// find a village
Location village = new TARDISVillageTravel(plugin).getRandomVillage(player, id);
if (village == null) {
TARDISMessage.send(player, "VILLAGE_NOT_FOUND");
return true;
}
// check respect
if (!plugin.getPluginRespect().getRespect(village, new Parameters(player, FLAG.getDefaultFlags()))) {
if (plugin.getConfig().getBoolean("travel.no_destination_malfunctions")) {
plugin.getTrackerKeeper().getMalfunction().put(id, true);
} else {
return true;
}
}
set.put("world", village.getWorld().getName());
set.put("x", village.getBlockX());
set.put("y", village.getBlockY());
set.put("z", village.getBlockZ());
set.put("submarine", 0);
which = "Village";
}
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "TRAVEL_LOADED", which, !plugin.getTrackerKeeper().getDestinationVortex().containsKey(id));
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
return true;
} else if (player.hasPermission("tardis.timetravel.player")) {
if (!plugin.getDifficulty().equals(DIFFICULTY.EASY) && !plugin.getUtils().inGracePeriod(player, false)) {
TARDISMessage.send(player, "ADV_PLAYER");
return true;
}
if (player.getName().equalsIgnoreCase(args[0])) {
TARDISMessage.send(player, "TRAVEL_NO_SELF");
return true;
}
HashMap<String, Object> wherecl = new HashMap<String, Object>();
wherecl.put("tardis_id", id);
ResultSetCurrentLocation rsc = new ResultSetCurrentLocation(plugin, wherecl);
if (!rsc.resultSet()) {
TARDISMessage.send(player, "CURRENT_NOT_FOUND");
return true;
}
// check the player
Player saved = plugin.getServer().getPlayer(args[0]);
if (saved == null) {
TARDISMessage.send(player, "NOT_ONLINE");
return true;
}
// check the to player's DND status
HashMap<String, Object> wherednd = new HashMap<String, Object>();
wherednd.put("uuid", saved.getUniqueId().toString());
ResultSetPlayerPrefs rspp = new ResultSetPlayerPrefs(plugin, wherednd);
if (rspp.resultSet() && rspp.isDND()) {
TARDISMessage.send(player, "DND", args[0]);
return true;
}
new TARDISRescue(plugin).rescue(player, saved.getUniqueId(), id, tt, rsc.getDirection(), false, false);
return true;
} else {
TARDISMessage.send(player, "NO_PERM_PLAYER");
return true;
}
}
if (args.length == 2 && (args[1].equals("?") || args[1].equalsIgnoreCase("tpa"))) {
if (!player.hasPermission("tardis.timetravel.player")) {
TARDISMessage.send(player, "NO_PERM_PLAYER");
return true;
}
Player requested = plugin.getServer().getPlayer(args[0]);
if (requested == null) {
TARDISMessage.send(player, "NOT_ONLINE");
return true;
}
// check the to player's DND status
HashMap<String, Object> wherednd = new HashMap<String, Object>();
wherednd.put("uuid", requested.getUniqueId().toString());
ResultSetPlayerPrefs rspp = new ResultSetPlayerPrefs(plugin, wherednd);
if (rspp.resultSet() && rspp.isDND()) {
TARDISMessage.send(player, "DND", args[0]);
return true;
}
// check the location
TARDISTravelRequest ttr = new TARDISTravelRequest(plugin);
if (!ttr.getRequest(player, requested, requested.getLocation())) {
return true;
}
// ask if we can travel to this player
final UUID requestedUUID = requested.getUniqueId();
TARDISMessage.send(requested, "REQUEST_TRAVEL", player.getName(), ChatColor.AQUA + "tardis request accept" + ChatColor.RESET);
plugin.getTrackerKeeper().getChat().put(requestedUUID, player.getUniqueId());
final Player p = player;
final String to = args[0];
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
if (plugin.getTrackerKeeper().getChat().containsKey(requestedUUID)) {
plugin.getTrackerKeeper().getChat().remove(requestedUUID);
TARDISMessage.send(p, "REQUEST_NO_RESPONSE", to);
}
}
}, 1200L);
return true;
}
if (args.length == 2 && args[0].equalsIgnoreCase("biome")) {
// we're thinking this is a biome search
if (!player.hasPermission("tardis.timetravel.biome")) {
TARDISMessage.send(player, "TRAVEL_NO_PERM_BIOME");
return true;
}
String upper = args[1].toUpperCase(Locale.ENGLISH);
if (!plugin.getDifficulty().equals(DIFFICULTY.EASY) && mustUseAdvanced.contains(args[0].toLowerCase()) && !plugin.getUtils().inGracePeriod(player, false) && !upper.equals("LIST")) {
if (plugin.getDifficulty().equals(DIFFICULTY.MEDIUM)) {
// check they have a biome disk in storage
boolean hasBiomeDisk = false;
UUID uuid = player.getUniqueId();
HashMap<String, Object> whereb = new HashMap<String, Object>();
whereb.put("uuid", uuid.toString());
ResultSetDiskStorage rsb = new ResultSetDiskStorage(plugin, whereb);
if (rsb.resultSet()) {
try {
ItemStack[] disks1 = TARDISSerializeInventory.itemStacksFromString(rsb.getBiomesOne());
if (TARDISBiomeReaderListener.hasBiomeDisk(disks1, upper)) {
hasBiomeDisk = true;
} else {
ItemStack[] disks2 = TARDISSerializeInventory.itemStacksFromString(rsb.getBiomesTwo());
if (TARDISBiomeReaderListener.hasBiomeDisk(disks2, upper)) {
hasBiomeDisk = true;
}
}
} catch (IOException ex) {
}
}
if (!hasBiomeDisk) {
TARDISMessage.send(player, "BIOME_DISK_NOT_FOUND");
return true;
}
} else {
TARDISMessage.send(player, "ADV_BIOME");
return true;
}
}
if (upper.equals("LIST")) {
StringBuilder buf = new StringBuilder();
for (String bi : BIOME_SUBS) {
buf.append(bi).append(", ");
}
String b = buf.toString().substring(0, buf.length() - 2);
TARDISMessage.send(player, "BIOMES", b);
return true;
} else {
try {
Biome biome = Biome.valueOf(upper);
TARDISMessage.send(player, "BIOME_SEARCH");
HashMap<String, Object> wherecl = new HashMap<String, Object>();
wherecl.put("tardis_id", tardis.getTardis_id());
ResultSetCurrentLocation rsc = new ResultSetCurrentLocation(plugin, wherecl);
if (!rsc.resultSet()) {
TARDISMessage.send(player, "CURRENT_NOT_FOUND");
return true;
}
Location tb = searchBiome(player, id, biome, rsc.getWorld(), rsc.getX() + 5, rsc.getZ() + 5);
if (tb == null) {
TARDISMessage.send(player, "BIOME_NOT_FOUND");
return true;
} else {
if (!plugin.getPluginRespect().getRespect(tb, new Parameters(player, FLAG.getDefaultFlags()))) {
if (plugin.getConfig().getBoolean("travel.no_destination_malfunctions")) {
plugin.getTrackerKeeper().getMalfunction().put(id, true);
} else {
return true;
}
}
World bw = tb.getWorld();
// check location
while (!bw.getChunkAt(tb).isLoaded()) {
bw.getChunkAt(tb).load();
}
int[] start_loc = tt.getStartLocation(tb, rsc.getDirection());
int tmp_y = tb.getBlockY();
for (int up = 0; up < 10; up++) {
int count = tt.safeLocation(start_loc[0], tmp_y + up, start_loc[2], start_loc[1], start_loc[3], tb.getWorld(), rsc.getDirection());
if (count == 0) {
tb.setY(tmp_y + up);
break;
}
}
set.put("world", tb.getWorld().getName());
set.put("x", tb.getBlockX());
set.put("y", tb.getBlockY());
set.put("z", tb.getBlockZ());
set.put("direction", rsc.getDirection().toString());
set.put("submarine", 0);
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "BIOME_SET", !plugin.getTrackerKeeper().getDestinationVortex().containsKey(id));
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
}
} catch (IllegalArgumentException iae) {
TARDISMessage.send(player, "BIOME_NOT_VALID");
return true;
}
return true;
}
}
if (args.length == 2 && args[0].equalsIgnoreCase("dest")) {
// we're thinking this is a saved destination name
if (player.hasPermission("tardis.save")) {
HashMap<String, Object> whered = new HashMap<String, Object>();
whered.put("dest_name", args[1]);
whered.put("tardis_id", id);
ResultSetDestinations rsd = new ResultSetDestinations(plugin, whered, false);
if (!rsd.resultSet()) {
TARDISMessage.send(player, "SAVE_NOT_FOUND");
return true;
}
World w = plugin.getServer().getWorld(rsd.getWorld());
if (w != null) {
if (w.getName().startsWith("TARDIS_")) {
TARDISMessage.send(player, "SAVE_NO_TARDIS");
return true;
}
Location save_dest = new Location(w, rsd.getX(), rsd.getY(), rsd.getZ());
if (!plugin.getPluginRespect().getRespect(save_dest, new Parameters(player, FLAG.getDefaultFlags()))) {
if (plugin.getConfig().getBoolean("travel.no_destination_malfunctions")) {
plugin.getTrackerKeeper().getMalfunction().put(id, true);
} else {
return true;
}
}
if (!plugin.getTardisArea().areaCheckInExisting(save_dest)) {
// save is in a TARDIS area, so check that the spot is not occupied
HashMap<String, Object> wheres = new HashMap<String, Object>();
wheres.put("world", rsd.getWorld());
wheres.put("x", rsd.getX());
wheres.put("y", rsd.getY());
wheres.put("z", rsd.getZ());
ResultSetCurrentLocation rsz = new ResultSetCurrentLocation(plugin, wheres);
if (rsz.resultSet()) {
TARDISMessage.send(player, "TARDIS_IN_SPOT", ChatColor.AQUA + "/tardistravel area [name]" + ChatColor.RESET);
return true;
}
}
set.put("world", rsd.getWorld());
set.put("x", rsd.getX());
set.put("y", rsd.getY());
set.put("z", rsd.getZ());
if (!rsd.getDirection().isEmpty() && rsd.getDirection().length() < 6) {
set.put("direction", rsd.getDirection());
} else {
// get current direction
HashMap<String, Object> wherecl = new HashMap<String, Object>();
wherecl.put("tardis_id", tardis.getTardis_id());
ResultSetCurrentLocation rsc = new ResultSetCurrentLocation(plugin, wherecl);
if (!rsc.resultSet()) {
TARDISMessage.send(player, "CURRENT_NOT_FOUND");
return true;
}
set.put("direction", rsc.getDirection().toString());
}
set.put("submarine", (rsd.isSubmarine()) ? 1 : 0);
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "LOC_SET", !plugin.getTrackerKeeper().getDestinationVortex().containsKey(id));
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
return true;
} else {
TARDISMessage.send(player, "SAVE_NO_WORLD");
return true;
}
} else {
TARDISMessage.send(player, "TRAVEL_NO_PERM_SAVE");
return true;
}
}
if (args.length == 2 && args[0].equalsIgnoreCase("area")) {
// we're thinking this is admin defined area name
HashMap<String, Object> wherea = new HashMap<String, Object>();
wherea.put("area_name", args[1]);
ResultSetAreas rsa = new ResultSetAreas(plugin, wherea, false, false);
if (!rsa.resultSet()) {
TARDISMessage.send(player, "AREA_NOT_FOUND", ChatColor.GREEN + "/tardis list areas" + ChatColor.RESET);
return true;
}
if ((!player.hasPermission("tardis.area." + args[1]) && !player.hasPermission("tardis.area.*")) || (!player.isPermissionSet("tardis.area." + args[1]) && !player.isPermissionSet("tardis.area.*"))) {
TARDISMessage.send(player, "TRAVEL_NO_AREA_PERM", args[1]);
return true;
}
if (!plugin.getDifficulty().equals(DIFFICULTY.EASY) && mustUseAdvanced.contains(args[0].toLowerCase()) && !plugin.getUtils().inGracePeriod(player, false)) {
TARDISMessage.send(player, "ADV_AREA");
return true;
}
Location l = plugin.getTardisArea().getNextSpot(rsa.getArea().getAreaName());
if (l == null) {
TARDISMessage.send(player, "NO_MORE_SPOTS");
return true;
}
set.put("world", l.getWorld().getName());
set.put("x", l.getBlockX());
set.put("y", l.getBlockY());
set.put("z", l.getBlockZ());
set.put("submarine", 0);
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "TRAVEL_APPROVED", args[1]);
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
return true;
}
if (player.hasPermission("tardis.timetravel.location")) {
switch (args.length) {
case 0:
case 1:
case 2:
TARDISMessage.send(player, "ARG_COORDS");
return false;
case 3:
if (args[0].startsWith("~")) {
HashMap<String, Object> wherecl = new HashMap<String, Object>();
wherecl.put("tardis_id", id);
ResultSetCurrentLocation rsc = new ResultSetCurrentLocation(plugin, wherecl);
if (!rsc.resultSet()) {
TARDISMessage.send(player, "CURRENT_NOT_FOUND");
return true;
}
if (rsc.isSubmarine()) {
TARDISMessage.send(player, "SUB_NO_CMD");
return true;
}
// check args
int rx = getRelativeCoordinate(args[0]);
int ry = getRelativeCoordinate(args[1]);
int rz = getRelativeCoordinate(args[2]);
if (rx == Integer.MAX_VALUE || ry == Integer.MAX_VALUE || rz == Integer.MAX_VALUE) {
TARDISMessage.send(player, "RELATIVE_NOT_FOUND");
return true;
}
// add relative coordinates
int x = rsc.getX() + rx;
int y = rsc.getY() + ry;
int z = rsc.getZ() + rz;
// make location
Location location = new Location(rsc.getWorld(), x, y, z);
// check location
int count = this.checkLocation(location, player, id, tt);
if (count > 0) {
TARDISMessage.send(player, "NOT_SAFE");
return true;
} else {
set.put("world", location.getWorld().getName());
set.put("x", location.getBlockX());
set.put("y", location.getBlockY());
set.put("z", location.getBlockZ());
set.put("submarine", 0);
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "LOC_SAVED", true);
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
return true;
}
} else {
// automatically get highest block Y coord
Location determiney = getCoordinateLocation(args, player, id);
if (determiney != null) {
int count = this.checkLocation(determiney, player, id, tt);
if (count > 0) {
TARDISMessage.send(player, "NOT_SAFE");
return true;
} else {
set.put("world", determiney.getWorld().getName());
set.put("x", determiney.getBlockX());
set.put("y", determiney.getBlockY());
set.put("z", determiney.getBlockZ());
set.put("submarine", 0);
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "LOC_SAVED", true);
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
return true;
}
}
}
break;
default:
// coords
Location giveny = getCoordinateLocation(args, player, id);
if (giveny != null) {
// check location
int count = this.checkLocation(giveny, player, id, tt);
if (count > 0) {
TARDISMessage.send(player, "NOT_SAFE");
return true;
} else {
set.put("world", giveny.getWorld().getName());
set.put("x", giveny.getBlockX());
set.put("y", giveny.getBlockY());
set.put("z", giveny.getBlockZ());
set.put("submarine", 0);
qf.doSyncUpdate("next", set, tid);
TARDISMessage.send(player, "LOC_SAVED", true);
plugin.getTrackerKeeper().getHasDestination().put(id, travel);
if (plugin.getTrackerKeeper().getRescue().containsKey(id)) {
plugin.getTrackerKeeper().getRescue().remove(id);
}
if (plugin.getTrackerKeeper().getDestinationVortex().containsKey(id)) {
new TARDISLand(plugin, id, player).exitVortex();
}
return true;
}
}
break;
}
} else {
TARDISMessage.send(player, "TRAVEL_NO_PERM_COORDS");
return true;
}
}
} else {
TARDISMessage.send(player, "NO_PERMS");
return false;
}
}
return false;
}
private String getQuotedString(String[] args) {
StringBuilder buf = new StringBuilder();
String w_str = "";
for (String s : args) {
buf.append(s).append(" ");
}
String tmp = buf.toString();
Pattern p = Pattern.compile("'([^']*)'");
Matcher m = p.matcher(tmp);
while (m.find()) {
w_str = m.group(1);
}
return w_str;
}
private Location getCoordinateLocation(String[] args, Player player, int id) {
// coords
String w_str = args[0];
if (w_str.contains("'")) {
w_str = getQuotedString(args);
}
if (args[1].startsWith("~")) {
TARDISMessage.send(player, "NO_WORLD_RELATIVE");
return null;
}
// must be a location then
int x, y, z;
World w;
if (args[0].equals("~")) {
HashMap<String, Object> wherecl = new HashMap<String, Object>();
wherecl.put("tardis_id", id);
ResultSetCurrentLocation rsc = new ResultSetCurrentLocation(plugin, wherecl);
if (!rsc.resultSet()) {
TARDISMessage.send(player, "CURRENT_NOT_FOUND");
return null;
}
w = rsc.getWorld();
} else {
if (plugin.isMVOnServer()) {
w = plugin.getMVHelper().getWorld(w_str);
} else {
w = plugin.getServer().getWorld(w_str);
}
}
if (w == null) {
TARDISMessage.send(player, "WORLD_NOT_FOUND");
return null;
}
if (!plugin.getConfig().getBoolean("worlds." + w.getName())) {
TARDISMessage.send(player, "NO_WORLD_TRAVEL");
return null;
}
if (!plugin.getConfig().getBoolean("travel.include_default_world") && plugin.getConfig().getBoolean("creation.default_world") && args[0].equals(plugin.getConfig().getString("creation.default_world_name"))) {
TARDISMessage.send(player, "NO_WORLD_TRAVEL");
return null;
}
z = TARDISNumberParsers.parseInt(args[args.length - 1]);
if (args.length > 3) {
x = TARDISNumberParsers.parseInt(args[args.length - 3]);
y = TARDISNumberParsers.parseInt(args[args.length - 2]);
if (y == 0 || y > 250) {
TARDISMessage.send(player, "Y_NOT_VALID");
return null;
}
} else {
x = TARDISNumberParsers.parseInt(args[args.length - 2]);
Chunk chunk = w.getChunkAt(x, z);
while (!chunk.isLoaded()) {
chunk.load();
}
y = w.getHighestBlockYAt(x, z);
}
int max = Math.min(plugin.getConfig().getInt("travel.max_distance"), (int) (w.getWorldBorder().getSize() / 2) - 17);
if (x > max || x < -max || z > max || z < -max) {
TARDISMessage.send(player, "XZ_NOT_VALID");
return null;
}
return new Location(w, x, y, z);
}
public Location searchBiome(Player p, int id, Biome b, World w, int startx, int startz) {
if (b == null) {
TARDISMessage.send(p, "BIOME_NOT_VALID");
return null;
}
HashMap<String, Object> wherecl = new HashMap<String, Object>();
wherecl.put("tardis_id", id);
ResultSetCurrentLocation rsc = new ResultSetCurrentLocation(plugin, wherecl);
if (!rsc.resultSet()) {
TARDISMessage.send(p, "CURRENT_NOT_FOUND");
return null;
}
Location l = null;
// get a world
// Assume all non-nether/non-end world environments are NORMAL
if (w != null && !w.getEnvironment().equals(Environment.NETHER) && !w.getEnvironment().equals(Environment.THE_END)) {
int limite = startx + 30000;
int limits = startz + 30000;
int limitw = startx - 30000;
int limitn = startz - 30000;
if (plugin.getPM().isPluginEnabled("WorldBorder")) {
// get the border limit for this world
TARDISWorldBorderChecker wb = new TARDISWorldBorderChecker(plugin, plugin.getPluginRespect().isBorderOnServer());
int[] data = wb.getBorderDistance(w.getName());
limite = data[0];
limits = data[1];
limitw = -data[0];
limitn = -data[1];
}
int step = 10;
// search in a random direction
Integer[] directions = new Integer[]{0, 1, 2, 3};
Collections.shuffle(Arrays.asList(directions));
for (int i = 0; i < 4; i++) {
switch (directions[i]) {
case 0:
// east
for (int east = startx; east < limite; east += step) {
Biome chkb = w.getBiome(east, startz);
if (chkb.equals(b)) {
TARDISMessage.send(p, "BIOME_E", b.toString());
return new Location(w, east, w.getHighestBlockYAt(east, startz), startz);
}
}
break;
case 1:
// south
for (int south = startz; south < limits; south += step) {
Biome chkb = w.getBiome(startx, south);
if (chkb.equals(b)) {
TARDISMessage.send(p, "BIOME_S", b.toString());
return new Location(w, startx, w.getHighestBlockYAt(startx, south), south);
}
}
break;
case 2:
// west
for (int west = startx; west > limitw; west -= step) {
Biome chkb = w.getBiome(west, startz);
if (chkb.equals(b)) {
TARDISMessage.send(p, "BIOME_W", b.toString());
return new Location(w, west, w.getHighestBlockYAt(west, startz), startz);
}
}
break;
case 3:
// north
for (int north = startz; north > limitn; north -= step) {
Biome chkb = w.getBiome(startx, north);
if (chkb.equals(b)) {
TARDISMessage.send(p, "BIOME_N", b.toString());
return new Location(w, startx, w.getHighestBlockYAt(startx, north), north);
}
}
break;
}
}
}
return l;
}
private int checkLocation(Location location, Player player, int id, TARDISTimeTravel tt) {
if (!plugin.getTardisArea().areaCheckInExisting(location)) {
TARDISMessage.send(player, "TRAVEL_IN_AREA", ChatColor.AQUA + "/tardistravel area [area name]");
return 1;
}
if (!plugin.getPluginRespect().getRespect(location, new Parameters(player, FLAG.getDefaultFlags()))) {
return 1;
}
HashMap<String, Object> wherecl = new HashMap<String, Object>();
wherecl.put("tardis_id", id);
ResultSetCurrentLocation rsc = new ResultSetCurrentLocation(plugin, wherecl);
if (!rsc.resultSet()) {
TARDISMessage.send(player, "CURRENT_NOT_FOUND");
return 1;
}
// check location
int[] start_loc = tt.getStartLocation(location, rsc.getDirection());
return tt.safeLocation(start_loc[0], location.getBlockY(), start_loc[2], start_loc[1], start_loc[3], location.getWorld(), rsc.getDirection());
}
private int getRelativeCoordinate(String arg) {
if (arg.startsWith("~")) {
String value = arg.substring(1);
if (value.isEmpty()) {
return 0;
}
try {
return Integer.parseInt(value);
} catch (NumberFormatException nfe) {
plugin.debug("Could not convert relative coordinate! " + nfe.getMessage());
return Integer.MAX_VALUE;
}
}
return Integer.MAX_VALUE;
}
}