diff --git a/src/main/java/us/talabrek/ultimateskyblock/LocationUtil.java b/src/main/java/us/talabrek/ultimateskyblock/LocationUtil.java new file mode 100644 index 000000000..ab3d13788 --- /dev/null +++ b/src/main/java/us/talabrek/ultimateskyblock/LocationUtil.java @@ -0,0 +1,23 @@ +package us.talabrek.ultimateskyblock; + +import org.bukkit.Location; + +/** + * Responsible for various transformations of locations. + */ +public enum LocationUtil {; + public static String asString(Location loc) { + if (loc == null) { + return null; + } + String s = ""; + if (loc.getWorld() != null && loc.getWorld().getName() != null) { + s += loc.getWorld().getName() + ":"; + } + s += String.format("%5.2f,%5.2f,%5.2f", loc.getX(), loc.getY(), loc.getZ()); + if (loc.getYaw() != 0f || loc.getPitch() != 0f) { + s += String.format(":%3.2f:%3.2f", loc.getYaw(), loc.getPitch()); + } + return s; + } +} diff --git a/src/main/java/us/talabrek/ultimateskyblock/TimeUtil.java b/src/main/java/us/talabrek/ultimateskyblock/TimeUtil.java new file mode 100644 index 000000000..1191993d0 --- /dev/null +++ b/src/main/java/us/talabrek/ultimateskyblock/TimeUtil.java @@ -0,0 +1,33 @@ +package us.talabrek.ultimateskyblock; + +public enum TimeUtil {; + private static final long SEC = 1000; + private static final long MIN = 60*SEC; + private static final long HOUR = 60*MIN; + private static final long DAYS = 24*HOUR; + + public static String millisAsString(long millis) { + long d = millis / DAYS; + long h = (millis % DAYS) / HOUR; + long m = (millis % HOUR) / MIN; + long s = (millis % MIN) / SEC; + String str = ""; + if (d > 0) { + str += d + "d"; + } + if (h > 0) { + str += " " + h + "h"; + } + if (m > 0) { + str += " " + m + "m"; + } + if (s > 0) { + str += " " + s + "s"; + } + return str.trim(); + } + + public static String ticksAsString(int ticks) { + return millisAsString(ticks * 50); + } +} diff --git a/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java b/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java index 421af59c3..81eb80b30 100644 --- a/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java +++ b/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java @@ -40,5 +40,6 @@ protected void doExecute(CommandSender sender, PlayerInfo playerInfo) { sender.sendMessage(playerInfo.toString()); } }); + add(new FixCommand(plugin)); } } diff --git a/src/main/java/us/talabrek/ultimateskyblock/command/admin/FixCommand.java b/src/main/java/us/talabrek/ultimateskyblock/command/admin/FixCommand.java new file mode 100644 index 000000000..69dc535a6 --- /dev/null +++ b/src/main/java/us/talabrek/ultimateskyblock/command/admin/FixCommand.java @@ -0,0 +1,48 @@ +package us.talabrek.ultimateskyblock.command.admin; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import us.talabrek.ultimateskyblock.command.common.AbstractUSBCommand; +import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; +import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.util.Map; + +/** + * Tries to clear an area of flatland. + */ +public class FixCommand extends AbstractUSBCommand { + private final uSkyBlock plugin; + + public FixCommand(uSkyBlock plugin) { + super("fix-flatland", "usb.admin.remove", "?player", "tries to fix the the area of flatland."); + this.plugin = plugin; + } + + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + String playerName = null; + if (args.length == 1) { + playerName = args[0]; + } else if (args.length == 0 && sender instanceof Player) { + playerName = WorldGuardHandler.getRegionAt(((Player) sender).getLocation()); + } + PlayerInfo playerInfo = playerName != null ? plugin.getPlayerInfo(playerName) : null; + if (!tryFlatlandFix(sender, playerName, playerInfo)) { + sender.sendMessage("\u00a74No valid island found"); + } + return true; + } + + private boolean tryFlatlandFix(CommandSender sender, String playerName, PlayerInfo playerInfo) { + if (playerInfo.getHasIsland() && playerInfo.getIslandLocation() != null) { + // TODO: 29/12/2014 - R4zorax: Load chunks first? + if (!plugin.getIslandLogic().clearFlatland(sender, playerInfo.getIslandLocation(), 0)) { + sender.sendMessage("\u00a74No flatland detected at " + playerName + "'s island!"); + } + return true; + } + return false; + } +} diff --git a/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java b/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java index 7f71912ff..fe5ed4d61 100644 --- a/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java +++ b/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java @@ -23,7 +23,7 @@ public static void importWorld(World skyWorld) { MultiverseCore core = getMultiverseCore(); if (core != null) { if (!core.getMVWorldManager().isMVWorld(skyWorld)) { - core.getMVWorldManager().addWorld(skyWorld.getName(), World.Environment.NORMAL, null, WorldType.NORMAL, false, "uSkyBlock"); + core.getMVWorldManager().addWorld(skyWorld.getName(), World.Environment.NORMAL, "0", WorldType.NORMAL, false, "uSkyBlock"); } } } diff --git a/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java b/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java index 81dc145b3..87f9fac81 100644 --- a/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java +++ b/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java @@ -169,4 +169,17 @@ public static void transferRegion(final String owner, final String player, final uSkyBlock.log(Level.INFO, "Error transferring WorldGuard Protected Region from (" + owner + ") to (" + player + ")"); } } + + public static String getRegionAt(Location location) { + WorldGuardPlugin worldGuard = getWorldGuard(); + RegionManager regionManager = worldGuard.getRegionManager(location.getWorld()); + ApplicableRegionSet applicableRegions = regionManager.getApplicableRegions(location); + for (ProtectedRegion region : applicableRegions) { + String id = region.getId().toLowerCase(); + if (!id.equalsIgnoreCase("__global__") && id.endsWith("island")) { + return id.substring(0, id.length()-6); + } + } + return null; + } } diff --git a/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java b/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java index dd65654d1..efcb734df 100644 --- a/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java +++ b/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java @@ -5,22 +5,32 @@ import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.block.Block; import org.bukkit.command.CommandSender; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; +import us.talabrek.ultimateskyblock.LocationUtil; import us.talabrek.ultimateskyblock.Settings; -import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.TimeUtil; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; +import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; +import static org.bukkit.Material.AIR; +import static org.bukkit.Material.BEDROCK; + /** * Responsible for island creation, locating locations, purging, clearing etc. */ @@ -73,6 +83,60 @@ public void clearIsland(Location loc) { } } + public boolean clearFlatland(final CommandSender sender, final Location loc, int delay) { + if (loc == null) { + return false; + } + final World w = loc.getWorld(); + final int px = loc.getBlockX(); + final int pz = loc.getBlockZ(); + final int py = 0; + final int range = Math.max(Settings.island_protectionRange, Settings.island_distance) + 1; + final int radius = range/2; + // 5 sampling points... + if (w.getBlockAt(px, py, pz).getType() == BEDROCK + || w.getBlockAt(px+radius, py, pz+radius).getType() == BEDROCK + || w.getBlockAt(px+radius, py, pz-radius).getType() == BEDROCK + || w.getBlockAt(px-radius, py, pz+radius).getType() == BEDROCK + || w.getBlockAt(px-radius, py, pz-radius).getType() == BEDROCK) + { + sender.sendMessage(String.format("\u00a74Flatland detected under your island!\u00a7e Clearing it in %s, stay clear.", TimeUtil.ticksAsString(delay))); + final AtomicInteger sharedY = new AtomicInteger(0); + final Runnable clearYLayer = new Runnable() { + long tStart; + long timeUsed = 0; + @Override + public void run() { + long t = System.currentTimeMillis(); + int y = sharedY.getAndIncrement(); + if (y <= 3) { + if (y == 0) { + tStart = t; + } + for (int dx = 1; dx <= range; dx++) { + for (int dz = 1; dz <= range; dz++) { + Block b = w.getBlockAt(px + (dx % 2 == 0 ? dx/2 : -dx/2), + y, pz + (dz % 2 == 0 ? dz/2 : -dz/2)); + if (b.getType() != AIR) { + b.setType(AIR); + } + } + } + long diffTicks = (System.currentTimeMillis() - t)/50; + timeUsed += diffTicks; + plugin.getServer().getScheduler().runTaskLater(plugin, this, diffTicks); + } else { + plugin.log(Level.INFO, String.format("Flatland cleared at %s in %s (%s)", LocationUtil.asString(loc), TimeUtil.millisAsString(System.currentTimeMillis() - tStart), TimeUtil.millisAsString(timeUsed))); + sender.sendMessage("\u00a7eFlatland was cleared under your island. Take care."); + } + } + }; + plugin.getServer().getScheduler().runTaskLater(plugin, clearYLayer, delay); + return true; + } + return false; + } + public void reloadIsland(Location location) { reloadIsland(location2Name(location)); } diff --git a/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 4a74dc1f2..0d4d542ab 100644 --- a/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -880,7 +880,7 @@ public PlayerInfo getPlayerInfo(Player player) { public PlayerInfo getPlayerInfo(String playerName) { PlayerInfo playerInfo = activePlayers.get(playerName); if (playerInfo == null) { - playerInfo = loadPlayerAndIsland(playerName); + playerInfo = loadPlayerInfo(playerName); activePlayers.put(playerName, playerInfo); } return playerInfo; @@ -899,17 +899,18 @@ public void removeActivePlayer(final String player) { } public PlayerInfo loadPlayerData(Player player) { - final PlayerInfo pi = loadPlayerAndIsland(player.getName()); + final PlayerInfo pi = loadPlayerInfo(player.getName()); if (pi.getHasIsland()) { IslandInfo islandInfo = islandLogic.getIslandInfo(pi); WorldGuardHandler.protectIsland(player, islandInfo.getLeader(), pi); + islandLogic.clearFlatland(player, pi.getIslandLocation(), 200); } addActivePlayer(player.getName(), pi); uSkyBlock.log(Level.INFO, "Loaded player file for " + player.getName()); return pi; } - private PlayerInfo loadPlayerAndIsland(String playerName) { + private PlayerInfo loadPlayerInfo(String playerName) { final PlayerInfo playerInfo = new PlayerInfo(playerName); activePlayers.put(playerName, playerInfo); return playerInfo;