/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock 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.
*
* ASkyBlock 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 ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package com.wasteofplastic.askyblock;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.material.SimpleAttachableMaterialData;
import org.bukkit.material.TrapDoor;
import org.bukkit.util.Vector;
import com.wasteofplastic.askyblock.Island.SettingsFlag;
import com.wasteofplastic.askyblock.util.Util;
/**
* This class manages the island islandGrid. It knows where every island is, and
* where new
* ones should go. It can handle any size of island or protection size
* The islandGrid is stored in a YML file.
*
* @author tastybento
*/
public class GridManager {
private static final String SETTINGS_KEY = "settingskey";
private static final String ISLANDS_FILENAME = "islands.yml";
private static final String ISLANDNAMES_FILENAME = "islandnames.yml";
private ASkyBlock plugin;
// 2D islandGrid of islands, x,z
private TreeMap<Integer, TreeMap<Integer, Island>> islandGrid = new TreeMap<Integer, TreeMap<Integer, Island>>();
// private TreeMap<Integer,TreeMap<Integer,PlayerIsland>> protectionGrid = new
// TreeMap<Integer,TreeMap<Integer,PlayerIsland>>();
// Reverse lookup for owner, if they exists
private HashMap<UUID, Island> ownershipMap = new HashMap<UUID, Island>();
private File islandFile;
private Island spawn;
private File islandNameFile;
private YamlConfiguration islandNames = new YamlConfiguration();
/**
* @param plugin
*/
public GridManager(ASkyBlock plugin) {
this.plugin = plugin;
loadGrid();
}
private void loadGrid() {
plugin.getLogger().info("Loading island grid...");
islandGrid.clear();
// protectionGrid.clear();
islandNameFile = new File(plugin.getDataFolder(), ISLANDNAMES_FILENAME);
if (!islandNameFile.exists()) {
try {
islandNameFile.createNewFile();
} catch (IOException e) {
plugin.getLogger().severe("Could not create " + ISLANDNAMES_FILENAME + "!");
}
}
try {
islandNames.load(islandNameFile);
} catch (Exception e) {
//e.printStackTrace();
plugin.getLogger().severe("Could not load " + ISLANDNAMES_FILENAME);
}
islandFile = new File(plugin.getDataFolder(), ISLANDS_FILENAME);
if (!islandFile.exists()) {
// check if island folder exists
plugin.getLogger().info(ISLANDS_FILENAME + " does not exist. Creating...");
convert();
plugin.getLogger().info(ISLANDS_FILENAME + " created.");
} else {
plugin.getLogger().info("Loading " + ISLANDS_FILENAME);
YamlConfiguration islandYaml = new YamlConfiguration();
try {
islandYaml.load(islandFile);
List<String> islandList = new ArrayList<String>();
if (islandYaml.contains(Settings.worldName)) {
// Load the island settings key
List<String> settingsKey = islandYaml.getStringList(SETTINGS_KEY);
// Load spawn, if it exists - V3.0.6 onwards
if (islandYaml.contains("spawn")) {
Location spawnLoc = Util.getLocationString(islandYaml.getString("spawn.location"));
// Validate entries
if (spawnLoc != null && spawnLoc.getWorld() != null && spawnLoc.getWorld().equals(ASkyBlock.getIslandWorld())) {
Location spawnPoint = Util.getLocationString(islandYaml.getString("spawn.spawnpoint"));
int range = islandYaml.getInt("spawn.range", Settings.islandProtectionRange);
if (range < 0) {
range = Settings.islandProtectionRange;
}
String spawnSettings = islandYaml.getString("spawn.settings");
// Make the spawn
Island newSpawn = new Island(plugin, spawnLoc.getBlockX(), spawnLoc.getBlockZ());
newSpawn.setSpawn(true);
if (spawnPoint != null)
newSpawn.setSpawnPoint(spawnPoint);
newSpawn.setProtectionSize(range);
newSpawn.setSettings(spawnSettings, settingsKey);
spawn = newSpawn;
}
}
// Load the islands
islandList = islandYaml.getStringList(Settings.worldName);
for (String island : islandList) {
Island newIsland = addIsland(island, settingsKey);
if (newIsland.getOwner() != null) {
ownershipMap.put(newIsland.getOwner(), newIsland);
}
if (newIsland.isSpawn()) {
spawn = newIsland;
}
}
} else {
plugin.getLogger().severe("Could not find any islands for this world. World name in config.yml is probably wrong.");
plugin.getLogger().severe("Making backup of " + ISLANDS_FILENAME + ". Correct world name and then replace " + ISLANDS_FILENAME);
File rename = new File(plugin.getDataFolder(), "islands_backup.yml");
islandFile.renameTo(rename);
}
} catch (Exception e) {
//e.printStackTrace();
plugin.getLogger().severe("Could not load " + ISLANDS_FILENAME);
}
}
// for (int x : protectionGrid.)
// plugin.getLogger().info("Debug: protection grid is size " +
// protectionGrid.size());
// plugin.getLogger().info("Debug: Island grid is sized = " +
// islandGrid.size());
}
/**
* Provides confirmation that the island is on the grid lines
*
* @param loc
* @return
*/
public boolean onGrid(Location loc) {
int x = loc.getBlockX();
int z = loc.getBlockZ();
return onGrid(x, z);
}
public boolean onGrid(int x, int z) {
if ((x - Settings.islandXOffset) % Settings.islandDistance != 0) {
return false;
}
if ((z - Settings.islandZOffset) % Settings.islandDistance != 0) {
return false;
}
return true;
}
/**
* Converts from the old version where islands were stored in an island
* folder.
* Did not work for large installations.
*/
private void convert() {
// Read spawn file if it exists
final File spawnFile = new File(plugin.getDataFolder(), "spawn.yml");
if (spawnFile.exists()) {
YamlConfiguration spawn = new YamlConfiguration();
try {
spawn.load(spawnFile);
int range = spawn.getInt("spawn.range");
// plugin.getLogger().info("DEBUG:" + range + " " +
// spawn.getString("spawn.bedrock",""));
Location spawnLoc = Util.getLocationString(spawn.getString("spawn.bedrock", ""));
if (spawnLoc != null && onGrid(spawnLoc)) {
Island newIsland = addIsland(spawnLoc.getBlockX(), spawnLoc.getBlockZ());
setSpawn(newIsland);
newIsland.setProtectionSize(range);
} else {
plugin.getLogger().severe("Spawn could not be imported! Location " + spawnLoc);
plugin.getLogger().severe("Go to the spawn island and set it manually");
}
} catch (Exception e) {
plugin.getLogger().severe("Spawn could not be imported! File could not load.");
}
}
// Go through player folder
final File playerFolder = new File(plugin.getDataFolder() + File.separator + "players");
final File quarantineFolder = new File(plugin.getDataFolder() + File.separator + "quarantine");
YamlConfiguration playerFile = new YamlConfiguration();
int noisland = 0;
int inTeam = 0;
int count = 0;
if (playerFolder.exists() && playerFolder.listFiles().length > 0) {
plugin.getLogger().warning("Reading player folder...");
if (playerFolder.listFiles().length > 5000) {
plugin.getLogger().warning("This could take some time with a large number of islands...");
}
for (File f : playerFolder.listFiles()) {
// Need to remove the .yml suffix
String fileName = f.getName();
if (fileName.endsWith(".yml")) {
try {
playerFile.load(f);
boolean hasIsland = playerFile.getBoolean("hasIsland", false);
if (hasIsland) {
String islandLocation = playerFile.getString("islandLocation");
if (islandLocation.isEmpty()) {
plugin.getLogger().severe("Problem with " + fileName);
plugin.getLogger().severe("Owner :" + playerFile.getString("playerName", "Unknown"));
plugin.getLogger().severe("Player file says they have an island, but there is no location.");
// Move to quarantine
if (!quarantineFolder.exists()) {
quarantineFolder.mkdir();
}
// Move the file
plugin.getLogger().severe("Moving " + f.getName() + " to " + quarantineFolder.getName());
File rename = new File(quarantineFolder, f.getName());
f.renameTo(rename);
} else {
// Location exists
Location islandLoc = Util.getLocationString(islandLocation);
if (islandLoc != null) {
// Check to see if this island is already loaded
Island island = getIslandAt(islandLoc);
if (island != null) {
// PlayerIsland exists, compare creation dates
plugin.getLogger().severe("Problem with " + fileName);
plugin.getLogger().severe("Owner :" + playerFile.getString("playerName", "Unknown"));
plugin.getLogger().severe("This island location already exists and is already imported");
if (island.getUpdatedDate() > f.lastModified()) {
plugin.getLogger().severe("Previous file is more recent so keeping it.");
// Original file is more recent
// Move to quarantine
if (!quarantineFolder.exists()) {
quarantineFolder.mkdir();
}
plugin.getLogger().severe(
"Moving " + (playerFile.getString("playerName", "Unknown")) + "'s file (" + f.getName() + ") to "
+ quarantineFolder.getName());
File rename = new File(quarantineFolder, f.getName());
f.renameTo(rename);
} else {
// New file is more recent
plugin.getLogger().severe(playerFile.getString("playerName", "Unknown") + "'s file is more recent");
File oldFile = new File(playerFolder, island.getOwner().toString() + ".yml");
File rename = new File(quarantineFolder, oldFile.getName());
// Move to quarantine
if (!quarantineFolder.exists()) {
quarantineFolder.mkdir();
}
plugin.getLogger().severe("Moving previous file (" + oldFile.getName() + ") to " + quarantineFolder.getName());
oldFile.renameTo(rename);
deleteIsland(islandLoc);
island = null;
}
}
if (island == null) {
if (!onGrid(islandLoc)) {
plugin.getLogger().severe("Problem with " + fileName);
plugin.getLogger().severe("Owner :" + playerFile.getString("playerName", "Unknown"));
plugin.getLogger().severe("Island is not on grid lines! " + islandLoc);
}
String ownerString = fileName.substring(0, fileName.length() - 4);
// Add the island
UUID owner = UUID.fromString(ownerString);
Island newIsland = addIsland(islandLoc.getBlockX(), islandLoc.getBlockZ(), owner);
ownershipMap.put(owner, newIsland);
// Grab when this was last updated
newIsland.setUpdatedDate(f.lastModified());
if ((count) % 1000 == 0) {
plugin.getLogger().info("Converted " + count + " islands");
}
count++;
// plugin.getLogger().info("Converted island at "
// + islandLoc);
// Top ten
int islandLevel = playerFile.getInt("islandLevel", 0);
String teamLeaderUUID = playerFile.getString("teamLeader", "");
if (islandLevel > 0) {
if (!playerFile.getBoolean("hasTeam")) {
TopTen.topTenAddEntry(owner, islandLevel);
} else if (!teamLeaderUUID.isEmpty()) {
if (teamLeaderUUID.equals(ownerString)) {
TopTen.topTenAddEntry(owner, islandLevel);
}
}
}
// Check if there is an island info string and see if it jibes
String islandInfo = playerFile.getString("islandInfo","");
if (!islandInfo.isEmpty()) {
String[] split = islandInfo.split(":");
try {
//int protectionRange = Integer.parseInt(split[3]);
//int islandDistance = Integer.parseInt(split[4]);
newIsland.setLocked(false);
if (split.length > 6) {
// Get locked status
if (split[6].equalsIgnoreCase("true")) {
newIsland.setLocked(true);
}
}
// Check if deletable
newIsland.setPurgeProtected(false);
if (split.length > 7) {
if (split[7].equalsIgnoreCase("true")) {
newIsland.setPurgeProtected(true);
}
}
if (!split[5].equals("null")) {
if (split[5].equals("spawn")) {
newIsland.setSpawn(true);
// Try to get the spawn point
if (split.length > 8) {
//plugin.getLogger().info("DEBUG: " + serial.substring(serial.indexOf(":SP:") + 4));
Location spawnPoint = Util.getLocationString(islandInfo.substring(islandInfo.indexOf(":SP:") + 4));
newIsland.setSpawnPoint(spawnPoint);
}
}
}
// Check if protection options there
if (!newIsland.isSpawn()) {
//plugin.getLogger().info("DEBUG: NOT SPAWN owner is " + owner + " location " + center);
if (split.length > 8 && split[8].length() == 29) {
// Parse the 8th string into island guard protection settings
int index = 0;
// Run through the enum and set
for (SettingsFlag flag : SettingsFlag.values()) {
if (index < split[8].length()) {
newIsland.setIgsFlag(flag, split[8].charAt(index++) == '1' ? true : false);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else {
plugin.getLogger().severe("Problem with " + fileName);
plugin.getLogger().severe("Owner :" + playerFile.getString("playerName", "Unknown"));
plugin.getLogger().severe("The world for this file does not exist!");
}
}
} else {
noisland++;
if (playerFile.getBoolean("hasTeam", false)) {
inTeam++;
}
}
} catch (Exception e) {
plugin.getLogger().severe("Problem with " + fileName);
//e.printStackTrace();
}
}
}
plugin.getLogger().info("Converted " + count + " islands from player's folder");
plugin.getLogger().info(noisland + " have no island, of which " + inTeam + " are in a team.");
plugin.getLogger().info((noisland - inTeam) + " are in the system, but have no island or team");
}
TopTen.topTenSave();
int count2 = 0;
// Check island folder
final File islandFolder = new File(plugin.getDataFolder() + File.separator + "islands");
if (islandFolder.exists() && islandFolder.listFiles().length > 0) {
plugin.getLogger().warning("Reading island folder...");
if (islandFolder.listFiles().length > 5000) {
plugin.getLogger().warning("This could take some time with a large number of islands...");
}
for (File f : islandFolder.listFiles()) {
// Need to remove the .yml suffix
String fileName = f.getName();
int comma = fileName.indexOf(",");
if (fileName.endsWith(".yml") && comma != -1) {
try {
// Parse to an island value
int x = Integer.parseInt(fileName.substring(0, comma));
int z = Integer.parseInt(fileName.substring(comma + 1, fileName.indexOf(".")));
if (!onGrid(x, z)) {
plugin.getLogger().severe("Island is not on grid lines! " + x + "," + z + " skipping...");
} else {
// Note that this is the CENTER of the island
if (getIslandAt(x, z) == null) {
addIsland(x, z);
if (count2 % 1000 == 0) {
plugin.getLogger().info("Converted " + count + " islands");
}
count2++;
// plugin.getLogger().info("Added island from island folder: "
// + x + "," +z);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
plugin.getLogger().info("Converted " + count2 + " islands from island folder");
plugin.getLogger().info("Total " + (count + count2) + " islands converted.");
}
// Now save the islandGrid
saveGrid();
}
/**
* Saves the grid asynchronously
*/
public void saveGrid() {
saveGrid(true);
}
/**
* Saves the grid. Option to save sync or async.
* Async cannot be used when disabling the plugin
* @param async
*/
public void saveGrid(boolean async) {
final File islandFile = new File(plugin.getDataFolder(), ISLANDS_FILENAME);
final YamlConfiguration islandYaml = new YamlConfiguration();
// Save the settings config key
List<String> islandSettings = new ArrayList<String>();
for (SettingsFlag flag: SettingsFlag.values()) {
islandSettings.add(flag.toString());
}
islandYaml.set(SETTINGS_KEY, islandSettings);
// Save spawn
if (getSpawn() != null) {
islandYaml.set("spawn.location", Util.getStringLocation(getSpawn().getCenter()));
islandYaml.set("spawn.spawnpoint", Util.getStringLocation(getSpawn().getSpawnPoint()));
islandYaml.set("spawn.range", getSpawn().getProtectionSize());
islandYaml.set("spawn.settings", getSpawn().getSettings());
}
// Save the regular islands
List<String> islandList = new ArrayList<String>();
Iterator<TreeMap<Integer, Island>> it = islandGrid.values().iterator();
while (it.hasNext()) {
Iterator<Island> islandIt = it.next().values().iterator();
while (islandIt.hasNext()) {
Island island = islandIt.next();
if (!island.isSpawn()) {
islandList.add(island.save());
}
}
}
islandYaml.set(Settings.worldName, islandList);
// Save the file
if (async) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
public void run() {
try {
islandYaml.save(islandFile);
} catch (Exception e) {
plugin.getLogger().severe("Could not save " + ISLANDS_FILENAME + "!");
//e.printStackTrace();
}}
});
} else {
try {
islandYaml.save(islandFile);
} catch (Exception e) {
plugin.getLogger().severe("Could not save " + ISLANDS_FILENAME + "! " + e.getMessage());
}
}
// Save any island names
if (islandNames != null) {
try {
islandNames.save(islandNameFile);
} catch (IOException e) {
plugin.getLogger().severe("Could not save islandnames.yml! " + e.getMessage());
}
}
}
/**
* Returns the island at the location or null if there is none.
* This includes the full island space, not just the protected area
*
* @param location
* @return PlayerIsland object
*/
public Island getIslandAt(Location location) {
if (location == null) {
return null;
}
// World check
if (!inWorld(location)) {
return null;
}
// Check if it is spawn
if (spawn != null && spawn.onIsland(location)) {
return spawn;
}
return getIslandAt(location.getBlockX(), location.getBlockZ());
}
/**
* Determines if a location is in the island world or not or
* in the new nether if it is activated
* @param loc
* @return true if in the island world
*/
protected boolean inWorld(Location loc) {
if (loc.getWorld().equals(ASkyBlock.getIslandWorld())) {
return true;
}
if (Settings.createNether && Settings.newNether && ASkyBlock.getNetherWorld() != null && loc.getWorld().equals(ASkyBlock.getNetherWorld())) {
return true;
}
return false;
}
/**
* Returns the island at the x,z location or null if there is none.
* This includes the full island space, not just the protected area.
*
* @param x
* @param z
* @return PlayerIsland or null
*/
public Island getIslandAt(int x, int z) {
Entry<Integer, TreeMap<Integer, Island>> en = islandGrid.floorEntry(x);
if (en != null) {
Entry<Integer, Island> ent = en.getValue().floorEntry(z);
if (ent != null) {
// Check if in the island range
Island island = ent.getValue();
if (island.inIslandSpace(x, z)) {
// plugin.getLogger().info("DEBUG: In island space");
return island;
}
//plugin.getLogger().info("DEBUG: not in island space");
}
}
return null;
}
/**
* Returns the island being public at the location or null if there is none
*
* @param location
* @return PlayerIsland object
*/
public Island getProtectedIslandAt(Location location) {
//plugin.getLogger().info("DEBUG: getProtectedIslandAt " + location);
// Try spawn
if (spawn != null && spawn.onIsland(location)) {
return spawn;
}
Island island = getIslandAt(location);
if (island == null) {
//plugin.getLogger().info("DEBUG: no island at this location");
return null;
}
if (island.onIsland(location)) {
return island;
}
return null;
}
/**
* Returns the owner of the island at location or null if there is none
*
* @param location
* @return UUID of owner
*/
public UUID getOwnerOfIslandAt(Location location) {
Island island = getIslandAt(location);
if (island != null) {
return island.getOwner();
}
return null;
}
// islandGrid manipulation methods
/**
* Adds an island to the islandGrid with the CENTER point x,z
*
* @param x
* @param z
*/
public Island addIsland(int x, int z) {
return addIsland(x, z, null);
}
/**
* Adds an island to the islandGrid with the center point x,z owner UUID
*
* @param x
* @param z
* @param owner
*/
public Island addIsland(int x, int z, UUID owner) {
// Check if this owner already has an island
if (ownershipMap.containsKey(owner)) {
// Island exists
Island island = ownershipMap.get(owner);
// Remove island if the player already has a different one
if (island.getCenter().getBlockX() != x || island.getCenter().getBlockZ() != z) {
//plugin.getLogger().warning(
//"Island at " + island.getCenter().getBlockX() + ", " + island.getCenter().getBlockZ()
//+ " is already owned by this player. Removing ownership of this island.");
island.setOwner(null);
ownershipMap.remove(owner);
} else {
// Player already has island
addToGrids(island);
return island;
}
}
// plugin.getLogger().info("DEBUG: adding island to grid at " + x + ", "
// + z + " for " + owner.toString());
Island newIsland = new Island(plugin, x, z, owner);
// if (newIsland != null) {
// plugin.getLogger().info("DEBUG: new island is good");
// }
addToGrids(newIsland);
return newIsland;
}
/**
* Adds island to the grid using the stored information
*
* @param islandSerialized
*/
public Island addIsland(String islandSerialized, List<String> settingsKey) {
// plugin.getLogger().info("DEBUG: adding island " + islandSerialized);
Island newIsland = new Island(plugin, islandSerialized, settingsKey);
addToGrids(newIsland);
return newIsland;
}
/**
* Adds an island to the grid register
* @param newIsland
*/
private void addToGrids(Island newIsland) {
//plugin.getLogger().info("DEBUG: adding island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ());
if (newIsland.getOwner() != null) {
ownershipMap.put(newIsland.getOwner(), newIsland);
}
if (islandGrid.containsKey(newIsland.getMinX())) {
//plugin.getLogger().info("DEBUG: min x is in the grid :" + newIsland.getMinX());
TreeMap<Integer, Island> zEntry = islandGrid.get(newIsland.getMinX());
if (zEntry.containsKey(newIsland.getMinZ())) {
//plugin.getLogger().info("DEBUG: min z is in the grid :" + newIsland.getMinZ());
// Island already exists
Island conflict = islandGrid.get(newIsland.getMinX()).get(newIsland.getMinZ());
plugin.getLogger().warning("*** Duplicate or overlapping islands! ***");
plugin.getLogger().warning(
"Island at (" + newIsland.getCenter().getBlockX() + ", " + newIsland.getCenter().getBlockZ() + ") conflicts with ("
+ conflict.getCenter().getBlockX() + ", " + conflict.getCenter().getBlockZ() + ")");
if (conflict.getOwner() != null) {
plugin.getLogger().warning("Accepted island is owned by " + plugin.getPlayers().getName(conflict.getOwner()));
plugin.getLogger().warning(conflict.getOwner().toString() + ".yml");
} else {
plugin.getLogger().warning("Accepted island is unowned.");
}
if (newIsland.getOwner() != null) {
plugin.getLogger().warning("Denied island is owned by " + plugin.getPlayers().getName(newIsland.getOwner()));
plugin.getLogger().warning(newIsland.getOwner().toString() + ".yml");
} else {
plugin.getLogger().warning("Denied island is unowned and was just found in the islands folder. Skipping it...");
}
plugin.getLogger().warning("Recommend that the denied player file is deleted otherwise weird things can happen.");
return;
} else {
// Add island
//plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ());
zEntry.put(newIsland.getMinZ(), newIsland);
islandGrid.put(newIsland.getMinX(), zEntry);
// plugin.getLogger().info("Debug: " + newIsland.toString());
}
} else {
// Add island
//plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ());
TreeMap<Integer, Island> zEntry = new TreeMap<Integer, Island>();
zEntry.put(newIsland.getMinZ(), newIsland);
islandGrid.put(newIsland.getMinX(), zEntry);
}
}
/**
* Deletes any island owned by owner from the grid. Does not actually remove the island
* from the world. Used for cleaning up issues such as mismatches between player files
* and island.yml
* @param owner
*/
public void deleteIslandOwner(UUID owner) {
if (owner != null && ownershipMap.containsKey(owner)) {
Island island = ownershipMap.get(owner);
if (island != null) {
island.setOwner(null);
}
ownershipMap.remove(owner);
}
}
/**
* Removes the island at location loc from the grid and removes the player
* from the ownership map
*
* @param loc
*/
public void deleteIsland(Location loc) {
// plugin.getLogger().info("DEBUG: deleting island at " + loc);
Island island = getIslandAt(loc);
if (island != null) {
UUID owner = island.getOwner();
int x = island.getMinX();
int z = island.getMinZ();
// plugin.getLogger().info("DEBUG: x = " + x + " z = " + z);
if (islandGrid.containsKey(x)) {
// plugin.getLogger().info("DEBUG: x found");
TreeMap<Integer, Island> zEntry = islandGrid.get(x);
if (zEntry.containsKey(z)) {
// plugin.getLogger().info("DEBUG: z found - deleting the island");
// Island exists - delete it
Island deletedIsland = zEntry.get(z);
deletedIsland.setOwner(null);
deletedIsland.setLocked(false);
zEntry.remove(z);
islandGrid.put(x, zEntry);
} // else {
// plugin.getLogger().info("DEBUG: could not find z");
// }
}
// Remove from the ownership map
// If the owner already has been given a new island, then this will
// not be needed
if (owner != null && ownershipMap.containsKey(owner)) {
if (ownershipMap.get(owner).equals(island)) {
ownershipMap.remove(owner);
}
}
}
}
/**
* Gets island by owner's UUID. Just because the island does not exist in
* this map
* does not mean it does not exist in this world, due to legacy island
* support
* Will return the island that this player is a member of if a team player
*
* @param owner
* @return island object or null if it does not exist in the list
*/
public Island getIsland(UUID owner) {
if (owner != null) {
if (ownershipMap.containsKey(owner)) {
return ownershipMap.get(owner);
}
// Try and get team islands
UUID leader = plugin.getPlayers().getTeamLeader(owner);
if (leader != null && ownershipMap.containsKey(leader)) {
return ownershipMap.get(leader);
}
}
return null;
}
/**
* Sets an island to be owned by another player. If the new owner had an
* island, that island is released to null ownership
*
* @param island
* @param newOwner
*/
public void setIslandOwner(Island island, UUID newOwner) {
// The old owner
UUID oldOwner = island.getOwner();
// If the island owner is being set to null - remove the old owner's
// ownership
if (newOwner == null && oldOwner != null) {
ownershipMap.remove(oldOwner);
island.setOwner(null);
return;
}
// Check if the new owner already has an island
if (ownershipMap.containsKey(newOwner)) {
Island oldIsland = ownershipMap.get(newOwner);
// plugin.getLogger().warning("Island at " +
// oldIsland.getCenter().getBlockX() + ", " +
// oldIsland.getCenter().getBlockZ()
// +
// " is already owned by this player. Removing ownership of this island.");
oldIsland.setOwner(null);
ownershipMap.remove(newOwner);
}
// Make the new owner own the island
if (newOwner != null && island != null) {
// See if this island has an owner already
island.setOwner(newOwner);
// If the old owner exists remove them from the map
if (oldOwner != null && ownershipMap.containsKey(oldOwner)) {
// Remove the old entry
ownershipMap.remove(oldOwner);
}
// Insert the new entry
ownershipMap.put(newOwner, island);
}
}
/**
* @return the ownershipMap
*/
public HashMap<UUID, Island> getOwnershipMap() {
return ownershipMap;
}
/**
* @return the spawn or null if spawn does not exist
*/
public Island getSpawn() {
return spawn;
}
/**
* @param spawn
* the spawn to set
*/
public void setSpawn(Island spawn) {
// plugin.getLogger().info("DEBUG: Spawn set");
spawn.setSpawn(true);
spawn.setProtectionSize(spawn.getIslandDistance());
this.spawn = spawn;
}
public void deleteSpawn() {
deleteIsland(spawn.getCenter());
this.spawn = null;
}
/**
* Indicates whether a player is at the island spawn or not
*
* @param playerLoc
* @return true if they are, false if they are not, or spawn does not exist
*/
public boolean isAtSpawn(Location playerLoc) {
if (spawn == null) {
return false;
}
return spawn.onIsland(playerLoc);
}
/**
* Determines if an island is at a location in this area
* location. Also checks if the spawn island is in this area.
* Used for creating new islands ONLY
*
* @param loc
* @return true if found, otherwise false
*/
public boolean islandAtLocation(Location loc) {
if (loc == null) {
return true;
}
// Make sure location is on the grid
loc = getClosestIsland(loc);
// getLogger().info("DEBUG checking islandAtLocation for location " +
// loc.toString());
// Check the island grid
if (getIslandAt(loc) != null) {
// This checks if loc is inside the island spawn radius too
return true;
}
final int px = loc.getBlockX();
final int pz = loc.getBlockZ();
// Extra spawn area check
// If island protection distance is less than island distance then the
// check above will cover it
// Island edge must be > protection edge spawn
Island spawn = getSpawn();
if (spawn != null && spawn.getProtectionSize() > spawn.getIslandDistance()) {
if (Math.abs(px - spawn.getCenter().getBlockX()) < ((spawn.getProtectionSize() + Settings.islandDistance) / 2)
&& Math.abs(pz - spawn.getCenter().getBlockZ()) < ((spawn.getProtectionSize() + Settings.islandDistance) / 2)) {
// getLogger().info("DEBUG: island is within spawn space " + px
// + " " + pz);
return true;
}
}
if (!Settings.useOwnGenerator) {
// Block check
if (!loc.getBlock().isEmpty() && !loc.getBlock().isLiquid()) {
// Get the closest island
plugin.getLogger().info("Found solid block at island height - adding to " + ISLANDS_FILENAME + " " + px + "," + pz);
addIsland(px, pz);
return true;
}
// Look around
for (int x = -5; x <= 5; x++) {
for (int y = 10; y <= 255; y++) {
for (int z = -5; z <= 5; z++) {
if (!loc.getWorld().getBlockAt(x + px, y, z + pz).isEmpty() && !loc.getWorld().getBlockAt(x + px, y, z + pz).isLiquid()) {
plugin.getLogger().info("Solid block found during long search - adding to " + ISLANDS_FILENAME + " " + px + "," + pz);
addIsland(px, pz);
return true;
}
}
}
}
}
return false;
}
/**
* This returns the coordinate of where an island should be on the grid.
*
* @param location
* @return Location of closest island
*/
public Location getClosestIsland(Location location) {
long x = Math.round((double) location.getBlockX() / Settings.islandDistance) * Settings.islandDistance + Settings.islandXOffset;
long z = Math.round((double) location.getBlockZ() / Settings.islandDistance) * Settings.islandDistance + Settings.islandZOffset;
long y = Settings.islandHeight;
return new Location(location.getWorld(), x, y, z);
}
/**
* Checks if this location is safe for a player to teleport to. Used by
* warps and boat exits Unsafe is any liquid or air and also if there's no
* space
*
* @param l
* - Location to be checked
* @return true if safe, otherwise false
*/
public static boolean isSafeLocation(final Location l) {
if (l == null) {
return false;
}
// TODO: improve the safe location finding.
//Bukkit.getLogger().info("DEBUG: " + l.toString());
final Block ground = l.getBlock().getRelative(BlockFace.DOWN);
final Block space1 = l.getBlock();
final Block space2 = l.getBlock().getRelative(BlockFace.UP);
//Bukkit.getLogger().info("DEBUG: ground = " + ground.getType());
//Bukkit.getLogger().info("DEBUG: space 1 = " + space1.getType());
//Bukkit.getLogger().info("DEBUG: space 2 = " + space2.getType());
// Portals are not "safe"
if (space1.getType() == Material.PORTAL || ground.getType() == Material.PORTAL || space2.getType() == Material.PORTAL
|| space1.getType() == Material.ENDER_PORTAL || ground.getType() == Material.ENDER_PORTAL || space2.getType() == Material.ENDER_PORTAL) {
return false;
}
// If ground is AIR, then this is either not good, or they are on slab,
// stair, etc.
if (ground.getType() == Material.AIR) {
// Bukkit.getLogger().info("DEBUG: air");
return false;
}
// In ASkyBlock, liquid may be unsafe
if (ground.isLiquid() || space1.isLiquid() || space2.isLiquid()) {
// Check if acid has no damage
if (Settings.acidDamage > 0D) {
// Bukkit.getLogger().info("DEBUG: acid");
return false;
} else if (ground.getType().equals(Material.STATIONARY_LAVA) || ground.getType().equals(Material.LAVA)
|| space1.getType().equals(Material.STATIONARY_LAVA) || space1.getType().equals(Material.LAVA)
|| space2.getType().equals(Material.STATIONARY_LAVA) || space2.getType().equals(Material.LAVA)) {
// Lava check only
// Bukkit.getLogger().info("DEBUG: lava");
return false;
}
}
MaterialData md = ground.getState().getData();
if (md instanceof SimpleAttachableMaterialData) {
//Bukkit.getLogger().info("DEBUG: trapdoor/button/tripwire hook etc.");
if (md instanceof TrapDoor) {
TrapDoor trapDoor = (TrapDoor)md;
if (trapDoor.isOpen()) {
//Bukkit.getLogger().info("DEBUG: trapdoor open");
return false;
}
} else {
return false;
}
//Bukkit.getLogger().info("DEBUG: trapdoor closed");
}
if (ground.getType().equals(Material.CACTUS) || ground.getType().equals(Material.BOAT) || ground.getType().equals(Material.FENCE)
|| ground.getType().equals(Material.NETHER_FENCE) || ground.getType().equals(Material.SIGN_POST) || ground.getType().equals(Material.WALL_SIGN)) {
// Bukkit.getLogger().info("DEBUG: cactus");
return false;
}
// Check that the space is not solid
// The isSolid function is not fully accurate (yet) so we have to
// check
// a few other items
// isSolid thinks that PLATEs and SIGNS are solid, but they are not
if (space1.getType().isSolid() && !space1.getType().equals(Material.SIGN_POST) && !space1.getType().equals(Material.WALL_SIGN)) {
return false;
}
if (space2.getType().isSolid()&& !space2.getType().equals(Material.SIGN_POST) && !space2.getType().equals(Material.WALL_SIGN)) {
return false;
}
// Safe
//Bukkit.getLogger().info("DEBUG: safe!");
return true;
}
/**
* Determines a safe teleport spot on player's island or the team island
* they belong to.
*
* @param p UUID of player
* @param number - starting home location e.g., 1
* @return Location of a safe teleport spot or null if one cannot be found
*/
public Location getSafeHomeLocation(final UUID p, int number) {
// Try the numbered home location first
Location l = plugin.getPlayers().getHomeLocation(p, number);
if (l == null) {
// Get the default home, which may be null too, but that's okay
number = 1;
l = plugin.getPlayers().getHomeLocation(p, number);
}
// Check if it is safe
//plugin.getLogger().info("DEBUG: Home location " + l);
if (l != null) {
// Homes are stored as integers and need correcting to be more central
if (isSafeLocation(l)) {
return l.clone().add(new Vector(0.5D,0,0.5D));
}
// To cover slabs, stairs and other half blocks, try one block above
Location lPlusOne = l.clone();
lPlusOne.add(new Vector(0, 1, 0));
if (lPlusOne != null) {
if (isSafeLocation(lPlusOne)) {
// Adjust the home location accordingly
plugin.getPlayers().setHomeLocation(p, lPlusOne, number);
return lPlusOne.clone().add(new Vector(0.5D,0,0.5D));
}
}
}
//plugin.getLogger().info("DEBUG: Home location either isn't safe, or does not exist so try the island");
// Home location either isn't safe, or does not exist so try the island
// location
if (plugin.getPlayers().inTeam(p)) {
l = plugin.getPlayers().getTeamIslandLocation(p);
if (isSafeLocation(l)) {
plugin.getPlayers().setHomeLocation(p, l, number);
return l.clone().add(new Vector(0.5D,0,0.5D));
} else {
// try team leader's home
Location tlh = plugin.getPlayers().getHomeLocation(plugin.getPlayers().getTeamLeader(p));
if (tlh != null) {
if (isSafeLocation(tlh)) {
plugin.getPlayers().setHomeLocation(p, tlh, number);
return tlh.clone().add(new Vector(0.5D,0,0.5D));
}
}
}
} else {
l = plugin.getPlayers().getIslandLocation(p);
if (isSafeLocation(l)) {
plugin.getPlayers().setHomeLocation(p, l, number);
return l.clone().add(new Vector(0.5D,0,0.5D));
}
}
if (l == null) {
plugin.getLogger().warning(plugin.getPlayers().getName(p) + " player has no island!");
return null;
}
//plugin.getLogger().info("DEBUG: If these island locations are not safe, then we need to get creative");
// If these island locations are not safe, then we need to get creative
// Try the default location
//plugin.getLogger().info("DEBUG: default");
Location dl = new Location(l.getWorld(), l.getX() + 0.5D, l.getY() + 5D, l.getZ() + 2.5D, 0F, 30F);
if (isSafeLocation(dl)) {
plugin.getPlayers().setHomeLocation(p, dl, number);
return dl;
}
// Try just above the bedrock
//plugin.getLogger().info("DEBUG: above bedrock");
dl = new Location(l.getWorld(), l.getX() + 0.5D, l.getY() + 5D, l.getZ() + 0.5D, 0F, 30F);
if (isSafeLocation(dl)) {
plugin.getPlayers().setHomeLocation(p, dl, number);
return dl;
}
// Try all the way up to the sky
//plugin.getLogger().info("DEBUG: try all the way to the sky");
for (int y = l.getBlockY(); y < 255; y++) {
final Location n = new Location(l.getWorld(), l.getX() + 0.5D, y, l.getZ() + 0.5D);
if (isSafeLocation(n)) {
plugin.getPlayers().setHomeLocation(p, n, number);
return n;
}
}
//plugin.getLogger().info("DEBUG: unsuccessful");
// Unsuccessful
return null;
}
/**
* This is a generic scan that can work in the overworld or the nether
* @param l - location around which to scan
* @param i - the range to scan for a location < 0 means the full island.
* @return - safe location, or null if none can be found
*/
public Location bigScan(Location l, int i) {
final int height;
final int depth;
if (i > 0) {
height = i;
depth = i;
} else {
Island island = plugin.getGrid().getIslandAt(l);
if (island == null) {
return null;
}
i = island.getProtectionSize();
height = l.getWorld().getMaxHeight() - l.getBlockY();
depth = l.getBlockY();
}
//plugin.getLogger().info("DEBUG: ranges i = " + i);
//plugin.getLogger().info(" " + minX + "," + minZ + " " + maxX + " " + maxZ);
//plugin.getLogger().info("DEBUG: height = " + height);
//plugin.getLogger().info("DEBUG: depth = " + depth);
//plugin.getLogger().info("DEBUG: trying to find a safe spot at " + l.toString());
// Work outwards from l until the closest safe location is found.
int minXradius = 0;
int maxXradius = 0;
int minZradius = 0;
int maxZradius = 0;
int minYradius = 0;
int maxYradius = 0;
do {
int minX = l.getBlockX()-minXradius;
int minZ = l.getBlockZ()-minZradius;
int minY = l.getBlockY()-minYradius;
int maxX = l.getBlockX()+maxXradius;
int maxZ = l.getBlockZ()+maxZradius;
int maxY = l.getBlockY()+maxYradius;
for (int x = minX; x<= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
if (!((x > minX && x < maxX) && (z > minZ && z < maxZ) && (y > minY && y < maxY))) {
//plugin.getLogger().info("DEBUG: checking " + x + "," + y + "," + z);
Location ultimate = new Location(l.getWorld(), x + 0.5D, y, z + 0.5D);
if (isSafeLocation(ultimate)) {
//plugin.getLogger().info("DEBUG: Found! " + ultimate);
return ultimate;
}
}
}
}
}
if (minXradius < i) {
minXradius++;
}
if (maxXradius < i) {
maxXradius++;
}
if (minZradius < i) {
minZradius++;
}
if (maxZradius < i) {
maxZradius++;
}
if (minYradius < depth) {
minYradius++;
}
if (maxYradius < height) {
maxYradius++;
}
//plugin.getLogger().info("DEBUG: Radii " + minXradius + "," + minYradius + "," + minZradius +
// "," + maxXradius + "," + maxYradius + "," + maxZradius);
} while (minXradius < i || maxXradius < i || minZradius < i || maxZradius < i || minYradius < depth
|| maxYradius < height);
// Nothing worked
return null;
}
/**
* This teleports player to their island. If not safe place can be found
* then the player is sent to spawn via /spawn command
*
* @param player
* @return true if the home teleport is successful
*/
public boolean homeTeleport(final Player player) {
return homeTeleport(player, 1);
}
/**
* Teleport player to a home location. If one cannot be found a search is done to
* find a safe place.
* @param player
* @param number - home location to do to
* @return true if successful, false if not
*/
public boolean homeTeleport(final Player player, int number) {
Location home = null;
//plugin.getLogger().info("home teleport called for #" + number);
home = getSafeHomeLocation(player.getUniqueId(), number);
//plugin.getLogger().info("home get safe loc = " + home);
// Check if the player is a passenger in a boat
if (player.isInsideVehicle()) {
Entity boat = player.getVehicle();
if (boat instanceof Boat) {
player.leaveVehicle();
// Remove the boat so they don't lie around everywhere
boat.remove();
player.getInventory().addItem(new ItemStack(Material.BOAT, 1));
player.updateInventory();
}
}
if (home == null) {
//plugin.getLogger().info("Fixing home location using safe spot teleport");
// Try to fix this teleport location and teleport the player if possible
new SafeSpotTeleport(plugin, player, plugin.getPlayers().getHomeLocation(player.getUniqueId(), number), number);
return true;
}
//plugin.getLogger().info("DEBUG: home loc = " + home + " teleporting");
//home.getChunk().load();
player.teleport(home);
//player.sendBlockChange(home, Material.GLOWSTONE, (byte)0);
if (number ==1 ) {
Util.sendMessage(player, ChatColor.GREEN + plugin.myLocale(player.getUniqueId()).islandteleport);
} else {
Util.sendMessage(player, ChatColor.GREEN + plugin.myLocale(player.getUniqueId()).islandteleport + " #" + number);
}
return true;
}
/**
* Sets the numbered home location based on where the player is now
* @param player
* @param number
*/
public void homeSet(Player player, int number) {
// Check if player is in their home world
if (!player.getWorld().equals(plugin.getPlayers().getIslandLocation(player.getUniqueId()).getWorld())) {
Util.sendMessage(player, ChatColor.RED + plugin.myLocale(player.getUniqueId()).setHomeerrorNotOnIsland);
return;
}
// Check if player is on island, ignore coops
if (!plugin.getGrid().playerIsOnIsland(player, false)) {
Util.sendMessage(player, ChatColor.RED + plugin.myLocale(player.getUniqueId()).setHomeerrorNotOnIsland);
return;
}
plugin.getPlayers().setHomeLocation(player.getUniqueId(), player.getLocation(), number);
if (number == 1) {
Util.sendMessage(player, ChatColor.GREEN + plugin.myLocale(player.getUniqueId()).setHomehomeSet);
} else {
Util.sendMessage(player, ChatColor.GREEN + plugin.myLocale(player.getUniqueId()).setHomehomeSet + " #" + number);
}
}
/**
* Sets the home location based on where the player is now
*
* @param player
*/
public void homeSet(final Player player) {
homeSet(player, 1);
}
/**
* Checks if a specific location is within the protected range of an island
* owned by the player
*
* @param player
* @param loc
* @return true if location is on island of player
*/
public boolean locationIsOnIsland(final Player player, final Location loc) {
if (player == null) {
return false;
}
// Get the player's island from the grid if it exists
Island island = getIslandAt(loc);
if (island != null) {
//plugin.getLogger().info("DEBUG: island here is " + island.getCenter());
// On an island in the grid
//plugin.getLogger().info("DEBUG: onIsland = " + island.onIsland(loc));
//plugin.getLogger().info("DEBUG: members = " + island.getMembers());
//plugin.getLogger().info("DEBUG: player UUID = " + player.getUniqueId());
if (island.onIsland(loc) && island.getMembers().contains(player.getUniqueId())) {
//plugin.getLogger().info("DEBUG: allowed");
// In a protected zone but is on the list of acceptable players
return true;
} else {
// Not allowed
//plugin.getLogger().info("DEBUG: not allowed");
return false;
}
} else {
//plugin.getLogger().info("DEBUG: no island at this location");
}
// Not in the grid, so do it the old way
// Make a list of test locations and test them
Set<Location> islandTestLocations = new HashSet<Location>();
if (plugin.getPlayers().hasIsland(player.getUniqueId())) {
islandTestLocations.add(plugin.getPlayers().getIslandLocation(player.getUniqueId()));
} else if (plugin.getPlayers().inTeam(player.getUniqueId())) {
islandTestLocations.add(plugin.getPlayers().get(player.getUniqueId()).getTeamIslandLocation());
}
// Check any coop locations
islandTestLocations.addAll(CoopPlay.getInstance().getCoopIslands(player));
if (islandTestLocations.isEmpty()) {
return false;
}
// Run through all the locations
for (Location islandTestLocation : islandTestLocations) {
if (loc.getWorld().equals(islandTestLocation.getWorld())) {
if (loc.getX() >= islandTestLocation.getX() - Settings.islandProtectionRange / 2
&& loc.getX() < islandTestLocation.getX() + Settings.islandProtectionRange / 2
&& loc.getZ() >= islandTestLocation.getZ() - Settings.islandProtectionRange / 2
&& loc.getZ() < islandTestLocation.getZ() + Settings.islandProtectionRange / 2) {
return true;
}
}
}
return false;
}
/**
* Finds out if location is within a set of island locations and returns the
* one that is there or null if not
*
* @param islandTestLocations
* @param loc
* @return Location found that is on the island
*/
public Location locationIsOnIsland(final Set<Location> islandTestLocations, final Location loc) {
// Run through all the locations
for (Location islandTestLocation : islandTestLocations) {
if (loc.getWorld().equals(islandTestLocation.getWorld())) {
if (getIslandAt(islandTestLocation) != null) {
// Get the protection range for this location if possible
Island island = getProtectedIslandAt(islandTestLocation);
if (island != null) {
// We are in a protected island area.
return island.getCenter();
}
} else if (loc.getX() > islandTestLocation.getX() - Settings.islandProtectionRange / 2
&& loc.getX() < islandTestLocation.getX() + Settings.islandProtectionRange / 2
&& loc.getZ() > islandTestLocation.getZ() - Settings.islandProtectionRange / 2
&& loc.getZ() < islandTestLocation.getZ() + Settings.islandProtectionRange / 2) {
return islandTestLocation;
}
}
}
return null;
}
/**
* Checks if an online player is in the protected area of their island, a team island or a
* coop island
*
* @param player
* @return true if on valid island, false if not
*/
public boolean playerIsOnIsland(final Player player) {
return playerIsOnIsland(player, true);
}
/**
* Checks if an online player is in the protected area of their island, a team island or a
* coop island
* @param player
* @param coop - if true, coop islands are included
* @return true if on valid island, false if not
*/
public boolean playerIsOnIsland(final Player player, boolean coop) {
return locationIsAtHome(player, coop, player.getLocation());
}
/**
* Checks if a location is within the home boundaries of a player. If coop is true, this check includes coop players.
* @param player
* @param coop
* @param loc
* @return true if the location is within home boundaries
*/
public boolean locationIsAtHome(final Player player, boolean coop, Location loc) {
// Make a list of test locations and test them
Set<Location> islandTestLocations = new HashSet<Location>();
if (plugin.getPlayers().hasIsland(player.getUniqueId())) {
islandTestLocations.add(plugin.getPlayers().getIslandLocation(player.getUniqueId()));
// If new Nether
if (Settings.createNether && Settings.newNether && ASkyBlock.getNetherWorld() != null) {
islandTestLocations.add(netherIsland(plugin.getPlayers().getIslandLocation(player.getUniqueId())));
}
} else if (plugin.getPlayers().inTeam(player.getUniqueId())) {
islandTestLocations.add(plugin.getPlayers().getTeamIslandLocation(player.getUniqueId()));
if (Settings.createNether && Settings.newNether && ASkyBlock.getNetherWorld() != null) {
islandTestLocations.add(netherIsland(plugin.getPlayers().getTeamIslandLocation(player.getUniqueId())));
}
}
// Check coop locations
if (coop) {
islandTestLocations.addAll(CoopPlay.getInstance().getCoopIslands(player));
}
if (islandTestLocations.isEmpty()) {
return false;
}
// Run through all the locations
for (Location islandTestLocation : islandTestLocations) {
// Must be in the same world as the locations being checked
// Note that getWorld can return null if a world has been deleted on the server
if (islandTestLocation != null && islandTestLocation.getWorld() != null && islandTestLocation.getWorld().equals(loc.getWorld())) {
int protectionRange = Settings.islandProtectionRange;
if (getIslandAt(islandTestLocation) != null) {
// Get the protection range for this location if possible
Island island = getProtectedIslandAt(islandTestLocation);
if (island != null) {
// We are in a protected island area.
protectionRange = island.getProtectionSize();
}
}
if (loc.getX() > islandTestLocation.getX() - protectionRange / 2
&& loc.getX() < islandTestLocation.getX() + protectionRange / 2
&& loc.getZ() > islandTestLocation.getZ() - protectionRange / 2
&& loc.getZ() < islandTestLocation.getZ() + protectionRange / 2) {
return true;
}
}
}
return false;
}
/**
* Generates a Nether version of the locations
* @param islandLocation
* @return
*/
private Location netherIsland(Location islandLocation) {
//plugin.getLogger().info("DEBUG: netherworld = " + ASkyBlock.getNetherWorld());
return islandLocation.toVector().toLocation(ASkyBlock.getNetherWorld());
}
/**
* Checks to see if a player is trespassing on another player's island
* Both players must be online.
*
* @param owner
* - owner or team member of an island
* @param target
* @return true if they are on the island otherwise false.
*/
public boolean isOnIsland(final Player owner, final Player target) {
// Check world
if (target.getWorld().equals(ASkyBlock.getIslandWorld()) || (Settings.newNether && Settings.createNether && target.getWorld().equals(ASkyBlock.getNetherWorld()))) {
// Get the island location of owner
Location islandTestLocation = null;
if (plugin.getPlayers().inTeam(owner.getUniqueId())) {
// Is the target in the owner's team?
if (plugin.getPlayers().getMembers(plugin.getPlayers().getTeamLeader(owner.getUniqueId())).contains(target.getUniqueId())) {
// Yes, so this is not a trespass for sure
return false;
}
// No, so check where the target is now
islandTestLocation = plugin.getPlayers().getTeamIslandLocation(owner.getUniqueId());
} else {
islandTestLocation = plugin.getPlayers().getIslandLocation(owner.getUniqueId());
}
// Check position of target
if (islandTestLocation == null) {
return false;
}
int protectionRange = Settings.islandProtectionRange;
if (getIslandAt(islandTestLocation) != null) {
Island island = getProtectedIslandAt(islandTestLocation);
// Get the protection range for this location if possible
if (island != null) {
// We are in a protected island area.
protectionRange = island.getProtectionSize();
}
}
if (target.getLocation().getX() > islandTestLocation.getX() - protectionRange / 2
&& target.getLocation().getX() < islandTestLocation.getX() + protectionRange / 2
&& target.getLocation().getZ() > islandTestLocation.getZ() - protectionRange / 2
&& target.getLocation().getZ() < islandTestLocation.getZ() + protectionRange / 2) {
return true;
}
}
return false;
}
/**
* Transfers ownership of an island from one player to another
*
* @param oldOwner
* @param newOwner
* @return true if successful
*/
public boolean transferIsland(final UUID oldOwner, final UUID newOwner) {
if (plugin.getPlayers().hasIsland(oldOwner)) {
Location islandLoc = plugin.getPlayers().getIslandLocation(oldOwner);
plugin.getPlayers().setHasIsland(newOwner, true);
plugin.getPlayers().setIslandLocation(newOwner, islandLoc);
// plugin.getPlayers().setIslandLevel(newOwner,
// plugin.getPlayers().getIslandLevel(oldOwner));
plugin.getPlayers().setTeamIslandLocation(newOwner, null);
plugin.getPlayers().setHasIsland(oldOwner, false);
plugin.getPlayers().setIslandLocation(oldOwner, null);
// plugin.getPlayers().setIslandLevel(oldOwner, 0);
plugin.getPlayers().setTeamIslandLocation(oldOwner, islandLoc);
// Update grid
Island island = getIslandAt(islandLoc);
if (island != null) {
setIslandOwner(island, newOwner);
}
// Update top ten list
// Remove old owner score from top ten list
TopTen.remove(oldOwner);
return true;
}
return false;
}
/**
* Removes monsters around location l
*
* @param l
*/
public void removeMobs(final Location l) {
if (!inWorld(l)) {
return;
}
//plugin.getLogger().info("DEBUG: removing mobs");
// Don't remove mobs if at spawn
if (this.isAtSpawn(l)) {
//plugin.getLogger().info("DEBUG: at spawn!");
return;
}
final int px = l.getBlockX();
final int py = l.getBlockY();
final int pz = l.getBlockZ();
for (int x = -1; x <= 1; x++) {
for (int z = -1; z <= 1; z++) {
final Chunk c = l.getWorld().getChunkAt(new Location(l.getWorld(), px + x * 16, py, pz + z * 16));
if (c.isLoaded()) {
for (final Entity e : c.getEntities()) {
//plugin.getLogger().info("DEBUG: " + e.getType());
if (e instanceof Monster && !Settings.mobWhiteList.contains(e.getType())) {
Monster monster = (Monster)e;
//plugin.getLogger().info("DEBUG: monster found. custom name is '" + monster.getCustomName() + "'");
//plugin.getLogger().info("DEBUG: remove when far away = " + monster.getRemoveWhenFarAway());
// Don't remove if the monster has a name tag
if (monster.getCustomName() == null || monster.getRemoveWhenFarAway()) {
e.remove();
}
}
}
}
}
}
}
/**
* This removes players from an island overworld and nether - used when reseting or deleting an island
* Mobs are killed when the chunks are refreshed.
* @param island to remove players from
* @param uuid
*/
public void removePlayersFromIsland(final Island island, UUID uuid) {
// Teleport players away
for (Player player : plugin.getServer().getOnlinePlayers()) {
if (island.inIslandSpace(player.getLocation())) {
//plugin.getLogger().info("DEBUG: in island space");
// Teleport island players to their island home
if (!player.getUniqueId().equals(uuid) && (plugin.getPlayers().hasIsland(player.getUniqueId()) || plugin.getPlayers().inTeam(player.getUniqueId()))) {
//plugin.getLogger().info("DEBUG: home teleport");
homeTeleport(player);
} else {
//plugin.getLogger().info("DEBUG: move player to spawn");
// Move player to spawn
Island spawn = getSpawn();
if (spawn != null) {
// go to island spawn
player.teleport(ASkyBlock.getIslandWorld().getSpawnLocation());
//plugin.getLogger().warning("During island deletion player " + player.getName() + " sent to spawn.");
} else {
if (!player.performCommand(Settings.SPAWNCOMMAND)) {
plugin.getLogger().warning(
"During island deletion player " + player.getName() + " could not be sent to spawn so was dropped, sorry.");
}
}
}
}
}
}
/**
* @return a list of unowned islands
*/
public HashMap<String, Island> getUnownedIslands() {
HashMap<String, Island> result = new HashMap<String,Island>();
for (Entry<Integer, TreeMap<Integer, Island>> x : islandGrid.entrySet()) {
for (Island island : x.getValue().values()) {
//plugin.getLogger().info("DEBUG: checking island at " + island.getCenter());
if (island.getOwner() == null && !island.isSpawn() && !island.isPurgeProtected()) {
Location center = island.getCenter();
String serialized = island.getCenter().getWorld().getName() + ":" + center.getBlockX() + ":" + center.getBlockY() + ":" + center.getBlockZ();
result.put(serialized,island);
}
}
}
return result;
}
/**
* Set the spawn point for the island world
* @param location
*/
public void setSpawnPoint(Location location) {
ASkyBlock.getIslandWorld().setSpawnLocation(location.getBlockX(), location.getBlockY(), location.getBlockZ());
//plugin.getLogger().info("DEBUG: setting spawn point to " + location);
spawn.setSpawnPoint(location);
}
/**
* @return the spawnPoint or null if spawn does not exist
*/
public Location getSpawnPoint() {
//plugin.getLogger().info("DEBUG: getting spawn point : " + spawn.getSpawnPoint());
if (spawn == null)
return null;
return spawn.getSpawnPoint();
}
/**
* @return how many islands are in the grid
*/
public int getIslandCount() {
return ownershipMap.size();
}
/**
* Get the ownership map of islands
* @return Hashmap of owned islands with owner UUID as a key
*
*/
public HashMap<UUID, Island> getOwnedIslands() {
return ownershipMap;
}
/**
* Get name of the island owned by owner
* @param owner
* @return Returns the name of owner's island, or the owner's name if there is none.
*/
public String getIslandName(UUID owner) {
return ChatColor.translateAlternateColorCodes('&', islandNames.getString(owner.toString(), plugin.getPlayers().getName(owner))) + ChatColor.RESET;
}
/**
* Set the island name
* @param owner
* @param name
*/
public void setIslandName(UUID owner, String name) {
islandNames.set(owner.toString(), name);
try {
islandNames.save(islandNameFile);
} catch (IOException e) {
plugin.getLogger().severe("Could not save islandnames.yml! " + e.getMessage());
}
}
}